unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* preliminary patch for emacsclient.c
@ 2002-11-07  5:12 Ben Key
  0 siblings, 0 replies; only message in thread
From: Ben Key @ 2002-11-07  5:12 UTC (permalink / raw)


[-- Attachment #1: Type: text/plain, Size: 196 bytes --]

As requested, here is a patch that incorporates the changes I have made so
far to emacsclient.c.  These changes have not been fully tested since I have
not been able to get server-start to work.


[-- Attachment #2: 21_3-emacsclient.c.diff --]
[-- Type: application/octet-stream, Size: 28202 bytes --]

--- _21.3/lib-src/emacsclient.c	2002-09-30 20:45:30.000000000 -0400
+++ 21.3/lib-src/emacsclient.c	2002-11-06 23:47:58.000000000 -0500
@@ -40,7 +40,18 @@
 #else
 # include <pwd.h>
 #endif /* not VMS */
-
+#ifdef WINDOWSNT
+# include <errno.h>
+# include <fcntl.h>
+  extern int _execvp (const char*, char* const*);
+#  ifndef HAVE_STRUCT_SOCKADDR_UN
+    struct sockaddr_un
+		{
+			short int sun_family; /* AF_UNIX */
+			char sun_path[108]; /* path name (gag) */
+		};
+#  endif
+#endif
 char *getenv (), *getwd ();
 char *getcwd ();

@@ -229,7 +240,6 @@
 }


-\f
 #if !defined (HAVE_SOCKETS) || defined (NO_SOCKETS_IN_FILE_SYSTEM)

 int
@@ -248,7 +258,904 @@

 #include <sys/types.h>
 #include <sys/socket.h>
+#ifndef WINDOWSNT
 #include <sys/un.h>
+#endif
+#ifdef WINDOWSNT
+/*
+	BEGIN: Borrowed from w32.c
+*/
+/* parallel array of private info on file handles */
+filedesc fd_info [ MAXDESC ];
+/* Wrappers for  winsock functions to map between our file descriptors
+   and winsock's handles; also set h_errno for convenience.
+
+   To allow Emacs to run on systems which don't have winsock support
+   installed, we dynamically link to winsock on startup if present, and
+   otherwise provide the minimum necessary functionality
+   (eg. gethostname). */
+
+/* function pointers for relevant socket functions */
+int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
+void (PASCAL *pfn_WSASetLastError) (int iError);
+int (PASCAL *pfn_WSAGetLastError) (void);
+int (PASCAL *pfn_socket) (int af, int type, int protocol);
+int (PASCAL *pfn_bind) (SOCKET s, const struct sockaddr *addr, int namelen);
+int (PASCAL *pfn_connect) (SOCKET s, const struct sockaddr *addr, int namelen);
+int (PASCAL *pfn_ioctlsocket) (SOCKET s, long cmd, u_long *argp);
+int (PASCAL *pfn_recv) (SOCKET s, char * buf, int len, int flags);
+int (PASCAL *pfn_send) (SOCKET s, const char * buf, int len, int flags);
+int (PASCAL *pfn_closesocket) (SOCKET s);
+int (PASCAL *pfn_shutdown) (SOCKET s, int how);
+int (PASCAL *pfn_WSACleanup) (void);
+u_short (PASCAL *pfn_htons) (u_short hostshort);
+u_short (PASCAL *pfn_ntohs) (u_short netshort);
+unsigned long (PASCAL *pfn_inet_addr) (const char * cp);
+int (PASCAL *pfn_gethostname) (char * name, int namelen);
+struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
+struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto);
+int (PASCAL *pfn_getpeername) (SOCKET s, struct sockaddr *addr, int * namelen);
+int (PASCAL *pfn_setsockopt) (SOCKET s, int level, int optname,
+			      const char * optval, int optlen);
+int (PASCAL *pfn_listen) (SOCKET s, int backlog);
+int (PASCAL *pfn_getsockname) (SOCKET s, struct sockaddr * name,
+			       int * namelen);
+SOCKET (PASCAL *pfn_accept) (SOCKET s, struct sockaddr * addr, int * addrlen);
+int (PASCAL *pfn_recvfrom) (SOCKET s, char * buf, int len, int flags,
+		       struct sockaddr * from, int * fromlen);
+int (PASCAL *pfn_sendto) (SOCKET s, const char * buf, int len, int flags,
+			  const struct sockaddr * to, int tolen);
+
+/* SetHandleInformation is only needed to make sockets non-inheritable. */
+BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags);
+#ifndef HANDLE_FLAG_INHERIT
+#define HANDLE_FLAG_INHERIT	1
+#endif
+
+HANDLE winsock_lib;
+static int winsock_inuse;
+BOOL
+term_winsock (void)
+{
+  if (winsock_lib != NULL && winsock_inuse == 0)
+    {
+      /* Not sure what would cause WSAENETDOWN, or even if it can happen
+	 after WSAStartup returns successfully, but it seems reasonable
+	 to allow unloading winsock anyway in that case. */
+      if (pfn_WSACleanup () == 0 ||
+					pfn_WSAGetLastError () == WSAENETDOWN)
+				{
+					if (FreeLibrary (winsock_lib))
+						winsock_lib = NULL;
+					return TRUE;
+				}
+    }
+  return FALSE;
+}
+
+BOOL
+init_winsock (int load_now)
+{
+  WSADATA  winsockData;
+  if (winsock_lib != NULL)
+    return TRUE;
+  pfn_SetHandleInformation = NULL;
+  pfn_SetHandleInformation
+    = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
+															 "SetHandleInformation");
+  winsock_lib = LoadLibrary ("wsock32.dll");
+  if (winsock_lib != NULL)
+    {
+      /* dynamically link to socket functions */
+#define LOAD_PROC(fn) \
+      if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
+        goto fail;
+      LOAD_PROC( WSAStartup );
+      LOAD_PROC( WSASetLastError );
+      LOAD_PROC( WSAGetLastError );
+      LOAD_PROC( socket );
+      LOAD_PROC( bind );
+      LOAD_PROC( connect );
+      LOAD_PROC( ioctlsocket );
+      LOAD_PROC( recv );
+      LOAD_PROC( send );
+      LOAD_PROC( closesocket );
+      LOAD_PROC( shutdown );
+      LOAD_PROC( htons );
+      LOAD_PROC( ntohs );
+      LOAD_PROC( inet_addr );
+      LOAD_PROC( gethostname );
+      LOAD_PROC( gethostbyname );
+      LOAD_PROC( getservbyname );
+      LOAD_PROC( getpeername );
+      LOAD_PROC( WSACleanup );
+      LOAD_PROC( setsockopt );
+      LOAD_PROC( listen );
+      LOAD_PROC( getsockname );
+      LOAD_PROC( accept );
+      LOAD_PROC( recvfrom );
+      LOAD_PROC( sendto );
+#undef LOAD_PROC
+      /* specify version 1.1 of winsock */
+      if (pfn_WSAStartup (0x101, &winsockData) == 0)
+        {
+					if (winsockData.wVersion != 0x101)
+						goto fail;
+					if (!load_now)
+						{
+							/* Report that winsock exists and is usable, but leave
+								 socket functions disabled.  I am assuming that calling
+								 WSAStartup does not require any network interaction,
+								 and in particular does not cause or require a dial-up
+								 connection to be established. */
+							pfn_WSACleanup ();
+							FreeLibrary (winsock_lib);
+							winsock_lib = NULL;
+						}
+					winsock_inuse = 0;
+					return TRUE;
+				}
+    fail:
+      FreeLibrary (winsock_lib);
+      winsock_lib = NULL;
+    }
+  return FALSE;
+}
+
+int h_errno = 0;
+
+/* function to set h_errno for compatability; map winsock error codes to
+   normal system codes where they overlap (non-overlapping definitions
+   are already in <sys/socket.h> */
+static void set_errno ()
+{
+  if (winsock_lib == NULL)
+    h_errno = EINVAL;
+  else
+    h_errno = pfn_WSAGetLastError ();
+  switch (h_errno)
+    {
+    case WSAEACCES:		h_errno = EACCES; break;
+    case WSAEBADF: 		h_errno = EBADF; break;
+    case WSAEFAULT:		h_errno = EFAULT; break;
+    case WSAEINTR: 		h_errno = EINTR; break;
+    case WSAEINVAL:		h_errno = EINVAL; break;
+    case WSAEMFILE:		h_errno = EMFILE; break;
+    case WSAENAMETOOLONG: 	h_errno = ENAMETOOLONG; break;
+    case WSAENOTEMPTY:		h_errno = ENOTEMPTY; break;
+    }
+  errno = h_errno;
+}
+
+static void check_errno ()
+{
+  if (h_errno == 0 && winsock_lib != NULL)
+    pfn_WSASetLastError (0);
+}
+
+/* Extend strerror to handle the winsock-specific error codes.  */
+struct {
+  int errnum;
+  char * msg;
+} _wsa_errlist[] = {
+  WSAEINTR                , "Interrupted function call",
+  WSAEBADF                , "Bad file descriptor",
+  WSAEACCES               , "Permission denied",
+  WSAEFAULT               , "Bad address",
+  WSAEINVAL               , "Invalid argument",
+  WSAEMFILE               , "Too many open files",
+  WSAEWOULDBLOCK          , "Resource temporarily unavailable",
+  WSAEINPROGRESS          , "Operation now in progress",
+  WSAEALREADY             , "Operation already in progress",
+  WSAENOTSOCK             , "Socket operation on non-socket",
+  WSAEDESTADDRREQ         , "Destination address required",
+  WSAEMSGSIZE             , "Message too long",
+  WSAEPROTOTYPE           , "Protocol wrong type for socket",
+  WSAENOPROTOOPT          , "Bad protocol option",
+  WSAEPROTONOSUPPORT      , "Protocol not supported",
+  WSAESOCKTNOSUPPORT      , "Socket type not supported",
+  WSAEOPNOTSUPP           , "Operation not supported",
+  WSAEPFNOSUPPORT         , "Protocol family not supported",
+  WSAEAFNOSUPPORT         , "Address family not supported by protocol family",
+  WSAEADDRINUSE           , "Address already in use",
+  WSAEADDRNOTAVAIL        , "Cannot assign requested address",
+  WSAENETDOWN             , "Network is down",
+  WSAENETUNREACH          , "Network is unreachable",
+  WSAENETRESET            , "Network dropped connection on reset",
+  WSAECONNABORTED         , "Software caused connection abort",
+  WSAECONNRESET           , "Connection reset by peer",
+  WSAENOBUFS              , "No buffer space available",
+  WSAEISCONN              , "Socket is already connected",
+  WSAENOTCONN             , "Socket is not connected",
+  WSAESHUTDOWN            , "Cannot send after socket shutdown",
+  WSAETOOMANYREFS         , "Too many references",	    /* not sure */
+  WSAETIMEDOUT            , "Connection timed out",
+  WSAECONNREFUSED         , "Connection refused",
+  WSAELOOP                , "Network loop",		    /* not sure */
+  WSAENAMETOOLONG         , "Name is too long",
+  WSAEHOSTDOWN            , "Host is down",
+  WSAEHOSTUNREACH         , "No route to host",
+  WSAENOTEMPTY            , "Buffer not empty",		    /* not sure */
+  WSAEPROCLIM             , "Too many processes",
+  WSAEUSERS               , "Too many users",		    /* not sure */
+  WSAEDQUOT               , "Double quote in host name",    /* really not sure */
+  WSAESTALE               , "Data is stale",		    /* not sure */
+  WSAEREMOTE              , "Remote error",		    /* not sure */
+  WSASYSNOTREADY          , "Network subsystem is unavailable",
+  WSAVERNOTSUPPORTED      , "WINSOCK.DLL version out of range",
+  WSANOTINITIALISED       , "Winsock not initialized successfully",
+  WSAEDISCON              , "Graceful shutdown in progress",
+#ifdef WSAENOMORE
+  WSAENOMORE              , "No more operations allowed",   /* not sure */
+  WSAECANCELLED           , "Operation cancelled",	    /* not sure */
+  WSAEINVALIDPROCTABLE    , "Invalid procedure table from service provider",
+  WSAEINVALIDPROVIDER     , "Invalid service provider version number",
+  WSAEPROVIDERFAILEDINIT  , "Unable to initialize a service provider",
+  WSASYSCALLFAILURE       , "System call failured",
+  WSASERVICE_NOT_FOUND    , "Service not found",	    /* not sure */
+  WSATYPE_NOT_FOUND       , "Class type not found",
+  WSA_E_NO_MORE           , "No more resources available",  /* really not sure */
+  WSA_E_CANCELLED         , "Operation already cancelled",  /* really not sure */
+  WSAEREFUSED             , "Operation refused",	    /* not sure */
+#endif
+  WSAHOST_NOT_FOUND       , "Host not found",
+  WSATRY_AGAIN            , "Authoritative host not found during name lookup",
+  WSANO_RECOVERY          , "Non-recoverable error during name lookup",
+  WSANO_DATA              , "Valid name, no data record of requested type",
+  -1, NULL
+};
+
+char *
+sys_strerror(int error_no)
+{
+  int i;
+  static char unknown_msg[40];
+  if (error_no >= 0 && error_no < sys_nerr)
+    return sys_errlist[error_no];
+  for (i = 0; _wsa_errlist[i].errnum >= 0; i++)
+    if (_wsa_errlist[i].errnum == error_no)
+      return _wsa_errlist[i].msg;
+  sprintf(unknown_msg, "Unidentified error: %d", error_no);
+  return unknown_msg;
+}
+
+/* [andrewi 3-May-96] I've had conflicting results using both methods,
+   but I believe the method of keeping the socket handle separate (and
+   insuring it is not inheritable) is the correct one. */
+
+//#define SOCK_REPLACE_HANDLE
+
+#ifdef SOCK_REPLACE_HANDLE
+#define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
+#else
+#define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
+#endif
+
+int socket_to_fd (SOCKET s);
+
+int
+sys_socket(int af, int type, int protocol)
+{
+	SOCKET s;
+
+  if (winsock_lib == NULL)
+    {
+      h_errno = ENETDOWN;
+      return INVALID_SOCKET;
+    }
+
+  check_errno ();
+
+  /* call the real socket function */
+  s = pfn_socket (af, type, protocol);
+
+  if (s != INVALID_SOCKET)
+    return socket_to_fd (s);
+
+  set_errno ();
+  return -1;
+}
+
+/* Convert a SOCKET to a file descriptor.  */
+int
+socket_to_fd (SOCKET s)
+{
+  int fd;
+  child_process * cp;
+
+  /* Although under NT 3.5 _open_osfhandle will accept a socket
+     handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
+     that does not work under NT 3.1.  However, we can get the same
+     effect by using a backdoor function to replace an existing
+     descriptor handle with the one we want. */
+
+  /* allocate a file descriptor (with appropriate flags) */
+  fd = _open ("NUL:", _O_RDWR);
+  if (fd >= 0)
+    {
+#ifdef SOCK_REPLACE_HANDLE
+      /* now replace handle to NUL with our socket handle */
+      CloseHandle ((HANDLE) _get_osfhandle (fd));
+      _free_osfhnd (fd);
+      _set_osfhnd (fd, s);
+      /* setmode (fd, _O_BINARY); */
+#else
+      /* Make a non-inheritable copy of the socket handle.  Note
+	 that it is possible that sockets aren't actually kernel
+	 handles, which appears to be the case on Windows 9x when
+	 the MS Proxy winsock client is installed.  */
+      {
+	/* Apparently there is a bug in NT 3.51 with some service
+	   packs, which prevents using DuplicateHandle to make a
+	   socket handle non-inheritable (causes WSACleanup to
+	   hang).  The work-around is to use SetHandleInformation
+	   instead if it is available and implemented. */
+	if (pfn_SetHandleInformation)
+	  {
+	    pfn_SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0);
+	  }
+	else
+	  {
+	    HANDLE parent = GetCurrentProcess ();
+	    HANDLE new_s = INVALID_HANDLE_VALUE;
+
+	    if (DuplicateHandle (
+							parent,
+							(HANDLE) s,
+							parent,
+							&new_s,
+							0,
+							FALSE,
+							DUPLICATE_SAME_ACCESS))
+	      {
+					/* It is possible that DuplicateHandle succeeds even
+						 though the socket wasn't really a kernel handle,
+						 because a real handle has the same value.  So
+						 test whether the new handle really is a socket.  */
+					long nonblocking = 0;
+					if (pfn_ioctlsocket ((SOCKET) new_s, FIONBIO, &nonblocking) == 0)
+						{
+							pfn_closesocket (s);
+							s = (SOCKET) new_s;
+						}
+					else
+						{
+							CloseHandle (new_s);
+						}
+	      }
+	  }
+      }
+      fd_info[fd].hnd = (HANDLE) s;
+#endif
+
+      /* set our own internal flags */
+      fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
+
+      cp = new_child ();
+      if (cp)
+	{
+	  cp->fd = fd;
+	  cp->status = STATUS_READ_ACKNOWLEDGED;
+
+	  /* attach child_process to fd_info */
+	  if (fd_info[ fd ].cp != NULL)
+	    {
+	      DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
+	      abort ();
+	    }
+
+	  fd_info[ fd ].cp = cp;
+
+	  /* success! */
+	  winsock_inuse++;	/* count open sockets */
+	  return fd;
+	}
+
+      /* clean up */
+      _close (fd);
+    }
+  pfn_closesocket (s);
+  h_errno = EMFILE;
+  return -1;
+}
+
+
+int
+sys_bind (int s, const struct sockaddr * addr, int namelen)
+{
+  if (winsock_lib == NULL)
+    {
+      h_errno = ENOTSOCK;
+      return SOCKET_ERROR;
+    }
+
+  check_errno ();
+  if (fd_info[s].flags & FILE_SOCKET)
+    {
+      int rc = pfn_bind (SOCK_HANDLE (s), addr, namelen);
+      if (rc == SOCKET_ERROR)
+	set_errno ();
+      return rc;
+    }
+  h_errno = ENOTSOCK;
+  return SOCKET_ERROR;
+}
+
+
+int
+sys_connect (int s, const struct sockaddr * name, int namelen)
+{
+  if (winsock_lib == NULL)
+    {
+      h_errno = ENOTSOCK;
+      return SOCKET_ERROR;
+    }
+
+  check_errno ();
+  if (fd_info[s].flags & FILE_SOCKET)
+    {
+      int rc = pfn_connect (SOCK_HANDLE (s), name, namelen);
+      if (rc == SOCKET_ERROR)
+	set_errno ();
+      return rc;
+    }
+  h_errno = ENOTSOCK;
+  return SOCKET_ERROR;
+}
+
+int
+sys_gethostname (char * name, int namelen)
+{
+  if (winsock_lib != NULL)
+    return pfn_gethostname (name, namelen);
+
+  if (namelen > MAX_COMPUTERNAME_LENGTH)
+    return !GetComputerName (name, (DWORD *)&namelen);
+
+  h_errno = EFAULT;
+  return SOCKET_ERROR;
+}
+
+/* Function to do blocking read of one byte, needed to implement
+   select.  It is only allowed on sockets and pipes. */
+int
+_sys_read_ahead (int fd)
+{
+  child_process * cp;
+  int rc;
+
+  if (fd < 0 || fd >= MAXDESC)
+    return STATUS_READ_ERROR;
+
+  cp = fd_info[fd].cp;
+
+  if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
+    return STATUS_READ_ERROR;
+
+  if ((fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) == 0
+      || (fd_info[fd].flags & FILE_READ) == 0)
+    {
+      DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd));
+      abort ();
+    }
+
+  cp->status = STATUS_READ_IN_PROGRESS;
+
+  if (fd_info[fd].flags & FILE_PIPE)
+    {
+      rc = _read (fd, &cp->chr, sizeof (char));
+
+      /* Give subprocess time to buffer some more output for us before
+	 reporting that input is available; we need this because Windows 95
+	 connects DOS programs to pipes by making the pipe appear to be
+	 the normal console stdout - as a result most DOS programs will
+	 write to stdout without buffering, ie.  one character at a
+	 time.  Even some W32 programs do this - "dir" in a command
+	 shell on NT is very slow if we don't do this. */
+      if (rc > 0)
+	{
+	  int wait = 0;
+		if (nowait==0)
+			{
+				wait=100;
+			}
+		if (wait > 0)
+	    Sleep (wait);
+	  else if (wait < 0)
+	    while (++wait <= 0)
+	      /* Yield remainder of our time slice, effectively giving a
+		 temporary priority boost to the child process. */
+	      Sleep (0);
+	}
+    }
+#ifdef HAVE_SOCKETS
+  else if (fd_info[fd].flags & FILE_SOCKET)
+    {
+      unsigned long nblock = 0;
+      /* We always want this to block, so temporarily disable NDELAY.  */
+      if (fd_info[fd].flags & FILE_NDELAY)
+	pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
+
+      rc = pfn_recv (SOCK_HANDLE (fd), &cp->chr, sizeof (char), 0);
+
+      if (fd_info[fd].flags & FILE_NDELAY)
+	{
+	  nblock = 1;
+	  pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
+	}
+    }
+#endif
+
+  if (rc == sizeof (char))
+    cp->status = STATUS_READ_SUCCEEDED;
+  else
+    cp->status = STATUS_READ_FAILED;
+
+  return cp->status;
+}
+
+/*
+BEGIN: Borrowed from w32proc.c
+*/
+
+/* Emulate getpwuid, getpwnam and others.  */
+
+#define PASSWD_FIELD_SIZE 256
+
+static char the_passwd_name[PASSWD_FIELD_SIZE];
+static char the_passwd_passwd[PASSWD_FIELD_SIZE];
+static char the_passwd_gecos[PASSWD_FIELD_SIZE];
+static char the_passwd_dir[PASSWD_FIELD_SIZE];
+static char the_passwd_shell[PASSWD_FIELD_SIZE];
+
+static struct passwd the_passwd =
+{
+  the_passwd_name,
+  the_passwd_passwd,
+  0,
+  0,
+  0,
+  the_passwd_gecos,
+  the_passwd_dir,
+  the_passwd_shell,
+};
+
+int
+getuid ()
+{
+  return the_passwd.pw_uid;
+}
+
+int
+geteuid ()
+{
+  /* I could imagine arguing for checking to see whether the user is
+     in the Administrators group and returning a UID of 0 for that
+     case, but I don't know how wise that would be in the long run.  */
+  return getuid ();
+}
+
+int
+getgid ()
+{
+  return the_passwd.pw_gid;
+}
+
+int
+getegid ()
+{
+  return getgid ();
+}
+
+struct passwd *
+getpwuid (int uid)
+{
+  if (uid == the_passwd.pw_uid)
+    return &the_passwd;
+  return NULL;
+}
+
+struct passwd *
+getpwnam (char *name)
+{
+  struct passwd *pw;
+
+  pw = getpwuid (getuid ());
+  if (!pw)
+    return pw;
+
+  if (stricmp (name, pw->pw_name))
+    return NULL;
+
+  return pw;
+}
+
+void
+init_user_info ()
+{
+  /* Find the user's real name by opening the process token and
+     looking up the name associated with the user-sid in that token.
+
+     Use the relative portion of the identifier authority value from
+     the user-sid as the user id value (same for group id using the
+     primary group sid from the process token). */
+
+  char            user_sid[256], name[256], domain[256];
+  DWORD           length = sizeof (name), dlength = sizeof (domain), trash;
+  HANDLE          token = NULL;
+  SID_NAME_USE    user_type;
+
+  if (OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token)
+      && GetTokenInformation (token, TokenUser,
+			      (PVOID) user_sid, sizeof (user_sid), &trash)
+      && LookupAccountSid (NULL, *((PSID *) user_sid), name, &length,
+			   domain, &dlength, &user_type))
+    {
+      strcpy (the_passwd.pw_name, name);
+      /* Determine a reasonable uid value. */
+      if (stricmp ("administrator", name) == 0)
+	{
+	  the_passwd.pw_uid = 0;
+	  the_passwd.pw_gid = 0;
+	}
+      else
+	{
+	  SID_IDENTIFIER_AUTHORITY * pSIA;
+
+	  pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid));
+	  /* I believe the relative portion is the last 4 bytes (of 6)
+	     with msb first. */
+	  the_passwd.pw_uid = ((pSIA->Value[2] << 24) +
+			       (pSIA->Value[3] << 16) +
+			       (pSIA->Value[4] << 8)  +
+			       (pSIA->Value[5] << 0));
+	  /* restrict to conventional uid range for normal users */
+	  the_passwd.pw_uid = the_passwd.pw_uid % 60001;
+
+	  /* Get group id */
+	  if (GetTokenInformation (token, TokenPrimaryGroup,
+				   (PVOID) user_sid, sizeof (user_sid), &trash))
+	    {
+	      SID_IDENTIFIER_AUTHORITY * pSIA;
+
+	      pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid));
+	      the_passwd.pw_gid = ((pSIA->Value[2] << 24) +
+				   (pSIA->Value[3] << 16) +
+				   (pSIA->Value[4] << 8)  +
+				   (pSIA->Value[5] << 0));
+	      /* I don't know if this is necessary, but for safety... */
+	      the_passwd.pw_gid = the_passwd.pw_gid % 60001;
+	    }
+	  else
+	    the_passwd.pw_gid = the_passwd.pw_uid;
+	}
+    }
+  /* If security calls are not supported (presumably because we
+       are running under Windows 95), fallback to this. */
+  else if (GetUserName (name, &length))
+    {
+      strcpy (the_passwd.pw_name, name);
+      if (stricmp ("administrator", name) == 0)
+	the_passwd.pw_uid = 0;
+      else
+	the_passwd.pw_uid = 123;
+      the_passwd.pw_gid = the_passwd.pw_uid;
+    }
+  else
+    {
+      strcpy (the_passwd.pw_name, "unknown");
+      the_passwd.pw_uid = 123;
+      the_passwd.pw_gid = 123;
+    }
+
+  /* Ensure HOME and SHELL are defined. */
+  if (getenv ("HOME") == NULL)
+    abort ();
+  if (getenv ("SHELL") == NULL)
+  {
+	  if (getenv ("ComSpec")==NULL)
+	  {
+		abort ();
+	  }
+  }
+
+  /* Set dir and shell from environment variables. */
+  strcpy (the_passwd.pw_dir, getenv ("HOME"));
+  if (getenv("SHELL"))
+  {
+	strcpy (the_passwd.pw_shell, getenv ("SHELL"));
+  }
+  else
+  {
+	strcpy (the_passwd.pw_shell, getenv ("ComSpec"));
+  }
+
+  if (token)
+    CloseHandle (token);
+}
+
+/*
+END: Borrowed from w32.c
+*/
+
+/*
+BEGIN: Borrowed from w32proc.c
+*/
+
+
+/* Child process management list.  */
+int child_proc_count = 0;
+child_process child_procs[ MAX_CHILDREN ];
+child_process *dead_child = NULL;
+
+DWORD WINAPI reader_thread (void *arg);
+
+child_process *
+new_child (void)
+{
+  child_process *cp;
+  DWORD id;
+
+  for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
+    if (!CHILD_ACTIVE (cp))
+      goto Initialise;
+  if (child_proc_count == MAX_CHILDREN)
+    return NULL;
+  cp = &child_procs[child_proc_count++];
+
+ Initialise:
+  memset (cp, 0, sizeof(*cp));
+  cp->fd = -1;
+  cp->pid = -1;
+  cp->procinfo.hProcess = NULL;
+  cp->status = STATUS_READ_ERROR;
+
+  /* use manual reset event so that select() will function properly */
+  cp->char_avail = CreateEvent (NULL, TRUE, FALSE, NULL);
+  if (cp->char_avail)
+    {
+      cp->char_consumed = CreateEvent (NULL, FALSE, FALSE, NULL);
+      if (cp->char_consumed)
+        {
+	  cp->thrd = CreateThread (NULL, 1024, reader_thread, cp, 0, &id);
+	  if (cp->thrd)
+	    return cp;
+	}
+    }
+  delete_child (cp);
+  return NULL;
+}
+
+void
+delete_child (child_process *cp)
+{
+  int i;
+
+  /* Should not be deleting a child that is still needed. */
+  for (i = 0; i < MAXDESC; i++)
+    if (fd_info[i].cp == cp)
+      abort ();
+
+  if (!CHILD_ACTIVE (cp))
+    return;
+
+  /* reap thread if necessary */
+  if (cp->thrd)
+    {
+      DWORD rc;
+
+      if (GetExitCodeThread (cp->thrd, &rc) && rc == STILL_ACTIVE)
+        {
+	  /* let the thread exit cleanly if possible */
+	  cp->status = STATUS_READ_ERROR;
+	  SetEvent (cp->char_consumed);
+	  if (WaitForSingleObject (cp->thrd, 1000) != WAIT_OBJECT_0)
+	    {
+	      DebPrint (("delete_child.WaitForSingleObject (thread) failed "
+			 "with %lu for fd %ld\n", GetLastError (), cp->fd));
+	      TerminateThread (cp->thrd, 0);
+	    }
+	}
+      CloseHandle (cp->thrd);
+      cp->thrd = NULL;
+    }
+  if (cp->char_avail)
+    {
+      CloseHandle (cp->char_avail);
+      cp->char_avail = NULL;
+    }
+  if (cp->char_consumed)
+    {
+      CloseHandle (cp->char_consumed);
+      cp->char_consumed = NULL;
+    }
+
+  /* update child_proc_count (highest numbered slot in use plus one) */
+  if (cp == child_procs + child_proc_count - 1)
+    {
+      for (i = child_proc_count-1; i >= 0; i--)
+	if (CHILD_ACTIVE (&child_procs[i]))
+	  {
+	    child_proc_count = i + 1;
+	    break;
+	  }
+    }
+  if (i < 0)
+    child_proc_count = 0;
+}
+
+
+/* Find a child by pid.  */
+static child_process *
+find_child_pid (DWORD pid)
+{
+  child_process *cp;
+
+  for (cp = child_procs+(child_proc_count-1); cp >= child_procs; cp--)
+    if (CHILD_ACTIVE (cp) && pid == cp->pid)
+      return cp;
+  return NULL;
+}
+
+/* Thread proc for child process and socket reader threads. Each thread
+   is normally blocked until woken by select() to check for input by
+   reading one char.  When the read completes, char_avail is signalled
+   to wake up the select emulator and the thread blocks itself again. */
+DWORD WINAPI
+reader_thread (void *arg)
+{
+  child_process *cp;
+
+  /* Our identity */
+  cp = (child_process *)arg;
+
+  /* We have to wait for the go-ahead before we can start */
+  if (cp == NULL
+      || WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
+    return 1;
+
+  for (;;)
+    {
+      int rc;
+
+      rc = _sys_read_ahead (cp->fd);
+
+      /* The name char_avail is a misnomer - it really just means the
+	 read-ahead has completed, whether successfully or not. */
+      if (!SetEvent (cp->char_avail))
+        {
+	  DebPrint (("reader_thread.SetEvent failed with %lu for fd %ld\n",
+		     GetLastError (), cp->fd));
+	  return 1;
+	}
+
+      if (rc == STATUS_READ_ERROR)
+	return 1;
+
+      /* If the read died, the child has died so let the thread die */
+      if (rc == STATUS_READ_FAILED)
+	break;
+
+      /* Wait until our input is acknowledged before reading again */
+      if (WaitForSingleObject (cp->char_consumed, INFINITE) != WAIT_OBJECT_0)
+        {
+	  DebPrint (("reader_thread.WaitForSingleObject failed with "
+		     "%lu for fd %ld\n", GetLastError (), cp->fd));
+	  break;
+        }
+    }
+  return 0;
+}
+
+/*
+END: Borrowed from w32proc.c
+*/
+
+
+
+
+#endif  /* WINDOWSNT */
+
 #include <sys/stat.h>
 #include <errno.h>

@@ -288,6 +1195,11 @@
   char *cwd, *str;
   char string[BUFSIZ];

+#ifdef WINDOWSNT
+  init_winsock (1);
+  init_user_info ();
+#endif
+
   progname = argv[0];

   /* Process options.  */
@@ -488,6 +1400,9 @@
     printf ("\n");
   fflush (stdout);

+#ifdef WINDOWSNT
+  term_winsock ();
+#endif
   return 0;
 }


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2002-11-07  5:12 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-11-07  5:12 preliminary patch for emacsclient.c Ben Key

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).