home *** CD-ROM | disk | FTP | other *** search
/ Network Support Encyclopedia 96-1 / novell-nsepro-1996-1-cd2.iso / download / netware / xdir1.exe / DIR.C next >
Text File  |  1995-08-29  |  13KB  |  556 lines

  1. /****************************************************************************
  2. **    File:    DIR.C
  3. **
  4. **    Desc:    Sample code showing how to do a recursive subdirectory search.
  5. **
  6. **    Disclaimer:
  7. **
  8. **        Novell, Inc. makes no representations or warranties with respect to
  9. **        any NetWare software, and specifically disclaims any express or
  10. **        implied warranties of merchantability, title, or fitness for a
  11. **        particular purpose.  
  12. **
  13. **        Distribution of any NetWare software is forbidden without the
  14. **        express written consent of Novell, Inc.  Further, Novell reserves
  15. **        the right to discontinue distribution of any NetWare software.
  16. **
  17. **        Novell is not responsible for lost profits or revenue, loss of use
  18. **        of the software, loss of data, costs of re-creating lost data, the
  19. **        cost of any substitute equipment or program, or claims by any party
  20. **        other than you.  Novell strongly recommends a backup be made before
  21. **        any software is installed.   Developer support for this software
  22. **        may be provided at the discretion of Novell.
  23. **
  24. **    QMK386 options used:
  25. **
  26. **        None
  27. **
  28. **    Programmers:
  29. **
  30. **        Ini    Who                    Firm
  31. **        -----------------------------------------------------------------------
  32. **        ABJ    Adam B. Jerome        Novell Developer Support.
  33. **
  34. **    History:
  35. **
  36. **        When        Who    What
  37. **        -----------------------------------------------------------------------
  38. **        08-28-95    ABJ    First code.
  39. */
  40.  
  41. /****************************************************************************
  42. **    Compiler setup
  43. */
  44.     /*------------------------------------------------------------------------
  45.     **    ANSI
  46.     */
  47.     #include <stdlib.h>     /* malloc() free() */
  48.     #include <stdio.h>     /*    stdout, vfprintf(), printf() */
  49.     #include <string.h>     /*    strrchr(), strupr(), strlen(), strcat(), strcpy() */
  50.     #include <errno.h>   /*    ESUCCESS, ENOMEM, EFAILURE, errno */
  51.     #include <stdarg.h>     /*    va_list */
  52.     #include <conio.h>     /* kbhit(), getch() */
  53.     #include <signal.h>     /*    signal(), SIGTERM, SIGINT */
  54.  
  55.     /*------------------------------------------------------------------------
  56.     **    NetWare
  57.     */
  58.     #include <nwdir.h>         /*    opendir(), readdir(), closedir(), DIR, _A_NORMAL, ...*/
  59.     #include <niterror.h>     /* NetWareErrno */
  60.     #include <process.h>     /* ThreadSwitchWithDelay() */
  61.  
  62. /****************************************************************************
  63. ** Globals
  64. */
  65. int    NLM_exiting      =    FALSE;
  66. int    NLM_threadCnt    =    0;
  67. int    NLM_pause         =    FALSE;
  68. int    NLM_subSearch    =    FALSE;
  69.  
  70. /****************************************************************************
  71. ** Paste two path fragments into a malloced buffer.
  72. */
  73. char *NLM_PastePath(char *frag1, char *frag2)
  74.    {
  75.    char *cp;
  76.    char *fullPath;
  77.  
  78.    fullPath=malloc(strlen(frag1) + 1 + strlen(frag2) + 1);
  79.    if(fullPath == NULL) return(NULL);
  80.  
  81.    strcpy(fullPath, frag1);
  82.    
  83.    /*------------------------------------------------------------------------
  84.    ** Locate the last character of the string.
  85.    */
  86.    cp=fullPath;
  87.    while(*cp) ++cp;
  88.    if(cp > fullPath) --cp;
  89.  
  90.    if((*cp != '\\') && (*cp != '/') && (*cp != ':') && (*fullPath != '\0'))
  91.       strcat(fullPath, "\\");
  92.  
  93.    strcat(fullPath, frag2);
  94.  
  95.    return(fullPath);
  96.    }
  97.  
  98. /****************************************************************************
  99. ** Parse the specified path into drive:path and wildcard.
  100. */
  101. int NLM_ParsePath(char *fullPath, char **path, char **wild)
  102.    {
  103.    int   cCode=ESUCCESS;
  104.     char *cp;
  105.    char  ch;
  106.  
  107.    cp=strrchr(fullPath, '\\');
  108.    if(cp==NULL) cp=strrchr(fullPath, '/');
  109.    if(cp==NULL) cp=strrchr(fullPath, ':');
  110.    
  111.    /*-----------------------------------------------------------------------
  112.    ** No path, just a wild.
  113.    */
  114.    if(cp == NULL)
  115.       {
  116.       *path=malloc(1);
  117.       if(*path == NULL)
  118.             {
  119.             cCode=ENOMEM;
  120.             goto END;
  121.             }
  122.  
  123.       **path='\0';
  124.       *wild=malloc(strlen(fullPath)+1);
  125.       if(*wild == NULL)
  126.          {
  127.          free(*path);
  128.             cCode=ENOMEM;
  129.          goto END;
  130.          }
  131.       strcpy(*wild, fullPath);
  132.       goto END;
  133.       }
  134.  
  135.    *wild=malloc(strlen(&cp[1]) +1);
  136.    if(*wild == NULL)
  137.         {
  138.         cCode=ENOMEM;
  139.         goto END;
  140.         }
  141.  
  142.    strcpy(*wild, &cp[1]);
  143.  
  144.    if((*cp == '\\') || (*cp == '/'))
  145.       if(cp > fullPath)
  146.          {
  147.          --cp;
  148.          if(*cp == ':') cp += 2;
  149.          else ++cp;
  150.          }
  151.  
  152.    ch = *cp;
  153.    *cp = '\0';
  154.  
  155.    *path=malloc(strlen(fullPath) + 1 + 1);
  156.    if(*path == NULL)
  157.       {
  158.       free(*wild);
  159.       cCode=ENOMEM;
  160.         goto END;
  161.       }
  162.    strcpy(*path, fullPath);
  163.    *cp=ch;
  164.  
  165. END:
  166.  
  167.     if(cCode == ESUCCESS)
  168.         {
  169.         strupr(*path);
  170.         strupr(*wild);
  171.         }
  172.  
  173.    return(cCode);
  174.    }
  175.  
  176. /****************************************************************************
  177. **    Print a line on the screen, printf() compatable.
  178. */
  179. int NLM_PrintLine(char *format, ...)
  180.     {
  181.     int charCnt;
  182.     int ch;
  183.     va_list argList;
  184.     static lineCnt = 0;
  185.  
  186.     va_start(argList, format);
  187.     charCnt=vfprintf(stdout, format, argList);
  188.     va_end(argList);
  189.  
  190.     printf("\n");
  191.     ++lineCnt;
  192.  
  193.     if((lineCnt == 24) && (NLM_pause))
  194.         {
  195.         lineCnt = 0;
  196.         printf(">>> C=Continuous ESC=Quit AnyOtherKey=More <<<");
  197.         while((!kbhit()) && (!NLM_exiting))
  198.             ThreadSwitchWithDelay();
  199.  
  200.         while(kbhit())
  201.             ch=getch();
  202.  
  203.         /*---------------------------------------------------------------------
  204.         **    Handle special keys:
  205.         */
  206.         switch(ch)
  207.             {
  208.             case 27:        /* ESCAPE    */
  209.                 NLM_exiting=TRUE;
  210.                 break;
  211.  
  212.             case 'C':    /* Continuous */
  213.             case 'c':
  214.                 NLM_pause = FALSE;
  215.                 break;
  216.             }
  217.  
  218.         printf("\r");
  219.         printf("                                                             ");
  220.         printf("\r");
  221.         }
  222.  
  223.     return(charCnt);
  224.     }
  225.  
  226. /****************************************************************************
  227. **    Recursive Directory listing.
  228. */
  229. int NLM_Dir(char *path, char *wild, unsigned long searchAttributes)
  230.     {
  231.     int cCode=ESUCCESS;
  232.     char *tempPath;
  233.     struct dirent    *de;
  234.     DIR *dir;
  235.  
  236.     /*------------------------------------------------------------------------
  237.     **    Scan for non-directories.
  238.     */
  239.    tempPath=NLM_PastePath(path, wild);
  240.    if(tempPath == NULL)
  241.       {
  242.       printf("ERROR: NLM_PastePath() reports NULL return value.\n");
  243.       return(EFAILURE);
  244.       }
  245.  
  246.     if((searchAttributes & _A_SUBDIR) != _A_SUBDIR)
  247.         {
  248.         NLM_PrintLine("");
  249.         NLM_PrintLine("%s", tempPath);
  250.         }
  251.     else
  252.         NLM_PrintLine("%s", path);
  253.  
  254.     dir=opendir(tempPath);
  255.     if(dir == NULL) 
  256.         {
  257.         /*---------------------------------------------------------------------
  258.         **    Error recovery.
  259.         */
  260.         if((errno == 1) && (NetWareErrno == 255))
  261.             /* This simply indicates that the directory was empty */;
  262.         else
  263.             {
  264.             printf("ERROR: opendir(\"%s\") reports NULL return value.\n", tempPath);
  265.             printf("\"\"\"\"\":  errno=%d    NetWareErrno= %d\n", errno, NetWareErrno);
  266.             free(tempPath);
  267.             return(EFAILURE);
  268.             }
  269.         }
  270.     free(tempPath);
  271.  
  272.     cCode=SetReaddirAttribute(
  273.         /*    I-    dirP                */    dir,
  274.         /*    I-    newAttribute    */    searchAttributes
  275.         );
  276.     if(cCode != ESUCCESS)
  277.         {
  278.         printf("ERROR: SetReaddirAttribute() reports %d.\n", cCode);
  279.         goto END_ERR;
  280.         }
  281.  
  282.     de=readdir(dir);
  283.     while((de != NULL) && (!NLM_exiting))
  284.         {
  285.         if(!(de->d_attr & _A_SUBDIR)) 
  286.             {
  287.             NLM_PrintLine("%-12.12s %10lu %02d-%02d-%02d %2d:%02d",
  288.                 de->d_name,
  289.                 de->d_size,
  290.                 (de->d_date & 0x01E0) >> 5,     /* Month */
  291.                 de->d_date & 0x001F,                /* Day    */
  292.                 (de->d_date >> 9) + 80,            /* Year    */
  293.                 de->d_time >> 11,                    /*    Hour    */
  294.                 (de->d_time & 0x07E0) >> 5        /* Minute*/
  295.                 );
  296.             }
  297.         de=readdir(dir);
  298.         }
  299.     closedir(dir);
  300.  
  301.     if(!NLM_subSearch)
  302.         return(ESUCCESS);    
  303.  
  304.     /*------------------------------------------------------------------------
  305.     **    Scan for directories.
  306.     */
  307.    tempPath=NLM_PastePath(path, "*.*");
  308.    if(tempPath == NULL)
  309.       {
  310.       printf("ERROR: NLM_PastePath() reports NULL return value.\n");
  311.       return(EFAILURE);
  312.       }
  313.  
  314.     dir=opendir(tempPath);
  315.     if(dir == NULL) 
  316.         {
  317.         /*---------------------------------------------------------------------
  318.         **    Error recovery.
  319.         */
  320.         if((errno == 1) && (NetWareErrno == 255))
  321.             /* This simply indicates that the directory was empty */;
  322.         else
  323.             {
  324.             printf("ERROR: opendir(\"%s\") reports NULL return value.\n", tempPath);
  325.             printf("\"\"\"\"\":  errno=%d    NetWareErrno= %d\n", errno, NetWareErrno);
  326.             free(tempPath);
  327.             return(EFAILURE);
  328.             }
  329.         }
  330.     free(tempPath);
  331.  
  332.     cCode=SetReaddirAttribute(
  333.         /*    I-    dirP                */    dir,
  334.         /*    I-    newAttribute    */    searchAttributes
  335.         );
  336.     if(cCode != ESUCCESS)
  337.         {
  338.         printf("ERROR: SetReaddirAttribute() reports %d.\n", cCode);
  339.         goto END_ERR;
  340.         }
  341.  
  342.     de=readdir(dir);
  343.     while((de != NULL) && (!NLM_exiting))
  344.         {
  345.         if(de->d_attr & _A_SUBDIR)
  346.             {
  347.             tempPath=NLM_PastePath(path, de->d_name);
  348.             NLM_Dir(tempPath, wild, searchAttributes);
  349.             free(tempPath);
  350.             }
  351.         de=readdir(dir);
  352.         }
  353.     closedir(dir);
  354.  
  355. END_ERR:
  356.  
  357.     return(cCode);
  358.     }
  359.  
  360. /****************************************************************************
  361. **    Signal handler.
  362. */
  363. void NLM_SignalHandler(int sig)
  364.     {
  365.     switch(sig)
  366.         {
  367.         case SIGTERM:
  368.             NLM_exiting = TRUE;
  369.             while(NLM_threadCnt)
  370.                 ThreadSwitchWithDelay();
  371.             break;
  372.             
  373.         case SIGINT:
  374.             NLM_exiting = TRUE;
  375.             signal(SIGINT, NLM_SignalHandler);
  376.             break;
  377.  
  378.         default:
  379.             break;
  380.         }
  381.  
  382.     return;
  383.     }
  384.  
  385. /****************************************************************************
  386. **    Program help
  387. */
  388. void NLM_Help(void)
  389.     {
  390.    printf("\n");
  391.    printf("Usage: LOAD DIR {path}wildcard {:[parameters]}\n");
  392.     printf("\n");
  393.     printf("Parameters:\n");
  394.     printf("\n");
  395.     printf("     :P     Pause display.\n");
  396.     printf("     :S     Search Sub-directories.\n");
  397.     printf("     :R     Search Read-Only files.\n");
  398.     printf("     :H     Search Hidden files.\n");
  399.     printf("     :B     Search System files.\n");
  400.     printf("     :V     Search Volume ID entry.\n");
  401.     printf("     :A     Search Archive files.\n");
  402.     printf("         :X     List only directories.\n");
  403.     printf("\n");
  404.     printf("Example: LOAD DIR sys:system\\*.*\n");
  405.     printf("\n");
  406.  
  407.     return;
  408.     }
  409.  
  410. /****************************************************************************
  411. **    Program start
  412. */
  413. void main(int argC, char *argV[])
  414.    {
  415.     char                 *wild                 = NULL;
  416.     char                 *path             = NULL;
  417.     unsigned long      searchAttributes = _A_NORMAL;
  418.    unsigned          rVal;
  419.     int                  nCnt;
  420.  
  421.     ++NLM_threadCnt;
  422.  
  423.    /*------------------------------------------------------------------------
  424.    ** Register signal handlers.
  425.    */
  426.     signal(SIGTERM, NLM_SignalHandler);
  427.     signal(SIGINT, NLM_SignalHandler);
  428.  
  429.    /*------------------------------------------------------------------------
  430.    ** Parse command line.
  431.     **
  432.     **    Discourse:
  433.     **
  434.     **        ABJ 8-29-95    You may be wondering why I chose the ':' character to
  435.     **                        prefix each parameter on the (user) command line.  It
  436.     **                        is perhaps more common to use other characters such as
  437.     **                        '/', '\', or '-'.  Those more commonly used characters
  438.     **                        are all legal characters for a path specification.
  439.     **                        Although the ':' character is also a legal character,
  440.     **                        it never appears as the first character of a path.
  441.     **                        Therefore the ':'is perfect as a parameter prefix.  As
  442.     **                        the logic below shows, it makes parsing a user command
  443.     **                        line very easy, and allows the parameters (including
  444.     **                        the path) to be specified in any order.
  445.     */
  446.     for(nCnt=1; nCnt < argC; ++nCnt)
  447.         {
  448.         if(argV[nCnt][0] != ':')
  449.             {
  450.             if(path != NULL)    /* Path already specified? */
  451.                 {
  452.                 NLM_Help();
  453.                 goto END_ERR;
  454.                 }
  455.          rVal=NLM_ParsePath(argV[1], &path, &wild);
  456.          if(rVal != ESUCCESS)
  457.                 {
  458.                 printf("ERROR: NLM_ParsePath() indicates %d\n", rVal);
  459.                 goto END_ERR;
  460.                 }
  461.  
  462.             continue;
  463.             }
  464.         switch(argV[nCnt][1])
  465.             {
  466.             case 'P':
  467.             case 'p':
  468.                 NLM_pause=TRUE;
  469.                 break;
  470.  
  471.             case 'S':
  472.             case 's':
  473.                 NLM_subSearch=TRUE; 
  474.                 break;
  475.  
  476.             case 'X':
  477.             case 'x':
  478.                 NLM_subSearch=TRUE; 
  479.                 searchAttributes |= _A_SUBDIR;
  480.                 break;
  481.  
  482.             case 'R':
  483.             case 'r':
  484.                 searchAttributes |= _A_RDONLY;
  485.                 break;
  486.  
  487.             case 'H':
  488.             case 'h':
  489.                 searchAttributes |= _A_HIDDEN;
  490.                 break;
  491.  
  492.             case 'B':
  493.             case 'b':
  494.                 searchAttributes |= _A_SYSTEM;
  495.                 break;
  496.  
  497.             case 'V':
  498.             case 'v':
  499.                 searchAttributes |= _A_VOLID;
  500.                 break;
  501.  
  502.             case 'A':
  503.             case 'a':
  504.                 searchAttributes |= _A_ARCH;
  505.                 break;
  506.  
  507.             default:
  508.                 NLM_Help();
  509.                 goto END_ERR;
  510.             }
  511.         }
  512.  
  513.    /*------------------------------------------------------------------------
  514.    ** Validate parameters.
  515.    */
  516.     if(path == NULL)
  517.         {
  518.         NLM_Help();
  519.         goto END_ERR;
  520.         }
  521.  
  522.    /*------------------------------------------------------------------------
  523.    ** Perform directory search.
  524.    */
  525.     NLM_Dir(path, wild, searchAttributes);
  526.     NLM_PrintLine("");
  527.  
  528. END_ERR:
  529.  
  530.     /*------------------------------------------------------------------------
  531.     **    Free up resources.
  532.     */
  533.     if(path != NULL)
  534.         free(path);
  535.  
  536.     if(wild != NULL)
  537.         free(wild);
  538.  
  539.     --NLM_threadCnt;
  540.  
  541.     return;
  542.     }
  543.  
  544.  
  545.  
  546.  
  547.  
  548.  
  549.  
  550.  
  551.  
  552.  
  553.  
  554.  
  555.  
  556.