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