Annotation of src/usr.bin/tset/termcap.c, Revision 1.2
1.2 ! millert 1: /* $OpenBSD: termcap.c,v 1.1 1998/11/16 03:08:41 millert Exp $ */
1.1 millert 2: /* $NetBSD: termcap.c,v 1.7 1995/06/05 19:45:52 pk Exp $ */
3:
4: /*
5: * Copyright (c) 1980, 1991, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: */
36:
37: #ifndef lint
1.2 ! millert 38: static char rcsid[] = "$OpenBSD: termcap.c,v 1.1 1998/11/16 03:08:41 millert Exp $";
1.1 millert 39: #endif /* not lint */
40:
41: #define PVECSIZ 32 /* max number of names in path */
42: #define _PATH_DEF ".termcap /usr/share/misc/termcap"
43:
44: #include <sys/param.h>
45: #include <sys/types.h>
46: #include <stdio.h>
47: #include <ctype.h>
48: #include <stdlib.h>
49: #include <string.h>
50: #include <unistd.h>
51:
52: /*
53: * Get an entry for terminal name in buffer bp from the termcap file.
54: */
55: int
56: tcgetent(bp, name)
57: char *bp;
58: const char *name;
59: {
60: char *p;
61: char *cp;
62: char *dummy;
63: char **fname;
64: char *home;
65: int i;
66: char pathbuf[MAXPATHLEN]; /* holds raw path of filenames */
67: char *pathvec[PVECSIZ]; /* to point to names in pathbuf */
68: char **pvec; /* holds usable tail of path vector */
69: char *termpath;
70: char *ttype;
71:
72: fname = pathvec;
73: pvec = pathvec;
74:
75: if (!issetugid()) {
76: cp = getenv("TERMCAP");
77: /*
78: * TERMCAP can have one of two things in it. It can be the name
79: * of a file to use instead of /usr/share/misc/termcap. In this
80: * case it better start with a "/". Or it can be an entry to
81: * use so we don't have to read the file. In this case it
82: * has to already have the newlines crunched out. If TERMCAP
83: * does not hold a file name then a path of names is searched
84: * instead. The path is found in the TERMPATH variable, or
85: * becomes "$HOME/.termcap /usr/share/misc/termcap" if no
86: * TERMPATH exists.
87: */
88: if (!cp || *cp != '/') { /* no TERMCAP or it holds an entry */
89: if ((termpath = getenv("TERMPATH")) != NULL)
90: strlcpy(pathbuf, termpath, sizeof(pathbuf));
91: else {
92: if ((home = getenv("HOME")) != NULL &&
1.2 ! millert 93: *home != '\0' &&
1.1 millert 94: strlen(home) + sizeof(_PATH_DEF) <
95: sizeof(pathbuf)) {
96: sprintf(pathbuf, "%s/%s", home,
97: _PATH_DEF);
98: } else {
99: strlcpy(pathbuf, _PATH_DEF,
100: sizeof(pathbuf));
101: }
102: }
103: } else { /* user-defined path in TERMCAP */
104: /* still can be tokenized */
105: strlcpy(pathbuf, cp, sizeof(pathbuf));
106: }
107: *fname++ = pathbuf; /* tokenize path into vector of names */
108: }
109:
110: /* split pathbuf into a vector of paths */
111: p = pathbuf;
112: while (*++p)
113: if (*p == ' ' || *p == ':') {
114: *p = '\0';
115: while (*++p)
116: if (*p != ' ' && *p != ':')
117: break;
118: if (*p == '\0')
119: break;
120: *fname++ = p;
121: if (fname >= pathvec + PVECSIZ) {
122: fname--;
123: break;
124: }
125: }
126: *fname = (char *) 0; /* mark end of vector */
127: if (cp && *cp && *cp != '/')
128: if (cgetset(cp) < 0)
129: return (-2);
130:
131: dummy = NULL;
132: i = cgetent(&dummy, pathvec, (char *)name);
133:
134: if (i == 0 && bp != NULL) {
135: strlcpy(bp, dummy, 1024);
136: if ((cp = strrchr(bp, ':')) != NULL)
137: if (cp[1] != '\0')
138: cp[1] = '\0';
139: }
140: else if (i == 0 && bp == NULL)
141: bp = dummy;
142: else if (dummy != NULL)
143: free(dummy);
144:
145: /* no tc reference loop return code in libterm XXX */
146: if (i == -3)
147: return (-1);
148: return (i + 1);
149: }
150:
151: /*
152: * Output termcap entry to stdout, quoting characters that would give the
153: * shell problems and omitting empty fields.
154: */
155: void
156: wrtermcap(bp)
157: char *bp;
158: {
159: int ch;
160: char *p;
161: char *t, *sep;
162:
163: /* Find the end of the terminal names. */
164: if ((t = strchr(bp, ':')) == NULL)
165: err("termcap names not colon terminated");
166: *t++ = '\0';
167:
168: /* Output terminal names that don't have whitespace. */
169: sep = "";
170: while ((p = strsep(&bp, "|")) != NULL)
171: if (*p != '\0' && strpbrk(p, " \t") == NULL) {
172: (void)printf("%s%s", sep, p);
173: sep = "|";
174: }
175: (void)putchar(':');
176:
177: /*
178: * Output fields, transforming any dangerous characters. Skip
179: * empty fields or fields containing only whitespace.
180: */
181: while ((p = strsep(&t, ":")) != NULL) {
182: while ((ch = *p) != '\0' && isspace(ch))
183: ++p;
184: if (ch == '\0')
185: continue;
186: while ((ch = *p++) != '\0')
187: switch(ch) {
188: case '\033':
189: (void)printf("\\E");
190: case ' ': /* No spaces. */
191: (void)printf("\\040");
192: break;
193: case '!': /* No csh history chars. */
194: (void)printf("\\041");
195: break;
196: case ',': /* No csh history chars. */
197: (void)printf("\\054");
198: break;
199: case '"': /* No quotes. */
200: (void)printf("\\042");
201: break;
202: case '\'': /* No quotes. */
203: (void)printf("\\047");
204: break;
205: case '`': /* No quotes. */
206: (void)printf("\\140");
207: break;
208: case '\\': /* Anything following is OK. */
209: case '^':
210: (void)putchar(ch);
211: if ((ch = *p++) == '\0')
212: break;
213: /* FALLTHROUGH */
214: default:
215: (void)putchar(ch);
216: }
217: (void)putchar(':');
218: }
219: }