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.

947 lines
31 KiB

  1. // Analyses the output from the new chkeckrel
  2. // t-mhills
  3. #include <direct.h>
  4. #include <io.h>
  5. #include <ctype.h>
  6. #include <string.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <errno.h>
  10. #define F_flag 1 //Values to store in the command line switches flag
  11. #define I1_flag 2
  12. #define I2_flag 4
  13. #define X_flag 8
  14. // These codes should match the codes below in the usage description
  15. #define par_err 6 //comand line parameter error exit code 5
  16. #define exep_err 5 //error in the exception file
  17. #define chk_err 4 //error in the one of the source files
  18. #define mem_err 3 //memory allocation error
  19. #define file_err 2 //file find/read error
  20. #define comp_err 1 //comparison found differences
  21. #define no_err 0 // files compared okay
  22. #define exceptionfilelinelength 512 //These value used to control the size of temporary strings
  23. #define chkfilelinelength 2048 //Ideally there would be no limit but file reads require static variables
  24. #define maxpathlength 200
  25. struct translatetable //Used to store translate commands from the exception file.
  26. {
  27. struct translatetable *next;
  28. char *source1name;
  29. char *source2name;
  30. };
  31. struct excludetable //Used to store exclude commands from the exception file.
  32. {
  33. struct excludetable *next;
  34. char *path;
  35. };
  36. struct checksums //Used to store checksums with file names.
  37. {
  38. struct checksums *next;
  39. long sum;
  40. char filename; // This structure is of variable length to accomodate any string length.
  41. };
  42. void error (char exitcode); //Ends program and returns exitcode to the system.
  43. void showchecksumlist (struct checksums *list); //Displays Checksums with filenames.
  44. void showdualchecksumlist (struct checksums *list); //Shows checksums in a format good for missmatched checksums.
  45. char excluded (char *str, struct excludetable *ex); //If any of the exclude strings are in str it returns true.
  46. char *translate (char *str, struct translatetable *tran); //Make a copy of str with changes from exception file.
  47. long readhex (char *str); //Convert hex string to long.
  48. char proccessline (char *tempstr, struct translatetable *translations, struct excludetable *exclusions,
  49. char *startpath, char flags, char **filename, long *filesum);
  50. //Parse line and apply all exceptions and flags
  51. char loadsource1 (char *filename, struct checksums **sums,
  52. struct translatetable *translations, struct excludetable * exclusions,
  53. char *startpath, char flags); //Load source1 into a checksum list.
  54. char comparesource2 (char *filename, struct checksums **sums,
  55. struct checksums **extrasource2, struct checksums **missmatched,
  56. struct translatetable *translations, struct excludetable * exclusions,
  57. char *startpath, char flags); //Compare the second file to the checksum list.
  58. void removewhitespace (char *str); //Removes whitespace from the end of a string.
  59. char *strstrupcase (char *str1, char *str2); //Case insensitive strstr.
  60. char proccess_exception_file (char *filename, struct translatetable **trans, struct excludetable **exclude, char **path);
  61. //Parse exception file.
  62. char proccess_command_line (int argc, char *argv[ ], char **source1, char **source2, char *flags, char **exception);
  63. //Parse command line arguments
  64. void completehelp (); //Show nearly complete documentation
  65. // ******************************** MAIN ***************************
  66. void __cdecl
  67. main(
  68. int argc,
  69. char *argv[ ]
  70. )
  71. {
  72. char errnum = 0;
  73. char *source1filename = NULL;
  74. char *source2filename = NULL;
  75. char *exceptionfilename = NULL;
  76. char flags; // flags: /F=1=(F_flag); /I1=2=(I1_flag); /I2=4=(I2_flag); /X=8=(X_flag)
  77. struct translatetable *translations = NULL; //
  78. struct excludetable *exclusions = NULL; //Information from exception file stored here.
  79. char *startpath = NULL; //
  80. struct checksums *source1checksums = NULL; //List of extra files in Source1
  81. struct checksums *source2checksums = NULL; //List of extra files in Source2
  82. struct checksums *missmatched = NULL; //List of files with chechsums that don't match.
  83. struct translatetable *temp = NULL; //
  84. struct checksums *temp2 = NULL; //Temporary pointers used to help deallocate memory
  85. //Parse command line.
  86. if (errnum = proccess_command_line (argc, argv, &source1filename, &source2filename, &flags, &exceptionfilename))
  87. {
  88. goto freecommandline; // skip to end and deallocate memory
  89. }
  90. //Show information obtained from command line.
  91. printf ("Source1 = %s\n", source1filename);
  92. printf ("Source2 = %s\n", source2filename);
  93. if (flags & F_flag)
  94. printf ("Comparing flat Share.\n");
  95. if (flags & I1_flag)
  96. printf ("Ignoring extra files in Source1.\n");
  97. if (flags & I2_flag)
  98. printf ("Ignoring extra files in Source2.\n");
  99. if (flags & X_flag)
  100. printf ("Exception file = %s\n", exceptionfilename);
  101. //Parse the excpetion file if it exists.
  102. if (flags & X_flag)
  103. {
  104. if (errnum = proccess_exception_file (exceptionfilename, &translations, &exclusions, &startpath))
  105. {
  106. goto freeexceptiontable; //skip to end and dealocate memory
  107. };
  108. //Display information from exception file.
  109. temp = translations;
  110. while (temp != NULL)
  111. {
  112. printf ("TRANSLATE %s --> %s\n", temp->source1name, temp->source2name);
  113. temp = temp->next;
  114. };
  115. temp = (struct translatetable *) exclusions; //note: using wrong type to avoid making another temp pointer
  116. while (temp != NULL)
  117. {
  118. printf ("EXCLUDE %s\n", temp->source1name);
  119. temp = temp->next;
  120. };
  121. if (startpath != NULL)
  122. printf ("STARTPATH %s\n", startpath);
  123. };
  124. //Read source1 and store files and checksums in source1checksums.
  125. if (errnum = loadsource1 (source1filename, &source1checksums, translations, exclusions, startpath, flags))
  126. {
  127. goto freesource1checksums;
  128. };
  129. //printf ("\n\nSource1:\n\n"); //for debugging
  130. //showchecksumlist (source1checksums);
  131. //Read source2 and compare it to the files/checksums from source1. Store differences.
  132. if (errnum = comparesource2 (source2filename, &source1checksums, &source2checksums, &missmatched,
  133. translations, exclusions, startpath, flags))
  134. {
  135. goto freesource2checksums;
  136. };
  137. //Display extra files unless /I1 or /I2 was used in the command line.
  138. if ((!(flags & I1_flag)) & (source1checksums != NULL))
  139. {
  140. errnum = 1;
  141. printf ("\n********** Extra files in %s **********\n", source1filename);
  142. showchecksumlist (source1checksums);
  143. };
  144. if ((!(flags & I2_flag)) & (source2checksums != NULL))
  145. {
  146. errnum = 1;
  147. printf ("\n********** Extra files in %s **********\n", source2filename);
  148. showchecksumlist (source2checksums);
  149. };
  150. //Display missmatched checksums.
  151. if (missmatched != NULL)
  152. {
  153. errnum = 1;
  154. printf ("\n********** Checksums from %s != checksums from %s.**********\n", source1filename, source2filename);
  155. showdualchecksumlist (missmatched);
  156. };
  157. //Deallocate memory.
  158. freesource2checksums:
  159. while (source2checksums != NULL)
  160. {
  161. temp2 = source2checksums;
  162. source2checksums = source2checksums->next;
  163. free (temp2);
  164. };
  165. while (missmatched != NULL)
  166. {
  167. temp2 = missmatched;
  168. missmatched = missmatched->next;
  169. free (temp2);
  170. };
  171. freesource1checksums:
  172. while (source1checksums != NULL)
  173. {
  174. temp2 = source1checksums;
  175. source1checksums = source1checksums->next;
  176. free (temp2);
  177. };
  178. freeexceptiontable:
  179. if (startpath != NULL)
  180. free (startpath);
  181. while (translations != NULL)
  182. {
  183. if (translations->source1name != NULL)
  184. free (translations->source1name);
  185. if (translations->source2name != NULL)
  186. free (translations->source2name);
  187. temp = translations;
  188. translations = translations->next;
  189. free (temp);
  190. };
  191. while (exclusions != NULL)
  192. {
  193. if (exclusions->path != NULL)
  194. free (exclusions->path);
  195. temp = (struct translatetable *) exclusions;
  196. exclusions = exclusions->next;
  197. free (temp);
  198. };
  199. freecommandline:
  200. if (source1filename != NULL)
  201. free (source1filename);
  202. if (source2filename != NULL)
  203. free (source2filename);
  204. if (exceptionfilename != NULL)
  205. free (exceptionfilename);
  206. //End program and show help if needed.
  207. error (errnum);
  208. };
  209. void showchecksumlist (struct checksums *list)
  210. {
  211. while (list != NULL)
  212. {
  213. printf ("%d %s\n", list->sum, &(list->filename));
  214. list = list->next;
  215. };
  216. };
  217. void showdualchecksumlist (struct checksums *list)
  218. //This can only be used with the missmatched checksums list since it assumes that the files
  219. //come in pairs of identical filenames with different checksums.
  220. {
  221. while (list != NULL)
  222. {
  223. if (list->next == NULL)
  224. {
  225. printf ("Error: list corruption detected in showdualchecksumlist function.\n");
  226. return;
  227. };
  228. printf ("%d != %d %s\n", list->sum, list->next->sum, &(list->filename));
  229. list = list->next->next;
  230. };
  231. };
  232. char excluded (char *str, struct excludetable *ex) //If any of the exclude strings are in str it returns true.
  233. {
  234. while (ex != NULL)
  235. {
  236. if (strstr (str, ex->path))
  237. return (1);
  238. ex = ex->next;
  239. }
  240. return (0);
  241. };
  242. char *translate (char *str, struct translatetable *tran)
  243. {
  244. char *temp;
  245. char *newstr;
  246. while (tran != NULL) //Search translate table.
  247. {
  248. if ((temp = strstr (str, tran->source1name)) != NULL) //If we found one that needs translating
  249. {
  250. //Allocate memory for new string.
  251. if ((newstr = malloc (strlen (str) + strlen (tran->source2name) - strlen(tran->source1name) + 1))==NULL)
  252. return (NULL);
  253. strncpy(newstr, str, (size_t)(temp - str)); //Write part before translations.
  254. strcpy (&newstr [temp-str], tran->source2name); //Add translated part
  255. strcat (newstr, &temp [strlen (tran->source1name)]); //Add end of string
  256. return (newstr);
  257. };
  258. tran = tran->next;
  259. };
  260. return (_strdup (str)); //If didn't need to be translated, make a new copy anyway for uniformity.
  261. };
  262. long readhex (char *str)
  263. {
  264. long temp = 0;
  265. int position = 0;
  266. for (position = 0; 1;position++)
  267. {
  268. if ((str[position] == ' ')|(str[position] == '\n')|(str[position] == '\x00'))
  269. {
  270. return (temp);
  271. }
  272. else
  273. {
  274. temp *= 16;
  275. if ((str [position] >= '0') & (str [position] <= '9'))
  276. {
  277. temp+=(str[position]-'0');
  278. }
  279. else if ((str [position] >= 'a') & (str [position] <= 'f'))
  280. {
  281. temp+=(str[position]-'a'+10);
  282. }
  283. else
  284. return (-1);
  285. };
  286. };
  287. };
  288. char proccessline (char *tempstr, struct translatetable *translations, struct excludetable *exclusions,
  289. char *startpath, char flags, char **filename, long *filesum)
  290. {
  291. char *name;
  292. char *newname;
  293. char *sumstr;
  294. *filename = NULL; //Make sure that if no name is returned this is blank
  295. removewhitespace (tempstr);
  296. //If it is a line that says "- N0 files" then the sum is assigned to 0
  297. if ((sumstr = strstr (tempstr, " - No files")) != NULL)
  298. {
  299. *filesum=0;
  300. sumstr [0]=0;
  301. }
  302. //Otherwise find checksum
  303. else
  304. {
  305. sumstr = tempstr + strlen (tempstr); //Find checksum by finding the last space in the line
  306. while ((sumstr [0] != ' ')&(sumstr != tempstr)) //
  307. sumstr--; //
  308. if (sumstr==tempstr) //
  309. {
  310. printf ("Comment: %s", tempstr); //If there is no space before the first character,
  311. return (chk_err); //the line is invalid. Assume it is a comment.
  312. };
  313. sumstr [0] = 0; //Split string into path/filename and checksum
  314. sumstr++; //
  315. //convert checksum string to a number
  316. if ((*filesum = readhex (sumstr))==-1)
  317. {
  318. printf ("Comment: %s %s\n", tempstr, sumstr); //If the checksum isn't a valid hex number
  319. return (chk_err); //assume the line is a commment.
  320. };
  321. };
  322. //Apply any translations that may be valid for this path/file.
  323. if ((name = translate (tempstr, translations)) == NULL)
  324. {
  325. printf ("Need memory.");
  326. return (mem_err);
  327. };
  328. //Make sure this file isn't excluded.
  329. if (!excluded (name, exclusions))
  330. {
  331. //If there isn't a startpath then all files will be proccessed
  332. //If there is a startpath then only the ones containing the path will be proccessed
  333. if (startpath == NULL)
  334. {
  335. newname = name;
  336. goto instartpath;
  337. }
  338. else if ((newname = strstr (name, startpath)) != NULL) //If this file is in startpath
  339. {
  340. newname = newname + strlen (startpath); //Remove startpath
  341. instartpath: //This happens if one of the above conditions was true
  342. //Remove path if doing a flat compare.
  343. if (flags & F_flag)
  344. {
  345. while (strstr (newname, "\\") != NULL) // Remove path
  346. { //
  347. newname = strstr (newname, "\\"); //
  348. newname++; // and leading "\\"
  349. };
  350. };
  351. //Make a final copy of the path/file to return
  352. if ((*filename = _strdup (newname)) == NULL)
  353. {
  354. printf ("Memory err.");
  355. free (name);
  356. return (mem_err);
  357. };
  358. };
  359. };
  360. free (name);
  361. return (0);
  362. };
  363. char loadsource1 (char *filename, struct checksums **sums,
  364. struct translatetable *translations, struct excludetable * exclusions,
  365. char *startpath, char flags)
  366. {
  367. FILE *chkfile;
  368. char tempstr [chkfilelinelength];
  369. char *name;
  370. char err;
  371. long tempsum;
  372. struct checksums *newsum;
  373. struct checksums **last; //Used to keep trak of the end of the linked list.
  374. last = sums;
  375. if ((chkfile = fopen (filename, "r"))==NULL)
  376. {
  377. printf ("Error opening source1.\n\n");
  378. return (file_err);
  379. };
  380. //Proccess all lines
  381. while (fgets (tempstr, chkfilelinelength, chkfile) != NULL)
  382. {
  383. //Verify that the entire line was read in and not just part of it
  384. if (tempstr [strlen (tempstr)-1] != '\n')
  385. {
  386. printf ("Unexpected end of line. chkfilelinelength may need to be larger.\n %s\n", tempstr);
  387. fclose (chkfile);
  388. return (chk_err);
  389. };
  390. //Parse line
  391. if ((err = proccessline (tempstr, translations, exclusions, startpath, flags, &name, &tempsum)) == 0)
  392. {
  393. //If this line was excluded or not in the path don't do anything, just go on to the next line.
  394. if (name != NULL)
  395. {
  396. //Create a new structure and add it to the end of the linked list.
  397. if ((newsum = malloc (sizeof (struct checksums) + strlen (name))) == NULL)
  398. { //Note: this is a variable length structure to fit any size of string.
  399. printf ("Memory err.");
  400. fclose (chkfile);
  401. return (mem_err);
  402. };
  403. *last = newsum;
  404. newsum->next = NULL;
  405. newsum->sum = tempsum;
  406. strcpy(&(newsum->filename), name);
  407. last = &((*last)->next);
  408. //Free temporary storage.
  409. free (name);
  410. };
  411. }
  412. else
  413. {
  414. if (err != chk_err) //Just skip line if it isn't understandable.
  415. {
  416. fclose (chkfile);
  417. return (err);
  418. };
  419. };
  420. };
  421. //Ckeck to make sure it quit because it was done and not because of file errors.
  422. if (ferror (chkfile))
  423. {
  424. printf ("Error reading source1.\n\n");
  425. return (file_err);
  426. };
  427. if (fclose (chkfile))
  428. {
  429. printf ("Error closing source1.\n\nContinuing anyway...");
  430. };
  431. return (0);
  432. };
  433. char notnull_strcmp (struct checksums *sum, char *str)
  434. // perform short circuit evaluation of ((sum != NULL) & (strcmp (&(sum->filename), str) != 0)
  435. {
  436. if (sum != NULL)
  437. {
  438. if (strcmp (&(sum->filename), str) != 0)
  439. {
  440. return (1);
  441. };
  442. };
  443. return (0);
  444. };
  445. char comparesource2 (char *filename, struct checksums **sums,
  446. struct checksums **extrasource2, struct checksums **missmatched,
  447. struct translatetable *translations, struct excludetable * exclusions,
  448. char *startpath, char flags)
  449. {
  450. FILE *chkfile;
  451. char tempstr [chkfilelinelength];
  452. char *name;
  453. char err;
  454. long tempsum;
  455. struct checksums *newsum;
  456. struct checksums *search;
  457. struct checksums **lastlink;
  458. if ((chkfile = fopen (filename, "r"))==NULL)
  459. {
  460. printf ("Error opening source2.\n\n");
  461. return (file_err);
  462. };
  463. while (fgets (tempstr, chkfilelinelength, chkfile) != NULL)
  464. {
  465. //Verify that the entire line was read.
  466. if (tempstr [strlen (tempstr)-1] != '\n')
  467. {
  468. printf ("Unexpected end of line. chkfilelinelength may need to be larger.\n %s\n", tempstr);
  469. fclose (chkfile);
  470. return (chk_err);
  471. };
  472. //Parse line
  473. if ((err = proccessline (tempstr, NULL, exclusions, startpath, flags, &name, &tempsum)) == 0)
  474. {
  475. //If file was skipped do nothing
  476. if (name != NULL)
  477. {
  478. //Prepare to look for a match
  479. search = *sums;
  480. lastlink = sums;
  481. //short circuit evaluation of:(search != NULL) & (strcmp (&(search->filename), name) != 0)
  482. while (notnull_strcmp (search, name))
  483. {
  484. search = search->next;
  485. lastlink = &((*lastlink)->next);
  486. };
  487. if (search != NULL) //If a match was found
  488. { // remove it from the sums list
  489. *lastlink = search->next; // by linking around it
  490. if (search->sum == tempsum) // If checksums match
  491. { //
  492. search->sum=0;
  493. free (search); // Deallocate memory
  494. } //
  495. else // If the checksums didn't match
  496. { //
  497. if ((newsum = malloc (sizeof (struct checksums) + strlen (name))) == NULL)
  498. { // Add 2nd name and checksum to missmatched list
  499. printf ("Memory err."); //
  500. fclose (chkfile); //
  501. return (mem_err); //
  502. }; //
  503. newsum->next = *missmatched; //
  504. newsum->sum = tempsum; //
  505. strcpy(&(newsum->filename), name);
  506. *missmatched = newsum; //
  507. search->next = *missmatched; // Add 1st name to the missmatched list
  508. *missmatched = search; //
  509. }; //
  510. } //
  511. else //If no match was found
  512. { // this needs to be added to extrasource2 list
  513. if ((newsum = malloc (sizeof (struct checksums) + strlen (name))) == NULL)
  514. { //Note: this is a variable length structure to fit any size of string.
  515. printf ("Memory err.");
  516. fclose (chkfile);
  517. return (mem_err);
  518. };
  519. newsum->next = *extrasource2;
  520. newsum->sum = tempsum;
  521. strcpy(&(newsum->filename), name);
  522. *extrasource2 = newsum;
  523. };
  524. //free temporary storage
  525. free (name);
  526. };
  527. }
  528. else
  529. {
  530. if (err != chk_err) //Just skip the line (don't abort) if it is bad
  531. {
  532. fclose (chkfile);
  533. return (err);
  534. };
  535. };
  536. };
  537. if (ferror (chkfile))
  538. {
  539. printf ("Error reading source2.\n\n");
  540. return (file_err);
  541. };
  542. if (fclose (chkfile))
  543. {
  544. printf ("Error closing source2.\n\nContinuing anyway...");
  545. };
  546. return (0);
  547. };
  548. void removewhitespace (char *str) // removes whitespace from the end of a string
  549. {
  550. int end;
  551. end = strlen (str);
  552. while ((end > 0)&((str [end-1] == '\n')|(str [end-1] == ' ')))
  553. end--;
  554. str [end] = 0;
  555. };
  556. char *strstrupcase (char *str1, char *str2)
  557. {
  558. char *temp;
  559. size_t count;
  560. size_t length;
  561. length = strlen (str2);
  562. for (temp = str1; strlen (temp) > length; temp++)
  563. {
  564. for (count = 0; (toupper (temp [count]) == toupper (str2 [count]))&(count < length); count++);
  565. if (count==length)
  566. {
  567. return (temp);
  568. };
  569. };
  570. return (NULL);
  571. };
  572. char proccess_exception_file (char *filename, struct translatetable **trans, struct excludetable **exclude, char **path)
  573. {
  574. FILE *efile;
  575. char tempstr [exceptionfilelinelength];
  576. char *start;
  577. char *end;
  578. struct translatetable *temp;
  579. if ((efile = fopen (filename, "r"))==NULL)
  580. {
  581. printf ("Error opening excetion file.\n\n");
  582. return (file_err);
  583. }
  584. while (fgets (tempstr, exceptionfilelinelength, efile) != NULL)
  585. {
  586. start = tempstr;
  587. while (start [0] == ' ') //Remove leading whitespace
  588. start++;
  589. //If it is a translate command
  590. if (strstrupcase (start, "TRANSLATE") == start)
  591. {
  592. start = start + 10; //Go past translate
  593. while (start [0] == ' ') //skip spaces
  594. start++;
  595. if (start [0] == 0)
  596. {
  597. printf ("Unexpected end of line in exception file:\n%s", tempstr);
  598. return (exep_err);
  599. };
  600. end = strstr (start, "-->"); //Find second part of string
  601. if (end == NULL)
  602. {
  603. printf ("Line: %s \nmust have two file names separated by -->", tempstr);
  604. return (exep_err);
  605. }
  606. end [0] = '\0'; //Split string
  607. removewhitespace (start);
  608. if ((temp = malloc (sizeof (struct translatetable))) == NULL)
  609. {
  610. printf ("Insufficient memory to load exception table.");
  611. return (mem_err);
  612. }
  613. if ((temp->source1name = _strdup (start)) == NULL)
  614. {
  615. printf ("Unable to allocate memory for char temp->source1name in proccess_exception_file.\n");
  616. free (temp);
  617. return (mem_err);
  618. }
  619. start = end + 3;
  620. while (start [0] == ' ') //Remove leading whitespace
  621. start++;
  622. if (start [0] == 0)
  623. {
  624. printf ("Unexpected end of line in exception file:\n %s", tempstr);
  625. free (temp->source1name);
  626. free (temp);
  627. return (exep_err);
  628. };
  629. removewhitespace (start);
  630. if ((temp->source2name = _strdup (start)) == NULL)
  631. {
  632. printf ("Unable to allocate memory for char temp->source1name in proccess_exception_file.\n");
  633. free (temp->source1name);
  634. free (temp);
  635. return (mem_err);
  636. }
  637. temp->next = *trans;
  638. *trans = temp;
  639. }
  640. //If it is an exclude command.
  641. else if (strstrupcase (start, "EXCLUDE") == start)
  642. {
  643. start = start + 7; //Go past exclude
  644. while (start [0] == ' ') //skip spaces
  645. start++;
  646. if (start [0] == 0)
  647. {
  648. printf ("Unexpected end of line in exception file:\n %s", tempstr);
  649. return (exep_err);
  650. };
  651. removewhitespace (start);
  652. if ((temp = malloc (sizeof (struct excludetable))) == NULL)
  653. {
  654. printf ("Insufficient memory to load exception table.");
  655. return (mem_err);
  656. }
  657. if ((temp->source1name = _strdup (start)) == NULL) //source1name coresponds to path
  658. {
  659. printf ("Unable to allocate memory for char temp->path in proccess_exception_file.\n");
  660. free (temp);
  661. return (mem_err);
  662. }
  663. temp->next = (struct translatetable *) *exclude;
  664. *exclude = (struct excludetable *) temp;
  665. }
  666. //If it is a startpath command
  667. else if (strstrupcase (start, "STARTPATH") == start)
  668. {
  669. if (*path != NULL)
  670. {
  671. printf ("Only one STARTPATH command is allowed in the exception file.\n");
  672. return (exep_err);
  673. };
  674. start = start + 9; //Go past startpath
  675. while (start [0] == ' ') //skip spaces
  676. start++;
  677. if (start [0] == 0)
  678. {
  679. printf ("Unexpected end of line in exception file:\n %s", tempstr);
  680. return (exep_err);
  681. };
  682. removewhitespace (start);
  683. if ((*path = _strdup (start)) == NULL)
  684. {
  685. printf ("Unable to allocate memory for char path in proccess_exception_file.\n");
  686. return (mem_err);
  687. }
  688. }
  689. else if (!start [0] == ';') //if it's not a comment
  690. {
  691. printf ("Unexpected line in exception file:\n %s", tempstr);
  692. return (exep_err);
  693. };
  694. };
  695. if (ferror (efile))
  696. {
  697. printf ("Error reading exception file.\n\n");
  698. return (file_err);
  699. };
  700. if (fclose (efile))
  701. {
  702. printf ("Error closing excetion file.\n\nContinuing anyway...");
  703. };
  704. return (0);
  705. };
  706. char proccess_command_line (int argc, char *argv[ ], char **source1, char **source2, char *flags, char **exception)
  707. // flags: /F=1=(F_flag); /I1=2=(I1_flag); /I2=4=(I2_flag); /X=8=(X_flag)
  708. {
  709. int argloop;
  710. *flags=0; //temporarily using 16=source1 found; 32=source2 found
  711. for (argloop = 1;argloop < argc; argloop++)
  712. {
  713. if (argv[argloop][0] == '/')
  714. {
  715. if ((argv[argloop][1] == 'F')|(argv[argloop][1] == 'f')) //we got a /f
  716. {
  717. *flags|=F_flag; //duplicate flags will not cause errors
  718. }
  719. else if (argv[argloop][1] == '?')
  720. {
  721. completehelp ();
  722. }
  723. else if ((argv[argloop][1] == 'I')|(argv[argloop][1] == 'i'))
  724. {
  725. if (argv[argloop][2] == '1')
  726. {
  727. *flags|=I1_flag; //we got a /i1
  728. }
  729. else if (argv[argloop][2] == '2')
  730. {
  731. *flags|=I2_flag; //we got a /i2
  732. }
  733. else
  734. {
  735. printf ("Unknown switch \"/I%c\" .\n\n", argv[argloop][2]);
  736. return (par_err);
  737. }
  738. }
  739. else if ((argv[argloop][1] == 'X')|(argv[argloop][1] == 'x'))
  740. {
  741. *flags|=X_flag; // we got a /x
  742. if (argloop+1 == argc)
  743. {
  744. printf ("Parameter /X must be followed by a filename.\n\n");
  745. return (par_err);
  746. };
  747. if ((*exception = _strdup (argv [argloop + 1]))==NULL)
  748. {
  749. printf ("Unable to allocate memory for char *exception in proccess_command_line.\n");
  750. error (mem_err);
  751. };
  752. argloop++; //to skip this parameter in the general parser
  753. }
  754. else
  755. {
  756. printf ("Unknown switch \"/%c\" .\n\n", argv[argloop][1]);
  757. return (par_err);
  758. }
  759. }
  760. else // it must be a source filename
  761. {
  762. if (!(*flags & 16)) //first source in command line
  763. {
  764. if ((*source1 = _strdup (argv [argloop]))==NULL)
  765. {
  766. printf ("Unable to allocate memory for char *source1 in proccess_command_line.\n");
  767. return (mem_err);
  768. };
  769. *flags|=16;
  770. }
  771. else if (!(*flags & 32)) //second source in command line
  772. {
  773. if ((*source2 = _strdup (argv [argloop]))==NULL)
  774. {
  775. printf ("Unable to allocate memory for char *source2 in proccess_command_line.\n");
  776. return (mem_err);
  777. };
  778. *flags|=32;
  779. }
  780. else
  781. {
  782. printf ("Too many source filenames in the command line.\n\n");
  783. return (par_err);
  784. };
  785. };
  786. };
  787. if (!(*flags & 32))
  788. {
  789. printf ("Command line must contain two source files.\n\n");
  790. return (par_err);
  791. };
  792. *flags|=(!(32+16)); // clear temporary source1 and source2 flags
  793. return (0);
  794. };
  795. void completehelp ()
  796. {
  797. printf ("Usage:\n"
  798. "CHKVERFY <Source1> <Source2> [/F] [/X <exceptionfile>] [/I1] [/I2]\n"
  799. " /F = Flat share (ignore paths).\n"
  800. " /I1 = Ignore extra files in Source1.\n"
  801. " /I2 = Ignore extra files in Source2.\n"
  802. " /X = excetion file with the following commands.\n"
  803. " TRANSLATE <Source1name> --> <Source2name>\n"
  804. " Replaces <Source1name> with <Sourece2name> whereever found.\n"
  805. " Note: make sure the filename you are using is only in the full\n"
  806. " filename of the files you mant to translate.\n\n"
  807. " EXCLUDE <pathsegment>\n"
  808. " Any path and file containing this string will be ignored.\n\n"
  809. " STARTPATH <directory name>\n"
  810. " Files without this string in the path will be ignored.\n"
  811. " The part of the path before this string will be ignored.\n\n"
  812. " Note: These three commands are proccessed in the order shown above. \n"
  813. " For example, the command \"TRANSLATE C:\\nt --> C:\\\" will\n"
  814. " override the command \"EXCLUDE C:\\nt\".\n"
  815. " The order of commands in the exception files doesn't matter\n"
  816. " unless two commands both try to translate the same file.\n"
  817. " In that case, the last command in the file takes precedence.\n"
  818. "Exit codes:\n" // These code values should match the codes defined above.
  819. " 6 = Invalid command line arguments.\n"
  820. " 5 = Error in exception file format.\n"
  821. " 4 = Error in chkfile.\n"
  822. " 3 = Memory allocation error.\n"
  823. " 2 = File access error.\n"
  824. " 1 = No errors: Source1 and Source2 failed compare.\n"
  825. " 0 = No errors: Source1 and Source2 compared successfully.\n\n"
  826. );
  827. exit (0);
  828. };
  829. void error (char exitcode)
  830. {
  831. if (exitcode >= exep_err)
  832. {
  833. printf ("Usage:\n"
  834. "CHKVERFY <Source1> <Source2> [/F] [/X <exceptionfile>] [/I1] [/I2]\n"
  835. " /? = Complete help.\n"
  836. " /F = Flat share (ignore paths).\n"
  837. " /I1 = Ignore extra files in Source1.\n"
  838. " /I2 = Ignore extra files in Source2.\n"
  839. " /X = excetion file with the following commands.\n"
  840. );
  841. };
  842. switch (exitcode)
  843. {
  844. case 0:
  845. printf ("\n\n(0) Files compare okay.\n");
  846. break;
  847. case 1:
  848. printf ("\n\n(1) Some files or checksums don't match.\n");
  849. break;
  850. case 2:
  851. printf ("\n\n(2) Terminated due to file access error.\n");
  852. break;
  853. case 3:
  854. printf ("\n\n(3) Terminated due to memory allocation error.\n");
  855. break;
  856. case 4:
  857. printf ("\n\n(4) The format of the source files was not as expected.\n");
  858. break;
  859. case 5:
  860. printf ("\n\n(5) Error in exception file format.\n");
  861. break;
  862. case 6:
  863. printf ("\n\n(6) Bad command line argument.\n");
  864. break;
  865. };
  866. exit (exitcode);
  867. };