(Vwin32_downcase_file_names): New variable.
[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
480b0c5b
GV
727 *str++ = '\\';
728 *str = 0;
95ed0025 729 }
480b0c5b
GV
730
731 if (pPath)
732 *pPath = name;
733
734 if (GetVolumeInformation (rootname,
735 volume_info.name, 32,
736 &volume_info.serialnum,
737 &volume_info.maxcomp,
738 &volume_info.flags,
739 volume_info.type, 32))
95ed0025 740 {
480b0c5b 741 return TRUE;
95ed0025 742 }
480b0c5b
GV
743 return FALSE;
744}
745
746/* Determine if volume is FAT format (ie. only supports short 8.3
747 names); also set path pointer to start of pathname in name. */
748int
749is_fat_volume (const char * name, const char ** pPath)
750{
751 if (get_volume_info (name, pPath))
752 return (volume_info.maxcomp == 12);
753 return FALSE;
754}
755
756/* Map filename to a legal 8.3 name if necessary. */
757const char *
758map_win32_filename (const char * name, const char ** pPath)
759{
760 static char shortname[MAX_PATH];
761 char * str = shortname;
762 char c;
480b0c5b
GV
763 char * path;
764
765 if (is_fat_volume (name, &path)) /* truncate to 8.3 */
95ed0025 766 {
480b0c5b
GV
767 register int left = 8; /* maximum number of chars in part */
768 register int extn = 0; /* extension added? */
769 register int dots = 2; /* maximum number of dots allowed */
770
771 while (name < path)
772 *str++ = *name++; /* skip past UNC header */
773
774 while ((c = *name++))
775 {
776 switch ( c )
777 {
778 case '\\':
779 case '/':
780 *str++ = '\\';
781 extn = 0; /* reset extension flags */
782 dots = 2; /* max 2 dots */
783 left = 8; /* max length 8 for main part */
784 break;
785 case ':':
786 *str++ = ':';
787 extn = 0; /* reset extension flags */
788 dots = 2; /* max 2 dots */
789 left = 8; /* max length 8 for main part */
790 break;
791 case '.':
792 if ( dots )
793 {
794 /* Convert path components of the form .xxx to _xxx,
795 but leave . and .. as they are. This allows .emacs
796 to be read as _emacs, for example. */
797
798 if (! *name ||
799 *name == '.' ||
800 IS_DIRECTORY_SEP (*name))
801 {
802 *str++ = '.';
803 dots--;
804 }
805 else
806 {
807 *str++ = '_';
808 left--;
809 dots = 0;
810 }
811 }
812 else if ( !extn )
813 {
814 *str++ = '.';
815 extn = 1; /* we've got an extension */
816 left = 3; /* 3 chars in extension */
817 }
818 else
819 {
820 /* any embedded dots after the first are converted to _ */
821 *str++ = '_';
822 }
823 break;
824 case '~':
825 case '#': /* don't lose these, they're important */
826 if ( ! left )
827 str[-1] = c; /* replace last character of part */
828 /* FALLTHRU */
829 default:
830 if ( left )
831 {
832 *str++ = tolower (c); /* map to lower case (looks nicer) */
833 left--;
834 dots = 0; /* started a path component */
835 }
836 break;
837 }
838 }
839 *str = '\0';
fc85cb29
RS
840 }
841 else
842 {
843 strcpy (shortname, name);
844 unixtodos_filename (shortname);
95ed0025 845 }
480b0c5b
GV
846
847 if (pPath)
fc85cb29 848 *pPath = shortname + (path - name);
480b0c5b 849
fc85cb29 850 return shortname;
480b0c5b
GV
851}
852
853
854/* Shadow some MSVC runtime functions to map requests for long filenames
855 to reasonable short names if necessary. This was originally added to
856 permit running Emacs on NT 3.1 on a FAT partition, which doesn't support
857 long file names. */
858
859int
860sys_access (const char * path, int mode)
861{
862 return _access (map_win32_filename (path, NULL), mode);
863}
864
865int
866sys_chdir (const char * path)
867{
868 return _chdir (map_win32_filename (path, NULL));
869}
870
871int
872sys_chmod (const char * path, int mode)
873{
874 return _chmod (map_win32_filename (path, NULL), mode);
875}
876
877int
878sys_creat (const char * path, int mode)
879{
880 return _creat (map_win32_filename (path, NULL), mode);
881}
882
883FILE *
884sys_fopen(const char * path, const char * mode)
885{
886 int fd;
887 int oflag;
888 const char * mode_save = mode;
889
890 /* Force all file handles to be non-inheritable. This is necessary to
891 ensure child processes don't unwittingly inherit handles that might
892 prevent future file access. */
893
894 if (mode[0] == 'r')
895 oflag = O_RDONLY;
896 else if (mode[0] == 'w' || mode[0] == 'a')
897 oflag = O_WRONLY | O_CREAT | O_TRUNC;
95ed0025 898 else
480b0c5b
GV
899 return NULL;
900
901 /* Only do simplistic option parsing. */
902 while (*++mode)
903 if (mode[0] == '+')
904 {
905 oflag &= ~(O_RDONLY | O_WRONLY);
906 oflag |= O_RDWR;
907 }
908 else if (mode[0] == 'b')
909 {
910 oflag &= ~O_TEXT;
911 oflag |= O_BINARY;
912 }
913 else if (mode[0] == 't')
914 {
915 oflag &= ~O_BINARY;
916 oflag |= O_TEXT;
917 }
918 else break;
919
920 fd = _open (map_win32_filename (path, NULL), oflag | _O_NOINHERIT, 0644);
921 if (fd < 0)
922 return NULL;
923
924 return fdopen (fd, mode_save);
95ed0025 925}
480b0c5b
GV
926
927int
928sys_link (const char * path1, const char * path2)
929{
930 errno = EINVAL;
931 return -1;
932}
933
934int
935sys_mkdir (const char * path)
936{
937 return _mkdir (map_win32_filename (path, NULL));
938}
939
940char *
941sys_mktemp (char * template)
942{
943 return (char *) map_win32_filename ((const char *) _mktemp (template), NULL);
944}
945
946int
947sys_open (const char * path, int oflag, int mode)
948{
949 /* Force all file handles to be non-inheritable. */
950 return _open (map_win32_filename (path, NULL), oflag | _O_NOINHERIT, mode);
951}
952
953int
954sys_rename (const char * oldname, const char * newname)
955{
956 char temp[MAX_PATH];
957
958 /* MoveFile on Win95 doesn't correctly change the short file name
959 alias when oldname has a three char extension and newname has the
960 same first three chars in its extension. To avoid problems, on
961 Win95 we rename to a temporary name first. */
962
963 strcpy (temp, map_win32_filename (oldname, NULL));
964
965 if (GetVersion () & 0x80000000)
966 {
967 char * p;
968
969 unixtodos_filename (temp);
970 if (p = strrchr (temp, '\\'))
971 p++;
972 else
973 p = temp;
974 strcpy (p, "__XXXXXX");
975 _mktemp (temp);
976 if (rename (map_win32_filename (oldname, NULL), temp) < 0)
977 return -1;
978 }
979
980 /* Emulate Unix behaviour - newname is deleted if it already exists
981 (at least if it is a file; don't do this for directories). */
982 newname = map_win32_filename (newname, NULL);
983 if (GetFileAttributes (newname) != -1)
984 {
985 _chmod (newname, 0666);
986 _unlink (newname);
987 }
988
989 return rename (temp, newname);
990}
991
992int
993sys_rmdir (const char * path)
994{
995 return _rmdir (map_win32_filename (path, NULL));
996}
997
998int
999sys_unlink (const char * path)
1000{
1001 return _unlink (map_win32_filename (path, NULL));
1002}
1003
1004static FILETIME utc_base_ft;
1005static long double utc_base;
1006static int init = 0;
1007
1008static time_t
1009convert_time (FILETIME ft)
1010{
1011 long double ret;
1012
1013 if (!init)
1014 {
1015 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
1016 SYSTEMTIME st;
1017
1018 st.wYear = 1970;
1019 st.wMonth = 1;
1020 st.wDay = 1;
1021 st.wHour = 0;
1022 st.wMinute = 0;
1023 st.wSecond = 0;
1024 st.wMilliseconds = 0;
1025
1026 SystemTimeToFileTime (&st, &utc_base_ft);
1027 utc_base = (long double) utc_base_ft.dwHighDateTime
1028 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
1029 init = 1;
1030 }
1031
1032 if (CompareFileTime (&ft, &utc_base_ft) < 0)
1033 return 0;
1034
1035 ret = (long double) ft.dwHighDateTime * 4096 * 1024 * 1024 + ft.dwLowDateTime;
1036 ret -= utc_base;
1037 return (time_t) (ret * 1e-7);
1038}
1039
1040#if 0
1041/* in case we ever have need of this */
1042void
1043convert_from_time_t (time_t time, FILETIME * pft)
1044{
1045 long double tmp;
1046
1047 if (!init)
1048 {
1049 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
1050 SYSTEMTIME st;
1051
1052 st.wYear = 1970;
1053 st.wMonth = 1;
1054 st.wDay = 1;
1055 st.wHour = 0;
1056 st.wMinute = 0;
1057 st.wSecond = 0;
1058 st.wMilliseconds = 0;
1059
1060 SystemTimeToFileTime (&st, &utc_base_ft);
1061 utc_base = (long double) utc_base_ft.dwHighDateTime
1062 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime;
1063 init = 1;
1064 }
1065
1066 /* time in 100ns units since 1-Jan-1601 */
1067 tmp = (long double) time * 1e7 + utc_base;
1068 pft->dwHighDateTime = (DWORD) (tmp / (4096.0 * 1024 * 1024));
1069 pft->dwLowDateTime = (DWORD) (tmp - pft->dwHighDateTime);
1070}
1071#endif
1072
1073/* "PJW" algorithm (see the "Dragon" compiler book). */
1074static unsigned
1075hashval (const char * str)
1076{
1077 unsigned h = 0;
1078 unsigned g;
1079 while (*str)
1080 {
1081 h = (h << 4) + *str++;
1082 if ((g = h & 0xf0000000) != 0)
1083 h = (h ^ (g >> 24)) & 0x0fffffff;
1084 }
1085 return h;
1086}
1087
1088/* Return the hash value of the canonical pathname, excluding the
1089 drive/UNC header, to get a hopefully unique inode number. */
1090static _ino_t
1091generate_inode_val (const char * name)
1092{
1093 char fullname[ MAX_PATH ];
1094 char * p;
1095 unsigned hash;
1096
1097 GetFullPathName (name, sizeof (fullname), fullname, &p);
1098 get_volume_info (fullname, &p);
1099 /* Normal Win32 filesystems are still case insensitive. */
1100 _strlwr (p);
1101 hash = hashval (p);
1102 return (_ino_t) (hash ^ (hash >> 16));
1103}
1104
1105/* MSVC stat function can't cope with UNC names and has other bugs, so
1106 replace it with our own. This also allows us to calculate consistent
1107 inode values without hacks in the main Emacs code. */
1108int
1109stat (const char * path, struct stat * buf)
1110{
1111 char * name;
1112 WIN32_FIND_DATA wfd;
1113 HANDLE fh;
1114 int permission;
1115 int len;
1116 int rootdir = FALSE;
1117
1118 if (path == NULL || buf == NULL)
1119 {
1120 errno = EFAULT;
1121 return -1;
1122 }
1123
1124 name = (char *) map_win32_filename (path, &path);
1125 /* must be valid filename, no wild cards */
1126 if (strchr (name, '*') || strchr (name, '?'))
1127 {
1128 errno = ENOENT;
1129 return -1;
1130 }
1131
1132 /* Remove trailing directory separator, unless name is the root
1133 directory of a drive or UNC volume in which case ensure there
1134 is a trailing separator. */
1135 len = strlen (name);
1136 rootdir = (path >= name + len - 1
1137 && (IS_DIRECTORY_SEP (*path) || *path == 0));
1138 name = strcpy (alloca (len + 2), name);
1139
1140 if (rootdir)
1141 {
1142 if (!IS_DIRECTORY_SEP (name[len-1]))
1143 strcat (name, "\\");
1144 if (GetDriveType (name) < 2)
1145 {
1146 errno = ENOENT;
1147 return -1;
1148 }
1149 memset (&wfd, 0, sizeof (wfd));
1150 wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
1151 wfd.ftCreationTime = utc_base_ft;
1152 wfd.ftLastAccessTime = utc_base_ft;
1153 wfd.ftLastWriteTime = utc_base_ft;
1154 strcpy (wfd.cFileName, name);
1155 }
1156 else
1157 {
1158 if (IS_DIRECTORY_SEP (name[len-1]))
1159 name[len - 1] = 0;
1160 fh = FindFirstFile (name, &wfd);
1161 if (fh == INVALID_HANDLE_VALUE)
1162 {
1163 errno = ENOENT;
1164 return -1;
1165 }
1166 FindClose (fh);
1167 }
1168
1169 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1170 {
1171 buf->st_mode = _S_IFDIR;
1172 buf->st_nlink = 2; /* doesn't really matter */
1173 }
1174 else
1175 {
1176#if 0
1177 /* This is more accurate in terms of gettting the correct number
1178 of links, but is quite slow (it is noticable when Emacs is
1179 making a list of file name completions). */
1180 BY_HANDLE_FILE_INFORMATION info;
1181
1182 fh = CreateFile (name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
1183 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1184
1185 if (GetFileInformationByHandle (fh, &info))
1186 {
1187 switch (GetFileType (fh))
1188 {
1189 case FILE_TYPE_DISK:
1190 buf->st_mode = _S_IFREG;
1191 break;
1192 case FILE_TYPE_PIPE:
1193 buf->st_mode = _S_IFIFO;
1194 break;
1195 case FILE_TYPE_CHAR:
1196 case FILE_TYPE_UNKNOWN:
1197 default:
1198 buf->st_mode = _S_IFCHR;
1199 }
1200 buf->st_nlink = info.nNumberOfLinks;
1201 /* Could use file index, but this is not guaranteed to be
1202 unique unless we keep a handle open all the time. */
1203 /* buf->st_ino = info.nFileIndexLow ^ info.nFileIndexHigh; */
1204 CloseHandle (fh);
1205 }
1206 else
1207 {
1208 errno = EACCES;
1209 return -1;
1210 }
1211#else
1212 buf->st_mode = _S_IFREG;
1213 buf->st_nlink = 1;
1214#endif
1215 }
1216
1217 /* consider files to belong to current user */
1218 buf->st_uid = the_passwd.pw_uid;
1219 buf->st_gid = the_passwd.pw_gid;
1220
1221 /* volume_info is set indirectly by map_win32_filename */
1222 buf->st_dev = volume_info.serialnum;
1223 buf->st_rdev = volume_info.serialnum;
1224
1225 buf->st_ino = generate_inode_val (name);
1226
1227 buf->st_size = wfd.nFileSizeLow;
1228
1229 /* Convert timestamps to Unix format. */
1230 buf->st_mtime = convert_time (wfd.ftLastWriteTime);
1231 buf->st_atime = convert_time (wfd.ftLastAccessTime);
1232 if (buf->st_atime == 0) buf->st_atime = buf->st_mtime;
1233 buf->st_ctime = convert_time (wfd.ftCreationTime);
1234 if (buf->st_ctime == 0) buf->st_ctime = buf->st_mtime;
1235
1236 /* determine rwx permissions */
1237 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
1238 permission = _S_IREAD;
1239 else
1240 permission = _S_IREAD | _S_IWRITE;
1241
1242 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1243 permission |= _S_IEXEC;
1244 else
1245 {
1246 char * p = strrchr (name, '.');
1247 if (p != NULL &&
1248 (stricmp (p, ".exe") == 0 ||
1249 stricmp (p, ".com") == 0 ||
1250 stricmp (p, ".bat") == 0 ||
1251 stricmp (p, ".cmd") == 0))
1252 permission |= _S_IEXEC;
1253 }
1254
1255 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
1256
1257 return 0;
1258}
1259
1260#ifdef HAVE_SOCKETS
1261
1262/* Wrappers for winsock functions to map between our file descriptors
1263 and winsock's handles; also set h_errno for convenience.
1264
1265 To allow Emacs to run on systems which don't have winsock support
1266 installed, we dynamically link to winsock on startup if present, and
1267 otherwise provide the minimum necessary functionality
1268 (eg. gethostname). */
1269
1270/* function pointers for relevant socket functions */
1271int (PASCAL *pfn_WSAStartup) (WORD wVersionRequired, LPWSADATA lpWSAData);
1272void (PASCAL *pfn_WSASetLastError) (int iError);
1273int (PASCAL *pfn_WSAGetLastError) (void);
1274int (PASCAL *pfn_socket) (int af, int type, int protocol);
1275int (PASCAL *pfn_bind) (SOCKET s, const struct sockaddr *addr, int namelen);
1276int (PASCAL *pfn_connect) (SOCKET s, const struct sockaddr *addr, int namelen);
1277int (PASCAL *pfn_ioctlsocket) (SOCKET s, long cmd, u_long *argp);
1278int (PASCAL *pfn_recv) (SOCKET s, char * buf, int len, int flags);
1279int (PASCAL *pfn_send) (SOCKET s, const char * buf, int len, int flags);
1280int (PASCAL *pfn_closesocket) (SOCKET s);
1281int (PASCAL *pfn_shutdown) (SOCKET s, int how);
1282int (PASCAL *pfn_WSACleanup) (void);
1283
1284u_short (PASCAL *pfn_htons) (u_short hostshort);
1285u_short (PASCAL *pfn_ntohs) (u_short netshort);
1286unsigned long (PASCAL *pfn_inet_addr) (const char * cp);
1287int (PASCAL *pfn_gethostname) (char * name, int namelen);
1288struct hostent * (PASCAL *pfn_gethostbyname) (const char * name);
1289struct servent * (PASCAL *pfn_getservbyname) (const char * name, const char * proto);
1290
1291static int have_winsock;
1292static HANDLE winsock_lib;
1293
1294static void
1295term_winsock (void)
1296{
1297 if (have_winsock)
1298 {
1299 pfn_WSACleanup ();
1300 FreeLibrary (winsock_lib);
1301 }
1302}
1303
1304static void
1305init_winsock ()
1306{
1307 WSADATA winsockData;
1308
1309 winsock_lib = LoadLibrary ("wsock32.dll");
1310
1311 if (winsock_lib != NULL)
1312 {
1313 /* dynamically link to socket functions */
1314
1315#define LOAD_PROC(fn) \
1316 if ((pfn_##fn = (void *) GetProcAddress (winsock_lib, #fn)) == NULL) \
1317 goto fail;
1318
1319 LOAD_PROC( WSAStartup );
1320 LOAD_PROC( WSASetLastError );
1321 LOAD_PROC( WSAGetLastError );
1322 LOAD_PROC( socket );
1323 LOAD_PROC( bind );
1324 LOAD_PROC( connect );
1325 LOAD_PROC( ioctlsocket );
1326 LOAD_PROC( recv );
1327 LOAD_PROC( send );
1328 LOAD_PROC( closesocket );
1329 LOAD_PROC( shutdown );
1330 LOAD_PROC( htons );
1331 LOAD_PROC( ntohs );
1332 LOAD_PROC( inet_addr );
1333 LOAD_PROC( gethostname );
1334 LOAD_PROC( gethostbyname );
1335 LOAD_PROC( getservbyname );
1336 LOAD_PROC( WSACleanup );
1337
1338 /* specify version 1.1 of winsock */
1339 if (pfn_WSAStartup (0x101, &winsockData) == 0)
1340 {
1341 have_winsock = TRUE;
1342 return;
1343 }
1344
1345 fail:
1346 FreeLibrary (winsock_lib);
1347 }
1348 have_winsock = FALSE;
1349}
1350
1351
1352int h_errno = 0;
1353
1354/* function to set h_errno for compatability; map winsock error codes to
1355 normal system codes where they overlap (non-overlapping definitions
1356 are already in <sys/socket.h> */
1357static void set_errno ()
1358{
1359 if (!have_winsock)
1360 h_errno = EINVAL;
1361 else
1362 h_errno = pfn_WSAGetLastError ();
1363
1364 switch (h_errno)
1365 {
1366 case WSAEACCES: h_errno = EACCES; break;
1367 case WSAEBADF: h_errno = EBADF; break;
1368 case WSAEFAULT: h_errno = EFAULT; break;
1369 case WSAEINTR: h_errno = EINTR; break;
1370 case WSAEINVAL: h_errno = EINVAL; break;
1371 case WSAEMFILE: h_errno = EMFILE; break;
1372 case WSAENAMETOOLONG: h_errno = ENAMETOOLONG; break;
1373 case WSAENOTEMPTY: h_errno = ENOTEMPTY; break;
1374 }
1375 errno = h_errno;
1376}
1377
1378static void check_errno ()
1379{
1380 if (h_errno == 0 && have_winsock)
1381 pfn_WSASetLastError (0);
1382}
1383
1384/* [andrewi 3-May-96] I've had conflicting results using both methods,
1385 but I believe the method of keeping the socket handle separate (and
1386 insuring it is not inheritable) is the correct one. */
1387
1388//#define SOCK_REPLACE_HANDLE
1389
1390#ifdef SOCK_REPLACE_HANDLE
1391#define SOCK_HANDLE(fd) ((SOCKET) _get_osfhandle (fd))
1392#else
1393#define SOCK_HANDLE(fd) ((SOCKET) fd_info[fd].hnd)
1394#endif
1395
1396int
1397sys_socket(int af, int type, int protocol)
1398{
1399 int fd;
1400 long s;
1401 child_process * cp;
1402
1403 if (!have_winsock)
1404 {
1405 h_errno = ENETDOWN;
1406 return INVALID_SOCKET;
1407 }
1408
1409 check_errno ();
1410
1411 /* call the real socket function */
1412 s = (long) pfn_socket (af, type, protocol);
1413
1414 if (s != INVALID_SOCKET)
1415 {
1416 /* Although under NT 3.5 _open_osfhandle will accept a socket
1417 handle, if opened with SO_OPENTYPE == SO_SYNCHRONOUS_NONALERT,
1418 that does not work under NT 3.1. However, we can get the same
1419 effect by using a backdoor function to replace an existing
1420 descriptor handle with the one we want. */
1421
1422 /* allocate a file descriptor (with appropriate flags) */
1423 fd = _open ("NUL:", _O_RDWR);
1424 if (fd >= 0)
1425 {
1426#ifdef SOCK_REPLACE_HANDLE
1427 /* now replace handle to NUL with our socket handle */
1428 CloseHandle ((HANDLE) _get_osfhandle (fd));
1429 _free_osfhnd (fd);
1430 _set_osfhnd (fd, s);
1431 /* setmode (fd, _O_BINARY); */
1432#else
1433 /* Make a non-inheritable copy of the socket handle. */
1434 {
1435 HANDLE parent;
1436 HANDLE new_s = INVALID_HANDLE_VALUE;
1437
1438 parent = GetCurrentProcess ();
1439
1440 DuplicateHandle (parent,
1441 (HANDLE) s,
1442 parent,
1443 &new_s,
1444 0,
1445 FALSE,
1446 DUPLICATE_SAME_ACCESS);
1447 pfn_closesocket (s);
1448 fd_info[fd].hnd = new_s;
1449 s = (SOCKET) new_s;
1450 }
1451#endif
1452
1453 /* set our own internal flags */
1454 fd_info[fd].flags = FILE_SOCKET | FILE_BINARY | FILE_READ | FILE_WRITE;
1455
1456 cp = new_child ();
1457 if (cp)
1458 {
1459 cp->fd = fd;
1460 cp->status = STATUS_READ_ACKNOWLEDGED;
1461
1462 /* attach child_process to fd_info */
1463 if (fd_info[ fd ].cp != NULL)
1464 {
1465 DebPrint (("sys_socket: fd_info[%d] apparently in use!\n", fd));
1466 abort ();
1467 }
1468
1469 fd_info[ fd ].cp = cp;
1470
1471 /* success! */
1472 return fd;
1473 }
1474
1475 /* clean up */
1476 _close (fd);
1477 }
1478 pfn_closesocket (s);
1479 h_errno = EMFILE;
1480 }
1481 set_errno ();
1482
1483 return -1;
1484}
1485
1486
1487int
1488sys_bind (int s, const struct sockaddr * addr, int namelen)
1489{
1490 if (!have_winsock)
1491 {
1492 h_errno = ENOTSOCK;
1493 return SOCKET_ERROR;
1494 }
1495
1496 check_errno ();
1497 if (fd_info[s].flags & FILE_SOCKET)
1498 {
1499 int rc = pfn_bind (SOCK_HANDLE (s), addr, namelen);
1500 if (rc == SOCKET_ERROR)
1501 set_errno ();
1502 return rc;
1503 }
1504 h_errno = ENOTSOCK;
1505 return SOCKET_ERROR;
1506}
1507
1508
1509int
1510sys_connect (int s, const struct sockaddr * name, int namelen)
1511{
1512 if (!have_winsock)
1513 {
1514 h_errno = ENOTSOCK;
1515 return SOCKET_ERROR;
1516 }
1517
1518 check_errno ();
1519 if (fd_info[s].flags & FILE_SOCKET)
1520 {
1521 int rc = pfn_connect (SOCK_HANDLE (s), name, namelen);
1522 if (rc == SOCKET_ERROR)
1523 set_errno ();
1524 return rc;
1525 }
1526 h_errno = ENOTSOCK;
1527 return SOCKET_ERROR;
1528}
1529
1530u_short
1531sys_htons (u_short hostshort)
1532{
1533 return (have_winsock) ?
1534 pfn_htons (hostshort) : hostshort;
1535}
1536
1537u_short
1538sys_ntohs (u_short netshort)
1539{
1540 return (have_winsock) ?
1541 pfn_ntohs (netshort) : netshort;
1542}
1543
1544unsigned long
1545sys_inet_addr (const char * cp)
1546{
1547 return (have_winsock) ?
1548 pfn_inet_addr (cp) : INADDR_NONE;
1549}
1550
1551int
1552sys_gethostname (char * name, int namelen)
1553{
1554 if (have_winsock)
1555 return pfn_gethostname (name, namelen);
1556
1557 if (namelen > MAX_COMPUTERNAME_LENGTH)
1558 return !GetComputerName (name, &namelen);
1559
1560 h_errno = EFAULT;
1561 return SOCKET_ERROR;
1562}
1563
1564struct hostent *
1565sys_gethostbyname(const char * name)
1566{
1567 struct hostent * host;
1568
1569 if (!have_winsock)
1570 {
1571 h_errno = ENETDOWN;
1572 return NULL;
1573 }
1574
1575 check_errno ();
1576 host = pfn_gethostbyname (name);
1577 if (!host)
1578 set_errno ();
1579 return host;
1580}
1581
1582struct servent *
1583sys_getservbyname(const char * name, const char * proto)
1584{
1585 struct servent * serv;
1586
1587 if (!have_winsock)
1588 {
1589 h_errno = ENETDOWN;
1590 return NULL;
1591 }
1592
1593 check_errno ();
1594 serv = pfn_getservbyname (name, proto);
1595 if (!serv)
1596 set_errno ();
1597 return serv;
1598}
1599
1600#endif /* HAVE_SOCKETS */
1601
1602
1603/* Shadow main io functions: we need to handle pipes and sockets more
1604 intelligently, and implement non-blocking mode as well. */
1605
1606int
1607sys_close (int fd)
1608{
1609 int rc;
1610
1611 if (fd < 0 || fd >= MAXDESC)
1612 {
1613 errno = EBADF;
1614 return -1;
1615 }
1616
1617 if (fd_info[fd].cp)
1618 {
1619 child_process * cp = fd_info[fd].cp;
1620
1621 fd_info[fd].cp = NULL;
1622
1623 if (CHILD_ACTIVE (cp))
1624 {
1625 /* if last descriptor to active child_process then cleanup */
1626 int i;
1627 for (i = 0; i < MAXDESC; i++)
1628 {
1629 if (i == fd)
1630 continue;
1631 if (fd_info[i].cp == cp)
1632 break;
1633 }
1634 if (i == MAXDESC)
1635 {
1636#if defined (HAVE_SOCKETS) && !defined (SOCK_REPLACE_HANDLE)
1637 if (fd_info[fd].flags & FILE_SOCKET)
1638 {
1639 if (!have_winsock) abort ();
1640
1641 pfn_shutdown (SOCK_HANDLE (fd), 2);
1642 rc = pfn_closesocket (SOCK_HANDLE (fd));
1643 }
1644#endif
1645 delete_child (cp);
1646 }
1647 }
1648 }
1649
1650 /* Note that sockets do not need special treatment here (at least on
1651 NT and Win95 using the standard tcp/ip stacks) - it appears that
1652 closesocket is equivalent to CloseHandle, which is to be expected
1653 because socket handles are fully fledged kernel handles. */
1654 rc = _close (fd);
1655
1656 if (rc == 0)
1657 fd_info[fd].flags = 0;
1658
1659 return rc;
1660}
1661
1662int
1663sys_dup (int fd)
1664{
1665 int new_fd;
1666
1667 new_fd = _dup (fd);
1668 if (new_fd >= 0)
1669 {
1670 /* duplicate our internal info as well */
1671 fd_info[new_fd] = fd_info[fd];
1672 }
1673 return new_fd;
1674}
1675
1676
1677int
1678sys_dup2 (int src, int dst)
1679{
1680 int rc;
1681
1682 if (dst < 0 || dst >= MAXDESC)
1683 {
1684 errno = EBADF;
1685 return -1;
1686 }
1687
1688 /* make sure we close the destination first if it's a pipe or socket */
1689 if (src != dst && fd_info[dst].flags != 0)
1690 sys_close (dst);
1691
1692 rc = _dup2 (src, dst);
1693 if (rc == 0)
1694 {
1695 /* duplicate our internal info as well */
1696 fd_info[dst] = fd_info[src];
1697 }
1698 return rc;
1699}
1700
1701/* From callproc.c */
1702extern Lisp_Object Vbinary_process_input;
1703extern Lisp_Object Vbinary_process_output;
1704
1705/* Unix pipe() has only one arg */
1706int
1707sys_pipe (int * phandles)
1708{
1709 int rc;
1710 unsigned flags;
1711 child_process * cp;
1712
1713 /* make pipe handles non-inheritable; when we spawn a child,
1714 we replace the relevant handle with an inheritable one. */
1715 rc = _pipe (phandles, 0, _O_NOINHERIT);
1716
1717 if (rc == 0)
1718 {
1719 /* set internal flags, and put read and write handles into binary
1720 mode as necessary; if not in binary mode, set the MSVC internal
1721 FDEV (0x40) flag to prevent _read from treating ^Z as eof (this
1722 could otherwise allow Emacs to hang because it then waits
1723 indefinitely for the child process to exit, when it might not be
1724 finished). */
1725 flags = FILE_PIPE | FILE_READ;
1726 if (!NILP (Vbinary_process_output))
1727 {
1728 flags |= FILE_BINARY;
1729 setmode (phandles[0], _O_BINARY);
1730 }
1731#if (_MSC_VER == 900)
1732 else
1733 _osfile[phandles[0]] |= 0x40;
1734#endif
1735
1736 fd_info[phandles[0]].flags = flags;
1737
1738 flags = FILE_PIPE | FILE_WRITE;
1739 if (!NILP (Vbinary_process_input))
1740 {
1741 flags |= FILE_BINARY;
1742 setmode (phandles[1], _O_BINARY);
1743 }
1744#if (_MSC_VER == 900)
1745 else
1746 _osfile[phandles[1]] |= 0x40;
1747#endif
1748
1749 fd_info[phandles[1]].flags = flags;
1750 }
1751
1752 return rc;
1753}
1754
f7554349
KH
1755/* From ntproc.c */
1756extern Lisp_Object Vwin32_pipe_read_delay;
1757
480b0c5b
GV
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)
f7554349
KH
1784 {
1785 /* Use read to get CRLF translation */
1786 rc = _read (fd, &cp->chr, sizeof (char));
1787
1788 /* Give subprocess time to buffer some more output for us before
1789 reporting that input is available; we need this because Win95
1790 connects DOS programs to pipes by making the pipe appear to be
1791 the normal console stdout - as a result most DOS programs will
1792 write to stdout without buffering, ie. one character at a
1793 time. Even some Win32 programs do this - "dir" in a command
1794 shell on NT is very slow if we don't do this. */
1795 if (rc > 0)
1796 {
1797 int wait = XINT (Vwin32_pipe_read_delay);
1798
1799 if (wait > 0)
1800 Sleep (wait);
1801 else if (wait < 0)
1802 while (++wait <= 0)
1803 /* Yield remainder of our time slice, effectively giving a
1804 temporary priority boost to the child process. */
1805 Sleep (0);
1806 }
1807 }
480b0c5b
GV
1808#ifdef HAVE_SOCKETS
1809 else if (fd_info[fd].flags & FILE_SOCKET)
1810 rc = pfn_recv (SOCK_HANDLE (fd), &cp->chr, sizeof (char), 0);
1811#endif
1812
1813 if (rc == sizeof (char))
1814 cp->status = STATUS_READ_SUCCEEDED;
1815 else
1816 cp->status = STATUS_READ_FAILED;
1817
1818 return cp->status;
1819}
1820
1821int
1822sys_read (int fd, char * buffer, unsigned int count)
1823{
1824 int nchars;
1825 int extra = 0;
1826 int to_read;
1827 DWORD waiting;
1828
1829 if (fd < 0 || fd >= MAXDESC)
1830 {
1831 errno = EBADF;
1832 return -1;
1833 }
1834
1835 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
1836 {
1837 child_process *cp = fd_info[fd].cp;
1838
1839 if ((fd_info[fd].flags & FILE_READ) == 0)
1840 {
1841 errno = EBADF;
1842 return -1;
1843 }
1844
1845 /* presence of a child_process structure means we are operating in
1846 non-blocking mode - otherwise we just call _read directly.
1847 Note that the child_process structure might be missing because
1848 reap_subprocess has been called; in this case the pipe is
1849 already broken, so calling _read on it is okay. */
1850 if (cp)
1851 {
1852 int current_status = cp->status;
1853
1854 switch (current_status)
1855 {
1856 case STATUS_READ_FAILED:
1857 case STATUS_READ_ERROR:
1858 /* report normal EOF */
1859 return 0;
1860
1861 case STATUS_READ_READY:
1862 case STATUS_READ_IN_PROGRESS:
1863 DebPrint (("sys_read called when read is in progress\n"));
1864 errno = EWOULDBLOCK;
1865 return -1;
1866
1867 case STATUS_READ_SUCCEEDED:
1868 /* consume read-ahead char */
1869 *buffer++ = cp->chr;
1870 count--;
1871 extra = 1;
1872 cp->status = STATUS_READ_ACKNOWLEDGED;
1873 ResetEvent (cp->char_avail);
1874
1875 case STATUS_READ_ACKNOWLEDGED:
1876 break;
1877
1878 default:
1879 DebPrint (("sys_read: bad status %d\n", current_status));
1880 errno = EBADF;
1881 return -1;
1882 }
1883
1884 if (fd_info[fd].flags & FILE_PIPE)
1885 {
1886 PeekNamedPipe ((HANDLE) _get_osfhandle (fd), NULL, 0, NULL, &waiting, NULL);
1887 to_read = min (waiting, (DWORD) count);
1888
1889 /* Use read to get CRLF translation */
1890 nchars = _read (fd, buffer, to_read);
1891 }
1892#ifdef HAVE_SOCKETS
1893 else /* FILE_SOCKET */
1894 {
1895 if (!have_winsock) abort ();
1896
1897 /* do the equivalent of a non-blocking read */
1898 pfn_ioctlsocket (SOCK_HANDLE (fd), FIONREAD, &waiting);
1899 if (waiting == 0 && extra == 0)
1900 {
1901 h_errno = errno = EWOULDBLOCK;
1902 return -1;
1903 }
1904
1905 nchars = 0;
1906 if (waiting)
1907 {
1908 /* always use binary mode for sockets */
1909 nchars = pfn_recv (SOCK_HANDLE (fd), buffer, count, 0);
1910 if (nchars == SOCKET_ERROR)
1911 {
1912 DebPrint(("sys_read.recv failed with error %d on socket %ld\n",
1913 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
1914 if (extra == 0)
1915 {
1916 set_errno ();
1917 return -1;
1918 }
1919 nchars = 0;
1920 }
1921 }
1922 }
1923#endif
1924 }
1925 else
1926 nchars = _read (fd, buffer, count);
1927 }
1928 else
1929 nchars = _read (fd, buffer, count);
1930
1931 return nchars + extra;
1932}
1933
1934/* For now, don't bother with a non-blocking mode */
1935int
1936sys_write (int fd, const void * buffer, unsigned int count)
1937{
1938 int nchars;
1939
1940 if (fd < 0 || fd >= MAXDESC)
1941 {
1942 errno = EBADF;
1943 return -1;
1944 }
1945
1946 if (fd_info[fd].flags & (FILE_PIPE | FILE_SOCKET))
1947 if ((fd_info[fd].flags & FILE_WRITE) == 0)
1948 {
1949 errno = EBADF;
1950 return -1;
1951 }
1952#ifdef HAVE_SOCKETS
1953 if (fd_info[fd].flags & FILE_SOCKET)
1954 {
1955 if (!have_winsock) abort ();
1956 nchars = pfn_send (SOCK_HANDLE (fd), buffer, count, 0);
1957 if (nchars == SOCKET_ERROR)
1958 {
1959 DebPrint(("sys_read.send failed with error %d on socket %ld\n",
1960 pfn_WSAGetLastError (), SOCK_HANDLE (fd)));
1961 set_errno ();
1962 }
1963 }
1964 else
1965#endif
1966 nchars = _write (fd, buffer, count);
1967
1968 return nchars;
1969}
1970
1971
1972void
1973term_ntproc ()
1974{
1975#ifdef HAVE_SOCKETS
1976 /* shutdown the socket interface if necessary */
1977 term_winsock ();
1978#endif
1979}
1980
f7554349
KH
1981extern BOOL can_run_dos_process;
1982extern BOOL dos_process_running;
1983
480b0c5b
GV
1984void
1985init_ntproc ()
1986{
1987#ifdef HAVE_SOCKETS
1988 /* initialise the socket interface if available */
1989 init_winsock ();
1990#endif
1991
1992 /* Initial preparation for subprocess support: replace our standard
1993 handles with non-inheritable versions. */
1994 {
1995 HANDLE parent;
1996 HANDLE stdin_save = INVALID_HANDLE_VALUE;
1997 HANDLE stdout_save = INVALID_HANDLE_VALUE;
1998 HANDLE stderr_save = INVALID_HANDLE_VALUE;
1999
2000 parent = GetCurrentProcess ();
2001
2002 /* ignore errors when duplicating and closing; typically the
2003 handles will be invalid when running as a gui program. */
2004 DuplicateHandle (parent,
2005 GetStdHandle (STD_INPUT_HANDLE),
2006 parent,
2007 &stdin_save,
2008 0,
2009 FALSE,
2010 DUPLICATE_SAME_ACCESS);
2011
2012 DuplicateHandle (parent,
2013 GetStdHandle (STD_OUTPUT_HANDLE),
2014 parent,
2015 &stdout_save,
2016 0,
2017 FALSE,
2018 DUPLICATE_SAME_ACCESS);
2019
2020 DuplicateHandle (parent,
2021 GetStdHandle (STD_ERROR_HANDLE),
2022 parent,
2023 &stderr_save,
2024 0,
2025 FALSE,
2026 DUPLICATE_SAME_ACCESS);
2027
2028 fclose (stdin);
2029 fclose (stdout);
2030 fclose (stderr);
2031
2032 if (stdin_save != INVALID_HANDLE_VALUE)
2033 _open_osfhandle ((long) stdin_save, O_TEXT);
2034 else
2035 open ("nul", O_TEXT | O_NOINHERIT | O_RDONLY);
2036 fdopen (0, "r");
2037
2038 if (stdout_save != INVALID_HANDLE_VALUE)
2039 _open_osfhandle ((long) stdout_save, O_TEXT);
2040 else
2041 open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
2042 fdopen (1, "w");
2043
2044 if (stderr_save != INVALID_HANDLE_VALUE)
2045 _open_osfhandle ((long) stderr_save, O_TEXT);
2046 else
2047 open ("nul", O_TEXT | O_NOINHERIT | O_WRONLY);
2048 fdopen (2, "w");
2049 }
2050
f7554349
KH
2051 /* Only allow Emacs to run DOS programs on Win95. */
2052 can_run_dos_process = (GetVersion () & 0x80000000);
2053 dos_process_running = FALSE;
2054
480b0c5b
GV
2055 /* unfortunately, atexit depends on implementation of malloc */
2056 /* atexit (term_ntproc); */
2057 signal (SIGABRT, term_ntproc);
2058}
2059
2060/* end of nt.c */