/* * Copyright (c) 1980, 1993 * The Regents of the University of California. All rights reserved. * * %sccs.include.redist.c% */ #ifndef lint static char sccsid[] = "@(#)termcap.c 8.1 (Berkeley) 06/04/93"; #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 "pathnames.h" /* * termcap - routines for dealing with the terminal capability data base * * BUG: Should use a "last" pointer in tbuf, so that searching * for capabilities alphabetically would not be a n**2/2 * process when large numbers of capabilities are given. * Note: If we add a last pointer now we will screw up the * tc capability. We really should compile termcap. * * Essentially all the work here is scanning and decoding escapes * in string capabilities. We don't use stdio because the editor * doesn't, and because living w/o it is not hard. */ static char *tbuf; /* termcap buffer */ /* * Get an entry for terminal name in buffer bp from the termcap file. */ int tgetent(bp, name) char *bp, *name; { register char *p; register char *cp; char *dummy; 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; 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. */ if (!cp || *cp != '/') { /* no TERMCAP or it holds an entry */ if (termpath = getenv("TERMPATH")) strncpy(pathbuf, termpath, PBUFSIZ); else { if (home = getenv("HOME")) { /* set up default */ p += strlen(home); /* path, looking in */ strcpy(pathbuf, home); /* $HOME first */ *p++ = '/'; } /* if no $HOME look in current directory */ strncpy(p, _PATH_DEF, PBUFSIZ - (p - pathbuf)); } } else /* user-defined name in TERMCAP */ strncpy(pathbuf, cp, PBUFSIZ); /* still can be tokenized */ *fname++ = pathbuf; /* tokenize path into vector of names */ while (*++p) if (*p == ' ' || *p == ':') { *p = '\0'; while (*++p) if (*p != ' ' && *p != ':') break; if (*p == '\0') break; *fname++ = p; if (fname >= pathvec + PVECSIZ) { fname--; break; } } *fname = (char *) 0; /* mark end of vector */ if (cp && *cp && *cp != '/') if (cgetset(cp) < 0) return(-2); i = cgetent(&dummy, pathvec, name); if (i == 0) strcpy(bp, dummy); if (dummy) free(dummy); /* no tc reference loop return code in libterm XXX */ if (i == -3) return(-1); return(i + 1); } /* * Return the (numeric) option id. * Numeric options look like * li#80 * i.e. the option string is separated from the numeric value by * a # character. If the option is not found we return -1. * Note that we handle octal numbers beginning with 0. */ int tgetnum(id) char *id; { long num; if (cgetnum(tbuf, id, &num) == 0) return(num); else return(-1); } /* * 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 tgetflag(id) char *id; { return(cgetcap(tbuf, id, ':') != 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) char *id, **area; { char ids[3]; char *s; int i; /* * XXX * This is for all the boneheaded programs that relied on tgetstr * to look only at the first 2 characters of the string passed... */ *ids = *id; ids[1] = id[1]; ids[2] = '\0'; if ((i = cgetstr(tbuf, ids, &s)) < 0) return NULL; strcpy(*area, s); *area += i + 1; return(s); }