[comp.sources.misc] v15i104: capabilities database routines

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