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