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