]>
Commit | Line | Data |
---|---|---|
1fd5e000 CF |
1 | /* cygcheck.cc |
2 | ||
c662f402 | 3 | Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. |
1fd5e000 CF |
4 | |
5 | This file is part of Cygwin. | |
6 | ||
7 | This software is a copyrighted work licensed under the terms of the | |
8 | Cygwin license. Please consult the file "CYGWIN_LICENSE" for | |
9 | details. */ | |
10 | ||
11 | #include <stdio.h> | |
12 | #include <stdlib.h> | |
13 | #include <string.h> | |
468b26c5 | 14 | #include <sys/time.h> |
4ddb62e7 | 15 | #include <ctype.h> |
dbc49afd | 16 | #include <io.h> |
1fd5e000 | 17 | #include <windows.h> |
dbc49afd | 18 | #include "path.h" |
bd79b736 | 19 | #include <getopt.h> |
012858ec | 20 | #include "cygwin/include/sys/cygwin.h" |
4239e5ec | 21 | #include "cygwin/include/mntent.h" |
1fd5e000 | 22 | |
902edd45 CF |
23 | #define alloca __builtin_alloca |
24 | ||
1fd5e000 CF |
25 | int verbose = 0; |
26 | int registry = 0; | |
27 | int sysinfo = 0; | |
28 | int givehelp = 0; | |
41a0695b | 29 | int keycheck = 0; |
d0d51791 | 30 | int check_setup = 0; |
59a76035 | 31 | int dump_only = 0; |
200f243c CV |
32 | int find_package = 0; |
33 | int list_package = 0; | |
1fd5e000 CF |
34 | |
35 | #ifdef __GNUC__ | |
36 | typedef long long longlong; | |
37 | #else | |
38 | typedef __int64 longlong; | |
39 | #endif | |
40 | ||
71f90de8 | 41 | void dump_setup (int, char **, bool); |
200f243c CV |
42 | void package_find (int, char **); |
43 | void package_list (int, char **); | |
d0d51791 | 44 | |
67763c0c CF |
45 | static const char version[] = "$Revision$"; |
46 | ||
47 | static const char *known_env_vars[] = { | |
1fd5e000 CF |
48 | "c_include_path", |
49 | "compiler_path", | |
50 | "cxx_include_path", | |
51 | "cygwin", | |
52 | "cygwin32", | |
53 | "dejagnu", | |
54 | "expect", | |
55 | "gcc_default_options", | |
56 | "gcc_exec_prefix", | |
57 | "home", | |
58 | "ld_library_path", | |
59 | "library_path", | |
60 | "login", | |
61 | "lpath", | |
62 | "make_mode", | |
63 | "makeflags", | |
64 | "path", | |
65 | "pwd", | |
66 | "strace", | |
67 | "tcl_library", | |
68 | "user", | |
69 | 0 | |
70 | }; | |
71 | ||
eedc36cb CF |
72 | struct |
73 | { | |
1fd5e000 CF |
74 | const char *name; |
75 | int missing_is_good; | |
eedc36cb | 76 | } |
b56dedef | 77 | static common_apps[] = { |
4a9cbef0 | 78 | {"awk", 0}, |
ce475802 CF |
79 | {"bash", 0}, |
80 | {"cat", 0}, | |
4a9cbef0 | 81 | {"cp", 0}, |
ce475802 CF |
82 | {"cpp", 1}, |
83 | {"find", 0}, | |
84 | {"gcc", 0}, | |
85 | {"gdb", 0}, | |
4a9cbef0 | 86 | {"grep", 0}, |
ce475802 CF |
87 | {"ld", 0}, |
88 | {"ls", 0}, | |
89 | {"make", 0}, | |
4a9cbef0 CF |
90 | {"mv", 0}, |
91 | {"rm", 0}, | |
92 | {"sed", 0}, | |
ce475802 | 93 | {"sh", 0}, |
4a9cbef0 | 94 | {"tar", 0}, |
ce475802 | 95 | {0, 0} |
1fd5e000 CF |
96 | }; |
97 | ||
67763c0c CF |
98 | static int num_paths = 0, max_paths = 0; |
99 | static char **paths = 0; | |
1fd5e000 | 100 | |
64069abe CF |
101 | /* |
102 | * keyeprint() is used to report failure modes | |
103 | */ | |
67763c0c | 104 | static int |
64069abe CF |
105 | keyeprint (const char *name) |
106 | { | |
107 | fprintf (stderr, "cygcheck: %s failed: %lu\n", name, GetLastError ()); | |
108 | return 1; | |
109 | } | |
110 | ||
67763c0c | 111 | static void |
1fd5e000 CF |
112 | add_path (char *s, int maxlen) |
113 | { | |
114 | if (num_paths >= max_paths) | |
115 | { | |
116 | max_paths += 10; | |
117 | if (paths) | |
118 | paths = (char **) realloc (paths, max_paths * sizeof (char *)); | |
119 | else | |
120 | paths = (char **) malloc (max_paths * sizeof (char *)); | |
121 | } | |
122 | paths[num_paths] = (char *) malloc (maxlen + 1); | |
64069abe CF |
123 | if (paths[num_paths] == NULL) |
124 | { | |
125 | keyeprint ("add_path: malloc()"); | |
126 | return; | |
127 | } | |
1fd5e000 CF |
128 | memcpy (paths[num_paths], s, maxlen); |
129 | paths[num_paths][maxlen] = 0; | |
130 | char *e = paths[num_paths] + strlen (paths[num_paths]); | |
131 | if (e[-1] == '\\' && e[-2] != ':') | |
132 | *--e = 0; | |
133 | for (int i = 1; i < num_paths; i++) | |
134 | if (strcasecmp (paths[num_paths], paths[i]) == 0) | |
76ad4d0a CF |
135 | { |
136 | free (paths[num_paths]); | |
137 | return; | |
138 | } | |
1fd5e000 CF |
139 | num_paths++; |
140 | } | |
141 | ||
67763c0c | 142 | static void |
1fd5e000 CF |
143 | init_paths () |
144 | { | |
145 | char tmp[4000], *sl; | |
eedc36cb CF |
146 | add_path ((char *) ".", 1); /* to be replaced later */ |
147 | add_path ((char *) ".", 1); /* the current directory */ | |
64069abe CF |
148 | if (GetSystemDirectory (tmp, 4000)) |
149 | add_path (tmp, strlen (tmp)); | |
150 | else | |
151 | keyeprint ("init_paths: GetSystemDirectory()"); | |
1fd5e000 CF |
152 | sl = strrchr (tmp, '\\'); |
153 | if (sl) | |
154 | { | |
155 | strcpy (sl, "\\SYSTEM"); | |
156 | add_path (tmp, strlen (tmp)); | |
157 | } | |
158 | GetWindowsDirectory (tmp, 4000); | |
159 | add_path (tmp, strlen (tmp)); | |
160 | ||
2fac517d CF |
161 | char *wpath = getenv ("PATH"); |
162 | if (wpath) | |
1fd5e000 | 163 | { |
2fac517d | 164 | char *b, *e; |
1fd5e000 CF |
165 | b = wpath; |
166 | while (1) | |
167 | { | |
2fac517d | 168 | for (e = b; *e && *e != ';'; e++); |
1fd5e000 CF |
169 | add_path (b, e - b); |
170 | if (!*e) | |
171 | break; | |
172 | b = e + 1; | |
173 | } | |
174 | } | |
175 | else | |
176 | printf ("WARNING: PATH is not set at all!\n"); | |
177 | } | |
178 | ||
67763c0c | 179 | static char * |
1fd5e000 CF |
180 | find_on_path (char *file, char *default_extension, |
181 | int showall = 0, int search_sysdirs = 0) | |
182 | { | |
183 | static char rv[4000]; | |
184 | char tmp[4000], *ptr = rv; | |
185 | ||
dbc49afd | 186 | if (!file) |
64069abe CF |
187 | { |
188 | keyeprint ("find_on_path: NULL pointer for file"); | |
189 | return 0; | |
190 | } | |
191 | ||
192 | if (default_extension == NULL) | |
193 | { | |
194 | keyeprint ("find_on_path: NULL pointer for default_extension"); | |
195 | return 0; | |
196 | } | |
197 | ||
1fd5e000 | 198 | if (strchr (file, ':') || strchr (file, '\\') || strchr (file, '/')) |
dbc49afd | 199 | return cygpath (file, NULL); |
1fd5e000 CF |
200 | |
201 | if (strchr (file, '.')) | |
eedc36cb | 202 | default_extension = (char *) ""; |
1fd5e000 CF |
203 | |
204 | for (int i = 0; i < num_paths; i++) | |
205 | { | |
206 | if (!search_sysdirs && (i == 0 || i == 2 || i == 3)) | |
207 | continue; | |
208 | if (i == 0 || !search_sysdirs || strcasecmp (paths[i], paths[0])) | |
209 | { | |
210 | sprintf (ptr, "%s\\%s%s", paths[i], file, default_extension); | |
64069abe | 211 | if (GetFileAttributes (ptr) != (DWORD) - 1) |
1fd5e000 CF |
212 | { |
213 | if (showall) | |
214 | printf ("Found: %s\n", ptr); | |
215 | if (ptr == tmp && verbose) | |
216 | printf ("Warning: %s hides %s\n", rv, ptr); | |
217 | ptr = tmp; | |
218 | } | |
219 | } | |
220 | } | |
221 | ||
222 | if (ptr == tmp) | |
223 | return rv; | |
224 | ||
225 | return 0; | |
226 | } | |
227 | ||
228 | #define DID_NEW 1 | |
229 | #define DID_ACTIVE 2 | |
230 | #define DID_INACTIVE 3 | |
231 | ||
232 | struct Did | |
233 | { | |
234 | Did *next; | |
235 | char *file; | |
236 | int state; | |
237 | }; | |
67763c0c | 238 | static Did *did = 0; |
1fd5e000 | 239 | |
67763c0c | 240 | static Did * |
1fd5e000 CF |
241 | already_did (char *file) |
242 | { | |
243 | Did *d; | |
244 | for (d = did; d; d = d->next) | |
245 | if (strcasecmp (d->file, file) == 0) | |
246 | return d; | |
e47cd9cd | 247 | d = (Did *) malloc (sizeof (Did)); |
1fd5e000 CF |
248 | d->file = strdup (file); |
249 | d->next = did; | |
250 | d->state = DID_NEW; | |
251 | did = d; | |
252 | return d; | |
253 | } | |
254 | ||
67763c0c | 255 | static int |
1fd5e000 CF |
256 | get_word (HANDLE fh, int offset) |
257 | { | |
258 | short rv; | |
259 | unsigned r; | |
64069abe CF |
260 | |
261 | if (SetFilePointer (fh, offset, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER | |
262 | && GetLastError () != NO_ERROR) | |
263 | keyeprint ("get_word: SetFilePointer()"); | |
264 | ||
b56dedef | 265 | if (!ReadFile (fh, &rv, 2, (DWORD *) &r, 0)) |
64069abe CF |
266 | keyeprint ("get_word: Readfile()"); |
267 | ||
1fd5e000 CF |
268 | return rv; |
269 | } | |
270 | ||
67763c0c | 271 | static int |
1fd5e000 CF |
272 | get_dword (HANDLE fh, int offset) |
273 | { | |
274 | int rv; | |
275 | unsigned r; | |
64069abe CF |
276 | |
277 | if (SetFilePointer (fh, offset, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER | |
278 | && GetLastError () != NO_ERROR) | |
279 | keyeprint ("get_word: SetFilePointer()"); | |
280 | ||
b56dedef | 281 | if (!ReadFile (fh, &rv, 4, (DWORD *) &r, 0)) |
64069abe CF |
282 | keyeprint ("get_dword: Readfile()"); |
283 | ||
1fd5e000 CF |
284 | return rv; |
285 | } | |
286 | ||
287 | struct Section | |
288 | { | |
289 | char name[8]; | |
290 | int virtual_size; | |
291 | int virtual_address; | |
292 | int size_of_raw_data; | |
293 | int pointer_to_raw_data; | |
294 | }; | |
295 | ||
67763c0c | 296 | static int |
1fd5e000 CF |
297 | rva_to_offset (int rva, char *sections, int nsections, int *sz) |
298 | { | |
299 | int i; | |
64069abe CF |
300 | |
301 | if (sections == NULL) | |
302 | { | |
303 | keyeprint ("rva_to_offset: NULL passed for sections"); | |
304 | return 0; | |
305 | } | |
306 | ||
1fd5e000 CF |
307 | for (i = 0; i < nsections; i++) |
308 | { | |
309 | Section *s = (Section *) (sections + i * 40); | |
310 | #if 0 | |
311 | printf ("%08x < %08x < %08x ? %08x\n", | |
312 | s->virtual_address, rva, | |
313 | s->virtual_address + s->virtual_size, s->pointer_to_raw_data); | |
314 | #endif | |
315 | if (rva >= s->virtual_address | |
316 | && rva < s->virtual_address + s->virtual_size) | |
317 | { | |
318 | if (sz) | |
319 | *sz = s->virtual_address + s->virtual_size - rva; | |
320 | return rva - s->virtual_address + s->pointer_to_raw_data; | |
321 | } | |
322 | } | |
323 | return 0; /* punt */ | |
324 | } | |
325 | ||
326 | struct ExpDirectory | |
327 | { | |
328 | int flags; | |
329 | int timestamp; | |
330 | short major_ver; | |
331 | short minor_ver; | |
332 | int name_rva; | |
333 | }; | |
334 | ||
335 | struct ImpDirectory | |
eedc36cb CF |
336 | { |
337 | unsigned characteristics; | |
338 | unsigned timestamp; | |
339 | unsigned forwarder_chain; | |
340 | unsigned name_rva; | |
341 | unsigned iat_rva; | |
342 | }; | |
1fd5e000 CF |
343 | |
344 | ||
67763c0c | 345 | static void track_down (char *file, char *suffix, int lvl); |
1fd5e000 | 346 | |
749bdbe9 CF |
347 | #define CYGPREFIX (sizeof ("%%% Cygwin ") - 1) |
348 | static void | |
349 | cygwin_info (HANDLE h) | |
350 | { | |
64069abe | 351 | char *buf, *bufend, *buf_start = NULL; |
749bdbe9 CF |
352 | const char *hello = " Cygwin DLL version info:\n"; |
353 | DWORD size = GetFileSize (h, NULL); | |
354 | DWORD n; | |
355 | ||
356 | if (size == 0xffffffff) | |
357 | return; | |
358 | ||
64069abe CF |
359 | buf_start = buf = (char *) calloc (1, size + 1); |
360 | if (buf == NULL) | |
361 | { | |
362 | keyeprint ("cygwin_info: malloc()"); | |
363 | return; | |
364 | } | |
749bdbe9 CF |
365 | |
366 | (void) SetFilePointer (h, 0, NULL, FILE_BEGIN); | |
367 | if (!ReadFile (h, buf, size, &n, NULL)) | |
64069abe CF |
368 | { |
369 | free (buf_start); | |
370 | return; | |
371 | } | |
749bdbe9 | 372 | |
ad466e2f CF |
373 | static char dummy[] = "\0\0\0\0\0\0\0"; |
374 | char *dll_major = dummy; | |
749bdbe9 | 375 | bufend = buf + size; |
749bdbe9 CF |
376 | while (buf < bufend) |
377 | if ((buf = (char *) memchr (buf, '%', bufend - buf)) == NULL) | |
eedc36cb | 378 | break; |
749bdbe9 | 379 | else if (strncmp ("%%% Cygwin ", buf, CYGPREFIX) != 0) |
eedc36cb | 380 | buf++; |
749bdbe9 CF |
381 | else |
382 | { | |
383 | char *p = strchr (buf += CYGPREFIX, '\n'); | |
64069abe CF |
384 | if (!p) |
385 | break; | |
2fac517d CF |
386 | if (strncasecmp (buf, "dll major:", 10) == 0) |
387 | { | |
388 | dll_major = buf + 11; | |
389 | continue; | |
390 | } | |
391 | char *s, pbuf[80]; | |
392 | int len; | |
393 | len = 1 + p - buf; | |
394 | if (strncasecmp (buf, "dll minor:", 10) != 0) | |
395 | s = buf; | |
396 | else | |
397 | { | |
398 | char c = dll_major[1]; | |
399 | dll_major[1] = '\0'; | |
400 | int maj = atoi (dll_major); | |
401 | dll_major[1] = c; | |
402 | int min = atoi (dll_major + 1); | |
b56dedef CF |
403 | sprintf (pbuf, "DLL version: %d.%d.%.*s", maj, min, len - 11, |
404 | buf + 11); | |
2fac517d CF |
405 | len = strlen (s = pbuf); |
406 | } | |
407 | if (strncmp (s, "dll", 3) == 0) | |
408 | memcpy (s, "DLL", 3); | |
409 | else if (strncmp (s, "api", 3) == 0) | |
410 | memcpy (s, "API", 3); | |
411 | else if (islower (*s)) | |
412 | *s = toupper (*s); | |
413 | fprintf (stdout, "%s %.*s", hello, len, s); | |
749bdbe9 CF |
414 | hello = ""; |
415 | } | |
416 | ||
417 | if (!*hello) | |
418 | puts (""); | |
64069abe CF |
419 | |
420 | free (buf_start); | |
749bdbe9 CF |
421 | return; |
422 | } | |
423 | ||
67763c0c | 424 | static void |
749bdbe9 | 425 | dll_info (const char *path, HANDLE fh, int lvl, int recurse) |
1fd5e000 CF |
426 | { |
427 | DWORD junk; | |
428 | int i; | |
429 | int pe_header_offset = get_dword (fh, 0x3c); | |
430 | int opthdr_ofs = pe_header_offset + 4 + 20; | |
431 | unsigned short v[6]; | |
64069abe CF |
432 | |
433 | if (path == NULL) | |
434 | { | |
435 | keyeprint ("dll_info: NULL passed for path"); | |
436 | return; | |
437 | } | |
438 | ||
b56dedef CF |
439 | if (SetFilePointer (fh, opthdr_ofs + 40, 0, FILE_BEGIN) == |
440 | INVALID_SET_FILE_POINTER && GetLastError () != NO_ERROR) | |
64069abe CF |
441 | keyeprint ("dll_info: SetFilePointer()"); |
442 | ||
443 | if (!ReadFile (fh, &v, sizeof (v), &junk, 0)) | |
444 | keyeprint ("dll_info: Readfile()"); | |
445 | ||
1fd5e000 CF |
446 | if (verbose) |
447 | printf (" - os=%d.%d img=%d.%d sys=%d.%d\n", | |
448 | v[0], v[1], v[2], v[3], v[4], v[5]); | |
449 | else | |
450 | printf ("\n"); | |
64069abe | 451 | |
1fd5e000 CF |
452 | int num_entries = get_dword (fh, opthdr_ofs + 92); |
453 | int export_rva = get_dword (fh, opthdr_ofs + 96); | |
454 | int export_size = get_dword (fh, opthdr_ofs + 100); | |
455 | int import_rva = get_dword (fh, opthdr_ofs + 104); | |
456 | int import_size = get_dword (fh, opthdr_ofs + 108); | |
457 | ||
458 | int nsections = get_word (fh, pe_header_offset + 4 + 2); | |
459 | char *sections = (char *) malloc (nsections * 40); | |
64069abe CF |
460 | |
461 | if (SetFilePointer (fh, pe_header_offset + 4 + 20 + | |
462 | get_word (fh, pe_header_offset + 4 + 16), 0, | |
463 | FILE_BEGIN) == INVALID_SET_FILE_POINTER | |
464 | && GetLastError () != NO_ERROR) | |
465 | keyeprint ("dll_info: SetFilePointer()"); | |
466 | ||
467 | if (!ReadFile (fh, sections, nsections * 40, &junk, 0)) | |
468 | keyeprint ("dll_info: Readfile()"); | |
1fd5e000 CF |
469 | |
470 | if (verbose && num_entries >= 1 && export_size > 0) | |
471 | { | |
472 | int expsz; | |
473 | int expbase = rva_to_offset (export_rva, sections, nsections, &expsz); | |
64069abe | 474 | |
1fd5e000 CF |
475 | if (expbase) |
476 | { | |
b56dedef CF |
477 | if (SetFilePointer (fh, expbase, 0, FILE_BEGIN) == |
478 | INVALID_SET_FILE_POINTER && GetLastError () != NO_ERROR) | |
64069abe CF |
479 | keyeprint ("dll_info: SetFilePointer()"); |
480 | ||
1fd5e000 | 481 | unsigned char *exp = (unsigned char *) malloc (expsz); |
64069abe CF |
482 | |
483 | if (!ReadFile (fh, exp, expsz, &junk, 0)) | |
484 | keyeprint ("dll_info: Readfile()"); | |
485 | ||
1fd5e000 CF |
486 | ExpDirectory *ed = (ExpDirectory *) exp; |
487 | int ofs = ed->name_rva - export_rva; | |
488 | struct tm *tm = localtime ((const time_t *) &(ed->timestamp)); | |
489 | if (tm->tm_year < 60) | |
490 | tm->tm_year += 2000; | |
491 | if (tm->tm_year < 200) | |
492 | tm->tm_year += 1900; | |
493 | printf ("%*c", lvl + 2, ' '); | |
494 | printf ("\"%s\" v%d.%d ts=", exp + ofs, | |
495 | ed->major_ver, ed->minor_ver); | |
496 | printf ("%d/%d/%d %d:%02d\n", | |
497 | tm->tm_year, tm->tm_mon + 1, tm->tm_mday, | |
498 | tm->tm_hour, tm->tm_min); | |
499 | } | |
500 | } | |
501 | ||
502 | if (num_entries >= 2 && import_size > 0 && recurse) | |
503 | { | |
504 | int impsz; | |
505 | int impbase = rva_to_offset (import_rva, sections, nsections, &impsz); | |
506 | if (impbase) | |
507 | { | |
b56dedef CF |
508 | if (SetFilePointer (fh, impbase, 0, FILE_BEGIN) == |
509 | INVALID_SET_FILE_POINTER && GetLastError () != NO_ERROR) | |
64069abe CF |
510 | keyeprint ("dll_info: SetFilePointer()"); |
511 | ||
1fd5e000 | 512 | unsigned char *imp = (unsigned char *) malloc (impsz); |
64069abe CF |
513 | if (imp == NULL) |
514 | { | |
515 | keyeprint ("dll_info: malloc()"); | |
516 | return; | |
517 | } | |
518 | ||
519 | if (!ReadFile (fh, imp, impsz, &junk, 0)) | |
520 | keyeprint ("dll_info: Readfile()"); | |
521 | ||
1fd5e000 CF |
522 | ImpDirectory *id = (ImpDirectory *) imp; |
523 | for (i = 0; id[i].name_rva; i++) | |
524 | { | |
525 | /* int ofs = id[i].name_rva - import_rva; */ | |
526 | track_down ((char *) imp + id[i].name_rva - import_rva, | |
527 | (char *) ".dll", lvl + 2); | |
528 | } | |
529 | } | |
530 | } | |
749bdbe9 CF |
531 | if (strstr (path, "\\cygwin1.dll")) |
532 | cygwin_info (fh); | |
1fd5e000 CF |
533 | } |
534 | ||
67763c0c | 535 | static void |
1fd5e000 CF |
536 | track_down (char *file, char *suffix, int lvl) |
537 | { | |
64069abe CF |
538 | if (file == NULL) |
539 | { | |
540 | keyeprint ("track_down: malloc()"); | |
541 | return; | |
542 | } | |
543 | ||
544 | if (suffix == NULL) | |
545 | { | |
546 | keyeprint ("track_down: malloc()"); | |
547 | return; | |
548 | } | |
549 | ||
1fd5e000 CF |
550 | char *path = find_on_path (file, suffix, 0, 1); |
551 | if (!path) | |
552 | { | |
553 | printf ("Error: could not find %s\n", file); | |
554 | return; | |
555 | } | |
556 | ||
557 | Did *d = already_did (file); | |
558 | switch (d->state) | |
559 | { | |
560 | case DID_NEW: | |
561 | break; | |
562 | case DID_ACTIVE: | |
563 | if (verbose) | |
564 | { | |
565 | if (lvl) | |
566 | printf ("%*c", lvl, ' '); | |
567 | printf ("%s", path); | |
568 | printf (" (recursive)\n"); | |
569 | } | |
570 | return; | |
571 | case DID_INACTIVE: | |
572 | if (verbose) | |
573 | { | |
574 | if (lvl) | |
575 | printf ("%*c", lvl, ' '); | |
576 | printf ("%s", path); | |
577 | printf (" (already done)\n"); | |
578 | } | |
579 | return; | |
64069abe CF |
580 | default: |
581 | break; | |
1fd5e000 CF |
582 | } |
583 | ||
584 | if (lvl) | |
585 | printf ("%*c", lvl, ' '); | |
586 | ||
587 | if (!path) | |
588 | { | |
589 | printf ("%s not found\n", file); | |
590 | return; | |
591 | } | |
592 | ||
593 | printf ("%s", path); | |
594 | ||
eedc36cb CF |
595 | HANDLE fh = |
596 | CreateFile (path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, | |
597 | NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | |
1fd5e000 CF |
598 | if (fh == INVALID_HANDLE_VALUE) |
599 | { | |
600 | printf (" - Cannot open\n"); | |
601 | return; | |
602 | } | |
603 | ||
604 | d->state = DID_ACTIVE; | |
605 | ||
749bdbe9 | 606 | dll_info (path, fh, lvl, 1); |
1fd5e000 | 607 | d->state = DID_INACTIVE; |
64069abe CF |
608 | if (!CloseHandle (fh)) |
609 | keyeprint ("track_down: CloseHandle()"); | |
1fd5e000 CF |
610 | } |
611 | ||
67763c0c | 612 | static void |
1fd5e000 CF |
613 | ls (char *f) |
614 | { | |
615 | HANDLE h = CreateFile (f, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, | |
616 | 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); | |
617 | BY_HANDLE_FILE_INFORMATION info; | |
64069abe CF |
618 | |
619 | if (!GetFileInformationByHandle (h, &info)) | |
620 | keyeprint ("ls: GetFileInformationByHandle()"); | |
621 | ||
1fd5e000 | 622 | SYSTEMTIME systime; |
64069abe CF |
623 | |
624 | if (!FileTimeToSystemTime (&info.ftLastWriteTime, &systime)) | |
625 | keyeprint ("ls: FileTimeToSystemTime()"); | |
1fd5e000 CF |
626 | printf ("%5dk %04d/%02d/%02d %s", |
627 | (((int) info.nFileSizeLow) + 512) / 1024, | |
eedc36cb | 628 | systime.wYear, systime.wMonth, systime.wDay, f); |
749bdbe9 | 629 | dll_info (f, h, 16, 0); |
64069abe CF |
630 | if (!CloseHandle (h)) |
631 | keyeprint ("ls: CloseHandle()"); | |
1fd5e000 CF |
632 | } |
633 | ||
67763c0c | 634 | static void |
1fd5e000 CF |
635 | cygcheck (char *app) |
636 | { | |
637 | char *papp = find_on_path (app, (char *) ".exe", 1, 0); | |
638 | if (!papp) | |
639 | { | |
640 | printf ("Error: could not find %s\n", app); | |
641 | return; | |
642 | } | |
643 | char *s = strdup (papp); | |
644 | char *sl = 0, *t; | |
645 | for (t = s; *t; t++) | |
646 | if (*t == '/' || *t == '\\' || *t == ':') | |
647 | sl = t; | |
648 | if (sl == 0) | |
649 | paths[0] = (char *) "."; | |
650 | else | |
651 | { | |
652 | *sl = 0; | |
653 | paths[0] = s; | |
654 | } | |
655 | did = 0; | |
656 | track_down (papp, (char *) ".exe", 0); | |
657 | } | |
658 | ||
659 | ||
660 | extern char **environ; | |
661 | ||
662 | struct RegInfo | |
eedc36cb CF |
663 | { |
664 | RegInfo *prev; | |
665 | char *name; | |
666 | HKEY key; | |
667 | }; | |
1fd5e000 | 668 | |
67763c0c | 669 | static void |
1fd5e000 CF |
670 | show_reg (RegInfo * ri, int nest) |
671 | { | |
672 | if (!ri) | |
673 | return; | |
674 | show_reg (ri->prev, 1); | |
675 | if (nest) | |
676 | printf ("%s\\", ri->name); | |
677 | else | |
678 | printf ("%s\n", ri->name); | |
679 | } | |
680 | ||
67763c0c | 681 | static void |
1fd5e000 CF |
682 | scan_registry (RegInfo * prev, HKEY hKey, char *name, int cygnus) |
683 | { | |
684 | RegInfo ri; | |
685 | ri.prev = prev; | |
686 | ri.name = name; | |
687 | ri.key = hKey; | |
688 | ||
689 | char *cp; | |
690 | for (cp = name; *cp; cp++) | |
691 | if (strncasecmp (cp, "cygnus", 6) == 0) | |
692 | cygnus = 1; | |
693 | ||
694 | DWORD num_subkeys, max_subkey_len, num_values; | |
695 | DWORD max_value_len, max_valdata_len, i; | |
696 | if (RegQueryInfoKey (hKey, 0, 0, 0, &num_subkeys, &max_subkey_len, 0, | |
697 | &num_values, &max_value_len, &max_valdata_len, 0, 0) | |
698 | != ERROR_SUCCESS) | |
699 | { | |
700 | #if 0 | |
701 | char tmp[400]; | |
702 | FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError (), | |
eedc36cb | 703 | MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), tmp, 400, 0); |
1fd5e000 CF |
704 | printf ("RegQueryInfoKey: %s\n", tmp); |
705 | #endif | |
706 | return; | |
707 | } | |
708 | ||
709 | if (cygnus) | |
710 | { | |
711 | show_reg (&ri, 0); | |
64069abe | 712 | |
1fd5e000 | 713 | char *value_name = (char *) malloc (max_value_len + 1); |
64069abe CF |
714 | if (value_name == NULL) |
715 | { | |
716 | keyeprint ("scan_registry: malloc()"); | |
717 | return; | |
718 | } | |
719 | ||
1fd5e000 | 720 | char *value_data = (char *) malloc (max_valdata_len + 1); |
64069abe CF |
721 | if (value_data == NULL) |
722 | { | |
723 | keyeprint ("scan_registry: malloc()"); | |
724 | return; | |
725 | } | |
1fd5e000 CF |
726 | |
727 | for (i = 0; i < num_values; i++) | |
728 | { | |
729 | DWORD dlen = max_valdata_len + 1; | |
730 | DWORD nlen = max_value_len + 1; | |
731 | DWORD type; | |
732 | RegEnumValue (hKey, i, value_name, &nlen, 0, | |
733 | &type, (BYTE *) value_data, &dlen); | |
734 | { | |
735 | printf (" %s = ", i ? value_name : "(default)"); | |
736 | switch (type) | |
737 | { | |
738 | case REG_DWORD: | |
739 | printf ("0x%08x\n", *(unsigned *) value_data); | |
740 | break; | |
741 | case REG_EXPAND_SZ: | |
742 | case REG_SZ: | |
743 | printf ("`%s'\n", value_data); | |
744 | break; | |
745 | default: | |
746 | printf ("(unsupported type)\n"); | |
747 | break; | |
748 | } | |
749 | } | |
1fd5e000 CF |
750 | } |
751 | free (value_name); | |
752 | free (value_data); | |
753 | } | |
754 | ||
755 | char *subkey_name = (char *) malloc (max_subkey_len + 1); | |
756 | for (i = 0; i < num_subkeys; i++) | |
757 | { | |
eedc36cb CF |
758 | if (RegEnumKey (hKey, i, subkey_name, max_subkey_len + 1) == |
759 | ERROR_SUCCESS) | |
1fd5e000 CF |
760 | { |
761 | HKEY sKey; | |
71f90de8 | 762 | if (RegOpenKeyEx (hKey, subkey_name, 0, KEY_READ, &sKey) |
1fd5e000 CF |
763 | == ERROR_SUCCESS) |
764 | { | |
765 | scan_registry (&ri, sKey, subkey_name, cygnus); | |
64069abe CF |
766 | if (RegCloseKey (sKey) != ERROR_SUCCESS) |
767 | keyeprint ("scan_registry: RegCloseKey()"); | |
1fd5e000 CF |
768 | } |
769 | } | |
770 | } | |
771 | free (subkey_name); | |
772 | } | |
773 | ||
dbc49afd CF |
774 | void |
775 | pretty_id (const char *s, char *cygwin, size_t cyglen) | |
776 | { | |
777 | char *groups[16384]; | |
778 | ||
779 | strcpy (cygwin + cyglen++, " "); | |
780 | strcpy (cygwin + cyglen, s); | |
781 | putenv (cygwin); | |
782 | ||
783 | char *id = cygpath ("/bin/id.exe", NULL); | |
bd79b736 | 784 | for (char *p = id; (p = strchr (p, '/')); p++) |
dbc49afd CF |
785 | *p = '\\'; |
786 | ||
787 | if (access (id, X_OK)) | |
7dddf53f CF |
788 | { |
789 | fprintf (stderr, "`id' program not found\n"); | |
790 | return; | |
791 | } | |
dbc49afd CF |
792 | |
793 | FILE *f = popen (id, "rt"); | |
794 | ||
795 | char buf[16384]; | |
7dddf53f | 796 | buf[0] = '\0'; |
dbc49afd | 797 | fgets (buf, sizeof (buf), f); |
a5aa8c3e | 798 | pclose (f); |
7dddf53f CF |
799 | char *uid = strtok (buf, ")"); |
800 | if (uid) | |
801 | uid += strlen ("uid="); | |
802 | else | |
902edd45 CF |
803 | { |
804 | fprintf (stderr, "garbled output from `id' command - no uid= found\n"); | |
167f0d85 | 805 | return; |
902edd45 | 806 | } |
7dddf53f CF |
807 | char *gid = strtok (NULL, ")"); |
808 | if (gid) | |
809 | gid += strlen ("gid=") + 1; | |
810 | else | |
902edd45 CF |
811 | { |
812 | fprintf (stderr, "garbled output from `id' command - no gid= found\n"); | |
167f0d85 | 813 | return; |
902edd45 CF |
814 | } |
815 | ||
816 | char **ng = groups - 1; | |
0ffa77a9 CF |
817 | size_t len_uid = strlen ("UID: )") + strlen (uid); |
818 | size_t len_gid = strlen ("GID: )") + strlen (gid); | |
0597641a CF |
819 | *++ng = groups[0] = (char *) alloca (len_uid + 1); |
820 | *++ng = groups[1] = (char *) alloca (len_gid + 1); | |
902edd45 CF |
821 | sprintf (groups[0], "UID: %s)", uid); |
822 | sprintf (groups[1], "GID: %s)", gid); | |
823 | size_t sz = max (len_uid, len_gid); | |
824 | while ((*++ng = strtok (NULL, ","))) | |
dbc49afd CF |
825 | { |
826 | char *p = strchr (*ng, '\n'); | |
827 | if (p) | |
828 | *p = '\0'; | |
902edd45 | 829 | if (ng == groups + 2) |
6806f4f6 | 830 | *ng += strlen (" groups="); |
dbc49afd CF |
831 | size_t len = strlen (*ng); |
832 | if (sz < len) | |
833 | sz = len; | |
834 | } | |
167f0d85 | 835 | ng--; |
dbc49afd | 836 | |
6806f4f6 | 837 | printf ("\nOutput from %s (%s)\n", id, s); |
167f0d85 | 838 | int n = 80 / (int) ++sz; |
eedf2474 | 839 | int i = n > 2 ? n - 2 : 0; |
167f0d85 CF |
840 | sz = -sz; |
841 | for (char **g = groups; g <= ng; g++) | |
842 | if ((g != ng) && (++i < n)) | |
eedf2474 | 843 | printf ("%*s", sz, *g); |
902edd45 CF |
844 | else |
845 | { | |
846 | puts (*g); | |
847 | i = 0; | |
848 | } | |
dbc49afd CF |
849 | } |
850 | ||
67763c0c | 851 | static void |
1fd5e000 CF |
852 | dump_sysinfo () |
853 | { | |
854 | int i, j; | |
855 | char tmp[4000]; | |
856 | time_t now; | |
749bdbe9 | 857 | char *found_cygwin_dll; |
1fd5e000 | 858 | |
0cf94b8c | 859 | printf ("\nCygwin Configuration Diagnostics\n"); |
1fd5e000 CF |
860 | time (&now); |
861 | printf ("Current System Time: %s\n", ctime (&now)); | |
862 | ||
863 | OSVERSIONINFO osversion; | |
864 | osversion.dwOSVersionInfoSize = sizeof (osversion); | |
64069abe CF |
865 | if (!GetVersionEx (&osversion)) |
866 | keyeprint ("dump_sysinfo: GetVersionEx()"); | |
1fd5e000 CF |
867 | char *osname = (char *) "unknown OS"; |
868 | switch (osversion.dwPlatformId) | |
869 | { | |
870 | case VER_PLATFORM_WIN32s: | |
e4087b75 | 871 | osname = (char *) "32s"; |
1fd5e000 CF |
872 | break; |
873 | case VER_PLATFORM_WIN32_WINDOWS: | |
874 | switch (osversion.dwMinorVersion) | |
875 | { | |
876 | case 0: | |
b56dedef | 877 | if (strchr (osversion.szCSDVersion, 'C')) |
e4087b75 | 878 | osname = (char *) "95 OSR2"; |
9a6c0a24 | 879 | else |
e4087b75 | 880 | osname = (char *) "95"; |
1fd5e000 | 881 | break; |
9a6c0a24 | 882 | case 10: |
b56dedef | 883 | if (strchr (osversion.szCSDVersion, 'A')) |
e4087b75 | 884 | osname = (char *) "98 SE"; |
9a6c0a24 | 885 | else |
e4087b75 | 886 | osname = (char *) "98"; |
9a6c0a24 CV |
887 | break; |
888 | case 90: | |
e4087b75 | 889 | osname = (char *) "ME"; |
1fd5e000 CF |
890 | break; |
891 | default: | |
e4087b75 | 892 | osname = (char *) "9X"; |
1fd5e000 CF |
893 | break; |
894 | } | |
895 | break; | |
896 | case VER_PLATFORM_WIN32_NT: | |
9a6c0a24 CV |
897 | if (osversion.dwMajorVersion == 5) |
898 | { | |
e4087b75 CV |
899 | BOOL more_info = FALSE; |
900 | OSVERSIONINFOEX osversionex; | |
901 | osversionex.dwOSVersionInfoSize = sizeof (osversionex); | |
b56dedef | 902 | if (GetVersionEx ((OSVERSIONINFO *) &osversionex)) |
e4087b75 | 903 | more_info = TRUE; |
9a6c0a24 | 904 | if (osversion.dwMinorVersion == 0) |
e4087b75 CV |
905 | { |
906 | if (!more_info) | |
907 | osname = (char *) "2000"; | |
5e051b1b | 908 | else if (osversionex.wProductType == VER_NT_SERVER |
b56dedef CF |
909 | || osversionex.wProductType == |
910 | VER_NT_DOMAIN_CONTROLLER) | |
911 | { | |
912 | if (osversionex.wSuiteMask &VER_SUITE_DATACENTER) | |
5e051b1b CV |
913 | osname = (char *) "2000 Datacenter Server"; |
914 | else if (osversionex.wSuiteMask & VER_SUITE_ENTERPRISE) | |
915 | osname = (char *) "2000 Advanced Server"; | |
916 | else | |
917 | osname = (char *) "2000 Server"; | |
b56dedef | 918 | } |
e4087b75 | 919 | else |
b56dedef | 920 | osname = (char *) "2000 Professional"; |
e4087b75 | 921 | } |
9a6c0a24 | 922 | else |
e4087b75 CV |
923 | { |
924 | if (!more_info) | |
925 | osname = (char *) "XP"; | |
5e051b1b | 926 | else if (osversionex.wProductType == VER_NT_SERVER |
b56dedef CF |
927 | || osversionex.wProductType == |
928 | VER_NT_DOMAIN_CONTROLLER) | |
929 | { | |
5e051b1b CV |
930 | if (osversionex.wSuiteMask & VER_SUITE_ENTERPRISE) |
931 | osname = (char *) ".NET Enterprise Server"; | |
932 | else | |
933 | osname = (char *) ".NET Server"; | |
934 | } | |
e4087b75 | 935 | else if (osversionex.wSuiteMask & VER_SUITE_PERSONAL) |
b56dedef | 936 | osname = (char *) "XP Home Edition"; |
e4087b75 | 937 | else |
b56dedef CF |
938 | osname = (char *) "XP Professional"; |
939 | ||
e4087b75 | 940 | } |
b56dedef | 941 | } |
9a6c0a24 | 942 | else |
e4087b75 | 943 | osname = (char *) "NT"; |
1fd5e000 CF |
944 | break; |
945 | default: | |
e4087b75 | 946 | osname = (char *) "??"; |
1fd5e000 CF |
947 | break; |
948 | } | |
d1ba802d CV |
949 | printf ("Windows %s Ver %lu.%lu Build %lu %s\n\n", osname, |
950 | osversion.dwMajorVersion, osversion.dwMinorVersion, | |
951 | osversion.dwPlatformId == VER_PLATFORM_WIN32_NT ? | |
b56dedef | 952 | osversion.dwBuildNumber : (osversion.dwBuildNumber & 0xffff), |
d1ba802d | 953 | osversion.dwPlatformId == VER_PLATFORM_WIN32_NT ? |
b56dedef | 954 | osversion.szCSDVersion : ""); |
1fd5e000 CF |
955 | |
956 | printf ("Path:"); | |
957 | char *s = getenv ("PATH"), *e; | |
958 | char sep = strchr (s, ';') ? ';' : ':'; | |
959 | int count_path_items = 0; | |
960 | while (1) | |
961 | { | |
962 | for (e = s; *e && *e != sep; e++); | |
5f175ea6 | 963 | if (e-s) |
82e127ca | 964 | printf ("\t%.*s\n", e - s, s); |
5f175ea6 | 965 | else |
82e127ca | 966 | puts ("\t."); |
1fd5e000 CF |
967 | count_path_items++; |
968 | if (!*e) | |
969 | break; | |
970 | s = e + 1; | |
971 | } | |
972 | ||
dbc49afd CF |
973 | fflush (stdout); |
974 | ||
ce7a3610 CF |
975 | char *cygwin = getenv ("CYGWIN"); |
976 | if (cygwin) | |
977 | cygwin -= strlen ("CYGWIN="); | |
978 | else | |
979 | cygwin = const_cast <char *> ("CYGWIN="); | |
dbc49afd CF |
980 | size_t cyglen = strlen (cygwin); |
981 | cygwin = strcpy ((char *) malloc (cyglen + sizeof (" nontsec")), cygwin); | |
982 | pretty_id ("nontsec", cygwin, cyglen); | |
983 | pretty_id ("ntsec", cygwin, cyglen); | |
984 | cygwin[cyglen] = 0; | |
985 | putenv (cygwin); | |
986 | ||
64069abe CF |
987 | if (!GetSystemDirectory (tmp, 4000)) |
988 | keyeprint ("dump_sysinfo: GetSystemDirectory()"); | |
1fd5e000 | 989 | printf ("\nSysDir: %s\n", tmp); |
64069abe | 990 | |
1fd5e000 CF |
991 | GetWindowsDirectory (tmp, 4000); |
992 | printf ("WinDir: %s\n\n", tmp); | |
993 | ||
994 | ||
995 | if (givehelp) | |
996 | printf ("Here's some environment variables that may affect cygwin:\n"); | |
997 | for (i = 0; environ[i]; i++) | |
998 | { | |
999 | char *eq = strchr (environ[i], '='); | |
1000 | if (!eq) | |
1001 | continue; | |
1002 | /* int len = eq - environ[i]; */ | |
1003 | for (j = 0; known_env_vars[j]; j++) | |
1004 | { | |
1005 | *eq = 0; | |
1006 | if (strcmp (environ[i], "PATH") == 0) | |
1007 | continue; /* we handle this one specially */ | |
1008 | if (strcasecmp (environ[i], known_env_vars[j]) == 0) | |
1009 | printf ("%s = `%s'\n", environ[i], eq + 1); | |
1010 | *eq = '='; | |
1011 | } | |
1012 | } | |
1013 | printf ("\n"); | |
1014 | ||
1015 | if (verbose) | |
1016 | { | |
1017 | if (givehelp) | |
1018 | printf ("Here's the rest of your environment variables:\n"); | |
1019 | for (i = 0; environ[i]; i++) | |
1020 | { | |
1021 | int found = 0; | |
1022 | char *eq = strchr (environ[i], '='); | |
1023 | if (!eq) | |
1024 | continue; | |
1025 | /* int len = eq - environ[i]; */ | |
1026 | for (j = 0; known_env_vars[j]; j++) | |
1027 | { | |
1028 | *eq = 0; | |
1029 | if (strcasecmp (environ[i], known_env_vars[j]) == 0) | |
1030 | found = 1; | |
1031 | *eq = '='; | |
1032 | } | |
1033 | if (!found) | |
1034 | { | |
1035 | *eq = 0; | |
1036 | printf ("%s = `%s'\n", environ[i], eq + 1); | |
1037 | *eq = '='; | |
1038 | } | |
1039 | } | |
1040 | printf ("\n"); | |
1041 | } | |
1042 | ||
1043 | if (registry) | |
1044 | { | |
1045 | if (givehelp) | |
1046 | printf ("Scanning registry for keys with `Cygnus' in them...\n"); | |
1047 | #if 0 | |
1048 | /* big and not generally useful */ | |
1049 | scan_registry (0, HKEY_CLASSES_ROOT, (char *) "HKEY_CLASSES_ROOT", 0); | |
1050 | #endif | |
1051 | scan_registry (0, HKEY_CURRENT_CONFIG, | |
1052 | (char *) "HKEY_CURRENT_CONFIG", 0); | |
1053 | scan_registry (0, HKEY_CURRENT_USER, (char *) "HKEY_CURRENT_USER", 0); | |
1054 | scan_registry (0, HKEY_LOCAL_MACHINE, (char *) "HKEY_LOCAL_MACHINE", 0); | |
1055 | #if 0 | |
1056 | /* the parts we need are duplicated in HKEY_CURRENT_USER anyway */ | |
1057 | scan_registry (0, HKEY_USERS, (char *) "HKEY_USERS", 0); | |
1058 | #endif | |
1059 | printf ("\n"); | |
1060 | } | |
1061 | else | |
1062 | printf ("Use `-r' to scan registry\n\n"); | |
1063 | ||
1064 | if (givehelp) | |
1065 | { | |
1066 | printf ("Listing available drives...\n"); | |
be957eb5 | 1067 | printf ("Drv Type Size Used Flags Name\n"); |
1fd5e000 | 1068 | } |
eedc36cb CF |
1069 | int prev_mode = |
1070 | SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); | |
1fd5e000 CF |
1071 | int drivemask = GetLogicalDrives (); |
1072 | ||
1073 | HINSTANCE k32 = LoadLibrary ("kernel32.dll"); | |
eedc36cb | 1074 | BOOL (WINAPI * gdfse) (LPCSTR, long long *, long long *, long long *) = |
1fd5e000 | 1075 | (BOOL (WINAPI *) (LPCSTR, long long *, long long *, long long *)) |
eedc36cb | 1076 | GetProcAddress (k32, "GetDiskFreeSpaceExA"); |
1fd5e000 CF |
1077 | |
1078 | for (i = 0; i < 26; i++) | |
1079 | { | |
1080 | if (!(drivemask & (1 << i))) | |
1081 | continue; | |
1082 | char drive[4], name[200], fsname[200]; | |
1083 | DWORD serno = 0, maxnamelen = 0, flags = 0; | |
1084 | name[0] = name[0] = fsname[0] = 0; | |
1085 | sprintf (drive, "%c:\\", i + 'a'); | |
4bfc614b CF |
1086 | /* Report all errors, except if the Volume is ERROR_NOT_READY. |
1087 | ERROR_NOT_READY is returned when removeable media drives are empty | |
1088 | (CD, floppy, etc.) */ | |
b56dedef CF |
1089 | if (!GetVolumeInformation |
1090 | (drive, name, sizeof (name), &serno, &maxnamelen, &flags, fsname, | |
1091 | sizeof (fsname)) && GetLastError () != ERROR_NOT_READY) | |
64069abe | 1092 | keyeprint ("dump_sysinfo: GetVolumeInformation()"); |
1fd5e000 CF |
1093 | |
1094 | int dtype = GetDriveType (drive); | |
1095 | char drive_type[4] = "unk"; | |
1096 | switch (dtype) | |
1097 | { | |
1098 | case DRIVE_REMOVABLE: | |
1099 | strcpy (drive_type, "fd "); | |
1100 | break; | |
1101 | case DRIVE_FIXED: | |
1102 | strcpy (drive_type, "hd "); | |
1103 | break; | |
1104 | case DRIVE_REMOTE: | |
1105 | strcpy (drive_type, "net"); | |
1106 | break; | |
1107 | case DRIVE_CDROM: | |
1108 | strcpy (drive_type, "cd "); | |
1109 | break; | |
1110 | case DRIVE_RAMDISK: | |
1111 | strcpy (drive_type, "ram"); | |
1112 | break; | |
64069abe CF |
1113 | default: |
1114 | strcpy (drive_type, "unk"); | |
1fd5e000 CF |
1115 | } |
1116 | ||
1117 | long capacity_mb = -1; | |
1118 | int percent_full = -1; | |
1119 | ||
1120 | long long free_me = 0ULL, free_bytes = 0ULL, total_bytes = 1ULL; | |
eedc36cb | 1121 | if (gdfse != NULL && gdfse (drive, &free_me, &total_bytes, &free_bytes)) |
1fd5e000 CF |
1122 | { |
1123 | capacity_mb = total_bytes / (1024L * 1024L); | |
1124 | percent_full = 100 - (int) ((100.0 * free_me) / total_bytes); | |
1125 | } | |
1126 | else | |
1127 | { | |
1128 | DWORD spc = 0, bps = 0, fc = 0, tc = 1; | |
1129 | if (GetDiskFreeSpace (drive, &spc, &bps, &fc, &tc)) | |
1130 | { | |
1131 | capacity_mb = (spc * bps * tc) / (1024 * 1024); | |
1132 | percent_full = 100 - (int) ((100.0 * fc) / tc); | |
1133 | } | |
1134 | } | |
1135 | ||
1136 | printf ("%.2s %s %-6s ", drive, drive_type, fsname); | |
1137 | if (capacity_mb >= 0) | |
be957eb5 | 1138 | printf ("%7dMb %3d%% ", (int) capacity_mb, (int) percent_full); |
1fd5e000 | 1139 | else |
be957eb5 | 1140 | printf (" N/A N/A "); |
1fd5e000 CF |
1141 | printf ("%s %s %s %s %s %s %s\n", |
1142 | flags & FS_CASE_IS_PRESERVED ? "CP" : " ", | |
1143 | flags & FS_CASE_SENSITIVE ? "CS" : " ", | |
1144 | flags & FS_UNICODE_STORED_ON_DISK ? "UN" : " ", | |
1145 | flags & FS_PERSISTENT_ACLS ? "PA" : " ", | |
1146 | flags & FS_FILE_COMPRESSION ? "FC" : " ", | |
1147 | flags & FS_VOL_IS_COMPRESSED ? "VC" : " ", | |
1148 | #if 0 | |
1149 | flags & FILE_SUPPORTS_ENCRYPTION ? "EN" : " ", | |
1150 | flags & FILE_SUPPORTS_OBJECT_IDS ? "OI" : " ", | |
1151 | flags & FILE_SUPPORTS_REPARSE_POINTS ? "RP" : " ", | |
1152 | flags & FILE_SUPPORTS_SPARSE_FILES ? "SP" : " ", | |
1153 | flags & FILE_VOLUME_QUOTAS ? "QU" : " ", | |
1154 | #endif | |
1155 | name); | |
1156 | } | |
1157 | ||
64069abe CF |
1158 | if (!FreeLibrary (k32)) |
1159 | keyeprint ("dump_sysinfo: FreeLibrary()"); | |
1fd5e000 CF |
1160 | SetErrorMode (prev_mode); |
1161 | if (givehelp) | |
1162 | { | |
a3a40100 | 1163 | puts ("\n" |
be1d479e BG |
1164 | "fd = floppy, hd = hard drive, cd = CD-ROM\n" |
1165 | "net= Network Share, ram= RAM drive, unk= Unknown\n" | |
1166 | "CP = Case Preserving, CS = Case Sensitive, UN = Unicode\n" | |
1167 | "PA = Persistent ACLS, FC = File Compression, VC = Volume Compression"); | |
1fd5e000 CF |
1168 | } |
1169 | printf ("\n"); | |
1170 | ||
ad466e2f | 1171 | unsigned ml_fsname = 4, ml_dir = 7, ml_type = 6; |
0795a245 | 1172 | bool ml_trailing = false; |
1fd5e000 | 1173 | |
2fac517d CF |
1174 | struct mntent *mnt; |
1175 | setmntent (0, 0); | |
1176 | while ((mnt = getmntent (0))) | |
1177 | { | |
ad466e2f | 1178 | unsigned n = (int) strlen (mnt->mnt_fsname); |
0795a245 | 1179 | ml_trailing |= (n > 1 && strchr ("\\/", mnt->mnt_fsname[n - 1])); |
2fac517d CF |
1180 | if (ml_fsname < n) |
1181 | ml_fsname = n; | |
1182 | n = (int) strlen (mnt->mnt_dir); | |
0795a245 | 1183 | ml_trailing |= (n > 1 && strchr ("\\/", mnt->mnt_dir[n - 1])); |
2fac517d CF |
1184 | if (ml_dir < n) |
1185 | ml_dir = n; | |
1186 | } | |
1187 | ||
0795a245 CF |
1188 | if (ml_trailing) |
1189 | puts ("Warning: Mount entries should not have a trailing (back)slash\n"); | |
1190 | ||
1fd5e000 CF |
1191 | if (givehelp) |
1192 | { | |
eedc36cb CF |
1193 | printf |
1194 | ("Mount entries: these map POSIX directories to your NT drives.\n"); | |
1195 | printf ("%-*s %-*s %-*s %s\n", ml_fsname, "-NT-", ml_dir, "-POSIX-", | |
1fd5e000 CF |
1196 | ml_type, "-Type-", "-Flags-"); |
1197 | } | |
1198 | ||
1fd5e000 | 1199 | setmntent (0, 0); |
1fd5e000 CF |
1200 | while ((mnt = getmntent (0))) |
1201 | { | |
1202 | printf ("%-*s %-*s %-*s %s\n", | |
1203 | ml_fsname, mnt->mnt_fsname, | |
eedc36cb | 1204 | ml_dir, mnt->mnt_dir, ml_type, mnt->mnt_type, mnt->mnt_opts); |
1fd5e000 CF |
1205 | } |
1206 | printf ("\n"); | |
1207 | ||
1208 | add_path ((char *) "\\bin", 4); /* just in case */ | |
1209 | ||
1210 | if (givehelp) | |
eedc36cb CF |
1211 | printf |
1212 | ("Looking to see where common programs can be found, if at all...\n"); | |
1fd5e000 CF |
1213 | for (i = 0; common_apps[i].name; i++) |
1214 | if (!find_on_path ((char *) common_apps[i].name, (char *) ".exe", 1, 0)) | |
eedc36cb CF |
1215 | { |
1216 | if (common_apps[i].missing_is_good) | |
1217 | printf ("Not Found: %s (good!)\n", common_apps[i].name); | |
1218 | else | |
1219 | printf ("Not Found: %s\n", common_apps[i].name); | |
1220 | } | |
1fd5e000 CF |
1221 | printf ("\n"); |
1222 | ||
1223 | if (givehelp) | |
1224 | printf ("Looking for various Cygnus DLLs... (-v gives version info)\n"); | |
1225 | for (i = 0; i < num_paths; i++) | |
1226 | { | |
1227 | WIN32_FIND_DATA ffinfo; | |
1228 | sprintf (tmp, "%s/*.*", paths[i]); | |
1229 | HANDLE ff = FindFirstFile (tmp, &ffinfo); | |
1230 | int found = (ff != INVALID_HANDLE_VALUE); | |
749bdbe9 | 1231 | found_cygwin_dll = NULL; |
1fd5e000 CF |
1232 | while (found) |
1233 | { | |
1234 | char *f = ffinfo.cFileName; | |
1235 | if (strcasecmp (f + strlen (f) - 4, ".dll") == 0) | |
1236 | { | |
1237 | if (strncasecmp (f, "cyg", 3) == 0) | |
1238 | { | |
1239 | sprintf (tmp, "%s\\%s", paths[i], f); | |
749bdbe9 CF |
1240 | if (strcasecmp (f, "cygwin1.dll") == 0) |
1241 | found_cygwin_dll = strdup (tmp); | |
1242 | else | |
1243 | ls (tmp); | |
1fd5e000 CF |
1244 | } |
1245 | } | |
1246 | found = FindNextFile (ff, &ffinfo); | |
1247 | } | |
749bdbe9 CF |
1248 | if (found_cygwin_dll) |
1249 | { | |
1250 | ls (found_cygwin_dll); | |
1251 | free (found_cygwin_dll); | |
1252 | } | |
1253 | ||
1fd5e000 CF |
1254 | FindClose (ff); |
1255 | } | |
1256 | } | |
1257 | ||
67763c0c | 1258 | static int |
41a0695b CV |
1259 | check_keys () |
1260 | { | |
1261 | HANDLE h = CreateFileA ("CONIN$", GENERIC_READ | GENERIC_WRITE, | |
eedc36cb CF |
1262 | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, |
1263 | OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | |
41a0695b CV |
1264 | |
1265 | if (h == INVALID_HANDLE_VALUE || h == NULL) | |
64069abe | 1266 | return (keyeprint ("check_key: Opening CONIN$")); |
41a0695b CV |
1267 | |
1268 | DWORD mode; | |
1269 | ||
1270 | if (!GetConsoleMode (h, &mode)) | |
64069abe | 1271 | keyeprint ("check_keys: GetConsoleMode()"); |
41a0695b CV |
1272 | else |
1273 | { | |
1274 | mode &= ~ENABLE_PROCESSED_INPUT; | |
1275 | if (!SetConsoleMode (h, mode)) | |
64069abe | 1276 | keyeprint ("check_keys: GetConsoleMode()"); |
41a0695b CV |
1277 | } |
1278 | ||
1279 | fputs ("\nThis key check works only in a console window,", stderr); | |
1280 | fputs (" _NOT_ in a terminal session!\n", stderr); | |
1281 | fputs ("Abort with Ctrl+C if in a terminal session.\n\n", stderr); | |
1282 | fputs ("Press `q' to exit.\n", stderr); | |
1283 | ||
1284 | INPUT_RECORD in, prev_in; | |
1285 | ||
1286 | // Drop first <RETURN> key | |
1287 | ReadConsoleInput (h, &in, 1, &mode); | |
1288 | ||
1289 | memset (&in, 0, sizeof in); | |
1290 | ||
1291 | do | |
1292 | { | |
1293 | prev_in = in; | |
1294 | if (!ReadConsoleInput (h, &in, 1, &mode)) | |
eedc36cb | 1295 | keyeprint ("ReadConsoleInput"); |
41a0695b CV |
1296 | |
1297 | if (!memcmp (&in, &prev_in, sizeof in)) | |
eedc36cb | 1298 | continue; |
41a0695b CV |
1299 | |
1300 | switch (in.EventType) | |
eedc36cb CF |
1301 | { |
1302 | case KEY_EVENT: | |
1303 | printf ("%s %ux VK: 0x%02x VS: 0x%02x A: 0x%02x CTRL: ", | |
1304 | in.Event.KeyEvent.bKeyDown ? "Pressed " : "Released", | |
1305 | in.Event.KeyEvent.wRepeatCount, | |
1306 | in.Event.KeyEvent.wVirtualKeyCode, | |
1307 | in.Event.KeyEvent.wVirtualScanCode, | |
1308 | (unsigned char) in.Event.KeyEvent.uChar.AsciiChar); | |
1309 | fputs (in.Event.KeyEvent.dwControlKeyState & CAPSLOCK_ON ? | |
1310 | "CL " : "-- ", stdout); | |
1311 | fputs (in.Event.KeyEvent.dwControlKeyState & ENHANCED_KEY ? | |
1312 | "EK " : "-- ", stdout); | |
1313 | fputs (in.Event.KeyEvent.dwControlKeyState & LEFT_ALT_PRESSED ? | |
1314 | "LA " : "-- ", stdout); | |
1315 | fputs (in.Event.KeyEvent.dwControlKeyState & LEFT_CTRL_PRESSED ? | |
1316 | "LC " : "-- ", stdout); | |
1317 | fputs (in.Event.KeyEvent.dwControlKeyState & NUMLOCK_ON ? | |
1318 | "NL " : "-- ", stdout); | |
1319 | fputs (in.Event.KeyEvent.dwControlKeyState & RIGHT_ALT_PRESSED ? | |
1320 | "RA " : "-- ", stdout); | |
1321 | fputs (in.Event.KeyEvent.dwControlKeyState & RIGHT_CTRL_PRESSED ? | |
1322 | "RC " : "-- ", stdout); | |
1323 | fputs (in.Event.KeyEvent.dwControlKeyState & SCROLLLOCK_ON ? | |
1324 | "SL " : "-- ", stdout); | |
1325 | fputs (in.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED ? | |
1326 | "SH " : "-- ", stdout); | |
1327 | fputc ('\n', stdout); | |
1328 | break; | |
1329 | ||
64069abe CF |
1330 | default: |
1331 | break; | |
eedc36cb | 1332 | } |
41a0695b CV |
1333 | } |
1334 | while (in.EventType != KEY_EVENT || | |
eedc36cb CF |
1335 | in.Event.KeyEvent.bKeyDown != FALSE || |
1336 | in.Event.KeyEvent.uChar.AsciiChar != 'q'); | |
41a0695b CV |
1337 | |
1338 | CloseHandle (h); | |
1339 | return 0; | |
1340 | } | |
eedc36cb | 1341 | |
67763c0c | 1342 | static void |
b56dedef | 1343 | usage (FILE * stream, int status) |
1fd5e000 | 1344 | { |
67763c0c | 1345 | fprintf (stream, "\ |
aa275fe0 JDF |
1346 | Usage: cygcheck [OPTIONS] [PROGRAM...]\n\ |
1347 | Check system information or PROGRAM library dependencies\n\ | |
1348 | \n\ | |
200f243c | 1349 | -c, --check-setup check packages installed via setup.exe\n\ |
59a76035 | 1350 | -d, --dump-only no integrity checking of package contents (requires -c)\n\ |
200f243c | 1351 | -s, --sysinfo system information (not with -k)\n\ |
59a76035 | 1352 | -v, --verbose verbose output (indented) (for -[cfls] or programs)\n\ |
200f243c CV |
1353 | -r, --registry registry search (requires -s)\n\ |
1354 | -k, --keycheck perform a keyboard check session (not with -[scfl])\n\ | |
1355 | -f, --find-package find installed packages containing files (not with -[cl])\n\ | |
1356 | -l, --list-package list the contents of installed packages (not with -[cf])\n\ | |
1357 | -h, --help give help about the info (not with -[cfl])\n\ | |
1358 | -V, --version output version information and exit\n\ | |
67763c0c CF |
1359 | You must at least give either -s or -k or a program name\n"); |
1360 | exit (status); | |
1fd5e000 CF |
1361 | } |
1362 | ||
41a0695b | 1363 | struct option longopts[] = { |
d0d51791 | 1364 | {"check-setup", no_argument, NULL, 'c'}, |
59a76035 | 1365 | {"dump-only", no_argument, NULL, 'd'}, |
eedc36cb CF |
1366 | {"sysinfo", no_argument, NULL, 's'}, |
1367 | {"registry", no_argument, NULL, 'r'}, | |
1368 | {"verbose", no_argument, NULL, 'v'}, | |
1369 | {"keycheck", no_argument, NULL, 'k'}, | |
200f243c CV |
1370 | {"find-package", no_argument, NULL, 'f'}, |
1371 | {"list-package", no_argument, NULL, 'l'}, | |
eedc36cb | 1372 | {"help", no_argument, NULL, 'h'}, |
b9262dd9 | 1373 | {"version", no_argument, 0, 'V'}, |
eedc36cb | 1374 | {0, no_argument, NULL, 0} |
41a0695b | 1375 | }; |
ce475802 | 1376 | |
59a76035 | 1377 | static char opts[] = "cdfhklrsvV"; |
67763c0c CF |
1378 | |
1379 | static void | |
1380 | print_version () | |
1381 | { | |
1382 | const char *v = strchr (version, ':'); | |
1383 | int len; | |
1384 | if (!v) | |
1385 | { | |
1386 | v = "?"; | |
1387 | len = 1; | |
1388 | } | |
1389 | else | |
1390 | { | |
1391 | v += 2; | |
1392 | len = strchr (v, ' ') - v; | |
1393 | } | |
1394 | printf ("\ | |
1395 | cygcheck version %.*s\n\ | |
1396 | System Checker for Cygwin\n\ | |
c662f402 | 1397 | Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.\n\ |
98467dae JDF |
1398 | Compiled on %s\n\ |
1399 | ", len, v, __DATE__); | |
67763c0c | 1400 | } |
41a0695b | 1401 | |
1fd5e000 CF |
1402 | int |
1403 | main (int argc, char **argv) | |
1404 | { | |
1405 | int i; | |
1fd5e000 | 1406 | |
744ed079 | 1407 | (void) putenv("POSIXLY_CORRECT=1"); |
41a0695b CV |
1408 | while ((i = getopt_long (argc, argv, opts, longopts, NULL)) != EOF) |
1409 | switch (i) | |
1410 | { | |
1411 | case 's': | |
eedc36cb CF |
1412 | sysinfo = 1; |
1413 | break; | |
d0d51791 CF |
1414 | case 'c': |
1415 | check_setup = 1; | |
1416 | break; | |
59a76035 CV |
1417 | case 'd': |
1418 | dump_only = 1; | |
1419 | break; | |
41a0695b | 1420 | case 'r': |
eedc36cb CF |
1421 | registry = 1; |
1422 | break; | |
41a0695b | 1423 | case 'v': |
eedc36cb CF |
1424 | verbose = 1; |
1425 | break; | |
41a0695b | 1426 | case 'k': |
eedc36cb CF |
1427 | keycheck = 1; |
1428 | break; | |
200f243c CV |
1429 | case 'f': |
1430 | find_package = 1; | |
1431 | break; | |
1432 | case 'l': | |
1433 | list_package = 1; | |
1434 | break; | |
41a0695b | 1435 | case 'h': |
eedc36cb CF |
1436 | givehelp = 1; |
1437 | break; | |
67763c0c CF |
1438 | case 'V': |
1439 | print_version (); | |
b56dedef | 1440 | exit (0); |
41a0695b | 1441 | default: |
67763c0c | 1442 | usage (stderr, 1); |
eedc36cb | 1443 | /*NOTREACHED*/} |
41a0695b CV |
1444 | argc -= optind; |
1445 | argv += optind; | |
1446 | ||
35e15d99 | 1447 | if (argc == 0 && !sysinfo && !keycheck && !check_setup) |
b56dedef CF |
1448 | if (givehelp) |
1449 | usage (stdout, 0); | |
1450 | else | |
1451 | usage (stderr, 1); | |
41a0695b | 1452 | |
200f243c CV |
1453 | if ((check_setup || sysinfo || find_package || list_package) && keycheck) |
1454 | usage (stderr, 1); | |
1455 | ||
1456 | if ((find_package || list_package) && check_setup) | |
1457 | usage (stderr, 1); | |
1458 | ||
59a76035 CV |
1459 | if (dump_only && !check_setup) |
1460 | usage (stderr, 1); | |
1461 | ||
200f243c | 1462 | if (find_package && list_package) |
67763c0c | 1463 | usage (stderr, 1); |
1fd5e000 | 1464 | |
41a0695b | 1465 | if (keycheck) |
eedc36cb | 1466 | return check_keys (); |
41a0695b | 1467 | |
1fd5e000 CF |
1468 | init_paths (); |
1469 | ||
200f243c CV |
1470 | /* FIXME: Add help for check_setup and {list,find}_package */ |
1471 | if (argc >= 1 && givehelp && !check_setup && !find_package && !list_package) | |
1fd5e000 | 1472 | { |
200f243c CV |
1473 | printf("Here is where the OS will find your program%s, and which dlls\n", |
1474 | argc > 1 ? "s" : ""); | |
1475 | printf ("will be used for it. Use -v to see DLL version info\n"); | |
1fd5e000 CF |
1476 | |
1477 | if (!sysinfo) | |
1478 | printf ("\n"); | |
1479 | } | |
1480 | ||
d0d51791 | 1481 | if (check_setup) |
1fd5e000 | 1482 | { |
59a76035 | 1483 | dump_setup (verbose, argv, !dump_only); |
200f243c CV |
1484 | } |
1485 | else if (find_package) | |
1486 | { | |
1487 | package_find (verbose, argv); | |
1488 | } | |
1489 | else if (list_package) | |
1490 | { | |
1491 | package_list (verbose, argv); | |
1fd5e000 | 1492 | } |
d0d51791 CF |
1493 | else |
1494 | for (i = 0; i < argc; i++) | |
1495 | { | |
200f243c CV |
1496 | if (i) |
1497 | puts (""); | |
d0d51791 | 1498 | cygcheck (argv[i]); |
d0d51791 | 1499 | } |
1fd5e000 CF |
1500 | |
1501 | if (sysinfo) | |
da9e28d0 CF |
1502 | { |
1503 | dump_sysinfo (); | |
1504 | if (!check_setup) | |
1505 | { | |
e1af9739 | 1506 | puts (""); |
71f90de8 | 1507 | dump_setup (verbose, NULL, false); |
da9e28d0 | 1508 | } |
1fd5e000 | 1509 | |
200f243c CV |
1510 | if (!givehelp) |
1511 | puts ("Use -h to see help about each section"); | |
1512 | } | |
1fd5e000 CF |
1513 | |
1514 | return 0; | |
1515 | } |