122072Sdist /* 236499Sbostic * Copyright (c) 1980 The Regents of the University of California. 336499Sbostic * All rights reserved. 436499Sbostic * 556138Selan * Redistribution and use in source and binary forms, with or without 656138Selan * modification, are permitted provided that the following conditions 756138Selan * are met: 856138Selan * 1. Redistributions of source code must retain the above copyright 956138Selan * notice, this list of conditions and the following disclaimer. 1056138Selan * 2. Redistributions in binary form must reproduce the above copyright 1156138Selan * notice, this list of conditions and the following disclaimer in the 1256138Selan * documentation and/or other materials provided with the distribution. 1356138Selan * 3. All advertising materials mentioning features or use of this software 1456138Selan * must display the following acknowledgement: 1556138Selan * This product includes software developed by the University of 1656138Selan * California, Berkeley and its contributors. 1756138Selan * 4. Neither the name of the University nor the names of its contributors 1856138Selan * may be used to endorse or promote products derived from this software 1956138Selan * without specific prior written permission. 2056138Selan * 2156138Selan * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2256138Selan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2356138Selan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2456138Selan * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2556138Selan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2656138Selan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2756138Selan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2856138Selan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2956138Selan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3056138Selan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3156138Selan * SUCH DAMAGE. 3222072Sdist */ 3322072Sdist 3413300Ssam #ifndef lint 3556138Selan static char sccsid[] = "@(#)termcap.c 5.7 (Berkeley) 8/6/92"; 3636499Sbostic #endif /* not lint */ 3713300Ssam 3832153Sjak #define PBUFSIZ 512 /* max length of filename path */ 3932153Sjak #define PVECSIZ 32 /* max number of names in path */ 4013300Ssam 4156138Selan #include <stdio.h> 4213300Ssam #include <ctype.h> 4354673Storek #include <stdlib.h> 4456138Selan #include <string.h> 4537833Sbostic #include "pathnames.h" 4637833Sbostic 4713300Ssam /* 4813300Ssam * termcap - routines for dealing with the terminal capability data base 4913300Ssam * 5013300Ssam * BUG: Should use a "last" pointer in tbuf, so that searching 5113300Ssam * for capabilities alphabetically would not be a n**2/2 5213300Ssam * process when large numbers of capabilities are given. 5313300Ssam * Note: If we add a last pointer now we will screw up the 5413300Ssam * tc capability. We really should compile termcap. 5513300Ssam * 5613300Ssam * Essentially all the work here is scanning and decoding escapes 5713300Ssam * in string capabilities. We don't use stdio because the editor 5813300Ssam * doesn't, and because living w/o it is not hard. 5913300Ssam */ 6013300Ssam 6156138Selan static char *tbuf; /* termcap buffer */ 6213300Ssam 6313300Ssam /* 6432153Sjak * Get an entry for terminal name in buffer bp from the termcap file. 6513300Ssam */ 6656138Selan int 6713300Ssam tgetent(bp, name) 6813300Ssam char *bp, *name; 6913300Ssam { 7032153Sjak register char *p; 7113300Ssam register char *cp; 7256138Selan char *dummy; 7356138Selan char **fname; 7456138Selan char *home; 7556138Selan int i; 7656138Selan char pathbuf[PBUFSIZ]; /* holds raw path of filenames */ 7756138Selan char *pathvec[PVECSIZ]; /* to point to names in pathbuf */ 7856138Selan char **pvec; /* holds usable tail of path vector */ 7956138Selan char *termpath; 8013300Ssam 8156138Selan fname = pathvec; 8232153Sjak pvec = pathvec; 8313300Ssam tbuf = bp; 8432153Sjak p = pathbuf; 8513300Ssam cp = getenv("TERMCAP"); 8613300Ssam /* 8713300Ssam * TERMCAP can have one of two things in it. It can be the 8813300Ssam * name of a file to use instead of /etc/termcap. In this 8913300Ssam * case it better start with a "/". Or it can be an entry to 9013300Ssam * use so we don't have to read the file. In this case it 9132153Sjak * has to already have the newlines crunched out. If TERMCAP 9232153Sjak * does not hold a file name then a path of names is searched 9332153Sjak * instead. The path is found in the TERMPATH variable, or 9432153Sjak * becomes "$HOME/.termcap /etc/termcap" if no TERMPATH exists. 9513300Ssam */ 9632153Sjak if (!cp || *cp != '/') { /* no TERMCAP or it holds an entry */ 9732153Sjak if (termpath = getenv("TERMPATH")) 9832153Sjak strncpy(pathbuf, termpath, PBUFSIZ); 9932153Sjak else { 10032153Sjak if (home = getenv("HOME")) { /* set up default */ 10132153Sjak p += strlen(home); /* path, looking in */ 10232153Sjak strcpy(pathbuf, home); /* $HOME first */ 10332153Sjak *p++ = '/'; 10432153Sjak } /* if no $HOME look in current directory */ 10537833Sbostic strncpy(p, _PATH_DEF, PBUFSIZ - (p - pathbuf)); 10617676Sserge } 10713300Ssam } 10832153Sjak else /* user-defined name in TERMCAP */ 10932153Sjak strncpy(pathbuf, cp, PBUFSIZ); /* still can be tokenized */ 11037833Sbostic 11132153Sjak *fname++ = pathbuf; /* tokenize path into vector of names */ 11232153Sjak while (*++p) 11332153Sjak if (*p == ' ' || *p == ':') { 11432153Sjak *p = '\0'; 11532153Sjak while (*++p) 11632153Sjak if (*p != ' ' && *p != ':') 11732153Sjak break; 11832153Sjak if (*p == '\0') 11932153Sjak break; 12032153Sjak *fname++ = p; 12132153Sjak if (fname >= pathvec + PVECSIZ) { 12232153Sjak fname--; 12332153Sjak break; 12432153Sjak } 12532153Sjak } 12632153Sjak *fname = (char *) 0; /* mark end of vector */ 12756138Selan if (cp && *cp && *cp != '/') 12856138Selan if (cgetset(cp) < 0) 12956138Selan return(-2); 13032153Sjak 13156138Selan i = cgetent(&dummy, pathvec, name); 13256138Selan 13356138Selan if (i == 0) 13456138Selan strcpy(bp, dummy); 13556138Selan 13656138Selan if (dummy) 13756138Selan free(dummy); 13856138Selan /* no tc reference loop return code in libterm XXX */ 13956138Selan if (i == -3) 14056138Selan return(-1); 14156138Selan return(i + 1); 14213300Ssam } 14313300Ssam 14413300Ssam /* 14513300Ssam * Return the (numeric) option id. 14613300Ssam * Numeric options look like 14713300Ssam * li#80 14813300Ssam * i.e. the option string is separated from the numeric value by 14913300Ssam * a # character. If the option is not found we return -1. 15013300Ssam * Note that we handle octal numbers beginning with 0. 15113300Ssam */ 15256138Selan int 15313300Ssam tgetnum(id) 15413300Ssam char *id; 15513300Ssam { 15656138Selan long num; 15713300Ssam 15856138Selan if (cgetnum(tbuf, id, &num) == 0) 15956138Selan return(num); 16056138Selan else 16156138Selan return(-1); 16213300Ssam } 16313300Ssam 16413300Ssam /* 16513300Ssam * Handle a flag option. 16613300Ssam * Flag options are given "naked", i.e. followed by a : or the end 16713300Ssam * of the buffer. Return 1 if we find the option, or 0 if it is 16813300Ssam * not given. 16913300Ssam */ 17056138Selan int 17113300Ssam tgetflag(id) 17213300Ssam char *id; 17313300Ssam { 17456138Selan return(cgetcap(tbuf, id, ':') != NULL); 17513300Ssam } 17613300Ssam 17713300Ssam /* 17813300Ssam * Get a string valued option. 17913300Ssam * These are given as 18013300Ssam * cl=^Z 18113300Ssam * Much decoding is done on the strings, and the strings are 18213300Ssam * placed in area, which is a ref parameter which is updated. 18313300Ssam * No checking on area overflow. 18413300Ssam */ 18513300Ssam char * 18613300Ssam tgetstr(id, area) 18713300Ssam char *id, **area; 18813300Ssam { 189*56240Selan char ids[3]; 19056138Selan char *s; 19113300Ssam int i; 19256138Selan 193*56240Selan /* 194*56240Selan * XXX 195*56240Selan * This is for all the boneheaded programs that relied on tgetstr 196*56240Selan * to look only at the first 2 characters of the string passed... 197*56240Selan */ 198*56240Selan *ids = *id; 199*56240Selan ids[1] = id[1]; 200*56240Selan ids[2] = '\0'; 201*56240Selan 202*56240Selan if ((i = cgetstr(tbuf, ids, &s)) < 0) 20356138Selan return NULL; 20456138Selan 20556138Selan strcpy(*area, s); 20656138Selan *area += i + 1; 20756138Selan return(s); 20813300Ssam } 209