(w32_get_long_filename): Handle root dirs correctly.
[bpt/emacs.git] / 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 *o = '\0';
507 size -= len;
508
509 while (p != NULL && *p)
510 {
511 q = p;
512 p = strchr (q, '\\');
513 if (p) *p = '\0';
514 len = get_long_basename (full, o, size);
515 if (len > 0)
516 {
517 o += len;
518 size -= len;
519 if (p != NULL)
520 {
521 *p++ = '\\';
522 if (size < 2)
523 return FALSE;
524 *o++ = '\\';
525 size--;
526 *o = '\0';
527 }
528 }
529 else
530 return FALSE;
531 }
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 buf->st_nlink = info.nNumberOfLinks;
1964 /* Might as well use file index to fake inode values, but this
1965 is not guaranteed to be unique unless we keep a handle open
1966 all the time (even then there are situations where it is
1967 not unique). Reputedly, there are at most 48 bits of info
1968 (on NTFS, presumably less on FAT). */
1969 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
1970 }
1971 else
1972 {
1973 buf->st_nlink = 1;
1974 fake_inode = 0;
1975 }
1976
1977 switch (GetFileType (fh))
1978 {
1979 case FILE_TYPE_DISK:
1980 buf->st_mode = _S_IFREG;
1981 break;
1982 case FILE_TYPE_PIPE:
1983 buf->st_mode = _S_IFIFO;
1984 break;
1985 case FILE_TYPE_CHAR:
1986 case FILE_TYPE_UNKNOWN:
1987 default:
1988 buf->st_mode = _S_IFCHR;
1989 }
1990 CloseHandle (fh);
1991 }
1992 else
1993 {
1994 /* Don't bother to make this information more accurate. */
1995 buf->st_mode = _S_IFREG;
1996 buf->st_nlink = 1;
1997 fake_inode = 0;
1998 }
1999
2000 #if 0
2001 /* Not sure if there is any point in this. */
2002 if (!NILP (Vw32_generate_fake_inodes))
2003 fake_inode = generate_inode_val (name);
2004 else if (fake_inode == 0)
2005 {
2006 /* For want of something better, try to make everything unique. */
2007 static DWORD gen_num = 0;
2008 fake_inode = ++gen_num;
2009 }
2010 #endif
2011
2012 /* MSVC defines _ino_t to be short; other libc's might not. */
2013 if (sizeof (buf->st_ino) == 2)
2014 buf->st_ino = fake_inode ^ (fake_inode >> 16);
2015 else
2016 buf->st_ino = fake_inode;
2017
2018 /* consider files to belong to current user */
2019 buf->st_uid = the_passwd.pw_uid;
2020 buf->st_gid = the_passwd.pw_gid;
2021
2022 /* volume_info is set indirectly by map_w32_filename */
2023 buf->st_dev = volume_info.serialnum;
2024 buf->st_rdev = volume_info.serialnum;
2025
2026
2027 buf->st_size = wfd.nFileSizeLow;
2028
2029 /* Convert timestamps to Unix format. */
2030 buf->st_mtime = convert_time (wfd.ftLastWriteTime);
2031 buf->st_atime = convert_time (wfd.ftLastAccessTime);
2032 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
2033 buf->st_ctime = convert_time (wfd.ftCreationTime);
2034 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
2035
2036 /* determine rwx permissions */
2037 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
2038 permission = _S_IREAD;
2039 else
2040 permission = _S_IREAD | _S_IWRITE;
2041
2042 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2043 permission |= _S_IEXEC;
2044 else if (is_exec (name))
2045 permission |= _S_IEXEC;
2046
2047 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
2048
2049 return 0;
2050 }
2051
2052 /* Provide fstat and utime as well as stat for consistent handling of
2053 file timestamps. */
2054 int
2055 fstat (int desc, struct stat * buf)
2056 {
2057 HANDLE fh = (HANDLE) _get_osfhandle (desc);
2058 BY_HANDLE_FILE_INFORMATION info;
2059 DWORD fake_inode;
2060 int permission;
2061
2062 switch (GetFileType (fh) & ~FILE_TYPE_REMOTE)
2063 {
2064 case FILE_TYPE_DISK:
2065 buf->st_mode = _S_IFREG;
2066 if (!GetFileInformationByHandle (fh, &info))
2067 {
2068 errno = EACCES;
2069 return -1;
2070 }
2071 break;
2072 case FILE_TYPE_PIPE:
2073 buf->st_mode = _S_IFIFO;
2074 goto non_disk;
2075 case FILE_TYPE_CHAR:
2076 case FILE_TYPE_UNKNOWN:
2077 default:
2078 buf->st_mode = _S_IFCHR;
2079 non_disk:
2080 memset (&info, 0, sizeof (info));
2081 info.dwFileAttributes = 0;
2082 info.ftCreationTime = utc_base_ft;
2083 info.ftLastAccessTime = utc_base_ft;
2084 info.ftLastWriteTime = utc_base_ft;
2085 }
2086
2087 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2088 {
2089 buf->st_mode = _S_IFDIR;
2090 buf->st_nlink = 2; /* doesn't really matter */
2091 fake_inode = 0; /* this doesn't either I think */
2092 }
2093 else
2094 {
2095 buf->st_nlink = info.nNumberOfLinks;
2096 /* Might as well use file index to fake inode values, but this
2097 is not guaranteed to be unique unless we keep a handle open
2098 all the time (even then there are situations where it is
2099 not unique). Reputedly, there are at most 48 bits of info
2100 (on NTFS, presumably less on FAT). */
2101 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
2102 }
2103
2104 /* MSVC defines _ino_t to be short; other libc's might not. */
2105 if (sizeof (buf->st_ino) == 2)
2106 buf->st_ino = fake_inode ^ (fake_inode >> 16);
2107 else
2108 buf->st_ino = fake_inode;
2109
2110 /* consider files to belong to current user */
2111 buf->st_uid = 0;
2112 buf->st_gid = 0;
2113
2114 buf->st_dev = info.dwVolumeSerialNumber;
2115 buf->st_rdev = info.dwVolumeSerialNumber;
2116
2117 buf->st_size = info.nFileSizeLow;
2118
2119 /* Convert timestamps to Unix format. */
2120 buf->st_mtime = convert_time (info.ftLastWriteTime);
2121 buf->st_atime = convert_time (info.ftLastAccessTime);
2122 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
2123 buf->st_ctime = convert_time (info.ftCreationTime);
2124 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
2125
2126 /* determine rwx permissions */
2127 if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
2128 permission = _S_IREAD;
2129 else
2130 permission = _S_IREAD | _S_IWRITE;
2131
2132 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2133 permission |= _S_IEXEC;
2134 else
2135 {
2136 #if 0 /* no way of knowing the filename */
2137 char * p = strrchr (name, '.');
2138 if (p != NULL &&
2139 (stricmp (p, ".exe") == 0 ||
2140 stricmp (p, ".com") == 0 ||
2141 stricmp (p, ".bat") == 0 ||
2142 stricmp (p, ".cmd") == 0))
2143 permission |= _S_IEXEC;
2144 #endif
2145 }
2146
2147 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
2148
2149 return 0;
2150 }
2151
2152 int
2153 utime (const char *name, struct utimbuf *times)
2154 {
2155 struct utimbuf deftime;
2156 HANDLE fh;
2157 FILETIME mtime;
2158 FILETIME atime;
2159
2160 if (times == NULL)
2161 {
2162 deftime.modtime = deftime.actime = time (NULL);
2163 times = &deftime;
2164 }
2165
2166 /* Need write access to set times. */
2167 fh = CreateFile (name, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
2168 0, OPEN_EXISTING, 0, NULL);
2169 if (fh)
2170 {
2171 convert_from_time_t (times->actime, &atime);
2172 convert_from_time_t (times->modtime, &mtime);
2173 if (!SetFileTime (fh, NULL, &atime, &mtime))
2174 {
2175 CloseHandle (fh);
2176 errno = EACCES;
2177 return -1;
2178 }
2179 CloseHandle (fh);
2180 }
2181 else
2182 {
2183 errno = EINVAL;
2184 return -1;
2185 }
2186 return 0;
2187 }
2188
2189 #ifdef HAVE_SOCKETS
2190
2191 /* Wrappers for winsock functions to map between our file descriptors
2192 and winsock's handles; also set h_errno for convenience.
2193
2194 To allow Emacs to run on systems which don't have winsock support
2195 installed, we dynamically link to winsock on startup if present, and
2196 otherwise provide the minimum necessary functionality
2197 (eg. gethostname). */
2198
2199 /* function pointers for relevant socket functions */
2200 int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
2201 void (PASCAL *pfn_WSASetLastError) (int iError);
2202 int (PASCAL *pfn_WSAGetLastError) (void);
2203 int (PASCAL *pfn_socket) (int af, int type, int protocol);
2204 int (PASCAL *pfn_bind) (SOCKET s, const struct sockaddr *addr, int namelen);
2205 int (PASCAL *pfn_connect) (SOCKET s, const struct sockaddr *addr, int namelen);
2206 int (PASCAL *pfn_ioctlsocket) (SOCKET s, long cmd, u_long *argp);
2207 int (PASCAL *pfn_recv) (SOCKET s, char * buf, int len, int flags);
2208 int (PASCAL *pfn_send) (SOCKET s, const char * buf, int len, int flags);
2209 int (PASCAL *pfn_closesocket) (SOCKET s);
2210 int (PASCAL *pfn_shutdown) (SOCKET s, int how);
2211 int (PASCAL *pfn_WSACleanup) (void);
2212
2213 u_short (PASCAL *pfn_htons) (u_short hostshort);
2214 u_short (PASCAL *pfn_ntohs) (u_short netshort);
2215 unsigned long (PASCAL *pfn_inet_addr) (const char * cp);
2216 int (PASCAL *pfn_gethostname) (char * name, int namelen);
2217 struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
2218 struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto);
2219
2220 /* SetHandleInformation is only needed to make sockets non-inheritable. */
2221 BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags);
2222 #ifndef HANDLE_FLAG_INHERIT
2223 #define HANDLE_FLAG_INHERIT 1
2224 #endif
2225
2226 HANDLE winsock_lib;
2227 static int winsock_inuse;
2228
2229 BOOL
2230 term_winsock (void)
2231 {
2232 if (winsock_lib != NULL && winsock_inuse == 0)
2233 {
2234 /* Not sure what would cause WSAENETDOWN, or even if it can happen
2235 after WSAStartup returns successfully, but it seems reasonable
2236 to allow unloading winsock anyway in that case. */
2237 if (pfn_WSACleanup () == 0 ||
2238 pfn_WSAGetLastError () == WSAENETDOWN)
2239 {
2240 if (FreeLibrary (winsock_lib))
2241 winsock_lib = NULL;
2242 return TRUE;
2243 }
2244 }
2245 return FALSE;
2246 }
2247
2248 BOOL
2249 init_winsock (int load_now)
2250 {
2251 WSADATA winsockData;
2252
2253 if (winsock_lib != NULL)
2254 return TRUE;
2255
2256 pfn_SetHandleInformation = NULL;
2257 pfn_SetHandleInformation
2258 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
2259 "SetHandleInformation");
2260
2261 winsock_lib = LoadLibrary ("wsock32.dll");
2262
2263 if (winsock_lib != NULL)
2264 {
2265 /* dynamically link to socket functions */
2266
2267 #define LOAD_PROC(fn) \
2268 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
2269 goto fail;
2270
2271 LOAD_PROC( WSAStartup );
2272 LOAD_PROC( WSASetLastError );
2273 LOAD_PROC( WSAGetLastError );
2274 LOAD_PROC( socket );
2275 LOAD_PROC( bind );
2276 LOAD_PROC( connect );
2277 LOAD_PROC( ioctlsocket );
2278 LOAD_PROC( recv );
2279 LOAD_PROC( send );
2280 LOAD_PROC( closesocket );
2281 LOAD_PROC( shutdown );
2282 LOAD_PROC( htons );
2283 LOAD_PROC( ntohs );
2284 LOAD_PROC( inet_addr );
2285 LOAD_PROC( gethostname );
2286 LOAD_PROC( gethostbyname );
2287 LOAD_PROC( getservbyname );
2288 LOAD_PROC( WSACleanup );
2289
2290 #undef LOAD_PROC
2291
2292 /* specify version 1.1 of winsock */
2293 if (pfn_WSAStartup (0x101, &winsockData) == 0)
2294 {
2295 if (winsockData.wVersion != 0x101)
2296 goto fail;
2297
2298 if (!load_now)
2299 {
2300 /* Report that winsock exists and is usable, but leave
2301 socket functions disabled. I am assuming that calling
2302 WSAStartup does not require any network interaction,
2303 and in particular does not cause or require a dial-up
2304 connection to be established. */
2305
2306 pfn_WSACleanup ();
2307 FreeLibrary (winsock_lib);
2308 winsock_lib = NULL;
2309 }
2310 winsock_inuse = 0;
2311 return TRUE;
2312 }
2313
2314 fail:
2315 FreeLibrary (winsock_lib);
2316 winsock_lib = NULL;
2317 }
2318
2319 return FALSE;
2320 }
2321
2322
2323 int h_errno = 0;
2324
2325 /* function to set h_errno for compatability; map winsock error codes to
2326 normal system codes where they overlap (non-overlapping definitions
2327 are already in <sys/socket.h> */
2328 static void set_errno ()
2329 {
2330 if (winsock_lib == NULL)
2331 h_errno = EINVAL;
2332 else
2333 h_errno = pfn_WSAGetLastError ();
2334
2335 switch (h_errno)
2336 {
2337 case WSAEACCES: h_errno = EACCES; break;
2338 case WSAEBADF: h_errno = EBADF; break;
2339 case WSAEFAULT: h_errno = EFAULT; break;
2340 case WSAEINTR: h_errno = EINTR; break;
2341 case WSAEINVAL: h_errno = EINVAL; break;
2342 case WSAEMFILE: h_errno = EMFILE; break;
2343 case WSAENAMETOOLONG: h_errno = ENAMETOOLONG; break;
2344 case WSAENOTEMPTY: h_errno = ENOTEMPTY; break;
2345 }
2346 errno = h_errno;
2347 }
2348
2349 static void check_errno ()
2350 {
2351 if (h_errno == 0 && winsock_lib != NULL)
2352 pfn_WSASetLastError (0);
2353 }
2354
2355 /* [andrewi 3-May-96] I've had conflicting results using both methods,
2356 but I believe the method of keeping the socket handle separate (and
2357 insuring it is not inheritable) is the correct one. */
2358
2359 //#define SOCK_REPLACE_HANDLE
2360
2361 #ifdef SOCK_REPLACE_HANDLE
2362 #define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
2363 #else
2364 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
2365 #endif
2366
2367 int
2368 sys_socket(int af, int type, int protocol)
2369 {
2370 int fd;
2371 long s;
2372 child_process * cp;
2373
2374 if (winsock_lib == NULL)
2375 {
2376 h_errno = ENETDOWN;
2377 return INVALID_SOCKET;
2378 }
2379
2380 check_errno ();
2381
2382 /* call the real socket function */
2383 s = (long) pfn_socket (af, type, protocol);
2384
2385 if (s != INVALID_SOCKET)
2386 {
2387 /* Although under NT 3.5 _open_osfhandle will accept a socket
2388 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
2389 that does not work under NT 3.1. However, we can get the same
2390 effect by using a backdoor function to replace an existing
2391 descriptor handle with the one we want. */
2392
2393 /* allocate a file descriptor (with appropriate flags) */
2394 fd = _open ("NUL:", _O_RDWR);
2395 if (fd >= 0)
2396 {
2397 #ifdef SOCK_REPLACE_HANDLE
2398 /* now replace handle to NUL with our socket handle */
2399 CloseHandle ((HANDLE) _get_osfhandle (fd));
2400 _free_osfhnd (fd);
2401 _set_osfhnd (fd, s);
2402 /* setmode (fd, _O_BINARY); */
2403 #else
2404 /* Make a non-inheritable copy of the socket handle. */
2405 {
2406 HANDLE parent;
2407 HANDLE new_s = INVALID_HANDLE_VALUE;
2408
2409 parent = GetCurrentProcess ();
2410
2411 /* Apparently there is a bug in NT 3.51 with some service
2412 packs, which prevents using DuplicateHandle to make a
2413 socket handle non-inheritable (causes WSACleanup to
2414 hang). The work-around is to use SetHandleInformation
2415 instead if it is available and implemented. */
2416 if (!pfn_SetHandleInformation
2417 || !pfn_SetHandleInformation ((HANDLE) s,
2418 HANDLE_FLAG_INHERIT,
2419 0))
2420 {
2421 DuplicateHandle (parent,
2422 (HANDLE) s,
2423 parent,
2424 &new_s,
2425 0,
2426 FALSE,
2427 DUPLICATE_SAME_ACCESS);
2428 pfn_closesocket (s);
2429 s = (SOCKET) new_s;
2430 }
2431 fd_info[fd].hnd = (HANDLE) s;
2432 }
2433 #endif
2434
2435 /* set our own internal flags */
2436 fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
2437
2438 cp = new_child ();
2439 if (cp)
2440 {
2441 cp->fd = fd;
2442 cp->status = STATUS_READ_ACKNOWLEDGED;
2443
2444 /* attach child_process to fd_info */
2445 if (fd_info[ fd ].cp != NULL)
2446 {
2447 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
2448 abort ();
2449 }
2450
2451 fd_info[ fd ].cp = cp;
2452
2453 /* success! */
2454 winsock_inuse++; /* count open sockets */
2455 return fd;
2456 }
2457
2458 /* clean up */
2459 _close (fd);
2460 }
2461 pfn_closesocket (s);
2462 h_errno = EMFILE;
2463 }
2464 set_errno ();
2465
2466 return -1;
2467 }
2468
2469
2470 int
2471 sys_bind (int s, const struct sockaddr * addr, int namelen)
2472 {
2473 if (winsock_lib == NULL)
2474 {
2475 h_errno = ENOTSOCK;
2476 return SOCKET_ERROR;
2477 }
2478
2479 check_errno ();
2480 if (fd_info[s].flags & FILE_SOCKET)
2481 {
2482 int rc = pfn_bind (SOCK_HANDLE (s), addr, namelen);
2483 if (rc == SOCKET_ERROR)
2484 set_errno ();
2485 return rc;
2486 }
2487 h_errno = ENOTSOCK;
2488 return SOCKET_ERROR;
2489 }
2490
2491
2492 int
2493 sys_connect (int s, const struct sockaddr * name, int namelen)
2494 {
2495 if (winsock_lib == NULL)
2496 {
2497 h_errno = ENOTSOCK;
2498 return SOCKET_ERROR;
2499 }
2500
2501 check_errno ();
2502 if (fd_info[s].flags & FILE_SOCKET)
2503 {
2504 int rc = pfn_connect (SOCK_HANDLE (s), name, namelen);
2505 if (rc == SOCKET_ERROR)
2506 set_errno ();
2507 return rc;
2508 }
2509 h_errno = ENOTSOCK;
2510 return SOCKET_ERROR;
2511 }
2512
2513 u_short
2514 sys_htons (u_short hostshort)
2515 {
2516 return (winsock_lib != NULL) ?
2517 pfn_htons (hostshort) : hostshort;
2518 }
2519
2520 u_short
2521 sys_ntohs (u_short netshort)
2522 {
2523 return (winsock_lib != NULL) ?
2524 pfn_ntohs (netshort) : netshort;
2525 }
2526
2527 unsigned long
2528 sys_inet_addr (const char * cp)
2529 {
2530 return (winsock_lib != NULL) ?
2531 pfn_inet_addr (cp) : INADDR_NONE;
2532 }
2533
2534 int
2535 sys_gethostname (char * name, int namelen)
2536 {
2537 if (winsock_lib != NULL)
2538 return pfn_gethostname (name, namelen);
2539
2540 if (namelen > MAX_COMPUTERNAME_LENGTH)
2541 return !GetComputerName (name, &namelen);
2542
2543 h_errno = EFAULT;
2544 return SOCKET_ERROR;
2545 }
2546
2547 struct hostent *
2548 sys_gethostbyname(const char * name)
2549 {
2550 struct hostent * host;
2551
2552 if (winsock_lib == NULL)
2553 {
2554 h_errno = ENETDOWN;
2555 return NULL;
2556 }
2557
2558 check_errno ();
2559 host = pfn_gethostbyname (name);
2560 if (!host)
2561 set_errno ();
2562 return host;
2563 }
2564
2565 struct servent *
2566 sys_getservbyname(const char * name, const char * proto)
2567 {
2568 struct servent * serv;
2569
2570 if (winsock_lib == NULL)
2571 {
2572 h_errno = ENETDOWN;
2573 return NULL;
2574 }
2575
2576 check_errno ();
2577 serv = pfn_getservbyname (name, proto);
2578 if (!serv)
2579 set_errno ();
2580 return serv;
2581 }
2582
2583 int
2584 sys_shutdown (int s, int how)
2585 {
2586 int rc;
2587
2588 if (winsock_lib == NULL)
2589 {
2590 h_errno = ENETDOWN;
2591 return SOCKET_ERROR;
2592 }
2593
2594 check_errno ();
2595 if (fd_info[s].flags & FILE_SOCKET)
2596 {
2597 int rc = pfn_shutdown (SOCK_HANDLE (s), how);
2598 if (rc == SOCKET_ERROR)
2599 set_errno ();
2600 return rc;
2601 }
2602 h_errno = ENOTSOCK;
2603 return SOCKET_ERROR;
2604 }
2605
2606 #endif /* HAVE_SOCKETS */
2607
2608
2609 /* Shadow main io functions: we need to handle pipes and sockets more
2610 intelligently, and implement non-blocking mode as well. */
2611
2612 int
2613 sys_close (int fd)
2614 {
2615 int rc;
2616
2617 if (fd < 0 || fd >= MAXDESC)
2618 {
2619 errno = EBADF;
2620 return -1;
2621 }
2622
2623 if (fd_info[fd].cp)
2624 {
2625 child_process * cp = fd_info[fd].cp;
2626
2627 fd_info[fd].cp = NULL;
2628
2629 if (CHILD_ACTIVE (cp))
2630 {
2631 /* if last descriptor to active child_process then cleanup */
2632 int i;
2633 for (i = 0; i < MAXDESC; i++)
2634 {
2635 if (i == fd)
2636 continue;
2637 if (fd_info[i].cp == cp)
2638 break;
2639 }
2640 if (i == MAXDESC)
2641 {
2642 #ifdef HAVE_SOCKETS
2643 if (fd_info[fd].flags & FILE_SOCKET)
2644 {
2645 #ifndef SOCK_REPLACE_HANDLE
2646 if (winsock_lib == NULL) abort ();
2647
2648 pfn_shutdown (SOCK_HANDLE (fd), 2);
2649 rc = pfn_closesocket (SOCK_HANDLE (fd));
2650 #endif
2651 winsock_inuse--; /* count open sockets */
2652 }
2653 #endif
2654 delete_child (cp);
2655 }
2656 }
2657 }
2658
2659 /* Note that sockets do not need special treatment here (at least on
2660 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
2661 closesocket is equivalent to CloseHandle, which is to be expected
2662 because socket handles are fully fledged kernel handles. */
2663 rc = _close (fd);
2664
2665 if (rc == 0)
2666 fd_info[fd].flags = 0;
2667
2668 return rc;
2669 }
2670
2671 int
2672 sys_dup (int fd)
2673 {
2674 int new_fd;
2675
2676 new_fd = _dup (fd);
2677 if (new_fd >= 0)
2678 {
2679 /* duplicate our internal info as well */
2680 fd_info[new_fd] = fd_info[fd];
2681 }
2682 return new_fd;
2683 }
2684
2685
2686 int
2687 sys_dup2 (int src, int dst)
2688 {
2689 int rc;
2690
2691 if (dst < 0 || dst >= MAXDESC)
2692 {
2693 errno = EBADF;
2694 return -1;
2695 }
2696
2697 /* make sure we close the destination first if it's a pipe or socket */
2698 if (src != dst && fd_info[dst].flags != 0)
2699 sys_close (dst);
2700
2701 rc = _dup2 (src, dst);
2702 if (rc == 0)
2703 {
2704 /* duplicate our internal info as well */
2705 fd_info[dst] = fd_info[src];
2706 }
2707 return rc;
2708 }
2709
2710 /* Unix pipe() has only one arg */
2711 int
2712 sys_pipe (int * phandles)
2713 {
2714 int rc;
2715 unsigned flags;
2716 child_process * cp;
2717
2718 /* make pipe handles non-inheritable; when we spawn a child, we
2719 replace the relevant handle with an inheritable one. Also put
2720 pipes into binary mode; we will do text mode translation ourselves
2721 if required. */
2722 rc = _pipe (phandles, 0, _O_NOINHERIT | _O_BINARY);
2723
2724 if (rc == 0)
2725 {
2726 flags = FILE_PIPE | FILE_READ | FILE_BINARY;
2727 fd_info[phandles[0]].flags = flags;
2728
2729 flags = FILE_PIPE | FILE_WRITE | FILE_BINARY;
2730 fd_info[phandles[1]].flags = flags;
2731 }
2732
2733 return rc;
2734 }
2735
2736 /* From ntproc.c */
2737 extern Lisp_Object Vw32_pipe_read_delay;
2738
2739 /* Function to do blocking read of one byte, needed to implement
2740 select. It is only allowed on sockets and pipes. */
2741 int
2742 _sys_read_ahead (int fd)
2743 {
2744 child_process * cp;
2745 int rc;
2746
2747 if (fd < 0 || fd >= MAXDESC)
2748 return STATUS_READ_ERROR;
2749
2750 cp = fd_info[fd].cp;
2751
2752 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
2753 return STATUS_READ_ERROR;
2754
2755 if ((fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) == 0
2756 || (fd_info[fd].flags & FILE_READ) == 0)
2757 {
2758 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd));
2759 abort ();
2760 }
2761
2762 cp->status = STATUS_READ_IN_PROGRESS;
2763
2764 if (fd_info[fd].flags & FILE_PIPE)
2765 {
2766 rc = _read (fd, &cp->chr, sizeof (char));
2767
2768 /* Give subprocess time to buffer some more output for us before
2769 reporting that input is available; we need this because Windows 95
2770 connects DOS programs to pipes by making the pipe appear to be
2771 the normal console stdout - as a result most DOS programs will
2772 write to stdout without buffering, ie. one character at a
2773 time. Even some W32 programs do this - "dir" in a command
2774 shell on NT is very slow if we don't do this. */
2775 if (rc > 0)
2776 {
2777 int wait = XINT (Vw32_pipe_read_delay);
2778
2779 if (wait > 0)
2780 Sleep (wait);
2781 else if (wait < 0)
2782 while (++wait <= 0)
2783 /* Yield remainder of our time slice, effectively giving a
2784 temporary priority boost to the child process. */
2785 Sleep (0);
2786 }
2787 }
2788 #ifdef HAVE_SOCKETS
2789 else if (fd_info[fd].flags & FILE_SOCKET)
2790 rc = pfn_recv (SOCK_HANDLE (fd), &cp->chr, sizeof (char), 0);
2791 #endif
2792
2793 if (rc == sizeof (char))
2794 cp->status = STATUS_READ_SUCCEEDED;
2795 else
2796 cp->status = STATUS_READ_FAILED;
2797
2798 return cp->status;
2799 }
2800
2801 int
2802 sys_read (int fd, char * buffer, unsigned int count)
2803 {
2804 int nchars;
2805 int to_read;
2806 DWORD waiting;
2807 char * orig_buffer = buffer;
2808
2809 if (fd < 0 || fd >= MAXDESC)
2810 {
2811 errno = EBADF;
2812 return -1;
2813 }
2814
2815 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
2816 {
2817 child_process *cp = fd_info[fd].cp;
2818
2819 if ((fd_info[fd].flags & FILE_READ) == 0)
2820 {
2821 errno = EBADF;
2822 return -1;
2823 }
2824
2825 nchars = 0;
2826
2827 /* re-read CR carried over from last read */
2828 if (fd_info[fd].flags & FILE_LAST_CR)
2829 {
2830 if (fd_info[fd].flags & FILE_BINARY) abort ();
2831 *buffer++ = 0x0d;
2832 count--;
2833 nchars++;
2834 fd_info[fd].flags &= ~FILE_LAST_CR;
2835 }
2836
2837 /* presence of a child_process structure means we are operating in
2838 non-blocking mode - otherwise we just call _read directly.
2839 Note that the child_process structure might be missing because
2840 reap_subprocess has been called; in this case the pipe is
2841 already broken, so calling _read on it is okay. */
2842 if (cp)
2843 {
2844 int current_status = cp->status;
2845
2846 switch (current_status)
2847 {
2848 case STATUS_READ_FAILED:
2849 case STATUS_READ_ERROR:
2850 /* report normal EOF if nothing in buffer */
2851 if (nchars <= 0)
2852 fd_info[fd].flags |= FILE_AT_EOF;
2853 return nchars;
2854
2855 case STATUS_READ_READY:
2856 case STATUS_READ_IN_PROGRESS:
2857 DebPrint (("sys_read called when read is in progress\n"));
2858 errno = EWOULDBLOCK;
2859 return -1;
2860
2861 case STATUS_READ_SUCCEEDED:
2862 /* consume read-ahead char */
2863 *buffer++ = cp->chr;
2864 count--;
2865 nchars++;
2866 cp->status = STATUS_READ_ACKNOWLEDGED;
2867 ResetEvent (cp->char_avail);
2868
2869 case STATUS_READ_ACKNOWLEDGED:
2870 break;
2871
2872 default:
2873 DebPrint (("sys_read: bad status %d\n", current_status));
2874 errno = EBADF;
2875 return -1;
2876 }
2877
2878 if (fd_info[fd].flags & FILE_PIPE)
2879 {
2880 PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL);
2881 to_read = min (waiting, (DWORD) count);
2882
2883 if (to_read > 0)
2884 nchars += _read (fd, buffer, to_read);
2885 }
2886 #ifdef HAVE_SOCKETS
2887 else /* FILE_SOCKET */
2888 {
2889 if (winsock_lib == NULL) abort ();
2890
2891 /* do the equivalent of a non-blocking read */
2892 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
2893 if (waiting == 0 && nchars == 0)
2894 {
2895 h_errno = errno = EWOULDBLOCK;
2896 return -1;
2897 }
2898
2899 if (waiting)
2900 {
2901 /* always use binary mode for sockets */
2902 int res = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0);
2903 if (res == SOCKET_ERROR)
2904 {
2905 DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
2906 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
2907 set_errno ();
2908 return -1;
2909 }
2910 nchars += res;
2911 }
2912 }
2913 #endif
2914 }
2915 else
2916 {
2917 int nread = _read (fd, buffer, count);
2918 if (nread >= 0)
2919 nchars += nread;
2920 else if (nchars == 0)
2921 nchars = nread;
2922 }
2923
2924 if (nchars <= 0)
2925 fd_info[fd].flags |= FILE_AT_EOF;
2926 /* Perform text mode translation if required. */
2927 else if ((fd_info[fd].flags & FILE_BINARY) == 0)
2928 {
2929 nchars = crlf_to_lf (nchars, orig_buffer);
2930 /* If buffer contains only CR, return that. To be absolutely
2931 sure we should attempt to read the next char, but in
2932 practice a CR to be followed by LF would not appear by
2933 itself in the buffer. */
2934 if (nchars > 1 && orig_buffer[nchars - 1] == 0x0d)
2935 {
2936 fd_info[fd].flags |= FILE_LAST_CR;
2937 nchars--;
2938 }
2939 }
2940 }
2941 else
2942 nchars = _read (fd, buffer, count);
2943
2944 return nchars;
2945 }
2946
2947 /* For now, don't bother with a non-blocking mode */
2948 int
2949 sys_write (int fd, const void * buffer, unsigned int count)
2950 {
2951 int nchars;
2952
2953 if (fd < 0 || fd >= MAXDESC)
2954 {
2955 errno = EBADF;
2956 return -1;
2957 }
2958
2959 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
2960 {
2961 if ((fd_info[fd].flags & FILE_WRITE) == 0)
2962 {
2963 errno = EBADF;
2964 return -1;
2965 }
2966
2967 /* Perform text mode translation if required. */
2968 if ((fd_info[fd].flags & FILE_BINARY) == 0)
2969 {
2970 char * tmpbuf = alloca (count * 2);
2971 unsigned char * src = (void *)buffer;
2972 unsigned char * dst = tmpbuf;
2973 int nbytes = count;
2974
2975 while (1)
2976 {
2977 unsigned char *next;
2978 /* copy next line or remaining bytes */
2979 next = _memccpy (dst, src, '\n', nbytes);
2980 if (next)
2981 {
2982 /* copied one line ending with '\n' */
2983 int copied = next - dst;
2984 nbytes -= copied;
2985 src += copied;
2986 /* insert '\r' before '\n' */
2987 next[-1] = '\r';
2988 next[0] = '\n';
2989 dst = next + 1;
2990 count++;
2991 }
2992 else
2993 /* copied remaining partial line -> now finished */
2994 break;
2995 }
2996 buffer = tmpbuf;
2997 }
2998 }
2999
3000 #ifdef HAVE_SOCKETS
3001 if (fd_info[fd].flags & FILE_SOCKET)
3002 {
3003 if (winsock_lib == NULL) abort ();
3004 nchars = pfn_send (SOCK_HANDLE (fd), buffer, count, 0);
3005 if (nchars == SOCKET_ERROR)
3006 {
3007 DebPrint(("sys_read.send failed with error %d on socket %ld\n",
3008 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
3009 set_errno ();
3010 }
3011 }
3012 else
3013 #endif
3014 nchars = _write (fd, buffer, count);
3015
3016 return nchars;
3017 }
3018
3019 static void
3020 check_windows_init_file ()
3021 {
3022 extern int noninteractive, inhibit_window_system;
3023
3024 /* A common indication that Emacs is not installed properly is when
3025 it cannot find the Windows installation file. If this file does
3026 not exist in the expected place, tell the user. */
3027
3028 if (!noninteractive && !inhibit_window_system)
3029 {
3030 extern Lisp_Object Vwindow_system, Vload_path, Qfile_exists_p;
3031 Lisp_Object objs[2];
3032 Lisp_Object full_load_path;
3033 Lisp_Object init_file;
3034 int fd;
3035
3036 objs[0] = Vload_path;
3037 objs[1] = decode_env_path (0, (getenv ("EMACSLOADPATH")));
3038 full_load_path = Fappend (2, objs);
3039 init_file = build_string ("term/w32-win");
3040 fd = openp (full_load_path, init_file, ".el:.elc", NULL, 0);
3041 if (fd < 0)
3042 {
3043 Lisp_Object load_path_print = Fprin1_to_string (full_load_path, Qnil);
3044 char *init_file_name = XSTRING (init_file)->data;
3045 char *load_path = XSTRING (load_path_print)->data;
3046 char *buffer = alloca (1024);
3047
3048 sprintf (buffer,
3049 "The Emacs Windows initialization file \"%s.el\" "
3050 "could not be found in your Emacs installation. "
3051 "Emacs checked the following directories for this file:\n"
3052 "\n%s\n\n"
3053 "When Emacs cannot find this file, it usually means that it "
3054 "was not installed properly, or its distribution file was "
3055 "not unpacked properly.\nSee the README.W32 file in the "
3056 "top-level Emacs directory for more information.",
3057 init_file_name, load_path);
3058 MessageBox (NULL,
3059 buffer,
3060 "Emacs Abort Dialog",
3061 MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
3062 /* Use the low-level Emacs abort. */
3063 #undef abort
3064 abort ();
3065 }
3066 else
3067 {
3068 close (fd);
3069 }
3070 }
3071 }
3072
3073 void
3074 term_ntproc ()
3075 {
3076 #ifdef HAVE_SOCKETS
3077 /* shutdown the socket interface if necessary */
3078 term_winsock ();
3079 #endif
3080 }
3081
3082 void
3083 init_ntproc ()
3084 {
3085 #ifdef HAVE_SOCKETS
3086 /* Initialise the socket interface now if available and requested by
3087 the user by defining PRELOAD_WINSOCK; otherwise loading will be
3088 delayed until open-network-stream is called (w32-has-winsock can
3089 also be used to dynamically load or reload winsock).
3090
3091 Conveniently, init_environment is called before us, so
3092 PRELOAD_WINSOCK can be set in the registry. */
3093
3094 /* Always initialize this correctly. */
3095 winsock_lib = NULL;
3096
3097 if (getenv ("PRELOAD_WINSOCK") != NULL)
3098 init_winsock (TRUE);
3099 #endif
3100
3101 /* Initial preparation for subprocess support: replace our standard
3102 handles with non-inheritable versions. */
3103 {
3104 HANDLE parent;
3105 HANDLE stdin_save = INVALID_HANDLE_VALUE;
3106 HANDLE stdout_save = INVALID_HANDLE_VALUE;
3107 HANDLE stderr_save = INVALID_HANDLE_VALUE;
3108
3109 parent = GetCurrentProcess ();
3110
3111 /* ignore errors when duplicating and closing; typically the
3112 handles will be invalid when running as a gui program. */
3113 DuplicateHandle (parent,
3114 GetStdHandle (STD_INPUT_HANDLE),
3115 parent,
3116 &stdin_save,
3117 0,
3118 FALSE,
3119 DUPLICATE_SAME_ACCESS);
3120
3121 DuplicateHandle (parent,
3122 GetStdHandle (STD_OUTPUT_HANDLE),
3123 parent,
3124 &stdout_save,
3125 0,
3126 FALSE,
3127 DUPLICATE_SAME_ACCESS);
3128
3129 DuplicateHandle (parent,
3130 GetStdHandle (STD_ERROR_HANDLE),
3131 parent,
3132 &stderr_save,
3133 0,
3134 FALSE,
3135 DUPLICATE_SAME_ACCESS);
3136
3137 fclose (stdin);
3138 fclose (stdout);
3139 fclose (stderr);
3140
3141 if (stdin_save != INVALID_HANDLE_VALUE)
3142 _open_osfhandle ((long) stdin_save, O_TEXT);
3143 else
3144 _open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY);
3145 _fdopen (0, "r");
3146
3147 if (stdout_save != INVALID_HANDLE_VALUE)
3148 _open_osfhandle ((long) stdout_save, O_TEXT);
3149 else
3150 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
3151 _fdopen (1, "w");
3152
3153 if (stderr_save != INVALID_HANDLE_VALUE)
3154 _open_osfhandle ((long) stderr_save, O_TEXT);
3155 else
3156 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
3157 _fdopen (2, "w");
3158 }
3159
3160 /* unfortunately, atexit depends on implementation of malloc */
3161 /* atexit (term_ntproc); */
3162 signal (SIGABRT, term_ntproc);
3163
3164 /* determine which drives are fixed, for GetCachedVolumeInformation */
3165 {
3166 /* GetDriveType must have trailing backslash. */
3167 char drive[] = "A:\\";
3168
3169 /* Loop over all possible drive letters */
3170 while (*drive <= 'Z')
3171 {
3172 /* Record if this drive letter refers to a fixed drive. */
3173 fixed_drives[DRIVE_INDEX (*drive)] =
3174 (GetDriveType (drive) == DRIVE_FIXED);
3175
3176 (*drive)++;
3177 }
3178 }
3179
3180 /* Check to see if Emacs has been installed correctly. */
3181 check_windows_init_file ();
3182 }
3183
3184 /* end of nt.c */