Mercurial > hg > xemacs-beta
comparison src/nt.c @ 412:697ef44129c6 r21-2-14
Import from CVS: tag r21-2-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:20:41 +0200 |
parents | de805c49cfc1 |
children | 41dbb7a9d5f2 |
comparison
equal
deleted
inserted
replaced
411:12e008d41344 | 412:697ef44129c6 |
---|---|
23 | 23 |
24 /* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */ | 24 /* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */ |
25 /* Sync'ed with Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */ | 25 /* Sync'ed with Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */ |
26 | 26 |
27 #include <config.h> | 27 #include <config.h> |
28 | |
29 #undef signal | |
28 #define getwd _getwd | 30 #define getwd _getwd |
29 #include "lisp.h" | 31 #include "lisp.h" |
30 #undef getwd | 32 #undef getwd |
31 | 33 |
32 #include "systime.h" | 34 #include "systime.h" |
33 #include "syssignal.h" | 35 #include "syssignal.h" |
34 #include "sysproc.h" | 36 #include "sysproc.h" |
35 #include "sysfile.h" | 37 #include "sysfile.h" |
36 #include "syspwd.h" | 38 |
37 #include "sysdir.h" | 39 #include <ctype.h> |
38 | 40 #include <direct.h> |
39 #include "syswindows.h" | 41 #include <errno.h> |
42 #include <fcntl.h> | |
43 #include <io.h> | |
44 #include <pwd.h> | |
45 #include <signal.h> | |
46 #include <stddef.h> /* for offsetof */ | |
47 #include <string.h> | |
48 #include <stdlib.h> | |
49 #include <stdio.h> | |
50 | |
51 #include <windows.h> | |
52 #ifndef __MINGW32__ | |
53 #include <mmsystem.h> | |
54 #else | |
55 typedef void (CALLBACK TIMECALLBACK)(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2); | |
56 | |
57 typedef TIMECALLBACK FAR *LPTIMECALLBACK; | |
58 DWORD WINAPI timeGetTime(void); | |
59 MMRESULT WINAPI timeSetEvent(UINT uDelay, UINT uResolution, | |
60 LPTIMECALLBACK fptc, DWORD dwUser, UINT fuEvent); | |
61 MMRESULT WINAPI timeKillEvent(UINT uTimerID); | |
62 MMRESULT WINAPI timeGetDevCaps(TIMECAPS* ptc, UINT cbtc); | |
63 MMRESULT WINAPI timeBeginPeriod(UINT uPeriod); | |
64 MMRESULT WINAPI timeEndPeriod(UINT uPeriod); | |
65 #endif | |
40 | 66 |
41 #include "nt.h" | 67 #include "nt.h" |
68 #include <sys/dir.h> | |
42 #include "ntheap.h" | 69 #include "ntheap.h" |
43 | 70 |
44 | 71 |
45 extern Lisp_Object Vmswindows_downcase_file_names; | 72 extern Lisp_Object Vmswindows_downcase_file_names; |
46 #if 0 | 73 #if 0 |
47 extern Lisp_Object Vwin32_generate_fake_inodes; | 74 extern Lisp_Object Vwin32_generate_fake_inodes; |
48 #endif | 75 #endif |
49 extern Lisp_Object Vmswindows_get_true_file_attributes; | 76 extern Lisp_Object Vmswindows_get_true_file_attributes; |
50 | 77 |
51 int nt_fake_unix_uid; | 78 extern char *get_home_directory(void); |
52 | 79 |
53 static char startup_dir[ MAXPATHLEN ]; | 80 static char startup_dir[ MAXPATHLEN ]; |
54 | 81 |
55 /* Get the current working directory. */ | 82 /* Get the current working directory. */ |
56 char * | 83 char * |
103 the_passwd_gecos, | 130 the_passwd_gecos, |
104 the_passwd_dir, | 131 the_passwd_dir, |
105 the_passwd_shell, | 132 the_passwd_shell, |
106 }; | 133 }; |
107 | 134 |
108 uid_t | 135 int |
109 getuid (void) | 136 getuid () |
110 { | |
111 return nt_fake_unix_uid; | |
112 } | |
113 | |
114 uid_t | |
115 geteuid (void) | |
116 { | 137 { |
117 return nt_fake_unix_uid; | 138 return the_passwd.pw_uid; |
118 } | 139 } |
119 | 140 |
120 gid_t | 141 int |
121 getgid (void) | 142 geteuid () |
143 { | |
144 /* I could imagine arguing for checking to see whether the user is | |
145 in the Administrators group and returning a UID of 0 for that | |
146 case, but I don't know how wise that would be in the long run. */ | |
147 return getuid (); | |
148 } | |
149 | |
150 int | |
151 getgid () | |
122 { | 152 { |
123 return the_passwd.pw_gid; | 153 return the_passwd.pw_gid; |
124 } | 154 } |
125 | 155 |
126 gid_t | 156 int |
127 getegid (void) | 157 getegid () |
128 { | 158 { |
129 return getgid (); | 159 return getgid (); |
130 } | 160 } |
131 | 161 |
132 struct passwd * | 162 struct passwd * |
133 getpwuid (uid_t uid) | 163 getpwuid (int uid) |
134 { | 164 { |
135 if (uid == nt_fake_unix_uid) | 165 if (uid == the_passwd.pw_uid) |
136 { | 166 return &the_passwd; |
137 the_passwd.pw_gid = the_passwd.pw_uid = uid; | 167 return NULL; |
138 return &the_passwd; | |
139 } | |
140 else | |
141 return NULL; | |
142 } | 168 } |
143 | 169 |
144 struct passwd * | 170 struct passwd * |
145 getpwnam (const char *name) | 171 getpwnam (const char *name) |
146 { | 172 { |
155 | 181 |
156 return pw; | 182 return pw; |
157 } | 183 } |
158 | 184 |
159 void | 185 void |
160 init_user_info (void) | 186 init_user_info () |
161 { | 187 { |
162 /* This code is pretty much of ad hoc nature. There is no unix-like | |
163 UIDs under Windows NT. There is no concept of root user, because | |
164 all security is ACL-based. Instead, let's use a simple variable, | |
165 nt-fake-unix-uid, which would allow the user to have a uid of | |
166 choice. --kkm, 02/03/2000 */ | |
167 #if 0 | |
168 /* Find the user's real name by opening the process token and | 188 /* Find the user's real name by opening the process token and |
169 looking up the name associated with the user-sid in that token. | 189 looking up the name associated with the user-sid in that token. |
170 | 190 |
171 Use the relative portion of the identifier authority value from | 191 Use the relative portion of the identifier authority value from |
172 the user-sid as the user id value (same for group id using the | 192 the user-sid as the user id value (same for group id using the |
238 strcpy (the_passwd.pw_name, "unknown"); | 258 strcpy (the_passwd.pw_name, "unknown"); |
239 the_passwd.pw_uid = 123; | 259 the_passwd.pw_uid = 123; |
240 the_passwd.pw_gid = 123; | 260 the_passwd.pw_gid = 123; |
241 } | 261 } |
242 | 262 |
243 if (token) | |
244 CloseHandle (token); | |
245 #else | |
246 /* Obtain only logon id here, uid part is moved to getuid */ | |
247 char name[256]; | |
248 DWORD length = sizeof (name); | |
249 if (GetUserName (name, &length)) | |
250 strcpy (the_passwd.pw_name, name); | |
251 else | |
252 strcpy (the_passwd.pw_name, "unknown"); | |
253 #endif | |
254 | |
255 /* Ensure HOME and SHELL are defined. */ | 263 /* Ensure HOME and SHELL are defined. */ |
256 #if 0 | 264 #if 0 |
257 /* | 265 /* |
258 * With XEmacs, setting $HOME is deprecated. | 266 * With XEmacs, setting $HOME is deprecated. |
259 */ | 267 */ |
262 #endif | 270 #endif |
263 if (getenv ("SHELL") == NULL) | 271 if (getenv ("SHELL") == NULL) |
264 putenv ((GetVersion () & 0x80000000) ? "SHELL=command" : "SHELL=cmd"); | 272 putenv ((GetVersion () & 0x80000000) ? "SHELL=command" : "SHELL=cmd"); |
265 | 273 |
266 /* Set dir and shell from environment variables. */ | 274 /* Set dir and shell from environment variables. */ |
267 strcpy (the_passwd.pw_dir, (char *)get_home_directory()); | 275 strcpy (the_passwd.pw_dir, get_home_directory()); |
268 strcpy (the_passwd.pw_shell, getenv ("SHELL")); | 276 strcpy (the_passwd.pw_shell, getenv ("SHELL")); |
277 | |
278 if (token) | |
279 CloseHandle (token); | |
269 } | 280 } |
270 | 281 |
271 /* Normalize filename by converting all path separators to | 282 /* Normalize filename by converting all path separators to |
272 the specified separator. Also conditionally convert upper | 283 the specified separator. Also conditionally convert upper |
273 case path name components to lower case. */ | 284 case path name components to lower case. */ |
274 | 285 |
275 static void | 286 static void |
276 normalize_filename (char *fp, char path_sep) | 287 normalize_filename (fp, path_sep) |
288 REGISTER char *fp; | |
289 char path_sep; | |
277 { | 290 { |
278 char sep; | 291 char sep; |
279 char *elem; | 292 char *elem; |
280 | 293 |
281 /* Always lower-case drive letters a-z, even if the filesystem | 294 /* Always lower-case drive letters a-z, even if the filesystem |
327 } while (*fp++); | 340 } while (*fp++); |
328 } | 341 } |
329 | 342 |
330 /* Destructively turn backslashes into slashes. */ | 343 /* Destructively turn backslashes into slashes. */ |
331 void | 344 void |
332 dostounix_filename (char *p) | 345 dostounix_filename (p) |
346 REGISTER char *p; | |
333 { | 347 { |
334 normalize_filename (p, '/'); | 348 normalize_filename (p, '/'); |
335 } | 349 } |
336 | 350 |
337 /* Destructively turn slashes into backslashes. */ | 351 /* Destructively turn slashes into backslashes. */ |
338 void | 352 void |
339 unixtodos_filename (char *p) | 353 unixtodos_filename (p) |
354 REGISTER char *p; | |
340 { | 355 { |
341 normalize_filename (p, '\\'); | 356 normalize_filename (p, '\\'); |
342 } | 357 } |
343 | 358 |
344 /* Remove all CR's that are followed by a LF. | 359 /* Remove all CR's that are followed by a LF. |
345 (From msdos.c...probably should figure out a way to share it, | 360 (From msdos.c...probably should figure out a way to share it, |
346 although this code isn't going to ever change.) */ | 361 although this code isn't going to ever change.) */ |
347 int | 362 int |
348 crlf_to_lf (int n, unsigned char *buf, unsigned *lf_count) | 363 crlf_to_lf (n, buf, lf_count) |
364 REGISTER int n; | |
365 REGISTER unsigned char *buf; | |
366 REGISTER unsigned *lf_count; | |
349 { | 367 { |
350 unsigned char *np = buf; | 368 unsigned char *np = buf; |
351 unsigned char *startp = buf; | 369 unsigned char *startp = buf; |
352 unsigned char *endp = buf + n; | 370 unsigned char *endp = buf + n; |
353 | 371 |
520 #endif /* 0 */ | 538 #endif /* 0 */ |
521 | 539 |
522 #define REG_ROOT "SOFTWARE\\GNU\\XEmacs" | 540 #define REG_ROOT "SOFTWARE\\GNU\\XEmacs" |
523 | 541 |
524 LPBYTE | 542 LPBYTE |
525 nt_get_resource (char *key, LPDWORD lpdwtype) | 543 nt_get_resource (key, lpdwtype) |
544 char *key; | |
545 LPDWORD lpdwtype; | |
526 { | 546 { |
527 LPBYTE lpvalue; | 547 LPBYTE lpvalue; |
528 HKEY hrootkey = NULL; | 548 HKEY hrootkey = NULL; |
529 DWORD cbData; | 549 DWORD cbData; |
530 | 550 |
565 | 585 |
566 return (NULL); | 586 return (NULL); |
567 } | 587 } |
568 | 588 |
569 void | 589 void |
570 init_environment (void) | 590 init_environment () |
571 { | 591 { |
572 /* Check for environment variables and use registry if they don't exist */ | 592 /* Check for environment variables and use registry if they don't exist */ |
573 { | 593 { |
574 int i; | 594 int i; |
575 LPBYTE lpval; | 595 LPBYTE lpval; |
587 "EMACSPATH", | 607 "EMACSPATH", |
588 "EMACSPACKAGEPATH", | 608 "EMACSPACKAGEPATH", |
589 "EMACSLOCKDIR", | 609 "EMACSLOCKDIR", |
590 "INFOPATH" | 610 "INFOPATH" |
591 }; | 611 }; |
592 #if defined (HEAP_IN_DATA) && !defined(PDUMP) | 612 |
593 cache_system_info (); | |
594 #endif | |
595 for (i = 0; i < countof (env_vars); i++) | 613 for (i = 0; i < countof (env_vars); i++) |
596 { | 614 { |
597 if (!getenv (env_vars[i]) && | 615 if (!getenv (env_vars[i]) && |
598 (lpval = nt_get_resource (env_vars[i], &dwType)) != NULL) | 616 (lpval = nt_get_resource (env_vars[i], &dwType)) != NULL) |
599 { | 617 { |
1061 dir_is_fat = is_fat_volume (filename, NULL); | 1079 dir_is_fat = is_fat_volume (filename, NULL); |
1062 | 1080 |
1063 return dirp; | 1081 return dirp; |
1064 } | 1082 } |
1065 | 1083 |
1066 int | 1084 void |
1067 closedir (DIR *dirp) | 1085 closedir (DIR *dirp) |
1068 { | 1086 { |
1069 BOOL retval; | |
1070 | |
1071 /* If we have a find-handle open, close it. */ | 1087 /* If we have a find-handle open, close it. */ |
1072 if (dir_find_handle != INVALID_HANDLE_VALUE) | 1088 if (dir_find_handle != INVALID_HANDLE_VALUE) |
1073 { | 1089 { |
1074 retval = FindClose (dir_find_handle); | 1090 FindClose (dir_find_handle); |
1075 dir_find_handle = INVALID_HANDLE_VALUE; | 1091 dir_find_handle = INVALID_HANDLE_VALUE; |
1076 } | 1092 } |
1077 xfree (dirp); | 1093 xfree (dirp); |
1078 if (retval) | |
1079 return 0; | |
1080 else | |
1081 return -1; | |
1082 } | 1094 } |
1083 | 1095 |
1084 struct direct * | 1096 struct direct * |
1085 readdir (DIR *dirp) | 1097 readdir (DIR *dirp) |
1086 { | 1098 { |
1189 return rename (temp, newname); | 1201 return rename (temp, newname); |
1190 } | 1202 } |
1191 #endif /* 0 */ | 1203 #endif /* 0 */ |
1192 | 1204 |
1193 static FILETIME utc_base_ft; | 1205 static FILETIME utc_base_ft; |
1206 static long double utc_base; | |
1194 static int init = 0; | 1207 static int init = 0; |
1195 | |
1196 #if 0 | |
1197 | |
1198 static long double utc_base; | |
1199 | 1208 |
1200 time_t | 1209 time_t |
1201 convert_time (FILETIME ft) | 1210 convert_time (FILETIME ft) |
1202 { | 1211 { |
1203 long double ret; | 1212 long double ret; |
1226 | 1235 |
1227 ret = (long double) ft.dwHighDateTime * 4096 * 1024 * 1024 + ft.dwLowDateTime; | 1236 ret = (long double) ft.dwHighDateTime * 4096 * 1024 * 1024 + ft.dwLowDateTime; |
1228 ret -= utc_base; | 1237 ret -= utc_base; |
1229 return (time_t) (ret * 1e-7); | 1238 return (time_t) (ret * 1e-7); |
1230 } | 1239 } |
1231 #else | 1240 |
1232 | 1241 #if 0 |
1233 #if defined(MINGW) && CYGWIN_VERSION_DLL_MAJOR <= 21 | 1242 /* in case we ever have need of this */ |
1234 #define LowPart u.LowPart | 1243 void |
1235 #define HighPart u.HighPart | 1244 convert_from_time_t (time_t time, FILETIME * pft) |
1236 #endif | 1245 { |
1237 | 1246 long double tmp; |
1238 static LARGE_INTEGER utc_base_li; | |
1239 | |
1240 time_t | |
1241 convert_time (FILETIME uft) | |
1242 { | |
1243 time_t ret; | |
1244 #ifndef MAXLONGLONG | |
1245 SYSTEMTIME st; | |
1246 struct tm t; | |
1247 FILETIME ft; | |
1248 TIME_ZONE_INFORMATION tzi; | |
1249 DWORD tzid; | |
1250 #else | |
1251 LARGE_INTEGER lft; | |
1252 #endif | |
1253 | 1247 |
1254 if (!init) | 1248 if (!init) |
1255 { | 1249 { |
1256 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */ | 1250 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */ |
1257 SYSTEMTIME st; | 1251 SYSTEMTIME st; |
1263 st.wMinute = 0; | 1257 st.wMinute = 0; |
1264 st.wSecond = 0; | 1258 st.wSecond = 0; |
1265 st.wMilliseconds = 0; | 1259 st.wMilliseconds = 0; |
1266 | 1260 |
1267 SystemTimeToFileTime (&st, &utc_base_ft); | 1261 SystemTimeToFileTime (&st, &utc_base_ft); |
1268 | |
1269 utc_base_li.LowPart = utc_base_ft.dwLowDateTime; | |
1270 utc_base_li.HighPart = utc_base_ft.dwHighDateTime; | |
1271 | |
1272 init = 1; | |
1273 } | |
1274 | |
1275 #ifdef MAXLONGLONG | |
1276 | |
1277 /* On a compiler that supports long integers, do it the easy way */ | |
1278 lft.LowPart = uft.dwLowDateTime; | |
1279 lft.HighPart = uft.dwHighDateTime; | |
1280 ret = (time_t) ((lft.QuadPart - utc_base_li.QuadPart) / 10000000); | |
1281 | |
1282 #else | |
1283 | |
1284 /* Do it the hard way using mktime. */ | |
1285 FileTimeToLocalFileTime(&uft, &ft); | |
1286 FileTimeToSystemTime (&ft, &st); | |
1287 tzid = GetTimeZoneInformation (&tzi); | |
1288 t.tm_year = st.wYear - 1900; | |
1289 t.tm_mon = st.wMonth - 1; | |
1290 t.tm_mday = st.wDay; | |
1291 t.tm_hour = st.wHour; | |
1292 t.tm_min = st.wMinute; | |
1293 t.tm_sec = st.wSecond; | |
1294 t.tm_isdst = (tzid == TIME_ZONE_ID_DAYLIGHT); | |
1295 /* st.wMilliseconds not applicable */ | |
1296 ret = mktime(&t); | |
1297 if (ret == -1) | |
1298 { | |
1299 ret = 0; | |
1300 } | |
1301 | |
1302 #endif | |
1303 | |
1304 return ret; | |
1305 } | |
1306 #endif | |
1307 #if defined(MINGW) && CYGWIN_VERSION_DLL_MAJOR <= 21 | |
1308 #undef LowPart | |
1309 #undef HighPart | |
1310 #endif | |
1311 | |
1312 #if 0 | |
1313 /* in case we ever have need of this */ | |
1314 void | |
1315 convert_from_time_t (time_t time, FILETIME * pft) | |
1316 { | |
1317 long double tmp; | |
1318 | |
1319 if (!init) | |
1320 { | |
1321 /* Determine the delta between 1-Jan-1601 and 1-Jan-1970. */ | |
1322 SYSTEMTIME st; | |
1323 | |
1324 st.wYear = 1970; | |
1325 st.wMonth = 1; | |
1326 st.wDay = 1; | |
1327 st.wHour = 0; | |
1328 st.wMinute = 0; | |
1329 st.wSecond = 0; | |
1330 st.wMilliseconds = 0; | |
1331 | |
1332 SystemTimeToFileTime (&st, &utc_base_ft); | |
1333 utc_base = (long double) utc_base_ft.dwHighDateTime | 1262 utc_base = (long double) utc_base_ft.dwHighDateTime |
1334 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime; | 1263 * 4096 * 1024 * 1024 + utc_base_ft.dwLowDateTime; |
1335 init = 1; | 1264 init = 1; |
1336 } | 1265 } |
1337 | 1266 |
1383 return hashval (p); | 1312 return hashval (p); |
1384 } | 1313 } |
1385 | 1314 |
1386 #endif | 1315 #endif |
1387 | 1316 |
1388 /* #### aichner@ecf.teradyne.com reported that with the library | |
1389 provided stat/fstat, (file-exist "d:\\tmp\\") =>> nil, | |
1390 (file-exist "d:\\tmp") =>> t, when d:\tmp exists. Whenever | |
1391 we opt to use non-encapsulated stat(), this should serve as | |
1392 a compatibility test. --kkm */ | |
1393 | |
1394 /* Since stat is encapsulated on Windows NT, we need to encapsulate | |
1395 the equally broken fstat as well. */ | |
1396 int | |
1397 mswindows_fstat (int handle, struct stat *buffer) | |
1398 { | |
1399 int ret; | |
1400 BY_HANDLE_FILE_INFORMATION lpFileInfo; | |
1401 /* Initialize values */ | |
1402 buffer->st_mode = 0; | |
1403 buffer->st_size = 0; | |
1404 buffer->st_dev = 0; | |
1405 buffer->st_rdev = 0; | |
1406 buffer->st_atime = 0; | |
1407 buffer->st_ctime = 0; | |
1408 buffer->st_mtime = 0; | |
1409 buffer->st_nlink = 0; | |
1410 ret = GetFileInformationByHandle((HANDLE) _get_osfhandle(handle), &lpFileInfo); | |
1411 if (!ret) | |
1412 { | |
1413 return -1; | |
1414 } | |
1415 else | |
1416 { | |
1417 buffer->st_mtime = convert_time (lpFileInfo.ftLastWriteTime); | |
1418 buffer->st_atime = convert_time (lpFileInfo.ftLastAccessTime); | |
1419 if (buffer->st_atime == 0) buffer->st_atime = buffer->st_mtime; | |
1420 buffer->st_ctime = convert_time (lpFileInfo.ftCreationTime); | |
1421 if (buffer->st_ctime == 0) buffer->st_ctime = buffer->st_mtime; | |
1422 buffer->st_size = lpFileInfo.nFileSizeLow; | |
1423 buffer->st_nlink = (short) lpFileInfo.nNumberOfLinks; | |
1424 return 0; | |
1425 } | |
1426 } | |
1427 | |
1428 /* MSVC stat function can't cope with UNC names and has other bugs, so | 1317 /* MSVC stat function can't cope with UNC names and has other bugs, so |
1429 replace it with our own. This also allows us to calculate consistent | 1318 replace it with our own. This also allows us to calculate consistent |
1430 inode values without hacks in the main Emacs code. */ | 1319 inode values without hacks in the main Emacs code. */ |
1431 int | 1320 int |
1432 mswindows_stat (const char * path, struct stat * buf) | 1321 stat (const char * path, struct stat * buf) |
1433 { | 1322 { |
1434 char * name; | 1323 char * name; |
1435 WIN32_FIND_DATA wfd; | 1324 WIN32_FIND_DATA wfd; |
1436 HANDLE fh; | 1325 HANDLE fh; |
1437 DWORD fake_inode; | 1326 DWORD fake_inode; |
1457 directory of a drive or UNC volume in which case ensure there | 1346 directory of a drive or UNC volume in which case ensure there |
1458 is a trailing separator. */ | 1347 is a trailing separator. */ |
1459 len = strlen (name); | 1348 len = strlen (name); |
1460 rootdir = (path >= name + len - 1 | 1349 rootdir = (path >= name + len - 1 |
1461 && (IS_DIRECTORY_SEP (*path) || *path == 0)); | 1350 && (IS_DIRECTORY_SEP (*path) || *path == 0)); |
1462 name = strcpy ((char *)alloca (len + 2), name); | 1351 name = strcpy (alloca (len + 2), name); |
1463 | 1352 |
1464 if (rootdir) | 1353 if (rootdir) |
1465 { | 1354 { |
1466 if (!IS_DIRECTORY_SEP (name[len-1])) | 1355 if (!IS_DIRECTORY_SEP (name[len-1])) |
1467 strcat (name, "\\"); | 1356 strcat (name, "\\"); |
1575 | 1464 |
1576 /* #### MSVC defines _ino_t to be short; other libc's might not. */ | 1465 /* #### MSVC defines _ino_t to be short; other libc's might not. */ |
1577 buf->st_ino = (unsigned short) (fake_inode ^ (fake_inode >> 16)); | 1466 buf->st_ino = (unsigned short) (fake_inode ^ (fake_inode >> 16)); |
1578 | 1467 |
1579 /* consider files to belong to current user */ | 1468 /* consider files to belong to current user */ |
1580 buf->st_uid = buf->st_gid = nt_fake_unix_uid; | 1469 buf->st_uid = the_passwd.pw_uid; |
1470 buf->st_gid = the_passwd.pw_gid; | |
1581 | 1471 |
1582 /* volume_info is set indirectly by map_win32_filename */ | 1472 /* volume_info is set indirectly by map_win32_filename */ |
1583 buf->st_dev = volume_info.serialnum; | 1473 buf->st_dev = volume_info.serialnum; |
1584 buf->st_rdev = volume_info.serialnum; | 1474 buf->st_rdev = volume_info.serialnum; |
1475 | |
1585 | 1476 |
1586 buf->st_size = wfd.nFileSizeLow; | 1477 buf->st_size = wfd.nFileSizeLow; |
1587 | 1478 |
1588 /* Convert timestamps to Unix format. */ | 1479 /* Convert timestamps to Unix format. */ |
1589 buf->st_mtime = convert_time (wfd.ftLastWriteTime); | 1480 buf->st_mtime = convert_time (wfd.ftLastWriteTime); |
1653 term_ntproc (int unused) | 1544 term_ntproc (int unused) |
1654 { | 1545 { |
1655 } | 1546 } |
1656 | 1547 |
1657 void | 1548 void |
1658 init_ntproc (void) | 1549 init_ntproc () |
1659 { | 1550 { |
1660 /* Initial preparation for subprocess support: replace our standard | 1551 /* Initial preparation for subprocess support: replace our standard |
1661 handles with non-inheritable versions. */ | 1552 handles with non-inheritable versions. */ |
1662 { | 1553 { |
1663 HANDLE parent; | 1554 HANDLE parent; |
1786 unsigned signal_block_mask = 0; | 1677 unsigned signal_block_mask = 0; |
1787 | 1678 |
1788 /* Signal pending mask: bit set to 1 means sig is pending */ | 1679 /* Signal pending mask: bit set to 1 means sig is pending */ |
1789 unsigned signal_pending_mask = 0; | 1680 unsigned signal_pending_mask = 0; |
1790 | 1681 |
1791 mswindows_sighandler mswindows_sigset (int nsig, mswindows_sighandler handler) | 1682 msw_sighandler msw_sigset (int nsig, msw_sighandler handler) |
1792 { | 1683 { |
1793 /* We delegate some signals to the system function */ | 1684 /* We delegate some signals to the system function */ |
1794 if (nsig == SIGFPE || nsig == SIGABRT || nsig == SIGINT) | 1685 if (nsig == SIGFPE || nsig == SIGABRT || nsig == SIGINT) |
1795 return signal (nsig, handler); | 1686 return signal (nsig, handler); |
1796 | 1687 |
1800 return NULL; | 1691 return NULL; |
1801 } | 1692 } |
1802 | 1693 |
1803 /* Store handler ptr */ | 1694 /* Store handler ptr */ |
1804 { | 1695 { |
1805 mswindows_sighandler old_handler = signal_handlers[nsig]; | 1696 msw_sighandler old_handler = signal_handlers[nsig]; |
1806 signal_handlers[nsig] = handler; | 1697 signal_handlers[nsig] = handler; |
1807 return old_handler; | 1698 return old_handler; |
1808 } | 1699 } |
1809 } | 1700 } |
1810 | 1701 |
1811 int mswindows_sighold (int nsig) | 1702 int msw_sighold (int nsig) |
1812 { | 1703 { |
1813 if (nsig < 0 || nsig > SIG_MAX) | 1704 if (nsig < 0 || nsig > SIG_MAX) |
1814 return errno = EINVAL; | 1705 return errno = EINVAL; |
1815 | 1706 |
1816 signal_block_mask |= sigmask(nsig); | 1707 signal_block_mask |= sigmask(nsig); |
1817 return 0; | 1708 return 0; |
1818 } | 1709 } |
1819 | 1710 |
1820 int mswindows_sigrelse (int nsig) | 1711 int msw_sigrelse (int nsig) |
1821 { | 1712 { |
1822 if (nsig < 0 || nsig > SIG_MAX) | 1713 if (nsig < 0 || nsig > SIG_MAX) |
1823 return errno = EINVAL; | 1714 return errno = EINVAL; |
1824 | 1715 |
1825 signal_block_mask &= ~sigmask(nsig); | 1716 signal_block_mask &= ~sigmask(nsig); |
1826 | 1717 |
1827 if (signal_pending_mask & sigmask(nsig)) | 1718 if (signal_pending_mask & sigmask(nsig)) |
1828 mswindows_raise (nsig); | 1719 msw_raise (nsig); |
1829 | 1720 |
1830 return 0; | 1721 return 0; |
1831 } | 1722 } |
1832 | 1723 |
1833 int mswindows_sigpause (int nsig) | 1724 int msw_sigpause (int nsig) |
1834 { | 1725 { |
1835 /* This is currently not called, because the only | 1726 /* This is currently not called, because the only |
1836 call to sigpause inside XEmacs is with SIGCHLD | 1727 call to sigpause inside XEmacs is with SIGCHLD |
1837 parameter. Just in case, we put an assert here, | 1728 parameter. Just in case, we put an assert here, |
1838 so anyone who will add a call to sigpause will | 1729 so anyone who will add a call to sigpause will |
1839 be surprised (or surprise someone else...) */ | 1730 be surprised (or surprise someone else...) */ |
1840 assert (0); | 1731 assert (0); |
1841 return 0; | 1732 return 0; |
1842 } | 1733 } |
1843 | 1734 |
1844 int mswindows_raise (int nsig) | 1735 int msw_raise (int nsig) |
1845 { | 1736 { |
1846 /* We delegate some raises to the system routine */ | 1737 /* We delegate some raises to the system routine */ |
1847 if (nsig == SIGFPE || nsig == SIGABRT || nsig == SIGINT) | 1738 if (nsig == SIGFPE || nsig == SIGABRT || nsig == SIGINT) |
1848 return raise (nsig); | 1739 return raise (nsig); |
1849 | 1740 |
1905 | 1796 |
1906 static void CALLBACK timer_proc (UINT uID, UINT uMsg, DWORD dwUser, | 1797 static void CALLBACK timer_proc (UINT uID, UINT uMsg, DWORD dwUser, |
1907 DWORD dw1, DWORD dw2) | 1798 DWORD dw1, DWORD dw2) |
1908 { | 1799 { |
1909 /* Just raise a signal indicated by dwUser parameter */ | 1800 /* Just raise a signal indicated by dwUser parameter */ |
1910 mswindows_raise (dwUser); | 1801 msw_raise (dwUser); |
1911 } | 1802 } |
1912 | 1803 |
1913 /* Divide time in ms specified by IT by DENOM. Return 1 ms | 1804 /* Divide time in ms specified by IT by DENOM. Return 1 ms |
1914 if division results in zero */ | 1805 if division results in zero */ |
1915 static UINT period (const struct itimerval* it, UINT denom) | 1806 static UINT period (const struct itimerval* it, UINT denom) |
1988 return setitimer_helper (itnew, itold, &it_prof, &tid_prof, SIGPROF); | 1879 return setitimer_helper (itnew, itold, &it_prof, &tid_prof, SIGPROF); |
1989 else | 1880 else |
1990 return errno = EINVAL; | 1881 return errno = EINVAL; |
1991 } | 1882 } |
1992 | 1883 |
1993 | |
1994 /*--------------------------------------------------------------------*/ | |
1995 /* Memory-mapped files */ | |
1996 /*--------------------------------------------------------------------*/ | |
1997 | |
1998 int | 1884 int |
1999 open_input_file (file_data *p_file, const char *filename) | 1885 open_input_file (file_data *p_file, CONST char *filename) |
2000 { | 1886 { |
2001 /* Synched with FSF 20.6. We fixed some warnings. */ | |
2002 HANDLE file; | 1887 HANDLE file; |
2003 HANDLE file_mapping; | 1888 HANDLE file_mapping; |
2004 void *file_base; | 1889 void *file_base; |
2005 DWORD size, upper_size; | 1890 DWORD size, upper_size; |
2006 | 1891 |
2017 | 1902 |
2018 file_base = MapViewOfFile (file_mapping, FILE_MAP_READ, 0, 0, size); | 1903 file_base = MapViewOfFile (file_mapping, FILE_MAP_READ, 0, 0, size); |
2019 if (file_base == 0) | 1904 if (file_base == 0) |
2020 return FALSE; | 1905 return FALSE; |
2021 | 1906 |
2022 p_file->name = (char *)filename; | 1907 p_file->name = (char*)filename; |
2023 p_file->size = size; | 1908 p_file->size = size; |
2024 p_file->file = file; | 1909 p_file->file = file; |
2025 p_file->file_mapping = file_mapping; | 1910 p_file->file_mapping = file_mapping; |
2026 p_file->file_base = (char *)file_base; | 1911 p_file->file_base = file_base; |
2027 | 1912 |
2028 return TRUE; | 1913 return TRUE; |
2029 } | |
2030 | |
2031 int | |
2032 open_output_file (file_data *p_file, const char *filename, unsigned long size) | |
2033 { | |
2034 /* Synched with FSF 20.6. We fixed some warnings. */ | |
2035 HANDLE file; | |
2036 HANDLE file_mapping; | |
2037 void *file_base; | |
2038 | |
2039 file = CreateFile (filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, | |
2040 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); | |
2041 if (file == INVALID_HANDLE_VALUE) | |
2042 return FALSE; | |
2043 | |
2044 file_mapping = CreateFileMapping (file, NULL, PAGE_READWRITE, | |
2045 0, size, NULL); | |
2046 if (!file_mapping) | |
2047 return FALSE; | |
2048 | |
2049 file_base = MapViewOfFile (file_mapping, FILE_MAP_WRITE, 0, 0, size); | |
2050 if (file_base == NULL) | |
2051 return FALSE; | |
2052 | |
2053 p_file->name = filename; | |
2054 p_file->size = size; | |
2055 p_file->file = file; | |
2056 p_file->file_mapping = file_mapping; | |
2057 p_file->file_base = (char*) file_base; | |
2058 | |
2059 return TRUE; | |
2060 } | |
2061 | |
2062 #if 1 /* !defined(MINGW) */ | |
2063 /* Return pointer to section header for section containing the given | |
2064 relative virtual address. */ | |
2065 static IMAGE_SECTION_HEADER * | |
2066 rva_to_section (DWORD rva, IMAGE_NT_HEADERS * nt_header) | |
2067 { | |
2068 /* Synched with FSF 20.6. We added MINGW stuff. */ | |
2069 PIMAGE_SECTION_HEADER section; | |
2070 int i; | |
2071 | |
2072 section = IMAGE_FIRST_SECTION (nt_header); | |
2073 | |
2074 for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++) | |
2075 { | |
2076 /* Some linkers (eg. the NT SDK linker I believe) swapped the | |
2077 meaning of these two values - or rather, they ignored | |
2078 VirtualSize entirely and always set it to zero. This affects | |
2079 some very old exes (eg. gzip dated Dec 1993). Since | |
2080 mswindows_executable_type relies on this function to work reliably, | |
2081 we need to cope with this. */ | |
2082 DWORD real_size = max (section->SizeOfRawData, | |
2083 section->Misc.VirtualSize); | |
2084 if (rva >= section->VirtualAddress | |
2085 && rva < section->VirtualAddress + real_size) | |
2086 return section; | |
2087 section++; | |
2088 } | |
2089 return NULL; | |
2090 } | |
2091 #endif | |
2092 | |
2093 void | |
2094 mswindows_executable_type (const char * filename, int * is_dos_app, | |
2095 int * is_cygnus_app) | |
2096 { | |
2097 /* Synched with FSF 20.6. We added MINGW stuff and casts. */ | |
2098 file_data executable; | |
2099 char * p; | |
2100 | |
2101 /* Default values in case we can't tell for sure. */ | |
2102 *is_dos_app = FALSE; | |
2103 *is_cygnus_app = FALSE; | |
2104 | |
2105 if (!open_input_file (&executable, filename)) | |
2106 return; | |
2107 | |
2108 p = strrchr (filename, '.'); | |
2109 | |
2110 /* We can only identify DOS .com programs from the extension. */ | |
2111 if (p && stricmp (p, ".com") == 0) | |
2112 *is_dos_app = TRUE; | |
2113 else if (p && (stricmp (p, ".bat") == 0 || | |
2114 stricmp (p, ".cmd") == 0)) | |
2115 { | |
2116 /* A DOS shell script - it appears that CreateProcess is happy to | |
2117 accept this (somewhat surprisingly); presumably it looks at | |
2118 COMSPEC to determine what executable to actually invoke. | |
2119 Therefore, we have to do the same here as well. */ | |
2120 /* Actually, I think it uses the program association for that | |
2121 extension, which is defined in the registry. */ | |
2122 p = egetenv ("COMSPEC"); | |
2123 if (p) | |
2124 mswindows_executable_type (p, is_dos_app, is_cygnus_app); | |
2125 } | |
2126 else | |
2127 { | |
2128 /* Look for DOS .exe signature - if found, we must also check that | |
2129 it isn't really a 16- or 32-bit Windows exe, since both formats | |
2130 start with a DOS program stub. Note that 16-bit Windows | |
2131 executables use the OS/2 1.x format. */ | |
2132 | |
2133 #if 0 /* defined( MINGW ) */ | |
2134 /* mingw32 doesn't have enough headers to detect cygwin | |
2135 apps, just do what we can. */ | |
2136 FILHDR * exe_header; | |
2137 | |
2138 exe_header = (FILHDR*) executable.file_base; | |
2139 if (exe_header->e_magic != DOSMAGIC) | |
2140 goto unwind; | |
2141 | |
2142 if ((char*) exe_header->e_lfanew > (char*) executable.size) | |
2143 { | |
2144 /* Some dos headers (pkunzip) have bogus e_lfanew fields. */ | |
2145 *is_dos_app = TRUE; | |
2146 } | |
2147 else if (exe_header->nt_signature != NT_SIGNATURE) | |
2148 { | |
2149 *is_dos_app = TRUE; | |
2150 } | |
2151 #else | |
2152 IMAGE_DOS_HEADER * dos_header; | |
2153 IMAGE_NT_HEADERS * nt_header; | |
2154 | |
2155 dos_header = (PIMAGE_DOS_HEADER) executable.file_base; | |
2156 if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) | |
2157 goto unwind; | |
2158 | |
2159 nt_header = (PIMAGE_NT_HEADERS) ((char*) dos_header + dos_header->e_lfanew); | |
2160 | |
2161 if ((char*) nt_header > (char*) dos_header + executable.size) | |
2162 { | |
2163 /* Some dos headers (pkunzip) have bogus e_lfanew fields. */ | |
2164 *is_dos_app = TRUE; | |
2165 } | |
2166 else if (nt_header->Signature != IMAGE_NT_SIGNATURE && | |
2167 LOWORD (nt_header->Signature) != IMAGE_OS2_SIGNATURE) | |
2168 { | |
2169 *is_dos_app = TRUE; | |
2170 } | |
2171 else if (nt_header->Signature == IMAGE_NT_SIGNATURE) | |
2172 { | |
2173 /* Look for cygwin.dll in DLL import list. */ | |
2174 IMAGE_DATA_DIRECTORY import_dir = | |
2175 nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; | |
2176 IMAGE_IMPORT_DESCRIPTOR * imports; | |
2177 IMAGE_SECTION_HEADER * section; | |
2178 | |
2179 section = rva_to_section (import_dir.VirtualAddress, nt_header); | |
2180 imports = (IMAGE_IMPORT_DESCRIPTOR *) RVA_TO_PTR (import_dir.VirtualAddress, | |
2181 section, executable); | |
2182 | |
2183 for ( ; imports->Name; imports++) | |
2184 { | |
2185 char *dllname = (char*) RVA_TO_PTR (imports->Name, section, executable); | |
2186 | |
2187 /* The exact name of the cygwin dll has changed with | |
2188 various releases, but hopefully this will be reasonably | |
2189 future proof. */ | |
2190 if (strncmp (dllname, "cygwin", 6) == 0) | |
2191 { | |
2192 *is_cygnus_app = TRUE; | |
2193 break; | |
2194 } | |
2195 } | |
2196 } | |
2197 #endif | |
2198 } | |
2199 | |
2200 unwind: | |
2201 close_file_data (&executable); | |
2202 } | 1914 } |
2203 | 1915 |
2204 /* Close the system structures associated with the given file. */ | 1916 /* Close the system structures associated with the given file. */ |
2205 void | 1917 void |
2206 close_file_data (file_data *p_file) | 1918 close_file_data (file_data *p_file) |
2208 UnmapViewOfFile (p_file->file_base); | 1920 UnmapViewOfFile (p_file->file_base); |
2209 CloseHandle (p_file->file_mapping); | 1921 CloseHandle (p_file->file_mapping); |
2210 CloseHandle (p_file->file); | 1922 CloseHandle (p_file->file); |
2211 } | 1923 } |
2212 | 1924 |
2213 void | |
2214 vars_of_nt (void) | |
2215 { | |
2216 DEFVAR_INT ("nt-fake-unix-uid", &nt_fake_unix_uid /* | |
2217 *Set uid returned by `user-uid' and `user-real-uid'. | |
2218 Under NT and 9x, there is no uids, and even no almighty user called root. | |
2219 By setting this variable, you can have any uid of choice. Default is 0. | |
2220 Changes to this variable take effect immediately. | |
2221 */ ); | |
2222 nt_fake_unix_uid = 0; | |
2223 } | |
2224 | |
2225 /* end of nt.c */ | 1925 /* end of nt.c */ |