/* Utility and Unix shadow routines for GNU Emacs on the Microsoft W32 API.
- Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <sys/utime.h>
/* must include CRT headers *before* config.h */
-#include "config.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
#undef access
#undef chdir
#undef chmod
#undef gethostname
#undef gethostbyname
#undef getservbyname
+#undef getpeername
#undef shutdown
+#undef setsockopt
+#undef listen
+#undef getsockname
+#undef accept
+#undef recvfrom
+#undef sendto
#endif
#include "w32.h"
#include "w32heap.h"
#include "systime.h"
-#undef min
-#undef max
-#define min(x, y) (((x) < (y)) ? (x) : (y))
-#define max(x, y) (((x) > (y)) ? (x) : (y))
-
extern Lisp_Object Vw32_downcase_file_names;
extern Lisp_Object Vw32_generate_fake_inodes;
extern Lisp_Object Vw32_get_true_file_attributes;
extern Lisp_Object Vw32_num_mouse_buttons;
\f
+/*
+ BEGIN: Wrapper functions around OpenProcessToken
+ and other functions in advapi32.dll that are only
+ supported in Windows NT / 2k / XP
+*/
+ /* ** Function pointer typedefs ** */
+typedef BOOL (WINAPI * OpenProcessToken_Proc) (
+ HANDLE ProcessHandle,
+ DWORD DesiredAccess,
+ PHANDLE TokenHandle);
+typedef BOOL (WINAPI * GetTokenInformation_Proc) (
+ HANDLE TokenHandle,
+ TOKEN_INFORMATION_CLASS TokenInformationClass,
+ LPVOID TokenInformation,
+ DWORD TokenInformationLength,
+ PDWORD ReturnLength);
+#ifdef _UNICODE
+const char * const LookupAccountSid_Name = "LookupAccountSidW";
+#else
+const char * const LookupAccountSid_Name = "LookupAccountSidA";
+#endif
+typedef BOOL (WINAPI * LookupAccountSid_Proc) (
+ LPCTSTR lpSystemName,
+ PSID Sid,
+ LPTSTR Name,
+ LPDWORD cbName,
+ LPTSTR DomainName,
+ LPDWORD cbDomainName,
+ PSID_NAME_USE peUse);
+typedef PSID_IDENTIFIER_AUTHORITY (WINAPI * GetSidIdentifierAuthority_Proc) (
+ PSID pSid);
+
+ /* ** A utility function ** */
+static BOOL is_windows_9x ()
+{
+ BOOL b_ret=0;
+ OSVERSIONINFO os_ver;
+ ZeroMemory(&os_ver, sizeof(OSVERSIONINFO));
+ os_ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ if (GetVersionEx (&os_ver))
+ {
+ b_ret = (os_ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
+ }
+ return b_ret;
+}
+
+ /* ** The wrapper functions ** */
+
+BOOL WINAPI open_process_token (
+ HANDLE ProcessHandle,
+ DWORD DesiredAccess,
+ PHANDLE TokenHandle)
+{
+ OpenProcessToken_Proc pfn_Open_Process_Token = NULL;
+ HMODULE hm_advapi32 = NULL;
+ if (is_windows_9x () == TRUE)
+ {
+ return FALSE;
+ }
+ hm_advapi32 = LoadLibrary ("Advapi32.dll");
+ pfn_Open_Process_Token =
+ (OpenProcessToken_Proc) GetProcAddress (hm_advapi32, "OpenProcessToken");
+ if (pfn_Open_Process_Token == NULL)
+ {
+ return FALSE;
+ }
+ return (
+ pfn_Open_Process_Token (
+ ProcessHandle,
+ DesiredAccess,
+ TokenHandle)
+ );
+}
+
+BOOL WINAPI get_token_information (
+ HANDLE TokenHandle,
+ TOKEN_INFORMATION_CLASS TokenInformationClass,
+ LPVOID TokenInformation,
+ DWORD TokenInformationLength,
+ PDWORD ReturnLength)
+{
+ GetTokenInformation_Proc pfn_Get_Token_Information = NULL;
+ HMODULE hm_advapi32 = NULL;
+ if (is_windows_9x () == TRUE)
+ {
+ return FALSE;
+ }
+ hm_advapi32 = LoadLibrary ("Advapi32.dll");
+ pfn_Get_Token_Information =
+ (GetTokenInformation_Proc) GetProcAddress (hm_advapi32, "GetTokenInformation");
+ if (pfn_Get_Token_Information == NULL)
+ {
+ return FALSE;
+ }
+ return (
+ pfn_Get_Token_Information (
+ TokenHandle,
+ TokenInformationClass,
+ TokenInformation,
+ TokenInformationLength,
+ ReturnLength)
+ );
+}
+
+BOOL WINAPI lookup_account_sid (
+ LPCTSTR lpSystemName,
+ PSID Sid,
+ LPTSTR Name,
+ LPDWORD cbName,
+ LPTSTR DomainName,
+ LPDWORD cbDomainName,
+ PSID_NAME_USE peUse)
+{
+ LookupAccountSid_Proc pfn_Lookup_Account_Sid = NULL;
+ HMODULE hm_advapi32 = NULL;
+ if (is_windows_9x () == TRUE)
+ {
+ return FALSE;
+ }
+ hm_advapi32 = LoadLibrary ("Advapi32.dll");
+ pfn_Lookup_Account_Sid =
+ (LookupAccountSid_Proc) GetProcAddress (hm_advapi32, LookupAccountSid_Name);
+ if (pfn_Lookup_Account_Sid == NULL)
+ {
+ return FALSE;
+ }
+ return (
+ pfn_Lookup_Account_Sid (
+ lpSystemName,
+ Sid,
+ Name,
+ cbName,
+ DomainName,
+ cbDomainName,
+ peUse)
+ );
+}
+
+PSID_IDENTIFIER_AUTHORITY WINAPI get_sid_identifier_authority (
+ PSID pSid)
+{
+ GetSidIdentifierAuthority_Proc pfn_Get_Sid_Identifier_Authority = NULL;
+ HMODULE hm_advapi32 = NULL;
+ if (is_windows_9x () == TRUE)
+ {
+ return NULL;
+ }
+ hm_advapi32 = LoadLibrary ("Advapi32.dll");
+ pfn_Get_Sid_Identifier_Authority =
+ (GetSidIdentifierAuthority_Proc) GetProcAddress (
+ hm_advapi32, "GetSidIdentifierAuthority");
+ if (pfn_Get_Sid_Identifier_Authority == NULL)
+ {
+ return NULL;
+ }
+ return (pfn_Get_Sid_Identifier_Authority (pSid));
+}
+
+/*
+ END: Wrapper functions around OpenProcessToken
+ and other functions in advapi32.dll that are only
+ supported in Windows NT / 2k / XP
+*/
+
+\f
/* Equivalent of strerror for W32 error codes. */
char *
w32_strerror (int error_no)
HANDLE token = NULL;
SID_NAME_USE user_type;
- if (OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token)
- && GetTokenInformation (token, TokenUser,
+ if (
+ open_process_token (GetCurrentProcess (), TOKEN_QUERY, &token)
+ && get_token_information (
+ token, TokenUser,
(PVOID) user_sid, sizeof (user_sid), &trash)
- && LookupAccountSid (NULL, *((PSID *) user_sid), name, &length,
- domain, &dlength, &user_type))
+ && lookup_account_sid (
+ NULL, *((PSID *) user_sid), name, &length,
+ domain, &dlength, &user_type)
+ )
{
strcpy (the_passwd.pw_name, name);
/* Determine a reasonable uid value. */
{
SID_IDENTIFIER_AUTHORITY * pSIA;
- pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid));
+ pSIA = get_sid_identifier_authority (*((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) +
the_passwd.pw_uid = the_passwd.pw_uid % 60001;
/* Get group id */
- if (GetTokenInformation (token, TokenPrimaryGroup,
+ if (get_token_information (token, TokenPrimaryGroup,
(PVOID) user_sid, sizeof (user_sid), &trash))
{
SID_IDENTIFIER_AUTHORITY * pSIA;
- pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid));
+ pSIA = get_sid_identifier_authority (*((PSID *) user_sid));
the_passwd.pw_gid = ((pSIA->Value[2] << 24) +
(pSIA->Value[3] << 16) +
(pSIA->Value[4] << 8) +
{
char * var = alloca (strlen (tmp) + 8);
sprintf (var, "TMPDIR=%s", tmp);
- _putenv (var);
+ _putenv (strdup (var));
break;
}
}
{"HOME", "C:/"},
{"PRELOAD_WINSOCK", NULL},
{"emacs_dir", "C:/emacs"},
- {"EMACSLOADPATH", "%emacs_dir%/site-lisp;%emacs_dir%/lisp;%emacs_dir%/leim"},
+ {"EMACSLOADPATH", "%emacs_dir%/site-lisp;%emacs_dir%/../site-lisp;%emacs_dir%/lisp;%emacs_dir%/leim"},
{"SHELL", "%emacs_dir%/bin/cmdproxy.exe"},
{"EMACSDATA", "%emacs_dir%/etc"},
{"EMACSPATH", "%emacs_dir%/bin"},
- {"EMACSLOCKDIR", "%emacs_dir%/lock"},
/* We no longer set INFOPATH because Info-default-directory-list
is then ignored. */
/* {"INFOPATH", "%emacs_dir%/info"}, */
init_user_info ();
}
+char *
+emacs_root_dir (void)
+{
+ static char root_dir[FILENAME_MAX];
+ const char *p;
+
+ p = getenv ("emacs_dir");
+ if (p == NULL)
+ abort ();
+ strcpy (root_dir, p);
+ root_dir[parse_root (root_dir, NULL)] = '\0';
+ dostounix_filename (root_dir);
+ return root_dir;
+}
+
/* We don't have scripts to automatically determine the system configuration
for Emacs before it's compiled, and we don't want to have to make the
user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
int
sys_open (const char * path, int oflag, int mode)
{
- /* Force all file handles to be non-inheritable. */
- return _open (map_w32_filename (path, NULL), oflag | _O_NOINHERIT, mode);
+ const char* mpath = map_w32_filename (path, NULL);
+ /* Try to open file without _O_CREAT, to be able to write to hidden
+ and system files. Force all file handles to be
+ non-inheritable. */
+ int res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode);
+ if (res >= 0)
+ return res;
+ return _open (mpath, oflag | _O_NOINHERIT, mode);
}
int
}
}
- if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- {
- buf->st_mode = _S_IFDIR;
- buf->st_nlink = 2; /* doesn't really matter */
- fake_inode = 0; /* this doesn't either I think */
- }
- else if (!NILP (Vw32_get_true_file_attributes)
- /* No access rights required to get info. */
- && (fh = CreateFile (name, 0, 0, NULL, OPEN_EXISTING, 0, NULL))
- != INVALID_HANDLE_VALUE)
+ if (!NILP (Vw32_get_true_file_attributes)
+ /* No access rights required to get info. */
+ && (fh = CreateFile (name, 0, 0, NULL, OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS, NULL))
+ != INVALID_HANDLE_VALUE)
{
/* This is more accurate in terms of gettting the correct number
of links, but is quite slow (it is noticable when Emacs is
fake_inode = 0;
}
- switch (GetFileType (fh))
+ if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
- case FILE_TYPE_DISK:
- buf->st_mode = _S_IFREG;
- break;
- case FILE_TYPE_PIPE:
- buf->st_mode = _S_IFIFO;
- break;
- case FILE_TYPE_CHAR:
- case FILE_TYPE_UNKNOWN:
- default:
- buf->st_mode = _S_IFCHR;
+ buf->st_mode = _S_IFDIR;
+ }
+ else
+ {
+ switch (GetFileType (fh))
+ {
+ case FILE_TYPE_DISK:
+ buf->st_mode = _S_IFREG;
+ break;
+ case FILE_TYPE_PIPE:
+ buf->st_mode = _S_IFIFO;
+ break;
+ case FILE_TYPE_CHAR:
+ case FILE_TYPE_UNKNOWN:
+ default:
+ buf->st_mode = _S_IFCHR;
+ }
}
CloseHandle (fh);
}
else
{
/* Don't bother to make this information more accurate. */
- buf->st_mode = _S_IFREG;
+ buf->st_mode = (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
+ _S_IFDIR : _S_IFREG;
buf->st_nlink = 1;
fake_inode = 0;
}
}
if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- {
buf->st_mode = _S_IFDIR;
- buf->st_nlink = 2; /* doesn't really matter */
- fake_inode = 0; /* this doesn't either I think */
- }
- else
- {
- buf->st_nlink = info.nNumberOfLinks;
- /* Might as well use file index to fake inode values, but this
- is not guaranteed to be unique unless we keep a handle open
- all the time (even then there are situations where it is
- not unique). Reputedly, there are at most 48 bits of info
- (on NTFS, presumably less on FAT). */
- fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
- }
+
+ buf->st_nlink = info.nNumberOfLinks;
+ /* Might as well use file index to fake inode values, but this
+ is not guaranteed to be unique unless we keep a handle open
+ all the time (even then there are situations where it is
+ not unique). Reputedly, there are at most 48 bits of info
+ (on NTFS, presumably less on FAT). */
+ fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
/* MSVC defines _ino_t to be short; other libc's might not. */
if (sizeof (buf->st_ino) == 2)
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
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 */
#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)
{
- int fd;
- long s;
- child_process * cp;
+ SOCKET s;
if (winsock_lib == NULL)
{
check_errno ();
/* call the real socket function */
- s = (long) pfn_socket (af, type, protocol);
+ s = pfn_socket (af, type, protocol);
if (s != INVALID_SOCKET)
- {
- /* 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. */
+ return socket_to_fd (s);
- /* allocate a file descriptor (with appropriate flags) */
- fd = _open ("NUL:", _O_RDWR);
- if (fd >= 0)
- {
+ 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); */
+ /* 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. */
+ /* 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)
{
- /* 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
+ 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))
{
- 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)
{
- /* 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);
- }
- }
- }
+ pfn_closesocket (s);
+ s = (SOCKET) new_s;
+ }
+ else
+ {
+ CloseHandle (new_s);
+ }
+ }
}
- fd_info[fd].hnd = (HANDLE) 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 ();
- }
+ /* set our own internal flags */
+ fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
- fd_info[ fd ].cp = cp;
+ cp = new_child ();
+ if (cp)
+ {
+ cp->fd = fd;
+ cp->status = STATUS_READ_ACKNOWLEDGED;
- /* success! */
- winsock_inuse++; /* count open sockets */
- return fd;
+ /* attach child_process to fd_info */
+ if (fd_info[ fd ].cp != NULL)
+ {
+ DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
+ abort ();
}
- /* clean up */
- _close (fd);
+ fd_info[ fd ].cp = cp;
+
+ /* success! */
+ winsock_inuse++; /* count open sockets */
+ return fd;
}
- pfn_closesocket (s);
- h_errno = EMFILE;
- }
- set_errno ();
+ /* clean up */
+ _close (fd);
+ }
+ pfn_closesocket (s);
+ h_errno = EMFILE;
return -1;
}
return serv;
}
+int
+sys_getpeername (int s, struct sockaddr *addr, int * namelen)
+{
+ if (winsock_lib == NULL)
+ {
+ h_errno = ENETDOWN;
+ return SOCKET_ERROR;
+ }
+
+ check_errno ();
+ if (fd_info[s].flags & FILE_SOCKET)
+ {
+ int rc = pfn_getpeername (SOCK_HANDLE (s), addr, namelen);
+ if (rc == SOCKET_ERROR)
+ set_errno ();
+ return rc;
+ }
+ h_errno = ENOTSOCK;
+ return SOCKET_ERROR;
+}
+
+
int
sys_shutdown (int s, int how)
{
return SOCKET_ERROR;
}
+int
+sys_setsockopt (int s, int level, int optname, const char * optval, int optlen)
+{
+ if (winsock_lib == NULL)
+ {
+ h_errno = ENETDOWN;
+ return SOCKET_ERROR;
+ }
+
+ check_errno ();
+ if (fd_info[s].flags & FILE_SOCKET)
+ {
+ int rc = pfn_setsockopt (SOCK_HANDLE (s), level, optname,
+ optval, optlen);
+ if (rc == SOCKET_ERROR)
+ set_errno ();
+ return rc;
+ }
+ h_errno = ENOTSOCK;
+ return SOCKET_ERROR;
+}
+
+int
+sys_listen (int s, int backlog)
+{
+ if (winsock_lib == NULL)
+ {
+ h_errno = ENETDOWN;
+ return SOCKET_ERROR;
+ }
+
+ check_errno ();
+ if (fd_info[s].flags & FILE_SOCKET)
+ {
+ int rc = pfn_listen (SOCK_HANDLE (s), backlog);
+ if (rc == SOCKET_ERROR)
+ set_errno ();
+ return rc;
+ }
+ h_errno = ENOTSOCK;
+ return SOCKET_ERROR;
+}
+
+int
+sys_getsockname (int s, struct sockaddr * name, int * namelen)
+{
+ if (winsock_lib == NULL)
+ {
+ h_errno = ENETDOWN;
+ return SOCKET_ERROR;
+ }
+
+ check_errno ();
+ if (fd_info[s].flags & FILE_SOCKET)
+ {
+ int rc = pfn_getsockname (SOCK_HANDLE (s), name, namelen);
+ if (rc == SOCKET_ERROR)
+ set_errno ();
+ return rc;
+ }
+ h_errno = ENOTSOCK;
+ return SOCKET_ERROR;
+}
+
+int
+sys_accept (int s, struct sockaddr * addr, int * addrlen)
+{
+ if (winsock_lib == NULL)
+ {
+ h_errno = ENETDOWN;
+ return -1;
+ }
+
+ check_errno ();
+ if (fd_info[s].flags & FILE_SOCKET)
+ {
+ SOCKET t = pfn_accept (SOCK_HANDLE (s), addr, addrlen);
+ if (t != INVALID_SOCKET)
+ return socket_to_fd (t);
+
+ set_errno ();
+ return -1;
+ }
+ h_errno = ENOTSOCK;
+ return -1;
+}
+
+int
+sys_recvfrom (int s, char * buf, int len, int flags,
+ struct sockaddr * from, int * fromlen)
+{
+ if (winsock_lib == NULL)
+ {
+ h_errno = ENETDOWN;
+ return SOCKET_ERROR;
+ }
+
+ check_errno ();
+ if (fd_info[s].flags & FILE_SOCKET)
+ {
+ int rc = pfn_recvfrom (SOCK_HANDLE (s), buf, len, flags, from, fromlen);
+ if (rc == SOCKET_ERROR)
+ set_errno ();
+ return rc;
+ }
+ h_errno = ENOTSOCK;
+ return SOCKET_ERROR;
+}
+
+int
+sys_sendto (int s, const char * buf, int len, int flags,
+ const struct sockaddr * to, int tolen)
+{
+ if (winsock_lib == NULL)
+ {
+ h_errno = ENETDOWN;
+ return SOCKET_ERROR;
+ }
+
+ check_errno ();
+ if (fd_info[s].flags & FILE_SOCKET)
+ {
+ int rc = pfn_sendto (SOCK_HANDLE (s), buf, len, flags, to, tolen);
+ if (rc == SOCKET_ERROR)
+ set_errno ();
+ return rc;
+ }
+ h_errno = ENOTSOCK;
+ return SOCKET_ERROR;
+}
+
+/* Windows does not have an fcntl function. Provide an implementation
+ solely for making sockets non-blocking. */
+int
+fcntl (int s, int cmd, int options)
+{
+ if (winsock_lib == NULL)
+ {
+ h_errno = ENETDOWN;
+ return -1;
+ }
+
+ check_errno ();
+ if (fd_info[s].flags & FILE_SOCKET)
+ {
+ if (cmd == F_SETFL && options == O_NDELAY)
+ {
+ unsigned long nblock = 1;
+ int rc = pfn_ioctlsocket (SOCK_HANDLE (s), FIONBIO, &nblock);
+ if (rc == SOCKET_ERROR)
+ set_errno();
+ /* Keep track of the fact that we set this to non-blocking. */
+ fd_info[s].flags |= FILE_NDELAY;
+ return rc;
+ }
+ else
+ {
+ h_errno = EINVAL;
+ return SOCKET_ERROR;
+ }
+ }
+ h_errno = ENOTSOCK;
+ return SOCKET_ERROR;
+}
+
#endif /* HAVE_SOCKETS */
}
#ifdef HAVE_SOCKETS
else if (fd_info[fd].flags & FILE_SOCKET)
- rc = pfn_recv (SOCK_HANDLE (fd), &cp->chr, sizeof (char), 0);
+ {
+ 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))
#ifdef HAVE_SOCKETS
if (fd_info[fd].flags & FILE_SOCKET)
{
+ unsigned long nblock = 0;
if (winsock_lib == NULL) abort ();
+
+ /* TODO: implement select() properly so non-blocking I/O works. */
+ /* For now, make sure the write blocks. */
+ if (fd_info[fd].flags & FILE_NDELAY)
+ pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
+
nchars = pfn_send (SOCK_HANDLE (fd), buffer, count, 0);
+
+ /* Set the socket back to non-blocking if it was before,
+ for other operations that support it. */
+ if (fd_info[fd].flags & FILE_NDELAY)
+ {
+ nblock = 1;
+ pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
+ }
+
if (nchars == SOCKET_ERROR)
{
DebPrint(("sys_read.send failed with error %d on socket %ld\n",
objs[1] = decode_env_path (0, (getenv ("EMACSLOADPATH")));
full_load_path = Fappend (2, objs);
init_file = build_string ("term/w32-win");
- fd = openp (full_load_path, init_file, ".el:.elc", NULL, 0);
+ fd = openp (full_load_path, init_file, Vload_suffixes, NULL, Qnil);
if (fd < 0)
{
Lisp_Object load_path_print = Fprin1_to_string (full_load_path, Qnil);
- char *init_file_name = XSTRING (init_file)->data;
- char *load_path = XSTRING (load_path_print)->data;
+ char *init_file_name = SDATA (init_file);
+ char *load_path = SDATA (load_path_print);
char *buffer = alloca (1024);
sprintf (buffer,