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