(command-line): Set `temporary-file-directory' based
[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++;
1563 }
1564 /* This loop must surely terminate! */
1565 while (rename (oldname, temp) < 0 && errno == EEXIST);
1566 if (errno != EEXIST)
480b0c5b
GV
1567 return -1;
1568 }
1569
1570 /* Emulate Unix behaviour - newname is deleted if it already exists
5162ffce 1571 (at least if it is a file; don't do this for directories).
76b3903d 1572
b3308d2e
KH
1573 Since we mustn't do this if we are just changing the case of the
1574 file name (we would end up deleting the file we are trying to
1575 rename!), we let rename detect if the destination file already
1576 exists - that way we avoid the possible pitfalls of trying to
1577 determine ourselves whether two names really refer to the same
1578 file, which is not always possible in the general case. (Consider
1579 all the permutations of shared or subst'd drives, etc.) */
1580
1581 newname = map_w32_filename (newname, NULL);
eb9ea53f 1582 result = rename (temp, newname);
b3308d2e
KH
1583
1584 if (result < 0
1585 && errno == EEXIST
1586 && _chmod (newname, 0666) == 0
1587 && _unlink (newname) == 0)
1588 result = rename (temp, newname);
480b0c5b 1589
eb9ea53f 1590 return result;
480b0c5b
GV
1591}
1592
1593int
1594sys_rmdir (const char * path)
1595{
fbd6baed 1596 return _rmdir (map_w32_filename (path, NULL));
480b0c5b
GV
1597}
1598
1599int
1600sys_unlink (const char * path)
1601{
16bb7578
GV
1602 path = map_w32_filename (path, NULL);
1603
1604 /* On Unix, unlink works without write permission. */
1605 _chmod (path, 0666);
1606 return _unlink (path);
480b0c5b
GV
1607}
1608
1609static FILETIME utc_base_ft;
1610static long double utc_base;
1611static int init = 0;
1612
1613static time_t
1614convert_time (FILETIME ft)
1615{
1616 long double ret;
1617
1618 if (!init)
1619 {
1620 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
1621 SYSTEMTIME st;
1622
1623 st.wYear = 1970;
1624 st.wMonth = 1;
1625 st.wDay = 1;
1626 st.wHour = 0;
1627 st.wMinute = 0;
1628 st.wSecond = 0;
1629 st.wMilliseconds = 0;
1630
1631 SystemTimeToFileTime (&st, &utc_base_ft);
1632 utc_base = (long double) utc_base_ft.dwHighDateTime
1633 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
1634 init = 1;
1635 }
1636
1637 if (CompareFileTime (&ft, &utc_base_ft) < 0)
1638 return 0;
1639
1640 ret = (long double) ft.dwHighDateTime * 4096 * 1024 * 1024 + ft.dwLowDateTime;
1641 ret -= utc_base;
1642 return (time_t) (ret * 1e-7);
1643}
1644
480b0c5b
GV
1645void
1646convert_from_time_t (time_t time, FILETIME * pft)
1647{
1648 long double tmp;
1649
1650 if (!init)
1651 {
1652 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
1653 SYSTEMTIME st;
1654
1655 st.wYear = 1970;
1656 st.wMonth = 1;
1657 st.wDay = 1;
1658 st.wHour = 0;
1659 st.wMinute = 0;
1660 st.wSecond = 0;
1661 st.wMilliseconds = 0;
1662
1663 SystemTimeToFileTime (&st, &utc_base_ft);
1664 utc_base = (long double) utc_base_ft.dwHighDateTime
1665 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
1666 init = 1;
1667 }
1668
1669 /* time in 100ns units since 1-Jan-1601 */
1670 tmp = (long double) time * 1e7 + utc_base;
1671 pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024));
16bb7578 1672 pft->dwLowDateTime = (DWORD) (tmp - (4096.0 * 1024 * 1024) * pft->dwHighDateTime);
480b0c5b 1673}
480b0c5b 1674
76b3903d
GV
1675#if 0
1676/* No reason to keep this; faking inode values either by hashing or even
1677 using the file index from GetInformationByHandle, is not perfect and
1678 so by default Emacs doesn't use the inode values on Windows.
1679 Instead, we now determine file-truename correctly (except for
1680 possible drive aliasing etc). */
1681
1682/* Modified version of "PJW" algorithm (see the "Dragon" compiler book). */
480b0c5b 1683static unsigned
76b3903d 1684hashval (const unsigned char * str)
480b0c5b
GV
1685{
1686 unsigned h = 0;
480b0c5b
GV
1687 while (*str)
1688 {
1689 h = (h << 4) + *str++;
76b3903d 1690 h ^= (h >> 28);
480b0c5b
GV
1691 }
1692 return h;
1693}
1694
1695/* Return the hash value of the canonical pathname, excluding the
1696 drive/UNC header, to get a hopefully unique inode number. */
76b3903d 1697static DWORD
480b0c5b
GV
1698generate_inode_val (const char * name)
1699{
1700 char fullname[ MAX_PATH ];
1701 char * p;
1702 unsigned hash;
1703
76b3903d
GV
1704 /* Get the truly canonical filename, if it exists. (Note: this
1705 doesn't resolve aliasing due to subst commands, or recognise hard
1706 links. */
1707 if (!w32_get_long_filename ((char *)name, fullname, MAX_PATH))
1708 abort ();
1709
1710 parse_root (fullname, &p);
fbd6baed 1711 /* Normal W32 filesystems are still case insensitive. */
480b0c5b 1712 _strlwr (p);
76b3903d 1713 return hashval (p);
480b0c5b
GV
1714}
1715
76b3903d
GV
1716#endif
1717
480b0c5b
GV
1718/* MSVC stat function can't cope with UNC names and has other bugs, so
1719 replace it with our own. This also allows us to calculate consistent
1720 inode values without hacks in the main Emacs code. */
1721int
1722stat (const char * path, struct stat * buf)
1723{
eb9ea53f 1724 char *name, *r;
480b0c5b
GV
1725 WIN32_FIND_DATA wfd;
1726 HANDLE fh;
76b3903d 1727 DWORD fake_inode;
480b0c5b
GV
1728 int permission;
1729 int len;
1730 int rootdir = FALSE;
1731
1732 if (path == NULL || buf == NULL)
1733 {
1734 errno = EFAULT;
1735 return -1;
1736 }
1737
fbd6baed 1738 name = (char *) map_w32_filename (path, &path);
bb1584c8
RS
1739 /* must be valid filename, no wild cards or other illegal characters */
1740 if (strpbrk (name, "*?|<>\""))
480b0c5b
GV
1741 {
1742 errno = ENOENT;
1743 return -1;
1744 }
1745
eb9ea53f
GV
1746 /* If name is "c:/.." or "/.." then stat "c:/" or "/". */
1747 r = IS_DEVICE_SEP (name[1]) ? &name[2] : name;
1748 if (IS_DIRECTORY_SEP (r[0]) && r[1] == '.' && r[2] == '.' && r[3] == '\0')
1749 {
1750 r[1] = r[2] = '\0';
1751 }
1752
480b0c5b
GV
1753 /* Remove trailing directory separator, unless name is the root
1754 directory of a drive or UNC volume in which case ensure there
1755 is a trailing separator. */
1756 len = strlen (name);
1757 rootdir = (path >= name + len - 1
1758 && (IS_DIRECTORY_SEP (*path) || *path == 0));
1759 name = strcpy (alloca (len + 2), name);
1760
1761 if (rootdir)
1762 {
1763 if (!IS_DIRECTORY_SEP (name[len-1]))
1764 strcat (name, "\\");
1765 if (GetDriveType (name) < 2)
1766 {
1767 errno = ENOENT;
1768 return -1;
1769 }
1770 memset (&wfd, 0, sizeof (wfd));
1771 wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
1772 wfd.ftCreationTime = utc_base_ft;
1773 wfd.ftLastAccessTime = utc_base_ft;
1774 wfd.ftLastWriteTime = utc_base_ft;
1775 strcpy (wfd.cFileName, name);
1776 }
1777 else
1778 {
1779 if (IS_DIRECTORY_SEP (name[len-1]))
1780 name[len - 1] = 0;
76b3903d
GV
1781
1782 /* (This is hacky, but helps when doing file completions on
1783 network drives.) Optimize by using information available from
1784 active readdir if possible. */
1785 if (dir_find_handle != INVALID_HANDLE_VALUE
1786 && (len = strlen (dir_pathname)),
1787 strnicmp (name, dir_pathname, len) == 0
1788 && IS_DIRECTORY_SEP (name[len])
1789 && stricmp (name + len + 1, dir_static.d_name) == 0)
480b0c5b 1790 {
76b3903d
GV
1791 /* This was the last entry returned by readdir. */
1792 wfd = dir_find_data;
1793 }
1794 else
1795 {
1796 fh = FindFirstFile (name, &wfd);
1797 if (fh == INVALID_HANDLE_VALUE)
1798 {
1799 errno = ENOENT;
1800 return -1;
1801 }
1802 FindClose (fh);
480b0c5b 1803 }
480b0c5b
GV
1804 }
1805
1806 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1807 {
1808 buf->st_mode = _S_IFDIR;
1809 buf->st_nlink = 2; /* doesn't really matter */
76b3903d 1810 fake_inode = 0; /* this doesn't either I think */
480b0c5b 1811 }
76b3903d 1812 else if (!NILP (Vw32_get_true_file_attributes))
480b0c5b 1813 {
480b0c5b
GV
1814 /* This is more accurate in terms of gettting the correct number
1815 of links, but is quite slow (it is noticable when Emacs is
1816 making a list of file name completions). */
1817 BY_HANDLE_FILE_INFORMATION info;
1818
76b3903d
GV
1819 /* No access rights required to get info. */
1820 fh = CreateFile (name, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
480b0c5b
GV
1821
1822 if (GetFileInformationByHandle (fh, &info))
1823 {
1824 switch (GetFileType (fh))
1825 {
1826 case FILE_TYPE_DISK:
1827 buf->st_mode = _S_IFREG;
1828 break;
1829 case FILE_TYPE_PIPE:
1830 buf->st_mode = _S_IFIFO;
1831 break;
1832 case FILE_TYPE_CHAR:
1833 case FILE_TYPE_UNKNOWN:
1834 default:
1835 buf->st_mode = _S_IFCHR;
1836 }
1837 buf->st_nlink = info.nNumberOfLinks;
76b3903d
GV
1838 /* Might as well use file index to fake inode values, but this
1839 is not guaranteed to be unique unless we keep a handle open
1840 all the time (even then there are situations where it is
1841 not unique). Reputedly, there are at most 48 bits of info
1842 (on NTFS, presumably less on FAT). */
1843 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
480b0c5b
GV
1844 CloseHandle (fh);
1845 }
1846 else
1847 {
1848 errno = EACCES;
1849 return -1;
1850 }
76b3903d
GV
1851 }
1852 else
1853 {
1854 /* Don't bother to make this information more accurate. */
480b0c5b
GV
1855 buf->st_mode = _S_IFREG;
1856 buf->st_nlink = 1;
76b3903d
GV
1857 fake_inode = 0;
1858 }
1859
1860#if 0
1861 /* Not sure if there is any point in this. */
1862 if (!NILP (Vw32_generate_fake_inodes))
1863 fake_inode = generate_inode_val (name);
1864 else if (fake_inode == 0)
1865 {
1866 /* For want of something better, try to make everything unique. */
1867 static DWORD gen_num = 0;
1868 fake_inode = ++gen_num;
480b0c5b 1869 }
76b3903d
GV
1870#endif
1871
1872 /* MSVC defines _ino_t to be short; other libc's might not. */
1873 if (sizeof (buf->st_ino) == 2)
1874 buf->st_ino = fake_inode ^ (fake_inode >> 16);
1875 else
1876 buf->st_ino = fake_inode;
480b0c5b
GV
1877
1878 /* consider files to belong to current user */
1879 buf->st_uid = the_passwd.pw_uid;
1880 buf->st_gid = the_passwd.pw_gid;
1881
fbd6baed 1882 /* volume_info is set indirectly by map_w32_filename */
480b0c5b
GV
1883 buf->st_dev = volume_info.serialnum;
1884 buf->st_rdev = volume_info.serialnum;
1885
480b0c5b
GV
1886
1887 buf->st_size = wfd.nFileSizeLow;
1888
1889 /* Convert timestamps to Unix format. */
1890 buf->st_mtime = convert_time (wfd.ftLastWriteTime);
1891 buf->st_atime = convert_time (wfd.ftLastAccessTime);
1892 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
1893 buf->st_ctime = convert_time (wfd.ftCreationTime);
1894 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
1895
1896 /* determine rwx permissions */
1897 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
1898 permission = _S_IREAD;
1899 else
1900 permission = _S_IREAD | _S_IWRITE;
1901
1902 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1903 permission |= _S_IEXEC;
b3308d2e
KH
1904 else if (is_exec (name))
1905 permission |= _S_IEXEC;
480b0c5b
GV
1906
1907 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
1908
1909 return 0;
1910}
1911
16bb7578
GV
1912/* Provide fstat and utime as well as stat for consistent handling of
1913 file timestamps. */
1914int
1915fstat (int desc, struct stat * buf)
1916{
1917 HANDLE fh = (HANDLE) _get_osfhandle (desc);
1918 BY_HANDLE_FILE_INFORMATION info;
1919 DWORD fake_inode;
1920 int permission;
1921
1922 switch (GetFileType (fh) & ~FILE_TYPE_REMOTE)
1923 {
1924 case FILE_TYPE_DISK:
1925 buf->st_mode = _S_IFREG;
1926 if (!GetFileInformationByHandle (fh, &info))
1927 {
1928 errno = EACCES;
1929 return -1;
1930 }
1931 break;
1932 case FILE_TYPE_PIPE:
1933 buf->st_mode = _S_IFIFO;
1934 goto non_disk;
1935 case FILE_TYPE_CHAR:
1936 case FILE_TYPE_UNKNOWN:
1937 default:
1938 buf->st_mode = _S_IFCHR;
1939 non_disk:
1940 memset (&info, 0, sizeof (info));
1941 info.dwFileAttributes = 0;
1942 info.ftCreationTime = utc_base_ft;
1943 info.ftLastAccessTime = utc_base_ft;
1944 info.ftLastWriteTime = utc_base_ft;
1945 }
1946
1947 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1948 {
1949 buf->st_mode = _S_IFDIR;
1950 buf->st_nlink = 2; /* doesn't really matter */
1951 fake_inode = 0; /* this doesn't either I think */
1952 }
1953 else
1954 {
1955 buf->st_nlink = info.nNumberOfLinks;
1956 /* Might as well use file index to fake inode values, but this
1957 is not guaranteed to be unique unless we keep a handle open
1958 all the time (even then there are situations where it is
1959 not unique). Reputedly, there are at most 48 bits of info
1960 (on NTFS, presumably less on FAT). */
1961 fake_inode = info.nFileIndexLow ^ info.nFileIndexHigh;
1962 }
1963
1964 /* MSVC defines _ino_t to be short; other libc's might not. */
1965 if (sizeof (buf->st_ino) == 2)
1966 buf->st_ino = fake_inode ^ (fake_inode >> 16);
1967 else
1968 buf->st_ino = fake_inode;
1969
1970 /* consider files to belong to current user */
1971 buf->st_uid = 0;
1972 buf->st_gid = 0;
1973
1974 buf->st_dev = info.dwVolumeSerialNumber;
1975 buf->st_rdev = info.dwVolumeSerialNumber;
1976
1977 buf->st_size = info.nFileSizeLow;
1978
1979 /* Convert timestamps to Unix format. */
1980 buf->st_mtime = convert_time (info.ftLastWriteTime);
1981 buf->st_atime = convert_time (info.ftLastAccessTime);
1982 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
1983 buf->st_ctime = convert_time (info.ftCreationTime);
1984 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
1985
1986 /* determine rwx permissions */
1987 if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
1988 permission = _S_IREAD;
1989 else
1990 permission = _S_IREAD | _S_IWRITE;
1991
1992 if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1993 permission |= _S_IEXEC;
1994 else
1995 {
1996#if 0 /* no way of knowing the filename */
1997 char * p = strrchr (name, '.');
1998 if (p != NULL &&
1999 (stricmp (p, ".exe") == 0 ||
2000 stricmp (p, ".com") == 0 ||
2001 stricmp (p, ".bat") == 0 ||
2002 stricmp (p, ".cmd") == 0))
2003 permission |= _S_IEXEC;
2004#endif
2005 }
2006
2007 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
2008
2009 return 0;
2010}
2011
2012int
2013utime (const char *name, struct utimbuf *times)
2014{
2015 struct utimbuf deftime;
2016 HANDLE fh;
2017 FILETIME mtime;
2018 FILETIME atime;
2019
2020 if (times == NULL)
2021 {
2022 deftime.modtime = deftime.actime = time (NULL);
2023 times = &deftime;
2024 }
2025
2026 /* Need write access to set times. */
2027 fh = CreateFile (name, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
2028 0, OPEN_EXISTING, 0, NULL);
2029 if (fh)
2030 {
2031 convert_from_time_t (times->actime, &atime);
2032 convert_from_time_t (times->modtime, &mtime);
2033 if (!SetFileTime (fh, NULL, &atime, &mtime))
2034 {
2035 CloseHandle (fh);
2036 errno = EACCES;
2037 return -1;
2038 }
2039 CloseHandle (fh);
2040 }
2041 else
2042 {
2043 errno = EINVAL;
2044 return -1;
2045 }
2046 return 0;
2047}
2048
480b0c5b
GV
2049#ifdef HAVE_SOCKETS
2050
2051/* Wrappers for winsock functions to map between our file descriptors
2052 and winsock's handles; also set h_errno for convenience.
2053
2054 To allow Emacs to run on systems which don't have winsock support
2055 installed, we dynamically link to winsock on startup if present, and
2056 otherwise provide the minimum necessary functionality
2057 (eg. gethostname). */
2058
2059/* function pointers for relevant socket functions */
2060int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
2061void (PASCAL *pfn_WSASetLastError) (int iError);
2062int (PASCAL *pfn_WSAGetLastError) (void);
2063int (PASCAL *pfn_socket) (int af, int type, int protocol);
2064int (PASCAL *pfn_bind) (SOCKET s, const struct sockaddr *addr, int namelen);
2065int (PASCAL *pfn_connect) (SOCKET s, const struct sockaddr *addr, int namelen);
2066int (PASCAL *pfn_ioctlsocket) (SOCKET s, long cmd, u_long *argp);
2067int (PASCAL *pfn_recv) (SOCKET s, char * buf, int len, int flags);
2068int (PASCAL *pfn_send) (SOCKET s, const char * buf, int len, int flags);
2069int (PASCAL *pfn_closesocket) (SOCKET s);
2070int (PASCAL *pfn_shutdown) (SOCKET s, int how);
2071int (PASCAL *pfn_WSACleanup) (void);
2072
2073u_short (PASCAL *pfn_htons) (u_short hostshort);
2074u_short (PASCAL *pfn_ntohs) (u_short netshort);
2075unsigned long (PASCAL *pfn_inet_addr) (const char * cp);
2076int (PASCAL *pfn_gethostname) (char * name, int namelen);
2077struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
2078struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto);
f1614061
RS
2079
2080/* SetHandleInformation is only needed to make sockets non-inheritable. */
2081BOOL (WINAPI *pfn_SetHandleInformation) (HANDLE object, DWORD mask, DWORD flags);
2082#ifndef HANDLE_FLAG_INHERIT
2083#define HANDLE_FLAG_INHERIT 1
2084#endif
480b0c5b 2085
f249a012
RS
2086HANDLE winsock_lib;
2087static int winsock_inuse;
480b0c5b 2088
f249a012 2089BOOL
480b0c5b
GV
2090term_winsock (void)
2091{
f249a012 2092 if (winsock_lib != NULL && winsock_inuse == 0)
480b0c5b 2093 {
f249a012
RS
2094 /* Not sure what would cause WSAENETDOWN, or even if it can happen
2095 after WSAStartup returns successfully, but it seems reasonable
2096 to allow unloading winsock anyway in that case. */
2097 if (pfn_WSACleanup () == 0 ||
2098 pfn_WSAGetLastError () == WSAENETDOWN)
2099 {
2100 if (FreeLibrary (winsock_lib))
2101 winsock_lib = NULL;
2102 return TRUE;
2103 }
480b0c5b 2104 }
f249a012 2105 return FALSE;
480b0c5b
GV
2106}
2107
f249a012
RS
2108BOOL
2109init_winsock (int load_now)
480b0c5b
GV
2110{
2111 WSADATA winsockData;
2112
f249a012
RS
2113 if (winsock_lib != NULL)
2114 return TRUE;
f1614061
RS
2115
2116 pfn_SetHandleInformation = NULL;
2117 pfn_SetHandleInformation
2118 = (void *) GetProcAddress (GetModuleHandle ("kernel32.dll"),
2119 "SetHandleInformation");
2120
480b0c5b
GV
2121 winsock_lib = LoadLibrary ("wsock32.dll");
2122
2123 if (winsock_lib != NULL)
2124 {
2125 /* dynamically link to socket functions */
2126
2127#define LOAD_PROC(fn) \
2128 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
2129 goto fail;
2130
2131 LOAD_PROC( WSAStartup );
2132 LOAD_PROC( WSASetLastError );
2133 LOAD_PROC( WSAGetLastError );
2134 LOAD_PROC( socket );
2135 LOAD_PROC( bind );
2136 LOAD_PROC( connect );
2137 LOAD_PROC( ioctlsocket );
2138 LOAD_PROC( recv );
2139 LOAD_PROC( send );
2140 LOAD_PROC( closesocket );
2141 LOAD_PROC( shutdown );
2142 LOAD_PROC( htons );
2143 LOAD_PROC( ntohs );
2144 LOAD_PROC( inet_addr );
2145 LOAD_PROC( gethostname );
2146 LOAD_PROC( gethostbyname );
2147 LOAD_PROC( getservbyname );
2148 LOAD_PROC( WSACleanup );
2149
f249a012
RS
2150#undef LOAD_PROC
2151
480b0c5b
GV
2152 /* specify version 1.1 of winsock */
2153 if (pfn_WSAStartup (0x101, &winsockData) == 0)
2154 {
f249a012
RS
2155 if (winsockData.wVersion != 0x101)
2156 goto fail;
2157
2158 if (!load_now)
2159 {
2160 /* Report that winsock exists and is usable, but leave
2161 socket functions disabled. I am assuming that calling
2162 WSAStartup does not require any network interaction,
2163 and in particular does not cause or require a dial-up
2164 connection to be established. */
2165
2166 pfn_WSACleanup ();
2167 FreeLibrary (winsock_lib);
2168 winsock_lib = NULL;
2169 }
2170 winsock_inuse = 0;
2171 return TRUE;
480b0c5b
GV
2172 }
2173
2174 fail:
2175 FreeLibrary (winsock_lib);
f249a012 2176 winsock_lib = NULL;
480b0c5b 2177 }
f249a012
RS
2178
2179 return FALSE;
480b0c5b
GV
2180}
2181
2182
2183int h_errno = 0;
2184
2185/* function to set h_errno for compatability; map winsock error codes to
2186 normal system codes where they overlap (non-overlapping definitions
2187 are already in <sys/socket.h> */
2188static void set_errno ()
2189{
f249a012 2190 if (winsock_lib == NULL)
480b0c5b
GV
2191 h_errno = EINVAL;
2192 else
2193 h_errno = pfn_WSAGetLastError ();
2194
2195 switch (h_errno)
2196 {
2197 case WSAEACCES: h_errno = EACCES; break;
2198 case WSAEBADF: h_errno = EBADF; break;
2199 case WSAEFAULT: h_errno = EFAULT; break;
2200 case WSAEINTR: h_errno = EINTR; break;
2201 case WSAEINVAL: h_errno = EINVAL; break;
2202 case WSAEMFILE: h_errno = EMFILE; break;
2203 case WSAENAMETOOLONG: h_errno = ENAMETOOLONG; break;
2204 case WSAENOTEMPTY: h_errno = ENOTEMPTY; break;
2205 }
2206 errno = h_errno;
2207}
2208
2209static void check_errno ()
2210{
f249a012 2211 if (h_errno == 0 && winsock_lib != NULL)
480b0c5b
GV
2212 pfn_WSASetLastError (0);
2213}
2214
2215/* [andrewi 3-May-96] I've had conflicting results using both methods,
2216 but I believe the method of keeping the socket handle separate (and
2217 insuring it is not inheritable) is the correct one. */
2218
2219//#define SOCK_REPLACE_HANDLE
2220
2221#ifdef SOCK_REPLACE_HANDLE
2222#define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
2223#else
2224#define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
2225#endif
2226
2227int
2228sys_socket(int af, int type, int protocol)
2229{
2230 int fd;
2231 long s;
2232 child_process * cp;
2233
f249a012 2234 if (winsock_lib == NULL)
480b0c5b
GV
2235 {
2236 h_errno = ENETDOWN;
2237 return INVALID_SOCKET;
2238 }
2239
2240 check_errno ();
2241
2242 /* call the real socket function */
2243 s = (long) pfn_socket (af, type, protocol);
2244
2245 if (s != INVALID_SOCKET)
2246 {
2247 /* Although under NT 3.5 _open_osfhandle will accept a socket
2248 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
2249 that does not work under NT 3.1. However, we can get the same
2250 effect by using a backdoor function to replace an existing
2251 descriptor handle with the one we want. */
2252
2253 /* allocate a file descriptor (with appropriate flags) */
2254 fd = _open ("NUL:", _O_RDWR);
2255 if (fd >= 0)
2256 {
2257#ifdef SOCK_REPLACE_HANDLE
2258 /* now replace handle to NUL with our socket handle */
2259 CloseHandle ((HANDLE) _get_osfhandle (fd));
2260 _free_osfhnd (fd);
2261 _set_osfhnd (fd, s);
2262 /* setmode (fd, _O_BINARY); */
2263#else
2264 /* Make a non-inheritable copy of the socket handle. */
2265 {
2266 HANDLE parent;
2267 HANDLE new_s = INVALID_HANDLE_VALUE;
2268
2269 parent = GetCurrentProcess ();
2270
f1614061
RS
2271 /* Apparently there is a bug in NT 3.51 with some service
2272 packs, which prevents using DuplicateHandle to make a
2273 socket handle non-inheritable (causes WSACleanup to
2274 hang). The work-around is to use SetHandleInformation
2275 instead if it is available and implemented. */
2276 if (!pfn_SetHandleInformation
2277 || !pfn_SetHandleInformation ((HANDLE) s,
2278 HANDLE_FLAG_INHERIT,
caf1a172 2279 0))
f1614061
RS
2280 {
2281 DuplicateHandle (parent,
2282 (HANDLE) s,
2283 parent,
2284 &new_s,
2285 0,
2286 FALSE,
2287 DUPLICATE_SAME_ACCESS);
2288 pfn_closesocket (s);
2289 s = (SOCKET) new_s;
2290 }
2291 fd_info[fd].hnd = (HANDLE) s;
480b0c5b
GV
2292 }
2293#endif
2294
2295 /* set our own internal flags */
2296 fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
2297
2298 cp = new_child ();
2299 if (cp)
2300 {
2301 cp->fd = fd;
2302 cp->status = STATUS_READ_ACKNOWLEDGED;
2303
2304 /* attach child_process to fd_info */
2305 if (fd_info[ fd ].cp != NULL)
2306 {
2307 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
2308 abort ();
2309 }
2310
2311 fd_info[ fd ].cp = cp;
2312
2313 /* success! */
f249a012 2314 winsock_inuse++; /* count open sockets */
480b0c5b
GV
2315 return fd;
2316 }
2317
2318 /* clean up */
2319 _close (fd);
2320 }
2321 pfn_closesocket (s);
2322 h_errno = EMFILE;
2323 }
2324 set_errno ();
2325
2326 return -1;
2327}
2328
2329
2330int
2331sys_bind (int s, const struct sockaddr * addr, int namelen)
2332{
f249a012 2333 if (winsock_lib == NULL)
480b0c5b
GV
2334 {
2335 h_errno = ENOTSOCK;
2336 return SOCKET_ERROR;
2337 }
2338
2339 check_errno ();
2340 if (fd_info[s].flags & FILE_SOCKET)
2341 {
2342 int rc = pfn_bind (SOCK_HANDLE (s), addr, namelen);
2343 if (rc == SOCKET_ERROR)
2344 set_errno ();
2345 return rc;
2346 }
2347 h_errno = ENOTSOCK;
2348 return SOCKET_ERROR;
2349}
2350
2351
2352int
2353sys_connect (int s, const struct sockaddr * name, int namelen)
2354{
f249a012 2355 if (winsock_lib == NULL)
480b0c5b
GV
2356 {
2357 h_errno = ENOTSOCK;
2358 return SOCKET_ERROR;
2359 }
2360
2361 check_errno ();
2362 if (fd_info[s].flags & FILE_SOCKET)
2363 {
2364 int rc = pfn_connect (SOCK_HANDLE (s), name, namelen);
2365 if (rc == SOCKET_ERROR)
2366 set_errno ();
2367 return rc;
2368 }
2369 h_errno = ENOTSOCK;
2370 return SOCKET_ERROR;
2371}
2372
2373u_short
2374sys_htons (u_short hostshort)
2375{
f249a012 2376 return (winsock_lib != NULL) ?
480b0c5b
GV
2377 pfn_htons (hostshort) : hostshort;
2378}
2379
2380u_short
2381sys_ntohs (u_short netshort)
2382{
f249a012 2383 return (winsock_lib != NULL) ?
480b0c5b
GV
2384 pfn_ntohs (netshort) : netshort;
2385}
2386
2387unsigned long
2388sys_inet_addr (const char * cp)
2389{
f249a012 2390 return (winsock_lib != NULL) ?
480b0c5b
GV
2391 pfn_inet_addr (cp) : INADDR_NONE;
2392}
2393
2394int
2395sys_gethostname (char * name, int namelen)
2396{
f249a012 2397 if (winsock_lib != NULL)
480b0c5b
GV
2398 return pfn_gethostname (name, namelen);
2399
2400 if (namelen > MAX_COMPUTERNAME_LENGTH)
2401 return !GetComputerName (name, &namelen);
2402
2403 h_errno = EFAULT;
2404 return SOCKET_ERROR;
2405}
2406
2407struct hostent *
2408sys_gethostbyname(const char * name)
2409{
2410 struct hostent * host;
2411
f249a012 2412 if (winsock_lib == NULL)
480b0c5b
GV
2413 {
2414 h_errno = ENETDOWN;
2415 return NULL;
2416 }
2417
2418 check_errno ();
2419 host = pfn_gethostbyname (name);
2420 if (!host)
2421 set_errno ();
2422 return host;
2423}
2424
2425struct servent *
2426sys_getservbyname(const char * name, const char * proto)
2427{
2428 struct servent * serv;
2429
f249a012 2430 if (winsock_lib == NULL)
480b0c5b
GV
2431 {
2432 h_errno = ENETDOWN;
2433 return NULL;
2434 }
2435
2436 check_errno ();
2437 serv = pfn_getservbyname (name, proto);
2438 if (!serv)
2439 set_errno ();
2440 return serv;
2441}
2442
380961a6
GV
2443int
2444sys_shutdown (int s, int how)
2445{
2446 int rc;
2447
2448 if (winsock_lib == NULL)
2449 {
2450 h_errno = ENETDOWN;
2451 return SOCKET_ERROR;
2452 }
2453
2454 check_errno ();
2455 if (fd_info[s].flags & FILE_SOCKET)
2456 {
2457 int rc = pfn_shutdown (SOCK_HANDLE (s), how);
2458 if (rc == SOCKET_ERROR)
2459 set_errno ();
2460 return rc;
2461 }
2462 h_errno = ENOTSOCK;
2463 return SOCKET_ERROR;
2464}
2465
480b0c5b
GV
2466#endif /* HAVE_SOCKETS */
2467
2468
2469/* Shadow main io functions: we need to handle pipes and sockets more
2470 intelligently, and implement non-blocking mode as well. */
2471
2472int
2473sys_close (int fd)
2474{
2475 int rc;
2476
2477 if (fd < 0 || fd >= MAXDESC)
2478 {
2479 errno = EBADF;
2480 return -1;
2481 }
2482
2483 if (fd_info[fd].cp)
2484 {
2485 child_process * cp = fd_info[fd].cp;
2486
2487 fd_info[fd].cp = NULL;
2488
2489 if (CHILD_ACTIVE (cp))
2490 {
2491 /* if last descriptor to active child_process then cleanup */
2492 int i;
2493 for (i = 0; i < MAXDESC; i++)
2494 {
2495 if (i == fd)
2496 continue;
2497 if (fd_info[i].cp == cp)
2498 break;
2499 }
2500 if (i == MAXDESC)
2501 {
f249a012 2502#ifdef HAVE_SOCKETS
480b0c5b
GV
2503 if (fd_info[fd].flags & FILE_SOCKET)
2504 {
f249a012
RS
2505#ifndef SOCK_REPLACE_HANDLE
2506 if (winsock_lib == NULL) abort ();
480b0c5b
GV
2507
2508 pfn_shutdown (SOCK_HANDLE (fd), 2);
2509 rc = pfn_closesocket (SOCK_HANDLE (fd));
f249a012
RS
2510#endif
2511 winsock_inuse--; /* count open sockets */
480b0c5b
GV
2512 }
2513#endif
2514 delete_child (cp);
2515 }
2516 }
2517 }
2518
2519 /* Note that sockets do not need special treatment here (at least on
e9e23e23 2520 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
480b0c5b
GV
2521 closesocket is equivalent to CloseHandle, which is to be expected
2522 because socket handles are fully fledged kernel handles. */
2523 rc = _close (fd);
2524
2525 if (rc == 0)
2526 fd_info[fd].flags = 0;
2527
2528 return rc;
2529}
2530
2531int
2532sys_dup (int fd)
2533{
2534 int new_fd;
2535
2536 new_fd = _dup (fd);
2537 if (new_fd >= 0)
2538 {
2539 /* duplicate our internal info as well */
2540 fd_info[new_fd] = fd_info[fd];
2541 }
2542 return new_fd;
2543}
2544
2545
2546int
2547sys_dup2 (int src, int dst)
2548{
2549 int rc;
2550
2551 if (dst < 0 || dst >= MAXDESC)
2552 {
2553 errno = EBADF;
2554 return -1;
2555 }
2556
2557 /* make sure we close the destination first if it's a pipe or socket */
2558 if (src != dst && fd_info[dst].flags != 0)
2559 sys_close (dst);
2560
2561 rc = _dup2 (src, dst);
2562 if (rc == 0)
2563 {
2564 /* duplicate our internal info as well */
2565 fd_info[dst] = fd_info[src];
2566 }
2567 return rc;
2568}
2569
480b0c5b
GV
2570/* Unix pipe() has only one arg */
2571int
2572sys_pipe (int * phandles)
2573{
2574 int rc;
2575 unsigned flags;
2576 child_process * cp;
2577
76b3903d
GV
2578 /* make pipe handles non-inheritable; when we spawn a child, we
2579 replace the relevant handle with an inheritable one. Also put
2580 pipes into binary mode; we will do text mode translation ourselves
2581 if required. */
2582 rc = _pipe (phandles, 0, _O_NOINHERIT | _O_BINARY);
480b0c5b
GV
2583
2584 if (rc == 0)
2585 {
7664e306 2586 flags = FILE_PIPE | FILE_READ | FILE_BINARY;
480b0c5b
GV
2587 fd_info[phandles[0]].flags = flags;
2588
7664e306 2589 flags = FILE_PIPE | FILE_WRITE | FILE_BINARY;
480b0c5b
GV
2590 fd_info[phandles[1]].flags = flags;
2591 }
2592
2593 return rc;
2594}
2595
f7554349 2596/* From ntproc.c */
fbd6baed 2597extern Lisp_Object Vw32_pipe_read_delay;
f7554349 2598
480b0c5b
GV
2599/* Function to do blocking read of one byte, needed to implement
2600 select. It is only allowed on sockets and pipes. */
2601int
2602_sys_read_ahead (int fd)
2603{
2604 child_process * cp;
2605 int rc;
2606
2607 if (fd < 0 || fd >= MAXDESC)
2608 return STATUS_READ_ERROR;
2609
2610 cp = fd_info[fd].cp;
2611
2612 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
2613 return STATUS_READ_ERROR;
2614
2615 if ((fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) == 0
2616 || (fd_info[fd].flags & FILE_READ) == 0)
2617 {
2618 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd));
2619 abort ();
2620 }
2621
2622 cp->status = STATUS_READ_IN_PROGRESS;
2623
2624 if (fd_info[fd].flags & FILE_PIPE)
f7554349 2625 {
f7554349
KH
2626 rc = _read (fd, &cp->chr, sizeof (char));
2627
2628 /* Give subprocess time to buffer some more output for us before
e9e23e23 2629 reporting that input is available; we need this because Windows 95
f7554349
KH
2630 connects DOS programs to pipes by making the pipe appear to be
2631 the normal console stdout - as a result most DOS programs will
2632 write to stdout without buffering, ie. one character at a
fbd6baed 2633 time. Even some W32 programs do this - "dir" in a command
f7554349
KH
2634 shell on NT is very slow if we don't do this. */
2635 if (rc > 0)
2636 {
fbd6baed 2637 int wait = XINT (Vw32_pipe_read_delay);
f7554349
KH
2638
2639 if (wait > 0)
2640 Sleep (wait);
2641 else if (wait < 0)
2642 while (++wait <= 0)
2643 /* Yield remainder of our time slice, effectively giving a
2644 temporary priority boost to the child process. */
2645 Sleep (0);
2646 }
2647 }
480b0c5b
GV
2648#ifdef HAVE_SOCKETS
2649 else if (fd_info[fd].flags & FILE_SOCKET)
2650 rc = pfn_recv (SOCK_HANDLE (fd), &cp->chr, sizeof (char), 0);
2651#endif
2652
2653 if (rc == sizeof (char))
2654 cp->status = STATUS_READ_SUCCEEDED;
2655 else
2656 cp->status = STATUS_READ_FAILED;
2657
2658 return cp->status;
2659}
2660
2661int
2662sys_read (int fd, char * buffer, unsigned int count)
2663{
2664 int nchars;
480b0c5b
GV
2665 int to_read;
2666 DWORD waiting;
76b3903d 2667 char * orig_buffer = buffer;
480b0c5b
GV
2668
2669 if (fd < 0 || fd >= MAXDESC)
2670 {
2671 errno = EBADF;
2672 return -1;
2673 }
2674
2675 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
2676 {
2677 child_process *cp = fd_info[fd].cp;
2678
2679 if ((fd_info[fd].flags & FILE_READ) == 0)
2680 {
2681 errno = EBADF;
2682 return -1;
2683 }
2684
76b3903d
GV
2685 nchars = 0;
2686
2687 /* re-read CR carried over from last read */
2688 if (fd_info[fd].flags & FILE_LAST_CR)
2689 {
2690 if (fd_info[fd].flags & FILE_BINARY) abort ();
2691 *buffer++ = 0x0d;
2692 count--;
2693 nchars++;
f52eb3ef 2694 fd_info[fd].flags &= ~FILE_LAST_CR;
76b3903d
GV
2695 }
2696
480b0c5b
GV
2697 /* presence of a child_process structure means we are operating in
2698 non-blocking mode - otherwise we just call _read directly.
2699 Note that the child_process structure might be missing because
2700 reap_subprocess has been called; in this case the pipe is
2701 already broken, so calling _read on it is okay. */
2702 if (cp)
2703 {
2704 int current_status = cp->status;
2705
2706 switch (current_status)
2707 {
2708 case STATUS_READ_FAILED:
2709 case STATUS_READ_ERROR:
f52eb3ef
GV
2710 /* report normal EOF if nothing in buffer */
2711 if (nchars <= 0)
2712 fd_info[fd].flags |= FILE_AT_EOF;
2713 return nchars;
480b0c5b
GV
2714
2715 case STATUS_READ_READY:
2716 case STATUS_READ_IN_PROGRESS:
2717 DebPrint (("sys_read called when read is in progress\n"));
2718 errno = EWOULDBLOCK;
2719 return -1;
2720
2721 case STATUS_READ_SUCCEEDED:
2722 /* consume read-ahead char */
2723 *buffer++ = cp->chr;
2724 count--;
76b3903d 2725 nchars++;
480b0c5b
GV
2726 cp->status = STATUS_READ_ACKNOWLEDGED;
2727 ResetEvent (cp->char_avail);
2728
2729 case STATUS_READ_ACKNOWLEDGED:
2730 break;
2731
2732 default:
2733 DebPrint (("sys_read: bad status %d\n", current_status));
2734 errno = EBADF;
2735 return -1;
2736 }
2737
2738 if (fd_info[fd].flags & FILE_PIPE)
2739 {
2740 PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL);
2741 to_read = min (waiting, (DWORD) count);
f52eb3ef
GV
2742
2743 if (to_read > 0)
2744 nchars += _read (fd, buffer, to_read);
480b0c5b
GV
2745 }
2746#ifdef HAVE_SOCKETS
2747 else /* FILE_SOCKET */
2748 {
f249a012 2749 if (winsock_lib == NULL) abort ();
480b0c5b
GV
2750
2751 /* do the equivalent of a non-blocking read */
2752 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
76b3903d 2753 if (waiting == 0 && nchars == 0)
480b0c5b
GV
2754 {
2755 h_errno = errno = EWOULDBLOCK;
2756 return -1;
2757 }
2758
480b0c5b
GV
2759 if (waiting)
2760 {
2761 /* always use binary mode for sockets */
76b3903d
GV
2762 int res = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0);
2763 if (res == SOCKET_ERROR)
480b0c5b
GV
2764 {
2765 DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
2766 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
76b3903d
GV
2767 set_errno ();
2768 return -1;
480b0c5b 2769 }
76b3903d 2770 nchars += res;
480b0c5b
GV
2771 }
2772 }
2773#endif
2774 }
2775 else
f52eb3ef
GV
2776 {
2777 int nread = _read (fd, buffer, count);
2778 if (nread >= 0)
2779 nchars += nread;
2780 else if (nchars == 0)
2781 nchars = nread;
2782 }
76b3903d 2783
f52eb3ef
GV
2784 if (nchars <= 0)
2785 fd_info[fd].flags |= FILE_AT_EOF;
76b3903d 2786 /* Perform text mode translation if required. */
f52eb3ef 2787 else if ((fd_info[fd].flags & FILE_BINARY) == 0)
76b3903d
GV
2788 {
2789 nchars = crlf_to_lf (nchars, orig_buffer);
2790 /* If buffer contains only CR, return that. To be absolutely
2791 sure we should attempt to read the next char, but in
2792 practice a CR to be followed by LF would not appear by
2793 itself in the buffer. */
2794 if (nchars > 1 && orig_buffer[nchars - 1] == 0x0d)
2795 {
2796 fd_info[fd].flags |= FILE_LAST_CR;
2797 nchars--;
2798 }
76b3903d 2799 }
480b0c5b
GV
2800 }
2801 else
2802 nchars = _read (fd, buffer, count);
2803
76b3903d 2804 return nchars;
480b0c5b
GV
2805}
2806
2807/* For now, don't bother with a non-blocking mode */
2808int
2809sys_write (int fd, const void * buffer, unsigned int count)
2810{
2811 int nchars;
2812
2813 if (fd < 0 || fd >= MAXDESC)
2814 {
2815 errno = EBADF;
2816 return -1;
2817 }
2818
2819 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
76b3903d
GV
2820 {
2821 if ((fd_info[fd].flags & FILE_WRITE) == 0)
2822 {
2823 errno = EBADF;
2824 return -1;
2825 }
2826
2827 /* Perform text mode translation if required. */
2828 if ((fd_info[fd].flags & FILE_BINARY) == 0)
2829 {
2830 char * tmpbuf = alloca (count * 2);
2831 unsigned char * src = (void *)buffer;
2832 unsigned char * dst = tmpbuf;
2833 int nbytes = count;
2834
2835 while (1)
2836 {
2837 unsigned char *next;
2838 /* copy next line or remaining bytes */
2839 next = _memccpy (dst, src, '\n', nbytes);
2840 if (next)
2841 {
2842 /* copied one line ending with '\n' */
2843 int copied = next - dst;
2844 nbytes -= copied;
2845 src += copied;
2846 /* insert '\r' before '\n' */
2847 next[-1] = '\r';
2848 next[0] = '\n';
2849 dst = next + 1;
2850 count++;
2851 }
2852 else
2853 /* copied remaining partial line -> now finished */
2854 break;
2855 }
2856 buffer = tmpbuf;
2857 }
2858 }
2859
480b0c5b
GV
2860#ifdef HAVE_SOCKETS
2861 if (fd_info[fd].flags & FILE_SOCKET)
2862 {
f249a012 2863 if (winsock_lib == NULL) abort ();
480b0c5b
GV
2864 nchars = pfn_send (SOCK_HANDLE (fd), buffer, count, 0);
2865 if (nchars == SOCKET_ERROR)
2866 {
2867 DebPrint(("sys_read.send failed with error %d on socket %ld\n",
2868 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
2869 set_errno ();
2870 }
2871 }
2872 else
2873#endif
2874 nchars = _write (fd, buffer, count);
2875
2876 return nchars;
2877}
2878
f52eb3ef
GV
2879static void
2880check_windows_init_file ()
2881{
2882 extern int noninteractive, inhibit_window_system;
2883
2884 /* A common indication that Emacs is not installed properly is when
2885 it cannot find the Windows installation file. If this file does
2886 not exist in the expected place, tell the user. */
2887
2888 if (!noninteractive && !inhibit_window_system) {
2889 extern Lisp_Object Vwindow_system, Vload_path;
2890 Lisp_Object init_file;
2891 int fd;
2892
2893 init_file = build_string ("term/w32-win");
2894 fd = openp (Vload_path, init_file, ".el:.elc", NULL, 0);
2895 if (fd < 0) {
2896 Lisp_Object load_path_print = Fprin1_to_string (Vload_path, Qnil);
2897 char *init_file_name = XSTRING (init_file)->data;
2898 char *load_path = XSTRING (load_path_print)->data;
2899 char *buffer = alloca (1024);
2900
2901 sprintf (buffer,
2902 "The Emacs Windows initialization file \"%s.el\" "
2903 "could not be found in your Emacs installation. "
2904 "Emacs checked the following directories for this file:\n"
2905 "\n%s\n\n"
2906 "When Emacs cannot find this file, it usually means that it "
2907 "was not installed properly, or its distribution file was "
2908 "not unpacked properly.\nSee the README.W32 file in the "
2909 "top-level Emacs directory for more information.",
2910 init_file_name, load_path);
2911 MessageBox (NULL,
2912 buffer,
2913 "Emacs Abort Dialog",
2914 MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL);
2915 close (fd);
2916
2917 /* Use the low-level Emacs abort. */
2918#undef abort
2919 abort ();
2920 }
2921 }
2922}
480b0c5b
GV
2923
2924void
2925term_ntproc ()
2926{
2927#ifdef HAVE_SOCKETS
2928 /* shutdown the socket interface if necessary */
2929 term_winsock ();
2930#endif
f52eb3ef
GV
2931
2932 /* Check whether we are shutting down because we cannot find the
2933 Windows initialization file. Do this during shutdown so that
2934 Emacs is initialized as possible, and so that it is out of the
2935 critical startup path. */
2936 check_windows_init_file ();
480b0c5b
GV
2937}
2938
2939void
2940init_ntproc ()
2941{
2942#ifdef HAVE_SOCKETS
f249a012
RS
2943 /* Initialise the socket interface now if available and requested by
2944 the user by defining PRELOAD_WINSOCK; otherwise loading will be
fbd6baed 2945 delayed until open-network-stream is called (w32-has-winsock can
f249a012
RS
2946 also be used to dynamically load or reload winsock).
2947
2948 Conveniently, init_environment is called before us, so
2949 PRELOAD_WINSOCK can be set in the registry. */
2950
2951 /* Always initialize this correctly. */
2952 winsock_lib = NULL;
2953
2954 if (getenv ("PRELOAD_WINSOCK") != NULL)
2955 init_winsock (TRUE);
480b0c5b
GV
2956#endif
2957
2958 /* Initial preparation for subprocess support: replace our standard
2959 handles with non-inheritable versions. */
2960 {
2961 HANDLE parent;
2962 HANDLE stdin_save = INVALID_HANDLE_VALUE;
2963 HANDLE stdout_save = INVALID_HANDLE_VALUE;
2964 HANDLE stderr_save = INVALID_HANDLE_VALUE;
2965
2966 parent = GetCurrentProcess ();
2967
2968 /* ignore errors when duplicating and closing; typically the
2969 handles will be invalid when running as a gui program. */
2970 DuplicateHandle (parent,
2971 GetStdHandle (STD_INPUT_HANDLE),
2972 parent,
2973 &stdin_save,
2974 0,
2975 FALSE,
2976 DUPLICATE_SAME_ACCESS);
2977
2978 DuplicateHandle (parent,
2979 GetStdHandle (STD_OUTPUT_HANDLE),
2980 parent,
2981 &stdout_save,
2982 0,
2983 FALSE,
2984 DUPLICATE_SAME_ACCESS);
2985
2986 DuplicateHandle (parent,
2987 GetStdHandle (STD_ERROR_HANDLE),
2988 parent,
2989 &stderr_save,
2990 0,
2991 FALSE,
2992 DUPLICATE_SAME_ACCESS);
2993
2994 fclose (stdin);
2995 fclose (stdout);
2996 fclose (stderr);
2997
2998 if (stdin_save != INVALID_HANDLE_VALUE)
2999 _open_osfhandle ((long) stdin_save, O_TEXT);
3000 else
76b3903d
GV
3001 _open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY);
3002 _fdopen (0, "r");
480b0c5b
GV
3003
3004 if (stdout_save != INVALID_HANDLE_VALUE)
3005 _open_osfhandle ((long) stdout_save, O_TEXT);
3006 else
76b3903d
GV
3007 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
3008 _fdopen (1, "w");
480b0c5b
GV
3009
3010 if (stderr_save != INVALID_HANDLE_VALUE)
3011 _open_osfhandle ((long) stderr_save, O_TEXT);
3012 else
76b3903d
GV
3013 _open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
3014 _fdopen (2, "w");
480b0c5b
GV
3015 }
3016
3017 /* unfortunately, atexit depends on implementation of malloc */
3018 /* atexit (term_ntproc); */
3019 signal (SIGABRT, term_ntproc);
76b3903d
GV
3020
3021 /* determine which drives are fixed, for GetCachedVolumeInformation */
3022 {
3023 /* GetDriveType must have trailing backslash. */
3024 char drive[] = "A:\\";
3025
3026 /* Loop over all possible drive letters */
3027 while (*drive <= 'Z')
3028 {
3029 /* Record if this drive letter refers to a fixed drive. */
3030 fixed_drives[DRIVE_INDEX (*drive)] =
3031 (GetDriveType (drive) == DRIVE_FIXED);
3032
3033 (*drive)++;
3034 }
3035 }
480b0c5b
GV
3036}
3037
3038/* end of nt.c */