aboutsummaryrefslogtreecommitdiffstats
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c378
1 files changed, 352 insertions, 26 deletions
diff --git a/main.c b/main.c
index 24201a9..3e944fb 100644
--- a/main.c
+++ b/main.c
@@ -1,4 +1,4 @@
-/* $Id: main.c,v 1.247 2005/02/26 17:06:44 ukai Exp $ */
+/* $Id: main.c,v 1.248 2006/04/05 14:18:54 inu Exp $ */
#define MAINPROGRAM
#include "fm.h"
#include <signal.h>
@@ -14,6 +14,13 @@
#include "terms.h"
#include "myctype.h"
#include "regex.h"
+
+#ifdef USE_REMOTE
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <dirent.h>
+#endif
+
#ifdef USE_MOUSE
#ifdef USE_GPM
#include <gpm.h>
@@ -24,6 +31,12 @@ extern int do_getch();
#endif /* defined(USE_GPM) || defined(USE_SYSMOUSE) */
#endif
+#ifdef __MINGW32_VERSION
+#include <winsock.h>
+
+WSADATA WSAData;
+#endif
+
#define DSTR_LEN 256
Hist *LoadHist;
@@ -65,7 +78,11 @@ static char *MarkString = NULL;
static char *SearchString = NULL;
int (*searchRoutine) (Buffer *, char *);
+#ifndef __MINGW32_VERSION
JMP_BUF IntReturn;
+#else
+_JBTYPE IntReturn[_JBLEN];
+#endif /* __MINGW32_VERSION */
static void delBuffer(Buffer *buf);
static void cmd_loadfile(char *path);
@@ -104,6 +121,19 @@ static int searchKeyNum(void);
#define help() fusage(stdout, 0)
#define usage() fusage(stderr, 1)
+#ifdef USE_REMOTE
+static int open_remote(int id);
+static void execute_remote(int sock, char *arg);
+static Str find_sock(int pid);
+static int init_serv(void);
+static int init_remote(char *prefix);
+static void parse_sock_data(void);
+static Str SockName;
+static int SockFd = -1, UseRemote = FALSE, ExecuteRemote = FALSE, RemoteId = -1;
+struct sockaddr_un SockAddr;
+socklen_t SockLength;
+#endif
+
static void
fversion(FILE * f)
{
@@ -134,6 +164,9 @@ fversion(FILE * f)
",sysmouse"
#endif
#endif
+#ifdef USE_REMOTE
+ ",remote"
+#endif
#ifdef USE_MENU
",menu"
#endif
@@ -229,6 +262,11 @@ fusage(FILE * f, int err)
#ifdef USE_MOUSE
fprintf(f, " -no-mouse don't use mouse\n");
#endif /* USE_MOUSE */
+#ifdef USE_REMOTE
+ fprintf(f, " -enable_remote accept remote operation\n");
+ fprintf(f, " -remote command execute command in an already running w3m process\n");
+ fprintf(f, " -remote_id pid select a w3m to control with -remote option\n");
+#endif /* USE_MOUSE */
#ifdef USE_COOKIE
fprintf(f,
" -cookie use cookie (-no-cookie: don't use cookie)\n");
@@ -727,6 +765,33 @@ main(int argc, char **argv, char **envp)
else if (!strcmp("-dummy", argv[i])) {
/* do nothing */
}
+#ifdef USE_REMOTE
+ else if (!strcmp("-enable_remote", argv[i])) {
+ UseRemote = TRUE;
+ }
+ else if (!strcmp("-remote_id", argv[i])) {
+ if (++i >= argc)
+ usage();
+ RemoteId = atoi(argv[i]);
+ }
+ else if (!strcmp("-remote", argv[i])) {
+ ExecuteRemote = TRUE;
+
+ SockFd = open_remote(RemoteId);
+ if (SockFd < 0) {
+ fprintf(stderr, "Can't find w3m process.\n");
+ exit(1);
+ }
+ while (++i < argc) {
+ if ((*argv[i] == '+') || (*argv[i] == '-')) {
+ i--;
+ break;
+ }
+ execute_remote(SockFd, argv[i]);
+ }
+ close(SockFd);
+ }
+#endif
else if (!strcmp("-debug", argv[i]))
w3m_debug = TRUE;
else {
@@ -741,13 +806,34 @@ main(int argc, char **argv, char **envp)
}
i++;
}
-
+#ifdef USE_REMOTE
+ if (ExecuteRemote) {
+ exit(0);
+ }
+#endif
#ifdef __WATT32__
if (w3m_debug)
dbug_init();
sock_init();
#endif
+#ifdef __MINGW32_VERSION
+ {
+ int err;
+ WORD wVerReq;
+
+ wVerReq = MAKEWORD(1, 1);
+
+ err = WSAStartup(wVerReq, &WSAData);
+ if (err != 0)
+ {
+ fprintf(stderr, "Can't find winsock\n");
+ return 1;
+ }
+ _fmode = _O_BINARY;
+ }
+#endif
+
FirstTab = NULL;
LastTab = NULL;
nTab = 0;
@@ -1028,6 +1114,13 @@ main(int argc, char **argv, char **envp)
if (line_str) {
_goLine(line_str);
}
+
+#ifdef USE_REMOTE
+ if (UseRemote) {
+ init_serv();
+ }
+#endif
+
for (;;) {
if (add_download_list) {
add_download_list = FALSE;
@@ -1044,7 +1137,6 @@ main(int argc, char **argv, char **envp)
/* event processing */
if (CurrentEvent) {
CurrentKey = -1;
- CurrentKeyData = NULL;
CurrentCmdData = (char *)CurrentEvent->data;
w3mFuncList[CurrentEvent->cmd].func();
CurrentCmdData = NULL;
@@ -1059,7 +1151,6 @@ main(int argc, char **argv, char **envp)
if (CurrentAlarm->sec == 0) { /* refresh (0sec) */
Currentbuf->event = NULL;
CurrentKey = -1;
- CurrentKeyData = NULL;
CurrentCmdData = (char *)CurrentAlarm->data;
w3mFuncList[CurrentAlarm->cmd].func();
CurrentCmdData = NULL;
@@ -1098,7 +1189,20 @@ main(int argc, char **argv, char **envp)
} while (sleep_till_anykey(1, 0) <= 0);
}
#endif
+#ifdef USE_REMOTE
+ if (UseRemote) {
+ int n;
+ c = getch_select(SockFd, &n);
+ if (n == 1) {
+ parse_sock_data();
+ continue;
+ }
+ } else {
+ c = getch();
+ }
+#else
c = getch();
+#endif
#ifdef SIGWINCH
mySignal(SIGWINCH, resize_hook);
#endif
@@ -1126,10 +1230,240 @@ main(int argc, char **argv, char **envp)
}
prev_key = CurrentKey;
CurrentKey = -1;
- CurrentKeyData = NULL;
}
}
+#ifdef USE_REMOTE
+#ifndef HAVE_GETPEEREID
+#ifdef HAVE_SO_PEERCRED
+int
+getpeereid(int s, uid_t *euid, gid_t *egid)
+{
+ struct ucred cr;
+ int cl = sizeof(cr), r;
+
+ r = getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cl);
+ if (r)
+ return r;
+
+ *euid = cr.uid;
+ *egid = cr.gid;
+ return 0;
+}
+#endif /* HAVE_SO_PEERCRED */
+#endif /* ! HAVE_GETPEEREID */
+
+static int
+open_remote(int id)
+{
+#if defined(HAVE_SO_PEERCRED) || defined(HAVE_GETPEEREID)
+ uid_t euid;
+ gid_t egid;
+#endif
+ Str sock_name = find_sock(id);
+
+ if (! sock_name)
+ return -1;
+
+ if (sizeof(SockAddr.sun_path) <= sock_name->length)
+ return -1;
+
+ if (init_remote("w3mclis"))
+ return -1;
+
+ SockAddr.sun_family = AF_UNIX;
+ strcpy(SockAddr.sun_path, sock_name->ptr);
+ SockLength = sizeof(SockAddr.sun_family) + strlen(SockAddr.sun_path);
+
+ if (connect(SockFd, (struct sockaddr *) &SockAddr, SockLength)) {
+ close(SockFd);
+ unlink(SockName->ptr);
+ return -1;
+ }
+
+#if defined(HAVE_SO_PEERCRED) || defined(HAVE_GETPEEREID)
+ if (getpeereid(SockFd, &euid, &egid) != 0 || euid != getuid()) {
+ close(SockFd);
+ unlink(SockName->ptr);
+ return -1;
+ }
+#endif
+
+ return SockFd;
+}
+
+static void
+execute_remote(int sock, char *arg)
+{
+ write(sock, arg, strlen(arg));
+ write(sock, "\n", 1);
+}
+
+static Str
+find_sock(int pid)
+{
+ DIR *dot_w3m;
+ Str sock_name;
+ struct dirent *file = NULL;
+ struct stat sbuf;
+
+ if (pid > 0) {
+ sock_name = Sprintf("w3msock%d", pid);
+ } else {
+ sock_name = Strnew_charp("w3msock");
+ }
+
+ dot_w3m = opendir(rc_dir);
+ if (! dot_w3m)
+ return NULL;
+
+ while ((file = readdir(dot_w3m))) {
+ if ((pid > 0 && (Strcmp_charp(sock_name, file->d_name) == 0)) ||
+ (pid <= 0 && Strncmp_charp(sock_name, file->d_name, sock_name->length) == 0)) {
+ sock_name = Sprintf("%s/%s", rc_dir, file->d_name);
+ if ((stat(sock_name->ptr, &sbuf) == 0) &&
+ (sbuf.st_mode & S_IFSOCK) &&
+ !(sbuf.st_mode & (S_IRWXO | S_IRWXG)) &&
+ (sbuf.st_uid == getuid()))
+ goto SockFound;
+ }
+ }
+ closedir(dot_w3m);
+ return NULL;
+
+ SockFound:
+ closedir(dot_w3m);
+ return sock_name;
+}
+
+static int
+init_serv(void)
+{
+ if (init_remote("w3msock")) {
+ return 1;
+ }
+
+ if (listen(SockFd, 5)) {
+ unlink(SockName->ptr);
+ close(SockFd);
+ SockFd = -1;
+ UseRemote = FALSE;
+ return 1;
+ }
+
+ fcntl(SockFd, F_SETFL, O_NONBLOCK);
+ return 0;
+}
+
+
+static int
+init_remote(char *prefix)
+{
+ SockName = Sprintf("%s/%s%d", rc_dir, prefix, CurrentPid);
+ if (sizeof(SockAddr.sun_path) <= SockName->length)
+ goto SockErr;
+
+ SockAddr.sun_family = AF_UNIX;
+ strcpy(SockAddr.sun_path, SockName->ptr);
+ SockLength = sizeof(SockAddr.sun_family) + strlen(SockAddr.sun_path);
+
+ if ((SockFd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
+ goto SockErr;
+
+ unlink(SockName->ptr);
+ if (bind(SockFd, (struct sockaddr *) &SockAddr, SockLength))
+ goto SockErr;
+
+ chmod(SockName->ptr, S_IRUSR | S_IWUSR);
+ return 0;
+
+ SockErr:
+ unlink(SockName->ptr);
+ if (SockFd >= 0) {
+ close(SockFd);
+ }
+ SockFd = -1;
+ UseRemote = FALSE;
+ return 1;
+}
+
+static void
+parse_sock_data(void)
+{
+ Str data = NULL;
+ char buf[64];
+ char *p, *q, *s;
+ int l, f, conn;
+ struct sockaddr_un sock_addr = SockAddr;
+ socklen_t sock_length = SockLength;
+#if defined(HAVE_SO_PEERCRED) || defined(HAVE_GETPEEREID)
+ uid_t euid;
+ gid_t egid;
+#else
+ struct stat sbuf;
+ time_t staletime;
+#endif
+
+ if (!UseRemote || SockFd < 0) {
+ return;
+ }
+
+ if (!data)
+ data = Strnew();
+
+ conn = accept(SockFd, (struct sockaddr *) &sock_addr, &sock_length);
+
+ if (conn < 0)
+ return;
+
+
+ sock_length -= sizeof(sock_addr.sun_family);
+ sock_addr.sun_path[sock_length] = '\0';
+#if defined(HAVE_SO_PEERCRED) || defined(HAVE_GETPEEREID)
+ if (getpeereid(conn, &euid, &egid) != 0 || euid != getuid()) {
+#else
+#define STALE_LIMIT 60
+ staletime = time(NULL) - STALE_LIMIT;
+ if ((stat(sock_addr.sun_path, &sbuf) < 0) ||
+ !(sbuf.st_mode & S_IFSOCK) ||
+ (sbuf.st_mode & (S_IRWXO | S_IRWXG)) ||
+ (sbuf.st_uid != getuid()) ||
+ (sbuf.st_atime < staletime) ||
+ (sbuf.st_ctime < staletime) ||
+ (sbuf.st_mtime < staletime)) {
+#endif
+ close(conn);
+ return;
+ }
+ unlink(sock_addr.sun_path);
+ while ((l = read(conn, buf, sizeof(buf))) > 0) {
+ Strcat_charp_n(data, buf, l);
+ }
+ close(conn);
+
+ p = data->ptr;
+
+ while ((q = strchr(p, '\n'))) {
+ Str funcname = Strnew();
+ Str cmd = Strnew_charp_n(p, q - p);
+
+ s = cmd->ptr;
+ SKIP_BLANKS(s);
+ while (*s && !IS_SPACE(*s))
+ Strcat_char(funcname, *(s++));
+
+ SKIP_BLANKS(s);
+ f = getFuncList(funcname->ptr);
+ if (f >= 0) {
+ Str tmp = Strnew_charp(s);
+ Strchop(tmp);
+ pushEvent(f, tmp->ptr);
+ }
+ p = q + 1;
+ }
+}
+#endif /* USE_REMOTE */
+
static void
keyPressEventProc(int c)
{
@@ -1908,7 +2242,6 @@ DEFUN(setEnv, SETENV, "Set environment variable")
char *env;
char *var, *value;
- CurrentKeyData = NULL; /* not allowed in w3m-control: */
env = searchKeyData();
if (env == NULL || *env == '\0' || strchr(env, '=') == NULL) {
if (env != NULL && *env != '\0')
@@ -1933,7 +2266,6 @@ DEFUN(pipeBuf, PIPE_BUF, "Send rendered document to pipe")
char *cmd, *tmpf;
FILE *f;
- CurrentKeyData = NULL; /* not allowed in w3m-control: */
cmd = searchKeyData();
if (cmd == NULL || *cmd == '\0') {
/* FIXME: gettextize? */
@@ -1978,7 +2310,6 @@ DEFUN(pipesh, PIPE_SHELL, "Execute shell command and browse")
Buffer *buf;
char *cmd;
- CurrentKeyData = NULL; /* not allowed in w3m-control: */
cmd = searchKeyData();
if (cmd == NULL || *cmd == '\0') {
cmd = inputLineHist("(read shell[pipe])!", "", IN_COMMAND, ShellHist);
@@ -2010,7 +2341,6 @@ DEFUN(readsh, READ_SHELL, "Execute shell command and load")
MySignalHandler(*prevtrap) ();
char *cmd;
- CurrentKeyData = NULL; /* not allowed in w3m-control: */
cmd = searchKeyData();
if (cmd == NULL || *cmd == '\0') {
cmd = inputLineHist("(read shell)!", "", IN_COMMAND, ShellHist);
@@ -2045,7 +2375,6 @@ DEFUN(execsh, EXEC_SHELL SHELL, "Execute shell command")
{
char *cmd;
- CurrentKeyData = NULL; /* not allowed in w3m-control: */
cmd = searchKeyData();
if (cmd == NULL || *cmd == '\0') {
cmd = inputLineHist("(exec shell)!", "", IN_COMMAND, ShellHist);
@@ -4149,7 +4478,6 @@ DEFUN(setOpt, SET_OPTION, "Set option")
{
char *opt;
- CurrentKeyData = NULL; /* not allowed in w3m-control: */
opt = searchKeyData();
if (opt == NULL || *opt == '\0' || strchr(opt, '=') == NULL) {
if (opt != NULL && *opt != '\0') {
@@ -4335,7 +4663,6 @@ DEFUN(ldHist, HISTORY, "View history of URL")
/* download HREF link */
DEFUN(svA, SAVE_LINK, "Save link to file")
{
- CurrentKeyData = NULL; /* not allowed in w3m-control: */
do_download = TRUE;
followA();
do_download = FALSE;
@@ -4344,7 +4671,6 @@ DEFUN(svA, SAVE_LINK, "Save link to file")
/* download IMG link */
DEFUN(svI, SAVE_IMAGE, "Save image to file")
{
- CurrentKeyData = NULL; /* not allowed in w3m-control: */
do_download = TRUE;
followI();
do_download = FALSE;
@@ -4357,7 +4683,6 @@ DEFUN(svBuf, PRINT SAVE_SCREEN, "Save rendered document to file")
FILE *f;
int is_pipe;
- CurrentKeyData = NULL; /* not allowed in w3m-control: */
file = searchKeyData();
if (file == NULL || *file == '\0') {
/* FIXME: gettextize? */
@@ -4406,7 +4731,6 @@ DEFUN(svSrc, DOWNLOAD SAVE, "Save document source to file")
if (Currentbuf->sourcefile == NULL)
return;
- CurrentKeyData = NULL; /* not allowed in w3m-control: */
PermitSaveToPipe = TRUE;
if (Currentbuf->real_scheme == SCM_LOCAL)
file = conv_from_system(guess_save_name(NULL,
@@ -4943,7 +5267,6 @@ invoke_browser(char *url)
char *browser = NULL;
int bg = 0, len;
- CurrentKeyData = NULL; /* not allowed in w3m-control: */
browser = searchKeyData();
if (browser == NULL || *browser == '\0') {
switch (prec_num) {
@@ -5184,7 +5507,6 @@ do_mouse_action(int btn, int x, int y)
mouse_action.cursorX = x;
mouse_action.cursorY = y;
CurrentKey = -1;
- CurrentKeyData = NULL;
CurrentCmdData = map->data;
(*map->func) ();
CurrentCmdData = NULL;
@@ -5643,13 +5965,10 @@ searchKeyData(void)
{
char *data = NULL;
- if (CurrentKeyData != NULL && *CurrentKeyData != '\0')
- data = CurrentKeyData;
- else if (CurrentCmdData != NULL && *CurrentCmdData != '\0')
+ if (CurrentCmdData != NULL && *CurrentCmdData != '\0')
data = CurrentCmdData;
else if (CurrentKey >= 0)
data = getKeyData(CurrentKey);
- CurrentKeyData = NULL;
CurrentCmdData = NULL;
if (data == NULL || *data == '\0')
return NULL;
@@ -5714,6 +6033,14 @@ w3m_exit(int i)
#ifdef USE_NNTP
disconnectNews();
#endif
+#ifdef USE_REMOTE
+ if (UseRemote) {
+ unlink(SockName->ptr);
+ }
+#endif
+#ifdef __MINGW32_VERSION
+ WSACleanup();
+#endif
exit(i);
}
@@ -5722,7 +6049,6 @@ DEFUN(execCmd, COMMAND, "Execute w3m command(s)")
char *data, *p;
int cmd;
- CurrentKeyData = NULL; /* not allowed in w3m-control: */
data = searchKeyData();
if (data == NULL || *data == '\0') {
data = inputStrHist("command [; ...]: ", "", TextHist);
@@ -5744,7 +6070,6 @@ DEFUN(execCmd, COMMAND, "Execute w3m command(s)")
break;
p = getQWord(&data);
CurrentKey = -1;
- CurrentKeyData = NULL;
CurrentCmdData = *p ? p : NULL;
#ifdef USE_MOUSE
if (use_mouse)
@@ -5768,7 +6093,6 @@ SigAlarm(SIGNAL_ARG)
if (CurrentAlarm->sec > 0) {
CurrentKey = -1;
- CurrentKeyData = NULL;
CurrentCmdData = data = (char *)CurrentAlarm->data;
#ifdef USE_MOUSE
if (use_mouse)
@@ -5806,7 +6130,6 @@ DEFUN(setAlarm, ALARM, "Set alarm")
char *data;
int sec = 0, cmd = -1;
- CurrentKeyData = NULL; /* not allowed in w3m-control: */
data = searchKeyData();
if (data == NULL || *data == '\0') {
data = inputStrHist("(Alarm)sec command: ", "", TextHist);
@@ -5919,7 +6242,6 @@ DEFUN(defKey, DEFINE_KEY,
{
char *data;
- CurrentKeyData = NULL; /* not allowed in w3m-control: */
data = searchKeyData();
if (data == NULL || *data == '\0') {
data = inputStrHist("Key definition: ", "", TextHist);
@@ -6438,7 +6760,9 @@ download_action(struct parsed_tagarg *arg)
for (; arg; arg = arg->next) {
if (!strncmp(arg->arg, "stop", 4)) {
pid = (pid_t) atoi(&arg->arg[4]);
+#ifndef __MINGW32_VERSION
kill(pid, SIGKILL);
+#endif
}
else if (!strncmp(arg->arg, "ok", 2))
pid = (pid_t) atoi(&arg->arg[2]);
@@ -6472,7 +6796,9 @@ stopDownload(void)
for (d = FirstDL; d != NULL; d = d->next) {
if (d->ok)
continue;
+#ifndef __MINGW32_VERSION
kill(d->pid, SIGKILL);
+#endif
unlink(d->lock);
}
}