/*+++* * title: tset.c * abstract: set terminal from termcap for UNIX V7. * author: T.R.Hageman, Groningen, The Netherlands. * created: december 1988 * modified: 21-Dec-88 [0.1e] fix XTABS bug. * 23-Dec-88 [0.1f] flush output before ioctl() * 05-Oct-89 [0.1g] always restore sane terminal modes. * 15-Jan-90 [0.1h] compress TERMCAP entry, rearranged stuff * for portability. * 08-Mar-90 [0.1j] support FASTCAP implementation. * 09-Mar-90 [1.0b] TERMIO support; "reset" alias. * 12-Mar-90 [1.0c] fixed bug in -m handling. * 25-Jun-92 [1.1a] support reverse FASTCAP; general cleanup. * 4-Sep-92 [1.1b] port to BSD systems. * description: * implementation of ``tset'' for UNIX 7th Edition, * with the following extensions: * o -s option also generates commands to set the environment * variable TERMCAP to the current termcap entry (unless TERMCAP * specifies an alternate termcap file). * o -S option generates TERM name as first parameter, and TERMCAP * entry as second and following parameters. * o -? option shows version number of this implementation. * the options -EC and -r are not implemented. *---*/ char * version = "v1.1b 4-Sep-92 TRH"; #include #include #include #include #ifdef __STDC__ #include #endif #include "_termcap.h" /* Internal definitions from termcap package */ #define TRUE 1 #define FALSE 0 const char *strtoi __(( const char *_(s), int *_(result) )); void WarnTerm __(( const char *_(message) )), PutCap __(( int _(quote) )); unsigned Baud __(( void )); /* variables for termcap */ char tcpbuf[TBUFSIZE]; char strbuf[512]; char *str_p = strbuf; const char *terminal; /* the name of the terminal */ const char *ttydev; const char *_pname; int quiet, ask, report, force_read; char kill_char, erase_char, intr_char, quit_char; enum { NO_COMMANDS, SHELL_COMMANDS, VALUE_ONLY, TERM_ONLY } set_shell; enum RelOp { NONE, LT, LE, EQ, GE, GT, NE }; /* these must be globally visible since termcap library needs them */ char PC; short ospeed; /* some terminal characteristics */ int Lines, Columns, TabStop; int HardTabs, AutoMargin; const char *CarrReturn = "\r", *Tab = "\t", *NewLine = "\n", *FormFeed = "\f", *MoveRight, *MoveNRight, *SetCurHor, *ClearAllTabs, *SetTabHere; int can_tab; void OpenTermcap(name) const char *name; { register int status; register char *s; switch (status = tgetent(tcpbuf, name)) { case NO_FILE: error("cannot open termcap database"); case NO_ENTRY: error("terminal \"%s\" not found in termcap", name); case SUCCESS: break; case TRUNCATED: error("incomplete termcap entry for \"%s\"", name); default: error("bad status (%d) from tgetent", status); } if ((Lines = tgetnum("li")) < 0) WarnTerm("missing \"li\"nes"); if ((Columns = tgetnum("co")) < 0) WarnTerm("missing \"co\"lumns"); if ((s = tgetstr("cr", &str_p)) && *s) CarrReturn = s; if ((s = tgetstr("ff", &str_p)) && *s) FormFeed = s; if ((s = tgetstr("sf", &str_p)) && *s) NewLine = s; if ((s = tgetstr("ta", &str_p)) && *s) { can_tab = TRUE; Tab = s; } TabStop = tgetnum("it"); ClearAllTabs = tgetstr("ct", &str_p); SetTabHere = tgetstr("st", &str_p); can_tab |= TabStop && ClearAllTabs && SetTabHere; MoveRight = tgetstr("nd", &str_p); MoveNRight = tgetstr("RI", &str_p); SetCurHor = tgetstr("ch", &str_p); AutoMargin = tgetflag("am"); if (s = tgetstr("pc", &str_p)) PC = *s; } /* get padding time in ms from capability string "cap" */ #define STAR 0x8000 /* ORed in with delay to flag '*' */ int tgetpad(cap) const char *cap; { register const char *s; int t; if ((s = cap) == NULL) return 0; #ifdef TERMINFO /* scan for "$" in capability */ do { if (*s == '\0') return 0; } while (!(*s++ == '$' && *s == '<')); ++s; #endif /* TERMINFO */ s = strtoi(s, &t); if (*s == '.' && (++s, isdigit(*s)) && *s++ >= '5') /* round fraction */ t++; if (*s == '*') t |= STAR; return t; } /* a "real" output routine */ int Putc(c) { return putc(c, stderr); } /* padded output */ void putp(s) const char *s; { tputs(s, 1, Putc); } void ExecProg(prog) const char *prog; { register int pid = fork(); int status; if (pid == 0) { execlp(prog, prog, NULL); error("cannot exec \"%s\"", prog); } else if (pid < 0) { puterr("fork for \"%s\" failed", prog); } else { while (pid != wait(&status)) ; } } /* ExecProg */ void PutFile(file) const char *file; { char buf[BUFSIZ]; register int n; register FILE *f; if ((f = fopen(file, "r")) == NULL) { puterr("cannot open \"%s\"", file); } else { while ((n = fread(buf, 1, sizeof buf, f)) > 0) fwrite(buf, 1, n, stderr); fclose(f); } } const char * basename(file) const char *file; { register const char *s; return (s = strrchr(file, '/')) ? ++s : file; } void InitTabs() { register int col = 0, i, tabstop; if ((tabstop = TabStop) == 0) return; else if (tabstop < 0) tabstop = 8; putp(CarrReturn); /* to first column */ if (!SetTabHere) { WarnTerm("cannot set tabs"); } else if (!ClearAllTabs) { WarnTerm("cannot clear tabs"); } else { putp(ClearAllTabs); if (MoveNRight) { char * ToNext = tgoto(MoveNRight, 0, tabstop); while ((col += tabstop) < Columns) { putp(ToNext); putp(SetTabHere); } } else if (SetCurHor) { while ((col += tabstop) < Columns) { putp(tgoto(SetCurHor, 0, col)); putp(SetTabHere); } } else if (MoveRight) { while ((col += tabstop) && col < Columns) { for (i = tabstop; --i >= 0; ) putp(MoveRight); putp(SetTabHere); } } else { while ((col += tabstop) && col < Columns) { for (i = tabstop; --i >= 0; ) putchar(' '); putp(SetTabHere); } } putp(CarrReturn); } } /*++* * title: IniTerminal * abstract: Initialize terminal according to terminfo(4) scheme * description: * (equivalent terminfo codes are given bracketed by < >.) * check if lines and columns are defined; * get pad character; * * do the following, in the given order: * - send "i1" , if present * - send "is" (the "old" termcap init string) if present * - if terminal has no hardware tabs, try to initialize tabstops * to every 8th position * - if "if" is present, send contents of initialization file * - if "ip" is present, execute initialization program * - send "i2" if present. * * all output is sent to stderr. * * the "old" termcap initialization would comprise: * "is", set tabs, "if". * notes: * this routine assumes that the variable "ospeed" is already initialized * to the terminal's output speed (since it calls putp for padded output). * return value: * none *---*/ void IniTerminal() { register const char *s; if (s = tgetstr("i1", &str_p)) putp(s); if (s = tgetstr("is", &str_p)) putp(s); if (TabStop) InitTabs(); if (s = tgetstr("if", &str_p)) PutFile(s); if (s = tgetstr("iP", &str_p)) ExecProg(s); if (s = tgetstr("i2", &str_p)) putp(s); } /*++* * title: ResetTerminal * abstract: Reset terminal according to terminfo(4) scheme * description: * (equivalent terminfo codes are given bracketed by < >.) * * do the following, in the given order: * - send "r1" , if present * - send "rs" (the "old" termcap init string) if present, * else send "r2" if present * - since we're at it, we could just as well set tab stops. * - if "rf" is present, send contents of reset file * - send "r3" if present. * * all output is sent to stderr. * * the "old" termcap reset would comprise: * "rs", "rf". * notes: * this routine assumes that the variable "ospeed" is already initialized * to the terminal's output speed (since it calls putp for padded output). * return value: * none *---*/ void ResetTerminal() { register const char *s; if (s = tgetstr("r1", &str_p)) putp(s); if ((s = tgetstr("rs", &str_p)) || (s = tgetstr("r2", &str_p))) putp(s); if (TabStop) InitTabs(); if (s = tgetstr("rf", &str_p)) PutFile(s); if (s = tgetstr("r3", &str_p)) putp(s); } #define SANE(var,def) if (var <= 0 || var >= 0200 || isprint(var)) var = def; /*------START SYSTEM-DEPENDENT TTY STUFF------*/ #ifndef TERMIO # include #else # include #endif #ifndef CKILL # define CKILL '\030' #endif #ifndef CERASE # define CERASE '\010' #endif #ifndef CINTR # define CINTR '\177' /* "sane" tchars */ #endif #ifndef CQUIT # define CQUIT '\034' #endif #ifndef CEOF # define CEOF '\004' #endif #ifndef TERMIO struct sgttyb sg; void ttyInit() { char *ttyname(); if (!isatty(fileno(stderr))) error("not a tty"); ttydev = basename(ttyname(fileno(stderr))); ioctl(fileno(stderr), TIOCGETP, &sg); ospeed = sg.sg_ospeed; } void ttyRaw() { fflush(stderr); sg.sg_flags &= ~(XTABS|CRMOD|ECHO); ioctl(fileno(stderr), TIOCSETN, &sg); } void ttyCooked() { struct tchars tc; fflush(stderr); sg.sg_flags |= ECHO|CRMOD; /* reset terminal to sane modes */ sg.sg_flags &= ~(RAW|CBREAK); ioctl(fileno(stderr), TIOCSETN, &sg); ioctl(fileno(stderr), TIOCGETC, &tc); /* reset tchars to sane values */ SANE(tc.t_intrc, CINTR); SANE(tc.t_quitc, CQUIT); SANE(tc.t_startc, XON); SANE(tc.t_stopc, XOFF); SANE(tc.t_eofc, CEOF); tc.t_brkc = -1; if (intr_char) tc.t_intrc = intr_char; if (quit_char) tc.t_quitc = quit_char; ioctl(fileno(stderr), TIOCSETC, &tc); } SetDelays() { register int delay; if (can_tab) sg.sg_flags &= ~XTABS; else sg.sg_flags |= XTABS; #ifdef ALLDELAY /* assume delays are encoded in sg_flags. */ sg.sg_flags &= ~ALLDELAY; if (!((delay = tgetnum("pb")) >= 0 && Baud() >= delay)) { # ifdef CR1 if (delay = tgetpad(CarrReturn)) sg.sg_flags |= (delay & STAR) ? CR1 : (delay < 120) ? CR2 : CR3; # endif # ifdef NL1 if (delay = tgetpad(NewLine)) sg.sg_flags |= NL1; # endif if (delay = tgetpad(FormFeed)) sg.sg_flags |= VTDELAY; # ifdef TAB1 if (delay = tgetpad(Tab)) sg.c_oflag |= (delay & STAR) ? TAB1 : TAB2; # endif if (delay = tgetpad(tgetstr("le", &str_p))) sg.c_oflag |= BSDELAY; } #else /* assume delay fields in sgtty struct. */ if ((delay = tgetnum("pb")) >= 0 && Baud() >= delay) { sg.sg_crdly = sg.sg_nldly = sg.sg_vtdly = sg.sg_htdly = 0; } else { if (delay = tgetpad(CarrReturn)) sg.sg_crdly = delay & ~STAR; if (delay = tgetpad(NewLine)) sg.sg_nldly = delay & ~STAR; if (delay = tgetpad(FormFeed)) sg.sg_vtdly = delay & ~STAR; if (delay = tgetpad(Tab)) sg.sg_htdly = delay & ~STAR; } #endif } void SetKillErase() { if (!kill_char) kill_char = (sg.sg_kill && sg.sg_kill != (char)-1 && !isprint(sg.sg_kill)) ? sg.sg_kill : CKILL; if (!erase_char) erase_char = (sg.sg_erase && sg.sg_erase != (char)-1 && !isprint(sg.sg_erase)) ? sg.sg_erase : CERASE; if (kill_char != sg.sg_kill || erase_char != sg.sg_erase) { sg.sg_kill = kill_char; sg.sg_erase = erase_char; } } #else /* TERMIO */ struct termio sg; void ttyInit() { char *ttyname(); if (!isatty(fileno(stderr))) error("not a tty"); ttydev = basename(ttyname(fileno(stderr))); ioctl(fileno(stderr), TCGETA, &sg); ospeed = sg.c_cflag & CBAUD; } void ttyRaw() { fflush(stderr); sg.c_lflag &= ~(ISIG|ICANON|ECHO); sg.c_oflag &= ~(OPOST); /* disabled during init. sequence */ ioctl(fileno(stderr), TCSETA, &sg); } void ttyCooked() { fflush(stderr); sg.c_lflag |= ISIG|ICANON|ECHO; /* reset terminal to sane modes */ sg.c_oflag |= OPOST; SANE(sg.c_cc[VINTR], CINTR); /* 'sane' tchars mode */ SANE(sg.c_cc[VQUIT], CQUIT); SANE(sg.c_cc[VEOF], CEOF); if (intr_char) sg.c_cc[VINTR] = intr_char; if (quit_char) sg.c_cc[VQUIT] = quit_char; ioctl(fileno(stderr), TCSETAW, &sg); } SetDelays() { register int delay; register int pad_baud; sg.c_oflag &= ~(OFDEL|NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY); if (PC == '\177') sg.c_oflag |= OFDEL; if ((pad_baud = tgetnum("pb")) < 0 || Baud() < pad_baud) { if (delay = tgetpad(CarrReturn)) sg.c_oflag = (delay & STAR) ? CR1 : (delay < 120) ? CR2 : CR3; if (delay = tgetpad(NewLine)) sg.c_oflag |= NL1; if (delay = tgetpad(FormFeed)) sg.c_oflag |= VT1|FF1; if (delay = tgetpad(Tab)) sg.c_oflag |= (delay & STAR) ? TAB1 : TAB2; if (delay = tgetpad(tgetstr("le", &str_p))) sg.c_oflag |= BS1; } if (!can_tab) sg.c_oflag |= TAB3; /* EXTENSION: set 8-bits mode if terminal has meta-key */ if (tgetflag("km")) { sg.c_cflag |= CS8; sg.c_cflag &= ~(PARENB); sg.c_iflag &= ~(ISTRIP|INPCK); } } void SetKillErase() { if (!kill_char) kill_char = (sg.c_cc[VKILL] && sg.c_cc[VKILL] != (char)-1 && !isprint(sg.c_cc[VKILL])) ? sg.c_cc[VKILL] : CKILL; if (!erase_char) erase_char = (sg.c_cc[VERASE] && sg.c_cc[VERASE] != (char)-1 && !isprint(sg.c_cc[VERASE]) ? sg.c_cc[VERASE] : CERASE; if (kill_char != sg.c_cc[VKILL] || erase_char != sg.c_cc[VERASE]) { sg.c_cc[VKILL] = kill_char; sg.c_cc[VERASE] = erase_char; } } #endif /* TERMIO */ unsigned Baud() { #if (B9600 == 96 && B2400 == 24) /* Minix 1.5 coding: ospeed = baud/100 */ return ospeed * 100; #else static unsigned speeds[] = { # ifdef B0 0, # endif # ifdef B50 50, # endif # ifdef B75 75, # endif # ifdef B110 110, # endif # ifdef B134 134, # endif # ifdef B150 150, # endif # ifdef B200 200, # endif # ifdef B300 300, # endif # ifdef B600 600, # endif # ifdef B900 900, # endif # ifdef B1200 1200, # endif # ifdef B1800 1800, # endif # ifdef B2400 2400, # endif # ifdef B3600 3600, # endif # ifdef B4800 4800, # endif # ifdef B7200 7200, # endif # ifdef B9600 9600, # endif # ifdef B19200 19200, # endif # ifdef B38400 38400, # endif 0, 0, 0, 0 }; #endif return speeds[ospeed]; } /*------END SYSTEM-DEPENDENT TTY STUFF------*/ /* some utility routines */ const char * strtoi(s, result) register const char *s; int * result; { register int t = 0; while (isdigit(*s)) t = t * 10 + *s++ - '0'; *result = t; return s; } void usage(message, where) const char *message, *where; { static const char *options[] = { " options:\n\ - report terminal type\n\ -e[C] set erase char (default ^H)\n\ -k[C] set kill char (default ^U)\n\ -i[C] set interrupt char (default DEL)\n\ -q[C] set quit char (default ^\\)\n", #ifdef BSD " -h force read of /etc/ttys for type\n\ -n set new tty driver crt modes\n", #else " -h force read of /etc/ttytype for type\n", #endif #ifdef TERMINFO " -s generate shell commands to set TERM\n", #else " -s generate shell commands to set TERM/TERMCAP\n", #endif " -A ask TERM type from user\n\ -I suppress terminal initialization\n\ -Q quiet\n", #ifdef TERMINFO " -S output values assigned to TERM\n", #else " -S output values assigned to TERM/TERMCAP\n\ -T suppress output of TERMCAP\n", #endif " -m[[port][test baudrate]:[?]type] map port to TERM type\n", }; const char **p; fprintf(stderr, "%s: %s\n", message, where); fprintf(stderr, "Usage: %s [options] [[?]type]\n", _pname); for (p = options; p < &options[sizeof(options)/sizeof(options[0])]; ) fputs(*p++, stderr); exit(2); } void WarnTerm(message) const char *message; { if (!quiet) fprintf(stderr, "%s: %s (TERM %s)\n", _pname, message, terminal); } const char * GetTtyType() { static char Separators[] = " \t\n"; static char linebuf[128]; static const char *ttytype; register FILE *f; register const char *name, *dev; if (!ttytype) { /* this is the first time */ #ifndef BSD if (f = fopen("/etc/ttytype", "r")) { while (fgets(linebuf, sizeof linebuf, f)) { if ((name = strtok(linebuf, Separators)) && (dev = strtok(NULL, Separators)) && strcmp(ttydev, dev) == 0) { ttytype = name; break; } } fclose(f); } #else /* BSD systems seem to have their terminal database in /etc/ttys */ if (f = fopen("/etc/ttys", "r")) { /* port getty terminaltype. */ while (fgets(linebuf, sizeof linebuf, f)) { if ((dev = strtok(linebuf, Separators)) && (strtok(NULL, Separators)) && (name = strtok(NULL, Separators)) && strcmp(ttydev, dev) == 0) { ttytype = name; break; } } fclose(f); } #endif if (!ttytype) ttytype = ""; } return ttytype; } int RelCmp(op1, operator, op2) unsigned op1, op2; enum RelOp operator; { switch(operator) { case NONE: return TRUE; case LT: return (op1 < op2); case LE: return (op1 <= op2); case EQ: return (op1 == op2); case NE: return (op1 != op2); case GE: return (op1 >= op2); case GT: return (op1 > op2); default: error("RelOp: unknown operator"); } } void map(arg) char *arg; { register char *s; register char c; int baudrate; enum RelOp test = NONE; for (s = arg; *s && !strchr(":<=>!@", *s); s++) ; if (!(c = *s)) usage("bad -m argument", arg); *s++ = '\0'; /* terminate ident */ if (c != ':') { switch (c) { case '<': if (*s == '=' || *s == '@') { s++; test = LE; } else { test = LT; } break; case '>': if (*s == '=' || *s == '@') { s++; test = GE; } else { test = GT; } break; case '=': case '@': switch (*s++) { case '!': test = NE; break; case '<': test = LE; break; case '>': test = GE; break; default: test = EQ; --s; } break; case '!': if (*s == '=' || *s == '@') s++; test = NE; break; } if (isdigit(*s)) s = strtoi(s, &baudrate); if (*s++ != ':') usage("bad baud rate in -m", s-1); } if ((!*arg || strcmp(arg, GetTtyType()) == 0) && (test == NONE || RelCmp(Baud(), test, baudrate))) terminal = s; } int GetChar(str) const char *str; { register const char *s = str; register int c = *s++; if (c == '^' && (c = *s++)) c = tocntrl(c); if (*s) usage("use single character or ^X", str); return c; } const char * Chr(c) { static char template[] = "Ctrl-@"; #define AT template[sizeof template - 2] if (!isprint(c)) if (c == '?') return "Delete"; else return (AT = c + '@'), template; else return (AT = c), &AT; #undef AT } void ShellCmds(put_termcap) int put_termcap; { const char *shell = getenv("SHELL"); #ifndef TERMINFO const char *termcap = getenv("TERMCAP"); put_termcap &= (!termcap || *termcap != '/'); #endif if (shell && strcmp(&shell[strlen(shell)-3], "csh") == 0) { printf("set noglob; setenv TERM %s;\n", terminal); #ifndef TERMINFO if (put_termcap) { printf("setenv TERMCAP "); PutCap(TRUE); } #endif printf(";unset noglob\n"); } else { /* assume Bourne shell */ printf("TERM='%s' export TERM;\n", terminal); #ifndef TERMINFO if (put_termcap) { printf("TERMCAP="); PutCap(TRUE); printf(" export TERMCAP\n"); } #endif } } #ifndef TERMINFO void PutCap(quote) { #if FASTCAP /* * While building its lookup table FASTCAP has already removed duplicate * capabilities (and de-escaped its value strings). So all we have to do * now is walk through the table and spit it out, re-escaped. */ register const char *s; register int c; register t_entry *tp; if (quote) putchar('\''); /* start quote for shell */ for (s = (quote) ? terminal : tcpbuf; *s; ) /* output name first */ putchar(*s++); putchar(':'); for (tp = &_tcptable.t_body[_tcptable.t_size]; --tp >= _tcptable.t_body; ) { s = _TCP_VAL(tp); if (*s == '@') continue; /* invalidated */ c = (unsigned) tp->t_cap >> 8; /* first char of cap. name */ if (!isgraph(c) || c == '.') continue; /* junk, or commented out */ putchar(c); /* output cap. name */ putchar((char)tp->t_cap); while (c = UC(*s++)) { /* re-escape... */ switch (c) { case '\'': if (quote) { printf("'\\''"); /* oh those shell quotes! */ continue; } default: if (c >= 0177) { printf("\\%03o", c); continue; } if (c < ' ') { putchar('^'); c += '@'; } putchar(c); continue; case '\33': c = 'E'; break; case '\r': c = 'r'; break; case '\n': c = 'n'; break; case '\t': c = 't'; break; case '\b': c = 'b'; break; case '\f': c = 'f'; break; case '\\': break; case ':': break; case '^': break; case ' ': break; } putchar('\\'); putchar(c); } putchar(':'); } putchar('\''); putchar('\n'); #else /* ! FASTCAP */ char names[2*300]; /* should be enough */ register char *s = tcpbuf, *d = s, *p, *top = names; /* Compact termcap entry. First replace verbose name with actual terminal, then remove duplicate and commented-out capabilities. We can actually do it in-place since we only delete capabilities. */ while (*s && *s++ != ':') ; /* skip verbose name */ for (p = terminal; *d++ = *p++; ) ; d[-1] = *--s; /* the first ':' */ while (*s++ == ':') { if (isgraph(*s) && *s != '.') { for (p = names; p < top; p += 2) if (p[0] == s[0] && p[1] == s[1]) /* duplicate */ break; if (p == top) { if (p < &names[sizeof names]) { *p++ = s[0], *p++ = s[1], top = p; } if (s[2] != '@') { /* copy capability */ while ((*d++ = *s) && *s != ':') if (*s++ == '\\' && !(*d++ = *s++)) break; continue; } } } while (*s && *s != ':') /* ignore capability */ if (*s++ == '\\' && !*s++) break; } /* now, output the string with proper shell quotes */ putchar('\''); for (s = tcpbuf; s < d; putchar(*s++)) { if (*s == '\'') putchar(*s), putchar('\\'), putchar(*s); } putchar('\''); putchar('\n'); #endif /* ! FASTCAP */ } #endif /* ! TERMINFO */ const char * Query(prompt, dflt) const char *prompt, *dflt; { static char buf[80]; const char *s; fprintf(stderr, "%s ", prompt); if (dflt && *dflt) fprintf(stderr, "(%s) ", dflt); fflush(stderr); if (gets(buf) == NULL) return NULL; if ((s = strtok(buf, " \t")) == NULL) return dflt; return s; } void main(argc, argv) int argc; char *argv[]; { char ttybuf[BUFSIZ]; int no_termcap = FALSE, no_init = FALSE, reset = FALSE; const char *arg; _pname = *argv++; if (tolower(*basename(_pname)) == 'r') /* who am I? reset or tset */ reset++; setbuf(stderr, ttybuf); ttyInit(); while ((arg = *argv++) && *arg == '-') { report = FALSE; switch (*++arg) { case 'e': /* get erase character */ if (!(erase_char = GetChar(++arg))) erase_char = BS; break; case 'k': if (!(kill_char = GetChar(++arg))) kill_char = CTL'U'; break; case 'i': if (!(intr_char = GetChar(++arg))) intr_char = CINTR; break; case 'q': if (!(quit_char = GetChar(++arg))) quit_char = CQUIT; break; case '\0': report++; if (set_shell == NO_COMMANDS) set_shell = TERM_ONLY; break; case 's': set_shell = SHELL_COMMANDS; break; case 'I': no_init++; break; case 'Q': quiet++; break; case 'A': ask++; break; case 'S': set_shell = VALUE_ONLY; break; case 'T': no_termcap++; break; case 'h': force_read++; break; case 'm': if (*++arg == '\0') if ((arg = *argv++) == NULL) usage("missing argument", "-m"); if (!terminal) map(arg); break; case '?': usage(_pname, version); break; default: usage("bad option", arg); } } /* * get default terminal name if not yet determined */ if (!terminal || !*terminal) { terminal = arg; /* explicit argument */ if (!terminal || !*terminal) { if (!force_read) { terminal = getenv("TERM"); /* current TERM setting */ if (report) no_init++; } if (!terminal || !*terminal) { terminal = GetTtyType(); /* from /etc/ttytype */ } } } if (ask || (terminal && *terminal == '?' && (++terminal /* skip "?" */, 1))) terminal = Query("TERM =", terminal); if (!terminal || !*terminal) terminal = "unknown"; if (reset) { quiet++; set_shell = NO_COMMANDS; } OpenTermcap(terminal); /* so we don't get disturbed... */ signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); if (no_init) { quiet++; } else { ttyRaw(); if (reset) ResetTerminal(); else IniTerminal(); } switch (set_shell) { case NO_COMMANDS: break; case TERM_ONLY: puts(terminal); break; case VALUE_ONLY: puts(terminal); #ifndef TERMINFO PutCap(FALSE); #endif break; case SHELL_COMMANDS: ShellCmds(!no_termcap); break; } SetKillErase(); SetDelays(); ttyCooked(); if (!quiet) { fprintf(stderr, "Kill is %s\n", Chr(kill_char)); fprintf(stderr, "Erase is %s\n", Chr(erase_char)); } exit(0); } /* main tset */