[w3m-dev 04151] Re: w3m -remote

Hiroyuki Ito <[email protected]> Tue, 28 Jun 2005 23:17:10 +0900 (JST)
Newsgroups gmane.comp.web.w3m.devel
Message-ID <[email protected]>

w3m -remote 


  -enable_remote      

  -remote COMMAND ...  w3m  COMMAND 
                      COMMAND 

  -remote_id PID       w3m  id 
                       w3m 
                      


  -enabel_remote  ~/.w3m  w3msock* (*  pid) 
  -remote COMMAND 
  
  


   w3m  w3m 
  ~/.w3m  700 
   UID 

  Linux (2.2 )  getsockopt()  SO_PEERCRED 
  FreeBSD  getpeereid() 
  
   LOCAL_CREDS  
  linux 

  getpeereid(), SO_PEERCRED 
   stat  UID 





Index: acinclude.m4
===================================================================
RCS file: /cvsroot/w3m/w3m/acinclude.m4,v
retrieving revision 1.40
diff -u -r1.40 acinclude.m4
--- acinclude.m4	14 Feb 2005 16:36:30 -0000	1.40
+++ acinclude.m4	28 Jun 2005 13:27:54 -0000
@@ -70,6 +70,18 @@
 AC_MSG_RESULT($enable_mouse)])
 #
 # ----------------------------------------------------------------
+# AC_W3M_REMOTE
+# ----------------------------------------------------------------
+AC_DEFUN([AC_W3M_REMOTE],
+[AC_SUBST(USE_MOUSE)
+AC_MSG_CHECKING(if remote operation enabled)
+AC_ARG_ENABLE(remote,
+ [  --disable-remote		disable remote operation],,
+ [enable_remote="yes"])
+test x"$enable_remote" = xyes && AC_DEFINE(USE_REMOTE)
+AC_MSG_RESULT($enable_remote)])
+#
+# ----------------------------------------------------------------
 # AC_W3M_COOKIE
 # ----------------------------------------------------------------
 AC_DEFUN([AC_W3M_COOKIE],
@@ -877,3 +889,27 @@
  else
   AC_DEFINE(SIGNAL_RETURN,return 0)
  fi])
+#
+# ----------------------------------------------------------------
+# AC_W3M_SO_PEERCRED
+# ----------------------------------------------------------------
+AC_DEFUN([AC_W3M_SO_PEERCRED],
+[AC_SUBST(HAVE_SO_PEERCRED)
+AC_MSG_CHECKING(for SO_PEERCRED)
+AC_TRY_COMPILE(
+[#include <sys/socket.h>],
+[ int sopt = SO_PEERCRED;
+   exit(sopt);],
+[have_so_peercred="yes"; AC_DEFINE(HAVE_SO_PEERCRED)],
+[have_so_peercred="no"])
+AC_MSG_RESULT($have_so_peercred)])
+#
+# ----------------------------------------------------------------
+# AC_W3M_GETPEEREID
+# ----------------------------------------------------------------
+AC_DEFUN([AC_W3M_GETPEEREID],
+[AC_SUBST(HAVE_GETPEEREID)
+AC_MSG_CHECKING(for getpeereid)
+AC_CHECK_FUNC(getpeereid, 
+[have_getpeereid="yes"; AC_DEFINE(HAVE_GETPEEREID)],
+[have_getpeereid="no"])])
Index: aclocal.m4
===================================================================
RCS file: /cvsroot/w3m/w3m/aclocal.m4,v
retrieving revision 1.41
diff -u -r1.41 aclocal.m4
--- aclocal.m4	14 Feb 2005 16:36:30 -0000	1.41
+++ aclocal.m4	28 Jun 2005 13:27:55 -0000
@@ -82,6 +82,18 @@
 AC_MSG_RESULT($enable_mouse)])
 #
 # ----------------------------------------------------------------
