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