Annotation of src/usr.bin/tset/termcap.c, Revision 1.7
1.7 ! deraadt 1: /* $OpenBSD: termcap.c,v 1.6 2007/03/20 03:56:13 tedu 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: #define PVECSIZ 32 /* max number of names in path */
34: #define _PATH_DEF ".termcap /usr/share/misc/termcap"
35:
36: #include <sys/param.h>
37: #include <sys/types.h>
38: #include <stdio.h>
39: #include <ctype.h>
1.3 pvalchev 40: #include <err.h>
1.1 millert 41: #include <stdlib.h>
42: #include <string.h>
43: #include <unistd.h>
44:
45: /*
46: * Get an entry for terminal name in buffer bp from the termcap file.
47: */
48: int
49: tcgetent(bp, name)
50: char *bp;
51: const char *name;
52: {
53: char *p;
54: char *cp;
55: char *dummy;
56: char **fname;
57: char *home;
58: int i;
59: char pathbuf[MAXPATHLEN]; /* holds raw path of filenames */
60: char *pathvec[PVECSIZ]; /* to point to names in pathbuf */
61: char **pvec; /* holds usable tail of path vector */
62: char *termpath;
63:
64: fname = pathvec;
65: pvec = pathvec;
66:
67: if (!issetugid()) {
68: cp = getenv("TERMCAP");
69: /*
70: * TERMCAP can have one of two things in it. It can be the name
71: * of a file to use instead of /usr/share/misc/termcap. In this
72: * case it better start with a "/". Or it can be an entry to
73: * use so we don't have to read the file. In this case it
74: * has to already have the newlines crunched out. If TERMCAP
75: * does not hold a file name then a path of names is searched
76: * instead. The path is found in the TERMPATH variable, or
77: * becomes "$HOME/.termcap /usr/share/misc/termcap" if no
78: * TERMPATH exists.
79: */
80: if (!cp || *cp != '/') { /* no TERMCAP or it holds an entry */
81: if ((termpath = getenv("TERMPATH")) != NULL)
82: strlcpy(pathbuf, termpath, sizeof(pathbuf));
83: else {
84: if ((home = getenv("HOME")) != NULL &&
1.2 millert 85: *home != '\0' &&
1.1 millert 86: strlen(home) + sizeof(_PATH_DEF) <
87: sizeof(pathbuf)) {
1.4 deraadt 88: snprintf(pathbuf, sizeof pathbuf,
89: "%s/%s", home, _PATH_DEF);
1.1 millert 90: } else {
91: strlcpy(pathbuf, _PATH_DEF,
92: sizeof(pathbuf));
93: }
94: }
95: } else { /* user-defined path in TERMCAP */
96: /* still can be tokenized */
97: strlcpy(pathbuf, cp, sizeof(pathbuf));
98: }
99: *fname++ = pathbuf; /* tokenize path into vector of names */
100: }
101:
102: /* split pathbuf into a vector of paths */
103: p = pathbuf;
104: while (*++p)
105: if (*p == ' ' || *p == ':') {
106: *p = '\0';
107: while (*++p)
108: if (*p != ' ' && *p != ':')
109: break;
110: if (*p == '\0')
111: break;
112: *fname++ = p;
113: if (fname >= pathvec + PVECSIZ) {
114: fname--;
115: break;
116: }
117: }
118: *fname = (char *) 0; /* mark end of vector */
119: if (cp && *cp && *cp != '/')
120: if (cgetset(cp) < 0)
121: return (-2);
122:
123: dummy = NULL;
124: i = cgetent(&dummy, pathvec, (char *)name);
125:
126: if (i == 0 && bp != NULL) {
127: strlcpy(bp, dummy, 1024);
128: if ((cp = strrchr(bp, ':')) != NULL)
129: if (cp[1] != '\0')
130: cp[1] = '\0';
131: }
132: else if (i == 0 && bp == NULL)
133: bp = dummy;
134: else if (dummy != NULL)
135: free(dummy);
136:
137: /* no tc reference loop return code in libterm XXX */
138: if (i == -3)
139: return (-1);
140: return (i + 1);
141: }
142:
143: /*
144: * Output termcap entry to stdout, quoting characters that would give the
145: * shell problems and omitting empty fields.
146: */
147: void
148: wrtermcap(bp)
149: char *bp;
150: {
151: int ch;
152: char *p;
153: char *t, *sep;
154:
155: /* Find the end of the terminal names. */
156: if ((t = strchr(bp, ':')) == NULL)
1.3 pvalchev 157: err(1, "termcap names not colon terminated");
1.1 millert 158: *t++ = '\0';
159:
160: /* Output terminal names that don't have whitespace. */
161: sep = "";
162: while ((p = strsep(&bp, "|")) != NULL)
163: if (*p != '\0' && strpbrk(p, " \t") == NULL) {
164: (void)printf("%s%s", sep, p);
165: sep = "|";
166: }
167: (void)putchar(':');
168:
169: /*
170: * Output fields, transforming any dangerous characters. Skip
171: * empty fields or fields containing only whitespace.
172: */
173: while ((p = strsep(&t, ":")) != NULL) {
1.6 tedu 174: while (isspace(*p))
1.1 millert 175: ++p;
1.6 tedu 176: if (*p == '\0')
1.1 millert 177: continue;
178: while ((ch = *p++) != '\0')
179: switch(ch) {
180: case '\033':
181: (void)printf("\\E");
182: case ' ': /* No spaces. */
183: (void)printf("\\040");
184: break;
185: case '!': /* No csh history chars. */
186: (void)printf("\\041");
187: break;
188: case ',': /* No csh history chars. */
189: (void)printf("\\054");
190: break;
191: case '"': /* No quotes. */
192: (void)printf("\\042");
193: break;
194: case '\'': /* No quotes. */
195: (void)printf("\\047");
196: break;
197: case '`': /* No quotes. */
198: (void)printf("\\140");
199: break;
200: case '\\': /* Anything following is OK. */
201: case '^':
202: (void)putchar(ch);
203: if ((ch = *p++) == '\0')
204: break;
205: /* FALLTHROUGH */
206: default:
207: (void)putchar(ch);
208: }
209: (void)putchar(':');
210: }
211: }