aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGeoff Voelker1996-05-03 18:32:52 +0000
committerGeoff Voelker1996-05-03 18:32:52 +0000
commit480b0c5b52b7c3abfd6dfbe096166235a290b35a (patch)
tree1b90d111edf22de2e2ead555b5292b60756c2cf7 /src
parent2fd5e802b74c05dac1f6a61569fc2411d9e2e40b (diff)
downloademacs-480b0c5b52b7c3abfd6dfbe096166235a290b35a.tar.gz
emacs-480b0c5b52b7c3abfd6dfbe096166235a290b35a.zip
(nt_stat, nt_ctime): Functions deleted.
Undefine macros of CRT functions.
Diffstat (limited to 'src')
-rw-r--r--src/w32.c2391
1 files changed, 1685 insertions, 706 deletions
diff --git a/src/w32.c b/src/w32.c
index c6338b2a677..63f843606f8 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -22,55 +22,37 @@ Boston, MA 02111-1307, USA.
22*/ 22*/
23 23
24 24
25/* Define stat before including config.h. */
26#include <string.h>
27#include <sys/stat.h>
28#include <malloc.h>
29
30static int is_toplevel_share_name (char *);
31static int stat_toplevel_share (char *, void *);
32
33int
34nt_stat (char *filename, struct stat *statbuf)
35{
36 int l = strlen (filename);
37 char *str = NULL;
38
39 /* stat has a bug when passed a name of a directory with a trailing
40 backslash (but a trailing forward slash works fine). */
41 if (filename[l - 1] == '\\')
42 {
43 str = (char *) alloca (l + 1);
44 strcpy (str, filename);
45 str[l - 1] = '/';
46 return stat (str, statbuf);
47 }
48
49 if (stat (filename, statbuf) == 0)
50 return 0;
51 else if (is_toplevel_share_name (filename))
52 return stat_toplevel_share (filename, statbuf);
53 else
54 return -1;
55}
56
57/* Place a wrapper around the NT version of ctime. It returns NULL
58 on network directories, so we handle that case here.
59 Define it before including config.h. (Ulrich Leodolter, 1/11/95). */
60char *
61nt_ctime (const time_t *t)
62{
63 char *str = (char *) ctime (t);
64 return (str ? str : "Sun Jan 01 00:00:00 1970");
65}
66
67#include <config.h>
68#include <windows.h>
69#include <stdlib.h> 25#include <stdlib.h>
70#include <stdio.h> 26#include <stdio.h>
71#include <io.h> 27#include <io.h>
28#include <errno.h>
72#include <fcntl.h> 29#include <fcntl.h>
73#include <ctype.h> 30#include <ctype.h>
31#include <signal.h>
32#include <sys/time.h>
33
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
49
50#undef close
51#undef dup
52#undef dup2
53#undef pipe
54#undef read
55#undef write
74 56
75#define getwd _getwd 57#define getwd _getwd
76#include "lisp.h" 58#include "lisp.h"
@@ -78,114 +60,35 @@ nt_ctime (const time_t *t)
78 60
79#include <pwd.h> 61#include <pwd.h>
80 62
81#include "ndir.h" 63#include <windows.h>
82#include "ntheap.h"
83
84extern int report_file_error (char *, Lisp_Object);
85
86/* Routines for extending stat above. */
87static int
88get_unassigned_drive_letter ()
89{
90 int i;
91 unsigned int mask;
92
93 mask = GetLogicalDrives ();
94 for (i = 0; i < 26; i++)
95 {
96 if (mask & (1 << i))
97 continue;
98 break;
99 }
100 return (i == 26 ? -1 : 'A' + i);
101}
102
103void dostounix_filename (char *);
104
105/* Return nonzero if NAME is of the form \\host\share (forward slashes
106 also valid), otherwise return 0. */
107static int
108is_toplevel_share_name (char *filename)
109{
110 int len;
111 char *name;
112 char *host;
113 char *share;
114 char *suffix;
115
116 len = strlen (filename);
117 name = alloca (len + 1);
118 strcpy (name, filename);
119
120 dostounix_filename (name);
121 if (name[0] != '/' || name[1] != '/')
122 return 0;
123
124 host = strtok (&name[2], "/");
125 share = strtok (NULL, "/");
126 suffix = strtok (NULL, "/");
127 if (!host || !share || suffix)
128 return 0;
129
130 return 1;
131}
132
133
134/* FILENAME is of the form \\host\share, and stat can't handle names
135 of this form. But stat can handle \\host\share if it's been
136 assigned a drive letter. So we create a network connection to this
137 share, assign it a drive letter, stat the drive letter, and
138 disconnect from the share. Hassle... */
139static int
140stat_toplevel_share (char *filename, void *statbuf)
141{
142 NETRESOURCE net;
143 int drive_letter;
144 char drive[4];
145 int result;
146
147 drive_letter = get_unassigned_drive_letter ();
148 if (drive_letter < 0)
149 return -1;
150
151 drive[0] = drive_letter;
152 drive[1] = ':';
153 drive[2] = '\0';
154 net.dwType = RESOURCETYPE_DISK;
155 net.lpLocalName = drive;
156 net.lpRemoteName = filename;
157 net.lpProvider = NULL;
158
159 switch (WNetAddConnection2 (&net, NULL, NULL, 0))
160 {
161 case NO_ERROR:
162 break;
163 case ERROR_ALREADY_ASSIGNED:
164 default:
165 return -1;
166 }
167
168 /* Name the toplevel directory on the drive letter. */
169 drive[2] = '/';
170 drive[3] = '\0';
171 result = stat (drive, (void *) statbuf);
172
173 /* Strip the slash so we can disconnect. */
174 drive[2] = '\0';
175 if (WNetCancelConnection2 (drive, 0, TRUE) != NO_ERROR)
176 result = -1;
177 64
178 return result; 65#ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
179} 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
180 77
78#include "nt.h"
79#include "ndir.h"
80#include "ntheap.h"
181 81
182/* Get the current working directory. */ 82/* Get the current working directory. */
183int 83char *
184getwd (char *dir) 84getwd (char *dir)
185{ 85{
186 return GetCurrentDirectory (MAXPATHLEN, dir); 86 if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
87 return dir;
88 return NULL;
187} 89}
188 90
91#ifndef HAVE_SOCKETS
189/* Emulate gethostname. */ 92/* Emulate gethostname. */
190int 93int
191gethostname (char *buffer, int size) 94gethostname (char *buffer, int size)
@@ -194,6 +97,7 @@ gethostname (char *buffer, int size)
194 certainly large enough. */ 97 certainly large enough. */
195 return !GetComputerName (buffer, &size); 98 return !GetComputerName (buffer, &size);
196} 99}
100#endif /* HAVE_SOCKETS */
197 101
198/* Emulate getloadavg. */ 102/* Emulate getloadavg. */
199int 103int
@@ -209,124 +113,14 @@ getloadavg (double loadavg[], int nelem)
209 return i; 113 return i;
210} 114}
211 115
212/* Emulate sleep...we could have done this with a define, but that
213 would necessitate including windows.h in the files that used it.
214 This is much easier. */
215void
216nt_sleep (int seconds)
217{
218 Sleep (seconds * 1000);
219}
220
221/* Emulate rename. */
222
223#ifndef ENOENT
224#define ENOENT 2
225#endif
226#ifndef EXDEV
227#define EXDEV 18
228#endif
229#ifndef EINVAL
230#define EINVAL 22
231#endif
232
233int
234rename (const char *oldname, const char *newname)
235{
236#ifdef WINDOWS95
237 int i, len, len0, len1;
238 char *dirs[2], *names[2], *ptr;
239
240 /* A bug in MoveFile under Windows 95 incorrectly renames files in
241 some cases. If the old name is of the form FILENAME or
242 FILENAME.SUF, and the new name is of the form FILENAME~ or
243 FILENAME.SUF~, and both the source and target are in the same
244 directory, then MoveFile renames the long form of the filename to
245 FILENAME~ (FILENAME.SUF~) but leaves the DOS short form as
246 FILENAME (FILENAME.SUF). The result is that the two different
247 filenames refer to the same file. In this case, rename the
248 source to a temporary name that can then successfully be renamed
249 to the target. */
250
251 dirs[0] = names[0] = oldname;
252 dirs[1] = names[1] = newname;
253 for (i = 0; i < 2; i++)
254 {
255 /* Canonicalize and remove prefix. */
256 len = strlen (names[i]);
257 for (ptr = names[i] + len - 1; ptr > names[i]; ptr--)
258 {
259 if (IS_ANY_SEP (ptr[0]) && ptr[1] != '\0')
260 {
261 names[i] = ptr + 1;
262 break;
263 }
264 }
265 }
266
267 len0 = strlen (names[0]);
268 len1 = strlen (names[1]);
269
270 /* The predicate is whether the file is being renamed to a filename
271 with ~ appended. This is conservative, but should be correct. */
272 if ((len0 == len1 - 1)
273 && (names[1][len0] == '~')
274 && (!strnicmp (names[0], names[1], len0)))
275 {
276 /* Rename the source to a temporary name that can succesfully be
277 renamed to the target. The temporary name is in the directory
278 of the target. */
279 char *tmp, *fulltmp;
280
281 tmp = "eXXXXXX";
282 fulltmp = alloca (strlen (dirs[1]) + strlen (tmp) + 1);
283 fulltmp[0] = '\0';
284 if (dirs[1] != names[1])
285 {
286 len = names[1] - dirs[1];
287 strncpy (fulltmp, dirs[1], len);
288 fulltmp[len] = '\0';
289 }
290 strcat (fulltmp, tmp);
291 mktemp (fulltmp);
292
293 if (rename (oldname, fulltmp) < 0)
294 return -1;
295
296 oldname = fulltmp;
297 }
298#endif
299
300 if (!MoveFile (oldname, newname))
301 {
302 switch (GetLastError ())
303 {
304 case ERROR_FILE_NOT_FOUND:
305 errno = ENOENT;
306 break;
307 case ERROR_ACCESS_DENIED:
308 /* This gets returned when going across devices. */
309 errno = EXDEV;
310 break;
311 case ERROR_FILE_EXISTS:
312 case ERROR_ALREADY_EXISTS:
313 default:
314 errno = EINVAL;
315 break;
316 }
317 return -1;
318 }
319 errno = 0;
320 return 0;
321}
322
323/* Emulate the Unix directory procedures opendir, closedir, 116/* Emulate the Unix directory procedures opendir, closedir,
324 and readdir. We can't use the procedures supplied in sysdep.c, 117 and readdir. We can't use the procedures supplied in sysdep.c,
325 so we provide them here. */ 118 so we provide them here. */
326 119
327struct direct dir_static; /* simulated directory contents */ 120struct direct dir_static; /* simulated directory contents */
328static int dir_finding; 121static HANDLE dir_find_handle = INVALID_HANDLE_VALUE;
329static HANDLE dir_find_handle; 122static int dir_is_fat;
123static char dir_pathname[MAXPATHLEN+1];
330 124
331DIR * 125DIR *
332opendir (char *filename) 126opendir (char *filename)
@@ -334,22 +128,21 @@ opendir (char *filename)
334 DIR *dirp; 128 DIR *dirp;
335 129
336 /* Opening is done by FindFirstFile. However, a read is inherent to 130 /* Opening is done by FindFirstFile. However, a read is inherent to
337 this operation, so we have a flag to handle the open at read 131 this operation, so we defer the open until read time. */
338 time. This flag essentially means "there is a find-handle open and
339 it needs to be closed." */
340 132
341 if (!(dirp = (DIR *) malloc (sizeof (DIR)))) 133 if (!(dirp = (DIR *) malloc (sizeof (DIR))))
342 { 134 return NULL;
343 return 0; 135 if (dir_find_handle != INVALID_HANDLE_VALUE)
344 } 136 return NULL;
345 137
346 dirp->dd_fd = 0; 138 dirp->dd_fd = 0;
347 dirp->dd_loc = 0; 139 dirp->dd_loc = 0;
348 dirp->dd_size = 0; 140 dirp->dd_size = 0;
349 141
350 /* This is tacky, but we need the directory name for our 142 strncpy (dir_pathname, filename, MAXPATHLEN);
351 implementation of readdir. */ 143 dir_pathname[MAXPATHLEN] = '\0';
352 strncpy (dirp->dd_buf, filename, DIRBLKSIZ); 144 dir_is_fat = is_fat_volume (filename, NULL);
145
353 return dirp; 146 return dirp;
354} 147}
355 148
@@ -357,10 +150,10 @@ void
357closedir (DIR *dirp) 150closedir (DIR *dirp)
358{ 151{
359 /* If we have a find-handle open, close it. */ 152 /* If we have a find-handle open, close it. */
360 if (dir_finding) 153 if (dir_find_handle != INVALID_HANDLE_VALUE)
361 { 154 {
362 FindClose (dir_find_handle); 155 FindClose (dir_find_handle);
363 dir_finding = 0; 156 dir_find_handle = INVALID_HANDLE_VALUE;
364 } 157 }
365 xfree ((char *) dirp); 158 xfree ((char *) dirp);
366} 159}
@@ -371,46 +164,44 @@ readdir (DIR *dirp)
371 WIN32_FIND_DATA find_data; 164 WIN32_FIND_DATA find_data;
372 165
373 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */ 166 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
374 if (!dir_finding) 167 if (dir_find_handle == INVALID_HANDLE_VALUE)
375 { 168 {
376 char filename[MAXNAMLEN + 3]; 169 char filename[MAXNAMLEN + 3];
377 int ln; 170 int ln;
378 171
379 strncpy (filename, dirp->dd_buf, MAXNAMLEN); 172 strcpy (filename, dir_pathname);
380 ln = strlen (filename)-1; 173 ln = strlen (filename) - 1;
381 if (!IS_ANY_SEP (filename[ln])) 174 if (!IS_DIRECTORY_SEP (filename[ln]))
382 strcat (filename, "\\"); 175 strcat (filename, "\\");
383 strcat (filename, "*.*"); 176 strcat (filename, "*");
384 177
385 dir_find_handle = FindFirstFile (filename, &find_data); 178 dir_find_handle = FindFirstFile (filename, &find_data);
386 179
387 if (dir_find_handle == INVALID_HANDLE_VALUE) 180 if (dir_find_handle == INVALID_HANDLE_VALUE)
388 return NULL; 181 return NULL;
389 182 }
390 dir_finding = 1; 183 else
391 }
392 else
393 { 184 {
394 if (!FindNextFile (dir_find_handle, &find_data)) 185 if (!FindNextFile (dir_find_handle, &find_data))
395 return NULL; 186 return NULL;
396 } 187 }
397 188
398 /* NT's unique ID for a file is 64 bits, so we have to fake it here. 189 /* Emacs never uses this value, so don't bother making it match
399 This should work as long as we never use 0. */ 190 value returned by stat(). */
400 dir_static.d_ino = 1; 191 dir_static.d_ino = 1;
401 192
402 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 + 193 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 +
403 dir_static.d_namlen - dir_static.d_namlen % 4; 194 dir_static.d_namlen - dir_static.d_namlen % 4;
404 195
405 dir_static.d_namlen = strlen (find_data.cFileName); 196 dir_static.d_namlen = strlen (find_data.cFileName);
406 strncpy (dir_static.d_name, find_data.cFileName, MAXNAMLEN); 197 strcpy (dir_static.d_name, find_data.cFileName);
198 if (dir_is_fat)
199 _strlwr (dir_static.d_name);
407 200
408 return &dir_static; 201 return &dir_static;
409} 202}
410 203
411/* Emulate getpwuid and getpwnam. */ 204/* Emulate getpwuid, getpwnam and others. */
412
413int getuid (); /* forward declaration */
414 205
415#define PASSWD_FIELD_SIZE 256 206#define PASSWD_FIELD_SIZE 256
416 207
@@ -432,22 +223,39 @@ static struct passwd the_passwd =
432 the_passwd_shell, 223 the_passwd_shell,
433}; 224};
434 225
226int
227getuid ()
228{
229 return the_passwd.pw_uid;
230}
231
232int
233geteuid ()
234{
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. */
238 return getuid ();
239}
240
241int
242getgid ()
243{
244 return the_passwd.pw_gid;
245}
246
247int
248getegid ()
249{
250 return getgid ();
251}
252
435struct passwd * 253struct passwd *
436getpwuid (int uid) 254getpwuid (int uid)
437{ 255{
438 int size = PASSWD_FIELD_SIZE; 256 if (uid == the_passwd.pw_uid)
439 257 return &the_passwd;
440 if (!GetUserName (the_passwd.pw_name, &size)) 258 return NULL;
441 return NULL;
442
443 the_passwd.pw_passwd[0] = '\0';
444 the_passwd.pw_uid = 0;
445 the_passwd.pw_gid = 0;
446 strcpy (the_passwd.pw_gecos, the_passwd.pw_name);
447 the_passwd.pw_dir[0] = '\0';
448 the_passwd.pw_shell[0] = '\0';
449
450 return &the_passwd;
451} 259}
452 260
453struct passwd * 261struct passwd *
@@ -459,12 +267,311 @@ getpwnam (char *name)
459 if (!pw) 267 if (!pw)
460 return pw; 268 return pw;
461 269
462 if (strcmp (name, pw->pw_name)) 270 if (stricmp (name, pw->pw_name))
463 return NULL; 271 return NULL;
464 272
465 return pw; 273 return pw;
466} 274}
467 275
276void
277init_user_info ()
278{
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.
281
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). */
285
286 char user_sid[256], name[256], domain[256];
287 DWORD length = sizeof (name), dlength = sizeof (domain), trash;
288 HANDLE token = NULL;
289 SID_NAME_USE user_type;
290
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))
296 {
297 strcpy (the_passwd.pw_name, name);
298 /* Determine a reasonable uid value. */
299 if (stricmp ("administrator", name) == 0)
300 {
301 the_passwd.pw_uid = 0;
302 the_passwd.pw_gid = 0;
303 }
304 else
305 {
306 SID_IDENTIFIER_AUTHORITY * pSIA;
307
308 pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid));
309 /* I believe the relative portion is the last 4 bytes (of 6)
310 with msb first. */
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;
317
318 /* Get group id */
319 if (GetTokenInformation (token, TokenPrimaryGroup,
320 (PVOID) user_sid, sizeof (user_sid), &trash))
321 {
322 SID_IDENTIFIER_AUTHORITY * pSIA;
323
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;
331 }
332 else
333 the_passwd.pw_gid = the_passwd.pw_uid;
334 }
335 }
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))
339 {
340 strcpy (the_passwd.pw_name, name);
341 if (stricmp ("administrator", name) == 0)
342 the_passwd.pw_uid = 0;
343 else
344 the_passwd.pw_uid = 123;
345 the_passwd.pw_gid = the_passwd.pw_uid;
346 }
347 else
348 {
349 strcpy (the_passwd.pw_name, "unknown");
350 the_passwd.pw_uid = 123;
351 the_passwd.pw_gid = 123;
352 }
353
354 /* Ensure HOME and SHELL are defined. */
355 if (getenv ("HOME") == NULL)
356 putenv ("HOME=c:/");
357 if (getenv ("SHELL") == NULL)
358 putenv ((GetVersion () & 0x80000000) ? "SHELL=command" : "SHELL=cmd");
359
360 /* Set dir and shell from environment variables. */
361 strcpy (the_passwd.pw_dir, getenv ("HOME"));
362 strcpy (the_passwd.pw_shell, getenv ("SHELL"));
363
364 if (token)
365 CloseHandle (token);
366}
367
368int
369random ()
370{
371 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
372 return ((rand () << 15) | rand ());
373}
374
375void
376srandom (int seed)
377{
378 srand (seed);
379}
380
381/* Destructively turn backslashes into slashes. */
382void
383dostounix_filename (p)
384 register char *p;
385{
386 while (*p)
387 {
388 if (*p == '\\')
389 *p = '/';
390 p++;
391 }
392}
393
394/* Destructively turn slashes into backslashes. */
395void
396unixtodos_filename (p)
397 register char *p;
398{
399 while (*p)
400 {
401 if (*p == '/')
402 *p = '\\';
403 p++;
404 }
405}
406
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.) */
410int
411crlf_to_lf (n, buf)
412 register int n;
413 register unsigned char *buf;
414{
415 unsigned char *np = buf;
416 unsigned char *startp = buf;
417 unsigned char *endp = buf + n;
418
419 if (n == 0)
420 return n;
421 while (buf < endp - 1)
422 {
423 if (*buf == 0x0d)
424 {
425 if (*(++buf) != 0x0a)
426 *np++ = 0x0d;
427 }
428 else
429 *np++ = *buf++;
430 }
431 if (buf < endp)
432 *np++ = *buf++;
433 return np - startp;
434}
435
436/* Routines that are no-ops on NT but are defined to get Emacs to compile. */
437
438int
439sigsetmask (int signal_mask)
440{
441 return 0;
442}
443
444int
445sigblock (int sig)
446{
447 return 0;
448}
449
450int
451setpgrp (int pid, int gid)
452{
453 return 0;
454}
455
456int
457alarm (int seconds)
458{
459 return 0;
460}
461
462int
463unrequest_sigio (void)
464{
465 return 0;
466}
467
468int
469request_sigio (void)
470{
471 return 0;
472}
473
474#define REG_ROOT "SOFTWARE\\GNU\\Emacs"
475
476LPBYTE
477nt_get_resource (key, lpdwtype)
478 char *key;
479 LPDWORD lpdwtype;
480{
481 LPBYTE lpvalue;
482 HKEY hrootkey = NULL;
483 DWORD cbData;
484 BOOL ok = FALSE;
485
486 /* Check both the current user and the local machine to see if
487 we have any resources. */
488
489 if (RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
490 {
491 lpvalue = NULL;
492
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)
496 {
497 return (lpvalue);
498 }
499
500 if (lpvalue) xfree (lpvalue);
501
502 RegCloseKey (hrootkey);
503 }
504
505 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
506 {
507 lpvalue = NULL;
508
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)
512 {
513 return (lpvalue);
514 }
515
516 if (lpvalue) xfree (lpvalue);
517
518 RegCloseKey (hrootkey);
519 }
520
521 return (NULL);
522}
523
524void
525init_environment ()
526{
527 /* Check for environment variables and use registry if they don't exist */
528 {
529 int i;
530 LPBYTE lpval;
531 DWORD dwType;
532
533 static char * env_vars[] =
534 {
535 "HOME",
536 "emacs_dir",
537 "EMACSLOADPATH",
538 "SHELL",
539 "EMACSDATA",
540 "EMACSPATH",
541 "EMACSLOCKDIR",
542 "INFOPATH",
543 "EMACSDOC",
544 "TERM",
545 };
546
547 for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++)
548 {
549 if (!getenv (env_vars[i]) &&
550 (lpval = nt_get_resource (env_vars[i], &dwType)) != NULL)
551 {
552 if (dwType == REG_EXPAND_SZ)
553 {
554 char buf1[500], buf2[500];
555
556 ExpandEnvironmentStrings ((LPSTR) lpval, buf1, 500);
557 _snprintf (buf2, 499, "%s=%s", env_vars[i], buf1);
558 putenv (strdup (buf2));
559 }
560 else if (dwType == REG_SZ)
561 {
562 char buf[500];
563
564 _snprintf (buf, 499, "%s=%s", env_vars[i], lpval);
565 putenv (strdup (buf));
566 }
567
568 xfree (lpval);
569 }
570 }
571 }
572
573 init_user_info ();
574}
468 575
469/* We don't have scripts to automatically determine the system configuration 576/* We don't have scripts to automatically determine the system configuration
470 for Emacs before it's compiled, and we don't want to have to make the 577 for Emacs before it's compiled, and we don't want to have to make the
@@ -518,533 +625,1405 @@ get_emacs_configuration (void)
518 /* Let oem be "*" until we figure out how to decode the OEM field. */ 625 /* Let oem be "*" until we figure out how to decode the OEM field. */
519 oem = "*"; 626 oem = "*";
520 627
521#ifdef WINDOWS95 628 os = (GetVersion () & 0x80000000) ? "win95" : "nt";
522 os = "win";
523#else
524 os = "nt";
525#endif
526 629
527 sprintf (configuration_buffer, "%s-%s-%s%d.%d", arch, oem, os, 630 sprintf (configuration_buffer, "%s-%s-%s%d.%d", arch, oem, os,
528 get_nt_major_version (), get_nt_minor_version ()); 631 get_nt_major_version (), get_nt_minor_version ());
529 return configuration_buffer; 632 return configuration_buffer;
530} 633}
531 634
532/* Conjure up inode and device numbers that will serve the purpose 635#include <sys/timeb.h>
533 of Emacs. Return 1 upon success, 0 upon failure. */ 636
637/* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
638void
639gettimeofday (struct timeval *tv, struct timezone *tz)
640{
641 struct _timeb tb;
642 _ftime (&tb);
643
644 tv->tv_sec = tb.time;
645 tv->tv_usec = tb.millitm * 1000L;
646 if (tz)
647 {
648 tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */
649 tz->tz_dsttime = tb.dstflag; /* type of dst correction */
650 }
651}
652
653/* ------------------------------------------------------------------------- */
654/* IO support and wrapper functions for Win32 API. */
655/* ------------------------------------------------------------------------- */
656
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). */
660char *
661sys_ctime (const time_t *t)
662{
663 char *str = (char *) ctime (t);
664 return (str ? str : "Sun Jan 01 00:00:00 1970");
665}
666
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. */
670void
671sys_sleep (int seconds)
672{
673 Sleep (seconds * 1000);
674}
675
676/* Internal MSVC data and functions for low-level descriptor munging */
677#if (_MSC_VER == 900)
678extern char _osfile[];
679#endif
680extern int __cdecl _set_osfhnd (int fd, long h);
681extern int __cdecl _free_osfhnd (int fd);
682
683/* parallel array of private info on file handles */
684filedesc fd_info [ MAXDESC ];
685
686static struct {
687 DWORD serialnum;
688 DWORD maxcomp;
689 DWORD flags;
690 char name[32];
691 char type[32];
692} volume_info;
693
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). */
534int 696int
535get_inode_and_device_vals (Lisp_Object filename, Lisp_Object *p_inode, 697get_volume_info (const char * name, const char ** pPath)
536 Lisp_Object *p_device)
537{ 698{
538 /* File uids on NT are found using a handle to a file, which 699 char temp[MAX_PATH];
539 implies that it has been opened. Since we want to be able 700 char *rootname = NULL; /* default to current volume */
540 to stat an arbitrary file, we must open it, get the info,
541 and then close it.
542
543 Also, NT file uids are 64-bits. This is a problem. */
544
545 HANDLE handle;
546 BOOL result;
547 DWORD attrs;
548 BY_HANDLE_FILE_INFORMATION info;
549
550 /* We have to stat files and directories differently, so check
551 to see what filename references. */
552 attrs = GetFileAttributes (XSTRING (filename)->data);
553 if (attrs == 0xFFFFFFFF) {
554 return 0;
555 }
556 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
557 /* Conjure up bogus, but unique, values. */
558 attrs = GetTickCount ();
559 *p_inode = make_number (attrs);
560 *p_device = make_number (attrs);
561 return 1;
562 }
563 701
564 /* FIXME: It shouldn't be opened without READ access, but NT on x86 702 if (name == NULL)
565 doesn't allow GetFileInfo in that case (NT on mips does). */ 703 return FALSE;
566
567 handle = CreateFile (XSTRING (filename)->data,
568 GENERIC_READ,
569 FILE_SHARE_READ | FILE_SHARE_WRITE,
570 NULL,
571 OPEN_EXISTING,
572 FILE_ATTRIBUTE_NORMAL,
573 NULL);
574 if (handle == INVALID_HANDLE_VALUE)
575 return 0;
576 704
577 result = GetFileInformationByHandle (handle, &info); 705 /* find the root name of the volume if given */
578 CloseHandle (handle); 706 if (isalpha (name[0]) && name[1] == ':')
579 if (!result) 707 {
580 return 0; 708 rootname = temp;
709 temp[0] = *name++;
710 temp[1] = *name++;
711 temp[2] = '\\';
712 temp[3] = 0;
713 }
714 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
715 {
716 char *str = temp;
717 int slashes = 4;
718 rootname = temp;
719 do
720 {
721 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
722 break;
723 *str++ = *name++;
724 }
725 while ( *name );
726
727 if (slashes > 1)
728 return FALSE;
581 729
582 *p_inode = make_number (info.nFileIndexLow); /* use the low value */ 730 *str++ = '\\';
583 *p_device = make_number (info.dwVolumeSerialNumber); 731 *str = 0;
732 }
584 733
585 return 1; 734 if (pPath)
735 *pPath = name;
736
737 if (GetVolumeInformation (rootname,
738 volume_info.name, 32,
739 &volume_info.serialnum,
740 &volume_info.maxcomp,
741 &volume_info.flags,
742 volume_info.type, 32))
743 {
744 return TRUE;
745 }
746 return FALSE;
586} 747}
587 748
588/* The following pipe routines are used to support our fork emulation. 749/* Determine if volume is FAT format (ie. only supports short 8.3
589 Since NT's crt dup always creates inherited handles, we 750 names); also set path pointer to start of pathname in name. */
590 must be careful in setting up pipes. First create 751int
591 non-inherited pipe handles, then create an inherited handle 752is_fat_volume (const char * name, const char ** pPath)
592 to the write end by dup-ing it, and then close the non-inherited 753{
593 end that was just duped. This gives us one non-inherited handle 754 if (get_volume_info (name, pPath))
594 on the read end and one inherited handle to the write end. As 755 return (volume_info.maxcomp == 12);
595 the parent, we close the inherited handle to the write end after 756 return FALSE;
596 spawning the child. */ 757}
597 758
598/* From callproc.c */ 759/* Map filename to a legal 8.3 name if necessary. */
599extern Lisp_Object Vbinary_process_input; 760const char *
600extern Lisp_Object Vbinary_process_output; 761map_win32_filename (const char * name, const char ** pPath)
762{
763 static char shortname[MAX_PATH];
764 char * str = shortname;
765 char c;
766 const char * orig_name = name;
767 char * path;
601 768
602void 769 if (is_fat_volume (name, &path)) /* truncate to 8.3 */
603pipe_with_inherited_out (int fds[2]) 770 {
771 register int left = 8; /* maximum number of chars in part */
772 register int extn = 0; /* extension added? */
773 register int dots = 2; /* maximum number of dots allowed */
774
775 while (name < path)
776 *str++ = *name++; /* skip past UNC header */
777
778 while ((c = *name++))
779 {
780 switch ( c )
781 {
782 case '\\':
783 case '/':
784 *str++ = '\\';
785 extn = 0; /* reset extension flags */
786 dots = 2; /* max 2 dots */
787 left = 8; /* max length 8 for main part */
788 break;
789 case ':':
790 *str++ = ':';
791 extn = 0; /* reset extension flags */
792 dots = 2; /* max 2 dots */
793 left = 8; /* max length 8 for main part */
794 break;
795 case '.':
796 if ( dots )
797 {
798 /* Convert path components of the form .xxx to _xxx,
799 but leave . and .. as they are. This allows .emacs
800 to be read as _emacs, for example. */
801
802 if (! *name ||
803 *name == '.' ||
804 IS_DIRECTORY_SEP (*name))
805 {
806 *str++ = '.';
807 dots--;
808 }
809 else
810 {
811 *str++ = '_';
812 left--;
813 dots = 0;
814 }
815 }
816 else if ( !extn )
817 {
818 *str++ = '.';
819 extn = 1; /* we've got an extension */
820 left = 3; /* 3 chars in extension */
821 }
822 else
823 {
824 /* any embedded dots after the first are converted to _ */
825 *str++ = '_';
826 }
827 break;
828 case '~':
829 case '#': /* don't lose these, they're important */
830 if ( ! left )
831 str[-1] = c; /* replace last character of part */
832 /* FALLTHRU */
833 default:
834 if ( left )
835 {
836 *str++ = tolower (c); /* map to lower case (looks nicer) */
837 left--;
838 dots = 0; /* started a path component */
839 }
840 break;
841 }
842 }
843 *str = '\0';
844
845 name = shortname;
846 }
847
848 if (pPath)
849 *pPath = name + (path - orig_name);
850
851 return name;
852}
853
854
855/* Shadow some MSVC runtime functions to map requests for long filenames
856 to reasonable short names if necessary. This was originally added to
857 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
858 long file names. */
859
860int
861sys_access (const char * path, int mode)
604{ 862{
605 int inherit_out; 863 return _access (map_win32_filename (path, NULL), mode);
606 unsigned int flags = _O_NOINHERIT; 864}
607 865
608 if (!NILP (Vbinary_process_output)) 866int
609 flags |= _O_BINARY; 867sys_chdir (const char * path)
868{
869 return _chdir (map_win32_filename (path, NULL));
870}
610 871
611 _pipe (fds, 0, flags); 872int
612 inherit_out = dup (fds[1]); 873sys_chmod (const char * path, int mode)
613 close (fds[1]); 874{
614 fds[1] = inherit_out; 875 return _chmod (map_win32_filename (path, NULL), mode);
615} 876}
616 877
617void 878int
618pipe_with_inherited_in (int fds[2]) 879sys_creat (const char * path, int mode)
619{ 880{
620 int inherit_in; 881 return _creat (map_win32_filename (path, NULL), mode);
621 unsigned int flags = _O_NOINHERIT; 882}
622 883
623 if (!NILP (Vbinary_process_input)) 884FILE *
624 flags |= _O_BINARY; 885sys_fopen(const char * path, const char * mode)
886{
887 int fd;
888 int oflag;
889 const char * mode_save = mode;
890
891 /* Force all file handles to be non-inheritable. This is necessary to
892 ensure child processes don't unwittingly inherit handles that might
893 prevent future file access. */
894
895 if (mode[0] == 'r')
896 oflag = O_RDONLY;
897 else if (mode[0] == 'w' || mode[0] == 'a')
898 oflag = O_WRONLY | O_CREAT | O_TRUNC;
899 else
900 return NULL;
625 901
626 _pipe (fds, 0, flags); 902 /* Only do simplistic option parsing. */
627 inherit_in = dup (fds[0]); 903 while (*++mode)
628 close (fds[0]); 904 if (mode[0] == '+')
629 fds[0] = inherit_in; 905 {
906 oflag &= ~(O_RDONLY | O_WRONLY);
907 oflag |= O_RDWR;
908 }
909 else if (mode[0] == 'b')
910 {
911 oflag &= ~O_TEXT;
912 oflag |= O_BINARY;
913 }
914 else if (mode[0] == 't')
915 {
916 oflag &= ~O_BINARY;
917 oflag |= O_TEXT;
918 }
919 else break;
920
921 fd = _open (map_win32_filename (path, NULL), oflag | _O_NOINHERIT, 0644);
922 if (fd < 0)
923 return NULL;
924
925 return fdopen (fd, mode_save);
630} 926}
631 927
632/* The following two routines are used to manipulate stdin, stdout, and 928int
633 stderr of our child processes. 929sys_link (const char * path1, const char * path2)
930{
931 errno = EINVAL;
932 return -1;
933}
634 934
635 Assuming that in, out, and err are inherited, we make them stdin, 935int
636 stdout, and stderr of the child as follows: 936sys_mkdir (const char * path)
937{
938 return _mkdir (map_win32_filename (path, NULL));
939}
940
941char *
942sys_mktemp (char * template)
943{
944 return (char *) map_win32_filename ((const char *) _mktemp (template), NULL);
945}
637 946
638 - Save the parent's current standard handles. 947int
639 - Set the parent's standard handles to the handles being passed in. 948sys_open (const char * path, int oflag, int mode)
640 (Note that _get_osfhandle is an io.h procedure that 949{
641 maps crt file descriptors to NT file handles.) 950 /* Force all file handles to be non-inheritable. */
642 - Spawn the child, which inherits in, out, and err as stdin, 951 return _open (map_win32_filename (path, NULL), oflag | _O_NOINHERIT, mode);
643 stdout, and stderr. (see Spawnve) 952}
644 - Reset the parent's standard handles to the saved handles.
645 (see reset_standard_handles)
646 We assume that the caller closes in, out, and err after calling us. */
647 953
648void 954int
649prepare_standard_handles (int in, int out, int err, HANDLE handles[4]) 955sys_rename (const char * oldname, const char * newname)
650{ 956{
651 HANDLE parent, stdin_save, stdout_save, stderr_save, err_handle; 957 char temp[MAX_PATH];
652
653#ifdef WINDOWS95
654 /* The Win95 beta doesn't set the standard handles correctly.
655 Handicap subprocesses until we get a version that works correctly.
656 Undefining the subprocesses macro reveals other incompatibilities,
657 so, since we're expecting subprocs to work in the near future,
658 disable them here. */
659 report_file_error ("Subprocesses currently disabled on Win95", Qnil);
660#endif
661 958
662 parent = GetCurrentProcess (); 959 /* MoveFile on Win95 doesn't correctly change the short file name
663 stdin_save = GetStdHandle (STD_INPUT_HANDLE); 960 alias when oldname has a three char extension and newname has the
664 stdout_save = GetStdHandle (STD_OUTPUT_HANDLE); 961 same first three chars in its extension. To avoid problems, on
665 stderr_save = GetStdHandle (STD_ERROR_HANDLE); 962 Win95 we rename to a temporary name first. */
666 963
667#ifndef HAVE_NTGUI 964 strcpy (temp, map_win32_filename (oldname, NULL));
668 if (!DuplicateHandle (parent, 965
669 GetStdHandle (STD_INPUT_HANDLE), 966 if (GetVersion () & 0x80000000)
670 parent,
671 &stdin_save,
672 0,
673 FALSE,
674 DUPLICATE_SAME_ACCESS))
675 report_file_error ("Duplicating parent's input handle", Qnil);
676
677 if (!DuplicateHandle (parent,
678 GetStdHandle (STD_OUTPUT_HANDLE),
679 parent,
680 &stdout_save,
681 0,
682 FALSE,
683 DUPLICATE_SAME_ACCESS))
684 report_file_error ("Duplicating parent's output handle", Qnil);
685
686 if (!DuplicateHandle (parent,
687 GetStdHandle (STD_ERROR_HANDLE),
688 parent,
689 &stderr_save,
690 0,
691 FALSE,
692 DUPLICATE_SAME_ACCESS))
693 report_file_error ("Duplicating parent's error handle", Qnil);
694#endif /* !HAVE_NTGUI */
695
696 if (!SetStdHandle (STD_INPUT_HANDLE, (HANDLE) _get_osfhandle (in)))
697 report_file_error ("Changing stdin handle", Qnil);
698
699 if (!SetStdHandle (STD_OUTPUT_HANDLE, (HANDLE) _get_osfhandle (out)))
700 report_file_error ("Changing stdout handle", Qnil);
701
702 /* We lose data if we use the same handle to the pipe for stdout and
703 stderr, so make a duplicate. This took a while to find. */
704 if (out == err)
705 { 967 {
706 if (!DuplicateHandle (parent, 968 char * p;
707 (HANDLE) _get_osfhandle (err), 969
708 parent, 970 unixtodos_filename (temp);
709 &err_handle, 971 if (p = strrchr (temp, '\\'))
710 0, 972 p++;
711 TRUE, 973 else
712 DUPLICATE_SAME_ACCESS)) 974 p = temp;
713 report_file_error ("Duplicating out handle to make err handle.", 975 strcpy (p, "__XXXXXX");
714 Qnil); 976 _mktemp (temp);
715 } 977 if (rename (map_win32_filename (oldname, NULL), temp) < 0)
716 else 978 return -1;
979 }
980
981 /* Emulate Unix behaviour - newname is deleted if it already exists
982 (at least if it is a file; don't do this for directories). */
983 newname = map_win32_filename (newname, NULL);
984 if (GetFileAttributes (newname) != -1)
985 {
986 _chmod (newname, 0666);
987 _unlink (newname);
988 }
989
990 return rename (temp, newname);
991}
992
993int
994sys_rmdir (const char * path)
995{
996 return _rmdir (map_win32_filename (path, NULL));
997}
998
999int
1000sys_unlink (const char * path)
1001{
1002 return _unlink (map_win32_filename (path, NULL));
1003}
1004
1005static FILETIME utc_base_ft;
1006static long double utc_base;
1007static int init = 0;
1008
1009static time_t
1010convert_time (FILETIME ft)
1011{
1012 long double ret;
1013
1014 if (!init)
717 { 1015 {
718 err_handle = (HANDLE) _get_osfhandle (err); 1016 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
1017 SYSTEMTIME st;
1018
1019 st.wYear = 1970;
1020 st.wMonth = 1;
1021 st.wDay = 1;
1022 st.wHour = 0;
1023 st.wMinute = 0;
1024 st.wSecond = 0;
1025 st.wMilliseconds = 0;
1026
1027 SystemTimeToFileTime (&st, &utc_base_ft);
1028 utc_base = (long double) utc_base_ft.dwHighDateTime
1029 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
1030 init = 1;
719 } 1031 }
720 1032
721 if (!SetStdHandle (STD_ERROR_HANDLE, err_handle)) 1033 if (CompareFileTime (&ft, &utc_base_ft) < 0)
722 report_file_error ("Changing stderr handle", Qnil); 1034 return 0;
723 1035
724 handles[0] = stdin_save; 1036 ret = (long double) ft.dwHighDateTime * 4096 * 1024 * 1024 + ft.dwLowDateTime;
725 handles[1] = stdout_save; 1037 ret -= utc_base;
726 handles[2] = stderr_save; 1038 return (time_t) (ret * 1e-7);
727 handles[3] = err_handle;
728} 1039}
729 1040
1041#if 0
1042/* in case we ever have need of this */
730void 1043void
731reset_standard_handles (int in, int out, int err, HANDLE handles[4]) 1044convert_from_time_t (time_t time, FILETIME * pft)
732{ 1045{
733 HANDLE stdin_save = handles[0]; 1046 long double tmp;
734 HANDLE stdout_save = handles[1];
735 HANDLE stderr_save = handles[2];
736 HANDLE err_handle = handles[3];
737 int i;
738 1047
739#ifndef HAVE_NTGUI 1048 if (!init)
740 if (!SetStdHandle (STD_INPUT_HANDLE, stdin_save))
741 report_file_error ("Resetting input handle", Qnil);
742
743 if (!SetStdHandle (STD_OUTPUT_HANDLE, stdout_save))
744 { 1049 {
745 i = GetLastError (); 1050 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
746 report_file_error ("Resetting output handle", Qnil); 1051 SYSTEMTIME st;
1052
1053 st.wYear = 1970;
1054 st.wMonth = 1;
1055 st.wDay = 1;
1056 st.wHour = 0;
1057 st.wMinute = 0;
1058 st.wSecond = 0;
1059 st.wMilliseconds = 0;
1060
1061 SystemTimeToFileTime (&st, &utc_base_ft);
1062 utc_base = (long double) utc_base_ft.dwHighDateTime
1063 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
1064 init = 1;
747 } 1065 }
748 1066
749 if (!SetStdHandle (STD_ERROR_HANDLE, stderr_save)) 1067 /* time in 100ns units since 1-Jan-1601 */
750 report_file_error ("Resetting error handle", Qnil); 1068 tmp = (long double) time * 1e7 + utc_base;
751#endif /* !HAVE_NTGUI */ 1069 pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024));
752 1070 pft->dwLowDateTime = (DWORD) (tmp - pft->dwHighDateTime);
753 if (out == err) 1071}
1072#endif
1073
1074/* "PJW" algorithm (see the "Dragon" compiler book). */
1075static unsigned
1076hashval (const char * str)
1077{
1078 unsigned h = 0;
1079 unsigned g;
1080 while (*str)
754 { 1081 {
755 /* If out and err are the same handle, then we duplicated out 1082 h = (h << 4) + *str++;
756 and stuck it in err_handle. Close the duplicate to clean up. */ 1083 if ((g = h & 0xf0000000) != 0)
757 if (!CloseHandle (err_handle)) 1084 h = (h ^ (g >> 24)) & 0x0fffffff;
758 report_file_error ("Closing error handle duplicated from out.",
759 Qnil);
760 } 1085 }
1086 return h;
761} 1087}
762 1088
1089/* Return the hash value of the canonical pathname, excluding the
1090 drive/UNC header, to get a hopefully unique inode number. */
1091static _ino_t
1092generate_inode_val (const char * name)
1093{
1094 char fullname[ MAX_PATH ];
1095 char * p;
1096 unsigned hash;
1097
1098 GetFullPathName (name, sizeof (fullname), fullname, &p);
1099 get_volume_info (fullname, &p);
1100 /* Normal Win32 filesystems are still case insensitive. */
1101 _strlwr (p);
1102 hash = hashval (p);
1103 return (_ino_t) (hash ^ (hash >> 16));
1104}
1105
1106/* MSVC stat function can't cope with UNC names and has other bugs, so
1107 replace it with our own. This also allows us to calculate consistent
1108 inode values without hacks in the main Emacs code. */
763int 1109int
764random () 1110stat (const char * path, struct stat * buf)
765{ 1111{
766 /* rand () on NT gives us 15 random bits...hack together 30 bits. */ 1112 char * name;
767 return ((rand () << 15) | rand ()); 1113 WIN32_FIND_DATA wfd;
1114 HANDLE fh;
1115 int permission;
1116 int len;
1117 int rootdir = FALSE;
1118
1119 if (path == NULL || buf == NULL)
1120 {
1121 errno = EFAULT;
1122 return -1;
1123 }
1124
1125 name = (char *) map_win32_filename (path, &path);
1126 /* must be valid filename, no wild cards */
1127 if (strchr (name, '*') || strchr (name, '?'))
1128 {
1129 errno = ENOENT;
1130 return -1;
1131 }
1132
1133 /* Remove trailing directory separator, unless name is the root
1134 directory of a drive or UNC volume in which case ensure there
1135 is a trailing separator. */
1136 len = strlen (name);
1137 rootdir = (path >= name + len - 1
1138 && (IS_DIRECTORY_SEP (*path) || *path == 0));
1139 name = strcpy (alloca (len + 2), name);
1140
1141 if (rootdir)
1142 {
1143 if (!IS_DIRECTORY_SEP (name[len-1]))
1144 strcat (name, "\\");
1145 if (GetDriveType (name) < 2)
1146 {
1147 errno = ENOENT;
1148 return -1;
1149 }
1150 memset (&wfd, 0, sizeof (wfd));
1151 wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
1152 wfd.ftCreationTime = utc_base_ft;
1153 wfd.ftLastAccessTime = utc_base_ft;
1154 wfd.ftLastWriteTime = utc_base_ft;
1155 strcpy (wfd.cFileName, name);
1156 }
1157 else
1158 {
1159 if (IS_DIRECTORY_SEP (name[len-1]))
1160 name[len - 1] = 0;
1161 fh = FindFirstFile (name, &wfd);
1162 if (fh == INVALID_HANDLE_VALUE)
1163 {
1164 errno = ENOENT;
1165 return -1;
1166 }
1167 FindClose (fh);
1168 }
1169
1170 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1171 {
1172 buf->st_mode = _S_IFDIR;
1173 buf->st_nlink = 2; /* doesn't really matter */
1174 }
1175 else
1176 {
1177#if 0
1178 /* This is more accurate in terms of gettting the correct number
1179 of links, but is quite slow (it is noticable when Emacs is
1180 making a list of file name completions). */
1181 BY_HANDLE_FILE_INFORMATION info;
1182
1183 fh = CreateFile (name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
1184 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1185
1186 if (GetFileInformationByHandle (fh, &info))
1187 {
1188 switch (GetFileType (fh))
1189 {
1190 case FILE_TYPE_DISK:
1191 buf->st_mode = _S_IFREG;
1192 break;
1193 case FILE_TYPE_PIPE:
1194 buf->st_mode = _S_IFIFO;
1195 break;
1196 case FILE_TYPE_CHAR:
1197 case FILE_TYPE_UNKNOWN:
1198 default:
1199 buf->st_mode = _S_IFCHR;
1200 }
1201 buf->st_nlink = info.nNumberOfLinks;
1202 /* Could use file index, but this is not guaranteed to be
1203 unique unless we keep a handle open all the time. */
1204 /* buf->st_ino = info.nFileIndexLow ^ info.nFileIndexHigh; */
1205 CloseHandle (fh);
1206 }
1207 else
1208 {
1209 errno = EACCES;
1210 return -1;
1211 }
1212#else
1213 buf->st_mode = _S_IFREG;
1214 buf->st_nlink = 1;
1215#endif
1216 }
1217
1218 /* consider files to belong to current user */
1219 buf->st_uid = the_passwd.pw_uid;
1220 buf->st_gid = the_passwd.pw_gid;
1221
1222 /* volume_info is set indirectly by map_win32_filename */
1223 buf->st_dev = volume_info.serialnum;
1224 buf->st_rdev = volume_info.serialnum;
1225
1226 buf->st_ino = generate_inode_val (name);
1227
1228 buf->st_size = wfd.nFileSizeLow;
1229
1230 /* Convert timestamps to Unix format. */
1231 buf->st_mtime = convert_time (wfd.ftLastWriteTime);
1232 buf->st_atime = convert_time (wfd.ftLastAccessTime);
1233 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
1234 buf->st_ctime = convert_time (wfd.ftCreationTime);
1235 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
1236
1237 /* determine rwx permissions */
1238 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
1239 permission = _S_IREAD;
1240 else
1241 permission = _S_IREAD | _S_IWRITE;
1242
1243 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1244 permission |= _S_IEXEC;
1245 else
1246 {
1247 char * p = strrchr (name, '.');
1248 if (p != NULL &&
1249 (stricmp (p, ".exe") == 0 ||
1250 stricmp (p, ".com") == 0 ||
1251 stricmp (p, ".bat") == 0 ||
1252 stricmp (p, ".cmd") == 0))
1253 permission |= _S_IEXEC;
1254 }
1255
1256 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
1257
1258 return 0;
768} 1259}
769 1260
770void 1261#ifdef HAVE_SOCKETS
771srandom (int seed) 1262
1263/* Wrappers for winsock functions to map between our file descriptors
1264 and winsock's handles; also set h_errno for convenience.
1265
1266 To allow Emacs to run on systems which don't have winsock support
1267 installed, we dynamically link to winsock on startup if present, and
1268 otherwise provide the minimum necessary functionality
1269 (eg. gethostname). */
1270
1271/* function pointers for relevant socket functions */
1272int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
1273void (PASCAL *pfn_WSASetLastError) (int iError);
1274int (PASCAL *pfn_WSAGetLastError) (void);
1275int (PASCAL *pfn_socket) (int af, int type, int protocol);
1276int (PASCAL *pfn_bind) (SOCKET s, const struct sockaddr *addr, int namelen);
1277int (PASCAL *pfn_connect) (SOCKET s, const struct sockaddr *addr, int namelen);
1278int (PASCAL *pfn_ioctlsocket) (SOCKET s, long cmd, u_long *argp);
1279int (PASCAL *pfn_recv) (SOCKET s, char * buf, int len, int flags);
1280int (PASCAL *pfn_send) (SOCKET s, const char * buf, int len, int flags);
1281int (PASCAL *pfn_closesocket) (SOCKET s);
1282int (PASCAL *pfn_shutdown) (SOCKET s, int how);
1283int (PASCAL *pfn_WSACleanup) (void);
1284
1285u_short (PASCAL *pfn_htons) (u_short hostshort);
1286u_short (PASCAL *pfn_ntohs) (u_short netshort);
1287unsigned long (PASCAL *pfn_inet_addr) (const char * cp);
1288int (PASCAL *pfn_gethostname) (char * name, int namelen);
1289struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
1290struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto);
1291
1292static int have_winsock;
1293static HANDLE winsock_lib;
1294
1295static void
1296term_winsock (void)
772{ 1297{
773 srand (seed); 1298 if (have_winsock)
1299 {
1300 pfn_WSACleanup ();
1301 FreeLibrary (winsock_lib);
1302 }
774} 1303}
775 1304
776/* Destructively turn backslashes into slashes. */ 1305static void
777void 1306init_winsock ()
778dostounix_filename (p)
779 register char *p;
780{ 1307{
781 while (*p) 1308 WSADATA winsockData;
1309
1310 winsock_lib = LoadLibrary ("wsock32.dll");
1311
1312 if (winsock_lib != NULL)
782 { 1313 {
783 if (*p == '\\') 1314 /* dynamically link to socket functions */
784 *p = '/'; 1315
785 p++; 1316#define LOAD_PROC(fn) \
1317 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
1318 goto fail;
1319
1320 LOAD_PROC( WSAStartup );
1321 LOAD_PROC( WSASetLastError );
1322 LOAD_PROC( WSAGetLastError );
1323 LOAD_PROC( socket );
1324 LOAD_PROC( bind );
1325 LOAD_PROC( connect );
1326 LOAD_PROC( ioctlsocket );
1327 LOAD_PROC( recv );
1328 LOAD_PROC( send );
1329 LOAD_PROC( closesocket );
1330 LOAD_PROC( shutdown );
1331 LOAD_PROC( htons );
1332 LOAD_PROC( ntohs );
1333 LOAD_PROC( inet_addr );
1334 LOAD_PROC( gethostname );
1335 LOAD_PROC( gethostbyname );
1336 LOAD_PROC( getservbyname );
1337 LOAD_PROC( WSACleanup );
1338
1339 /* specify version 1.1 of winsock */
1340 if (pfn_WSAStartup (0x101, &winsockData) == 0)
1341 {
1342 have_winsock = TRUE;
1343 return;
1344 }
1345
1346 fail:
1347 FreeLibrary (winsock_lib);
786 } 1348 }
1349 have_winsock = FALSE;
787} 1350}
788 1351
789/* Routines that are no-ops on NT but are defined to get Emacs to compile. */
790 1352
1353int h_errno = 0;
791 1354
792int 1355/* function to set h_errno for compatability; map winsock error codes to
793sigsetmask (int signal_mask) 1356 normal system codes where they overlap (non-overlapping definitions
794{ 1357 are already in <sys/socket.h> */
795 return 0; 1358static void set_errno ()
1359{
1360 if (!have_winsock)
1361 h_errno = EINVAL;
1362 else
1363 h_errno = pfn_WSAGetLastError ();
1364
1365 switch (h_errno)
1366 {
1367 case WSAEACCES: h_errno = EACCES; break;
1368 case WSAEBADF: h_errno = EBADF; break;
1369 case WSAEFAULT: h_errno = EFAULT; break;
1370 case WSAEINTR: h_errno = EINTR; break;
1371 case WSAEINVAL: h_errno = EINVAL; break;
1372 case WSAEMFILE: h_errno = EMFILE; break;
1373 case WSAENAMETOOLONG: h_errno = ENAMETOOLONG; break;
1374 case WSAENOTEMPTY: h_errno = ENOTEMPTY; break;
1375 }
1376 errno = h_errno;
796} 1377}
797 1378
798int 1379static void check_errno ()
799sigblock (int sig) 1380{
800{ 1381 if (h_errno == 0 && have_winsock)
801 return 0; 1382 pfn_WSASetLastError (0);
802} 1383}
803 1384
804int 1385/* [andrewi 3-May-96] I've had conflicting results using both methods,
805kill (int pid, int signal) 1386 but I believe the method of keeping the socket handle separate (and
806{ 1387 insuring it is not inheritable) is the correct one. */
807 return 0; 1388
1389//#define SOCK_REPLACE_HANDLE
1390
1391#ifdef SOCK_REPLACE_HANDLE
1392#define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
1393#else
1394#define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
1395#endif
1396
1397int
1398sys_socket(int af, int type, int protocol)
1399{
1400 int fd;
1401 long s;
1402 child_process * cp;
1403
1404 if (!have_winsock)
1405 {
1406 h_errno = ENETDOWN;
1407 return INVALID_SOCKET;
1408 }
1409
1410 check_errno ();
1411
1412 /* call the real socket function */
1413 s = (long) pfn_socket (af, type, protocol);
1414
1415 if (s != INVALID_SOCKET)
1416 {
1417 /* Although under NT 3.5 _open_osfhandle will accept a socket
1418 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
1419 that does not work under NT 3.1. However, we can get the same
1420 effect by using a backdoor function to replace an existing
1421 descriptor handle with the one we want. */
1422
1423 /* allocate a file descriptor (with appropriate flags) */
1424 fd = _open ("NUL:", _O_RDWR);
1425 if (fd >= 0)
1426 {
1427#ifdef SOCK_REPLACE_HANDLE
1428 /* now replace handle to NUL with our socket handle */
1429 CloseHandle ((HANDLE) _get_osfhandle (fd));
1430 _free_osfhnd (fd);
1431 _set_osfhnd (fd, s);
1432 /* setmode (fd, _O_BINARY); */
1433#else
1434 /* Make a non-inheritable copy of the socket handle. */
1435 {
1436 HANDLE parent;
1437 HANDLE new_s = INVALID_HANDLE_VALUE;
1438
1439 parent = GetCurrentProcess ();
1440
1441 DuplicateHandle (parent,
1442 (HANDLE) s,
1443 parent,
1444 &new_s,
1445 0,
1446 FALSE,
1447 DUPLICATE_SAME_ACCESS);
1448 pfn_closesocket (s);
1449 fd_info[fd].hnd = new_s;
1450 s = (SOCKET) new_s;
1451 }
1452#endif
1453
1454 /* set our own internal flags */
1455 fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
1456
1457 cp = new_child ();
1458 if (cp)
1459 {
1460 cp->fd = fd;
1461 cp->status = STATUS_READ_ACKNOWLEDGED;
1462
1463 /* attach child_process to fd_info */
1464 if (fd_info[ fd ].cp != NULL)
1465 {
1466 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
1467 abort ();
1468 }
1469
1470 fd_info[ fd ].cp = cp;
1471
1472 /* success! */
1473 return fd;
1474 }
1475
1476 /* clean up */
1477 _close (fd);
1478 }
1479 pfn_closesocket (s);
1480 h_errno = EMFILE;
1481 }
1482 set_errno ();
1483
1484 return -1;
808} 1485}
809 1486
810int 1487
811setpgrp (int pid, int gid) 1488int
812{ 1489sys_bind (int s, const struct sockaddr * addr, int namelen)
813 return 0; 1490{
1491 if (!have_winsock)
1492 {
1493 h_errno = ENOTSOCK;
1494 return SOCKET_ERROR;
1495 }
1496
1497 check_errno ();
1498 if (fd_info[s].flags & FILE_SOCKET)
1499 {
1500 int rc = pfn_bind (SOCK_HANDLE (s), addr, namelen);
1501 if (rc == SOCKET_ERROR)
1502 set_errno ();
1503 return rc;
1504 }
1505 h_errno = ENOTSOCK;
1506 return SOCKET_ERROR;
814} 1507}
815 1508
816int 1509
817alarm (int seconds) 1510int
818{ 1511sys_connect (int s, const struct sockaddr * name, int namelen)
819 return 0; 1512{
1513 if (!have_winsock)
1514 {
1515 h_errno = ENOTSOCK;
1516 return SOCKET_ERROR;
1517 }
1518
1519 check_errno ();
1520 if (fd_info[s].flags & FILE_SOCKET)
1521 {
1522 int rc = pfn_connect (SOCK_HANDLE (s), name, namelen);
1523 if (rc == SOCKET_ERROR)
1524 set_errno ();
1525 return rc;
1526 }
1527 h_errno = ENOTSOCK;
1528 return SOCKET_ERROR;
820} 1529}
821 1530
822int 1531u_short
823unrequest_sigio (void) 1532sys_htons (u_short hostshort)
824{ 1533{
825 return 0; 1534 return (have_winsock) ?
1535 pfn_htons (hostshort) : hostshort;
826} 1536}
827 1537
828int 1538u_short
829request_sigio (void) 1539sys_ntohs (u_short netshort)
830{ 1540{
831 return 0; 1541 return (have_winsock) ?
1542 pfn_ntohs (netshort) : netshort;
832} 1543}
833 1544
834int 1545unsigned long
835getuid () 1546sys_inet_addr (const char * cp)
836{ 1547{
837 char buffer[256]; 1548 return (have_winsock) ?
838 int size = 256; 1549 pfn_inet_addr (cp) : INADDR_NONE;
1550}
839 1551
840 if (!GetUserName (buffer, &size)) 1552int
841 /* Assume all powers upon failure. */ 1553sys_gethostname (char * name, int namelen)
842 return 0; 1554{
1555 if (have_winsock)
1556 return pfn_gethostname (name, namelen);
843 1557
844 if (!stricmp ("administrator", buffer)) 1558 if (namelen > MAX_COMPUTERNAME_LENGTH)
845 return 0; 1559 return !GetComputerName (name, &namelen);
846 else 1560
847 /* A complete fabrication...is there anything to base it on? */ 1561 h_errno = EFAULT;
848 return 123; 1562 return SOCKET_ERROR;
849} 1563}
850 1564
851int 1565struct hostent *
852geteuid () 1566sys_gethostbyname(const char * name)
853{ 1567{
854 /* I could imagine arguing for checking to see whether the user is 1568 struct hostent * host;
855 in the Administrators group and returning a UID of 0 for that 1569
856 case, but I don't know how wise that would be in the long run. */ 1570 if (!have_winsock)
857 return getuid (); 1571 {
1572 h_errno = ENETDOWN;
1573 return NULL;
1574 }
1575
1576 check_errno ();
1577 host = pfn_gethostbyname (name);
1578 if (!host)
1579 set_errno ();
1580 return host;
858} 1581}
859 1582
860/* Remove all CR's that are followed by a LF. 1583struct servent *
861 (From msdos.c...probably should figure out a way to share it, 1584sys_getservbyname(const char * name, const char * proto)
862 although this code isn't going to ever change.) */ 1585{
1586 struct servent * serv;
1587
1588 if (!have_winsock)
1589 {
1590 h_errno = ENETDOWN;
1591 return NULL;
1592 }
1593
1594 check_errno ();
1595 serv = pfn_getservbyname (name, proto);
1596 if (!serv)
1597 set_errno ();
1598 return serv;
1599}
1600
1601#endif /* HAVE_SOCKETS */
1602
1603
1604/* Shadow main io functions: we need to handle pipes and sockets more
1605 intelligently, and implement non-blocking mode as well. */
1606
863int 1607int
864crlf_to_lf (n, buf) 1608sys_close (int fd)
865 register int n;
866 register unsigned char *buf;
867{ 1609{
868 unsigned char *np = buf; 1610 int rc;
869 unsigned char *startp = buf;
870 unsigned char *endp = buf + n;
871 1611
872 if (n == 0) 1612 if (fd < 0 || fd >= MAXDESC)
873 return n;
874 while (buf < endp - 1)
875 { 1613 {
876 if (*buf == 0x0d) 1614 errno = EBADF;
877 { 1615 return -1;
878 if (*(++buf) != 0x0a) 1616 }
879 *np++ = 0x0d; 1617
1618 if (fd_info[fd].cp)
1619 {
1620 child_process * cp = fd_info[fd].cp;
1621
1622 fd_info[fd].cp = NULL;
1623
1624 if (CHILD_ACTIVE (cp))
1625 {
1626 /* if last descriptor to active child_process then cleanup */
1627 int i;
1628 for (i = 0; i < MAXDESC; i++)
1629 {
1630 if (i == fd)
1631 continue;
1632 if (fd_info[i].cp == cp)
1633 break;
1634 }
1635 if (i == MAXDESC)
1636 {
1637#if defined (HAVE_SOCKETS) && !defined (SOCK_REPLACE_HANDLE)
1638 if (fd_info[fd].flags & FILE_SOCKET)
1639 {
1640 if (!have_winsock) abort ();
1641
1642 pfn_shutdown (SOCK_HANDLE (fd), 2);
1643 rc = pfn_closesocket (SOCK_HANDLE (fd));
1644 }
1645#endif
1646 delete_child (cp);
1647 }
880 } 1648 }
881 else
882 *np++ = *buf++;
883 } 1649 }
884 if (buf < endp) 1650
885 *np++ = *buf++; 1651 /* Note that sockets do not need special treatment here (at least on
886 return np - startp; 1652 NT and Win95 using the standard tcp/ip stacks) - it appears that
1653 closesocket is equivalent to CloseHandle, which is to be expected
1654 because socket handles are fully fledged kernel handles. */
1655 rc = _close (fd);
1656
1657 if (rc == 0)
1658 fd_info[fd].flags = 0;
1659
1660 return rc;
887} 1661}
888 1662
889#define REG_ROOT "SOFTWARE\\GNU\\Emacs\\" 1663int
1664sys_dup (int fd)
1665{
1666 int new_fd;
890 1667
891LPBYTE 1668 new_fd = _dup (fd);
892nt_get_resource (key, lpdwtype) 1669 if (new_fd >= 0)
893 char *key; 1670 {
894 LPDWORD lpdwtype; 1671 /* duplicate our internal info as well */
1672 fd_info[new_fd] = fd_info[fd];
1673 }
1674 return new_fd;
1675}
1676
1677
1678int
1679sys_dup2 (int src, int dst)
895{ 1680{
896 LPBYTE lpvalue; 1681 int rc;
897 HKEY hrootkey = NULL; 1682
898 DWORD cbData; 1683 if (dst < 0 || dst >= MAXDESC)
899 BOOL ok = FALSE; 1684 {
900 1685 errno = EBADF;
901 /* Check both the current user and the local machine to see if 1686 return -1;
902 we have any resources. */ 1687 }
1688
1689 /* make sure we close the destination first if it's a pipe or socket */
1690 if (src != dst && fd_info[dst].flags != 0)
1691 sys_close (dst);
903 1692
904 if (RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS) 1693 rc = _dup2 (src, dst);
1694 if (rc == 0)
905 { 1695 {
906 lpvalue = NULL; 1696 /* duplicate our internal info as well */
1697 fd_info[dst] = fd_info[src];
1698 }
1699 return rc;
1700}
907 1701
908 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS 1702/* From callproc.c */
909 && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL 1703extern Lisp_Object Vbinary_process_input;
910 && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS) 1704extern Lisp_Object Vbinary_process_output;
1705
1706/* Unix pipe() has only one arg */
1707int
1708sys_pipe (int * phandles)
1709{
1710 int rc;
1711 unsigned flags;
1712 child_process * cp;
1713
1714 /* make pipe handles non-inheritable; when we spawn a child,
1715 we replace the relevant handle with an inheritable one. */
1716 rc = _pipe (phandles, 0, _O_NOINHERIT);
1717
1718 if (rc == 0)
1719 {
1720 /* set internal flags, and put read and write handles into binary
1721 mode as necessary; if not in binary mode, set the MSVC internal
1722 FDEV (0x40) flag to prevent _read from treating ^Z as eof (this
1723 could otherwise allow Emacs to hang because it then waits
1724 indefinitely for the child process to exit, when it might not be
1725 finished). */
1726 flags = FILE_PIPE | FILE_READ;
1727 if (!NILP (Vbinary_process_output))
911 { 1728 {
912 return (lpvalue); 1729 flags |= FILE_BINARY;
1730 setmode (phandles[0], _O_BINARY);
913 } 1731 }
1732#if (_MSC_VER == 900)
1733 else
1734 _osfile[phandles[0]] |= 0x40;
1735#endif
914 1736
915 if (lpvalue) xfree (lpvalue); 1737 fd_info[phandles[0]].flags = flags;
916 1738
917 RegCloseKey (hrootkey); 1739 flags = FILE_PIPE | FILE_WRITE;
918 } 1740 if (!NILP (Vbinary_process_input))
919
920 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
921 {
922 lpvalue = NULL;
923
924 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS &&
925 (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL &&
926 RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
927 { 1741 {
928 return (lpvalue); 1742 flags |= FILE_BINARY;
1743 setmode (phandles[1], _O_BINARY);
929 } 1744 }
930 1745#if (_MSC_VER == 900)
931 if (lpvalue) xfree (lpvalue); 1746 else
932 1747 _osfile[phandles[1]] |= 0x40;
933 RegCloseKey (hrootkey); 1748#endif
934 } 1749
1750 fd_info[phandles[1]].flags = flags;
1751 }
1752
1753 return rc;
1754}
1755
1756/* Function to do blocking read of one byte, needed to implement
1757 select. It is only allowed on sockets and pipes. */
1758int
1759_sys_read_ahead (int fd)
1760{
1761 child_process * cp;
1762 int rc;
1763
1764 if (fd < 0 || fd >= MAXDESC)
1765 return STATUS_READ_ERROR;
1766
1767 cp = fd_info[fd].cp;
1768
1769 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
1770 return STATUS_READ_ERROR;
1771
1772 if ((fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) == 0
1773 || (fd_info[fd].flags & FILE_READ) == 0)
1774 {
1775 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd));
1776 abort ();
1777 }
935 1778
936 return (NULL); 1779 cp->status = STATUS_READ_IN_PROGRESS;
1780
1781 if (fd_info[fd].flags & FILE_PIPE)
1782 /* Use read to get CRLF translation */
1783 rc = _read (fd, &cp->chr, sizeof (char));
1784#ifdef HAVE_SOCKETS
1785 else if (fd_info[fd].flags & FILE_SOCKET)
1786 rc = pfn_recv (SOCK_HANDLE (fd), &cp->chr, sizeof (char), 0);
1787#endif
1788
1789 if (rc == sizeof (char))
1790 cp->status = STATUS_READ_SUCCEEDED;
1791 else
1792 cp->status = STATUS_READ_FAILED;
1793
1794 return cp->status;
937} 1795}
938 1796
939void 1797int
940init_environment () 1798sys_read (int fd, char * buffer, unsigned int count)
941{ 1799{
942 /* Open a console window to display messages during dumping. */ 1800 int nchars;
943 if (!initialized) 1801 int extra = 0;
944 AllocConsole (); 1802 int to_read;
1803 DWORD waiting;
945 1804
946 /* Check for environment variables and use registry if they don't exist */ 1805 if (fd < 0 || fd >= MAXDESC)
947 { 1806 {
948 int i; 1807 errno = EBADF;
949 LPBYTE lpval; 1808 return -1;
950 DWORD dwType; 1809 }
951 1810
952 static char * env_vars[] = 1811 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
953 { 1812 {
954 "emacs_path", 1813 child_process *cp = fd_info[fd].cp;
955 "EMACSLOADPATH", 1814
956 "SHELL", 1815 if ((fd_info[fd].flags & FILE_READ) == 0)
957 "EMACSDATA", 1816 {
958 "EMACSPATH", 1817 errno = EBADF;
959 "EMACSLOCKDIR", 1818 return -1;
960 "INFOPATH", 1819 }
961 "EMACSDOC", 1820
962 "TERM", 1821 /* presence of a child_process structure means we are operating in
963 }; 1822 non-blocking mode - otherwise we just call _read directly.
964 1823 Note that the child_process structure might be missing because
965 for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++) 1824 reap_subprocess has been called; in this case the pipe is
966 { 1825 already broken, so calling _read on it is okay. */
967 if (!getenv (env_vars[i]) && 1826 if (cp)
968 (lpval = nt_get_resource (env_vars[i], &dwType)) != NULL) 1827 {
1828 int current_status = cp->status;
1829
1830 switch (current_status)
969 { 1831 {
970 if (dwType == REG_EXPAND_SZ) 1832 case STATUS_READ_FAILED:
971 { 1833 case STATUS_READ_ERROR:
972 char buf1[500], buf2[500]; 1834 /* report normal EOF */
1835 return 0;
1836
1837 case STATUS_READ_READY:
1838 case STATUS_READ_IN_PROGRESS:
1839 DebPrint (("sys_read called when read is in progress\n"));
1840 errno = EWOULDBLOCK;
1841 return -1;
1842
1843 case STATUS_READ_SUCCEEDED:
1844 /* consume read-ahead char */
1845 *buffer++ = cp->chr;
1846 count--;
1847 extra = 1;
1848 cp->status = STATUS_READ_ACKNOWLEDGED;
1849 ResetEvent (cp->char_avail);
1850
1851 case STATUS_READ_ACKNOWLEDGED:
1852 break;
973 1853
974 ExpandEnvironmentStrings ((LPSTR) lpval, buf1, 500); 1854 default:
975 _snprintf (buf2, 499, "%s=%s", env_vars[i], buf1); 1855 DebPrint (("sys_read: bad status %d\n", current_status));
976 putenv (strdup (buf2)); 1856 errno = EBADF;
977 } 1857 return -1;
978 else if (dwType == REG_SZ) 1858 }
979 { 1859
980 char buf[500]; 1860 if (fd_info[fd].flags & FILE_PIPE)
981 1861 {
982 _snprintf (buf, 499, "%s=%s", env_vars[i], lpval); 1862 PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL);
983 putenv (strdup (buf)); 1863 to_read = min (waiting, (DWORD) count);
1864
1865 /* Use read to get CRLF translation */
1866 nchars = _read (fd, buffer, to_read);
1867 }
1868#ifdef HAVE_SOCKETS
1869 else /* FILE_SOCKET */
1870 {
1871 if (!have_winsock) abort ();
1872
1873 /* do the equivalent of a non-blocking read */
1874 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
1875 if (waiting == 0 && extra == 0)
1876 {
1877 h_errno = errno = EWOULDBLOCK;
1878 return -1;
984 } 1879 }
985 1880
986 xfree (lpval); 1881 nchars = 0;
1882 if (waiting)
1883 {
1884 /* always use binary mode for sockets */
1885 nchars = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0);
1886 if (nchars == SOCKET_ERROR)
1887 {
1888 DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
1889 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
1890 if (extra == 0)
1891 {
1892 set_errno ();
1893 return -1;
1894 }
1895 nchars = 0;
1896 }
1897 }
987 } 1898 }
1899#endif
988 } 1900 }
1901 else
1902 nchars = _read (fd, buffer, count);
989 } 1903 }
990} 1904 else
1905 nchars = _read (fd, buffer, count);
991 1906
992#ifdef HAVE_TIMEVAL 1907 return nchars + extra;
993#include <sys/timeb.h> 1908}
994 1909
995/* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */ 1910/* For now, don't bother with a non-blocking mode */
996void 1911int
997gettimeofday (struct timeval *tv, struct timezone *tz) 1912sys_write (int fd, const void * buffer, unsigned int count)
998{ 1913{
999 struct _timeb tb; 1914 int nchars;
1000 _ftime (&tb);
1001 1915
1002 tv->tv_sec = tb.time; 1916 if (fd < 0 || fd >= MAXDESC)
1003 tv->tv_usec = tb.millitm * 1000L;
1004 if (tz)
1005 { 1917 {
1006 tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */ 1918 errno = EBADF;
1007 tz->tz_dsttime = tb.dstflag; /* type of dst correction */ 1919 return -1;
1008 } 1920 }
1009}
1010#endif /* HAVE_TIMEVAL */
1011 1921
1012 1922 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
1013#ifdef PIGSFLY 1923 if ((fd_info[fd].flags & FILE_WRITE) == 0)
1014Keep this around...we might need it later. 1924 {
1015#ifdef WINDOWSNT 1925 errno = EBADF;
1016{ 1926 return -1;
1017 /* 1927 }
1018 * Find the user's real name by opening the process token and looking 1928#ifdef HAVE_SOCKETS
1019 * up the name associated with the user-sid in that token. 1929 if (fd_info[fd].flags & FILE_SOCKET)
1020 */
1021
1022 char b[256], Name[256], RefD[256];
1023 DWORD length = 256, rlength = 256, trash;
1024 HANDLE Token;
1025 SID_NAME_USE User;
1026
1027 if (1)
1028 Vuser_real_login_name = build_string ("foo");
1029 else if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &Token))
1030 {
1031 Vuser_real_login_name = build_string ("unknown");
1032 }
1033 else if (!GetTokenInformation (Token, TokenUser, (PVOID)b, 256,
1034 &trash))
1035 {
1036 CloseHandle (Token);
1037 Vuser_real_login_name = build_string ("unknown");
1038 }
1039 else if (!LookupAccountSid ((void *)0, (PSID)b, Name, &length, RefD,
1040 &rlength, &User))
1041 { 1930 {
1042 CloseHandle (Token); 1931 if (!have_winsock) abort ();
1043 Vuser_real_login_name = build_string ("unknown"); 1932 nchars = pfn_send (SOCK_HANDLE (fd), buffer, count, 0);
1933 if (nchars == SOCKET_ERROR)
1934 {
1935 DebPrint(("sys_read.send failed with error %d on socket %ld\n",
1936 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
1937 set_errno ();
1938 }
1044 } 1939 }
1045 else 1940 else
1046 Vuser_real_login_name = build_string (Name); 1941#endif
1942 nchars = _write (fd, buffer, count);
1943
1944 return nchars;
1047} 1945}
1048#else /* not WINDOWSNT */ 1946
1049#endif /* not WINDOWSNT */ 1947
1050#endif /* PIGSFLY */ 1948void
1949term_ntproc ()
1950{
1951#ifdef HAVE_SOCKETS
1952 /* shutdown the socket interface if necessary */
1953 term_winsock ();
1954#endif
1955}
1956
1957void
1958init_ntproc ()
1959{
1960#ifdef HAVE_SOCKETS
1961 /* initialise the socket interface if available */
1962 init_winsock ();
1963#endif
1964
1965 /* Initial preparation for subprocess support: replace our standard
1966 handles with non-inheritable versions. */
1967 {
1968 HANDLE parent;
1969 HANDLE stdin_save = INVALID_HANDLE_VALUE;
1970 HANDLE stdout_save = INVALID_HANDLE_VALUE;
1971 HANDLE stderr_save = INVALID_HANDLE_VALUE;
1972
1973 parent = GetCurrentProcess ();
1974
1975 /* ignore errors when duplicating and closing; typically the
1976 handles will be invalid when running as a gui program. */
1977 DuplicateHandle (parent,
1978 GetStdHandle (STD_INPUT_HANDLE),
1979 parent,
1980 &stdin_save,
1981 0,
1982 FALSE,
1983 DUPLICATE_SAME_ACCESS);
1984
1985 DuplicateHandle (parent,
1986 GetStdHandle (STD_OUTPUT_HANDLE),
1987 parent,
1988 &stdout_save,
1989 0,
1990 FALSE,
1991 DUPLICATE_SAME_ACCESS);
1992
1993 DuplicateHandle (parent,
1994 GetStdHandle (STD_ERROR_HANDLE),
1995 parent,
1996 &stderr_save,
1997 0,
1998 FALSE,
1999 DUPLICATE_SAME_ACCESS);
2000
2001 fclose (stdin);
2002 fclose (stdout);
2003 fclose (stderr);
2004
2005 if (stdin_save != INVALID_HANDLE_VALUE)
2006 _open_osfhandle ((long) stdin_save, O_TEXT);
2007 else
2008 open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY);
2009 fdopen (0, "r");
2010
2011 if (stdout_save != INVALID_HANDLE_VALUE)
2012 _open_osfhandle ((long) stdout_save, O_TEXT);
2013 else
2014 open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
2015 fdopen (1, "w");
2016
2017 if (stderr_save != INVALID_HANDLE_VALUE)
2018 _open_osfhandle ((long) stderr_save, O_TEXT);
2019 else
2020 open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
2021 fdopen (2, "w");
2022 }
2023
2024 /* unfortunately, atexit depends on implementation of malloc */
2025 /* atexit (term_ntproc); */
2026 signal (SIGABRT, term_ntproc);
2027}
2028
2029/* end of nt.c */