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