[REGEX_FREE]: Use ((void)0) instead of just (0).
[emacs.git] / src / w32.c
blob960110e4eb870f6487b2dd52409b801771a08d90
1 /* Utility and Unix shadow routines for GNU Emacs on Windows NT.
2 Copyright (C) 1994, 1995 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any later
9 version.
11 GNU Emacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 more details.
16 You should have received a copy of the GNU General Public License along
17 with GNU Emacs; see the file COPYING. If not, write to the Free Software
18 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20 Geoff Voelker (voelker@cs.washington.edu) 7-29-94
23 /* Define stat before including config.h. */
24 #include <string.h>
25 #include <sys/stat.h>
26 int
27 nt_stat (char *filename, struct stat *statbuf)
29 int r, l = strlen (filename);
30 char *str = NULL;
31 extern long *xmalloc ();
32 extern void xfree ();
34 /* stat has a bug when passed a name of a directory with a trailing
35 backslash (but a trailing forward slash works fine). */
36 if (filename[l - 1] == '\\')
38 str = (char *) xmalloc (l + 1);
39 strcpy (str, filename);
40 str[l - 1] = '/';
41 r = stat (str, statbuf);
42 xfree (str);
43 return r;
45 else
46 return stat (filename, statbuf);
49 /* Place a wrapper around the NT version of ctime. It returns NULL
50 on network directories, so we handle that case here.
51 Define it before including config.h. (Ulrich Leodolter, 1/11/95). */
52 char *
53 nt_ctime (const time_t *t)
55 char *str = (char *) ctime (t);
56 return (str ? str : "Sun Jan 01 00:00:00 1970");
59 #include <windows.h>
60 #include <stdlib.h>
61 #include <stdio.h>
62 #include <io.h>
63 #include <fcntl.h>
64 #include <ctype.h>
66 #include "config.h"
67 #define getwd _getwd
68 #include "lisp.h"
69 #undef getwd
71 #include <pwd.h>
73 #include "ndir.h"
74 #include "ntheap.h"
76 extern int report_file_error (char *, Lisp_Object);
78 /* Get the current working directory. */
79 int
80 getwd (char *dir)
82 return GetCurrentDirectory (MAXPATHLEN, dir);
85 /* Emulate gethostname. */
86 int
87 gethostname (char *buffer, int size)
89 /* NT only allows small host names, so the buffer is
90 certainly large enough. */
91 return !GetComputerName (buffer, &size);
94 /* Emulate getloadavg. */
95 int
96 getloadavg (double loadavg[], int nelem)
98 int i;
100 /* A faithful emulation is going to have to be saved for a rainy day. */
101 for (i = 0; i < nelem; i++)
103 loadavg[i] = 0.0;
105 return i;
108 /* Emulate sleep...we could have done this with a define, but that
109 would necessitate including windows.h in the files that used it.
110 This is much easier. */
111 void
112 nt_sleep (int seconds)
114 Sleep (seconds * 1000);
117 /* Emulate the Unix directory procedures opendir, closedir,
118 and readdir. We can't use the procedures supplied in sysdep.c,
119 so we provide them here. */
121 struct direct dir_static; /* simulated directory contents */
122 static int dir_finding;
123 static HANDLE dir_find_handle;
125 DIR *
126 opendir (char *filename)
128 DIR *dirp;
130 /* Opening is done by FindFirstFile. However, a read is inherent to
131 this operation, so we have a flag to handle the open at read
132 time. This flag essentially means "there is a find-handle open and
133 it needs to be closed." */
135 if (!(dirp = (DIR *) malloc (sizeof (DIR))))
137 return 0;
140 dirp->dd_fd = 0;
141 dirp->dd_loc = 0;
142 dirp->dd_size = 0;
144 /* This is tacky, but we need the directory name for our
145 implementation of readdir. */
146 strncpy (dirp->dd_buf, filename, DIRBLKSIZ);
147 return dirp;
150 void
151 closedir (DIR *dirp)
153 /* If we have a find-handle open, close it. */
154 if (dir_finding)
156 FindClose (dir_find_handle);
157 dir_finding = 0;
159 xfree ((char *) dirp);
162 struct direct *
163 readdir (DIR *dirp)
165 WIN32_FIND_DATA find_data;
167 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
168 if (!dir_finding)
170 char filename[MAXNAMLEN + 3];
171 int ln;
173 strncpy (filename, dirp->dd_buf, MAXNAMLEN);
174 ln = strlen (filename)-1;
175 if (filename[ln] != '\\' && filename[ln] != ':')
176 strcat (filename, "\\");
177 strcat (filename, "*.*");
179 dir_find_handle = FindFirstFile (filename, &find_data);
181 if (dir_find_handle == INVALID_HANDLE_VALUE)
182 return NULL;
184 dir_finding = 1;
186 else
188 if (!FindNextFile (dir_find_handle, &find_data))
189 return NULL;
192 /* NT's unique ID for a file is 64 bits, so we have to fake it here.
193 This should work as long as we never use 0. */
194 dir_static.d_ino = 1;
196 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 +
197 dir_static.d_namlen - dir_static.d_namlen % 4;
199 dir_static.d_namlen = strlen (find_data.cFileName);
200 strncpy (dir_static.d_name, find_data.cFileName, MAXNAMLEN);
202 return &dir_static;
205 /* Emulate getpwuid and getpwnam. */
207 int getuid (); /* forward declaration */
209 static char the_passwd_name[256];
210 static char the_passwd_passwd[256];
211 static char the_passwd_gecos[256];
212 static char the_passwd_dir[256];
213 static char the_passwd_shell[256];
215 static struct passwd the_passwd =
217 the_passwd_name,
218 the_passwd_passwd,
222 the_passwd_gecos,
223 the_passwd_dir,
224 the_passwd_shell,
227 struct passwd *
228 getpwuid (int uid)
230 int size = 256;
232 if (!GetUserName (the_passwd.pw_name, &size))
233 return NULL;
235 the_passwd.pw_passwd[0] = '\0';
236 the_passwd.pw_uid = 0;
237 the_passwd.pw_gid = 0;
238 strcpy (the_passwd.pw_gecos, the_passwd.pw_name);
239 the_passwd.pw_dir[0] = '\0';
240 the_passwd.pw_shell[0] = '\0';
242 return &the_passwd;
245 struct passwd *
246 getpwnam (char *name)
248 struct passwd *pw;
250 pw = getpwuid (getuid ());
251 if (!pw)
252 return pw;
254 if (strcmp (name, pw->pw_name))
255 return NULL;
257 return pw;
261 /* We don't have scripts to automatically determine the system configuration
262 for Emacs before it's compiled, and we don't want to have to make the
263 user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
264 routine. */
266 static char configuration_buffer[16];
268 char *
269 get_emacs_configuration (void)
271 char *arch, *oem;
273 /* Determine the processor type. */
274 switch (get_processor_type ())
276 case PROCESSOR_INTEL_386:
277 case PROCESSOR_INTEL_486:
278 case PROCESSOR_INTEL_PENTIUM:
279 arch = "i386";
280 break;
281 case PROCESSOR_INTEL_860:
282 arch = "i860";
283 break;
284 case PROCESSOR_MIPS_R2000:
285 case PROCESSOR_MIPS_R3000:
286 case PROCESSOR_MIPS_R4000:
287 arch = "mips";
288 break;
289 case PROCESSOR_ALPHA_21064:
290 arch = "alpha";
291 break;
292 default:
293 arch = "unknown";
294 break;
297 /* Let oem be "*" until we figure out how to decode the OEM field. */
298 oem = "*";
300 sprintf (configuration_buffer, "%s-%s-nt%d.%d", arch, oem,
301 get_nt_major_version (), get_nt_minor_version ());
302 return configuration_buffer;
305 /* Conjure up inode and device numbers that will serve the purpose
306 of Emacs. Return 1 upon success, 0 upon failure. */
308 get_inode_and_device_vals (Lisp_Object filename, Lisp_Object *p_inode,
309 Lisp_Object *p_device)
311 /* File uids on NT are found using a handle to a file, which
312 implies that it has been opened. Since we want to be able
313 to stat an arbitrary file, we must open it, get the info,
314 and then close it.
316 Also, NT file uids are 64-bits. This is a problem. */
318 HANDLE handle;
319 BOOL result;
320 DWORD attrs;
321 BY_HANDLE_FILE_INFORMATION info;
323 /* We have to stat files and directories differently, so check
324 to see what filename references. */
325 attrs = GetFileAttributes (XSTRING (filename)->data);
326 if (attrs == 0xFFFFFFFF) {
327 return 0;
329 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
330 /* Conjure up bogus, but unique, values. */
331 attrs = GetTickCount ();
332 *p_inode = make_number (attrs);
333 *p_device = make_number (attrs);
334 return 1;
337 /* FIXME: It shouldn't be opened without READ access, but NT on x86
338 doesn't allow GetFileInfo in that case (NT on mips does). */
340 handle = CreateFile (XSTRING (filename)->data,
341 GENERIC_READ,
342 FILE_SHARE_READ | FILE_SHARE_WRITE,
343 NULL,
344 OPEN_EXISTING,
345 FILE_ATTRIBUTE_NORMAL,
346 NULL);
347 if (handle == INVALID_HANDLE_VALUE)
348 return 0;
350 result = GetFileInformationByHandle (handle, &info);
351 CloseHandle (handle);
352 if (!result)
353 return 0;
355 *p_inode = make_number (info.nFileIndexLow); /* use the low value */
356 *p_device = make_number (info.dwVolumeSerialNumber);
358 return 1;
361 /* The following pipe routines are used to support our fork emulation.
362 Since NT's crt dup always creates inherited handles, we
363 must be careful in setting up pipes. First create
364 non-inherited pipe handles, then create an inherited handle
365 to the write end by dup-ing it, and then close the non-inherited
366 end that was just duped. This gives us one non-inherited handle
367 on the read end and one inherited handle to the write end. As
368 the parent, we close the inherited handle to the write end after
369 spawning the child. */
371 /* From callproc.c */
372 extern Lisp_Object Vbinary_process_input;
373 extern Lisp_Object Vbinary_process_output;
375 void
376 pipe_with_inherited_out (int fds[2])
378 int inherit_out;
379 unsigned int flags = _O_NOINHERIT;
381 if (!NILP (Vbinary_process_output))
382 flags |= _O_BINARY;
384 _pipe (fds, 0, flags);
385 inherit_out = dup (fds[1]);
386 close (fds[1]);
387 fds[1] = inherit_out;
390 void
391 pipe_with_inherited_in (int fds[2])
393 int inherit_in;
394 unsigned int flags = _O_NOINHERIT;
396 if (!NILP (Vbinary_process_input))
397 flags |= _O_BINARY;
399 _pipe (fds, 0, flags);
400 inherit_in = dup (fds[0]);
401 close (fds[0]);
402 fds[0] = inherit_in;
405 /* The following two routines are used to manipulate stdin, stdout, and
406 stderr of our child processes.
408 Assuming that in, out, and err are inherited, we make them stdin,
409 stdout, and stderr of the child as follows:
411 - Save the parent's current standard handles.
412 - Set the parent's standard handles to the handles being passed in.
413 (Note that _get_osfhandle is an io.h procedure that
414 maps crt file descriptors to NT file handles.)
415 - Spawn the child, which inherits in, out, and err as stdin,
416 stdout, and stderr. (see Spawnve)
417 - Reset the parent's standard handles to the saved handles.
418 (see reset_standard_handles)
419 We assume that the caller closes in, out, and err after calling us. */
421 void
422 prepare_standard_handles (int in, int out, int err, HANDLE handles[4])
424 HANDLE parent, stdin_save, stdout_save, stderr_save, err_handle;
426 parent = GetCurrentProcess ();
427 if (!DuplicateHandle (parent,
428 GetStdHandle (STD_INPUT_HANDLE),
429 parent,
430 &stdin_save,
432 FALSE,
433 DUPLICATE_SAME_ACCESS))
434 report_file_error ("Duplicating parent's input handle", Qnil);
436 if (!DuplicateHandle (parent,
437 GetStdHandle (STD_OUTPUT_HANDLE),
438 parent,
439 &stdout_save,
441 FALSE,
442 DUPLICATE_SAME_ACCESS))
443 report_file_error ("Duplicating parent's output handle", Qnil);
445 if (!DuplicateHandle (parent,
446 GetStdHandle (STD_ERROR_HANDLE),
447 parent,
448 &stderr_save,
450 FALSE,
451 DUPLICATE_SAME_ACCESS))
452 report_file_error ("Duplicating parent's error handle", Qnil);
454 if (!SetStdHandle (STD_INPUT_HANDLE, (HANDLE) _get_osfhandle (in)))
455 report_file_error ("Changing stdin handle", Qnil);
457 if (!SetStdHandle (STD_OUTPUT_HANDLE, (HANDLE) _get_osfhandle (out)))
458 report_file_error ("Changing stdout handle", Qnil);
460 /* We lose data if we use the same handle to the pipe for stdout and
461 stderr, so make a duplicate. This took a while to find. */
462 if (out == err)
464 if (!DuplicateHandle (parent,
465 (HANDLE) _get_osfhandle (err),
466 parent,
467 &err_handle,
469 TRUE,
470 DUPLICATE_SAME_ACCESS))
471 report_file_error ("Duplicating out handle to make err handle.",
472 Qnil);
474 else
476 err_handle = (HANDLE) _get_osfhandle (err);
479 if (!SetStdHandle (STD_ERROR_HANDLE, err_handle))
480 report_file_error ("Changing stderr handle", Qnil);
482 handles[0] = stdin_save;
483 handles[1] = stdout_save;
484 handles[2] = stderr_save;
485 handles[3] = err_handle;
488 void
489 reset_standard_handles (int in, int out, int err, HANDLE handles[4])
491 HANDLE stdin_save = handles[0];
492 HANDLE stdout_save = handles[1];
493 HANDLE stderr_save = handles[2];
494 HANDLE err_handle = handles[3];
496 if (!SetStdHandle (STD_INPUT_HANDLE, stdin_save))
497 report_file_error ("Resetting input handle", Qnil);
499 if (!SetStdHandle (STD_OUTPUT_HANDLE, stdout_save))
500 report_file_error ("Resetting output handle", Qnil);
502 if (!SetStdHandle (STD_ERROR_HANDLE, stderr_save))
503 report_file_error ("Resetting error handle", Qnil);
505 if (out == err)
507 /* If out and err are the same handle, then we duplicated out
508 and stuck it in err_handle. Close the duplicate to clean up. */
509 if (!CloseHandle (err_handle))
510 report_file_error ("Closing error handle duplicated from out.",
511 Qnil);
516 random ()
518 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
519 return ((rand () << 15) | rand ());
522 void
523 srandom (int seed)
525 srand (seed);
528 /* Destructively turn backslashes into slashes. */
529 void
530 dostounix_filename (p)
531 register char *p;
533 while (*p)
535 if (*p == '\\')
536 *p = '/';
537 p++;
541 /* Routines that are no-ops on NT but are defined to get Emacs to compile. */
544 int
545 sigsetmask (int signal_mask)
547 return 0;
550 int
551 sigblock (int sig)
553 return 0;
556 int
557 kill (int pid, int signal)
559 return 0;
562 int
563 setpgrp (int pid, int gid)
565 return 0;
568 int
569 alarm (int seconds)
571 return 0;
574 int
575 unrequest_sigio (void)
577 return 0;
580 int
581 request_sigio (void)
583 return 0;
586 int
587 getuid ()
589 return 0;
592 int
593 geteuid ()
595 return 0;
598 /* Remove all CR's that are followed by a LF.
599 (From msdos.c...probably should figure out a way to share it,
600 although this code isn't going to ever change.) */
602 crlf_to_lf (n, buf)
603 register int n;
604 register unsigned char *buf;
606 unsigned char *np = buf;
607 unsigned char *startp = buf;
608 unsigned char *endp = buf + n;
610 if (n == 0)
611 return n;
612 while (buf < endp - 1)
614 if (*buf == 0x0d)
616 if (*(++buf) != 0x0a)
617 *np++ = 0x0d;
619 else
620 *np++ = *buf++;
622 if (buf < endp)
623 *np++ = *buf++;
624 return np - startp;
627 #ifdef HAVE_TIMEVAL
628 #include <sys/timeb.h>
630 /* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
631 void
632 gettimeofday (struct timeval *tv, struct timezone *tz)
634 struct _timeb tb;
635 _ftime (&tb);
637 tv->tv_sec = tb.time;
638 tv->tv_usec = tb.millitm * 1000L;
639 if (tz)
641 tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */
642 tz->tz_dsttime = tb.dstflag; /* type of dst correction */
645 #endif /* HAVE_TIMEVAL */
648 #ifdef PIGSFLY
649 Keep this around...we might need it later.
650 #ifdef WINDOWSNT
653 * Find the user's real name by opening the process token and looking
654 * up the name associated with the user-sid in that token.
657 char b[256], Name[256], RefD[256];
658 DWORD length = 256, rlength = 256, trash;
659 HANDLE Token;
660 SID_NAME_USE User;
662 if (1)
663 Vuser_real_name = build_string ("foo");
664 else if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &Token))
666 Vuser_real_name = build_string ("unknown");
668 else if (!GetTokenInformation (Token, TokenUser, (PVOID)b, 256,
669 &trash))
671 CloseHandle (Token);
672 Vuser_real_name = build_string ("unknown");
674 else if (!LookupAccountSid ((void *)0, (PSID)b, Name, &length, RefD,
675 &rlength, &User))
677 CloseHandle (Token);
678 Vuser_real_name = build_string ("unknown");
680 else
681 Vuser_real_name = build_string (Name);
683 #else /* not WINDOWSNT */
684 #endif /* not WINDOWSNT */
685 #endif /* PIGSFLY */