1 /* Utility and Unix shadow routines for GNU Emacs on Windows NT.
2 Copyright (C) 1994 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 1, or (at your option) any later
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
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
40 extern int report_file_error (char *, Lisp_Object
);
42 /* Get the current working directory. */
46 return GetCurrentDirectory (MAXPATHLEN
, dir
);
49 /* Emulate gethostname. */
51 gethostname (char *buffer
, int size
)
53 /* NT only allows small host names, so the buffer is
54 certainly large enough. */
55 return !GetComputerName (buffer
, &size
);
58 /* Emulate getloadavg. */
60 getloadavg (double loadavg
[], int nelem
)
64 /* A faithful emulation is going to have to be saved for a rainy day. */
65 for (i
= 0; i
< nelem
; i
++)
72 /* Emulate sleep...we could have done this with a define, but that
73 would necessitate including windows.h in the files that used it.
74 This is much easier. */
76 nt_sleep (int seconds
)
78 Sleep (seconds
* 1000);
81 /* Emulate the Unix directory procedures opendir, closedir,
82 and readdir. We can't use the procedures supplied in sysdep.c,
83 so we provide them here. */
85 struct direct dir_static
; /* simulated directory contents */
86 static int dir_finding
;
87 static HANDLE dir_find_handle
;
90 opendir (char *filename
)
94 /* Opening is done by FindFirstFile. However, a read is inherent to
95 this operation, so we have a flag to handle the open at read
96 time. This flag essentially means "there is a find-handle open and
97 it needs to be closed." */
99 if (!(dirp
= (DIR *) malloc (sizeof (DIR))))
108 /* This is tacky, but we need the directory name for our
109 implementation of readdir. */
110 strncpy (dirp
->dd_buf
, filename
, DIRBLKSIZ
);
117 /* If we have a find-handle open, close it. */
120 FindClose (dir_find_handle
);
123 xfree ((char *) dirp
);
129 WIN32_FIND_DATA find_data
;
131 /* If we aren't dir_finding, do a find-first, otherwise do a find-next. */
134 char filename
[MAXNAMLEN
+ 3];
137 strncpy (filename
, dirp
->dd_buf
, MAXNAMLEN
);
138 ln
= strlen (filename
)-1;
139 if (filename
[ln
] != '\\' && filename
[ln
] != ':')
140 strcat (filename
, "\\");
141 strcat (filename
, "*.*");
143 dir_find_handle
= FindFirstFile (filename
, &find_data
);
145 if (dir_find_handle
== INVALID_HANDLE_VALUE
)
152 if (!FindNextFile (dir_find_handle
, &find_data
))
156 /* Don't return . or .. since it doesn't look like any of the
157 readdir calling code expects them. */
158 while (strcmp (find_data
.cFileName
, ".") == 0
159 || strcmp (find_data
.cFileName
, "..") == 0)
161 if (!FindNextFile (dir_find_handle
, &find_data
))
165 /* NT's unique ID for a file is 64 bits, so we have to fake it here.
166 This should work as long as we never use 0. */
167 dir_static
.d_ino
= 1;
169 dir_static
.d_reclen
= sizeof (struct direct
) - MAXNAMLEN
+ 3 +
170 dir_static
.d_namlen
- dir_static
.d_namlen
% 4;
172 dir_static
.d_namlen
= strlen (find_data
.cFileName
);
173 strncpy (dir_static
.d_name
, find_data
.cFileName
, MAXNAMLEN
);
178 /* Emulate getpwuid and getpwnam. */
180 int getuid (); /* forward declaration */
182 static char the_passwd_name
[256];
183 static char the_passwd_passwd
[256];
184 static char the_passwd_gecos
[256];
185 static char the_passwd_dir
[256];
186 static char the_passwd_shell
[256];
188 static struct passwd the_passwd
=
205 if (!GetUserName (the_passwd
.pw_name
, &size
))
208 the_passwd
.pw_passwd
[0] = '\0';
209 the_passwd
.pw_uid
= 0;
210 the_passwd
.pw_gid
= 0;
211 strcpy (the_passwd
.pw_gecos
, the_passwd
.pw_name
);
212 the_passwd
.pw_dir
[0] = '\0';
213 the_passwd
.pw_shell
[0] = '\0';
219 getpwnam (char *name
)
223 pw
= getpwuid (getuid ());
227 if (strcmp (name
, pw
->pw_name
))
234 /* We don't have scripts to automatically determine the system configuration
235 for Emacs before it's compiled, and we don't want to have to make the
236 user enter it, so we define EMACS_CONFIGURATION to invoke this runtime
239 static char configuration_buffer
[16];
242 get_emacs_configuration (void)
246 /* Determine the processor type. */
247 switch (get_processor_type ())
249 case PROCESSOR_INTEL_386
:
250 case PROCESSOR_INTEL_486
:
251 case PROCESSOR_INTEL_PENTIUM
:
254 case PROCESSOR_INTEL_860
:
257 case PROCESSOR_MIPS_R2000
:
258 case PROCESSOR_MIPS_R3000
:
259 case PROCESSOR_MIPS_R4000
:
262 case PROCESSOR_ALPHA_21064
:
270 /* Let oem be "*" until we figure out how to decode the OEM field. */
273 sprintf (configuration_buffer
, "%s-%s-nt%d.%d", arch
, oem
,
274 get_nt_major_version (), get_nt_minor_version ());
275 return configuration_buffer
;
278 /* Conjure up inode and device numbers that will serve the purpose
279 of Emacs. Return 1 upon success, 0 upon failure. */
281 get_inode_and_device_vals (Lisp_Object filename
, Lisp_Object
*p_inode
,
282 Lisp_Object
*p_device
)
284 /* File uids on NT are found using a handle to a file, which
285 implies that it has been opened. Since we want to be able
286 to stat an arbitrary file, we must open it, get the info,
289 Also, NT file uids are 64-bits. This is a problem. */
293 BY_HANDLE_FILE_INFORMATION info
;
295 /* FIXME: It shouldn't be opened without READ access, but NT on x86
296 doesn't allow GetFileInfo in that case (NT on mips does). */
298 handle
= CreateFile (XSTRING (filename
)->data
,
300 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
303 FILE_ATTRIBUTE_NORMAL
,
305 if (handle
== INVALID_HANDLE_VALUE
)
308 result
= GetFileInformationByHandle (handle
, &info
);
309 CloseHandle (handle
);
313 *p_inode
= make_number (info
.nFileIndexLow
); /* use the low value */
314 *p_device
= make_number (info
.dwVolumeSerialNumber
);
319 /* The following pipe routines are used to support our fork emulation.
320 Since NT's crt dup always creates inherited handles, we
321 must be careful in setting up pipes. First create
322 non-inherited pipe handles, then create an inherited handle
323 to the write end by dup-ing it, and then close the non-inherited
324 end that was just duped. This gives us one non-inherited handle
325 on the read end and one inherited handle to the write end. As
326 the parent, we close the inherited handle to the write end after
327 spawning the child. */
329 /* From callproc.c */
330 extern Lisp_Object Vbinary_process_input
;
331 extern Lisp_Object Vbinary_process_output
;
334 pipe_with_inherited_out (int fds
[2])
337 unsigned int flags
= _O_NOINHERIT
;
339 if (!NILP (Vbinary_process_output
))
342 _pipe (fds
, 0, flags
);
343 inherit_out
= dup (fds
[1]);
345 fds
[1] = inherit_out
;
349 pipe_with_inherited_in (int fds
[2])
352 unsigned int flags
= _O_NOINHERIT
;
354 if (!NILP (Vbinary_process_input
))
357 _pipe (fds
, 0, flags
);
358 inherit_in
= dup (fds
[0]);
363 /* The following two routines are used to manipulate stdin, stdout, and
364 stderr of our child processes.
366 Assuming that in, out, and err are inherited, we make them stdin,
367 stdout, and stderr of the child as follows:
369 - Save the parent's current standard handles.
370 - Set the parent's standard handles to the handles being passed in.
371 (Note that _get_osfhandle is an io.h procedure that
372 maps crt file descriptors to NT file handles.)
373 - Spawn the child, which inherits in, out, and err as stdin,
374 stdout, and stderr. (see Spawnve)
375 - Reset the parent's standard handles to the saved handles.
376 (see reset_standard_handles)
377 We assume that the caller closes in, out, and err after calling us. */
380 prepare_standard_handles (int in
, int out
, int err
, HANDLE handles
[4])
382 HANDLE parent
, stdin_save
, stdout_save
, stderr_save
, err_handle
;
384 parent
= GetCurrentProcess ();
385 if (!DuplicateHandle (parent
,
386 GetStdHandle (STD_INPUT_HANDLE
),
391 DUPLICATE_SAME_ACCESS
))
392 report_file_error ("Duplicating parent's input handle", Qnil
);
394 if (!DuplicateHandle (parent
,
395 GetStdHandle (STD_OUTPUT_HANDLE
),
400 DUPLICATE_SAME_ACCESS
))
401 report_file_error ("Duplicating parent's output handle", Qnil
);
403 if (!DuplicateHandle (parent
,
404 GetStdHandle (STD_ERROR_HANDLE
),
409 DUPLICATE_SAME_ACCESS
))
410 report_file_error ("Duplicating parent's error handle", Qnil
);
412 if (!SetStdHandle (STD_INPUT_HANDLE
, (HANDLE
) _get_osfhandle (in
)))
413 report_file_error ("Changing stdin handle", Qnil
);
415 if (!SetStdHandle (STD_OUTPUT_HANDLE
, (HANDLE
) _get_osfhandle (out
)))
416 report_file_error ("Changing stdout handle", Qnil
);
418 /* We lose data if we use the same handle to the pipe for stdout and
419 stderr, so make a duplicate. This took a while to find. */
422 if (!DuplicateHandle (parent
,
423 (HANDLE
) _get_osfhandle (err
),
428 DUPLICATE_SAME_ACCESS
))
429 report_file_error ("Duplicating out handle to make err handle.",
434 err_handle
= (HANDLE
) _get_osfhandle (err
);
437 if (!SetStdHandle (STD_ERROR_HANDLE
, err_handle
))
438 report_file_error ("Changing stderr handle", Qnil
);
440 handles
[0] = stdin_save
;
441 handles
[1] = stdout_save
;
442 handles
[2] = stderr_save
;
443 handles
[3] = err_handle
;
447 reset_standard_handles (int in
, int out
, int err
, HANDLE handles
[4])
449 HANDLE stdin_save
= handles
[0];
450 HANDLE stdout_save
= handles
[1];
451 HANDLE stderr_save
= handles
[2];
452 HANDLE err_handle
= handles
[3];
454 if (!SetStdHandle (STD_INPUT_HANDLE
, stdin_save
))
455 report_file_error ("Resetting input handle", Qnil
);
457 if (!SetStdHandle (STD_OUTPUT_HANDLE
, stdout_save
))
458 report_file_error ("Resetting output handle", Qnil
);
460 if (!SetStdHandle (STD_ERROR_HANDLE
, stderr_save
))
461 report_file_error ("Resetting error handle", Qnil
);
465 /* If out and err are the same handle, then we duplicated out
466 and stuck it in err_handle. Close the duplicate to clean up. */
467 if (!CloseHandle (err_handle
))
468 report_file_error ("Closing error handle duplicated from out.",
473 /* Destructively turn backslashes into slashes. */
475 dostounix_filename (p
)
486 /* Routines that are no-ops on NT but are defined to get Emacs to compile. */
490 sigsetmask (int signal_mask
)
502 kill (int pid
, int signal
)
508 setpgrp (int pid
, int gid
)
520 unrequest_sigio (void)
543 /* Remove all CR's that are followed by a LF.
544 (From msdos.c...probably should figure out a way to share it,
545 although this code isn't going to ever change.) */
549 register unsigned char *buf
;
551 unsigned char *np
= buf
;
552 unsigned char *startp
= buf
;
553 unsigned char *endp
= buf
+ n
;
557 while (buf
< endp
- 1)
561 if (*(++buf
) != 0x0a)
574 Keep
this around
...we might need it later
.
578 * Find the user's real name by opening the process token and looking
579 * up the name associated with the user-sid in that token.
582 char b
[256], Name
[256], RefD
[256];
583 DWORD length
= 256, rlength
= 256, trash
;
588 Vuser_real_name
= build_string ("foo");
589 else if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY
, &Token
))
591 Vuser_real_name
= build_string ("unknown");
593 else if (!GetTokenInformation (Token
, TokenUser
, (PVOID
)b
, 256,
597 Vuser_real_name
= build_string ("unknown");
599 else if (!LookupAccountSid ((void *)0, (PSID
)b
, Name
, &length
, RefD
,
603 Vuser_real_name
= build_string ("unknown");
606 Vuser_real_name
= build_string (Name
);
608 #else /* not WINDOWSNT */
609 #endif /* not WINDOWSNT */