(stat, get_long_basename): Fail if filename contains any
[bpt/emacs.git] / src / w32.c
CommitLineData
e9e23e23 1/* Utility and Unix shadow routines for GNU Emacs on the Microsoft W32 API.
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
76b3903d 25#include <stddef.h> /* for offsetof */
95ed0025
RS
26#include <stdlib.h>
27#include <stdio.h>
28#include <io.h>
480b0c5b 29#include <errno.h>
95ed0025
RS
30#include <fcntl.h>
31#include <ctype.h>
480b0c5b
GV
32#include <signal.h>
33#include <sys/time.h>
16bb7578 34#include <sys/utime.h>
480b0c5b
GV
35
36/* must include CRT headers *before* config.h */
37#include "config.h"
38#undef access
39#undef chdir
40#undef chmod
41#undef creat
42#undef ctime
43#undef fopen
44#undef link
45#undef mkdir
46#undef mktemp
47#undef open
48#undef rename
49#undef rmdir
50#undef unlink
51
52#undef close
53#undef dup
54#undef dup2
55#undef pipe
56#undef read
57#undef write
95ed0025 58
95ed0025 59#include "lisp.h"
95ed0025
RS
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
380961a6 76#undef shutdown
480b0c5b 77#endif
00b3b7b3 78
489f9371 79#include "w32.h"
480b0c5b 80#include "ndir.h"
489f9371 81#include "w32heap.h"
76b3903d 82
03887dd3
KH
83#undef min
84#undef max
85#define min(x, y) (((x) < (y)) ? (x) : (y))
86#define max(x, y) (((x) > (y)) ? (x) : (y))
87
76b3903d
GV
88extern Lisp_Object Vw32_downcase_file_names;
89extern Lisp_Object Vw32_generate_fake_inodes;
90extern Lisp_Object Vw32_get_true_file_attributes;
91
92static char startup_dir[MAXPATHLEN];
00b3b7b3 93
95ed0025 94/* Get the current working directory. */
480b0c5b 95char *
95ed0025
RS
96getwd (char *dir)
97{
76b3903d 98#if 0
480b0c5b
GV
99 if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
100 return dir;
101 return NULL;
76b3903d
GV
102#else
103 /* Emacs doesn't actually change directory itself, and we want to
104 force our real wd to be where emacs.exe is to avoid unnecessary
105 conflicts when trying to rename or delete directories. */
106 strcpy (dir, startup_dir);
107 return dir;
108#endif
95ed0025
RS
109}
110
480b0c5b 111#ifndef HAVE_SOCKETS
95ed0025
RS
112/* Emulate gethostname. */
113int
114gethostname (char *buffer, int size)
115{
116 /* NT only allows small host names, so the buffer is
117 certainly large enough. */
118 return !GetComputerName (buffer, &size);
119}
480b0c5b 120#endif /* HAVE_SOCKETS */
95ed0025
RS
121
122/* Emulate getloadavg. */
123int
124getloadavg (double loadavg[], int nelem)
125{
126 int i;
127
128 /* A faithful emulation is going to have to be saved for a rainy day. */
129 for (i = 0; i < nelem; i++)
130 {
131 loadavg[i] = 0.0;
132 }
133 return i;
134}
135
480b0c5b 136/* Emulate getpwuid, getpwnam and others. */
95ed0025 137
051fe60d
GV
138#define PASSWD_FIELD_SIZE 256
139
140static char the_passwd_name[PASSWD_FIELD_SIZE];
141static char the_passwd_passwd[PASSWD_FIELD_SIZE];
142static char the_passwd_gecos[PASSWD_FIELD_SIZE];
143static char the_passwd_dir[PASSWD_FIELD_SIZE];
144static char the_passwd_shell[PASSWD_FIELD_SIZE];
95ed0025
RS
145
146static struct passwd the_passwd =
147{
148 the_passwd_name,
149 the_passwd_passwd,
150 0,
151 0,
152 0,
153 the_passwd_gecos,
154 the_passwd_dir,
155 the_passwd_shell,
156};
157
480b0c5b
GV
158int
159getuid ()
160{
161 return the_passwd.pw_uid;
162}
163
164int
165geteuid ()
166{
167 /* I could imagine arguing for checking to see whether the user is
168 in the Administrators group and returning a UID of 0 for that
169 case, but I don't know how wise that would be in the long run. */
170 return getuid ();
171}
172
173int
174getgid ()
175{
176 return the_passwd.pw_gid;
177}
178
179int
180getegid ()
181{
182 return getgid ();
183}
184
95ed0025
RS
185struct passwd *
186getpwuid (int uid)
187{
480b0c5b
GV
188 if (uid == the_passwd.pw_uid)
189 return &the_passwd;
190 return NULL;
95ed0025
RS
191}
192
193struct passwd *
194getpwnam (char *name)
195{
196 struct passwd *pw;
197
198 pw = getpwuid (getuid ());
199 if (!pw)
200 return pw;
201
480b0c5b 202 if (stricmp (name, pw->pw_name))
95ed0025
RS
203 return NULL;
204
205 return pw;
206}
207
480b0c5b
GV
208void
209init_user_info ()
95ed0025 210{
480b0c5b
GV
211 /* Find the user's real name by opening the process token and
212 looking up the name associated with the user-sid in that token.
213
214 Use the relative portion of the identifier authority value from
215 the user-sid as the user id value (same for group id using the
216 primary group sid from the process token). */
217
218 char user_sid[256], name[256], domain[256];
219 DWORD length = sizeof (name), dlength = sizeof (domain), trash;
220 HANDLE token = NULL;
221 SID_NAME_USE user_type;
222
223 if (OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token)
224 && GetTokenInformation (token, TokenUser,
225 (PVOID) user_sid, sizeof (user_sid), &trash)
226 && LookupAccountSid (NULL, *((PSID *) user_sid), name, &length,
227 domain, &dlength, &user_type))
d1c1c3d2 228 {
480b0c5b
GV
229 strcpy (the_passwd.pw_name, name);
230 /* Determine a reasonable uid value. */
231 if (stricmp ("administrator", name) == 0)
232 {
233 the_passwd.pw_uid = 0;
234 the_passwd.pw_gid = 0;
235 }
236 else
237 {
238 SID_IDENTIFIER_AUTHORITY * pSIA;
239
240 pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid));
241 /* I believe the relative portion is the last 4 bytes (of 6)
242 with msb first. */
243 the_passwd.pw_uid = ((pSIA->Value[2] << 24) +
244 (pSIA->Value[3] << 16) +
245 (pSIA->Value[4] << 8) +
246 (pSIA->Value[5] << 0));
247 /* restrict to conventional uid range for normal users */
248 the_passwd.pw_uid = the_passwd.pw_uid % 60001;
249
250 /* Get group id */
251 if (GetTokenInformation (token, TokenPrimaryGroup,
252 (PVOID) user_sid, sizeof (user_sid), &trash))
253 {
254 SID_IDENTIFIER_AUTHORITY * pSIA;
255
256 pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid));
257 the_passwd.pw_gid = ((pSIA->Value[2] << 24) +
258 (pSIA->Value[3] << 16) +
259 (pSIA->Value[4] << 8) +
260 (pSIA->Value[5] << 0));
261 /* I don't know if this is necessary, but for safety... */
262 the_passwd.pw_gid = the_passwd.pw_gid % 60001;
263 }
264 else
265 the_passwd.pw_gid = the_passwd.pw_uid;
266 }
267 }
268 /* If security calls are not supported (presumably because we
269 are running under Windows 95), fallback to this. */
270 else if (GetUserName (name, &length))
271 {
272 strcpy (the_passwd.pw_name, name);
273 if (stricmp ("administrator", name) == 0)
274 the_passwd.pw_uid = 0;
275 else
276 the_passwd.pw_uid = 123;
277 the_passwd.pw_gid = the_passwd.pw_uid;
278 }
279 else
280 {
281 strcpy (the_passwd.pw_name, "unknown");
282 the_passwd.pw_uid = 123;
283 the_passwd.pw_gid = 123;
d1c1c3d2 284 }
95ed0025 285
480b0c5b
GV
286 /* Ensure HOME and SHELL are defined. */
287 if (getenv ("HOME") == NULL)
288 putenv ("HOME=c:/");
289 if (getenv ("SHELL") == NULL)
76b3903d 290 putenv (os_subtype == OS_WIN95 ? "SHELL=command" : "SHELL=cmd");
95ed0025 291
480b0c5b
GV
292 /* Set dir and shell from environment variables. */
293 strcpy (the_passwd.pw_dir, getenv ("HOME"));
294 strcpy (the_passwd.pw_shell, getenv ("SHELL"));
bd4a449f 295
480b0c5b
GV
296 if (token)
297 CloseHandle (token);
95ed0025
RS
298}
299
95ed0025 300int
480b0c5b 301random ()
95ed0025 302{
480b0c5b
GV
303 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
304 return ((rand () << 15) | rand ());
95ed0025
RS
305}
306
95ed0025 307void
480b0c5b 308srandom (int seed)
95ed0025 309{
480b0c5b 310 srand (seed);
95ed0025
RS
311}
312
76b3903d 313
cbe39279
RS
314/* Normalize filename by converting all path separators to
315 the specified separator. Also conditionally convert upper
316 case path name components to lower case. */
317
318static void
319normalize_filename (fp, path_sep)
320 register char *fp;
321 char path_sep;
322{
323 char sep;
324 char *elem;
325
5162ffce
MB
326 /* Always lower-case drive letters a-z, even if the filesystem
327 preserves case in filenames.
328 This is so filenames can be compared by string comparison
329 functions that are case-sensitive. Even case-preserving filesystems
330 do not distinguish case in drive letters. */
331 if (fp[1] == ':' && *fp >= 'A' && *fp <= 'Z')
332 {
333 *fp += 'a' - 'A';
334 fp += 2;
335 }
336
fbd6baed 337 if (NILP (Vw32_downcase_file_names))
cbe39279
RS
338 {
339 while (*fp)
340 {
341 if (*fp == '/' || *fp == '\\')
342 *fp = path_sep;
343 fp++;
344 }
345 return;
346 }
347
348 sep = path_sep; /* convert to this path separator */
349 elem = fp; /* start of current path element */
350
351 do {
352 if (*fp >= 'a' && *fp <= 'z')
353 elem = 0; /* don't convert this element */
354
355 if (*fp == 0 || *fp == ':')
356 {
357 sep = *fp; /* restore current separator (or 0) */
358 *fp = '/'; /* after conversion of this element */
359 }
360
361 if (*fp == '/' || *fp == '\\')
362 {
363 if (elem && elem != fp)
364 {
365 *fp = 0; /* temporary end of string */
366 _strlwr (elem); /* while we convert to lower case */
367 }
368 *fp = sep; /* convert (or restore) path separator */
369 elem = fp + 1; /* next element starts after separator */
370 sep = path_sep;
371 }
372 } while (*fp++);
373}
374
480b0c5b 375/* Destructively turn backslashes into slashes. */
95ed0025 376void
480b0c5b
GV
377dostounix_filename (p)
378 register char *p;
95ed0025 379{
cbe39279 380 normalize_filename (p, '/');
95ed0025
RS
381}
382
480b0c5b 383/* Destructively turn slashes into backslashes. */
95ed0025 384void
480b0c5b
GV
385unixtodos_filename (p)
386 register char *p;
95ed0025 387{
cbe39279 388 normalize_filename (p, '\\');
95ed0025
RS
389}
390
480b0c5b
GV
391/* Remove all CR's that are followed by a LF.
392 (From msdos.c...probably should figure out a way to share it,
393 although this code isn't going to ever change.) */
35f0d482 394int
480b0c5b
GV
395crlf_to_lf (n, buf)
396 register int n;
397 register unsigned char *buf;
35f0d482 398{
480b0c5b
GV
399 unsigned char *np = buf;
400 unsigned char *startp = buf;
401 unsigned char *endp = buf + n;
35f0d482 402
480b0c5b
GV
403 if (n == 0)
404 return n;
405 while (buf < endp - 1)
95ed0025 406 {
480b0c5b
GV
407 if (*buf == 0x0d)
408 {
409 if (*(++buf) != 0x0a)
410 *np++ = 0x0d;
411 }
412 else
413 *np++ = *buf++;
95ed0025 414 }
480b0c5b
GV
415 if (buf < endp)
416 *np++ = *buf++;
417 return np - startp;
95ed0025
RS
418}
419
76b3903d
GV
420/* Parse the root part of file name, if present. Return length and
421 optionally store pointer to char after root. */
422static int
423parse_root (char * name, char ** pPath)
424{
425 char * start = name;
426
427 if (name == NULL)
428 return 0;
429
430 /* find the root name of the volume if given */
431 if (isalpha (name[0]) && name[1] == ':')
432 {
433 /* skip past drive specifier */
434 name += 2;
435 if (IS_DIRECTORY_SEP (name[0]))
436 name++;
437 }
438 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
439 {
440 int slashes = 2;
441 name += 2;
442 do
443 {
444 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
445 break;
446 name++;
447 }
448 while ( *name );
449 if (IS_DIRECTORY_SEP (name[0]))
450 name++;
451 }
452
453 if (pPath)
454 *pPath = name;
455
456 return name - start;
457}
458
459/* Get long base name for name; name is assumed to be absolute. */
460static int
461get_long_basename (char * name, char * buf, int size)
462{
463 WIN32_FIND_DATA find_data;
464 HANDLE dir_handle;
465 int len = 0;
466
bb1584c8
RS
467 /* must be valid filename, no wild cards or other illegal characters */
468 if (strpbrk (name, "*?|<>\""))
469 return 0;
470
76b3903d
GV
471 dir_handle = FindFirstFile (name, &find_data);
472 if (dir_handle != INVALID_HANDLE_VALUE)
473 {
474 if ((len = strlen (find_data.cFileName)) < size)
475 memcpy (buf, find_data.cFileName, len + 1);
476 else
477 len = 0;
478 FindClose (dir_handle);
479 }
480 return len;
481}
482
483/* Get long name for file, if possible (assumed to be absolute). */
484BOOL
485w32_get_long_filename (char * name, char * buf, int size)
486{
487 char * o = buf;
488 char * p;
489 char * q;
490 char full[ MAX_PATH ];
491 int len;
492
493 len = strlen (name);
494 if (len >= MAX_PATH)
495 return FALSE;
496
497 /* Use local copy for destructive modification. */
498 memcpy (full, name, len+1);
499 unixtodos_filename (full);
500
501 /* Copy root part verbatim. */
502 len = parse_root (full, &p);
503 memcpy (o, full, len);
504 o += len;
505 size -= len;
506
507 do
508 {
509 q = p;
510 p = strchr (q, '\\');
511 if (p) *p = '\0';
512 len = get_long_basename (full, o, size);
513 if (len > 0)
514 {
515 o += len;
516 size -= len;
517 if (p != NULL)
518 {
519 *p++ = '\\';
520 if (size < 2)
521 return FALSE;
522 *o++ = '\\';
523 size--;
524 *o = '\0';
525 }
526 }
527 else
528 return FALSE;
529 }
530 while (p != NULL && *p);
531
532 return TRUE;
533}
534
535
95ed0025
RS
536/* Routines that are no-ops on NT but are defined to get Emacs to compile. */
537
95ed0025
RS
538int
539sigsetmask (int signal_mask)
540{
541 return 0;
542}
543
544int
545sigblock (int sig)
546{
547 return 0;
548}
549
95ed0025
RS
550int
551setpgrp (int pid, int gid)
552{
553 return 0;
554}
555
556int
557alarm (int seconds)
558{
559 return 0;
560}
561
c6624584 562void
95ed0025
RS
563unrequest_sigio (void)
564{
c6624584 565 return;
95ed0025
RS
566}
567
c6624584 568void
95ed0025
RS
569request_sigio (void)
570{
c6624584 571 return;
95ed0025
RS
572}
573
480b0c5b 574#define REG_ROOT "SOFTWARE\\GNU\\Emacs"
f332b293
GV
575
576LPBYTE
fbd6baed 577w32_get_resource (key, lpdwtype)
f332b293
GV
578 char *key;
579 LPDWORD lpdwtype;
580{
581 LPBYTE lpvalue;
582 HKEY hrootkey = NULL;
583 DWORD cbData;
584 BOOL ok = FALSE;
585
586 /* Check both the current user and the local machine to see if
587 we have any resources. */
588
589 if (RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
590 {
591 lpvalue = NULL;
592
593 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
594 && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL
595 && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
596 {
597 return (lpvalue);
598 }
599
600 if (lpvalue) xfree (lpvalue);
601
602 RegCloseKey (hrootkey);
603 }
604
605 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
606 {
607 lpvalue = NULL;
608
76b3903d
GV
609 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
610 && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL
611 && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
f332b293
GV
612 {
613 return (lpvalue);
614 }
615
616 if (lpvalue) xfree (lpvalue);
617
618 RegCloseKey (hrootkey);
619 }
620
621 return (NULL);
622}
623
75b08edb
GV
624char *get_emacs_configuration (void);
625extern Lisp_Object Vsystem_configuration;
626
f332b293
GV
627void
628init_environment ()
629{
f332b293
GV
630 /* Check for environment variables and use registry if they don't exist */
631 {
480b0c5b
GV
632 int i;
633 LPBYTE lpval;
634 DWORD dwType;
f332b293 635
480b0c5b
GV
636 static char * env_vars[] =
637 {
638 "HOME",
f249a012 639 "PRELOAD_WINSOCK",
480b0c5b
GV
640 "emacs_dir",
641 "EMACSLOADPATH",
642 "SHELL",
76b3903d 643 "CMDPROXY",
480b0c5b
GV
644 "EMACSDATA",
645 "EMACSPATH",
646 "EMACSLOCKDIR",
76b3903d
GV
647 /* We no longer set INFOPATH because Info-default-directory-list
648 is then ignored. We use a hook in winnt.el instead. */
649 /* "INFOPATH", */
480b0c5b
GV
650 "EMACSDOC",
651 "TERM",
652 };
653
654 for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++)
f332b293 655 {
76b3903d
GV
656 if (!getenv (env_vars[i])
657 && (lpval = w32_get_resource (env_vars[i], &dwType)) != NULL)
480b0c5b
GV
658 {
659 if (dwType == REG_EXPAND_SZ)
660 {
661 char buf1[500], buf2[500];
662
663 ExpandEnvironmentStrings ((LPSTR) lpval, buf1, 500);
664 _snprintf (buf2, 499, "%s=%s", env_vars[i], buf1);
665 putenv (strdup (buf2));
666 }
667 else if (dwType == REG_SZ)
668 {
669 char buf[500];
f332b293 670
480b0c5b
GV
671 _snprintf (buf, 499, "%s=%s", env_vars[i], lpval);
672 putenv (strdup (buf));
673 }
f332b293 674
480b0c5b
GV
675 xfree (lpval);
676 }
677 }
678 }
679
75b08edb
GV
680 /* Rebuild system configuration to reflect invoking system. */
681 Vsystem_configuration = build_string (EMACS_CONFIGURATION);
682
76b3903d
GV
683 /* Another special case: on NT, the PATH variable is actually named
684 "Path" although cmd.exe (perhaps NT itself) arranges for
685 environment variable lookup and setting to be case insensitive.
686 However, Emacs assumes a fully case sensitive environment, so we
687 need to change "Path" to "PATH" to match the expectations of
688 various elisp packages. We do this by the sneaky method of
689 modifying the string in the C runtime environ entry.
690
691 The same applies to COMSPEC. */
692 {
693 char ** envp;
694
695 for (envp = environ; *envp; envp++)
696 if (_strnicmp (*envp, "PATH=", 5) == 0)
697 memcpy (*envp, "PATH=", 5);
698 else if (_strnicmp (*envp, "COMSPEC=", 8) == 0)
699 memcpy (*envp, "COMSPEC=", 8);
700 }
701
702 /* Remember the initial working directory for getwd, then make the
703 real wd be the location of emacs.exe to avoid conflicts when
704 renaming or deleting directories. (We also don't call chdir when
705 running subprocesses for the same reason.) */
706 if (!GetCurrentDirectory (MAXPATHLEN, startup_dir))
707 abort ();
708
709 {
710 char *p;
711 char modname[MAX_PATH];
712
713 if (!GetModuleFileName (NULL, modname, MAX_PATH))
714 abort ();
715 if ((p = strrchr (modname, '\\')) == NULL)
716 abort ();
717 *p = 0;
718
719 SetCurrentDirectory (modname);
720 }
721
480b0c5b
GV
722 init_user_info ();
723}
724
725/* We don't have scripts to automatically determine the system configuration
726 for Emacs before it's compiled, and we don't want to have to make the
727 user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
728 routine. */
729
730static char configuration_buffer[32];
731
732char *
733get_emacs_configuration (void)
734{
735 char *arch, *oem, *os;
736
737 /* Determine the processor type. */
738 switch (get_processor_type ())
739 {
740
741#ifdef PROCESSOR_INTEL_386
742 case PROCESSOR_INTEL_386:
743 case PROCESSOR_INTEL_486:
744 case PROCESSOR_INTEL_PENTIUM:
745 arch = "i386";
746 break;
747#endif
748
749#ifdef PROCESSOR_INTEL_860
750 case PROCESSOR_INTEL_860:
751 arch = "i860";
752 break;
753#endif
754
755#ifdef PROCESSOR_MIPS_R2000
756 case PROCESSOR_MIPS_R2000:
757 case PROCESSOR_MIPS_R3000:
758 case PROCESSOR_MIPS_R4000:
759 arch = "mips";
760 break;
761#endif
762
763#ifdef PROCESSOR_ALPHA_21064
764 case PROCESSOR_ALPHA_21064:
765 arch = "alpha";
766 break;
767#endif
768
769 default:
770 arch = "unknown";
771 break;
f332b293 772 }
480b0c5b
GV
773
774 /* Let oem be "*" until we figure out how to decode the OEM field. */
775 oem = "*";
776
76b3903d 777 os = (GetVersion () & OS_WIN95) ? "windows95" : "nt";
480b0c5b
GV
778
779 sprintf (configuration_buffer, "%s-%s-%s%d.%d", arch, oem, os,
fbd6baed 780 get_w32_major_version (), get_w32_minor_version ());
480b0c5b 781 return configuration_buffer;
f332b293
GV
782}
783
35f0d482
KH
784#include <sys/timeb.h>
785
786/* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
787void
788gettimeofday (struct timeval *tv, struct timezone *tz)
789{
790 struct _timeb tb;
791 _ftime (&tb);
792
793 tv->tv_sec = tb.time;
794 tv->tv_usec = tb.millitm * 1000L;
795 if (tz)
796 {
797 tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */
798 tz->tz_dsttime = tb.dstflag; /* type of dst correction */
799 }
800}
35f0d482 801
480b0c5b 802/* ------------------------------------------------------------------------- */
fbd6baed 803/* IO support and wrapper functions for W32 API. */
480b0c5b 804/* ------------------------------------------------------------------------- */
95ed0025 805
480b0c5b
GV
806/* Place a wrapper around the MSVC version of ctime. It returns NULL
807 on network directories, so we handle that case here.
808 (Ulrich Leodolter, 1/11/95). */
809char *
810sys_ctime (const time_t *t)
811{
812 char *str = (char *) ctime (t);
813 return (str ? str : "Sun Jan 01 00:00:00 1970");
814}
815
816/* Emulate sleep...we could have done this with a define, but that
817 would necessitate including windows.h in the files that used it.
818 This is much easier. */
819void
820sys_sleep (int seconds)
821{
822 Sleep (seconds * 1000);
823}
824
76b3903d 825/* Internal MSVC functions for low-level descriptor munging */
480b0c5b
GV
826extern int __cdecl _set_osfhnd (int fd, long h);
827extern int __cdecl _free_osfhnd (int fd);
828
829/* parallel array of private info on file handles */
830filedesc fd_info [ MAXDESC ];
831
76b3903d
GV
832typedef struct volume_info_data {
833 struct volume_info_data * next;
834
835 /* time when info was obtained */
836 DWORD timestamp;
837
838 /* actual volume info */
839 char * root_dir;
480b0c5b
GV
840 DWORD serialnum;
841 DWORD maxcomp;
842 DWORD flags;
76b3903d
GV
843 char * name;
844 char * type;
845} volume_info_data;
846
847/* Global referenced by various functions. */
848static volume_info_data volume_info;
849
850/* Vector to indicate which drives are local and fixed (for which cached
851 data never expires). */
852static BOOL fixed_drives[26];
853
854/* Consider cached volume information to be stale if older than 10s,
855 at least for non-local drives. Info for fixed drives is never stale. */
856#define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
857#define VOLINFO_STILL_VALID( root_dir, info ) \
858 ( ( isalpha (root_dir[0]) && \
859 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
860 || GetTickCount () - info->timestamp < 10000 )
861
862/* Cache support functions. */
863
864/* Simple linked list with linear search is sufficient. */
865static volume_info_data *volume_cache = NULL;
866
867static volume_info_data *
868lookup_volume_info (char * root_dir)
869{
870 volume_info_data * info;
871
872 for (info = volume_cache; info; info = info->next)
873 if (stricmp (info->root_dir, root_dir) == 0)
874 break;
875 return info;
876}
877
878static void
879add_volume_info (char * root_dir, volume_info_data * info)
880{
881 info->root_dir = strdup (root_dir);
882 info->next = volume_cache;
883 volume_cache = info;
884}
885
886
887/* Wrapper for GetVolumeInformation, which uses caching to avoid
888 performance penalty (~2ms on 486 for local drives, 7.5ms for local
889 cdrom drive, ~5-10ms or more for remote drives on LAN). */
890volume_info_data *
891GetCachedVolumeInformation (char * root_dir)
892{
893 volume_info_data * info;
894 char default_root[ MAX_PATH ];
895
896 /* NULL for root_dir means use root from current directory. */
897 if (root_dir == NULL)
898 {
899 if (GetCurrentDirectory (MAX_PATH, default_root) == 0)
900 return NULL;
901 parse_root (default_root, &root_dir);
902 *root_dir = 0;
903 root_dir = default_root;
904 }
905
906 /* Local fixed drives can be cached permanently. Removable drives
907 cannot be cached permanently, since the volume name and serial
908 number (if nothing else) can change. Remote drives should be
909 treated as if they are removable, since there is no sure way to
910 tell whether they are or not. Also, the UNC association of drive
911 letters mapped to remote volumes can be changed at any time (even
912 by other processes) without notice.
913
914 As a compromise, so we can benefit from caching info for remote
915 volumes, we use a simple expiry mechanism to invalidate cache
916 entries that are more than ten seconds old. */
917
918#if 0
919 /* No point doing this, because WNetGetConnection is even slower than
920 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
921 GetDriveType is about the only call of this type which does not
922 involve network access, and so is extremely quick). */
923
924 /* Map drive letter to UNC if remote. */
925 if ( isalpha( root_dir[0] ) && !fixed[ DRIVE_INDEX( root_dir[0] ) ] )
926 {
927 char remote_name[ 256 ];
928 char drive[3] = { root_dir[0], ':' };
929
930 if (WNetGetConnection (drive, remote_name, sizeof (remote_name))
931 == NO_ERROR)
932 /* do something */ ;
933 }
934#endif
935
936 info = lookup_volume_info (root_dir);
937
938 if (info == NULL || ! VOLINFO_STILL_VALID (root_dir, info))
939 {
940 char name[ 256 ];
941 DWORD serialnum;
942 DWORD maxcomp;
943 DWORD flags;
944 char type[ 256 ];
945
946 /* Info is not cached, or is stale. */
947 if (!GetVolumeInformation (root_dir,
948 name, sizeof (name),
949 &serialnum,
950 &maxcomp,
951 &flags,
952 type, sizeof (type)))
953 return NULL;
954
955 /* Cache the volume information for future use, overwriting existing
956 entry if present. */
957 if (info == NULL)
958 {
959 info = (volume_info_data *) xmalloc (sizeof (volume_info_data));
960 add_volume_info (root_dir, info);
961 }
962 else
963 {
964 free (info->name);
965 free (info->type);
966 }
967
968 info->name = strdup (name);
969 info->serialnum = serialnum;
970 info->maxcomp = maxcomp;
971 info->flags = flags;
972 info->type = strdup (type);
973 info->timestamp = GetTickCount ();
974 }
975
976 return info;
977}
480b0c5b
GV
978
979/* Get information on the volume where name is held; set path pointer to
980 start of pathname in name (past UNC header\volume header if present). */
981int
982get_volume_info (const char * name, const char ** pPath)
95ed0025 983{
480b0c5b
GV
984 char temp[MAX_PATH];
985 char *rootname = NULL; /* default to current volume */
76b3903d 986 volume_info_data * info;
480b0c5b
GV
987
988 if (name == NULL)
989 return FALSE;
990
991 /* find the root name of the volume if given */
992 if (isalpha (name[0]) && name[1] == ':')
993 {
994 rootname = temp;
995 temp[0] = *name++;
996 temp[1] = *name++;
997 temp[2] = '\\';
998 temp[3] = 0;
999 }
1000 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
95ed0025 1001 {
480b0c5b
GV
1002 char *str = temp;
1003 int slashes = 4;
1004 rootname = temp;
1005 do
1006 {
1007 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
1008 break;
1009 *str++ = *name++;
1010 }
1011 while ( *name );
1012
480b0c5b
GV
1013 *str++ = '\\';
1014 *str = 0;
95ed0025 1015 }
480b0c5b
GV
1016
1017 if (pPath)
1018 *pPath = name;
1019
76b3903d
GV
1020 info = GetCachedVolumeInformation (rootname);
1021 if (info != NULL)
95ed0025 1022 {
76b3903d
GV
1023 /* Set global referenced by other functions. */
1024 volume_info = *info;
480b0c5b 1025 return TRUE;
95ed0025 1026 }
480b0c5b
GV
1027 return FALSE;
1028}
1029
1030/* Determine if volume is FAT format (ie. only supports short 8.3
1031 names); also set path pointer to start of pathname in name. */
1032int
1033is_fat_volume (const char * name, const char ** pPath)
1034{
1035 if (get_volume_info (name, pPath))
1036 return (volume_info.maxcomp == 12);
1037 return FALSE;
1038}
1039
1040/* Map filename to a legal 8.3 name if necessary. */
1041const char *
fbd6baed 1042map_w32_filename (const char * name, const char ** pPath)
480b0c5b
GV
1043{
1044 static char shortname[MAX_PATH];
1045 char * str = shortname;
1046 char c;
480b0c5b 1047 char * path;
76b3903d 1048 const char * save_name = name;
480b0c5b
GV
1049
1050 if (is_fat_volume (name, &path)) /* truncate to 8.3 */
95ed0025 1051 {
480b0c5b
GV
1052 register int left = 8; /* maximum number of chars in part */
1053 register int extn = 0; /* extension added? */
1054 register int dots = 2; /* maximum number of dots allowed */
1055
1056 while (name < path)
1057 *str++ = *name++; /* skip past UNC header */
1058
1059 while ((c = *name++))
1060 {
1061 switch ( c )
1062 {
1063 case '\\':
1064 case '/':
1065 *str++ = '\\';
1066 extn = 0; /* reset extension flags */
1067 dots = 2; /* max 2 dots */
1068 left = 8; /* max length 8 for main part */
1069 break;
1070 case ':':
1071 *str++ = ':';
1072 extn = 0; /* reset extension flags */
1073 dots = 2; /* max 2 dots */
1074 left = 8; /* max length 8 for main part */
1075 break;
1076 case '.':
1077 if ( dots )
1078 {
1079 /* Convert path components of the form .xxx to _xxx,
1080 but leave . and .. as they are. This allows .emacs
1081 to be read as _emacs, for example. */
1082
1083 if (! *name ||
1084 *name == '.' ||
1085 IS_DIRECTORY_SEP (*name))
1086 {
1087 *str++ = '.';
1088 dots--;
1089 }
1090 else
1091 {
1092 *str++ = '_';
1093 left--;
1094 dots = 0;
1095 }
1096 }
1097 else if ( !extn )
1098 {
1099 *str++ = '.';
1100 extn = 1; /* we've got an extension */
1101 left = 3; /* 3 chars in extension */
1102 }
1103 else
1104 {
1105 /* any embedded dots after the first are converted to _ */
1106 *str++ = '_';
1107 }
1108 break;
1109 case '~':
1110 case '#': /* don't lose these, they're important */
1111 if ( ! left )
1112 str[-1] = c; /* replace last character of part */
1113 /* FALLTHRU */
1114 default:
1115 if ( left )
1116 {
1117 *str++ = tolower (c); /* map to lower case (looks nicer) */
1118 left--;
1119 dots = 0; /* started a path component */
1120 }
1121 break;
1122 }
1123 }
1124 *str = '\0';
fc85cb29
RS
1125 }
1126 else
1127 {
1128 strcpy (shortname, name);
1129 unixtodos_filename (shortname);
95ed0025 1130 }
480b0c5b
GV
1131
1132 if (pPath)
76b3903d 1133 *pPath = shortname + (path - save_name);
480b0c5b 1134
fc85cb29 1135 return shortname;
480b0c5b
GV
1136}
1137
76b3903d
GV
1138/* Emulate the Unix directory procedures opendir, closedir,
1139 and readdir. We can't use the procedures supplied in sysdep.c,
1140 so we provide them here. */
1141
1142struct direct dir_static; /* simulated directory contents */
1143static HANDLE dir_find_handle = INVALID_HANDLE_VALUE;
1144static int dir_is_fat;
1145static char dir_pathname[MAXPATHLEN+1];
1146static WIN32_FIND_DATA dir_find_data;
1147
1148DIR *
1149opendir (char *filename)
1150{
1151 DIR *dirp;
1152
1153 /* Opening is done by FindFirstFile. However, a read is inherent to
1154 this operation, so we defer the open until read time. */
1155
1156 if (!(dirp = (DIR *) malloc (sizeof (DIR))))
1157 return NULL;
1158 if (dir_find_handle != INVALID_HANDLE_VALUE)
1159 return NULL;
1160
1161 dirp->dd_fd = 0;
1162 dirp->dd_loc = 0;
1163 dirp->dd_size = 0;
1164
1165 strncpy (dir_pathname, map_w32_filename (filename, NULL), MAXPATHLEN);
1166 dir_pathname[MAXPATHLEN] = '\0';
1167 dir_is_fat = is_fat_volume (filename, NULL);
1168
1169 return dirp;
1170}
1171
1172void
1173closedir (DIR *dirp)
1174{
1175 /* If we have a find-handle open, close it. */
1176 if (dir_find_handle != INVALID_HANDLE_VALUE)
1177 {
1178 FindClose (dir_find_handle);
1179 dir_find_handle = INVALID_HANDLE_VALUE;
1180 }
1181 xfree ((char *) dirp);
1182}
1183
1184struct direct *
1185readdir (DIR *dirp)
1186{
1187 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
1188 if (dir_find_handle == INVALID_HANDLE_VALUE)
1189 {
1190 char filename[MAXNAMLEN + 3];
1191 int ln;
1192
1193 strcpy (filename, dir_pathname);
1194 ln = strlen (filename) - 1;
1195 if (!IS_DIRECTORY_SEP (filename[ln]))
1196 strcat (filename, "\\");
1197 strcat (filename, "*");
1198
1199 dir_find_handle = FindFirstFile (filename, &dir_find_data);
1200
1201 if (dir_find_handle == INVALID_HANDLE_VALUE)
1202 return NULL;
1203 }
1204 else
1205 {
1206 if (!FindNextFile (dir_find_handle, &dir_find_data))
1207 return NULL;
1208 }
1209
1210 /* Emacs never uses this value, so don't bother making it match
1211 value returned by stat(). */
1212 dir_static.d_ino = 1;
1213
1214 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 +
1215 dir_static.d_namlen - dir_static.d_namlen % 4;
1216
1217 dir_static.d_namlen = strlen (dir_find_data.cFileName);
1218 strcpy (dir_static.d_name, dir_find_data.cFileName);
1219 if (dir_is_fat)
1220 _strlwr (dir_static.d_name);
1221 else if (!NILP (Vw32_downcase_file_names))
1222 {
1223 register char *p;
1224 for (p = dir_static.d_name; *p; p++)
1225 if (*p >= 'a' && *p <= 'z')
1226 break;
1227 if (!*p)
1228 _strlwr (dir_static.d_name);
1229 }
1230
1231 return &dir_static;
1232}
1233
480b0c5b
GV
1234
1235/* Shadow some MSVC runtime functions to map requests for long filenames
1236 to reasonable short names if necessary. This was originally added to
1237 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
1238 long file names. */
1239
1240int
1241sys_access (const char * path, int mode)
1242{
fbd6baed 1243 return _access (map_w32_filename (path, NULL), mode);
480b0c5b
GV
1244}
1245
1246int
1247sys_chdir (const char * path)
1248{
fbd6baed 1249 return _chdir (map_w32_filename (path, NULL));
480b0c5b
GV
1250}
1251
1252int
1253sys_chmod (const char * path, int mode)
1254{
fbd6baed 1255 return _chmod (map_w32_filename (path, NULL), mode);
480b0c5b
GV
1256}
1257
1258int
1259sys_creat (const char * path, int mode)
1260{
fbd6baed 1261 return _creat (map_w32_filename (path, NULL), mode);
480b0c5b
GV
1262}
1263
1264FILE *
1265sys_fopen(const char * path, const char * mode)
1266{
1267 int fd;
1268 int oflag;
1269 const char * mode_save = mode;
1270
1271 /* Force all file handles to be non-inheritable. This is necessary to
1272 ensure child processes don't unwittingly inherit handles that might
1273 prevent future file access. */
1274
1275 if (mode[0] == 'r')
1276 oflag = O_RDONLY;
1277 else if (mode[0] == 'w' || mode[0] == 'a')
1278 oflag = O_WRONLY | O_CREAT | O_TRUNC;
95ed0025 1279 else
480b0c5b
GV
1280 return NULL;
1281
1282 /* Only do simplistic option parsing. */
1283 while (*++mode)
1284 if (mode[0] == '+')
1285 {
1286 oflag &= ~(O_RDONLY | O_WRONLY);
1287 oflag |= O_RDWR;
1288 }
1289 else if (mode[0] == 'b')
1290 {
1291 oflag &= ~O_TEXT;
1292 oflag |= O_BINARY;
1293 }
1294 else if (mode[0] == 't')
1295 {
1296 oflag &= ~O_BINARY;
1297 oflag |= O_TEXT;
1298 }
1299 else break;
1300
fbd6baed 1301 fd = _open (map_w32_filename (path, NULL), oflag | _O_NOINHERIT, 0644);
480b0c5b
GV
1302 if (fd < 0)
1303 return NULL;
1304
76b3903d 1305 return _fdopen (fd, mode_save);
95ed0025 1306}
480b0c5b 1307
76b3903d 1308/* This only works on NTFS volumes, but is useful to have. */
480b0c5b 1309int
76b3903d 1310sys_link (const char * old, const char * new)
480b0c5b 1311{
76b3903d
GV
1312 HANDLE fileh;
1313 int result = -1;
1314 char oldname[MAX_PATH], newname[MAX_PATH];
1315
1316 if (old == NULL || new == NULL)
1317 {
1318 errno = ENOENT;
1319 return -1;
1320 }
1321
1322 strcpy (oldname, map_w32_filename (old, NULL));
1323 strcpy (newname, map_w32_filename (new, NULL));
1324
1325 fileh = CreateFile (oldname, 0, 0, NULL, OPEN_EXISTING,
1326 FILE_FLAG_BACKUP_SEMANTICS, NULL);
1327 if (fileh != INVALID_HANDLE_VALUE)
1328 {
1329 int wlen;
1330
1331 /* Confusingly, the "alternate" stream name field does not apply
1332 when restoring a hard link, and instead contains the actual
1333 stream data for the link (ie. the name of the link to create).
1334 The WIN32_STREAM_ID structure before the cStreamName field is
1335 the stream header, which is then immediately followed by the
1336 stream data. */
1337
1338 struct {
1339 WIN32_STREAM_ID wid;
1340 WCHAR wbuffer[MAX_PATH]; /* extra space for link name */
1341 } data;
1342
1343 wlen = MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, newname, -1,
1344 data.wid.cStreamName, MAX_PATH);
1345 if (wlen > 0)
1346 {
1347 LPVOID context = NULL;
1348 DWORD wbytes = 0;
1349
1350 data.wid.dwStreamId = BACKUP_LINK;
1351 data.wid.dwStreamAttributes = 0;
1352 data.wid.Size.LowPart = wlen * sizeof(WCHAR);
1353 data.wid.Size.HighPart = 0;
1354 data.wid.dwStreamNameSize = 0;
1355
1356 if (BackupWrite (fileh, (LPBYTE)&data,
1357 offsetof (WIN32_STREAM_ID, cStreamName)
1358 + data.wid.Size.LowPart,
1359 &wbytes, FALSE, FALSE, &context)
1360 && BackupWrite (fileh, NULL, 0, &wbytes, TRUE, FALSE, &context))
1361 {
1362 /* succeeded */
1363 result = 0;
1364 }
1365 else
1366 {
1367 /* Should try mapping GetLastError to errno; for now just
1368 indicate a general error (eg. links not supported). */
1369 errno = EINVAL; // perhaps EMLINK?
1370 }
1371 }
1372
1373 CloseHandle (fileh);
1374 }
1375 else
1376 errno = ENOENT;
1377
1378 return result;
480b0c5b
GV
1379}
1380
1381int
1382sys_mkdir (const char * path)
1383{
fbd6baed 1384 return _mkdir (map_w32_filename (path, NULL));
480b0c5b
GV
1385}
1386
9d1778b1
RS
1387/* Because of long name mapping issues, we need to implement this
1388 ourselves. Also, MSVC's _mktemp returns NULL when it can't generate
1389 a unique name, instead of setting the input template to an empty
1390 string.
1391
1392 Standard algorithm seems to be use pid or tid with a letter on the
1393 front (in place of the 6 X's) and cycle through the letters to find a
1394 unique name. We extend that to allow any reasonable character as the
1395 first of the 6 X's. */
480b0c5b
GV
1396char *
1397sys_mktemp (char * template)
1398{
9d1778b1
RS
1399 char * p;
1400 int i;
1401 unsigned uid = GetCurrentThreadId ();
1402 static char first_char[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
1403
1404 if (template == NULL)
1405 return NULL;
1406 p = template + strlen (template);
1407 i = 5;
1408 /* replace up to the last 5 X's with uid in decimal */
1409 while (--p >= template && p[0] == 'X' && --i >= 0)
1410 {
1411 p[0] = '0' + uid % 10;
1412 uid /= 10;
1413 }
1414
1415 if (i < 0 && p[0] == 'X')
1416 {
1417 i = 0;
1418 do
1419 {
1420 int save_errno = errno;
1421 p[0] = first_char[i];
1422 if (sys_access (template, 0) < 0)
1423 {
1424 errno = save_errno;
1425 return template;
1426 }
1427 }
1428 while (++i < sizeof (first_char));
1429 }
1430
1431 /* Template is badly formed or else we can't generate a unique name,
1432 so return empty string */
1433 template[0] = 0;
1434 return template;
480b0c5b
GV
1435}
1436
1437int
1438sys_open (const char * path, int oflag, int mode)
1439{
1440 /* Force all file handles to be non-inheritable. */
fbd6baed 1441 return _open (map_w32_filename (path, NULL), oflag | _O_NOINHERIT, mode);
480b0c5b
GV
1442}
1443
1444int
1445sys_rename (const char * oldname, const char * newname)
1446{
1447 char temp[MAX_PATH];
5162ffce 1448 DWORD attr;
480b0c5b 1449
e9e23e23 1450 /* MoveFile on Windows 95 doesn't correctly change the short file name
5162ffce
MB
1451 alias in a number of circumstances (it is not easy to predict when
1452 just by looking at oldname and newname, unfortunately). In these
1453 cases, renaming through a temporary name avoids the problem.
1454
e9e23e23 1455 A second problem on Windows 95 is that renaming through a temp name when
5162ffce
MB
1456 newname is uppercase fails (the final long name ends up in
1457 lowercase, although the short alias might be uppercase) UNLESS the
1458 long temp name is not 8.3.
1459
e9e23e23 1460 So, on Windows 95 we always rename through a temp name, and we make sure
5162ffce 1461 the temp name has a long extension to ensure correct renaming. */
480b0c5b 1462
fbd6baed 1463 strcpy (temp, map_w32_filename (oldname, NULL));
480b0c5b 1464
76b3903d 1465 if (os_subtype == OS_WIN95)
480b0c5b
GV
1466 {
1467 char * p;
1468
480b0c5b
GV
1469 if (p = strrchr (temp, '\\'))
1470 p++;
1471 else
1472 p = temp;
5162ffce
MB
1473 /* Force temp name to require a manufactured 8.3 alias - this
1474 seems to make the second rename work properly. */
76b3903d
GV
1475 strcpy (p, "_rename_temp.XXXXXX");
1476 sys_mktemp (temp);
fbd6baed 1477 if (rename (map_w32_filename (oldname, NULL), temp) < 0)
480b0c5b
GV
1478 return -1;
1479 }
1480
1481 /* Emulate Unix behaviour - newname is deleted if it already exists
5162ffce
MB
1482 (at least if it is a file; don't do this for directories).
1483 However, don't do this if we are just changing the case of the file
1484 name - we will end up deleting the file we are trying to rename! */
fbd6baed 1485 newname = map_w32_filename (newname, NULL);
76b3903d
GV
1486
1487 /* TODO: Use GetInformationByHandle (on NT) to ensure newname and temp
1488 do not refer to the same file, eg. through share aliases. */
5162ffce
MB
1489 if (stricmp (newname, temp) != 0
1490 && (attr = GetFileAttributes (newname)) != -1
1491 && (attr & FILE_ATTRIBUTE_DIRECTORY) == 0)
480b0c5b
GV
1492 {
1493 _chmod (newname, 0666);
1494 _unlink (newname);
1495 }
1496
1497 return rename (temp, newname);
1498}
1499
1500int
1501sys_rmdir (const char * path)
1502{
fbd6baed 1503 return _rmdir (map_w32_filename (path, NULL));
480b0c5b
GV
1504}
1505
1506int
1507sys_unlink (const char * path)
1508{
16bb7578
GV
1509 path = map_w32_filename (path, NULL);
1510
1511 /* On Unix, unlink works without write permission. */
1512 _chmod (path, 0666);
1513 return _unlink (path);
480b0c5b
GV
1514}
1515
1516static FILETIME utc_base_ft;
1517static long double utc_base;
1518static int init = 0;
1519
1520static time_t
1521convert_time (FILETIME ft)
1522{
1523 long double ret;
1524
1525 if (!init)
1526 {
1527 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
1528 SYSTEMTIME st;
1529
1530 st.wYear = 1970;
1531 st.wMonth = 1;
1532 st.wDay = 1;
1533 st.wHour = 0;
1534 st.wMinute = 0;
1535 st.wSecond = 0;
1536 st.wMilliseconds = 0;
1537
1538 SystemTimeToFileTime (&st, &utc_base_ft);
1539 utc_base = (long double) utc_base_ft.dwHighDateTime
1540 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
1541 init = 1;
1542 }
1543
1544 if (CompareFileTime (&ft, &utc_base_ft) < 0)
1545 return 0;
1546
1547 ret = (long double) ft.dwHighDateTime * 4096 * 1024 * 1024 + ft.dwLowDateTime;
1548 ret -= utc_base;
1549 return (time_t) (ret * 1e-7);
1550}
1551
480b0c5b
GV
1552void
1553convert_from_time_t (time_t time, FILETIME * pft)
1554{
1555 long double tmp;
1556
1557 if (!init)
1558 {
1559 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
1560 SYSTEMTIME st;
1561
1562 st.wYear = 1970;
1563 st.wMonth = 1;
1564 st.wDay = 1;
1565 st.wHour = 0;
1566 st.wMinute = 0;
1567 st.wSecond = 0;
1568 st.wMilliseconds = 0;
1569
1570 SystemTimeToFileTime (&st, &utc_base_ft);
1571 utc_base = (long double) utc_base_ft.dwHighDateTime
1572 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
1573 init = 1;
1574 }
1575
1576 /* time in 100ns units since 1-Jan-1601 */
1577 tmp = (long double) time * 1e7 + utc_base;
1578 pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024));
16bb7578 1579 pft->dwLowDateTime = (DWORD) (tmp - (4096.0 * 1024 * 1024) * pft->dwHighDateTime);
480b0c5b 1580}
480b0c5b 1581
76b3903d
GV
1582#if 0
1583/* No reason to keep this; faking inode values either by hashing or even
1584 using the file index from GetInformationByHandle, is not perfect and
1585 so by default Emacs doesn't use the inode values on Windows.
1586 Instead, we now determine file-truename correctly (except for
1587 possible drive aliasing etc). */
1588
1589/* Modified version of "PJW" algorithm (see the "Dragon" compiler book). */
480b0c5b 1590static unsigned
76b3903d 1591hashval (const unsigned char * str)
480b0c5b
GV
1592{
1593 unsigned h = 0;
480b0c5b
GV
1594 while (*str)
1595 {
1596 h = (h << 4) + *str++;
76b3903d 1597 h ^= (h >> 28);
480b0c5b
GV
1598 }
1599 return h;
1600}
1601
1602/* Return the hash value of the canonical pathname, excluding the
1603 drive/UNC header, to get a hopefully unique inode number. */
76b3903d 1604static DWORD
480b0c5b
GV
1605generate_inode_val (const char * name)
1606{
1607 char fullname[ MAX_PATH ];
1608 char * p;
1609 unsigned hash;
1610
76b3903d
GV
1611 /* Get the truly canonical filename, if it exists. (Note: this
1612 doesn't resolve aliasing due to subst commands, or recognise hard
1613 links. */
1614 if (!w32_get_long_filename ((char *)name, fullname, MAX_PATH))
1615 abort ();
1616
1617 parse_root (fullname, &p);
fbd6baed 1618 /* Normal W32 filesystems are still case insensitive. */
480b0c5b 1619 _strlwr (p);
76b3903d 1620 return hashval (p);
480b0c5b
GV
1621}
1622
76b3903d
GV
1623#endif
1624
480b0c5b
GV
1625/* MSVC stat function can't cope with UNC names and has other bugs, so
1626 replace it with our own. This also allows us to calculate consistent
1627 inode values without hacks in the main Emacs code. */
1628int
1629stat (const char * path, struct stat * buf)
1630{
1631 char * name;
1632 WIN32_FIND_DATA wfd;
1633 HANDLE fh;
76b3903d 1634 DWORD fake_inode;
480b0c5b
GV
1635 int permission;
1636 int len;
1637 int rootdir = FALSE;
1638
1639 if (path == NULL || buf == NULL)
1640 {
1641 errno = EFAULT;
1642 return -1;
1643 }
1644
fbd6baed 1645 name = (char *) map_w32_filename (path, &path);
bb1584c8
RS
1646 /* must be valid filename, no wild cards or other illegal characters */
1647 if (strpbrk (name, "*?|<>\""))
480b0c5b
GV
1648 {
1649 errno = ENOENT;
1650 return -1;
1651 }
1652
1653 /* Remove trailing directory separator, unless name is the root
1654 directory of a drive or UNC volume in which case ensure there
1655 is a trailing separator. */
1656 len = strlen (name);
1657 rootdir = (path >= name + len - 1
1658 && (IS_DIRECTORY_SEP (*path) || *path == 0));
1659 name = strcpy (alloca (len + 2), name);
1660
1661 if (rootdir)
1662 {
1663 if (!IS_DIRECTORY_SEP (name[len-1]))
1664 strcat (name, "\\");
1665 if (GetDriveType (name) < 2)
1666 {
1667 errno = ENOENT;
1668 return -1;
1669 }
1670 memset (&wfd, 0, sizeof (wfd));
1671 wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
1672 wfd.ftCreationTime = utc_base_ft;
1673 wfd.ftLastAccessTime = utc_base_ft;
1674 wfd.ftLastWriteTime = utc_base_ft;
1675 strcpy (wfd.cFileName, name);
1676 }
1677 else
1678 {
1679 if (IS_DIRECTORY_SEP (name[len-1]))
1680 name[len - 1] = 0;
76b3903d
GV
1681
1682 /* (This is hacky, but helps when doing file completions on
1683 network drives.) Optimize by using information available from
1684 active readdir if possible. */
1685 if (dir_find_handle != INVALID_HANDLE_VALUE
1686 && (len = strlen (dir_pathname)),
1687 strnicmp (name, dir_pathname, len) == 0
1688 && IS_DIRECTORY_SEP (name[len])
1689 && stricmp (name + len + 1, dir_static.d_name) == 0)
480b0c5b 1690 {
76b3903d
GV
1691 /* This was the last entry returned by readdir. */
1692 wfd = dir_find_data;
1693 }
1694 else
1695 {
1696 fh = FindFirstFile (name, &wfd);
1697 if (fh == INVALID_HANDLE_VALUE)
1698 {
1699 errno = ENOENT;
1700 return -1;
1701 }
1702 FindClose (fh);
480b0c5b 1703 }
480b0c5b
GV
1704 }
1705
1706 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1707 {
1708 buf->st_mode = _S_IFDIR;
1709 buf->st_nlink = 2; /* doesn't really matter */
76b3903d 1710 fake_inode = 0; /* this doesn't either I think */
480b0c5b 1711 }
76b3903d 1712 else if (!NILP (Vw32_get_true_file_attributes))
480b0c5b 1713 {
480b0c5b
GV
1714 /* This is more accurate in terms of gettting the correct number
1715 of links, but is quite slow (it is noticable when Emacs is
1716 making a list of file name completions). */
1717 BY_HANDLE_FILE_INFORMATION info;
1718
76b3903d
GV
1719 /* No access rights required to get info. */
1720 fh = CreateFile (name, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
480b0c5b
GV
1721
1722 if (GetFileInformationByHandle (fh, &info))
1723 {
1724 switch (GetFileType (fh))
1725 {
1726 case FILE_TYPE_DISK:
1727 buf->st_mode = _S_IFREG;
1728 break;
1729 case FILE_TYPE_PIPE:
1730 buf->st_mode = _S_IFIFO;
1731 break;
1732 case FILE_TYPE_CHAR:
1733 case FILE_TYPE_UNKNOWN:
1734 default:
1735 buf->st_mode = _S_IFCHR;
1736 }
1737 buf->st_nlink = info.nNumberOfLinks;
76b3903d
GV
1738 /* Might as well use file index to fake inode values, but this
1739 is not guaranteed to be unique unless we keep a handle open
1740 all the time (even then there are situations where it is
1741 not unique). Reputedly, there are at most 48 bits of info
1742 (on NTFS, presumably less on FAT). */
1743 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
480b0c5b
GV
1744 CloseHandle (fh);
1745 }
1746 else
1747 {
1748 errno = EACCES;
1749 return -1;
1750 }
76b3903d
GV
1751 }
1752 else
1753 {
1754 /* Don't bother to make this information more accurate. */
480b0c5b
GV
1755 buf->st_mode = _S_IFREG;
1756 buf->st_nlink = 1;
76b3903d
GV
1757 fake_inode = 0;
1758 }
1759
1760#if 0
1761 /* Not sure if there is any point in this. */
1762 if (!NILP (Vw32_generate_fake_inodes))
1763 fake_inode = generate_inode_val (name);
1764 else if (fake_inode == 0)
1765 {
1766 /* For want of something better, try to make everything unique. */
1767 static DWORD gen_num = 0;
1768 fake_inode = ++gen_num;
480b0c5b 1769 }
76b3903d
GV
1770#endif
1771
1772 /* MSVC defines _ino_t to be short; other libc's might not. */
1773 if (sizeof (buf->st_ino) == 2)
1774 buf->st_ino = fake_inode ^ (fake_inode >> 16);
1775 else
1776 buf->st_ino = fake_inode;
480b0c5b
GV
1777
1778 /* consider files to belong to current user */
1779 buf->st_uid = the_passwd.pw_uid;
1780 buf->st_gid = the_passwd.pw_gid;
1781
fbd6baed 1782 /* volume_info is set indirectly by map_w32_filename */
480b0c5b
GV
1783 buf->st_dev = volume_info.serialnum;
1784 buf->st_rdev = volume_info.serialnum;
1785
480b0c5b
GV
1786
1787 buf->st_size = wfd.nFileSizeLow;
1788
1789 /* Convert timestamps to Unix format. */
1790 buf->st_mtime = convert_time (wfd.ftLastWriteTime);
1791 buf->st_atime = convert_time (wfd.ftLastAccessTime);
1792 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
1793 buf->st_ctime = convert_time (wfd.ftCreationTime);
1794 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
1795
1796 /* determine rwx permissions */
1797 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
1798 permission = _S_IREAD;
1799 else
1800 permission = _S_IREAD | _S_IWRITE;
1801
1802 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1803 permission |= _S_IEXEC;
1804 else
1805 {
1806 char * p = strrchr (name, '.');
76b3903d
GV
1807 if (p != NULL
1808 && (stricmp (p, ".exe") == 0 ||
1809 stricmp (p, ".com") == 0 ||
1810 stricmp (p, ".bat") == 0 ||
1811 stricmp (p, ".cmd") == 0))
480b0c5b
GV
1812 permission |= _S_IEXEC;
1813 }
1814
1815 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
1816
1817 return 0;
1818}
1819
16bb7578
GV
1820/* Provide fstat and utime as well as stat for consistent handling of
1821 file timestamps. */
1822int
1823fstat (int desc, struct stat * buf)
1824{
1825 HANDLE fh = (HANDLE) _get_osfhandle (desc);
1826 BY_HANDLE_FILE_INFORMATION info;
1827 DWORD fake_inode;
1828 int permission;
1829
1830 switch (GetFileType (fh) & ~FILE_TYPE_REMOTE)
1831 {
1832 case FILE_TYPE_DISK:
1833 buf->st_mode = _S_IFREG;
1834 if (!GetFileInformationByHandle (fh, &info))
1835 {
1836 errno = EACCES;
1837 return -1;
1838 }
1839 break;
1840 case FILE_TYPE_PIPE:
1841 buf->st_mode = _S_IFIFO;
1842 goto non_disk;
1843 case FILE_TYPE_CHAR:
1844 case FILE_TYPE_UNKNOWN:
1845 default:
1846 buf->st_mode = _S_IFCHR;
1847 non_disk:
1848 memset (&info, 0, sizeof (info));
1849 info.dwFileAttributes = 0;
1850 info.ftCreationTime = utc_base_ft;
1851 info.ftLastAccessTime = utc_base_ft;
1852 info.ftLastWriteTime = utc_base_ft;
1853 }
1854
1855 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1856 {
1857 buf->st_mode = _S_IFDIR;
1858 buf->st_nlink = 2; /* doesn't really matter */
1859 fake_inode = 0; /* this doesn't either I think */
1860 }
1861 else
1862 {
1863 buf->st_nlink = info.nNumberOfLinks;
1864 /* Might as well use file index to fake inode values, but this
1865 is not guaranteed to be unique unless we keep a handle open
1866 all the time (even then there are situations where it is
1867 not unique). Reputedly, there are at most 48 bits of info
1868 (on NTFS, presumably less on FAT). */
1869 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
1870 }
1871
1872 /* MSVC defines _ino_t to be short; other libc's might not. */
1873 if (sizeof (buf->st_ino) == 2)
1874 buf->st_ino = fake_inode ^ (fake_inode >> 16);
1875 else
1876 buf->st_ino = fake_inode;
1877
1878 /* consider files to belong to current user */
1879 buf->st_uid = 0;
1880 buf->st_gid = 0;
1881
1882 buf->st_dev = info.dwVolumeSerialNumber;
1883 buf->st_rdev = info.dwVolumeSerialNumber;
1884
1885 buf->st_size = info.nFileSizeLow;
1886
1887 /* Convert timestamps to Unix format. */
1888 buf->st_mtime = convert_time (info.ftLastWriteTime);
1889 buf->st_atime = convert_time (info.ftLastAccessTime);
1890 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
1891 buf->st_ctime = convert_time (info.ftCreationTime);
1892 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
1893
1894 /* determine rwx permissions */
1895 if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
1896 permission = _S_IREAD;
1897 else
1898 permission = _S_IREAD | _S_IWRITE;
1899
1900 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1901 permission |= _S_IEXEC;
1902 else
1903 {
1904#if 0 /* no way of knowing the filename */
1905 char * p = strrchr (name, '.');
1906 if (p != NULL &&
1907 (stricmp (p, ".exe") == 0 ||
1908 stricmp (p, ".com") == 0 ||
1909 stricmp (p, ".bat") == 0 ||
1910 stricmp (p, ".cmd") == 0))
1911 permission |= _S_IEXEC;
1912#endif
1913 }
1914
1915 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
1916
1917 return 0;
1918}
1919
1920int
1921utime (const char *name, struct utimbuf *times)
1922{
1923 struct utimbuf deftime;
1924 HANDLE fh;
1925 FILETIME mtime;
1926 FILETIME atime;
1927
1928 if (times == NULL)
1929 {
1930 deftime.modtime = deftime.actime = time (NULL);
1931 times = &deftime;
1932 }
1933
1934 /* Need write access to set times. */
1935 fh = CreateFile (name, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
1936 0, OPEN_EXISTING, 0, NULL);
1937 if (fh)
1938 {
1939 convert_from_time_t (times->actime, &atime);
1940 convert_from_time_t (times->modtime, &mtime);
1941 if (!SetFileTime (fh, NULL, &atime, &mtime))
1942 {
1943 CloseHandle (fh);
1944 errno = EACCES;
1945 return -1;
1946 }
1947 CloseHandle (fh);
1948 }
1949 else
1950 {
1951 errno = EINVAL;
1952 return -1;
1953 }
1954 return 0;
1955}
1956
480b0c5b
GV
1957#ifdef HAVE_SOCKETS
1958
1959/* Wrappers for winsock functions to map between our file descriptors
1960 and winsock's handles; also set h_errno for convenience.
1961
1962 To allow Emacs to run on systems which don't have winsock support
1963 installed, we dynamically link to winsock on startup if present, and
1964 otherwise provide the minimum necessary functionality
1965 (eg. gethostname). */
1966
1967/* function pointers for relevant socket functions */
1968int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
1969void (PASCAL *pfn_WSASetLastError) (int iError);
1970int (PASCAL *pfn_WSAGetLastError) (void);
1971int (PASCAL *pfn_socket) (int af, int type, int protocol);
1972int (PASCAL *pfn_bind) (SOCKET s, const struct sockaddr *addr, int namelen);
1973int (PASCAL *pfn_connect) (SOCKET s, const struct sockaddr *addr, int namelen);
1974int (PASCAL *pfn_ioctlsocket) (SOCKET s, long cmd, u_long *argp);
1975int (PASCAL *pfn_recv) (SOCKET s, char * buf, int len, int flags);
1976int (PASCAL *pfn_send) (SOCKET s, const char * buf, int len, int flags);
1977int (PASCAL *pfn_closesocket) (SOCKET s);
1978int (PASCAL *pfn_shutdown) (SOCKET s, int how);
1979int (PASCAL *pfn_WSACleanup) (void);
1980
1981u_short (PASCAL *pfn_htons) (u_short hostshort);
1982u_short (PASCAL *pfn_ntohs) (u_short netshort);
1983unsigned long (PASCAL *pfn_inet_addr) (const char * cp);
1984int (PASCAL *pfn_gethostname) (char * name, int namelen);
1985struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
1986struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto);
f1614061
RS
1987
1988/* SetHandleInformation is only needed to make sockets non-inheritable. */
1989BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags);
1990#ifndef HANDLE_FLAG_INHERIT
1991#define HANDLE_FLAG_INHERIT 1
1992#endif
480b0c5b 1993
f249a012
RS
1994HANDLE winsock_lib;
1995static int winsock_inuse;
480b0c5b 1996
f249a012 1997BOOL
480b0c5b
GV
1998term_winsock (void)
1999{
f249a012 2000 if (winsock_lib != NULL && winsock_inuse == 0)
480b0c5b 2001 {
f249a012
RS
2002 /* Not sure what would cause WSAENETDOWN, or even if it can happen
2003 after WSAStartup returns successfully, but it seems reasonable
2004 to allow unloading winsock anyway in that case. */
2005 if (pfn_WSACleanup () == 0 ||
2006 pfn_WSAGetLastError () == WSAENETDOWN)
2007 {
2008 if (FreeLibrary (winsock_lib))
2009 winsock_lib = NULL;
2010 return TRUE;
2011 }
480b0c5b 2012 }
f249a012 2013 return FALSE;
480b0c5b
GV
2014}
2015
f249a012
RS
2016BOOL
2017init_winsock (int load_now)
480b0c5b
GV
2018{
2019 WSADATA winsockData;
2020
f249a012
RS
2021 if (winsock_lib != NULL)
2022 return TRUE;
f1614061
RS
2023
2024 pfn_SetHandleInformation = NULL;
2025 pfn_SetHandleInformation
2026 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
2027 "SetHandleInformation");
2028
480b0c5b
GV
2029 winsock_lib = LoadLibrary ("wsock32.dll");
2030
2031 if (winsock_lib != NULL)
2032 {
2033 /* dynamically link to socket functions */
2034
2035#define LOAD_PROC(fn) \
2036 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
2037 goto fail;
2038
2039 LOAD_PROC( WSAStartup );
2040 LOAD_PROC( WSASetLastError );
2041 LOAD_PROC( WSAGetLastError );
2042 LOAD_PROC( socket );
2043 LOAD_PROC( bind );
2044 LOAD_PROC( connect );
2045 LOAD_PROC( ioctlsocket );
2046 LOAD_PROC( recv );
2047 LOAD_PROC( send );
2048 LOAD_PROC( closesocket );
2049 LOAD_PROC( shutdown );
2050 LOAD_PROC( htons );
2051 LOAD_PROC( ntohs );
2052 LOAD_PROC( inet_addr );
2053 LOAD_PROC( gethostname );
2054 LOAD_PROC( gethostbyname );
2055 LOAD_PROC( getservbyname );
2056 LOAD_PROC( WSACleanup );
2057
f249a012
RS
2058#undef LOAD_PROC
2059
480b0c5b
GV
2060 /* specify version 1.1 of winsock */
2061 if (pfn_WSAStartup (0x101, &winsockData) == 0)
2062 {
f249a012
RS
2063 if (winsockData.wVersion != 0x101)
2064 goto fail;
2065
2066 if (!load_now)
2067 {
2068 /* Report that winsock exists and is usable, but leave
2069 socket functions disabled. I am assuming that calling
2070 WSAStartup does not require any network interaction,
2071 and in particular does not cause or require a dial-up
2072 connection to be established. */
2073
2074 pfn_WSACleanup ();
2075 FreeLibrary (winsock_lib);
2076 winsock_lib = NULL;
2077 }
2078 winsock_inuse = 0;
2079 return TRUE;
480b0c5b
GV
2080 }
2081
2082 fail:
2083 FreeLibrary (winsock_lib);
f249a012 2084 winsock_lib = NULL;
480b0c5b 2085 }
f249a012
RS
2086
2087 return FALSE;
480b0c5b
GV
2088}
2089
2090
2091int h_errno = 0;
2092
2093/* function to set h_errno for compatability; map winsock error codes to
2094 normal system codes where they overlap (non-overlapping definitions
2095 are already in <sys/socket.h> */
2096static void set_errno ()
2097{
f249a012 2098 if (winsock_lib == NULL)
480b0c5b
GV
2099 h_errno = EINVAL;
2100 else
2101 h_errno = pfn_WSAGetLastError ();
2102
2103 switch (h_errno)
2104 {
2105 case WSAEACCES: h_errno = EACCES; break;
2106 case WSAEBADF: h_errno = EBADF; break;
2107 case WSAEFAULT: h_errno = EFAULT; break;
2108 case WSAEINTR: h_errno = EINTR; break;
2109 case WSAEINVAL: h_errno = EINVAL; break;
2110 case WSAEMFILE: h_errno = EMFILE; break;
2111 case WSAENAMETOOLONG: h_errno = ENAMETOOLONG; break;
2112 case WSAENOTEMPTY: h_errno = ENOTEMPTY; break;
2113 }
2114 errno = h_errno;
2115}
2116
2117static void check_errno ()
2118{
f249a012 2119 if (h_errno == 0 && winsock_lib != NULL)
480b0c5b
GV
2120 pfn_WSASetLastError (0);
2121}
2122
2123/* [andrewi 3-May-96] I've had conflicting results using both methods,
2124 but I believe the method of keeping the socket handle separate (and
2125 insuring it is not inheritable) is the correct one. */
2126
2127//#define SOCK_REPLACE_HANDLE
2128
2129#ifdef SOCK_REPLACE_HANDLE
2130#define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
2131#else
2132#define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
2133#endif
2134
2135int
2136sys_socket(int af, int type, int protocol)
2137{
2138 int fd;
2139 long s;
2140 child_process * cp;
2141
f249a012 2142 if (winsock_lib == NULL)
480b0c5b
GV
2143 {
2144 h_errno = ENETDOWN;
2145 return INVALID_SOCKET;
2146 }
2147
2148 check_errno ();
2149
2150 /* call the real socket function */
2151 s = (long) pfn_socket (af, type, protocol);
2152
2153 if (s != INVALID_SOCKET)
2154 {
2155 /* Although under NT 3.5 _open_osfhandle will accept a socket
2156 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
2157 that does not work under NT 3.1. However, we can get the same
2158 effect by using a backdoor function to replace an existing
2159 descriptor handle with the one we want. */
2160
2161 /* allocate a file descriptor (with appropriate flags) */
2162 fd = _open ("NUL:", _O_RDWR);
2163 if (fd >= 0)
2164 {
2165#ifdef SOCK_REPLACE_HANDLE
2166 /* now replace handle to NUL with our socket handle */
2167 CloseHandle ((HANDLE) _get_osfhandle (fd));
2168 _free_osfhnd (fd);
2169 _set_osfhnd (fd, s);
2170 /* setmode (fd, _O_BINARY); */
2171#else
2172 /* Make a non-inheritable copy of the socket handle. */
2173 {
2174 HANDLE parent;
2175 HANDLE new_s = INVALID_HANDLE_VALUE;
2176
2177 parent = GetCurrentProcess ();
2178
f1614061
RS
2179 /* Apparently there is a bug in NT 3.51 with some service
2180 packs, which prevents using DuplicateHandle to make a
2181 socket handle non-inheritable (causes WSACleanup to
2182 hang). The work-around is to use SetHandleInformation
2183 instead if it is available and implemented. */
2184 if (!pfn_SetHandleInformation
2185 || !pfn_SetHandleInformation ((HANDLE) s,
2186 HANDLE_FLAG_INHERIT,
caf1a172 2187 0))
f1614061
RS
2188 {
2189 DuplicateHandle (parent,
2190 (HANDLE) s,
2191 parent,
2192 &new_s,
2193 0,
2194 FALSE,
2195 DUPLICATE_SAME_ACCESS);
2196 pfn_closesocket (s);
2197 s = (SOCKET) new_s;
2198 }
2199 fd_info[fd].hnd = (HANDLE) s;
480b0c5b
GV
2200 }
2201#endif
2202
2203 /* set our own internal flags */
2204 fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
2205
2206 cp = new_child ();
2207 if (cp)
2208 {
2209 cp->fd = fd;
2210 cp->status = STATUS_READ_ACKNOWLEDGED;
2211
2212 /* attach child_process to fd_info */
2213 if (fd_info[ fd ].cp != NULL)
2214 {
2215 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
2216 abort ();
2217 }
2218
2219 fd_info[ fd ].cp = cp;
2220
2221 /* success! */
f249a012 2222 winsock_inuse++; /* count open sockets */
480b0c5b
GV
2223 return fd;
2224 }
2225
2226 /* clean up */
2227 _close (fd);
2228 }
2229 pfn_closesocket (s);
2230 h_errno = EMFILE;
2231 }
2232 set_errno ();
2233
2234 return -1;
2235}
2236
2237
2238int
2239sys_bind (int s, const struct sockaddr * addr, int namelen)
2240{
f249a012 2241 if (winsock_lib == NULL)
480b0c5b
GV
2242 {
2243 h_errno = ENOTSOCK;
2244 return SOCKET_ERROR;
2245 }
2246
2247 check_errno ();
2248 if (fd_info[s].flags & FILE_SOCKET)
2249 {
2250 int rc = pfn_bind (SOCK_HANDLE (s), addr, namelen);
2251 if (rc == SOCKET_ERROR)
2252 set_errno ();
2253 return rc;
2254 }
2255 h_errno = ENOTSOCK;
2256 return SOCKET_ERROR;
2257}
2258
2259
2260int
2261sys_connect (int s, const struct sockaddr * name, int namelen)
2262{
f249a012 2263 if (winsock_lib == NULL)
480b0c5b
GV
2264 {
2265 h_errno = ENOTSOCK;
2266 return SOCKET_ERROR;
2267 }
2268
2269 check_errno ();
2270 if (fd_info[s].flags & FILE_SOCKET)
2271 {
2272 int rc = pfn_connect (SOCK_HANDLE (s), name, namelen);
2273 if (rc == SOCKET_ERROR)
2274 set_errno ();
2275 return rc;
2276 }
2277 h_errno = ENOTSOCK;
2278 return SOCKET_ERROR;
2279}
2280
2281u_short
2282sys_htons (u_short hostshort)
2283{
f249a012 2284 return (winsock_lib != NULL) ?
480b0c5b
GV
2285 pfn_htons (hostshort) : hostshort;
2286}
2287
2288u_short
2289sys_ntohs (u_short netshort)
2290{
f249a012 2291 return (winsock_lib != NULL) ?
480b0c5b
GV
2292 pfn_ntohs (netshort) : netshort;
2293}
2294
2295unsigned long
2296sys_inet_addr (const char * cp)
2297{
f249a012 2298 return (winsock_lib != NULL) ?
480b0c5b
GV
2299 pfn_inet_addr (cp) : INADDR_NONE;
2300}
2301
2302int
2303sys_gethostname (char * name, int namelen)
2304{
f249a012 2305 if (winsock_lib != NULL)
480b0c5b
GV
2306 return pfn_gethostname (name, namelen);
2307
2308 if (namelen > MAX_COMPUTERNAME_LENGTH)
2309 return !GetComputerName (name, &namelen);
2310
2311 h_errno = EFAULT;
2312 return SOCKET_ERROR;
2313}
2314
2315struct hostent *
2316sys_gethostbyname(const char * name)
2317{
2318 struct hostent * host;
2319
f249a012 2320 if (winsock_lib == NULL)
480b0c5b
GV
2321 {
2322 h_errno = ENETDOWN;
2323 return NULL;
2324 }
2325
2326 check_errno ();
2327 host = pfn_gethostbyname (name);
2328 if (!host)
2329 set_errno ();
2330 return host;
2331}
2332
2333struct servent *
2334sys_getservbyname(const char * name, const char * proto)
2335{
2336 struct servent * serv;
2337
f249a012 2338 if (winsock_lib == NULL)
480b0c5b
GV
2339 {
2340 h_errno = ENETDOWN;
2341 return NULL;
2342 }
2343
2344 check_errno ();
2345 serv = pfn_getservbyname (name, proto);
2346 if (!serv)
2347 set_errno ();
2348 return serv;
2349}
2350
380961a6
GV
2351int
2352sys_shutdown (int s, int how)
2353{
2354 int rc;
2355
2356 if (winsock_lib == NULL)
2357 {
2358 h_errno = ENETDOWN;
2359 return SOCKET_ERROR;
2360 }
2361
2362 check_errno ();
2363 if (fd_info[s].flags & FILE_SOCKET)
2364 {
2365 int rc = pfn_shutdown (SOCK_HANDLE (s), how);
2366 if (rc == SOCKET_ERROR)
2367 set_errno ();
2368 return rc;
2369 }
2370 h_errno = ENOTSOCK;
2371 return SOCKET_ERROR;
2372}
2373
480b0c5b
GV
2374#endif /* HAVE_SOCKETS */
2375
2376
2377/* Shadow main io functions: we need to handle pipes and sockets more
2378 intelligently, and implement non-blocking mode as well. */
2379
2380int
2381sys_close (int fd)
2382{
2383 int rc;
2384
2385 if (fd < 0 || fd >= MAXDESC)
2386 {
2387 errno = EBADF;
2388 return -1;
2389 }
2390
2391 if (fd_info[fd].cp)
2392 {
2393 child_process * cp = fd_info[fd].cp;
2394
2395 fd_info[fd].cp = NULL;
2396
2397 if (CHILD_ACTIVE (cp))
2398 {
2399 /* if last descriptor to active child_process then cleanup */
2400 int i;
2401 for (i = 0; i < MAXDESC; i++)
2402 {
2403 if (i == fd)
2404 continue;
2405 if (fd_info[i].cp == cp)
2406 break;
2407 }
2408 if (i == MAXDESC)
2409 {
f249a012 2410#ifdef HAVE_SOCKETS
480b0c5b
GV
2411 if (fd_info[fd].flags & FILE_SOCKET)
2412 {
f249a012
RS
2413#ifndef SOCK_REPLACE_HANDLE
2414 if (winsock_lib == NULL) abort ();
480b0c5b
GV
2415
2416 pfn_shutdown (SOCK_HANDLE (fd), 2);
2417 rc = pfn_closesocket (SOCK_HANDLE (fd));
f249a012
RS
2418#endif
2419 winsock_inuse--; /* count open sockets */
480b0c5b
GV
2420 }
2421#endif
2422 delete_child (cp);
2423 }
2424 }
2425 }
2426
2427 /* Note that sockets do not need special treatment here (at least on
e9e23e23 2428 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
480b0c5b
GV
2429 closesocket is equivalent to CloseHandle, which is to be expected
2430 because socket handles are fully fledged kernel handles. */
2431 rc = _close (fd);
2432
2433 if (rc == 0)
2434 fd_info[fd].flags = 0;
2435
2436 return rc;
2437}
2438
2439int
2440sys_dup (int fd)
2441{
2442 int new_fd;
2443
2444 new_fd = _dup (fd);
2445 if (new_fd >= 0)
2446 {
2447 /* duplicate our internal info as well */
2448 fd_info[new_fd] = fd_info[fd];
2449 }
2450 return new_fd;
2451}
2452
2453
2454int
2455sys_dup2 (int src, int dst)
2456{
2457 int rc;
2458
2459 if (dst < 0 || dst >= MAXDESC)
2460 {
2461 errno = EBADF;
2462 return -1;
2463 }
2464
2465 /* make sure we close the destination first if it's a pipe or socket */
2466 if (src != dst && fd_info[dst].flags != 0)
2467 sys_close (dst);
2468
2469 rc = _dup2 (src, dst);
2470 if (rc == 0)
2471 {
2472 /* duplicate our internal info as well */
2473 fd_info[dst] = fd_info[src];
2474 }
2475 return rc;
2476}
2477
480b0c5b
GV
2478/* Unix pipe() has only one arg */
2479int
2480sys_pipe (int * phandles)
2481{
2482 int rc;
2483 unsigned flags;
2484 child_process * cp;
2485
76b3903d
GV
2486 /* make pipe handles non-inheritable; when we spawn a child, we
2487 replace the relevant handle with an inheritable one. Also put
2488 pipes into binary mode; we will do text mode translation ourselves
2489 if required. */
2490 rc = _pipe (phandles, 0, _O_NOINHERIT | _O_BINARY);
480b0c5b
GV
2491
2492 if (rc == 0)
2493 {
7664e306 2494 flags = FILE_PIPE | FILE_READ | FILE_BINARY;
480b0c5b
GV
2495 fd_info[phandles[0]].flags = flags;
2496
7664e306 2497 flags = FILE_PIPE | FILE_WRITE | FILE_BINARY;
480b0c5b
GV
2498 fd_info[phandles[1]].flags = flags;
2499 }
2500
2501 return rc;
2502}
2503
f7554349 2504/* From ntproc.c */
fbd6baed 2505extern Lisp_Object Vw32_pipe_read_delay;
f7554349 2506
480b0c5b
GV
2507/* Function to do blocking read of one byte, needed to implement
2508 select. It is only allowed on sockets and pipes. */
2509int
2510_sys_read_ahead (int fd)
2511{
2512 child_process * cp;
2513 int rc;
2514
2515 if (fd < 0 || fd >= MAXDESC)
2516 return STATUS_READ_ERROR;
2517
2518 cp = fd_info[fd].cp;
2519
2520 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
2521 return STATUS_READ_ERROR;
2522
2523 if ((fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) == 0
2524 || (fd_info[fd].flags & FILE_READ) == 0)
2525 {
2526 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd));
2527 abort ();
2528 }
2529
2530 cp->status = STATUS_READ_IN_PROGRESS;
2531
2532 if (fd_info[fd].flags & FILE_PIPE)
f7554349 2533 {
f7554349
KH
2534 rc = _read (fd, &cp->chr, sizeof (char));
2535
2536 /* Give subprocess time to buffer some more output for us before
e9e23e23 2537 reporting that input is available; we need this because Windows 95
f7554349
KH
2538 connects DOS programs to pipes by making the pipe appear to be
2539 the normal console stdout - as a result most DOS programs will
2540 write to stdout without buffering, ie. one character at a
fbd6baed 2541 time. Even some W32 programs do this - "dir" in a command
f7554349
KH
2542 shell on NT is very slow if we don't do this. */
2543 if (rc > 0)
2544 {
fbd6baed 2545 int wait = XINT (Vw32_pipe_read_delay);
f7554349
KH
2546
2547 if (wait > 0)
2548 Sleep (wait);
2549 else if (wait < 0)
2550 while (++wait <= 0)
2551 /* Yield remainder of our time slice, effectively giving a
2552 temporary priority boost to the child process. */
2553 Sleep (0);
2554 }
2555 }
480b0c5b
GV
2556#ifdef HAVE_SOCKETS
2557 else if (fd_info[fd].flags & FILE_SOCKET)
2558 rc = pfn_recv (SOCK_HANDLE (fd), &cp->chr, sizeof (char), 0);
2559#endif
2560
2561 if (rc == sizeof (char))
2562 cp->status = STATUS_READ_SUCCEEDED;
2563 else
2564 cp->status = STATUS_READ_FAILED;
2565
2566 return cp->status;
2567}
2568
2569int
2570sys_read (int fd, char * buffer, unsigned int count)
2571{
2572 int nchars;
480b0c5b
GV
2573 int to_read;
2574 DWORD waiting;
76b3903d 2575 char * orig_buffer = buffer;
480b0c5b
GV
2576
2577 if (fd < 0 || fd >= MAXDESC)
2578 {
2579 errno = EBADF;
2580 return -1;
2581 }
2582
2583 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
2584 {
2585 child_process *cp = fd_info[fd].cp;
2586
2587 if ((fd_info[fd].flags & FILE_READ) == 0)
2588 {
2589 errno = EBADF;
2590 return -1;
2591 }
2592
76b3903d
GV
2593 nchars = 0;
2594
2595 /* re-read CR carried over from last read */
2596 if (fd_info[fd].flags & FILE_LAST_CR)
2597 {
2598 if (fd_info[fd].flags & FILE_BINARY) abort ();
2599 *buffer++ = 0x0d;
2600 count--;
2601 nchars++;
f52eb3ef 2602 fd_info[fd].flags &= ~FILE_LAST_CR;
76b3903d
GV
2603 }
2604
480b0c5b
GV
2605 /* presence of a child_process structure means we are operating in
2606 non-blocking mode - otherwise we just call _read directly.
2607 Note that the child_process structure might be missing because
2608 reap_subprocess has been called; in this case the pipe is
2609 already broken, so calling _read on it is okay. */
2610 if (cp)
2611 {
2612 int current_status = cp->status;
2613
2614 switch (current_status)
2615 {
2616 case STATUS_READ_FAILED:
2617 case STATUS_READ_ERROR:
f52eb3ef
GV
2618 /* report normal EOF if nothing in buffer */
2619 if (nchars <= 0)
2620 fd_info[fd].flags |= FILE_AT_EOF;
2621 return nchars;
480b0c5b
GV
2622
2623 case STATUS_READ_READY:
2624 case STATUS_READ_IN_PROGRESS:
2625 DebPrint (("sys_read called when read is in progress\n"));
2626 errno = EWOULDBLOCK;
2627 return -1;
2628
2629 case STATUS_READ_SUCCEEDED:
2630 /* consume read-ahead char */
2631 *buffer++ = cp->chr;
2632 count--;
76b3903d 2633 nchars++;
480b0c5b
GV
2634 cp->status = STATUS_READ_ACKNOWLEDGED;
2635 ResetEvent (cp->char_avail);
2636
2637 case STATUS_READ_ACKNOWLEDGED:
2638 break;
2639
2640 default:
2641 DebPrint (("sys_read: bad status %d\n", current_status));
2642 errno = EBADF;
2643 return -1;
2644 }
2645
2646 if (fd_info[fd].flags & FILE_PIPE)
2647 {
2648 PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL);
2649 to_read = min (waiting, (DWORD) count);
f52eb3ef
GV
2650
2651 if (to_read > 0)
2652 nchars += _read (fd, buffer, to_read);
480b0c5b
GV
2653 }
2654#ifdef HAVE_SOCKETS
2655 else /* FILE_SOCKET */
2656 {
f249a012 2657 if (winsock_lib == NULL) abort ();
480b0c5b
GV
2658
2659 /* do the equivalent of a non-blocking read */
2660 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
76b3903d 2661 if (waiting == 0 && nchars == 0)
480b0c5b
GV
2662 {
2663 h_errno = errno = EWOULDBLOCK;
2664 return -1;
2665 }
2666
480b0c5b
GV
2667 if (waiting)
2668 {
2669 /* always use binary mode for sockets */
76b3903d
GV
2670 int res = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0);
2671 if (res == SOCKET_ERROR)
480b0c5b
GV
2672 {
2673 DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
2674 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
76b3903d
GV
2675 set_errno ();
2676 return -1;
480b0c5b 2677 }
76b3903d 2678 nchars += res;
480b0c5b
GV
2679 }
2680 }
2681#endif
2682 }
2683 else
f52eb3ef
GV
2684 {
2685 int nread = _read (fd, buffer, count);
2686 if (nread >= 0)
2687 nchars += nread;
2688 else if (nchars == 0)
2689 nchars = nread;
2690 }
76b3903d 2691
f52eb3ef
GV
2692 if (nchars <= 0)
2693 fd_info[fd].flags |= FILE_AT_EOF;
76b3903d 2694 /* Perform text mode translation if required. */
f52eb3ef 2695 else if ((fd_info[fd].flags & FILE_BINARY) == 0)
76b3903d
GV
2696 {
2697 nchars = crlf_to_lf (nchars, orig_buffer);
2698 /* If buffer contains only CR, return that. To be absolutely
2699 sure we should attempt to read the next char, but in
2700 practice a CR to be followed by LF would not appear by
2701 itself in the buffer. */
2702 if (nchars > 1 && orig_buffer[nchars - 1] == 0x0d)
2703 {
2704 fd_info[fd].flags |= FILE_LAST_CR;
2705 nchars--;
2706 }
76b3903d 2707 }
480b0c5b
GV
2708 }
2709 else
2710 nchars = _read (fd, buffer, count);
2711
76b3903d 2712 return nchars;
480b0c5b
GV
2713}
2714
2715/* For now, don't bother with a non-blocking mode */
2716int
2717sys_write (int fd, const void * buffer, unsigned int count)
2718{
2719 int nchars;
2720
2721 if (fd < 0 || fd >= MAXDESC)
2722 {
2723 errno = EBADF;
2724 return -1;
2725 }
2726
2727 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
76b3903d
GV
2728 {
2729 if ((fd_info[fd].flags & FILE_WRITE) == 0)
2730 {
2731 errno = EBADF;
2732 return -1;
2733 }
2734
2735 /* Perform text mode translation if required. */
2736 if ((fd_info[fd].flags & FILE_BINARY) == 0)
2737 {
2738 char * tmpbuf = alloca (count * 2);
2739 unsigned char * src = (void *)buffer;
2740 unsigned char * dst = tmpbuf;
2741 int nbytes = count;
2742
2743 while (1)
2744 {
2745 unsigned char *next;
2746 /* copy next line or remaining bytes */
2747 next = _memccpy (dst, src, '\n', nbytes);
2748 if (next)
2749 {
2750 /* copied one line ending with '\n' */
2751 int copied = next - dst;
2752 nbytes -= copied;
2753 src += copied;
2754 /* insert '\r' before '\n' */
2755 next[-1] = '\r';
2756 next[0] = '\n';
2757 dst = next + 1;
2758 count++;
2759 }
2760 else
2761 /* copied remaining partial line -> now finished */
2762 break;
2763 }
2764 buffer = tmpbuf;
2765 }
2766 }
2767
480b0c5b
GV
2768#ifdef HAVE_SOCKETS
2769 if (fd_info[fd].flags & FILE_SOCKET)
2770 {
f249a012 2771 if (winsock_lib == NULL) abort ();
480b0c5b
GV
2772 nchars = pfn_send (SOCK_HANDLE (fd), buffer, count, 0);
2773 if (nchars == SOCKET_ERROR)
2774 {
2775 DebPrint(("sys_read.send failed with error %d on socket %ld\n",
2776 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
2777 set_errno ();
2778 }
2779 }
2780 else
2781#endif
2782 nchars = _write (fd, buffer, count);
2783
2784 return nchars;
2785}
2786
f52eb3ef
GV
2787static void
2788check_windows_init_file ()
2789{
2790 extern int noninteractive, inhibit_window_system;
2791
2792 /* A common indication that Emacs is not installed properly is when
2793 it cannot find the Windows installation file. If this file does
2794 not exist in the expected place, tell the user. */
2795
2796 if (!noninteractive && !inhibit_window_system) {
2797 extern Lisp_Object Vwindow_system, Vload_path;
2798 Lisp_Object init_file;
2799 int fd;
2800
2801 init_file = build_string ("term/w32-win");
2802 fd = openp (Vload_path, init_file, ".el:.elc", NULL, 0);
2803 if (fd < 0) {
2804 Lisp_Object load_path_print = Fprin1_to_string (Vload_path, Qnil);
2805 char *init_file_name = XSTRING (init_file)->data;
2806 char *load_path = XSTRING (load_path_print)->data;
2807 char *buffer = alloca (1024);
2808
2809 sprintf (buffer,
2810 "The Emacs Windows initialization file \"%s.el\" "
2811 "could not be found in your Emacs installation. "
2812 "Emacs checked the following directories for this file:\n"
2813 "\n%s\n\n"
2814 "When Emacs cannot find this file, it usually means that it "
2815 "was not installed properly, or its distribution file was "
2816 "not unpacked properly.\nSee the README.W32 file in the "
2817 "top-level Emacs directory for more information.",
2818 init_file_name, load_path);
2819 MessageBox (NULL,
2820 buffer,
2821 "Emacs Abort Dialog",
2822 MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
2823 close (fd);
2824
2825 /* Use the low-level Emacs abort. */
2826#undef abort
2827 abort ();
2828 }
2829 }
2830}
480b0c5b
GV
2831
2832void
2833term_ntproc ()
2834{
2835#ifdef HAVE_SOCKETS
2836 /* shutdown the socket interface if necessary */
2837 term_winsock ();
2838#endif
f52eb3ef
GV
2839
2840 /* Check whether we are shutting down because we cannot find the
2841 Windows initialization file. Do this during shutdown so that
2842 Emacs is initialized as possible, and so that it is out of the
2843 critical startup path. */
2844 check_windows_init_file ();
480b0c5b
GV
2845}
2846
2847void
2848init_ntproc ()
2849{
2850#ifdef HAVE_SOCKETS
f249a012
RS
2851 /* Initialise the socket interface now if available and requested by
2852 the user by defining PRELOAD_WINSOCK; otherwise loading will be
fbd6baed 2853 delayed until open-network-stream is called (w32-has-winsock can
f249a012
RS
2854 also be used to dynamically load or reload winsock).
2855
2856 Conveniently, init_environment is called before us, so
2857 PRELOAD_WINSOCK can be set in the registry. */
2858
2859 /* Always initialize this correctly. */
2860 winsock_lib = NULL;
2861
2862 if (getenv ("PRELOAD_WINSOCK") != NULL)
2863 init_winsock (TRUE);
480b0c5b
GV
2864#endif
2865
2866 /* Initial preparation for subprocess support: replace our standard
2867 handles with non-inheritable versions. */
2868 {
2869 HANDLE parent;
2870 HANDLE stdin_save = INVALID_HANDLE_VALUE;
2871 HANDLE stdout_save = INVALID_HANDLE_VALUE;
2872 HANDLE stderr_save = INVALID_HANDLE_VALUE;
2873
2874 parent = GetCurrentProcess ();
2875
2876 /* ignore errors when duplicating and closing; typically the
2877 handles will be invalid when running as a gui program. */
2878 DuplicateHandle (parent,
2879 GetStdHandle (STD_INPUT_HANDLE),
2880 parent,
2881 &stdin_save,
2882 0,
2883 FALSE,
2884 DUPLICATE_SAME_ACCESS);
2885
2886 DuplicateHandle (parent,
2887 GetStdHandle (STD_OUTPUT_HANDLE),
2888 parent,
2889 &stdout_save,
2890 0,
2891 FALSE,
2892 DUPLICATE_SAME_ACCESS);
2893
2894 DuplicateHandle (parent,
2895 GetStdHandle (STD_ERROR_HANDLE),
2896 parent,
2897 &stderr_save,
2898 0,
2899 FALSE,
2900 DUPLICATE_SAME_ACCESS);
2901
2902 fclose (stdin);
2903 fclose (stdout);
2904 fclose (stderr);
2905
2906 if (stdin_save != INVALID_HANDLE_VALUE)
2907 _open_osfhandle ((long) stdin_save, O_TEXT);
2908 else
76b3903d
GV
2909 _open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY);
2910 _fdopen (0, "r");
480b0c5b
GV
2911
2912 if (stdout_save != INVALID_HANDLE_VALUE)
2913 _open_osfhandle ((long) stdout_save, O_TEXT);
2914 else
76b3903d
GV
2915 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
2916 _fdopen (1, "w");
480b0c5b
GV
2917
2918 if (stderr_save != INVALID_HANDLE_VALUE)
2919 _open_osfhandle ((long) stderr_save, O_TEXT);
2920 else
76b3903d
GV
2921 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
2922 _fdopen (2, "w");
480b0c5b
GV
2923 }
2924
2925 /* unfortunately, atexit depends on implementation of malloc */
2926 /* atexit (term_ntproc); */
2927 signal (SIGABRT, term_ntproc);
76b3903d
GV
2928
2929 /* determine which drives are fixed, for GetCachedVolumeInformation */
2930 {
2931 /* GetDriveType must have trailing backslash. */
2932 char drive[] = "A:\\";
2933
2934 /* Loop over all possible drive letters */
2935 while (*drive <= 'Z')
2936 {
2937 /* Record if this drive letter refers to a fixed drive. */
2938 fixed_drives[DRIVE_INDEX (*drive)] =
2939 (GetDriveType (drive) == DRIVE_FIXED);
2940
2941 (*drive)++;
2942 }
2943 }
480b0c5b
GV
2944}
2945
2946/* end of nt.c */