+# AC_W3M_REMOTE
+# ----------------------------------------------------------------
+AC_DEFUN([AC_W3M_REMOTE],
+[AC_SUBST(USE_MOUSE)
+AC_MSG_CHECKING(if remote operation enabled)
+AC_ARG_ENABLE(remote,
+ [  --disable-remote		disable remote operation],,
+ [enable_remote="yes"])
+test x"$enable_remote" = xyes && AC_DEFINE(USE_REMOTE)
+AC_MSG_RESULT($enable_remote)])
+#
+# ----------------------------------------------------------------
 # AC_W3M_COOKIE
 # ----------------------------------------------------------------
 AC_DEFUN([AC_W3M_COOKIE],
@@ -890,6 +902,31 @@
   AC_DEFINE(SIGNAL_RETURN,return 0)
  fi])
 
+#
+# ----------------------------------------------------------------
+# AC_W3M_SO_PEERCRED
+# ----------------------------------------------------------------
+AC_DEFUN([AC_W3M_SO_PEERCRED],
+[AC_SUBST(HAVE_SO_PEERCRED)
+AC_MSG_CHECKING(for SO_PEERCRED)
+AC_TRY_COMPILE(
+[#include <sys/socket.h>],
+[ int sopt = SO_PEERCRED;
+   exit(sopt);],
+[have_so_peercred="yes"; AC_DEFINE(HAVE_SO_PEERCRED)],
+[have_so_peercred="no"])
+AC_MSG_RESULT($have_so_peercred)])
+#
+# ----------------------------------------------------------------
+# AC_W3M_GETPEEREID
+# ----------------------------------------------------------------
+AC_DEFUN([AC_W3M_GETPEEREID],
+[AC_SUBST(HAVE_GETPEEREID)
+AC_MSG_CHECKING(for getpeereid)
+AC_CHECK_FUNC(getpeereid, 
+[have_getpeereid="yes"; AC_DEFINE(HAVE_GETPEEREID)],
+[have_getpeereid="no"])])
+
 # lib-prefix.m4 serial 3 (gettext-0.13)
 dnl Copyright (C) 2001-2003 Free Software Foundation, Inc.
 dnl This file is free software, distributed under the terms of the GNU
Index: config.h.in
===================================================================
RCS file: /cvsroot/w3m/w3m/config.h.in,v
retrieving revision 1.16
diff -u -r1.16 config.h.in
--- config.h.in	26 Feb 2005 17:06:44 -0000	1.16
+++ config.h.in	28 Jun 2005 13:27:56 -0000
@@ -53,6 +53,7 @@
 #undef USE_MIGEMO
 #define USE_MARK
 #undef USE_MOUSE
+#undef USE_REMOTE
 #undef USE_GPM
 #undef USE_SYSMOUSE
 #undef USE_MENU
@@ -143,6 +144,8 @@
 #undef HAVE_SETPGRP
 #undef HAVE_SETLOCALE
 #undef HAVE_LANGINFO_CODESET
+#undef HAVE_SO_PEERCRED
+#undef HAVE_GETPEEREID
 
 #undef SETPGRP_VOID
 #ifdef HAVE_SETPGRP
Index: configure
===================================================================
RCS file: /cvsroot/w3m/w3m/configure,v
retrieving revision 1.153
diff -u -r1.153 configure
--- configure	26 Feb 2005 17:13:58 -0000	1.153
+++ configure	28 Jun 2005 13:27:59 -0000
@@ -310,7 +310,7 @@
 # include <unistd.h>
 #endif"
 
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS PACKAGE VERSION W3M W3M_LANG AWK CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE RANLIB ac_ct_RANLIB PERL NKF MAN build build_cpu build_vendor build_os host host_cpu host_vendor host_os W3M_TARGET W3M_LIBS USE_M17N USE_UNICODE WCTARGET WCCFLAGS DISPLAY_CHARSET SYSTEM_CHARSET DOCUMENT_CHARSET POSUBST POLANG MKINSTALLDIRS USE_NLS MSGFMT GMSGFMT XGETTEXT MSGMERGE LIBICONV LTLIBICONV INTLLIBS LIBINTL LTLIBINTL POSUB INTLTARGET NLSTARGET USE_COLOR USE_ANSI_COLOR USE_BG_COLOR USE_IMAGE USE_W3
 MIMG_X11 USE_W3MIMG_FB W3MIMGDISPLAY_SETUID INSTALL_W3MIMGDISPLAY USE_GDKPIXBUF USE_GTK2 !
 USE_IMLIB USE_IMLIB2 IMGTARGETS IMGOBJS IMGX11CFLAGS IMGX11LDFLAGS IMGFBCFLAGS IMGFBLDFLAGS USE_XFACE uncompface KEYMAP_FILE HELP_FILE KEYBIND USE_MENU USE_MOUSE USE_HISTORY USE_ALARM USE_COOKIE USE_DIGEST_AUTH USE_NNTP USE_GOPHER USE_DICT USE_HELP_CGI USE_EXTERNAL_URI_LOADER USE_W3MMAILER USE_MIGEMO DEF_MIGEMO_COMMAND DEF_EDITOR DEF_MAILER DEF_EXT_BROWSER INET6 HAVE_OLD_SS_FAMILY USE_SSL USE_SSL_VERIFY PKG_CONFIG SSL_CFLAGS SSL_LIBS USE_W3M USE_SYSMOUSE AUXBIN_TARGETS EGREP USE_BINMODE_STREAM HAVE_SYS_ERRLIST HAVE_SIGSETJMP RETSIGTYPE SIGNAL_RETURN HELP_DIR RC_DIR DOCDIRS CURRENT_VERSION LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS PACKAGE VERSION W3M W3M_LANG AWK CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE RANLIB ac_ct_RANLIB PERL NKF MAN build build_cpu build_vendor build_os host host_cpu host_vendor host_os W3M_TARGET W3M_LIBS USE_M17N USE_UNICODE WCTARGET WCCFLAGS DISPLAY_CHARSET SYSTEM_CHARSET DOCUMENT_CHARSET POSUBST POLANG MKINSTALLDIRS USE_NLS MSGFMT GMSGFMT XGETTEXT MSGMERGE LIBICONV LTLIBICONV INTLLIBS LIBINTL LTLIBINTL POSUB INTLTARGET NLSTARGET USE_COLOR USE_ANSI_COLOR USE_BG_COLOR USE_IMAGE USE_W3
 MIMG_X11 USE_W3MIMG_FB W3MIMGDISPLAY_SETUID INSTALL_W3MIMGDISPLAY USE_GDKPIXBUF USE_GTK2 !
 USE_IMLIB USE_IMLIB2 IMGTARGETS IMGOBJS IMGX11CFLAGS IMGX11LDFLAGS IMGFBCFLAGS IMGFBLDFLAGS USE_XFACE uncompface KEYMAP_FILE HELP_FILE KEYBIND USE_MENU USE_MOUSE USE_HISTORY USE_ALARM USE_COOKIE USE_DIGEST_AUTH USE_NNTP USE_GOPHER USE_DICT USE_HELP_CGI USE_EXTERNAL_URI_LOADER USE_W3MMAILER USE_MIGEMO DEF_MIGEMO_COMMAND DEF_EDITOR DEF_MAILER DEF_EXT_BROWSER INET6 HAVE_OLD_SS_FAMILY USE_SSL USE_SSL_VERIFY PKG_CONFIG SSL_CFLAGS SSL_LIBS USE_W3M USE_SYSMOUSE AUXBIN_TARGETS EGREP USE_BINMODE_STREAM HAVE_SYS_ERRLIST HAVE_SIGSETJMP RETSIGTYPE SIGNAL_RETURN HAVE_SO_PEERCRED HAVE_GETPEEREID HELP_DIR RC_DIR DOCDIRS CURRENT_VERSION LIBOBJS LTLIBOBJS'
 ac_subst_files=''
 
 # Initialize some variables set by options.
@@ -866,6 +866,7 @@
   --disable-mouse		disable mouse operation
   --disable-history		disable URL history
   --disable-alarm		disable alarm
+  --disable-remote		disable remote operation
   --disable-cookie		disable cookie
   --disable-digest-auth		disable digest auth
   --disable-nntp		disable NNTP
@@ -5502,6 +5503,22 @@
 rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
  fi
 
+echo "$as_me:$LINENO: checking if remote operation enabled" >&5
+echo $ECHO_N "checking if remote operation enabled... $ECHO_C" >&6
+# Check whether --enable-remote or --disable-remote was given.
+if test "${enable_remote+set}" = set; then
+  enableval="$enable_remote"
+
+else
+  enable_remote="yes"
+fi;
+test x"$enable_remote" = xyes && cat >>confdefs.h <<\_ACEOF
+#define USE_REMOTE 1
+_ACEOF
+
+echo "$as_me:$LINENO: result: $enable_remote" >&5
+echo "${ECHO_T}$enable_remote" >&6
+
 
 echo "$as_me:$LINENO: checking if cookie is enabled" >&5
 echo $ECHO_N "checking if cookie is enabled... $ECHO_C" >&6
@@ -10256,6 +10273,160 @@
 
  fi
 
+echo "$as_me:$LINENO: checking for SO_PEERCRED" >&5
+echo $ECHO_N "checking for SO_PEERCRED... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <sys/socket.h>
+int
+main ()
+{
+ int sopt = SO_PEERCRED;
+   exit(sopt);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+  (eval $ac_compile) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest.$ac_objext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  have_so_peercred="yes"; cat >>confdefs.h <<\_ACEOF
+#define HAVE_SO_PEERCRED 1
+_ACEOF
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+have_so_peercred="no"
+fi
+rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $have_so_peercred" >&5
+echo "${ECHO_T}$have_so_peercred" >&6
+
+echo "$as_me:$LINENO: checking for getpeereid" >&5
+echo $ECHO_N "checking for getpeereid... $ECHO_C" >&6
+echo "$as_me:$LINENO: checking for getpeereid" >&5
+echo $ECHO_N "checking for getpeereid... $ECHO_C" >&6
+if test "${ac_cv_func_getpeereid+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define getpeereid to an innocuous variant, in case <limits.h> declares getpeereid.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define getpeereid innocuous_getpeereid
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char getpeereid (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef getpeereid
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char getpeereid ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_getpeereid) || defined (__stub___getpeereid)
+choke me
+#else
+char (*f) () = getpeereid;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != getpeereid;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_getpeereid=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_getpeereid=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_getpeereid" >&5
+echo "${ECHO_T}$ac_cv_func_getpeereid" >&6
+if test $ac_cv_func_getpeereid = yes; then
+  have_getpeereid="yes"; cat >>confdefs.h <<\_ACEOF
+#define HAVE_GETPEEREID 1
+_ACEOF
+
+else
+  have_getpeereid="no"
+fi
+
+
 
 HELP_DIR="$datadir/$PACKAGE"
 cat >>confdefs.h <<\_ACEOF
@@ -11042,6 +11213,8 @@
 s,@HAVE_SIGSETJMP@,$HAVE_SIGSETJMP,;t t
 s,@RETSIGTYPE@,$RETSIGTYPE,;t t
 s,@SIGNAL_RETURN@,$SIGNAL_RETURN,;t t
+s,@HAVE_SO_PEERCRED@,$HAVE_SO_PEERCRED,;t t
+s,@HAVE_GETPEEREID@,$HAVE_GETPEEREID,;t t
 s,@HELP_DIR@,$HELP_DIR,;t t
 s,@RC_DIR@,$RC_DIR,;t t
 s,@DOCDIRS@,$DOCDIRS,;t t
Index: configure.ac
===================================================================
RCS file: /cvsroot/w3m/w3m/configure.ac,v
retrieving revision 1.1
diff -u -r1.1 configure.ac
--- configure.ac	26 Feb 2005 17:13:59 -0000	1.1
+++ configure.ac	28 Jun 2005 13:27:59 -0000
@@ -67,6 +67,7 @@
 AC_W3M_MOUSE
 AC_W3M_HISTORY
 AC_W3M_ALARM
+AC_W3M_REMOTE
 
 AC_W3M_COOKIE
 AC_W3M_DIGEST_AUTH
@@ -152,6 +153,8 @@
 AC_W3M_SYS_ERRLIST
 AC_W3M_SIGSETJMP
 AC_W3M_SIGNAL
+AC_W3M_SO_PEERCRED
+AC_W3M_GETPEEREID
 
 AC_SUBST(HELP_DIR)
 HELP_DIR="$datadir/$PACKAGE"
Index: main.c
===================================================================
RCS file: /cvsroot/w3m/w3m/main.c,v
retrieving revision 1.247
diff -u -r1.247 main.c
--- main.c	26 Feb 2005 17:06:44 -0000	1.247
+++ main.c	28 Jun 2005 13:28:01 -0000
@@ -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>
@@ -104,6 +111,19 @@
 #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 +154,9 @@
 	    ",sysmouse"
 #endif
 #endif
+#ifdef USE_REMOTE
+	    ",remote"
+#endif
 #ifdef USE_MENU
 	    ",menu"
 #endif
@@ -229,6 +252,11 @@
 #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 +755,33 @@
 	    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,7 +796,11 @@
 	}
 	i++;
     }
