mjr@decuac.DEC.COM (Marcus J. Ranum) (12/18/90)
Posting-number: Volume 15, Issue 104 Submitted-by: mjr@decuac.DEC.COM (Marcus J. Ranum) Archive-name: caplib/part01 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: caplib.3 caplib.c # Wrapped by mjr@hussar.dco.dec.com on Wed Nov 28 22:14:23 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f caplib.3 -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"caplib.3\" else echo shar: Extracting \"caplib.3\" \(4168 characters\) sed "s/^X//" >caplib.3 <<'END_OF_caplib.3' X.\" Copyright (c) 1980 The Regents of the University of California. X.\" All rights reserved. X.\" X.\" Redistribution and use in source and binary forms are permitted provided X.\" that: (1) source distributions retain this entire copyright notice and X.\" comment, and (2) distributions including binaries display the following X.\" acknowledgement: ``This product includes software developed by the X.\" University of California, Berkeley and its contributors'' in the X.\" documentation or other materials provided with the distribution and in X.\" all advertising materials mentioning features or use of this software. X.\" Neither the name of the University nor the names of its contributors may X.\" be used to endorse or promote products derived from this software without X.\" specific prior written permission. X.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED X.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF X.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X.\" X.\" @(#)termcap.3 6.5 (Berkeley) 6/23/90 X.\" X.\" modified to reflect caplib changes by Marcus Ranum, DEC, 1990 X.\" mjr@decuac.dec.com X.\" X.TH CAPLIB 3 "Dec 1, 1990" X.UC 4 X.SH NAME Xcapgetent, capgetnum, capgetflag, capgetstr \- capabilities database routines. X.SH SYNOPSIS X.nf X.PP X.B capgetent(capfile, name, capbuf, capbufsiz) X.B char *capfile, *name, *capbuf; X.B int capbufsiz; X.PP X.B capgetnum(capbuf, id) X.B char *capbuf, *id; X.PP X.B capgetflag(capbuf,id) X.B char *capbuf, *id; X.PP X.B char * X.B capgetstr(capbuf, id, area, asizep) X.B char *capbuf, *id, **area; X.B int *asizep; X.PP X.B capgetnext(fp, capbuf, capbufsiz) X.B FILE *fp; X.B char *capbuf; X.B int capbufsiz; X.fi X.SH DESCRIPTION XThese functions extract and use capabilities from a terminal capability-style Xdata base, the format of which is described in X.IR termcap (5). X.PP X.I Capgetent Xextracts the entry for the capability from the file named X.I capfile Xand the entry X.I name Xinto the buffer at X.I capbuf. X.I Capbuf Xis assumed to be at least of size capbufsiz Xand may be passed to subsequent calls to X.I capgetnum, X.I capgetflag, Xand X.I capgetstr. X.I Capgetent Xreturns \-1 if the Xdata base file could be opened, X0 if the capability name given does not have an entry, X2 if the buffer is not sufficiently large, Xand 1 if all goes well. X.I Capgetent Xdoes not check for environment variables or user-defined capabilities Xfiles, though such searches can easily be performed as a higher level Xof software that makes multiple calls to X.I capgetent. X.PP X.I Capgetnum Xgets the numeric value of capability X.I id, Xfrom the capability buffer X.I capbuf Xreturning \-1 if is not given for the database entry. X.I Capgetflag Xreturns 1 if the specified capability is present in Xthe database's entry, 0 if it is not. X.I Capgetstr Xreturns the string value of the capability X.I id, Xfrom the buffer X.I capbuf, Xplaces it in a second buffer at X.I area, Xand advances the X.I area Xpointer. The remaining amount of space in X.I area Xis stored in X.I asizep Xand is adjusted as more space is used. If X.I asizep Xis a null pointer, the size of the buffer is assumed to be infinite. You Xare warned. When a call to X.I capgetstr Xis made initially, the value of the contents of X.I asizep Xshould accurately reflect the size of the area. XIt decodes the abbreviations for this field described in X.IR termcap (5). X.I Capgetstr Xreturns NULL if the capability was not found. X.PP X.I Capgetnext Xreads the next database entry from the FILE pointer X.I fp Xinto the space provided at X.I capbuf Xup to a maximum size of X.I capbufsiz. X1 is returned if the read was succesful, 0 is returned at end-of-file, X-1 is returned if the FILE pointer is a null pointer, and 2 is returned Xif the space provided was insufficient. X.SH FILES X.SH LIMITATIONS XThe caplib library differs from X.I termcap Xin that the "tc=" kludge has been removed and size checking has been Xadded. Checking environmental variables is not supported as in X.I termcap Xbut can easily be supported in higher-level code (which is where Xit belonged in the first place). No file descriptors are kept open, Xnor are there any globals. X.DT X.SH SEE ALSO Xex(1), curses(3), termcap(5) END_OF_caplib.3 if test 4168 -ne `wc -c <caplib.3`; then echo shar: \"caplib.3\" unpacked with wrong size! fi # end of overwriting check fi if test -f caplib.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"caplib.c\" else echo shar: Extracting \"caplib.c\" \(6015 characters\) sed "s/^X//" >caplib.c <<'END_OF_caplib.c' X/* X * Copyright (c) 1983 Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that the above copyright notice and this paragraph are X * duplicated in all such forms and that any documentation, X * advertising materials, and other materials related to such X * distribution and use acknowledge that the software was developed X * by the University of California, Berkeley. The name of the X * University may not be used to endorse or promote products derived X * from this software without specific prior written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. X */ X X/* X * From the BSD lpd source, cleaned into a general library by X * Marcus J. Ranum, Digital Equipment Corporation. 1990 X * X * I took out the code that handled the multiple tc= entries, as X * the manner in which it was implemented was so vile, and nauseating X * as to be unmentionable. :) I added buffer-boundary checking everywhere X * appropriate, so now you can use more than BUFSIZ worth of information X * if that turns you on. X */ X X#include <ctype.h> X#include <stdio.h> X X X/* X * capnamatch deals with name matching. The first field of the X * entry is a sequence of names separated by |'s, so we compare X * against each such name. The normal : terminator after the last X * name (before the first field) stops us. X */ Xstatic int Xcapnamatch(tbuf,np) Xregister char *tbuf; Xchar *np; X{ X register char *p1; X X if (*tbuf == '#') X return(0); X for (;;) { X for (p1 = np; *p1 && *tbuf == *p1; tbuf++, p1++) X continue; X X if (*p1 == 0 && (*tbuf == '|' || *tbuf == ':' || *tbuf == 0)) X return(1); X X while (*tbuf && *tbuf != ':' && *tbuf != '|') X tbuf++; X X if (*tbuf == 0 || *tbuf == ':') X return(0); X tbuf++; X } X} X X X X Xcapgetnext(fp,bp,bsiz) XFILE *fp; Xregister char *bp; Xint bsiz; X{ X register int c; X register int skip = 0; X char *tbuf; X X if (fp == NULL) X return(-1); X X tbuf = bp; X for (;;) { X switch (c = getc(fp)) { X case EOF: X fp = NULL; X return(0); X X case '\n': X if(bp == tbuf) { X skip = 0; X continue; X } X if (bp[-1] == '\\') { X bp--; X continue; X } X *bp = '\0'; X return(1); X X case '#': X if (bp == tbuf) X skip++; X X default: X if (skip) X continue; X if (bp >= tbuf + bsiz) { X *bp = '\0'; X return(2); X } X *bp++ = c; X } X } X} X X X X Xstatic char * Xcapskip(bp) Xregister char *bp; X{ X X while((*bp != '\0' && *bp != ':') || (*(bp - 1) == '\\' && *bp == ':')) X bp++; X X if(*bp == ':') X bp++; X X return(bp); X} X X X X X X/* X * Get an entry for entr "name" in buffer bp, X * from the cap file. Parse is very rudimentary; X * we just notice escaped newlines. X */ Xcapgetent(capfile,name,bp,bsiz) Xchar *capfile; Xchar *name; Xchar *bp; Xint bsiz; X{ X register char *cp; X register int c; X register int i = 0; X register int cnt = 0; X char *tbuf; X FILE *tf = (FILE *)NULL; X char *cp2; X X tbuf = bp; X X if((tf = fopen(capfile,"r")) == (FILE *)NULL) X return(-1); X X for(;;) { X cp = bp; X X for(;;) { X if((c = getc(tf)) == EOF) { X (void)fclose(tf); X return(0); X } X X if (c == '\n') { X if(cp > bp && *(cp - 1) == '\\'){ X cp--; X continue; X } X break; X } X X if (cp >= bp + bsiz) X return(2); X X *cp++ = c; X } X *cp = 0; X X /* The real work for the match. */ X if(capnamatch(tbuf,name)) { X (void)fclose(tf); X return(1); X } X } X} X X X X X X/* X * Return the (numeric) option id. X * Numeric options look like X * li#80 X * i.e. the option string is separated from the numeric value by X * a # character. If the option is not found we return -1. X * Note that we handle octal numbers beginning with 0. X */ Xcapgetnum(tbuf,id) Xchar *tbuf; Xchar *id; X{ X register int i, base; X register char *bp = tbuf; X X for (;;) { X bp = capskip(bp); X if(*bp == 0) X return(-1); X X if(*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) { X bp++; X if(*bp == '@') X return(-1); X X if(*bp != '#') X continue; X bp++; X base = 10; X if (*bp == '0') X base = 8; X i = 0; X X while (isdigit(*bp)) X i *= base, i += *bp++ - '0'; X X return(i); X } X } X} X X X X X/* X * Handle a flag option. X * Flag options are given "naked", i.e. followed by a : or the end X * of the buffer. Return 1 if we find the option, or 0 if it is X * not given. X */ Xcapgetflag(tbuf,id) Xchar *tbuf; Xchar *id; X{ X register char *bp = tbuf; X X for(;;) { X bp = capskip(bp); X if(!*bp) X return (0); X X if(*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) { X if(!*bp || *bp == ':') X return(1); X else X if(*bp == '@') X return(0); X } X } X} X X X X X/* X * capdecode does the grung work to decode the X * string capability escapes. X */ Xstatic char * Xcapdecode(str,area,asiz) Xregister char *str; Xchar **area; Xint *asiz; X{ X register char *cp; X register int c; X register char *dp; X int i; X X cp = *area; X X while((c = *str++) && c != ':') { X switch (c) { X X case '^': X c = *str++ & 037; X break; X X case '\\': X dp = "E\033^^\\\\::n\nr\rt\tb\bf\f"; X c = *str++; Xnextc: X if (*dp++ == c) { X c = *dp++; X break; X } X dp++; X if (*dp) X goto nextc; X X if(isdigit(c)) { X c -= '0', i = 2; X do { X c <<= 3, c |= *str++ - '0'; X } while(--i && isdigit(*str)); X } X break; X } X X if(asiz != (int *)0 && (*asiz)-- <= 0) X return(NULL); X X *cp++ = c; X } X *cp++ = 0; X str = *area; X *area = cp; X return(str); X} X X X X X/* X * Get a string valued option. X * These are given as X * cl=^Z X * Much decoding is done on the strings, and the strings are X * placed in area, which is a ref parameter which is updated. X */ Xchar * Xcapgetstr(tbuf,id,area,asiz) Xchar *tbuf; Xchar *id; Xchar **area; Xint *asiz; X{ X register char *bp = tbuf; X X for (;;) { X bp = capskip(bp); X if (!*bp) X return (0); X X if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1]) X continue; X X if (*bp == '@') X return(0); X X if (*bp != '=') X continue; X bp++; X return(capdecode(bp,area,asiz)); X } X} END_OF_caplib.c if test 6015 -ne `wc -c <caplib.c`; then echo shar: \"caplib.c\" unpacked with wrong size! fi chmod +x caplib.c # end of overwriting check fi echo shar: End of shell archive. exit 0