home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1983 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
- /*
- * From the BSD lpd source, cleaned into a general library by
- * Marcus J. Ranum, Digital Equipment Corporation. 1990
- *
- * I took out the code that handled the multiple tc= entries, as
- * the manner in which it was implemented was so vile, and nauseating
- * as to be unmentionable. :) I added buffer-boundary checking everywhere
- * appropriate, so now you can use more than BUFSIZ worth of information
- * if that turns you on.
- */
-
- #include <ctype.h>
- #include <stdio.h>
-
-
- /*
- * capnamatch deals with name matching. The first field of the
- * entry is a sequence of names separated by |'s, so we compare
- * against each such name. The normal : terminator after the last
- * name (before the first field) stops us.
- */
- static int
- capnamatch(tbuf,np)
- register char *tbuf;
- char *np;
- {
- register char *p1;
-
- if (*tbuf == '#')
- return(0);
- for (;;) {
- for (p1 = np; *p1 && *tbuf == *p1; tbuf++, p1++)
- continue;
-
- if (*p1 == 0 && (*tbuf == '|' || *tbuf == ':' || *tbuf == 0))
- return(1);
-
- while (*tbuf && *tbuf != ':' && *tbuf != '|')
- tbuf++;
-
- if (*tbuf == 0 || *tbuf == ':')
- return(0);
- tbuf++;
- }
- }
-
-
-
-
- capgetnext(fp,bp,bsiz)
- FILE *fp;
- register char *bp;
- int bsiz;
- {
- register int c;
- register int skip = 0;
- char *tbuf;
-
- if (fp == NULL)
- return(-1);
-
- tbuf = bp;
- for (;;) {
- switch (c = getc(fp)) {
- case EOF:
- fp = NULL;
- return(0);
-
- case '\n':
- if(bp == tbuf) {
- skip = 0;
- continue;
- }
- if (bp[-1] == '\\') {
- bp--;
- continue;
- }
- *bp = '\0';
- return(1);
-
- case '#':
- if (bp == tbuf)
- skip++;
-
- default:
- if (skip)
- continue;
- if (bp >= tbuf + bsiz) {
- *bp = '\0';
- return(2);
- }
- *bp++ = c;
- }
- }
- }
-
-
-
-
- static char *
- capskip(bp)
- register char *bp;
- {
-
- while((*bp != '\0' && *bp != ':') || (*(bp - 1) == '\\' && *bp == ':'))
- bp++;
-
- if(*bp == ':')
- bp++;
-
- return(bp);
- }
-
-
-
-
-
- /*
- * Get an entry for entr "name" in buffer bp,
- * from the cap file. Parse is very rudimentary;
- * we just notice escaped newlines.
- */
- capgetent(capfile,name,bp,bsiz)
- char *capfile;
- char *name;
- char *bp;
- int bsiz;
- {
- register char *cp;
- register int c;
- register int i = 0;
- register int cnt = 0;
- char *tbuf;
- FILE *tf = (FILE *)NULL;
- char *cp2;
-
- tbuf = bp;
-
- if((tf = fopen(capfile,"r")) == (FILE *)NULL)
- return(-1);
-
- for(;;) {
- cp = bp;
-
- for(;;) {
- if((c = getc(tf)) == EOF) {
- (void)fclose(tf);
- return(0);
- }
-
- if (c == '\n') {
- if(cp > bp && *(cp - 1) == '\\'){
- cp--;
- continue;
- }
- break;
- }
-
- if (cp >= bp + bsiz)
- return(2);
-
- *cp++ = c;
- }
- *cp = 0;
-
- /* The real work for the match. */
- if(capnamatch(tbuf,name)) {
- (void)fclose(tf);
- return(1);
- }
- }
- }
-
-
-
-
-
- /*
- * Return the (numeric) option id.
- * Numeric options look like
- * li#80
- * i.e. the option string is separated from the numeric value by
- * a # character. If the option is not found we return -1.
- * Note that we handle octal numbers beginning with 0.
- */
- capgetnum(tbuf,id)
- char *tbuf;
- char *id;
- {
- register int i, base;
- register char *bp = tbuf;
-
- for (;;) {
- bp = capskip(bp);
- if(*bp == 0)
- return(-1);
-
- if(*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
- bp++;
- if(*bp == '@')
- return(-1);
-
- if(*bp != '#')
- continue;
- bp++;
- base = 10;
- if (*bp == '0')
- base = 8;
- i = 0;
-
- while (isdigit(*bp))
- i *= base, i += *bp++ - '0';
-
- return(i);
- }
- }
- }
-
-
-
-
- /*
- * Handle a flag option.
- * Flag options are given "naked", i.e. followed by a : or the end
- * of the buffer. Return 1 if we find the option, or 0 if it is
- * not given.
- */
- capgetflag(tbuf,id)
- char *tbuf;
- char *id;
- {
- register char *bp = tbuf;
-
- for(;;) {
- bp = capskip(bp);
- if(!*bp)
- return (0);
-
- if(*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
- if(!*bp || *bp == ':')
- return(1);
- else
- if(*bp == '@')
- return(0);
- }
- }
- }
-
-
-
-
- /*
- * capdecode does the grung work to decode the
- * string capability escapes.
- */
- static char *
- capdecode(str,area,asiz)
- register char *str;
- char **area;
- int *asiz;
- {
- register char *cp;
- register int c;
- register char *dp;
- int i;
-
- cp = *area;
-
- while((c = *str++) && c != ':') {
- switch (c) {
-
- case '^':
- c = *str++ & 037;
- break;
-
- case '\\':
- dp = "E\033^^\\\\::n\nr\rt\tb\bf\f";
- c = *str++;
- nextc:
- if (*dp++ == c) {
- c = *dp++;
- break;
- }
- dp++;
- if (*dp)
- goto nextc;
-
- if(isdigit(c)) {
- c -= '0', i = 2;
- do {
- c <<= 3, c |= *str++ - '0';
- } while(--i && isdigit(*str));
- }
- break;
- }
-
- if(asiz != (int *)0 && (*asiz)-- <= 0)
- return(NULL);
-
- *cp++ = c;
- }
- *cp++ = 0;
- str = *area;
- *area = cp;
- return(str);
- }
-
-
-
-
- /*
- * Get a string valued option.
- * These are given as
- * cl=^Z
- * Much decoding is done on the strings, and the strings are
- * placed in area, which is a ref parameter which is updated.
- */
- char *
- capgetstr(tbuf,id,area,asiz)
- char *tbuf;
- char *id;
- char **area;
- int *asiz;
- {
- register char *bp = tbuf;
-
- for (;;) {
- bp = capskip(bp);
- if (!*bp)
- return (0);
-
- if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
- continue;
-
- if (*bp == '@')
- return(0);
-
- if (*bp != '=')
- continue;
- bp++;
- return(capdecode(bp,area,asiz));
- }
- }
-