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/>. */
28 #include <sys/types.h>
32 #include <sys/timeb.h>
39 int tz_minuteswest
; /* minutes west of Greenwich */
40 int tz_dsttime
; /* type of dst correction */
43 #define MAXPATHLEN _MAX_PATH
45 /* Emulate sleep...we could have done this with a define, but that
46 would necessitate including windows.h in the files that used it.
47 This is much easier. */
49 sleep (unsigned long seconds
)
51 Sleep (seconds
* 1000);
54 /* Get the current working directory. */
58 if (GetCurrentDirectory (MAXPATHLEN
, dir
) > 0)
63 static HANDLE getppid_parent
;
64 static int getppid_ppid
;
72 ppid
= getenv ("EM_PARENT_PROCESS_ID");
80 getppid_ppid
= atoi (ppid
);
85 getppid_parent
= OpenProcess (SYNCHRONIZE
, FALSE
, atoi (ppid
));
88 printf ("Failed to open handle to parent process: %d\n",
94 result
= WaitForSingleObject (getppid_parent
, 0);
98 /* The parent is still alive. */
101 /* The parent is gone. Return the pid of Unix init (1). */
105 printf ("Checking parent status failed: %d\n", GetLastError ());
113 static char user_name
[256];
114 DWORD length
= sizeof (user_name
);
116 if (GetUserName (user_name
, &length
))
124 char * name
= getlogin ();
126 return strcpy (s
, name
? name
: "");
149 setuid (unsigned uid
)
155 setregid (unsigned rgid
, unsigned gid
)
161 getpwuid (unsigned uid
)
167 getpass (const char * prompt
)
169 static char input
[256];
174 in
= GetStdHandle (STD_INPUT_HANDLE
);
175 err
= GetStdHandle (STD_ERROR_HANDLE
);
177 if (in
== INVALID_HANDLE_VALUE
|| err
== INVALID_HANDLE_VALUE
)
180 if (WriteFile (err
, prompt
, strlen (prompt
), &count
, NULL
))
182 int istty
= (GetFileType (in
) == FILE_TYPE_CHAR
);
188 if (GetConsoleMode (in
, &old_flags
))
189 SetConsoleMode (in
, ENABLE_LINE_INPUT
| ENABLE_PROCESSED_INPUT
);
193 rc
= ReadFile (in
, input
, sizeof (input
), &count
, NULL
);
194 if (count
>= 2 && input
[count
- 2] == '\r')
195 input
[count
- 2] = '\0';
199 while (ReadFile (in
, buf
, sizeof (buf
), &count
, NULL
) > 0)
200 if (count
>= 2 && buf
[count
- 2] == '\r')
203 WriteFile (err
, "\r\n", 2, &count
, NULL
);
205 SetConsoleMode (in
, old_flags
);
213 /* This is needed because lib/gettime.c calls gettimeofday, which MSVC
214 doesn't have. Copied from w32.c. */
216 gettimeofday (struct timeval
*tv
, struct timezone
*tz
)
221 tv
->tv_sec
= tb
.time
;
222 tv
->tv_usec
= tb
.millitm
* 1000L;
223 /* Implementation note: _ftime sometimes doesn't update the dstflag
224 according to the new timezone when the system timezone is
225 changed. We could fix that by using GetSystemTime and
226 GetTimeZoneInformation, but that doesn't seem necessary, since
227 Emacs always calls gettimeofday with the 2nd argument NULL (see
228 current_emacs_time). */
231 tz
->tz_minuteswest
= tb
.timezone
; /* minutes west of Greenwich */
232 tz
->tz_dsttime
= tb
.dstflag
; /* type of dst correction */
237 fchown (int fd
, unsigned uid
, unsigned gid
)
242 /* Place a wrapper around the MSVC version of ctime. It returns NULL
243 on network directories, so we handle that case here.
244 (Ulrich Leodolter, 1/11/95). */
246 sys_ctime (const time_t *t
)
248 char *str
= (char *) ctime (t
);
249 return (str
? str
: "Sun Jan 01 00:00:00 1970");
253 sys_fopen (const char * path
, const char * mode
)
255 return fopen (path
, mode
);
259 sys_chdir (const char * path
)
261 return _chdir (path
);
264 static FILETIME utc_base_ft
;
265 static long double utc_base
;
269 convert_time (FILETIME ft
)
273 if (CompareFileTime (&ft
, &utc_base_ft
) < 0)
276 ret
= (long double) ft
.dwHighDateTime
277 * 4096.0L * 1024.0L * 1024.0L + ft
.dwLowDateTime
;
279 return (time_t) (ret
* 1e-7L);
283 is_exec (const char * name
)
285 char * p
= strrchr (name
, '.');
288 && (stricmp (p
, ".exe") == 0 ||
289 stricmp (p
, ".com") == 0 ||
290 stricmp (p
, ".bat") == 0 ||
291 stricmp (p
, ".cmd") == 0));
294 /* FIXME? This is in config.nt now - is this still needed? */
295 #define IS_DIRECTORY_SEP(x) ((x) == '/' || (x) == '\\')
297 /* We need this because nt/inc/sys/stat.h defines struct stat that is
298 incompatible with the MS run-time libraries. */
300 stat (const char * path
, struct stat
* buf
)
307 char *name
= alloca (FILENAME_MAX
);
311 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
320 st
.wMilliseconds
= 0;
322 SystemTimeToFileTime (&st
, &utc_base_ft
);
323 utc_base
= (long double) utc_base_ft
.dwHighDateTime
324 * 4096.0L * 1024.0L * 1024.0L + utc_base_ft
.dwLowDateTime
;
328 if (path
== NULL
|| buf
== NULL
|| *path
== '\0')
333 if (_mbspbrk (path
, "*?|<>\""))
340 /* Remove trailing directory separator, unless name is the root
341 directory of a drive in which case ensure there is a trailing
344 rootdir
= IS_DIRECTORY_SEP (name
[0])
345 || (len
== 3 && name
[1] == ':' && IS_DIRECTORY_SEP (name
[2]));
348 if (GetDriveType (name
) < 2)
353 memset (&wfd
, 0, sizeof (wfd
));
354 wfd
.dwFileAttributes
= FILE_ATTRIBUTE_DIRECTORY
;
355 wfd
.ftCreationTime
= utc_base_ft
;
356 wfd
.ftLastAccessTime
= utc_base_ft
;
357 wfd
.ftLastWriteTime
= utc_base_ft
;
358 strcpy (wfd
.cFileName
, name
);
362 if (IS_DIRECTORY_SEP (name
[len
-1]))
365 fh
= FindFirstFile (name
, &wfd
);
366 if (fh
== INVALID_HANDLE_VALUE
)
373 buf
->st_mode
= (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) ?
378 if (name
[0] && name
[1] == ':')
379 buf
->st_dev
= tolower (name
[0]) - 'a' + 1;
381 buf
->st_dev
= _getdrive ();
382 buf
->st_rdev
= buf
->st_dev
;
384 buf
->st_size
= wfd
.nFileSizeLow
;
386 /* Convert timestamps to Unix format. */
387 buf
->st_mtime
= convert_time (wfd
.ftLastWriteTime
);
388 buf
->st_atime
= convert_time (wfd
.ftLastAccessTime
);
389 if (buf
->st_atime
== 0) buf
->st_atime
= buf
->st_mtime
;
390 buf
->st_ctime
= convert_time (wfd
.ftCreationTime
);
391 if (buf
->st_ctime
== 0) buf
->st_ctime
= buf
->st_mtime
;
393 /* determine rwx permissions */
394 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
395 permission
= S_IREAD
;
397 permission
= S_IREAD
| S_IWRITE
;
399 if (wfd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
400 permission
|= S_IEXEC
;
401 else if (is_exec (name
))
402 permission
|= S_IEXEC
;
404 buf
->st_mode
|= permission
| (permission
>> 3) | (permission
>> 6);
410 lstat (const char * path
, struct stat
* buf
)
412 return stat (path
, buf
);