(compile_pattern_1): Treat non-nil and non-string of
[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, 2000, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21
22 Geoff Voelker (voelker@cs.washington.edu) 7-29-94
23 */
24 #include <stddef.h> /* for offsetof */
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <io.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <ctype.h>
31 #include <signal.h>
32 #include <sys/file.h>
33 #include <sys/time.h>
34 #include <sys/utime.h>
35 #include <mbstring.h> /* for _mbspbrk */
36
37 /* must include CRT headers *before* config.h */
38
39 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 #endif
42
43 #undef access
44 #undef chdir
45 #undef chmod
46 #undef creat
47 #undef ctime
48 #undef fopen
49 #undef link
50 #undef mkdir
51 #undef mktemp
52 #undef open
53 #undef rename
54 #undef rmdir
55 #undef unlink
56
57 #undef close
58 #undef dup
59 #undef dup2
60 #undef pipe
61 #undef read
62 #undef write
63
64 #undef strerror
65
66 #include "lisp.h"
67
68 #include <pwd.h>
69 #include <grp.h>
70
71 #ifdef __GNUC__
72 #define _ANONYMOUS_UNION
73 #define _ANONYMOUS_STRUCT
74 #endif
75 #include <windows.h>
76 #include <shlobj.h>
77
78 #ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
79 #include <sys/socket.h>
80 #undef socket
81 #undef bind
82 #undef connect
83 #undef htons
84 #undef ntohs
85 #undef inet_addr
86 #undef gethostname
87 #undef gethostbyname
88 #undef getservbyname
89 #undef getpeername
90 #undef shutdown
91 #undef setsockopt
92 #undef listen
93 #undef getsockname
94 #undef accept
95 #undef recvfrom
96 #undef sendto
97 #endif
98
99 #include "w32.h"
100 #include "ndir.h"
101 #include "w32heap.h"
102 #include "systime.h"
103
104 typedef HRESULT (WINAPI * ShGetFolderPath_fn)
105 (IN HWND, IN int, IN HANDLE, IN DWORD, OUT char *);
106
107 void globals_of_w32 ();
108
109 extern Lisp_Object Vw32_downcase_file_names;
110 extern Lisp_Object Vw32_generate_fake_inodes;
111 extern Lisp_Object Vw32_get_true_file_attributes;
112 extern int w32_num_mouse_buttons;
113
114 \f
115 /*
116 Initialization states
117 */
118 static BOOL g_b_init_is_windows_9x;
119 static BOOL g_b_init_open_process_token;
120 static BOOL g_b_init_get_token_information;
121 static BOOL g_b_init_lookup_account_sid;
122 static BOOL g_b_init_get_sid_identifier_authority;
123
124 /*
125 BEGIN: Wrapper functions around OpenProcessToken
126 and other functions in advapi32.dll that are only
127 supported in Windows NT / 2k / XP
128 */
129 /* ** Function pointer typedefs ** */
130 typedef BOOL (WINAPI * OpenProcessToken_Proc) (
131 HANDLE ProcessHandle,
132 DWORD DesiredAccess,
133 PHANDLE TokenHandle);
134 typedef BOOL (WINAPI * GetTokenInformation_Proc) (
135 HANDLE TokenHandle,
136 TOKEN_INFORMATION_CLASS TokenInformationClass,
137 LPVOID TokenInformation,
138 DWORD TokenInformationLength,
139 PDWORD ReturnLength);
140 #ifdef _UNICODE
141 const char * const LookupAccountSid_Name = "LookupAccountSidW";
142 #else
143 const char * const LookupAccountSid_Name = "LookupAccountSidA";
144 #endif
145 typedef BOOL (WINAPI * LookupAccountSid_Proc) (
146 LPCTSTR lpSystemName,
147 PSID Sid,
148 LPTSTR Name,
149 LPDWORD cbName,
150 LPTSTR DomainName,
151 LPDWORD cbDomainName,
152 PSID_NAME_USE peUse);
153 typedef PSID_IDENTIFIER_AUTHORITY (WINAPI * GetSidIdentifierAuthority_Proc) (
154 PSID pSid);
155
156 /* ** A utility function ** */
157 static BOOL
158 is_windows_9x ()
159 {
160 static BOOL s_b_ret=0;
161 OSVERSIONINFO os_ver;
162 if (g_b_init_is_windows_9x == 0)
163 {
164 g_b_init_is_windows_9x = 1;
165 ZeroMemory(&os_ver, sizeof(OSVERSIONINFO));
166 os_ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
167 if (GetVersionEx (&os_ver))
168 {
169 s_b_ret = (os_ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
170 }
171 }
172 return s_b_ret;
173 }
174
175 /* ** The wrapper functions ** */
176
177 BOOL WINAPI open_process_token (
178 HANDLE ProcessHandle,
179 DWORD DesiredAccess,
180 PHANDLE TokenHandle)
181 {
182 static OpenProcessToken_Proc s_pfn_Open_Process_Token = NULL;
183 HMODULE hm_advapi32 = NULL;
184 if (is_windows_9x () == TRUE)
185 {
186 return FALSE;
187 }
188 if (g_b_init_open_process_token == 0)
189 {
190 g_b_init_open_process_token = 1;
191 hm_advapi32 = LoadLibrary ("Advapi32.dll");
192 s_pfn_Open_Process_Token =
193 (OpenProcessToken_Proc) GetProcAddress (hm_advapi32, "OpenProcessToken");
194 }
195 if (s_pfn_Open_Process_Token == NULL)
196 {
197 return FALSE;
198 }
199 return (
200 s_pfn_Open_Process_Token (
201 ProcessHandle,
202 DesiredAccess,
203 TokenHandle)
204 );
205 }
206
207 BOOL WINAPI get_token_information (
208 HANDLE TokenHandle,
209 TOKEN_INFORMATION_CLASS TokenInformationClass,
210 LPVOID TokenInformation,
211 DWORD TokenInformationLength,
212 PDWORD ReturnLength)
213 {
214 static GetTokenInformation_Proc s_pfn_Get_Token_Information = NULL;
215 HMODULE hm_advapi32 = NULL;
216 if (is_windows_9x () == TRUE)
217 {
218 return FALSE;
219 }
220 if (g_b_init_get_token_information == 0)
221 {
222 g_b_init_get_token_information = 1;
223 hm_advapi32 = LoadLibrary ("Advapi32.dll");
224 s_pfn_Get_Token_Information =
225 (GetTokenInformation_Proc) GetProcAddress (hm_advapi32, "GetTokenInformation");
226 }
227 if (s_pfn_Get_Token_Information == NULL)
228 {
229 return FALSE;
230 }
231 return (
232 s_pfn_Get_Token_Information (
233 TokenHandle,
234 TokenInformationClass,
235 TokenInformation,
236 TokenInformationLength,
237 ReturnLength)
238 );
239 }
240
241 BOOL WINAPI lookup_account_sid (
242 LPCTSTR lpSystemName,
243 PSID Sid,
244 LPTSTR Name,
245 LPDWORD cbName,
246 LPTSTR DomainName,
247 LPDWORD cbDomainName,
248 PSID_NAME_USE peUse)
249 {
250 static LookupAccountSid_Proc s_pfn_Lookup_Account_Sid = NULL;
251 HMODULE hm_advapi32 = NULL;
252 if (is_windows_9x () == TRUE)
253 {
254 return FALSE;
255 }
256 if (g_b_init_lookup_account_sid == 0)
257 {
258 g_b_init_lookup_account_sid = 1;
259 hm_advapi32 = LoadLibrary ("Advapi32.dll");
260 s_pfn_Lookup_Account_Sid =
261 (LookupAccountSid_Proc) GetProcAddress (hm_advapi32, LookupAccountSid_Name);
262 }
263 if (s_pfn_Lookup_Account_Sid == NULL)
264 {
265 return FALSE;
266 }
267 return (
268 s_pfn_Lookup_Account_Sid (
269 lpSystemName,
270 Sid,
271 Name,
272 cbName,
273 DomainName,
274 cbDomainName,
275 peUse)
276 );
277 }
278
279 PSID_IDENTIFIER_AUTHORITY WINAPI get_sid_identifier_authority (
280 PSID pSid)
281 {
282 static GetSidIdentifierAuthority_Proc s_pfn_Get_Sid_Identifier_Authority = NULL;
283 HMODULE hm_advapi32 = NULL;
284 if (is_windows_9x () == TRUE)
285 {
286 return NULL;
287 }
288 if (g_b_init_get_sid_identifier_authority == 0)
289 {
290 g_b_init_get_sid_identifier_authority = 1;
291 hm_advapi32 = LoadLibrary ("Advapi32.dll");
292 s_pfn_Get_Sid_Identifier_Authority =
293 (GetSidIdentifierAuthority_Proc) GetProcAddress (
294 hm_advapi32, "GetSidIdentifierAuthority");
295 }
296 if (s_pfn_Get_Sid_Identifier_Authority == NULL)
297 {
298 return NULL;
299 }
300 return (s_pfn_Get_Sid_Identifier_Authority (pSid));
301 }
302
303 /*
304 END: Wrapper functions around OpenProcessToken
305 and other functions in advapi32.dll that are only
306 supported in Windows NT / 2k / XP
307 */
308
309 \f
310 /* Equivalent of strerror for W32 error codes. */
311 char *
312 w32_strerror (int error_no)
313 {
314 static char buf[500];
315
316 if (error_no == 0)
317 error_no = GetLastError ();
318
319 buf[0] = '\0';
320 if (!FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL,
321 error_no,
322 0, /* choose most suitable language */
323 buf, sizeof (buf), NULL))
324 sprintf (buf, "w32 error %u", error_no);
325 return buf;
326 }
327
328 /* Return 1 if P is a valid pointer to an object of size SIZE. Return
329 0 if P is NOT a valid pointer. Return -1 if we cannot validate P.
330
331 This is called from alloc.c:valid_pointer_p. */
332 int
333 w32_valid_pointer_p (void *p, int size)
334 {
335 SIZE_T done;
336 HANDLE h = OpenProcess (PROCESS_VM_READ, FALSE, GetCurrentProcessId ());
337
338 if (h)
339 {
340 unsigned char *buf = alloca (size);
341 int retval = ReadProcessMemory (h, p, buf, size, &done);
342
343 CloseHandle (h);
344 return retval;
345 }
346 else
347 return -1;
348 }
349
350 static char startup_dir[MAXPATHLEN];
351
352 /* Get the current working directory. */
353 char *
354 getwd (char *dir)
355 {
356 #if 0
357 if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
358 return dir;
359 return NULL;
360 #else
361 /* Emacs doesn't actually change directory itself, and we want to
362 force our real wd to be where emacs.exe is to avoid unnecessary
363 conflicts when trying to rename or delete directories. */
364 strcpy (dir, startup_dir);
365 return dir;
366 #endif
367 }
368
369 #ifndef HAVE_SOCKETS
370 /* Emulate gethostname. */
371 int
372 gethostname (char *buffer, int size)
373 {
374 /* NT only allows small host names, so the buffer is
375 certainly large enough. */
376 return !GetComputerName (buffer, &size);
377 }
378 #endif /* HAVE_SOCKETS */
379
380 /* Emulate getloadavg. */
381 int
382 getloadavg (double loadavg[], int nelem)
383 {
384 int i;
385
386 /* A faithful emulation is going to have to be saved for a rainy day. */
387 for (i = 0; i < nelem; i++)
388 {
389 loadavg[i] = 0.0;
390 }
391 return i;
392 }
393
394 /* Emulate getpwuid, getpwnam and others. */
395
396 #define PASSWD_FIELD_SIZE 256
397
398 static char the_passwd_name[PASSWD_FIELD_SIZE];
399 static char the_passwd_passwd[PASSWD_FIELD_SIZE];
400 static char the_passwd_gecos[PASSWD_FIELD_SIZE];
401 static char the_passwd_dir[PASSWD_FIELD_SIZE];
402 static char the_passwd_shell[PASSWD_FIELD_SIZE];
403
404 static struct passwd the_passwd =
405 {
406 the_passwd_name,
407 the_passwd_passwd,
408 0,
409 0,
410 0,
411 the_passwd_gecos,
412 the_passwd_dir,
413 the_passwd_shell,
414 };
415
416 static struct group the_group =
417 {
418 /* There are no groups on NT, so we just return "root" as the
419 group name. */
420 "root",
421 };
422
423 int
424 getuid ()
425 {
426 return the_passwd.pw_uid;
427 }
428
429 int
430 geteuid ()
431 {
432 /* I could imagine arguing for checking to see whether the user is
433 in the Administrators group and returning a UID of 0 for that
434 case, but I don't know how wise that would be in the long run. */
435 return getuid ();
436 }
437
438 int
439 getgid ()
440 {
441 return the_passwd.pw_gid;
442 }
443
444 int
445 getegid ()
446 {
447 return getgid ();
448 }
449
450 struct passwd *
451 getpwuid (int uid)
452 {
453 if (uid == the_passwd.pw_uid)
454 return &the_passwd;
455 return NULL;
456 }
457
458 struct group *
459 getgrgid (gid_t gid)
460 {
461 return &the_group;
462 }
463
464 struct passwd *
465 getpwnam (char *name)
466 {
467 struct passwd *pw;
468
469 pw = getpwuid (getuid ());
470 if (!pw)
471 return pw;
472
473 if (stricmp (name, pw->pw_name))
474 return NULL;
475
476 return pw;
477 }
478
479 void
480 init_user_info ()
481 {
482 /* Find the user's real name by opening the process token and
483 looking up the name associated with the user-sid in that token.
484
485 Use the relative portion of the identifier authority value from
486 the user-sid as the user id value (same for group id using the
487 primary group sid from the process token). */
488
489 char user_sid[256], name[256], domain[256];
490 DWORD length = sizeof (name), dlength = sizeof (domain), trash;
491 HANDLE token = NULL;
492 SID_NAME_USE user_type;
493
494 if (open_process_token (GetCurrentProcess (), TOKEN_QUERY, &token)
495 && get_token_information (token, TokenUser,
496 (PVOID) user_sid, sizeof (user_sid), &trash)
497 && lookup_account_sid (NULL, *((PSID *) user_sid), name, &length,
498 domain, &dlength, &user_type))
499 {
500 strcpy (the_passwd.pw_name, name);
501 /* Determine a reasonable uid value. */
502 if (stricmp ("administrator", name) == 0)
503 {
504 the_passwd.pw_uid = 0;
505 the_passwd.pw_gid = 0;
506 }
507 else
508 {
509 SID_IDENTIFIER_AUTHORITY * pSIA;
510
511 pSIA = get_sid_identifier_authority (*((PSID *) user_sid));
512 /* I believe the relative portion is the last 4 bytes (of 6)
513 with msb first. */
514 the_passwd.pw_uid = ((pSIA->Value[2] << 24) +
515 (pSIA->Value[3] << 16) +
516 (pSIA->Value[4] << 8) +
517 (pSIA->Value[5] << 0));
518 /* restrict to conventional uid range for normal users */
519 the_passwd.pw_uid = the_passwd.pw_uid % 60001;
520
521 /* Get group id */
522 if (get_token_information (token, TokenPrimaryGroup,
523 (PVOID) user_sid, sizeof (user_sid), &trash))
524 {
525 SID_IDENTIFIER_AUTHORITY * pSIA;
526
527 pSIA = get_sid_identifier_authority (*((PSID *) user_sid));
528 the_passwd.pw_gid = ((pSIA->Value[2] << 24) +
529 (pSIA->Value[3] << 16) +
530 (pSIA->Value[4] << 8) +
531 (pSIA->Value[5] << 0));
532 /* I don't know if this is necessary, but for safety... */
533 the_passwd.pw_gid = the_passwd.pw_gid % 60001;
534 }
535 else
536 the_passwd.pw_gid = the_passwd.pw_uid;
537 }
538 }
539 /* If security calls are not supported (presumably because we
540 are running under Windows 95), fallback to this. */
541 else if (GetUserName (name, &length))
542 {
543 strcpy (the_passwd.pw_name, name);
544 if (stricmp ("administrator", name) == 0)
545 the_passwd.pw_uid = 0;
546 else
547 the_passwd.pw_uid = 123;
548 the_passwd.pw_gid = the_passwd.pw_uid;
549 }
550 else
551 {
552 strcpy (the_passwd.pw_name, "unknown");
553 the_passwd.pw_uid = 123;
554 the_passwd.pw_gid = 123;
555 }
556
557 /* Ensure HOME and SHELL are defined. */
558 if (getenv ("HOME") == NULL)
559 abort ();
560 if (getenv ("SHELL") == NULL)
561 abort ();
562
563 /* Set dir and shell from environment variables. */
564 strcpy (the_passwd.pw_dir, getenv ("HOME"));
565 strcpy (the_passwd.pw_shell, getenv ("SHELL"));
566
567 if (token)
568 CloseHandle (token);
569 }
570
571 int
572 random ()
573 {
574 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
575 return ((rand () << 15) | rand ());
576 }
577
578 void
579 srandom (int seed)
580 {
581 srand (seed);
582 }
583
584
585 /* Normalize filename by converting all path separators to
586 the specified separator. Also conditionally convert upper
587 case path name components to lower case. */
588
589 static void
590 normalize_filename (fp, path_sep)
591 register char *fp;
592 char path_sep;
593 {
594 char sep;
595 char *elem;
596
597 /* Always lower-case drive letters a-z, even if the filesystem
598 preserves case in filenames.
599 This is so filenames can be compared by string comparison
600 functions that are case-sensitive. Even case-preserving filesystems
601 do not distinguish case in drive letters. */
602 if (fp[1] == ':' && *fp >= 'A' && *fp <= 'Z')
603 {
604 *fp += 'a' - 'A';
605 fp += 2;
606 }
607
608 if (NILP (Vw32_downcase_file_names))
609 {
610 while (*fp)
611 {
612 if (*fp == '/' || *fp == '\\')
613 *fp = path_sep;
614 fp++;
615 }
616 return;
617 }
618
619 sep = path_sep; /* convert to this path separator */
620 elem = fp; /* start of current path element */
621
622 do {
623 if (*fp >= 'a' && *fp <= 'z')
624 elem = 0; /* don't convert this element */
625
626 if (*fp == 0 || *fp == ':')
627 {
628 sep = *fp; /* restore current separator (or 0) */
629 *fp = '/'; /* after conversion of this element */
630 }
631
632 if (*fp == '/' || *fp == '\\')
633 {
634 if (elem && elem != fp)
635 {
636 *fp = 0; /* temporary end of string */
637 _strlwr (elem); /* while we convert to lower case */
638 }
639 *fp = sep; /* convert (or restore) path separator */
640 elem = fp + 1; /* next element starts after separator */
641 sep = path_sep;
642 }
643 } while (*fp++);
644 }
645
646 /* Destructively turn backslashes into slashes. */
647 void
648 dostounix_filename (p)
649 register char *p;
650 {
651 normalize_filename (p, '/');
652 }
653
654 /* Destructively turn slashes into backslashes. */
655 void
656 unixtodos_filename (p)
657 register char *p;
658 {
659 normalize_filename (p, '\\');
660 }
661
662 /* Remove all CR's that are followed by a LF.
663 (From msdos.c...probably should figure out a way to share it,
664 although this code isn't going to ever change.) */
665 int
666 crlf_to_lf (n, buf)
667 register int n;
668 register unsigned char *buf;
669 {
670 unsigned char *np = buf;
671 unsigned char *startp = buf;
672 unsigned char *endp = buf + n;
673
674 if (n == 0)
675 return n;
676 while (buf < endp - 1)
677 {
678 if (*buf == 0x0d)
679 {
680 if (*(++buf) != 0x0a)
681 *np++ = 0x0d;
682 }
683 else
684 *np++ = *buf++;
685 }
686 if (buf < endp)
687 *np++ = *buf++;
688 return np - startp;
689 }
690
691 /* Parse the root part of file name, if present. Return length and
692 optionally store pointer to char after root. */
693 static int
694 parse_root (char * name, char ** pPath)
695 {
696 char * start = name;
697
698 if (name == NULL)
699 return 0;
700
701 /* find the root name of the volume if given */
702 if (isalpha (name[0]) && name[1] == ':')
703 {
704 /* skip past drive specifier */
705 name += 2;
706 if (IS_DIRECTORY_SEP (name[0]))
707 name++;
708 }
709 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
710 {
711 int slashes = 2;
712 name += 2;
713 do
714 {
715 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
716 break;
717 name++;
718 }
719 while ( *name );
720 if (IS_DIRECTORY_SEP (name[0]))
721 name++;
722 }
723
724 if (pPath)
725 *pPath = name;
726
727 return name - start;
728 }
729
730 /* Get long base name for name; name is assumed to be absolute. */
731 static int
732 get_long_basename (char * name, char * buf, int size)
733 {
734 WIN32_FIND_DATA find_data;
735 HANDLE dir_handle;
736 int len = 0;
737
738 /* must be valid filename, no wild cards or other invalid characters */
739 if (_mbspbrk (name, "*?|<>\""))
740 return 0;
741
742 dir_handle = FindFirstFile (name, &find_data);
743 if (dir_handle != INVALID_HANDLE_VALUE)
744 {
745 if ((len = strlen (find_data.cFileName)) < size)
746 memcpy (buf, find_data.cFileName, len + 1);
747 else
748 len = 0;
749 FindClose (dir_handle);
750 }
751 return len;
752 }
753
754 /* Get long name for file, if possible (assumed to be absolute). */
755 BOOL
756 w32_get_long_filename (char * name, char * buf, int size)
757 {
758 char * o = buf;
759 char * p;
760 char * q;
761 char full[ MAX_PATH ];
762 int len;
763
764 len = strlen (name);
765 if (len >= MAX_PATH)
766 return FALSE;
767
768 /* Use local copy for destructive modification. */
769 memcpy (full, name, len+1);
770 unixtodos_filename (full);
771
772 /* Copy root part verbatim. */
773 len = parse_root (full, &p);
774 memcpy (o, full, len);
775 o += len;
776 *o = '\0';
777 size -= len;
778
779 while (p != NULL && *p)
780 {
781 q = p;
782 p = strchr (q, '\\');
783 if (p) *p = '\0';
784 len = get_long_basename (full, o, size);
785 if (len > 0)
786 {
787 o += len;
788 size -= len;
789 if (p != NULL)
790 {
791 *p++ = '\\';
792 if (size < 2)
793 return FALSE;
794 *o++ = '\\';
795 size--;
796 *o = '\0';
797 }
798 }
799 else
800 return FALSE;
801 }
802
803 return TRUE;
804 }
805
806 int
807 is_unc_volume (const char *filename)
808 {
809 const char *ptr = filename;
810
811 if (!IS_DIRECTORY_SEP (ptr[0]) || !IS_DIRECTORY_SEP (ptr[1]) || !ptr[2])
812 return 0;
813
814 if (_mbspbrk (ptr + 2, "*?|<>\"\\/"))
815 return 0;
816
817 return 1;
818 }
819
820 /* Routines that are no-ops on NT but are defined to get Emacs to compile. */
821
822 int
823 sigsetmask (int signal_mask)
824 {
825 return 0;
826 }
827
828 int
829 sigmask (int sig)
830 {
831 return 0;
832 }
833
834 int
835 sigblock (int sig)
836 {
837 return 0;
838 }
839
840 int
841 sigunblock (int sig)
842 {
843 return 0;
844 }
845
846 int
847 setpgrp (int pid, int gid)
848 {
849 return 0;
850 }
851
852 int
853 alarm (int seconds)
854 {
855 return 0;
856 }
857
858 void
859 unrequest_sigio (void)
860 {
861 return;
862 }
863
864 void
865 request_sigio (void)
866 {
867 return;
868 }
869
870 #define REG_ROOT "SOFTWARE\\GNU\\Emacs"
871
872 LPBYTE
873 w32_get_resource (key, lpdwtype)
874 char *key;
875 LPDWORD lpdwtype;
876 {
877 LPBYTE lpvalue;
878 HKEY hrootkey = NULL;
879 DWORD cbData;
880
881 /* Check both the current user and the local machine to see if
882 we have any resources. */
883
884 if (RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
885 {
886 lpvalue = NULL;
887
888 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
889 && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL
890 && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
891 {
892 RegCloseKey (hrootkey);
893 return (lpvalue);
894 }
895
896 if (lpvalue) xfree (lpvalue);
897
898 RegCloseKey (hrootkey);
899 }
900
901 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
902 {
903 lpvalue = NULL;
904
905 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
906 && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL
907 && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
908 {
909 RegCloseKey (hrootkey);
910 return (lpvalue);
911 }
912
913 if (lpvalue) xfree (lpvalue);
914
915 RegCloseKey (hrootkey);
916 }
917
918 return (NULL);
919 }
920
921 char *get_emacs_configuration (void);
922 extern Lisp_Object Vsystem_configuration;
923
924 void
925 init_environment (char ** argv)
926 {
927 static const char * const tempdirs[] = {
928 "$TMPDIR", "$TEMP", "$TMP", "c:/"
929 };
930
931 int i;
932
933 const int imax = sizeof (tempdirs) / sizeof (tempdirs[0]);
934
935 /* Make sure they have a usable $TMPDIR. Many Emacs functions use
936 temporary files and assume "/tmp" if $TMPDIR is unset, which
937 will break on DOS/Windows. Refuse to work if we cannot find
938 a directory, not even "c:/", usable for that purpose. */
939 for (i = 0; i < imax ; i++)
940 {
941 const char *tmp = tempdirs[i];
942
943 if (*tmp == '$')
944 tmp = getenv (tmp + 1);
945 /* Note that `access' can lie to us if the directory resides on a
946 read-only filesystem, like CD-ROM or a write-protected floppy.
947 The only way to be really sure is to actually create a file and
948 see if it succeeds. But I think that's too much to ask. */
949 if (tmp && _access (tmp, D_OK) == 0)
950 {
951 char * var = alloca (strlen (tmp) + 8);
952 sprintf (var, "TMPDIR=%s", tmp);
953 _putenv (strdup (var));
954 break;
955 }
956 }
957 if (i >= imax)
958 cmd_error_internal
959 (Fcons (Qerror,
960 Fcons (build_string ("no usable temporary directories found!!"),
961 Qnil)),
962 "While setting TMPDIR: ");
963
964 /* Check for environment variables and use registry settings if they
965 don't exist. Fallback on default values where applicable. */
966 {
967 int i;
968 LPBYTE lpval;
969 DWORD dwType;
970 char locale_name[32];
971 struct stat ignored;
972 char default_home[MAX_PATH];
973
974 static const struct env_entry
975 {
976 char * name;
977 char * def_value;
978 } dflt_envvars[] =
979 {
980 {"HOME", "C:/"},
981 {"PRELOAD_WINSOCK", NULL},
982 {"emacs_dir", "C:/emacs"},
983 {"EMACSLOADPATH", "%emacs_dir%/site-lisp;%emacs_dir%/../site-lisp;%emacs_dir%/lisp;%emacs_dir%/leim"},
984 {"SHELL", "%emacs_dir%/bin/cmdproxy.exe"},
985 {"EMACSDATA", "%emacs_dir%/etc"},
986 {"EMACSPATH", "%emacs_dir%/bin"},
987 /* We no longer set INFOPATH because Info-default-directory-list
988 is then ignored. */
989 /* {"INFOPATH", "%emacs_dir%/info"}, */
990 {"EMACSDOC", "%emacs_dir%/etc"},
991 {"TERM", "cmd"},
992 {"LANG", NULL},
993 };
994
995 #define N_ENV_VARS sizeof(dflt_envvars)/sizeof(dflt_envvars[0])
996
997 /* We need to copy dflt_envvars[] and work on the copy because we
998 don't want the dumped Emacs to inherit the values of
999 environment variables we saw during dumping (which could be on
1000 a different system). The defaults above must be left intact. */
1001 struct env_entry env_vars[N_ENV_VARS];
1002
1003 for (i = 0; i < N_ENV_VARS; i++)
1004 env_vars[i] = dflt_envvars[i];
1005
1006 /* For backwards compatibility, check if a .emacs file exists in C:/
1007 If not, then we can try to default to the appdata directory under the
1008 user's profile, which is more likely to be writable. */
1009 if (stat ("C:/.emacs", &ignored) < 0)
1010 {
1011 HRESULT profile_result;
1012 /* Dynamically load ShGetFolderPath, as it won't exist on versions
1013 of Windows 95 and NT4 that have not been updated to include
1014 MSIE 5. Also we don't link with shell32.dll by default. */
1015 HMODULE shell32_dll;
1016 ShGetFolderPath_fn get_folder_path;
1017 shell32_dll = GetModuleHandle ("shell32.dll");
1018 get_folder_path = (ShGetFolderPath_fn)
1019 GetProcAddress (shell32_dll, "SHGetFolderPathA");
1020
1021 if (get_folder_path != NULL)
1022 {
1023 profile_result = get_folder_path (NULL, CSIDL_APPDATA, NULL,
1024 0, default_home);
1025
1026 /* If we can't get the appdata dir, revert to old behaviour. */
1027 if (profile_result == S_OK)
1028 env_vars[0].def_value = default_home;
1029 }
1030
1031 /* Unload shell32.dll, it is not needed anymore. */
1032 FreeLibrary (shell32_dll);
1033 }
1034
1035 /* Get default locale info and use it for LANG. */
1036 if (GetLocaleInfo (LOCALE_USER_DEFAULT,
1037 LOCALE_SABBREVLANGNAME | LOCALE_USE_CP_ACP,
1038 locale_name, sizeof (locale_name)))
1039 {
1040 for (i = 0; i < N_ENV_VARS; i++)
1041 {
1042 if (strcmp (env_vars[i].name, "LANG") == 0)
1043 {
1044 env_vars[i].def_value = locale_name;
1045 break;
1046 }
1047 }
1048 }
1049
1050 #define SET_ENV_BUF_SIZE (4 * MAX_PATH) /* to cover EMACSLOADPATH */
1051
1052 /* Treat emacs_dir specially: set it unconditionally based on our
1053 location, if it appears that we are running from the bin subdir
1054 of a standard installation. */
1055 {
1056 char *p;
1057 char modname[MAX_PATH];
1058
1059 if (!GetModuleFileName (NULL, modname, MAX_PATH))
1060 abort ();
1061 if ((p = strrchr (modname, '\\')) == NULL)
1062 abort ();
1063 *p = 0;
1064
1065 if ((p = strrchr (modname, '\\')) && stricmp (p, "\\bin") == 0)
1066 {
1067 char buf[SET_ENV_BUF_SIZE];
1068
1069 *p = 0;
1070 for (p = modname; *p; p++)
1071 if (*p == '\\') *p = '/';
1072
1073 _snprintf (buf, sizeof(buf)-1, "emacs_dir=%s", modname);
1074 _putenv (strdup (buf));
1075 }
1076 /* Handle running emacs from the build directory: src/oo-spd/i386/ */
1077
1078 /* FIXME: should use substring of get_emacs_configuration ().
1079 But I don't think the Windows build supports alpha, mips etc
1080 anymore, so have taken the easy option for now. */
1081 else if (p && stricmp (p, "\\i386") == 0)
1082 {
1083 *p = 0;
1084 p = strrchr (modname, '\\');
1085 if (p != NULL)
1086 {
1087 *p = 0;
1088 p = strrchr (modname, '\\');
1089 if (p && stricmp (p, "\\src") == 0)
1090 {
1091 char buf[SET_ENV_BUF_SIZE];
1092
1093 *p = 0;
1094 for (p = modname; *p; p++)
1095 if (*p == '\\') *p = '/';
1096
1097 _snprintf (buf, sizeof(buf)-1, "emacs_dir=%s", modname);
1098 _putenv (strdup (buf));
1099 }
1100 }
1101 }
1102 }
1103
1104 for (i = 0; i < N_ENV_VARS; i++)
1105 {
1106 if (!getenv (env_vars[i].name))
1107 {
1108 int dont_free = 0;
1109
1110 if ((lpval = w32_get_resource (env_vars[i].name, &dwType)) == NULL
1111 /* Also ignore empty environment variables. */
1112 || *lpval == 0)
1113 {
1114 if (lpval) xfree (lpval);
1115 lpval = env_vars[i].def_value;
1116 dwType = REG_EXPAND_SZ;
1117 dont_free = 1;
1118 }
1119
1120 if (lpval)
1121 {
1122 char buf1[SET_ENV_BUF_SIZE], buf2[SET_ENV_BUF_SIZE];
1123
1124 if (dwType == REG_EXPAND_SZ)
1125 ExpandEnvironmentStrings ((LPSTR) lpval, buf1, sizeof(buf1));
1126 else if (dwType == REG_SZ)
1127 strcpy (buf1, lpval);
1128 if (dwType == REG_EXPAND_SZ || dwType == REG_SZ)
1129 {
1130 _snprintf (buf2, sizeof(buf2)-1, "%s=%s", env_vars[i].name,
1131 buf1);
1132 _putenv (strdup (buf2));
1133 }
1134
1135 if (!dont_free)
1136 xfree (lpval);
1137 }
1138 }
1139 }
1140 }
1141
1142 /* Rebuild system configuration to reflect invoking system. */
1143 Vsystem_configuration = build_string (EMACS_CONFIGURATION);
1144
1145 /* Another special case: on NT, the PATH variable is actually named
1146 "Path" although cmd.exe (perhaps NT itself) arranges for
1147 environment variable lookup and setting to be case insensitive.
1148 However, Emacs assumes a fully case sensitive environment, so we
1149 need to change "Path" to "PATH" to match the expectations of
1150 various elisp packages. We do this by the sneaky method of
1151 modifying the string in the C runtime environ entry.
1152
1153 The same applies to COMSPEC. */
1154 {
1155 char ** envp;
1156
1157 for (envp = environ; *envp; envp++)
1158 if (_strnicmp (*envp, "PATH=", 5) == 0)
1159 memcpy (*envp, "PATH=", 5);
1160 else if (_strnicmp (*envp, "COMSPEC=", 8) == 0)
1161 memcpy (*envp, "COMSPEC=", 8);
1162 }
1163
1164 /* Remember the initial working directory for getwd, then make the
1165 real wd be the location of emacs.exe to avoid conflicts when
1166 renaming or deleting directories. (We also don't call chdir when
1167 running subprocesses for the same reason.) */
1168 if (!GetCurrentDirectory (MAXPATHLEN, startup_dir))
1169 abort ();
1170
1171 {
1172 char *p;
1173 static char modname[MAX_PATH];
1174
1175 if (!GetModuleFileName (NULL, modname, MAX_PATH))
1176 abort ();
1177 if ((p = strrchr (modname, '\\')) == NULL)
1178 abort ();
1179 *p = 0;
1180
1181 SetCurrentDirectory (modname);
1182
1183 /* Ensure argv[0] has the full path to Emacs. */
1184 *p = '\\';
1185 argv[0] = modname;
1186 }
1187
1188 /* Determine if there is a middle mouse button, to allow parse_button
1189 to decide whether right mouse events should be mouse-2 or
1190 mouse-3. */
1191 w32_num_mouse_buttons = GetSystemMetrics (SM_CMOUSEBUTTONS);
1192
1193 init_user_info ();
1194 }
1195
1196 char *
1197 emacs_root_dir (void)
1198 {
1199 static char root_dir[FILENAME_MAX];
1200 const char *p;
1201
1202 p = getenv ("emacs_dir");
1203 if (p == NULL)
1204 abort ();
1205 strcpy (root_dir, p);
1206 root_dir[parse_root (root_dir, NULL)] = '\0';
1207 dostounix_filename (root_dir);
1208 return root_dir;
1209 }
1210
1211 /* We don't have scripts to automatically determine the system configuration
1212 for Emacs before it's compiled, and we don't want to have to make the
1213 user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
1214 routine. */
1215
1216 char *
1217 get_emacs_configuration (void)
1218 {
1219 char *arch, *oem, *os;
1220 int build_num;
1221 static char configuration_buffer[32];
1222
1223 /* Determine the processor type. */
1224 switch (get_processor_type ())
1225 {
1226
1227 #ifdef PROCESSOR_INTEL_386
1228 case PROCESSOR_INTEL_386:
1229 case PROCESSOR_INTEL_486:
1230 case PROCESSOR_INTEL_PENTIUM:
1231 arch = "i386";
1232 break;
1233 #endif
1234
1235 #ifdef PROCESSOR_INTEL_860
1236 case PROCESSOR_INTEL_860:
1237 arch = "i860";
1238 break;
1239 #endif
1240
1241 #ifdef PROCESSOR_MIPS_R2000
1242 case PROCESSOR_MIPS_R2000:
1243 case PROCESSOR_MIPS_R3000:
1244 case PROCESSOR_MIPS_R4000:
1245 arch = "mips";
1246 break;
1247 #endif
1248
1249 #ifdef PROCESSOR_ALPHA_21064
1250 case PROCESSOR_ALPHA_21064:
1251 arch = "alpha";
1252 break;
1253 #endif
1254
1255 default:
1256 arch = "unknown";
1257 break;
1258 }
1259
1260 /* Use the OEM field to reflect the compiler/library combination. */
1261 #ifdef _MSC_VER
1262 #define COMPILER_NAME "msvc"
1263 #else
1264 #ifdef __GNUC__
1265 #define COMPILER_NAME "mingw"
1266 #else
1267 #define COMPILER_NAME "unknown"
1268 #endif
1269 #endif
1270 oem = COMPILER_NAME;
1271
1272 switch (osinfo_cache.dwPlatformId) {
1273 case VER_PLATFORM_WIN32_NT:
1274 os = "nt";
1275 build_num = osinfo_cache.dwBuildNumber;
1276 break;
1277 case VER_PLATFORM_WIN32_WINDOWS:
1278 if (osinfo_cache.dwMinorVersion == 0) {
1279 os = "windows95";
1280 } else {
1281 os = "windows98";
1282 }
1283 build_num = LOWORD (osinfo_cache.dwBuildNumber);
1284 break;
1285 case VER_PLATFORM_WIN32s:
1286 /* Not supported, should not happen. */
1287 os = "windows32s";
1288 build_num = LOWORD (osinfo_cache.dwBuildNumber);
1289 break;
1290 default:
1291 os = "unknown";
1292 build_num = 0;
1293 break;
1294 }
1295
1296 if (osinfo_cache.dwPlatformId == VER_PLATFORM_WIN32_NT) {
1297 sprintf (configuration_buffer, "%s-%s-%s%d.%d.%d", arch, oem, os,
1298 get_w32_major_version (), get_w32_minor_version (), build_num);
1299 } else {
1300 sprintf (configuration_buffer, "%s-%s-%s.%d", arch, oem, os, build_num);
1301 }
1302
1303 return configuration_buffer;
1304 }
1305
1306 char *
1307 get_emacs_configuration_options (void)
1308 {
1309 static char options_buffer[256];
1310
1311 /* Work out the effective configure options for this build. */
1312 #ifdef _MSC_VER
1313 #define COMPILER_VERSION "--with-msvc (%d.%02d)", _MSC_VER / 100, _MSC_VER % 100
1314 #else
1315 #ifdef __GNUC__
1316 #define COMPILER_VERSION "--with-gcc (%d.%d)", __GNUC__, __GNUC_MINOR__
1317 #else
1318 #define COMPILER_VERSION ""
1319 #endif
1320 #endif
1321
1322 sprintf (options_buffer, COMPILER_VERSION);
1323 #ifdef EMACSDEBUG
1324 strcat (options_buffer, " --no-opt");
1325 #endif
1326 #ifdef USER_CFLAGS
1327 strcat (options_buffer, " --cflags");
1328 strcat (options_buffer, USER_CFLAGS);
1329 #endif
1330 #ifdef USER_LDFLAGS
1331 strcat (options_buffer, " --ldflags");
1332 strcat (options_buffer, USER_LDFLAGS);
1333 #endif
1334 return options_buffer;
1335 }
1336
1337
1338 #include <sys/timeb.h>
1339
1340 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
1341 void
1342 gettimeofday (struct timeval *tv, struct timezone *tz)
1343 {
1344 struct _timeb tb;
1345 _ftime (&tb);
1346
1347 tv->tv_sec = tb.time;
1348 tv->tv_usec = tb.millitm * 1000L;
1349 if (tz)
1350 {
1351 tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */
1352 tz->tz_dsttime = tb.dstflag; /* type of dst correction */
1353 }
1354 }
1355
1356 /* ------------------------------------------------------------------------- */
1357 /* IO support and wrapper functions for W32 API. */
1358 /* ------------------------------------------------------------------------- */
1359
1360 /* Place a wrapper around the MSVC version of ctime. It returns NULL
1361 on network directories, so we handle that case here.
1362 (Ulrich Leodolter, 1/11/95). */
1363 char *
1364 sys_ctime (const time_t *t)
1365 {
1366 char *str = (char *) ctime (t);
1367 return (str ? str : "Sun Jan 01 00:00:00 1970");
1368 }
1369
1370 /* Emulate sleep...we could have done this with a define, but that
1371 would necessitate including windows.h in the files that used it.
1372 This is much easier. */
1373 void
1374 sys_sleep (int seconds)
1375 {
1376 Sleep (seconds * 1000);
1377 }
1378
1379 /* Internal MSVC functions for low-level descriptor munging */
1380 extern int __cdecl _set_osfhnd (int fd, long h);
1381 extern int __cdecl _free_osfhnd (int fd);
1382
1383 /* parallel array of private info on file handles */
1384 filedesc fd_info [ MAXDESC ];
1385
1386 typedef struct volume_info_data {
1387 struct volume_info_data * next;
1388
1389 /* time when info was obtained */
1390 DWORD timestamp;
1391
1392 /* actual volume info */
1393 char * root_dir;
1394 DWORD serialnum;
1395 DWORD maxcomp;
1396 DWORD flags;
1397 char * name;
1398 char * type;
1399 } volume_info_data;
1400
1401 /* Global referenced by various functions. */
1402 static volume_info_data volume_info;
1403
1404 /* Vector to indicate which drives are local and fixed (for which cached
1405 data never expires). */
1406 static BOOL fixed_drives[26];
1407
1408 /* Consider cached volume information to be stale if older than 10s,
1409 at least for non-local drives. Info for fixed drives is never stale. */
1410 #define DRIVE_INDEX( c ) ( (c) <= 'Z' ? (c) - 'A' : (c) - 'a' )
1411 #define VOLINFO_STILL_VALID( root_dir, info ) \
1412 ( ( isalpha (root_dir[0]) && \
1413 fixed_drives[ DRIVE_INDEX (root_dir[0]) ] ) \
1414 || GetTickCount () - info->timestamp < 10000 )
1415
1416 /* Cache support functions. */
1417
1418 /* Simple linked list with linear search is sufficient. */
1419 static volume_info_data *volume_cache = NULL;
1420
1421 static volume_info_data *
1422 lookup_volume_info (char * root_dir)
1423 {
1424 volume_info_data * info;
1425
1426 for (info = volume_cache; info; info = info->next)
1427 if (stricmp (info->root_dir, root_dir) == 0)
1428 break;
1429 return info;
1430 }
1431
1432 static void
1433 add_volume_info (char * root_dir, volume_info_data * info)
1434 {
1435 info->root_dir = xstrdup (root_dir);
1436 info->next = volume_cache;
1437 volume_cache = info;
1438 }
1439
1440
1441 /* Wrapper for GetVolumeInformation, which uses caching to avoid
1442 performance penalty (~2ms on 486 for local drives, 7.5ms for local
1443 cdrom drive, ~5-10ms or more for remote drives on LAN). */
1444 volume_info_data *
1445 GetCachedVolumeInformation (char * root_dir)
1446 {
1447 volume_info_data * info;
1448 char default_root[ MAX_PATH ];
1449
1450 /* NULL for root_dir means use root from current directory. */
1451 if (root_dir == NULL)
1452 {
1453 if (GetCurrentDirectory (MAX_PATH, default_root) == 0)
1454 return NULL;
1455 parse_root (default_root, &root_dir);
1456 *root_dir = 0;
1457 root_dir = default_root;
1458 }
1459
1460 /* Local fixed drives can be cached permanently. Removable drives
1461 cannot be cached permanently, since the volume name and serial
1462 number (if nothing else) can change. Remote drives should be
1463 treated as if they are removable, since there is no sure way to
1464 tell whether they are or not. Also, the UNC association of drive
1465 letters mapped to remote volumes can be changed at any time (even
1466 by other processes) without notice.
1467
1468 As a compromise, so we can benefit from caching info for remote
1469 volumes, we use a simple expiry mechanism to invalidate cache
1470 entries that are more than ten seconds old. */
1471
1472 #if 0
1473 /* No point doing this, because WNetGetConnection is even slower than
1474 GetVolumeInformation, consistently taking ~50ms on a 486 (FWIW,
1475 GetDriveType is about the only call of this type which does not
1476 involve network access, and so is extremely quick). */
1477
1478 /* Map drive letter to UNC if remote. */
1479 if ( isalpha( root_dir[0] ) && !fixed[ DRIVE_INDEX( root_dir[0] ) ] )
1480 {
1481 char remote_name[ 256 ];
1482 char drive[3] = { root_dir[0], ':' };
1483
1484 if (WNetGetConnection (drive, remote_name, sizeof (remote_name))
1485 == NO_ERROR)
1486 /* do something */ ;
1487 }
1488 #endif
1489
1490 info = lookup_volume_info (root_dir);
1491
1492 if (info == NULL || ! VOLINFO_STILL_VALID (root_dir, info))
1493 {
1494 char name[ 256 ];
1495 DWORD serialnum;
1496 DWORD maxcomp;
1497 DWORD flags;
1498 char type[ 256 ];
1499
1500 /* Info is not cached, or is stale. */
1501 if (!GetVolumeInformation (root_dir,
1502 name, sizeof (name),
1503 &serialnum,
1504 &maxcomp,
1505 &flags,
1506 type, sizeof (type)))
1507 return NULL;
1508
1509 /* Cache the volume information for future use, overwriting existing
1510 entry if present. */
1511 if (info == NULL)
1512 {
1513 info = (volume_info_data *) xmalloc (sizeof (volume_info_data));
1514 add_volume_info (root_dir, info);
1515 }
1516 else
1517 {
1518 xfree (info->name);
1519 xfree (info->type);
1520 }
1521
1522 info->name = xstrdup (name);
1523 info->serialnum = serialnum;
1524 info->maxcomp = maxcomp;
1525 info->flags = flags;
1526 info->type = xstrdup (type);
1527 info->timestamp = GetTickCount ();
1528 }
1529
1530 return info;
1531 }
1532
1533 /* Get information on the volume where name is held; set path pointer to
1534 start of pathname in name (past UNC header\volume header if present). */
1535 int
1536 get_volume_info (const char * name, const char ** pPath)
1537 {
1538 char temp[MAX_PATH];
1539 char *rootname = NULL; /* default to current volume */
1540 volume_info_data * info;
1541
1542 if (name == NULL)
1543 return FALSE;
1544
1545 /* find the root name of the volume if given */
1546 if (isalpha (name[0]) && name[1] == ':')
1547 {
1548 rootname = temp;
1549 temp[0] = *name++;
1550 temp[1] = *name++;
1551 temp[2] = '\\';
1552 temp[3] = 0;
1553 }
1554 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
1555 {
1556 char *str = temp;
1557 int slashes = 4;
1558 rootname = temp;
1559 do
1560 {
1561 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
1562 break;
1563 *str++ = *name++;
1564 }
1565 while ( *name );
1566
1567 *str++ = '\\';
1568 *str = 0;
1569 }
1570
1571 if (pPath)
1572 *pPath = name;
1573
1574 info = GetCachedVolumeInformation (rootname);
1575 if (info != NULL)
1576 {
1577 /* Set global referenced by other functions. */
1578 volume_info = *info;
1579 return TRUE;
1580 }
1581 return FALSE;
1582 }
1583
1584 /* Determine if volume is FAT format (ie. only supports short 8.3
1585 names); also set path pointer to start of pathname in name. */
1586 int
1587 is_fat_volume (const char * name, const char ** pPath)
1588 {
1589 if (get_volume_info (name, pPath))
1590 return (volume_info.maxcomp == 12);
1591 return FALSE;
1592 }
1593
1594 /* Map filename to a valid 8.3 name if necessary. */
1595 const char *
1596 map_w32_filename (const char * name, const char ** pPath)
1597 {
1598 static char shortname[MAX_PATH];
1599 char * str = shortname;
1600 char c;
1601 char * path;
1602 const char * save_name = name;
1603
1604 if (strlen (name) >= MAX_PATH)
1605 {
1606 /* Return a filename which will cause callers to fail. */
1607 strcpy (shortname, "?");
1608 return shortname;
1609 }
1610
1611 if (is_fat_volume (name, (const char **)&path)) /* truncate to 8.3 */
1612 {
1613 register int left = 8; /* maximum number of chars in part */
1614 register int extn = 0; /* extension added? */
1615 register int dots = 2; /* maximum number of dots allowed */
1616
1617 while (name < path)
1618 *str++ = *name++; /* skip past UNC header */
1619
1620 while ((c = *name++))
1621 {
1622 switch ( c )
1623 {
1624 case '\\':
1625 case '/':
1626 *str++ = '\\';
1627 extn = 0; /* reset extension flags */
1628 dots = 2; /* max 2 dots */
1629 left = 8; /* max length 8 for main part */
1630 break;
1631 case ':':
1632 *str++ = ':';
1633 extn = 0; /* reset extension flags */
1634 dots = 2; /* max 2 dots */
1635 left = 8; /* max length 8 for main part */
1636 break;
1637 case '.':
1638 if ( dots )
1639 {
1640 /* Convert path components of the form .xxx to _xxx,
1641 but leave . and .. as they are. This allows .emacs
1642 to be read as _emacs, for example. */
1643
1644 if (! *name ||
1645 *name == '.' ||
1646 IS_DIRECTORY_SEP (*name))
1647 {
1648 *str++ = '.';
1649 dots--;
1650 }
1651 else
1652 {
1653 *str++ = '_';
1654 left--;
1655 dots = 0;
1656 }
1657 }
1658 else if ( !extn )
1659 {
1660 *str++ = '.';
1661 extn = 1; /* we've got an extension */
1662 left = 3; /* 3 chars in extension */
1663 }
1664 else
1665 {
1666 /* any embedded dots after the first are converted to _ */
1667 *str++ = '_';
1668 }
1669 break;
1670 case '~':
1671 case '#': /* don't lose these, they're important */
1672 if ( ! left )
1673 str[-1] = c; /* replace last character of part */
1674 /* FALLTHRU */
1675 default:
1676 if ( left )
1677 {
1678 *str++ = tolower (c); /* map to lower case (looks nicer) */
1679 left--;
1680 dots = 0; /* started a path component */
1681 }
1682 break;
1683 }
1684 }
1685 *str = '\0';
1686 }
1687 else
1688 {
1689 strcpy (shortname, name);
1690 unixtodos_filename (shortname);
1691 }
1692
1693 if (pPath)
1694 *pPath = shortname + (path - save_name);
1695
1696 return shortname;
1697 }
1698
1699 static int
1700 is_exec (const char * name)
1701 {
1702 char * p = strrchr (name, '.');
1703 return
1704 (p != NULL
1705 && (stricmp (p, ".exe") == 0 ||
1706 stricmp (p, ".com") == 0 ||
1707 stricmp (p, ".bat") == 0 ||
1708 stricmp (p, ".cmd") == 0));
1709 }
1710
1711 /* Emulate the Unix directory procedures opendir, closedir,
1712 and readdir. We can't use the procedures supplied in sysdep.c,
1713 so we provide them here. */
1714
1715 struct direct dir_static; /* simulated directory contents */
1716 static HANDLE dir_find_handle = INVALID_HANDLE_VALUE;
1717 static int dir_is_fat;
1718 static char dir_pathname[MAXPATHLEN+1];
1719 static WIN32_FIND_DATA dir_find_data;
1720
1721 /* Support shares on a network resource as subdirectories of a read-only
1722 root directory. */
1723 static HANDLE wnet_enum_handle = INVALID_HANDLE_VALUE;
1724 HANDLE open_unc_volume (const char *);
1725 char *read_unc_volume (HANDLE, char *, int);
1726 void close_unc_volume (HANDLE);
1727
1728 DIR *
1729 opendir (char *filename)
1730 {
1731 DIR *dirp;
1732
1733 /* Opening is done by FindFirstFile. However, a read is inherent to
1734 this operation, so we defer the open until read time. */
1735
1736 if (dir_find_handle != INVALID_HANDLE_VALUE)
1737 return NULL;
1738 if (wnet_enum_handle != INVALID_HANDLE_VALUE)
1739 return NULL;
1740
1741 if (is_unc_volume (filename))
1742 {
1743 wnet_enum_handle = open_unc_volume (filename);
1744 if (wnet_enum_handle == INVALID_HANDLE_VALUE)
1745 return NULL;
1746 }
1747
1748 if (!(dirp = (DIR *) malloc (sizeof (DIR))))
1749 return NULL;
1750
1751 dirp->dd_fd = 0;
1752 dirp->dd_loc = 0;
1753 dirp->dd_size = 0;
1754
1755 strncpy (dir_pathname, map_w32_filename (filename, NULL), MAXPATHLEN);
1756 dir_pathname[MAXPATHLEN] = '\0';
1757 dir_is_fat = is_fat_volume (filename, NULL);
1758
1759 return dirp;
1760 }
1761
1762 void
1763 closedir (DIR *dirp)
1764 {
1765 /* If we have a find-handle open, close it. */
1766 if (dir_find_handle != INVALID_HANDLE_VALUE)
1767 {
1768 FindClose (dir_find_handle);
1769 dir_find_handle = INVALID_HANDLE_VALUE;
1770 }
1771 else if (wnet_enum_handle != INVALID_HANDLE_VALUE)
1772 {
1773 close_unc_volume (wnet_enum_handle);
1774 wnet_enum_handle = INVALID_HANDLE_VALUE;
1775 }
1776 xfree ((char *) dirp);
1777 }
1778
1779 struct direct *
1780 readdir (DIR *dirp)
1781 {
1782 int downcase = !NILP (Vw32_downcase_file_names);
1783
1784 if (wnet_enum_handle != INVALID_HANDLE_VALUE)
1785 {
1786 if (!read_unc_volume (wnet_enum_handle,
1787 dir_find_data.cFileName,
1788 MAX_PATH))
1789 return NULL;
1790 }
1791 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
1792 else if (dir_find_handle == INVALID_HANDLE_VALUE)
1793 {
1794 char filename[MAXNAMLEN + 3];
1795 int ln;
1796
1797 strcpy (filename, dir_pathname);
1798 ln = strlen (filename) - 1;
1799 if (!IS_DIRECTORY_SEP (filename[ln]))
1800 strcat (filename, "\\");
1801 strcat (filename, "*");
1802
1803 dir_find_handle = FindFirstFile (filename, &dir_find_data);
1804
1805 if (dir_find_handle == INVALID_HANDLE_VALUE)
1806 return NULL;
1807 }
1808 else
1809 {
1810 if (!FindNextFile (dir_find_handle, &dir_find_data))
1811 return NULL;
1812 }
1813
1814 /* Emacs never uses this value, so don't bother making it match
1815 value returned by stat(). */
1816 dir_static.d_ino = 1;
1817
1818 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 +
1819 dir_static.d_namlen - dir_static.d_namlen % 4;
1820
1821 /* If the file name in cFileName[] includes `?' characters, it means
1822 the original file name used characters that cannot be represented
1823 by the current ANSI codepage. To avoid total lossage, retrieve
1824 the short 8+3 alias of the long file name. */
1825 if (_mbspbrk (dir_find_data.cFileName, "?"))
1826 {
1827 strcpy (dir_static.d_name, dir_find_data.cAlternateFileName);
1828 /* 8+3 aliases are returned in all caps, which could break
1829 various alists that look at filenames' extensions. */
1830 downcase = 1;
1831 }
1832 else
1833 strcpy (dir_static.d_name, dir_find_data.cFileName);
1834 dir_static.d_namlen = strlen (dir_static.d_name);
1835 if (dir_is_fat)
1836 _strlwr (dir_static.d_name);
1837 else if (downcase)
1838 {
1839 register char *p;
1840 for (p = dir_static.d_name; *p; p++)
1841 if (*p >= 'a' && *p <= 'z')
1842 break;
1843 if (!*p)
1844 _strlwr (dir_static.d_name);
1845 }
1846
1847 return &dir_static;
1848 }
1849
1850 HANDLE
1851 open_unc_volume (const char *path)
1852 {
1853 NETRESOURCE nr;
1854 HANDLE henum;
1855 int result;
1856
1857 nr.dwScope = RESOURCE_GLOBALNET;
1858 nr.dwType = RESOURCETYPE_DISK;
1859 nr.dwDisplayType = RESOURCEDISPLAYTYPE_SERVER;
1860 nr.dwUsage = RESOURCEUSAGE_CONTAINER;
1861 nr.lpLocalName = NULL;
1862 nr.lpRemoteName = (LPSTR)map_w32_filename (path, NULL);
1863 nr.lpComment = NULL;
1864 nr.lpProvider = NULL;
1865
1866 result = WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK,
1867 RESOURCEUSAGE_CONNECTABLE, &nr, &henum);
1868
1869 if (result == NO_ERROR)
1870 return henum;
1871 else
1872 return INVALID_HANDLE_VALUE;
1873 }
1874
1875 char *
1876 read_unc_volume (HANDLE henum, char *readbuf, int size)
1877 {
1878 DWORD count;
1879 int result;
1880 DWORD bufsize = 512;
1881 char *buffer;
1882 char *ptr;
1883
1884 count = 1;
1885 buffer = alloca (bufsize);
1886 result = WNetEnumResource (wnet_enum_handle, &count, buffer, &bufsize);
1887 if (result != NO_ERROR)
1888 return NULL;
1889
1890 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
1891 ptr = ((LPNETRESOURCE) buffer)->lpRemoteName;
1892 ptr += 2;
1893 while (*ptr && !IS_DIRECTORY_SEP (*ptr)) ptr++;
1894 ptr++;
1895
1896 strncpy (readbuf, ptr, size);
1897 return readbuf;
1898 }
1899
1900 void
1901 close_unc_volume (HANDLE henum)
1902 {
1903 if (henum != INVALID_HANDLE_VALUE)
1904 WNetCloseEnum (henum);
1905 }
1906
1907 DWORD
1908 unc_volume_file_attributes (const char *path)
1909 {
1910 HANDLE henum;
1911 DWORD attrs;
1912
1913 henum = open_unc_volume (path);
1914 if (henum == INVALID_HANDLE_VALUE)
1915 return -1;
1916
1917 attrs = FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_DIRECTORY;
1918
1919 close_unc_volume (henum);
1920
1921 return attrs;
1922 }
1923
1924
1925 /* Shadow some MSVC runtime functions to map requests for long filenames
1926 to reasonable short names if necessary. This was originally added to
1927 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
1928 long file names. */
1929
1930 int
1931 sys_access (const char * path, int mode)
1932 {
1933 DWORD attributes;
1934
1935 /* MSVC implementation doesn't recognize D_OK. */
1936 path = map_w32_filename (path, NULL);
1937 if (is_unc_volume (path))
1938 {
1939 attributes = unc_volume_file_attributes (path);
1940 if (attributes == -1) {
1941 errno = EACCES;
1942 return -1;
1943 }
1944 }
1945 else if ((attributes = GetFileAttributes (path)) == -1)
1946 {
1947 /* Should try mapping GetLastError to errno; for now just indicate
1948 that path doesn't exist. */
1949 errno = EACCES;
1950 return -1;
1951 }
1952 if ((mode & X_OK) != 0 && !is_exec (path))
1953 {
1954 errno = EACCES;
1955 return -1;
1956 }
1957 if ((mode & W_OK) != 0 && (attributes & FILE_ATTRIBUTE_READONLY) != 0)
1958 {
1959 errno = EACCES;
1960 return -1;
1961 }
1962 if ((mode & D_OK) != 0 && (attributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
1963 {
1964 errno = EACCES;
1965 return -1;
1966 }
1967 return 0;
1968 }
1969
1970 int
1971 sys_chdir (const char * path)
1972 {
1973 return _chdir (map_w32_filename (path, NULL));
1974 }
1975
1976 int
1977 sys_chmod (const char * path, int mode)
1978 {
1979 return _chmod (map_w32_filename (path, NULL), mode);
1980 }
1981
1982 int
1983 sys_chown (const char *path, uid_t owner, gid_t group)
1984 {
1985 if (sys_chmod (path, _S_IREAD) == -1) /* check if file exists */
1986 return -1;
1987 return 0;
1988 }
1989
1990 int
1991 sys_creat (const char * path, int mode)
1992 {
1993 return _creat (map_w32_filename (path, NULL), mode);
1994 }
1995
1996 FILE *
1997 sys_fopen(const char * path, const char * mode)
1998 {
1999 int fd;
2000 int oflag;
2001 const char * mode_save = mode;
2002
2003 /* Force all file handles to be non-inheritable. This is necessary to
2004 ensure child processes don't unwittingly inherit handles that might
2005 prevent future file access. */
2006
2007 if (mode[0] == 'r')
2008 oflag = O_RDONLY;
2009 else if (mode[0] == 'w' || mode[0] == 'a')
2010 oflag = O_WRONLY | O_CREAT | O_TRUNC;
2011 else
2012 return NULL;
2013
2014 /* Only do simplistic option parsing. */
2015 while (*++mode)
2016 if (mode[0] == '+')
2017 {
2018 oflag &= ~(O_RDONLY | O_WRONLY);
2019 oflag |= O_RDWR;
2020 }
2021 else if (mode[0] == 'b')
2022 {
2023 oflag &= ~O_TEXT;
2024 oflag |= O_BINARY;
2025 }
2026 else if (mode[0] == 't')
2027 {
2028 oflag &= ~O_BINARY;
2029 oflag |= O_TEXT;
2030 }
2031 else break;
2032
2033 fd = _open (map_w32_filename (path, NULL), oflag | _O_NOINHERIT, 0644);
2034 if (fd < 0)
2035 return NULL;
2036
2037 return _fdopen (fd, mode_save);
2038 }
2039
2040 /* This only works on NTFS volumes, but is useful to have. */
2041 int
2042 sys_link (const char * old, const char * new)
2043 {
2044 HANDLE fileh;
2045 int result = -1;
2046 char oldname[MAX_PATH], newname[MAX_PATH];
2047
2048 if (old == NULL || new == NULL)
2049 {
2050 errno = ENOENT;
2051 return -1;
2052 }
2053
2054 strcpy (oldname, map_w32_filename (old, NULL));
2055 strcpy (newname, map_w32_filename (new, NULL));
2056
2057 fileh = CreateFile (oldname, 0, 0, NULL, OPEN_EXISTING,
2058 FILE_FLAG_BACKUP_SEMANTICS, NULL);
2059 if (fileh != INVALID_HANDLE_VALUE)
2060 {
2061 int wlen;
2062
2063 /* Confusingly, the "alternate" stream name field does not apply
2064 when restoring a hard link, and instead contains the actual
2065 stream data for the link (ie. the name of the link to create).
2066 The WIN32_STREAM_ID structure before the cStreamName field is
2067 the stream header, which is then immediately followed by the
2068 stream data. */
2069
2070 struct {
2071 WIN32_STREAM_ID wid;
2072 WCHAR wbuffer[MAX_PATH]; /* extra space for link name */
2073 } data;
2074
2075 wlen = MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, newname, -1,
2076 data.wid.cStreamName, MAX_PATH);
2077 if (wlen > 0)
2078 {
2079 LPVOID context = NULL;
2080 DWORD wbytes = 0;
2081
2082 data.wid.dwStreamId = BACKUP_LINK;
2083 data.wid.dwStreamAttributes = 0;
2084 data.wid.Size.LowPart = wlen * sizeof(WCHAR);
2085 data.wid.Size.HighPart = 0;
2086 data.wid.dwStreamNameSize = 0;
2087
2088 if (BackupWrite (fileh, (LPBYTE)&data,
2089 offsetof (WIN32_STREAM_ID, cStreamName)
2090 + data.wid.Size.LowPart,
2091 &wbytes, FALSE, FALSE, &context)
2092 && BackupWrite (fileh, NULL, 0, &wbytes, TRUE, FALSE, &context))
2093 {
2094 /* succeeded */
2095 result = 0;
2096 }
2097 else
2098 {
2099 /* Should try mapping GetLastError to errno; for now just
2100 indicate a general error (eg. links not supported). */
2101 errno = EINVAL; // perhaps EMLINK?
2102 }
2103 }
2104
2105 CloseHandle (fileh);
2106 }
2107 else
2108 errno = ENOENT;
2109
2110 return result;
2111 }
2112
2113 int
2114 sys_mkdir (const char * path)
2115 {
2116 return _mkdir (map_w32_filename (path, NULL));
2117 }
2118
2119 /* Because of long name mapping issues, we need to implement this
2120 ourselves. Also, MSVC's _mktemp returns NULL when it can't generate
2121 a unique name, instead of setting the input template to an empty
2122 string.
2123
2124 Standard algorithm seems to be use pid or tid with a letter on the
2125 front (in place of the 6 X's) and cycle through the letters to find a
2126 unique name. We extend that to allow any reasonable character as the
2127 first of the 6 X's. */
2128 char *
2129 sys_mktemp (char * template)
2130 {
2131 char * p;
2132 int i;
2133 unsigned uid = GetCurrentThreadId ();
2134 static char first_char[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#";
2135
2136 if (template == NULL)
2137 return NULL;
2138 p = template + strlen (template);
2139 i = 5;
2140 /* replace up to the last 5 X's with uid in decimal */
2141 while (--p >= template && p[0] == 'X' && --i >= 0)
2142 {
2143 p[0] = '0' + uid % 10;
2144 uid /= 10;
2145 }
2146
2147 if (i < 0 && p[0] == 'X')
2148 {
2149 i = 0;
2150 do
2151 {
2152 int save_errno = errno;
2153 p[0] = first_char[i];
2154 if (sys_access (template, 0) < 0)
2155 {
2156 errno = save_errno;
2157 return template;
2158 }
2159 }
2160 while (++i < sizeof (first_char));
2161 }
2162
2163 /* Template is badly formed or else we can't generate a unique name,
2164 so return empty string */
2165 template[0] = 0;
2166 return template;
2167 }
2168
2169 int
2170 sys_open (const char * path, int oflag, int mode)
2171 {
2172 const char* mpath = map_w32_filename (path, NULL);
2173 /* Try to open file without _O_CREAT, to be able to write to hidden
2174 and system files. Force all file handles to be
2175 non-inheritable. */
2176 int res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode);
2177 if (res >= 0)
2178 return res;
2179 return _open (mpath, oflag | _O_NOINHERIT, mode);
2180 }
2181
2182 int
2183 sys_rename (const char * oldname, const char * newname)
2184 {
2185 BOOL result;
2186 char temp[MAX_PATH];
2187
2188 /* MoveFile on Windows 95 doesn't correctly change the short file name
2189 alias in a number of circumstances (it is not easy to predict when
2190 just by looking at oldname and newname, unfortunately). In these
2191 cases, renaming through a temporary name avoids the problem.
2192
2193 A second problem on Windows 95 is that renaming through a temp name when
2194 newname is uppercase fails (the final long name ends up in
2195 lowercase, although the short alias might be uppercase) UNLESS the
2196 long temp name is not 8.3.
2197
2198 So, on Windows 95 we always rename through a temp name, and we make sure
2199 the temp name has a long extension to ensure correct renaming. */
2200
2201 strcpy (temp, map_w32_filename (oldname, NULL));
2202
2203 if (os_subtype == OS_WIN95)
2204 {
2205 char * o;
2206 char * p;
2207 int i = 0;
2208
2209 oldname = map_w32_filename (oldname, NULL);
2210 if (o = strrchr (oldname, '\\'))
2211 o++;
2212 else
2213 o = (char *) oldname;
2214
2215 if (p = strrchr (temp, '\\'))
2216 p++;
2217 else
2218 p = temp;
2219
2220 do
2221 {
2222 /* Force temp name to require a manufactured 8.3 alias - this
2223 seems to make the second rename work properly. */
2224 sprintf (p, "_.%s.%u", o, i);
2225 i++;
2226 result = rename (oldname, temp);
2227 }
2228 /* This loop must surely terminate! */
2229 while (result < 0 && errno == EEXIST);
2230 if (result < 0)
2231 return -1;
2232 }
2233
2234 /* Emulate Unix behaviour - newname is deleted if it already exists
2235 (at least if it is a file; don't do this for directories).
2236
2237 Since we mustn't do this if we are just changing the case of the
2238 file name (we would end up deleting the file we are trying to
2239 rename!), we let rename detect if the destination file already
2240 exists - that way we avoid the possible pitfalls of trying to
2241 determine ourselves whether two names really refer to the same
2242 file, which is not always possible in the general case. (Consider
2243 all the permutations of shared or subst'd drives, etc.) */
2244
2245 newname = map_w32_filename (newname, NULL);
2246 result = rename (temp, newname);
2247
2248 if (result < 0
2249 && errno == EEXIST
2250 && _chmod (newname, 0666) == 0
2251 && _unlink (newname) == 0)
2252 result = rename (temp, newname);
2253
2254 return result;
2255 }
2256
2257 int
2258 sys_rmdir (const char * path)
2259 {
2260 return _rmdir (map_w32_filename (path, NULL));
2261 }
2262
2263 int
2264 sys_unlink (const char * path)
2265 {
2266 path = map_w32_filename (path, NULL);
2267
2268 /* On Unix, unlink works without write permission. */
2269 _chmod (path, 0666);
2270 return _unlink (path);
2271 }
2272
2273 static FILETIME utc_base_ft;
2274 static long double utc_base;
2275 static int init = 0;
2276
2277 static time_t
2278 convert_time (FILETIME ft)
2279 {
2280 long double ret;
2281
2282 if (!init)
2283 {
2284 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
2285 SYSTEMTIME st;
2286
2287 st.wYear = 1970;
2288 st.wMonth = 1;
2289 st.wDay = 1;
2290 st.wHour = 0;
2291 st.wMinute = 0;
2292 st.wSecond = 0;
2293 st.wMilliseconds = 0;
2294
2295 SystemTimeToFileTime (&st, &utc_base_ft);
2296 utc_base = (long double) utc_base_ft.dwHighDateTime
2297 * 4096.0L * 1024.0L * 1024.0L + utc_base_ft.dwLowDateTime;
2298 init = 1;
2299 }
2300
2301 if (CompareFileTime (&ft, &utc_base_ft) < 0)
2302 return 0;
2303
2304 ret = (long double) ft.dwHighDateTime
2305 * 4096.0L * 1024.0L * 1024.0L + ft.dwLowDateTime;
2306 ret -= utc_base;
2307 return (time_t) (ret * 1e-7L);
2308 }
2309
2310 void
2311 convert_from_time_t (time_t time, FILETIME * pft)
2312 {
2313 long double tmp;
2314
2315 if (!init)
2316 {
2317 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
2318 SYSTEMTIME st;
2319
2320 st.wYear = 1970;
2321 st.wMonth = 1;
2322 st.wDay = 1;
2323 st.wHour = 0;
2324 st.wMinute = 0;
2325 st.wSecond = 0;
2326 st.wMilliseconds = 0;
2327
2328 SystemTimeToFileTime (&st, &utc_base_ft);
2329 utc_base = (long double) utc_base_ft.dwHighDateTime
2330 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
2331 init = 1;
2332 }
2333
2334 /* time in 100ns units since 1-Jan-1601 */
2335 tmp = (long double) time * 1e7 + utc_base;
2336 pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024));
2337 pft->dwLowDateTime = (DWORD) (tmp - (4096.0 * 1024 * 1024) * pft->dwHighDateTime);
2338 }
2339
2340 #if 0
2341 /* No reason to keep this; faking inode values either by hashing or even
2342 using the file index from GetInformationByHandle, is not perfect and
2343 so by default Emacs doesn't use the inode values on Windows.
2344 Instead, we now determine file-truename correctly (except for
2345 possible drive aliasing etc). */
2346
2347 /* Modified version of "PJW" algorithm (see the "Dragon" compiler book). */
2348 static unsigned
2349 hashval (const unsigned char * str)
2350 {
2351 unsigned h = 0;
2352 while (*str)
2353 {
2354 h = (h << 4) + *str++;
2355 h ^= (h >> 28);
2356 }
2357 return h;
2358 }
2359
2360 /* Return the hash value of the canonical pathname, excluding the
2361 drive/UNC header, to get a hopefully unique inode number. */
2362 static DWORD
2363 generate_inode_val (const char * name)
2364 {
2365 char fullname[ MAX_PATH ];
2366 char * p;
2367 unsigned hash;
2368
2369 /* Get the truly canonical filename, if it exists. (Note: this
2370 doesn't resolve aliasing due to subst commands, or recognise hard
2371 links. */
2372 if (!w32_get_long_filename ((char *)name, fullname, MAX_PATH))
2373 abort ();
2374
2375 parse_root (fullname, &p);
2376 /* Normal W32 filesystems are still case insensitive. */
2377 _strlwr (p);
2378 return hashval (p);
2379 }
2380
2381 #endif
2382
2383 /* MSVC stat function can't cope with UNC names and has other bugs, so
2384 replace it with our own. This also allows us to calculate consistent
2385 inode values without hacks in the main Emacs code. */
2386 int
2387 stat (const char * path, struct stat * buf)
2388 {
2389 char *name, *r;
2390 WIN32_FIND_DATA wfd;
2391 HANDLE fh;
2392 DWORD fake_inode;
2393 int permission;
2394 int len;
2395 int rootdir = FALSE;
2396
2397 if (path == NULL || buf == NULL)
2398 {
2399 errno = EFAULT;
2400 return -1;
2401 }
2402
2403 name = (char *) map_w32_filename (path, &path);
2404 /* Must be valid filename, no wild cards or other invalid
2405 characters. We use _mbspbrk to support multibyte strings that
2406 might look to strpbrk as if they included literal *, ?, and other
2407 characters mentioned below that are disallowed by Windows
2408 filesystems. */
2409 if (_mbspbrk (name, "*?|<>\""))
2410 {
2411 errno = ENOENT;
2412 return -1;
2413 }
2414
2415 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
2416 r = IS_DEVICE_SEP (name[1]) ? &name[2] : name;
2417 if (IS_DIRECTORY_SEP (r[0]) && r[1] == '.' && r[2] == '.' && r[3] == '\0')
2418 {
2419 r[1] = r[2] = '\0';
2420 }
2421
2422 /* Remove trailing directory separator, unless name is the root
2423 directory of a drive or UNC volume in which case ensure there
2424 is a trailing separator. */
2425 len = strlen (name);
2426 rootdir = (path >= name + len - 1
2427 && (IS_DIRECTORY_SEP (*path) || *path == 0));
2428 name = strcpy (alloca (len + 2), name);
2429
2430 if (is_unc_volume (name))
2431 {
2432 DWORD attrs = unc_volume_file_attributes (name);
2433
2434 if (attrs == -1)
2435 return -1;
2436
2437 memset (&wfd, 0, sizeof (wfd));
2438 wfd.dwFileAttributes = attrs;
2439 wfd.ftCreationTime = utc_base_ft;
2440 wfd.ftLastAccessTime = utc_base_ft;
2441 wfd.ftLastWriteTime = utc_base_ft;
2442 strcpy (wfd.cFileName, name);
2443 }
2444 else if (rootdir)
2445 {
2446 if (!IS_DIRECTORY_SEP (name[len-1]))
2447 strcat (name, "\\");
2448 if (GetDriveType (name) < 2)
2449 {
2450 errno = ENOENT;
2451 return -1;
2452 }
2453 memset (&wfd, 0, sizeof (wfd));
2454 wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
2455 wfd.ftCreationTime = utc_base_ft;
2456 wfd.ftLastAccessTime = utc_base_ft;
2457 wfd.ftLastWriteTime = utc_base_ft;
2458 strcpy (wfd.cFileName, name);
2459 }
2460 else
2461 {
2462 if (IS_DIRECTORY_SEP (name[len-1]))
2463 name[len - 1] = 0;
2464
2465 /* (This is hacky, but helps when doing file completions on
2466 network drives.) Optimize by using information available from
2467 active readdir if possible. */
2468 len = strlen (dir_pathname);
2469 if (IS_DIRECTORY_SEP (dir_pathname[len-1]))
2470 len--;
2471 if (dir_find_handle != INVALID_HANDLE_VALUE
2472 && strnicmp (name, dir_pathname, len) == 0
2473 && IS_DIRECTORY_SEP (name[len])
2474 && stricmp (name + len + 1, dir_static.d_name) == 0)
2475 {
2476 /* This was the last entry returned by readdir. */
2477 wfd = dir_find_data;
2478 }
2479 else
2480 {
2481 fh = FindFirstFile (name, &wfd);
2482 if (fh == INVALID_HANDLE_VALUE)
2483 {
2484 errno = ENOENT;
2485 return -1;
2486 }
2487 FindClose (fh);
2488 }
2489 }
2490
2491 if (!NILP (Vw32_get_true_file_attributes)
2492 /* No access rights required to get info. */
2493 && (fh = CreateFile (name, 0, 0, NULL, OPEN_EXISTING,
2494 FILE_FLAG_BACKUP_SEMANTICS, NULL))
2495 != INVALID_HANDLE_VALUE)
2496 {
2497 /* This is more accurate in terms of gettting the correct number
2498 of links, but is quite slow (it is noticeable when Emacs is
2499 making a list of file name completions). */
2500 BY_HANDLE_FILE_INFORMATION info;
2501
2502 if (GetFileInformationByHandle (fh, &info))
2503 {
2504 buf->st_nlink = info.nNumberOfLinks;
2505 /* Might as well use file index to fake inode values, but this
2506 is not guaranteed to be unique unless we keep a handle open
2507 all the time (even then there are situations where it is
2508 not unique). Reputedly, there are at most 48 bits of info
2509 (on NTFS, presumably less on FAT). */
2510 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
2511 }
2512 else
2513 {
2514 buf->st_nlink = 1;
2515 fake_inode = 0;
2516 }
2517
2518 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2519 {
2520 buf->st_mode = _S_IFDIR;
2521 }
2522 else
2523 {
2524 switch (GetFileType (fh))
2525 {
2526 case FILE_TYPE_DISK:
2527 buf->st_mode = _S_IFREG;
2528 break;
2529 case FILE_TYPE_PIPE:
2530 buf->st_mode = _S_IFIFO;
2531 break;
2532 case FILE_TYPE_CHAR:
2533 case FILE_TYPE_UNKNOWN:
2534 default:
2535 buf->st_mode = _S_IFCHR;
2536 }
2537 }
2538 CloseHandle (fh);
2539 }
2540 else
2541 {
2542 /* Don't bother to make this information more accurate. */
2543 buf->st_mode = (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
2544 _S_IFDIR : _S_IFREG;
2545 buf->st_nlink = 1;
2546 fake_inode = 0;
2547 }
2548
2549 #if 0
2550 /* Not sure if there is any point in this. */
2551 if (!NILP (Vw32_generate_fake_inodes))
2552 fake_inode = generate_inode_val (name);
2553 else if (fake_inode == 0)
2554 {
2555 /* For want of something better, try to make everything unique. */
2556 static DWORD gen_num = 0;
2557 fake_inode = ++gen_num;
2558 }
2559 #endif
2560
2561 /* MSVC defines _ino_t to be short; other libc's might not. */
2562 if (sizeof (buf->st_ino) == 2)
2563 buf->st_ino = fake_inode ^ (fake_inode >> 16);
2564 else
2565 buf->st_ino = fake_inode;
2566
2567 /* consider files to belong to current user */
2568 buf->st_uid = the_passwd.pw_uid;
2569 buf->st_gid = the_passwd.pw_gid;
2570
2571 /* volume_info is set indirectly by map_w32_filename */
2572 buf->st_dev = volume_info.serialnum;
2573 buf->st_rdev = volume_info.serialnum;
2574
2575
2576 buf->st_size = wfd.nFileSizeLow;
2577
2578 /* Convert timestamps to Unix format. */
2579 buf->st_mtime = convert_time (wfd.ftLastWriteTime);
2580 buf->st_atime = convert_time (wfd.ftLastAccessTime);
2581 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
2582 buf->st_ctime = convert_time (wfd.ftCreationTime);
2583 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
2584
2585 /* determine rwx permissions */
2586 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
2587 permission = _S_IREAD;
2588 else
2589 permission = _S_IREAD | _S_IWRITE;
2590
2591 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2592 permission |= _S_IEXEC;
2593 else if (is_exec (name))
2594 permission |= _S_IEXEC;
2595
2596 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
2597
2598 return 0;
2599 }
2600
2601 /* Provide fstat and utime as well as stat for consistent handling of
2602 file timestamps. */
2603 int
2604 fstat (int desc, struct stat * buf)
2605 {
2606 HANDLE fh = (HANDLE) _get_osfhandle (desc);
2607 BY_HANDLE_FILE_INFORMATION info;
2608 DWORD fake_inode;
2609 int permission;
2610
2611 switch (GetFileType (fh) & ~FILE_TYPE_REMOTE)
2612 {
2613 case FILE_TYPE_DISK:
2614 buf->st_mode = _S_IFREG;
2615 if (!GetFileInformationByHandle (fh, &info))
2616 {
2617 errno = EACCES;
2618 return -1;
2619 }
2620 break;
2621 case FILE_TYPE_PIPE:
2622 buf->st_mode = _S_IFIFO;
2623 goto non_disk;
2624 case FILE_TYPE_CHAR:
2625 case FILE_TYPE_UNKNOWN:
2626 default:
2627 buf->st_mode = _S_IFCHR;
2628 non_disk:
2629 memset (&info, 0, sizeof (info));
2630 info.dwFileAttributes = 0;
2631 info.ftCreationTime = utc_base_ft;
2632 info.ftLastAccessTime = utc_base_ft;
2633 info.ftLastWriteTime = utc_base_ft;
2634 }
2635
2636 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2637 buf->st_mode = _S_IFDIR;
2638
2639 buf->st_nlink = info.nNumberOfLinks;
2640 /* Might as well use file index to fake inode values, but this
2641 is not guaranteed to be unique unless we keep a handle open
2642 all the time (even then there are situations where it is
2643 not unique). Reputedly, there are at most 48 bits of info
2644 (on NTFS, presumably less on FAT). */
2645 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
2646
2647 /* MSVC defines _ino_t to be short; other libc's might not. */
2648 if (sizeof (buf->st_ino) == 2)
2649 buf->st_ino = fake_inode ^ (fake_inode >> 16);
2650 else
2651 buf->st_ino = fake_inode;
2652
2653 /* consider files to belong to current user */
2654 buf->st_uid = 0;
2655 buf->st_gid = 0;
2656
2657 buf->st_dev = info.dwVolumeSerialNumber;
2658 buf->st_rdev = info.dwVolumeSerialNumber;
2659
2660 buf->st_size = info.nFileSizeLow;
2661
2662 /* Convert timestamps to Unix format. */
2663 buf->st_mtime = convert_time (info.ftLastWriteTime);
2664 buf->st_atime = convert_time (info.ftLastAccessTime);
2665 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
2666 buf->st_ctime = convert_time (info.ftCreationTime);
2667 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
2668
2669 /* determine rwx permissions */
2670 if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
2671 permission = _S_IREAD;
2672 else
2673 permission = _S_IREAD | _S_IWRITE;
2674
2675 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2676 permission |= _S_IEXEC;
2677 else
2678 {
2679 #if 0 /* no way of knowing the filename */
2680 char * p = strrchr (name, '.');
2681 if (p != NULL &&
2682 (stricmp (p, ".exe") == 0 ||
2683 stricmp (p, ".com") == 0 ||
2684 stricmp (p, ".bat") == 0 ||
2685 stricmp (p, ".cmd") == 0))
2686 permission |= _S_IEXEC;
2687 #endif
2688 }
2689
2690 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
2691
2692 return 0;
2693 }
2694
2695 int
2696 utime (const char *name, struct utimbuf *times)
2697 {
2698 struct utimbuf deftime;
2699 HANDLE fh;
2700 FILETIME mtime;
2701 FILETIME atime;
2702
2703 if (times == NULL)
2704 {
2705 deftime.modtime = deftime.actime = time (NULL);
2706 times = &deftime;
2707 }
2708
2709 /* Need write access to set times. */
2710 fh = CreateFile (name, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
2711 0, OPEN_EXISTING, 0, NULL);
2712 if (fh)
2713 {
2714 convert_from_time_t (times->actime, &atime);
2715 convert_from_time_t (times->modtime, &mtime);
2716 if (!SetFileTime (fh, NULL, &atime, &mtime))
2717 {
2718 CloseHandle (fh);
2719 errno = EACCES;
2720 return -1;
2721 }
2722 CloseHandle (fh);
2723 }
2724 else
2725 {
2726 errno = EINVAL;
2727 return -1;
2728 }
2729 return 0;
2730 }
2731
2732 #ifdef HAVE_SOCKETS
2733
2734 /* Wrappers for winsock functions to map between our file descriptors
2735 and winsock's handles; also set h_errno for convenience.
2736
2737 To allow Emacs to run on systems which don't have winsock support
2738 installed, we dynamically link to winsock on startup if present, and
2739 otherwise provide the minimum necessary functionality
2740 (eg. gethostname). */
2741
2742 /* function pointers for relevant socket functions */
2743 int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
2744 void (PASCAL *pfn_WSASetLastError) (int iError);
2745 int (PASCAL *pfn_WSAGetLastError) (void);
2746 int (PASCAL *pfn_WSAEventSelect) (SOCKET s, HANDLE hEventObject, long lNetworkEvents);
2747 HANDLE (PASCAL *pfn_WSACreateEvent) (void);
2748 int (PASCAL *pfn_WSACloseEvent) (HANDLE hEvent);
2749 int (PASCAL *pfn_socket) (int af, int type, int protocol);
2750 int (PASCAL *pfn_bind) (SOCKET s, const struct sockaddr *addr, int namelen);
2751 int (PASCAL *pfn_connect) (SOCKET s, const struct sockaddr *addr, int namelen);
2752 int (PASCAL *pfn_ioctlsocket) (SOCKET s, long cmd, u_long *argp);
2753 int (PASCAL *pfn_recv) (SOCKET s, char * buf, int len, int flags);
2754 int (PASCAL *pfn_send) (SOCKET s, const char * buf, int len, int flags);
2755 int (PASCAL *pfn_closesocket) (SOCKET s);
2756 int (PASCAL *pfn_shutdown) (SOCKET s, int how);
2757 int (PASCAL *pfn_WSACleanup) (void);
2758
2759 u_short (PASCAL *pfn_htons) (u_short hostshort);
2760 u_short (PASCAL *pfn_ntohs) (u_short netshort);
2761 unsigned long (PASCAL *pfn_inet_addr) (const char * cp);
2762 int (PASCAL *pfn_gethostname) (char * name, int namelen);
2763 struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
2764 struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto);
2765 int (PASCAL *pfn_getpeername) (SOCKET s, struct sockaddr *addr, int * namelen);
2766 int (PASCAL *pfn_setsockopt) (SOCKET s, int level, int optname,
2767 const char * optval, int optlen);
2768 int (PASCAL *pfn_listen) (SOCKET s, int backlog);
2769 int (PASCAL *pfn_getsockname) (SOCKET s, struct sockaddr * name,
2770 int * namelen);
2771 SOCKET (PASCAL *pfn_accept) (SOCKET s, struct sockaddr * addr, int * addrlen);
2772 int (PASCAL *pfn_recvfrom) (SOCKET s, char * buf, int len, int flags,
2773 struct sockaddr * from, int * fromlen);
2774 int (PASCAL *pfn_sendto) (SOCKET s, const char * buf, int len, int flags,
2775 const struct sockaddr * to, int tolen);
2776
2777 /* SetHandleInformation is only needed to make sockets non-inheritable. */
2778 BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags);
2779 #ifndef HANDLE_FLAG_INHERIT
2780 #define HANDLE_FLAG_INHERIT 1
2781 #endif
2782
2783 HANDLE winsock_lib;
2784 static int winsock_inuse;
2785
2786 BOOL
2787 term_winsock (void)
2788 {
2789 if (winsock_lib != NULL && winsock_inuse == 0)
2790 {
2791 /* Not sure what would cause WSAENETDOWN, or even if it can happen
2792 after WSAStartup returns successfully, but it seems reasonable
2793 to allow unloading winsock anyway in that case. */
2794 if (pfn_WSACleanup () == 0 ||
2795 pfn_WSAGetLastError () == WSAENETDOWN)
2796 {
2797 if (FreeLibrary (winsock_lib))
2798 winsock_lib = NULL;
2799 return TRUE;
2800 }
2801 }
2802 return FALSE;
2803 }
2804
2805 BOOL
2806 init_winsock (int load_now)
2807 {
2808 WSADATA winsockData;
2809
2810 if (winsock_lib != NULL)
2811 return TRUE;
2812
2813 pfn_SetHandleInformation = NULL;
2814 pfn_SetHandleInformation
2815 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
2816 "SetHandleInformation");
2817
2818 winsock_lib = LoadLibrary ("Ws2_32.dll");
2819
2820 if (winsock_lib != NULL)
2821 {
2822 /* dynamically link to socket functions */
2823
2824 #define LOAD_PROC(fn) \
2825 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
2826 goto fail;
2827
2828 LOAD_PROC( WSAStartup );
2829 LOAD_PROC( WSASetLastError );
2830 LOAD_PROC( WSAGetLastError );
2831 LOAD_PROC( WSAEventSelect );
2832 LOAD_PROC( WSACreateEvent );
2833 LOAD_PROC( WSACloseEvent );
2834 LOAD_PROC( socket );
2835 LOAD_PROC( bind );
2836 LOAD_PROC( connect );
2837 LOAD_PROC( ioctlsocket );
2838 LOAD_PROC( recv );
2839 LOAD_PROC( send );
2840 LOAD_PROC( closesocket );
2841 LOAD_PROC( shutdown );
2842 LOAD_PROC( htons );
2843 LOAD_PROC( ntohs );
2844 LOAD_PROC( inet_addr );
2845 LOAD_PROC( gethostname );
2846 LOAD_PROC( gethostbyname );
2847 LOAD_PROC( getservbyname );
2848 LOAD_PROC( getpeername );
2849 LOAD_PROC( WSACleanup );
2850 LOAD_PROC( setsockopt );
2851 LOAD_PROC( listen );
2852 LOAD_PROC( getsockname );
2853 LOAD_PROC( accept );
2854 LOAD_PROC( recvfrom );
2855 LOAD_PROC( sendto );
2856 #undef LOAD_PROC
2857
2858 /* specify version 1.1 of winsock */
2859 if (pfn_WSAStartup (0x101, &winsockData) == 0)
2860 {
2861 if (winsockData.wVersion != 0x101)
2862 goto fail;
2863
2864 if (!load_now)
2865 {
2866 /* Report that winsock exists and is usable, but leave
2867 socket functions disabled. I am assuming that calling
2868 WSAStartup does not require any network interaction,
2869 and in particular does not cause or require a dial-up
2870 connection to be established. */
2871
2872 pfn_WSACleanup ();
2873 FreeLibrary (winsock_lib);
2874 winsock_lib = NULL;
2875 }
2876 winsock_inuse = 0;
2877 return TRUE;
2878 }
2879
2880 fail:
2881 FreeLibrary (winsock_lib);
2882 winsock_lib = NULL;
2883 }
2884
2885 return FALSE;
2886 }
2887
2888
2889 int h_errno = 0;
2890
2891 /* function to set h_errno for compatability; map winsock error codes to
2892 normal system codes where they overlap (non-overlapping definitions
2893 are already in <sys/socket.h> */
2894 static void
2895 set_errno ()
2896 {
2897 if (winsock_lib == NULL)
2898 h_errno = EINVAL;
2899 else
2900 h_errno = pfn_WSAGetLastError ();
2901
2902 switch (h_errno)
2903 {
2904 case WSAEACCES: h_errno = EACCES; break;
2905 case WSAEBADF: h_errno = EBADF; break;
2906 case WSAEFAULT: h_errno = EFAULT; break;
2907 case WSAEINTR: h_errno = EINTR; break;
2908 case WSAEINVAL: h_errno = EINVAL; break;
2909 case WSAEMFILE: h_errno = EMFILE; break;
2910 case WSAENAMETOOLONG: h_errno = ENAMETOOLONG; break;
2911 case WSAENOTEMPTY: h_errno = ENOTEMPTY; break;
2912 }
2913 errno = h_errno;
2914 }
2915
2916 static void
2917 check_errno ()
2918 {
2919 if (h_errno == 0 && winsock_lib != NULL)
2920 pfn_WSASetLastError (0);
2921 }
2922
2923 /* Extend strerror to handle the winsock-specific error codes. */
2924 struct {
2925 int errnum;
2926 char * msg;
2927 } _wsa_errlist[] = {
2928 WSAEINTR , "Interrupted function call",
2929 WSAEBADF , "Bad file descriptor",
2930 WSAEACCES , "Permission denied",
2931 WSAEFAULT , "Bad address",
2932 WSAEINVAL , "Invalid argument",
2933 WSAEMFILE , "Too many open files",
2934
2935 WSAEWOULDBLOCK , "Resource temporarily unavailable",
2936 WSAEINPROGRESS , "Operation now in progress",
2937 WSAEALREADY , "Operation already in progress",
2938 WSAENOTSOCK , "Socket operation on non-socket",
2939 WSAEDESTADDRREQ , "Destination address required",
2940 WSAEMSGSIZE , "Message too long",
2941 WSAEPROTOTYPE , "Protocol wrong type for socket",
2942 WSAENOPROTOOPT , "Bad protocol option",
2943 WSAEPROTONOSUPPORT , "Protocol not supported",
2944 WSAESOCKTNOSUPPORT , "Socket type not supported",
2945 WSAEOPNOTSUPP , "Operation not supported",
2946 WSAEPFNOSUPPORT , "Protocol family not supported",
2947 WSAEAFNOSUPPORT , "Address family not supported by protocol family",
2948 WSAEADDRINUSE , "Address already in use",
2949 WSAEADDRNOTAVAIL , "Cannot assign requested address",
2950 WSAENETDOWN , "Network is down",
2951 WSAENETUNREACH , "Network is unreachable",
2952 WSAENETRESET , "Network dropped connection on reset",
2953 WSAECONNABORTED , "Software caused connection abort",
2954 WSAECONNRESET , "Connection reset by peer",
2955 WSAENOBUFS , "No buffer space available",
2956 WSAEISCONN , "Socket is already connected",
2957 WSAENOTCONN , "Socket is not connected",
2958 WSAESHUTDOWN , "Cannot send after socket shutdown",
2959 WSAETOOMANYREFS , "Too many references", /* not sure */
2960 WSAETIMEDOUT , "Connection timed out",
2961 WSAECONNREFUSED , "Connection refused",
2962 WSAELOOP , "Network loop", /* not sure */
2963 WSAENAMETOOLONG , "Name is too long",
2964 WSAEHOSTDOWN , "Host is down",
2965 WSAEHOSTUNREACH , "No route to host",
2966 WSAENOTEMPTY , "Buffer not empty", /* not sure */
2967 WSAEPROCLIM , "Too many processes",
2968 WSAEUSERS , "Too many users", /* not sure */
2969 WSAEDQUOT , "Double quote in host name", /* really not sure */
2970 WSAESTALE , "Data is stale", /* not sure */
2971 WSAEREMOTE , "Remote error", /* not sure */
2972
2973 WSASYSNOTREADY , "Network subsystem is unavailable",
2974 WSAVERNOTSUPPORTED , "WINSOCK.DLL version out of range",
2975 WSANOTINITIALISED , "Winsock not initialized successfully",
2976 WSAEDISCON , "Graceful shutdown in progress",
2977 #ifdef WSAENOMORE
2978 WSAENOMORE , "No more operations allowed", /* not sure */
2979 WSAECANCELLED , "Operation cancelled", /* not sure */
2980 WSAEINVALIDPROCTABLE , "Invalid procedure table from service provider",
2981 WSAEINVALIDPROVIDER , "Invalid service provider version number",
2982 WSAEPROVIDERFAILEDINIT , "Unable to initialize a service provider",
2983 WSASYSCALLFAILURE , "System call failure",
2984 WSASERVICE_NOT_FOUND , "Service not found", /* not sure */
2985 WSATYPE_NOT_FOUND , "Class type not found",
2986 WSA_E_NO_MORE , "No more resources available", /* really not sure */
2987 WSA_E_CANCELLED , "Operation already cancelled", /* really not sure */
2988 WSAEREFUSED , "Operation refused", /* not sure */
2989 #endif
2990
2991 WSAHOST_NOT_FOUND , "Host not found",
2992 WSATRY_AGAIN , "Authoritative host not found during name lookup",
2993 WSANO_RECOVERY , "Non-recoverable error during name lookup",
2994 WSANO_DATA , "Valid name, no data record of requested type",
2995
2996 -1, NULL
2997 };
2998
2999 char *
3000 sys_strerror(int error_no)
3001 {
3002 int i;
3003 static char unknown_msg[40];
3004
3005 if (error_no >= 0 && error_no < sys_nerr)
3006 return sys_errlist[error_no];
3007
3008 for (i = 0; _wsa_errlist[i].errnum >= 0; i++)
3009 if (_wsa_errlist[i].errnum == error_no)
3010 return _wsa_errlist[i].msg;
3011
3012 sprintf(unknown_msg, "Unidentified error: %d", error_no);
3013 return unknown_msg;
3014 }
3015
3016 /* [andrewi 3-May-96] I've had conflicting results using both methods,
3017 but I believe the method of keeping the socket handle separate (and
3018 insuring it is not inheritable) is the correct one. */
3019
3020 //#define SOCK_REPLACE_HANDLE
3021
3022 #ifdef SOCK_REPLACE_HANDLE
3023 #define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
3024 #else
3025 #define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
3026 #endif
3027
3028 int socket_to_fd (SOCKET s);
3029
3030 int
3031 sys_socket(int af, int type, int protocol)
3032 {
3033 SOCKET s;
3034
3035 if (winsock_lib == NULL)
3036 {
3037 h_errno = ENETDOWN;
3038 return INVALID_SOCKET;
3039 }
3040
3041 check_errno ();
3042
3043 /* call the real socket function */
3044 s = pfn_socket (af, type, protocol);
3045
3046 if (s != INVALID_SOCKET)
3047 return socket_to_fd (s);
3048
3049 set_errno ();
3050 return -1;
3051 }
3052
3053 /* Convert a SOCKET to a file descriptor. */
3054 int
3055 socket_to_fd (SOCKET s)
3056 {
3057 int fd;
3058 child_process * cp;
3059
3060 /* Although under NT 3.5 _open_osfhandle will accept a socket
3061 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
3062 that does not work under NT 3.1. However, we can get the same
3063 effect by using a backdoor function to replace an existing
3064 descriptor handle with the one we want. */
3065
3066 /* allocate a file descriptor (with appropriate flags) */
3067 fd = _open ("NUL:", _O_RDWR);
3068 if (fd >= 0)
3069 {
3070 #ifdef SOCK_REPLACE_HANDLE
3071 /* now replace handle to NUL with our socket handle */
3072 CloseHandle ((HANDLE) _get_osfhandle (fd));
3073 _free_osfhnd (fd);
3074 _set_osfhnd (fd, s);
3075 /* setmode (fd, _O_BINARY); */
3076 #else
3077 /* Make a non-inheritable copy of the socket handle. Note
3078 that it is possible that sockets aren't actually kernel
3079 handles, which appears to be the case on Windows 9x when
3080 the MS Proxy winsock client is installed. */
3081 {
3082 /* Apparently there is a bug in NT 3.51 with some service
3083 packs, which prevents using DuplicateHandle to make a
3084 socket handle non-inheritable (causes WSACleanup to
3085 hang). The work-around is to use SetHandleInformation
3086 instead if it is available and implemented. */
3087 if (pfn_SetHandleInformation)
3088 {
3089 pfn_SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0);
3090 }
3091 else
3092 {
3093 HANDLE parent = GetCurrentProcess ();
3094 HANDLE new_s = INVALID_HANDLE_VALUE;
3095
3096 if (DuplicateHandle (parent,
3097 (HANDLE) s,
3098 parent,
3099 &new_s,
3100 0,
3101 FALSE,
3102 DUPLICATE_SAME_ACCESS))
3103 {
3104 /* It is possible that DuplicateHandle succeeds even
3105 though the socket wasn't really a kernel handle,
3106 because a real handle has the same value. So
3107 test whether the new handle really is a socket. */
3108 long nonblocking = 0;
3109 if (pfn_ioctlsocket ((SOCKET) new_s, FIONBIO, &nonblocking) == 0)
3110 {
3111 pfn_closesocket (s);
3112 s = (SOCKET) new_s;
3113 }
3114 else
3115 {
3116 CloseHandle (new_s);
3117 }
3118 }
3119 }
3120 }
3121 fd_info[fd].hnd = (HANDLE) s;
3122 #endif
3123
3124 /* set our own internal flags */
3125 fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
3126
3127 cp = new_child ();
3128 if (cp)
3129 {
3130 cp->fd = fd;
3131 cp->status = STATUS_READ_ACKNOWLEDGED;
3132
3133 /* attach child_process to fd_info */
3134 if (fd_info[ fd ].cp != NULL)
3135 {
3136 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
3137 abort ();
3138 }
3139
3140 fd_info[ fd ].cp = cp;
3141
3142 /* success! */
3143 winsock_inuse++; /* count open sockets */
3144 return fd;
3145 }
3146
3147 /* clean up */
3148 _close (fd);
3149 }
3150 pfn_closesocket (s);
3151 h_errno = EMFILE;
3152 return -1;
3153 }
3154
3155
3156 int
3157 sys_bind (int s, const struct sockaddr * addr, int namelen)
3158 {
3159 if (winsock_lib == NULL)
3160 {
3161 h_errno = ENOTSOCK;
3162 return SOCKET_ERROR;
3163 }
3164
3165 check_errno ();
3166 if (fd_info[s].flags & FILE_SOCKET)
3167 {
3168 int rc = pfn_bind (SOCK_HANDLE (s), addr, namelen);
3169 if (rc == SOCKET_ERROR)
3170 set_errno ();
3171 return rc;
3172 }
3173 h_errno = ENOTSOCK;
3174 return SOCKET_ERROR;
3175 }
3176
3177
3178 int
3179 sys_connect (int s, const struct sockaddr * name, int namelen)
3180 {
3181 if (winsock_lib == NULL)
3182 {
3183 h_errno = ENOTSOCK;
3184 return SOCKET_ERROR;
3185 }
3186
3187 check_errno ();
3188 if (fd_info[s].flags & FILE_SOCKET)
3189 {
3190 int rc = pfn_connect (SOCK_HANDLE (s), name, namelen);
3191 if (rc == SOCKET_ERROR)
3192 set_errno ();
3193 return rc;
3194 }
3195 h_errno = ENOTSOCK;
3196 return SOCKET_ERROR;
3197 }
3198
3199 u_short
3200 sys_htons (u_short hostshort)
3201 {
3202 return (winsock_lib != NULL) ?
3203 pfn_htons (hostshort) : hostshort;
3204 }
3205
3206 u_short
3207 sys_ntohs (u_short netshort)
3208 {
3209 return (winsock_lib != NULL) ?
3210 pfn_ntohs (netshort) : netshort;
3211 }
3212
3213 unsigned long
3214 sys_inet_addr (const char * cp)
3215 {
3216 return (winsock_lib != NULL) ?
3217 pfn_inet_addr (cp) : INADDR_NONE;
3218 }
3219
3220 int
3221 sys_gethostname (char * name, int namelen)
3222 {
3223 if (winsock_lib != NULL)
3224 return pfn_gethostname (name, namelen);
3225
3226 if (namelen > MAX_COMPUTERNAME_LENGTH)
3227 return !GetComputerName (name, (DWORD *)&namelen);
3228
3229 h_errno = EFAULT;
3230 return SOCKET_ERROR;
3231 }
3232
3233 struct hostent *
3234 sys_gethostbyname(const char * name)
3235 {
3236 struct hostent * host;
3237
3238 if (winsock_lib == NULL)
3239 {
3240 h_errno = ENETDOWN;
3241 return NULL;
3242 }
3243
3244 check_errno ();
3245 host = pfn_gethostbyname (name);
3246 if (!host)
3247 set_errno ();
3248 return host;
3249 }
3250
3251 struct servent *
3252 sys_getservbyname(const char * name, const char * proto)
3253 {
3254 struct servent * serv;
3255
3256 if (winsock_lib == NULL)
3257 {
3258 h_errno = ENETDOWN;
3259 return NULL;
3260 }
3261
3262 check_errno ();
3263 serv = pfn_getservbyname (name, proto);
3264 if (!serv)
3265 set_errno ();
3266 return serv;
3267 }
3268
3269 int
3270 sys_getpeername (int s, struct sockaddr *addr, int * namelen)
3271 {
3272 if (winsock_lib == NULL)
3273 {
3274 h_errno = ENETDOWN;
3275 return SOCKET_ERROR;
3276 }
3277
3278 check_errno ();
3279 if (fd_info[s].flags & FILE_SOCKET)
3280 {
3281 int rc = pfn_getpeername (SOCK_HANDLE (s), addr, namelen);
3282 if (rc == SOCKET_ERROR)
3283 set_errno ();
3284 return rc;
3285 }
3286 h_errno = ENOTSOCK;
3287 return SOCKET_ERROR;
3288 }
3289
3290
3291 int
3292 sys_shutdown (int s, int how)
3293 {
3294 if (winsock_lib == NULL)
3295 {
3296 h_errno = ENETDOWN;
3297 return SOCKET_ERROR;
3298 }
3299
3300 check_errno ();
3301 if (fd_info[s].flags & FILE_SOCKET)
3302 {
3303 int rc = pfn_shutdown (SOCK_HANDLE (s), how);
3304 if (rc == SOCKET_ERROR)
3305 set_errno ();
3306 return rc;
3307 }
3308 h_errno = ENOTSOCK;
3309 return SOCKET_ERROR;
3310 }
3311
3312 int
3313 sys_setsockopt (int s, int level, int optname, const void * optval, int optlen)
3314 {
3315 if (winsock_lib == NULL)
3316 {
3317 h_errno = ENETDOWN;
3318 return SOCKET_ERROR;
3319 }
3320
3321 check_errno ();
3322 if (fd_info[s].flags & FILE_SOCKET)
3323 {
3324 int rc = pfn_setsockopt (SOCK_HANDLE (s), level, optname,
3325 (const char *)optval, optlen);
3326 if (rc == SOCKET_ERROR)
3327 set_errno ();
3328 return rc;
3329 }
3330 h_errno = ENOTSOCK;
3331 return SOCKET_ERROR;
3332 }
3333
3334 int
3335 sys_listen (int s, int backlog)
3336 {
3337 if (winsock_lib == NULL)
3338 {
3339 h_errno = ENETDOWN;
3340 return SOCKET_ERROR;
3341 }
3342
3343 check_errno ();
3344 if (fd_info[s].flags & FILE_SOCKET)
3345 {
3346 int rc = pfn_listen (SOCK_HANDLE (s), backlog);
3347 if (rc == SOCKET_ERROR)
3348 set_errno ();
3349 else
3350 fd_info[s].flags |= FILE_LISTEN;
3351 return rc;
3352 }
3353 h_errno = ENOTSOCK;
3354 return SOCKET_ERROR;
3355 }
3356
3357 int
3358 sys_getsockname (int s, struct sockaddr * name, int * namelen)
3359 {
3360 if (winsock_lib == NULL)
3361 {
3362 h_errno = ENETDOWN;
3363 return SOCKET_ERROR;
3364 }
3365
3366 check_errno ();
3367 if (fd_info[s].flags & FILE_SOCKET)
3368 {
3369 int rc = pfn_getsockname (SOCK_HANDLE (s), name, namelen);
3370 if (rc == SOCKET_ERROR)
3371 set_errno ();
3372 return rc;
3373 }
3374 h_errno = ENOTSOCK;
3375 return SOCKET_ERROR;
3376 }
3377
3378 int
3379 sys_accept (int s, struct sockaddr * addr, int * addrlen)
3380 {
3381 if (winsock_lib == NULL)
3382 {
3383 h_errno = ENETDOWN;
3384 return -1;
3385 }
3386
3387 check_errno ();
3388 if (fd_info[s].flags & FILE_LISTEN)
3389 {
3390 SOCKET t = pfn_accept (SOCK_HANDLE (s), addr, addrlen);
3391 int fd = -1;
3392 if (t == INVALID_SOCKET)
3393 set_errno ();
3394 else
3395 fd = socket_to_fd (t);
3396
3397 fd_info[s].cp->status = STATUS_READ_ACKNOWLEDGED;
3398 ResetEvent (fd_info[s].cp->char_avail);
3399 return fd;
3400 }
3401 h_errno = ENOTSOCK;
3402 return -1;
3403 }
3404
3405 int
3406 sys_recvfrom (int s, char * buf, int len, int flags,
3407 struct sockaddr * from, int * fromlen)
3408 {
3409 if (winsock_lib == NULL)
3410 {
3411 h_errno = ENETDOWN;
3412 return SOCKET_ERROR;
3413 }
3414
3415 check_errno ();
3416 if (fd_info[s].flags & FILE_SOCKET)
3417 {
3418 int rc = pfn_recvfrom (SOCK_HANDLE (s), buf, len, flags, from, fromlen);
3419 if (rc == SOCKET_ERROR)
3420 set_errno ();
3421 return rc;
3422 }
3423 h_errno = ENOTSOCK;
3424 return SOCKET_ERROR;
3425 }
3426
3427 int
3428 sys_sendto (int s, const char * buf, int len, int flags,
3429 const struct sockaddr * to, int tolen)
3430 {
3431 if (winsock_lib == NULL)
3432 {
3433 h_errno = ENETDOWN;
3434 return SOCKET_ERROR;
3435 }
3436
3437 check_errno ();
3438 if (fd_info[s].flags & FILE_SOCKET)
3439 {
3440 int rc = pfn_sendto (SOCK_HANDLE (s), buf, len, flags, to, tolen);
3441 if (rc == SOCKET_ERROR)
3442 set_errno ();
3443 return rc;
3444 }
3445 h_errno = ENOTSOCK;
3446 return SOCKET_ERROR;
3447 }
3448
3449 /* Windows does not have an fcntl function. Provide an implementation
3450 solely for making sockets non-blocking. */
3451 int
3452 fcntl (int s, int cmd, int options)
3453 {
3454 if (winsock_lib == NULL)
3455 {
3456 h_errno = ENETDOWN;
3457 return -1;
3458 }
3459
3460 check_errno ();
3461 if (fd_info[s].flags & FILE_SOCKET)
3462 {
3463 if (cmd == F_SETFL && options == O_NDELAY)
3464 {
3465 unsigned long nblock = 1;
3466 int rc = pfn_ioctlsocket (SOCK_HANDLE (s), FIONBIO, &nblock);
3467 if (rc == SOCKET_ERROR)
3468 set_errno();
3469 /* Keep track of the fact that we set this to non-blocking. */
3470 fd_info[s].flags |= FILE_NDELAY;
3471 return rc;
3472 }
3473 else
3474 {
3475 h_errno = EINVAL;
3476 return SOCKET_ERROR;
3477 }
3478 }
3479 h_errno = ENOTSOCK;
3480 return SOCKET_ERROR;
3481 }
3482
3483 #endif /* HAVE_SOCKETS */
3484
3485
3486 /* Shadow main io functions: we need to handle pipes and sockets more
3487 intelligently, and implement non-blocking mode as well. */
3488
3489 int
3490 sys_close (int fd)
3491 {
3492 int rc;
3493
3494 if (fd < 0)
3495 {
3496 errno = EBADF;
3497 return -1;
3498 }
3499
3500 if (fd < MAXDESC && fd_info[fd].cp)
3501 {
3502 child_process * cp = fd_info[fd].cp;
3503
3504 fd_info[fd].cp = NULL;
3505
3506 if (CHILD_ACTIVE (cp))
3507 {
3508 /* if last descriptor to active child_process then cleanup */
3509 int i;
3510 for (i = 0; i < MAXDESC; i++)
3511 {
3512 if (i == fd)
3513 continue;
3514 if (fd_info[i].cp == cp)
3515 break;
3516 }
3517 if (i == MAXDESC)
3518 {
3519 #ifdef HAVE_SOCKETS
3520 if (fd_info[fd].flags & FILE_SOCKET)
3521 {
3522 #ifndef SOCK_REPLACE_HANDLE
3523 if (winsock_lib == NULL) abort ();
3524
3525 pfn_shutdown (SOCK_HANDLE (fd), 2);
3526 rc = pfn_closesocket (SOCK_HANDLE (fd));
3527 #endif
3528 winsock_inuse--; /* count open sockets */
3529 }
3530 #endif
3531 delete_child (cp);
3532 }
3533 }
3534 }
3535
3536 /* Note that sockets do not need special treatment here (at least on
3537 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
3538 closesocket is equivalent to CloseHandle, which is to be expected
3539 because socket handles are fully fledged kernel handles. */
3540 rc = _close (fd);
3541
3542 if (rc == 0 && fd < MAXDESC)
3543 fd_info[fd].flags = 0;
3544
3545 return rc;
3546 }
3547
3548 int
3549 sys_dup (int fd)
3550 {
3551 int new_fd;
3552
3553 new_fd = _dup (fd);
3554 if (new_fd >= 0 && new_fd < MAXDESC)
3555 {
3556 /* duplicate our internal info as well */
3557 fd_info[new_fd] = fd_info[fd];
3558 }
3559 return new_fd;
3560 }
3561
3562
3563 int
3564 sys_dup2 (int src, int dst)
3565 {
3566 int rc;
3567
3568 if (dst < 0 || dst >= MAXDESC)
3569 {
3570 errno = EBADF;
3571 return -1;
3572 }
3573
3574 /* make sure we close the destination first if it's a pipe or socket */
3575 if (src != dst && fd_info[dst].flags != 0)
3576 sys_close (dst);
3577
3578 rc = _dup2 (src, dst);
3579 if (rc == 0)
3580 {
3581 /* duplicate our internal info as well */
3582 fd_info[dst] = fd_info[src];
3583 }
3584 return rc;
3585 }
3586
3587 /* Unix pipe() has only one arg */
3588 int
3589 sys_pipe (int * phandles)
3590 {
3591 int rc;
3592 unsigned flags;
3593
3594 /* make pipe handles non-inheritable; when we spawn a child, we
3595 replace the relevant handle with an inheritable one. Also put
3596 pipes into binary mode; we will do text mode translation ourselves
3597 if required. */
3598 rc = _pipe (phandles, 0, _O_NOINHERIT | _O_BINARY);
3599
3600 if (rc == 0)
3601 {
3602 /* Protect against overflow, since Windows can open more handles than
3603 our fd_info array has room for. */
3604 if (phandles[0] >= MAXDESC || phandles[1] >= MAXDESC)
3605 {
3606 _close (phandles[0]);
3607 _close (phandles[1]);
3608 rc = -1;
3609 }
3610 else
3611 {
3612 flags = FILE_PIPE | FILE_READ | FILE_BINARY;
3613 fd_info[phandles[0]].flags = flags;
3614
3615 flags = FILE_PIPE | FILE_WRITE | FILE_BINARY;
3616 fd_info[phandles[1]].flags = flags;
3617 }
3618 }
3619
3620 return rc;
3621 }
3622
3623 /* From ntproc.c */
3624 extern int w32_pipe_read_delay;
3625
3626 /* Function to do blocking read of one byte, needed to implement
3627 select. It is only allowed on sockets and pipes. */
3628 int
3629 _sys_read_ahead (int fd)
3630 {
3631 child_process * cp;
3632 int rc;
3633
3634 if (fd < 0 || fd >= MAXDESC)
3635 return STATUS_READ_ERROR;
3636
3637 cp = fd_info[fd].cp;
3638
3639 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
3640 return STATUS_READ_ERROR;
3641
3642 if ((fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) == 0
3643 || (fd_info[fd].flags & FILE_READ) == 0)
3644 {
3645 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd));
3646 abort ();
3647 }
3648
3649 cp->status = STATUS_READ_IN_PROGRESS;
3650
3651 if (fd_info[fd].flags & FILE_PIPE)
3652 {
3653 rc = _read (fd, &cp->chr, sizeof (char));
3654
3655 /* Give subprocess time to buffer some more output for us before
3656 reporting that input is available; we need this because Windows 95
3657 connects DOS programs to pipes by making the pipe appear to be
3658 the normal console stdout - as a result most DOS programs will
3659 write to stdout without buffering, ie. one character at a
3660 time. Even some W32 programs do this - "dir" in a command
3661 shell on NT is very slow if we don't do this. */
3662 if (rc > 0)
3663 {
3664 int wait = w32_pipe_read_delay;
3665
3666 if (wait > 0)
3667 Sleep (wait);
3668 else if (wait < 0)
3669 while (++wait <= 0)
3670 /* Yield remainder of our time slice, effectively giving a
3671 temporary priority boost to the child process. */
3672 Sleep (0);
3673 }
3674 }
3675 #ifdef HAVE_SOCKETS
3676 else if (fd_info[fd].flags & FILE_SOCKET)
3677 {
3678 unsigned long nblock = 0;
3679 /* We always want this to block, so temporarily disable NDELAY. */
3680 if (fd_info[fd].flags & FILE_NDELAY)
3681 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
3682
3683 rc = pfn_recv (SOCK_HANDLE (fd), &cp->chr, sizeof (char), 0);
3684
3685 if (fd_info[fd].flags & FILE_NDELAY)
3686 {
3687 nblock = 1;
3688 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
3689 }
3690 }
3691 #endif
3692
3693 if (rc == sizeof (char))
3694 cp->status = STATUS_READ_SUCCEEDED;
3695 else
3696 cp->status = STATUS_READ_FAILED;
3697
3698 return cp->status;
3699 }
3700
3701 int
3702 _sys_wait_accept (int fd)
3703 {
3704 HANDLE hEv;
3705 child_process * cp;
3706 int rc;
3707
3708 if (fd < 0 || fd >= MAXDESC)
3709 return STATUS_READ_ERROR;
3710
3711 cp = fd_info[fd].cp;
3712
3713 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
3714 return STATUS_READ_ERROR;
3715
3716 cp->status = STATUS_READ_FAILED;
3717
3718 hEv = pfn_WSACreateEvent ();
3719 rc = pfn_WSAEventSelect (SOCK_HANDLE (fd), hEv, FD_ACCEPT);
3720 if (rc != SOCKET_ERROR)
3721 {
3722 rc = WaitForSingleObject (hEv, INFINITE);
3723 pfn_WSAEventSelect (SOCK_HANDLE (fd), NULL, 0);
3724 if (rc == WAIT_OBJECT_0)
3725 cp->status = STATUS_READ_SUCCEEDED;
3726 }
3727 pfn_WSACloseEvent (hEv);
3728
3729 return cp->status;
3730 }
3731
3732 int
3733 sys_read (int fd, char * buffer, unsigned int count)
3734 {
3735 int nchars;
3736 int to_read;
3737 DWORD waiting;
3738 char * orig_buffer = buffer;
3739
3740 if (fd < 0)
3741 {
3742 errno = EBADF;
3743 return -1;
3744 }
3745
3746 if (fd < MAXDESC && fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
3747 {
3748 child_process *cp = fd_info[fd].cp;
3749
3750 if ((fd_info[fd].flags & FILE_READ) == 0)
3751 {
3752 errno = EBADF;
3753 return -1;
3754 }
3755
3756 nchars = 0;
3757
3758 /* re-read CR carried over from last read */
3759 if (fd_info[fd].flags & FILE_LAST_CR)
3760 {
3761 if (fd_info[fd].flags & FILE_BINARY) abort ();
3762 *buffer++ = 0x0d;
3763 count--;
3764 nchars++;
3765 fd_info[fd].flags &= ~FILE_LAST_CR;
3766 }
3767
3768 /* presence of a child_process structure means we are operating in
3769 non-blocking mode - otherwise we just call _read directly.
3770 Note that the child_process structure might be missing because
3771 reap_subprocess has been called; in this case the pipe is
3772 already broken, so calling _read on it is okay. */
3773 if (cp)
3774 {
3775 int current_status = cp->status;
3776
3777 switch (current_status)
3778 {
3779 case STATUS_READ_FAILED:
3780 case STATUS_READ_ERROR:
3781 /* report normal EOF if nothing in buffer */
3782 if (nchars <= 0)
3783 fd_info[fd].flags |= FILE_AT_EOF;
3784 return nchars;
3785
3786 case STATUS_READ_READY:
3787 case STATUS_READ_IN_PROGRESS:
3788 DebPrint (("sys_read called when read is in progress\n"));
3789 errno = EWOULDBLOCK;
3790 return -1;
3791
3792 case STATUS_READ_SUCCEEDED:
3793 /* consume read-ahead char */
3794 *buffer++ = cp->chr;
3795 count--;
3796 nchars++;
3797 cp->status = STATUS_READ_ACKNOWLEDGED;
3798 ResetEvent (cp->char_avail);
3799
3800 case STATUS_READ_ACKNOWLEDGED:
3801 break;
3802
3803 default:
3804 DebPrint (("sys_read: bad status %d\n", current_status));
3805 errno = EBADF;
3806 return -1;
3807 }
3808
3809 if (fd_info[fd].flags & FILE_PIPE)
3810 {
3811 PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL);
3812 to_read = min (waiting, (DWORD) count);
3813
3814 if (to_read > 0)
3815 nchars += _read (fd, buffer, to_read);
3816 }
3817 #ifdef HAVE_SOCKETS
3818 else /* FILE_SOCKET */
3819 {
3820 if (winsock_lib == NULL) abort ();
3821
3822 /* do the equivalent of a non-blocking read */
3823 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
3824 if (waiting == 0 && nchars == 0)
3825 {
3826 h_errno = errno = EWOULDBLOCK;
3827 return -1;
3828 }
3829
3830 if (waiting)
3831 {
3832 /* always use binary mode for sockets */
3833 int res = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0);
3834 if (res == SOCKET_ERROR)
3835 {
3836 DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
3837 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
3838 set_errno ();
3839 return -1;
3840 }
3841 nchars += res;
3842 }
3843 }
3844 #endif
3845 }
3846 else
3847 {
3848 int nread = _read (fd, buffer, count);
3849 if (nread >= 0)
3850 nchars += nread;
3851 else if (nchars == 0)
3852 nchars = nread;
3853 }
3854
3855 if (nchars <= 0)
3856 fd_info[fd].flags |= FILE_AT_EOF;
3857 /* Perform text mode translation if required. */
3858 else if ((fd_info[fd].flags & FILE_BINARY) == 0)
3859 {
3860 nchars = crlf_to_lf (nchars, orig_buffer);
3861 /* If buffer contains only CR, return that. To be absolutely
3862 sure we should attempt to read the next char, but in
3863 practice a CR to be followed by LF would not appear by
3864 itself in the buffer. */
3865 if (nchars > 1 && orig_buffer[nchars - 1] == 0x0d)
3866 {
3867 fd_info[fd].flags |= FILE_LAST_CR;
3868 nchars--;
3869 }
3870 }
3871 }
3872 else
3873 nchars = _read (fd, buffer, count);
3874
3875 return nchars;
3876 }
3877
3878 /* For now, don't bother with a non-blocking mode */
3879 int
3880 sys_write (int fd, const void * buffer, unsigned int count)
3881 {
3882 int nchars;
3883
3884 if (fd < 0)
3885 {
3886 errno = EBADF;
3887 return -1;
3888 }
3889
3890 if (fd < MAXDESC && fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
3891 {
3892 if ((fd_info[fd].flags & FILE_WRITE) == 0)
3893 {
3894 errno = EBADF;
3895 return -1;
3896 }
3897
3898 /* Perform text mode translation if required. */
3899 if ((fd_info[fd].flags & FILE_BINARY) == 0)
3900 {
3901 char * tmpbuf = alloca (count * 2);
3902 unsigned char * src = (void *)buffer;
3903 unsigned char * dst = tmpbuf;
3904 int nbytes = count;
3905
3906 while (1)
3907 {
3908 unsigned char *next;
3909 /* copy next line or remaining bytes */
3910 next = _memccpy (dst, src, '\n', nbytes);
3911 if (next)
3912 {
3913 /* copied one line ending with '\n' */
3914 int copied = next - dst;
3915 nbytes -= copied;
3916 src += copied;
3917 /* insert '\r' before '\n' */
3918 next[-1] = '\r';
3919 next[0] = '\n';
3920 dst = next + 1;
3921 count++;
3922 }
3923 else
3924 /* copied remaining partial line -> now finished */
3925 break;
3926 }
3927 buffer = tmpbuf;
3928 }
3929 }
3930
3931 #ifdef HAVE_SOCKETS
3932 if (fd < MAXDESC && fd_info[fd].flags & FILE_SOCKET)
3933 {
3934 unsigned long nblock = 0;
3935 if (winsock_lib == NULL) abort ();
3936
3937 /* TODO: implement select() properly so non-blocking I/O works. */
3938 /* For now, make sure the write blocks. */
3939 if (fd_info[fd].flags & FILE_NDELAY)
3940 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
3941
3942 nchars = pfn_send (SOCK_HANDLE (fd), buffer, count, 0);
3943
3944 /* Set the socket back to non-blocking if it was before,
3945 for other operations that support it. */
3946 if (fd_info[fd].flags & FILE_NDELAY)
3947 {
3948 nblock = 1;
3949 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONBIO, &nblock);
3950 }
3951
3952 if (nchars == SOCKET_ERROR)
3953 {
3954 DebPrint(("sys_write.send failed with error %d on socket %ld\n",
3955 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
3956 set_errno ();
3957 }
3958 }
3959 else
3960 #endif
3961 nchars = _write (fd, buffer, count);
3962
3963 return nchars;
3964 }
3965
3966 static void
3967 check_windows_init_file ()
3968 {
3969 extern int noninteractive, inhibit_window_system;
3970
3971 /* A common indication that Emacs is not installed properly is when
3972 it cannot find the Windows installation file. If this file does
3973 not exist in the expected place, tell the user. */
3974
3975 if (!noninteractive && !inhibit_window_system)
3976 {
3977 extern Lisp_Object Vwindow_system, Vload_path, Qfile_exists_p;
3978 Lisp_Object objs[2];
3979 Lisp_Object full_load_path;
3980 Lisp_Object init_file;
3981 int fd;
3982
3983 objs[0] = Vload_path;
3984 objs[1] = decode_env_path (0, (getenv ("EMACSLOADPATH")));
3985 full_load_path = Fappend (2, objs);
3986 init_file = build_string ("term/w32-win");
3987 fd = openp (full_load_path, init_file, Fget_load_suffixes (), NULL, Qnil);
3988 if (fd < 0)
3989 {
3990 Lisp_Object load_path_print = Fprin1_to_string (full_load_path, Qnil);
3991 char *init_file_name = SDATA (init_file);
3992 char *load_path = SDATA (load_path_print);
3993 char *buffer = alloca (1024
3994 + strlen (init_file_name)
3995 + strlen (load_path));
3996
3997 sprintf (buffer,
3998 "The Emacs Windows initialization file \"%s.el\" "
3999 "could not be found in your Emacs installation. "
4000 "Emacs checked the following directories for this file:\n"
4001 "\n%s\n\n"
4002 "When Emacs cannot find this file, it usually means that it "
4003 "was not installed properly, or its distribution file was "
4004 "not unpacked properly.\nSee the README.W32 file in the "
4005 "top-level Emacs directory for more information.",
4006 init_file_name, load_path);
4007 MessageBox (NULL,
4008 buffer,
4009 "Emacs Abort Dialog",
4010 MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
4011 /* Use the low-level Emacs abort. */
4012 #undef abort
4013 abort ();
4014 }
4015 else
4016 {
4017 _close (fd);
4018 }
4019 }
4020 }
4021
4022 void
4023 term_ntproc ()
4024 {
4025 #ifdef HAVE_SOCKETS
4026 /* shutdown the socket interface if necessary */
4027 term_winsock ();
4028 #endif
4029
4030 term_w32select ();
4031 }
4032
4033 void
4034 init_ntproc ()
4035 {
4036 #ifdef HAVE_SOCKETS
4037 /* Initialise the socket interface now if available and requested by
4038 the user by defining PRELOAD_WINSOCK; otherwise loading will be
4039 delayed until open-network-stream is called (w32-has-winsock can
4040 also be used to dynamically load or reload winsock).
4041
4042 Conveniently, init_environment is called before us, so
4043 PRELOAD_WINSOCK can be set in the registry. */
4044
4045 /* Always initialize this correctly. */
4046 winsock_lib = NULL;
4047
4048 if (getenv ("PRELOAD_WINSOCK") != NULL)
4049 init_winsock (TRUE);
4050 #endif
4051
4052 /* Initial preparation for subprocess support: replace our standard
4053 handles with non-inheritable versions. */
4054 {
4055 HANDLE parent;
4056 HANDLE stdin_save = INVALID_HANDLE_VALUE;
4057 HANDLE stdout_save = INVALID_HANDLE_VALUE;
4058 HANDLE stderr_save = INVALID_HANDLE_VALUE;
4059
4060 parent = GetCurrentProcess ();
4061
4062 /* ignore errors when duplicating and closing; typically the
4063 handles will be invalid when running as a gui program. */
4064 DuplicateHandle (parent,
4065 GetStdHandle (STD_INPUT_HANDLE),
4066 parent,
4067 &stdin_save,
4068 0,
4069 FALSE,
4070 DUPLICATE_SAME_ACCESS);
4071
4072 DuplicateHandle (parent,
4073 GetStdHandle (STD_OUTPUT_HANDLE),
4074 parent,
4075 &stdout_save,
4076 0,
4077 FALSE,
4078 DUPLICATE_SAME_ACCESS);
4079
4080 DuplicateHandle (parent,
4081 GetStdHandle (STD_ERROR_HANDLE),
4082 parent,
4083 &stderr_save,
4084 0,
4085 FALSE,
4086 DUPLICATE_SAME_ACCESS);
4087
4088 fclose (stdin);
4089 fclose (stdout);
4090 fclose (stderr);
4091
4092 if (stdin_save != INVALID_HANDLE_VALUE)
4093 _open_osfhandle ((long) stdin_save, O_TEXT);
4094 else
4095 _open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY);
4096 _fdopen (0, "r");
4097
4098 if (stdout_save != INVALID_HANDLE_VALUE)
4099 _open_osfhandle ((long) stdout_save, O_TEXT);
4100 else
4101 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
4102 _fdopen (1, "w");
4103
4104 if (stderr_save != INVALID_HANDLE_VALUE)
4105 _open_osfhandle ((long) stderr_save, O_TEXT);
4106 else
4107 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
4108 _fdopen (2, "w");
4109 }
4110
4111 /* unfortunately, atexit depends on implementation of malloc */
4112 /* atexit (term_ntproc); */
4113 signal (SIGABRT, term_ntproc);
4114
4115 /* determine which drives are fixed, for GetCachedVolumeInformation */
4116 {
4117 /* GetDriveType must have trailing backslash. */
4118 char drive[] = "A:\\";
4119
4120 /* Loop over all possible drive letters */
4121 while (*drive <= 'Z')
4122 {
4123 /* Record if this drive letter refers to a fixed drive. */
4124 fixed_drives[DRIVE_INDEX (*drive)] =
4125 (GetDriveType (drive) == DRIVE_FIXED);
4126
4127 (*drive)++;
4128 }
4129
4130 /* Reset the volume info cache. */
4131 volume_cache = NULL;
4132 }
4133
4134 /* Check to see if Emacs has been installed correctly. */
4135 check_windows_init_file ();
4136 }
4137
4138 /*
4139 shutdown_handler ensures that buffers' autosave files are
4140 up to date when the user logs off, or the system shuts down.
4141 */
4142 BOOL WINAPI shutdown_handler(DWORD type)
4143 {
4144 /* Ctrl-C and Ctrl-Break are already suppressed, so don't handle them. */
4145 if (type == CTRL_CLOSE_EVENT /* User closes console window. */
4146 || type == CTRL_LOGOFF_EVENT /* User logs off. */
4147 || type == CTRL_SHUTDOWN_EVENT) /* User shutsdown. */
4148 {
4149 /* Shut down cleanly, making sure autosave files are up to date. */
4150 shut_down_emacs (0, 0, Qnil);
4151 }
4152
4153 /* Allow other handlers to handle this signal. */
4154 return FALSE;
4155 }
4156
4157 /*
4158 globals_of_w32 is used to initialize those global variables that
4159 must always be initialized on startup even when the global variable
4160 initialized is non zero (see the function main in emacs.c).
4161 */
4162 void
4163 globals_of_w32 ()
4164 {
4165 g_b_init_is_windows_9x = 0;
4166 g_b_init_open_process_token = 0;
4167 g_b_init_get_token_information = 0;
4168 g_b_init_lookup_account_sid = 0;
4169 g_b_init_get_sid_identifier_authority = 0;
4170 /* The following sets a handler for shutdown notifications for
4171 console apps. This actually applies to Emacs in both console and
4172 GUI modes, since we had to fool windows into thinking emacs is a
4173 console application to get console mode to work. */
4174 SetConsoleCtrlHandler(shutdown_handler, TRUE);
4175 }
4176
4177 /* end of w32.c */
4178
4179 /* arch-tag: 90442dd3-37be-482b-b272-ac752e3049f1
4180 (do not change this comment) */