* 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 external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.