home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 2: PC / frozenfish_august_1995.bin / bbs / d01xx / d0134.lha / Find / find.c < prev    next >
C/C++ Source or Header  |  1988-03-18  |  18KB  |  852 lines

  1. /**********************************************************************/
  2. /*                                                                    */
  3. /* find - Version 1.0                                                 */
  4. /*                                                                    */
  5. /* Copyright (c) 1988 - Rodney Lewis                                  */
  6. /* This program is freely copyable and distributable. All copyrights  */
  7. /* are reserved by the author. You may give copies of this program to */
  8. /* anyone you wish but you may not sell it.                           */
  9. /*                                                                    */
  10. /* Pattern matching routine taken from Matt Dillon's csh program;     */
  11. /* reproduced by permission.                                          */
  12. /*                                                                    */
  13. /**********************************************************************/
  14.  
  15. /**********************************************************************/
  16. /*                                                                    */
  17. /* find    - searches the directory hierachy looking for files that   */
  18. /*           match a given boolean expression. Based  on  the  U**X   */
  19. /*           find command.                                            */
  20. /*                                                                    */
  21. /**********************************************************************/
  22.  
  23. #include <exec/types.h>
  24. #include <exec/memory.h>
  25. #include <libraries/dosextens.h>
  26. #include <stdio.h>
  27. #include <functions.h>
  28.  
  29. #define MAXARGS        20
  30. #define NULL_PRIM    (struct primary *) NULL
  31. #define EQ(x,y)        (strcmp(x, y) == 0)
  32. #define PROTECTION    (FIBF_READ | FIBF_WRITE | FIBF_EXECUTE | FIBF_DELETE)
  33.  
  34. /* boolean expression node structure */
  35.  
  36. struct node {
  37.     unsigned long        type;
  38.     struct node    *first;
  39.     struct node    *second;
  40. };
  41.  
  42. /* Node types - must be different from primary node types (below) */
  43.  
  44. #define OR    0x000000ff
  45. #define AND    0x0000ff00
  46. #define NOT    0x00ff0000
  47.  
  48. /* structure to hold interpreted primary information */
  49.  
  50. struct primary {
  51.     unsigned long        type;
  52.     unsigned long        size;
  53.     char                *data[MAXARGS];
  54. };
  55.  
  56. /* start of compiled expression tree */
  57.  
  58. struct node *node_head;
  59.  
  60. /* Primary types */
  61.  
  62. #define PRINT    0x00000001
  63. #define NAME    0x00000002
  64. #define SIZE    0x00000004
  65. #define TYPE    0x00000008
  66. #define EXEC    0x00000010
  67. #define NEWER    0x00000020
  68. #define MTIME    0x00000040
  69. #define PERM    0x00000080
  70. #define PRIMS    0x0000ffff
  71.  
  72. /* type qualifiers */
  73.  
  74. #define DIRECT    0x00010000        /* directory for -type */
  75. #define PLAIN    0x00020000        /* plain file for -type */
  76. #define PROMPT    0x00040000        /* prompt for EXEC */
  77. #define LT        0x00080000        /* greater than */
  78. #define GT        0x00100000        /* less than */
  79. #define CHAR    0x00200000        /* use characters in -size check */
  80. #define QUALS    0xffff0000
  81.  
  82. int breakflag = FALSE;
  83.  
  84. char path[80] = "";                /* memory to hold full path name */
  85. struct DateStamp date;
  86.  
  87. /* manx releases the memory allocated by calloc when you call exit() */
  88.  
  89. extern char        *calloc();
  90.  
  91. main(argc, argv)
  92. int argc;
  93. char *argv[];
  94. {
  95.     register struct FileLock *start;
  96.     register i;
  97.     extern struct node *compile();
  98.  
  99.     DateStamp(&date);
  100.  
  101.     /* must be at least three arguments */
  102.  
  103.     if (argc < 3) {
  104.         fprintf(stderr, "Usage: find <path-list> <expression>\n");
  105.         exit(1);
  106.     }
  107.  
  108.     /* find the start of the boolean expression */
  109.  
  110.     for (i = 1 ; argv[i][0] != '-' && argv[i][0] != '!' && argv[i][0] != '(' ; i++);
  111.     if (i == 1) {
  112.         /* no path name list */
  113.         fprintf(stderr, "Usage: find <path-list> <expression>\n");
  114.         exit(1);
  115.     }
  116.  
  117.     /* compile the boolean expression */
  118.  
  119.     if (node_head = compile(argc - i, &argv[i])) {
  120.  
  121.         /* search each path-name specified */
  122.  
  123.         for (i = 1 ; argv[i][0] != '-' && argv[i][0] != '!' && argv[i][0] != '(' ; ++i) {
  124.             start = Lock(argv[i], ACCESS_READ);
  125.             if (start == NULL) {
  126.                 fprintf(stderr, "can't access '%s'\n", argv[i]);
  127.                 continue;
  128.             }
  129.  
  130.             search(start);
  131.             UnLock(start);
  132.         }
  133.     }
  134.  
  135.     exit(0);
  136. }
  137.  
  138. /* search the given directory and for each file
  139.  * execute the boolean expression.
  140.  */
  141.  
  142. search(lock)
  143. register struct FileLock *lock;
  144. {
  145.     register struct FileInfoBlock *fib;
  146.     register struct FileLock *nlock;
  147.     char *prev, file[80];
  148.  
  149.     fib = (struct FileInfoBlock *) AllocMem((long) sizeof(struct FileInfoBlock), MEMF_CLEAR);
  150.     if (fib == NULL) {
  151.         fprintf(stderr, "can't allocate file info block\n");
  152.         return(0);
  153.     }
  154.  
  155.     /* save current position in full path name */
  156.  
  157.     prev = path + strlen(path);
  158.  
  159.     if (*path == '\0' && pwd(ParentDir(lock)) == 0) {
  160.         FreeMem(fib, (long) sizeof(struct FileInfoBlock));
  161.         return(0);
  162.     }
  163.  
  164.     /* examine initial path name */
  165.  
  166.     if (Examine(lock, fib)) {
  167.  
  168.         /* execute the expression on the inital path */
  169.  
  170.         execute(node_head, fib);
  171.  
  172.         if (fib->fib_DirEntryType > 0) {
  173.  
  174.             /* set up printable path name */
  175.  
  176.             if (*path) {
  177.                 strcat(path, fib->fib_FileName);
  178.                 strcat(path, "/");
  179.             }
  180.             else if (pwd(lock) == 0) {
  181.                 *prev = '\0';
  182.                 FreeMem(fib, (long) sizeof(struct FileInfoBlock));
  183.                 return(0);
  184.             }
  185.         }
  186.  
  187.         else {
  188.  
  189.             /* if initial path name is not a directory then we just return */
  190.  
  191.             *prev = '\0';
  192.             FreeMem(fib, (long) sizeof(struct FileInfoBlock));
  193.             return(0);
  194.         }
  195.  
  196.         /* examine directory contents */
  197.  
  198.         while(ExNext(lock, fib)) {
  199.             if (breakflag) break;
  200.  
  201.             /* recurse if we have found a directory */
  202.  
  203.             if (fib->fib_DirEntryType > 0) {
  204.                 strcpy(file, path);
  205.                 strcat(file, fib->fib_FileName);
  206.                 nlock = Lock(file, ACCESS_READ);
  207.                 if (nlock == NULL)
  208.                     fprintf(stderr, "locking error - %s\n", file);
  209.                 else {
  210.                     search(nlock);
  211.                     UnLock(nlock);
  212.                 }
  213.             }
  214.             else
  215.                 execute(node_head, fib);
  216.  
  217.             if (SetSignal(0L, 0L) & SIGBREAKF_CTRL_C) {
  218.                 breakflag = TRUE;
  219.                 break;
  220.             }
  221.         }
  222.     }
  223.  
  224.     *prev = '\0';
  225.     FreeMem(fib, (long) sizeof(struct FileInfoBlock));
  226. }
  227.  
  228. /* execute the boolean expression on the given file */
  229.  
  230. execute(cnode, fib)
  231. struct node *cnode;
  232. struct FileInfoBlock *fib;
  233. {
  234.     register struct primary *prim;
  235.     register long checksize;
  236.     register j;
  237.     register struct DateStamp *ds;
  238.     char file[80], ok[10];
  239.     char *av[MAXARGS];
  240.  
  241.     /* check node type */
  242.  
  243.     if (cnode->type == AND)
  244.         if  (execute(cnode->first, fib))
  245.             return(execute(cnode->second, fib));
  246.         else
  247.             return(0);
  248.  
  249.     else if (cnode->type == OR)
  250.         if  (execute(cnode->first, fib))
  251.             return(1);
  252.         else
  253.             return(execute(cnode->second, fib));
  254.  
  255.     else if (cnode->type == NOT)
  256.         return(!execute(cnode->first, fib));
  257.  
  258.     else {
  259.  
  260.         /* we have an actual primary */
  261.  
  262.         prim = (struct primary *) cnode;
  263.         switch (prim->type & PRIMS) {
  264.  
  265.         case PRINT:
  266.  
  267.             if (*path)
  268.                 printf("%s%s\n", path, fib->fib_FileName);
  269.             else
  270.                 printf("%s:\n", fib->fib_FileName);
  271.             return(1);
  272.  
  273.         case NAME:
  274.  
  275.             if (compare_ok(prim->data[0], fib->fib_FileName))
  276.                 return(1);
  277.             else
  278.                 return(0);
  279.  
  280.         case SIZE:
  281.  
  282.             if (prim->type & CHAR)
  283.                 checksize = fib->fib_Size;
  284.             else
  285.                 checksize = fib->fib_NumBlocks;
  286.  
  287.             if (((prim->type & GT) && (checksize > prim->size) ) ||
  288.                 ((prim->type & LT) && (checksize < prim->size) ) ||
  289.                 ((prim->type & (GT | LT)) == 0 && (checksize == prim->size)))
  290.                 return(1);
  291.             else
  292.                 return(0);
  293.  
  294.         case TYPE:
  295.  
  296.             switch (prim->type & QUALS | (fib->fib_DirEntryType > 0)) {
  297.  
  298.             case DIRECT:
  299.             case (PLAIN | 1):
  300.                 return(0);
  301.  
  302.             default:
  303.                 return(1);
  304.             }
  305.  
  306.         case EXEC:
  307.  
  308.             for (j = 0 ; prim->data[j] ; j++)
  309.                 if (EQ("{}", prim->data[j])) {
  310.                     strcpy(file, path);
  311.                     strcat(file, fib->fib_FileName);
  312.                     av[j] = file;
  313.                 }
  314.                 else
  315.                     av[j] = prim->data[j];
  316.             av[j] = NULL;
  317.  
  318.             if (!(prim->type & PROMPT) || (pr_cmd(av) && gets(ok) &&
  319.                  ((ok[0] == 'y') || (ok[0] == 'Y')))) {
  320.                 if (fexecv(av[0], av) == -1)
  321.                     return(0);
  322.                 else if (wait())
  323.                     return(0);
  324.                 else
  325.                     return(1);
  326.             }
  327.  
  328.         case NEWER:
  329.  
  330.             ds = (struct DateStamp *) prim->data[0];
  331.             if (fib->fib_Date.ds_Days > ds->ds_Days)
  332.                 return(1);
  333.             else if (fib->fib_Date.ds_Days == ds->ds_Days &&
  334.                      fib->fib_Date.ds_Minute > ds->ds_Minute)
  335.                 return(1);
  336.             else if (fib->fib_Date.ds_Days == ds->ds_Days &&
  337.                      fib->fib_Date.ds_Minute == ds->ds_Minute &&
  338.                      fib->fib_Date.ds_Tick > ds->ds_Tick)
  339.                 return(1);
  340.             else
  341.                 return(0);
  342.  
  343.         case MTIME:
  344.  
  345.             checksize = date.ds_Days - fib->fib_Date.ds_Days;
  346.  
  347.             if (((prim->type & GT) && (checksize > prim->size) ) ||
  348.                 ((prim->type & LT) && (checksize < prim->size) ) ||
  349.                 ((prim->type & (GT | LT)) == 0 && (checksize == prim->size)))
  350.                 return(1);
  351.             else
  352.                 return(0);
  353.  
  354.         case PERM:
  355.  
  356.             if ((fib->fib_Protection & PROTECTION) == prim->size)
  357.                 return(1);
  358.             else
  359.                 return(0);
  360.  
  361.         }
  362.         return(0);
  363.     }
  364. }
  365.  
  366. /* print the command to be executed on the screen */
  367.  
  368. pr_cmd(av)
  369. char *av[];
  370. {
  371.     register j;
  372.  
  373.     printf("< ");
  374.     for (j = 0 ; av[j] ; j++) printf("%s ", av[j]);
  375.     printf("> ? ");
  376.     return(1);
  377. }
  378.  
  379. /* compile the boolean expression: returns a pointer to the start
  380.  * of the compiled expression tree, or NULL if a failure occurs.
  381.  */
  382.  
  383. struct node *
  384. compile(argc, argv)
  385. int argc;
  386. char *argv[];
  387. {
  388.     register i, j, scan;
  389.     register struct primary *prim;
  390.     register struct node *node_head = (struct node *) NULL, *tmp_node;
  391.  
  392.     for(i = 0 ; i < argc ; i++) {
  393.  
  394.         prim = (struct primary *) calloc(1, sizeof(struct primary));
  395.         if (prim == NULL_PRIM) {
  396.             fprintf(stderr, "out memory in primary interpretation\n");
  397.             exit(5);
  398.         }
  399.  
  400.  
  401.         if (EQ("-o", argv[i])) {
  402.             free(prim);
  403.  
  404.             /* -o cannot be the first argument */
  405.  
  406.             if (node_head == NULL_PRIM) {
  407.                 fprintf(stderr, "misplaced 'or' operator ... ignored\n");
  408.                 continue;
  409.             }
  410.  
  411.             else {
  412.  
  413.                 /* create OR node */
  414.  
  415.                 tmp_node = (struct node *) calloc(1, sizeof(struct node));
  416.                 if (tmp_node == NULL) {
  417.                     fprintf(stderr, "out of memory in expression compilation");
  418.                     exit(5);
  419.                 }
  420.                 tmp_node->type = OR;
  421.                 tmp_node->first = node_head;
  422.  
  423.                 /* compile rest of expression and attach it to OR node */
  424.  
  425.                 if ((tmp_node->second = compile(argc - i - 1, argv + i + 1)) == NULL) {
  426.                     free(tmp_node);
  427.                     return(node_head);
  428.                 }
  429.                 else
  430.                     return(tmp_node);
  431.             }
  432.         }
  433.  
  434.         else if (EQ("(", argv[i])) {
  435.             free(prim);
  436.  
  437.             /* scan to matching brackets */
  438.  
  439.             for (j = 0, scan = 0 ; ++i < argc && (!EQ(")", argv[i]) || scan != 0) ; j++) {
  440.                 if (EQ("(", argv[i])) scan++;
  441.                 if (EQ(")", argv[i])) scan--;
  442.             }
  443.  
  444.             if (i >= argc) {
  445.                 fprintf(stderr, "unmatched bracket\n");
  446.                 exit(5);
  447.             }
  448.  
  449.             if (j == 0) {
  450.                 fprintf(stderr, "empty brackets ... ignored\n");
  451.                 continue;
  452.             }
  453.  
  454.             /* compile what is in the brackets */
  455.  
  456.             if ((prim = (struct primary *) compile(j, argv + i - j)) == NULL)
  457.                 continue;
  458.         }
  459.  
  460.         else if (EQ("!", argv[i])) {
  461.             if (++i >= argc) {
  462.                 fprintf(stderr, "trailing '!' ignored\n");
  463.                 continue;
  464.             }
  465.             if (EQ("-o", argv[i])) {
  466.                 fprintf(stderr, "illegal 'or' operator placement\n");
  467.                 exit(5);
  468.             }
  469.  
  470.             tmp_node = (struct node *) calloc(1, sizeof(struct node));
  471.             if (tmp_node == NULL) {
  472.                 fprintf(stderr, "out of memory in expression compilation\n");
  473.                 exit(5);
  474.             }
  475.             tmp_node->type = NOT;
  476.  
  477.             if (EQ("(", argv[i])) {
  478.  
  479.                 /* scan to matching bracket */
  480.  
  481.                 for (j = 0, scan = 0 ; ++i < argc && (!EQ(")", argv[i]) || scan != 0) ; j++) {
  482.                     if (EQ("(", argv[i])) scan++;
  483.                     if (EQ(")", argv[i])) scan--;
  484.                 }
  485.  
  486.                 if (i >= argc) {
  487.                     fprintf(stderr, "unmatched bracket\n");
  488.                     exit(5);
  489.                 }
  490.  
  491.                 if (j == 0) {
  492.                     fprintf(stderr, "empty brackets ... ignored\n");
  493.                     free(tmp_node);
  494.                     continue;
  495.                 }
  496.  
  497.                 /* compile what is in the brackets */
  498.  
  499.                 if ((tmp_node->first = compile(j, argv + i - j)) == NULL)
  500.                     continue;
  501.             }
  502.             else {
  503.                 tmp_node->first = (struct node *) prim;
  504.                 i += interpret(prim, argc - i, argv + i);
  505.             }
  506.             prim = (struct primary *) tmp_node;
  507.         }
  508.  
  509.         else
  510.             i += interpret(prim, argc - i, argv + i);
  511.  
  512.         /* attach interpreted primary to expression tree */
  513.  
  514.         if (node_head == NULL)
  515.             node_head = (struct node *) prim;
  516.         else {
  517.             tmp_node = (struct node *) calloc(1, sizeof(struct node));
  518.             if (tmp_node == NULL) {
  519.                 fprintf(stderr, "out of memory in expression compilation\n");
  520.                 exit(5);
  521.             }
  522.             tmp_node->type   = AND;
  523.             tmp_node->first  = node_head;
  524.             tmp_node->second = (struct node *) prim;
  525.             node_head        = tmp_node;
  526.         }
  527.     }
  528.  
  529.     return(node_head);
  530. }
  531.  
  532. /* interpret a primary */
  533.  
  534. interpret(prim, argc, argv)
  535. struct primary *prim;
  536. char *argv[];
  537. {
  538.     register i, j;
  539.     register struct FileLock *lock;
  540.     register struct FileInfoBlock *fib;
  541.     register struct DateStamp *ds;
  542.     char *numstr;
  543.     extern unsigned long atol();
  544.  
  545.     for (i = 0 ; i < argc ; i++) {
  546.  
  547.         if (EQ("-print", argv[i]))
  548.             prim->type = PRINT;
  549.  
  550.         else if (EQ("-name", argv[i])) {
  551.             prim->type = NAME;
  552.             prim->data[0] = argv[++i];
  553.         }
  554.  
  555.         else if (EQ("-size", argv[i])) {
  556.             prim->type = SIZE;
  557.  
  558.             /* get required size */
  559.  
  560.             numstr = argv[++i];
  561.  
  562.             if (*numstr == '+') {
  563.                 prim->type |= GT;
  564.                 numstr++;
  565.             }
  566.  
  567.             else if (*numstr == '-') {
  568.                 prim->type |= LT;
  569.                 numstr++;
  570.             }
  571.  
  572.             if (numstr[strlen(numstr) - 1] == 'c') {
  573.                 prim->type |= CHAR;
  574.                 numstr[strlen(numstr) - 1] == '\0';
  575.             }
  576.  
  577.             prim->size = atol(numstr);
  578.         }
  579.  
  580.         else if (EQ("-type", argv[i])) {
  581.             prim->type = TYPE;
  582.             if (EQ(argv[++i], "d"))
  583.                 prim->type |= DIRECT;
  584.             else if (EQ(argv[i], "f"))
  585.                 prim->type |= PLAIN;
  586.             else {
  587.                 fprintf(stderr, "illegal file type specified\n");
  588.                 exit(5);
  589.             }
  590.         }
  591.  
  592.         else if (EQ("-exec", argv[i])) {
  593.             prim->type = EXEC;
  594.  
  595.             /* scan to ending ';', saving pointers to arguments */
  596.  
  597.             for (j=0 ; (j<MAXARGS) && (++i < argc) && !EQ(";",argv[i]) ; j++)
  598.                 prim->data[j] = argv[i];
  599.  
  600.             if (i >= argc) {
  601.                 fprintf(stderr, "no ending ';' on command\n");
  602.                 exit(5);
  603.             }
  604.  
  605.             else if (j >= MAXARGS) {
  606.                 fprintf(stderr, "command too long\n");
  607.                 exit(5);
  608.             }
  609.  
  610.             else
  611.                 argv[j] = NULL;
  612.         }
  613.  
  614.         else if (EQ("-ok", argv[i])) {
  615.             prim->type = EXEC | PROMPT;
  616.  
  617.             /* scan to ending ';', saving pointers to arguments */
  618.  
  619.             for (j=0 ; (j<MAXARGS) && (++i < argc) && !EQ(";",argv[i]) ; j++)
  620.                 prim->data[j] = argv[i];
  621.  
  622.             if (i >= argc) {
  623.                 fprintf(stderr, "no ending ';' on command\n");
  624.                 exit(5);
  625.             }
  626.  
  627.             else if (j >= MAXARGS) {
  628.                 fprintf(stderr, "command too long\n");
  629.                 exit(5);
  630.             }
  631.  
  632.             else
  633.                 argv[j] = NULL;
  634.         }
  635.  
  636.         else if (EQ("-newer", argv[i])) {
  637.             prim->type = NEWER;
  638.  
  639.             if (lock = Lock(argv[++i])) {
  640.                 fib = (struct FileInfoBlock *) AllocMem((long) sizeof(struct FileInfoBlock), MEMF_CLEAR);
  641.                 if (fib == NULL) {
  642.                     fprintf(stderr, "no mem for -newer test\n");
  643.                     UnLock(lock);
  644.                     exit(5);
  645.                 }
  646.  
  647.                 if (Examine(lock, fib) == 0) {
  648.                     fprintf(stderr, "could not examine %s\n", argv[i]);
  649.                     FreeMem(fib, (long) sizeof(struct FileInfoBlock));
  650.                     UnLock(lock);
  651.                     exit(5);
  652.                 }
  653.  
  654.                 /* save date stamp of given file */
  655.  
  656.                 ds = (struct DateStamp *) calloc(1, sizeof(struct DateStamp));
  657.                 if (ds == NULL) {
  658.                     fprintf(stderr, "no mem for DateStamp on %s\n", argv[i]);
  659.                     FreeMem(fib, (long) sizeof(struct FileInfoBlock));
  660.                     UnLock(lock);
  661.                     exit(5);
  662.                 }
  663.  
  664.                 prim->data[0] = (char *) ds;
  665.                 *ds = fib->fib_Date;
  666.  
  667.                 FreeMem(fib, (long) sizeof(struct FileInfoBlock));
  668.                 UnLock(lock);
  669.             }
  670.  
  671.             else {
  672.                 fprintf(stderr, "unable to access %s\n", argv[i]);
  673.                 exit(5);
  674.             }
  675.         }
  676.  
  677.         else if (EQ("-mtime", argv[i])) {
  678.             prim->type = MTIME;
  679.  
  680.             /* get required number of days */
  681.  
  682.             numstr = argv[++i];
  683.  
  684.             if (*numstr == '+') {
  685.                 prim->type |= GT;
  686.                 numstr++;
  687.             }
  688.             else if (*numstr == '-') {
  689.                 prim->type |= LT;
  690.                 numstr++;
  691.             }
  692.  
  693.             prim->size = atol(numstr);
  694.         }
  695.  
  696.         else if (EQ("-perm", argv[i])) {
  697.             prim->type = PERM;
  698.             prim->size = PROTECTION;
  699.  
  700.             /* assemble desired protection bits */
  701.  
  702.             for(i++, j = 0 ; argv[i][j] ; j++) {
  703.                 switch(argv[i][j]) {
  704.  
  705.                 case 'n':
  706.                     prim->size = PROTECTION;
  707.                     return(i);
  708.  
  709.                 case 'r':
  710.                     prim->size &= ~FIBF_READ;
  711.                     break;
  712.  
  713.                 case 'w':
  714.                     prim->size &= ~FIBF_WRITE;
  715.                     break;
  716.  
  717.                 case 'e':
  718.                     prim->size &= ~FIBF_EXECUTE;
  719.                     break;
  720.  
  721.                 case 'd':
  722.                     prim->size &= ~FIBF_DELETE;
  723.                     break;
  724.  
  725.                 default:
  726.                     fprintf(stderr, "unknown code '%c' ... ignored\n", argv[i][j]);
  727.                     break;
  728.                 }
  729.             }
  730.         }
  731.  
  732.         else {
  733.             fprintf(stderr, "unknown primary: %s\n", argv[i]);
  734.             exit(5);
  735.         }
  736.  
  737.         return(i);
  738.     }
  739. }
  740.  
  741. /* find the full path name of the given lock */
  742.  
  743. pwd(dir)
  744. register struct FileLock *dir;
  745. {
  746.     register struct FileLock *par;
  747.     register struct FileInfoBlock *fib;
  748.  
  749.     if (dir == NULL) {
  750.         *path = '\0';
  751.         return(1);
  752.     }
  753.  
  754.     fib = (struct FileInfoBlock *) AllocMem((long) sizeof(struct FileInfoBlock), MEMF_CLEAR);
  755.     if (fib == NULL) {
  756.         fprintf(stderr, "pwd: can't allocate a FileInfoBlock\n");
  757.         return(0);
  758.     }
  759.  
  760.     if (!Examine(dir, fib)) {
  761.         fprintf(stderr, "pwd: examine failed\n");
  762.         FreeMem(fib, (long) sizeof(struct FileInfoBlock));
  763.         return(0);
  764.     }
  765.  
  766.     if (par = ParentDir(dir)) {
  767.  
  768.         /* find full path name of parent */
  769.  
  770.         if (pwd(par) == 0) {
  771.             FreeMem(fib, (long) sizeof(struct FileInfoBlock));
  772.             return(0);
  773.         }
  774.  
  775.         /* add current name */
  776.  
  777.         strcat(path, fib->fib_FileName);
  778.         strcat(path, "/");
  779.     }
  780.     else {
  781.  
  782.         /* found the root name */
  783.  
  784.         strcpy(path, fib->fib_FileName);
  785.         strcat(path, ":");
  786.     }
  787.  
  788.     FreeMem(fib, (long) sizeof(struct FileInfoBlock));
  789.     return(1);
  790. }
  791.  
  792. /*
  793.  * Compare a wild card name with a normal name.
  794.  * Taken from Matt Dillon's csh program.
  795.  */
  796.  
  797. #define MAXB   8
  798.  
  799. compare_ok(wild, name)
  800. char *wild, *name;
  801. {
  802.    register char *w = wild;
  803.    register char *n = name;
  804.    char *back[MAXB][2];
  805.    register char s1, s2;
  806.    int    bi = 0;
  807.  
  808.    while (*n || *w) {
  809.       switch (*w) {
  810.       case '*':
  811.      if (bi == MAXB) {
  812.         fprintf(stderr,"Too many levels of '*'\n");
  813.         return (0);
  814.      }
  815.      back[bi][0] = w;
  816.      back[bi][1] = n;
  817.      ++bi;
  818.      ++w;
  819.      continue;
  820. goback:
  821.      --bi;
  822.      while (bi >= 0 && *back[bi][1] == '\0')
  823.         --bi;
  824.      if (bi < 0)
  825.         return (0);
  826.      w = back[bi][0] + 1;
  827.      n = ++back[bi][1];
  828.      ++bi;
  829.      continue;
  830.       case '?':
  831.      if (!*n) {
  832.         if (bi)
  833.            goto goback;
  834.         return (0);
  835.      }
  836.      break;
  837.       default:
  838.      s1 = (*n >= 'A' && *n <= 'Z') ? *n - 'A' + 'a' : *n;
  839.      s2 = (*w >= 'A' && *w <= 'Z') ? *w - 'A' + 'a' : *w;
  840.      if (s1 != s2) {
  841.         if (bi)
  842.            goto goback;
  843.         return (0);
  844.      }
  845.      break;
  846.       }
  847.       if (*n)  ++n;
  848.       if (*w)  ++w;
  849.    }
  850.    return (1);
  851. }
  852.