-
+#ifdef USE_REMOTE
+    if (ExecuteRemote) {
+      exit(0);
+    }
+#endif
 #ifdef	__WATT32__
     if (w3m_debug)
 	dbug_init();
@@ -1028,6 +1087,13 @@
     if (line_str) {
 	_goLine(line_str);
     }
+
+#ifdef USE_REMOTE
+    if (UseRemote) {
+      init_serv();
+    }
+#endif
+
     for (;;) {
 	if (add_download_list) {
 	    add_download_list = FALSE;
@@ -1098,7 +1164,20 @@
 	    } 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
@@ -1130,6 +1209,237 @@
     }
 }
 
+#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)
 {
@@ -5714,6 +6024,11 @@
 #ifdef USE_NNTP
     disconnectNews();
 #endif
+#ifdef USE_REMOTE
+    if (UseRemote) {
+      unlink(SockName->ptr);
+    }
+#endif
     exit(i);
 }
 
Index: proto.h
===================================================================
RCS file: /cvsroot/w3m/w3m/proto.h,v
retrieving revision 1.99
diff -u -r1.99 proto.h
--- proto.h	16 Apr 2004 18:47:19 -0000	1.99
+++ proto.h	28 Jun 2005 13:28:01 -0000
@@ -492,6 +492,9 @@
 extern void flush_tty(void);
 extern void toggle_stand(void);
 extern char getch(void);
