Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

346 lines
10 KiB

  1. /* find where the various command arguments are from
  2. *
  3. * HISTORY:
  4. * 25-Jan-2000 a-anurag in the 'found' function changed the printf format of the year in the date from
  5. * %d to %02d and did ptm->tm_year%100 to display the right year in 2 digits.
  6. * 06-Aug-1990 davegi Added check for no arguments
  7. * 03-Mar-1987 danl Update usage
  8. * 17-Feb-1987 BW Move strExeType to TOOLS.LIB
  9. * 18-Jul-1986 DL Add /t
  10. * 18-Jun-1986 DL handle *. properly
  11. * Search current directory if no env specified
  12. * 17-Jun-1986 DL Do look4match on Recurse and wildcards
  13. * 16-Jun-1986 DL Add wild cards to $FOO:BAR, added /q
  14. * 1-Jun-1986 DL Add /r, fix Match to handle pat ending with '*'
  15. * 27-May-1986 MZ Add *NIX searching.
  16. * 30-Jan-1998 ravisp Add /Q
  17. *
  18. */
  19. #define INCL_DOSMISC
  20. #include <sys/types.h>
  21. #include <sys\stat.h>
  22. #include <ctype.h>
  23. #include <stdlib.h>
  24. #include <time.h>
  25. #include <string.h>
  26. #include <stdio.h>
  27. #include <windows.h>
  28. #include <tools.h>
  29. #include <stdarg.h>
  30. // Function Forward Declarations...
  31. void __cdecl Usage( char *, ... );
  32. int found( char * );
  33. int Match( char *, char * );
  34. void look4match( char *, struct findType *, void * );
  35. flagType chkdir( char *, va_list );
  36. char const rgstrUsage[] = {
  37. "Usage: WHERE [/r dir] [/qte] pattern ...\n"
  38. " /r - recurse starting with directory dir\n"
  39. " /q - quiet, use exit code\n"
  40. " /t - times, display size and time\n"
  41. " /e - .EXE, display .EXE type\n"
  42. " /Q - double quote the output\n"
  43. " WHERE bar Find ALL bar along path\n"
  44. " WHERE $foo:bar Find ALL bar along foo\n"
  45. " WHERE /r \\ bar Find ALL bar on current drive\n"
  46. " WHERE /r . bar Find ALL bar recursing on current directory\n"
  47. " WHERE /r d:\\foo\\foo bar Find ALL bar recursing on d:\\foo\\foo\n"
  48. " Wildcards, * ?, allowed in bar in all of above.\n"
  49. };
  50. flagType fQuiet = FALSE; /* TRUE, use exit code, no print out */
  51. flagType fQuote = FALSE; /* TRUE, double quote the output */
  52. flagType fAnyFound = FALSE;
  53. flagType fRecurse = FALSE;
  54. flagType fTimes = FALSE;
  55. flagType fExe = FALSE;
  56. flagType fFound;
  57. flagType fWildCards;
  58. flagType fHasDot;
  59. struct _stat sbuf;
  60. char *pPattern; /* arg to look4match, contains * or ? */
  61. char strDirFileExtBuf[MAX_PATH]; /* fully qualified file name */
  62. char *strDirFileExt = strDirFileExtBuf;
  63. char strBuf[MAX_PATH]; /* hold curdir or env var expansion */
  64. /* Usage takes a variable number of strings, terminated by zero,
  65. e.g. Usage ("first ", "second ", 0);
  66. */
  67. void
  68. __cdecl
  69. Usage(
  70. char *p,
  71. ...
  72. )
  73. {
  74. if (p) {
  75. va_list args;
  76. char *rgstr;
  77. va_start(args, p);
  78. rgstr = p;
  79. fputs("WHERE: ", stdout);
  80. while (rgstr) {
  81. fputs (rgstr, stdout);
  82. rgstr = va_arg(args, char *);
  83. }
  84. fputs ("\n", stdout);
  85. va_end(args);
  86. }
  87. puts(rgstrUsage);
  88. exit (1);
  89. }
  90. int
  91. found (
  92. char *p
  93. )
  94. {
  95. struct _stat sbuf;
  96. struct tm *ptm;
  97. fAnyFound = fFound = TRUE;
  98. if (!fQuiet) {
  99. if (fTimes) {
  100. if ( ( _stat(p, &sbuf) == 0 ) &&
  101. ( ptm = localtime (&sbuf.st_mtime) ) ) {
  102. printf ("% 9ld %2d-%02d-%02d %2d:%02d%c ", sbuf.st_size,
  103. ptm->tm_mon+1, ptm->tm_mday, ptm->tm_year%100,
  104. ( ptm->tm_hour > 12 ? ptm->tm_hour-12 : ptm->tm_hour ),
  105. ptm->tm_min,
  106. ( ptm->tm_hour >= 12 ? 'p' : 'a' ));
  107. } else {
  108. printf(" ? ? ? " );
  109. }
  110. }
  111. if (fExe) {
  112. printf ("%-10s", strExeType(exeType(p)) );
  113. }
  114. if (fQuote) {
  115. printf ("\"%s\"\n", p);
  116. } else {
  117. printf ("%s\n", p );
  118. }
  119. }
  120. return( 0 );
  121. }
  122. int
  123. Match (
  124. char *pat,
  125. char *text
  126. )
  127. {
  128. switch (*pat) {
  129. case '\0':
  130. return *text == '\0';
  131. case '?':
  132. return *text != '\0' && Match (pat + 1, text + 1);
  133. case '*':
  134. do {
  135. if (Match (pat + 1, text))
  136. return TRUE;
  137. } while (*text++);
  138. return FALSE;
  139. default:
  140. return toupper (*text) == toupper (*pat) && Match (pat + 1, text + 1);
  141. }
  142. }
  143. void
  144. look4match (
  145. char *pFile,
  146. struct findType *b,
  147. void *dummy
  148. )
  149. {
  150. char *p = b->fbuf.cFileName;
  151. if (!strcmp (p, ".") || !strcmp (p, "..") || !_strcmpi (p, "deleted"))
  152. return;
  153. /* if pattern has dot and filename does NOT ..., this handles case of
  154. where *. to look for files with no extensions */
  155. if (fHasDot && !*strbscan (p, ".")) {
  156. strcpy (strBuf, p);
  157. strcat (strBuf, ".");
  158. p = strBuf;
  159. }
  160. if (Match (pPattern, p))
  161. found (pFile);
  162. p = b->fbuf.cFileName;
  163. if (fRecurse && TESTFLAG (b->fbuf.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY)) {
  164. p = strend (pFile);
  165. strcat (p, "\\*.*");
  166. forfile (pFile, FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, look4match, NULL);
  167. *p = '\0';
  168. }
  169. }
  170. flagType
  171. chkdir (
  172. char *pDir,
  173. va_list pa
  174. )
  175. /*
  176. pDir == dir name
  177. pa == fileext
  178. */
  179. {
  180. char *pFileExt = va_arg( pa, char* );
  181. if ( strDirFileExt == strDirFileExtBuf &&
  182. strlen(pDir) > sizeof(strDirFileExtBuf) ) {
  183. strDirFileExt = (char *)malloc(strlen(pDir)+1);
  184. if (!strDirFileExt) {
  185. strDirFileExt = strDirFileExtBuf;
  186. return FALSE;
  187. }
  188. }
  189. strcpy (strDirFileExt, pDir);
  190. /* if prefix does not have trailing path char */
  191. if (!fPathChr (strend(strDirFileExt)[-1]))
  192. strcat (strDirFileExt, PSEPSTR);
  193. if (fRecurse || fWildCards) {
  194. pPattern = pFileExt; /* implicit arg to look4match */
  195. strcat (strDirFileExt, "*.*");
  196. forfile(strDirFileExt, FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, look4match, NULL);
  197. } else {
  198. /* if file name has leading path char */
  199. if (fPathChr (*pFileExt))
  200. strcat (strDirFileExt, pFileExt+1);
  201. else
  202. strcat (strDirFileExt, pFileExt);
  203. if (_stat (strDirFileExt, &sbuf) != -1)
  204. found (strDirFileExt);
  205. }
  206. return FALSE;
  207. }
  208. int
  209. __cdecl
  210. main (
  211. int c,
  212. char *v[]
  213. )
  214. {
  215. char *p, *p1, *p2;
  216. char *strDir;
  217. strDir = (char *)malloc(MAX_PATH);
  218. if (!strDir) {
  219. printf("Out of memory\n");
  220. exit(1);
  221. }
  222. ConvertAppToOem( c, v );
  223. SHIFT (c, v);
  224. while (c != 0 && fSwitChr (*(p = *v))) {
  225. while (*++p) {
  226. switch (*p) {
  227. case 'r':
  228. fRecurse = TRUE;
  229. SHIFT (c, v);
  230. if (c) {
  231. if ( rootpath (*v, strDir) ||
  232. GetFileAttributes( strDir ) == -1 ) {
  233. Usage ("Could not find directory ", *v, 0);
  234. }
  235. } else {
  236. Usage ("No directory specified.", 0);
  237. }
  238. break;
  239. case 'q':
  240. fQuiet = TRUE;
  241. break;
  242. case 'Q':
  243. fQuote = TRUE;
  244. break;
  245. case 't':
  246. fTimes = TRUE;
  247. break;
  248. case 'e':
  249. fExe = TRUE;
  250. break;
  251. case '?':
  252. Usage (0);
  253. break;
  254. default:
  255. Usage ("Bad switch: ", p, 0);
  256. }
  257. }
  258. SHIFT (c, v);
  259. }
  260. if (!c)
  261. Usage ("No pattern(s).", 0);
  262. while (c) {
  263. fFound = FALSE;
  264. p = _strlwr (*v);
  265. if (*p == '$') {
  266. if (fRecurse)
  267. Usage ("$FOO not allowed with /r", 0);
  268. if (*(p1=strbscan (*v, ":")) == '\0')
  269. Usage ("Missing \":\" in ", *v, 0);
  270. *p1 = 0;
  271. if ((p2 = getenvOem (_strupr (p+1))) == NULL) {
  272. rootpath (".", strDir);
  273. printf ("WHERE: Warning env variable \"%s\" is NULL, using current dir %s\n",
  274. p+1, strDir);
  275. } else
  276. strcpy (strDir, p2);
  277. *p1++ = ':';
  278. p = p1;
  279. } else if (!fRecurse) {
  280. if ((p2 = getenvOem ("PATH")) == NULL)
  281. rootpath (".", strDir);
  282. else {
  283. //
  284. // if the path is longer than the allocated space for it, make more space
  285. // this is safe, it does not collide with the recurse case where strDir
  286. // is already set to something else
  287. //
  288. unsigned int length = strlen(p2) + 3; // including .; and null
  289. if (length > MAX_PATH) {
  290. strDir = (char *)realloc(strDir, length);
  291. }
  292. strcpy (strDir, ".;");
  293. strcat (strDir, p2);
  294. }
  295. }
  296. /* N.B. if fRecurse, then strDir was set in case 'r' above */
  297. if (!*p)
  298. Usage ("No pattern in ", *v, 0);
  299. /* strDir == cur dir or a FOO expansion */
  300. /* p == filename, may have wild cards */
  301. /* does p contain wild cards */
  302. fWildCards = *strbscan (p, "*?");
  303. fHasDot = *strbscan (p, ".");
  304. if (*(p2 = (strend (strDir) - 1)) == ';')
  305. /* prevents forsemi from doing enum with null str as last enum */
  306. *p2 = '\0';
  307. if (*strDir)
  308. forsemi (strDir, chkdir, p);
  309. if (!fFound && !fQuiet)
  310. printf ("Could not find %s\n", *v);
  311. SHIFT (c, v);
  312. }
  313. return( fAnyFound ? 0 : 1 );
  314. }