Subject: qterm - a better 'tset' (#279) Index: local/qterm 2.11BSD Description: From the contributor, Robin Birch : "Here is a noddy terminal query program that is a little brighter than tset ... I got it off a tools cd that O'Reilly published some time ago. Cheers." Repeat-By: N/A Fix: Included below is a shar archive containing a small patch to /VERSION and the shar archive of the qterm program itself. Cut where indicated, saving to a file (/tmp/279). Then: sh /tmp/279 sh /tmp/qterm.shar cd /usr/src/local/qterm make make install make clean patch -p0 < /tmp/p.279 rm /tmp/279 /tmp/p.279 /tmp/qterm.shar The README file and man page should be self explanatory. This and previous 2.11BSD updates may be obtained via anonymous FTP to the host 'NS.IIPO.GTEGSC.COM' in the directory /pub/2.11BSD. ========================cut here===================== #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # /tmp/p.279 # /tmp/qterm.shar # This archive created: Tue Nov 21 20:31:38 1995 export PATH; PATH=/bin:/usr/bin:$PATH if test -f '/tmp/p.279' then echo shar: "will not over-write existing file '/tmp/p.279'" else sed 's/^Y//' << \SHAR_EOF > '/tmp/p.279' Y*** /VERSION.old Tue Nov 21 19:55:22 1995 Y--- /VERSION Tue Nov 21 20:28:28 1995 Y*************** Y*** 1,4 **** Y! Current Patch Level: 278 Y Y 2.11 BSD Y ============ Y--- 1,4 ---- Y! Current Patch Level: 279 Y Y 2.11 BSD Y ============ SHAR_EOF fi if test -f '/tmp/qterm.shar' then echo shar: "will not over-write existing file '/tmp/qterm.shar'" else sed 's/^Y//' << \SHAR_EOF > '/tmp/qterm.shar' Y#! /bin/sh Y# This is a shell archive, meaning: Y# 1. Remove everything above the #! /bin/sh line. Y# 2. Save the resulting text in a file. Y# 3. Execute the file with /bin/sh (not csh) to create: Y# /usr/src/local/qterm Y# This archive created: Tue Nov 21 20:31:07 1995 Yexport PATH; PATH=/bin:/usr/bin:$PATH Yif test ! -d '/usr/src/local/qterm' Ythen Y mkdir '/usr/src/local/qterm' Yfi Ycd '/usr/src/local/qterm' Yif test -f 'README' Ythen Y echo shar: "will not over-write existing file 'README'" Yelse Ysed 's/^X//' << \SHAR_EOF > 'README' YX YX Q T E R M - Q U E R Y T E R M I N A L YX YX Version 5.0 YX YXQterm is a program that queries terminals to find out what kind of YXterminal is responding. It is useful to automagically define your YXterminal type. It prints the name of the terminal (compatible, YXhopefully, with a termcap/terminfo name) such as "vt100" to standard YXoutput. See the manual for details. YX YXThe major changes in these version of qterm is a re-write of command YXline parsing and the options qterm accepts. I've written a new, YX"generic" command line parsing package called "options" which is YXincluded as part of this distribution of qterm. (See the options.3 YXman page for details on programming with the options package.) Qterm YXnow has a totally new set of (hopefully) clear and concise options. YXThe old command line options are still accepted if qterm is compiled YXwith OPT_COMPAT defined (see Makefile). WARNING: Some of the old YXoptions conflict with the new options. i.e. If OPT_COMPAT is YXdefined, "qterm -file foo" does not do what you think it will. This YXis parsed as "qterm -f ile foo". YX YXQterm was written under 4.[23] BSD and will probably run without YXmodification on other Berkeley Unix systems. This version has also YXbeen tested under UTS 2.1 which is a System V.3 derivative. It was YXcompiled with "USG5" defined and setting $(LIBS) to "-lPW". (See YXMakefile for more info). It should work on other System V platforms. YX YXIt has been running at one point or another here at USC on: YX YX Sun-3, Sun-4, Sun386i's under SunOS 3.X, 4.0, 4.0.3, 4.1, 4.1.1 YX Alliant's under Concentrix 3.X, 4.X, 5.X YX IBM RT's under ACIS 4.2 and 4.3 YX DEC VAX & DEC RISC under Ultrix 2.2, 3.1, 4.0, 4.1 YX 4.[23]BSD (VAX) YX 4.3BSD [MORE/bsd] (HP) YX Amdahl UTS (System V.3) 2.1 YX YXIf you have Internet access, the latest and greatest version of qterm YXis available from "usc.edu" via anonymous ftp in the file YX/pub/qterm.shar. I update this file whenever there are any changes, YXso it's bound to be newer than a copy from any other source. YX YX YXMichael A. Cooper, University Computing Services, U of Southern California YX INTERNET: mcooper@usc.edu PHONE: 213-740-2957 YX UUCP: ...!uunet!usc!mcooper BITNET: mcooper@gamera YSHAR_EOF Ychmod 644 'README' Yfi Yif test -f 'qtermtab' Ythen Y echo shar: "will not over-write existing file 'qtermtab'" Yelse Ysed 's/^X//' << \SHAR_EOF > 'qtermtab' YX# YX# $Header: /am/sol/src/common/usc/bin/qterm/RCS/qtermtab,v 5.0 90/12/15 18:30:49 mcooper Release $ YX# YX# QtermTab - Query terminal table for qterm(1). YX# YX#SendStr ReceiveStr TermName FullTermName YX# YX^[Z ^[[?1;0c vt100 Base vt100 YX^[Z ^[[?1;1c vt100 vt100 with STP YX^[Z ^[[?1;2c vt100 ANSI/VT100 Clone YX^[Z ^[[?1;3c vt100 vt100 with AVO and STP YX^[Z ^[[?1;4c vt100 vt100 with GPO YX^[Z ^[[?1;5c vt100 vt100 with GPO and STP YX^[Z ^[[?1;6c vt100 vt100 with GPO and AVO YX^[Z ^[[?1;7c vt100 vt100 with GPO, STP, and AVO YX^[Z ^[[?6;2c vt100 Uniterm vt100 Emulator YX^[Z ^[/K h29 Zenith z29 in zenith mode YX^[Z ^[/Z vt52 Generic vt52 YX^[Z ^[[0n vt100 AT&T Unix PC 7300 YX^[Z ^[[62;1;2;6;8c f220 Freedom 220 DEC clone YX^[Z ^[[=1;1c avt-4p-s Concept with 4 pages memory YX^[Z ^[[=1;2c avt-8p-s Concept with 8 pages memory YX^[Z ^[[?10c la120 DEC Writer III YX^[Z ^[[?12;7;0;102c vt125 DEC Pro 350 in vt125 mode YX^[Z ^[[?12c vt100 Concept from Pro 350/UNIX YX^[Z ^[[?1;11c cit101e CIE CIT-101 Enhanced w/Graphics YX^[Z ^[[?62;1;2;6;7;8;9c vt220 DEC VT220 YX^[Z ^[[?62;1;2;6;7;8c vt100 Amiga Handshake YX^[Z ^[[?62;1;4;6;7;8;9;15c vt200-sb Microvax II VMS YX^[Z ^[[?63;1;2;6;7;8c tvi9220 TeleVideo 9220 YX^[Z ^[[?6c vt100 Generic vt100 YX^[Z ^[[?8;8;6c att630 AT&T 630 MTG YX^[Z ^[[?8c vt100 TeleVideo 970 YX^[Z ^[[?;c vt100 Concept From Pro 350/UNIX YX^[Z ^[[?l;0c vt100 AT&T Unix PC 7300 YX^[Z ^[iB0 h29 Zenith z29 in zenith mode YX#^[Z ^[[?1;11c xt100+ Northern Tech LANPARSCOPE YX############################################################################ YX# YX# Enable at your own risk YX# YX#^[\040 50 wyse50 Wyse 50 Terminal YX#^[i0 ^[iB0 z29 Zenith z29 YX# YX# HP terminals YX# YX#^[*s1\^ 2621^J hp2621 Hewlett-Packard HP-2621 YX#^[*s1\^ 2621A^J hp2621a Hewlett-Packard HP-2621A YX#^[*s1\^ 2621B^J hp2621b Hewlett-Packard HP-2621B YX#^[*s1\^ 2621K^J hp2621k Hewlett-Packard HP-2621K YX#^[*s1\^ 2621K45^J hp2621k45 Hewlett-Packard HP-2621K45 YX#^[*s1\^ 2621NL^J hp2621nl Hewlett-Packard HP-2621NL YX#^[*s1\^ 2621NT^J hp2621nt Hewlett-Packard HP-2621NT YX#^[*s1\^ 2621P^J hp2621p Hewlett-Packard HP-2621P YX#^[*s1\^ 2621WL^J hp2621wl Hewlett-Packard HP-2621WL YX#^[*s1\^ 2622^J hp2622 Hewlett-Packard HP-2622 YX#^[*s1\^ 2622A^J hp2622a Hewlett-Packard HP-2622A YX#^[*s1\^ 2622P^J hp2622p Hewlett-Packard HP-2622P YX#^[*s1\^ 2626^J hp2626 Hewlett-Packard HP-2626 YX#^[*s1\^ 2626A^J hp2626a Hewlett-Packard HP-2626A YX#^[*s1\^ 2626P^J hp2626p Hewlett-Packard HP-2626P YX#^[*s1\^ 2640^J hp2640 Hewlett-Packard HP-2640 YX#^[*s1\^ 2640A^J hp2640a Hewlett-Packard HP-2640A YX#^[*s1\^ 2640B^J hp2640b Hewlett-Packard HP-2640B YX#^[*s1\^ 2644A^J hp2644a Hewlett-Packard HP-2644A YX#^[*s1\^ 2645^J hp2645 Hewlett-Packard HP-2645 YX#^[*s1\^ 2645A^J hp2645a Hewlett-Packard HP-2645A YX#^[*s1\^ 2645NP^J hp2645np Hewlett-Packard HP-2645NP YX#^[*s1\^ 2647^J hp2647 Hewlett-Packard HP-2647 YX#^[*s1\^ 2647A^J hp2647a Hewlett-Packard HP-2647A YX#^[*s1\^ 2648^J hp2648 Hewlett-Packard HP-2648 YX#^[*s1\^ 2648A^J hp2648a Hewlett-Packard HP-2648A YX############################################################################ YSHAR_EOF Ychmod 644 'qtermtab' Yfi Yif test -f 'Makefile' Ythen Y echo shar: "will not over-write existing file 'Makefile'" Yelse Ysed 's/^X//' << \SHAR_EOF > 'Makefile' YX# YX# Copyright (c) 1990 Michael A. Cooper. YX# This software may be freely distributed provided it is not sold for YX# profit and the author is credited appropriately. YX# YX# $Header: /src/common/usc/bin/qterm/RCS/Makefile,v 5.1 1991/02/20 02:31:50 mcooper Exp $ YX# YX# Makefile for QTerm YX# YX YX# YX# DIR is the main/top-level directory. YX# If you change DIR, run "make reconfig". YX# YXDIR = /usr/local YX YX# YX# BIN is were the "qterm" binary gets installed. YX# YXBIN = $(DIR) YX YX# YX# MAN is the directory where the "qterm.1" man page goes. YX# YXMAN = $(DIR)/man/cat1 YX YX# YX# TABFILE should be set to the location you want the qterm table YX# file placed in. YX# YXTABFILE = $(DIR)/lib/qtermtab YX YX# YX# Add "-DUSG5" to DEFS below, if your system is Unix System V. YX# Add "-DHAS_VARARGS" if your system supports varargs. YX# Add "-DOPT_COMPAT" if you want compatibility with old command line options. YX# YXDEFS = -DTABFILE=\"$(TABFILE)\" -DOPT_COMPAT -DHAS_VARARGS YX YX# YX# On some System V systems you will need to add "-lPW" to LIBS. YX# YXLIBS = -lc YX YX YXCONFIGFILES = Makefile qterm.1 options.3 YXCFILES = qterm.c options.c YXHFILES = qterm.h options.h YXOBJS = qterm.o options.o YXCFLAGS = -O $(DEFS) YXLD = ld YXLDFLAGS = -i YX YX.c.o : YX $(CC) $(CFLAGS) -c $< YX YXall: qterm qterm.0 YX YXqterm: $(OBJS) $(HFILES) YX $(LD) $(LDFLAGS) /lib/crt0.o -o qterm $(OBJS) $(LIBS) YX YXreconfig: YX -@for i in $(CONFIGFILES); do \ YX echo ReConfiguring $$i...;\ YX sed "s;/usr/local;$(DIR);g" < $$i > $$i.tmp;\ YX mv -f $$i.tmp $$i;\ YX done YX YX$(OBJS): $(HFILES) YX YXqterm.0: YX /usr/man/manroff qterm.1 > qterm.0 YX YXshar: YX shar README qtermtab $(CONFIGFILES) $(CFILES) $(HFILES) > qterm.shar YX YXclean: YX rm -f *.o core log *~ \#* qterm qterm.shar o qterm.0 YX YX# YX# Install target for BSD machines. YX# YXinstall: qterm qterm.0 qtermtab YX install -c -m 755 qterm $(BIN) YX install -c -m 644 qterm.0 $(MAN) YX install -c -m 644 qtermtab $(TABFILE) YX YX# YX# Install target for System V machines. YX# YXinstall.usg5: qterm qterm.1 qtermtab YX cp qterm $(BIN); chmod 755 $(BIN)/qterm YX cp qterm.1 $(MAN); chmod 644 $(MAN)/qterm.1 YX cp qtermtab $(TABFILE); chmod 644 $(TABFILE) YSHAR_EOF Ychmod 644 'Makefile' Yfi Yif test -f 'qterm.1' Ythen Y echo shar: "will not over-write existing file 'qterm.1'" Yelse Ysed 's/^X//' << \SHAR_EOF > 'qterm.1' YX.\" YX.\" Copyright (c) 1990 Michael A. Cooper. YX.\" This software may be freely distributed provided it is not sold for YX.\" profit and the author is credited appropriately. YX.\" YX.\" $Header: /am/sol/src/common/usc/bin/qterm/RCS/qterm.1,v 5.0 90/12/15 18:30:38 mcooper Release $ YX.\" YX.TH QTERM 1 "6 November 1990" YX.ds ]W USC-UCS YX.SH NAME YXqterm \- Query Terminal YX.SH SYNOPSIS YXqterm YX[ YX.B +|\-alt YX] [ YX.B +|\-always YX] [ YX.B +|\-longname YX] [ YX.B +|\-quiet YX] [ YX.B +|\-sent YX] [ YX.B +|\-timeout YX] [ YX.B +|\-usrtab YX] [ YX.B +|\-watch YX] [ YX.B +|\-systab YX] [ YX.B \-wait YX.I interval YX] [ YX.B \-file YX.I tabfile YX] YX.SH DESCRIPTION YX.I Qterm YXis used to query a terminal to determine its name. YXThis is done by sending a special sequence to the terminal, YXreading in a response, and comparing it against a table of possible YXresponses. YXThe ``name'' printed to standard output should be one found in YXthe YX.I termcap(5) YX(or YX.I terminfo(5) YXfor System V systems) YXdatabase. YX.PP YXFor YX.I csh(1) YXusers, YXputting a line in your YX.I .login YXfile such as: YX.sp 1 YX.in +.5i YXsetenv TERM `qterm` YX.in -.5i YX.sp 1 YXshould automagically set your terminal type. YXFor YX.I sh(1) YXusers, putting these lines in your YX.I .profile YXfile should set your terminal type: YX.sp 1 YX.in +.5i YXTERM=`qterm` YX.br YXexport TERM YX.in -.5i YX.sp 1 YX.LP YXBy default, YX.B qterm YXuses the system tab file YX.I /usr/local/lib/qtermtab YXto obtain information for querying terminals. YX.SH OPTIONS YX.IP \fB+alt\fP YXUse the alternate string ``[c'' when asking the terminal to YXidentify itself. This string is recognized by most ANSI compatible YXterminals. YX.IP \fB\-alt\fP YXDon't use the alternate string, but the string found in the YX.B tabfile YXbeing used. YXThis is the default. YX.IP \fB+always\fP YXAlways send the terminal query string. YXNormally the query string is only sent if it differs from YXthe last string sent. YX.IP \fB-always\fP YXOnly send the terminal query string if it differs from the last YXstring sent. YXThis is the default. YX.IP "\fB\-file \fItabfile\fP" YXUse YX.I YXto find information for querying the terminal. YX.IP \fB+longname\fP YXPrint only the long (verbose) terminal name. YX.IP \fB\-longname\fP YXDon't print the long (verbose) terminal name. YXThis is the default. YX.IP \fB+quiet\fP YXBe quiet and only print the terminal name to standard output. YX.IP \fB\-quiet\fP YXDon't be quiet and only print the terminal name to standard output. YXThis is the default. YX.IP \fB+watch\fP YXWatch the characters sent and recieved to the terminal. YX.IP \fB\-watch\fP YXDon't watch the characters sent and recieved to the terminal. YXThis is the default. YX.IP \fB+timeout\fP YXWait for timeout when listening for response string. YXThis is useful if the first entry in a qtermtab doesn't have YXa response string with an ending character that is common YXwith the rest of the qtermtab entries. YX.IP \fB\-timeout\fP YXDisable waiting for timeout when listening for response string. YXThis is the default. YX.IP \fB+usrtab\fP YXUse YX.B $HOME/.qtermtab YXto find information for querying the terminal. YX.IP \fB\-usrtab\fP YXDon't use YX.B $HOME/.qtermtab YXto find information for querying the terminal. YXThis is the default. YX.IP \fB+sent\fP YXDisplay the final response sent from YXthe terminal in a ``nice'' fashion. YX.IP \fB-sent\fP YXDon't display the final response sent from the terminal. YXThis is the default. YX.IP \fB+systab\fP YXUse YX.B /usr/local/lib/qtermtab YXto find information for querying the terminal. YXThis is the default YX.IP \fB\-systab\fP YXDon't use YXsystem tab file YXto find information for querying the terminal. YX.IP "\fB\-wait \fIinterval\fP" YXSet the wait (timeout) period to YX.I interval YX(in seconds). YX.SH "QTERMTAB" YXThe format of the file YX$HOME/.qtermtab YXand YX.I qterm's YXsystem tab file YX.I /usr/local/lib/qtermtab, YXconsists of four fields each seperated by white space (tabs and/or spaces). YXThe first field is the string that should be used to query the terminal. YXThe second field is the string to expect in response to the query. YXThe third field is the terminal name (compatible with YX.I termcap(5)) YXto print to standard output. YXThe fourth field is optional and may contain a description of the exact YXmanufacturer and model name of the terminal to be used in a message YXprinted to standard error. YX.PP YXBlank lines or lines starting with the character ``#'' YXare ignored and may be used as comment lines. YXA character preceeded by a ``^'' is taken to mean the YX.I control YXcharacter. (i.e. ``^['' is interpretted as an ). YXBoth the send and receive (first and second) fields may contain YXoctal values preceeded by a `\\'. YX(i.e. can be represented by `\\033'.) YX.PP YXThe ``expect'' (second) field YXcan be a regular expression denoted by a leading backslash (`\\'). YXi.e. "^[[123" matches the string "^[[123", whereas "^[\\[123]" matches YX"^[1" or "^[2" or "^[3". YXSee YX.I ed(1) YXfor regular expression information. YX.PP YXBelow is a sample file: YX.sp 2 YX.nf YX # YX # QTerm File YX # YX ^[Z\0\0\0\0\0^[[?1;1c\0\0\0\0\0vt100\0\0\0\0\0A vt100 with STP YX ^[Z\0\0\0\0\0^[[?1;2c\0\0\0\0\0vt100\0\0\0\0\0ANSI/VT100 Clone YX ^[Z\0\0\0\0\0^[[?1;3c\0\0\0\0\0vt100\0\0\0\0\0A vt100 with AVO and STP YX ^[Z\0\0\0\0\0^[[?1;4c\0\0\0\0\0vt100\0\0\0\0\0A vt100 with GPO YX ^[Z\0\0\0\0\0^[iBO\0\0\0\0\0\0\0\0z29\0\0\0\0\0\0\0Zenith in Zenith Mode YX.fi YX.sp YX.SH AUTHOR YXMichael A. Cooper, YX.br YXUniversity Computing Services, YX.br YXUniversity of Southern California. YX.SH FILES YX.ta \w'/usr/local/lib/qtermtab\ \ \ 'u YX/usr/local/lib/qtermtab \- System table YX.br YX$HOME/.qtermtab \- User's table YX.br YX/etc/termcap \- termcap(5) database YX.SH SEE ALSO YXcsh(1), ed(1), sh(1), termcap(5) YX.SH DIAGNOSTICS YX.IP "\fITerminal not recognized - defaults to dumb.\fP" YX.I QTerm YXdid not receive a response from the terminal, or the response YXdid not match any that YX.I qterm YXhas stored internally. Use the \+watch option to check to see which YXis the case. YX.SH BUGS YXMany terminals do not send a response at all. YSHAR_EOF Ychmod 644 'qterm.1' Yfi Yif test -f 'options.3' Ythen Y echo shar: "will not over-write existing file 'options.3'" Yelse Ysed 's/^X//' << \SHAR_EOF > 'options.3' YX.\" YX.\" Copyright (c) 1990 Michael A. Cooper. YX.\" This software may be freely distributed provided it is not sold for YX.\" profit and the author is credited appropriately. YX.\" YX.\" $Header: /src/common/usc/lib/libgen/RCS/options.3,v 1.4 1991/02/22 02:30:06 mcooper Exp $ YX.\" YX.TH PARSEOPTIONS 3 "30 October 1990" YX.ds ]W USC-UCS YX.SH NAME YXParseOptions, UsageOptions, HelpOptions, Num_Opts \- Parse command line options YX.SH SYNOPSIS YX.LP YX.nf YX.ft B YX#include "/usr/local/include/options.h" YX.ft YX.fi YX.LP YX.nf YX.ft B YXint ParseOptions(options, num_options, argc, argv) YXOptionDescRec *options; YXint num_options; YXint argc; YXchar **argv; YX.ft YX.fi YX.LP YX.nf YX.ft B YXvoid UsageOptions(options, num_options, badoption) YXOptionDescRec *options; YXint num_options; YXchar *badoption; YX.ft YX.fi YX.LP YX.nf YX.ft B YXvoid HelpOptions(options, num_options, message) YXOptionDescRec *options; YXint num_options; YXchar **message; YX.ft YX.fi YX.LP YX.nf YX.ft B YXint Num_Opts(options) YXOptionDescRec *options; YX.ft YX.fi YX.LP YX.nf YX.ft B YXextern char *OptionChars; YXextern char *ProgramName; YX.ft YX.fi YX.SH DESCRIPTION YX.LP YX.BR ParseOptions(\|) YXparses a given set of options found in YX.B argv. YXThe YX.B argc YXparameter is the count of the number of string pointers YXin YX.B argv. YXBoth YX.B argc YXand YX.B argv YXare typically passed directly from a YX.B main(\|) YXfunction. YXThe YX.B argv YXparameter should contain an array of strings that YXneed to be parsed. YX.B ParseOptions(\|) YXreturns the number of entries in YX.B argv YXthat were successfully parsed or -1 upon error. YX.LP YXThe YX.B options YXstructure should contain a valid description list of options. YXThe type YX.B OptionDescRec YXis defined as the following in the YX.B "options.h" YXheader file: YX.RS YX.LP YX.nf YX.ft B YXtypedef struct { YX char *option; /* Option string in argv */ YX int flags; /* Flag bits */ YX int (*cvtarg)(); /* Function to convert argument */ YX caddr_t valp; /* Variable to set */ YX caddr_t value; /* Default value to provide */ YX char *usage; /* Usage message */ YX char *desc; /* Description message */ YX} OptionDescRec, *OptionDescList; YX.ft R YX.fi YX.RE YX.LP YXThe order of YX.I options YXis important because YXthe first partial match found in YX.I options YXis used. YXThis allows abbreviations (except if the option is a YX.I StickArg YX[see below]). YXFor instance, a user may specify only "\-n" for "\-number" provided YXthat "\-n" is unique to YX.I options YXor that "\-number" is placed before any other "\-n*" options in YX.I options. YX.LP YXThe YX.I option YXmember of YX.B OptionDescRec YXis the string name of the option. YXThis is typically something like YX.RS YX.ft B YX.nf YX.sp YX"\-c" YX"+c" YX"\-file" YX.fi YX.sp YX.ft YX.RE YXThe first character of YX.I option YXis special. It must be one of the characters know to be the YXstart of an option. YXThe default list of starting option characters is "\-+". YXThis indicates that an option can start with either a "\-" or YXa "+". This list of characters may be changed by setting YXthe variable YX.B OptionChars YXto point to a string of custom starting option characters. YX.LP YXThe YX.I flags YXmember is used to set bits to describe how an option YXis to be interpreted. YXValid flags are defined in the YX.I "options.h" YXheader file: YX.RS YX.IP NoArg YXNo argument for this option. YXUse the value in YX.I OptionDescRec.value YXto set the value in the YX.I valp YXmember of YX.B OptionDescRec. YX.IP IsArg YXValue is the option string itself. YX.IP SepArg YXValue is in next argument in argv. YX.IP StickyArg YXValue is the characters immediately following YXthe option. YX.IP SkipArg YXIgnore this option and the next argument in argv. YX.IP SkipLine YXIgnore this option and the rest of argv. YX.IP SkipNArgs YXIgnore this option and the next YX.I OptionDescRes.value YXarguments in argv. YX.IP ArgHidden YXDon't show this option in usage or help messages. YX.RE YX.LP YXThe next member of YX.B OptionDescRec YXis YX.I cvtarg. YXThis should be a pointer to a function that knows how to YXconvert the given argument into the correct type. YXThe predefined functions are as follows: YX.RS YX.IP OptBool YXConverts a boolean. YX.IP OptInt YXConverts an integer. YX.IP OptShort YXConverts a short. YX.IP OptLong YXConverts a long. YX.IP OptStr YXConverts a string. YX.RE YX.LP YXThe YX.I valp YXmember should be a pointer YXto the variable that needs to be set. YX.I valp YXshould accept whatever type YX.I cvtarg YXis expected to return. YX.LP YXThe YX.I value YXmember should contain a default value to YXbe used if no value is given for an option or YXthis type of option does not require an argument YX(according to the YX.I flags YXbits). YXIf YX.I value YXis YX.B NULL YXthen an argument for this option YXis optional. YX.LP YX.I usage YXis used to build usage and help messages. YXIt should be a string containing a description of any arguments YXthat may be used for this option. YXThe option string itself should not be a part of YX.I usage. YXThe YX.B UsageOptions(\|) YXand YX.B HelpOptions(\|) YXfunctions combine the YX.I option YXfield with YX.I usage YXand interpret the YX.I flags YXbits to build a usage string. YXIf this field is YX.B NULL, YXthen just the YX.I option YXfield itself is used for usage and help messages. YX.LP YXThe YX.I desc YXmember is used to build a help message for this option. YXThis should be a string containing a brief description on what this YXoption does. YX.LP YXThe YX.B num_options YXparameter should be the number of YX.B OptionDescRec's YXfound in YX.B options. YXThe function YX.BR Num_Opts(\|) YXwill return the number of YX.B OptionDescRec's. YX.LP YXThe YX.B UsageOptions(\|) YXfunction YXprints a usage message. YXIf YX.I badoption YXis not YX.B NULL, YXthen an initial message is displayed indicating that YX.I badoption YXis not a valid option. YX.LP YXThe YX.B HelpOptions(\|) YXfunction YXprints a nicely formatted message describing all options. YXIf YX.I message YXis not YX.B NULL YXit is taken to be a message that is displayed in the output of YXa "\-help" option. YX.SH EXAMPLE YX.LP YXHere is an example program: YX.nf YX.sp YX.ft B YX#include "options.h" YX YXchar *filename = NULL; YXint number = \-1; YXint foo = \-1; YXint I = \-1; YXlong L = \-1; YXshort S = \-1; YX YXOptionDescRec opts[] = { YX {"\-foo", NoArg, OptBool, (caddr_t) &foo, "0", YX (char *)NULL, "Disable foo bar"}, YX {"+foo", NoArg, OptBool, (caddr_t) &foo, "1", YX (char *)NULL, "Enable foo bar"}, YX {"\-I", StickyArg, OptInt, (caddr_t) &I, (caddr_t) NULL, YX (char *)NULL, "Set value of I"}, YX {"\-L", StickyArg, OptLong, (caddr_t) &L, (caddr_t) NULL, YX (char *)NULL, "Set value of L"}, YX {"\-S", SepArg, OptShort, (caddr_t) &S, (caddr_t) NULL, YX (char *)NULL, "Set value of S"}, YX {"\-C", StickyArg, OptStr, (caddr_t) &filename, (caddr_t) NULL, YX (char *)NULL, "Alternate file to use"}, YX {"\-number", SepArg, OptInt, (caddr_t) &number, "66", YX "interval", NULL}, YX {"\-file", SepArg, OptStr, (caddr_t) &filename, (caddr_t) NULL, YX "filename", "Specify alternate file to use"}, YX}; YX YXmain(argc, argv) YX int argc; YX char **argv; YX{ YX int c; YX YX c = ParseOptions(opts, Num_Opts(opts), argc, argv); YX printf("Count = %d of %d\n", c, argc); YX} YX.ft YX.fi YX.SH "RETURN VALUES" YX.B ParseOptions(\|) YXreturns the number of arguments parsed or -1 upon error. YX.SH NOTES YX.LP YXThe YX.I \-help YXoption is automatically built into YX.B ParseOptions(\|). YX.LP YXAll error messages are sent to YX.B stderr. YX.LP YXAn option may be both YX.I StickyArg YXand YX.I SepArg. YXIf both are set for one option, preference is given to YX.I SepArg YXparsing. YXAlso, no appreviations are allowed. YX.SH AUTHOR YXMichael A. Cooper, YX.br YXUniversity Computing Services, YX.br YXUniversity of Southern California. YSHAR_EOF Ychmod 644 'options.3' Yfi Yif test -f 'qterm.c' Ythen Y echo shar: "will not over-write existing file 'qterm.c'" Yelse Ysed 's/^X//' << \SHAR_EOF > 'qterm.c' YX#ifndef lint YXstatic char *RCSid = "$Header: /src/common/usc/bin/qterm/RCS/qterm.c,v 5.4 1991/03/21 02:09:40 mcooper Exp $"; YX#endif YX YX/* YX * Copyright (c) 1990 Michael A. Cooper. YX * This software may be freely distributed provided it is not sold for YX * profit and the author is credited appropriately. YX */ YX YX/* YX *------------------------------------------------------------------ YX * YX * $Source: /src/common/usc/bin/qterm/RCS/qterm.c,v $ YX * $Revision: 5.4 $ YX * $Date: 1991/03/21 02:09:40 $ YX * $State: Exp $ YX * $Author: mcooper $ YX * $Locker: $ YX * YX *------------------------------------------------------------------ YX * YX * Michael A. Cooper YX * Research and Development Group YX * University Computing Services YX * University of Southern California YX * (mcooper@usc.edu) YX * YX *------------------------------------------------------------------ YX * YX * $Log: qterm.c,v $ YX * Revision 5.4 1991/03/21 02:09:40 mcooper YX * Fix memory buffer problem with some C YX * compilers. (tp@vtold.vtol.fi) YX * YX * Revision 5.3 1991/03/16 05:36:30 mcooper YX * Fix casting of (char) NULL problem. YX * YX * Revision 5.2 1991/03/12 00:46:24 mcooper YX * Change CMASK to CHAR_CMASK to avoid conflict YX * under AIX 3.1. YX * YX * Revision 5.1 1991/02/20 02:23:33 mcooper YX * Cleanup #ifdef USG5 as part of port YX * to UTS 2.1 (System V.3). YX * YX * Revision 5.0 1990/12/15 18:30:41 mcooper YX * Version 5. YX * YX * Revision 4.13 90/12/15 18:14:23 mcooper YX * Add copywrite. YX * YX * Revision 4.12 90/11/13 16:00:03 mcooper YX * Convert OptInt's to OptBool's where needed. YX * YX * Revision 4.11 90/11/13 15:38:28 mcooper YX * Make OLD_SepArg include both YX * SepArg and StickyArg. YX * YX * Revision 4.10 90/11/08 15:41:08 mcooper YX * Make sure qt_fullname is not 0 length. YX * YX * Revision 4.9 90/11/08 13:02:06 mcooper YX * Fix bug that closes the tty when an error YX * occurs during command line parsing. YX * YX * Revision 4.8 90/11/06 13:19:40 mcooper YX * Changed command line options to new YX * longer names. YX * YX * Revision 4.7 90/11/05 17:09:30 mcooper YX * Update option help messages and option names YX * to be more mnemonic. YX * YX * Revision 4.6 90/11/05 16:44:35 mcooper YX * - Converted to use new ParseOptions() for YX * command line parsing. YX * - Major de-linting. YX * - Convert dprintf() to use varargs (if YX * HAS_VARARGS is defined). YX * - Lots of misc. cleanup. YX * YX * Revision 4.5 89/10/20 22:50:49 mcooper YX * Changed code indention to current local YX * standard of 4. (This should also mess up YX * everybody trying to do diff's from older versions!) YX * YX * Revision 4.4 89/10/20 14:03:48 mcooper YX * Fixed command line parsing of "-f -q". YX * YX * Revision 4.3 88/06/16 19:43:46 mcooper YX * - Added -T flag to wait until timeout when YX * listening for response string. This solves YX * problem when the first entry in a table YX * doesn't have a response string with a YX * common ending character to look for. YX * - Added -I flag for "intense" query mode. YX * - Cleaned up debugging a bit. YX * YX * Revision 4.2 88/06/08 15:30:53 mcooper YX * Cleanup pass including removing YX * extraneous debugging messages. YX * YX * Revision 4.1 88/04/25 13:24:38 mcooper YX * Added -S option to print send and recieve YX * strings as they are sent and recieved as YX * suggested by David W. Sanderson YX * (dws@attunix.att.com). YX * YX * Revision 4.0 88/03/08 19:30:59 mcooper YX * Version 4. YX * YX * Revision 3.7 88/03/08 19:28:32 mcooper YX * Major rewrite. YX * YX * Revision 3.6 88/03/08 15:31:35 mcooper YX * General cleanup time. YX * YX * Revision 3.5 88/03/08 13:59:39 mcooper YX * - Catch signals and fix terminal modes. YX * - Don't allow alarm times of 0. YX * - Support for HP-UX machines and cleaner YX * listen() code from Zenon Fortuna, YX * HP-UX Support, Hewlett-Packard Vienna. YX * YX * Revision 3.4 87/10/07 15:16:17 mcooper YX * - Beautify code a bit. YX * - Add -w option to set the wait time. YX * YX * Revision 3.3 87/08/24 19:25:32 mcooper YX * The following based on code from Frank Crawford YX * : YX * - Use $TERM as output string when the terminal YX * type is not known instead of "dumb". YX * - Regular Expressions are now supported. RE are YX * started with a leading `\'. YX * - Octal values may now be used in send/recieve strings. YX * YX * Revision 3.1 87/08/03 15:21:07 mcooper YX * As pointed out by Scott H. Robinson , YX * the -F switch does work. Problem was that it never read YX * in the ~/.qterm file. YX * YX * Revision 3.0 87/06/30 19:07:59 mcooper YX * Release of version 3. YX * YX * Revision 2.4 87/04/29 19:28:35 mcooper YX * In readtabfile() we now do special YX * things when opening "file" fails YX * depending on the bequiet flag. YX * YX * Revision 2.3 87/04/29 13:11:37 mcooper YX * - No more "internal" table. The master YX * table is read from a file (TABFILE). YX * This makes ~/.qterm stuff much cleaner. YX * - Error handling for qtermtab files is YX * much more informative now. YX * - More things I can't remember. YX * YX * Revision 2.2 87/03/05 21:01:28 mcooper YX * Fixed system V compiler problem. YX * YX * Revision 2.1 87/03/01 19:43:22 mcooper YX * Be more intelligent about the size of YX * the default terminal table. YX * YX * Revision 2.0 87/03/01 19:20:00 mcooper YX * General cleanup. YX * YX *------------------------------------------------------------------ YX */ YX YX YX/* YX * qterm - Query Terminal YX * YX * qterm is used to query a terminal to determine the name of the terminal. YX * This is done by sending a fairly universal string "\33Z" to the terminal, YX * reading in a response, and comparing it against a master table of responses YX * and names. The "name" printed to standard output should be one found in YX * the termcap(5) database. YX * YX * Putting a line in your ".login" file such as: YX * YX * setenv TERM `qterm` YX * YX * or the following lines in your ".profile" file: YX * YX * TERM=`qterm` YX * export TERM YX * YX * will set your terminal type automagically. YX * YX * If you add a terminal to the master table, please also send me a copy YX * so that I may put it into my version. YX * YX * Michael Cooper YX * Internet: mcooper@usc.edu YX * UUCP: ...!rutgers!usc!mcooper YX * BITNET: mcooper@gamera YX */ YX YX#include YX#include YX#include YX#include YX#include YX#include YX#ifdef USG5 YX# include YX#else /*USG5*/ YX# include YX# include YX#endif /*USG5*/ YX#include "qterm.h" YX#include "options.h" YX#ifdef HAS_VARARGS YX#include YX#endif /*HAS_VARARGS*/ YX YX#ifdef USG5 YXstruct termio _ntty, _otty; YX#else YXstruct sgttyb _tty; YX#endif YXint _tty_ch = 2; YXchar recvbuf[SIZE]; YXchar *progname; YXchar *termfile = NULL; YX YXint debug = FALSE; /* Debug mode */ YXint use_alt_str = FALSE; /* Alternate string */ YXint towait = FALSE; /* Time out wait flag */ YXint always_send = FALSE; /* Intense query mode */ YXint longname = FALSE; /* Print long terminal name */ YXint sent_chars = FALSE; /* Print strings sent from the terminal */ YXint watch_chars = FALSE; /* Watch strings as they are sent and recv. */ YXint quiet = FALSE; /* Quiet mode */ YXint do_usrtabfile = FALSE; /* Use user's own .qtermtab file */ YXint do_systabfile = TRUE; /* Use the system's qterm tab file */ YXint almwait = WAIT; /* Wait (timeout) interval */ YX YX/* YX * Old options should not be visable in help and usage messages. YX */ YX#ifdef OPT_COMPAT YX#define OLD_NoArg NoArg|ArgHidden YX#define OLD_SepArg SepArg|StickyArg|ArgHidden YX#define fFLAG "-f" YX#define FFLAG "-F" YX#endif YX YX/* YX * Command line options table. YX */ YXOptionDescRec opts[] = { YX#ifdef OPT_COMPAT YX {"-a", OLD_NoArg, OptInt, (caddr_t) &use_alt_str, "1", YX (char *)NULL, "Use alternate query string"}, YX {"-s", OLD_NoArg, OptInt, (caddr_t) &sent_chars, "1", YX (char *)NULL, "Display the characters the terminal sent"}, YX {"-t", ArgHidden|OLD_NoArg, OptInt, (caddr_t) &sent_chars, "1", YX (char *)NULL, "Display the characters the terminal sent"}, YX {"-I", OLD_NoArg, OptInt, (caddr_t) &always_send, "1", YX (char *)NULL, "Always send the terminal query string"}, YX {"-T", OLD_NoArg, OptInt, (caddr_t) &towait, "1", YX (char *)NULL, "Enable time out wait"}, YX {"-S", OLD_NoArg, OptInt, (caddr_t) &watch_chars, "1", YX (char *)NULL, "Print strings as they are sent and received"}, YX {"-q", OLD_NoArg, OptInt, (caddr_t) &quiet, "1", YX (char *)NULL, "Enable quite mode"}, YX {"-f", OLD_SepArg, OptStr, (caddr_t) &termfile, fFLAG, YX "", "Try , then ~/.qtermtab, then system tabfile"}, YX {"-F", OLD_SepArg, OptStr, (caddr_t) &termfile, FFLAG, YX "", "Try , then ~/.qtermtab"}, YX {"-l", OLD_NoArg, OptInt, (caddr_t) &longname, "1", YX (char *)NULL, "Output only the long (verbose) terminal name"}, YX {"-d", OLD_NoArg, OptInt, (caddr_t) &debug, "1", YX (char *)NULL, "Enable debug mode"}, YX {"-w", OLD_SepArg, OptInt, (caddr_t) &almwait, __ NULL, YX "", "Wait (timeout) period (in seconds)"}, YX#endif /*OPT_COMPAT*/ YX {"+alt", NoArg, OptBool, (caddr_t) &use_alt_str, "1", YX (char *)NULL, "Use alternate query string"}, YX {"-alt", NoArg, OptBool, (caddr_t) &use_alt_str, "0", YX (char *)NULL, "Don't use alternate query string"}, YX {"+always", NoArg, OptBool, (caddr_t) &always_send, "1", YX (char *)NULL, "Always send the terminal query string"}, YX {"-always", NoArg, OptBool, (caddr_t) &always_send, "0", YX (char *)NULL, "Don't always send the terminal query string"}, YX {"-file", SepArg, OptStr, (caddr_t) &termfile, __ NULL, YX "", "Use to query terminal"}, YX {"+longname",NoArg, OptBool, (caddr_t) &longname, "1", YX (char *)NULL, "Output only the long (verbose) terminal name"}, YX {"-longname",NoArg, OptBool, (caddr_t) &longname, "0", YX (char *)NULL, "Don't output the long (verbose) terminal name"}, YX {"+quiet", NoArg, OptBool, (caddr_t) &quiet, "1", YX (char *)NULL, "Enable quiet mode"}, YX {"-quiet", NoArg, OptBool, (caddr_t) &quiet, "0", YX (char *)NULL, "Disable quiet mode"}, YX {"+sent", NoArg, OptBool, (caddr_t) &sent_chars, "1", YX (char *)NULL, "Display the characters the terminal sent"}, YX {"-sent", NoArg, OptBool, (caddr_t) &sent_chars, "0", YX (char *)NULL, "Don't display the characters the terminal sent"}, YX {"+timeout",NoArg, OptBool, (caddr_t) &towait, "1", YX (char *)NULL, "Enable time out wait"}, YX {"-timeout",NoArg, OptBool, (caddr_t) &towait, "0", YX (char *)NULL, "Disable time out wait"}, YX {"+usrtab", NoArg, OptBool, (caddr_t) &do_usrtabfile, "1", YX (char *)NULL, "Enable using ~/.qtermtab"}, YX {"-usrtab", NoArg, OptBool, (caddr_t) &do_usrtabfile, "0", YX (char *)NULL, "Disable using ~/.qtermtab"}, YX {"-wait", SepArg, OptInt, (caddr_t) &almwait, __ NULL, YX "", "Wait (timeout) period (in seconds)"}, YX {"+watch", NoArg, OptBool, (caddr_t) &watch_chars, "1", YX (char *)NULL, "Watch the characters sent and recieved"}, YX {"-watch", NoArg, OptBool, (caddr_t) &watch_chars, "0", YX (char *)NULL, "Don't watch the characters sent and recieved"}, YX {"+systab", NoArg, OptBool, (caddr_t) &do_usrtabfile, "1", YX (char *)NULL, "Enable using system qtermtab file"}, YX {"-systab", NoArg, OptBool, (caddr_t) &do_systabfile, "0", YX (char *)NULL, "Disable using system qtermtab file"}, YX {"-debug", ArgHidden|NoArg, OptInt, (caddr_t) &debug, "1", YX (char *)NULL, "Enable debug mode"}, YX}; YX YXFILE *fopen(); YXchar *decode(); YXchar *getenv(); YXchar *malloc(); YXchar *re_comp(); YXchar *strcat(); YXchar *xmalloc(); YXint alarm(); YXint found = FALSE; YXint modes_set = FALSE; YXjmp_buf env; YXstruct termtable *compare(); YXstruct passwd *getpwuid(); YXvoid catch(); YXvoid done(); YXvoid dprintf(); YXvoid exit(); YXvoid myperror(); YXvoid mktable(); YXvoid notrecognized(); YXvoid proctab(); YXvoid wakeup(); YX#ifdef USG5 YXchar *regcmp(); YX#endif /* USG5 */ YX YXmain(argc, argv) YX int argc; YX char **argv; YX{ YX config(argc, argv); YX setmodes(); YX mktable(); YX proctab((struct termtable *)NULL); YX resetmodes(); YX YX if (!found) { YX notrecognized(); YX } YX YX exit(0); YX} YX YX/* YX * Config() - Perform configuration operations. YX */ YXconfig(argc, argv) YX int argc; YX char **argv; YX{ YX progname = argv[0]; YX YX /* YX * Parse command line args YX */ YX if (ParseOptions(opts, Num_Opts(opts), argc, argv) < 0) { YX done(1); YX /*NOTREACHED*/ YX } YX YX /* YX * Check results of command line parsing and perform any YX * needed post processing. YX */ YX YX if (longname) YX quiet = TRUE; YX YX if (almwait == 0) { YX (void) fprintf(stderr, YX "%s: Alarm (wait) time must be greater than 0.\n", YX progname); YX done(1); YX /*NOTREACHED*/ YX } YX YX#ifdef OPT_COMPAT YX /* YX * Kludgy stuff to be backwards compatable for command line options. YX */ YX if (termfile) { YX if (strcmp(termfile, fFLAG) == 0) { YX do_usrtabfile = TRUE; YX do_systabfile = TRUE; YX termfile = NULL; YX } else if (strcmp(termfile, FFLAG) == 0) { YX do_usrtabfile = TRUE; YX do_systabfile = FALSE; YX termfile = NULL; YX } YX } YX#endif /*OPT_COMPAT*/ YX YX dprintf("[ %s debug mode enabled ]\n\n", progname); YX} YX YX/* YX * Set signal catches and terminal modes YX */ YXsetmodes() YX{ YX if (!isatty(0)) { YX (void) fprintf(stderr, "%s: Not a tty.\n", progname); YX done(0); YX /*NOTREACHED*/ YX } YX YX /* YX * Set output buffers YX */ YX setbuf(stdout, (char *)0); YX if (debug) YX setbuf(stderr, (char *)0); YX YX /* YX * Cleanup terminal modes & such if we are killed YX */ YX (void) signal(SIGINT, catch); YX (void) signal(SIGHUP, catch); YX (void) signal(SIGTERM, catch); YX YX /* YX * Set terminal modes YX */ YX#ifdef USG5 YX if (ioctl(_tty_ch, TCGETA, &_otty) < 0) YX#else YX if (ioctl(_tty_ch, TIOCGETP, &_tty) < 0) YX#endif /* USG5 */ YX { YX myperror("gtty"); YX done(1); YX /*NOTREACHED*/ YX } YX#ifdef USG5 YX _ntty = _otty; YX#endif /* USG5 */ YX YX if (crmode() < 0) { YX myperror("crmode"); YX done(1); YX /*NOTREACHED*/ YX } YX YX if (noecho() < 0) { YX myperror("noecho"); YX done(1); YX /*NOTREACHED*/ YX } YX modes_set = TRUE; YX} YX YX/* YX * Reset terminal modes YX */ YXresetmodes() YX{ YX if (modes_set) { YX (void) nocrmode(); YX (void) echo(); YX } YX} YX YX/* YX * Print info about terminal structure t. YX */ YXprinfo(t, what) YX struct termtable *t; YX int what; YX{ YX int len = 0; YX int st = FALSE; YX YX if (t && t->qt_termname && (recvbuf[0] != (char) NULL)) { YX if (debug || sent_chars) { YX len = strlen(recvbuf); YX (void) fprintf(stderr, "%s received %d character%s:", YX progname, len, (len == 1) ? "" : "s"); YX (void) fprintf(stderr, " %s\n", decode(recvbuf)); YX } YX YX if (!quiet) { YX (void) fprintf(stderr, "Terminal recognized as %s", YX t->qt_termname); YX if (t->qt_fullname && t->qt_fullname[0]) YX (void) fprintf(stderr, " (%s)\n", t->qt_fullname); YX else YX (void) fprintf(stderr, "\n"); YX } YX YX if (longname) { YX if (t->qt_fullname && t->qt_fullname[0]) YX (void) printf("%s\n", t->qt_fullname); YX else YX (void) fprintf(stderr, "%s: No full terminal name for %s.\n", YX progname, t->qt_termname); YX } else { YX (void) printf("%s\n", t->qt_termname); YX } YX YX found = TRUE; YX done(0); YX /*NOTREACHED*/ YX } else { YX found = FALSE; YX YX if (what) { YX notrecognized(); YX done(1); YX /*NOTREACHED*/ YX } YX } YX YX return(st); YX} YX YX/* YX * compare - actually compare what we received against the table. YX */ YXstruct termtable *compare(str) YX char *str; YX{ YX#ifdef USG5 YX register char *reexp; YX#endif /* USG5 */ YX register struct termtable *t; YX char buf[BUFSIZ]; YX YX dprintf("compare %s\n", (str && str[0]) ? decode(str) : "nothing"); YX (void) alarm((unsigned)0); YX YX if (strlen(str) == 0) YX return(NULL); YX YX for (t = termtab; t != NULL; t = t->nxt) { YX dprintf(" with %s ", decode(t->qt_recvstr)); YX (void) sprintf(buf, "^%s$", t->qt_recvstr); YX YX#ifdef USG5 YX if ((reexp = regcmp(buf, NULL)) == NULL) { YX#else YX if (re_comp((char *)buf) != NULL) { YX#endif /* USG5 */ YX (void) fprintf(stderr, "%s: bad regular expression: \"%s\"\n", YX progname, t->qt_recvstr); YX done(1); YX /*NOTREACHED*/ YX } YX YX#ifdef USG5 YX if (regex(reexp, str) != NULL) { YX#else YX if (re_exec(str) == 1) { YX#endif /* USG5 */ YX found = TRUE; YX dprintf("\tOK\n"); YX return(t); YX } YX YX dprintf("\tNOPE\n"); YX#ifdef USG5 YX (void) free(reexp); YX#endif /* USG5 */ YX } YX found = FALSE; YX YX return(NULL); YX} YX YX/* YX * getch - read in a character at a time. YX */ YXgetch() YX{ YX char c; YX YX (void) read(0, &c, 1); YX YX return(c & CHAR_MASK); YX} YX YX/* YX * decode - print str in a readable fashion YX */ YXchar *decode(str) YX char *str; YX{ YX register int len; YX static char buf[BUFSIZ]; YX char tmp[10]; YX YX if (!str) YX return("(null)"); YX YX (void) strcpy(buf, ""); YX while (*str) { YX if (*str == ESC) { YX (void) strcat(buf, " "); YX } else if ((*str <= 33) || (*str >= 127)) { YX (void) sprintf(tmp,"\\%#o ", (unsigned) *str); YX (void) strcat(buf, tmp); YX } else { YX (void) sprintf(tmp,"%c ", *str); YX (void) strcat(buf, tmp); YX } YX ++str; YX } YX YX len = strlen(buf); YX if (len && buf[len - 1] == ' ') { YX buf[len - 1] = (char) NULL; YX } YX YX return(buf); YX} YX YX/* YX * Make a termtab table YX */ YXvoid mktable() YX{ YX char file[BUFSIZ]; YX struct passwd *pwd; YX char *home; YX YX dprintf("[ initilizing term table... ]\n"); YX YX if (termfile != NULL) { YX (void) readtabfile(termfile, FALSE); YX } YX YX if (do_usrtabfile) { YX /* YX * Try to read the user's own table YX */ YX if ((home = getenv("HOME")) == NULL) { YX if ((pwd = getpwuid(getuid())) == NULL) { YX (void) fprintf(stderr, YX "%s: Cannot find user info for uid %d.\n", YX progname, getuid()); YX done(1); YX /*NOTREACHED*/ YX } YX home = pwd->pw_dir; YX } YX YX (void) sprintf(file, "%s/%s", home, USRFILE); YX if (readtabfile(file, TRUE) < 0) { YX (void) sprintf(file, "%s/%s", home, OLDUSRFILE); YX (void) readtabfile(file, TRUE); YX } YX } YX YX if (do_systabfile) YX (void) readtabfile(TABFILE, FALSE); YX YX dprintf("[ mktable done ]\n"); YX} YX YXint readtabfile(file, bequiet) YX char *file; YX int bequiet; YX{ YX static int line = 0; YX char lbuf[4][BUFSIZ]; YX char buf[BUFSIZ]; YX FILE *fd; YX char *p, *fixctl(); YX char *errmsg = NULL; YX struct termtable *t; YX YX if ((fd = fopen(file, "r")) == NULL) { YX if (bequiet) { YX dprintf("[ tab file '%s' can not read ]\n", file); YX return(-1); YX } YX myperror(file); YX done(1); YX /*NOTREACHED*/ YX } YX YX dprintf("[ Read tab file '%s' ]\n", file); YX YX line = 0; YX while (fgets(buf, sizeof(buf), fd)) { YX ++line; YX YX if (buf[0] == '#' || buf[0] == '\n') YX continue; YX YX lbuf[0][0] = lbuf[1][0] = lbuf[2][0] = lbuf[3][0] = (char) NULL; YX YX (void) sscanf(buf, "%s%s%s\t%[^\n]", YX lbuf[0], lbuf[1], lbuf[2], lbuf[3]); YX YX if (lbuf[0][0] == (char) NULL) YX continue; YX YX if (lbuf[1][0] == (char) NULL) YX errmsg = "receive string"; YX YX if (lbuf[2][0] == (char) NULL) YX errmsg = "terminal name"; YX YX if (errmsg) { YX (void) fprintf(stderr, "%s: Line %d of %s: Error parsing %s.\n", YX progname, line, file, errmsg); YX done(1); YX /*NOTREACHED*/ YX } YX YX t = (struct termtable *) xmalloc(sizeof(struct termtable)); YX YX if (use_alt_str) YX p = fixctl(ALTSEND, 0); YX else YX p = fixctl(lbuf[0], 0); YX YX t->qt_sendstr = (char *) xmalloc(strlen(p)+1); YX (void) strcpy(t->qt_sendstr, p); YX YX p = fixctl(lbuf[1], 1); YX t->qt_recvstr = (char *) xmalloc(strlen(p)+1); YX (void) strcpy(t->qt_recvstr, p); YX YX t->qt_termname = (char *) xmalloc(strlen(lbuf[2])+1); YX (void) strcpy(t->qt_termname, lbuf[2]); YX YX t->qt_fullname = (char *) xmalloc(strlen(lbuf[3])+1); YX (void) strcpy(t->qt_fullname, lbuf[3]); YX YX dprintf("\n Send String = %s\n", decode(t->qt_sendstr)); YX dprintf("Expect String = %s\n", decode(t->qt_recvstr)); YX dprintf(" Terminal = '%s'\n", t->qt_termname); YX dprintf(" Full Name = '%s'\n", t->qt_fullname); YX YX (void) addterm(t); YX } YX YX return(0); YX} YX YX/* YX * Add termtab (n) entry to main termtab. YX */ YXint addterm(n) YX struct termtable *n; YX{ YX register struct termtable *t; YX YX if (!n) YX return(-1); YX YX n->nxt = NULL; YX YX if (termtab == NULL) { YX termtab = n; YX } else { YX t = termtab; YX while(t && t->nxt) YX t = t->nxt; YX t->nxt = n; YX } YX YX return(0); YX} YX YX/* YX * Listen for a response. YX */ YXvoid qterm_listen(q) YX struct termtable *q; YX{ YX static int i, len; YX register char c; YX char end; YX YX (void) alarm((unsigned)0); YX (void) strcpy(recvbuf, ""); YX i = 0; YX YX len = strlen(q->qt_recvstr); YX YX if (len) { YX end = q->qt_recvstr[len - 1]; YX } else { YX end = 'c'; /* Fairly standard ANSI default */ YX } YX YX dprintf("\nlisten for %s\t [ len = %d, end = `%c' ]\n", YX decode(q->qt_recvstr), len, end); YX YX /* YX * If we don't get an initial character, bounce out YX * of here and finish with done(0). YX */ YX if (setjmp(env)) { YX if (found) { YX done(0); YX /*NOTREACHED*/ YX } YX (void) fflush(stdin); YX proctab(q->nxt); YX } else { YX (void) signal(SIGALRM, wakeup); YX (void) alarm((unsigned)almwait); YX recvbuf[0] = getch(); YX (void) alarm((unsigned)0); YX } YX YX /* YX * Read in remaining response. Loop until ending character YX * is received or until alarm goes off. If towait is set, YX * then let alarm go off. YX */ YX for (i = 1, c = -1; (!towait && (c != end)) || towait; ) { YX if (setjmp(env)) { YX recvbuf[i] = (char) NULL; YX return; YX } else { YX (void) signal(SIGALRM, wakeup); YX (void) alarm((unsigned)almwait); YX c = getch(); YX (void) alarm((unsigned)0); YX } YX recvbuf[i++] = c; YX } YX recvbuf[i] = (char) NULL; YX YX dprintf("listen done. read %d chars.\n\n", i); YX} YX YX/* YX * Print a message since we didn't recognize this terminal. YX */ YXvoid notrecognized() YX{ YX char *envterm; YX YX if ((envterm = getenv("TERM")) == NULL) YX envterm = "dumb"; YX YX if (!quiet) YX (void) fprintf(stderr, YX "Terminal NOT recognized - defaults to \"%s\".\n", YX envterm); YX YX puts(envterm); YX} YX YX/* YX * Process entries in the termtable. YX */ YXvoid proctab(t) YX struct termtable *t; YX{ YX int st = FALSE; YX static int firsttime = TRUE; YX static struct termtable *lastt; YX YX dprintf("\n[ Processing entries ] \n"); YX YX if (firsttime) { YX t = termtab; YX lastt = NULL; YX } YX YX while ((!found || do_usrtabfile) && t && t->qt_sendstr && !st) { YX /* YX * If this is our first time or the sendstr is the same as YX * last time, don't send it again. YX */ YX if (always_send || firsttime || lastt == NULL || YX strcmp(t->qt_sendstr, lastt->qt_sendstr) != 0) { YX YX if (firsttime) YX firsttime = FALSE; YX YX if (watch_chars) YX (void) printf("Send: %s\n", decode(t->qt_sendstr)); YX YX (void) fflush(stdin); YX (void) fprintf(stderr, "%s", t->qt_sendstr); YX (void) fflush(stderr); YX YX lastt = t; YX (void) qterm_listen(t); YX YX if (watch_chars) YX (void) printf("\tRead: %s\n", decode(recvbuf)); YX } YX YX st = prinfo(compare(recvbuf), FALSE); YX YX lastt = t; YX t = t->nxt; YX } YX YX if (!found) YX notrecognized(); YX YX done(0); YX /*NOTREACHED*/ YX} YX YXchar *fixctl(str, rex) YX char *str; YX int rex; YX{ YX register int i; YX static char buf[BUFSIZ]; YX YX for (i = 0; str && *str; ) { YX switch (*str) { YX YX case '\\': YX if (isdigit(*++str)) { YX buf[i] = 0; YX while (isdigit(*str)) YX buf[i] = (char) (((int)buf[i] * 8) + YX (int)*str++ - (int) '0'); YX i++; YX } else YX buf[i++] = *str++; YX continue; YX YX case '^': YX switch (*++str) { YX case '?': YX buf[i++] = '\177'; YX break; YX default: YX buf[i++] = *str & 037; YX break; YX } YX break; YX YX /* Special R.E. symbols */ YX case '[': YX case '*': YX case '.': YX case '$': YX case '{': YX case '(': YX if (rex) YX buf[i++] = '\\'; YX YX default: YX buf[i++] = *str; YX } YX *++str; YX } YX YX buf[i] = (char) NULL; YX YX return(buf); YX} YX YX/* YX * xmalloc - Do a malloc with error checking. YX */ YXchar *xmalloc(size) YX int size; YX{ YX char *p; YX YX if ((p = malloc((unsigned) size)) == NULL) { YX myperror("malloc"); YX done(1); YX /*NOTREACHED*/ YX } YX YX return(p); YX} YX YX#ifdef HAS_VARARGS YXvoid dprintf(va_alist) YX va_dcl YX{ YX va_list args; YX char *fmt; YX YX if (!debug) YX return; YX YX va_start(args); YX fmt = (char *) va_arg(args, char *); YX (void) vprintf(fmt, args); YX va_end(args()); YX (void) fflush(stdout); YX} YX YX#else /*HAS_VARARGS*/ YX YXvoid dprintf(fmt, a1, a2, a3, a4, a5, a6) YX char *fmt; YX{ YX if (!debug) YX return; YX YX (void) printf(fmt, a1, a2, a3, a4, a5, a6); YX (void) fflush(stdout); YX} YX#endif /*HAS_VARARGS*/ YX YX/* YX * Catch kill signals and cleanup. YX */ YXvoid catch() YX{ YX done(2); YX /*NOTREACHED*/ YX} YX YXvoid wakeup() YX{ YX dprintf("wakeup called\n"); YX longjmp(env, 1); YX} YX YXvoid myperror(msg) YX char *msg; YX{ YX (void) fprintf(stderr, "%s: ", progname); YX perror(msg); YX} YX YX/* YX * Reset terminal and exit with status s. YX */ YXvoid done(s) YX int s; YX{ YX resetmodes(); YX exit(s); YX} YSHAR_EOF Ychmod 644 'qterm.c' Yfi Yif test -f 'options.c' Ythen Y echo shar: "will not over-write existing file 'options.c'" Yelse Ysed 's/^X//' << \SHAR_EOF > 'options.c' YX/* YX * Copyright (c) 1990 Michael A. Cooper. YX * This software may be freely distributed provided it is not sold for YX * profit and the author is credited appropriately. YX */ YX YX#ifndef lint YXstatic char *RCSid = "$Header: /am/sol/src/common/usc/lib/libgen/RCS/options.c,v 1.13 90/12/15 18:13:28 mcooper Exp $"; YX#endif YX YX/* YX * $Log: options.c,v $ YX * Revision 1.13 90/12/15 18:13:28 mcooper YX * Add copywrite notice. YX * YX * Revision 1.12 90/12/15 17:51:46 mcooper YX * Add #ifdef HAS_VARARGS around include for . YX * YX * Revision 1.11 90/11/13 16:39:28 mcooper YX * Add #ifdef HAS_VARARGS for systems without YX * varargs. YX * YX * Revision 1.10 90/11/13 15:28:01 mcooper YX * - Add OptBool cvtarg routine. YX * - Print default values in HelpOptions() YX * when appropriate. YX * YX * Revision 1.9 90/11/13 15:19:00 mcooper YX * Added supported for options being both YX * SepArg and StickyArg. YX * YX * Revision 1.8 90/10/30 21:02:31 mcooper YX * Need to exit() if -help is specified. YX * YX * Revision 1.7 90/10/30 20:24:33 mcooper YX * Fixed bug in UsageString(). YX * YX * Revision 1.6 90/10/30 19:53:05 mcooper YX * Cleaned up some NeXT cc and lint stuff. YX * YX * Revision 1.5 90/10/30 19:45:31 mcooper YX * Remove unneeded paramter to HelpOptions(). YX * YX * Revision 1.4 90/10/29 14:47:42 mcooper YX * Added real function UsageString() to YX * handle formating usage option strings. YX * YX * Revision 1.3 90/10/29 14:17:00 mcooper YX * Allow options to be abbreviated YX * (for all non StickArg options). YX * YX * Revision 1.2 90/10/26 15:56:11 mcooper YX * - Fix bug in SepArg code that ate arguments. YX * - Cleanup help message. YX * - Add ArgHidden code. YX * YX * Revision 1.1 90/10/26 14:42:51 mcooper YX * Initial revision YX * YX */ YX YX/* YX * Functions to parse options. YX */ YX YX#include "options.h" YX#ifdef HAS_VARARGS YX#include YX#endif YX YXchar *OptionChars = "-+"; /* Default option switching characters */ YXchar *ProgramName = NULL; /* Name of this program */ YXchar *UsageString(); YXstatic int isopt(); YXstatic int suppress_help_msg = 0; YXchar *strcat(); YX YX/* YX * ParseOptions - Parse options found in argv using "options". YX * Returns the number of options parsed if there YX * were no errors. Returns -1 if an error occurs. YX */ YXint ParseOptions(options, num_options, argc, argv) YX OptionDescRec *options; YX int num_options; YX int argc; YX char **argv; YX{ YX OptionDescRec *opt; YX register int x; YX char *p; YX YX if (ProgramName == NULL) YX ProgramName = argv[0]; YX YX#ifdef OPTION_DEBUG YX (void) printf("Option list is:\n"); YX for (x = 0; x < num_options; ++x) { YX opt = &options[x]; YX (void) printf("%s\n", opt->option); YX } YX YX (void) printf("Arguments (%d):", argc); YX for (x = 0; x < argc; ++x) { YX (void) printf(" %s", argv[x]); YX } YX (void) printf("\n"); YX#endif /* OPTION_DEBUG */ YX YX for (x = 1; x < argc; ++x) { YX if (strcmp(HELPSTR, argv[x]) == 0) { YX HelpOptions(options, num_options, (char **)NULL); YX exit(0); YX } YX YX opt = FindOption(options, num_options, argv[x]); YX if (opt == NULL) { YX if (isopt(argv[x])) { /* this was suppose to be an option */ YX UsageOptions(options, num_options, argv[x]); YX return(-1); YX } else { /* must be end of options */ YX break; YX } YX } YX YX if (opt->flags & NoArg) { YX if (!(*opt->cvtarg)(opt, opt->value, FALSE)) { YX UsageOptions(options, num_options, opt->option); YX return(-1); YX } YX } else if (opt->flags & IsArg) { YX if (!(*opt->cvtarg)(opt, opt->option, FALSE)) { YX UsageOptions(options, num_options, opt->option); YX return(-1); YX } YX } else if ((opt->flags & StickyArg) && (opt->flags & SepArg)) { YX p = (char *) &argv[x][strlen(opt->option)]; YX if (!*p) { /*** SepArg ***/ YX if (x + 1 >= argc || isopt(argv[x+1])) { YX if (opt->value == (caddr_t) NULL) { YX UserError("%s: Option requires an argument.", argv[x]); YX UsageOptions(options, num_options, opt->option); YX return(-1); YX } YX p = opt->value; YX } else { YX p = argv[++x]; YX } YX } YX if (!(*opt->cvtarg)(opt, p, TRUE)) { YX UsageOptions(options, num_options, opt->option); YX return(-1); YX } YX } else if (opt->flags & StickyArg) { YX p = (char *) &argv[x][strlen(opt->option)]; YX if (!*p) { YX if (opt->value == (caddr_t) NULL) { YX UserError("%s: Option requires an argument.", argv[x]); YX UsageOptions(options, num_options, opt->option); YX return(-1); YX } else { YX p = opt->value; YX } YX } YX if (!(*opt->cvtarg)(opt, p, TRUE)) { YX UsageOptions(options, num_options, opt->option); YX return(-1); YX } YX } else if (opt->flags & SepArg) { YX if (x + 1 >= argc || isopt(argv[x+1])) { YX if (opt->value == (caddr_t) NULL) { YX UserError("%s: Option requires an argument.", argv[x]); YX UsageOptions(options, num_options, opt->option); YX return(-1); YX } else { YX p = opt->value; YX } YX } else { YX p = argv[++x]; YX } YX if (!(*opt->cvtarg)(opt, p, TRUE)) { YX UsageOptions(options, num_options, opt->option); YX return(-1); YX } YX } else if (opt->flags & SkipArg) { YX x += 2; YX } else if (opt->flags & SkipLine) { YX return(x); YX } else if (opt->flags & SkipNArgs) { YX if (opt->value) { YX x += atoi(opt->value); YX } else { YX UserError("Internal Error: No 'value' set for SkipNArgs."); YX return(-1); YX } YX } else { YX UserError("Internal Error: Unknown argument type for option '%s'.", YX opt->option); YX return(-1); YX } YX } YX YX return(x); YX} YX YX/* YX * FindOption - Find "option" in "options". Returns NULL if not found. YX */ YXOptionDescRec *FindOption(options, num_options, option) YX OptionDescRec *options; YX int num_options; YX char *option; YX{ YX OptionDescRec *opt; YX register int x; YX YX for (x = 0; x < num_options; ++x) { YX opt = &options[x]; YX if (opt->flags & StickyArg) { YX if (strncmp(option, opt->option, strlen(opt->option)) == 0) YX return(opt); YX } else { YX if (strncmp(option, opt->option, strlen(option)) == 0) YX return(opt); YX } YX } YX YX return(NULL); YX} YX YX/* YX * isopt - Is "str" an option string? Compare first char of str against YX * list of option switch characters. Returns TRUE if it is an option. YX */ YXstatic int isopt(str) YX char *str; YX{ YX register char *p; YX YX for (p = OptionChars; p && *p; *++p) { YX if (*str == *p) { YX return(TRUE); YX } YX } YX YX return(FALSE); YX} YX YX/* YX * UsageOptions - Print a usage message based on "options". YX */ YXvoid UsageOptions(options, num_opts, badOption) YX OptionDescRec *options; YX int num_opts; YX char *badOption; YX{ YX OptionDescRec *opt; YX char *optstr; YX register int x; YX int col, len; YX YX if (badOption) YX (void) fprintf (stderr, "%s: bad command line option \"%s\"\r\n\n", YX ProgramName, badOption); YX YX (void) fprintf (stderr, "usage: %s", ProgramName); YX col = 8 + strlen(ProgramName); YX for (x = 0; x < num_opts; x++) { YX opt = &options[x]; YX if (opt->flags & ArgHidden) YX continue; YX optstr = UsageString(opt); YX len = strlen(optstr) + 3; /* space [ string ] */ YX if (col + len > 79) { YX (void) fprintf (stderr, "\r\n "); /* 3 spaces */ YX col = 3; YX } YX (void) fprintf (stderr, " [%s]", optstr); YX col += len; YX } YX YX if (suppress_help_msg) YX (void) fprintf(stderr, "\r\n\n"); YX else YX (void) fprintf(stderr, YX "\r\n\nType \"%s %s\" for a full description.\r\n\n", YX ProgramName, HELPSTR); YX} YX YX/* YX * HelpOptions - Print a nice help/usage message based on options. YX */ YXvoid HelpOptions(options, num_opts, message) YX OptionDescRec *options; YX int num_opts; YX char **message; YX{ YX OptionDescRec *opt; YX register int x; YX char **cpp; YX YX suppress_help_msg = 1; YX UsageOptions(options, num_opts, (char *)NULL); YX suppress_help_msg = 0; YX YX (void) fprintf (stderr, "where options include:\n"); YX for (x = 0; x < num_opts; x++) { YX opt = &options[x]; YX if (opt->flags & ArgHidden) YX continue; YX (void) fprintf (stderr, " %-28s %s\n", UsageString(opt), YX (opt->desc) ? opt->desc : ""); YX if (opt->value && opt->cvtarg != OptBool) YX (void) fprintf (stderr, " %-28s [ Default value is %s ]\n", YX "", opt->value); YX } YX YX if (message) { YX (void) putc ('\n', stderr); YX for (cpp = message; *cpp; cpp++) { YX (void) fputs (*cpp, stderr); YX (void) putc ('\n', stderr); YX } YX (void) putc ('\n', stderr); YX } YX} YX YX/* YX * UserError - Print a user error. YX */ YX#ifdef HAS_VARARGS YXvoid UserError(va_alist) YX va_dcl YX{ YX va_list args; YX char *fmt; YX YX va_start(args); YX if (ProgramName) YX (void) fprintf(stderr, "%s: ", ProgramName); YX fmt = (char *) va_arg(args, char *); YX (void) vfprintf(stderr, fmt, args); YX va_end(args); YX (void) fprintf(stderr, "\n"); YX} YX#else YXvoid UserError(fmt, a1, a2, a3, a4, a5, a6) YX char *fmt; YX{ YX if (ProgramName) YX (void) fprintf(stderr, "%s: ", ProgramName); YX (void) fprintf(stderr, fmt, a1, a2, a3, a4, a5, a6); YX (void) fprintf(stderr, "\n"); YX} YX#endif YX YXOptBool(opt, value, docopy) YX OptionDescRec *opt; YX caddr_t value; YX int docopy; /*ARGSUSED*/ YX{ YX char *vpp; YX YX *(int *) opt->valp = (int) strtol(value, &vpp, 0); YX if (*vpp) { YX UserError("Invalid integer argument for '%s'.", opt->option); YX return(FALSE); YX } else { YX return(TRUE); YX } YX} YX YXOptInt(opt, value, docopy) YX OptionDescRec *opt; YX caddr_t value; YX int docopy; /*ARGSUSED*/ YX{ YX char *vpp; YX YX *(int *) opt->valp = (int) strtol(value, &vpp, 0); YX if (*vpp) { YX UserError("Invalid integer argument for '%s'.", opt->option); YX return(FALSE); YX } else { YX return(TRUE); YX } YX} YX YXOptShort(opt, value, docopy) YX OptionDescRec *opt; YX caddr_t value; YX int docopy; /*ARGSUSED*/ YX{ YX char *vpp; YX YX *(short *) opt->valp = (short) strtol(value, &vpp, 0); YX if (*vpp) { YX UserError("Invalid integer argument for '%s'.", opt->option); YX return(FALSE); YX } else { YX return(TRUE); YX } YX} YX YXOptLong(opt, value, docopy) YX OptionDescRec *opt; YX caddr_t value; YX int docopy; /*ARGSUSED*/ YX{ YX char *vpp; YX YX *(long *) opt->valp = (long) strtol(value, &vpp, 0); YX if (*vpp) { YX UserError("Invalid integer argument for '%s'.", opt->option); YX return(FALSE); YX } else { YX return(TRUE); YX } YX} YX YXOptStr(opt, value, docopy) YX OptionDescRec *opt; YX caddr_t value; YX int docopy; YX{ YX char *p; YX YX if (docopy) { YX if ((p = (char *) malloc((unsigned)strlen(value)+1)) == NULL) { YX UserError("Cannot malloc memory: %s", SYSERR); YX return(FALSE); YX } YX (void) strcpy(p, value); YX } else { YX p = value; YX } YX YX *(char **) opt->valp = p; YX YX return(TRUE); YX} YX YXstatic char *UsageString(opt) YX OptionDescRec *opt; YX{ YX static char buf[BUFSIZ], buf2[BUFSIZ]; YX YX (void) sprintf(buf, opt->option); YX (void) strcpy(buf2, ""); YX if (opt->usage) { YX (void) sprintf(buf2, "%s%s%s%s", YX ((opt->flags & StickyArg) && YX !((opt->flags & StickyArg) && (opt->flags & SepArg))) YX ? "" : " ", YX (opt->value) ? "[" : "", YX opt->usage, YX (opt->value) ? "]" : "" YX ); YX } YX (void) strcat(buf, buf2); YX YX return(buf); YX} YSHAR_EOF Ychmod 644 'options.c' Yfi Yif test -f 'qterm.h' Ythen Y echo shar: "will not over-write existing file 'qterm.h'" Yelse Ysed 's/^X//' << \SHAR_EOF > 'qterm.h' YX/* YX * Copyright (c) 1990 Michael A. Cooper. YX * This software may be freely distributed provided it is not sold for YX * profit and the author is credited appropriately. YX */ YX YX/* YX * $Header: /src/common/usc/bin/qterm/RCS/qterm.h,v 5.1 1991/03/12 00:46:24 mcooper Exp $ YX *------------------------------------------------------------------ YX * YX * $Source: /src/common/usc/bin/qterm/RCS/qterm.h,v $ YX * $Revision: 5.1 $ YX * $Date: 1991/03/12 00:46:24 $ YX * $State: Exp $ YX * $Author: mcooper $ YX * $Locker: $ YX * YX *------------------------------------------------------------------ YX * YX * Michael A. Cooper YX * Research and Development Group YX * University Computing Services YX * University of Southern California YX * (mcooper@usc.edu) YX * YX *------------------------------------------------------------------ YX * $Log: qterm.h,v $ YX * Revision 5.1 1991/03/12 00:46:24 mcooper YX * - Changed CMASK to CHAR_CMASK to avoid conflict YX * under AIX 3.1. YX * - Expand tabs. YX * YX * Revision 5.0 1990/12/15 18:30:45 mcooper YX * Version 5. YX * YX * Revision 4.1 90/12/15 18:14:27 mcooper YX * Add copywrite. YX * YX * Revision 4.0 88/03/08 19:31:23 mcooper YX * Version 4. YX * YX * Revision 3.2 88/03/08 19:28:52 mcooper YX * Major rewrite. YX * YX * Revision 3.1 88/03/08 15:32:16 mcooper YX * Changed around user's qtermtab YX * file names. YX * YX * Revision 3.0 87/06/30 19:09:04 mcooper YX * Release of version 3. YX * YX * Revision 2.4 87/06/30 19:02:28 mcooper YX * WAIT changed to 2 for slow systems. YX * YX *------------------------------------------------------------------ YX */ YX YX YX YX#ifndef TABFILE YX# define TABFILE "/usr/local/lib/qtermtab" /* Default qtermtab file */ YX#endif YX#define USRFILE ".qtermtab" /* User's qtermtab file */ YX#define OLDUSRFILE ".qterm" /* Old user qtermtab file */ YX#define ALTSEND "\033[c" /* Alternate query string */ YX#define WAIT 2 /* Timeout (in seconds) */ YX#define SIZE 512 /* Receive buffer size */ YX#define CHAR_MASK 0377 /* Character mask */ YX#define ESC '\033' /* ESCAPE */ YX YX#ifdef TRUE YX#undef TRUE YX#endif YX#ifdef FALSE YX#undef FALSE YX#endif YX#define TRUE 1 YX#define FALSE 0 YX YX#ifdef USG5 YX# define crmode() (_ntty.c_lflag &= ~ICANON,\ YX _ntty.c_cc[VMIN] = 1, _ntty.c_cc[VTIME] = 0,\ YX ioctl(_tty_ch, TCSETAF, &_ntty)) YX# define nocrmode() (_ntty.c_lflag |= ICANON,\ YX _ntty.c_cc[VMIN] = _otty.c_cc[VMIN],\ YX _ntty.c_cc[VTIME] = _otty.c_cc[VTIME],\ YX ioctl(_tty_ch, TCSETAF, &_ntty)) YX# define echo() (_ntty.c_lflag |= ECHO,\ YX ioctl(_tty_ch, TCSETAF, &_ntty)) YX# define noecho() (_ntty.c_lflag &= ~ECHO,\ YX ioctl(_tty_ch, TCSETAF, &_ntty)) YX#else /* !USG5 */ YX# define crmode() (_tty.sg_flags |= CBREAK,\ YX ioctl(_tty_ch, TIOCSETP, &_tty)) YX# define nocrmode() (_tty.sg_flags &= ~CBREAK,\ YX ioctl(_tty_ch, TIOCSETP, &_tty)) YX# define echo() (_tty.sg_flags |= ECHO, \ YX ioctl(_tty_ch, TIOCSETP, &_tty)) YX# define noecho() (_tty.sg_flags &= ~ECHO, \ YX ioctl(_tty_ch, TIOCSETP, &_tty)) YX#endif /* USG5 */ YX YX/* YX * Terminal table structure YX */ YXstruct termtable { YX char *qt_sendstr; /* String to send to terminal */ YX char *qt_recvstr; /* String expected in response */ YX char *qt_termname; /* Terminal name */ YX char *qt_fullname; /* Full terminal name & description */ YX struct termtable *nxt; /* Next structure */ YX}; YXstruct termtable *termtab = NULL; YSHAR_EOF Ychmod 644 'qterm.h' Yfi Yif test -f 'options.h' Ythen Y echo shar: "will not over-write existing file 'options.h'" Yelse Ysed 's/^X//' << \SHAR_EOF > 'options.h' YX/* YX * Copyright (c) 1990 Michael A. Cooper. YX * This software may be freely distributed provided it is not sold for YX * profit and the author is credited appropriately. YX */ YX YX/* YX * $Header: /am/sol/src/common/usc/lib/libgen/RCS/options.h,v 1.7 90/12/15 18:13:30 mcooper Exp $ YX * YX * $Log: options.h,v $ YX * Revision 1.7 90/12/15 18:13:30 mcooper YX * Add copywrite notice. YX * YX * Revision 1.6 90/11/13 15:28:39 mcooper YX * Add OptBool cvtarg routine. YX * YX * Revision 1.5 90/10/29 19:34:03 mcooper YX * Fixed comment for NoArg. YX * YX * Revision 1.4 90/10/29 18:48:43 mcooper YX * Cleanup some comments. YX * YX * Revision 1.3 90/10/29 14:47:29 mcooper YX * UsageString is now a real function. YX * YX * Revision 1.2 90/10/26 15:55:44 mcooper YX * Add defines for "__" and ArgHidden. YX * YX * Revision 1.1 90/10/26 14:42:53 mcooper YX * Initial revision YX * YX */ YX YX YX#include YX#include YX#include YX YX#define Num_Opts(o) (sizeof(o)/sizeof(OptionDescRec)) YX#define HELPSTR "-help" YX#define __ (caddr_t) YX YX#ifndef SYSERR YX#define SYSERR sys_errlist[errno] YX#endif YX#ifndef TRUE YX#define TRUE 1 YX#endif YX#ifndef FALSE YX#define FALSE 0 YX#endif YX YX/* YX * Values for OptionDescRec.flags. YX */ YX#define NoArg 0x001 /* No argument for this option. Use YX OptionDescRec.value. */ YX#define IsArg 0x002 /* Value is the option string itself */ YX#define SepArg 0x004 /* Value is in next argument in argv */ YX#define StickyArg 0x008 /* Value is characters immediately following YX option */ YX#define SkipArg 0x010 /* Ignore this option and the next argument in YX argv */ YX#define SkipLine 0x020 /* Ignore this option and the rest of argv */ YX#define SkipNArgs 0x040 /* Ignore this option and the next YX OptionDescRes.value arguments in argv */ YX#define ArgHidden 0x080 /* Don't show in usage or help messages */ YX YX/* YX * Option description record. YX */ YXtypedef struct { YX char *option; /* Option string in argv */ YX int flags; /* Flag bits */ YX int (*cvtarg)(); /* Function to convert argument */ YX caddr_t valp; /* Variable to set */ YX caddr_t value; /* Default value to provide */ YX char *usage; /* Usage message */ YX char *desc; /* Description message */ YX} OptionDescRec, *OptionDescList; YX YXvoid UsageOptions(); YXvoid HelpOptions(); YXvoid UserError(); YXint ParseOptions(); YXOptionDescRec *FindOption(); YX YXint OptBool(); YXint OptInt(); YXint OptLong(); YXint OptShort(); YXint OptStr(); YX YXextern char *OptionChars; YXextern int errno; YXextern char *sys_errlist[]; YXextern long strtol(); YXextern char *malloc(); YXextern char *strcpy(); YSHAR_EOF Ychmod 644 'options.h' Yfi Ychmod 755 . Ycd .. Yexit 0 Y# End of shell archive SHAR_EOF fi exit 0 # End of shell archive