1 /* Utility and Unix shadow routines for GNU Emacs support programs on NT.
3 Copyright (C) 1994, 2001-2013 Free Software Foundation, Inc.
5 Author: Geoff Voelker (voelker@cs.washington.edu)
8 This file is part of GNU Emacs.
10 GNU Emacs is free software: you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
15 GNU Emacs is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
24 /* A kludge to avoid including header files in lib/. They cannot be
25 configured-out, and their stuff interferes with what we have
26 defined in this header and in other headers in nt/inc. Yuck! */
27 #define __need_system_fcntl_h
29 #define _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H
30 #define _GL_ALREADY_INCLUDING_SIGNAL_H
31 #define _GL_ALREADY_INCLUDING_STDIO_H
32 #define __need_system_stdlib_h
34 #define __need_system_sys_stat_h
42 #include <sys/types.h>
46 #include <sys/timeb.h>
51 /* MinGW64 defines _TIMEZONE_DEFINED and defines 'struct timespec' in
52 its system headers. */
53 #ifndef _TIMEZONE_DEFINED
56 int tz_minuteswest
; /* minutes west of Greenwich */
57 int tz_dsttime
; /* type of dst correction */
61 #define MAXPATHLEN _MAX_PATH
63 /* Emulate sleep...we could have done this with a define, but that
64 would necessitate including windows.h in the files that used it.
65 This is much easier. */
67 sleep (unsigned seconds
)
69 Sleep (seconds
* 1000);
73 /* Get the current working directory. */
77 if (GetCurrentDirectory (MAXPATHLEN
, dir
) > 0)
82 static HANDLE getppid_parent
;
83 static int getppid_ppid
;
91 ppid
= getenv ("EM_PARENT_PROCESS_ID");
99 getppid_ppid
= atoi (ppid
);
104 getppid_parent
= OpenProcess (SYNCHRONIZE
, FALSE
, atoi (ppid
));
107 printf ("Failed to open handle to parent process: %d\n",
113 result
= WaitForSingleObject (getppid_parent
, 0);
117 /* The parent is still alive. */
120 /* The parent is gone. Return the pid of Unix init (1). */
124 printf ("Checking parent status failed: %d\n", GetLastError ());
132 static char user_name
[256];
133 DWORD length
= sizeof (user_name
);
135 if (GetUserName (user_name
, &length
))
143 char * name
= getlogin ();
145 return strcpy (s
, name
? name
: "");
174 setuid (unsigned uid
)
180 setregid (unsigned rgid
, unsigned gid
)
186 getpwuid (unsigned uid
)
192 getpass (const char * prompt
)
194 static char input
[256];
199 in
= GetStdHandle (STD_INPUT_HANDLE
);
200 err
= GetStdHandle (STD_ERROR_HANDLE
);
202 if (in
== INVALID_HANDLE_VALUE
|| err
== INVALID_HANDLE_VALUE
)
205 if (WriteFile (err
, prompt
, strlen (prompt
), &count
, NULL
))
207 int istty
= (GetFileType (in
) == FILE_TYPE_CHAR
);
213 if (GetConsoleMode (in
, &old_flags
))
214 SetConsoleMode (in
, ENABLE_LINE_INPUT
| ENABLE_PROCESSED_INPUT
);
218 rc
= ReadFile (in
, input
, sizeof (input
), &count
, NULL
);
219 if (count
>= 2 && input
[count
- 2] == '\r')
220 input
[count
- 2] = '\0';
224 while (ReadFile (in
, buf
, sizeof (buf
), &count
, NULL
) > 0)
225 if (count
>= 2 && buf
[count
- 2] == '\r')
228 WriteFile (err
, "\r\n", 2, &count
, NULL
);
230 SetConsoleMode (in
, old_flags
);
238 /* This is needed because lib/gettime.c calls gettimeofday, which MSVC
239 doesn't have. Copied from w32.c. */
241 gettimeofday (struct timeval
*tv
, struct timezone
*tz
)
246 tv
->tv_sec
= tb
.time
;
247 tv
->tv_usec
= tb
.millitm
* 1000L;
248 /* Implementation note: _ftime sometimes doesn't update the dstflag
249 according to the new timezone when the system timezone is
250 changed. We could fix that by using GetSystemTime and
251 GetTimeZoneInformation, but that doesn't seem necessary, since
252 Emacs always calls gettimeofday with the 2nd argument NULL (see
253 current_emacs_time). */
256 tz
->tz_minuteswest
= tb
.timezone
; /* minutes west of Greenwich */
257 tz
->tz_dsttime
= tb
.dstflag
; /* type of dst correction */
262 fchown (int fd
, unsigned uid
, unsigned gid
)
267 /* Place a wrapper around the MSVC version of ctime. It returns NULL
268 on network directories, so we handle that case here.
269 (Ulrich Leodolter, 1/11/95). */
271 sys_ctime (const time_t *t
)
273 char *str
= (char *) ctime (t
);
274 return (str
? str
: "Sun Jan 01 00:00:00 1970");
278 sys_fopen (const char * path
, const char * mode
)
280 return fopen (path
, mode
);
284 sys_chdir (const char * path
)
286 return _chdir (path
);
289 static FILETIME utc_base_ft
;
290 static long double utc_base
;
294 convert_time (FILETIME ft
)
298 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
301 ret
= (long double) ft
.dwHighDateTime
302 * 4096.0L * 1024.0L * 1024.0L + ft
.dwLowDateTime
;
304 return (time_t) (ret
* 1e-7L);
308 is_exec (const char * name
)
310 char * p
= strrchr (name
, '.');
313 && (stricmp (p
, ".exe") == 0 ||
314 stricmp (p
, ".com") == 0 ||
315 stricmp (p
, ".bat") == 0 ||
316 stricmp (p
, ".cmd") == 0));
319 /* FIXME? This is in config.nt now - is this still needed? */
320 #define IS_DIRECTORY_SEP(x) ((x) == '/' || (x) == '\\')
322 /* We need this because nt/inc/sys/stat.h defines struct stat that is
323 incompatible with the MS run-time libraries. */
325 stat (const char * path
, struct stat
* buf
)
332 char *name
= alloca (FILENAME_MAX
);
336 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
345 st
.wMilliseconds
= 0;
347 SystemTimeToFileTime (&st
, &utc_base_ft
);
348 utc_base
= (long double) utc_base_ft
.dwHighDateTime
349 * 4096.0L * 1024.0L * 1024.0L + utc_base_ft
.dwLowDateTime
;
353 if (path
== NULL
|| buf
== NULL
|| *path
== '\0')
358 if (_mbspbrk (path
, "*?|<>\""))
365 /* Remove trailing directory separator, unless name is the root
366 directory of a drive in which case ensure there is a trailing
369 rootdir
= IS_DIRECTORY_SEP (name
[0])
370 || (len
== 3 && name
[1] == ':' && IS_DIRECTORY_SEP (name
[2]));
373 if (GetDriveType (name
) < 2)
378 memset (&wfd
, 0, sizeof (wfd
));
379 wfd
.dwFileAttributes
= FILE_ATTRIBUTE_DIRECTORY
;
380 wfd
.ftCreationTime
= utc_base_ft
;
381 wfd
.ftLastAccessTime
= utc_base_ft
;
382 wfd
.ftLastWriteTime
= utc_base_ft
;
383 strcpy (wfd
.cFileName
, name
);
387 if (IS_DIRECTORY_SEP (name
[len
-1]))
390 fh
= FindFirstFile (name
, &wfd
);
391 if (fh
== INVALID_HANDLE_VALUE
)
398 buf
->st_mode
= (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) ?
403 if (name
[0] && name
[1] == ':')
404 buf
->st_dev
= tolower (name
[0]) - 'a' + 1;
406 buf
->st_dev
= _getdrive ();
407 buf
->st_rdev
= buf
->st_dev
;
409 buf
->st_size
= wfd
.nFileSizeLow
;
411 /* Convert timestamps to Unix format. */
412 buf
->st_mtime
= convert_time (wfd
.ftLastWriteTime
);
413 buf
->st_atime
= convert_time (wfd
.ftLastAccessTime
);
414 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
415 buf
->st_ctime
= convert_time (wfd
.ftCreationTime
);
416 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
418 /* determine rwx permissions */
419 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
420 permission
= S_IREAD
;
422 permission
= S_IREAD
| S_IWRITE
;
424 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
425 permission
|= S_IEXEC
;
426 else if (is_exec (name
))
427 permission
|= S_IEXEC
;
429 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
435 lstat (const char * path
, struct stat
* buf
)
437 return stat (path
, buf
);