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