1 /* Utility and Unix shadow routines for GNU Emacs support programs on NT.
3 Copyright (C) 1994, 2001-2012 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/>. */
28 #include <sys/types.h>
32 #include <sys/timeb.h>
38 int tz_minuteswest
; /* minutes west of Greenwich */
39 int tz_dsttime
; /* type of dst correction */
42 #define MAXPATHLEN _MAX_PATH
44 /* Emulate sleep...we could have done this with a define, but that
45 would necessitate including windows.h in the files that used it.
46 This is much easier. */
48 sleep (unsigned long seconds
)
50 Sleep (seconds
* 1000);
53 /* Get the current working directory. */
57 if (GetCurrentDirectory (MAXPATHLEN
, dir
) > 0)
62 static HANDLE getppid_parent
;
63 static int getppid_ppid
;
71 ppid
= getenv ("EM_PARENT_PROCESS_ID");
79 getppid_ppid
= atoi (ppid
);
84 getppid_parent
= OpenProcess (SYNCHRONIZE
, FALSE
, atoi (ppid
));
87 printf ("Failed to open handle to parent process: %d\n",
93 result
= WaitForSingleObject (getppid_parent
, 0);
97 /* The parent is still alive. */
100 /* The parent is gone. Return the pid of Unix init (1). */
104 printf ("Checking parent status failed: %d\n", GetLastError ());
112 static char user_name
[256];
113 DWORD length
= sizeof (user_name
);
115 if (GetUserName (user_name
, &length
))
123 char * name
= getlogin ();
125 return strcpy (s
, name
? name
: "");
148 setuid (unsigned uid
)
154 setregid (unsigned rgid
, unsigned gid
)
160 getpwuid (unsigned uid
)
166 getpass (const char * prompt
)
168 static char input
[256];
173 in
= GetStdHandle (STD_INPUT_HANDLE
);
174 err
= GetStdHandle (STD_ERROR_HANDLE
);
176 if (in
== INVALID_HANDLE_VALUE
|| err
== INVALID_HANDLE_VALUE
)
179 if (WriteFile (err
, prompt
, strlen (prompt
), &count
, NULL
))
181 int istty
= (GetFileType (in
) == FILE_TYPE_CHAR
);
187 if (GetConsoleMode (in
, &old_flags
))
188 SetConsoleMode (in
, ENABLE_LINE_INPUT
| ENABLE_PROCESSED_INPUT
);
192 rc
= ReadFile (in
, input
, sizeof (input
), &count
, NULL
);
193 if (count
>= 2 && input
[count
- 2] == '\r')
194 input
[count
- 2] = '\0';
198 while (ReadFile (in
, buf
, sizeof (buf
), &count
, NULL
) > 0)
199 if (count
>= 2 && buf
[count
- 2] == '\r')
202 WriteFile (err
, "\r\n", 2, &count
, NULL
);
204 SetConsoleMode (in
, old_flags
);
212 /* This is needed because lib/gettime.c calls gettimeofday, which MSVC
213 doesn't have. Copied from w32.c. */
215 gettimeofday (struct timeval
*tv
, struct timezone
*tz
)
220 tv
->tv_sec
= tb
.time
;
221 tv
->tv_usec
= tb
.millitm
* 1000L;
222 /* Implementation note: _ftime sometimes doesn't update the dstflag
223 according to the new timezone when the system timezone is
224 changed. We could fix that by using GetSystemTime and
225 GetTimeZoneInformation, but that doesn't seem necessary, since
226 Emacs always calls gettimeofday with the 2nd argument NULL (see
227 current_emacs_time). */
230 tz
->tz_minuteswest
= tb
.timezone
; /* minutes west of Greenwich */
231 tz
->tz_dsttime
= tb
.dstflag
; /* type of dst correction */
236 fchown (int fd
, unsigned uid
, unsigned gid
)
241 /* Place a wrapper around the MSVC version of ctime. It returns NULL
242 on network directories, so we handle that case here.
243 (Ulrich Leodolter, 1/11/95). */
245 sys_ctime (const time_t *t
)
247 char *str
= (char *) ctime (t
);
248 return (str
? str
: "Sun Jan 01 00:00:00 1970");
252 sys_fopen (const char * path
, const char * mode
)
254 return fopen (path
, mode
);
258 sys_chdir (const char * path
)
260 return _chdir (path
);
263 static FILETIME utc_base_ft
;
264 static long double utc_base
;
268 convert_time (FILETIME ft
)
272 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
275 ret
= (long double) ft
.dwHighDateTime
276 * 4096.0L * 1024.0L * 1024.0L + ft
.dwLowDateTime
;
278 return (time_t) (ret
* 1e-7L);
282 is_exec (const char * name
)
284 char * p
= strrchr (name
, '.');
287 && (stricmp (p
, ".exe") == 0 ||
288 stricmp (p
, ".com") == 0 ||
289 stricmp (p
, ".bat") == 0 ||
290 stricmp (p
, ".cmd") == 0));
293 /* FIXME? This is in config.nt now - is this still needed? */
294 #define IS_DIRECTORY_SEP(x) ((x) == '/' || (x) == '\\')
296 /* We need this because nt/inc/sys/stat.h defines struct stat that is
297 incompatible with the MS run-time libraries. */
299 stat (const char * path
, struct stat
* buf
)
306 char *name
= alloca (FILENAME_MAX
);
310 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
319 st
.wMilliseconds
= 0;
321 SystemTimeToFileTime (&st
, &utc_base_ft
);
322 utc_base
= (long double) utc_base_ft
.dwHighDateTime
323 * 4096.0L * 1024.0L * 1024.0L + utc_base_ft
.dwLowDateTime
;
327 if (path
== NULL
|| buf
== NULL
|| *path
== '\0')
332 if (_mbspbrk (path
, "*?|<>\""))
339 /* Remove trailing directory separator, unless name is the root
340 directory of a drive in which case ensure there is a trailing
343 rootdir
= IS_DIRECTORY_SEP (name
[0])
344 || (len
== 3 && name
[1] == ':' && IS_DIRECTORY_SEP (name
[2]));
347 if (GetDriveType (name
) < 2)
352 memset (&wfd
, 0, sizeof (wfd
));
353 wfd
.dwFileAttributes
= FILE_ATTRIBUTE_DIRECTORY
;
354 wfd
.ftCreationTime
= utc_base_ft
;
355 wfd
.ftLastAccessTime
= utc_base_ft
;
356 wfd
.ftLastWriteTime
= utc_base_ft
;
357 strcpy (wfd
.cFileName
, name
);
361 if (IS_DIRECTORY_SEP (name
[len
-1]))
364 fh
= FindFirstFile (name
, &wfd
);
365 if (fh
== INVALID_HANDLE_VALUE
)
372 buf
->st_mode
= (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) ?
377 if (name
[0] && name
[1] == ':')
378 buf
->st_dev
= tolower (name
[0]) - 'a' + 1;
380 buf
->st_dev
= _getdrive ();
381 buf
->st_rdev
= buf
->st_dev
;
383 buf
->st_size
= wfd
.nFileSizeLow
;
385 /* Convert timestamps to Unix format. */
386 buf
->st_mtime
= convert_time (wfd
.ftLastWriteTime
);
387 buf
->st_atime
= convert_time (wfd
.ftLastAccessTime
);
388 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
389 buf
->st_ctime
= convert_time (wfd
.ftCreationTime
);
390 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
392 /* determine rwx permissions */
393 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
394 permission
= S_IREAD
;
396 permission
= S_IREAD
| S_IWRITE
;
398 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
399 permission
|= S_IEXEC
;
400 else if (is_exec (name
))
401 permission
|= S_IEXEC
;
403 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
409 lstat (const char * path
, struct stat
* buf
)
411 return stat (path
, buf
);