Change all uses of win95, winnt, and win32
[bpt/emacs.git] / src / w32.c
CommitLineData
95ed0025 1/* Utility and Unix shadow routines for GNU Emacs on Windows NT.
35f0d482 2 Copyright (C) 1994, 1995 Free Software Foundation, Inc.
95ed0025 3
3b7ad313
EN
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA.
95ed0025
RS
20
21 Geoff Voelker (voelker@cs.washington.edu) 7-29-94
22*/
23
00b3b7b3 24
95ed0025
RS
25#include <stdlib.h>
26#include <stdio.h>
27#include <io.h>
480b0c5b 28#include <errno.h>
95ed0025
RS
29#include <fcntl.h>
30#include <ctype.h>
480b0c5b
GV
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
95ed0025 56
95ed0025
RS
57#define getwd _getwd
58#include "lisp.h"
59#undef getwd
60
61#include <pwd.h>
62
480b0c5b 63#include <windows.h>
00b3b7b3 64
480b0c5b
GV
65#ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
66#include <sys/socket.h>
67#undef socket
68#undef bind
69#undef connect
70#undef htons
71#undef ntohs
72#undef inet_addr
73#undef gethostname
74#undef gethostbyname
75#undef getservbyname
76#endif
00b3b7b3 77
489f9371 78#include "w32.h"
480b0c5b 79#include "ndir.h"
489f9371 80#include "w32heap.h"
00b3b7b3 81
95ed0025 82/* Get the current working directory. */
480b0c5b 83char *
95ed0025
RS
84getwd (char *dir)
85{
480b0c5b
GV
86 if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
87 return dir;
88 return NULL;
95ed0025
RS
89}
90
480b0c5b 91#ifndef HAVE_SOCKETS
95ed0025
RS
92/* Emulate gethostname. */
93int
94gethostname (char *buffer, int size)
95{
96 /* NT only allows small host names, so the buffer is
97 certainly large enough. */
98 return !GetComputerName (buffer, &size);
99}
480b0c5b 100#endif /* HAVE_SOCKETS */
95ed0025
RS
101
102/* Emulate getloadavg. */
103int
104getloadavg (double loadavg[], int nelem)
105{
106 int i;
107
108 /* A faithful emulation is going to have to be saved for a rainy day. */
109 for (i = 0; i < nelem; i++)
110 {
111 loadavg[i] = 0.0;
112 }
113 return i;
114}
115
95ed0025
RS
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. */
119
120struct direct dir_static; /* simulated directory contents */
480b0c5b
GV
121static HANDLE dir_find_handle = INVALID_HANDLE_VALUE;
122static int dir_is_fat;
123static char dir_pathname[MAXPATHLEN+1];
95ed0025 124
fbd6baed 125extern Lisp_Object Vw32_downcase_file_names;
cbe39279 126
95ed0025
RS
127DIR *
128opendir (char *filename)
129{
130 DIR *dirp;
131
132 /* Opening is done by FindFirstFile. However, a read is inherent to
480b0c5b 133 this operation, so we defer the open until read time. */
95ed0025 134
480b0c5b
GV
135 if (!(dirp = (DIR *) malloc (sizeof (DIR))))
136 return NULL;
137 if (dir_find_handle != INVALID_HANDLE_VALUE)
138 return NULL;
95ed0025
RS
139
140 dirp->dd_fd = 0;
141 dirp->dd_loc = 0;
142 dirp->dd_size = 0;
143
480b0c5b
GV
144 strncpy (dir_pathname, filename, MAXPATHLEN);
145 dir_pathname[MAXPATHLEN] = '\0';
146 dir_is_fat = is_fat_volume (filename, NULL);
147
95ed0025
RS
148 return dirp;
149}
150
151void
152closedir (DIR *dirp)
153{
154 /* If we have a find-handle open, close it. */
480b0c5b 155 if (dir_find_handle != INVALID_HANDLE_VALUE)
95ed0025
RS
156 {
157 FindClose (dir_find_handle);
480b0c5b 158 dir_find_handle = INVALID_HANDLE_VALUE;
95ed0025
RS
159 }
160 xfree ((char *) dirp);
161}
162
163struct direct *
164readdir (DIR *dirp)
165{
166 WIN32_FIND_DATA find_data;
167
168 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
480b0c5b 169 if (dir_find_handle == INVALID_HANDLE_VALUE)
95ed0025
RS
170 {
171 char filename[MAXNAMLEN + 3];
172 int ln;
173
480b0c5b
GV
174 strcpy (filename, dir_pathname);
175 ln = strlen (filename) - 1;
176 if (!IS_DIRECTORY_SEP (filename[ln]))
95ed0025 177 strcat (filename, "\\");
480b0c5b 178 strcat (filename, "*");
95ed0025
RS
179
180 dir_find_handle = FindFirstFile (filename, &find_data);
181
480b0c5b 182 if (dir_find_handle == INVALID_HANDLE_VALUE)
95ed0025 183 return NULL;
480b0c5b
GV
184 }
185 else
95ed0025
RS
186 {
187 if (!FindNextFile (dir_find_handle, &find_data))
188 return NULL;
189 }
190
480b0c5b
GV
191 /* Emacs never uses this value, so don't bother making it match
192 value returned by stat(). */
95ed0025
RS
193 dir_static.d_ino = 1;
194
195 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 +
196 dir_static.d_namlen - dir_static.d_namlen % 4;
197
198 dir_static.d_namlen = strlen (find_data.cFileName);
480b0c5b
GV
199 strcpy (dir_static.d_name, find_data.cFileName);
200 if (dir_is_fat)
201 _strlwr (dir_static.d_name);
fbd6baed 202 else if (!NILP (Vw32_downcase_file_names))
cbe39279
RS
203 {
204 register char *p;
205 for (p = dir_static.d_name; *p; p++)
206 if (*p >= 'a' && *p <= 'z')
207 break;
208 if (!*p)
209 _strlwr (dir_static.d_name);
210 }
95ed0025
RS
211
212 return &dir_static;
213}
214
480b0c5b 215/* Emulate getpwuid, getpwnam and others. */
95ed0025 216
051fe60d
GV
217#define PASSWD_FIELD_SIZE 256
218
219static char the_passwd_name[PASSWD_FIELD_SIZE];
220static char the_passwd_passwd[PASSWD_FIELD_SIZE];
221static char the_passwd_gecos[PASSWD_FIELD_SIZE];
222static char the_passwd_dir[PASSWD_FIELD_SIZE];
223static char the_passwd_shell[PASSWD_FIELD_SIZE];
95ed0025
RS
224
225static struct passwd the_passwd =
226{
227 the_passwd_name,
228 the_passwd_passwd,
229 0,
230 0,
231 0,
232 the_passwd_gecos,
233 the_passwd_dir,
234 the_passwd_shell,
235};
236
480b0c5b
GV
237int
238getuid ()
239{
240 return the_passwd.pw_uid;
241}
242
243int
244geteuid ()
245{
246 /* I could imagine arguing for checking to see whether the user is
247 in the Administrators group and returning a UID of 0 for that
248 case, but I don't know how wise that would be in the long run. */
249 return getuid ();
250}
251
252int
253getgid ()
254{
255 return the_passwd.pw_gid;
256}
257
258int
259getegid ()
260{
261 return getgid ();
262}
263
95ed0025
RS
264struct passwd *
265getpwuid (int uid)
266{
480b0c5b
GV
267 if (uid == the_passwd.pw_uid)
268 return &the_passwd;
269 return NULL;
95ed0025
RS
270}
271
272struct passwd *
273getpwnam (char *name)
274{
275 struct passwd *pw;
276
277 pw = getpwuid (getuid ());
278 if (!pw)
279 return pw;
280
480b0c5b 281 if (stricmp (name, pw->pw_name))
95ed0025
RS
282 return NULL;
283
284 return pw;
285}
286
480b0c5b
GV
287void
288init_user_info ()
95ed0025 289{
480b0c5b
GV
290 /* Find the user's real name by opening the process token and
291 looking up the name associated with the user-sid in that token.
292
293 Use the relative portion of the identifier authority value from
294 the user-sid as the user id value (same for group id using the
295 primary group sid from the process token). */
296
297 char user_sid[256], name[256], domain[256];
298 DWORD length = sizeof (name), dlength = sizeof (domain), trash;
299 HANDLE token = NULL;
300 SID_NAME_USE user_type;
301
302 if (OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token)
303 && GetTokenInformation (token, TokenUser,
304 (PVOID) user_sid, sizeof (user_sid), &trash)
305 && LookupAccountSid (NULL, *((PSID *) user_sid), name, &length,
306 domain, &dlength, &user_type))
d1c1c3d2 307 {
480b0c5b
GV
308 strcpy (the_passwd.pw_name, name);
309 /* Determine a reasonable uid value. */
310 if (stricmp ("administrator", name) == 0)
311 {
312 the_passwd.pw_uid = 0;
313 the_passwd.pw_gid = 0;
314 }
315 else
316 {
317 SID_IDENTIFIER_AUTHORITY * pSIA;
318
319 pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid));
320 /* I believe the relative portion is the last 4 bytes (of 6)
321 with msb first. */
322 the_passwd.pw_uid = ((pSIA->Value[2] << 24) +
323 (pSIA->Value[3] << 16) +
324 (pSIA->Value[4] << 8) +
325 (pSIA->Value[5] << 0));
326 /* restrict to conventional uid range for normal users */
327 the_passwd.pw_uid = the_passwd.pw_uid % 60001;
328
329 /* Get group id */
330 if (GetTokenInformation (token, TokenPrimaryGroup,
331 (PVOID) user_sid, sizeof (user_sid), &trash))
332 {
333 SID_IDENTIFIER_AUTHORITY * pSIA;
334
335 pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid));
336 the_passwd.pw_gid = ((pSIA->Value[2] << 24) +
337 (pSIA->Value[3] << 16) +
338 (pSIA->Value[4] << 8) +
339 (pSIA->Value[5] << 0));
340 /* I don't know if this is necessary, but for safety... */
341 the_passwd.pw_gid = the_passwd.pw_gid % 60001;
342 }
343 else
344 the_passwd.pw_gid = the_passwd.pw_uid;
345 }
346 }
347 /* If security calls are not supported (presumably because we
348 are running under Windows 95), fallback to this. */
349 else if (GetUserName (name, &length))
350 {
351 strcpy (the_passwd.pw_name, name);
352 if (stricmp ("administrator", name) == 0)
353 the_passwd.pw_uid = 0;
354 else
355 the_passwd.pw_uid = 123;
356 the_passwd.pw_gid = the_passwd.pw_uid;
357 }
358 else
359 {
360 strcpy (the_passwd.pw_name, "unknown");
361 the_passwd.pw_uid = 123;
362 the_passwd.pw_gid = 123;
d1c1c3d2 363 }
95ed0025 364
480b0c5b
GV
365 /* Ensure HOME and SHELL are defined. */
366 if (getenv ("HOME") == NULL)
367 putenv ("HOME=c:/");
368 if (getenv ("SHELL") == NULL)
369 putenv ((GetVersion () & 0x80000000) ? "SHELL=command" : "SHELL=cmd");
95ed0025 370
480b0c5b
GV
371 /* Set dir and shell from environment variables. */
372 strcpy (the_passwd.pw_dir, getenv ("HOME"));
373 strcpy (the_passwd.pw_shell, getenv ("SHELL"));
bd4a449f 374
480b0c5b
GV
375 if (token)
376 CloseHandle (token);
95ed0025
RS
377}
378
95ed0025 379int
480b0c5b 380random ()
95ed0025 381{
480b0c5b
GV
382 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
383 return ((rand () << 15) | rand ());
95ed0025
RS
384}
385
95ed0025 386void
480b0c5b 387srandom (int seed)
95ed0025 388{
480b0c5b 389 srand (seed);
95ed0025
RS
390}
391
cbe39279
RS
392/* Normalize filename by converting all path separators to
393 the specified separator. Also conditionally convert upper
394 case path name components to lower case. */
395
396static void
397normalize_filename (fp, path_sep)
398 register char *fp;
399 char path_sep;
400{
401 char sep;
402 char *elem;
403
5162ffce
MB
404 /* Always lower-case drive letters a-z, even if the filesystem
405 preserves case in filenames.
406 This is so filenames can be compared by string comparison
407 functions that are case-sensitive. Even case-preserving filesystems
408 do not distinguish case in drive letters. */
409 if (fp[1] == ':' && *fp >= 'A' && *fp <= 'Z')
410 {
411 *fp += 'a' - 'A';
412 fp += 2;
413 }
414
fbd6baed 415 if (NILP (Vw32_downcase_file_names))
cbe39279
RS
416 {
417 while (*fp)
418 {
419 if (*fp == '/' || *fp == '\\')
420 *fp = path_sep;
421 fp++;
422 }
423 return;
424 }
425
426 sep = path_sep; /* convert to this path separator */
427 elem = fp; /* start of current path element */
428
429 do {
430 if (*fp >= 'a' && *fp <= 'z')
431 elem = 0; /* don't convert this element */
432
433 if (*fp == 0 || *fp == ':')
434 {
435 sep = *fp; /* restore current separator (or 0) */
436 *fp = '/'; /* after conversion of this element */
437 }
438
439 if (*fp == '/' || *fp == '\\')
440 {
441 if (elem && elem != fp)
442 {
443 *fp = 0; /* temporary end of string */
444 _strlwr (elem); /* while we convert to lower case */
445 }
446 *fp = sep; /* convert (or restore) path separator */
447 elem = fp + 1; /* next element starts after separator */
448 sep = path_sep;
449 }
450 } while (*fp++);
451}
452
480b0c5b 453/* Destructively turn backslashes into slashes. */
95ed0025 454void
480b0c5b
GV
455dostounix_filename (p)
456 register char *p;
95ed0025 457{
cbe39279 458 normalize_filename (p, '/');
95ed0025
RS
459}
460
480b0c5b 461/* Destructively turn slashes into backslashes. */
95ed0025 462void
480b0c5b
GV
463unixtodos_filename (p)
464 register char *p;
95ed0025 465{
cbe39279 466 normalize_filename (p, '\\');
95ed0025
RS
467}
468
480b0c5b
GV
469/* Remove all CR's that are followed by a LF.
470 (From msdos.c...probably should figure out a way to share it,
471 although this code isn't going to ever change.) */
35f0d482 472int
480b0c5b
GV
473crlf_to_lf (n, buf)
474 register int n;
475 register unsigned char *buf;
35f0d482 476{
480b0c5b
GV
477 unsigned char *np = buf;
478 unsigned char *startp = buf;
479 unsigned char *endp = buf + n;
35f0d482 480
480b0c5b
GV
481 if (n == 0)
482 return n;
483 while (buf < endp - 1)
95ed0025 484 {
480b0c5b
GV
485 if (*buf == 0x0d)
486 {
487 if (*(++buf) != 0x0a)
488 *np++ = 0x0d;
489 }
490 else
491 *np++ = *buf++;
95ed0025 492 }
480b0c5b
GV
493 if (buf < endp)
494 *np++ = *buf++;
495 return np - startp;
95ed0025
RS
496}
497
498/* Routines that are no-ops on NT but are defined to get Emacs to compile. */
499
95ed0025
RS
500int
501sigsetmask (int signal_mask)
502{
503 return 0;
504}
505
506int
507sigblock (int sig)
508{
509 return 0;
510}
511
95ed0025
RS
512int
513setpgrp (int pid, int gid)
514{
515 return 0;
516}
517
518int
519alarm (int seconds)
520{
521 return 0;
522}
523
524int
525unrequest_sigio (void)
526{
527 return 0;
528}
529
530int
531request_sigio (void)
532{
533 return 0;
534}
535
480b0c5b 536#define REG_ROOT "SOFTWARE\\GNU\\Emacs"
f332b293
GV
537
538LPBYTE
fbd6baed 539w32_get_resource (key, lpdwtype)
f332b293
GV
540 char *key;
541 LPDWORD lpdwtype;
542{
543 LPBYTE lpvalue;
544 HKEY hrootkey = NULL;
545 DWORD cbData;
546 BOOL ok = FALSE;
547
548 /* Check both the current user and the local machine to see if
549 we have any resources. */
550
551 if (RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
552 {
553 lpvalue = NULL;
554
555 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
556 && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL
557 && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
558 {
559 return (lpvalue);
560 }
561
562 if (lpvalue) xfree (lpvalue);
563
564 RegCloseKey (hrootkey);
565 }
566
567 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
568 {
569 lpvalue = NULL;
570
571 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS &&
572 (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL &&
573 RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
574 {
575 return (lpvalue);
576 }
577
578 if (lpvalue) xfree (lpvalue);
579
580 RegCloseKey (hrootkey);
581 }
582
583 return (NULL);
584}
585
586void
587init_environment ()
588{
f332b293
GV
589 /* Check for environment variables and use registry if they don't exist */
590 {
480b0c5b
GV
591 int i;
592 LPBYTE lpval;
593 DWORD dwType;
f332b293 594
480b0c5b
GV
595 static char * env_vars[] =
596 {
597 "HOME",
f249a012 598 "PRELOAD_WINSOCK",
480b0c5b
GV
599 "emacs_dir",
600 "EMACSLOADPATH",
601 "SHELL",
602 "EMACSDATA",
603 "EMACSPATH",
604 "EMACSLOCKDIR",
605 "INFOPATH",
606 "EMACSDOC",
607 "TERM",
608 };
609
610 for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++)
f332b293 611 {
480b0c5b 612 if (!getenv (env_vars[i]) &&
fbd6baed 613 (lpval = w32_get_resource (env_vars[i], &dwType)) != NULL)
480b0c5b
GV
614 {
615 if (dwType == REG_EXPAND_SZ)
616 {
617 char buf1[500], buf2[500];
618
619 ExpandEnvironmentStrings ((LPSTR) lpval, buf1, 500);
620 _snprintf (buf2, 499, "%s=%s", env_vars[i], buf1);
621 putenv (strdup (buf2));
622 }
623 else if (dwType == REG_SZ)
624 {
625 char buf[500];
f332b293 626
480b0c5b
GV
627 _snprintf (buf, 499, "%s=%s", env_vars[i], lpval);
628 putenv (strdup (buf));
629 }
f332b293 630
480b0c5b
GV
631 xfree (lpval);
632 }
633 }
634 }
635
636 init_user_info ();
637}
638
639/* We don't have scripts to automatically determine the system configuration
640 for Emacs before it's compiled, and we don't want to have to make the
641 user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
642 routine. */
643
644static char configuration_buffer[32];
645
646char *
647get_emacs_configuration (void)
648{
649 char *arch, *oem, *os;
650
651 /* Determine the processor type. */
652 switch (get_processor_type ())
653 {
654
655#ifdef PROCESSOR_INTEL_386
656 case PROCESSOR_INTEL_386:
657 case PROCESSOR_INTEL_486:
658 case PROCESSOR_INTEL_PENTIUM:
659 arch = "i386";
660 break;
661#endif
662
663#ifdef PROCESSOR_INTEL_860
664 case PROCESSOR_INTEL_860:
665 arch = "i860";
666 break;
667#endif
668
669#ifdef PROCESSOR_MIPS_R2000
670 case PROCESSOR_MIPS_R2000:
671 case PROCESSOR_MIPS_R3000:
672 case PROCESSOR_MIPS_R4000:
673 arch = "mips";
674 break;
675#endif
676
677#ifdef PROCESSOR_ALPHA_21064
678 case PROCESSOR_ALPHA_21064:
679 arch = "alpha";
680 break;
681#endif
682
683 default:
684 arch = "unknown";
685 break;
f332b293 686 }
480b0c5b
GV
687
688 /* Let oem be "*" until we figure out how to decode the OEM field. */
689 oem = "*";
690
1f8bd7fb 691 os = (GetVersion () & 0x80000000) ? "windows95" : "nt";
480b0c5b
GV
692
693 sprintf (configuration_buffer, "%s-%s-%s%d.%d", arch, oem, os,
fbd6baed 694 get_w32_major_version (), get_w32_minor_version ());
480b0c5b 695 return configuration_buffer;
f332b293
GV
696}
697
35f0d482
KH
698#include <sys/timeb.h>
699
700/* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
701void
702gettimeofday (struct timeval *tv, struct timezone *tz)
703{
704 struct _timeb tb;
705 _ftime (&tb);
706
707 tv->tv_sec = tb.time;
708 tv->tv_usec = tb.millitm * 1000L;
709 if (tz)
710 {
711 tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */
712 tz->tz_dsttime = tb.dstflag; /* type of dst correction */
713 }
714}
35f0d482 715
480b0c5b 716/* ------------------------------------------------------------------------- */
fbd6baed 717/* IO support and wrapper functions for W32 API. */
480b0c5b 718/* ------------------------------------------------------------------------- */
95ed0025 719
480b0c5b
GV
720/* Place a wrapper around the MSVC version of ctime. It returns NULL
721 on network directories, so we handle that case here.
722 (Ulrich Leodolter, 1/11/95). */
723char *
724sys_ctime (const time_t *t)
725{
726 char *str = (char *) ctime (t);
727 return (str ? str : "Sun Jan 01 00:00:00 1970");
728}
729
730/* Emulate sleep...we could have done this with a define, but that
731 would necessitate including windows.h in the files that used it.
732 This is much easier. */
733void
734sys_sleep (int seconds)
735{
736 Sleep (seconds * 1000);
737}
738
739/* Internal MSVC data and functions for low-level descriptor munging */
740#if (_MSC_VER == 900)
741extern char _osfile[];
742#endif
743extern int __cdecl _set_osfhnd (int fd, long h);
744extern int __cdecl _free_osfhnd (int fd);
745
746/* parallel array of private info on file handles */
747filedesc fd_info [ MAXDESC ];
748
749static struct {
750 DWORD serialnum;
751 DWORD maxcomp;
752 DWORD flags;
753 char name[32];
754 char type[32];
755} volume_info;
756
757/* Get information on the volume where name is held; set path pointer to
758 start of pathname in name (past UNC header\volume header if present). */
759int
760get_volume_info (const char * name, const char ** pPath)
95ed0025 761{
480b0c5b
GV
762 char temp[MAX_PATH];
763 char *rootname = NULL; /* default to current volume */
764
765 if (name == NULL)
766 return FALSE;
767
768 /* find the root name of the volume if given */
769 if (isalpha (name[0]) && name[1] == ':')
770 {
771 rootname = temp;
772 temp[0] = *name++;
773 temp[1] = *name++;
774 temp[2] = '\\';
775 temp[3] = 0;
776 }
777 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
95ed0025 778 {
480b0c5b
GV
779 char *str = temp;
780 int slashes = 4;
781 rootname = temp;
782 do
783 {
784 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
785 break;
786 *str++ = *name++;
787 }
788 while ( *name );
789
480b0c5b
GV
790 *str++ = '\\';
791 *str = 0;
95ed0025 792 }
480b0c5b
GV
793
794 if (pPath)
795 *pPath = name;
796
797 if (GetVolumeInformation (rootname,
798 volume_info.name, 32,
799 &volume_info.serialnum,
800 &volume_info.maxcomp,
801 &volume_info.flags,
802 volume_info.type, 32))
95ed0025 803 {
480b0c5b 804 return TRUE;
95ed0025 805 }
480b0c5b
GV
806 return FALSE;
807}
808
809/* Determine if volume is FAT format (ie. only supports short 8.3
810 names); also set path pointer to start of pathname in name. */
811int
812is_fat_volume (const char * name, const char ** pPath)
813{
814 if (get_volume_info (name, pPath))
815 return (volume_info.maxcomp == 12);
816 return FALSE;
817}
818
819/* Map filename to a legal 8.3 name if necessary. */
820const char *
fbd6baed 821map_w32_filename (const char * name, const char ** pPath)
480b0c5b
GV
822{
823 static char shortname[MAX_PATH];
824 char * str = shortname;
825 char c;
480b0c5b
GV
826 char * path;
827
828 if (is_fat_volume (name, &path)) /* truncate to 8.3 */
95ed0025 829 {
480b0c5b
GV
830 register int left = 8; /* maximum number of chars in part */
831 register int extn = 0; /* extension added? */
832 register int dots = 2; /* maximum number of dots allowed */
833
834 while (name < path)
835 *str++ = *name++; /* skip past UNC header */
836
837 while ((c = *name++))
838 {
839 switch ( c )
840 {
841 case '\\':
842 case '/':
843 *str++ = '\\';
844 extn = 0; /* reset extension flags */
845 dots = 2; /* max 2 dots */
846 left = 8; /* max length 8 for main part */
847 break;
848 case ':':
849 *str++ = ':';
850 extn = 0; /* reset extension flags */
851 dots = 2; /* max 2 dots */
852 left = 8; /* max length 8 for main part */
853 break;
854 case '.':
855 if ( dots )
856 {
857 /* Convert path components of the form .xxx to _xxx,
858 but leave . and .. as they are. This allows .emacs
859 to be read as _emacs, for example. */
860
861 if (! *name ||
862 *name == '.' ||
863 IS_DIRECTORY_SEP (*name))
864 {
865 *str++ = '.';
866 dots--;
867 }
868 else
869 {
870 *str++ = '_';
871 left--;
872 dots = 0;
873 }
874 }
875 else if ( !extn )
876 {
877 *str++ = '.';
878 extn = 1; /* we've got an extension */
879 left = 3; /* 3 chars in extension */
880 }
881 else
882 {
883 /* any embedded dots after the first are converted to _ */
884 *str++ = '_';
885 }
886 break;
887 case '~':
888 case '#': /* don't lose these, they're important */
889 if ( ! left )
890 str[-1] = c; /* replace last character of part */
891 /* FALLTHRU */
892 default:
893 if ( left )
894 {
895 *str++ = tolower (c); /* map to lower case (looks nicer) */
896 left--;
897 dots = 0; /* started a path component */
898 }
899 break;
900 }
901 }
902 *str = '\0';
fc85cb29
RS
903 }
904 else
905 {
906 strcpy (shortname, name);
907 unixtodos_filename (shortname);
95ed0025 908 }
480b0c5b
GV
909
910 if (pPath)
fc85cb29 911 *pPath = shortname + (path - name);
480b0c5b 912
fc85cb29 913 return shortname;
480b0c5b
GV
914}
915
916
917/* Shadow some MSVC runtime functions to map requests for long filenames
918 to reasonable short names if necessary. This was originally added to
919 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
920 long file names. */
921
922int
923sys_access (const char * path, int mode)
924{
fbd6baed 925 return _access (map_w32_filename (path, NULL), mode);
480b0c5b
GV
926}
927
928int
929sys_chdir (const char * path)
930{
fbd6baed 931 return _chdir (map_w32_filename (path, NULL));
480b0c5b
GV
932}
933
934int
935sys_chmod (const char * path, int mode)
936{
fbd6baed 937 return _chmod (map_w32_filename (path, NULL), mode);
480b0c5b
GV
938}
939
940int
941sys_creat (const char * path, int mode)
942{
fbd6baed 943 return _creat (map_w32_filename (path, NULL), mode);
480b0c5b
GV
944}
945
946FILE *
947sys_fopen(const char * path, const char * mode)
948{
949 int fd;
950 int oflag;
951 const char * mode_save = mode;
952
953 /* Force all file handles to be non-inheritable. This is necessary to
954 ensure child processes don't unwittingly inherit handles that might
955 prevent future file access. */
956
957 if (mode[0] == 'r')
958 oflag = O_RDONLY;
959 else if (mode[0] == 'w' || mode[0] == 'a')
960 oflag = O_WRONLY | O_CREAT | O_TRUNC;
95ed0025 961 else
480b0c5b
GV
962 return NULL;
963
964 /* Only do simplistic option parsing. */
965 while (*++mode)
966 if (mode[0] == '+')
967 {
968 oflag &= ~(O_RDONLY | O_WRONLY);
969 oflag |= O_RDWR;
970 }
971 else if (mode[0] == 'b')
972 {
973 oflag &= ~O_TEXT;
974 oflag |= O_BINARY;
975 }
976 else if (mode[0] == 't')
977 {
978 oflag &= ~O_BINARY;
979 oflag |= O_TEXT;
980 }
981 else break;
982
fbd6baed 983 fd = _open (map_w32_filename (path, NULL), oflag | _O_NOINHERIT, 0644);
480b0c5b
GV
984 if (fd < 0)
985 return NULL;
986
987 return fdopen (fd, mode_save);
95ed0025 988}
480b0c5b
GV
989
990int
991sys_link (const char * path1, const char * path2)
992{
993 errno = EINVAL;
994 return -1;
995}
996
997int
998sys_mkdir (const char * path)
999{
fbd6baed 1000 return _mkdir (map_w32_filename (path, NULL));
480b0c5b
GV
1001}
1002
9d1778b1
RS
1003/* Because of long name mapping issues, we need to implement this
1004 ourselves. Also, MSVC's _mktemp returns NULL when it can't generate
1005 a unique name, instead of setting the input template to an empty
1006 string.
1007
1008 Standard algorithm seems to be use pid or tid with a letter on the
1009 front (in place of the 6 X's) and cycle through the letters to find a
1010 unique name. We extend that to allow any reasonable character as the
1011 first of the 6 X's. */
480b0c5b
GV
1012char *
1013sys_mktemp (char * template)
1014{
9d1778b1
RS
1015 char * p;
1016 int i;
1017 unsigned uid = GetCurrentThreadId ();
1018 static char first_char[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
1019
1020 if (template == NULL)
1021 return NULL;
1022 p = template + strlen (template);
1023 i = 5;
1024 /* replace up to the last 5 X's with uid in decimal */
1025 while (--p >= template && p[0] == 'X' && --i >= 0)
1026 {
1027 p[0] = '0' + uid % 10;
1028 uid /= 10;
1029 }
1030
1031 if (i < 0 && p[0] == 'X')
1032 {
1033 i = 0;
1034 do
1035 {
1036 int save_errno = errno;
1037 p[0] = first_char[i];
1038 if (sys_access (template, 0) < 0)
1039 {
1040 errno = save_errno;
1041 return template;
1042 }
1043 }
1044 while (++i < sizeof (first_char));
1045 }
1046
1047 /* Template is badly formed or else we can't generate a unique name,
1048 so return empty string */
1049 template[0] = 0;
1050 return template;
480b0c5b
GV
1051}
1052
1053int
1054sys_open (const char * path, int oflag, int mode)
1055{
1056 /* Force all file handles to be non-inheritable. */
fbd6baed 1057 return _open (map_w32_filename (path, NULL), oflag | _O_NOINHERIT, mode);
480b0c5b
GV
1058}
1059
1060int
1061sys_rename (const char * oldname, const char * newname)
1062{
1063 char temp[MAX_PATH];
5162ffce 1064 DWORD attr;
480b0c5b
GV
1065
1066 /* MoveFile on Win95 doesn't correctly change the short file name
5162ffce
MB
1067 alias in a number of circumstances (it is not easy to predict when
1068 just by looking at oldname and newname, unfortunately). In these
1069 cases, renaming through a temporary name avoids the problem.
1070
1071 A second problem on Win95 is that renaming through a temp name when
1072 newname is uppercase fails (the final long name ends up in
1073 lowercase, although the short alias might be uppercase) UNLESS the
1074 long temp name is not 8.3.
1075
1076 So, on Win95 we always rename through a temp name, and we make sure
1077 the temp name has a long extension to ensure correct renaming. */
480b0c5b 1078
fbd6baed 1079 strcpy (temp, map_w32_filename (oldname, NULL));
480b0c5b
GV
1080
1081 if (GetVersion () & 0x80000000)
1082 {
1083 char * p;
1084
480b0c5b
GV
1085 if (p = strrchr (temp, '\\'))
1086 p++;
1087 else
1088 p = temp;
1089 strcpy (p, "__XXXXXX");
5162ffce
MB
1090 sys_mktemp (temp);
1091 /* Force temp name to require a manufactured 8.3 alias - this
1092 seems to make the second rename work properly. */
1093 strcat (temp, ".long");
fbd6baed 1094 if (rename (map_w32_filename (oldname, NULL), temp) < 0)
480b0c5b
GV
1095 return -1;
1096 }
1097
1098 /* Emulate Unix behaviour - newname is deleted if it already exists
5162ffce
MB
1099 (at least if it is a file; don't do this for directories).
1100 However, don't do this if we are just changing the case of the file
1101 name - we will end up deleting the file we are trying to rename! */
fbd6baed 1102 newname = map_w32_filename (newname, NULL);
5162ffce
MB
1103 if (stricmp (newname, temp) != 0
1104 && (attr = GetFileAttributes (newname)) != -1
1105 && (attr & FILE_ATTRIBUTE_DIRECTORY) == 0)
480b0c5b
GV
1106 {
1107 _chmod (newname, 0666);
1108 _unlink (newname);
1109 }
1110
1111 return rename (temp, newname);
1112}
1113
1114int
1115sys_rmdir (const char * path)
1116{
fbd6baed 1117 return _rmdir (map_w32_filename (path, NULL));
480b0c5b
GV
1118}
1119
1120int
1121sys_unlink (const char * path)
1122{
fbd6baed 1123 return _unlink (map_w32_filename (path, NULL));
480b0c5b
GV
1124}
1125
1126static FILETIME utc_base_ft;
1127static long double utc_base;
1128static int init = 0;
1129
1130static time_t
1131convert_time (FILETIME ft)
1132{
1133 long double ret;
1134
1135 if (!init)
1136 {
1137 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
1138 SYSTEMTIME st;
1139
1140 st.wYear = 1970;
1141 st.wMonth = 1;
1142 st.wDay = 1;
1143 st.wHour = 0;
1144 st.wMinute = 0;
1145 st.wSecond = 0;
1146 st.wMilliseconds = 0;
1147
1148 SystemTimeToFileTime (&st, &utc_base_ft);
1149 utc_base = (long double) utc_base_ft.dwHighDateTime
1150 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
1151 init = 1;
1152 }
1153
1154 if (CompareFileTime (&ft, &utc_base_ft) < 0)
1155 return 0;
1156
1157 ret = (long double) ft.dwHighDateTime * 4096 * 1024 * 1024 + ft.dwLowDateTime;
1158 ret -= utc_base;
1159 return (time_t) (ret * 1e-7);
1160}
1161
1162#if 0
1163/* in case we ever have need of this */
1164void
1165convert_from_time_t (time_t time, FILETIME * pft)
1166{
1167 long double tmp;
1168
1169 if (!init)
1170 {
1171 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
1172 SYSTEMTIME st;
1173
1174 st.wYear = 1970;
1175 st.wMonth = 1;
1176 st.wDay = 1;
1177 st.wHour = 0;
1178 st.wMinute = 0;
1179 st.wSecond = 0;
1180 st.wMilliseconds = 0;
1181
1182 SystemTimeToFileTime (&st, &utc_base_ft);
1183 utc_base = (long double) utc_base_ft.dwHighDateTime
1184 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
1185 init = 1;
1186 }
1187
1188 /* time in 100ns units since 1-Jan-1601 */
1189 tmp = (long double) time * 1e7 + utc_base;
1190 pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024));
1191 pft->dwLowDateTime = (DWORD) (tmp - pft->dwHighDateTime);
1192}
1193#endif
1194
1195/* "PJW" algorithm (see the "Dragon" compiler book). */
1196static unsigned
1197hashval (const char * str)
1198{
1199 unsigned h = 0;
1200 unsigned g;
1201 while (*str)
1202 {
1203 h = (h << 4) + *str++;
1204 if ((g = h & 0xf0000000) != 0)
1205 h = (h ^ (g >> 24)) & 0x0fffffff;
1206 }
1207 return h;
1208}
1209
1210/* Return the hash value of the canonical pathname, excluding the
1211 drive/UNC header, to get a hopefully unique inode number. */
1212static _ino_t
1213generate_inode_val (const char * name)
1214{
1215 char fullname[ MAX_PATH ];
1216 char * p;
1217 unsigned hash;
1218
1219 GetFullPathName (name, sizeof (fullname), fullname, &p);
1220 get_volume_info (fullname, &p);
fbd6baed 1221 /* Normal W32 filesystems are still case insensitive. */
480b0c5b
GV
1222 _strlwr (p);
1223 hash = hashval (p);
1224 return (_ino_t) (hash ^ (hash >> 16));
1225}
1226
1227/* MSVC stat function can't cope with UNC names and has other bugs, so
1228 replace it with our own. This also allows us to calculate consistent
1229 inode values without hacks in the main Emacs code. */
1230int
1231stat (const char * path, struct stat * buf)
1232{
1233 char * name;
1234 WIN32_FIND_DATA wfd;
1235 HANDLE fh;
1236 int permission;
1237 int len;
1238 int rootdir = FALSE;
1239
1240 if (path == NULL || buf == NULL)
1241 {
1242 errno = EFAULT;
1243 return -1;
1244 }
1245
fbd6baed 1246 name = (char *) map_w32_filename (path, &path);
480b0c5b
GV
1247 /* must be valid filename, no wild cards */
1248 if (strchr (name, '*') || strchr (name, '?'))
1249 {
1250 errno = ENOENT;
1251 return -1;
1252 }
1253
1254 /* Remove trailing directory separator, unless name is the root
1255 directory of a drive or UNC volume in which case ensure there
1256 is a trailing separator. */
1257 len = strlen (name);
1258 rootdir = (path >= name + len - 1
1259 && (IS_DIRECTORY_SEP (*path) || *path == 0));
1260 name = strcpy (alloca (len + 2), name);
1261
1262 if (rootdir)
1263 {
1264 if (!IS_DIRECTORY_SEP (name[len-1]))
1265 strcat (name, "\\");
1266 if (GetDriveType (name) < 2)
1267 {
1268 errno = ENOENT;
1269 return -1;
1270 }
1271 memset (&wfd, 0, sizeof (wfd));
1272 wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
1273 wfd.ftCreationTime = utc_base_ft;
1274 wfd.ftLastAccessTime = utc_base_ft;
1275 wfd.ftLastWriteTime = utc_base_ft;
1276 strcpy (wfd.cFileName, name);
1277 }
1278 else
1279 {
1280 if (IS_DIRECTORY_SEP (name[len-1]))
1281 name[len - 1] = 0;
1282 fh = FindFirstFile (name, &wfd);
1283 if (fh == INVALID_HANDLE_VALUE)
1284 {
1285 errno = ENOENT;
1286 return -1;
1287 }
1288 FindClose (fh);
1289 }
1290
1291 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1292 {
1293 buf->st_mode = _S_IFDIR;
1294 buf->st_nlink = 2; /* doesn't really matter */
1295 }
1296 else
1297 {
1298#if 0
1299 /* This is more accurate in terms of gettting the correct number
1300 of links, but is quite slow (it is noticable when Emacs is
1301 making a list of file name completions). */
1302 BY_HANDLE_FILE_INFORMATION info;
1303
1304 fh = CreateFile (name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
1305 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1306
1307 if (GetFileInformationByHandle (fh, &info))
1308 {
1309 switch (GetFileType (fh))
1310 {
1311 case FILE_TYPE_DISK:
1312 buf->st_mode = _S_IFREG;
1313 break;
1314 case FILE_TYPE_PIPE:
1315 buf->st_mode = _S_IFIFO;
1316 break;
1317 case FILE_TYPE_CHAR:
1318 case FILE_TYPE_UNKNOWN:
1319 default:
1320 buf->st_mode = _S_IFCHR;
1321 }
1322 buf->st_nlink = info.nNumberOfLinks;
1323 /* Could use file index, but this is not guaranteed to be
1324 unique unless we keep a handle open all the time. */
1325 /* buf->st_ino = info.nFileIndexLow ^ info.nFileIndexHigh; */
1326 CloseHandle (fh);
1327 }
1328 else
1329 {
1330 errno = EACCES;
1331 return -1;
1332 }
1333#else
1334 buf->st_mode = _S_IFREG;
1335 buf->st_nlink = 1;
1336#endif
1337 }
1338
1339 /* consider files to belong to current user */
1340 buf->st_uid = the_passwd.pw_uid;
1341 buf->st_gid = the_passwd.pw_gid;
1342
fbd6baed 1343 /* volume_info is set indirectly by map_w32_filename */
480b0c5b
GV
1344 buf->st_dev = volume_info.serialnum;
1345 buf->st_rdev = volume_info.serialnum;
1346
1347 buf->st_ino = generate_inode_val (name);
1348
1349 buf->st_size = wfd.nFileSizeLow;
1350
1351 /* Convert timestamps to Unix format. */
1352 buf->st_mtime = convert_time (wfd.ftLastWriteTime);
1353 buf->st_atime = convert_time (wfd.ftLastAccessTime);
1354 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
1355 buf->st_ctime = convert_time (wfd.ftCreationTime);
1356 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
1357
1358 /* determine rwx permissions */
1359 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
1360 permission = _S_IREAD;
1361 else
1362 permission = _S_IREAD | _S_IWRITE;
1363
1364 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1365 permission |= _S_IEXEC;
1366 else
1367 {
1368 char * p = strrchr (name, '.');
1369 if (p != NULL &&
1370 (stricmp (p, ".exe") == 0 ||
1371 stricmp (p, ".com") == 0 ||
1372 stricmp (p, ".bat") == 0 ||
1373 stricmp (p, ".cmd") == 0))
1374 permission |= _S_IEXEC;
1375 }
1376
1377 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
1378
1379 return 0;
1380}
1381
1382#ifdef HAVE_SOCKETS
1383
1384/* Wrappers for winsock functions to map between our file descriptors
1385 and winsock's handles; also set h_errno for convenience.
1386
1387 To allow Emacs to run on systems which don't have winsock support
1388 installed, we dynamically link to winsock on startup if present, and
1389 otherwise provide the minimum necessary functionality
1390 (eg. gethostname). */
1391
1392/* function pointers for relevant socket functions */
1393int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
1394void (PASCAL *pfn_WSASetLastError) (int iError);
1395int (PASCAL *pfn_WSAGetLastError) (void);
1396int (PASCAL *pfn_socket) (int af, int type, int protocol);
1397int (PASCAL *pfn_bind) (SOCKET s, const struct sockaddr *addr, int namelen);
1398int (PASCAL *pfn_connect) (SOCKET s, const struct sockaddr *addr, int namelen);
1399int (PASCAL *pfn_ioctlsocket) (SOCKET s, long cmd, u_long *argp);
1400int (PASCAL *pfn_recv) (SOCKET s, char * buf, int len, int flags);
1401int (PASCAL *pfn_send) (SOCKET s, const char * buf, int len, int flags);
1402int (PASCAL *pfn_closesocket) (SOCKET s);
1403int (PASCAL *pfn_shutdown) (SOCKET s, int how);
1404int (PASCAL *pfn_WSACleanup) (void);
1405
1406u_short (PASCAL *pfn_htons) (u_short hostshort);
1407u_short (PASCAL *pfn_ntohs) (u_short netshort);
1408unsigned long (PASCAL *pfn_inet_addr) (const char * cp);
1409int (PASCAL *pfn_gethostname) (char * name, int namelen);
1410struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
1411struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto);
f1614061
RS
1412
1413/* SetHandleInformation is only needed to make sockets non-inheritable. */
1414BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags);
1415#ifndef HANDLE_FLAG_INHERIT
1416#define HANDLE_FLAG_INHERIT 1
1417#endif
480b0c5b 1418
f249a012
RS
1419HANDLE winsock_lib;
1420static int winsock_inuse;
480b0c5b 1421
f249a012 1422BOOL
480b0c5b
GV
1423term_winsock (void)
1424{
f249a012 1425 if (winsock_lib != NULL && winsock_inuse == 0)
480b0c5b 1426 {
f249a012
RS
1427 /* Not sure what would cause WSAENETDOWN, or even if it can happen
1428 after WSAStartup returns successfully, but it seems reasonable
1429 to allow unloading winsock anyway in that case. */
1430 if (pfn_WSACleanup () == 0 ||
1431 pfn_WSAGetLastError () == WSAENETDOWN)
1432 {
1433 if (FreeLibrary (winsock_lib))
1434 winsock_lib = NULL;
1435 return TRUE;
1436 }
480b0c5b 1437 }
f249a012 1438 return FALSE;
480b0c5b
GV
1439}
1440
f249a012
RS
1441BOOL
1442init_winsock (int load_now)
480b0c5b
GV
1443{
1444 WSADATA winsockData;
1445
f249a012
RS
1446 if (winsock_lib != NULL)
1447 return TRUE;
f1614061
RS
1448
1449 pfn_SetHandleInformation = NULL;
1450 pfn_SetHandleInformation
1451 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
1452 "SetHandleInformation");
1453
480b0c5b
GV
1454 winsock_lib = LoadLibrary ("wsock32.dll");
1455
1456 if (winsock_lib != NULL)
1457 {
1458 /* dynamically link to socket functions */
1459
1460#define LOAD_PROC(fn) \
1461 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
1462 goto fail;
1463
1464 LOAD_PROC( WSAStartup );
1465 LOAD_PROC( WSASetLastError );
1466 LOAD_PROC( WSAGetLastError );
1467 LOAD_PROC( socket );
1468 LOAD_PROC( bind );
1469 LOAD_PROC( connect );
1470 LOAD_PROC( ioctlsocket );
1471 LOAD_PROC( recv );
1472 LOAD_PROC( send );
1473 LOAD_PROC( closesocket );
1474 LOAD_PROC( shutdown );
1475 LOAD_PROC( htons );
1476 LOAD_PROC( ntohs );
1477 LOAD_PROC( inet_addr );
1478 LOAD_PROC( gethostname );
1479 LOAD_PROC( gethostbyname );
1480 LOAD_PROC( getservbyname );
1481 LOAD_PROC( WSACleanup );
1482
f249a012
RS
1483#undef LOAD_PROC
1484
480b0c5b
GV
1485 /* specify version 1.1 of winsock */
1486 if (pfn_WSAStartup (0x101, &winsockData) == 0)
1487 {
f249a012
RS
1488 if (winsockData.wVersion != 0x101)
1489 goto fail;
1490
1491 if (!load_now)
1492 {
1493 /* Report that winsock exists and is usable, but leave
1494 socket functions disabled. I am assuming that calling
1495 WSAStartup does not require any network interaction,
1496 and in particular does not cause or require a dial-up
1497 connection to be established. */
1498
1499 pfn_WSACleanup ();
1500 FreeLibrary (winsock_lib);
1501 winsock_lib = NULL;
1502 }
1503 winsock_inuse = 0;
1504 return TRUE;
480b0c5b
GV
1505 }
1506
1507 fail:
1508 FreeLibrary (winsock_lib);
f249a012 1509 winsock_lib = NULL;
480b0c5b 1510 }
f249a012
RS
1511
1512 return FALSE;
480b0c5b
GV
1513}
1514
1515
1516int h_errno = 0;
1517
1518/* function to set h_errno for compatability; map winsock error codes to
1519 normal system codes where they overlap (non-overlapping definitions
1520 are already in <sys/socket.h> */
1521static void set_errno ()
1522{
f249a012 1523 if (winsock_lib == NULL)
480b0c5b
GV
1524 h_errno = EINVAL;
1525 else
1526 h_errno = pfn_WSAGetLastError ();
1527
1528 switch (h_errno)
1529 {
1530 case WSAEACCES: h_errno = EACCES; break;
1531 case WSAEBADF: h_errno = EBADF; break;
1532 case WSAEFAULT: h_errno = EFAULT; break;
1533 case WSAEINTR: h_errno = EINTR; break;
1534 case WSAEINVAL: h_errno = EINVAL; break;
1535 case WSAEMFILE: h_errno = EMFILE; break;
1536 case WSAENAMETOOLONG: h_errno = ENAMETOOLONG; break;
1537 case WSAENOTEMPTY: h_errno = ENOTEMPTY; break;
1538 }
1539 errno = h_errno;
1540}
1541
1542static void check_errno ()
1543{
f249a012 1544 if (h_errno == 0 && winsock_lib != NULL)
480b0c5b
GV
1545 pfn_WSASetLastError (0);
1546}
1547
1548/* [andrewi 3-May-96] I've had conflicting results using both methods,
1549 but I believe the method of keeping the socket handle separate (and
1550 insuring it is not inheritable) is the correct one. */
1551
1552//#define SOCK_REPLACE_HANDLE
1553
1554#ifdef SOCK_REPLACE_HANDLE
1555#define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
1556#else
1557#define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
1558#endif
1559
1560int
1561sys_socket(int af, int type, int protocol)
1562{
1563 int fd;
1564 long s;
1565 child_process * cp;
1566
f249a012 1567 if (winsock_lib == NULL)
480b0c5b
GV
1568 {
1569 h_errno = ENETDOWN;
1570 return INVALID_SOCKET;
1571 }
1572
1573 check_errno ();
1574
1575 /* call the real socket function */
1576 s = (long) pfn_socket (af, type, protocol);
1577
1578 if (s != INVALID_SOCKET)
1579 {
1580 /* Although under NT 3.5 _open_osfhandle will accept a socket
1581 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
1582 that does not work under NT 3.1. However, we can get the same
1583 effect by using a backdoor function to replace an existing
1584 descriptor handle with the one we want. */
1585
1586 /* allocate a file descriptor (with appropriate flags) */
1587 fd = _open ("NUL:", _O_RDWR);
1588 if (fd >= 0)
1589 {
1590#ifdef SOCK_REPLACE_HANDLE
1591 /* now replace handle to NUL with our socket handle */
1592 CloseHandle ((HANDLE) _get_osfhandle (fd));
1593 _free_osfhnd (fd);
1594 _set_osfhnd (fd, s);
1595 /* setmode (fd, _O_BINARY); */
1596#else
1597 /* Make a non-inheritable copy of the socket handle. */
1598 {
1599 HANDLE parent;
1600 HANDLE new_s = INVALID_HANDLE_VALUE;
1601
1602 parent = GetCurrentProcess ();
1603
f1614061
RS
1604 /* Apparently there is a bug in NT 3.51 with some service
1605 packs, which prevents using DuplicateHandle to make a
1606 socket handle non-inheritable (causes WSACleanup to
1607 hang). The work-around is to use SetHandleInformation
1608 instead if it is available and implemented. */
1609 if (!pfn_SetHandleInformation
1610 || !pfn_SetHandleInformation ((HANDLE) s,
1611 HANDLE_FLAG_INHERIT,
1612 HANDLE_FLAG_INHERIT))
1613 {
1614 DuplicateHandle (parent,
1615 (HANDLE) s,
1616 parent,
1617 &new_s,
1618 0,
1619 FALSE,
1620 DUPLICATE_SAME_ACCESS);
1621 pfn_closesocket (s);
1622 s = (SOCKET) new_s;
1623 }
1624 fd_info[fd].hnd = (HANDLE) s;
480b0c5b
GV
1625 }
1626#endif
1627
1628 /* set our own internal flags */
1629 fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
1630
1631 cp = new_child ();
1632 if (cp)
1633 {
1634 cp->fd = fd;
1635 cp->status = STATUS_READ_ACKNOWLEDGED;
1636
1637 /* attach child_process to fd_info */
1638 if (fd_info[ fd ].cp != NULL)
1639 {
1640 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
1641 abort ();
1642 }
1643
1644 fd_info[ fd ].cp = cp;
1645
1646 /* success! */
f249a012 1647 winsock_inuse++; /* count open sockets */
480b0c5b
GV
1648 return fd;
1649 }
1650
1651 /* clean up */
1652 _close (fd);
1653 }
1654 pfn_closesocket (s);
1655 h_errno = EMFILE;
1656 }
1657 set_errno ();
1658
1659 return -1;
1660}
1661
1662
1663int
1664sys_bind (int s, const struct sockaddr * addr, int namelen)
1665{
f249a012 1666 if (winsock_lib == NULL)
480b0c5b
GV
1667 {
1668 h_errno = ENOTSOCK;
1669 return SOCKET_ERROR;
1670 }
1671
1672 check_errno ();
1673 if (fd_info[s].flags & FILE_SOCKET)
1674 {
1675 int rc = pfn_bind (SOCK_HANDLE (s), addr, namelen);
1676 if (rc == SOCKET_ERROR)
1677 set_errno ();
1678 return rc;
1679 }
1680 h_errno = ENOTSOCK;
1681 return SOCKET_ERROR;
1682}
1683
1684
1685int
1686sys_connect (int s, const struct sockaddr * name, int namelen)
1687{
f249a012 1688 if (winsock_lib == NULL)
480b0c5b
GV
1689 {
1690 h_errno = ENOTSOCK;
1691 return SOCKET_ERROR;
1692 }
1693
1694 check_errno ();
1695 if (fd_info[s].flags & FILE_SOCKET)
1696 {
1697 int rc = pfn_connect (SOCK_HANDLE (s), name, namelen);
1698 if (rc == SOCKET_ERROR)
1699 set_errno ();
1700 return rc;
1701 }
1702 h_errno = ENOTSOCK;
1703 return SOCKET_ERROR;
1704}
1705
1706u_short
1707sys_htons (u_short hostshort)
1708{
f249a012 1709 return (winsock_lib != NULL) ?
480b0c5b
GV
1710 pfn_htons (hostshort) : hostshort;
1711}
1712
1713u_short
1714sys_ntohs (u_short netshort)
1715{
f249a012 1716 return (winsock_lib != NULL) ?
480b0c5b
GV
1717 pfn_ntohs (netshort) : netshort;
1718}
1719
1720unsigned long
1721sys_inet_addr (const char * cp)
1722{
f249a012 1723 return (winsock_lib != NULL) ?
480b0c5b
GV
1724 pfn_inet_addr (cp) : INADDR_NONE;
1725}
1726
1727int
1728sys_gethostname (char * name, int namelen)
1729{
f249a012 1730 if (winsock_lib != NULL)
480b0c5b
GV
1731 return pfn_gethostname (name, namelen);
1732
1733 if (namelen > MAX_COMPUTERNAME_LENGTH)
1734 return !GetComputerName (name, &namelen);
1735
1736 h_errno = EFAULT;
1737 return SOCKET_ERROR;
1738}
1739
1740struct hostent *
1741sys_gethostbyname(const char * name)
1742{
1743 struct hostent * host;
1744
f249a012 1745 if (winsock_lib == NULL)
480b0c5b
GV
1746 {
1747 h_errno = ENETDOWN;
1748 return NULL;
1749 }
1750
1751 check_errno ();
1752 host = pfn_gethostbyname (name);
1753 if (!host)
1754 set_errno ();
1755 return host;
1756}
1757
1758struct servent *
1759sys_getservbyname(const char * name, const char * proto)
1760{
1761 struct servent * serv;
1762
f249a012 1763 if (winsock_lib == NULL)
480b0c5b
GV
1764 {
1765 h_errno = ENETDOWN;
1766 return NULL;
1767 }
1768
1769 check_errno ();
1770 serv = pfn_getservbyname (name, proto);
1771 if (!serv)
1772 set_errno ();
1773 return serv;
1774}
1775
1776#endif /* HAVE_SOCKETS */
1777
1778
1779/* Shadow main io functions: we need to handle pipes and sockets more
1780 intelligently, and implement non-blocking mode as well. */
1781
1782int
1783sys_close (int fd)
1784{
1785 int rc;
1786
1787 if (fd < 0 || fd >= MAXDESC)
1788 {
1789 errno = EBADF;
1790 return -1;
1791 }
1792
1793 if (fd_info[fd].cp)
1794 {
1795 child_process * cp = fd_info[fd].cp;
1796
1797 fd_info[fd].cp = NULL;
1798
1799 if (CHILD_ACTIVE (cp))
1800 {
1801 /* if last descriptor to active child_process then cleanup */
1802 int i;
1803 for (i = 0; i < MAXDESC; i++)
1804 {
1805 if (i == fd)
1806 continue;
1807 if (fd_info[i].cp == cp)
1808 break;
1809 }
1810 if (i == MAXDESC)
1811 {
f249a012 1812#ifdef HAVE_SOCKETS
480b0c5b
GV
1813 if (fd_info[fd].flags & FILE_SOCKET)
1814 {
f249a012
RS
1815#ifndef SOCK_REPLACE_HANDLE
1816 if (winsock_lib == NULL) abort ();
480b0c5b
GV
1817
1818 pfn_shutdown (SOCK_HANDLE (fd), 2);
1819 rc = pfn_closesocket (SOCK_HANDLE (fd));
f249a012
RS
1820#endif
1821 winsock_inuse--; /* count open sockets */
480b0c5b
GV
1822 }
1823#endif
1824 delete_child (cp);
1825 }
1826 }
1827 }
1828
1829 /* Note that sockets do not need special treatment here (at least on
1830 NT and Win95 using the standard tcp/ip stacks) - it appears that
1831 closesocket is equivalent to CloseHandle, which is to be expected
1832 because socket handles are fully fledged kernel handles. */
1833 rc = _close (fd);
1834
1835 if (rc == 0)
1836 fd_info[fd].flags = 0;
1837
1838 return rc;
1839}
1840
1841int
1842sys_dup (int fd)
1843{
1844 int new_fd;
1845
1846 new_fd = _dup (fd);
1847 if (new_fd >= 0)
1848 {
1849 /* duplicate our internal info as well */
1850 fd_info[new_fd] = fd_info[fd];
1851 }
1852 return new_fd;
1853}
1854
1855
1856int
1857sys_dup2 (int src, int dst)
1858{
1859 int rc;
1860
1861 if (dst < 0 || dst >= MAXDESC)
1862 {
1863 errno = EBADF;
1864 return -1;
1865 }
1866
1867 /* make sure we close the destination first if it's a pipe or socket */
1868 if (src != dst && fd_info[dst].flags != 0)
1869 sys_close (dst);
1870
1871 rc = _dup2 (src, dst);
1872 if (rc == 0)
1873 {
1874 /* duplicate our internal info as well */
1875 fd_info[dst] = fd_info[src];
1876 }
1877 return rc;
1878}
1879
1880/* From callproc.c */
1881extern Lisp_Object Vbinary_process_input;
1882extern Lisp_Object Vbinary_process_output;
1883
1884/* Unix pipe() has only one arg */
1885int
1886sys_pipe (int * phandles)
1887{
1888 int rc;
1889 unsigned flags;
1890 child_process * cp;
1891
1892 /* make pipe handles non-inheritable; when we spawn a child,
1893 we replace the relevant handle with an inheritable one. */
1894 rc = _pipe (phandles, 0, _O_NOINHERIT);
1895
1896 if (rc == 0)
1897 {
1898 /* set internal flags, and put read and write handles into binary
1899 mode as necessary; if not in binary mode, set the MSVC internal
1900 FDEV (0x40) flag to prevent _read from treating ^Z as eof (this
1901 could otherwise allow Emacs to hang because it then waits
1902 indefinitely for the child process to exit, when it might not be
1903 finished). */
1904 flags = FILE_PIPE | FILE_READ;
1905 if (!NILP (Vbinary_process_output))
1906 {
1907 flags |= FILE_BINARY;
1908 setmode (phandles[0], _O_BINARY);
1909 }
1910#if (_MSC_VER == 900)
1911 else
1912 _osfile[phandles[0]] |= 0x40;
1913#endif
1914
1915 fd_info[phandles[0]].flags = flags;
1916
1917 flags = FILE_PIPE | FILE_WRITE;
1918 if (!NILP (Vbinary_process_input))
1919 {
1920 flags |= FILE_BINARY;
1921 setmode (phandles[1], _O_BINARY);
1922 }
1923#if (_MSC_VER == 900)
1924 else
1925 _osfile[phandles[1]] |= 0x40;
1926#endif
1927
1928 fd_info[phandles[1]].flags = flags;
1929 }
1930
1931 return rc;
1932}
1933
f7554349 1934/* From ntproc.c */
fbd6baed 1935extern Lisp_Object Vw32_pipe_read_delay;
f7554349 1936
480b0c5b
GV
1937/* Function to do blocking read of one byte, needed to implement
1938 select. It is only allowed on sockets and pipes. */
1939int
1940_sys_read_ahead (int fd)
1941{
1942 child_process * cp;
1943 int rc;
1944
1945 if (fd < 0 || fd >= MAXDESC)
1946 return STATUS_READ_ERROR;
1947
1948 cp = fd_info[fd].cp;
1949
1950 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
1951 return STATUS_READ_ERROR;
1952
1953 if ((fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) == 0
1954 || (fd_info[fd].flags & FILE_READ) == 0)
1955 {
1956 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd));
1957 abort ();
1958 }
1959
1960 cp->status = STATUS_READ_IN_PROGRESS;
1961
1962 if (fd_info[fd].flags & FILE_PIPE)
f7554349
KH
1963 {
1964 /* Use read to get CRLF translation */
1965 rc = _read (fd, &cp->chr, sizeof (char));
1966
1967 /* Give subprocess time to buffer some more output for us before
1968 reporting that input is available; we need this because Win95
1969 connects DOS programs to pipes by making the pipe appear to be
1970 the normal console stdout - as a result most DOS programs will
1971 write to stdout without buffering, ie. one character at a
fbd6baed 1972 time. Even some W32 programs do this - "dir" in a command
f7554349
KH
1973 shell on NT is very slow if we don't do this. */
1974 if (rc > 0)
1975 {
fbd6baed 1976 int wait = XINT (Vw32_pipe_read_delay);
f7554349
KH
1977
1978 if (wait > 0)
1979 Sleep (wait);
1980 else if (wait < 0)
1981 while (++wait <= 0)
1982 /* Yield remainder of our time slice, effectively giving a
1983 temporary priority boost to the child process. */
1984 Sleep (0);
1985 }
1986 }
480b0c5b
GV
1987#ifdef HAVE_SOCKETS
1988 else if (fd_info[fd].flags & FILE_SOCKET)
1989 rc = pfn_recv (SOCK_HANDLE (fd), &cp->chr, sizeof (char), 0);
1990#endif
1991
1992 if (rc == sizeof (char))
1993 cp->status = STATUS_READ_SUCCEEDED;
1994 else
1995 cp->status = STATUS_READ_FAILED;
1996
1997 return cp->status;
1998}
1999
2000int
2001sys_read (int fd, char * buffer, unsigned int count)
2002{
2003 int nchars;
2004 int extra = 0;
2005 int to_read;
2006 DWORD waiting;
2007
2008 if (fd < 0 || fd >= MAXDESC)
2009 {
2010 errno = EBADF;
2011 return -1;
2012 }
2013
2014 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
2015 {
2016 child_process *cp = fd_info[fd].cp;
2017
2018 if ((fd_info[fd].flags & FILE_READ) == 0)
2019 {
2020 errno = EBADF;
2021 return -1;
2022 }
2023
2024 /* presence of a child_process structure means we are operating in
2025 non-blocking mode - otherwise we just call _read directly.
2026 Note that the child_process structure might be missing because
2027 reap_subprocess has been called; in this case the pipe is
2028 already broken, so calling _read on it is okay. */
2029 if (cp)
2030 {
2031 int current_status = cp->status;
2032
2033 switch (current_status)
2034 {
2035 case STATUS_READ_FAILED:
2036 case STATUS_READ_ERROR:
2037 /* report normal EOF */
2038 return 0;
2039
2040 case STATUS_READ_READY:
2041 case STATUS_READ_IN_PROGRESS:
2042 DebPrint (("sys_read called when read is in progress\n"));
2043 errno = EWOULDBLOCK;
2044 return -1;
2045
2046 case STATUS_READ_SUCCEEDED:
2047 /* consume read-ahead char */
2048 *buffer++ = cp->chr;
2049 count--;
2050 extra = 1;
2051 cp->status = STATUS_READ_ACKNOWLEDGED;
2052 ResetEvent (cp->char_avail);
2053
2054 case STATUS_READ_ACKNOWLEDGED:
2055 break;
2056
2057 default:
2058 DebPrint (("sys_read: bad status %d\n", current_status));
2059 errno = EBADF;
2060 return -1;
2061 }
2062
2063 if (fd_info[fd].flags & FILE_PIPE)
2064 {
2065 PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL);
2066 to_read = min (waiting, (DWORD) count);
2067
2068 /* Use read to get CRLF translation */
2069 nchars = _read (fd, buffer, to_read);
2070 }
2071#ifdef HAVE_SOCKETS
2072 else /* FILE_SOCKET */
2073 {
f249a012 2074 if (winsock_lib == NULL) abort ();
480b0c5b
GV
2075
2076 /* do the equivalent of a non-blocking read */
2077 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
2078 if (waiting == 0 && extra == 0)
2079 {
2080 h_errno = errno = EWOULDBLOCK;
2081 return -1;
2082 }
2083
2084 nchars = 0;
2085 if (waiting)
2086 {
2087 /* always use binary mode for sockets */
2088 nchars = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0);
2089 if (nchars == SOCKET_ERROR)
2090 {
2091 DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
2092 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
2093 if (extra == 0)
2094 {
2095 set_errno ();
2096 return -1;
2097 }
2098 nchars = 0;
2099 }
2100 }
2101 }
2102#endif
2103 }
2104 else
2105 nchars = _read (fd, buffer, count);
2106 }
2107 else
2108 nchars = _read (fd, buffer, count);
2109
2110 return nchars + extra;
2111}
2112
2113/* For now, don't bother with a non-blocking mode */
2114int
2115sys_write (int fd, const void * buffer, unsigned int count)
2116{
2117 int nchars;
2118
2119 if (fd < 0 || fd >= MAXDESC)
2120 {
2121 errno = EBADF;
2122 return -1;
2123 }
2124
2125 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
2126 if ((fd_info[fd].flags & FILE_WRITE) == 0)
2127 {
2128 errno = EBADF;
2129 return -1;
2130 }
2131#ifdef HAVE_SOCKETS
2132 if (fd_info[fd].flags & FILE_SOCKET)
2133 {
f249a012 2134 if (winsock_lib == NULL) abort ();
480b0c5b
GV
2135 nchars = pfn_send (SOCK_HANDLE (fd), buffer, count, 0);
2136 if (nchars == SOCKET_ERROR)
2137 {
2138 DebPrint(("sys_read.send failed with error %d on socket %ld\n",
2139 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
2140 set_errno ();
2141 }
2142 }
2143 else
2144#endif
2145 nchars = _write (fd, buffer, count);
2146
2147 return nchars;
2148}
2149
2150
2151void
2152term_ntproc ()
2153{
2154#ifdef HAVE_SOCKETS
2155 /* shutdown the socket interface if necessary */
2156 term_winsock ();
2157#endif
2158}
2159
f7554349
KH
2160extern BOOL dos_process_running;
2161
480b0c5b
GV
2162void
2163init_ntproc ()
2164{
2165#ifdef HAVE_SOCKETS
f249a012
RS
2166 /* Initialise the socket interface now if available and requested by
2167 the user by defining PRELOAD_WINSOCK; otherwise loading will be
fbd6baed 2168 delayed until open-network-stream is called (w32-has-winsock can
f249a012
RS
2169 also be used to dynamically load or reload winsock).
2170
2171 Conveniently, init_environment is called before us, so
2172 PRELOAD_WINSOCK can be set in the registry. */
2173
2174 /* Always initialize this correctly. */
2175 winsock_lib = NULL;
2176
2177 if (getenv ("PRELOAD_WINSOCK") != NULL)
2178 init_winsock (TRUE);
480b0c5b
GV
2179#endif
2180
2181 /* Initial preparation for subprocess support: replace our standard
2182 handles with non-inheritable versions. */
2183 {
2184 HANDLE parent;
2185 HANDLE stdin_save = INVALID_HANDLE_VALUE;
2186 HANDLE stdout_save = INVALID_HANDLE_VALUE;
2187 HANDLE stderr_save = INVALID_HANDLE_VALUE;
2188
2189 parent = GetCurrentProcess ();
2190
2191 /* ignore errors when duplicating and closing; typically the
2192 handles will be invalid when running as a gui program. */
2193 DuplicateHandle (parent,
2194 GetStdHandle (STD_INPUT_HANDLE),
2195 parent,
2196 &stdin_save,
2197 0,
2198 FALSE,
2199 DUPLICATE_SAME_ACCESS);
2200
2201 DuplicateHandle (parent,
2202 GetStdHandle (STD_OUTPUT_HANDLE),
2203 parent,
2204 &stdout_save,
2205 0,
2206 FALSE,
2207 DUPLICATE_SAME_ACCESS);
2208
2209 DuplicateHandle (parent,
2210 GetStdHandle (STD_ERROR_HANDLE),
2211 parent,
2212 &stderr_save,
2213 0,
2214 FALSE,
2215 DUPLICATE_SAME_ACCESS);
2216
2217 fclose (stdin);
2218 fclose (stdout);
2219 fclose (stderr);
2220
2221 if (stdin_save != INVALID_HANDLE_VALUE)
2222 _open_osfhandle ((long) stdin_save, O_TEXT);
2223 else
2224 open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY);
2225 fdopen (0, "r");
2226
2227 if (stdout_save != INVALID_HANDLE_VALUE)
2228 _open_osfhandle ((long) stdout_save, O_TEXT);
2229 else
2230 open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
2231 fdopen (1, "w");
2232
2233 if (stderr_save != INVALID_HANDLE_VALUE)
2234 _open_osfhandle ((long) stderr_save, O_TEXT);
2235 else
2236 open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
2237 fdopen (2, "w");
2238 }
2239
6b5edcad 2240 /* Restrict Emacs to running only one DOS program at a time (with any
fbd6baed 2241 number of W32 programs). This is to prevent the user from
6b5edcad
RS
2242 running into problems with DOS programs being run in the same VDM
2243 under both Windows 95 and Windows NT.
4ffab11c
RS
2244
2245 Note that it is possible for Emacs to run DOS programs in separate
6b5edcad 2246 VDMs, but unfortunately the pipe implementation on Windows 95 then
4ffab11c
RS
2247 fails to report when the DOS process exits (which is supposed to
2248 break the pipe). Until this bug is fixed, or we can devise a
2249 work-around, we must try to avoid letting the user start more than
2250 one DOS program if possible. */
2251
f7554349
KH
2252 dos_process_running = FALSE;
2253
480b0c5b
GV
2254 /* unfortunately, atexit depends on implementation of malloc */
2255 /* atexit (term_ntproc); */
2256 signal (SIGABRT, term_ntproc);
2257}
2258
2259/* end of nt.c */