(normalize_filename): New function.
[bpt/emacs.git] / src / w32.c
CommitLineData
95ed0025 1/* Utility and Unix shadow routines for GNU Emacs on Windows NT.
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
95ed0025
RS
25#include <stdlib.h>
26#include <stdio.h>
27#include <io.h>
480b0c5b 28#include <errno.h>
95ed0025
RS
29#include <fcntl.h>
30#include <ctype.h>
480b0c5b
GV
31#include <signal.h>
32#include <sys/time.h>
33
34/* must include CRT headers *before* config.h */
35#include "config.h"
36#undef access
37#undef chdir
38#undef chmod
39#undef creat
40#undef ctime
41#undef fopen
42#undef link
43#undef mkdir
44#undef mktemp
45#undef open
46#undef rename
47#undef rmdir
48#undef unlink
49
50#undef close
51#undef dup
52#undef dup2
53#undef pipe
54#undef read
55#undef write
95ed0025 56
95ed0025
RS
57#define getwd _getwd
58#include "lisp.h"
59#undef getwd
60
61#include <pwd.h>
62
480b0c5b 63#include <windows.h>
00b3b7b3 64
480b0c5b
GV
65#ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
66#include <sys/socket.h>
67#undef socket
68#undef bind
69#undef connect
70#undef htons
71#undef ntohs
72#undef inet_addr
73#undef gethostname
74#undef gethostbyname
75#undef getservbyname
76#endif
00b3b7b3 77
480b0c5b
GV
78#include "nt.h"
79#include "ndir.h"
80#include "ntheap.h"
00b3b7b3 81
95ed0025 82/* Get the current working directory. */
480b0c5b 83char *
95ed0025
RS
84getwd (char *dir)
85{
480b0c5b
GV
86 if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
87 return dir;
88 return NULL;
95ed0025
RS
89}
90
480b0c5b 91#ifndef HAVE_SOCKETS
95ed0025
RS
92/* Emulate gethostname. */
93int
94gethostname (char *buffer, int size)
95{
96 /* NT only allows small host names, so the buffer is
97 certainly large enough. */
98 return !GetComputerName (buffer, &size);
99}
480b0c5b 100#endif /* HAVE_SOCKETS */
95ed0025
RS
101
102/* Emulate getloadavg. */
103int
104getloadavg (double loadavg[], int nelem)
105{
106 int i;
107
108 /* A faithful emulation is going to have to be saved for a rainy day. */
109 for (i = 0; i < nelem; i++)
110 {
111 loadavg[i] = 0.0;
112 }
113 return i;
114}
115
95ed0025
RS
116/* Emulate the Unix directory procedures opendir, closedir,
117 and readdir. We can't use the procedures supplied in sysdep.c,
118 so we provide them here. */
119
120struct direct dir_static; /* simulated directory contents */
480b0c5b
GV
121static HANDLE dir_find_handle = INVALID_HANDLE_VALUE;
122static int dir_is_fat;
123static char dir_pathname[MAXPATHLEN+1];
95ed0025 124
cbe39279
RS
125extern Lisp_Object Vwin32_downcase_file_names;
126
95ed0025
RS
127DIR *
128opendir (char *filename)
129{
130 DIR *dirp;
131
132 /* Opening is done by FindFirstFile. However, a read is inherent to
480b0c5b 133 this operation, so we defer the open until read time. */
95ed0025 134
480b0c5b
GV
135 if (!(dirp = (DIR *) malloc (sizeof (DIR))))
136 return NULL;
137 if (dir_find_handle != INVALID_HANDLE_VALUE)
138 return NULL;
95ed0025
RS
139
140 dirp->dd_fd = 0;
141 dirp->dd_loc = 0;
142 dirp->dd_size = 0;
143
480b0c5b
GV
144 strncpy (dir_pathname, filename, MAXPATHLEN);
145 dir_pathname[MAXPATHLEN] = '\0';
146 dir_is_fat = is_fat_volume (filename, NULL);
147
95ed0025
RS
148 return dirp;
149}
150
151void
152closedir (DIR *dirp)
153{
154 /* If we have a find-handle open, close it. */
480b0c5b 155 if (dir_find_handle != INVALID_HANDLE_VALUE)
95ed0025
RS
156 {
157 FindClose (dir_find_handle);
480b0c5b 158 dir_find_handle = INVALID_HANDLE_VALUE;
95ed0025
RS
159 }
160 xfree ((char *) dirp);
161}
162
163struct direct *
164readdir (DIR *dirp)
165{
166 WIN32_FIND_DATA find_data;
167
168 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
480b0c5b 169 if (dir_find_handle == INVALID_HANDLE_VALUE)
95ed0025
RS
170 {
171 char filename[MAXNAMLEN + 3];
172 int ln;
173
480b0c5b
GV
174 strcpy (filename, dir_pathname);
175 ln = strlen (filename) - 1;
176 if (!IS_DIRECTORY_SEP (filename[ln]))
95ed0025 177 strcat (filename, "\\");
480b0c5b 178 strcat (filename, "*");
95ed0025
RS
179
180 dir_find_handle = FindFirstFile (filename, &find_data);
181
480b0c5b 182 if (dir_find_handle == INVALID_HANDLE_VALUE)
95ed0025 183 return NULL;
480b0c5b
GV
184 }
185 else
95ed0025
RS
186 {
187 if (!FindNextFile (dir_find_handle, &find_data))
188 return NULL;
189 }
190
480b0c5b
GV
191 /* Emacs never uses this value, so don't bother making it match
192 value returned by stat(). */
95ed0025
RS
193 dir_static.d_ino = 1;
194
195 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 +
196 dir_static.d_namlen - dir_static.d_namlen % 4;
197
198 dir_static.d_namlen = strlen (find_data.cFileName);
480b0c5b
GV
199 strcpy (dir_static.d_name, find_data.cFileName);
200 if (dir_is_fat)
201 _strlwr (dir_static.d_name);
cbe39279
RS
202 else if (!NILP (Vwin32_downcase_file_names))
203 {
204 register char *p;
205 for (p = dir_static.d_name; *p; p++)
206 if (*p >= 'a' && *p <= 'z')
207 break;
208 if (!*p)
209 _strlwr (dir_static.d_name);
210 }
95ed0025
RS
211
212 return &dir_static;
213}
214
480b0c5b 215/* Emulate getpwuid, getpwnam and others. */
95ed0025 216
051fe60d
GV
217#define PASSWD_FIELD_SIZE 256
218
219static char the_passwd_name[PASSWD_FIELD_SIZE];
220static char the_passwd_passwd[PASSWD_FIELD_SIZE];
221static char the_passwd_gecos[PASSWD_FIELD_SIZE];
222static char the_passwd_dir[PASSWD_FIELD_SIZE];
223static char the_passwd_shell[PASSWD_FIELD_SIZE];
95ed0025
RS
224
225static struct passwd the_passwd =
226{
227 the_passwd_name,
228 the_passwd_passwd,
229 0,
230 0,
231 0,
232 the_passwd_gecos,
233 the_passwd_dir,
234 the_passwd_shell,
235};
236
480b0c5b
GV
237int
238getuid ()
239{
240 return the_passwd.pw_uid;
241}
242
243int
244geteuid ()
245{
246 /* I could imagine arguing for checking to see whether the user is
247 in the Administrators group and returning a UID of 0 for that
248 case, but I don't know how wise that would be in the long run. */
249 return getuid ();
250}
251
252int
253getgid ()
254{
255 return the_passwd.pw_gid;
256}
257
258int
259getegid ()
260{
261 return getgid ();
262}
263
95ed0025
RS
264struct passwd *
265getpwuid (int uid)
266{
480b0c5b
GV
267 if (uid == the_passwd.pw_uid)
268 return &the_passwd;
269 return NULL;
95ed0025
RS
270}
271
272struct passwd *
273getpwnam (char *name)
274{
275 struct passwd *pw;
276
277 pw = getpwuid (getuid ());
278 if (!pw)
279 return pw;
280
480b0c5b 281 if (stricmp (name, pw->pw_name))
95ed0025
RS
282 return NULL;
283
284 return pw;
285}
286
480b0c5b
GV
287void
288init_user_info ()
95ed0025 289{
480b0c5b
GV
290 /* Find the user's real name by opening the process token and
291 looking up the name associated with the user-sid in that token.
292
293 Use the relative portion of the identifier authority value from
294 the user-sid as the user id value (same for group id using the
295 primary group sid from the process token). */
296
297 char user_sid[256], name[256], domain[256];
298 DWORD length = sizeof (name), dlength = sizeof (domain), trash;
299 HANDLE token = NULL;
300 SID_NAME_USE user_type;
301
302 if (OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &token)
303 && GetTokenInformation (token, TokenUser,
304 (PVOID) user_sid, sizeof (user_sid), &trash)
305 && LookupAccountSid (NULL, *((PSID *) user_sid), name, &length,
306 domain, &dlength, &user_type))
d1c1c3d2 307 {
480b0c5b
GV
308 strcpy (the_passwd.pw_name, name);
309 /* Determine a reasonable uid value. */
310 if (stricmp ("administrator", name) == 0)
311 {
312 the_passwd.pw_uid = 0;
313 the_passwd.pw_gid = 0;
314 }
315 else
316 {
317 SID_IDENTIFIER_AUTHORITY * pSIA;
318
319 pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid));
320 /* I believe the relative portion is the last 4 bytes (of 6)
321 with msb first. */
322 the_passwd.pw_uid = ((pSIA->Value[2] << 24) +
323 (pSIA->Value[3] << 16) +
324 (pSIA->Value[4] << 8) +
325 (pSIA->Value[5] << 0));
326 /* restrict to conventional uid range for normal users */
327 the_passwd.pw_uid = the_passwd.pw_uid % 60001;
328
329 /* Get group id */
330 if (GetTokenInformation (token, TokenPrimaryGroup,
331 (PVOID) user_sid, sizeof (user_sid), &trash))
332 {
333 SID_IDENTIFIER_AUTHORITY * pSIA;
334
335 pSIA = GetSidIdentifierAuthority (*((PSID *) user_sid));
336 the_passwd.pw_gid = ((pSIA->Value[2] << 24) +
337 (pSIA->Value[3] << 16) +
338 (pSIA->Value[4] << 8) +
339 (pSIA->Value[5] << 0));
340 /* I don't know if this is necessary, but for safety... */
341 the_passwd.pw_gid = the_passwd.pw_gid % 60001;
342 }
343 else
344 the_passwd.pw_gid = the_passwd.pw_uid;
345 }
346 }
347 /* If security calls are not supported (presumably because we
348 are running under Windows 95), fallback to this. */
349 else if (GetUserName (name, &length))
350 {
351 strcpy (the_passwd.pw_name, name);
352 if (stricmp ("administrator", name) == 0)
353 the_passwd.pw_uid = 0;
354 else
355 the_passwd.pw_uid = 123;
356 the_passwd.pw_gid = the_passwd.pw_uid;
357 }
358 else
359 {
360 strcpy (the_passwd.pw_name, "unknown");
361 the_passwd.pw_uid = 123;
362 the_passwd.pw_gid = 123;
d1c1c3d2 363 }
95ed0025 364
480b0c5b
GV
365 /* Ensure HOME and SHELL are defined. */
366 if (getenv ("HOME") == NULL)
367 putenv ("HOME=c:/");
368 if (getenv ("SHELL") == NULL)
369 putenv ((GetVersion () & 0x80000000) ? "SHELL=command" : "SHELL=cmd");
95ed0025 370
480b0c5b
GV
371 /* Set dir and shell from environment variables. */
372 strcpy (the_passwd.pw_dir, getenv ("HOME"));
373 strcpy (the_passwd.pw_shell, getenv ("SHELL"));
bd4a449f 374
480b0c5b
GV
375 if (token)
376 CloseHandle (token);
95ed0025
RS
377}
378
95ed0025 379int
480b0c5b 380random ()
95ed0025 381{
480b0c5b
GV
382 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
383 return ((rand () << 15) | rand ());
95ed0025
RS
384}
385
95ed0025 386void
480b0c5b 387srandom (int seed)
95ed0025 388{
480b0c5b 389 srand (seed);
95ed0025
RS
390}
391
cbe39279
RS
392/* Normalize filename by converting all path separators to
393 the specified separator. Also conditionally convert upper
394 case path name components to lower case. */
395
396static void
397normalize_filename (fp, path_sep)
398 register char *fp;
399 char path_sep;
400{
401 char sep;
402 char *elem;
403
404 if (NILP (Vwin32_downcase_file_names))
405 {
406 while (*fp)
407 {
408 if (*fp == '/' || *fp == '\\')
409 *fp = path_sep;
410 fp++;
411 }
412 return;
413 }
414
415 sep = path_sep; /* convert to this path separator */
416 elem = fp; /* start of current path element */
417
418 do {
419 if (*fp >= 'a' && *fp <= 'z')
420 elem = 0; /* don't convert this element */
421
422 if (*fp == 0 || *fp == ':')
423 {
424 sep = *fp; /* restore current separator (or 0) */
425 *fp = '/'; /* after conversion of this element */
426 }
427
428 if (*fp == '/' || *fp == '\\')
429 {
430 if (elem && elem != fp)
431 {
432 *fp = 0; /* temporary end of string */
433 _strlwr (elem); /* while we convert to lower case */
434 }
435 *fp = sep; /* convert (or restore) path separator */
436 elem = fp + 1; /* next element starts after separator */
437 sep = path_sep;
438 }
439 } while (*fp++);
440}
441
480b0c5b 442/* Destructively turn backslashes into slashes. */
95ed0025 443void
480b0c5b
GV
444dostounix_filename (p)
445 register char *p;
95ed0025 446{
cbe39279 447 normalize_filename (p, '/');
95ed0025
RS
448}
449
480b0c5b 450/* Destructively turn slashes into backslashes. */
95ed0025 451void
480b0c5b
GV
452unixtodos_filename (p)
453 register char *p;
95ed0025 454{
cbe39279 455 normalize_filename (p, '\\');
95ed0025
RS
456}
457
480b0c5b
GV
458/* Remove all CR's that are followed by a LF.
459 (From msdos.c...probably should figure out a way to share it,
460 although this code isn't going to ever change.) */
35f0d482 461int
480b0c5b
GV
462crlf_to_lf (n, buf)
463 register int n;
464 register unsigned char *buf;
35f0d482 465{
480b0c5b
GV
466 unsigned char *np = buf;
467 unsigned char *startp = buf;
468 unsigned char *endp = buf + n;
35f0d482 469
480b0c5b
GV
470 if (n == 0)
471 return n;
472 while (buf < endp - 1)
95ed0025 473 {
480b0c5b
GV
474 if (*buf == 0x0d)
475 {
476 if (*(++buf) != 0x0a)
477 *np++ = 0x0d;
478 }
479 else
480 *np++ = *buf++;
95ed0025 481 }
480b0c5b
GV
482 if (buf < endp)
483 *np++ = *buf++;
484 return np - startp;
95ed0025
RS
485}
486
487/* Routines that are no-ops on NT but are defined to get Emacs to compile. */
488
95ed0025
RS
489int
490sigsetmask (int signal_mask)
491{
492 return 0;
493}
494
495int
496sigblock (int sig)
497{
498 return 0;
499}
500
95ed0025
RS
501int
502setpgrp (int pid, int gid)
503{
504 return 0;
505}
506
507int
508alarm (int seconds)
509{
510 return 0;
511}
512
513int
514unrequest_sigio (void)
515{
516 return 0;
517}
518
519int
520request_sigio (void)
521{
522 return 0;
523}
524
480b0c5b 525#define REG_ROOT "SOFTWARE\\GNU\\Emacs"
f332b293
GV
526
527LPBYTE
528nt_get_resource (key, lpdwtype)
529 char *key;
530 LPDWORD lpdwtype;
531{
532 LPBYTE lpvalue;
533 HKEY hrootkey = NULL;
534 DWORD cbData;
535 BOOL ok = FALSE;
536
537 /* Check both the current user and the local machine to see if
538 we have any resources. */
539
540 if (RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
541 {
542 lpvalue = NULL;
543
544 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
545 && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL
546 && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
547 {
548 return (lpvalue);
549 }
550
551 if (lpvalue) xfree (lpvalue);
552
553 RegCloseKey (hrootkey);
554 }
555
556 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
557 {
558 lpvalue = NULL;
559
560 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS &&
561 (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL &&
562 RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
563 {
564 return (lpvalue);
565 }
566
567 if (lpvalue) xfree (lpvalue);
568
569 RegCloseKey (hrootkey);
570 }
571
572 return (NULL);
573}
574
575void
576init_environment ()
577{
f332b293
GV
578 /* Check for environment variables and use registry if they don't exist */
579 {
480b0c5b
GV
580 int i;
581 LPBYTE lpval;
582 DWORD dwType;
f332b293 583
480b0c5b
GV
584 static char * env_vars[] =
585 {
586 "HOME",
587 "emacs_dir",
588 "EMACSLOADPATH",
589 "SHELL",
590 "EMACSDATA",
591 "EMACSPATH",
592 "EMACSLOCKDIR",
593 "INFOPATH",
594 "EMACSDOC",
595 "TERM",
596 };
597
598 for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++)
f332b293 599 {
480b0c5b
GV
600 if (!getenv (env_vars[i]) &&
601 (lpval = nt_get_resource (env_vars[i], &dwType)) != NULL)
602 {
603 if (dwType == REG_EXPAND_SZ)
604 {
605 char buf1[500], buf2[500];
606
607 ExpandEnvironmentStrings ((LPSTR) lpval, buf1, 500);
608 _snprintf (buf2, 499, "%s=%s", env_vars[i], buf1);
609 putenv (strdup (buf2));
610 }
611 else if (dwType == REG_SZ)
612 {
613 char buf[500];
f332b293 614
480b0c5b
GV
615 _snprintf (buf, 499, "%s=%s", env_vars[i], lpval);
616 putenv (strdup (buf));
617 }
f332b293 618
480b0c5b
GV
619 xfree (lpval);
620 }
621 }
622 }
623
624 init_user_info ();
625}
626
627/* We don't have scripts to automatically determine the system configuration
628 for Emacs before it's compiled, and we don't want to have to make the
629 user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
630 routine. */
631
632static char configuration_buffer[32];
633
634char *
635get_emacs_configuration (void)
636{
637 char *arch, *oem, *os;
638
639 /* Determine the processor type. */
640 switch (get_processor_type ())
641 {
642
643#ifdef PROCESSOR_INTEL_386
644 case PROCESSOR_INTEL_386:
645 case PROCESSOR_INTEL_486:
646 case PROCESSOR_INTEL_PENTIUM:
647 arch = "i386";
648 break;
649#endif
650
651#ifdef PROCESSOR_INTEL_860
652 case PROCESSOR_INTEL_860:
653 arch = "i860";
654 break;
655#endif
656
657#ifdef PROCESSOR_MIPS_R2000
658 case PROCESSOR_MIPS_R2000:
659 case PROCESSOR_MIPS_R3000:
660 case PROCESSOR_MIPS_R4000:
661 arch = "mips";
662 break;
663#endif
664
665#ifdef PROCESSOR_ALPHA_21064
666 case PROCESSOR_ALPHA_21064:
667 arch = "alpha";
668 break;
669#endif
670
671 default:
672 arch = "unknown";
673 break;
f332b293 674 }
480b0c5b
GV
675
676 /* Let oem be "*" until we figure out how to decode the OEM field. */
677 oem = "*";
678
679 os = (GetVersion () & 0x80000000) ? "win95" : "nt";
680
681 sprintf (configuration_buffer, "%s-%s-%s%d.%d", arch, oem, os,
682 get_nt_major_version (), get_nt_minor_version ());
683 return configuration_buffer;
f332b293
GV
684}
685
35f0d482
KH
686#include <sys/timeb.h>
687
688/* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
689void
690gettimeofday (struct timeval *tv, struct timezone *tz)
691{
692 struct _timeb tb;
693 _ftime (&tb);
694
695 tv->tv_sec = tb.time;
696 tv->tv_usec = tb.millitm * 1000L;
697 if (tz)
698 {
699 tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */
700 tz->tz_dsttime = tb.dstflag; /* type of dst correction */
701 }
702}
35f0d482 703
480b0c5b
GV
704/* ------------------------------------------------------------------------- */
705/* IO support and wrapper functions for Win32 API. */
706/* ------------------------------------------------------------------------- */
95ed0025 707
480b0c5b
GV
708/* Place a wrapper around the MSVC version of ctime. It returns NULL
709 on network directories, so we handle that case here.
710 (Ulrich Leodolter, 1/11/95). */
711char *
712sys_ctime (const time_t *t)
713{
714 char *str = (char *) ctime (t);
715 return (str ? str : "Sun Jan 01 00:00:00 1970");
716}
717
718/* Emulate sleep...we could have done this with a define, but that
719 would necessitate including windows.h in the files that used it.
720 This is much easier. */
721void
722sys_sleep (int seconds)
723{
724 Sleep (seconds * 1000);
725}
726
727/* Internal MSVC data and functions for low-level descriptor munging */
728#if (_MSC_VER == 900)
729extern char _osfile[];
730#endif
731extern int __cdecl _set_osfhnd (int fd, long h);
732extern int __cdecl _free_osfhnd (int fd);
733
734/* parallel array of private info on file handles */
735filedesc fd_info [ MAXDESC ];
736
737static struct {
738 DWORD serialnum;
739 DWORD maxcomp;
740 DWORD flags;
741 char name[32];
742 char type[32];
743} volume_info;
744
745/* Get information on the volume where name is held; set path pointer to
746 start of pathname in name (past UNC header\volume header if present). */
747int
748get_volume_info (const char * name, const char ** pPath)
95ed0025 749{
480b0c5b
GV
750 char temp[MAX_PATH];
751 char *rootname = NULL; /* default to current volume */
752
753 if (name == NULL)
754 return FALSE;
755
756 /* find the root name of the volume if given */
757 if (isalpha (name[0]) && name[1] == ':')
758 {
759 rootname = temp;
760 temp[0] = *name++;
761 temp[1] = *name++;
762 temp[2] = '\\';
763 temp[3] = 0;
764 }
765 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
95ed0025 766 {
480b0c5b
GV
767 char *str = temp;
768 int slashes = 4;
769 rootname = temp;
770 do
771 {
772 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
773 break;
774 *str++ = *name++;
775 }
776 while ( *name );
777
480b0c5b
GV
778 *str++ = '\\';
779 *str = 0;
95ed0025 780 }
480b0c5b
GV
781
782 if (pPath)
783 *pPath = name;
784
785 if (GetVolumeInformation (rootname,
786 volume_info.name, 32,
787 &volume_info.serialnum,
788 &volume_info.maxcomp,
789 &volume_info.flags,
790 volume_info.type, 32))
95ed0025 791 {
480b0c5b 792 return TRUE;
95ed0025 793 }
480b0c5b
GV
794 return FALSE;
795}
796
797/* Determine if volume is FAT format (ie. only supports short 8.3
798 names); also set path pointer to start of pathname in name. */
799int
800is_fat_volume (const char * name, const char ** pPath)
801{
802 if (get_volume_info (name, pPath))
803 return (volume_info.maxcomp == 12);
804 return FALSE;
805}
806
807/* Map filename to a legal 8.3 name if necessary. */
808const char *
809map_win32_filename (const char * name, const char ** pPath)
810{
811 static char shortname[MAX_PATH];
812 char * str = shortname;
813 char c;
480b0c5b
GV
814 char * path;
815
816 if (is_fat_volume (name, &path)) /* truncate to 8.3 */
95ed0025 817 {
480b0c5b
GV
818 register int left = 8; /* maximum number of chars in part */
819 register int extn = 0; /* extension added? */
820 register int dots = 2; /* maximum number of dots allowed */
821
822 while (name < path)
823 *str++ = *name++; /* skip past UNC header */
824
825 while ((c = *name++))
826 {
827 switch ( c )
828 {
829 case '\\':
830 case '/':
831 *str++ = '\\';
832 extn = 0; /* reset extension flags */
833 dots = 2; /* max 2 dots */
834 left = 8; /* max length 8 for main part */
835 break;
836 case ':':
837 *str++ = ':';
838 extn = 0; /* reset extension flags */
839 dots = 2; /* max 2 dots */
840 left = 8; /* max length 8 for main part */
841 break;
842 case '.':
843 if ( dots )
844 {
845 /* Convert path components of the form .xxx to _xxx,
846 but leave . and .. as they are. This allows .emacs
847 to be read as _emacs, for example. */
848
849 if (! *name ||
850 *name == '.' ||
851 IS_DIRECTORY_SEP (*name))
852 {
853 *str++ = '.';
854 dots--;
855 }
856 else
857 {
858 *str++ = '_';
859 left--;
860 dots = 0;
861 }
862 }
863 else if ( !extn )
864 {
865 *str++ = '.';
866 extn = 1; /* we've got an extension */
867 left = 3; /* 3 chars in extension */
868 }
869 else
870 {
871 /* any embedded dots after the first are converted to _ */
872 *str++ = '_';
873 }
874 break;
875 case '~':
876 case '#': /* don't lose these, they're important */
877 if ( ! left )
878 str[-1] = c; /* replace last character of part */
879 /* FALLTHRU */
880 default:
881 if ( left )
882 {
883 *str++ = tolower (c); /* map to lower case (looks nicer) */
884 left--;
885 dots = 0; /* started a path component */
886 }
887 break;
888 }
889 }
890 *str = '\0';
fc85cb29
RS
891 }
892 else
893 {
894 strcpy (shortname, name);
895 unixtodos_filename (shortname);
95ed0025 896 }
480b0c5b
GV
897
898 if (pPath)
fc85cb29 899 *pPath = shortname + (path - name);
480b0c5b 900
fc85cb29 901 return shortname;
480b0c5b
GV
902}
903
904
905/* Shadow some MSVC runtime functions to map requests for long filenames
906 to reasonable short names if necessary. This was originally added to
907 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
908 long file names. */
909
910int
911sys_access (const char * path, int mode)
912{
913 return _access (map_win32_filename (path, NULL), mode);
914}
915
916int
917sys_chdir (const char * path)
918{
919 return _chdir (map_win32_filename (path, NULL));
920}
921
922int
923sys_chmod (const char * path, int mode)
924{
925 return _chmod (map_win32_filename (path, NULL), mode);
926}
927
928int
929sys_creat (const char * path, int mode)
930{
931 return _creat (map_win32_filename (path, NULL), mode);
932}
933
934FILE *
935sys_fopen(const char * path, const char * mode)
936{
937 int fd;
938 int oflag;
939 const char * mode_save = mode;
940
941 /* Force all file handles to be non-inheritable. This is necessary to
942 ensure child processes don't unwittingly inherit handles that might
943 prevent future file access. */
944
945 if (mode[0] == 'r')
946 oflag = O_RDONLY;
947 else if (mode[0] == 'w' || mode[0] == 'a')
948 oflag = O_WRONLY | O_CREAT | O_TRUNC;
95ed0025 949 else
480b0c5b
GV
950 return NULL;
951
952 /* Only do simplistic option parsing. */
953 while (*++mode)
954 if (mode[0] == '+')
955 {
956 oflag &= ~(O_RDONLY | O_WRONLY);
957 oflag |= O_RDWR;
958 }
959 else if (mode[0] == 'b')
960 {
961 oflag &= ~O_TEXT;
962 oflag |= O_BINARY;
963 }
964 else if (mode[0] == 't')
965 {
966 oflag &= ~O_BINARY;
967 oflag |= O_TEXT;
968 }
969 else break;
970
971 fd = _open (map_win32_filename (path, NULL), oflag | _O_NOINHERIT, 0644);
972 if (fd < 0)
973 return NULL;
974
975 return fdopen (fd, mode_save);
95ed0025 976}
480b0c5b
GV
977
978int
979sys_link (const char * path1, const char * path2)
980{
981 errno = EINVAL;
982 return -1;
983}
984
985int
986sys_mkdir (const char * path)
987{
988 return _mkdir (map_win32_filename (path, NULL));
989}
990
991char *
992sys_mktemp (char * template)
993{
994 return (char *) map_win32_filename ((const char *) _mktemp (template), NULL);
995}
996
997int
998sys_open (const char * path, int oflag, int mode)
999{
1000 /* Force all file handles to be non-inheritable. */
1001 return _open (map_win32_filename (path, NULL), oflag | _O_NOINHERIT, mode);
1002}
1003
1004int
1005sys_rename (const char * oldname, const char * newname)
1006{
1007 char temp[MAX_PATH];
1008
1009 /* MoveFile on Win95 doesn't correctly change the short file name
1010 alias when oldname has a three char extension and newname has the
1011 same first three chars in its extension. To avoid problems, on
1012 Win95 we rename to a temporary name first. */
1013
1014 strcpy (temp, map_win32_filename (oldname, NULL));
1015
1016 if (GetVersion () & 0x80000000)
1017 {
1018 char * p;
1019
1020 unixtodos_filename (temp);
1021 if (p = strrchr (temp, '\\'))
1022 p++;
1023 else
1024 p = temp;
1025 strcpy (p, "__XXXXXX");
1026 _mktemp (temp);
1027 if (rename (map_win32_filename (oldname, NULL), temp) < 0)
1028 return -1;
1029 }
1030
1031 /* Emulate Unix behaviour - newname is deleted if it already exists
1032 (at least if it is a file; don't do this for directories). */
1033 newname = map_win32_filename (newname, NULL);
1034 if (GetFileAttributes (newname) != -1)
1035 {
1036 _chmod (newname, 0666);
1037 _unlink (newname);
1038 }
1039
1040 return rename (temp, newname);
1041}
1042
1043int
1044sys_rmdir (const char * path)
1045{
1046 return _rmdir (map_win32_filename (path, NULL));
1047}
1048
1049int
1050sys_unlink (const char * path)
1051{
1052 return _unlink (map_win32_filename (path, NULL));
1053}
1054
1055static FILETIME utc_base_ft;
1056static long double utc_base;
1057static int init = 0;
1058
1059static time_t
1060convert_time (FILETIME ft)
1061{
1062 long double ret;
1063
1064 if (!init)
1065 {
1066 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
1067 SYSTEMTIME st;
1068
1069 st.wYear = 1970;
1070 st.wMonth = 1;
1071 st.wDay = 1;
1072 st.wHour = 0;
1073 st.wMinute = 0;
1074 st.wSecond = 0;
1075 st.wMilliseconds = 0;
1076
1077 SystemTimeToFileTime (&st, &utc_base_ft);
1078 utc_base = (long double) utc_base_ft.dwHighDateTime
1079 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
1080 init = 1;
1081 }
1082
1083 if (CompareFileTime (&ft, &utc_base_ft) < 0)
1084 return 0;
1085
1086 ret = (long double) ft.dwHighDateTime * 4096 * 1024 * 1024 + ft.dwLowDateTime;
1087 ret -= utc_base;
1088 return (time_t) (ret * 1e-7);
1089}
1090
1091#if 0
1092/* in case we ever have need of this */
1093void
1094convert_from_time_t (time_t time, FILETIME * pft)
1095{
1096 long double tmp;
1097
1098 if (!init)
1099 {
1100 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
1101 SYSTEMTIME st;
1102
1103 st.wYear = 1970;
1104 st.wMonth = 1;
1105 st.wDay = 1;
1106 st.wHour = 0;
1107 st.wMinute = 0;
1108 st.wSecond = 0;
1109 st.wMilliseconds = 0;
1110
1111 SystemTimeToFileTime (&st, &utc_base_ft);
1112 utc_base = (long double) utc_base_ft.dwHighDateTime
1113 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
1114 init = 1;
1115 }
1116
1117 /* time in 100ns units since 1-Jan-1601 */
1118 tmp = (long double) time * 1e7 + utc_base;
1119 pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024));
1120 pft->dwLowDateTime = (DWORD) (tmp - pft->dwHighDateTime);
1121}
1122#endif
1123
1124/* "PJW" algorithm (see the "Dragon" compiler book). */
1125static unsigned
1126hashval (const char * str)
1127{
1128 unsigned h = 0;
1129 unsigned g;
1130 while (*str)
1131 {
1132 h = (h << 4) + *str++;
1133 if ((g = h & 0xf0000000) != 0)
1134 h = (h ^ (g >> 24)) & 0x0fffffff;
1135 }
1136 return h;
1137}
1138
1139/* Return the hash value of the canonical pathname, excluding the
1140 drive/UNC header, to get a hopefully unique inode number. */
1141static _ino_t
1142generate_inode_val (const char * name)
1143{
1144 char fullname[ MAX_PATH ];
1145 char * p;
1146 unsigned hash;
1147
1148 GetFullPathName (name, sizeof (fullname), fullname, &p);
1149 get_volume_info (fullname, &p);
1150 /* Normal Win32 filesystems are still case insensitive. */
1151 _strlwr (p);
1152 hash = hashval (p);
1153 return (_ino_t) (hash ^ (hash >> 16));
1154}
1155
1156/* MSVC stat function can't cope with UNC names and has other bugs, so
1157 replace it with our own. This also allows us to calculate consistent
1158 inode values without hacks in the main Emacs code. */
1159int
1160stat (const char * path, struct stat * buf)
1161{
1162 char * name;
1163 WIN32_FIND_DATA wfd;
1164 HANDLE fh;
1165 int permission;
1166 int len;
1167 int rootdir = FALSE;
1168
1169 if (path == NULL || buf == NULL)
1170 {
1171 errno = EFAULT;
1172 return -1;
1173 }
1174
1175 name = (char *) map_win32_filename (path, &path);
1176 /* must be valid filename, no wild cards */
1177 if (strchr (name, '*') || strchr (name, '?'))
1178 {
1179 errno = ENOENT;
1180 return -1;
1181 }
1182
1183 /* Remove trailing directory separator, unless name is the root
1184 directory of a drive or UNC volume in which case ensure there
1185 is a trailing separator. */
1186 len = strlen (name);
1187 rootdir = (path >= name + len - 1
1188 && (IS_DIRECTORY_SEP (*path) || *path == 0));
1189 name = strcpy (alloca (len + 2), name);
1190
1191 if (rootdir)
1192 {
1193 if (!IS_DIRECTORY_SEP (name[len-1]))
1194 strcat (name, "\\");
1195 if (GetDriveType (name) < 2)
1196 {
1197 errno = ENOENT;
1198 return -1;
1199 }
1200 memset (&wfd, 0, sizeof (wfd));
1201 wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
1202 wfd.ftCreationTime = utc_base_ft;
1203 wfd.ftLastAccessTime = utc_base_ft;
1204 wfd.ftLastWriteTime = utc_base_ft;
1205 strcpy (wfd.cFileName, name);
1206 }
1207 else
1208 {
1209 if (IS_DIRECTORY_SEP (name[len-1]))
1210 name[len - 1] = 0;
1211 fh = FindFirstFile (name, &wfd);
1212 if (fh == INVALID_HANDLE_VALUE)
1213 {
1214 errno = ENOENT;
1215 return -1;
1216 }
1217 FindClose (fh);
1218 }
1219
1220 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1221 {
1222 buf->st_mode = _S_IFDIR;
1223 buf->st_nlink = 2; /* doesn't really matter */
1224 }
1225 else
1226 {
1227#if 0
1228 /* This is more accurate in terms of gettting the correct number
1229 of links, but is quite slow (it is noticable when Emacs is
1230 making a list of file name completions). */
1231 BY_HANDLE_FILE_INFORMATION info;
1232
1233 fh = CreateFile (name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
1234 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1235
1236 if (GetFileInformationByHandle (fh, &info))
1237 {
1238 switch (GetFileType (fh))
1239 {
1240 case FILE_TYPE_DISK:
1241 buf->st_mode = _S_IFREG;
1242 break;
1243 case FILE_TYPE_PIPE:
1244 buf->st_mode = _S_IFIFO;
1245 break;
1246 case FILE_TYPE_CHAR:
1247 case FILE_TYPE_UNKNOWN:
1248 default:
1249 buf->st_mode = _S_IFCHR;
1250 }
1251 buf->st_nlink = info.nNumberOfLinks;
1252 /* Could use file index, but this is not guaranteed to be
1253 unique unless we keep a handle open all the time. */
1254 /* buf->st_ino = info.nFileIndexLow ^ info.nFileIndexHigh; */
1255 CloseHandle (fh);
1256 }
1257 else
1258 {
1259 errno = EACCES;
1260 return -1;
1261 }
1262#else
1263 buf->st_mode = _S_IFREG;
1264 buf->st_nlink = 1;
1265#endif
1266 }
1267
1268 /* consider files to belong to current user */
1269 buf->st_uid = the_passwd.pw_uid;
1270 buf->st_gid = the_passwd.pw_gid;
1271
1272 /* volume_info is set indirectly by map_win32_filename */
1273 buf->st_dev = volume_info.serialnum;
1274 buf->st_rdev = volume_info.serialnum;
1275
1276 buf->st_ino = generate_inode_val (name);
1277
1278 buf->st_size = wfd.nFileSizeLow;
1279
1280 /* Convert timestamps to Unix format. */
1281 buf->st_mtime = convert_time (wfd.ftLastWriteTime);
1282 buf->st_atime = convert_time (wfd.ftLastAccessTime);
1283 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
1284 buf->st_ctime = convert_time (wfd.ftCreationTime);
1285 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
1286
1287 /* determine rwx permissions */
1288 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
1289 permission = _S_IREAD;
1290 else
1291 permission = _S_IREAD | _S_IWRITE;
1292
1293 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1294 permission |= _S_IEXEC;
1295 else
1296 {
1297 char * p = strrchr (name, '.');
1298 if (p != NULL &&
1299 (stricmp (p, ".exe") == 0 ||
1300 stricmp (p, ".com") == 0 ||
1301 stricmp (p, ".bat") == 0 ||
1302 stricmp (p, ".cmd") == 0))
1303 permission |= _S_IEXEC;
1304 }
1305
1306 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
1307
1308 return 0;
1309}
1310
1311#ifdef HAVE_SOCKETS
1312
1313/* Wrappers for winsock functions to map between our file descriptors
1314 and winsock's handles; also set h_errno for convenience.
1315
1316 To allow Emacs to run on systems which don't have winsock support
1317 installed, we dynamically link to winsock on startup if present, and
1318 otherwise provide the minimum necessary functionality
1319 (eg. gethostname). */
1320
1321/* function pointers for relevant socket functions */
1322int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
1323void (PASCAL *pfn_WSASetLastError) (int iError);
1324int (PASCAL *pfn_WSAGetLastError) (void);
1325int (PASCAL *pfn_socket) (int af, int type, int protocol);
1326int (PASCAL *pfn_bind) (SOCKET s, const struct sockaddr *addr, int namelen);
1327int (PASCAL *pfn_connect) (SOCKET s, const struct sockaddr *addr, int namelen);
1328int (PASCAL *pfn_ioctlsocket) (SOCKET s, long cmd, u_long *argp);
1329int (PASCAL *pfn_recv) (SOCKET s, char * buf, int len, int flags);
1330int (PASCAL *pfn_send) (SOCKET s, const char * buf, int len, int flags);
1331int (PASCAL *pfn_closesocket) (SOCKET s);
1332int (PASCAL *pfn_shutdown) (SOCKET s, int how);
1333int (PASCAL *pfn_WSACleanup) (void);
1334
1335u_short (PASCAL *pfn_htons) (u_short hostshort);
1336u_short (PASCAL *pfn_ntohs) (u_short netshort);
1337unsigned long (PASCAL *pfn_inet_addr) (const char * cp);
1338int (PASCAL *pfn_gethostname) (char * name, int namelen);
1339struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
1340struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto);
1341
1342static int have_winsock;
1343static HANDLE winsock_lib;
1344
1345static void
1346term_winsock (void)
1347{
1348 if (have_winsock)
1349 {
1350 pfn_WSACleanup ();
1351 FreeLibrary (winsock_lib);
1352 }
1353}
1354
1355static void
1356init_winsock ()
1357{
1358 WSADATA winsockData;
1359
1360 winsock_lib = LoadLibrary ("wsock32.dll");
1361
1362 if (winsock_lib != NULL)
1363 {
1364 /* dynamically link to socket functions */
1365
1366#define LOAD_PROC(fn) \
1367 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
1368 goto fail;
1369
1370 LOAD_PROC( WSAStartup );
1371 LOAD_PROC( WSASetLastError );
1372 LOAD_PROC( WSAGetLastError );
1373 LOAD_PROC( socket );
1374 LOAD_PROC( bind );
1375 LOAD_PROC( connect );
1376 LOAD_PROC( ioctlsocket );
1377 LOAD_PROC( recv );
1378 LOAD_PROC( send );
1379 LOAD_PROC( closesocket );
1380 LOAD_PROC( shutdown );
1381 LOAD_PROC( htons );
1382 LOAD_PROC( ntohs );
1383 LOAD_PROC( inet_addr );
1384 LOAD_PROC( gethostname );
1385 LOAD_PROC( gethostbyname );
1386 LOAD_PROC( getservbyname );
1387 LOAD_PROC( WSACleanup );
1388
1389 /* specify version 1.1 of winsock */
1390 if (pfn_WSAStartup (0x101, &winsockData) == 0)
1391 {
1392 have_winsock = TRUE;
1393 return;
1394 }
1395
1396 fail:
1397 FreeLibrary (winsock_lib);
1398 }
1399 have_winsock = FALSE;
1400}
1401
1402
1403int h_errno = 0;
1404
1405/* function to set h_errno for compatability; map winsock error codes to
1406 normal system codes where they overlap (non-overlapping definitions
1407 are already in <sys/socket.h> */
1408static void set_errno ()
1409{
1410 if (!have_winsock)
1411 h_errno = EINVAL;
1412 else
1413 h_errno = pfn_WSAGetLastError ();
1414
1415 switch (h_errno)
1416 {
1417 case WSAEACCES: h_errno = EACCES; break;
1418 case WSAEBADF: h_errno = EBADF; break;
1419 case WSAEFAULT: h_errno = EFAULT; break;
1420 case WSAEINTR: h_errno = EINTR; break;
1421 case WSAEINVAL: h_errno = EINVAL; break;
1422 case WSAEMFILE: h_errno = EMFILE; break;
1423 case WSAENAMETOOLONG: h_errno = ENAMETOOLONG; break;
1424 case WSAENOTEMPTY: h_errno = ENOTEMPTY; break;
1425 }
1426 errno = h_errno;
1427}
1428
1429static void check_errno ()
1430{
1431 if (h_errno == 0 && have_winsock)
1432 pfn_WSASetLastError (0);
1433}
1434
1435/* [andrewi 3-May-96] I've had conflicting results using both methods,
1436 but I believe the method of keeping the socket handle separate (and
1437 insuring it is not inheritable) is the correct one. */
1438
1439//#define SOCK_REPLACE_HANDLE
1440
1441#ifdef SOCK_REPLACE_HANDLE
1442#define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
1443#else
1444#define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
1445#endif
1446
1447int
1448sys_socket(int af, int type, int protocol)
1449{
1450 int fd;
1451 long s;
1452 child_process * cp;
1453
1454 if (!have_winsock)
1455 {
1456 h_errno = ENETDOWN;
1457 return INVALID_SOCKET;
1458 }
1459
1460 check_errno ();
1461
1462 /* call the real socket function */
1463 s = (long) pfn_socket (af, type, protocol);
1464
1465 if (s != INVALID_SOCKET)
1466 {
1467 /* Although under NT 3.5 _open_osfhandle will accept a socket
1468 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
1469 that does not work under NT 3.1. However, we can get the same
1470 effect by using a backdoor function to replace an existing
1471 descriptor handle with the one we want. */
1472
1473 /* allocate a file descriptor (with appropriate flags) */
1474 fd = _open ("NUL:", _O_RDWR);
1475 if (fd >= 0)
1476 {
1477#ifdef SOCK_REPLACE_HANDLE
1478 /* now replace handle to NUL with our socket handle */
1479 CloseHandle ((HANDLE) _get_osfhandle (fd));
1480 _free_osfhnd (fd);
1481 _set_osfhnd (fd, s);
1482 /* setmode (fd, _O_BINARY); */
1483#else
1484 /* Make a non-inheritable copy of the socket handle. */
1485 {
1486 HANDLE parent;
1487 HANDLE new_s = INVALID_HANDLE_VALUE;
1488
1489 parent = GetCurrentProcess ();
1490
1491 DuplicateHandle (parent,
1492 (HANDLE) s,
1493 parent,
1494 &new_s,
1495 0,
1496 FALSE,
1497 DUPLICATE_SAME_ACCESS);
1498 pfn_closesocket (s);
1499 fd_info[fd].hnd = new_s;
1500 s = (SOCKET) new_s;
1501 }
1502#endif
1503
1504 /* set our own internal flags */
1505 fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
1506
1507 cp = new_child ();
1508 if (cp)
1509 {
1510 cp->fd = fd;
1511 cp->status = STATUS_READ_ACKNOWLEDGED;
1512
1513 /* attach child_process to fd_info */
1514 if (fd_info[ fd ].cp != NULL)
1515 {
1516 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
1517 abort ();
1518 }
1519
1520 fd_info[ fd ].cp = cp;
1521
1522 /* success! */
1523 return fd;
1524 }
1525
1526 /* clean up */
1527 _close (fd);
1528 }
1529 pfn_closesocket (s);
1530 h_errno = EMFILE;
1531 }
1532 set_errno ();
1533
1534 return -1;
1535}
1536
1537
1538int
1539sys_bind (int s, const struct sockaddr * addr, int namelen)
1540{
1541 if (!have_winsock)
1542 {
1543 h_errno = ENOTSOCK;
1544 return SOCKET_ERROR;
1545 }
1546
1547 check_errno ();
1548 if (fd_info[s].flags & FILE_SOCKET)
1549 {
1550 int rc = pfn_bind (SOCK_HANDLE (s), addr, namelen);
1551 if (rc == SOCKET_ERROR)
1552 set_errno ();
1553 return rc;
1554 }
1555 h_errno = ENOTSOCK;
1556 return SOCKET_ERROR;
1557}
1558
1559
1560int
1561sys_connect (int s, const struct sockaddr * name, int namelen)
1562{
1563 if (!have_winsock)
1564 {
1565 h_errno = ENOTSOCK;
1566 return SOCKET_ERROR;
1567 }
1568
1569 check_errno ();
1570 if (fd_info[s].flags & FILE_SOCKET)
1571 {
1572 int rc = pfn_connect (SOCK_HANDLE (s), name, namelen);
1573 if (rc == SOCKET_ERROR)
1574 set_errno ();
1575 return rc;
1576 }
1577 h_errno = ENOTSOCK;
1578 return SOCKET_ERROR;
1579}
1580
1581u_short
1582sys_htons (u_short hostshort)
1583{
1584 return (have_winsock) ?
1585 pfn_htons (hostshort) : hostshort;
1586}
1587
1588u_short
1589sys_ntohs (u_short netshort)
1590{
1591 return (have_winsock) ?
1592 pfn_ntohs (netshort) : netshort;
1593}
1594
1595unsigned long
1596sys_inet_addr (const char * cp)
1597{
1598 return (have_winsock) ?
1599 pfn_inet_addr (cp) : INADDR_NONE;
1600}
1601
1602int
1603sys_gethostname (char * name, int namelen)
1604{
1605 if (have_winsock)
1606 return pfn_gethostname (name, namelen);
1607
1608 if (namelen > MAX_COMPUTERNAME_LENGTH)
1609 return !GetComputerName (name, &namelen);
1610
1611 h_errno = EFAULT;
1612 return SOCKET_ERROR;
1613}
1614
1615struct hostent *
1616sys_gethostbyname(const char * name)
1617{
1618 struct hostent * host;
1619
1620 if (!have_winsock)
1621 {
1622 h_errno = ENETDOWN;
1623 return NULL;
1624 }
1625
1626 check_errno ();
1627 host = pfn_gethostbyname (name);
1628 if (!host)
1629 set_errno ();
1630 return host;
1631}
1632
1633struct servent *
1634sys_getservbyname(const char * name, const char * proto)
1635{
1636 struct servent * serv;
1637
1638 if (!have_winsock)
1639 {
1640 h_errno = ENETDOWN;
1641 return NULL;
1642 }
1643
1644 check_errno ();
1645 serv = pfn_getservbyname (name, proto);
1646 if (!serv)
1647 set_errno ();
1648 return serv;
1649}
1650
1651#endif /* HAVE_SOCKETS */
1652
1653
1654/* Shadow main io functions: we need to handle pipes and sockets more
1655 intelligently, and implement non-blocking mode as well. */
1656
1657int
1658sys_close (int fd)
1659{
1660 int rc;
1661
1662 if (fd < 0 || fd >= MAXDESC)
1663 {
1664 errno = EBADF;
1665 return -1;
1666 }
1667
1668 if (fd_info[fd].cp)
1669 {
1670 child_process * cp = fd_info[fd].cp;
1671
1672 fd_info[fd].cp = NULL;
1673
1674 if (CHILD_ACTIVE (cp))
1675 {
1676 /* if last descriptor to active child_process then cleanup */
1677 int i;
1678 for (i = 0; i < MAXDESC; i++)
1679 {
1680 if (i == fd)
1681 continue;
1682 if (fd_info[i].cp == cp)
1683 break;
1684 }
1685 if (i == MAXDESC)
1686 {
1687#if defined (HAVE_SOCKETS) && !defined (SOCK_REPLACE_HANDLE)
1688 if (fd_info[fd].flags & FILE_SOCKET)
1689 {
1690 if (!have_winsock) abort ();
1691
1692 pfn_shutdown (SOCK_HANDLE (fd), 2);
1693 rc = pfn_closesocket (SOCK_HANDLE (fd));
1694 }
1695#endif
1696 delete_child (cp);
1697 }
1698 }
1699 }
1700
1701 /* Note that sockets do not need special treatment here (at least on
1702 NT and Win95 using the standard tcp/ip stacks) - it appears that
1703 closesocket is equivalent to CloseHandle, which is to be expected
1704 because socket handles are fully fledged kernel handles. */
1705 rc = _close (fd);
1706
1707 if (rc == 0)
1708 fd_info[fd].flags = 0;
1709
1710 return rc;
1711}
1712
1713int
1714sys_dup (int fd)
1715{
1716 int new_fd;
1717
1718 new_fd = _dup (fd);
1719 if (new_fd >= 0)
1720 {
1721 /* duplicate our internal info as well */
1722 fd_info[new_fd] = fd_info[fd];
1723 }
1724 return new_fd;
1725}
1726
1727
1728int
1729sys_dup2 (int src, int dst)
1730{
1731 int rc;
1732
1733 if (dst < 0 || dst >= MAXDESC)
1734 {
1735 errno = EBADF;
1736 return -1;
1737 }
1738
1739 /* make sure we close the destination first if it's a pipe or socket */
1740 if (src != dst && fd_info[dst].flags != 0)
1741 sys_close (dst);
1742
1743 rc = _dup2 (src, dst);
1744 if (rc == 0)
1745 {
1746 /* duplicate our internal info as well */
1747 fd_info[dst] = fd_info[src];
1748 }
1749 return rc;
1750}
1751
1752/* From callproc.c */
1753extern Lisp_Object Vbinary_process_input;
1754extern Lisp_Object Vbinary_process_output;
1755
1756/* Unix pipe() has only one arg */
1757int
1758sys_pipe (int * phandles)
1759{
1760 int rc;
1761 unsigned flags;
1762 child_process * cp;
1763
1764 /* make pipe handles non-inheritable; when we spawn a child,
1765 we replace the relevant handle with an inheritable one. */
1766 rc = _pipe (phandles, 0, _O_NOINHERIT);
1767
1768 if (rc == 0)
1769 {
1770 /* set internal flags, and put read and write handles into binary
1771 mode as necessary; if not in binary mode, set the MSVC internal
1772 FDEV (0x40) flag to prevent _read from treating ^Z as eof (this
1773 could otherwise allow Emacs to hang because it then waits
1774 indefinitely for the child process to exit, when it might not be
1775 finished). */
1776 flags = FILE_PIPE | FILE_READ;
1777 if (!NILP (Vbinary_process_output))
1778 {
1779 flags |= FILE_BINARY;
1780 setmode (phandles[0], _O_BINARY);
1781 }
1782#if (_MSC_VER == 900)
1783 else
1784 _osfile[phandles[0]] |= 0x40;
1785#endif
1786
1787 fd_info[phandles[0]].flags = flags;
1788
1789 flags = FILE_PIPE | FILE_WRITE;
1790 if (!NILP (Vbinary_process_input))
1791 {
1792 flags |= FILE_BINARY;
1793 setmode (phandles[1], _O_BINARY);
1794 }
1795#if (_MSC_VER == 900)
1796 else
1797 _osfile[phandles[1]] |= 0x40;
1798#endif
1799
1800 fd_info[phandles[1]].flags = flags;
1801 }
1802
1803 return rc;
1804}
1805
f7554349
KH
1806/* From ntproc.c */
1807extern Lisp_Object Vwin32_pipe_read_delay;
1808
480b0c5b
GV
1809/* Function to do blocking read of one byte, needed to implement
1810 select. It is only allowed on sockets and pipes. */
1811int
1812_sys_read_ahead (int fd)
1813{
1814 child_process * cp;
1815 int rc;
1816
1817 if (fd < 0 || fd >= MAXDESC)
1818 return STATUS_READ_ERROR;
1819
1820 cp = fd_info[fd].cp;
1821
1822 if (cp == NULL || cp->fd != fd || cp->status != STATUS_READ_READY)
1823 return STATUS_READ_ERROR;
1824
1825 if ((fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET)) == 0
1826 || (fd_info[fd].flags & FILE_READ) == 0)
1827 {
1828 DebPrint (("_sys_read_ahead: internal error: fd %d is not a pipe or socket!\n", fd));
1829 abort ();
1830 }
1831
1832 cp->status = STATUS_READ_IN_PROGRESS;
1833
1834 if (fd_info[fd].flags & FILE_PIPE)
f7554349
KH
1835 {
1836 /* Use read to get CRLF translation */
1837 rc = _read (fd, &cp->chr, sizeof (char));
1838
1839 /* Give subprocess time to buffer some more output for us before
1840 reporting that input is available; we need this because Win95
1841 connects DOS programs to pipes by making the pipe appear to be
1842 the normal console stdout - as a result most DOS programs will
1843 write to stdout without buffering, ie. one character at a
1844 time. Even some Win32 programs do this - "dir" in a command
1845 shell on NT is very slow if we don't do this. */
1846 if (rc > 0)
1847 {
1848 int wait = XINT (Vwin32_pipe_read_delay);
1849
1850 if (wait > 0)
1851 Sleep (wait);
1852 else if (wait < 0)
1853 while (++wait <= 0)
1854 /* Yield remainder of our time slice, effectively giving a
1855 temporary priority boost to the child process. */
1856 Sleep (0);
1857 }
1858 }
480b0c5b
GV
1859#ifdef HAVE_SOCKETS
1860 else if (fd_info[fd].flags & FILE_SOCKET)
1861 rc = pfn_recv (SOCK_HANDLE (fd), &cp->chr, sizeof (char), 0);
1862#endif
1863
1864 if (rc == sizeof (char))
1865 cp->status = STATUS_READ_SUCCEEDED;
1866 else
1867 cp->status = STATUS_READ_FAILED;
1868
1869 return cp->status;
1870}
1871
1872int
1873sys_read (int fd, char * buffer, unsigned int count)
1874{
1875 int nchars;
1876 int extra = 0;
1877 int to_read;
1878 DWORD waiting;
1879
1880 if (fd < 0 || fd >= MAXDESC)
1881 {
1882 errno = EBADF;
1883 return -1;
1884 }
1885
1886 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
1887 {
1888 child_process *cp = fd_info[fd].cp;
1889
1890 if ((fd_info[fd].flags & FILE_READ) == 0)
1891 {
1892 errno = EBADF;
1893 return -1;
1894 }
1895
1896 /* presence of a child_process structure means we are operating in
1897 non-blocking mode - otherwise we just call _read directly.
1898 Note that the child_process structure might be missing because
1899 reap_subprocess has been called; in this case the pipe is
1900 already broken, so calling _read on it is okay. */
1901 if (cp)
1902 {
1903 int current_status = cp->status;
1904
1905 switch (current_status)
1906 {
1907 case STATUS_READ_FAILED:
1908 case STATUS_READ_ERROR:
1909 /* report normal EOF */
1910 return 0;
1911
1912 case STATUS_READ_READY:
1913 case STATUS_READ_IN_PROGRESS:
1914 DebPrint (("sys_read called when read is in progress\n"));
1915 errno = EWOULDBLOCK;
1916 return -1;
1917
1918 case STATUS_READ_SUCCEEDED:
1919 /* consume read-ahead char */
1920 *buffer++ = cp->chr;
1921 count--;
1922 extra = 1;
1923 cp->status = STATUS_READ_ACKNOWLEDGED;
1924 ResetEvent (cp->char_avail);
1925
1926 case STATUS_READ_ACKNOWLEDGED:
1927 break;
1928
1929 default:
1930 DebPrint (("sys_read: bad status %d\n", current_status));
1931 errno = EBADF;
1932 return -1;
1933 }
1934
1935 if (fd_info[fd].flags & FILE_PIPE)
1936 {
1937 PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL);
1938 to_read = min (waiting, (DWORD) count);
1939
1940 /* Use read to get CRLF translation */
1941 nchars = _read (fd, buffer, to_read);
1942 }
1943#ifdef HAVE_SOCKETS
1944 else /* FILE_SOCKET */
1945 {
1946 if (!have_winsock) abort ();
1947
1948 /* do the equivalent of a non-blocking read */
1949 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
1950 if (waiting == 0 && extra == 0)
1951 {
1952 h_errno = errno = EWOULDBLOCK;
1953 return -1;
1954 }
1955
1956 nchars = 0;
1957 if (waiting)
1958 {
1959 /* always use binary mode for sockets */
1960 nchars = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0);
1961 if (nchars == SOCKET_ERROR)
1962 {
1963 DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
1964 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
1965 if (extra == 0)
1966 {
1967 set_errno ();
1968 return -1;
1969 }
1970 nchars = 0;
1971 }
1972 }
1973 }
1974#endif
1975 }
1976 else
1977 nchars = _read (fd, buffer, count);
1978 }
1979 else
1980 nchars = _read (fd, buffer, count);
1981
1982 return nchars + extra;
1983}
1984
1985/* For now, don't bother with a non-blocking mode */
1986int
1987sys_write (int fd, const void * buffer, unsigned int count)
1988{
1989 int nchars;
1990
1991 if (fd < 0 || fd >= MAXDESC)
1992 {
1993 errno = EBADF;
1994 return -1;
1995 }
1996
1997 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
1998 if ((fd_info[fd].flags & FILE_WRITE) == 0)
1999 {
2000 errno = EBADF;
2001 return -1;
2002 }
2003#ifdef HAVE_SOCKETS
2004 if (fd_info[fd].flags & FILE_SOCKET)
2005 {
2006 if (!have_winsock) abort ();
2007 nchars = pfn_send (SOCK_HANDLE (fd), buffer, count, 0);
2008 if (nchars == SOCKET_ERROR)
2009 {
2010 DebPrint(("sys_read.send failed with error %d on socket %ld\n",
2011 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
2012 set_errno ();
2013 }
2014 }
2015 else
2016#endif
2017 nchars = _write (fd, buffer, count);
2018
2019 return nchars;
2020}
2021
2022
2023void
2024term_ntproc ()
2025{
2026#ifdef HAVE_SOCKETS
2027 /* shutdown the socket interface if necessary */
2028 term_winsock ();
2029#endif
2030}
2031
f7554349
KH
2032extern BOOL can_run_dos_process;
2033extern BOOL dos_process_running;
2034
480b0c5b
GV
2035void
2036init_ntproc ()
2037{
2038#ifdef HAVE_SOCKETS
2039 /* initialise the socket interface if available */
2040 init_winsock ();
2041#endif
2042
2043 /* Initial preparation for subprocess support: replace our standard
2044 handles with non-inheritable versions. */
2045 {
2046 HANDLE parent;
2047 HANDLE stdin_save = INVALID_HANDLE_VALUE;
2048 HANDLE stdout_save = INVALID_HANDLE_VALUE;
2049 HANDLE stderr_save = INVALID_HANDLE_VALUE;
2050
2051 parent = GetCurrentProcess ();
2052
2053 /* ignore errors when duplicating and closing; typically the
2054 handles will be invalid when running as a gui program. */
2055 DuplicateHandle (parent,
2056 GetStdHandle (STD_INPUT_HANDLE),
2057 parent,
2058 &stdin_save,
2059 0,
2060 FALSE,
2061 DUPLICATE_SAME_ACCESS);
2062
2063 DuplicateHandle (parent,
2064 GetStdHandle (STD_OUTPUT_HANDLE),
2065 parent,
2066 &stdout_save,
2067 0,
2068 FALSE,
2069 DUPLICATE_SAME_ACCESS);
2070
2071 DuplicateHandle (parent,
2072 GetStdHandle (STD_ERROR_HANDLE),
2073 parent,
2074 &stderr_save,
2075 0,
2076 FALSE,
2077 DUPLICATE_SAME_ACCESS);
2078
2079 fclose (stdin);
2080 fclose (stdout);
2081 fclose (stderr);
2082
2083 if (stdin_save != INVALID_HANDLE_VALUE)
2084 _open_osfhandle ((long) stdin_save, O_TEXT);
2085 else
2086 open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY);
2087 fdopen (0, "r");
2088
2089 if (stdout_save != INVALID_HANDLE_VALUE)
2090 _open_osfhandle ((long) stdout_save, O_TEXT);
2091 else
2092 open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
2093 fdopen (1, "w");
2094
2095 if (stderr_save != INVALID_HANDLE_VALUE)
2096 _open_osfhandle ((long) stderr_save, O_TEXT);
2097 else
2098 open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
2099 fdopen (2, "w");
2100 }
2101
f7554349
KH
2102 /* Only allow Emacs to run DOS programs on Win95. */
2103 can_run_dos_process = (GetVersion () & 0x80000000);
2104 dos_process_running = FALSE;
2105
480b0c5b
GV
2106 /* unfortunately, atexit depends on implementation of malloc */
2107 /* atexit (term_ntproc); */
2108 signal (SIGABRT, term_ntproc);
2109}
2110
2111/* end of nt.c */