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