(WIN32_KEY_SHIFTED): Macro undefined.
[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
35f0d482
KH
24/* Define stat before including config.h. */
25#include <string.h>
26#include <sys/stat.h>
27int
28nt_stat (char *filename, struct stat *statbuf)
29{
30 int r, l = strlen (filename);
31 char *str = NULL;
32 extern long *xmalloc ();
33 extern void xfree ();
34
35 /* stat has a bug when passed a name of a directory with a trailing
36 backslash (but a trailing forward slash works fine). */
37 if (filename[l - 1] == '\\')
38 {
39 str = (char *) xmalloc (l + 1);
40 strcpy (str, filename);
41 str[l - 1] = '/';
42 r = stat (str, statbuf);
43 xfree (str);
44 return r;
45 }
46 else
47 return stat (filename, statbuf);
48}
49
50/* Place a wrapper around the NT version of ctime. It returns NULL
51 on network directories, so we handle that case here.
52 Define it before including config.h. (Ulrich Leodolter, 1/11/95). */
53char *
54nt_ctime (const time_t *t)
55{
56 char *str = (char *) ctime (t);
57 return (str ? str : "Sun Jan 01 00:00:00 1970");
58}
59
6816efce 60#include <config.h>
95ed0025
RS
61#include <windows.h>
62#include <stdlib.h>
63#include <stdio.h>
64#include <io.h>
65#include <fcntl.h>
66#include <ctype.h>
67
95ed0025
RS
68#define getwd _getwd
69#include "lisp.h"
70#undef getwd
71
72#include <pwd.h>
73
74#include "ndir.h"
75#include "ntheap.h"
76
77extern int report_file_error (char *, Lisp_Object);
78
79/* Get the current working directory. */
80int
81getwd (char *dir)
82{
83 return GetCurrentDirectory (MAXPATHLEN, dir);
84}
85
86/* Emulate gethostname. */
87int
88gethostname (char *buffer, int size)
89{
90 /* NT only allows small host names, so the buffer is
91 certainly large enough. */
92 return !GetComputerName (buffer, &size);
93}
94
95/* Emulate getloadavg. */
96int
97getloadavg (double loadavg[], int nelem)
98{
99 int i;
100
101 /* A faithful emulation is going to have to be saved for a rainy day. */
102 for (i = 0; i < nelem; i++)
103 {
104 loadavg[i] = 0.0;
105 }
106 return i;
107}
108
109/* Emulate sleep...we could have done this with a define, but that
110 would necessitate including windows.h in the files that used it.
111 This is much easier. */
112void
113nt_sleep (int seconds)
114{
115 Sleep (seconds * 1000);
116}
117
118/* Emulate the Unix directory procedures opendir, closedir,
119 and readdir. We can't use the procedures supplied in sysdep.c,
120 so we provide them here. */
121
122struct direct dir_static; /* simulated directory contents */
123static int dir_finding;
124static HANDLE dir_find_handle;
125
126DIR *
127opendir (char *filename)
128{
129 DIR *dirp;
130
131 /* Opening is done by FindFirstFile. However, a read is inherent to
132 this operation, so we have a flag to handle the open at read
133 time. This flag essentially means "there is a find-handle open and
134 it needs to be closed." */
135
136 if (!(dirp = (DIR *) malloc (sizeof (DIR))))
137 {
138 return 0;
139 }
140
141 dirp->dd_fd = 0;
142 dirp->dd_loc = 0;
143 dirp->dd_size = 0;
144
145 /* This is tacky, but we need the directory name for our
146 implementation of readdir. */
147 strncpy (dirp->dd_buf, filename, DIRBLKSIZ);
148 return dirp;
149}
150
151void
152closedir (DIR *dirp)
153{
154 /* If we have a find-handle open, close it. */
155 if (dir_finding)
156 {
157 FindClose (dir_find_handle);
158 dir_finding = 0;
159 }
160 xfree ((char *) dirp);
161}
162
163struct direct *
164readdir (DIR *dirp)
165{
166 WIN32_FIND_DATA find_data;
167
168 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
169 if (!dir_finding)
170 {
171 char filename[MAXNAMLEN + 3];
172 int ln;
173
174 strncpy (filename, dirp->dd_buf, MAXNAMLEN);
175 ln = strlen (filename)-1;
176 if (filename[ln] != '\\' && filename[ln] != ':')
177 strcat (filename, "\\");
178 strcat (filename, "*.*");
179
180 dir_find_handle = FindFirstFile (filename, &find_data);
181
182 if (dir_find_handle == INVALID_HANDLE_VALUE)
183 return NULL;
184
185 dir_finding = 1;
186 }
187 else
188 {
189 if (!FindNextFile (dir_find_handle, &find_data))
190 return NULL;
191 }
192
95ed0025
RS
193 /* NT's unique ID for a file is 64 bits, so we have to fake it here.
194 This should work as long as we never use 0. */
195 dir_static.d_ino = 1;
196
197 dir_static.d_reclen = sizeof (struct direct) - MAXNAMLEN + 3 +
198 dir_static.d_namlen - dir_static.d_namlen % 4;
199
200 dir_static.d_namlen = strlen (find_data.cFileName);
201 strncpy (dir_static.d_name, find_data.cFileName, MAXNAMLEN);
202
203 return &dir_static;
204}
205
206/* Emulate getpwuid and getpwnam. */
207
208int getuid (); /* forward declaration */
209
051fe60d
GV
210#define PASSWD_FIELD_SIZE 256
211
212static char the_passwd_name[PASSWD_FIELD_SIZE];
213static char the_passwd_passwd[PASSWD_FIELD_SIZE];
214static char the_passwd_gecos[PASSWD_FIELD_SIZE];
215static char the_passwd_dir[PASSWD_FIELD_SIZE];
216static char the_passwd_shell[PASSWD_FIELD_SIZE];
95ed0025
RS
217
218static struct passwd the_passwd =
219{
220 the_passwd_name,
221 the_passwd_passwd,
222 0,
223 0,
224 0,
225 the_passwd_gecos,
226 the_passwd_dir,
227 the_passwd_shell,
228};
229
230struct passwd *
231getpwuid (int uid)
232{
051fe60d 233 int size = PASSWD_FIELD_SIZE;
95ed0025
RS
234
235 if (!GetUserName (the_passwd.pw_name, &size))
236 return NULL;
237
238 the_passwd.pw_passwd[0] = '\0';
239 the_passwd.pw_uid = 0;
240 the_passwd.pw_gid = 0;
241 strcpy (the_passwd.pw_gecos, the_passwd.pw_name);
242 the_passwd.pw_dir[0] = '\0';
243 the_passwd.pw_shell[0] = '\0';
244
245 return &the_passwd;
246}
247
248struct passwd *
249getpwnam (char *name)
250{
251 struct passwd *pw;
252
253 pw = getpwuid (getuid ());
254 if (!pw)
255 return pw;
256
257 if (strcmp (name, pw->pw_name))
258 return NULL;
259
260 return pw;
261}
262
263
264/* We don't have scripts to automatically determine the system configuration
265 for Emacs before it's compiled, and we don't want to have to make the
266 user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
267 routine. */
268
bd4a449f 269static char configuration_buffer[32];
95ed0025
RS
270
271char *
272get_emacs_configuration (void)
273{
d1c1c3d2 274 char *arch, *oem, *os;
95ed0025 275
d1c1c3d2
RS
276 /* Determine the processor type. */
277 switch (get_processor_type ())
278 {
051fe60d
GV
279
280#ifdef PROCESSOR_INTEL_386
d1c1c3d2
RS
281 case PROCESSOR_INTEL_386:
282 case PROCESSOR_INTEL_486:
283 case PROCESSOR_INTEL_PENTIUM:
284 arch = "i386";
285 break;
051fe60d
GV
286#endif
287
288#ifdef PROCESSOR_INTEL_860
d1c1c3d2
RS
289 case PROCESSOR_INTEL_860:
290 arch = "i860";
291 break;
051fe60d
GV
292#endif
293
294#ifdef PROCESSOR_MIPS_R2000
d1c1c3d2
RS
295 case PROCESSOR_MIPS_R2000:
296 case PROCESSOR_MIPS_R3000:
297 case PROCESSOR_MIPS_R4000:
298 arch = "mips";
299 break;
051fe60d
GV
300#endif
301
302#ifdef PROCESSOR_ALPHA_21064
d1c1c3d2
RS
303 case PROCESSOR_ALPHA_21064:
304 arch = "alpha";
305 break;
051fe60d
GV
306#endif
307
d1c1c3d2
RS
308 default:
309 arch = "unknown";
310 break;
311 }
95ed0025 312
d1c1c3d2
RS
313 /* Let oem be "*" until we figure out how to decode the OEM field. */
314 oem = "*";
95ed0025 315
bd4a449f 316#ifdef WINDOWS95
d1c1c3d2 317 os = "win";
bd4a449f 318#else
d1c1c3d2 319 os = "nt";
bd4a449f
GV
320#endif
321
d1c1c3d2
RS
322 sprintf (configuration_buffer, "%s-%s-%s%d.%d", arch, oem, os,
323 get_nt_major_version (), get_nt_minor_version ());
324 return configuration_buffer;
95ed0025
RS
325}
326
327/* Conjure up inode and device numbers that will serve the purpose
328 of Emacs. Return 1 upon success, 0 upon failure. */
329int
330get_inode_and_device_vals (Lisp_Object filename, Lisp_Object *p_inode,
331 Lisp_Object *p_device)
332{
333 /* File uids on NT are found using a handle to a file, which
334 implies that it has been opened. Since we want to be able
335 to stat an arbitrary file, we must open it, get the info,
336 and then close it.
337
338 Also, NT file uids are 64-bits. This is a problem. */
339
340 HANDLE handle;
341 BOOL result;
35f0d482 342 DWORD attrs;
95ed0025
RS
343 BY_HANDLE_FILE_INFORMATION info;
344
35f0d482
KH
345 /* We have to stat files and directories differently, so check
346 to see what filename references. */
347 attrs = GetFileAttributes (XSTRING (filename)->data);
348 if (attrs == 0xFFFFFFFF) {
349 return 0;
350 }
351 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
352 /* Conjure up bogus, but unique, values. */
353 attrs = GetTickCount ();
354 *p_inode = make_number (attrs);
355 *p_device = make_number (attrs);
356 return 1;
357 }
358
95ed0025
RS
359 /* FIXME: It shouldn't be opened without READ access, but NT on x86
360 doesn't allow GetFileInfo in that case (NT on mips does). */
361
362 handle = CreateFile (XSTRING (filename)->data,
363 GENERIC_READ,
364 FILE_SHARE_READ | FILE_SHARE_WRITE,
365 NULL,
366 OPEN_EXISTING,
367 FILE_ATTRIBUTE_NORMAL,
368 NULL);
369 if (handle == INVALID_HANDLE_VALUE)
370 return 0;
371
372 result = GetFileInformationByHandle (handle, &info);
373 CloseHandle (handle);
374 if (!result)
375 return 0;
376
377 *p_inode = make_number (info.nFileIndexLow); /* use the low value */
378 *p_device = make_number (info.dwVolumeSerialNumber);
379
380 return 1;
381}
382
383/* The following pipe routines are used to support our fork emulation.
384 Since NT's crt dup always creates inherited handles, we
385 must be careful in setting up pipes. First create
386 non-inherited pipe handles, then create an inherited handle
387 to the write end by dup-ing it, and then close the non-inherited
388 end that was just duped. This gives us one non-inherited handle
389 on the read end and one inherited handle to the write end. As
390 the parent, we close the inherited handle to the write end after
391 spawning the child. */
392
393/* From callproc.c */
394extern Lisp_Object Vbinary_process_input;
395extern Lisp_Object Vbinary_process_output;
396
397void
398pipe_with_inherited_out (int fds[2])
399{
400 int inherit_out;
401 unsigned int flags = _O_NOINHERIT;
402
403 if (!NILP (Vbinary_process_output))
404 flags |= _O_BINARY;
405
406 _pipe (fds, 0, flags);
407 inherit_out = dup (fds[1]);
408 close (fds[1]);
409 fds[1] = inherit_out;
410}
411
412void
413pipe_with_inherited_in (int fds[2])
414{
415 int inherit_in;
416 unsigned int flags = _O_NOINHERIT;
417
418 if (!NILP (Vbinary_process_input))
419 flags |= _O_BINARY;
420
421 _pipe (fds, 0, flags);
422 inherit_in = dup (fds[0]);
423 close (fds[0]);
424 fds[0] = inherit_in;
425}
426
427/* The following two routines are used to manipulate stdin, stdout, and
428 stderr of our child processes.
429
430 Assuming that in, out, and err are inherited, we make them stdin,
431 stdout, and stderr of the child as follows:
432
433 - Save the parent's current standard handles.
434 - Set the parent's standard handles to the handles being passed in.
435 (Note that _get_osfhandle is an io.h procedure that
436 maps crt file descriptors to NT file handles.)
437 - Spawn the child, which inherits in, out, and err as stdin,
438 stdout, and stderr. (see Spawnve)
439 - Reset the parent's standard handles to the saved handles.
440 (see reset_standard_handles)
441 We assume that the caller closes in, out, and err after calling us. */
442
443void
444prepare_standard_handles (int in, int out, int err, HANDLE handles[4])
445{
446 HANDLE parent, stdin_save, stdout_save, stderr_save, err_handle;
bd4a449f
GV
447
448#ifdef WINDOWS95
449 /* The Win95 beta doesn't set the standard handles correctly.
450 Handicap subprocesses until we get a version that works correctly.
451 Undefining the subprocesses macro reveals other incompatibilities,
452 so, since we're expecting subprocs to work in the near future,
453 disable them here. */
454 report_file_error ("Subprocesses currently disabled on Win95", Qnil);
455#endif
456
95ed0025 457 parent = GetCurrentProcess ();
bd4a449f
GV
458 stdin_save = GetStdHandle (STD_INPUT_HANDLE);
459 stdout_save = GetStdHandle (STD_OUTPUT_HANDLE);
460 stderr_save = GetStdHandle (STD_ERROR_HANDLE);
461
f332b293 462#ifndef HAVE_NTGUI
95ed0025
RS
463 if (!DuplicateHandle (parent,
464 GetStdHandle (STD_INPUT_HANDLE),
465 parent,
466 &stdin_save,
467 0,
468 FALSE,
469 DUPLICATE_SAME_ACCESS))
470 report_file_error ("Duplicating parent's input handle", Qnil);
471
472 if (!DuplicateHandle (parent,
473 GetStdHandle (STD_OUTPUT_HANDLE),
474 parent,
475 &stdout_save,
476 0,
477 FALSE,
478 DUPLICATE_SAME_ACCESS))
479 report_file_error ("Duplicating parent's output handle", Qnil);
480
481 if (!DuplicateHandle (parent,
482 GetStdHandle (STD_ERROR_HANDLE),
483 parent,
484 &stderr_save,
485 0,
486 FALSE,
487 DUPLICATE_SAME_ACCESS))
488 report_file_error ("Duplicating parent's error handle", Qnil);
f332b293 489#endif /* !HAVE_NTGUI */
95ed0025
RS
490
491 if (!SetStdHandle (STD_INPUT_HANDLE, (HANDLE) _get_osfhandle (in)))
492 report_file_error ("Changing stdin handle", Qnil);
493
494 if (!SetStdHandle (STD_OUTPUT_HANDLE, (HANDLE) _get_osfhandle (out)))
495 report_file_error ("Changing stdout handle", Qnil);
496
497 /* We lose data if we use the same handle to the pipe for stdout and
498 stderr, so make a duplicate. This took a while to find. */
499 if (out == err)
500 {
501 if (!DuplicateHandle (parent,
502 (HANDLE) _get_osfhandle (err),
503 parent,
504 &err_handle,
505 0,
506 TRUE,
507 DUPLICATE_SAME_ACCESS))
508 report_file_error ("Duplicating out handle to make err handle.",
509 Qnil);
510 }
511 else
512 {
513 err_handle = (HANDLE) _get_osfhandle (err);
514 }
515
516 if (!SetStdHandle (STD_ERROR_HANDLE, err_handle))
517 report_file_error ("Changing stderr handle", Qnil);
518
519 handles[0] = stdin_save;
520 handles[1] = stdout_save;
521 handles[2] = stderr_save;
522 handles[3] = err_handle;
523}
524
525void
526reset_standard_handles (int in, int out, int err, HANDLE handles[4])
527{
528 HANDLE stdin_save = handles[0];
529 HANDLE stdout_save = handles[1];
530 HANDLE stderr_save = handles[2];
531 HANDLE err_handle = handles[3];
bd4a449f
GV
532 int i;
533
f332b293 534#ifndef HAVE_NTGUI
95ed0025
RS
535 if (!SetStdHandle (STD_INPUT_HANDLE, stdin_save))
536 report_file_error ("Resetting input handle", Qnil);
537
538 if (!SetStdHandle (STD_OUTPUT_HANDLE, stdout_save))
bd4a449f
GV
539 {
540 i = GetLastError ();
541 report_file_error ("Resetting output handle", Qnil);
542 }
95ed0025
RS
543
544 if (!SetStdHandle (STD_ERROR_HANDLE, stderr_save))
545 report_file_error ("Resetting error handle", Qnil);
f332b293 546#endif /* !HAVE_NTGUI */
95ed0025
RS
547
548 if (out == err)
549 {
550 /* If out and err are the same handle, then we duplicated out
551 and stuck it in err_handle. Close the duplicate to clean up. */
552 if (!CloseHandle (err_handle))
553 report_file_error ("Closing error handle duplicated from out.",
554 Qnil);
555 }
556}
557
35f0d482
KH
558int
559random ()
560{
561 /* rand () on NT gives us 15 random bits...hack together 30 bits. */
562 return ((rand () << 15) | rand ());
563}
564
565void
566srandom (int seed)
567{
568 srand (seed);
569}
570
95ed0025
RS
571/* Destructively turn backslashes into slashes. */
572void
573dostounix_filename (p)
574 register char *p;
575{
576 while (*p)
577 {
578 if (*p == '\\')
579 *p = '/';
580 p++;
581 }
582}
583
584/* Routines that are no-ops on NT but are defined to get Emacs to compile. */
585
586
587int
588sigsetmask (int signal_mask)
589{
590 return 0;
591}
592
593int
594sigblock (int sig)
595{
596 return 0;
597}
598
599int
600kill (int pid, int signal)
601{
602 return 0;
603}
604
605int
606setpgrp (int pid, int gid)
607{
608 return 0;
609}
610
611int
612alarm (int seconds)
613{
614 return 0;
615}
616
617int
618unrequest_sigio (void)
619{
620 return 0;
621}
622
623int
624request_sigio (void)
625{
626 return 0;
627}
628
629int
630getuid ()
631{
03e123e7
GV
632 char buffer[256];
633 int size = 256;
634
635 if (!GetUserName (buffer, &size))
636 /* Assume all powers upon failure. */
637 return 0;
638
639 if (!stricmp ("administrator", buffer))
640 return 0;
641 else
642 /* A complete fabrication...is there anything to base it on? */
643 return 123;
95ed0025
RS
644}
645
646int
647geteuid ()
648{
03e123e7
GV
649 /* I could imagine arguing for checking to see whether the user is
650 in the Administrators group and returning a UID of 0 for that
651 case, but I don't know how wise that would be in the long run. */
652 return getuid ();
95ed0025
RS
653}
654
655/* Remove all CR's that are followed by a LF.
656 (From msdos.c...probably should figure out a way to share it,
657 although this code isn't going to ever change.) */
658int
659crlf_to_lf (n, buf)
660 register int n;
661 register unsigned char *buf;
662{
663 unsigned char *np = buf;
664 unsigned char *startp = buf;
665 unsigned char *endp = buf + n;
666
667 if (n == 0)
668 return n;
669 while (buf < endp - 1)
670 {
671 if (*buf == 0x0d)
672 {
673 if (*(++buf) != 0x0a)
674 *np++ = 0x0d;
675 }
676 else
677 *np++ = *buf++;
678 }
679 if (buf < endp)
680 *np++ = *buf++;
681 return np - startp;
682}
683
f332b293
GV
684#define REG_ROOT "SOFTWARE\\GNU\\Emacs\\"
685
686LPBYTE
687nt_get_resource (key, lpdwtype)
688 char *key;
689 LPDWORD lpdwtype;
690{
691 LPBYTE lpvalue;
692 HKEY hrootkey = NULL;
693 DWORD cbData;
694 BOOL ok = FALSE;
695
696 /* Check both the current user and the local machine to see if
697 we have any resources. */
698
699 if (RegOpenKeyEx (HKEY_CURRENT_USER, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
700 {
701 lpvalue = NULL;
702
703 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS
704 && (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL
705 && RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
706 {
707 return (lpvalue);
708 }
709
710 if (lpvalue) xfree (lpvalue);
711
712 RegCloseKey (hrootkey);
713 }
714
715 if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_ROOT, 0, KEY_READ, &hrootkey) == ERROR_SUCCESS)
716 {
717 lpvalue = NULL;
718
719 if (RegQueryValueEx (hrootkey, key, NULL, NULL, NULL, &cbData) == ERROR_SUCCESS &&
720 (lpvalue = (LPBYTE) xmalloc (cbData)) != NULL &&
721 RegQueryValueEx (hrootkey, key, NULL, lpdwtype, lpvalue, &cbData) == ERROR_SUCCESS)
722 {
723 return (lpvalue);
724 }
725
726 if (lpvalue) xfree (lpvalue);
727
728 RegCloseKey (hrootkey);
729 }
730
731 return (NULL);
732}
733
734void
735init_environment ()
736{
737 /* Open a console window to display messages during dumping. */
738 if (!initialized)
739 AllocConsole ();
740
741 /* Check for environment variables and use registry if they don't exist */
742 {
743 int i;
744 LPBYTE lpval;
745 DWORD dwType;
746
747 static char * env_vars[] =
748 {
749 "emacs_path",
750 "EMACSLOADPATH",
751 "SHELL",
752 "EMACSDATA",
753 "EMACSPATH",
754 "EMACSLOCKDIR",
755 "INFOPATH",
756 "EMACSDOC",
757 "TERM",
758 };
759
760 for (i = 0; i < (sizeof (env_vars) / sizeof (env_vars[0])); i++)
761 {
762 if (!getenv (env_vars[i]) &&
763 (lpval = nt_get_resource (env_vars[i], &dwType)) != NULL)
764 {
765 if (dwType == REG_EXPAND_SZ)
766 {
767 char buf1[500], buf2[500];
768
769 ExpandEnvironmentStrings ((LPSTR) lpval, buf1, 500);
770 _snprintf (buf2, 499, "%s=%s", env_vars[i], buf1);
771 putenv (strdup (buf2));
772 }
773 else if (dwType == REG_SZ)
774 {
775 char buf[500];
776
777 _snprintf (buf, 499, "%s=%s", env_vars[i], lpval);
778 putenv (strdup (buf));
779 }
780
781 xfree (lpval);
782 }
783 }
784 }
785}
786
35f0d482
KH
787#ifdef HAVE_TIMEVAL
788#include <sys/timeb.h>
789
790/* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
791void
792gettimeofday (struct timeval *tv, struct timezone *tz)
793{
794 struct _timeb tb;
795 _ftime (&tb);
796
797 tv->tv_sec = tb.time;
798 tv->tv_usec = tb.millitm * 1000L;
799 if (tz)
800 {
801 tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */
802 tz->tz_dsttime = tb.dstflag; /* type of dst correction */
803 }
804}
805#endif /* HAVE_TIMEVAL */
806
95ed0025
RS
807
808#ifdef PIGSFLY
809Keep this around...we might need it later.
810#ifdef WINDOWSNT
811{
812 /*
813 * Find the user's real name by opening the process token and looking
814 * up the name associated with the user-sid in that token.
815 */
816
817 char b[256], Name[256], RefD[256];
818 DWORD length = 256, rlength = 256, trash;
819 HANDLE Token;
820 SID_NAME_USE User;
821
822 if (1)
7cca72e3 823 Vuser_real_login_name = build_string ("foo");
95ed0025
RS
824 else if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &Token))
825 {
7cca72e3 826 Vuser_real_login_name = build_string ("unknown");
95ed0025
RS
827 }
828 else if (!GetTokenInformation (Token, TokenUser, (PVOID)b, 256,
829 &trash))
830 {
831 CloseHandle (Token);
7cca72e3 832 Vuser_real_login_name = build_string ("unknown");
95ed0025
RS
833 }
834 else if (!LookupAccountSid ((void *)0, (PSID)b, Name, &length, RefD,
835 &rlength, &User))
836 {
837 CloseHandle (Token);
7cca72e3 838 Vuser_real_login_name = build_string ("unknown");
95ed0025
RS
839 }
840 else
7cca72e3 841 Vuser_real_login_name = build_string (Name);
95ed0025
RS
842}
843#else /* not WINDOWSNT */
844#endif /* not WINDOWSNT */
845#endif /* PIGSFLY */