home *** CD-ROM | disk | FTP | other *** search
- Subject: v12i025: Query terminal for its type
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rs@uunet.UU.NET
-
- Submitted-by: Craig Bishop <charlie.oz.au!craig>
- Posting-number: Volume 12, Issue 25
- Archive-name: qterm.alt
-
- [ This program sends an Escape sequence to your terminal, and interprets
- the result to see what kind of terminal you have. It's table-driven,
- so adding new terminals is easy. It is a rewrite of the qterm
- program published in Volume 10. --r$ ]
-
- # This is a shell archive. Remove anything before this line, then
- # unpack it by saving it in a file and typing "sh file". (Files
- # unpacked will be owned by you and have default permissions.)
- # This archive contains:
- # README Makefile qtermtab gstty.h qterm.h qterm.c query.c table.c
-
- echo x - README
- cat > "README" << '//E*O*F README//'
- This is a rewrite of the qterm program which came across the net in
- comp.sources.unix the title was v10i072: Query terminal for its type.
- I decided to use the program before looking at the code. Eventually
- I decided to rewrite it.
-
- It is completely compatible with the original so if you are already
- using it I suggest you change to this one. There are couple more
- flags added to the program which are useful when testing a terminals
- responses to the various standard query sequences.
-
- Qterm is particularly valuable in port selector and terminal server
- environments. Most terminals can respond to the standard ANSI query
- sequences, others which cannot will often do answerback.
-
- If you find any bugs please report them to me.
-
- Craig Bishop ACSNET: craig@charlie.oz
- ARPA: craig%charlie.oz.au@uunet.uu.net
- UUCP: ...!uunet!munnari!charlie.oz!craig
- //E*O*F README//
-
- echo x - Makefile
- cat > "Makefile" << '//E*O*F Makefile//'
- #
- # Makefile for qterm.
- #
- # If this is a USG system then add the flag -DUSG to the
- # CFLAGS variable.
- #
-
- DESTDIR = /usr/local/bin
- CFLAGS = -O -DTABLEFILE=\"$(TABLEDIR)/$(TABLE)\"
- SOURCES = qterm.c query.c table.c
- OBJECTS = qterm.o query.o table.o
- HDRS = gstty.h qterm.h
- BINARY = qterm
- LIBS =
- MAN = qterm.1
- MANDIR = /usr/local/man/man1
- TABLE = qtermtab
- TABLEDIR = /usr/local/lib
-
- .DEFAULT:; co -q $<
-
- all: $(BINARY)
-
- $(BINARY): $(OBJECTS)
- cc -o $(BINARY) $(OBJECTS) $(LIBS)
-
- $(OBJECTS): $(HDRS)
-
- install:; cp $(BINARY) $(DESTDIR)
- chown bin $(DESTDIR)/$(BINARY)
- chmod 751 $(DESTDIR)/$(BINARY)
- cp $(MAN) $(MANDIR)
- chown man $(MANDIR)/$(MAN)
- chmod 644 $(MANDIR)/$(MAN)
-
- install_table:; cp $(TABLE) $(TABLEDIR)
- chown lib $(TABLEDIR)/$(TABLE)
- chmod 644 $(TABLEDIR)/$(TABLE)
-
- clean:; rm -f $(BINARY) $(OBJECTS)
-
- print:; pr Makefile $(HDRS) $(SOURCES) | lpr
- //E*O*F Makefile//
-
- echo x - qtermtab
- cat > "qtermtab" << '//E*O*F qtermtab//'
- #
- #SendStr ReceiveStr TermName FullTermName
- #
- ^[Z ^[iBO h29 Zenith z29 in zenith mode
- ^[Z ^[/K h29 Zenith z29 in zenith mode
- ^[Z ^[[?1;0c vt100 Base vt100
- ^[Z ^[[?1;1c vt100 vt100 with STP
- ^[Z ^[[?1;2c vt100 ANSI/VT100 Clone
- ^[Z ^[[?1;3c vt100 vt100 with AVO and STP
- ^[Z ^[[?1;4c vt100 vt100 with GPO
- ^[Z ^[[?1;5c vt100 vt100 with GPO and STP
- ^[Z ^[[?1;6c vt100 vt100 with GPO and AVO
- ^[Z ^[[?1;7c vt100 vt100 with GPO, STP, and AVO
- ^[Z ^[[?6c vt100 Generic vt100
- ^[Z ^[[?8c vt100 TeleVideo 970
- ^[Z ^[[0n vt100 AT&T Unix PC 7300
- ^[Z ^[[?l;0c vt100 AT&T Unix PC 7300
- ^[Z ^[[?12c vt100 Concept from Pro 350/UNIX
- ^[Z ^[[?;c vt100 Concept From Pro 350/UNIX
- ^[Z ^[[=1;1c avt-4p-s Concept with 4 pages memory
- ^[Z ^[[=1;2c avt-8p-s Concept with 8 pages memory
- ^[Z ^[/Z vt52 Generic vt52
- ^[Z ^[[?10c la120 DEC Writer III
- ^[Z ^[[?1;11c cit101e CIE CIT-101 Enhanced w/Graphics
- #^[Z ^[[?1;11c xt100+ Northern Tech LANPARSCOPE
- ^[Z ^[[?12;7;0;102c vt125 DEC Pro 350 in vt125 mode
- ^[Z ^[[?62;1;2;6;7;8;9c vt220 DEC VT220
- ^[Z ^[[?62;1;4;6;7;8;9;15c vt200-sb Microvax II VMS
- ^[Z ^[[62;1;2;6;8c f220 Freedom 220 DEC clone
- ^[Z ^[[?63;1;2;6;7;8c tvi9220 TeleVideo 9220
- //E*O*F qtermtab//
-
- echo x - gstty.h
- cat > "gstty.h" << '//E*O*F gstty.h//'
- /*
- ** gstty.h - defines and declarations for the getting and setting
- ** of terminal parameters on BSD and USG systems.
- **
- ** Author: Craig Bishop
- ** loosly based on original program by Michael Cooper.
- **
- ** $Header: gstty.h,v 1.1 87/09/30 15:25:46 craig Exp $
- */
-
- #include <sys/ioctl.h>
-
- #ifdef USG
- #include <termio.h>
-
- struct termio otty;
- struct termio ntty;
-
- #define setterm() (\
- (void)ioctl(0, TCGETA, &otty),\
- ntty = otty,\
- ntty.c_lflag &= ~ICANON,\
- ntty.c_lflag &= ~ECHO,\
- ntty.c_cc[VMIN] = 1,\
- ntty.c_cc[VTIME] = 0,\
- (void)ioctl(0, TCSETAF, &ntty)\
- )
-
- #define fixterm() (void)ioctl(0, TCSETAF, &otty)
- #else
- struct sgttyb otty;
- struct sgttyb ntty;
-
- #define setterm() (\
- (void)ioctl(0, TIOCGETP, &otty),\
- ntty = otty,\
- ntty.sg_flags |= CBREAK,\
- ntty.sg_flags &= ~ECHO,\
- (void)ioctl(0, TIOCSETP, &ntty)\
- )
-
- #define fixterm() (void)ioctl(0, TIOCSETP, &otty)
- #endif
- //E*O*F gstty.h//
-
- echo x - qterm.h
- cat > "qterm.h" << '//E*O*F qterm.h//'
- /*
- ** qterm.h - defines and declarations for the qterm modules.
- **
- ** Author: Craig Bishop
- ** loosly based on original program by Michael Cooper.
- **
- ** $Header: qterm.h,v 1.1 87/09/30 15:25:52 craig Exp $
- */
-
- /* defines for qterm */
-
- #define ABSEND "\05" /* Answerback string */
- #define ALTSEND "\033[c" /* Alternative string */
- #define DFLTSEND "\033Z" /* Default string */
- #define CMASK 0177 /* Character mask */
- #define ESC '\033' /* Escape in octal */
- #define MAXTERMS 100 /* Maximum # of terminals for qterm */
- #define STRFILE ".qterm" /* File containing terminal strings */
-
- /*
- ** This is the number of seconds for alarm timeouts. Some slower systems
- ** may need to increase this value to 2 or maybe 3 seconds. This value
- ** effects how long qterm will run, because for each query string sent
- ** the program must wait at least this long.
- */
-
- #define WAIT 1
-
- #define TRUE 1
- #define FALSE 0
-
- #define NULLSTR (char *) NULL
- #define NULLQT (struct qt *) NULL
- #define STREQUAL (0)
-
- #define FIELDSIZ 30
- #define FULLSIZ 80
-
- /* define the query terminal structure */
-
- struct qt
- {
- char sendstr[FIELDSIZ]; /* String to send to terminal */
- char recvstr[FIELDSIZ]; /* String expected in response */
- char termname[FIELDSIZ]; /* Terminal name */
- char fullname[FULLSIZ]; /* Full terminal name & description */
- };
-
- /* declare externals */
-
- extern int Fflag;
- extern int fflag;
- extern int qflag;
- extern int sflag;
-
- extern char querystr[];
- extern char recvbuf[];
- extern char *name;
-
- extern struct qt *termtab[];
-
- /* declare procedures */
-
- int mktable(),
- readtabfile();
-
- char getch();
-
- char *decode(),
- *fixctl(),
- *getenv(),
- *lalloc(),
- *listen(),
- *malloc();
-
- void catchint(),
- dumb(),
- prinfo(),
- wakeup();
-
- FILE *fopen();
-
- struct qt *compare(),
- *dotab();
- //E*O*F qterm.h//
-
- echo x - qterm.c
- cat > "qterm.c" << '//E*O*F qterm.c//'
- /*
- ** qterm.c - Qterm is used to query a terminal to determine the name
- ** of the terminal. This is done by sending a equiry string
- ** to the terminal and reading in a response.
- **
- ** Author: Craig Bishop
- ** loosly based on original program by Michael Cooper.
- */
-
- static char rcsid[] = "$Header: qterm.c,v 1.1 87/09/30 15:25:55 craig Exp $";
-
- #include <stdio.h>
- #include <signal.h>
-
- #include "gstty.h"
- #include "qterm.h"
-
- /* declare flags */
-
- int fflag = FALSE; /* use user's own .qterm file */
- int Fflag = FALSE; /* same as above, but don't add our own table */
- int qflag = FALSE; /* quiet mode */
- int sflag = FALSE; /* print strings */
-
- /* declare global variables */
-
- char decodebuf[BUFSIZ];
- char querystr[FIELDSIZ];
- char recvbuf[FIELDSIZ];
- char *name;
- char usage[] = "usage: %s [ -a ] [ -d ] [ -e ] [ -f ] [ -F ] [ -q ] [ -s ]\n";
-
- struct qt *termtab[MAXTERMS];
-
-
- int
- main(argc, argv)
- int argc;
- char *argv[];
- {
- register int i;
- register int j;
- struct qt *qtp;
-
- name = argv[0];
-
- for ( i = 1; i < argc; i++ )
- {
- if ( argv[i][0] != '-' )
- {
- (void)fprintf(stderr, usage, name);
- return 1;
- }
-
- for ( j = 1; argv[i][j] != NULL; j++ )
- switch ( argv[i][j] )
- {
- case 'a':
- (void)strcpy(querystr, ALTSEND);
- break;
- case 'd':
- (void)strcpy(querystr, DFLTSEND);
- break;
- case 'e':
- (void)strcpy(querystr, ABSEND);
- break;
- case 'f':
- fflag = TRUE;
- break;
- case 'F':
- Fflag = TRUE;
- break;
- case 'q':
- qflag = TRUE;
- break;
- case 's':
- sflag = TRUE;
- break;
- default:
- (void)fprintf(stderr, usage, name);
- return 1;
- }
- }
-
- if ( mktable() == FALSE )
- return 1;
-
- if ( !isatty(0) )
- {
- (void)fprintf(stderr, "%s: Not a tty.\n", name);
- return 1;
- }
-
- setterm();
- (void)signal(SIGHUP, catchint);
- (void)signal(SIGINT, catchint);
- (void)signal(SIGQUIT, catchint);
- (void)setbuf(stdout, 0);
- (void)setbuf(stderr, 0);
- qtp = dotab();
- fixterm();
-
- if ( qtp != NULLQT )
- prinfo(qtp);
- else
- dumb();
-
- return 0;
- }
-
-
- void
- catchint()
- {
- fixterm();
- exit(1);
- }
-
-
- void
- prinfo(ttent)
- struct qt *ttent;
- {
- register int len;
- register struct qt *qtp = ttent;
-
- if ( sflag )
- {
- len = strlen(recvbuf);
-
- (void)fprintf
- (
- stderr,
- "%s receives %d character%s: %s\n",
- name,
- len,
- (len == 1) ? "" : "s",
- decode(recvbuf)
- );
- }
-
- if ( !qflag )
- if ( *qtp->fullname != NULL )
- (void)fprintf
- (
- stderr,
- "Terminal recognized as %s (%s)\n",
- qtp->termname,
- qtp->fullname
- );
- else
- (void)fprintf
- (
- stderr,
- "Terminal recognized as %s\n",
- qtp->termname
- );
-
- (void)puts(qtp->termname);
- }
-
-
- void
- dumb()
- {
- register int len;
-
- if ( sflag )
- {
- len = strlen(recvbuf);
-
- (void)fprintf
- (
- stderr,
- "%s receives %d character%s",
- name,
- len,
- (len == 1) ? "" : "s"
- );
-
- if ( len )
- (void)fprintf(stderr, ": %s\n", decode(recvbuf));
- else
- (void)fputs(".\n", stderr);
- }
-
- if ( !qflag )
- (void)fprintf
- (
- stderr,
- "Terminal NOT recognized - defaults to \"dumb\".\n"
- );
-
- (void)puts("dumb");
- }
-
-
- char *
- decode(str)
- char *str;
- {
- register char *dbp = decodebuf;
- register char *cp1 = str;
- register char *cp2;
- char tmp[10];
-
- for ( *dbp = NULL, cp2 = tmp; *cp1 != NULL; cp1++ )
- {
- if ( *cp1 == ESC )
- {
- (void)strcat(dbp, "<esc> ");
- continue;
- }
-
- if ( (*cp1 <= 33) || (*cp1 == 127) )
- {
- (void)sprintf(cp2, "\\%o ", *cp1);
- (void)strcat(dbp, cp2);
- continue;
- }
-
- (void)sprintf(cp2, "%c ", *cp1);
- (void)strcat(dbp, cp2);
- }
-
- return dbp;
- }
- //E*O*F qterm.c//
-
- echo x - query.c
- cat > "query.c" << '//E*O*F query.c//'
- /*
- ** query.c - send query strings to the terminal and listen for
- ** the answering strings.
- **
- ** Author: Craig Bishop
- ** loosely based on a the original program by Michael Cooper.
- */
-
- static char rcsid[] = "$Header: query.c,v 1.1 87/09/30 15:25:58 craig Exp $";
-
- #include <stdio.h>
- #include <setjmp.h>
- #include <signal.h>
-
- #include "qterm.h"
-
- /* declare global variables */
-
- jmp_buf env;
-
-
- struct qt *
- dotab()
- {
- static int firsttime = TRUE;
- register struct qt **qtpp = termtab;
- register struct qt *lastqtp;
- struct qt *term;
-
- (void) fflush(stdin);
-
- for ( ; *qtpp != NULLQT; lastqtp = *qtpp++ )
- {
- if
- (
- firsttime
- ||
- strcmp((*qtpp)->sendstr, lastqtp->sendstr) != STREQUAL
- )
- {
- firsttime = FALSE;
- (void)fputs((*qtpp)->sendstr, stderr);
-
- if ( listen() == NULLSTR )
- continue;
- }
- else
- continue;
-
- if ( (term = compare(recvbuf, qtpp)) != NULLQT )
- return term;
- }
-
- return NULLQT;
- }
-
-
- char *
- listen()
- {
- register int i;
-
- if ( setjmp(env) )
- {
- (void)fflush(stdin);
- return recvbuf;
- }
-
- (void)signal(SIGALRM, wakeup);
-
- for ( i = 0; i < FIELDSIZ - 1; recvbuf[++i] = NULL )
- {
- (void)alarm(WAIT);
- recvbuf[i] = getch();
- (void)alarm(0);
- }
-
- (void)fflush(stdin);
- return recvbuf;
- }
-
-
- struct qt *
- compare(str, ttstart)
- char *str;
- struct qt **ttstart;
- {
- register char *cp1 = str;
- register char *cp2 = (*ttstart)->sendstr;
- register struct qt **qtpp = ttstart;
-
- for ( ; *qtpp != NULLQT && strcmp(cp2, (*qtpp)->sendstr) == STREQUAL; qtpp++ )
- if ( strcmp(cp1, (*qtpp)->recvstr) == STREQUAL )
- return *qtpp;
-
- return NULLQT;
- }
-
-
- char
- getch()
- {
- char c;
-
- (void)read(0, &c, 1);
- return (c & CMASK);
- }
-
-
- void
- wakeup()
- {
- longjmp(env, 1);
- }
- //E*O*F query.c//
-
- echo x - table.c
- cat > "table.c" << '//E*O*F table.c//'
- /*
- ** table.c - read in the terminal query table(s).
- **
- ** Author: Craig Bishop
- ** loosely based on a the original program by Michael Cooper.
- */
-
- static char rcsid[] = "$Header: table.c,v 1.1 87/09/30 15:26:01 craig Exp $";
-
- #include <stdio.h>
- #include <pwd.h>
-
- #include "qterm.h"
-
- #define talloc(T) (T*) lalloc(sizeof(T))
-
- /* declare global variables */
-
- char fixbuf[FIELDSIZ + 1];
-
- /* declare procedures */
-
- struct passwd *getpwuid();
-
-
- int
- mktable()
- {
- char file[BUFSIZ];
- char *home;
- struct passwd *pwd;
-
- if ( fflag || Fflag )
- {
- if ( (home = getenv("HOME")) == NULLSTR )
- {
- if ( (pwd = getpwuid(getuid())) == (struct passwd *) NULL )
- {
- (void)fprintf
- (
- stderr,
- "%s: Who the hell are you????\n",
- name
- );
-
- return FALSE;
- }
-
- home = pwd->pw_dir;
- }
-
- (void)sprintf(file, "%s/%s", home, STRFILE);
-
- if ( readtabfile(file) == FALSE )
- return FALSE;
- }
-
- if ( !Fflag )
- return readtabfile(TABLEFILE);
-
- return TRUE;
- }
-
-
- int
- readtabfile(file)
- char *file;
- {
- register int line;
- register char *cp;
- register struct qt **qtpp = termtab;
- char buf[BUFSIZ];
- FILE *fp;
-
- if ( (fp = fopen(file, "r")) == (FILE *) NULL )
- {
- (void)fprintf
- (
- stderr,
- "%s: Cannot read input file %s.\n",
- name,
- file
- );
-
- return FALSE;
- }
-
- for
- (
- *qtpp = talloc(struct qt), line = 1, cp = buf;
- qtpp < &termtab[MAXTERMS - 1] && fgets(cp, BUFSIZ, fp);
- line++
- )
- {
- if ( *cp == '#' || *cp == '\n')
- continue;
-
- (void)sscanf
- (
- cp,
- "%s%s%s\t%[^\n]",
- (*qtpp)->sendstr,
- (*qtpp)->recvstr,
- (*qtpp)->termname,
- (*qtpp)->fullname
- );
-
- if ( *(*qtpp)->sendstr == NULL )
- continue;
-
- if ( *(*qtpp)->recvstr == NULL || *(*qtpp)->termname == NULL )
- {
- (void)fprintf
- (
- stderr,
- "%s: Error parsing qterm file %s on line %d.\n",
- name,
- file,
- line
- );
-
- (void)fclose(fp);
- return FALSE;
- }
-
- if ( querystr[0] != NULL )
- (void)strcpy((*qtpp)->sendstr, querystr);
- else
- (void)strcpy((*qtpp)->sendstr, fixctl((*qtpp)->sendstr));
-
- (void)strcpy((*qtpp)->recvstr, fixctl((*qtpp)->recvstr));
- *++qtpp = talloc(struct qt);
- }
-
- (void)fclose(fp);
- (void)free(*qtpp);
- *qtpp = NULLQT;
-
- if ( qtpp == &termtab[MAXTERMS - 1] )
- {
- (void)fprintf
- (
- stderr,
- "%s: Greater than maximum terminals of %d.",
- name,
- MAXTERMS
- );
-
- return FALSE;
- }
-
- return TRUE;
- }
-
-
- char *
- fixctl(str)
- char *str;
- {
- register char *cp1 = str;
- register char *cp2 = fixbuf;
-
- for ( *cp2 = NULL; *cp1 != NULL; cp1++, cp2++ )
- {
- if ( *cp1 == '^')
- *cp2 = *++cp1 & 037;
- else
- *cp2 = *cp1;
- }
-
- *cp2 = NULL;
- return(fixbuf);
- }
-
-
- char *
- lalloc(size)
- int size;
- {
- register char *cp;
-
- if ( (cp = malloc((unsigned)size)) == NULLSTR )
- {
- (void)fprintf
- (
- stderr,
- "%s: No memory for malloc(%d)\n",
- name,
- size
- );
-
- exit(1);
- }
-
- return cp;
- }
- //E*O*F table.c//
-
- exit 0
-