+#ifdef USE_REMOTE
+char getch_select(int fd, int *num);
+#endif
 extern void bell(void);
 extern int sleep_till_anykey(int sec, int purge);
 #ifdef USE_IMAGE
Index: terms.c
===================================================================
RCS file: /cvsroot/w3m/w3m/terms.c,v
retrieving revision 1.53
diff -u -r1.53 terms.c
--- terms.c	18 Jan 2005 16:38:01 -0000	1.53
+++ terms.c	28 Jun 2005 13:28:02 -0000
@@ -1830,6 +1830,44 @@
     return c;
 }
 
+#ifdef USE_REMOTE
+char
+getch_select(int fd, int *fdn)
+{
+  int maxfd = tty;
+  fd_set rset;
+
+  if (fd < 0 || fd == tty) {
+    *fdn = 0;
+    return getch();
+  }
+
+  if (maxfd < fd)
+    maxfd = fd;
+
+  maxfd++;
+
+  FD_ZERO(&rset);
+  FD_SET(tty, &rset);
+  FD_SET(fd, &rset);
+
+  while (select(maxfd, &rset, NULL, NULL, NULL) < 1) {
+    FD_ZERO(&rset);
+    FD_SET(tty, &rset);
+    FD_SET(fd, &rset);
+  }
+
+  if (FD_ISSET(tty, &rset)) {
+    *fdn = 0;
+    return getch();
+  } else if (FD_ISSET(fd, &rset)) {
+    *fdn = 1;
+  }
+  return 0;
+}
+#endif
+
+
 #ifdef USE_MOUSE
 #ifdef USE_GPM
 char