home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / S12442.ZIP / DISERVER.C < prev    next >
C/C++ Source or Header  |  1989-07-31  |  8KB  |  265 lines

  1. /* diserver.c RHS 5/28/89
  2.  *
  3.  * directory information server
  4.  
  5.     Run this program before running any programs (like DIPOP or LS) that
  6.     use the server. Run the program with:
  7.  
  8.     DISERVER [/v]
  9.  
  10.     The optional /v will turn on verbose mode, and status messages are printed.
  11.  */
  12.  
  13. #define    INCL_DOS
  14. #define    INCL_ERRORS
  15.  
  16. #include<os2.h>
  17. #include<mt\stdio.h>
  18. #include<mt\process.h>
  19. #include<mt\string.h>
  20. #include"errexit.h"
  21.  
  22. #define DICODE
  23. #include"di.h"
  24.  
  25. #define    THREADSTACK    1000
  26. #define    MAXTHREADS    20
  27. #define    lastchar(str)        (str[strlen(str)-1])
  28. typedef struct _serverthreads
  29.     {
  30.     ULONG                    threadSem;
  31.     SHORT                    threadID;
  32.     PREQUESTHEADER        request;
  33.     SHORT                    threadnum;
  34.     UCHAR                    threadstack[THREADSTACK];
  35.     } SERVERTHREAD;
  36.  
  37. SERVERTHREAD SERVERTHREADS[MAXTHREADS];
  38.  
  39. USHORT verbose = FALSE;
  40.  
  41. void server_thread(SERVERTHREAD *threaddata);
  42.  
  43. void main(int argc, char **argv);
  44.  
  45. void main(int argc, char **argv)
  46.     {
  47.     USHORT            retval, qcount = 0, nextthread = 0;
  48.     HQUEUE             qhandle;
  49.     QUEUERESULT     qresult;
  50.     USHORT             ellength;
  51.     BYTE                priority;
  52.     PREQUESTHEADER    request;
  53.  
  54.     if(argc > 1)
  55.         if(((*argv[1]=='-') || (*argv[1]=='/')) &&
  56.                 (argv[1][1]=='v' || argv[1][1]=='V'))
  57.             verbose = TRUE;
  58.         else
  59.             printf("DiServer: ignoring unknown argument \"%s\"\n",argv[1]);
  60.  
  61.     /* create the server queue for taking requests from clients
  62.      */
  63.  
  64.     if(retval = DosCreateQueue(&qhandle,QUE_FIFO,DIRINFOQNAME))
  65.         error_exit(retval,"DosCreateQueue");
  66.  
  67.     if(verbose)
  68.         printf("DiServer: queue is open, awaiting requests...\n");
  69.  
  70.     memset(SERVERTHREADS,0,sizeof(SERVERTHREADS));
  71.  
  72.     while(TRUE)
  73.         {
  74.             /* read the queue to see if any requests have been made    */
  75.         if(retval = DosReadQueue(qhandle,&qresult,&ellength,
  76.                 (PVOID FAR *)&request,0x0000,DCWW_WAIT,&priority,0L))
  77.             if(retval != ERROR_QUE_EMPTY)    /* if error was not from empty queue */
  78.                 error_exit(retval,"DosReadQueue");
  79.  
  80.         DosQueryQueue(qhandle,&qcount);
  81.         if(verbose)
  82.             printf("DiServer: request received from process %u (%u pending)\n",
  83.                         qresult.pidProcess,qcount);
  84.  
  85.         /* request has been made:
  86.             o    find the next available server thread structure
  87.             o    set its semaphore so it will wait until you've started it
  88.             o    start the new server thread
  89.             o    once it's successfully started, set the request pointer in
  90.                 its data structure to the request that was received
  91.             o    then tell the thread to go ahead by clearing the semaphore--
  92.                 thus the thread can't go ahead without the request and without
  93.                 having it's own thread ID installed in it's structure
  94.             o    if the next thread structure isn't available, find one that is
  95.             o    if it goes all the way around and doesn't find one, it will sleep
  96.                 for a second before it tries again
  97.          */
  98.  
  99.         while(TRUE)
  100.             {
  101.             if(nextthread == MAXTHREADS)
  102.                 {
  103.                 nextthread = 0;
  104.                 DosSleep(1000L);
  105.                 }
  106.  
  107.             if(!SERVERTHREADS[nextthread].threadID)
  108.                 {
  109.                 DosSemSet(&SERVERTHREADS[nextthread].threadSem);
  110.                 if((SERVERTHREADS[nextthread].threadID = _beginthread(
  111.                         server_thread,    SERVERTHREADS[nextthread].threadstack,
  112.                         THREADSTACK,(void *)&SERVERTHREADS[nextthread]))
  113.                         == -1)
  114.                     error_exit(-1,"_beginthread");
  115.                 else
  116.                     {
  117.                     SERVERTHREADS[nextthread].request = request;
  118.                     SERVERTHREADS[nextthread].threadnum = nextthread;
  119.                     DosSemClear(&SERVERTHREADS[nextthread].threadSem);
  120.                     nextthread++;
  121.                     break;
  122.                     }
  123.                 }
  124.             while(++nextthread < MAXTHREADS)
  125.                 if(!SERVERTHREADS[nextthread].threadID)
  126.                     break;
  127.             }
  128.  
  129.         }
  130.     DosCloseQueue(qhandle);
  131.     DosExit(EXIT_PROCESS,0);                            /* and exit                        */
  132.     }
  133.  
  134. void server_thread(SERVERTHREAD *threaddata)
  135.     {
  136.     PREQUESTHEADER request;
  137.     USHORT i, retval,found, bufsize, attributes,count;
  138.     PDIRINFORESULT    results;
  139.     PFILEFINDBUF findbuf;
  140.     HDIR dirhandle;
  141.     char filespec[80],dircheck = FALSE;
  142.     char far *temp;
  143.  
  144.         /* wait until main thread says to continue    */
  145.     DosSemRequest(&threaddata->threadSem, SEM_INDEFINITE_WAIT);
  146.     request = threaddata->request;
  147.     if(verbose)
  148.         {
  149.         printf("Thread #%u:\n",threaddata->threadnum);
  150.         printf("\t%u filespec(s) in request\n",request->numRequests);
  151.         printf("\tClient's current directory is %s\n",request->currentdir);
  152.         }
  153.  
  154.     findbuf = request->resultptr;
  155.     temp = MAKEP(request->serverwsel,0);
  156.  
  157.         /* process each request:
  158.             o    build the complete path and filespec from currentdir, and filespec
  159.             o    get the attributes
  160.             o    if there are attributes, include the directory bit so the dirs
  161.                 will be found
  162.                 else set the directory bit
  163.             o    set bufsize to the max segment size minus the space already used
  164.                 by results already found
  165.          */
  166.  
  167.     for(request->totalresults = i = 0, results = &request->resultArray[0];
  168.             i < request->numRequests; i++, results++)
  169.         {
  170.         if(verbose)
  171.             printf("\tFilespec %u: Attr:%4x Dirspec: %s Filespec: %s\n",
  172.                     i,results->attributes,results->currentdir,results->filespec);
  173.         strcpy(filespec,results->currentdir);
  174.         if(lastchar(filespec) != '\\')
  175.             strcat(filespec,"\\");
  176.         strcat(filespec,results->filespec);
  177.         attributes = results->attributes;
  178.         if(attributes)
  179.             attributes |= FILE_DIRECTORY;
  180.         else
  181.             attributes = FILE_DIRECTORY;
  182.  
  183. expand_directory:
  184.         found = 0xffff;
  185.         dirhandle = HDIR_SYSTEM;
  186.         bufsize = MAXSEGSIZE-1;
  187.         bufsize -= ((char far *)findbuf-temp);
  188.  
  189.         /* find the files:
  190.             o    if an error occurred and it was not one of these listed, it's
  191.                 very bad news
  192.             o    otherwise the error is no files found
  193.             o    if no error, and we're not yet expanding a directory and we only
  194.                 found one file, and it has a directory attribute, try again
  195.             o    otherwise, we found 1 or more files
  196.          */
  197.         if(verbose)
  198.             printf("\tSearching for %s, buffersize=%u attributes=0x%04x\n",
  199.                     filespec,bufsize,attributes);
  200.         if(retval = DosFindFirst(filespec, &dirhandle, attributes, findbuf,
  201.                 bufsize, &found, 0L))
  202.             {
  203.             switch(retval)
  204.                 {
  205.                 case ERROR_FILE_NOT_FOUND:
  206.                 case ERROR_NO_MORE_FILES:
  207.                 case ERROR_PATH_NOT_FOUND:
  208.                     results->errorval = retval;
  209.                     break;
  210.                 default:
  211.                     error_exit(retval,"DosFindFirst");
  212.                 }
  213.             results->firstfile = NULL;
  214.             results->numfound = 0;
  215.             }
  216.         else
  217.             {
  218.             if(verbose)
  219.                 printf("\tFound %u files:\n",found);
  220.             if(!dircheck &&  (found == 1) && (findbuf->attrFile & FILE_DIRECTORY)
  221.                     &&    !strcmp(findbuf->achName,
  222.                         &filespec[strlen(filespec)-strlen(findbuf->achName)]))
  223.                 {
  224.                 strcat(filespec,"\\*.*");
  225.                 dircheck = TRUE;
  226.                 DosSleep(32L);
  227.                 goto expand_directory;
  228.                 }
  229.                     
  230.             results->firstfile = findbuf;
  231.             results->numfound = found;
  232.             request->totalresults += found;
  233.  
  234.             for( count = 0 ; found > 0; found--, count++)
  235.                 {
  236.                 if(verbose)
  237.                     {
  238.                     if(count == 5)
  239.                         {
  240.                         printf("\n");
  241.                         count = 0;
  242.                         }
  243.                     printf( ((findbuf->attrFile & FILE_DIRECTORY) ?
  244.                             "[%-12s] " : "%-15s"),findbuf->achName);
  245.                     }
  246.                 findbuf = (PFILEFINDBUF)(&(findbuf->cchName)+findbuf->cchName+2);
  247.                 }
  248.             DosSleep(32L);
  249.             }
  250.         }
  251.  
  252.         /* now resize the segment to include only the data    */
  253.     request->resultsize = (USHORT)((char far *)findbuf-temp)+5;
  254.  
  255.     if(verbose)
  256.         printf("\nThread #%u: Work area resized to %u bytes. Request complete.\n\n",
  257.                 threaddata->threadnum,request->resultsize);
  258.  
  259.     DosFreeSeg(request->serverwsel);                    /* free the results segment*/
  260.     DosSemClear(&request->RAMsem);                    /* tell client we're done    */
  261.     threaddata->threadID = 0;
  262.     DosExit(EXIT_THREAD,0);
  263.     }
  264.  
  265.