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