home *** CD-ROM | disk | FTP | other *** search
/ RBBS in a Box Volume 1 #3.1 / RBBSIABOX31.cdr / v2eg / usq.c < prev    next >
Text File  |  1990-09-29  |  9KB  |  384 lines

  1. static char *sccsid = "@(#)usq.c        1.8u (UCF) 83/09/02";
  2.  
  3. #include <stdio.h>
  4. /* #include <signal.h> */
  5. /* #include <ctype.h> */
  6.  
  7. #define TRUE 1
  8. #define FALSE 0
  9. #define ERROR (-1)
  10. #define PATHLEN 312    /* Number of characters allowed in pathname */
  11. #define OK 0
  12.  
  13. #define RECOGNIZE 0xFF76    /* unlikely pattern */
  14. #define DLE 0x90        /* repeat byte flag */
  15. #define SPEOF 256        /* special endfile token */
  16. #define NUMVALS 257        /* 256 data values plus SPEOF*/
  17. #define LARGE 30000
  18.  
  19. #ifdef VAX   /* then we don't want 32 bit integers */
  20.  
  21. typedef short INT;
  22. typedef unsigned short UNSIGNED;
  23.  
  24. #else    /*  16 bit machines  */
  25.  
  26. typedef int INT;
  27. typedef unsigned UNSIGNED;
  28.  
  29. #endif
  30.  
  31. struct _sqleaf {        /* Decoding tree */
  32.     INT _children[2];    /* left, right */
  33. };
  34. struct _sqleaf Dnode[NUMVALS - 1];
  35.  
  36.  
  37. INT Bpos;        /* last bit position read */
  38. INT Curin;        /* last byte value read */
  39. INT Repct;        /* Number of times to return value */
  40. INT Value;        /* current byte value or EOF */
  41.  
  42. INT MakeLCPathname=TRUE;    /* translate pathname to lc if all caps */
  43. INT Nlmode=FALSE;        /* zap cr's if true */
  44. INT Inbackground = FALSE;
  45.  
  46. INT getcr(), getuhuff(), portgetw();
  47.  
  48. extern int fflush(),ferror(),fclose();
  49. #define WILDCARD TRUE
  50.  
  51. main(argc, argv)
  52. unsigned char *argv[];
  53. {
  54.     register unsigned char *cp;
  55.     register INT npats=0;
  56.     unsigned char **patts;
  57.     INT n, errorstat;
  58.  
  59. /*
  60.     if (signal(SIGINT, SIG_IGN)==SIG_IGN)
  61.         Inbackground++;
  62.     else
  63.         signal(SIGINT, SIG_DFL);
  64.     signal(SIGHUP, SIG_IGN);
  65.                     */
  66.  
  67.     errorstat=0;
  68.     if(argc<2)
  69.         goto usage;
  70.     while (--argc) {
  71.         cp = *++argv;
  72.         if(*cp == '-') {
  73.             while( *++cp) {
  74.                 switch(*cp) {
  75.                 case 'n':
  76.                     Nlmode=TRUE; break;
  77.                 case 'u':
  78.                     MakeLCPathname=FALSE; break;
  79.                 default:
  80.                     goto usage;
  81.                 }
  82.             }
  83.         }
  84.         else if( !npats && argc>0) {
  85.             if(argv[0][0]) {
  86.                 npats=argc;
  87.                 patts=argv;
  88.             }
  89.         }
  90.     }
  91.     if(npats < 1) {
  92. usage:
  93.         fprintf(stderr,"Usage: usq [-nu] file ...\n");
  94.         fprintf(stderr,"\t-n Nlmode: remove carriage returns\n");
  95.         fprintf(stderr,"\t-u preserve Uppercase pathnames\n");
  96. #ifdef WILDCARD
  97.         fprintf(stderr,"\twildcards are acceptable in filenames.\n");
  98. #endif
  99.         exit(1);
  100.     }
  101.  
  102. #ifdef WILDCARD
  103.     for(n=0; n<npats; ++n){
  104.         unsigned char *dir(), *cp, *s;
  105.         if(cp=dir(patts[n],1)){
  106.            for(s=cp;*s;s+=(strlen(s)+1)) errorstat |= squeeze(s);
  107.            free(cp);
  108.         }
  109.         else errorstat |= squeeze(patts[n]);
  110.     }
  111. #else
  112.     for(n=0; n<npats; ++n)
  113.         errorstat |= squeeze(patts[n]);
  114. #endif
  115.  
  116.     exit(errorstat != 0);
  117. }
  118.  
  119. /*
  120.     The following code is primarily from typesq.c and utr.c.  Typesq
  121. is a modification of USQ by Dick Greenlaw.  Those modifications (usq
  122. to typesq) were made by Bob Mathias, I am responsible for the butchery
  123. done to make it work with cat.
  124.  
  125. */
  126.  
  127. FILE *in, *out;
  128. squeeze(fname)
  129. unsigned char *fname;
  130. {
  131.     register INT i, c;
  132.     register unsigned char *p;
  133.     register INT numnodes;            /* size of decoding tree */
  134.     register UNSIGNED crc;
  135.     UNSIGNED filecrc;
  136.     unsigned char origname[PATHLEN];    /* Original file name without
  137.                             drive */
  138.  
  139.     init_cr(); init_huff(); crc=0;
  140.  
  141.     if((in=fopen( fname, "rb"))==NULL) {
  142.         fprintf(stderr, "usq: can't open %s\n", fname);
  143.         return ERROR;
  144.     }
  145.     if(portgetw(in) != (INT) RECOGNIZE) {/* Process header */
  146.         fprintf(stderr, "usq: %s is not a SQueezed file\n", fname);
  147.         return(ERROR);
  148.     }
  149.     filecrc = (UNSIGNED) portgetw(in);    /* checksum */
  150.     p = origname;                /* Get original file name */
  151.     do {                    /* send it to array */
  152.         *p = getc(in);
  153.     } while(*p++ != '\0');
  154.  
  155.     numnodes = portgetw(in);
  156.     if(numnodes < 0 || numnodes >= NUMVALS) {
  157.         fprintf(stderr, "usq: %s has invalid decode tree\n", fname);
  158.         fclose(in);
  159.         return(ERROR);
  160.     }
  161.     /* Initialize for possible empty tree (SPEOF only) */
  162.     Dnode[0]._children[0] = -(SPEOF + 1);
  163.     Dnode[0]._children[1] = -(SPEOF + 1);
  164.  
  165.     for(i = 0; i < numnodes; ++i) { /* Get decoding tree from file */
  166.         Dnode[i]._children[0] = portgetw(in);
  167.         Dnode[i]._children[1] = portgetw(in);
  168.     }
  169.     /* Get translated output bytes and write file */
  170.     if(MakeLCPathname && !IsAnyLower(origname))
  171.         uncaps(origname);
  172.     for(p=origname; *p; ++p)        /* change / to _ */
  173.         if( *p == '/')
  174.             *p = '_';
  175.     if (!Inbackground)
  176.         fprintf(stderr, "usq: %s -> %s\n",fname,origname);
  177.     if((out=fopen(origname, "wb"))==NULL) {
  178.         fprintf(stderr, "usq: can't create %s\n", origname);
  179.     }
  180.     while ((c = getcr()) != EOF) {
  181.         crc += (UNSIGNED) c;
  182.         if ( c == '\r' && Nlmode)
  183.             continue;
  184.         if(fputc(c,out)!=c){
  185.             fclose(in);
  186.             abort("usq: error in writing file: %s\n",origname);
  187.         }
  188.     }
  189.     fclose(in);
  190.  
  191.     if(fflush(out)<0 || ferror(out)<0)
  192.         abort("usq: Error writing file: %s\n",origname);
  193.     if(fclose(out)<0)
  194.         abort("usq: Error closing file: %s\n",origname);
  195.  
  196.     if( crc != filecrc ) {
  197.         fprintf(stderr, "usq: bad checksum in %s\n", fname);
  198.         fflush(stdout);
  199.         return(ERROR);
  200.     }
  201.     return(OK);
  202. }
  203. /*** from utr.c - */
  204. /* initialize decoding functions */
  205.  
  206. init_cr()
  207. {
  208.     Repct = 0;
  209. }
  210.  
  211. init_huff()
  212. {
  213.     Bpos = 99;    /* force initial read */
  214. }
  215.  
  216. /* Get bytes with decoding - this decodes repetition,
  217.  * calls getuhuff to decode file stream into byte
  218.  * level code with only repetition encoding.
  219.  *
  220.  * The code is simple passing through of bytes except
  221.  * that DLE is encoded as DLE-zero and other values
  222.  * repeated more than twice are encoded as value-DLE-count.
  223.  */
  224.  
  225. INT
  226. getcr()
  227. {
  228.     register INT c;
  229.  
  230.     if(Repct > 0) {
  231.         /* Expanding a repeated char */
  232.         --Repct;
  233.         return(Value);
  234.     } else {
  235.         /* Nothing unusual */
  236.         if((c = getuhuff()) != DLE) {
  237.             /* It's not the special delimiter */
  238.             Value = c;
  239.             if(Value == EOF)
  240.                 Repct = LARGE;
  241.             return(Value);
  242.         } else {
  243.             /* Special token */
  244.             if((Repct = getuhuff()) == 0)
  245.                 /* DLE, zero represents DLE */
  246.                 return(DLE);
  247.             else {
  248.                 /* Begin expanding repetition */
  249.                 Repct -= 2;    /* 2nd time */
  250.                 return(Value);
  251.             }
  252.         }
  253.     }
  254. }
  255. /* Decode file stream into a byte level code with only
  256.  * repetition encoding remaining.
  257.  */
  258.  
  259. INT
  260. getuhuff()
  261. {
  262.     register INT i;
  263.  
  264.     /* Follow bit stream in tree to a leaf*/
  265.     i = 0;    /* Start at root of tree */
  266.     do {
  267.         if(++Bpos > 7) {
  268.             if((Curin = getc(in)) == ERROR)
  269.                 return(ERROR);
  270.             Bpos = 0;
  271.             /* move a level deeper in tree */
  272.             i = Dnode[i]._children[1 & Curin];
  273.         } else
  274.             i = Dnode[i]._children[1 & (Curin >>= 1)];
  275.     } while(i >= 0);
  276.  
  277.     /* Decode fake node index to original data value */
  278.     i = -(i + 1);
  279.     /* Decode special endfile token to normal EOF */
  280.     i = (i == SPEOF) ? EOF : i;
  281.     return(i);
  282. }
  283. /*
  284.  * Machine independent getw which always gets bytes in the same order
  285.  *  as the CP/M version of SQ wrote them
  286.  */
  287. INT
  288. portgetw(f)
  289. FILE *f;
  290. {
  291.     register INT c;
  292.  
  293.     c = getc(f) & 0377;
  294.     return(c | (getc(f) << 8));
  295. }
  296.  
  297.  
  298. /* make string s lower case */
  299. uncaps(s)
  300. unsigned char *s;
  301. {
  302.     for( ; *s; ++s)
  303.         if(isupper(*s))
  304.             *s = tolower(*s);
  305. }
  306.  
  307.  
  308. /*
  309.  * IsAnyLower returns TRUE if string s has lower case letters.
  310.  */
  311. IsAnyLower(s)
  312. unsigned char *s;
  313. {
  314.     for( ; *s; ++s)
  315.         if (islower(*s))
  316.             return(TRUE);
  317.     return(FALSE);
  318. }
  319.  
  320. /*    dir: for DOS ALL
  321.  
  322.     Entry:
  323.         1. Filename possibly containing wildcards ? and *
  324.         2. Drive specifier flag
  325.  
  326.     Returns: Pointer to data area containing NULL terminated
  327.          list of filenames, or NULL if none found.
  328.  
  329.     Notes: User must free up data allocated by this function
  330.         with free() if memory is to be restored to heap
  331.         after use.
  332.  
  333.           Drive specifier: if non-zero will drive specifiers
  334.         will be put on file names
  335.  
  336.           Path names: not supported
  337.  
  338. */
  339.  
  340. unsigned char *dir(filespec,drflag)
  341. unsigned char *filespec;
  342. short drflag;
  343. {
  344. #define BLOCK 100        /* room for fcb,dta,etc.. */
  345. #define FIRST 0x1100        /* search first */
  346. #define NEXT 0x1200        /* search next */
  347. #define CURRENT 0x19        /* get current drive */
  348. #define PARSE 0x2900        /* parse file name */
  349. #define SETDTA 0x1a00        /* set disk transfer address */
  350.  
  351. unsigned char *fcb,*rets,*cp,*tmp,*dta,*realloc();
  352. unsigned short mode,pos,i;
  353. struct regval { int ax,bx,cx,dx,si,di,ds,es;} r;
  354.  
  355.   tmp=realloc(0,BLOCK); fcb=realloc(0,BLOCK);
  356.   dta=realloc(0,BLOCK); rets=realloc(0,BLOCK);
  357.  
  358.   segread(&r.si);            /* parse file name */
  359.   r.es=r.ds; r.si=filespec; r.di=fcb; r.ax=PARSE; sysint21(&r,&r);
  360.  
  361.   segread(&r.si);            /* set dta */
  362.   r.dx=dta; r.ax=SETDTA; sysint21(&r,&r);
  363.  
  364.   for(pos=0,mode=FIRST;;mode=NEXT){
  365.     segread(&r.si); r.ax=mode; r.dx=fcb; sysint21(&r,&r);    /* search  */
  366.     if(r.ax&0xff==0xff)break;            /* not found */
  367.     cp=tmp;
  368.     if(drflag){                /* put on drive specifier */
  369.         if(*dta==0)*dta=(bdos(CURRENT)&0xff)+1;
  370.         *cp++=*dta+'A'-1; *cp++=':';
  371.     }
  372.     for(i=1;i<9;i++)if(*(dta+i)!=' ')*cp++=*(dta+i); *cp++='.';
  373.     for(;i<12;i++)if(*(dta+i)!=' ')*cp++=*(dta+i); *cp='\0';
  374.     rets=realloc(rets,pos+strlen(tmp)+1);    /* store file name */
  375.     strcpy(rets+pos,tmp);
  376.     pos+=(strlen(tmp)+1);
  377.   }
  378.  
  379.   if(pos)rets=realloc(rets,pos+strlen(tmp)+1);
  380.   else free(rets);
  381.   free(fcb); free(tmp); free(dta);
  382.   return pos ? rets: 0;
  383. }
  384. pos)rets=realloc(ret