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)
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
34 /* must include CRT headers *before* config.h */
65 #ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
66 #include <sys/socket.h>
82 /* Get the current working directory. */
86 if (GetCurrentDirectory (MAXPATHLEN
, dir
) > 0)
92 /* Emulate gethostname. */
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
)
108 /* A faithful emulation is going to have to be saved for a rainy day. */
109 for (i
= 0; i
< nelem
; 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];
126 opendir (char *filename
)
130 /* Opening is done by FindFirstFile. However, a read is inherent to
131 this operation, so we defer the open until read time. */
133 if (!(dirp
= (DIR *) malloc (sizeof (DIR))))
135 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
142 strncpy (dir_pathname
, filename
, MAXPATHLEN
);
143 dir_pathname
[MAXPATHLEN
] = '\0';
144 dir_is_fat
= is_fat_volume (filename
, NULL
);
152 /* If we have a find-handle open, close it. */
153 if (dir_find_handle
!= INVALID_HANDLE_VALUE
)
155 FindClose (dir_find_handle
);
156 dir_find_handle
= INVALID_HANDLE_VALUE
;
158 xfree ((char *) dirp
);
164 WIN32_FIND_DATA find_data
;
166 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
167 if (dir_find_handle
== INVALID_HANDLE_VALUE
)
169 char filename
[MAXNAMLEN
+ 3];
172 strcpy (filename
, dir_pathname
);
173 ln
= strlen (filename
) - 1;
174 if (!IS_DIRECTORY_SEP (filename
[ln
]))
175 strcat (filename
, "\\");
176 strcat (filename
, "*");
178 dir_find_handle
= FindFirstFile (filename
, &find_data
);
180 if (dir_find_handle
== INVALID_HANDLE_VALUE
)
185 if (!FindNextFile (dir_find_handle
, &find_data
))
189 /* Emacs never uses this value, so don't bother making it match
190 value returned by stat(). */
191 dir_static
.d_ino
= 1;
193 dir_static
.d_reclen
= sizeof (struct direct
) - MAXNAMLEN
+ 3 +
194 dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
196 dir_static
.d_namlen
= strlen (find_data
.cFileName
);
197 strcpy (dir_static
.d_name
, find_data
.cFileName
);
199 _strlwr (dir_static
.d_name
);
204 /* Emulate getpwuid, getpwnam and others. */
206 #define PASSWD_FIELD_SIZE 256
208 static char the_passwd_name
[PASSWD_FIELD_SIZE
];
209 static char the_passwd_passwd
[PASSWD_FIELD_SIZE
];
210 static char the_passwd_gecos
[PASSWD_FIELD_SIZE
];
211 static char the_passwd_dir
[PASSWD_FIELD_SIZE
];
212 static char the_passwd_shell
[PASSWD_FIELD_SIZE
];
214 static struct passwd the_passwd
=
229 return the_passwd
.pw_uid
;
235 /* I could imagine arguing for checking to see whether the user is
236 in the Administrators group and returning a UID of 0 for that
237 case, but I don't know how wise that would be in the long run. */
244 return the_passwd
.pw_gid
;
256 if (uid
== the_passwd
.pw_uid
)
262 getpwnam (char *name
)
266 pw
= getpwuid (getuid ());
270 if (stricmp (name
, pw
->pw_name
))
279 /* Find the user's real name by opening the process token and
280 looking up the name associated with the user-sid in that token.
282 Use the relative portion of the identifier authority value from
283 the user-sid as the user id value (same for group id using the
284 primary group sid from the process token). */
286 char user_sid
[256], name
[256], domain
[256];
287 DWORD length
= sizeof (name
), dlength
= sizeof (domain
), trash
;
289 SID_NAME_USE user_type
;
291 if (OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY
, &token
)
292 && GetTokenInformation (token
, TokenUser
,
293 (PVOID
) user_sid
, sizeof (user_sid
), &trash
)
294 && LookupAccountSid (NULL
, *((PSID
*) user_sid
), name
, &length
,
295 domain
, &dlength
, &user_type
))
297 strcpy (the_passwd
.pw_name
, name
);
298 /* Determine a reasonable uid value. */
299 if (stricmp ("administrator", name
) == 0)
301 the_passwd
.pw_uid
= 0;
302 the_passwd
.pw_gid
= 0;
306 SID_IDENTIFIER_AUTHORITY
* pSIA
;
308 pSIA
= GetSidIdentifierAuthority (*((PSID
*) user_sid
));
309 /* I believe the relative portion is the last 4 bytes (of 6)
311 the_passwd
.pw_uid
= ((pSIA
->Value
[2] << 24) +
312 (pSIA
->Value
[3] << 16) +
313 (pSIA
->Value
[4] << 8) +
314 (pSIA
->Value
[5] << 0));
315 /* restrict to conventional uid range for normal users */
316 the_passwd
.pw_uid
= the_passwd
.pw_uid
% 60001;
319 if (GetTokenInformation (token
, TokenPrimaryGroup
,
320 (PVOID
) user_sid
, sizeof (user_sid
), &trash
))
322 SID_IDENTIFIER_AUTHORITY
* pSIA
;
324 pSIA
= GetSidIdentifierAuthority (*((PSID
*) user_sid
));
325 the_passwd
.pw_gid
= ((pSIA
->Value
[2] << 24) +
326 (pSIA
->Value
[3] << 16) +
327 (pSIA
->Value
[4] << 8) +
328 (pSIA
->Value
[5] << 0));
329 /* I don't know if this is necessary, but for safety... */
330 the_passwd
.pw_gid
= the_passwd
.pw_gid
% 60001;
333 the_passwd
.pw_gid
= the_passwd
.pw_uid
;
336 /* If security calls are not supported (presumably because we
337 are running under Windows 95), fallback to this. */
338 else if (GetUserName (name
, &length
))
340 strcpy (the_passwd
.pw_name
, name
);
341 if (stricmp ("administrator", name
) == 0)
342 the_passwd
.pw_uid
= 0;
344 the_passwd
.pw_uid
= 123;
345 the_passwd
.pw_gid
= the_passwd
.pw_uid
;
349 strcpy (the_passwd
.pw_name
, "unknown");
350 the_passwd
.pw_uid
= 123;
351 the_passwd
.pw_gid
= 123;
354 /* Ensure HOME and SHELL are defined. */
355 if (getenv ("HOME") == NULL
)
357 if (getenv ("SHELL") == NULL
)
358 putenv ((GetVersion () & 0x80000000) ? "SHELL=command" : "SHELL=cmd");
360 /* Set dir and shell from environment variables. */
361 strcpy (the_passwd
.pw_dir
, getenv ("HOME"));
362 strcpy (the_passwd
.pw_shell
, getenv ("SHELL"));
371 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
372 return ((rand () << 15) | rand ());
381 /* Destructively turn backslashes into slashes. */
383 dostounix_filename (p
)
394 /* Destructively turn slashes into backslashes. */
396 unixtodos_filename (p
)
407 /* Remove all CR's that are followed by a LF.
408 (From msdos.c...probably should figure out a way to share it,
409 although this code isn't going to ever change.) */
413 register unsigned char *buf
;
415 unsigned char *np
= buf
;
416 unsigned char *startp
= buf
;
417 unsigned char *endp
= buf
+ n
;
421 while (buf
< endp
- 1)
425 if (*(++buf
) != 0x0a)
436 /* Routines that are no-ops on NT but are defined to get Emacs to compile. */
439 sigsetmask (int signal_mask
)
451 setpgrp (int pid
, int gid
)
463 unrequest_sigio (void)
474 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
477 nt_get_resource (key
, lpdwtype
)
482 HKEY hrootkey
= NULL
;
486 /* Check both the current user and the local machine to see if
487 we have any resources. */
489 if (RegOpenKeyEx (HKEY_CURRENT_USER
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
493 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
494 && (lpvalue
= (LPBYTE
) xmalloc (cbData
)) != NULL
495 && RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
500 if (lpvalue
) xfree (lpvalue
);
502 RegCloseKey (hrootkey
);
505 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE
, REG_ROOT
, 0, KEY_READ
, &hrootkey
) == ERROR_SUCCESS
)
509 if (RegQueryValueEx (hrootkey
, key
, NULL
, NULL
, NULL
, &cbData
) == ERROR_SUCCESS
&&
510 (lpvalue
= (LPBYTE
) xmalloc (cbData
)) != NULL
&&
511 RegQueryValueEx (hrootkey
, key
, NULL
, lpdwtype
, lpvalue
, &cbData
) == ERROR_SUCCESS
)
516 if (lpvalue
) xfree (lpvalue
);
518 RegCloseKey (hrootkey
);
527 /* Check for environment variables and use registry if they don't exist */
533 static char * env_vars
[] =
547 for (i
= 0; i
< (sizeof (env_vars
) / sizeof (env_vars
[0])); i
++)
549 if (!getenv (env_vars
[i
]) &&
550 (lpval
= nt_get_resource (env_vars
[i
], &dwType
)) != NULL
)
552 if (dwType
== REG_EXPAND_SZ
)
554 char buf1
[500], buf2
[500];
556 ExpandEnvironmentStrings ((LPSTR
) lpval
, buf1
, 500);
557 _snprintf (buf2
, 499, "%s=%s", env_vars
[i
], buf1
);
558 putenv (strdup (buf2
));
560 else if (dwType
== REG_SZ
)
564 _snprintf (buf
, 499, "%s=%s", env_vars
[i
], lpval
);
565 putenv (strdup (buf
));
576 /* We don't have scripts to automatically determine the system configuration
577 for Emacs before it's compiled, and we don't want to have to make the
578 user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
581 static char configuration_buffer
[32];
584 get_emacs_configuration (void)
586 char *arch
, *oem
, *os
;
588 /* Determine the processor type. */
589 switch (get_processor_type ())
592 #ifdef PROCESSOR_INTEL_386
593 case PROCESSOR_INTEL_386
:
594 case PROCESSOR_INTEL_486
:
595 case PROCESSOR_INTEL_PENTIUM
:
600 #ifdef PROCESSOR_INTEL_860
601 case PROCESSOR_INTEL_860
:
606 #ifdef PROCESSOR_MIPS_R2000
607 case PROCESSOR_MIPS_R2000
:
608 case PROCESSOR_MIPS_R3000
:
609 case PROCESSOR_MIPS_R4000
:
614 #ifdef PROCESSOR_ALPHA_21064
615 case PROCESSOR_ALPHA_21064
:
625 /* Let oem be "*" until we figure out how to decode the OEM field. */
628 os
= (GetVersion () & 0x80000000) ? "win95" : "nt";
630 sprintf (configuration_buffer
, "%s-%s-%s%d.%d", arch
, oem
, os
,
631 get_nt_major_version (), get_nt_minor_version ());
632 return configuration_buffer
;
635 #include <sys/timeb.h>
637 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
639 gettimeofday (struct timeval
*tv
, struct timezone
*tz
)
644 tv
->tv_sec
= tb
.time
;
645 tv
->tv_usec
= tb
.millitm
* 1000L;
648 tz
->tz_minuteswest
= tb
.timezone
; /* minutes west of Greenwich */
649 tz
->tz_dsttime
= tb
.dstflag
; /* type of dst correction */
653 /* ------------------------------------------------------------------------- */
654 /* IO support and wrapper functions for Win32 API. */
655 /* ------------------------------------------------------------------------- */
657 /* Place a wrapper around the MSVC version of ctime. It returns NULL
658 on network directories, so we handle that case here.
659 (Ulrich Leodolter, 1/11/95). */
661 sys_ctime (const time_t *t
)
663 char *str
= (char *) ctime (t
);
664 return (str
? str
: "Sun Jan 01 00:00:00 1970");
667 /* Emulate sleep...we could have done this with a define, but that
668 would necessitate including windows.h in the files that used it.
669 This is much easier. */
671 sys_sleep (int seconds
)
673 Sleep (seconds
* 1000);
676 /* Internal MSVC data and functions for low-level descriptor munging */
677 #if (_MSC_VER == 900)
678 extern char _osfile
[];
680 extern int __cdecl
_set_osfhnd (int fd
, long h
);
681 extern int __cdecl
_free_osfhnd (int fd
);
683 /* parallel array of private info on file handles */
684 filedesc fd_info
[ MAXDESC
];
694 /* Get information on the volume where name is held; set path pointer to
695 start of pathname in name (past UNC header\volume header if present). */
697 get_volume_info (const char * name
, const char ** pPath
)
700 char *rootname
= NULL
; /* default to current volume */
705 /* find the root name of the volume if given */
706 if (isalpha (name
[0]) && name
[1] == ':')
714 else if (IS_DIRECTORY_SEP (name
[0]) && IS_DIRECTORY_SEP (name
[1]))
721 if (IS_DIRECTORY_SEP (*name
) && --slashes
== 0)
734 if (GetVolumeInformation (rootname
,
735 volume_info
.name
, 32,
736 &volume_info
.serialnum
,
737 &volume_info
.maxcomp
,
739 volume_info
.type
, 32))
746 /* Determine if volume is FAT format (ie. only supports short 8.3
747 names); also set path pointer to start of pathname in name. */
749 is_fat_volume (const char * name
, const char ** pPath
)
751 if (get_volume_info (name
, pPath
))
752 return (volume_info
.maxcomp
== 12);
756 /* Map filename to a legal 8.3 name if necessary. */
758 map_win32_filename (const char * name
, const char ** pPath
)
760 static char shortname
[MAX_PATH
];
761 char * str
= shortname
;
765 if (is_fat_volume (name
, &path
)) /* truncate to 8.3 */
767 register int left
= 8; /* maximum number of chars in part */
768 register int extn
= 0; /* extension added? */
769 register int dots
= 2; /* maximum number of dots allowed */
772 *str
++ = *name
++; /* skip past UNC header */
774 while ((c
= *name
++))
781 extn
= 0; /* reset extension flags */
782 dots
= 2; /* max 2 dots */
783 left
= 8; /* max length 8 for main part */
787 extn
= 0; /* reset extension flags */
788 dots
= 2; /* max 2 dots */
789 left
= 8; /* max length 8 for main part */
794 /* Convert path components of the form .xxx to _xxx,
795 but leave . and .. as they are. This allows .emacs
796 to be read as _emacs, for example. */
800 IS_DIRECTORY_SEP (*name
))
815 extn
= 1; /* we've got an extension */
816 left
= 3; /* 3 chars in extension */
820 /* any embedded dots after the first are converted to _ */
825 case '#': /* don't lose these, they're important */
827 str
[-1] = c
; /* replace last character of part */
832 *str
++ = tolower (c
); /* map to lower case (looks nicer) */
834 dots
= 0; /* started a path component */
843 strcpy (shortname
, name
);
844 unixtodos_filename (shortname
);
848 *pPath
= shortname
+ (path
- name
);
854 /* Shadow some MSVC runtime functions to map requests for long filenames
855 to reasonable short names if necessary. This was originally added to
856 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
860 sys_access (const char * path
, int mode
)
862 return _access (map_win32_filename (path
, NULL
), mode
);
866 sys_chdir (const char * path
)
868 return _chdir (map_win32_filename (path
, NULL
));
872 sys_chmod (const char * path
, int mode
)
874 return _chmod (map_win32_filename (path
, NULL
), mode
);
878 sys_creat (const char * path
, int mode
)
880 return _creat (map_win32_filename (path
, NULL
), mode
);
884 sys_fopen(const char * path
, const char * mode
)
888 const char * mode_save
= mode
;
890 /* Force all file handles to be non-inheritable. This is necessary to
891 ensure child processes don't unwittingly inherit handles that might
892 prevent future file access. */
896 else if (mode
[0] == 'w' || mode
[0] == 'a')
897 oflag
= O_WRONLY
| O_CREAT
| O_TRUNC
;
901 /* Only do simplistic option parsing. */
905 oflag
&= ~(O_RDONLY
| O_WRONLY
);
908 else if (mode
[0] == 'b')
913 else if (mode
[0] == 't')
920 fd
= _open (map_win32_filename (path
, NULL
), oflag
| _O_NOINHERIT
, 0644);
924 return fdopen (fd
, mode_save
);
928 sys_link (const char * path1
, const char * path2
)
935 sys_mkdir (const char * path
)
937 return _mkdir (map_win32_filename (path
, NULL
));
941 sys_mktemp (char * template)
943 return (char *) map_win32_filename ((const char *) _mktemp (template), NULL
);
947 sys_open (const char * path
, int oflag
, int mode
)
949 /* Force all file handles to be non-inheritable. */
950 return _open (map_win32_filename (path
, NULL
), oflag
| _O_NOINHERIT
, mode
);
954 sys_rename (const char * oldname
, const char * newname
)
958 /* MoveFile on Win95 doesn't correctly change the short file name
959 alias when oldname has a three char extension and newname has the
960 same first three chars in its extension. To avoid problems, on
961 Win95 we rename to a temporary name first. */
963 strcpy (temp
, map_win32_filename (oldname
, NULL
));
965 if (GetVersion () & 0x80000000)
969 unixtodos_filename (temp
);
970 if (p
= strrchr (temp
, '\\'))
974 strcpy (p
, "__XXXXXX");
976 if (rename (map_win32_filename (oldname
, NULL
), temp
) < 0)
980 /* Emulate Unix behaviour - newname is deleted if it already exists
981 (at least if it is a file; don't do this for directories). */
982 newname
= map_win32_filename (newname
, NULL
);
983 if (GetFileAttributes (newname
) != -1)
985 _chmod (newname
, 0666);
989 return rename (temp
, newname
);
993 sys_rmdir (const char * path
)
995 return _rmdir (map_win32_filename (path
, NULL
));
999 sys_unlink (const char * path
)
1001 return _unlink (map_win32_filename (path
, NULL
));
1004 static FILETIME utc_base_ft
;
1005 static long double utc_base
;
1006 static int init
= 0;
1009 convert_time (FILETIME ft
)
1015 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
1024 st
.wMilliseconds
= 0;
1026 SystemTimeToFileTime (&st
, &utc_base_ft
);
1027 utc_base
= (long double) utc_base_ft
.dwHighDateTime
1028 * 4096 * 1024 * 1024 + utc_base_ft
.dwLowDateTime
;
1032 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
1035 ret
= (long double) ft
.dwHighDateTime
* 4096 * 1024 * 1024 + ft
.dwLowDateTime
;
1037 return (time_t) (ret
* 1e-7);
1041 /* in case we ever have need of this */
1043 convert_from_time_t (time_t time
, FILETIME
* pft
)
1049 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
1058 st
.wMilliseconds
= 0;
1060 SystemTimeToFileTime (&st
, &utc_base_ft
);
1061 utc_base
= (long double) utc_base_ft
.dwHighDateTime
1062 * 4096 * 1024 * 1024 + utc_base_ft
.dwLowDateTime
;
1066 /* time in 100ns units since 1-Jan-1601 */
1067 tmp
= (long double) time
* 1e7
+ utc_base
;
1068 pft
->dwHighDateTime
= (DWORD
) (tmp
/ (4096.0 * 1024 * 1024));
1069 pft
->dwLowDateTime
= (DWORD
) (tmp
- pft
->dwHighDateTime
);
1073 /* "PJW" algorithm (see the "Dragon" compiler book). */
1075 hashval (const char * str
)
1081 h
= (h
<< 4) + *str
++;
1082 if ((g
= h
& 0xf0000000) != 0)
1083 h
= (h
^ (g
>> 24)) & 0x0fffffff;
1088 /* Return the hash value of the canonical pathname, excluding the
1089 drive/UNC header, to get a hopefully unique inode number. */
1091 generate_inode_val (const char * name
)
1093 char fullname
[ MAX_PATH
];
1097 GetFullPathName (name
, sizeof (fullname
), fullname
, &p
);
1098 get_volume_info (fullname
, &p
);
1099 /* Normal Win32 filesystems are still case insensitive. */
1102 return (_ino_t
) (hash
^ (hash
>> 16));
1105 /* MSVC stat function can't cope with UNC names and has other bugs, so
1106 replace it with our own. This also allows us to calculate consistent
1107 inode values without hacks in the main Emacs code. */
1109 stat (const char * path
, struct stat
* buf
)
1112 WIN32_FIND_DATA wfd
;
1116 int rootdir
= FALSE
;
1118 if (path
== NULL
|| buf
== NULL
)
1124 name
= (char *) map_win32_filename (path
, &path
);
1125 /* must be valid filename, no wild cards */
1126 if (strchr (name
, '*') || strchr (name
, '?'))
1132 /* Remove trailing directory separator, unless name is the root
1133 directory of a drive or UNC volume in which case ensure there
1134 is a trailing separator. */
1135 len
= strlen (name
);
1136 rootdir
= (path
>= name
+ len
- 1
1137 && (IS_DIRECTORY_SEP (*path
) || *path
== 0));
1138 name
= strcpy (alloca (len
+ 2), name
);
1142 if (!IS_DIRECTORY_SEP (name
[len
-1]))
1143 strcat (name
, "\\");
1144 if (GetDriveType (name
) < 2)
1149 memset (&wfd
, 0, sizeof (wfd
));
1150 wfd
.dwFileAttributes
= FILE_ATTRIBUTE_DIRECTORY
;
1151 wfd
.ftCreationTime
= utc_base_ft
;
1152 wfd
.ftLastAccessTime
= utc_base_ft
;
1153 wfd
.ftLastWriteTime
= utc_base_ft
;
1154 strcpy (wfd
.cFileName
, name
);
1158 if (IS_DIRECTORY_SEP (name
[len
-1]))
1160 fh
= FindFirstFile (name
, &wfd
);
1161 if (fh
== INVALID_HANDLE_VALUE
)
1169 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
1171 buf
->st_mode
= _S_IFDIR
;
1172 buf
->st_nlink
= 2; /* doesn't really matter */
1177 /* This is more accurate in terms of gettting the correct number
1178 of links, but is quite slow (it is noticable when Emacs is
1179 making a list of file name completions). */
1180 BY_HANDLE_FILE_INFORMATION info
;
1182 fh
= CreateFile (name
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1183 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
1185 if (GetFileInformationByHandle (fh
, &info
))
1187 switch (GetFileType (fh
))
1189 case FILE_TYPE_DISK
:
1190 buf
->st_mode
= _S_IFREG
;
1192 case FILE_TYPE_PIPE
:
1193 buf
->st_mode
= _S_IFIFO
;
1195 case FILE_TYPE_CHAR
:
1196 case FILE_TYPE_UNKNOWN
:
1198 buf
->st_mode
= _S_IFCHR
;
1200 buf
->st_nlink
= info
.nNumberOfLinks
;
1201 /* Could use file index, but this is not guaranteed to be
1202 unique unless we keep a handle open all the time. */
1203 /* buf->st_ino = info.nFileIndexLow ^ info.nFileIndexHigh; */
1212 buf
->st_mode
= _S_IFREG
;
1217 /* consider files to belong to current user */
1218 buf
->st_uid
= the_passwd
.pw_uid
;
1219 buf
->st_gid
= the_passwd
.pw_gid
;
1221 /* volume_info is set indirectly by map_win32_filename */
1222 buf
->st_dev
= volume_info
.serialnum
;
1223 buf
->st_rdev
= volume_info
.serialnum
;
1225 buf
->st_ino
= generate_inode_val (name
);
1227 buf
->st_size
= wfd
.nFileSizeLow
;
1229 /* Convert timestamps to Unix format. */
1230 buf
->st_mtime
= convert_time (wfd
.ftLastWriteTime
);
1231 buf
->st_atime
= convert_time (wfd
.ftLastAccessTime
);
1232 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
1233 buf
->st_ctime
= convert_time (wfd
.ftCreationTime
);
1234 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
1236 /* determine rwx permissions */
1237 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
1238 permission
= _S_IREAD
;
1240 permission
= _S_IREAD
| _S_IWRITE
;
1242 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
1243 permission
|= _S_IEXEC
;
1246 char * p
= strrchr (name
, '.');
1248 (stricmp (p
, ".exe") == 0 ||
1249 stricmp (p
, ".com") == 0 ||
1250 stricmp (p
, ".bat") == 0 ||
1251 stricmp (p
, ".cmd") == 0))
1252 permission
|= _S_IEXEC
;
1255 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
1262 /* Wrappers for winsock functions to map between our file descriptors
1263 and winsock's handles; also set h_errno for convenience.
1265 To allow Emacs to run on systems which don't have winsock support
1266 installed, we dynamically link to winsock on startup if present, and
1267 otherwise provide the minimum necessary functionality
1268 (eg. gethostname). */
1270 /* function pointers for relevant socket functions */
1271 int (PASCAL
*pfn_WSAStartup
) (WORD wVersionRequired
, LPWSADATA lpWSAData
);
1272 void (PASCAL
*pfn_WSASetLastError
) (int iError
);
1273 int (PASCAL
*pfn_WSAGetLastError
) (void);
1274 int (PASCAL
*pfn_socket
) (int af
, int type
, int protocol
);
1275 int (PASCAL
*pfn_bind
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
1276 int (PASCAL
*pfn_connect
) (SOCKET s
, const struct sockaddr
*addr
, int namelen
);
1277 int (PASCAL
*pfn_ioctlsocket
) (SOCKET s
, long cmd
, u_long
*argp
);
1278 int (PASCAL
*pfn_recv
) (SOCKET s
, char * buf
, int len
, int flags
);
1279 int (PASCAL
*pfn_send
) (SOCKET s
, const char * buf
, int len
, int flags
);
1280 int (PASCAL
*pfn_closesocket
) (SOCKET s
);
1281 int (PASCAL
*pfn_shutdown
) (SOCKET s
, int how
);
1282 int (PASCAL
*pfn_WSACleanup
) (void);
1284 u_short (PASCAL
*pfn_htons
) (u_short hostshort
);
1285 u_short (PASCAL
*pfn_ntohs
) (u_short netshort
);
1286 unsigned long (PASCAL
*pfn_inet_addr
) (const char * cp
);
1287 int (PASCAL
*pfn_gethostname
) (char * name
, int namelen
);
1288 struct hostent
* (PASCAL
*pfn_gethostbyname
) (const char * name
);
1289 struct servent
* (PASCAL
*pfn_getservbyname
) (const char * name
, const char * proto
);
1291 static int have_winsock
;
1292 static HANDLE winsock_lib
;
1300 FreeLibrary (winsock_lib
);
1307 WSADATA winsockData
;
1309 winsock_lib
= LoadLibrary ("wsock32.dll");
1311 if (winsock_lib
!= NULL
)
1313 /* dynamically link to socket functions */
1315 #define LOAD_PROC(fn) \
1316 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
1319 LOAD_PROC( WSAStartup
);
1320 LOAD_PROC( WSASetLastError
);
1321 LOAD_PROC( WSAGetLastError
);
1322 LOAD_PROC( socket
);
1324 LOAD_PROC( connect
);
1325 LOAD_PROC( ioctlsocket
);
1328 LOAD_PROC( closesocket
);
1329 LOAD_PROC( shutdown
);
1332 LOAD_PROC( inet_addr
);
1333 LOAD_PROC( gethostname
);
1334 LOAD_PROC( gethostbyname
);
1335 LOAD_PROC( getservbyname
);
1336 LOAD_PROC( WSACleanup
);
1338 /* specify version 1.1 of winsock */
1339 if (pfn_WSAStartup (0x101, &winsockData
) == 0)
1341 have_winsock
= TRUE
;
1346 FreeLibrary (winsock_lib
);
1348 have_winsock
= FALSE
;
1354 /* function to set h_errno for compatability; map winsock error codes to
1355 normal system codes where they overlap (non-overlapping definitions
1356 are already in <sys/socket.h> */
1357 static void set_errno ()
1362 h_errno
= pfn_WSAGetLastError ();
1366 case WSAEACCES
: h_errno
= EACCES
; break;
1367 case WSAEBADF
: h_errno
= EBADF
; break;
1368 case WSAEFAULT
: h_errno
= EFAULT
; break;
1369 case WSAEINTR
: h_errno
= EINTR
; break;
1370 case WSAEINVAL
: h_errno
= EINVAL
; break;
1371 case WSAEMFILE
: h_errno
= EMFILE
; break;
1372 case WSAENAMETOOLONG
: h_errno
= ENAMETOOLONG
; break;
1373 case WSAENOTEMPTY
: h_errno
= ENOTEMPTY
; break;
1378 static void check_errno ()
1380 if (h_errno
== 0 && have_winsock
)
1381 pfn_WSASetLastError (0);
1384 /* [andrewi 3-May-96] I've had conflicting results using both methods,
1385 but I believe the method of keeping the socket handle separate (and
1386 insuring it is not inheritable) is the correct one. */
1388 //#define SOCK_REPLACE_HANDLE
1390 #ifdef SOCK_REPLACE_HANDLE
1391 #define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
1393 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
1397 sys_socket(int af
, int type
, int protocol
)
1406 return INVALID_SOCKET
;
1411 /* call the real socket function */
1412 s
= (long) pfn_socket (af
, type
, protocol
);
1414 if (s
!= INVALID_SOCKET
)
1416 /* Although under NT 3.5 _open_osfhandle will accept a socket
1417 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
1418 that does not work under NT 3.1. However, we can get the same
1419 effect by using a backdoor function to replace an existing
1420 descriptor handle with the one we want. */
1422 /* allocate a file descriptor (with appropriate flags) */
1423 fd
= _open ("NUL:", _O_RDWR
);
1426 #ifdef SOCK_REPLACE_HANDLE
1427 /* now replace handle to NUL with our socket handle */
1428 CloseHandle ((HANDLE
) _get_osfhandle (fd
));
1430 _set_osfhnd (fd
, s
);
1431 /* setmode (fd, _O_BINARY); */
1433 /* Make a non-inheritable copy of the socket handle. */
1436 HANDLE new_s
= INVALID_HANDLE_VALUE
;
1438 parent
= GetCurrentProcess ();
1440 DuplicateHandle (parent
,
1446 DUPLICATE_SAME_ACCESS
);
1447 pfn_closesocket (s
);
1448 fd_info
[fd
].hnd
= new_s
;
1453 /* set our own internal flags */
1454 fd_info
[fd
].flags
= FILE_SOCKET
| FILE_BINARY
| FILE_READ
| FILE_WRITE
;
1460 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
1462 /* attach child_process to fd_info */
1463 if (fd_info
[ fd
].cp
!= NULL
)
1465 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd
));
1469 fd_info
[ fd
].cp
= cp
;
1478 pfn_closesocket (s
);
1488 sys_bind (int s
, const struct sockaddr
* addr
, int namelen
)
1493 return SOCKET_ERROR
;
1497 if (fd_info
[s
].flags
& FILE_SOCKET
)
1499 int rc
= pfn_bind (SOCK_HANDLE (s
), addr
, namelen
);
1500 if (rc
== SOCKET_ERROR
)
1505 return SOCKET_ERROR
;
1510 sys_connect (int s
, const struct sockaddr
* name
, int namelen
)
1515 return SOCKET_ERROR
;
1519 if (fd_info
[s
].flags
& FILE_SOCKET
)
1521 int rc
= pfn_connect (SOCK_HANDLE (s
), name
, namelen
);
1522 if (rc
== SOCKET_ERROR
)
1527 return SOCKET_ERROR
;
1531 sys_htons (u_short hostshort
)
1533 return (have_winsock
) ?
1534 pfn_htons (hostshort
) : hostshort
;
1538 sys_ntohs (u_short netshort
)
1540 return (have_winsock
) ?
1541 pfn_ntohs (netshort
) : netshort
;
1545 sys_inet_addr (const char * cp
)
1547 return (have_winsock
) ?
1548 pfn_inet_addr (cp
) : INADDR_NONE
;
1552 sys_gethostname (char * name
, int namelen
)
1555 return pfn_gethostname (name
, namelen
);
1557 if (namelen
> MAX_COMPUTERNAME_LENGTH
)
1558 return !GetComputerName (name
, &namelen
);
1561 return SOCKET_ERROR
;
1565 sys_gethostbyname(const char * name
)
1567 struct hostent
* host
;
1576 host
= pfn_gethostbyname (name
);
1583 sys_getservbyname(const char * name
, const char * proto
)
1585 struct servent
* serv
;
1594 serv
= pfn_getservbyname (name
, proto
);
1600 #endif /* HAVE_SOCKETS */
1603 /* Shadow main io functions: we need to handle pipes and sockets more
1604 intelligently, and implement non-blocking mode as well. */
1611 if (fd
< 0 || fd
>= MAXDESC
)
1619 child_process
* cp
= fd_info
[fd
].cp
;
1621 fd_info
[fd
].cp
= NULL
;
1623 if (CHILD_ACTIVE (cp
))
1625 /* if last descriptor to active child_process then cleanup */
1627 for (i
= 0; i
< MAXDESC
; i
++)
1631 if (fd_info
[i
].cp
== cp
)
1636 #if defined (HAVE_SOCKETS) && !defined (SOCK_REPLACE_HANDLE)
1637 if (fd_info
[fd
].flags
& FILE_SOCKET
)
1639 if (!have_winsock
) abort ();
1641 pfn_shutdown (SOCK_HANDLE (fd
), 2);
1642 rc
= pfn_closesocket (SOCK_HANDLE (fd
));
1650 /* Note that sockets do not need special treatment here (at least on
1651 NT and Win95 using the standard tcp/ip stacks) - it appears that
1652 closesocket is equivalent to CloseHandle, which is to be expected
1653 because socket handles are fully fledged kernel handles. */
1657 fd_info
[fd
].flags
= 0;
1670 /* duplicate our internal info as well */
1671 fd_info
[new_fd
] = fd_info
[fd
];
1678 sys_dup2 (int src
, int dst
)
1682 if (dst
< 0 || dst
>= MAXDESC
)
1688 /* make sure we close the destination first if it's a pipe or socket */
1689 if (src
!= dst
&& fd_info
[dst
].flags
!= 0)
1692 rc
= _dup2 (src
, dst
);
1695 /* duplicate our internal info as well */
1696 fd_info
[dst
] = fd_info
[src
];
1701 /* From callproc.c */
1702 extern Lisp_Object Vbinary_process_input
;
1703 extern Lisp_Object Vbinary_process_output
;
1705 /* Unix pipe() has only one arg */
1707 sys_pipe (int * phandles
)
1713 /* make pipe handles non-inheritable; when we spawn a child,
1714 we replace the relevant handle with an inheritable one. */
1715 rc
= _pipe (phandles
, 0, _O_NOINHERIT
);
1719 /* set internal flags, and put read and write handles into binary
1720 mode as necessary; if not in binary mode, set the MSVC internal
1721 FDEV (0x40) flag to prevent _read from treating ^Z as eof (this
1722 could otherwise allow Emacs to hang because it then waits
1723 indefinitely for the child process to exit, when it might not be
1725 flags
= FILE_PIPE
| FILE_READ
;
1726 if (!NILP (Vbinary_process_output
))
1728 flags
|= FILE_BINARY
;
1729 setmode (phandles
[0], _O_BINARY
);
1731 #if (_MSC_VER == 900)
1733 _osfile
[phandles
[0]] |= 0x40;
1736 fd_info
[phandles
[0]].flags
= flags
;
1738 flags
= FILE_PIPE
| FILE_WRITE
;
1739 if (!NILP (Vbinary_process_input
))
1741 flags
|= FILE_BINARY
;
1742 setmode (phandles
[1], _O_BINARY
);
1744 #if (_MSC_VER == 900)
1746 _osfile
[phandles
[1]] |= 0x40;
1749 fd_info
[phandles
[1]].flags
= flags
;
1756 extern Lisp_Object Vwin32_pipe_read_delay
;
1758 /* Function to do blocking read of one byte, needed to implement
1759 select. It is only allowed on sockets and pipes. */
1761 _sys_read_ahead (int fd
)
1766 if (fd
< 0 || fd
>= MAXDESC
)
1767 return STATUS_READ_ERROR
;
1769 cp
= fd_info
[fd
].cp
;
1771 if (cp
== NULL
|| cp
->fd
!= fd
|| cp
->status
!= STATUS_READ_READY
)
1772 return STATUS_READ_ERROR
;
1774 if ((fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
)) == 0
1775 || (fd_info
[fd
].flags
& FILE_READ
) == 0)
1777 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd
));
1781 cp
->status
= STATUS_READ_IN_PROGRESS
;
1783 if (fd_info
[fd
].flags
& FILE_PIPE
)
1785 /* Use read to get CRLF translation */
1786 rc
= _read (fd
, &cp
->chr
, sizeof (char));
1788 /* Give subprocess time to buffer some more output for us before
1789 reporting that input is available; we need this because Win95
1790 connects DOS programs to pipes by making the pipe appear to be
1791 the normal console stdout - as a result most DOS programs will
1792 write to stdout without buffering, ie. one character at a
1793 time. Even some Win32 programs do this - "dir" in a command
1794 shell on NT is very slow if we don't do this. */
1797 int wait
= XINT (Vwin32_pipe_read_delay
);
1803 /* Yield remainder of our time slice, effectively giving a
1804 temporary priority boost to the child process. */
1809 else if (fd_info
[fd
].flags
& FILE_SOCKET
)
1810 rc
= pfn_recv (SOCK_HANDLE (fd
), &cp
->chr
, sizeof (char), 0);
1813 if (rc
== sizeof (char))
1814 cp
->status
= STATUS_READ_SUCCEEDED
;
1816 cp
->status
= STATUS_READ_FAILED
;
1822 sys_read (int fd
, char * buffer
, unsigned int count
)
1829 if (fd
< 0 || fd
>= MAXDESC
)
1835 if (fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
))
1837 child_process
*cp
= fd_info
[fd
].cp
;
1839 if ((fd_info
[fd
].flags
& FILE_READ
) == 0)
1845 /* presence of a child_process structure means we are operating in
1846 non-blocking mode - otherwise we just call _read directly.
1847 Note that the child_process structure might be missing because
1848 reap_subprocess has been called; in this case the pipe is
1849 already broken, so calling _read on it is okay. */
1852 int current_status
= cp
->status
;
1854 switch (current_status
)
1856 case STATUS_READ_FAILED
:
1857 case STATUS_READ_ERROR
:
1858 /* report normal EOF */
1861 case STATUS_READ_READY
:
1862 case STATUS_READ_IN_PROGRESS
:
1863 DebPrint (("sys_read called when read is in progress\n"));
1864 errno
= EWOULDBLOCK
;
1867 case STATUS_READ_SUCCEEDED
:
1868 /* consume read-ahead char */
1869 *buffer
++ = cp
->chr
;
1872 cp
->status
= STATUS_READ_ACKNOWLEDGED
;
1873 ResetEvent (cp
->char_avail
);
1875 case STATUS_READ_ACKNOWLEDGED
:
1879 DebPrint (("sys_read: bad status %d\n", current_status
));
1884 if (fd_info
[fd
].flags
& FILE_PIPE
)
1886 PeekNamedPipe ((HANDLE
) _get_osfhandle (fd
), NULL
, 0, NULL
, &waiting
, NULL
);
1887 to_read
= min (waiting
, (DWORD
) count
);
1889 /* Use read to get CRLF translation */
1890 nchars
= _read (fd
, buffer
, to_read
);
1893 else /* FILE_SOCKET */
1895 if (!have_winsock
) abort ();
1897 /* do the equivalent of a non-blocking read */
1898 pfn_ioctlsocket (SOCK_HANDLE (fd
), FIONREAD
, &waiting
);
1899 if (waiting
== 0 && extra
== 0)
1901 h_errno
= errno
= EWOULDBLOCK
;
1908 /* always use binary mode for sockets */
1909 nchars
= pfn_recv (SOCK_HANDLE (fd
), buffer
, count
, 0);
1910 if (nchars
== SOCKET_ERROR
)
1912 DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
1913 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
1926 nchars
= _read (fd
, buffer
, count
);
1929 nchars
= _read (fd
, buffer
, count
);
1931 return nchars
+ extra
;
1934 /* For now, don't bother with a non-blocking mode */
1936 sys_write (int fd
, const void * buffer
, unsigned int count
)
1940 if (fd
< 0 || fd
>= MAXDESC
)
1946 if (fd_info
[fd
].flags
& (FILE_PIPE
| FILE_SOCKET
))
1947 if ((fd_info
[fd
].flags
& FILE_WRITE
) == 0)
1953 if (fd_info
[fd
].flags
& FILE_SOCKET
)
1955 if (!have_winsock
) abort ();
1956 nchars
= pfn_send (SOCK_HANDLE (fd
), buffer
, count
, 0);
1957 if (nchars
== SOCKET_ERROR
)
1959 DebPrint(("sys_read.send failed with error %d on socket %ld\n",
1960 pfn_WSAGetLastError (), SOCK_HANDLE (fd
)));
1966 nchars
= _write (fd
, buffer
, count
);
1976 /* shutdown the socket interface if necessary */
1981 extern BOOL can_run_dos_process
;
1982 extern BOOL dos_process_running
;
1988 /* initialise the socket interface if available */
1992 /* Initial preparation for subprocess support: replace our standard
1993 handles with non-inheritable versions. */
1996 HANDLE stdin_save
= INVALID_HANDLE_VALUE
;
1997 HANDLE stdout_save
= INVALID_HANDLE_VALUE
;
1998 HANDLE stderr_save
= INVALID_HANDLE_VALUE
;
2000 parent
= GetCurrentProcess ();
2002 /* ignore errors when duplicating and closing; typically the
2003 handles will be invalid when running as a gui program. */
2004 DuplicateHandle (parent
,
2005 GetStdHandle (STD_INPUT_HANDLE
),
2010 DUPLICATE_SAME_ACCESS
);
2012 DuplicateHandle (parent
,
2013 GetStdHandle (STD_OUTPUT_HANDLE
),
2018 DUPLICATE_SAME_ACCESS
);
2020 DuplicateHandle (parent
,
2021 GetStdHandle (STD_ERROR_HANDLE
),
2026 DUPLICATE_SAME_ACCESS
);
2032 if (stdin_save
!= INVALID_HANDLE_VALUE
)
2033 _open_osfhandle ((long) stdin_save
, O_TEXT
);
2035 open ("nul", O_TEXT
| O_NOINHERIT
| O_RDONLY
);
2038 if (stdout_save
!= INVALID_HANDLE_VALUE
)
2039 _open_osfhandle ((long) stdout_save
, O_TEXT
);
2041 open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
2044 if (stderr_save
!= INVALID_HANDLE_VALUE
)
2045 _open_osfhandle ((long) stderr_save
, O_TEXT
);
2047 open ("nul", O_TEXT
| O_NOINHERIT
| O_WRONLY
);
2051 /* Only allow Emacs to run DOS programs on Win95. */
2052 can_run_dos_process
= (GetVersion () & 0x80000000);
2053 dos_process_running
= FALSE
;
2055 /* unfortunately, atexit depends on implementation of malloc */
2056 /* atexit (term_ntproc); */
2057 signal (SIGABRT
, term_ntproc
);