home *** CD-ROM | disk | FTP | other *** search
- From: sjg@zen.void.oz.au (Simon J. Gerraty)
- Newsgroups: comp.sources.misc
- Subject: v16i069: generic capability database routines., Part01/01
- Message-ID: <1991Jan12.051632.8982@sparky.IMD.Sterling.COM>
- Date: 12 Jan 91 05:16:32 GMT
- Approved: kent@sparky.imd.sterling.com
- X-Checksum-Snefru: 264244e6 52db193b bb402b5a 7712b3f5
-
- Submitted-by: sjg@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@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@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@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@uunet.uu.net.
-