home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1993 #2 / Image.iso / os2 / av180.zip / AVEXE.ZIP / SAMPLE.C < prev    next >
C/C++ Source or Header  |  1993-02-12  |  20KB  |  807 lines

  1. /****************************************************************************/
  2. /* Source code showing how to access info in ARCHIVER.BB2, and how to       */
  3. /* use that info to determine the archive type of a file.                   */
  4. /* Written by M. Kimes w/ CSet/2 for OS/2 2.x, may be freely used.          */
  5. /* ARCHIVER.BB2 and its format are donated to public domain.  Anyone        */
  6. /* needing to add fields should check with me first, though.  Thanks.       */
  7. /*                                                                          */
  8. /* see end of file for additional comments                                  */
  9. /****************************************************************************/
  10.  
  11. #define INCL_DOS
  12.  
  13. #include <os2.h>
  14. #include <stdlib.h>
  15. #include <stdio.h>
  16. #include <ctype.h>
  17. #include <string.h>
  18. #include <sys/types.h>
  19. #include <sys/stat.h>
  20. #include <share.h>
  21.  
  22. /*
  23.  * structure to hold information (record) from ARCHIVER.BB2
  24.  * in a singly linked list
  25.  */
  26.  
  27. typedef struct ARC_TYPE {
  28.   CHAR    *id;
  29.   CHAR    *ext;
  30.   LONG    file_offset;
  31.   CHAR    *list;
  32.   CHAR    *extract;
  33.   CHAR    *exwdirs;
  34.   CHAR    *test;
  35.   CHAR    *create;
  36.   CHAR    *move;
  37.   CHAR    *createrecurse;
  38.   CHAR    *createwdirs;
  39.   CHAR    *movewdirs;
  40.   CHAR    *delete;
  41.   CHAR    *signature;
  42.   CHAR    *startlist;
  43.   CHAR    *endlist;
  44.   INT     osizepos;
  45.   INT     nsizepos;
  46.   INT     fdpos;
  47.   INT     fdflds;
  48.   INT     fnpos;
  49.   struct ARC_TYPE *next;
  50. } ARC_TYPE;
  51.  
  52. /* # of lines in an ARCHIVER.BB2 record that we understand
  53.  * we'll skip any beyond this
  54.  */
  55.  
  56. #define NUMLINES 21
  57.  
  58. /* stuff for literal() */
  59.  
  60. #define HEX "0123456789ABCDEF"
  61. #define DEC "0123456789"
  62.  
  63.  
  64.  
  65. CHAR *strip_trail_char (CHAR *strip,CHAR *a) {
  66.  
  67.   register CHAR *p;
  68.  
  69.   if(a && *a && strip && *strip) {
  70.     p = &a[strlen(a) - 1];
  71.     while (*a && strchr(strip,*p) != NULL) {
  72.       *p = 0;
  73.       p--;
  74.     }
  75.   }
  76.   return a;
  77. }
  78.  
  79.  
  80. CHAR *strip_lead_char (CHAR *strip,CHAR *a) {
  81.  
  82.   register CHAR *p = a;
  83.  
  84.   if(a && *a && strip && *strip) {
  85.     while(*p && strchr(strip,*p) != NULL)
  86.       p++;
  87.     if(p != a)
  88.       memmove(a,p,strlen(p) + 1);
  89.   }
  90.   return a;
  91. }
  92.  
  93.  
  94. CHAR *convert_1_2_another (CHAR one,CHAR two,CHAR *a) {
  95.  
  96.   register CHAR *p = a;
  97.  
  98.   if(p && *p && one && two) {
  99.     while(*p) {
  100.       if(*p == one)
  101.         *p = two;
  102.       p++;
  103.     }
  104.   }
  105.   return a;
  106. }
  107.  
  108. #define lstrip(s)         strip_lead_char(" \t",(s))
  109. #define rstrip(s)         strip_trail_char(" \t",(s))
  110. #define stripcr(s)        strip_trail_char("\r\n",(s))
  111. #define trailbkslstrip(s) strip_trail_char("\\\/",(s))
  112. #define cvtbksl2sl(s)     convert_1_2_another('\\','/',(s))
  113. #define cvtsl2bksl(s)     convert_1_2_another('/','\\',(s))
  114.  
  115.  
  116. char *searchapath (char *path,char *filename) {
  117.  
  118.   /* search a single path */
  119.  
  120.     static char fbuf[1539];
  121.     struct stat st;
  122.     char        *envbuf = NULL,*p,temp;
  123.  
  124.     p = getenv(path);
  125.     if(!p)
  126.       return NULL;
  127.     envbuf = strdup(p);
  128.     if(!envbuf)
  129.       return NULL;
  130.  
  131.     p = strtok(envbuf,";");
  132.     do {
  133.         strncpy(fbuf,p,1024);
  134.         fbuf[1024] = 0;
  135.         temp = fbuf[strlen(fbuf) - 1];
  136.         if(temp != '/' && temp != '\\')
  137.           strcat(fbuf,"\\");
  138.         strcat(fbuf,filename);
  139.         if(!stat(fbuf,&st)) {
  140.             free(envbuf);
  141.             return fbuf;
  142.         }
  143.         p = strtok(0,";");
  144.     } while(p);
  145.     free(envbuf);
  146.     return NULL;
  147. }
  148.  
  149.  
  150. char *searchpath (char *filename) {
  151.  
  152.   /* search a group of paths */
  153.  
  154.   static char fbuf[1030];
  155.   struct stat st;
  156.   char        *p;
  157.  
  158.   if(!stat(filename,&st)) { /* try current dir first */
  159.     if(strchr(filename,'/') || strchr(filename,'\\') || strchr(filename,':')) {
  160.       strcpy(fbuf,filename);
  161.       return fbuf;
  162.     }
  163.     save_dir(fbuf);
  164.     strcat(fbuf,"\\");
  165.     strcat(fbuf,filename);
  166.     return fbuf;
  167.   }
  168.   if((p = searchapath("PATH",filename)) != NULL)
  169.     return p;
  170.   if((p = searchapath("DPATH",filename)) != NULL)
  171.     return p;
  172.   p = searchapath("XPATH",filename);
  173.   return p;
  174. }
  175.  
  176.  
  177. INT index (CHAR *s,CHAR c) {
  178.  
  179.    /* used by literal(); returns offset of c in s or -1 (error) */
  180.  
  181.     CHAR *p;
  182.  
  183.     p = strchr(s,c);
  184.     if(!p || !*p)
  185.       return -1;
  186.     return (INT)(p - s);
  187. }
  188.  
  189. CHAR *literal (CHAR *fsource) {
  190.  
  191.   /*
  192.    * perform C-style translation of \? escaped characters
  193.    * lets us put things like PK\x3\x4 as a signature in
  194.    * ARCHIVER.BB2's plain text format
  195.    */
  196.  
  197.   register INT wpos,w,x;
  198.   INT          wincomment;
  199.   CHAR         *fdestin,*freeme,wchar;
  200.  
  201.   if(!fsource || !*fsource) /* error */
  202.     return fsource;
  203.   x = strlen(fsource) + 1;
  204.   freeme = fdestin = malloc(x + 1); /* work area */
  205.   wincomment = 0;
  206.   memset(fdestin,0,x);      /* start out with NULL string */
  207.  
  208.   w = 0;                    /* set index to first character */
  209.   while (fsource[w]) {      /* until end of string */
  210.     switch(fsource[w]) {
  211.       case '\\':
  212.        if(!wincomment)
  213.         switch(fsource[w + 1]) {
  214.           case 'x' :                    /* hexadecimal */
  215.             wchar = 0;
  216.             w += 2;                     /* get past "\x" */
  217.             if (index(HEX,(CHAR)toupper(fsource[w])) != -1) {
  218.               while ((wpos = index(HEX,(CHAR)toupper(fsource[w]))) != -1) {
  219.                 wchar = (CHAR)(wchar << 4) + (CHAR)wpos;
  220.                 w++;
  221.               }
  222.             }
  223.             else wchar = 'x';         /* just an x */
  224.             w--;
  225.             *fdestin++ = wchar;
  226.             break;
  227.  
  228.           case '\\' :                 /* we want a "\" */
  229.             w++;
  230.             *fdestin++ = '\\';
  231.             break;
  232.  
  233.           case 't' :                  /* tab CHAR */
  234.             w++;
  235.              *fdestin++ = '\t';
  236.             break;
  237.  
  238.           case 'n' :                  /* new line */
  239.             w++;
  240.             *fdestin++ = 10;
  241.             break;
  242.  
  243.           case 'r' :                  /* carriage return */
  244.             w++;
  245.             *fdestin++ = '\r';
  246.             break;
  247.  
  248.           case 'b' :                  /* backspace */
  249.             w++;
  250.             *fdestin++ = '\b';
  251.             break;
  252.  
  253.           case 'a':                   /* bell */
  254.             w++;
  255.             *fdestin++ = '\07';
  256.             break;
  257.  
  258.           case '\'' :                 /* single quote */
  259.             w++;
  260.             *fdestin++ = '\'';
  261.             break;
  262.  
  263.           case '\"' :                 /* double quote */
  264.             w++;
  265.             *fdestin++ = '\"';
  266.             break;
  267.  
  268.           default :                   /* decimal */
  269.             w++;                      /* get past "\" */
  270.             wchar = 0;
  271.             if (index(DEC,fsource[w]) != -1) {
  272.               do {
  273.                 wchar = (CHAR)(wchar * 10 + (fsource[w++] - 48)); /* cnvt to binary */
  274.               } while (index(DEC,fsource[w]) != -1);
  275.               w--;
  276.             }
  277.             else wchar = fsource[w];
  278.             *fdestin ++ = wchar;
  279.             break;
  280.         }
  281.         break;
  282.  
  283.       case '*' :
  284.         if(wincomment) {
  285.           if (fsource[w + 1] == '/') {
  286.             wincomment--;            /* toggle the flag */
  287.             w++;
  288.           }
  289.         }
  290.         else
  291.           *fdestin++ = fsource[w];
  292.         break;
  293.  
  294.       case '/' :              /* beginning of comment perhaps */
  295.         if(fsource[w + 1] == '*') {
  296.           wincomment++;             /* toggle the flag */
  297.           w++;
  298.         }
  299.         break;
  300.  
  301.       default :
  302.         if(!wincomment)
  303.           *fdestin++ = fsource[w];
  304.         break;
  305.    }
  306.    w++;
  307.   }
  308.   *fdestin = 0;         /* terminate the string */
  309.  
  310.   strcpy(fsource,freeme);  /* swap 'em */
  311.   free(freeme);
  312.   return fsource;
  313. }
  314.  
  315.  
  316. ULONG checkfile2 (CHAR *file,INT *error) {
  317.  
  318.   /*
  319.    * check whether a file is executable
  320.    * used to ignore records that
  321.    * don't point to a useful program
  322.    */
  323.  
  324.   CHAR  *p,*pp;
  325.   INT   ret;
  326.   ULONG apptype = 0L;
  327.  
  328.   if(!file || !*file) {
  329.     *error = 3;
  330.     return apptype;
  331.   }
  332.   pp = strchr(file,' ');
  333.   if(pp)
  334.     *pp = 0;
  335.   p = searchpath(file);
  336.   if(pp)
  337.     *pp = ' ';
  338.   if(!p || !*p) {
  339.     *error = 1;
  340.   }
  341.   else {
  342.     ret = (INT)DosQAppType(p,&apptype);
  343.     if(ret) {
  344.       *error = -1;
  345.     }
  346.     else {
  347.       apptype &= (~FAPPTYP_32BIT);
  348.       if(!apptype ||
  349.          (apptype == FAPPTYP_NOTWINDOWCOMPAT) ||
  350.          (apptype == FAPPTYP_WINDOWCOMPAT) ||
  351.          (apptype & FAPPTYP_BOUND) ||
  352.          (apptype & FAPPTYP_WINDOWAPI) ||
  353.          (apptype & FAPPTYP_DOS)) {
  354.         *error = 0;
  355.       }
  356.       else {
  357.         *error = 2;
  358.       }
  359.     }
  360.   }
  361.   return apptype;
  362. }
  363.  
  364.  
  365. CHAR *stristr (CHAR *t, CHAR *s) {
  366.  
  367.   /* case insensitive strstr */
  368.  
  369.    register CHAR *t1;
  370.    register CHAR *s1;
  371.  
  372.    while(*t) {
  373.      t1 = t;
  374.      s1 = s;
  375.      while(*s1) {
  376.        if (toupper(*s1) != toupper(*t))
  377.          break;
  378.        else {
  379.          s1++;
  380.          t++;
  381.        }
  382.      }
  383.      if (!*s1)
  384.        return t1;
  385.      t = t1 + 1;
  386.    }
  387.    return NULL;
  388. }
  389.  
  390.  
  391. FILE *_fsopen (CHAR *filename,CHAR *mode,INT sharemode) {
  392.  
  393.   /* open file as stream with sharing */
  394.  
  395.   INT  openmode = 0;
  396.   INT  handle;
  397.   FILE *fp;
  398.  
  399.   if(stristr(mode,"r"))
  400.     openmode |= O_RDONLY;
  401.   else if(stristr(mode,"w"))
  402.     openmode |= (O_WRONLY | O_TRUNC | O_CREAT);
  403.   if(stristr(mode,"b"))
  404.     openmode |= O_BINARY;
  405.   else
  406.     openmode |= O_TEXT;
  407.   if(stristr(mode,"a")) {
  408.     openmode |= (O_APPEND | O_WRONLY);
  409.   }
  410.   if(stristr(mode,"+")) {
  411.     openmode &= (~(O_RDONLY | O_WRONLY));
  412.     openmode |= (O_RDWR | O_CREAT);
  413.   }
  414.   handle = sopen(filename,openmode,sharemode,S_IWRITE | S_IREAD);
  415.   if(handle == -1)
  416.     return NULL;
  417.   if(openmode & O_APPEND)
  418.     lseek(handle,0L,SEEK_END);
  419.   if(mode[strlen(mode) - 1] == 't')
  420.     mode[strlen(mode) - 1] = 0; /* bug bug bug */
  421.   fp = fdopen(handle,mode);
  422.   if(!fp) {
  423.     close(handle);
  424.     fp = fopen(filename,mode);  /* last ditch effort */
  425.   }
  426.   if(fp) {
  427.     if(openmode & O_TEXT)   /* line buffer text files */
  428.       setvbuf(fp,NULL,_IOLBF,BUFSIZ * 2);
  429.     else
  430.       setvbuf(fp,NULL,_IOFBF,BUFSIZ * 4);
  431.   }
  432.   return fp;
  433. }
  434.  
  435.  
  436. ARC_TYPE *find_type (CHAR *filespec,ARC_TYPE *topsig) {
  437.  
  438.   /*
  439.    * return pointer to matching archive info record, or NULL on
  440.    * failure (not an archive we understand).  Once you know the
  441.    * archive type you can employ the information in the ARC_TYPE
  442.    * structure to manipulate the archive.
  443.    */
  444.  
  445.   FILE        *file;        /* File handle */
  446.   ARC_TYPE    *info;
  447.   INT         l;            /* Length of the signature. */
  448.   CHAR        buffer[80];   /* Read buffer for the signatures. */
  449.   INT         error;
  450.  
  451.   file = _fsopen(filespec,"rb",SH_DENYNO);    /* Open the file */
  452.   if (!file)                     /* If can't open it, return with error. */
  453.     return NULL;
  454.   info = topsig;                 /* start of signatures */
  455.   while (info) {
  456.     rewind(file);
  457.     l = strlen(info->signature);   /* Get the signature length. */
  458.     if(l > 79)
  459.       l = 79;
  460.     if(info->file_offset >= 0L)
  461.       fseek(file,info->file_offset,SEEK_SET);
  462.     else
  463.       fseek(file,info->file_offset,SEEK_END);
  464.     if((error = fread(buffer,1,l,file)) > 0) {
  465.       buffer[l] = 0;
  466.       if(!memcmp(info->signature,buffer,l)) { /* match, see if useable */
  467.  
  468.         ULONG apptype;
  469.  
  470.         apptype = checkfile2(info->list,&error);
  471.         if(apptype && apptype != FAPPTYP_DOS) {
  472.            apptype = checkfile2(info->extract,&error);
  473.            if(apptype && apptype != FAPPTYP_DOS)  /* dammit! */
  474.             break;
  475.         }
  476.       }
  477.     }
  478.     info = info->next;
  479.   }
  480.   fclose(file);                        /* Either way, we're done for now */
  481.   return info;                         /* return signature, if any */
  482. }
  483.  
  484.  
  485. ARC_TYPE *load_archivers (INT *error) {
  486.  
  487.   /*
  488.    * load archiver records into linked list, return start of list or
  489.    * NULL (error then contains more info on reason for failure).
  490.    * the list may be traversed like this:
  491.    *
  492.    * ARC_TYPE *info;
  493.    *
  494.    * info = arcsighead;    // assign temp to head of list
  495.    * while(info) {         // while != NULL, end of list...
  496.    *   // do something with it
  497.    *   info = info->next;  // point to next structure in list
  498.    * }
  499.    */
  500.  
  501.   FILE            *handle;
  502.   CHAR            s[257],*p;
  503.   ARC_TYPE        *info = NULL,*last = NULL;
  504.   INT             numlines = NUMLINES,x;
  505.   static ARC_TYPE *arcsighead = NULL;
  506.  
  507.   *error = 0;               /* no error (yet) */
  508.   p = searchpath("ARCHIVER.BB2");
  509.   if(!p || !*p) {           /* can't find file */
  510.     *error = 1;
  511.     return NULL;
  512.   }
  513.   handle = _fsopen(p,"rt",SH_DENYNO);
  514.   if(!handle) {             /* can't open file */
  515.     *error = 2;
  516.     return NULL;
  517.   }
  518.   strcpy(archiverbb2,p);
  519.   if(!fgets(s,256,handle)) {  /* file is screwed up */
  520.     fclose(handle);
  521.     *error = 3;
  522.     return NULL;
  523.   }
  524.   p = strchr(s,';');
  525.   if(p)
  526.     *p = 0;
  527.   stripcr(s);
  528.   lstrip(s);
  529.   rstrip(s);
  530.   if(*s)
  531.     numlines = atoi(s);             /* # lines / record */
  532.   if(!*s || numlines < NUMLINES) {  /* too few lines; choke */
  533.     *error = 3;
  534.     return NULL;
  535.   }
  536.   while(!feof(handle)) {            /* load the records */
  537.     if(!fgets(s,256,handle))
  538.       break;
  539.     p = strchr(s,';');
  540.     if(p)
  541.       *p = 0;
  542.     stripcr(s);
  543.     lstrip(s);
  544.     rstrip(s);
  545.     if(*s) {
  546.       info = malloc(sizeof(ARC_TYPE));
  547.       if(!info)
  548.         break;
  549.       memset(info,0,sizeof(ARC_TYPE));
  550.       if(*s)
  551.         info->id = strdup(s);
  552.       else
  553.         info->id = NULL;
  554.       if(!fgets(s,256,handle))
  555.         break;
  556.       p = strchr(s,';');
  557.       if(p)
  558.         *p = 0;
  559.       stripcr(s);
  560.       lstrip(s);
  561.       rstrip(s);
  562.       if(*s)
  563.         info->ext = strdup(s);
  564.       else
  565.         info->ext = NULL;
  566.       if(!fgets(s,256,handle))
  567.         break;
  568.       p = strchr(s,';');
  569.       if(p)
  570.         *p = 0;
  571.       info->file_offset = atol(s);
  572.       if(!fgets(s,256,handle))
  573.         break;
  574.       p = strchr(s,';');
  575.       if(p)
  576.         *p = 0;
  577.       stripcr(s);
  578.       lstrip(s);
  579.       rstrip(s);
  580.       if(*s)
  581.         info->list = strdup(s);
  582.       else
  583.         info->list = NULL;
  584.       if(!info->list)
  585.         break;
  586.       if(!fgets(s,256,handle))
  587.         break;
  588.       p = strchr(s,';');
  589.       if(p)
  590.         *p = 0;
  591.       stripcr(s);
  592.       lstrip(s);
  593.       rstrip(s);
  594.       if(*s)
  595.         info->extract = strdup(s);
  596.       else
  597.         info->extract = NULL;
  598.       if(!fgets(s,256,handle))
  599.         break;
  600.       p = strchr(s,';');
  601.       if(p)
  602.         *p = 0;
  603.       stripcr(s);
  604.       lstrip(s);
  605.       rstrip(s);
  606.       if(*s)
  607.         info->exwdirs = strdup(s);
  608.       else
  609.         info->exwdirs = NULL;
  610.       if(!fgets(s,256,handle))
  611.         break;
  612.       p = strchr(s,';');
  613.       if(p)
  614.         *p = 0;
  615.       stripcr(s);
  616.       lstrip(s);
  617.       rstrip(s);
  618.       if(*s)
  619.         info->test = strdup(s);
  620.       else
  621.         info->test = NULL;
  622.       if(!fgets(s,256,handle))
  623.         break;
  624.       p = strchr(s,';');
  625.       if(p)
  626.         *p = 0;
  627.       stripcr(s);
  628.       lstrip(s);
  629.       rstrip(s);
  630.       if(*s)
  631.         info->create = strdup(s);
  632.       else
  633.         info->create = NULL;
  634.       if(!fgets(s,256,handle))
  635.         break;
  636.       p = strchr(s,';');
  637.       if(p)
  638.         *p = 0;
  639.       stripcr(s);
  640.       lstrip(s);
  641.       rstrip(s);
  642.       if(*s)
  643.         info->createwdirs = strdup(s);
  644.       else
  645.         info->createwdirs = NULL;
  646.       if(!fgets(s,256,handle))
  647.         break;
  648.       p = strchr(s,';');
  649.       if(p)
  650.         *p = 0;
  651.       stripcr(s);
  652.       lstrip(s);
  653.       rstrip(s);
  654.       if(*s)
  655.         info->createrecurse = strdup(s);
  656.       else
  657.         info->createrecurse = NULL;
  658.       if(!fgets(s,256,handle))
  659.         break;
  660.       p = strchr(s,';');
  661.       if(p)
  662.         *p = 0;
  663.       stripcr(s);
  664.       lstrip(s);
  665.       rstrip(s);
  666.       if(*s)
  667.         info->move = strdup(s);
  668.       else
  669.         info->move = NULL;
  670.       if(!fgets(s,256,handle))
  671.         break;
  672.       p = strchr(s,';');
  673.       if(p)
  674.         *p = 0;
  675.       stripcr(s);
  676.       lstrip(s);
  677.       rstrip(s);
  678.       if(*s)
  679.         info->movewdirs = strdup(s);
  680.       else
  681.         info->movewdirs = NULL;
  682.       if(!fgets(s,256,handle))
  683.         break;
  684.       p = strchr(s,';');
  685.       if(p)
  686.         *p = 0;
  687.       stripcr(s);
  688.       lstrip(s);
  689.       rstrip(s);
  690.       info->delete = strdup(s);
  691.       if(!fgets(s,256,handle))
  692.         break;
  693.       stripcr(s);
  694.       info->signature = strdup(literal(s));
  695.       if(!info->signature)
  696.         break;
  697.       if(!fgets(s,256,handle))
  698.         break;
  699.       stripcr(s);
  700.       info->startlist = strdup(s);
  701.       if(!fgets(s,256,handle))
  702.         break;
  703.       stripcr(s);
  704.       info->endlist = strdup(s);
  705.       if(!fgets(s,256,handle))
  706.         break;
  707.       p = strchr(s,';');
  708.       if(p)
  709.         *p = 0;
  710.       info->osizepos = atoi(s);
  711.       if(!fgets(s,256,handle))
  712.         break;
  713.       p = strchr(s,';');
  714.       if(p)
  715.         *p = 0;
  716.       info->nsizepos = atoi(s);
  717.       if(!fgets(s,256,handle))
  718.         break;
  719.       p = strchr(s,';');
  720.       if(p)
  721.         *p = 0;
  722.       info->fdpos = atoi(s);
  723.       if(!fgets(s,256,handle))
  724.         break;
  725.       p = strchr(s,';');
  726.       if(p)
  727.         *p = 0;
  728.       info->fdflds = atoi(s);
  729.       if(!fgets(s,256,handle))
  730.         break;
  731.       p = strchr(s,';');
  732.       if(p)
  733.         *p = 0;
  734.       info->fnpos = atoi(s);
  735.  
  736.       for(x = NUMLINES;x < numlines;x++) { /* skip extra lines
  737.         if(!fgets(s,256,handle))              since we don't understand
  738.           break;                              them */
  739.       }
  740.  
  741.       info->next = NULL;
  742.       if(!arcsighead)
  743.         arcsighead = last = info;
  744.       else {
  745.         last->next = info;
  746.         last = info;
  747.       }
  748.       if(info->extract && !*info->extract) {
  749.         free(info->extract);
  750.         info->extract = NULL;
  751.       }
  752.     }
  753.     info = NULL;
  754.   }
  755.   fclose(handle);
  756.   if(info) {
  757.     if(info->id)        free(info->id);
  758.     if(info->ext)       free(info->ext);
  759.     if(info->list)      free(info->list);
  760.     if(info->extract)   free(info->extract);
  761.     if(info->create)    free(info->create);
  762.     if(info->move)      free(info->move);
  763.     if(info->delete)    free(info->delete);
  764.     if(info->signature) free(info->signature);
  765.     if(info->startlist) free(info->startlist);
  766.     if(info->endlist)   free(info->endlist);
  767.     if(info->exwdirs)   free(info->exwdirs);
  768.     if(info->test)      free(info->test);
  769.     if(info->createrecurse)
  770.                         free(info->createrecurse);
  771.     if(info->createwdirs)
  772.                         free(info->createwdirs);
  773.     if(info->movewdirs) free(info->movewdirs);
  774.   }
  775.   if(!arcsighead) {   /* didn't get anything */
  776.     *error = 4;
  777.     return NULL;
  778.   }
  779.   return arcsighead;  /* head of list */
  780. }
  781.  
  782. #ifdef NEVER
  783.  
  784. typical usage:
  785.  
  786.   ARC_TYPE *arcsighead,*type;
  787.   INT      error;
  788.   CHAR     *filename = <whatever>,s[1050];
  789.  
  790.   arcsighead = load_archivers(&error);
  791.   if(!arcsighead) {
  792.     printf("\nCouldn't load archiver.bb2; error #%d\n",error);
  793.     exit(1);
  794.   }
  795.   /* might check to see if filename exists first... */
  796.   type = find_type(filename,arcsighead);
  797.   if(!type)
  798.     printf("\n%s is not an archive as I understand it.\n",filename);
  799.   else {
  800.     printf("\n%s appears to be a type %s archive.\n",filename,type->id);
  801.     if(type->extract && *type->extract) { /* extract all files in archive */
  802.     sprintf(s,"%s %s",type->extract,filename);
  803.     system(s);
  804.   }
  805.  
  806. #endif
  807.