home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume15 / caplib / part01 / caplib.c < prev   
Encoding:
C/C++ Source or Header  |  1990-12-17  |  5.9 KB  |  361 lines

  1. /*
  2.  * Copyright (c) 1983 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. /*
  19.  * From the BSD lpd source, cleaned into a general library by
  20.  * Marcus J. Ranum, Digital Equipment Corporation. 1990
  21.  *
  22.  * I took out the code that handled the multiple tc= entries, as
  23.  * the manner in which it was implemented was so vile, and nauseating
  24.  * as to be unmentionable. :) I added buffer-boundary checking everywhere
  25.  * appropriate, so now you can use more than BUFSIZ worth of information
  26.  * if that turns you on.
  27.  */
  28.  
  29. #include <ctype.h>
  30. #include <stdio.h>
  31.  
  32.  
  33. /*
  34.  * capnamatch deals with name matching.  The first field of the
  35.  * entry is a sequence of names separated by |'s, so we compare
  36.  * against each such name.  The normal : terminator after the last
  37.  * name (before the first field) stops us.
  38.  */
  39. static    int
  40. capnamatch(tbuf,np)
  41. register char    *tbuf;
  42. char    *np;
  43. {
  44.     register char    *p1;
  45.  
  46.     if (*tbuf == '#')
  47.         return(0);
  48.     for (;;) {
  49.         for (p1 = np; *p1 && *tbuf == *p1; tbuf++, p1++)
  50.             continue;
  51.  
  52.         if (*p1 == 0 && (*tbuf == '|' || *tbuf == ':' || *tbuf == 0))
  53.             return(1);
  54.  
  55.         while (*tbuf && *tbuf != ':' && *tbuf != '|')
  56.             tbuf++;
  57.  
  58.         if (*tbuf == 0 || *tbuf == ':')
  59.             return(0);
  60.         tbuf++;
  61.     }
  62. }
  63.  
  64.  
  65.  
  66.  
  67. capgetnext(fp,bp,bsiz)
  68. FILE        *fp;
  69. register char    *bp;
  70. int        bsiz;
  71. {
  72.     register int    c;
  73.     register int    skip = 0;
  74.     char        *tbuf;
  75.  
  76.     if (fp == NULL)
  77.         return(-1);
  78.  
  79.     tbuf = bp;
  80.     for (;;) {
  81.         switch (c = getc(fp)) {
  82.         case EOF:
  83.             fp = NULL;
  84.             return(0);
  85.  
  86.         case '\n':
  87.             if(bp == tbuf) {
  88.                 skip = 0;
  89.                 continue;
  90.             }
  91.             if (bp[-1] == '\\') {
  92.                 bp--;
  93.                 continue;
  94.             }
  95.             *bp = '\0';
  96.             return(1);
  97.  
  98.         case '#':
  99.             if (bp == tbuf)
  100.                 skip++;
  101.  
  102.         default:
  103.             if (skip)
  104.                 continue;
  105.             if (bp >= tbuf + bsiz) {
  106.                 *bp = '\0';
  107.                 return(2);
  108.             }
  109.             *bp++ = c;
  110.         }
  111.     }
  112. }
  113.  
  114.  
  115.  
  116.  
  117. static char *
  118. capskip(bp)
  119. register char    *bp;
  120. {
  121.  
  122.     while((*bp != '\0' && *bp != ':') || (*(bp - 1) == '\\' && *bp == ':'))
  123.         bp++;
  124.  
  125.     if(*bp == ':')
  126.         bp++;
  127.  
  128.     return(bp);
  129. }
  130.  
  131.  
  132.  
  133.  
  134.  
  135. /*
  136.  * Get an entry for entr "name" in buffer bp,
  137.  * from the cap file.  Parse is very rudimentary;
  138.  * we just notice escaped newlines.
  139.  */
  140. capgetent(capfile,name,bp,bsiz)
  141. char        *capfile;
  142. char        *name;
  143. char        *bp;
  144. int        bsiz;
  145. {
  146.     register char    *cp;
  147.     register int    c;
  148.     register int    i = 0;
  149.     register int    cnt = 0;
  150.     char        *tbuf;
  151.     FILE         *tf = (FILE *)NULL;
  152.     char        *cp2;
  153.  
  154.     tbuf = bp;
  155.     
  156.     if((tf = fopen(capfile,"r")) == (FILE *)NULL)
  157.         return(-1);
  158.  
  159.     for(;;) {
  160.         cp = bp;
  161.  
  162.         for(;;) {
  163.             if((c = getc(tf)) == EOF) {
  164.                 (void)fclose(tf);
  165.                 return(0);
  166.             }
  167.  
  168.             if (c == '\n') {
  169.                 if(cp > bp && *(cp - 1) == '\\'){
  170.                     cp--;
  171.                     continue;
  172.                 }
  173.                 break;
  174.             }
  175.  
  176.             if (cp >= bp + bsiz)
  177.                 return(2);
  178.  
  179.             *cp++ = c;
  180.         }
  181.         *cp = 0;
  182.  
  183.         /* The real work for the match. */
  184.         if(capnamatch(tbuf,name)) {
  185.             (void)fclose(tf);
  186.             return(1);
  187.         }
  188.     }
  189. }
  190.  
  191.  
  192.  
  193.  
  194.  
  195. /*
  196.  * Return the (numeric) option id.
  197.  * Numeric options look like
  198.  *    li#80
  199.  * i.e. the option string is separated from the numeric value by
  200.  * a # character.  If the option is not found we return -1.
  201.  * Note that we handle octal numbers beginning with 0.
  202.  */
  203. capgetnum(tbuf,id)
  204. char        *tbuf;
  205. char        *id;
  206. {
  207.     register int i, base;
  208.     register char *bp = tbuf;
  209.  
  210.     for (;;) {
  211.         bp = capskip(bp);
  212.         if(*bp == 0)
  213.             return(-1);
  214.  
  215.         if(*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
  216.             bp++;
  217.             if(*bp == '@')
  218.                 return(-1);
  219.  
  220.             if(*bp != '#')
  221.                 continue;
  222.             bp++;
  223.             base = 10;
  224.             if (*bp == '0')
  225.                 base = 8;
  226.             i = 0;
  227.  
  228.             while (isdigit(*bp))
  229.                 i *= base, i += *bp++ - '0';
  230.  
  231.             return(i);
  232.         }
  233.     }
  234. }
  235.  
  236.  
  237.  
  238.  
  239. /*
  240.  * Handle a flag option.
  241.  * Flag options are given "naked", i.e. followed by a : or the end
  242.  * of the buffer.  Return 1 if we find the option, or 0 if it is
  243.  * not given.
  244.  */
  245. capgetflag(tbuf,id)
  246. char        *tbuf;
  247. char        *id;
  248. {
  249.     register char *bp = tbuf;
  250.  
  251.     for(;;) {
  252.         bp = capskip(bp);
  253.         if(!*bp)
  254.             return (0);
  255.  
  256.         if(*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
  257.             if(!*bp || *bp == ':')
  258.                 return(1);
  259.             else
  260.                 if(*bp == '@')
  261.                     return(0);
  262.         }
  263.     }
  264. }
  265.  
  266.  
  267.  
  268.  
  269. /*
  270.  * capdecode does the grung work to decode the
  271.  * string capability escapes.
  272.  */
  273. static char *
  274. capdecode(str,area,asiz)
  275. register char    *str;
  276. char        **area;
  277. int        *asiz;
  278. {
  279.     register char    *cp;
  280.     register int    c;
  281.     register char    *dp;
  282.     int        i;
  283.  
  284.     cp = *area;
  285.  
  286.     while((c = *str++) && c != ':') {
  287.         switch (c) {
  288.  
  289.         case '^':
  290.             c = *str++ & 037;
  291.             break;
  292.  
  293.         case '\\':
  294.             dp = "E\033^^\\\\::n\nr\rt\tb\bf\f";
  295.             c = *str++;
  296. nextc:
  297.             if (*dp++ == c) {
  298.                 c = *dp++;
  299.                 break;
  300.             }
  301.             dp++;
  302.             if (*dp)
  303.                 goto nextc;
  304.  
  305.             if(isdigit(c)) {
  306.                 c -= '0', i = 2;
  307.                 do {
  308.                     c <<= 3, c |= *str++ - '0';
  309.                 } while(--i && isdigit(*str));
  310.             }
  311.             break;
  312.         }
  313.  
  314.         if(asiz != (int *)0 && (*asiz)-- <= 0)
  315.             return(NULL);
  316.  
  317.         *cp++ = c;
  318.     }
  319.     *cp++ = 0;
  320.     str = *area;
  321.     *area = cp;
  322.     return(str);
  323. }
  324.  
  325.  
  326.  
  327.  
  328. /*
  329.  * Get a string valued option.
  330.  * These are given as
  331.  *    cl=^Z
  332.  * Much decoding is done on the strings, and the strings are
  333.  * placed in area, which is a ref parameter which is updated.
  334.  */
  335. char *
  336. capgetstr(tbuf,id,area,asiz)
  337. char        *tbuf;
  338. char        *id;
  339. char        **area;
  340. int        *asiz;
  341. {
  342.     register char *bp = tbuf;
  343.  
  344.     for (;;) {
  345.         bp = capskip(bp);
  346.         if (!*bp)
  347.             return (0);
  348.  
  349.         if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
  350.             continue;
  351.  
  352.         if (*bp == '@')
  353.             return(0);
  354.  
  355.         if (*bp != '=')
  356.             continue;
  357.         bp++;
  358.         return(capdecode(bp,area,asiz));
  359.     }
  360. }
  361.