Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/lib/libterm/Attic/termcap.c,v retrieving revision 1.6 retrieving revision 1.24 diff -u -p -r1.6 -r1.24 --- src/lib/libterm/Attic/termcap.c 1995/02/27 10:18:54 1.6 +++ src/lib/libterm/Attic/termcap.c 2000/04/19 13:41:28 1.24 @@ -1,4 +1,4 @@ -/* $NetBSD: termcap.c,v 1.6 1995/02/27 10:18:54 cgd Exp $ */ +/* $NetBSD: termcap.c,v 1.24 2000/04/19 13:41:28 blymn Exp $ */ /* * Copyright (c) 1980, 1993 @@ -33,22 +33,27 @@ * SUCH DAMAGE. */ +#include #ifndef lint #if 0 static char sccsid[] = "@(#)termcap.c 8.1 (Berkeley) 6/4/93"; #else -static char rcsid[] = "$NetBSD: termcap.c,v 1.6 1995/02/27 10:18:54 cgd Exp $"; +__RCSID("$NetBSD: termcap.c,v 1.24 2000/04/19 13:41:28 blymn Exp $"); #endif #endif /* not lint */ #define PBUFSIZ 512 /* max length of filename path */ #define PVECSIZ 32 /* max number of names in path */ -#include +#include #include +#include #include #include +#include +#include #include "pathnames.h" +#include "termcap_private.h" /* * termcap - routines for dealing with the terminal capability data base @@ -65,50 +70,59 @@ static char rcsid[] = "$NetBSD: termcap. */ static char *tbuf; /* termcap buffer */ +static struct tinfo *fbuf; /* untruncated termcap buffer */ /* - * Get an entry for terminal name in buffer bp from the termcap file. + * Get an extended entry for the terminal name. This differs from + * tgetent only in a) the buffer is malloc'ed for the caller and + * b) the termcap entry is not truncated to 1023 characters. */ + int -tgetent(bp, name) - char *bp, *name; +t_getent(bp, name) + struct tinfo **bp; + const char *name; { - register char *p; - register char *cp; - char *dummy; + char *p; + char *cp; char **fname; char *home; int i; char pathbuf[PBUFSIZ]; /* holds raw path of filenames */ char *pathvec[PVECSIZ]; /* to point to names in pathbuf */ - char **pvec; /* holds usable tail of path vector */ char *termpath; + _DIAGASSERT(bp != NULL); + _DIAGASSERT(name != NULL); + + if ((*bp = malloc(sizeof(struct tinfo))) == NULL) return 0; + fname = pathvec; - pvec = pathvec; - tbuf = bp; p = pathbuf; cp = getenv("TERMCAP"); /* * TERMCAP can have one of two things in it. It can be the - * name of a file to use instead of /etc/termcap. In this - * case it better start with a "/". Or it can be an entry to - * use so we don't have to read the file. In this case it - * has to already have the newlines crunched out. If TERMCAP - * does not hold a file name then a path of names is searched - * instead. The path is found in the TERMPATH variable, or - * becomes "$HOME/.termcap /etc/termcap" if no TERMPATH exists. + * name of a file to use instead of + * /usr/share/misc/termcap. In this case it better start with + * a "/". Or it can be an entry to use so we don't have to + * read the file. In this case cgetset() withh crunch out the + * newlines. If TERMCAP does not hold a file name then a path + * of names is searched instead. The path is found in the + * TERMPATH variable, or becomes _PATH_DEF ("$HOME/.termcap + * /usr/share/misc/termcap") if no TERMPATH exists. */ if (!cp || *cp != '/') { /* no TERMCAP or it holds an entry */ - if (termpath = getenv("TERMPATH")) + if ((termpath = getenv("TERMPATH")) != NULL) strncpy(pathbuf, termpath, PBUFSIZ); else { - if (home = getenv("HOME")) { /* set up default */ + if ((home = getenv("HOME")) != NULL) { + /* set up default */ p += strlen(home); /* path, looking in */ - strcpy(pathbuf, home); /* $HOME first */ + (void)strncpy(pathbuf, home, + sizeof(pathbuf) - 1); /* $HOME first */ *p++ = '/'; } /* if no $HOME look in current directory */ - strncpy(p, _PATH_DEF, PBUFSIZ - (p - pathbuf)); + strncpy(p, _PATH_DEF, PBUFSIZ - (size_t)(p - pathbuf)); } } else /* user-defined name in TERMCAP */ @@ -134,14 +148,14 @@ tgetent(bp, name) if (cgetset(cp) < 0) return (-2); - dummy = NULL; - i = cgetent(&dummy, pathvec, name); - - if (i == 0) - strcpy(bp, dummy); - - if (dummy) - free(dummy); + /* + * XXX potential security hole here in a set-id program if the + * user had setup name to be built from a path they can not + * normally read. + */ + (*bp)->info = NULL; + i = cgetent(&((*bp)->info), pathvec, name); + /* no tc reference loop return code in libterm XXX */ if (i == -3) return (-1); @@ -149,6 +163,49 @@ tgetent(bp, name) } /* + * Get an entry for terminal name in buffer bp from the termcap file. + */ +int +tgetent(bp, name) + char *bp; + const char *name; +{ + int i, plen, elen, c; + char *ptrbuf = NULL; + + i = t_getent(&fbuf, name); + + if (i == 1) { + /* stash the full buffer pointer as the ZZ capability + in the termcap buffer passed. + */ + plen = asprintf(&ptrbuf, ":ZZ=%p", fbuf->info); + strncpy(bp, fbuf->info, 1024); + bp[1023] = '\0'; + elen = strlen(bp); + /* backup over the entry if the addition of the full + buffer pointer will overflow the buffer passed. We + want to truncate the termcap entry on a capability + boundary. + */ + if ((elen + plen) > 1023) { + bp[1023 - plen] = '\0'; + for (c = (elen - plen); c > 0; c--) { + if (bp[c] == ':') { + bp[c] = '\0'; + break; + } + } + } + + strcat(bp, ptrbuf); + tbuf = bp; + } + + return i; +} + +/* * Return the (numeric) option id. * Numeric options look like * li#80 @@ -157,28 +214,49 @@ tgetent(bp, name) * Note that we handle octal numbers beginning with 0. */ int -tgetnum(id) - char *id; + +t_getnum(info, id) + struct tinfo *info; + const char *id; { long num; - if (cgetnum(tbuf, id, &num) == 0) - return (num); + _DIAGASSERT(id != NULL); + + if (cgetnum(info->info, id, &num) == 0) + return (int)(num); else return (-1); } +int +tgetnum(id) + const char *id; +{ + return t_getnum(fbuf, id); +} + /* * 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. */ +int t_getflag(info, id) + struct tinfo *info; + const char *id; +{ + return (cgetcap(info->info, id, ':') != NULL); +} + int tgetflag(id) - char *id; + const char *id; { - return (cgetcap(tbuf, id, ':') != NULL); + + _DIAGASSERT(id != NULL); + + return t_getflag(fbuf, id); } /* @@ -187,16 +265,23 @@ tgetflag(id) * cl=^Z * Much decoding is done on the strings, and the strings are * placed in area, which is a ref parameter which is updated. - * No checking on area overflow. + * limit is the number of characters allowed to be put into + * area, this is updated. */ char * -tgetstr(id, area) - char *id, **area; +t_getstr(info, id, area, limit) + struct tinfo *info; + const char *id; + char **area; + size_t *limit; { char ids[3]; char *s; int i; - + + _DIAGASSERT(id != NULL); + _DIAGASSERT(area != NULL); + /* * XXX * This is for all the boneheaded programs that relied on tgetstr @@ -206,10 +291,101 @@ tgetstr(id, area) ids[1] = id[1]; ids[2] = '\0'; - if ((i = cgetstr(tbuf, ids, &s)) < 0) + if ((ids[0] == 'Z') && (ids[1] == 'Z')) { + /* return info->info address??? */ + } + + if ((i = cgetstr(info->info, ids, &s)) < 0) { + errno = ENOENT; return NULL; + } + + if (area != NULL) { + /* check if there is room for the new entry to be put into area */ + if (limit != NULL && (*limit < i)) { + errno = E2BIG; + return NULL; + } + + strcpy(*area, s); + *area += i + 1; + if (limit != NULL) *limit -= i; + + return (s); + } else { + *limit = i; + return NULL; + } +} + +/* + * 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. + * No checking on area overflow. + */ +char * +tgetstr(id, area) + const char *id; + char **area; +{ + struct tinfo dummy; + + if ((id[0] == 'Z') && (id[1] == 'Z')) { + dummy.info = tbuf; + return t_getstr(&dummy, id, area, NULL); + } + else + return t_getstr(fbuf, id, area, NULL); +} + +/* + * Free the buffer allocated by t_getent + * + */ +void +t_freent(info) + struct tinfo *info; +{ + free(info->info); + free(info); +} + +/* + * Get the terminal name string from the termcap entry. + * + */ +int +t_getterm(struct tinfo *info, char **area, size_t *limit) +{ + char *endp; + size_t count; + + if ((endp = index(info->info, ':')) == NULL) { + errno = EINVAL; + return -1; + } - strcpy(*area, s); - *area += i + 1; - return (s); + + count = endp - info->info + 1; + if (area == NULL) { + *limit = count; + return 0; + } else { + if ((limit != NULL) && (count > *limit)) { + errno = E2BIG; + return -1; + } + + strncpy(*area, info->info, count); + (*area)[count] = '\0'; + if (limit != NULL) + *limit -= count; + } + + return 0; } + +