v16i069: generic capability database routines., Part01/01
Simon J. Gerraty
sjg at zen.void.oz.au
Sat Jan 12 16:16:32 AEST 1991
Submitted-by: sjg at zen.void.oz.au (Simon J. Gerraty)
Posting-number: Volume 16, Issue 69
Archive-name: cap/part01
facility analagous to termcap(3X) but in a slightly more general
manner. These routines can be used to extract entries from
files that follow the termcap(5),printcap(5) format.
cap_getent() will search up to MAX_DBASE files for an entry and
follows ":tc=like:" pointers. The header section of cap.c
includes the documentation.
--------------------(cut)--------------------
echo x - cap.c
sed 's/^X//' >cap.c <<'*-*-END-of-cap.c-*-*'
X/* NAME:
X * cap.c - generic capability database facility.
X *
X * SYNOPSIS:
X * int cap_getent(char *buf, char *name);
X * int cap_ngetent(char *buf, char *name, int nbytes);
X * char *cap_getstr(char *id, char **area);
X * int cap_getnum(char *id);
X * int cap_getflag(char *id);
X *
X * DESCRIPTION:
X * The cap module provides functions similar to termcap(3X).
X * It is more general however. An application can
X * initialize *_cap_database[0-MAX_DBASE] to a list of
X * database files to search for cap entries.
X *
X * Each file refered to by _cap_database[n] is expected to
X * follow the layout of /etc/termcap. If _cap_database[0]
X * is not initialized the package "should" behave like the
X * equivalent termcap facilities.
X *
X * An application must call cap_getent or cap_ngetent
X * before calling any of the other functions. cap_getent
X * simply calls cap_ngetent with an assumed size of the
X * buffer provided by the application. The buffer passed
X * to cap_ngetent must remain valid for all subsequent
X * calls to this module.
X *
X * cap_ngetent will "follow" a ":tc=like:" at the end of an
X * an entry using recursive calls to cap_ngetent. If the
X * "like" entry is not found in any of the files refered to
X * by *_cap_database[] it is left as ":tc=like:".
X *
X *
X * RETURN VALUE:
X * cap_getent 1==success, 0==entry not found, -1==error.
X * cap_ngetent nbytes copied==success, 0==entry not found, -1==error.
X * cap_getstr str==success, NULL==failure.
X * cap_getnum num=success, -1==failure.
X * cap_getflag 1==success, 0==not found
X *
X * FILES:
X * /etc/termcap default database
X *
X * SEE ALSO:
X * termcap(3X), termcap(5), printcap(5).
X *
X * BUGS:
X * cap_get{str,num,flag} do not tolerate any spaces between
X * the : and the name. That is ":tc=like:" is ok, but
X * ": tc=like:" is not, nor is ":tc =like:". Whether this
X * is a bug or a feature is a bit subjective :-)
X *
X * cap_getstr does not interperate the content of the
X * string capability found in any way. (unlike tgetstr(3)).
X *
X * AMENDED:
X * 91/01/08 16:58:12 (sjg)
X *
X * RELEASED:
X * 91/01/08 16:58:15 v1.8
X *
X * SCCSID:
X * @(#)cap.c 1.8 91/01/08 16:58:12 (sjg)
X *
X * Copyright (c) 1989 Simon J. Gerraty.
X *
X * This is free software. It comes with NO WARRANTY.
X * Permission to use, modify and distribute this source code
X * is granted subject to the following conditions.
X * 1/ that that the above copyright notice and this notice
X * are preserved in all copies and that due credit be given
X * to the author.
X * 2/ that any changes to this code are clearly commented
X * as such so that the author does get blamed for bugs
X * other than his own.
X *
X * Please send copies of changes and bug-fixes to:
X * sjg at zen.void.oz.au
X *
X */
X#ifndef lint
Xstatic char sccs_id[] = "@(#)cap.c 1.8 91/01/08 16:58:12 (sjg)";
X#endif
X
X/* include files */
X#include <stdio.h>
X#ifdef __STDC__
X# include <stdlib.h>
X#endif
X#ifdef USG
X# include <string.h>
X#else
X# include <strings.h>
X# define strchr index
X# define strrchr rindex
X#endif /* USG */
X
X#define EXTERN
X#include "cap.h"
X#undef EXTERN
X
X/* some useful #defines */
X#define ENTRY
X#define LOCAL static
X#define TRUE 1
X#define FALSE 0
X
X#if defined(__STDC__) || defined(PROTO)
X# define _P_(p) p
X#else
X# define _P_(p) ()
X#endif
X
X/* manifest constants */
X
X/* macros */
X
X/* globals */
Xstatic char capname[CAP_NAMESZ + 1];
X
X
X/* external variable declarations */
X
X/* function prototypes */
Xextern char *getenv _P_((char *));
Xextern char *strstr _P_((const char *s1, const char *s2));
X
X
X
X/* functions */
X
X
X/* NAME:
X * cap_getent - look for capability description
X *
X * SYNOPSIS:
X * int cap_getent(char *buf, char *name);
X *
X * DESCRIPTION:
X * Look for cap entry "name" in either /etc/termcap, the
X * environment or the files listed in *_cap_database[].
X * If an entry is found it is copied to "buf".
X * ":tc=like:" entries cause a recursive call to cap_ngetent.
X *
X * RETURN VALUE:
X * 1==success, 0==entry not found, -1==failure
X */
X
XENTRY int
Xcap_getent(buf, name)
X char *buf;
X char *name;
X{
X register int i;
X
X return (((i = cap_ngetent(buf, name, (CAP_BUFSZ - 1))) > 0)
X ? 1 : i);
X}
X
X
X/* NAME:
X * cap_ngetent - look for capability description
X *
X * SYNOPSIS:
X * int cap_ngetent(char *buf, char *name, int nbytes);
X *
X * DESCRIPTION:
X * Look for cap entry "name" in either /etc/termcap, the
X * environment or the files listed in *_cap_database[].
X * If an entry is found it is copied to "buf" up to a
X * maximum of "nbytes".
X * ":tc=like:" entries cause a recursive call to cap_ngetent.
X *
X * RETURN VALUE:
X * nbytes copied==success, 0==entry not found, -1==failure
X */
X
XENTRY int
Xcap_ngetent(buf, name, nbytes)
X char *buf;
X char *name;
X int nbytes;
X{
X static callcnt = 0; /* check if we're recursing */
X register char *rcp;
X register int len;
X FILE *fp;
X char *cp;
X char tc_name[CAP_NAMESZ + 1];
X int finished = FALSE;
X int found = FALSE;
X int max = nbytes;
X int i = 0;
X
X if (max <= 0)
X return -1;
X if (callcnt == 0)
X {
X if (_cap_database[0] == NULL)
X {
X if ((rcp = getenv("TERMCAP")) != NULL)
X {
X if (*rcp == '/')
X _cap_database[0] = rcp;
X else
X if (strncmp(getenv("TERM"), name, strlen(name)))
X _cap_database[0] = "/etc/termcap";
X _cap_database[1] = NULL;
X }
X else
X return -1; /* nothing to work with */
X }
X _cap_buf = buf; /* needed by other functions */
X if (_cap_database[0] == NULL)
X {
X /*
X * we have a cap entry in the environment
X */
X (void) strncpy(buf, rcp, nbytes);
X buf[nbytes] = '\0';
X return (strlen(buf));
X }
X }
X /*
X * we have to look up "name" in the database file(s).
X */
X for (i = 0; max > 0 && found == FALSE &&
X i < MAX_DBASE && _cap_database[i]; i++)
X {
X if ((fp = fopen(_cap_database[i], "r")) == NULL)
X continue ; /* try next one */
X cp = buf;
X rcp = buf;
X finished = FALSE;
X
X while (!(finished))
X {
X if (max <= 0 || (fgets(cp, max, fp) == NULL))
X finished = TRUE;
X else
X {
X len = strlen(cp);
X rcp = cp;
X while (*rcp == ' ' || *rcp == '\t')
X rcp++;
X if (*rcp && *rcp != '\n' && *rcp != '#')
X {
X /* not a comment or blank */
X if (!found)
X if (*rcp != ':') /* start of an entry */
X {
X register char *rcp2;
X
X /*
X * be sure that the names match
X * not part of another tc=
X */
X if (rcp2 = strchr(rcp, ':'))
X *rcp2 = '\0';
X found = (strstr(rcp, name) != NULL);
X if (found && rcp2)
X {
X *rcp2 = ':';
X if (callcnt)
X /*
X * We are a recursive call,
X * we don't want the name part or the ':'.
X */
X rcp = ++rcp2;
X }
X }
X if (found)
X {
X if (rcp != cp)
X rcp = strcpy(cp, rcp);
X len = strlen(rcp);
X if (rcp[len - 2] == '\\') /* more to get */
X {
X len -= 2; /* lose the \ and \n */
X rcp[len] = '\0';
X cp = &rcp[len];
X }
X else
X finished = TRUE;
X max -= len;
X }
X }
X }
X }
X (void) fclose(fp);
X }
X if (found)
X {
X /*
X * allow for tc=termtype
X * as the last entry.
X */
X cp = tc_name;
X if ((name = cap_getstr("tc", &cp)) != NULL)
X {
X if ((rcp = strstr(buf, ":tc=")) != NULL)
X {
X callcnt++;
X if ((len = cap_ngetent(++rcp, name, max)) <= 0)
X (void) sprintf(rcp, "tc=%s\n", tc_name);
X else
X max -= len;
X callcnt--;
X }
X }
X }
X buf[nbytes] = '\0';
X if (max < 0)
X max = 0;
X return (found ? nbytes - max : 0);
X}
X
X
X/* NAME:
X * cap_getstr - get a string capability
X *
X * SYNOPSIS:
X * cap_getstr()
X *
X * DESCRIPTION:
X * Look for an item ":id=str:" in the buffer pointed to by
X * _cap_buf. If found copy "str" into the buffer at "area"
X * and advance "area". If all ok return a pointer to "str"
X * within the user's buffer (ie. the previous value of
X * "*area".
X *
X * Unlike tgetstr(3), this function does not interperate
X * the contents of "str" in anyway.
X *
X * RETURN VALUE:
X * str==success, -1==failure
X */
X
XENTRY char *
Xcap_getstr(id, area)
X char *id;
X char **area;
X{
X register char *rcp;
X register int len;
X
X (void) sprintf(capname, ":%s=", id);
X if ((rcp = strstr(_cap_buf, capname)) != NULL)
X {
X rcp += strlen(capname);
X len = strcspn(rcp, ":\n");
X rcp = strncpy((*area), rcp, len);
X (*area)[len] = '\0';
X *area += ++len;
X return rcp;
X }
X return NULL;
X}
X
X
X/* NAME:
X * cap_getnum - get a numeric capability
X *
X * SYNOPSIS:
X * cap_getnum()
X *
X * DESCRIPTION:
X * This function looks for an item ":id#num:" in the buffer
X * pointer to by _cap_buf. If found it returns "num"
X * otherwise -1.
X *
X * RETURN VALUE:
X * num==success, -1==failure
X */
X
XENTRY int
Xcap_getnum(id)
X char *id;
X{
X register char *rcp;
X
X (void) sprintf(capname, ":%s#", id);
X if ((rcp = strstr(_cap_buf, capname)) != NULL)
X {
X rcp += strlen(capname);
X return (atoi(rcp));
X }
X return -1;
X}
X
X
X/* NAME:
X * cap_getflag - check for presence of capability
X *
X * SYNOPSIS:
X * cap_getflag()
X *
X * DESCRIPTION:
X * This function simply looks for any item that matches the
X * RE ":id[:=#]" in the buffer pointed to by _cap_buf.
X * That is, it will return TRUE as soon as it finds a
X * boolean, numeric or string capability with the right
X * name "id".
X *
X * RETURN VALUE:
X * 1==found, 0==not found
X */
X
XENTRY int
Xcap_getflag(id)
X char *id;
X{
X register char *rcp;
X
X (void) sprintf(capname, ":%s", id);
X if ((rcp = strstr(_cap_buf, capname)) != NULL)
X {
X rcp += strlen(capname);
X return (strcspn(rcp, "=#:\n") == 0);
X }
X return 0;
X}
X
X/* This lot (for GNU-Emacs) goes at the end of the file. */
X/*
X * Local Variables:
X * version-control:t
X * comment-column:40
X * End:
X */
*-*-END-of-cap.c-*-*
echo x - cap.h
sed 's/^X//' >cap.h <<'*-*-END-of-cap.h-*-*'
X/* NAME:
X * cap.h - definitions for cap module
X *
X * SYNOPSIS:
X * int cap_getent(char *buf, char *name);
X * int cap_ngetent(char *buf, char *name, int nbytes);
X * int cap_getnum(char *id);
X * int cap_getflag(char *id);
X * char *cap_getstr(char *id, char **area);
X *
X * DESCRIPTION:
X * The cap module provides functions similar to termcap(3X).
X * Refer to the documentation in cap.c for full description.
X *
X * SEE ALSO:
X * cap.c
X *
X * AMENDED:
X * 91/01/04 13:20:04 (sjg)
X *
X * RELEASED:
X * 91/01/04 13:20:06 v1.4
X *
X * SCCSID:
X * @(#)cap.h 1.4 91/01/04 13:20:04 (sjg)
X *
X * Copyright (c) 1989 Simon J. Gerraty.
X *
X * This is free software. It comes with NO WARRANTY.
X * Permission to use, modify and distribute this source code
X * is granted subject to the following conditions.
X * 1/ that that the above copyright notice and this notice
X * are preserved in all copies and that due credit be given
X * to the author.
X * 2/ that any changes to this code are clearly commented
X * as such so that the author does get blamed for bugs
X * other than his own.
X *
X * Please send copies of changes and bug-fixes to:
X * sjg at zen.void.oz.au
X */
X
X/* some useful #defines */
X#ifndef EXTERN
X# define EXTERN extern
X# define EXTERN_DEFINED
X#endif
X
X#define ENTRY
X#define LOCAL static
X#define TRUE 1
X#define FALSE 0
X
X#if defined(__STDC__) || defined(PROTO)
X# define _P_(p) p
X#else
X# define _P_(p) ()
X#endif
X
X/* manifest constants */
X#define MAX_DBASE 10
X#define CAP_BUFSZ 1024
X#define CAP_NAMESZ 50
X
X/* struct / union */
X
X/* macros */
X
X/* external variable declarations */
XEXTERN char *_cap_database[MAX_DBASE];
XEXTERN char *_cap_buf;
X
X/* function prototypes */
X
XENTRY int cap_getent _P_((char *buf, char *name));
XENTRY int cap_ngetent _P_((char *buf, char *name, int nbytes));
XENTRY int cap_getnum _P_((char *id));
XENTRY int cap_getflag _P_((char *id));
XENTRY char *cap_getstr _P_((char *id, char **area));
X
X
X
X/* This lot goes at the END */
X/* be sure not to interfere with anyone else's idea about EXTERN */
X#ifdef EXTERN_DEFINED
X# undef EXTERN_DEFINED
X# undef EXTERN
X#endif
X/*
X * Local Variables:
X * version-control:t
X * comment-column:40
X * End:
X */
*-*-END-of-cap.h-*-*
exit
exit 0 # Just in case...
--
Kent Landfield INTERNET: kent at sparky.IMD.Sterling.COM
Sterling Software, IMD UUCP: uunet!sparky!kent
Phone: (402) 291-8300 FAX: (402) 291-4362
Please send comp.sources.misc-related mail to kent at uunet.uu.net.
More information about the Comp.sources.misc
mailing list