Fix warnings when compiling on MS-Windows with -std=gnu99.
[bpt/emacs.git] / lib-src / ntlib.c
CommitLineData
95ed0025 1/* Utility and Unix shadow routines for GNU Emacs support programs on NT.
59a428eb
GM
2
3Copyright (C) 1994, 2001-2012 Free Software Foundation, Inc.
4
5Author: Geoff Voelker (voelker@cs.washington.edu)
6Created: 10-8-94
95ed0025 7
3b7ad313
EN
8This file is part of GNU Emacs.
9
294981c7 10GNU Emacs is free software: you can redistribute it and/or modify
3b7ad313 11it under the terms of the GNU General Public License as published by
294981c7
GM
12the Free Software Foundation, either version 3 of the License, or
13(at your option) any later version.
3b7ad313
EN
14
15GNU Emacs is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
59a428eb 21along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
95ed0025
RS
22
23#include <windows.h>
24#include <stdlib.h>
25#include <stdio.h>
14f29224
GV
26#include <time.h>
27#include <direct.h>
10fea9c4
EZ
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <errno.h>
9c88f339 31#include <ctype.h>
62aba0d4 32#include <sys/timeb.h>
14f29224
GV
33
34#include "ntlib.h"
95ed0025 35
62aba0d4
FP
36struct timezone
37{
38 int tz_minuteswest; /* minutes west of Greenwich */
39 int tz_dsttime; /* type of dst correction */
40};
41
95ed0025
RS
42#define MAXPATHLEN _MAX_PATH
43
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. */
47void
7c3320d8 48sleep (unsigned long seconds)
95ed0025
RS
49{
50 Sleep (seconds * 1000);
51}
52
53/* Get the current working directory. */
133319ab 54char *
95ed0025
RS
55getwd (char *dir)
56{
14f29224
GV
57 if (GetCurrentDirectory (MAXPATHLEN, dir) > 0)
58 return dir;
59 return NULL;
95ed0025
RS
60}
61
62static HANDLE getppid_parent;
63static int getppid_ppid;
64
65int
7c3320d8 66getppid (void)
95ed0025
RS
67{
68 char *ppid;
69 DWORD result;
70
97e3c91b 71 ppid = getenv ("EM_PARENT_PROCESS_ID");
177c0ea7 72 if (!ppid)
95ed0025 73 {
7c3320d8 74 printf ("no pid.\n");
95ed0025 75 return 0;
177c0ea7
JB
76 }
77 else
95ed0025
RS
78 {
79 getppid_ppid = atoi (ppid);
80 }
81
177c0ea7 82 if (!getppid_parent)
95ed0025 83 {
7c3320d8 84 getppid_parent = OpenProcess (SYNCHRONIZE, FALSE, atoi (ppid));
177c0ea7 85 if (!getppid_parent)
95ed0025
RS
86 {
87 printf ("Failed to open handle to parent process: %d\n",
7c3320d8 88 GetLastError ());
95ed0025
RS
89 exit (1);
90 }
91 }
92
93 result = WaitForSingleObject (getppid_parent, 0);
177c0ea7 94 switch (result)
95ed0025
RS
95 {
96 case WAIT_TIMEOUT:
97 /* The parent is still alive. */
98 return getppid_ppid;
99 case WAIT_OBJECT_0:
100 /* The parent is gone. Return the pid of Unix init (1). */
101 return 1;
102 case WAIT_FAILED:
103 default:
7c3320d8 104 printf ("Checking parent status failed: %d\n", GetLastError ());
95ed0025
RS
105 exit (1);
106 }
107}
14f29224
GV
108
109char *
7c3320d8 110getlogin (void)
14f29224
GV
111{
112 static char user_name[256];
113 DWORD length = sizeof (user_name);
114
115 if (GetUserName (user_name, &length))
116 return user_name;
117 return NULL;
118}
119
120char *
121cuserid (char * s)
122{
123 char * name = getlogin ();
124 if (s)
125 return strcpy (s, name ? name : "");
126 return name;
127}
128
22749e9a 129unsigned
7c3320d8 130getuid (void)
14f29224
GV
131{
132 return 0;
133}
134
b372fceb 135unsigned
7c3320d8 136getgid (void)
b372fceb
JB
137{
138 return 0;
139}
140
141unsigned
7c3320d8 142getegid (void)
b372fceb
JB
143{
144 return 0;
145}
146
14f29224 147int
22749e9a 148setuid (unsigned uid)
14f29224
GV
149{
150 return 0;
151}
152
b372fceb 153int
f915f0f7 154setregid (unsigned rgid, unsigned gid)
b372fceb
JB
155{
156 return 0;
157}
158
14f29224 159struct passwd *
22749e9a 160getpwuid (unsigned uid)
14f29224
GV
161{
162 return NULL;
163}
164
165char *
166getpass (const char * prompt)
167{
168 static char input[256];
169 HANDLE in;
170 HANDLE err;
171 DWORD count;
172
173 in = GetStdHandle (STD_INPUT_HANDLE);
174 err = GetStdHandle (STD_ERROR_HANDLE);
175
176 if (in == INVALID_HANDLE_VALUE || err == INVALID_HANDLE_VALUE)
177 return NULL;
178
179 if (WriteFile (err, prompt, strlen (prompt), &count, NULL))
180 {
181 int istty = (GetFileType (in) == FILE_TYPE_CHAR);
182 DWORD old_flags;
183 int rc;
184
185 if (istty)
186 {
187 if (GetConsoleMode (in, &old_flags))
188 SetConsoleMode (in, ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT);
189 else
190 istty = 0;
191 }
192 rc = ReadFile (in, input, sizeof (input), &count, NULL);
193 if (count >= 2 && input[count - 2] == '\r')
194 input[count - 2] = '\0';
195 else
196 {
197 char buf[256];
198 while (ReadFile (in, buf, sizeof (buf), &count, NULL) > 0)
199 if (count >= 2 && buf[count - 2] == '\r')
200 break;
201 }
202 WriteFile (err, "\r\n", 2, &count, NULL);
203 if (istty)
204 SetConsoleMode (in, old_flags);
205 if (rc)
206 return input;
207 }
208
209 return NULL;
210}
211
62aba0d4
FP
212/* This is needed because lib/gettime.c calls gettimeofday, which MSVC
213 doesn't have. Copied from w32.c. */
214void
215gettimeofday (struct timeval *tv, struct timezone *tz)
216{
217 struct _timeb tb;
218 _ftime (&tb);
219
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). */
228 if (tz)
229 {
230 tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */
231 tz->tz_dsttime = tb.dstflag; /* type of dst correction */
232 }
233}
234
14f29224 235int
22749e9a 236fchown (int fd, unsigned uid, unsigned gid)
14f29224
GV
237{
238 return 0;
239}
240
241/* Place a wrapper around the MSVC version of ctime. It returns NULL
177c0ea7 242 on network directories, so we handle that case here.
14f29224
GV
243 (Ulrich Leodolter, 1/11/95). */
244char *
245sys_ctime (const time_t *t)
246{
247 char *str = (char *) ctime (t);
248 return (str ? str : "Sun Jan 01 00:00:00 1970");
249}
250
251FILE *
7c3320d8 252sys_fopen (const char * path, const char * mode)
14f29224
GV
253{
254 return fopen (path, mode);
255}
256
257int
258sys_chdir (const char * path)
259{
260 return _chdir (path);
261}
ab5796a9 262
10fea9c4
EZ
263static FILETIME utc_base_ft;
264static long double utc_base;
265static int init = 0;
266
267static time_t
268convert_time (FILETIME ft)
269{
270 long double ret;
271
272 if (CompareFileTime (&ft, &utc_base_ft) < 0)
273 return 0;
274
275 ret = (long double) ft.dwHighDateTime
276 * 4096.0L * 1024.0L * 1024.0L + ft.dwLowDateTime;
277 ret -= utc_base;
278 return (time_t) (ret * 1e-7L);
279}
280
281static int
282is_exec (const char * name)
283{
284 char * p = strrchr (name, '.');
285 return
286 (p != NULL
287 && (stricmp (p, ".exe") == 0 ||
288 stricmp (p, ".com") == 0 ||
289 stricmp (p, ".bat") == 0 ||
290 stricmp (p, ".cmd") == 0));
291}
292
59a428eb 293/* FIXME? This is in config.nt now - is this still needed? */
10fea9c4
EZ
294#define IS_DIRECTORY_SEP(x) ((x) == '/' || (x) == '\\')
295
296/* We need this because nt/inc/sys/stat.h defines struct stat that is
297 incompatible with the MS run-time libraries. */
298int
299stat (const char * path, struct stat * buf)
300{
301 WIN32_FIND_DATA wfd;
302 HANDLE fh;
303 int permission;
304 int len;
305 int rootdir = FALSE;
306 char *name = alloca (FILENAME_MAX);
307
308 if (!init)
309 {
310 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */
311 SYSTEMTIME st;
312
313 st.wYear = 1970;
314 st.wMonth = 1;
315 st.wDay = 1;
316 st.wHour = 0;
317 st.wMinute = 0;
318 st.wSecond = 0;
319 st.wMilliseconds = 0;
320
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;
324 init = 1;
325 }
326
327 if (path == NULL || buf == NULL || *path == '\0')
328 {
329 errno = EFAULT;
330 return -1;
331 }
332 if (_mbspbrk (path, "*?|<>\""))
333 {
334 errno = ENOENT;
335 return -1;
336 }
337
338 strcpy (name, path);
339 /* Remove trailing directory separator, unless name is the root
340 directory of a drive in which case ensure there is a trailing
341 separator. */
342 len = strlen (name);
343 rootdir = IS_DIRECTORY_SEP (name[0])
344 || (len == 3 && name[1] == ':' && IS_DIRECTORY_SEP (name[2]));
345 if (rootdir)
346 {
347 if (GetDriveType (name) < 2)
348 {
349 errno = ENOENT;
350 return -1;
351 }
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);
358 }
359 else
360 {
361 if (IS_DIRECTORY_SEP (name[len-1]))
362 name[len - 1] = 0;
363
364 fh = FindFirstFile (name, &wfd);
365 if (fh == INVALID_HANDLE_VALUE)
366 {
367 errno = ENOENT;
368 return -1;
369 }
370 FindClose (fh);
371 }
372 buf->st_mode = (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
373 S_IFDIR : S_IFREG;
374 buf->st_nlink = 1;
375 buf->st_ino = 0;
376
377 if (name[0] && name[1] == ':')
378 buf->st_dev = tolower (name[0]) - 'a' + 1;
379 else
380 buf->st_dev = _getdrive ();
381 buf->st_rdev = buf->st_dev;
382
383 buf->st_size = wfd.nFileSizeLow;
384
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;
391
392 /* determine rwx permissions */
393 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
394 permission = S_IREAD;
395 else
396 permission = S_IREAD | S_IWRITE;
397
398 if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
399 permission |= S_IEXEC;
400 else if (is_exec (name))
401 permission |= S_IEXEC;
402
403 buf->st_mode |= permission | (permission >> 3) | (permission >> 6);
404
405 return 0;
406}
407
6dad7178
EZ
408int
409lstat (const char * path, struct stat * buf)
410{
411 return stat (path, buf);
412}
413