1 | /****************************************************************************
|
---|
2 | * Copyright (c) 1998-2004,2005 Free Software Foundation, Inc. *
|
---|
3 | * *
|
---|
4 | * Permission is hereby granted, free of charge, to any person obtaining a *
|
---|
5 | * copy of this software and associated documentation files (the *
|
---|
6 | * "Software"), to deal in the Software without restriction, including *
|
---|
7 | * without limitation the rights to use, copy, modify, merge, publish, *
|
---|
8 | * distribute, distribute with modifications, sublicense, and/or sell *
|
---|
9 | * copies of the Software, and to permit persons to whom the Software is *
|
---|
10 | * furnished to do so, subject to the following conditions: *
|
---|
11 | * *
|
---|
12 | * The above copyright notice and this permission notice shall be included *
|
---|
13 | * in all copies or substantial portions of the Software. *
|
---|
14 | * *
|
---|
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
|
---|
16 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
|
---|
17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
|
---|
18 | * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
|
---|
19 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
|
---|
20 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
|
---|
21 | * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
---|
22 | * *
|
---|
23 | * Except as contained in this notice, the name(s) of the above copyright *
|
---|
24 | * holders shall not be used in advertising or otherwise to promote the *
|
---|
25 | * sale, use or other dealings in this Software without prior written *
|
---|
26 | * authorization. *
|
---|
27 | ****************************************************************************/
|
---|
28 |
|
---|
29 | /****************************************************************************
|
---|
30 | * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
|
---|
31 | * and: Eric S. Raymond <esr@snark.thyrsus.com> *
|
---|
32 | * and: Thomas E. Dickey 1996-on *
|
---|
33 | ****************************************************************************/
|
---|
34 |
|
---|
35 | /*
|
---|
36 | * tset.c - terminal initialization utility
|
---|
37 | *
|
---|
38 | * This code was mostly swiped from 4.4BSD tset, with some obsolescent
|
---|
39 | * cruft removed and substantial portions rewritten. A Regents of the
|
---|
40 | * University of California copyright applies to some portions of the
|
---|
41 | * code, and is reproduced below:
|
---|
42 | */
|
---|
43 | /*-
|
---|
44 | * Copyright (c) 1980, 1991, 1993
|
---|
45 | * The Regents of the University of California. All rights reserved.
|
---|
46 | *
|
---|
47 | * Redistribution and use in source and binary forms, with or without
|
---|
48 | * modification, are permitted provided that the following conditions
|
---|
49 | * are met:
|
---|
50 | * 1. Redistributions of source code must retain the above copyright
|
---|
51 | * notice, this list of conditions and the following disclaimer.
|
---|
52 | * 2. Redistributions in binary form must reproduce the above copyright
|
---|
53 | * notice, this list of conditions and the following disclaimer in the
|
---|
54 | * documentation and/or other materials provided with the distribution.
|
---|
55 | * 3. All advertising materials mentioning features or use of this software
|
---|
56 | * must display the following acknowledgement:
|
---|
57 | * This product includes software developed by the University of
|
---|
58 | * California, Berkeley and its contributors.
|
---|
59 | * 4. Neither the name of the University nor the names of its contributors
|
---|
60 | * may be used to endorse or promote products derived from this software
|
---|
61 | * without specific prior written permission.
|
---|
62 | *
|
---|
63 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
---|
64 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
---|
65 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
---|
66 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
---|
67 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
---|
68 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
---|
69 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
---|
70 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
---|
71 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
---|
72 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
---|
73 | * SUCH DAMAGE.
|
---|
74 | */
|
---|
75 |
|
---|
76 | #define __INTERNAL_CAPS_VISIBLE /* we need to see has_hardware_tabs */
|
---|
77 | #include <progs.priv.h>
|
---|
78 |
|
---|
79 | #include <errno.h>
|
---|
80 | #include <stdio.h>
|
---|
81 | #include <termcap.h>
|
---|
82 | #include <fcntl.h>
|
---|
83 |
|
---|
84 | #if HAVE_GETTTYNAM && HAVE_TTYENT_H
|
---|
85 | #include <ttyent.h>
|
---|
86 | #endif
|
---|
87 | #ifdef NeXT
|
---|
88 | char *ttyname(int fd);
|
---|
89 | #endif
|
---|
90 |
|
---|
91 | /* this is just to stifle a missing-prototype warning */
|
---|
92 | #ifdef linux
|
---|
93 | # include <sys/ioctl.h>
|
---|
94 | #endif
|
---|
95 |
|
---|
96 | #if NEED_PTEM_H
|
---|
97 | /* they neglected to define struct winsize in termios.h -- it's only
|
---|
98 | in termio.h */
|
---|
99 | #include <sys/stream.h>
|
---|
100 | #include <sys/ptem.h>
|
---|
101 | #endif
|
---|
102 |
|
---|
103 | #include <dump_entry.h>
|
---|
104 | #include <transform.h>
|
---|
105 |
|
---|
106 | MODULE_ID("$Id: tset.c,v 1.60 2005/09/25 00:43:52 tom Exp $")
|
---|
107 |
|
---|
108 | extern char **environ;
|
---|
109 |
|
---|
110 | #undef CTRL
|
---|
111 | #define CTRL(x) ((x) & 0x1f)
|
---|
112 |
|
---|
113 | const char *_nc_progname = "tset";
|
---|
114 |
|
---|
115 | static TTY mode, oldmode, original;
|
---|
116 |
|
---|
117 | static bool opt_c; /* set control-chars */
|
---|
118 | static bool opt_w; /* set window-size */
|
---|
119 |
|
---|
120 | static bool can_restore = FALSE;
|
---|
121 | static bool isreset = FALSE; /* invoked as reset */
|
---|
122 | static int terasechar = -1; /* new erase character */
|
---|
123 | static int intrchar = -1; /* new interrupt character */
|
---|
124 | static int tkillchar = -1; /* new kill character */
|
---|
125 | static int tlines, tcolumns; /* window size */
|
---|
126 |
|
---|
127 | #define LOWERCASE(c) ((isalpha(UChar(c)) && isupper(UChar(c))) ? tolower(UChar(c)) : (c))
|
---|
128 |
|
---|
129 | static int
|
---|
130 | CaselessCmp(const char *a, const char *b)
|
---|
131 | { /* strcasecmp isn't portable */
|
---|
132 | while (*a && *b) {
|
---|
133 | int cmp = LOWERCASE(*a) - LOWERCASE(*b);
|
---|
134 | if (cmp != 0)
|
---|
135 | break;
|
---|
136 | a++, b++;
|
---|
137 | }
|
---|
138 | return LOWERCASE(*a) - LOWERCASE(*b);
|
---|
139 | }
|
---|
140 |
|
---|
141 | static void
|
---|
142 | exit_error(void)
|
---|
143 | {
|
---|
144 | if (can_restore)
|
---|
145 | SET_TTY(STDERR_FILENO, &original);
|
---|
146 | (void) fprintf(stderr, "\n");
|
---|
147 | fflush(stderr);
|
---|
148 | ExitProgram(EXIT_FAILURE);
|
---|
149 | /* NOTREACHED */
|
---|
150 | }
|
---|
151 |
|
---|
152 | static void
|
---|
153 | err(const char *fmt,...)
|
---|
154 | {
|
---|
155 | va_list ap;
|
---|
156 | va_start(ap, fmt);
|
---|
157 | (void) fprintf(stderr, "%s: ", _nc_progname);
|
---|
158 | (void) vfprintf(stderr, fmt, ap);
|
---|
159 | va_end(ap);
|
---|
160 | exit_error();
|
---|
161 | /* NOTREACHED */
|
---|
162 | }
|
---|
163 |
|
---|
164 | static void
|
---|
165 | failed(const char *msg)
|
---|
166 | {
|
---|
167 | char temp[BUFSIZ];
|
---|
168 | unsigned len = strlen(_nc_progname) + 2;
|
---|
169 |
|
---|
170 | if (len < sizeof(temp) - 12) {
|
---|
171 | strcpy(temp, _nc_progname);
|
---|
172 | strcat(temp, ": ");
|
---|
173 | } else {
|
---|
174 | strcpy(temp, "tset: ");
|
---|
175 | }
|
---|
176 | perror(strncat(temp, msg, sizeof(temp) - strlen(temp) - 2));
|
---|
177 | exit_error();
|
---|
178 | /* NOTREACHED */
|
---|
179 | }
|
---|
180 |
|
---|
181 | static void
|
---|
182 | cat(char *file)
|
---|
183 | {
|
---|
184 | FILE *fp;
|
---|
185 | size_t nr;
|
---|
186 | char buf[BUFSIZ];
|
---|
187 |
|
---|
188 | if ((fp = fopen(file, "r")) == 0)
|
---|
189 | failed(file);
|
---|
190 |
|
---|
191 | while ((nr = fread(buf, sizeof(char), sizeof(buf), fp)) != 0)
|
---|
192 | if (fwrite(buf, sizeof(char), nr, stderr) != nr)
|
---|
193 | failed("write to stderr");
|
---|
194 | fclose(fp);
|
---|
195 | }
|
---|
196 |
|
---|
197 | static int
|
---|
198 | outc(int c)
|
---|
199 | {
|
---|
200 | return putc(c, stderr);
|
---|
201 | }
|
---|
202 |
|
---|
203 | /* Prompt the user for a terminal type. */
|
---|
204 | static const char *
|
---|
205 | askuser(const char *dflt)
|
---|
206 | {
|
---|
207 | static char answer[256];
|
---|
208 | char *p;
|
---|
209 |
|
---|
210 | /* We can get recalled; if so, don't continue uselessly. */
|
---|
211 | clearerr(stdin);
|
---|
212 | if (feof(stdin) || ferror(stdin)) {
|
---|
213 | (void) fprintf(stderr, "\n");
|
---|
214 | exit_error();
|
---|
215 | /* NOTREACHED */
|
---|
216 | }
|
---|
217 | for (;;) {
|
---|
218 | if (dflt)
|
---|
219 | (void) fprintf(stderr, "Terminal type? [%s] ", dflt);
|
---|
220 | else
|
---|
221 | (void) fprintf(stderr, "Terminal type? ");
|
---|
222 | (void) fflush(stderr);
|
---|
223 |
|
---|
224 | if (fgets(answer, sizeof(answer), stdin) == 0) {
|
---|
225 | if (dflt == 0) {
|
---|
226 | exit_error();
|
---|
227 | /* NOTREACHED */
|
---|
228 | }
|
---|
229 | return (dflt);
|
---|
230 | }
|
---|
231 |
|
---|
232 | if ((p = strchr(answer, '\n')) != 0)
|
---|
233 | *p = '\0';
|
---|
234 | if (answer[0])
|
---|
235 | return (answer);
|
---|
236 | if (dflt != 0)
|
---|
237 | return (dflt);
|
---|
238 | }
|
---|
239 | }
|
---|
240 |
|
---|
241 | /**************************************************************************
|
---|
242 | *
|
---|
243 | * Mapping logic begins here
|
---|
244 | *
|
---|
245 | **************************************************************************/
|
---|
246 |
|
---|
247 | /* Baud rate conditionals for mapping. */
|
---|
248 | #define GT 0x01
|
---|
249 | #define EQ 0x02
|
---|
250 | #define LT 0x04
|
---|
251 | #define NOT 0x08
|
---|
252 | #define GE (GT | EQ)
|
---|
253 | #define LE (LT | EQ)
|
---|
254 |
|
---|
255 | typedef struct map {
|
---|
256 | struct map *next; /* Linked list of maps. */
|
---|
257 | const char *porttype; /* Port type, or "" for any. */
|
---|
258 | const char *type; /* Terminal type to select. */
|
---|
259 | int conditional; /* Baud rate conditionals bitmask. */
|
---|
260 | int speed; /* Baud rate to compare against. */
|
---|
261 | } MAP;
|
---|
262 |
|
---|
263 | static MAP *cur, *maplist;
|
---|
264 |
|
---|
265 | typedef struct speeds {
|
---|
266 | const char *string;
|
---|
267 | int speed;
|
---|
268 | } SPEEDS;
|
---|
269 |
|
---|
270 | static const SPEEDS speeds[] =
|
---|
271 | {
|
---|
272 | {"0", B0},
|
---|
273 | {"50", B50},
|
---|
274 | {"75", B75},
|
---|
275 | {"110", B110},
|
---|
276 | {"134", B134},
|
---|
277 | {"134.5", B134},
|
---|
278 | {"150", B150},
|
---|
279 | {"200", B200},
|
---|
280 | {"300", B300},
|
---|
281 | {"600", B600},
|
---|
282 | {"1200", B1200},
|
---|
283 | {"1800", B1800},
|
---|
284 | {"2400", B2400},
|
---|
285 | {"4800", B4800},
|
---|
286 | {"9600", B9600},
|
---|
287 | /* sgttyb may define up to this point */
|
---|
288 | #ifdef B19200
|
---|
289 | {"19200", B19200},
|
---|
290 | #endif
|
---|
291 | #ifdef B38400
|
---|
292 | {"38400", B38400},
|
---|
293 | #endif
|
---|
294 | #ifdef B19200
|
---|
295 | {"19200", B19200},
|
---|
296 | #endif
|
---|
297 | #ifdef B38400
|
---|
298 | {"38400", B38400},
|
---|
299 | #endif
|
---|
300 | #ifdef B19200
|
---|
301 | {"19200", B19200},
|
---|
302 | #else
|
---|
303 | #ifdef EXTA
|
---|
304 | {"19200", EXTA},
|
---|
305 | #endif
|
---|
306 | #endif
|
---|
307 | #ifdef B38400
|
---|
308 | {"38400", B38400},
|
---|
309 | #else
|
---|
310 | #ifdef EXTB
|
---|
311 | {"38400", EXTB},
|
---|
312 | #endif
|
---|
313 | #endif
|
---|
314 | #ifdef B57600
|
---|
315 | {"57600", B57600},
|
---|
316 | #endif
|
---|
317 | #ifdef B115200
|
---|
318 | {"115200", B115200},
|
---|
319 | #endif
|
---|
320 | #ifdef B230400
|
---|
321 | {"230400", B230400},
|
---|
322 | #endif
|
---|
323 | #ifdef B460800
|
---|
324 | {"460800", B460800},
|
---|
325 | #endif
|
---|
326 | {(char *) 0, 0}
|
---|
327 | };
|
---|
328 |
|
---|
329 | static int
|
---|
330 | tbaudrate(char *rate)
|
---|
331 | {
|
---|
332 | const SPEEDS *sp;
|
---|
333 | int found = FALSE;
|
---|
334 |
|
---|
335 | /* The baudrate number can be preceded by a 'B', which is ignored. */
|
---|
336 | if (*rate == 'B')
|
---|
337 | ++rate;
|
---|
338 |
|
---|
339 | for (sp = speeds; sp->string; ++sp) {
|
---|
340 | if (!CaselessCmp(rate, sp->string)) {
|
---|
341 | found = TRUE;
|
---|
342 | break;
|
---|
343 | }
|
---|
344 | }
|
---|
345 | if (!found)
|
---|
346 | err("unknown baud rate %s", rate);
|
---|
347 | return (sp->speed);
|
---|
348 | }
|
---|
349 |
|
---|
350 | /*
|
---|
351 | * Syntax for -m:
|
---|
352 | * [port-type][test baudrate]:terminal-type
|
---|
353 | * The baud rate tests are: >, <, @, =, !
|
---|
354 | */
|
---|
355 | static void
|
---|
356 | add_mapping(const char *port, char *arg)
|
---|
357 | {
|
---|
358 | MAP *mapp;
|
---|
359 | char *copy, *p;
|
---|
360 | const char *termp;
|
---|
361 | char *base = 0;
|
---|
362 |
|
---|
363 | copy = strdup(arg);
|
---|
364 | mapp = (MAP *) malloc(sizeof(MAP));
|
---|
365 | if (copy == 0 || mapp == 0)
|
---|
366 | failed("malloc");
|
---|
367 | mapp->next = 0;
|
---|
368 | if (maplist == 0)
|
---|
369 | cur = maplist = mapp;
|
---|
370 | else {
|
---|
371 | cur->next = mapp;
|
---|
372 | cur = mapp;
|
---|
373 | }
|
---|
374 |
|
---|
375 | mapp->porttype = arg;
|
---|
376 | mapp->conditional = 0;
|
---|
377 |
|
---|
378 | arg = strpbrk(arg, "><@=!:");
|
---|
379 |
|
---|
380 | if (arg == 0) { /* [?]term */
|
---|
381 | mapp->type = mapp->porttype;
|
---|
382 | mapp->porttype = 0;
|
---|
383 | goto done;
|
---|
384 | }
|
---|
385 |
|
---|
386 | if (arg == mapp->porttype) /* [><@=! baud]:term */
|
---|
387 | termp = mapp->porttype = 0;
|
---|
388 | else
|
---|
389 | termp = base = arg;
|
---|
390 |
|
---|
391 | for (;; ++arg) { /* Optional conditionals. */
|
---|
392 | switch (*arg) {
|
---|
393 | case '<':
|
---|
394 | if (mapp->conditional & GT)
|
---|
395 | goto badmopt;
|
---|
396 | mapp->conditional |= LT;
|
---|
397 | break;
|
---|
398 | case '>':
|
---|
399 | if (mapp->conditional & LT)
|
---|
400 | goto badmopt;
|
---|
401 | mapp->conditional |= GT;
|
---|
402 | break;
|
---|
403 | case '@':
|
---|
404 | case '=': /* Not documented. */
|
---|
405 | mapp->conditional |= EQ;
|
---|
406 | break;
|
---|
407 | case '!':
|
---|
408 | mapp->conditional |= NOT;
|
---|
409 | break;
|
---|
410 | default:
|
---|
411 | goto next;
|
---|
412 | }
|
---|
413 | }
|
---|
414 |
|
---|
415 | next:
|
---|
416 | if (*arg == ':') {
|
---|
417 | if (mapp->conditional)
|
---|
418 | goto badmopt;
|
---|
419 | ++arg;
|
---|
420 | } else { /* Optional baudrate. */
|
---|
421 | arg = strchr(p = arg, ':');
|
---|
422 | if (arg == 0)
|
---|
423 | goto badmopt;
|
---|
424 | *arg++ = '\0';
|
---|
425 | mapp->speed = tbaudrate(p);
|
---|
426 | }
|
---|
427 |
|
---|
428 | if (arg == (char *) 0) /* Non-optional type. */
|
---|
429 | goto badmopt;
|
---|
430 |
|
---|
431 | mapp->type = arg;
|
---|
432 |
|
---|
433 | /* Terminate porttype, if specified. */
|
---|
434 | if (termp != 0)
|
---|
435 | *base = '\0';
|
---|
436 |
|
---|
437 | /* If a NOT conditional, reverse the test. */
|
---|
438 | if (mapp->conditional & NOT)
|
---|
439 | mapp->conditional = ~mapp->conditional & (EQ | GT | LT);
|
---|
440 |
|
---|
441 | /* If user specified a port with an option flag, set it. */
|
---|
442 | done:if (port) {
|
---|
443 | if (mapp->porttype)
|
---|
444 | badmopt:err("illegal -m option format: %s", copy);
|
---|
445 | mapp->porttype = port;
|
---|
446 | }
|
---|
447 | #ifdef MAPDEBUG
|
---|
448 | (void) printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY");
|
---|
449 | (void) printf("type: %s\n", mapp->type);
|
---|
450 | (void) printf("conditional: ");
|
---|
451 | p = "";
|
---|
452 | if (mapp->conditional & GT) {
|
---|
453 | (void) printf("GT");
|
---|
454 | p = "/";
|
---|
455 | }
|
---|
456 | if (mapp->conditional & EQ) {
|
---|
457 | (void) printf("%sEQ", p);
|
---|
458 | p = "/";
|
---|
459 | }
|
---|
460 | if (mapp->conditional & LT)
|
---|
461 | (void) printf("%sLT", p);
|
---|
462 | (void) printf("\nspeed: %d\n", mapp->speed);
|
---|
463 | #endif
|
---|
464 | }
|
---|
465 |
|
---|
466 | /*
|
---|
467 | * Return the type of terminal to use for a port of type 'type', as specified
|
---|
468 | * by the first applicable mapping in 'map'. If no mappings apply, return
|
---|
469 | * 'type'.
|
---|
470 | */
|
---|
471 | static const char *
|
---|
472 | mapped(const char *type)
|
---|
473 | {
|
---|
474 | MAP *mapp;
|
---|
475 | int match;
|
---|
476 |
|
---|
477 | for (mapp = maplist; mapp; mapp = mapp->next)
|
---|
478 | if (mapp->porttype == 0 || !strcmp(mapp->porttype, type)) {
|
---|
479 | switch (mapp->conditional) {
|
---|
480 | case 0: /* No test specified. */
|
---|
481 | match = TRUE;
|
---|
482 | break;
|
---|
483 | case EQ:
|
---|
484 | match = (ospeed == mapp->speed);
|
---|
485 | break;
|
---|
486 | case GE:
|
---|
487 | match = (ospeed >= mapp->speed);
|
---|
488 | break;
|
---|
489 | case GT:
|
---|
490 | match = (ospeed > mapp->speed);
|
---|
491 | break;
|
---|
492 | case LE:
|
---|
493 | match = (ospeed <= mapp->speed);
|
---|
494 | break;
|
---|
495 | case LT:
|
---|
496 | match = (ospeed < mapp->speed);
|
---|
497 | break;
|
---|
498 | default:
|
---|
499 | match = FALSE;
|
---|
500 | }
|
---|
501 | if (match)
|
---|
502 | return (mapp->type);
|
---|
503 | }
|
---|
504 | /* No match found; return given type. */
|
---|
505 | return (type);
|
---|
506 | }
|
---|
507 |
|
---|
508 | /**************************************************************************
|
---|
509 | *
|
---|
510 | * Entry fetching
|
---|
511 | *
|
---|
512 | **************************************************************************/
|
---|
513 |
|
---|
514 | /*
|
---|
515 | * Figure out what kind of terminal we're dealing with, and then read in
|
---|
516 | * its termcap entry.
|
---|
517 | */
|
---|
518 | static const char *
|
---|
519 | get_termcap_entry(char *userarg)
|
---|
520 | {
|
---|
521 | int errret;
|
---|
522 | char *p;
|
---|
523 | const char *ttype;
|
---|
524 | #if HAVE_GETTTYNAM
|
---|
525 | struct ttyent *t;
|
---|
526 | #else
|
---|
527 | FILE *fp;
|
---|
528 | #endif
|
---|
529 | char *ttypath;
|
---|
530 |
|
---|
531 | if (userarg) {
|
---|
532 | ttype = userarg;
|
---|
533 | goto found;
|
---|
534 | }
|
---|
535 |
|
---|
536 | /* Try the environment. */
|
---|
537 | if ((ttype = getenv("TERM")) != 0)
|
---|
538 | goto map;
|
---|
539 |
|
---|
540 | if ((ttypath = ttyname(STDERR_FILENO)) != 0) {
|
---|
541 | p = _nc_basename(ttypath);
|
---|
542 | #if HAVE_GETTTYNAM
|
---|
543 | /*
|
---|
544 | * We have the 4.3BSD library call getttynam(3); that means
|
---|
545 | * there's an /etc/ttys to look up device-to-type mappings in.
|
---|
546 | * Try ttyname(3); check for dialup or other mapping.
|
---|
547 | */
|
---|
548 | if ((t = getttynam(p))) {
|
---|
549 | ttype = t->ty_type;
|
---|
550 | goto map;
|
---|
551 | }
|
---|
552 | #else
|
---|
553 | if ((fp = fopen("/etc/ttytype", "r")) != 0
|
---|
554 | || (fp = fopen("/etc/ttys", "r")) != 0) {
|
---|
555 | char buffer[BUFSIZ];
|
---|
556 | char *s, *t, *d;
|
---|
557 |
|
---|
558 | while (fgets(buffer, sizeof(buffer) - 1, fp) != 0) {
|
---|
559 | for (s = buffer, t = d = 0; *s; s++) {
|
---|
560 | if (isspace(UChar(*s)))
|
---|
561 | *s = '\0';
|
---|
562 | else if (t == 0)
|
---|
563 | t = s;
|
---|
564 | else if (d == 0 && s != buffer && s[-1] == '\0')
|
---|
565 | d = s;
|
---|
566 | }
|
---|
567 | if (t != 0 && d != 0 && !strcmp(d, p)) {
|
---|
568 | ttype = strdup(t);
|
---|
569 | fclose(fp);
|
---|
570 | goto map;
|
---|
571 | }
|
---|
572 | }
|
---|
573 | fclose(fp);
|
---|
574 | }
|
---|
575 | #endif /* HAVE_GETTTYNAM */
|
---|
576 | }
|
---|
577 |
|
---|
578 | /* If still undefined, use "unknown". */
|
---|
579 | ttype = "unknown";
|
---|
580 |
|
---|
581 | map:ttype = mapped(ttype);
|
---|
582 |
|
---|
583 | /*
|
---|
584 | * If not a path, remove TERMCAP from the environment so we get a
|
---|
585 | * real entry from /etc/termcap. This prevents us from being fooled
|
---|
586 | * by out of date stuff in the environment.
|
---|
587 | */
|
---|
588 | found:if ((p = getenv("TERMCAP")) != 0 && *p != '/') {
|
---|
589 | /* 'unsetenv("TERMCAP")' is not portable.
|
---|
590 | * The 'environ' array is better.
|
---|
591 | */
|
---|
592 | int n;
|
---|
593 | for (n = 0; environ[n] != 0; n++) {
|
---|
594 | if (!strncmp("TERMCAP=", environ[n], 8)) {
|
---|
595 | while ((environ[n] = environ[n + 1]) != 0) {
|
---|
596 | n++;
|
---|
597 | }
|
---|
598 | break;
|
---|
599 | }
|
---|
600 | }
|
---|
601 | }
|
---|
602 |
|
---|
603 | /*
|
---|
604 | * ttype now contains a pointer to the type of the terminal.
|
---|
605 | * If the first character is '?', ask the user.
|
---|
606 | */
|
---|
607 | if (ttype[0] == '?') {
|
---|
608 | if (ttype[1] != '\0')
|
---|
609 | ttype = askuser(ttype + 1);
|
---|
610 | else
|
---|
611 | ttype = askuser(0);
|
---|
612 | }
|
---|
613 | /* Find the terminfo entry. If it doesn't exist, ask the user. */
|
---|
614 | while (setupterm((NCURSES_CONST char *) ttype, STDOUT_FILENO, &errret)
|
---|
615 | != OK) {
|
---|
616 | if (errret == 0) {
|
---|
617 | (void) fprintf(stderr, "%s: unknown terminal type %s\n",
|
---|
618 | _nc_progname, ttype);
|
---|
619 | ttype = 0;
|
---|
620 | } else {
|
---|
621 | (void) fprintf(stderr,
|
---|
622 | "%s: can't initialize terminal type %s (error %d)\n",
|
---|
623 | _nc_progname, ttype, errret);
|
---|
624 | ttype = 0;
|
---|
625 | }
|
---|
626 | ttype = askuser(ttype);
|
---|
627 | }
|
---|
628 | #if BROKEN_LINKER
|
---|
629 | tgetflag("am"); /* force lib_termcap.o to be linked for 'ospeed' */
|
---|
630 | #endif
|
---|
631 | return (ttype);
|
---|
632 | }
|
---|
633 |
|
---|
634 | /**************************************************************************
|
---|
635 | *
|
---|
636 | * Mode-setting logic
|
---|
637 | *
|
---|
638 | **************************************************************************/
|
---|
639 |
|
---|
640 | /* some BSD systems have these built in, some systems are missing
|
---|
641 | * one or more definitions. The safest solution is to override unless the
|
---|
642 | * commonly-altered ones are defined.
|
---|
643 | */
|
---|
644 | #if !(defined(CERASE) && defined(CINTR) && defined(CKILL) && defined(CQUIT))
|
---|
645 | #undef CEOF
|
---|
646 | #undef CERASE
|
---|
647 | #undef CINTR
|
---|
648 | #undef CKILL
|
---|
649 | #undef CLNEXT
|
---|
650 | #undef CRPRNT
|
---|
651 | #undef CQUIT
|
---|
652 | #undef CSTART
|
---|
653 | #undef CSTOP
|
---|
654 | #undef CSUSP
|
---|
655 | #endif
|
---|
656 |
|
---|
657 | /* control-character defaults */
|
---|
658 | #ifndef CEOF
|
---|
659 | #define CEOF CTRL('D')
|
---|
660 | #endif
|
---|
661 | #ifndef CERASE
|
---|
662 | #define CERASE CTRL('H')
|
---|
663 | #endif
|
---|
664 | #ifndef CINTR
|
---|
665 | #define CINTR 127 /* ^? */
|
---|
666 | #endif
|
---|
667 | #ifndef CKILL
|
---|
668 | #define CKILL CTRL('U')
|
---|
669 | #endif
|
---|
670 | #ifndef CLNEXT
|
---|
671 | #define CLNEXT CTRL('v')
|
---|
672 | #endif
|
---|
673 | #ifndef CRPRNT
|
---|
674 | #define CRPRNT CTRL('r')
|
---|
675 | #endif
|
---|
676 | #ifndef CQUIT
|
---|
677 | #define CQUIT CTRL('\\')
|
---|
678 | #endif
|
---|
679 | #ifndef CSTART
|
---|
680 | #define CSTART CTRL('Q')
|
---|
681 | #endif
|
---|
682 | #ifndef CSTOP
|
---|
683 | #define CSTOP CTRL('S')
|
---|
684 | #endif
|
---|
685 | #ifndef CSUSP
|
---|
686 | #define CSUSP CTRL('Z')
|
---|
687 | #endif
|
---|
688 |
|
---|
689 | #define CHK(val, dft) ((int)val <= 0 ? dft : val)
|
---|
690 |
|
---|
691 | static bool set_tabs(void);
|
---|
692 |
|
---|
693 | /*
|
---|
694 | * Reset the terminal mode bits to a sensible state. Very useful after
|
---|
695 | * a child program dies in raw mode.
|
---|
696 | */
|
---|
697 | static void
|
---|
698 | reset_mode(void)
|
---|
699 | {
|
---|
700 | #ifdef TERMIOS
|
---|
701 | tcgetattr(STDERR_FILENO, &mode);
|
---|
702 | #else
|
---|
703 | stty(STDERR_FILENO, &mode);
|
---|
704 | #endif
|
---|
705 |
|
---|
706 | #ifdef TERMIOS
|
---|
707 | #if defined(VDISCARD) && defined(CDISCARD)
|
---|
708 | mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD);
|
---|
709 | #endif
|
---|
710 | mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF);
|
---|
711 | mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE);
|
---|
712 | #if defined(VFLUSH) && defined(CFLUSH)
|
---|
713 | mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH);
|
---|
714 | #endif
|
---|
715 | mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR);
|
---|
716 | mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL);
|
---|
717 | #if defined(VLNEXT) && defined(CLNEXT)
|
---|
718 | mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT);
|
---|
719 | #endif
|
---|
720 | mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT);
|
---|
721 | #if defined(VREPRINT) && defined(CRPRNT)
|
---|
722 | mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT);
|
---|
723 | #endif
|
---|
724 | #if defined(VSTART) && defined(CSTART)
|
---|
725 | mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART);
|
---|
726 | #endif
|
---|
727 | #if defined(VSTOP) && defined(CSTOP)
|
---|
728 | mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP);
|
---|
729 | #endif
|
---|
730 | #if defined(VSUSP) && defined(CSUSP)
|
---|
731 | mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP);
|
---|
732 | #endif
|
---|
733 | #if defined(VWERASE) && defined(CWERASE)
|
---|
734 | mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE);
|
---|
735 | #endif
|
---|
736 |
|
---|
737 | mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR
|
---|
738 | #ifdef IUCLC
|
---|
739 | | IUCLC
|
---|
740 | #endif
|
---|
741 | #ifdef IXANY
|
---|
742 | | IXANY
|
---|
743 | #endif
|
---|
744 | | IXOFF);
|
---|
745 |
|
---|
746 | mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON
|
---|
747 | #ifdef IMAXBEL
|
---|
748 | | IMAXBEL
|
---|
749 | #endif
|
---|
750 | );
|
---|
751 |
|
---|
752 | mode.c_oflag &= ~(0
|
---|
753 | #ifdef OLCUC
|
---|
754 | | OLCUC
|
---|
755 | #endif
|
---|
756 | #ifdef OCRNL
|
---|
757 | | OCRNL
|
---|
758 | #endif
|
---|
759 | #ifdef ONOCR
|
---|
760 | | ONOCR
|
---|
761 | #endif
|
---|
762 | #ifdef ONLRET
|
---|
763 | | ONLRET
|
---|
764 | #endif
|
---|
765 | #ifdef OFILL
|
---|
766 | | OFILL
|
---|
767 | #endif
|
---|
768 | #ifdef OFDEL
|
---|
769 | | OFDEL
|
---|
770 | #endif
|
---|
771 | #ifdef NLDLY
|
---|
772 | | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY
|
---|
773 | #endif
|
---|
774 | );
|
---|
775 |
|
---|
776 | mode.c_oflag |= (OPOST
|
---|
777 | #ifdef ONLCR
|
---|
778 | | ONLCR
|
---|
779 | #endif
|
---|
780 | );
|
---|
781 |
|
---|
782 | mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | CLOCAL);
|
---|
783 | mode.c_cflag |= (CS8 | CREAD);
|
---|
784 | mode.c_lflag &= ~(ECHONL | NOFLSH
|
---|
785 | #ifdef TOSTOP
|
---|
786 | | TOSTOP
|
---|
787 | #endif
|
---|
788 | #ifdef ECHOPTR
|
---|
789 | | ECHOPRT
|
---|
790 | #endif
|
---|
791 | #ifdef XCASE
|
---|
792 | | XCASE
|
---|
793 | #endif
|
---|
794 | );
|
---|
795 |
|
---|
796 | mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK
|
---|
797 | #ifdef ECHOCTL
|
---|
798 | | ECHOCTL
|
---|
799 | #endif
|
---|
800 | #ifdef ECHOKE
|
---|
801 | | ECHOKE
|
---|
802 | #endif
|
---|
803 | );
|
---|
804 | #endif
|
---|
805 |
|
---|
806 | SET_TTY(STDERR_FILENO, &mode);
|
---|
807 | }
|
---|
808 |
|
---|
809 | /*
|
---|
810 | * Returns a "good" value for the erase character. This is loosely based on
|
---|
811 | * the BSD4.4 logic.
|
---|
812 | */
|
---|
813 | #ifdef TERMIOS
|
---|
814 | static int
|
---|
815 | default_erase(void)
|
---|
816 | {
|
---|
817 | int result;
|
---|
818 |
|
---|
819 | if (over_strike
|
---|
820 | && key_backspace != 0
|
---|
821 | && strlen(key_backspace) == 1)
|
---|
822 | result = key_backspace[0];
|
---|
823 | else
|
---|
824 | result = CERASE;
|
---|
825 |
|
---|
826 | return result;
|
---|
827 | }
|
---|
828 | #endif
|
---|
829 |
|
---|
830 | /*
|
---|
831 | * Update the values of the erase, interrupt, and kill characters in 'mode'.
|
---|
832 | *
|
---|
833 | * SVr4 tset (e.g., Solaris 2.5) only modifies the intr, quit or erase
|
---|
834 | * characters if they're unset, or if we specify them as options. This differs
|
---|
835 | * from BSD 4.4 tset, which always sets erase.
|
---|
836 | */
|
---|
837 | static void
|
---|
838 | set_control_chars(void)
|
---|
839 | {
|
---|
840 | #ifdef TERMIOS
|
---|
841 | if (mode.c_cc[VERASE] == 0 || terasechar >= 0)
|
---|
842 | mode.c_cc[VERASE] = terasechar >= 0 ? terasechar : default_erase();
|
---|
843 |
|
---|
844 | if (mode.c_cc[VINTR] == 0 || intrchar >= 0)
|
---|
845 | mode.c_cc[VINTR] = intrchar >= 0 ? intrchar : CINTR;
|
---|
846 |
|
---|
847 | if (mode.c_cc[VKILL] == 0 || tkillchar >= 0)
|
---|
848 | mode.c_cc[VKILL] = tkillchar >= 0 ? tkillchar : CKILL;
|
---|
849 | #endif
|
---|
850 | }
|
---|
851 |
|
---|
852 | /*
|
---|
853 | * Set up various conversions in 'mode', including parity, tabs, returns,
|
---|
854 | * echo, and case, according to the termcap entry. If the program we're
|
---|
855 | * running was named with a leading upper-case character, map external
|
---|
856 | * uppercase to internal lowercase.
|
---|
857 | */
|
---|
858 | static void
|
---|
859 | set_conversions(void)
|
---|
860 | {
|
---|
861 | #ifdef __OBSOLETE__
|
---|
862 | /*
|
---|
863 | * Conversion logic for some *really* ancient terminal glitches,
|
---|
864 | * not supported in terminfo. Left here for succeeding generations
|
---|
865 | * to marvel at.
|
---|
866 | */
|
---|
867 | if (tgetflag("UC")) {
|
---|
868 | #ifdef IUCLC
|
---|
869 | mode.c_iflag |= IUCLC;
|
---|
870 | mode.c_oflag |= OLCUC;
|
---|
871 | #endif
|
---|
872 | } else if (tgetflag("LC")) {
|
---|
873 | #ifdef IUCLC
|
---|
874 | mode.c_iflag &= ~IUCLC;
|
---|
875 | mode.c_oflag &= ~OLCUC;
|
---|
876 | #endif
|
---|
877 | }
|
---|
878 | mode.c_iflag &= ~(PARMRK | INPCK);
|
---|
879 | mode.c_lflag |= ICANON;
|
---|
880 | if (tgetflag("EP")) {
|
---|
881 | mode.c_cflag |= PARENB;
|
---|
882 | mode.c_cflag &= ~PARODD;
|
---|
883 | }
|
---|
884 | if (tgetflag("OP")) {
|
---|
885 | mode.c_cflag |= PARENB;
|
---|
886 | mode.c_cflag |= PARODD;
|
---|
887 | }
|
---|
888 | #endif /* __OBSOLETE__ */
|
---|
889 |
|
---|
890 | #ifdef TERMIOS
|
---|
891 | #ifdef ONLCR
|
---|
892 | mode.c_oflag |= ONLCR;
|
---|
893 | #endif
|
---|
894 | mode.c_iflag |= ICRNL;
|
---|
895 | mode.c_lflag |= ECHO;
|
---|
896 | #ifdef OXTABS
|
---|
897 | mode.c_oflag |= OXTABS;
|
---|
898 | #endif /* OXTABS */
|
---|
899 |
|
---|
900 | /* test used to be tgetflag("NL") */
|
---|
901 | if (newline != (char *) 0 && newline[0] == '\n' && !newline[1]) {
|
---|
902 | /* Newline, not linefeed. */
|
---|
903 | #ifdef ONLCR
|
---|
904 | mode.c_oflag &= ~ONLCR;
|
---|
905 | #endif
|
---|
906 | mode.c_iflag &= ~ICRNL;
|
---|
907 | }
|
---|
908 | #ifdef __OBSOLETE__
|
---|
909 | if (tgetflag("HD")) /* Half duplex. */
|
---|
910 | mode.c_lflag &= ~ECHO;
|
---|
911 | #endif /* __OBSOLETE__ */
|
---|
912 | #ifdef OXTABS
|
---|
913 | /* test used to be tgetflag("pt") */
|
---|
914 | if (has_hardware_tabs) /* Print tabs. */
|
---|
915 | mode.c_oflag &= ~OXTABS;
|
---|
916 | #endif /* OXTABS */
|
---|
917 | mode.c_lflag |= (ECHOE | ECHOK);
|
---|
918 | #endif
|
---|
919 | }
|
---|
920 |
|
---|
921 | /* Output startup string. */
|
---|
922 | static void
|
---|
923 | set_init(void)
|
---|
924 | {
|
---|
925 | char *p;
|
---|
926 | bool settle;
|
---|
927 |
|
---|
928 | #ifdef __OBSOLETE__
|
---|
929 | if (pad_char != (char *) 0) /* Get/set pad character. */
|
---|
930 | PC = pad_char[0];
|
---|
931 | #endif /* OBSOLETE */
|
---|
932 |
|
---|
933 | #ifdef TAB3
|
---|
934 | if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) {
|
---|
935 | oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET);
|
---|
936 | SET_TTY(STDERR_FILENO, &oldmode);
|
---|
937 | }
|
---|
938 | #endif
|
---|
939 | settle = set_tabs();
|
---|
940 |
|
---|
941 | if (isreset) {
|
---|
942 | if ((p = reset_1string) != 0) {
|
---|
943 | tputs(p, 0, outc);
|
---|
944 | settle = TRUE;
|
---|
945 | }
|
---|
946 | if ((p = reset_2string) != 0) {
|
---|
947 | tputs(p, 0, outc);
|
---|
948 | settle = TRUE;
|
---|
949 | }
|
---|
950 | /* What about rf, rs3, as per terminfo man page? */
|
---|
951 | /* also might be nice to send rmacs, rmul, rmm */
|
---|
952 | if ((p = reset_file) != 0
|
---|
953 | || (p = init_file) != 0) {
|
---|
954 | cat(p);
|
---|
955 | settle = TRUE;
|
---|
956 | }
|
---|
957 | }
|
---|
958 |
|
---|
959 | if (settle) {
|
---|
960 | (void) putc('\r', stderr);
|
---|
961 | (void) fflush(stderr);
|
---|
962 | (void) napms(1000); /* Settle the terminal. */
|
---|
963 | }
|
---|
964 | }
|
---|
965 |
|
---|
966 | /*
|
---|
967 | * Set the hardware tabs on the terminal, using the ct (clear all tabs),
|
---|
968 | * st (set one tab) and ch (horizontal cursor addressing) capabilities.
|
---|
969 | * This is done before if and is, so they can patch in case we blow this.
|
---|
970 | * Return TRUE if we set any tab stops, FALSE if not.
|
---|
971 | */
|
---|
972 | static bool
|
---|
973 | set_tabs()
|
---|
974 | {
|
---|
975 | if (set_tab && clear_all_tabs) {
|
---|
976 | int c;
|
---|
977 |
|
---|
978 | (void) putc('\r', stderr); /* Force to left margin. */
|
---|
979 | tputs(clear_all_tabs, 0, outc);
|
---|
980 |
|
---|
981 | for (c = 8; c < tcolumns; c += 8) {
|
---|
982 | /* Get to the right column. In BSD tset, this
|
---|
983 | * used to try a bunch of half-clever things
|
---|
984 | * with cup and hpa, for an average saving of
|
---|
985 | * somewhat less than two character times per
|
---|
986 | * tab stop, less than .01 sec at 2400cps. We
|
---|
987 | * lost all this cruft because it seemed to be
|
---|
988 | * introducing some odd bugs.
|
---|
989 | * -----------12345678----------- */
|
---|
990 | (void) fputs(" ", stderr);
|
---|
991 | tputs(set_tab, 0, outc);
|
---|
992 | }
|
---|
993 | putc('\r', stderr);
|
---|
994 | return (TRUE);
|
---|
995 | }
|
---|
996 | return (FALSE);
|
---|
997 | }
|
---|
998 |
|
---|
999 | /**************************************************************************
|
---|
1000 | *
|
---|
1001 | * Main sequence
|
---|
1002 | *
|
---|
1003 | **************************************************************************/
|
---|
1004 |
|
---|
1005 | /*
|
---|
1006 | * Tell the user if a control key has been changed from the default value.
|
---|
1007 | */
|
---|
1008 | #ifdef TERMIOS
|
---|
1009 | static void
|
---|
1010 | report(const char *name, int which, unsigned def)
|
---|
1011 | {
|
---|
1012 | unsigned older, newer;
|
---|
1013 | char *p;
|
---|
1014 |
|
---|
1015 | newer = mode.c_cc[which];
|
---|
1016 | older = oldmode.c_cc[which];
|
---|
1017 |
|
---|
1018 | if (older == newer && older == def)
|
---|
1019 | return;
|
---|
1020 |
|
---|
1021 | (void) fprintf(stderr, "%s %s ", name, older == newer ? "is" : "set to");
|
---|
1022 |
|
---|
1023 | /*
|
---|
1024 | * Check 'delete' before 'backspace', since the key_backspace value
|
---|
1025 | * is ambiguous.
|
---|
1026 | */
|
---|
1027 | if (newer == 0177)
|
---|
1028 | (void) fprintf(stderr, "delete.\n");
|
---|
1029 | else if ((p = key_backspace) != 0
|
---|
1030 | && newer == (unsigned char) p[0]
|
---|
1031 | && p[1] == '\0')
|
---|
1032 | (void) fprintf(stderr, "backspace.\n");
|
---|
1033 | else if (newer < 040) {
|
---|
1034 | newer ^= 0100;
|
---|
1035 | (void) fprintf(stderr, "control-%c (^%c).\n", UChar(newer), UChar(newer));
|
---|
1036 | } else
|
---|
1037 | (void) fprintf(stderr, "%c.\n", UChar(newer));
|
---|
1038 | }
|
---|
1039 | #endif
|
---|
1040 |
|
---|
1041 | /*
|
---|
1042 | * Convert the obsolete argument forms into something that getopt can handle.
|
---|
1043 | * This means that -e, -i and -k get default arguments supplied for them.
|
---|
1044 | */
|
---|
1045 | static void
|
---|
1046 | obsolete(char **argv)
|
---|
1047 | {
|
---|
1048 | for (; *argv; ++argv) {
|
---|
1049 | char *parm = argv[0];
|
---|
1050 |
|
---|
1051 | if (parm[0] == '-' && parm[1] == '\0') {
|
---|
1052 | argv[0] = strdup("-q");
|
---|
1053 | continue;
|
---|
1054 | }
|
---|
1055 |
|
---|
1056 | if ((parm[0] != '-')
|
---|
1057 | || (argv[1] && argv[1][0] != '-')
|
---|
1058 | || (parm[1] != 'e' && parm[1] != 'i' && parm[1] != 'k')
|
---|
1059 | || (parm[2] != '\0'))
|
---|
1060 | continue;
|
---|
1061 | switch (argv[0][1]) {
|
---|
1062 | case 'e':
|
---|
1063 | argv[0] = strdup("-e^H");
|
---|
1064 | break;
|
---|
1065 | case 'i':
|
---|
1066 | argv[0] = strdup("-i^C");
|
---|
1067 | break;
|
---|
1068 | case 'k':
|
---|
1069 | argv[0] = strdup("-k^U");
|
---|
1070 | break;
|
---|
1071 | }
|
---|
1072 | }
|
---|
1073 | }
|
---|
1074 |
|
---|
1075 | static void
|
---|
1076 | usage(void)
|
---|
1077 | {
|
---|
1078 | static const char *tbl[] =
|
---|
1079 | {
|
---|
1080 | ""
|
---|
1081 | ,"Options:"
|
---|
1082 | ," -c set control characters"
|
---|
1083 | ," -e ch erase character"
|
---|
1084 | ," -I no initialization strings"
|
---|
1085 | ," -i ch interrupt character"
|
---|
1086 | ," -k ch kill character"
|
---|
1087 | ," -m mapping map identifier to type"
|
---|
1088 | ," -Q do not output control key settings"
|
---|
1089 | ," -r display term on stderr"
|
---|
1090 | ," -s output TERM set command"
|
---|
1091 | ," -V print curses-version"
|
---|
1092 | ," -w set window-size"
|
---|
1093 | };
|
---|
1094 | unsigned n;
|
---|
1095 | (void) fprintf(stderr, "Usage: %s [options] [terminal]\n", _nc_progname);
|
---|
1096 | for (n = 0; n < sizeof(tbl) / sizeof(tbl[0]); ++n)
|
---|
1097 | fprintf(stderr, "%s\n", tbl[n]);
|
---|
1098 | exit_error();
|
---|
1099 | /* NOTREACHED */
|
---|
1100 | }
|
---|
1101 |
|
---|
1102 | static char
|
---|
1103 | arg_to_char(void)
|
---|
1104 | {
|
---|
1105 | return (optarg[0] == '^' && optarg[1] != '\0')
|
---|
1106 | ? ((optarg[1] == '?') ? '\177' : CTRL(optarg[1]))
|
---|
1107 | : optarg[0];
|
---|
1108 | }
|
---|
1109 |
|
---|
1110 | int
|
---|
1111 | main(int argc, char **argv)
|
---|
1112 | {
|
---|
1113 | #if defined(TIOCGWINSZ) && defined(TIOCSWINSZ)
|
---|
1114 | struct winsize win;
|
---|
1115 | #endif
|
---|
1116 | int ch, noinit, noset, quiet, Sflag, sflag, showterm;
|
---|
1117 | const char *p;
|
---|
1118 | const char *ttype;
|
---|
1119 |
|
---|
1120 | obsolete(argv);
|
---|
1121 | noinit = noset = quiet = Sflag = sflag = showterm = 0;
|
---|
1122 | while ((ch = getopt(argc, argv, "a:cd:e:Ii:k:m:np:qQSrsVw")) != EOF) {
|
---|
1123 | switch (ch) {
|
---|
1124 | case 'c': /* set control-chars */
|
---|
1125 | opt_c = TRUE;
|
---|
1126 | break;
|
---|
1127 | case 'a': /* OBSOLETE: map identifier to type */
|
---|
1128 | add_mapping("arpanet", optarg);
|
---|
1129 | break;
|
---|
1130 | case 'd': /* OBSOLETE: map identifier to type */
|
---|
1131 | add_mapping("dialup", optarg);
|
---|
1132 | break;
|
---|
1133 | case 'e': /* erase character */
|
---|
1134 | terasechar = arg_to_char();
|
---|
1135 | break;
|
---|
1136 | case 'I': /* no initialization strings */
|
---|
1137 | noinit = 1;
|
---|
1138 | break;
|
---|
1139 | case 'i': /* interrupt character */
|
---|
1140 | intrchar = arg_to_char();
|
---|
1141 | break;
|
---|
1142 | case 'k': /* kill character */
|
---|
1143 | tkillchar = arg_to_char();
|
---|
1144 | break;
|
---|
1145 | case 'm': /* map identifier to type */
|
---|
1146 | add_mapping(0, optarg);
|
---|
1147 | break;
|
---|
1148 | case 'n': /* OBSOLETE: set new tty driver */
|
---|
1149 | break;
|
---|
1150 | case 'p': /* OBSOLETE: map identifier to type */
|
---|
1151 | add_mapping("plugboard", optarg);
|
---|
1152 | break;
|
---|
1153 | case 'Q': /* don't output control key settings */
|
---|
1154 | quiet = 1;
|
---|
1155 | break;
|
---|
1156 | case 'q': /* display term only */
|
---|
1157 | noset = 1;
|
---|
1158 | break;
|
---|
1159 | case 'r': /* display term on stderr */
|
---|
1160 | showterm = 1;
|
---|
1161 | break;
|
---|
1162 | case 'S': /* OBSOLETE: output TERM & TERMCAP */
|
---|
1163 | Sflag = 1;
|
---|
1164 | break;
|
---|
1165 | case 's': /* output TERM set command */
|
---|
1166 | sflag = 1;
|
---|
1167 | break;
|
---|
1168 | case 'V': /* print curses-version */
|
---|
1169 | puts(curses_version());
|
---|
1170 | return EXIT_SUCCESS;
|
---|
1171 | case 'w': /* set window-size */
|
---|
1172 | opt_w = TRUE;
|
---|
1173 | break;
|
---|
1174 | case '?':
|
---|
1175 | default:
|
---|
1176 | usage();
|
---|
1177 | }
|
---|
1178 | }
|
---|
1179 |
|
---|
1180 | _nc_progname = _nc_rootname(*argv);
|
---|
1181 | argc -= optind;
|
---|
1182 | argv += optind;
|
---|
1183 |
|
---|
1184 | if (argc > 1)
|
---|
1185 | usage();
|
---|
1186 |
|
---|
1187 | if (!opt_c && !opt_w)
|
---|
1188 | opt_c = opt_w = TRUE;
|
---|
1189 |
|
---|
1190 | if (GET_TTY(STDERR_FILENO, &mode) < 0)
|
---|
1191 | failed("standard error");
|
---|
1192 | can_restore = TRUE;
|
---|
1193 | original = oldmode = mode;
|
---|
1194 | #ifdef TERMIOS
|
---|
1195 | ospeed = cfgetospeed(&mode);
|
---|
1196 | #else
|
---|
1197 | ospeed = mode.sg_ospeed;
|
---|
1198 | #endif
|
---|
1199 |
|
---|
1200 | if (!strcmp(_nc_progname, PROG_RESET)) {
|
---|
1201 | isreset = TRUE;
|
---|
1202 | reset_mode();
|
---|
1203 | }
|
---|
1204 |
|
---|
1205 | ttype = get_termcap_entry(*argv);
|
---|
1206 |
|
---|
1207 | if (!noset) {
|
---|
1208 | tcolumns = columns;
|
---|
1209 | tlines = lines;
|
---|
1210 |
|
---|
1211 | #if defined(TIOCGWINSZ) && defined(TIOCSWINSZ)
|
---|
1212 | if (opt_w) {
|
---|
1213 | /* Set window size */
|
---|
1214 | (void) ioctl(STDERR_FILENO, TIOCGWINSZ, &win);
|
---|
1215 | if (win.ws_row == 0 && win.ws_col == 0 &&
|
---|
1216 | tlines > 0 && tcolumns > 0) {
|
---|
1217 | win.ws_row = tlines;
|
---|
1218 | win.ws_col = tcolumns;
|
---|
1219 | (void) ioctl(STDERR_FILENO, TIOCSWINSZ, &win);
|
---|
1220 | }
|
---|
1221 | }
|
---|
1222 | #endif
|
---|
1223 | if (opt_c) {
|
---|
1224 | set_control_chars();
|
---|
1225 | set_conversions();
|
---|
1226 |
|
---|
1227 | if (!noinit)
|
---|
1228 | set_init();
|
---|
1229 |
|
---|
1230 | /* Set the modes if they've changed. */
|
---|
1231 | if (memcmp(&mode, &oldmode, sizeof(mode))) {
|
---|
1232 | SET_TTY(STDERR_FILENO, &mode);
|
---|
1233 | }
|
---|
1234 | }
|
---|
1235 | }
|
---|
1236 |
|
---|
1237 | /* Get the terminal name from the entry. */
|
---|
1238 | ttype = _nc_first_name(cur_term->type.term_names);
|
---|
1239 |
|
---|
1240 | if (noset)
|
---|
1241 | (void) printf("%s\n", ttype);
|
---|
1242 | else {
|
---|
1243 | if (showterm)
|
---|
1244 | (void) fprintf(stderr, "Terminal type is %s.\n", ttype);
|
---|
1245 | /*
|
---|
1246 | * If erase, kill and interrupt characters could have been
|
---|
1247 | * modified and not -Q, display the changes.
|
---|
1248 | */
|
---|
1249 | #ifdef TERMIOS
|
---|
1250 | if (!quiet) {
|
---|
1251 | report("Erase", VERASE, CERASE);
|
---|
1252 | report("Kill", VKILL, CKILL);
|
---|
1253 | report("Interrupt", VINTR, CINTR);
|
---|
1254 | }
|
---|
1255 | #endif
|
---|
1256 | }
|
---|
1257 |
|
---|
1258 | if (Sflag)
|
---|
1259 | err("The -S option is not supported under terminfo.");
|
---|
1260 |
|
---|
1261 | if (sflag) {
|
---|
1262 | int len;
|
---|
1263 | /*
|
---|
1264 | * Figure out what shell we're using. A hack, we look for an
|
---|
1265 | * environmental variable SHELL ending in "csh".
|
---|
1266 | */
|
---|
1267 | if ((p = getenv("SHELL")) != 0
|
---|
1268 | && (len = strlen(p)) >= 3
|
---|
1269 | && !strcmp(p + len - 3, "csh"))
|
---|
1270 | p = "set noglob;\nsetenv TERM %s;\nunset noglob;\n";
|
---|
1271 | else
|
---|
1272 | p = "TERM=%s;\n";
|
---|
1273 | (void) printf(p, ttype);
|
---|
1274 | }
|
---|
1275 |
|
---|
1276 | return EXIT_SUCCESS;
|
---|
1277 | }
|
---|