(ensure-mark): Minor rewrite.
[emacs.git] / src / w32.c
blob2f30e30b2ac3b03d8ea9edc1483c575897db09ef
1 /* Utility and Unix shadow routines for GNU Emacs on Windows NT.
2 Copyright (C) 1994, 1995 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
21 Geoff Voelker (voelker@cs.washington.edu) 7-29-94
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <io.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <ctype.h>
31 #include <signal.h>
32 #include <sys/time.h>
34 /* must include CRT headers *before* config.h */
35 #include "config.h"
36 #undef access
37 #undef chdir
38 #undef chmod
39 #undef creat
40 #undef ctime
41 #undef fopen
42 #undef link
43 #undef mkdir
44 #undef mktemp
45 #undef open
46 #undef rename
47 #undef rmdir
48 #undef unlink
50 #undef close
51 #undef dup
52 #undef dup2
53 #undef pipe
54 #undef read
55 #undef write
57 #define getwd _getwd
58 #include "lisp.h"
59 #undef getwd
61 #include <pwd.h>
63 #include <windows.h>
65 #ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
66 #include <sys/socket.h>
67 #undef socket
68 #undef bind
69 #undef connect
70 #undef htons
71 #undef ntohs
72 #undef inet_addr
73 #undef gethostname
74 #undef gethostbyname
75 #undef getservbyname
76 #endif
78 #include "nt.h"
79 #include "ndir.h"
80 #include "ntheap.h"
82 /* Get the current working directory. */
83 char *
84 getwd (char *dir)
86 if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
87 return dir;
88 return NULL;
91 #ifndef HAVE_SOCKETS
92 /* Emulate gethostname. */
93 int
94 gethostname (char *buffer, int size)
96 /* NT only allows small host names, so the buffer is
97 certainly large enough. */
98 return !GetComputerName (buffer, &size);
100 #endif /* HAVE_SOCKETS */
102 /* Emulate getloadavg. */
104 getloadavg (double loadavg[], int nelem)
106 int i;
108 /* A faithful emulation is going to have to be saved for a rainy day. */
109 for (i = 0; i < nelem; i++)
111 loadavg[i] = 0.0;
113 return i;
116 /* Emulate the Unix directory procedures opendir, closedir,
117 and readdir. We can't use the procedures supplied in sysdep.c,
118 so we provide them here. */
120 struct direct dir_static; /* simulated directory contents */
121 static HANDLE dir_find_handle = INVALID_HANDLE_VALUE;
122 static int dir_is_fat;
123 static char dir_pathname[MAXPATHLEN+1];
125 extern Lisp_Object Vwin32_downcase_file_names;
127 DIR *
128 opendir (char *filename)
130 DIR *dirp;
132 /* Opening is done by FindFirstFile. However, a read is inherent to
133 this operation, so we defer the open until read time. */
135 if (!(dirp = (DIR *) malloc (sizeof (DIR))))
136 return NULL;
137 if (dir_find_handle != INVALID_HANDLE_VALUE)
138 return NULL;
140 dirp->dd_fd = 0;
141 dirp->dd_loc = 0;
142 dirp->dd_size = 0;
144 strncpy (dir_pathname, filename, MAXPATHLEN);
145 dir_pathname[MAXPATHLEN] = '\0';
146 dir_is_fat = is_fat_volume (filename, NULL);
148 return dirp;
151 void
152 closedir (DIR *dirp)
154 /* If we have a find-handle open, close it. */
155 if (dir_find_handle != INVALID_HANDLE_VALUE)
157 FindClose (dir_find_handle);
158 dir_find_handle = INVALID_HANDLE_VALUE;
160 xfree ((char *) dirp);
163 struct direct *
164 readdir (DIR *dirp)
166 WIN32_FIND_DATA find_data;
168 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
169 if (dir_find_handle == INVALID_HANDLE_VALUE)
171 char filename[MAXNAMLEN + 3];
172 int ln;
174 strcpy (filename, dir_pathname);
175 ln = strlen (filename) - 1;
176 if (!IS_DIRECTORY_SEP (filename[ln]))
177 strcat (filename, "\\");
178 strcat (filename, "*");
180 dir_find_handle = FindFirstFile (filename, &find_data);
182 if (dir_find_handle == INVALID_HANDLE_VALUE)
183 return NULL;
185 else
187 if (!FindNextFile (dir_find_handle, &find_data))
188 return NULL;
191 /* Emacs never uses this value, so don't bother making it match
192 value returned by stat(). */
193 dir_static.d_ino = 1;
195 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 +
196 dir_static.d_namlen - dir_static.d_namlen % 4;
198 dir_static.d_namlen = strlen (find_data.cFileName);
199 strcpy (dir_static.d_name, find_data.cFileName);
200 if (dir_is_fat)
201 _strlwr (dir_static.d_name);
202 else if (!NILP (Vwin32_downcase_file_names))
204 register char *p;
205 for (p = dir_static.d_name; *p; p++)
206 if (*p >= 'a' && *p <= 'z')
207 break;
208 if (!*p)
209 _strlwr (dir_static.d_name);
212 return &dir_static;
215 /* Emulate getpwuid, getpwnam and others. */
217 #define PASSWD_FIELD_SIZE 256
219 static char the_passwd_name[PASSWD_FIELD_SIZE];
220 static char the_passwd_passwd[PASSWD_FIELD_SIZE];
221 static char the_passwd_gecos[PASSWD_FIELD_SIZE];
222 static char the_passwd_dir[PASSWD_FIELD_SIZE];
223 static char the_passwd_shell[PASSWD_FIELD_SIZE];
225 static struct passwd the_passwd =
227 the_passwd_name,
228 the_passwd_passwd,
232 the_passwd_gecos,
233 the_passwd_dir,
234 the_passwd_shell,
237 int
238 getuid ()
240 return the_passwd.pw_uid;
243 int
244 geteuid ()
246 /* I could imagine arguing for checking to see whether the user is
247 in the Administrators group and returning a UID of 0 for that
248 case, but I don't know how wise that would be in the long run. */
249 return getuid ();
252 int
253 getgid ()
255 return the_passwd.pw_gid;
258 int
259 getegid ()
261 return getgid ();
264 struct passwd *
265 getpwuid (int uid)
267 if (uid == the_passwd.pw_uid)
268 return &the_passwd;
269 return NULL;
272 struct passwd *
273 getpwnam (char *name)
275 struct passwd *pw;
277 pw = getpwuid (getuid ());
278 if (!pw)
279 return pw;
281 if (stricmp (name, pw->pw_name))
282 return NULL;
284 return pw;
287 void
288 init_user_info ()
290 /* Find the user's real name by opening the process token and
291 looking up the name associated with the user-sid in that token.
293 Use the relative portion of the identifier authority value from
294 the user-sid as the user id value (same for group id using the
295 primary group sid from the process token). */
297 char user_sid[256], name[256], domain[256];
298 DWORD length = sizeof (name), dlength = sizeof (domain), trash;
299 HANDLE token = NULL;
300 SID_NAME_USE user_type;
302 if (OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token)
303 && GetTokenInformation (token, TokenUser,
304 (PVOID) user_sid, sizeof (user_sid), &trash)
305 && LookupAccountSid (NULL, *((PSID *) user_sid), name, &length,
306 domain, &dlength, &user_type))
308 strcpy (the_passwd.pw_name, name);
309 /* Determine a reasonable uid value. */
310 if (stricmp ("administrator", name) == 0)
312 the_passwd.pw_uid = 0;
313 the_passwd.pw_gid = 0;
315 else
317 SID_IDENTIFIER_AUTHORITY * pSIA;
319 pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid));
320 /* I believe the relative portion is the last 4 bytes (of 6)
321 with msb first. */
322 the_passwd.pw_uid = ((pSIA->Value[2] << 24) +
323 (pSIA->Value[3] << 16) +
324 (pSIA->Value[4] << 8) +
325 (pSIA->Value[5] << 0));
326 /* restrict to conventional uid range for normal users */
327 the_passwd.pw_uid = the_passwd.pw_uid % 60001;
329 /* Get group id */
330 if (GetTokenInformation (token, TokenPrimaryGroup,
331 (PVOID) user_sid, sizeof (user_sid), &trash))
333 SID_IDENTIFIER_AUTHORITY * pSIA;
335 pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid));
336 the_passwd.pw_gid = ((pSIA->Value[2] << 24) +
337 (pSIA->Value[3] << 16) +
338 (pSIA->Value[4] << 8) +
339 (pSIA->Value[5] << 0));
340 /* I don't know if this is necessary, but for safety... */
341 the_passwd.pw_gid = the_passwd.pw_gid % 60001;
343 else
344 the_passwd.pw_gid = the_passwd.pw_uid;
347 /* If security calls are not supported (presumably because we
348 are running under Windows 95), fallback to this. */
349 else if (GetUserName (name, &length))
351 strcpy (the_passwd.pw_name, name);
352 if (stricmp ("administrator", name) == 0)
353 the_passwd.pw_uid = 0;
354 else
355 the_passwd.pw_uid = 123;
356 the_passwd.pw_gid = the_passwd.pw_uid;
358 else
360 strcpy (the_passwd.pw_name, "unknown");
361 the_passwd.pw_uid = 123;
362 the_passwd.pw_gid = 123;
365 /* Ensure HOME and SHELL are defined. */
366 if (getenv ("HOME") == NULL)
367 putenv ("HOME=c:/");
368 if (getenv ("SHELL") == NULL)
369 putenv ((GetVersion () & 0x80000000) ? "SHELL=command" : "SHELL=cmd");
371 /* Set dir and shell from environment variables. */
372 strcpy (the_passwd.pw_dir, getenv ("HOME"));
373 strcpy (the_passwd.pw_shell, getenv ("SHELL"));
375 if (token)
376 CloseHandle (token);
380 random ()
382 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
383 return ((rand () << 15) | rand ());
386 void
387 srandom (int seed)
389 srand (seed);
392 /* Normalize filename by converting all path separators to
393 the specified separator. Also conditionally convert upper
394 case path name components to lower case. */
396 static void
397 normalize_filename (fp, path_sep)
398 register char *fp;
399 char path_sep;
401 char sep;
402 char *elem;
404 /* Always lower-case drive letters a-z, even if the filesystem
405 preserves case in filenames.
406 This is so filenames can be compared by string comparison
407 functions that are case-sensitive. Even case-preserving filesystems
408 do not distinguish case in drive letters. */
409 if (fp[1] == ':' && *fp >= 'A' && *fp <= 'Z')
411 *fp += 'a' - 'A';
412 fp += 2;
415 if (NILP (Vwin32_downcase_file_names))
417 while (*fp)
419 if (*fp == '/' || *fp == '\\')
420 *fp = path_sep;
421 fp++;
423 return;
426 sep = path_sep; /* convert to this path separator */
427 elem = fp; /* start of current path element */
429 do {
430 if (*fp >= 'a' && *fp <= 'z')
431 elem = 0; /* don't convert this element */
433 if (*fp == 0 || *fp == ':')
435 sep = *fp; /* restore current separator (or 0) */
436 *fp = '/'; /* after conversion of this element */
439 if (*fp == '/' || *fp == '\\')
441 if (elem && elem != fp)
443 *fp = 0; /* temporary end of string */
444 _strlwr (elem); /* while we convert to lower case */
446 *fp = sep; /* convert (or restore) path separator */
447 elem = fp + 1; /* next element starts after separator */
448 sep = path_sep;
450 } while (*fp++);
453 /* Destructively turn backslashes into slashes. */
454 void
455 dostounix_filename (p)
456 register char *p;
458 normalize_filename (p, '/');
461 /* Destructively turn slashes into backslashes. */
462 void
463 unixtodos_filename (p)
464 register char *p;
466 normalize_filename (p, '\\');
469 /* Remove all CR's that are followed by a LF.
470 (From msdos.c...probably should figure out a way to share it,
471 although this code isn't going to ever change.) */
473 crlf_to_lf (n, buf)
474 register int n;
475 register unsigned char *buf;
477 unsigned char *np = buf;
478 unsigned char *startp = buf;
479 unsigned char *endp = buf + n;
481 if (n == 0)
482 return n;
483 while (buf < endp - 1)
485 if (*buf == 0x0d)
487 if (*(++buf) != 0x0a)
488 *np++ = 0x0d;
490 else
491 *np++ = *buf++;
493 if (buf < endp)
494 *np++ = *buf++;
495 return np - startp;
498 /* Routines that are no-ops on NT but are defined to get Emacs to compile. */
500 int
501 sigsetmask (int signal_mask)
503 return 0;
506 int
507 sigblock (int sig)
509 return 0;
512 int
513 setpgrp (int pid, int gid)
515 return 0;
518 int
519 alarm (int seconds)
521 return 0;
524 int
525 unrequest_sigio (void)
527 return 0;
530 int
531 request_sigio (void)
533 return 0;
536 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
538 LPBYTE
539 nt_get_resource (key, lpdwtype)
540 char *key;
541 LPDWORD lpdwtype;
543 LPBYTE lpvalue;
544 HKEY hrootkey = NULL;
545 DWORD cbData;
546 BOOL ok = FALSE;
548 /* Check both the current user and the local machine to see if
549 we have any resources. */
551 if (RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
553 lpvalue = NULL;
555 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
556 && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL
557 && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
559 return (lpvalue);
562 if (lpvalue) xfree (lpvalue);
564 RegCloseKey (hrootkey);
567 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
569 lpvalue = NULL;
571 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS &&
572 (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL &&
573 RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
575 return (lpvalue);
578 if (lpvalue) xfree (lpvalue);
580 RegCloseKey (hrootkey);
583 return (NULL);
586 void
587 init_environment ()
589 /* Check for environment variables and use registry if they don't exist */
591 int i;
592 LPBYTE lpval;
593 DWORD dwType;
595 static char * env_vars[] =
597 "HOME",
598 "PRELOAD_WINSOCK",
599 "emacs_dir",
600 "EMACSLOADPATH",
601 "SHELL",
602 "EMACSDATA",
603 "EMACSPATH",
604 "EMACSLOCKDIR",
605 "INFOPATH",
606 "EMACSDOC",
607 "TERM",
610 for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++)
612 if (!getenv (env_vars[i]) &&
613 (lpval = nt_get_resource (env_vars[i], &dwType)) != NULL)
615 if (dwType == REG_EXPAND_SZ)
617 char buf1[500], buf2[500];
619 ExpandEnvironmentStrings ((LPSTR) lpval, buf1, 500);
620 _snprintf (buf2, 499, "%s=%s", env_vars[i], buf1);
621 putenv (strdup (buf2));
623 else if (dwType == REG_SZ)
625 char buf[500];
627 _snprintf (buf, 499, "%s=%s", env_vars[i], lpval);
628 putenv (strdup (buf));
631 xfree (lpval);
636 init_user_info ();
639 /* We don't have scripts to automatically determine the system configuration
640 for Emacs before it's compiled, and we don't want to have to make the
641 user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
642 routine. */
644 static char configuration_buffer[32];
646 char *
647 get_emacs_configuration (void)
649 char *arch, *oem, *os;
651 /* Determine the processor type. */
652 switch (get_processor_type ())
655 #ifdef PROCESSOR_INTEL_386
656 case PROCESSOR_INTEL_386:
657 case PROCESSOR_INTEL_486:
658 case PROCESSOR_INTEL_PENTIUM:
659 arch = "i386";
660 break;
661 #endif
663 #ifdef PROCESSOR_INTEL_860
664 case PROCESSOR_INTEL_860:
665 arch = "i860";
666 break;
667 #endif
669 #ifdef PROCESSOR_MIPS_R2000
670 case PROCESSOR_MIPS_R2000:
671 case PROCESSOR_MIPS_R3000:
672 case PROCESSOR_MIPS_R4000:
673 arch = "mips";
674 break;
675 #endif
677 #ifdef PROCESSOR_ALPHA_21064
678 case PROCESSOR_ALPHA_21064:
679 arch = "alpha";
680 break;
681 #endif
683 default:
684 arch = "unknown";
685 break;
688 /* Let oem be "*" until we figure out how to decode the OEM field. */
689 oem = "*";
691 os = (GetVersion () & 0x80000000) ? "win95" : "nt";
693 sprintf (configuration_buffer, "%s-%s-%s%d.%d", arch, oem, os,
694 get_nt_major_version (), get_nt_minor_version ());
695 return configuration_buffer;
698 #include <sys/timeb.h>
700 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
701 void
702 gettimeofday (struct timeval *tv, struct timezone *tz)
704 struct _timeb tb;
705 _ftime (&tb);
707 tv->tv_sec = tb.time;
708 tv->tv_usec = tb.millitm * 1000L;
709 if (tz)
711 tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */
712 tz->tz_dsttime = tb.dstflag; /* type of dst correction */
716 /* ------------------------------------------------------------------------- */
717 /* IO support and wrapper functions for Win32 API. */
718 /* ------------------------------------------------------------------------- */
720 /* Place a wrapper around the MSVC version of ctime. It returns NULL
721 on network directories, so we handle that case here.
722 (Ulrich Leodolter, 1/11/95). */
723 char *
724 sys_ctime (const time_t *t)
726 char *str = (char *) ctime (t);
727 return (str ? str : "Sun Jan 01 00:00:00 1970");
730 /* Emulate sleep...we could have done this with a define, but that
731 would necessitate including windows.h in the files that used it.
732 This is much easier. */
733 void
734 sys_sleep (int seconds)
736 Sleep (seconds * 1000);
739 /* Internal MSVC data and functions for low-level descriptor munging */
740 #if (_MSC_VER == 900)
741 extern char _osfile[];
742 #endif
743 extern int __cdecl _set_osfhnd (int fd, long h);
744 extern int __cdecl _free_osfhnd (int fd);
746 /* parallel array of private info on file handles */
747 filedesc fd_info [ MAXDESC ];
749 static struct {
750 DWORD serialnum;
751 DWORD maxcomp;
752 DWORD flags;
753 char name[32];
754 char type[32];
755 } volume_info;
757 /* Get information on the volume where name is held; set path pointer to
758 start of pathname in name (past UNC header\volume header if present). */
760 get_volume_info (const char * name, const char ** pPath)
762 char temp[MAX_PATH];
763 char *rootname = NULL; /* default to current volume */
765 if (name == NULL)
766 return FALSE;
768 /* find the root name of the volume if given */
769 if (isalpha (name[0]) && name[1] == ':')
771 rootname = temp;
772 temp[0] = *name++;
773 temp[1] = *name++;
774 temp[2] = '\\';
775 temp[3] = 0;
777 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
779 char *str = temp;
780 int slashes = 4;
781 rootname = temp;
784 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
785 break;
786 *str++ = *name++;
788 while ( *name );
790 *str++ = '\\';
791 *str = 0;
794 if (pPath)
795 *pPath = name;
797 if (GetVolumeInformation (rootname,
798 volume_info.name, 32,
799 &volume_info.serialnum,
800 &volume_info.maxcomp,
801 &volume_info.flags,
802 volume_info.type, 32))
804 return TRUE;
806 return FALSE;
809 /* Determine if volume is FAT format (ie. only supports short 8.3
810 names); also set path pointer to start of pathname in name. */
812 is_fat_volume (const char * name, const char ** pPath)
814 if (get_volume_info (name, pPath))
815 return (volume_info.maxcomp == 12);
816 return FALSE;
819 /* Map filename to a legal 8.3 name if necessary. */
820 const char *
821 map_win32_filename (const char * name, const char ** pPath)
823 static char shortname[MAX_PATH];
824 char * str = shortname;
825 char c;
826 char * path;
828 if (is_fat_volume (name, &path)) /* truncate to 8.3 */
830 register int left = 8; /* maximum number of chars in part */
831 register int extn = 0; /* extension added? */
832 register int dots = 2; /* maximum number of dots allowed */
834 while (name < path)
835 *str++ = *name++; /* skip past UNC header */
837 while ((c = *name++))
839 switch ( c )
841 case '\\':
842 case '/':
843 *str++ = '\\';
844 extn = 0; /* reset extension flags */
845 dots = 2; /* max 2 dots */
846 left = 8; /* max length 8 for main part */
847 break;
848 case ':':
849 *str++ = ':';
850 extn = 0; /* reset extension flags */
851 dots = 2; /* max 2 dots */
852 left = 8; /* max length 8 for main part */
853 break;
854 case '.':
855 if ( dots )
857 /* Convert path components of the form .xxx to _xxx,
858 but leave . and .. as they are. This allows .emacs
859 to be read as _emacs, for example. */
861 if (! *name ||
862 *name == '.' ||
863 IS_DIRECTORY_SEP (*name))
865 *str++ = '.';
866 dots--;
868 else
870 *str++ = '_';
871 left--;
872 dots = 0;
875 else if ( !extn )
877 *str++ = '.';
878 extn = 1; /* we've got an extension */
879 left = 3; /* 3 chars in extension */
881 else
883 /* any embedded dots after the first are converted to _ */
884 *str++ = '_';
886 break;
887 case '~':
888 case '#': /* don't lose these, they're important */
889 if ( ! left )
890 str[-1] = c; /* replace last character of part */
891 /* FALLTHRU */
892 default:
893 if ( left )
895 *str++ = tolower (c); /* map to lower case (looks nicer) */
896 left--;
897 dots = 0; /* started a path component */
899 break;
902 *str = '\0';
904 else
906 strcpy (shortname, name);
907 unixtodos_filename (shortname);
910 if (pPath)
911 *pPath = shortname + (path - name);
913 return shortname;
917 /* Shadow some MSVC runtime functions to map requests for long filenames
918 to reasonable short names if necessary. This was originally added to
919 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
920 long file names. */
923 sys_access (const char * path, int mode)
925 return _access (map_win32_filename (path, NULL), mode);
929 sys_chdir (const char * path)
931 return _chdir (map_win32_filename (path, NULL));
935 sys_chmod (const char * path, int mode)
937 return _chmod (map_win32_filename (path, NULL), mode);
941 sys_creat (const char * path, int mode)
943 return _creat (map_win32_filename (path, NULL), mode);
946 FILE *
947 sys_fopen(const char * path, const char * mode)
949 int fd;
950 int oflag;
951 const char * mode_save = mode;
953 /* Force all file handles to be non-inheritable. This is necessary to
954 ensure child processes don't unwittingly inherit handles that might
955 prevent future file access. */
957 if (mode[0] == 'r')
958 oflag = O_RDONLY;
959 else if (mode[0] == 'w' || mode[0] == 'a')
960 oflag = O_WRONLY | O_CREAT | O_TRUNC;
961 else
962 return NULL;
964 /* Only do simplistic option parsing. */
965 while (*++mode)
966 if (mode[0] == '+')
968 oflag &= ~(O_RDONLY | O_WRONLY);
969 oflag |= O_RDWR;
971 else if (mode[0] == 'b')
973 oflag &= ~O_TEXT;
974 oflag |= O_BINARY;
976 else if (mode[0] == 't')
978 oflag &= ~O_BINARY;
979 oflag |= O_TEXT;
981 else break;
983 fd = _open (map_win32_filename (path, NULL), oflag | _O_NOINHERIT, 0644);
984 if (fd < 0)
985 return NULL;
987 return fdopen (fd, mode_save);
991 sys_link (const char * path1, const char * path2)
993 errno = EINVAL;
994 return -1;
998 sys_mkdir (const char * path)
1000 return _mkdir (map_win32_filename (path, NULL));
1003 /* Because of long name mapping issues, we need to implement this
1004 ourselves. Also, MSVC's _mktemp returns NULL when it can't generate
1005 a unique name, instead of setting the input template to an empty
1006 string.
1008 Standard algorithm seems to be use pid or tid with a letter on the
1009 front (in place of the 6 X's) and cycle through the letters to find a
1010 unique name. We extend that to allow any reasonable character as the
1011 first of the 6 X's. */
1012 char *
1013 sys_mktemp (char * template)
1015 char * p;
1016 int i;
1017 unsigned uid = GetCurrentThreadId ();
1018 static char first_char[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
1020 if (template == NULL)
1021 return NULL;
1022 p = template + strlen (template);
1023 i = 5;
1024 /* replace up to the last 5 X's with uid in decimal */
1025 while (--p >= template && p[0] == 'X' && --i >= 0)
1027 p[0] = '0' + uid % 10;
1028 uid /= 10;
1031 if (i < 0 && p[0] == 'X')
1033 i = 0;
1036 int save_errno = errno;
1037 p[0] = first_char[i];
1038 if (sys_access (template, 0) < 0)
1040 errno = save_errno;
1041 return template;
1044 while (++i < sizeof (first_char));
1047 /* Template is badly formed or else we can't generate a unique name,
1048 so return empty string */
1049 template[0] = 0;
1050 return template;
1054 sys_open (const char * path, int oflag, int mode)
1056 /* Force all file handles to be non-inheritable. */
1057 return _open (map_win32_filename (path, NULL), oflag | _O_NOINHERIT, mode);
1061 sys_rename (const char * oldname, const char * newname)
1063 char temp[MAX_PATH];
1064 DWORD attr;
1066 /* MoveFile on Win95 doesn't correctly change the short file name
1067 alias in a number of circumstances (it is not easy to predict when
1068 just by looking at oldname and newname, unfortunately). In these
1069 cases, renaming through a temporary name avoids the problem.
1071 A second problem on Win95 is that renaming through a temp name when
1072 newname is uppercase fails (the final long name ends up in
1073 lowercase, although the short alias might be uppercase) UNLESS the
1074 long temp name is not 8.3.
1076 So, on Win95 we always rename through a temp name, and we make sure
1077 the temp name has a long extension to ensure correct renaming. */
1079 strcpy (temp, map_win32_filename (oldname, NULL));
1081 if (GetVersion () & 0x80000000)
1083 char * p;
1085 if (p = strrchr (temp, '\\'))
1086 p++;
1087 else
1088 p = temp;
1089 strcpy (p, "__XXXXXX");
1090 sys_mktemp (temp);
1091 /* Force temp name to require a manufactured 8.3 alias - this
1092 seems to make the second rename work properly. */
1093 strcat (temp, ".long");
1094 if (rename (map_win32_filename (oldname, NULL), temp) < 0)
1095 return -1;
1098 /* Emulate Unix behaviour - newname is deleted if it already exists
1099 (at least if it is a file; don't do this for directories).
1100 However, don't do this if we are just changing the case of the file
1101 name - we will end up deleting the file we are trying to rename! */
1102 newname = map_win32_filename (newname, NULL);
1103 if (stricmp (newname, temp) != 0
1104 && (attr = GetFileAttributes (newname)) != -1
1105 && (attr & FILE_ATTRIBUTE_DIRECTORY) == 0)
1107 _chmod (newname, 0666);
1108 _unlink (newname);
1111 return rename (temp, newname);
1115 sys_rmdir (const char * path)
1117 return _rmdir (map_win32_filename (path, NULL));
1121 sys_unlink (const char * path)
1123 return _unlink (map_win32_filename (path, NULL));
1126 static FILETIME utc_base_ft;
1127 static long double utc_base;
1128 static int init = 0;
1130 static time_t
1131 convert_time (FILETIME ft)
1133 long double ret;
1135 if (!init)
1137 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
1138 SYSTEMTIME st;
1140 st.wYear = 1970;
1141 st.wMonth = 1;
1142 st.wDay = 1;
1143 st.wHour = 0;
1144 st.wMinute = 0;
1145 st.wSecond = 0;
1146 st.wMilliseconds = 0;
1148 SystemTimeToFileTime (&st, &utc_base_ft);
1149 utc_base = (long double) utc_base_ft.dwHighDateTime
1150 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
1151 init = 1;
1154 if (CompareFileTime (&ft, &utc_base_ft) < 0)
1155 return 0;
1157 ret = (long double) ft.dwHighDateTime * 4096 * 1024 * 1024 + ft.dwLowDateTime;
1158 ret -= utc_base;
1159 return (time_t) (ret * 1e-7);
1162 #if 0
1163 /* in case we ever have need of this */
1164 void
1165 convert_from_time_t (time_t time, FILETIME * pft)
1167 long double tmp;
1169 if (!init)
1171 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
1172 SYSTEMTIME st;
1174 st.wYear = 1970;
1175 st.wMonth = 1;
1176 st.wDay = 1;
1177 st.wHour = 0;
1178 st.wMinute = 0;
1179 st.wSecond = 0;
1180 st.wMilliseconds = 0;
1182 SystemTimeToFileTime (&st, &utc_base_ft);
1183 utc_base = (long double) utc_base_ft.dwHighDateTime
1184 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
1185 init = 1;
1188 /* time in 100ns units since 1-Jan-1601 */
1189 tmp = (long double) time * 1e7 + utc_base;
1190 pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024));
1191 pft->dwLowDateTime = (DWORD) (tmp - pft->dwHighDateTime);
1193 #endif
1195 /* "PJW" algorithm (see the "Dragon" compiler book). */
1196 static unsigned
1197 hashval (const char * str)
1199 unsigned h = 0;
1200 unsigned g;
1201 while (*str)
1203 h = (h << 4) + *str++;
1204 if ((g = h & 0xf0000000) != 0)
1205 h = (h ^ (g >> 24)) & 0x0fffffff;
1207 return h;
1210 /* Return the hash value of the canonical pathname, excluding the
1211 drive/UNC header, to get a hopefully unique inode number. */
1212 static _ino_t
1213 generate_inode_val (const char * name)
1215 char fullname[ MAX_PATH ];
1216 char * p;
1217 unsigned hash;
1219 GetFullPathName (name, sizeof (fullname), fullname, &p);
1220 get_volume_info (fullname, &p);
1221 /* Normal Win32 filesystems are still case insensitive. */
1222 _strlwr (p);
1223 hash = hashval (p);
1224 return (_ino_t) (hash ^ (hash >> 16));
1227 /* MSVC stat function can't cope with UNC names and has other bugs, so
1228 replace it with our own. This also allows us to calculate consistent
1229 inode values without hacks in the main Emacs code. */
1231 stat (const char * path, struct stat * buf)
1233 char * name;
1234 WIN32_FIND_DATA wfd;
1235 HANDLE fh;
1236 int permission;
1237 int len;
1238 int rootdir = FALSE;
1240 if (path == NULL || buf == NULL)
1242 errno = EFAULT;
1243 return -1;
1246 name = (char *) map_win32_filename (path, &path);
1247 /* must be valid filename, no wild cards */
1248 if (strchr (name, '*') || strchr (name, '?'))
1250 errno = ENOENT;
1251 return -1;
1254 /* Remove trailing directory separator, unless name is the root
1255 directory of a drive or UNC volume in which case ensure there
1256 is a trailing separator. */
1257 len = strlen (name);
1258 rootdir = (path >= name + len - 1
1259 && (IS_DIRECTORY_SEP (*path) || *path == 0));
1260 name = strcpy (alloca (len + 2), name);
1262 if (rootdir)
1264 if (!IS_DIRECTORY_SEP (name[len-1]))
1265 strcat (name, "\\");
1266 if (GetDriveType (name) < 2)
1268 errno = ENOENT;
1269 return -1;
1271 memset (&wfd, 0, sizeof (wfd));
1272 wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
1273 wfd.ftCreationTime = utc_base_ft;
1274 wfd.ftLastAccessTime = utc_base_ft;
1275 wfd.ftLastWriteTime = utc_base_ft;
1276 strcpy (wfd.cFileName, name);
1278 else
1280 if (IS_DIRECTORY_SEP (name[len-1]))
1281 name[len - 1] = 0;
1282 fh = FindFirstFile (name, &wfd);
1283 if (fh == INVALID_HANDLE_VALUE)
1285 errno = ENOENT;
1286 return -1;
1288 FindClose (fh);
1291 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1293 buf->st_mode = _S_IFDIR;
1294 buf->st_nlink = 2; /* doesn't really matter */
1296 else
1298 #if 0
1299 /* This is more accurate in terms of gettting the correct number
1300 of links, but is quite slow (it is noticable when Emacs is
1301 making a list of file name completions). */
1302 BY_HANDLE_FILE_INFORMATION info;
1304 fh = CreateFile (name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
1305 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1307 if (GetFileInformationByHandle (fh, &info))
1309 switch (GetFileType (fh))
1311 case FILE_TYPE_DISK:
1312 buf->st_mode = _S_IFREG;
1313 break;
1314 case FILE_TYPE_PIPE:
1315 buf->st_mode = _S_IFIFO;
1316 break;
1317 case FILE_TYPE_CHAR:
1318 case FILE_TYPE_UNKNOWN:
1319 default:
1320 buf->st_mode = _S_IFCHR;
1322 buf->st_nlink = info.nNumberOfLinks;
1323 /* Could use file index, but this is not guaranteed to be
1324 unique unless we keep a handle open all the time. */
1325 /* buf->st_ino = info.nFileIndexLow ^ info.nFileIndexHigh; */
1326 CloseHandle (fh);
1328 else
1330 errno = EACCES;
1331 return -1;
1333 #else
1334 buf->st_mode = _S_IFREG;
1335 buf->st_nlink = 1;
1336 #endif
1339 /* consider files to belong to current user */
1340 buf->st_uid = the_passwd.pw_uid;
1341 buf->st_gid = the_passwd.pw_gid;
1343 /* volume_info is set indirectly by map_win32_filename */
1344 buf->st_dev = volume_info.serialnum;
1345 buf->st_rdev = volume_info.serialnum;
1347 buf->st_ino = generate_inode_val (name);
1349 buf->st_size = wfd.nFileSizeLow;
1351 /* Convert timestamps to Unix format. */
1352 buf->st_mtime = convert_time (wfd.ftLastWriteTime);
1353 buf->st_atime = convert_time (wfd.ftLastAccessTime);
1354 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
1355 buf->st_ctime = convert_time (wfd.ftCreationTime);
1356 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
1358 /* determine rwx permissions */
1359 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
1360 permission = _S_IREAD;
1361 else
1362 permission = _S_IREAD | _S_IWRITE;
1364 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1365 permission |= _S_IEXEC;
1366 else
1368 char * p = strrchr (name, '.');
1369 if (p != NULL &&
1370 (stricmp (p, ".exe") == 0 ||
1371 stricmp (p, ".com") == 0 ||
1372 stricmp (p, ".bat") == 0 ||
1373 stricmp (p, ".cmd") == 0))
1374 permission |= _S_IEXEC;
1377 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
1379 return 0;
1382 #ifdef HAVE_SOCKETS
1384 /* Wrappers for winsock functions to map between our file descriptors
1385 and winsock's handles; also set h_errno for convenience.
1387 To allow Emacs to run on systems which don't have winsock support
1388 installed, we dynamically link to winsock on startup if present, and
1389 otherwise provide the minimum necessary functionality
1390 (eg. gethostname). */
1392 /* function pointers for relevant socket functions */
1393 int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
1394 void (PASCAL *pfn_WSASetLastError) (int iError);
1395 int (PASCAL *pfn_WSAGetLastError) (void);
1396 int (PASCAL *pfn_socket) (int af, int type, int protocol);
1397 int (PASCAL *pfn_bind) (SOCKET s, const struct sockaddr *addr, int namelen);
1398 int (PASCAL *pfn_connect) (SOCKET s, const struct sockaddr *addr, int namelen);
1399 int (PASCAL *pfn_ioctlsocket) (SOCKET s, long cmd, u_long *argp);
1400 int (PASCAL *pfn_recv) (SOCKET s, char * buf, int len, int flags);
1401 int (PASCAL *pfn_send) (SOCKET s, const char * buf, int len, int flags);
1402 int (PASCAL *pfn_closesocket) (SOCKET s);
1403 int (PASCAL *pfn_shutdown) (SOCKET s, int how);
1404 int (PASCAL *pfn_WSACleanup) (void);
1406 u_short (PASCAL *pfn_htons) (u_short hostshort);
1407 u_short (PASCAL *pfn_ntohs) (u_short netshort);
1408 unsigned long (PASCAL *pfn_inet_addr) (const char * cp);
1409 int (PASCAL *pfn_gethostname) (char * name, int namelen);
1410 struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
1411 struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto);
1413 /* SetHandleInformation is only needed to make sockets non-inheritable. */
1414 BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags);
1415 #ifndef HANDLE_FLAG_INHERIT
1416 #define HANDLE_FLAG_INHERIT 1
1417 #endif
1419 HANDLE winsock_lib;
1420 static int winsock_inuse;
1422 BOOL
1423 term_winsock (void)
1425 if (winsock_lib != NULL && winsock_inuse == 0)
1427 /* Not sure what would cause WSAENETDOWN, or even if it can happen
1428 after WSAStartup returns successfully, but it seems reasonable
1429 to allow unloading winsock anyway in that case. */
1430 if (pfn_WSACleanup () == 0 ||
1431 pfn_WSAGetLastError () == WSAENETDOWN)
1433 if (FreeLibrary (winsock_lib))
1434 winsock_lib = NULL;
1435 return TRUE;
1438 return FALSE;
1441 BOOL
1442 init_winsock (int load_now)
1444 WSADATA winsockData;
1446 if (winsock_lib != NULL)
1447 return TRUE;
1449 pfn_SetHandleInformation = NULL;
1450 pfn_SetHandleInformation
1451 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
1452 "SetHandleInformation");
1454 winsock_lib = LoadLibrary ("wsock32.dll");
1456 if (winsock_lib != NULL)
1458 /* dynamically link to socket functions */
1460 #define LOAD_PROC(fn) \
1461 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
1462 goto fail;
1464 LOAD_PROC( WSAStartup );
1465 LOAD_PROC( WSASetLastError );
1466 LOAD_PROC( WSAGetLastError );
1467 LOAD_PROC( socket );
1468 LOAD_PROC( bind );
1469 LOAD_PROC( connect );
1470 LOAD_PROC( ioctlsocket );
1471 LOAD_PROC( recv );
1472 LOAD_PROC( send );
1473 LOAD_PROC( closesocket );
1474 LOAD_PROC( shutdown );
1475 LOAD_PROC( htons );
1476 LOAD_PROC( ntohs );
1477 LOAD_PROC( inet_addr );
1478 LOAD_PROC( gethostname );
1479 LOAD_PROC( gethostbyname );
1480 LOAD_PROC( getservbyname );
1481 LOAD_PROC( WSACleanup );
1483 #undef LOAD_PROC
1485 /* specify version 1.1 of winsock */
1486 if (pfn_WSAStartup (0x101, &winsockData) == 0)
1488 if (winsockData.wVersion != 0x101)
1489 goto fail;
1491 if (!load_now)
1493 /* Report that winsock exists and is usable, but leave
1494 socket functions disabled. I am assuming that calling
1495 WSAStartup does not require any network interaction,
1496 and in particular does not cause or require a dial-up
1497 connection to be established. */
1499 pfn_WSACleanup ();
1500 FreeLibrary (winsock_lib);
1501 winsock_lib = NULL;
1503 winsock_inuse = 0;
1504 return TRUE;
1507 fail:
1508 FreeLibrary (winsock_lib);
1509 winsock_lib = NULL;
1512 return FALSE;
1516 int h_errno = 0;
1518 /* function to set h_errno for compatability; map winsock error codes to
1519 normal system codes where they overlap (non-overlapping definitions
1520 are already in <sys/socket.h> */
1521 static void set_errno ()
1523 if (winsock_lib == NULL)
1524 h_errno = EINVAL;
1525 else
1526 h_errno = pfn_WSAGetLastError ();
1528 switch (h_errno)
1530 case WSAEACCES: h_errno = EACCES; break;
1531 case WSAEBADF: h_errno = EBADF; break;
1532 case WSAEFAULT: h_errno = EFAULT; break;
1533 case WSAEINTR: h_errno = EINTR; break;
1534 case WSAEINVAL: h_errno = EINVAL; break;
1535 case WSAEMFILE: h_errno = EMFILE; break;
1536 case WSAENAMETOOLONG: h_errno = ENAMETOOLONG; break;
1537 case WSAENOTEMPTY: h_errno = ENOTEMPTY; break;
1539 errno = h_errno;
1542 static void check_errno ()
1544 if (h_errno == 0 && winsock_lib != NULL)
1545 pfn_WSASetLastError (0);
1548 /* [andrewi 3-May-96] I've had conflicting results using both methods,
1549 but I believe the method of keeping the socket handle separate (and
1550 insuring it is not inheritable) is the correct one. */
1552 //#define SOCK_REPLACE_HANDLE
1554 #ifdef SOCK_REPLACE_HANDLE
1555 #define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
1556 #else
1557 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
1558 #endif
1561 sys_socket(int af, int type, int protocol)
1563 int fd;
1564 long s;
1565 child_process * cp;
1567 if (winsock_lib == NULL)
1569 h_errno = ENETDOWN;
1570 return INVALID_SOCKET;
1573 check_errno ();
1575 /* call the real socket function */
1576 s = (long) pfn_socket (af, type, protocol);
1578 if (s != INVALID_SOCKET)
1580 /* Although under NT 3.5 _open_osfhandle will accept a socket
1581 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
1582 that does not work under NT 3.1. However, we can get the same
1583 effect by using a backdoor function to replace an existing
1584 descriptor handle with the one we want. */
1586 /* allocate a file descriptor (with appropriate flags) */
1587 fd = _open ("NUL:", _O_RDWR);
1588 if (fd >= 0)
1590 #ifdef SOCK_REPLACE_HANDLE
1591 /* now replace handle to NUL with our socket handle */
1592 CloseHandle ((HANDLE) _get_osfhandle (fd));
1593 _free_osfhnd (fd);
1594 _set_osfhnd (fd, s);
1595 /* setmode (fd, _O_BINARY); */
1596 #else
1597 /* Make a non-inheritable copy of the socket handle. */
1599 HANDLE parent;
1600 HANDLE new_s = INVALID_HANDLE_VALUE;
1602 parent = GetCurrentProcess ();
1604 /* Apparently there is a bug in NT 3.51 with some service
1605 packs, which prevents using DuplicateHandle to make a
1606 socket handle non-inheritable (causes WSACleanup to
1607 hang). The work-around is to use SetHandleInformation
1608 instead if it is available and implemented. */
1609 if (!pfn_SetHandleInformation
1610 || !pfn_SetHandleInformation ((HANDLE) s,
1611 HANDLE_FLAG_INHERIT,
1612 HANDLE_FLAG_INHERIT))
1614 DuplicateHandle (parent,
1615 (HANDLE) s,
1616 parent,
1617 &new_s,
1619 FALSE,
1620 DUPLICATE_SAME_ACCESS);
1621 pfn_closesocket (s);
1622 s = (SOCKET) new_s;
1624 fd_info[fd].hnd = (HANDLE) s;
1626 #endif
1628 /* set our own internal flags */
1629 fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
1631 cp = new_child ();
1632 if (cp)
1634 cp->fd = fd;
1635 cp->status = STATUS_READ_ACKNOWLEDGED;
1637 /* attach child_process to fd_info */
1638 if (fd_info[ fd ].cp != NULL)
1640 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
1641 abort ();
1644 fd_info[ fd ].cp = cp;
1646 /* success! */
1647 winsock_inuse++; /* count open sockets */
1648 return fd;
1651 /* clean up */
1652 _close (fd);
1654 pfn_closesocket (s);
1655 h_errno = EMFILE;
1657 set_errno ();
1659 return -1;
1664 sys_bind (int s, const struct sockaddr * addr, int namelen)
1666 if (winsock_lib == NULL)
1668 h_errno = ENOTSOCK;
1669 return SOCKET_ERROR;
1672 check_errno ();
1673 if (fd_info[s].flags & FILE_SOCKET)
1675 int rc = pfn_bind (SOCK_HANDLE (s), addr, namelen);
1676 if (rc == SOCKET_ERROR)
1677 set_errno ();
1678 return rc;
1680 h_errno = ENOTSOCK;
1681 return SOCKET_ERROR;
1686 sys_connect (int s, const struct sockaddr * name, int namelen)
1688 if (winsock_lib == NULL)
1690 h_errno = ENOTSOCK;
1691 return SOCKET_ERROR;
1694 check_errno ();
1695 if (fd_info[s].flags & FILE_SOCKET)
1697 int rc = pfn_connect (SOCK_HANDLE (s), name, namelen);
1698 if (rc == SOCKET_ERROR)
1699 set_errno ();
1700 return rc;
1702 h_errno = ENOTSOCK;
1703 return SOCKET_ERROR;
1706 u_short
1707 sys_htons (u_short hostshort)
1709 return (winsock_lib != NULL) ?
1710 pfn_htons (hostshort) : hostshort;
1713 u_short
1714 sys_ntohs (u_short netshort)
1716 return (winsock_lib != NULL) ?
1717 pfn_ntohs (netshort) : netshort;
1720 unsigned long
1721 sys_inet_addr (const char * cp)
1723 return (winsock_lib != NULL) ?
1724 pfn_inet_addr (cp) : INADDR_NONE;
1728 sys_gethostname (char * name, int namelen)
1730 if (winsock_lib != NULL)
1731 return pfn_gethostname (name, namelen);
1733 if (namelen > MAX_COMPUTERNAME_LENGTH)
1734 return !GetComputerName (name, &namelen);
1736 h_errno = EFAULT;
1737 return SOCKET_ERROR;
1740 struct hostent *
1741 sys_gethostbyname(const char * name)
1743 struct hostent * host;
1745 if (winsock_lib == NULL)
1747 h_errno = ENETDOWN;
1748 return NULL;
1751 check_errno ();
1752 host = pfn_gethostbyname (name);
1753 if (!host)
1754 set_errno ();
1755 return host;
1758 struct servent *
1759 sys_getservbyname(const char * name, const char * proto)
1761 struct servent * serv;
1763 if (winsock_lib == NULL)
1765 h_errno = ENETDOWN;
1766 return NULL;
1769 check_errno ();
1770 serv = pfn_getservbyname (name, proto);
1771 if (!serv)
1772 set_errno ();
1773 return serv;
1776 #endif /* HAVE_SOCKETS */
1779 /* Shadow main io functions: we need to handle pipes and sockets more
1780 intelligently, and implement non-blocking mode as well. */
1783 sys_close (int fd)
1785 int rc;
1787 if (fd < 0 || fd >= MAXDESC)
1789 errno = EBADF;
1790 return -1;
1793 if (fd_info[fd].cp)
1795 child_process * cp = fd_info[fd].cp;
1797 fd_info[fd].cp = NULL;
1799 if (CHILD_ACTIVE (cp))
1801 /* if last descriptor to active child_process then cleanup */
1802 int i;
1803 for (i = 0; i < MAXDESC; i++)
1805 if (i == fd)
1806 continue;
1807 if (fd_info[i].cp == cp)
1808 break;
1810 if (i == MAXDESC)
1812 #ifdef HAVE_SOCKETS
1813 if (fd_info[fd].flags & FILE_SOCKET)
1815 #ifndef SOCK_REPLACE_HANDLE
1816 if (winsock_lib == NULL) abort ();
1818 pfn_shutdown (SOCK_HANDLE (fd), 2);
1819 rc = pfn_closesocket (SOCK_HANDLE (fd));
1820 #endif
1821 winsock_inuse--; /* count open sockets */
1823 #endif
1824 delete_child (cp);
1829 /* Note that sockets do not need special treatment here (at least on
1830 NT and Win95 using the standard tcp/ip stacks) - it appears that
1831 closesocket is equivalent to CloseHandle, which is to be expected
1832 because socket handles are fully fledged kernel handles. */
1833 rc = _close (fd);
1835 if (rc == 0)
1836 fd_info[fd].flags = 0;
1838 return rc;
1842 sys_dup (int fd)
1844 int new_fd;
1846 new_fd = _dup (fd);
1847 if (new_fd >= 0)
1849 /* duplicate our internal info as well */
1850 fd_info[new_fd] = fd_info[fd];
1852 return new_fd;
1857 sys_dup2 (int src, int dst)
1859 int rc;
1861 if (dst < 0 || dst >= MAXDESC)
1863 errno = EBADF;
1864 return -1;
1867 /* make sure we close the destination first if it's a pipe or socket */
1868 if (src != dst && fd_info[dst].flags != 0)
1869 sys_close (dst);
1871 rc = _dup2 (src, dst);
1872 if (rc == 0)
1874 /* duplicate our internal info as well */
1875 fd_info[dst] = fd_info[src];
1877 return rc;
1880 /* From callproc.c */
1881 extern Lisp_Object Vbinary_process_input;
1882 extern Lisp_Object Vbinary_process_output;
1884 /* Unix pipe() has only one arg */
1886 sys_pipe (int * phandles)
1888 int rc;
1889 unsigned flags;
1890 child_process * cp;
1892 /* make pipe handles non-inheritable; when we spawn a child,
1893 we replace the relevant handle with an inheritable one. */
1894 rc = _pipe (phandles, 0, _O_NOINHERIT);
1896 if (rc == 0)
1898 /* set internal flags, and put read and write handles into binary
1899 mode as necessary; if not in binary mode, set the MSVC internal
1900 FDEV (0x40) flag to prevent _read from treating ^Z as eof (this
1901 could otherwise allow Emacs to hang because it then waits
1902 indefinitely for the child process to exit, when it might not be
1903 finished). */
1904 flags = FILE_PIPE | FILE_READ;
1905 if (!NILP (Vbinary_process_output))
1907 flags |= FILE_BINARY;
1908 setmode (phandles[0], _O_BINARY);
1910 #if (_MSC_VER == 900)
1911 else
1912 _osfile[phandles[0]] |= 0x40;
1913 #endif
1915 fd_info[phandles[0]].flags = flags;
1917 flags = FILE_PIPE | FILE_WRITE;
1918 if (!NILP (Vbinary_process_input))
1920 flags |= FILE_BINARY;
1921 setmode (phandles[1], _O_BINARY);
1923 #if (_MSC_VER == 900)
1924 else
1925 _osfile[phandles[1]] |= 0x40;
1926 #endif
1928 fd_info[phandles[1]].flags = flags;
1931 return rc;
1934 /* From ntproc.c */
1935 extern Lisp_Object Vwin32_pipe_read_delay;
1937 /* Function to do blocking read of one byte, needed to implement
1938 select. It is only allowed on sockets and pipes. */
1940 _sys_read_ahead (int fd)
1942 child_process * cp;
1943 int rc;
1945 if (fd < 0 || fd >= MAXDESC)
1946 return STATUS_READ_ERROR;
1948 cp = fd_info[fd].cp;
1950 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
1951 return STATUS_READ_ERROR;
1953 if ((fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) == 0
1954 || (fd_info[fd].flags & FILE_READ) == 0)
1956 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd));
1957 abort ();
1960 cp->status = STATUS_READ_IN_PROGRESS;
1962 if (fd_info[fd].flags & FILE_PIPE)
1964 /* Use read to get CRLF translation */
1965 rc = _read (fd, &cp->chr, sizeof (char));
1967 /* Give subprocess time to buffer some more output for us before
1968 reporting that input is available; we need this because Win95
1969 connects DOS programs to pipes by making the pipe appear to be
1970 the normal console stdout - as a result most DOS programs will
1971 write to stdout without buffering, ie. one character at a
1972 time. Even some Win32 programs do this - "dir" in a command
1973 shell on NT is very slow if we don't do this. */
1974 if (rc > 0)
1976 int wait = XINT (Vwin32_pipe_read_delay);
1978 if (wait > 0)
1979 Sleep (wait);
1980 else if (wait < 0)
1981 while (++wait <= 0)
1982 /* Yield remainder of our time slice, effectively giving a
1983 temporary priority boost to the child process. */
1984 Sleep (0);
1987 #ifdef HAVE_SOCKETS
1988 else if (fd_info[fd].flags & FILE_SOCKET)
1989 rc = pfn_recv (SOCK_HANDLE (fd), &cp->chr, sizeof (char), 0);
1990 #endif
1992 if (rc == sizeof (char))
1993 cp->status = STATUS_READ_SUCCEEDED;
1994 else
1995 cp->status = STATUS_READ_FAILED;
1997 return cp->status;
2001 sys_read (int fd, char * buffer, unsigned int count)
2003 int nchars;
2004 int extra = 0;
2005 int to_read;
2006 DWORD waiting;
2008 if (fd < 0 || fd >= MAXDESC)
2010 errno = EBADF;
2011 return -1;
2014 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
2016 child_process *cp = fd_info[fd].cp;
2018 if ((fd_info[fd].flags & FILE_READ) == 0)
2020 errno = EBADF;
2021 return -1;
2024 /* presence of a child_process structure means we are operating in
2025 non-blocking mode - otherwise we just call _read directly.
2026 Note that the child_process structure might be missing because
2027 reap_subprocess has been called; in this case the pipe is
2028 already broken, so calling _read on it is okay. */
2029 if (cp)
2031 int current_status = cp->status;
2033 switch (current_status)
2035 case STATUS_READ_FAILED:
2036 case STATUS_READ_ERROR:
2037 /* report normal EOF */
2038 return 0;
2040 case STATUS_READ_READY:
2041 case STATUS_READ_IN_PROGRESS:
2042 DebPrint (("sys_read called when read is in progress\n"));
2043 errno = EWOULDBLOCK;
2044 return -1;
2046 case STATUS_READ_SUCCEEDED:
2047 /* consume read-ahead char */
2048 *buffer++ = cp->chr;
2049 count--;
2050 extra = 1;
2051 cp->status = STATUS_READ_ACKNOWLEDGED;
2052 ResetEvent (cp->char_avail);
2054 case STATUS_READ_ACKNOWLEDGED:
2055 break;
2057 default:
2058 DebPrint (("sys_read: bad status %d\n", current_status));
2059 errno = EBADF;
2060 return -1;
2063 if (fd_info[fd].flags & FILE_PIPE)
2065 PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL);
2066 to_read = min (waiting, (DWORD) count);
2068 /* Use read to get CRLF translation */
2069 nchars = _read (fd, buffer, to_read);
2071 #ifdef HAVE_SOCKETS
2072 else /* FILE_SOCKET */
2074 if (winsock_lib == NULL) abort ();
2076 /* do the equivalent of a non-blocking read */
2077 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
2078 if (waiting == 0 && extra == 0)
2080 h_errno = errno = EWOULDBLOCK;
2081 return -1;
2084 nchars = 0;
2085 if (waiting)
2087 /* always use binary mode for sockets */
2088 nchars = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0);
2089 if (nchars == SOCKET_ERROR)
2091 DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
2092 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
2093 if (extra == 0)
2095 set_errno ();
2096 return -1;
2098 nchars = 0;
2102 #endif
2104 else
2105 nchars = _read (fd, buffer, count);
2107 else
2108 nchars = _read (fd, buffer, count);
2110 return nchars + extra;
2113 /* For now, don't bother with a non-blocking mode */
2115 sys_write (int fd, const void * buffer, unsigned int count)
2117 int nchars;
2119 if (fd < 0 || fd >= MAXDESC)
2121 errno = EBADF;
2122 return -1;
2125 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
2126 if ((fd_info[fd].flags & FILE_WRITE) == 0)
2128 errno = EBADF;
2129 return -1;
2131 #ifdef HAVE_SOCKETS
2132 if (fd_info[fd].flags & FILE_SOCKET)
2134 if (winsock_lib == NULL) abort ();
2135 nchars = pfn_send (SOCK_HANDLE (fd), buffer, count, 0);
2136 if (nchars == SOCKET_ERROR)
2138 DebPrint(("sys_read.send failed with error %d on socket %ld\n",
2139 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
2140 set_errno ();
2143 else
2144 #endif
2145 nchars = _write (fd, buffer, count);
2147 return nchars;
2151 void
2152 term_ntproc ()
2154 #ifdef HAVE_SOCKETS
2155 /* shutdown the socket interface if necessary */
2156 term_winsock ();
2157 #endif
2160 extern BOOL dos_process_running;
2162 void
2163 init_ntproc ()
2165 #ifdef HAVE_SOCKETS
2166 /* Initialise the socket interface now if available and requested by
2167 the user by defining PRELOAD_WINSOCK; otherwise loading will be
2168 delayed until open-network-stream is called (win32-has-winsock can
2169 also be used to dynamically load or reload winsock).
2171 Conveniently, init_environment is called before us, so
2172 PRELOAD_WINSOCK can be set in the registry. */
2174 /* Always initialize this correctly. */
2175 winsock_lib = NULL;
2177 if (getenv ("PRELOAD_WINSOCK") != NULL)
2178 init_winsock (TRUE);
2179 #endif
2181 /* Initial preparation for subprocess support: replace our standard
2182 handles with non-inheritable versions. */
2184 HANDLE parent;
2185 HANDLE stdin_save = INVALID_HANDLE_VALUE;
2186 HANDLE stdout_save = INVALID_HANDLE_VALUE;
2187 HANDLE stderr_save = INVALID_HANDLE_VALUE;
2189 parent = GetCurrentProcess ();
2191 /* ignore errors when duplicating and closing; typically the
2192 handles will be invalid when running as a gui program. */
2193 DuplicateHandle (parent,
2194 GetStdHandle (STD_INPUT_HANDLE),
2195 parent,
2196 &stdin_save,
2198 FALSE,
2199 DUPLICATE_SAME_ACCESS);
2201 DuplicateHandle (parent,
2202 GetStdHandle (STD_OUTPUT_HANDLE),
2203 parent,
2204 &stdout_save,
2206 FALSE,
2207 DUPLICATE_SAME_ACCESS);
2209 DuplicateHandle (parent,
2210 GetStdHandle (STD_ERROR_HANDLE),
2211 parent,
2212 &stderr_save,
2214 FALSE,
2215 DUPLICATE_SAME_ACCESS);
2217 fclose (stdin);
2218 fclose (stdout);
2219 fclose (stderr);
2221 if (stdin_save != INVALID_HANDLE_VALUE)
2222 _open_osfhandle ((long) stdin_save, O_TEXT);
2223 else
2224 open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY);
2225 fdopen (0, "r");
2227 if (stdout_save != INVALID_HANDLE_VALUE)
2228 _open_osfhandle ((long) stdout_save, O_TEXT);
2229 else
2230 open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
2231 fdopen (1, "w");
2233 if (stderr_save != INVALID_HANDLE_VALUE)
2234 _open_osfhandle ((long) stderr_save, O_TEXT);
2235 else
2236 open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
2237 fdopen (2, "w");
2240 /* Restrict Emacs to running only one DOS program at a time (with any
2241 number of Win32 programs). This is to prevent the user from
2242 running into problems with DOS programs being run in the same VDM
2243 under both Windows 95 and Windows NT.
2245 Note that it is possible for Emacs to run DOS programs in separate
2246 VDMs, but unfortunately the pipe implementation on Windows 95 then
2247 fails to report when the DOS process exits (which is supposed to
2248 break the pipe). Until this bug is fixed, or we can devise a
2249 work-around, we must try to avoid letting the user start more than
2250 one DOS program if possible. */
2252 dos_process_running = FALSE;
2254 /* unfortunately, atexit depends on implementation of malloc */
2255 /* atexit (term_ntproc); */
2256 signal (SIGABRT, term_ntproc);
2259 /* end of nt.c */