home *** CD-ROM | disk | FTP | other *** search
- #ifndef lint
- static char *RCSid = "$Header: qterm.c,v 3.0 87/06/30 19:07:59 mcooper Release $";
- #endif
-
- /*
- *------------------------------------------------------------------
- *
- * $Source: /big/src/usc/bin/qterm/RCS/qterm.c,v $
- * $Revision: 3.0 $
- * $Date: 87/06/30 19:07:59 $
- * $State: Release $
- * $Author: mcooper $
- * $Locker: $
- *
- *------------------------------------------------------------------
- *
- * Michael A. Cooper
- * Research and Development Group
- * University Computing Services
- * University of Southern California
- * (mcooper@oberon.USC.EDU)
- *
- *------------------------------------------------------------------
- *
- * $Log: qterm.c,v $
- * Revision 3.0 87/06/30 19:07:59 mcooper
- * Release of version 3.
- *
- * Revision 2.4 87/04/29 19:28:35 mcooper
- * In readtabfile() we now do special
- * things when opening "file" fails
- * depending on the bequiet flag.
- *
- * Revision 2.3 87/04/29 13:11:37 mcooper
- * - No more "internal" table. The master
- * table is read from a file (TABFILE).
- * This makes ~/.qterm stuff much cleaner.
- * - Error handling for qtermtab files is
- * much more informative now.
- * - More things I can't remember.
- *
- * Revision 2.2 87/03/05 21:01:28 mcooper
- * Fixed system V compiler problem.
- *
- * Revision 2.1 87/03/01 19:43:22 mcooper
- * Be more intelligent about the size of
- * the default terminal table.
- *
- * Revision 2.0 87/03/01 19:20:00 mcooper
- * General cleanup.
- *
- *------------------------------------------------------------------
- */
-
-
- /*
- * qterm - Query Terminal
- *
- * qterm is used to query a terminal to determine the name of the terminal.
- * This is done by sending a fairly universal string "\33Z" to the terminal,
- * reading in a response, and comparing it against a master table of responses
- * and names. The "name" printed to standard output should be one found in
- * the termcap(5) database.
- *
- * Putting a line in your ".login" file such as:
- *
- * setenv TERM `qterm`
- *
- * or the following lines in your ".profile" file:
- *
- * TERM=`qterm`
- * export TERM
- *
- * will set your terminal type automagically.
- *
- * If you add a terminal to the master table, please also send me a copy
- * so that I may put it into my version.
- *
- * Michael Cooper
- * ARPA: mcooper@oberon.USC.EDU
- * UUCP: {sdcrdcf, cit-vax}!oberon!mcooper
- * BITNET: mcooper@uscvaxq
- */
-
- #include <stdio.h>
- #include <pwd.h>
- #include <signal.h>
- #include <sys/ioctl.h>
- #include <setjmp.h>
- #ifdef USG5
- # include <termio.h>
- #else
- # include <sys/file.h>
- # include <sgtty.h>
- #endif
-
- #include "qterm.h"
-
- int tabtotal = 0;
- int has_set = 0;
-
- struct qt *compare();
- struct qt termtab[MAXTERMS];
-
- #ifdef USG5
- struct termio _ntty, _otty;
- #else
- struct sgttyb _tty;
- #endif
- int _tty_ch = 2;
-
-
- static char recvbuf[SIZE];
- static char *progname;
-
- int debug = FALSE; /* debug mode */
- int aflag = FALSE; /* alternate string */
- int sflag = FALSE; /* print strings */
- int qflag = FALSE; /* quiet mode */
- int fflag = FALSE; /* use user's own .qterm file */
- int Fflag = FALSE; /* same as above, but don't add our own table */
-
- int found = FALSE;
- int index = 0;
- int finish(), wakeup(), done();
-
- char *decode();
-
- jmp_buf env;
-
- main(argc, argv)
- char *argv[];
- {
- register int x;
-
- progname = argv[0];
-
- for (x = 1; x < argc; x++) {
- if (argv[x][0] != '-')
- break;
- switch (argv[x][1]) {
- case 'a':
- aflag = TRUE;
- break;
- case 't':
- case 's':
- sflag = TRUE;
- break;
- case 'q':
- qflag = TRUE;
- break;
- case 'f':
- fflag = TRUE;
- break;
- case 'F':
- Fflag = TRUE;
- break;
- case 'd':
- debug = TRUE;
- break;
- default:
- usage();
- exit(1);
- }
- }
-
- setbuf(stdout, 0);
- if(debug)
- setbuf(stderr, 0);
-
- dprintf("[ %s debug mode enabled ]\n\n", progname);
-
- if(!isatty(0))
- fprintf(stderr,"Not a tty.\n");
-
- #ifdef USG5
- if(ioctl(_tty_ch, TCGETA, &_otty) < 0)
- #else
- if(ioctl(_tty_ch, TIOCGETP, &_tty) < 0)
- #endif
- {
- perror("gtty");
- exit(1);
- }
- #ifdef USG5
- _ntty = _otty;
- #endif
- if(crmode() < 0) {
- perror("crmode");
- exit(1);
- }
- if(noecho() < 0) {
- perror("noecho");
- exit(1);
- }
-
- mktable();
-
- index = 0;
- dprintf("main: we'll do a dotab()\n");
- dotab();
- dprintf("main: dotab done\n");
-
- putc('\r', stderr);
- (void) nocrmode();
- (void) echo();
-
- if(!found) {
- dprintf("end of main\n");
- notrecognized();
- }
- }
-
- usage()
- {
- fprintf(stderr, "usage: %s [ -a ] [ -s ] [ -q ] [ -f ] [ -F ]\n",
- progname);
- }
-
- done(s)
- int s;
- {
- putc('\r', stderr);
- (void) nocrmode();
- (void) echo();
- exit(s);
- }
-
- /*
- * finish - clean things up.
- */
- finish()
- {
- dprintf("finish called\n");
-
- putc('\r', stderr);
- (void) nocrmode();
- (void) echo();
-
- if(recvbuf[0] != NULL)
- (void) prinfo(compare(recvbuf, 0, tabtotal), 1);
-
- dprintf("finish done\n");
- if(!found)
- notrecognized();
-
- exit(0);
- }
-
- prinfo(t, what)
- struct qt *t;
- int what;
- {
- int len = 0;
- int st = FALSE;
-
- dprintf("prinfo startup\n");
-
- if((t != NULL) && (t->qt_termname[0] != NULL) && (recvbuf[0] != NULL)) {
- if(debug || sflag) {
- len = strlen(recvbuf);
- fprintf(stderr, "%s receives %d character%s:",
- progname, len, (len == 1) ? "" : "s");
- fprintf(stderr, " %s\n", decode(recvbuf));
- }
- if(!qflag)
- if(t->qt_fullname[0] != NULL)
- fprintf(stderr, "Terminal recognized as %s (%s)\n",
- t->qt_termname, t->qt_fullname);
- else
- fprintf(stderr, "Terminal recognized as %s\n",
- t->qt_termname);
- printf("%s\n", t->qt_termname);
- found = TRUE;
- done(0);
- /*NOTREACHED*/
- } else {
- found = FALSE;
- if(what) {
- dprintf("prinfo(): doing notrecognized()\n");
- notrecognized();
- done(1);
- /*NOTREACHED*/
- }
- }
-
- dprintf("prinfo done\n");
-
- return(st);
- }
-
- /*
- * compare - actually compare what we received against the table.
- */
- struct qt *
- compare(str, start, stop)
- char *str;
- int start;
- int stop;
- {
- register int i = 0;
-
- dprintf("compare(%s, %d, %d) startup.\n", decode(str), start, stop);
- alarm(0);
-
- i = start;
- while(i <= stop) {
- dprintf("compare(): tr = '%s'\n", decode(termtab[i].qt_recvstr));
- if(strncmp(str, termtab[i].qt_recvstr,
- strlen(termtab[i].qt_recvstr)) == 0) {
- found = TRUE;
- return(&termtab[i]);
- }
- ++i;
- }
- found = FALSE;
-
- return(NULL);
- }
-
- /*
- * getch - read in a character at a time.
- */
- getch()
- {
- char c;
-
- (void) read(0, &c, 1);
- return(c & CMASK);
- }
-
- /*
- * decode - print str in a readable fashion
- */
- char *
- decode(str)
- char *str;
- {
- char buf[BUFSIZ];
- char tmp[10];
-
- strcpy(buf, "");
- while(*str) {
- if (*str == ESC) {
- strcat(buf, "<esc> ");
- } else if((*str <= 33) || (*str >= 127)) {
- sprintf(tmp,"\\%o ", *str);
- strcat(buf, tmp);
- } else {
- sprintf(tmp,"%c ", *str);
- strcat(buf, tmp);
- }
- *++str;
- }
- return(buf);
- }
-
- mktable()
- {
- char file[BUFSIZ];
- struct passwd *pwd;
- char *home;
-
- dprintf("[ initilizing term table... ]\n");
-
- if(fflag) {
- /*
- * Try and read the user's own table
- */
- if((home = (char *) getenv("HOME")) == NULL) {
- if((pwd = (struct passwd *) getpwuid(getuid())) == NULL) {
- fprintf(stderr, "Who the hell are you????\n");
- exit(1);
- }
- home = pwd->pw_dir;
- }
- dprintf("home = '%s'\n", home);
- sprintf(file, "%s/%s", home, STRFILE);
- dprintf("strfile = '%s'\n", file);
-
- (void) readtabfile(file, TRUE);
- }
-
- if(!Fflag)
- (void) readtabfile(TABFILE, FALSE);
-
- dprintf("termtab total = %d\n", tabtotal);
- dprintf("[ mktable done ]\n");
- }
-
- readtabfile(file, bequiet)
- char *file;
- int bequiet;
- {
- static int i = 0, line;
- char lbuf[4][BUFSIZ];
- char buf[BUFSIZ];
- FILE *fd, *fopen();
- char *msg, *fixctl();
- int iserr = 0;
-
- if((fd = fopen(file, "r")) == NULL) {
- if(bequiet)
- return(-1);
- perror(file);
- done(1);
- }
-
- line = 0;
- while(fgets(buf, sizeof(buf), fd) && i < MAXTERMS) {
- ++line;
-
- if(buf[0] == '#' || buf[0] == '\n')
- continue;
-
- lbuf[0][0] = NULL;
- lbuf[1][0] = NULL;
- lbuf[2][0] = NULL;
- lbuf[3][0] = NULL;
-
- (void) sscanf(buf, "%s%s%s\t%[^\n]",
- lbuf[0], lbuf[1], lbuf[2], lbuf[3]);
- if(lbuf[0][0] == NULL)
- continue;
- if(lbuf[1][0] == NULL) {
- iserr = TRUE;
- msg = "receive string";
- }
- if(lbuf[2][0] == NULL) {
- iserr = TRUE;
- msg = "terminal name";
- }
- if(iserr) {
- fprintf(stderr, "Line %d of %s: Error parsing %s.\n",
- line, file, msg);
- done(1);
- /* NOTREACHED */
- }
- if(aflag)
- (void) strcpy(termtab[i].qt_sendstr, fixctl(ALTSEND));
- else
- (void) strcpy(termtab[i].qt_sendstr, fixctl(lbuf[0]));
- (void) strcpy(termtab[i].qt_recvstr, fixctl(lbuf[1]));
- (void) strcpy(termtab[i].qt_termname, lbuf[2]);
- (void) strcpy(termtab[i].qt_fullname, lbuf[3]);
-
- dprintf("entry %d:\n", i);
- dprintf("qt_sendstr = %s\n", decode(termtab[i].qt_sendstr));
- dprintf("qt_recvstr = %s\n", decode(termtab[i].qt_recvstr));
- dprintf("qt_termname = '%s'\n", termtab[i].qt_termname);
- dprintf("qt_fullname = '%s'\n", termtab[i].qt_fullname);
-
- ++i;
- }
-
- tabtotal = i;
-
- return(0);
- }
-
- listen(q)
- struct qt *q;
- {
- register int i;
- register char c;
- char end, begin;
-
- dprintf("listen startup\n");
- alarm(0);
-
- dprintf("listen: listening for '%s'\n", decode(q->qt_recvstr));
-
- if (q->qt_recvstr[0] == NULL) {
- begin = ESC;
- end = 'c';
- } else {
- begin = q->qt_recvstr[0];
- end = q->qt_recvstr[strlen(q->qt_recvstr)-1];
- }
-
- dprintf("listen: read initial character...\n");
- if(setjmp(env)) {
- dprintf("listen: setjmp TRUE\n");
- if(found)
- done();
- ++index;
- (void) fflush(stdin);
- dprintf("listen: dotab()\n");
- dotab();
- } else {
- dprintf("listen: setjmp FALSE...set alarm\n");
- signal(SIGALRM, wakeup);
- alarm(WAIT);
- dprintf("listen: read char\n");
- recvbuf[0] = getch();
- alarm(0);
- dprintf("recvbuf[0] = '\\%o'\n", recvbuf[0]);
-
- }
- i = 0;
- if(recvbuf[0] == begin) {
- dprintf("listen begin\n");
- while(c != end) {
- if(setjmp(env)) {
- dprintf("listen: setjmp (2) return\n");
- return;
- } else {
- signal(SIGALRM, wakeup);
- alarm(WAIT);
- dprintf("listen: read (2) char\n");
- c = getch();
- alarm(0);
- dprintf("recvbuf[0] = '\\%o'\n", recvbuf[0]);
- }
- recvbuf[++i] = c;
- }
- if(debug)
- fprintf(stderr,"\n[ Received terminator. ]\n");
- } else {
- dprintf("listen: Not Recognized. exiting...\n");
- notrecognized();
- putc('\r',stderr);
- (void) nocrmode();
- (void) echo();
- exit(1);
- }
- dprintf("listen done\n");
- }
-
- notrecognized()
- {
- if(!qflag)
- fprintf(stderr,
- "Terminal NOT recognized - defaults to \"dumb\".\n");
- puts("dumb");
- }
-
- wakeup()
- {
- dprintf("wakeup called\n");
- longjmp(env, 1);
- dprintf("wakeUP: done\n");
- }
-
- dotab()
- {
- int wakeup();
- int st = FALSE;
- static int firsttime = TRUE;
-
- dprintf("dotab startup\n");
- dprintf("index = %d\n", index);
-
- if(index > tabtotal) {
- /*
- * if we haven't reset things yet, do so.
- * now try the internal tables if the user's
- * tables failed.
- */
- if(!has_set) {
- index = 0;
- has_set = 1;
- dprintf("dotab(): has_set now true.\n");
- dotab();
- }
- dprintf("dotab(): index > tabtotal\n");
- finish();
- }
- if(!found || fflag) {
- while(!found && termtab[index].qt_sendstr[0] != NULL && !st) {
- dprintf("dotab: termtab PASS %d\n", index);
- dprintf("dotab: sending str %s\n",
- decode(termtab[index].qt_sendstr));
- (void) fflush(stdin);
-
- if(firsttime || strncmp(termtab[index].qt_sendstr,
- termtab[index-1].qt_sendstr,
- strlen(termtab[index].qt_sendstr))) {
-
- firsttime = FALSE;
- dprintf("dotab(): sendstr's didn't match.\n");
- dprintf("dotab: str1 %s\n", decode(termtab[index].qt_sendstr));
- dprintf("dotab: str2 %s\n", decode(termtab[index-1].qt_sendstr));
-
- fprintf(stderr, termtab[index].qt_sendstr);
- (void) fflush(stdout);
- (void) fflush(stderr);
-
- (void) listen(&termtab[index]);
- } else {
- dprintf("dotab(): sendstr's DID match. No str sent.\n");
- dprintf("dotab: str1 %s\n", decode(termtab[index].qt_sendstr));
- dprintf("dotab: str2 %s\n", decode(termtab[index-1].qt_sendstr));
- }
-
- firsttime = FALSE;
- dprintf("dotab(): recbuf = '%s'\n", decode(recvbuf));
- dprintf("dotab(): qt_rec = '%s'\n", decode(termtab[index].qt_recvstr));
-
- st = prinfo(compare(recvbuf, 0, tabtotal), FALSE);
-
- dprintf("st = %d\n", st);
-
- ++index;
- }
- }
-
- if(!found) {
- dprintf("dotab: failed.\n");
- notrecognized();
- }
-
- done();
- }
-
- char *
- fixctl(str)
- char *str;
- {
- register int i;
- char buf[BUFSIZ];
-
- i = 0;
- while(*str) {
- if(*str == '^')
- buf[i++] = *++str & 037;
- else
- buf[i++] = *str;
- *++str;
- }
- buf[i] = NULL;
- return(buf);
- }
-