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