C-KERMIT (Part 8 of 10)

gregg at okstate.UUCP gregg at okstate.UUCP
Fri Mar 8 17:49:00 AEST 1985



echo x - ckusr2.c
sed '1,$s/^X//' <<\!FUNKY!STUFF! > ckusr2.c
X/*  C K U S R 2  --  "User Interface" STRINGS module for Unix Kermit  */
X
X/*  This module separates long strings from the body of the ckuser module. */  
X
X#include "ckermi.h"
X#include "ckcmd.h"
X#include "ckuser.h"
X
Xextern char cmdbuf[];
Xextern int nrmt, nprm, dfloc;
Xextern char *dftty;
Xextern struct keytab prmtab[];
Xextern struct keytab remcmd[];
X
Xstatic
Xchar *hlp1[] = {
X"\n",
X"  Usage: kermit [-x arg [-x arg]...[-yyy]..]]\n",
X"   x is an option that requires an argument, y an option with no argument:\n",
X"     actions (* options also require -l and -b) --\n",
X"       -s file(s)   send (use '-s -' to send from stdin)\n",
X"       -r           receive\n",
X"       -k           receive to stdout\n",
X"     * -g file(s)   get remote file(s) from server (quote wildcards)\n",
X"       -a name      alternate name, used with -s, -r, -g\n",
X"       -x           enter server mode\n",
X"     * -f           finish remote server\n",
X"     * -c           connect before transaction\n",
X"     * -n           connect after transaction\n",
X"       -h           help - print this message\n",
X"     settings --\n",
X"       -l line      communication line device\n",
X"       -b baud      line speed, e.g. 1200\n",
X"       -i           binary file or Unix-to-Unix\n",
X"       -p x         parity, x is one of e,o,m,s,n\n",
X"       -t           line turnaround handshake = xon, half duplex\n",
X"       -w           don't write over preexisting files\n",
X"       -q    	     be quiet during file transfer\n",
X"       -d   	     log debugging info to debug.log\n",
X" If no action command is included, enter interactive dialog.\n",
X""
X};
X
X/*  U S A G E */
X
Xusage() {
X    conola(hlp1);
X}
X
X/*  Help string definitions  */
X
Xstatic char *tophlp[] = { "\n\
XType ? for a list of commands, type 'help x' for any command x.\n\
XWhile typing commands, use the following special characters:\n\n\
X DEL, RUBOUT, BACKSPACE, CTRL-H: Delete the most recent character typed.\n\
X CTRL-W: Delete the most recent word typed.\n",
X
X"\
X CTRL-U: Delete the current line.\n\
X CTRL-R: Redisplay the current line.\n\
X ?       (question mark) display help on the current command or field.\n\
X ESC     (Escape or Altmode) Attempt to complete the current field.\n",
X
X"\
X \\       (backslash) include the following character literally.\n\n\
XFrom Unix command level, type 'kermit -h' to get help about command line args.\
X\n",
X"" };
X
Xstatic char *hmxxbye = "\
XShut down and log out a remote Kermit server";
X
Xstatic char *hmxxclo = "\
XClose one of the following logs:\n\
X session, transaction, packet, debugging -- 'help log' for further info.";
X
Xstatic char *hmxxcon = "\
XConnect to a remote system via the tty device given in the\n\
Xmost recent 'set line' command";
X
Xstatic char *hmxxget = "\
XFormat: 'get filespec'.  Tell the remote Kermit server to send the named\n\
Xfiles.  If filespec is omitted, then you are prompted for the remote and\n\
Xlocal filenames separately.";
X
Xstatic char *hmxxlg[] = { "\
XRecord information in a log file:\n\n\
X debugging             Debugging information, to help track down\n\
X  (default debug.log)  bugs in the C-Kermit program.\n\n\
X packets               Kermit packets, to help track down protocol problems.\n\
X  (packet.log)\n\n",
X
X" session               Terminal session, during CONNECT command.\n\
X  (session.log)\n\n\
X transactions          Names and statistics about files transferred.\n\
X  (transaction.log)\n",
X"" } ;
X
Xstatic char *hmxxlogi[] = { "\
XSyntax: script text\n\n",
X"Login to a remote system using the text provided.  The login script\n",
X"is intended to operate similarly to uucp \"L.sys\" entries.\n",
X"A login script is a sequence of the form:\n\n",
X"	expect send [expect send] . . .\n\n",
X"where 'expect' is a prompt or message to be issued by the remote site, and\n",
X"'send' is the names, numbers, etc, to return.  The send may also be the\n",
X"keyword EOT, to send control-d, or BREAK, to send a break.  Letters in\n",
X"send may be prefixed by ~ to send special characters.  These are:\n",
X"~b backspace, ~s space, ~q '?', ~n linefeed, ~r return, ~c don\'t\n",
X"append a return, and ~o[o[o]] for octal of a character.  As with some \n",
X"uucp systems, sent strings are followed by ~r unless they end with ~c.\n\n",
X"Only the last 7 characters in each expect are matched.  A null expect,\n",
X"e.g. ~0 or two adjacent dashes, causes a short delay.  If you expect\n",
X"that a sequence might not arrive, as with uucp, conditional sequences\n",
X"may be expressed in the form:\n\n",
X"	-send-expect[-send-expect[...]]\n\n",
X"where dashed sequences are followed as long as previous expects fail.\n",
X"" };
X
Xstatic char *hmxxrc[] = { "\
XFormat: 'receive [filespec]'.  Wait for a file to arrive from the other\n\
XKermit, which must be given a 'send' command.  If the optional filespec is\n",
X
X"given, the (first) incoming file will be stored under that name, otherwise\n\
Xit will be stored under the name it arrives with.",
X"" } ;
X
Xstatic char *hmxxsen = "\
XFormat: 'send file1 [file2]'.  File1 may contain wildcard characters '*' or\n\
X'?'.  If no wildcards, then file2 may be used to specify the name file1 is\n\
Xsent under; if file2 is omitted, file1 is sent under its own name.";
X
Xstatic char *hmxxser = "\
XEnter server mode on the currently selected line.  All further commands\n\
Xwill be taken in packet form from the other Kermit program.";
X
Xstatic char *hmhset = "\
XThe 'set' command is used to establish various communication or file\n\
Xparameters.  The 'show' command can be used to display the values of\n\
X'set' parameters.  Help is available for each individual parameter;\n\
Xtype 'help set ?' to see what's available.\n";
X
Xstatic char *hmxychkt = "\
XType of packet block check to be used for error detection, 1, 2, or 3.\n\
XType 1 is standard, and catches most errors.  Types 2 and 3 specify more\n\
Xrigorous checking, at the cost of higher overhead.  Not all Kermit programs\n\
Xsupport types 2 and 3.\n";
X
Xstatic char *hmxyf[] = { "\
Xset file: names, type, warning, display.\n\n\
X'names' are normally 'converted', which means file names are converted\n\
Xto 'common form' during transmission; 'literal' means use filenames\n\
Xliterally (useful between like Unix systems).\n",
X
X"\n\
X'type' is normally 'text', in which conversion is done between Unix newlines\n\
Xand CRLF line delimiters; 'binary' means to do no conversion.  Use 'binary'\n\
Xfor executable programs or binary data.\n",
X
X"\n\
X'warning' is 'on' or 'off', normally off.  When off, incoming files will\n\
Xoverwrite existing files of the same name.  When on, new names will be\n\
Xgiven to incoming files whose names are the same as existing files.\n" ,
X
X"\n\
X'display' is normally 'on', causing file transfer progress to be displayed\n\
Xon your screen when in local mode.  'set display off' is useful for allowing\n\
Xfile transfers to proceed in the background.\n\n",
X"" } ;
X
Xstatic char *hmhrmt[] = { "\
XThe 'remote' command is used to send file management instructions to a\n\
Xremote Kermit server.  There should already be a Kermit running in server\n\
Xmode on the other end of the currently selected line.  Type 'remote ?' to\n",
X
X"\
Xsee a list of available remote commands.  Type 'help remote x' to get\n\
Xfurther information about a particular remote command 'x'.\n" ,
X""} ;
X
X/*  D O H L P  --  Give a help message  */
X
Xdohlp(xx) int xx; {
X    int x,y;
X
X    if (xx < 0) return(xx);
X    switch (xx) {
X
Xcase XXBYE:
X    return(hmsg(hmxxbye));
X
Xcase XXCLO:
X    return(hmsg(hmxxclo));
X
Xcase XXCON:
X    return(hmsg(hmxxcon));
X
Xcase XXCWD:
X    return(hmsg("Change Working Directory, equivalent to Unix 'cd' command"));
X
Xcase XXDEL:
X    return(hmsg("Delete a local file or files"));
X
Xcase XXDIAL:
X    return(hmsg("Dial a number using modem autodialer"));
X
Xcase XXDIR:
X    return(hmsg("Display a directory of local files"));
X
Xcase XXECH:
X    return(hmsg("Display the rest of the command on the terminal,\n\
Xuseful in command files."));
X
Xcase XXEXI:
Xcase XXQUI:
X    return(hmsg("Exit from the Kermit program, closing any open logs."));
X
Xcase XXFIN:
X    return(hmsg("\
XTell the remote Kermit server to shut down without logging out."));
X
Xcase XXGET:
X    return(hmsg(hmxxget));
X
Xcase XXHLP:
X    return(hmsga(tophlp));
X
Xcase XXLOG:
X    return(hmsga(hmxxlg));
X
Xcase XXLOGI:
X    return(hmsga(hmxxlogi));
X
Xcase XXREC:
X    return(hmsga(hmxxrc));
X
Xcase XXREM:
X    if ((y = cmkey(remcmd,nrmt,"Remote command","")) == -2) return(y);
X    if (y == -1) return(y);
X    if (x = (cmcfm()) < 0) return(x);
X    return(dohrmt(y));
X
Xcase XXSEN:
X    return(hmsg(hmxxsen));
X
Xcase XXSER:
X    return(hmsg(hmxxser));
X
Xcase XXSET:
X    if ((y = cmkey(prmtab,nprm,"Parameter","")) == -2) return(y);
X    if (y == -2) return(y);
X    if (x = (cmcfm()) < 0) return(x);
X    return(dohset(y));
X
Xcase XXSHE:
X    return(hmsg("\
XIssue a command to the Unix shell (space required after '!')"));
X
Xcase XXSHO:
X    return(hmsg("\
XDisplay current values of 'set' parameters; 'show version' will display\n\
Xprogram version information for each of the C-Kermit modules."));
X
Xcase XXSPA:
X    return(hmsg("Display disk usage in current device, directory"));
X
Xcase XXSTA:
X    return(hmsg("Display statistics about most recent file transfer"));
X
Xcase XXTAK:
X    return(hmsg("\
XTake Kermit commands from the named file.  Kermit command files may\n\
Xthemselves contain 'take' commands, up to a reasonable depth of nesting."));
X
Xdefault:
X    if (x = (cmcfm()) < 0) return(x);
X    printf("Not available yet - %s\n",cmdbuf);
X    break;
X    }
X    return(0);
X}
X
X/*  H M S G  --  Get confirmation, then print the given message  */
X
Xhmsg(s) char *s; {
X    int x;
X    if (x = (cmcfm()) < 0) return(x);
X    printf("%s\n",s);
X    return(0);
X}
X
Xhmsga(s) char *s[]; {			/* Same function, but for arrays */
X    int x, i;
X    if ( x = (cmcfm()) < 0) return(x);
X    for ( i = 0; *s[i] ; i++ ) fputs(s[i], stdout);
X    fputc( '\n', stdout);
X    return(0);
X}
X
X/*  D O H S E T  --  Give help for SET command  */
X
Xdohset(xx) int xx; {
X    
X    if (xx == -3) {
X        printf(hmhset);
X    	return(0);
X    }
X    if (xx < 0) return(xx);
X    switch (xx) {
X
Xcase XYCHKT:
X    printf(hmxychkt);
X    return(0);
X
Xcase XYDELA: 
X    printf("\
XNumber of seconds to wait before sending first packet after 'send' command\n");
X    return(0);
X
Xcase XYDUPL:
X    printf("\
XDuring 'connect': 'full' means remote host echoes, 'half' means this program\n\
Xdoes its own echoing.\n");
X    return(0);
X
Xcase XYEOL:
X    printf("\
XDecimal ASCII value for character to terminate outbound packets, normally\n\
X13 (CR, carriage return).  Inbound packets are assumed to end with CR.\n");
X    return(0);
X
Xcase XYESC:
X    printf("\
XDecimal ASCII value for escape character during 'connect', normally 28\n\
X(Control-\\)\n");
X    return(0);
X
Xcase XYFILE:
X    printf(hmxyf[0]);
X    printf(hmxyf[1]);
X    printf(hmxyf[2]);
X    printf(hmxyf[3]);
X    return(0);
X
Xcase XYFLOW:
X    printf("\
XType of flow control to be used.  Choices are 'xon/xoff' and 'none'.\n\
Xnormally xon/xoff.\n");
X    return(0);
X
Xcase XYHAND:
X    printf("\
XDecimal ASCII value for character to use for half duplex line turnaround\n\
Xhandshake.  Normally, handshaking is not done.\n");
X    return(0);
X
Xcase XYLEN:
X    printf("\
XPacket length to use.  90 by default.  94 maximum.\n");
X    return(0);
X
Xcase XYLINE:
X    printf("Device name of communication line to use.  Normally %s.\n",dftty);
X    if (!dfloc) {
X	printf("If you set the line to other than %s, then Kermit\n",dftty);
X	printf("\
Xwill be in 'local' mode; 'set line' will reset Kermit to remote mode.\n");
X    printf("\
XIf the line has a modem, and if the modem-dialer is set to direct, this \n\
Xcommand causes waiting for a carrier detect (e.g., on a hayes type modem). \n\
XThis can be used to wait for incomming calls.  \n");
X    printf("\
XTo use the modem to dial out, first set modem-dialer (e.g., to hayes), then \n\
Xset line, next issue the dial command, and finally connect \n");
X    }
X    return(0);
X
Xcase XYMARK:
X    printf("\
XDecimal ASCII value of character that marks the beginning of packets sent by\n\
Xthis program (normally 1 = Control-A)\n");
X    return(0);
X
Xcase XYMODM:
X    printf("\
XType of modem for dialing remote connections.  Needed to indicate modem can\n\
Xbe commanded to dial without \"carrier detect\" from modem.  Many recently\n\
Xmanufactured modems use \"hayes\" protocol.\n");
X    return(0);
X
Xcase XYNPAD:
X    printf("\
XNumber of padding characters to request for inbound packets, normally 0.\n");
X    return(0);
X
Xcase XYPADC:
X    printf("Decimal ASCII value of inbound padding character, normally 0.\n");
X    return(0);
X
Xcase XYPARI:
X    printf("\
XParity to use during terminal connection and file transfer:\n\
Xeven, odd, mark, space, or none.  Normally none.\n");
X    return(0);
X
Xcase XYPROM:
X    printf("Prompt string for this program, normally 'C-Kermit>'.\n");
X    return(0);
X
Xcase XYSPEE:
X    printf("\
XCommunication line speed for external tty line specified in most recent\n\
X'set line'.  Any of the common baud rates: 0, 110, 150, 300, 600, 1200,\n\
X1800, 2400, 4800, 9600.\n");
X    return(0);
X
Xcase XYTIMO:
X    printf("\
XTimeout interval for this program to use during file transfer, seconds.\n");
X    return(0);
X
Xdefault:
X    printf("Not available yet - %s\n",cmdbuf);
X    return(0);
X    }
X}
X
X/*  D O H R M T  --  Give help about REMOTE command  */
X
Xdohrmt(xx) int xx; {
X    int x;
X    if (xx == -3) {
X	printf(hmhrmt[0]);
X	printf(hmhrmt[1]);
X    	return(0);
X    }
X    if (xx < 0) return(xx);
X    switch (xx) {
X
Xcase XZCWD:
X    return(hmsg("\
XAsk remote Kermit server to change its working directory."));
X
Xcase XZDEL:
X    return(hmsg("\
XAsk remote Kermit server to delete the named file(s)."));
X
Xcase XZDIR:
X    return(hmsg("\
XAsk remote Kermit server to provide directory listing of the named file(s)."));
X
Xcase XZHLP:
X    return(hmsg("\
XAsk remote Kermit server to tell you what services it provides."));
X
Xcase XZHOS:
X    return(hmsg("\
XSend a command to the remote system in its own command language\n\
Xthrough the remote Kermit server."));
X
Xcase XZSPA:
X    return(hmsg("\
XAsk the remote Kermit server to tell you about its disk space."));
X
Xcase XZTYP:
X    return(hmsg("\
XAsk the remote Kermit server to type the named file(s) on your screen."));
X
Xcase XZWHO:
X    return(hmsg("\
XAsk the remote Kermit server to list who's logged in, or to give information\n\
Xabout the specified user."));
X
Xdefault:
X    if (x = (cmcfm()) < 0) return(x);
X    printf("not working yet - %s\n",cmdbuf);
X    return(-2);
X    }
X}
!FUNKY!STUFF!
echo x - ckusr3.c
sed '1,$s/^X//' <<\!FUNKY!STUFF! > ckusr3.c
X/*  C K U S R 3 --  "User Interface" for Unix Kermit, part 3  */
X
X/*  SET and REMOTE commands; screen, debug, interrupt, and logging functions */
X
X
X/* Includes */
X
X#include "ckermi.h"
X#include "ckcmd.h"
X#include "ckuser.h"
X
X/* Variables */
X
Xextern int size, spsiz, npad, timint, speed, local, server, image, flow,
X  displa, binary, fncnv, delay, parity, deblog, escape, xargc,
X  turn, duplex, cxseen, czseen, nfils, ckxech, pktlog, seslog, tralog, stdouf,
X  turnch, chklen, bctr, bctu, fsize, dfloc, mdmtyp,
X  rptflg, ebqflg, warn, quiet, cnflg, timef, mypadn;
X
Xextern long filcnt, tlci, tlco, ffc, tfc;
X
Xextern char *versio, *protv, *ckxv, *ckzv, *fnsv, *connv, *dftty, *cmdv;
Xextern char *cmarg, *cmarg2, **xargv, **cmlist;
Xextern char mystch, sstate, mypadc, padch, eol, ctlq, filnam[], ttname[];
Xchar *strcpy();
X
X/* Declarations from cmd package */
X
Xextern char cmdbuf[];			/* Command buffer */
X
X/* From main ckuser module... */
X
Xextern char line[100], *lp;		/* Character buffer for anything */
Xextern char debfil[50],			/* Debugging log file name */
X pktfil[50],				/* Packet log file name */
X sesfil[50],				/* Session log file name */
X trafil[50];				/* Transaction log file name */
X
Xextern int tlevel;			/* Take Command file level */
Xextern FILE *tfile[];			/* Array of take command fd's */
X
X/* Keyword tables for SET commands */
X
X
X/* Block checks */
X
Xstruct keytab blktab[] = {
X    "1", 1, 0,
X    "2", 2, 0,
X    "3", 3, 0
X};
X
X/* Duplex keyword table */
X
Xstruct keytab dpxtab[] = {
X    "full", 	 0, 0,
X    "half",      1, 0
X};
X
Xstruct keytab filtab[] = {
X    "display", XYFILD, 0,
X    "names",   XYFILN, 0,
X    "type",    XYFILT, 0,
X    "warning", XYFILW, 0
X};
Xint nfilp = (sizeof(filtab) / sizeof(struct keytab));
X
X/* Flow Control */
X
Xstruct keytab flotab[] = {
X    "none",     0, 0,
X    "xon/xoff", 1, 0
X};
Xint nflo = (sizeof(flotab) / sizeof(struct keytab));
X
X/*  Handshake characters  */
X
Xstruct keytab hshtab[] = {
X    "bell", 007, 0,
X    "cr",   015, 0,
X    "esc",  033, 0,
X    "lf",   012, 0,
X    "none", 999, 0,  /* (can't use negative numbers) */
X    "xoff", 023, 0,
X    "xon",  021, 0
X};
Xint nhsh = (sizeof(hshtab) / sizeof(struct keytab));
X
Xstruct keytab fntab[] = {   		/* File naming */
X    "converted", 1, 0,
X    "literal",   0, 0
X};
X
Xstruct keytab fttab[] = {		/* File types */
X    "binary",    1, 0,
X    "text",      0, 0
X};
X
Xextern struct keytab mdmtab[] ;		/* Modem types (in module ckdial.c) */
Xextern int nmdm;
X
X
X/* Parity keyword table */
X
Xstruct keytab partab[] = {
X    "even",    'e', 0,
X    "mark",    'm', 0,
X    "none",      0, 0,
X    "odd",     'o', 0,
X    "space",   's', 0
X};
Xint npar = (sizeof(partab) / sizeof(struct keytab));
X
X
X/* On/Off table */
X
Xstruct keytab onoff[] = {
X    "off",       0, 0,
X    "on",        1, 0
X};
X
X/*  D O P R M  --  Set a parameter.  */
X/*
X Returns:
X  -2: illegal input
X  -1: reparse needed
X   0: success
X*/
Xdoprm(xx) int xx; {
X    int x, y, z;
X    char *s;
X
Xswitch (xx) {
X
Xcase XYLINE:
X    if ((x = cmtxt("Device name",dftty,&s)) < 0) return(x);
X    ttclos();				/* close old line, if any was open */
X    strcpy(ttname,s);
X    if (strcmp(ttname,dftty) == 0) local = dfloc; else local = 1;
X    if (ttopen(ttname,local,mdmtyp) < 0 ) { /* Can we open the new line? */
X	perror("Sorry, can't open line");
X	return(-2);			/* If not, give bad return */
X	}
X    return(0);
X
Xcase XYCHKT:
X    if ((y = cmkey(blktab,3,"","1")) < 0) return(y);
X    if ((x = cmcfm()) < 0) return(x);
X    bctr = y;
X    return(0);
X
Xcase XYDEBU:
X    return(seton(&deblog));
X
Xcase XYDELA:
X    y = cmnum("Number of seconds before starting to send","5",10,&x);
X    debug(F101,"XYDELA: y","",y);
X    return(setnum(&delay,x,y));
X
Xcase XYDUPL:
X    if ((y = cmkey(dpxtab,2,"","full")) < 0) return(y);
X    if ((x = cmcfm()) < 0) return(x);
X    duplex = y;
X    return(0);
X
Xcase XYEOL:
X    y = cmnum("Decimal ASCII code for packet terminator","0",10,&x);
X    y = setcc(&z,x,y);
X    eol = z;
X    return(y);
X
Xcase XYESC:
X    y = cmnum("Decimal ASCII code for escape character","",10,&x);
X    return(setcc(&escape,x,y));
X
Xcase XYFILE:
X    if ((y = cmkey(filtab,nfilp,"File parameter","")) < 0) return(y);
X    switch (y) {
X	int z;
X	case XYFILD:			/* Display */
X	    y = seton(&z);
X	    if (y < 0) return(y);
X	    quiet = !z;
X	    return(0);
X
X	case XYFILN:			/* Names */
X	    if ((x = cmkey(fntab,2,"how to handle filenames","converted")) < 0)
X	    	return(x);
X	    if ((z = cmcfm()) < 0) return(z);
X	    fncnv = x;
X	    return(0);
X
X	case XYFILT:			/* Type */
X	    if ((x = cmkey(fttab,2,"type of file","text")) < 0)
X	    	return(x);
X	    if ((z = cmcfm()) < 0) return(z);
X	    binary = x;
X	    return(0);
X
X	case XYFILW:			/* Warning/Write-Protect */
X	    return(seton(&warn));
X    }
X
Xcase XYFLOW:				/* Flow control */
X    if ((y = cmkey(flotab,nflo,"","xon/xoff")) < 0) return(y);
X    if ((x = cmcfm()) < 0) return(x);
X    flow = y;
X    return(0);
X
Xcase XYHAND:				/* Handshake */
X    if ((y = cmkey(hshtab,nhsh,"","none")) < 0) return(y);
X    if ((x = cmcfm()) < 0) return(x);
X    turn = (y > 0127) ? 0 : 1 ;
X    turnch == y;
X    return(0);
X
Xcase XYLEN:
X    y = cmnum("Maximum number of characters in a packet","80",10,&x);
X    return(setnum(&spsiz,x,y));
X
Xcase XYMARK:
X    y = cmnum("Decimal ASCII code for packet-start character","1",10,&x);
X    y = setcc(&z,x,y);
X    mystch = z;
X    return(y);
X
Xcase XYMODM:
X    if ((x=cmkey(mdmtab,nmdm,"type of modem, direct means none","direct")) < 0)
X	return(x);
X    if ((z = cmcfm()) < 0) return(z);
X    mdmtyp = x;
X    return(0);
X	
Xcase XYNPAD:
X    y = cmnum("How many padding characters for inbound packets","0",10,&x);
X    return(setnum(&mypadn,x,y));
X
Xcase XYPADC:
X    y = cmnum("Decimal ASCII code for inbound pad character","0",10,&x);
X    y = setcc(&z,x,y);
X    mypadc = z;
X    return(y);
X
Xcase XYPARI:
X    if ((y = cmkey(partab,npar,"","none")) < 0) return(y);
X    if ((x = cmcfm()) < 0) return(x);
X    parity = y;
X    ebqflg = 1;				/* Flag we want 8th-bit prefixing */
X    return(0);
X
Xcase XYPROM:
X    if ((x = cmtxt("Program's command prompt","C-Kermit>",&s)) < 0) return(x);
X    cmsetp(s);
X    return(0);
X
Xcase XYSPEE:
X    if (!local) {
X	printf("\nSpeed setting can only be done on an external line\n");
X	printf("You must 'set line' before issuing this command\n");
X	return(0);
X    }	
X    lp = line;
X    sprintf(lp,"Baud rate for %s",ttname);
X    if ((y = cmnum(line,"",10,&x)) < 0) return(y);
X    if (y = (cmcfm()) < 0) return(y);
X    y = chkspd(x);
X    if (y < 0) 
X    	printf("?Unsupported line speed - %d\n",x);
X    else {
X    	speed = y;
X	printf("%s: %d baud\n",ttname,speed);
X    }
X    return(0);
X
Xcase XYTIMO:
X    y = cmnum("Interpacket timeout interval","5",10,&x);
X    y = setnum(&timint,x,y);
X    if (y > -1) timef = 1;
X    return(y);
X
Xdefault:
X    if (x = (cmcfm()) < 0) return(x);
X    printf("Not working yet - %s\n",cmdbuf);
X    return(0);
X    }
X}
X
X/*  C H K S P D  --  Check if argument is a valid baud rate  */
X
Xchkspd(x) int x; {
X    switch (x) {
X	case 0:
X	case 110:
X	case 150:
X	case 300:
X	case 600:
X	case 1200:
X	case 1800:
X	case 2400:
X	case 4800:
X	case 9600:
X	    return(x);
X	default: 
X	    return(-1);
X      }
X}
X
X/*  S E T O N  --  Parse on/off (default on), set parameter to result  */
X
Xseton(prm) int *prm; {
X    int x, y;
X    if ((y = cmkey(onoff,2,"","on")) < 0) return(y);
X    if ((x = cmcfm()) < 0) return(x);
X    *prm = y;
X    return(0);
X}
X
X/*  S E T N U M  --  Set parameter to result of cmnum() parse.  */
X/*
X Call with x - number from cnum parse, y - return code from cmnum
X*/
Xsetnum(prm,x,y) int x, y, *prm; {
X    debug(F101,"setnum",y);
X    if (y < 0) return(y);
X    if (x > 94) {
X	printf("\n?Sorry, 94 is the maximum\n");
X	return(-2);
X    }
X    if ((y = cmcfm()) < 0) return(y);
X    *prm = x;
X    return(0);
X}
X
X/*  S E T C C  --  Set parameter to an ASCII control character value.  */
X
Xsetcc(prm,x,y) int x, y, *prm; {
X    if (y < 0) return(y);
X    if ((x > 037) && (x != 0177)) {
X	printf("\n?Not in ASCII control range - %d\n",x);
X	return(-2);
X    }
X    if ((y = cmcfm()) < 0) return(y);
X    *prm = x;
X    return(0);
X}
X
X/*  D O R M T  --  Do a remote command  */
X
Xdormt(xx) int xx; {
X    int x;
X    char *s, sbuf[50], *s2;
X
X    if (xx < 0) return(xx);
X    switch (xx) {
X
Xcase XZCWD:				/* CWD */
X    if ((x = cmtxt("Remote directory name","",&s)) < 0) return(x);
X    debug(F111,"XZCWD: ",s,x);
X    *sbuf = NUL;
X    s2 = sbuf;
X    if (*s != NUL) {			/* If directory name given, */
X					/* get password on separate line. */
X        if (tlevel > -1) {		/* From take file... */
X
X	    *line = NUL;
X	    if (fgets(sbuf,50,tfile[tlevel]) == NULL)
X	    	ermsg("take file ends prematurely in 'remote cwd'");
X	    debug(F110," pswd from take file",s2,0);
X
X        } else {			/* From terminal... */
X
X	    printf(" Password: "); 		/* get a password */
X	    while ((x = getchar()) != '\n') {   /* without echo. */
X	    	if ((x &= 0177) == '?') {
X	    	    printf("? Password of remote directory\n Password: ");
X		    s2 = sbuf;
X		    *sbuf = NUL;
X	    	}
X	    	else if (x == ESC)	/* Mini command line editor... */
X	    	    putchar(BEL);
X		else if (x == BS || x == 0177)
X		    *s2--;
X		else if (x == 025) {
X		    s2 = sbuf;
X		    *sbuf = NUL;
X		}
X	    	else
X		    *s2++ = x;
X            }
X	    *s2 = NUL;
X	    putchar('\n');
X        }
X        s2 = sbuf;
X    } else s2 = "";
X    debug(F110," password",s2,0);
X    sstate = setgen('C',s,s2,"");
X    return(0);
X
Xcase XZDEL:				/* Delete */
X    if ((x = cmtxt("Name of remote file(s) to delete","",&s)) < 0) return(x);
X    return(sstate = rfilop(s,'E'));
X
Xcase XZDIR:				/* Directory */
X    if ((x = cmtxt("Remote directory or file specification","",&s)) < 0)
X    	return(x);
X    return(sstate = setgen('D',s,"",""));
X
Xcase XZHLP:				/* Help */
X    if (x = (cmcfm()) < 0) return(x);
X    sstate = setgen('H',"","","");
X    return(0);
X
Xcase XZHOS:				/* Host */
X    if ((x = cmtxt("Command for remote system","",&cmarg)) < 0) return(x);
X    return(sstate = 'c');
X
Xcase XZPRI:				/* Print */
X    if ((x = cmtxt("Remote file(s) to print on remote printer","",&s)) < 0)
X    	return(x);
X    return(sstate = rfilop(s,'S'));
X
Xcase XZSPA:				/* Space */
X    if ((x = cmtxt("Confirm, or remote directory name","",&s)) < 0) return(x);
X    return(sstate = setgen('U',s,"",""));
X    
Xcase XZTYP:				/* Type */
X    if ((x = cmtxt("Remote file specification","",&s)) < 0) return(x);
X    return(sstate = rfilop(s,'T'));
X
Xcase XZWHO:
X    if ((x = cmtxt("Remote user name, or carriage return","",&s)) < 0)
X    	return(x);
X    return(sstate = setgen('W',s,"",""));
X
Xdefault:
X    if (x = (cmcfm()) < 0) return(x);
X    printf("not working yet - %s\n",cmdbuf);
X    return(-2);
X    }
X}
X
X
X
X/*  R F I L O P  --  Remote File Operation  */
X
Xrfilop(s,t) char *s, t; {
X    if (*s == NUL) {
X	printf("?File specification required\n");
X	return(-2);
X    }
X    debug(F111,"rfilop",s,t);
X    return(setgen(t,s,"",""));
X}
X
X/*  S C R E E N  --  Screen display function  */
X/*  
X   c - a character or small integer
X   n - an long integer
X   s - a string.
X Fill in this routine with the appropriate display update for the system.
X This version is for a dumb tty, and uses the arguments like this:
X   c:     0 - print s on a new line, followed by a space.
X          1 - print s at current screen position.
X          2 - print s at current position, followed by newline.
X	  3 - print "s: n" at current position, followed by newline.
X      other - print c as a character.
X   n: if c is 'other', used to decide whether or how to print c.
X   s: as above.
X Horizontal screen position is kept current if screen is only updated by 
X calling this function.  Wraparound is done at column 78.
X*/
Xscreen(c,n,s) char c; long n; char *s; {
X    static int p = 0;			/* Screen position */
X    int len;  char buf[80];
X    len = strlen(s);
X    if (!displa || quiet) return;	/* No update if display flag off */
X    switch (c) {
X	case 0:				/* Print s on newline */
X	    conoll("");			/* Start new line, */
X	    conol(s);			/* Print string. */
X	    conoc(SP);			/* Leave a space. */
X	    p = len + 1;		/* Set position counter. */
X	    return;
X	case 1:
X	    if (p + len > 78) { conoll(""); p = 0; }
X	    conol(s);  if ((p += len) > 78) conoll("");
X	    return;
X	case 2:				/* Print s, then newline */
X	    if (p + len > 78) conoll("");
X	    conoll(s);  p = 0;
X	    return;
X	case 3:
X	    sprintf(buf,"%s: %ld",s,n);  conoll(buf);  p = 0;
X	    return;
X	case BS:			/* Backspace */
X	    if (p > 0) p--;
X	case BEL:			/* Beep */
X	    conoc(c);
X	    return;
X	default:			/* Packet type display */
X	    if (c == 'Y') return;	/* Don't bother with ACKs */
X	    if (c == 'D') {		/* Only show every 4th data packet */
X		c = '.';
X		if (n % 4) return;
X	    }
X	    if (p++ > 78) {		/* If near left margin, */
X		conoll("");		/* Start new line */
X		p = 0;			/* and reset counter. */
X	    }
X	    conoc(c);			/* Display the character. */
X	    return;
X    }
X}
X
X/*  I N T M S G  --  Issue message about terminal interrupts  */
X
Xintmsg(n) long n; {
X    extern char *chstr();
X    char buf[80];
X
X    if ((!displa) || (quiet)) return;
X#ifdef UXIII
X    (void) conchk();	/* clear out pending escape-signals in ckxbsd.c */
X#endif
X    if (n == 1) {
X	screen(2,0l,"");
X#ifdef UXIII
X				/* we need to signal before kb input */
X	sprintf(buf,"Type escape (%s) followed by:",chstr(escape));
X	screen(2,0l,buf);
X#endif
X#ifdef PROVX1
X	screen(2,0l,"(transfer cannot be interrupted from keyboard)");
X#else
X	screen(2,0l,"CTRL-F to cancel file,  CTRL-R to resend current packet");
X	screen(2,0l,"CTRL-B to cancel batch, CTRL-A for status report...");
X#endif
X    }
X    else screen(1,0l," ");
X}
X
X/*  C H K I N T  --  Check for console interrupts  */
X
X/*** should rework not to destroy typeahead ***/
X
Xchkint() {
X    int ch, cn;
X
X    if ((!local) || (quiet)) return(0);	/* Only do this if local & not quiet */
X    cn = conchk();			/* Any input waiting? */
X    debug(F101,"conchk","",cn);
X
X    while (cn > 0) {			/* Yes, read it. */
X	cn--;
X			/* give read 5 seconds for interrupt character */
X	if ((ch = coninc(5)) < 0) return(0);
X	switch (ch & 0177) {
X	    case 0001:			/* CTRL-A */
X		screen(2,0l,"^A  Status report:");
X		screen(1,0l,     " file type: ");
X		if (binary) screen(2,0l,"binary"); else screen(2,0l,"text");
X		screen(3,filcnt," file number");
X		screen(3,ffc,   " characters ");
X		screen(3,(long) bctu,  " block check");
X		screen(3,(long)rptflg," compression");
X		screen(3,(long)ebqflg," 8th-bit prefixing");
X		continue;
X	    case 0002:			/* CTRL-B */
X	    	screen(1,0l,"^B - Cancelling Batch ");
X	    	czseen = 1;
X		continue;
X	    case 0006:			/* CTRL-F */
X	    	screen(1,0l,"^F - Cancelling File ");
X	    	cxseen = 1;
X		continue;
X	    case 0022:	    	    	/* CTRL-R */
X	    	screen(1,0l,"^R - Resending ");
X	    	resend();
X		return(1);
X	    default:			/* Anything else, just beep */
X	    	screen(BEL,0l,"");
X		continue;
X    	}
X    }
X    return(0);
X}
X
X/*  D E B U G  --  Enter a record in the debugging log  */
X
X/*
X Call with a format, two strings, and a number:
X   f  - Format, a bit string in range 0-7.
X        If bit x is on, then argument number x is printed.
X   s1 - String, argument number 1.  If selected, printed as is.
X   s2 - String, argument number 2.  If selected, printed in brackets.
X   n  - Int, argument 3.  If selected, printed preceded by equals sign.
X
X   f=0 is special: print s1,s2, and interpret n as a char.
X*/
Xdebug(f,s1,s2,n) int f, n; char *s1, *s2; {
X    static char s[200];
X    char *sp = s;
X
X    if (!deblog) return;		/* If no debug log, don't */
X    switch (f) {
X    	case F000:			/* 0, print both strings, */
X	    sprintf(sp,"%s%s%c\n",s1,s2,n); /*  and interpret n as a char */
X	    zsout(ZDFILE,s);
X	    break;
X    	case F001:			/* 1, "=n" */
X	    sprintf(sp,"=%d\n",n);
X	    zsout(ZDFILE,s);
X	    break;
X    	case F010:			/* 2, "[s2]" */
X	    sprintf(sp,"[%s]\n",s2);
X	    zsout(ZDFILE,"");
X	    break;
X    	case F011:			/* 3, "[s2]=n" */
X	    sprintf(sp,"[%s]=%d\n",s2,n);
X	    zsout(ZDFILE,s);
X	    break;
X    	case F100:			/* 4, "s1" */
X	    zsoutl(ZDFILE,s1);
X	    break;
X    	case F101:			/* 5, "s1=n" */
X	    sprintf(sp,"%s=%d\n",s1,n);
X	    zsout(ZDFILE,s);
X	    break;
X    	case F110:			/* 6, "s1[s2]" */
X	    sprintf(sp,"%s[%s]\n",s1,s2);
X	    zsout(ZDFILE,s);
X	    break;
X    	case F111:			/* 7, "s1[s2]=n" */
X	    sprintf(sp,"%s[%s]=%d\n",s1,s2,n);
X	    zsout(ZDFILE,s);
X	    break;
X	default:
X	    sprintf(sp,"\n?Invalid format for debug() - %d\n",n);
X	    zsout(ZDFILE,s);
X    }
X}
X
X/*  T L O G  --  Log a record in the transaction file  */
X/*
X Call with a format and 3 arguments: two strings and a number:
X   f  - Format, a bit string in range 0-7, bit x is on, arg #x is printed.
X   s1 - String, argument number 1.
X   s2 - String, argument number 2.
X   n  - Int, argument 3.
X*/
Xtlog(f,s1,s2,n) int f; long n; char *s1, *s2; {
X    static char s[200];
X    char *sp = s; int x;
X    
X    if (!tralog) return;		/* If no transaction log, don't */
X    switch (f) {
X    	case F000:			/* 0 (special) "s1 n s2"  */
X	    sprintf(sp,"%s %ld %s\n",s1,n,s2);
X	    zsout(ZTFILE,s);
X	    break;
X    	case F001:			/* 1, " n" */
X	    sprintf(sp," %ld\n",n);
X	    zsout(ZTFILE,s);
X	    break;
X    	case F010:			/* 2, "[s2]" */
X	    x = strlen(s2);
X	    if (s2[x] == '\n') s2[x] = '\0';
X	    sprintf(sp,"[%s]\n",s2);
X	    zsout(ZTFILE,"");
X	    break;
X    	case F011:			/* 3, "[s2] n" */
X	    x = strlen(s2);
X	    if (s2[x] == '\n') s2[x] = '\0';
X	    sprintf(sp,"[%s] %ld\n",s2,n);
X	    zsout(ZTFILE,s);
X	    break;
X    	case F100:			/* 4, "s1" */
X	    zsoutl(ZTFILE,s1);
X	    break;
X    	case F101:			/* 5, "s1: n" */
X	    sprintf(sp,"%s: %ld\n",s1,n);
X	    zsout(ZTFILE,s);
X	    break;
X    	case F110:			/* 6, "s1 s2" */
X	    x = strlen(s2);
X	    if (s2[x] == '\n') s2[x] = '\0';
X	    sprintf(sp,"%s %s\n",s1,s2);
X	    zsout(ZTFILE,s);
X	    break;
X    	case F111:			/* 7, "s1 s2: n" */
X	    x = strlen(s2);
X	    if (s2[x] == '\n') s2[x] = '\0';
X	    sprintf(sp,"%s %s: %ld\n",s1,s2,n);
X	    zsout(ZTFILE,s);
X	    break;
X	default:
X	    sprintf(sp,"\n?Invalid format for tlog() - %ld\n",n);
X	    zsout(ZTFILE,s);
X    }
X}
!FUNKY!STUFF!
echo x - ckwart.c
sed '1,$s/^X//' <<\!FUNKY!STUFF! > ckwart.c
X/* W A R T
X *
X * pre-process a lex-like file into a C program.
X *
X * Jeff Damens, Columbia University Center for Computing Activites, 11/84.
X * (Reorganized by Frank da Cruz into a single source module for ease
X * of distribution).
X * Copyright (C) 1984, Trustees of Columbia University.
X * May be copied and used except for explicitly commercial purposes.
X *
X * input format is:
X *  lines to be copied | %state <state names...>
X *  %%
X * <state> | <state,state,...> CHAR  { actions }
X * ...
X *  %%
X */
X
X#include <stdio.h>
X#include <ctype.h>
X
X/* token types */
X
X#define SEP 1
X#define LBRACK 2
X#define RBRACK 3
X#define WORD 4
X#define COMMA 5
X
X/* storage sizes */
X
X#define MAXSTATES 50			/* max number of states */
X#define MAXWORD 50			/* max # of chars/word */
X#define SBYTES ((MAXSTATES+7)/8)	/* # of bytes for state bitmask */
X
X/* name of wart function in generated program */
X
X#ifndef FNAME
X#define FNAME "wart"
X#endif
X
X/* data structure for state information */
X
X#ifdef PROVX1
Xtypedef unsigned short CHAR;
X#else
Xtypedef unsigned char CHAR;
X#endif
X
Xstruct trans { CHAR states[SBYTES];	/* included states */
X    	       int anyst;		/* true if this good from any state */
X    	       CHAR inchr;		/* input character */
X	       int actno;		/* associated action */
X	       struct trans *nxt; };	/* next transition */
X
Xtypedef struct trans *Trans;
X
X/* Variables and tables */
X
Xint lines,nstates,nacts;
X
Xchar tokval[MAXWORD];
X
Xint tbl[MAXSTATES*128];
X
X
X
Xchar *txt1 = "\n\
X#define BEGIN state =\n\
X\n\
Xint state = 0;\n\
X\n";
X
Xchar *fname = FNAME;		/* function name goes here */
X
X/* rest of program... */
X
Xchar *txt2 = "()\n\
X{\n\
X  int c,actno;\n\
X  extern int tbl[];\n\
X  while (1) {\n\
X	c = input();\n\
X	if ((actno = tbl[c + state*128]) != -1)\n\
X	  switch(actno) {\n";
X
X/* this program's output goes here, followed by final text... */
X
Xchar *txt3 = "\n    }\n  }\n\}\n\n";
X
X/*
X * turn on the bit associated with the given state
X *
X */
Xsetstate(state,t)
Xint state;
XTrans t;
X{
X  int idx,msk;
X  idx = state/8;			/* byte associated with state */
X  msk = 0x80 >> (state % 8);		/* bit mask for state */
X  t->states[idx] |= msk;
X}
X
X/*
X * see if the state is involved in the transition
X *
X */
X
Xteststate(state,t)
Xint state;
XTrans t;
X{
X  int idx,msk;
X  idx = state/8;
X  msk = 0x80 >> (state % 8);
X  return(t->states[idx] & msk);
X}
X
X
X/*
X * read input from here...
X *
X */
X
XTrans
Xrdinput(infp,outfp)
XFILE *infp,*outfp;
X{
X  Trans x,rdrules();
X  lines = 1;				/* line counter */
X  nstates = 0;				/* no states */
X  nacts = 0;				/* no actions yet */
X  fprintf(outfp,"\n\
X/* WARNING -- This C source program generated by Wart preprocessor. */\n");
X  fprintf(outfp,"\
X/* Do not edit this file; edit the Wart-format source file instead, */\n");
X  fprintf(outfp,"\
X/* and then run it through Wart to produce a new C source file.     */\n\n");
X  initial(infp,outfp);			/* read state names, initial defs */
X  prolog(outfp);			/* write out our initial code */
X  x = rdrules(infp,outfp);		/* read rules */
X  epilogue(outfp);			/* write out epilogue code */
X  return(x);
X}
X
X/*
X * initial - read initial definitions and state names.  Returns
X * on EOF or %%.
X *
X */
X
Xinitial(infp,outfp)
XFILE *infp,*outfp;
X{
X  int c;
X  char wordbuf[MAXWORD];
X  while ((c = getc(infp)) != EOF) {
X	if (c == '%') {
X			rdword(infp,wordbuf);
X			if (strcmp(wordbuf,"states") == 0)
X			    rdstates(infp,outfp);
X			else if (strcmp(wordbuf,"%") == 0) return;
X			else fprintf(outfp,"%%%s",wordbuf);
X		      }
X	else putc(c,outfp);
X	if (c == '\n') lines++;
X     }
X}
X
X/*
X * boolean function to tell if the given character can be part of
X * a word.
X *
X */
Xisin(s,c) char *s; int c; {
X   for (; *s != '\0'; s++)
X      if (*s == c) return(1);
X   return(0);
X}
Xisword(c)
Xint c;
X{
X  static char special[] = ".%_-$@";	/* these are allowable */
X  return(isalnum(c) || isin(special,c));
X}
X
X/*
X * read the next word into the given buffer.
X *
X */
Xrdword(fp,buf)
XFILE *fp;
Xchar *buf;
X{
X  int len = 0,c;
X  while (isword(c = getc(fp)) && ++len < MAXWORD) *buf++ = c;
X  *buf++ = '\0';			/* tie off word */
X  ungetc(c,fp);				/* put break char back */
X}
X
X/*
X * read state names, up to a newline.
X *
X */
X
Xrdstates(fp,ofp)
XFILE *fp,*ofp;
X{
X  int c;
X  char wordbuf[MAXWORD];
X  while ((c = getc(fp)) != EOF && c != '\n')
X  {
X	if (isspace(c)) continue;	/* skip whitespace */
X	ungetc(c,fp);			/* put char back */
X	rdword(fp,wordbuf);		/* read the whole word */
X	enter(wordbuf,++nstates);	/* put into symbol tbl */
X	fprintf(ofp,"#define %s %d\n",wordbuf,nstates);
X  }
X  lines++;
X}
X		
X/*
X * allocate a new, empty transition node
X *
X */
X
XTrans
Xnewtrans()
X{
X  Trans new;
X  int i;
X  new = (Trans) malloc(sizeof (struct trans));
X  for (i=0; i<SBYTES; i++) new->states[i] = 0;
X  new->anyst = 0;
X  new->nxt = NULL;
X  return(new);
X}
X
X/*
X * read all the rules.
X *
X */
X
XTrans
Xrdrules(fp,out)
XFILE *fp,*out;
X{
X  Trans head,cur,prev;
X  int curtok,i;
X  head = cur = NULL;
X  while ((curtok = gettoken(fp)) != SEP) 
X
X	switch(curtok) {
X		case LBRACK: if (cur == NULL) cur = newtrans();
X		    	     else fatal("duplicate state list");
X			     statelist(fp,cur);/* set states */
X			     continue;	/* prepare to read char */
X
X		case WORD:   if (strlen(tokval) != 1)
X					fatal("multiple chars in state");
X			     if (cur == NULL) {
X				cur = newtrans();
X				cur->anyst = 1;
X				}
X			     cur->actno = ++nacts;
X			     cur->inchr = tokval[0];
X			     if (head == NULL) head = cur;
X			     else prev->nxt = cur;
X			     prev = cur;
X			     cur = NULL;
X			     copyact(fp,out,nacts);
X			     break; 
X		 default: fatal("bad input format");
X	     }
X	
X   return(head);
X}
X
X/*
X * read a list of (comma-separated) states, set them in the
X * given transition.
X *
X */
Xstatelist(fp,t)
XFILE *fp;
XTrans t;
X{
X  int curtok,sval;
X  curtok = COMMA;
X  while (curtok != RBRACK) {
X	if (curtok != COMMA) fatal("missing comma");
X	if ((curtok = gettoken(fp)) != WORD) fatal("missing state name");
X        if ((sval = lkup(tokval)) == -1) {
X		fprintf(stderr,"state %s undefined\n",tokval);
X		fatal("undefined state");
X	   }
X        setstate(sval,t);
X	curtok = gettoken(fp);
X   }
X}
X
X/*
X * copy an action from the input to the output file
X *
X */
Xcopyact(inp,outp,actno)
XFILE *inp,*outp;
Xint actno;
X{
X  int c,bcnt;
X  fprintf(outp,"case %d:\n",actno);
X  while ((c = getc(inp)) != '\n' && isspace(c));	/* skip whitespace */
X  if (c == '{') {
X     bcnt = 1;
X     putc(c,outp);
X     while (bcnt > 0 && (c = getc(inp)) != EOF) {
X	if (c == '{') bcnt++;
X	else if (c == '}') bcnt--;
X	else if (c == '\n') lines++;
X	putc(c,outp);
X      }
X     if (bcnt > 0) fatal("action doesn't end");
X    }
X   else {
X	  while (c != '\n' && c != EOF) {
X		putc(c,outp);
X		c = getc(inp);
X	    }
X	  lines++;
X	}
X   fprintf(outp,"\nbreak;\n");
X}
X
X/*
X * find the action associated with a given character and state.
X * returns -1 if one can't be found.
X *
X */
Xfaction(hd,state,chr)
XTrans hd;
Xint state,chr;
X{
X  while (hd != NULL) {
X    if (hd->anyst || teststate(state,hd))
X      if (hd->inchr == '.' || hd->inchr == chr) return(hd->actno);
X    hd = hd->nxt;
X    }
X  return(-1);
X}
X
X
X/*
X * empty the table...
X *
X */
Xemptytbl()
X{
X  int i;
X  for (i=0; i<nstates*128; i++) tbl[i] = -1;
X}
X
X/*
X * add the specified action to the output for the given state and chr.
X *
X */
X
Xaddaction(act,state,chr)
Xint act,state,chr;
X{
X tbl[state*128 + chr] = act;
X}
X
Xwritetbl(fp)
XFILE *fp;
X{
X  warray(fp,"tbl",tbl,128*(nstates+1));
X}
X
X/*
X * write an array to the output file, given its name and size.
X *
X */
Xwarray(fp,nam,cont,siz)
XFILE *fp;
Xchar *nam;
Xint cont[],siz;
X{
X  int i;
X  fprintf(fp,"int %s[] = {\n",nam);
X  for (i = 0; i < siz; i++) {
X	fprintf(fp,"%d, ",cont[i]);
X	if ((i % 20) == 0) putc('\n',fp);
X	}
X  fprintf(fp,"};\n");
X}
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X  Trans head;
X  int state,c;
X  FILE *infile,*outfile;
X
X  if (argc > 1) {
X    if ((infile = fopen(argv[1],"r")) == NULL) {
X    	fprintf(stderr,"Can't open %s\n",argv[1]);
X	fatal("unreadable input file"); } }
X  else infile = stdin;
X
X  if (argc > 2) {
X    if ((outfile = fopen(argv[2],"w")) == NULL) {
X    	fprintf(stderr,"Can't write to %s\n",argv[2]);
X	fatal("bad output file"); } }
X  else outfile = stdout;
X
X  clrhash();				/* empty hash table */
X  head = rdinput(infile,outfile);	/* read input file */
X  emptytbl();				/* empty our tables */
X  for (state = 0; state <= nstates; state++)
X    for (c = 1; c < 128; c++)
X     addaction(faction(head,state,c),state,c);	/* find actions, add to tbl */
X  writetbl(outfile);
X  copyrest(infile,outfile);
X  printf("%d states, %d actions\n",nstates,nacts);
X#ifdef undef
X  for (state = 1; state <= nstates; state ++)
X    for (c = 1; c < 128; c++)
X       if (tbl[state*128 + c] != -1) printf("state %d, chr %d, act %d\n",
X       	state,c,tbl[state*128 + c]);
X#endif
X  exit(0);
X}
X
X/*
X * fatal error handler
X *
X */
X
Xfatal(msg)
Xchar *msg;
X{
X  fprintf(stderr,"error in line %d: %s\n",lines,msg);
X  exit(1);
X}
X
Xprolog(outfp)
XFILE *outfp;
X{
X  int c;
X  while ((c = *txt1++) != '\0')  putc(c,outfp);
X  while ((c = *fname++) != '\0') putc(c,outfp);
X  while ((c = *txt2++) != '\0')  putc(c,outfp);
X}
X
Xepilogue(outfp)
XFILE *outfp;
X{
X  int c;
X  while ((c = *txt3++) != '\0') putc(c,outfp);
X}
X
Xcopyrest(in,out)
XFILE *in,*out;
X{
X  int c;
X  while ((c = getc(in)) != EOF) putc(c,out);
X}
X
X/*
X * gettoken - returns token type of next token, sets tokval
X * to the string value of the token if appropriate.
X *
X */
X
Xgettoken(fp)
XFILE *fp;
X{
X  int c;
X  while (1) {				/* loop if reading comments... */
X    do {
X	  c = getc(fp);
X	  if (c == '\n') lines++;
X       } while (isspace(c));		/* skip whitespace */
X    switch(c) {
X	  case EOF: return(SEP);
X	  case '%': if ((c = getc(fp)) == '%') return(SEP);
X		    tokval[0] = '%';
X		    tokval[1] = c;
X		    rdword(fp,tokval+2);
X		    return(WORD);
X	  case '<': return(LBRACK);
X	  case '>': return(RBRACK);
X	  case ',': return(COMMA);
X	  case '/': if ((c = getc(fp)) == '*') {
X	    	      rdcmnt(fp);	/* skip over the comment */
X		      continue; }	/* and keep looping */
X		    else {
X			ungetc(c);	/* put this back into input */
X			c = '/'; }	/* put character back, fall thru */
X
X	  default: if (isword(c)) {
X			  ungetc(c,fp);
X			  rdword(fp,tokval);
X			  return(WORD);
X		      	}
X		   else fatal("Invalid character in input");
X	     }
X  }
X}
X
X/*
X * skip over a comment
X *
X */
X
Xrdcmnt(fp)
XFILE *fp;
X{
X  int c,star,prcnt;
X  prcnt = star = 0;			/* no star seen yet */
X  while (!((c = getc(fp)) == '/' && star)) {
X    if (c == EOF || (prcnt && c == '%')) fatal("Unterminated comment");
X    prcnt = (c == '%');
X    star = (c == '*');
X    if (c == '\n') lines++; }
X}
X
X
X/*
X * symbol table management for wart
X *
X * entry points:
X *   clrhash - empty hash table.
X *   enter - enter a name into the symbol table
X *   lkup - find a name's value in the symbol table.
X *
X */
X
X#define HASHSIZE 101			/* # of entries in hash table */
X
Xstruct sym { char *name;		/* symbol name */
X	     int val;			/* value */
X	     struct sym *hnxt; }	/* next on collision chain */
X    *htab[HASHSIZE];			/* the hash table */
X
X
X/*
X * empty the hash table before using it...
X *
X */
Xclrhash()
X{
X  int i;
X  for (i=0; i<HASHSIZE; i++) htab[i] = NULL;
X}
X
X/*
X * compute the value of the hash for a symbol
X *
X */
Xhash(name)
Xchar *name;
X{
X  int sum;
X  for (sum = 0; *name != '\0'; name++) sum += (sum + *name);
X  sum %= HASHSIZE;			/* take sum mod hashsize */
X  if (sum < 0) sum += HASHSIZE;		/* disallow negative hash value */
X  return(sum);
X}
X
X/*
X * make a private copy of a string...
X *
X */
Xchar *
Xcopy(s)
Xchar *s;
X{
X  char *new;
X  new = (char *) malloc(strlen(s) + 1);
X  strcpy(new,s);
X  return(new);
X}
X
X/*
X * enter state name into the hash table
X *
X */
Xenter(name,svalue)
Xchar *name;
Xint svalue;
X{
X  int h;
X  struct sym *cur;
X  if (lkup(name) != -1) {
X	fprintf(stderr,"state %s appears twice...\n");
X	exit(1); }
X  h = hash(name);
X  cur = (struct sym *)malloc(sizeof (struct sym));
X  cur->name = copy(name);
X  cur->val = svalue;
X  cur->hnxt = htab[h];
X  htab[h] = cur;
X}
X
X/*
X * find name in the symbol table, return its value.  Returns -1
X * if not found.
X *
X */
Xlkup(name)
Xchar *name;
X{
X  struct sym *cur;
X  for (cur = htab[hash(name)]; cur != NULL; cur = cur->hnxt)
X	if (strcmp(cur->name,name) == 0) return(cur->val);
X  return(-1);
X}
!FUNKY!STUFF!
echo x - ckmain.c
sed '1,$s/^X//' <<\!FUNKY!STUFF! > ckmain.c
Xchar *versio = "C-Kermit 4.2(030) PRERELEASE # 2, 5 March 85";
X
X/* C K M A I N  --  C-Kermit Main program */
X
X/*
X Authors: Frank da Cruz, Bill Catchings, Jeff Damens;
X Columbia University Center for Computing Activities, 1984-85.
X Copyright (C) 1985, Trustees of Columbia University in the City of New York.
X Permission is granted to any individual or institution to copy or use this
X program except for explicitly commercial purposes, provided this copyright
X notice is retained.
X*/
X/*
X The Kermit file transfer protocol was developed at Columbia University.
X It is named after Kermit the Frog, star of the television series THE
X MUPPET SHOW; the name is used by permission of Henson Associates, Inc.
X "Kermit" is also Celtic for "free".
X*/
X/*
X Thanks to Herm Fischer, Litton Data Systems, for extensive contributions to
X version 4, and to the following people for their contributions over the years:
X
X   Bob Cattani & Chris Maio, Columbia CS Dept
X   Alan Crosswell, CUCCA
X   Carl Fongheiser, CWRU
X   Jim Guyton, Rand Corp
X   Stan Hanks, Rice U.
X   Ken Harrenstein, SRI
X   Steve Hemminger, Tektronix
X   Tony Movshon, NYU
X   Ken Poulton, HP Labs
X   Dave Tweten, NASA Ames
X   Walter Underwood, Ford Aerospace
X   Pieter Van Der Linden, Centre Mondial (Paris)
X   Lauren Weinstein, Vortex
X
X and many others.
X*/
X
X#include "ckermi.h"
X
X/* Text message definitions */
X
X#ifndef XENIX
X
Xchar *hlptxt = "C-Kermit Server\n\
X\n\
XServer Function    Customary Command to Invoke the Function\n\
X Who's Logged In?   REMOTE WHO [user]\n\
X Help               REMOTE HELP\n\
X Finish Serving     FINISH\n\
X Send File(s)       GET filespec\n\
X Receive File(s)    SEND filespec\n\
X Directory Listing  REMOTE DIRECTORY [filespec]\n\
X Change Directory   REMOTE CWD [directory]\n\
X Type File(s)       REMOTE TYPE filespec\n\
X Delete File(s)     REMOTE DELETE filespec\n\
X Disk Usage Query   REMOTE SPACE [directory]\n\
X Unix Shell Command REMOTE HOST command-string\n\
X\n\0";
X
X#else
X
Xchar *hlptxt = "C-Kermit Server Commands Supported:\n\
X\n\
XGET filespec	REMOTE CWD [directory]		REMOTE SPACE [directory]\n\
XSEND filespec	REMOTE DIRECTORY [filespec]	REMOTE HOST command-string\n\
XFINISH		REMOTE DELETE filespec		REMOTE WHO [user]\n\
XREMOTE HELP	REMOTE TYPE filespec\n\
X\n\0";
X
X#endif
X
Xchar *srvtxt = "\r\n\
XC-Kermit server starting.  Return to your local machine by typing\r\n\
Xits escape sequence for closing the connection, and issue further\r\n\
Xcommands from there.  To shut down the C-Kermit server, issue the\r\n\
XFINISH command and then reconnect.\n\
X\r\n\0";
X
X/* Declarations for Send-Init Parameters */
X
Xint spsiz =  DSPSIZ,			/* maximum packet size we can send */
X    timint = DMYTIM,			/* My timeout interval */
X    timef = 0,				/* Flag for override packet timeout */
X    npad = MYPADN,			/* How much padding to send */
X    mypadn = MYPADN,			/* How much padding to ask for */
X    chklen = 1,				/* Length of block check */
X    bctr = 1,				/* Block check type requested */
X    bctu = 1,				/* Block check type used */
X    ebq =  MYEBQ,			/* 8th bit prefix */
X    ebqflg = 0,				/* 8th-bit quoting flag */
X    rpt = 0,				/* Repeat count */
X    rptq = MYRPTQ,			/* Repeat prefix */
X    rptflg = 0,				/* Repeat processing flag */
X    capas = 0;				/* Capabilities */
X
Xchar padch = MYPADC,			/* Padding character to send */
X    mypadc = MYPADC,			/* Padding character to ask for */
X    eol = MYEOL,			/* End-Of-Line character to send */
X    ctlq = CTLQ,			/* Control prefix in incoming data */
X    myctlq = CTLQ;			/* Outbound control character prefix */
X
X
X/* Packet-related variables */
X
Xint pktnum = 0,				/* Current packet number */
X    prvpkt = -1,			/* Previous packet number */
X    sndtyp,				/* Type of packet just sent */
X    size,				/* Current size of output pkt data */
X    osize,				/* Previous output packet data size */
X    maxsize,				/* Max size for building data field */
X    spktl;				/* Length packet being sent */
X
Xchar sndpkt[MAXPACK*2], 		/* Entire packet being sent */
X    recpkt[RBUFL], 			/* Packet most recently received */
X    data[MAXPACK+4],   			/* Packet data buffer */
X    srvcmd[MAXPACK*2],			/* Where to decode server command */
X    *srvptr,				/* Pointer to above */
X    mystch = SOH,			/* Outbound packet-start character */
X    stchr = SOH;			/* Incoming packet-start character */
X
X/* File-related variables */
X
Xchar filnam[50];			/* Name of current file. */
X
Xint nfils,				/* Number of files in file group */
X    fsize;				/* Size of current file */
X
X/* Communication line variables */
X
Xchar ttname[50];			/* Name of communication line. */
X
Xint parity,				/* Parity specified, 0,'e','o',etc */
X    flow,				/* Flow control, 1 = xon/xoff */
X    speed = -1,				/* Line speed */
X    turn = 0,				/* Line turnaround handshake flag */
X    turnch = XON,			/* Line turnaround character */
X    duplex = 0,				/* Duplex, full by default */
X    escape = 034,			/* Escape character for connect */
X    delay = DDELAY,			/* Initial delay before sending */
X    mdmtyp = 0;				/* Type of modem 1=hayes 2=ventel */
X
X
X/* Statistics variables */
X
Xlong filcnt,			/* Number of files in transaction */
X    flci,			/* Characters from line, current file */
X    flco,			/* Chars to line, current file  */
X    tlci,			/* Chars from line in transaction */
X    tlco,   	    	    	/* Chars to line in transaction */
X    ffc,			/* Chars to/from current file */
X    tfc;			/* Chars to/from files in transaction */
X
X/* Flags */
X
Xint deblog = 0,				/* Flag for debug logging */
X    pktlog = 0,				/* Flag for packet logging */
X    seslog = 0,				/* Session logging */
X    tralog = 0,				/* Transaction logging */
X    displa = 0,				/* File transfer display on/off */
X    stdouf = 0,				/* Flag for output to stdout */
X    xflg   = 0,				/* Flag for X instead of F packet */
X    hcflg  = 0,				/* Doing Host command */
X    fncnv  = 1,				/* Flag for file name conversion */
X    binary = 0,				/* Flag for binary file */
X    warn   = 0,				/* Flag for file warning */
X    quiet  = 0,				/* Be quiet during file transfer */
X    local  = 0,				/* Flag for external tty vs stdout */
X    server = 0,				/* Flag for being a server */
X    cnflg  = 0,				/* Connect after transaction */
X    cxseen = 0,				/* Flag for cancelling a file */
X    czseen = 0; 	    	    	/* Flag for cancelling file group */
X
X/* Variables passed from command parser to protocol module */
X
Xchar sstate  = 0;			/* Starting state for automaton */
Xchar *cmarg  = "";			/* Pointer to command data */
Xchar *cmarg2 = "";			/* Pointer to second data field */
Xchar **cmlist;				/* Pointer to file list in argv */
X
X/* Miscellaneous */
X
Xchar **xargv;				/* Global copies of argv */
Xint  xargc;				/* and argc  */
X
Xextern char *dftty;			/* Default tty name from ckx???.c */
Xextern int dfloc;			/* Default location: remote/local */
Xextern int dfprty;			/* Default parity */
Xextern int dfflow;			/* Default flow control */
X
X
X/*  M A I N  --  C-Kermit main program  */
X
Xmain(argc,argv) int argc; char **argv; {
X
X    char *strcpy();
X
X/* Do some initialization */
X
X    xargc = argc;			/* Make global copies of argc */
X    xargv = argv;			/* ...and argv. */
X    sstate = 0;				/* No default start state. */
X    strcpy(ttname,dftty);		/* Set up default tty name. */
X    local = dfloc;			/* And whether it's local or remote. */
X    parity = dfprty;			/* Set initial parity, */
X    flow = dfflow;			/* and flow control. */
X    
X/* Look for a UNIX-style command line... */
X
X    if (argc > 1) {			/* Command line arguments? */
X	sstate = cmdlin();		/* Yes, parse. */
X	if (sstate) {
X	    proto();			/* Take any requested action, then */
X	    if (!quiet) conoll("");	/* put cursor back at left margin, */
X	    if (cnflg) conect();	/* connect if requested, */
X	    doexit(0);			/* and then exit with status 0. */
X    	}
X    }	
X    
X/* If no action requested on command line, enter interactive parser */
X
X    cmdini();				/* Initialize command parser */
X    while(sstate = parser()) {		/* Loop getting commands. */
X	if (sstate) proto();		/* Enter protocol if requested. */
X    }
X}
!FUNKY!STUFF!
echo x - cklogi.c
sed '1,$s/^X//' <<\!FUNKY!STUFF! > cklogi.c
Xchar *loginv = "Login Command for Unix, V1.0(003) 28 Feb 85";
X
X/*  C K L O G I  --  Login script for logging onto remote system */
X
X/*
X This module should work under all versions of Unix.  It calls externally
X defined system-depended functions for i/o.
X
X The module expects a login string of the expect send [expect send] ...
X format.  It is intended to operate similarly to the way the common
X uucp "L.sys" login entries work.  Conditional responses are supported
X expect[-send-expect[...]] as with uucp.  The send keyword EOT sends a
X control-d, and the keyword BREAK sends a break.  Letters prefixed
X by '~' are '~b' backspace, '~s' space, '~n' linefeed, '~r' return,
X '~t' tab, '~q' ? (not allowed on kermit command lines), '~' ~, '~'', 
X '~"', '~c' don't append return, '~o[o[o]]' octal character.  As with
X some uucp systems, sent strings are followed by ~r (not ~n) unless they
X end with ~c. Null expect strings (e.g., ~0 or --) cause a short
X delay, and are useful for sending sequences requiring slight pauses.
X
X Author: Herm Fischer, Litton Data Systems, Van Nuys CA (HFISCHER at USC-ECLB)
X*/
X
X#include "ckermi.h"
X#include <signal.h>
X#include <setjmp.h>
X
Xextern int local, speed, flow, seslog, mdmtyp;
Xextern char ttname[];
Xstatic char * chstr();
X
X#define EXP_ALRM	15		/* Time to wait for expect string */
X#define SND_ALRM	15		/* Time to allow for sending string */
X#define NULL_EXP	2		/* Time to pause on null expect strg*/ 
X
X#define SBUFL 300			/* Login Sequence buffer */
Xstatic char seq_buf[SBUFL], *s;
Xstatic int got_it, no_cr;
X
X/*  connect state parent/child communication signal handlers */
X
Xstatic jmp_buf alrmRng;		/* Envir ptr for connect errors */
X
Xstatic
XtimeInt() {				/* modem read failure handler, */
X    longjmp(alrmRng,1);		/* notifies parent process to stop */
X}
X
X/*
X Sequence interpreter -- pick up next sequence from command string,
X decode escapes and place into seq_buf
X*/
Xstatic 
Xsequenc()  {
X
X    int i;
X    char c, oct_char;
X
X    no_cr = 0;				/* output needs cr appended */
X
X    for (i=0; i<SBUFL; ) {		
X	if (*s == '\0' || *s == '-' || *s == ' ') { /* done */
X	    seq_buf[i] = '\0';
X	    return ;
X	}
X
X	if (*s == '~') {		/* escape character */
X	    switch (c = *(++s) ) {
X		case 'n':	seq_buf[i++] = '\n'; break;
X		case 'r':	seq_buf[i++] = '\r'; break;
X		case 't':	seq_buf[i++] = '\t'; break;
X		case 'b':	seq_buf[i++] = '\b'; break;
X		case 'q':	seq_buf[i++] = '?';  break;
X		case '~':	seq_buf[i++] = '~';  break;
X		case '\'':	seq_buf[i++] = '\''; break;
X		case '\"':	seq_buf[i++] = '\"'; break;
X		case 's':	seq_buf[i++] = ' ';  break;
X		case 'c':	no_cr = 1; break;
X		default:
X		    if ( isdigit(c) ) {	    	/* octal character */
X		    	oct_char = (c & 7);	/* most significant digit */
X			if (isdigit( *(s+1) ) ) {
X			    oct_char = (oct_char<<3) | ( (*(++s)) & 7 ) ;
X			    if (isdigit( *(s+1) ) ) {
X			    	oct_char = (oct_char<<3) | ( (*(++s)) & 7 ) ;
X			    }
X			}
X			seq_buf[i++] = oct_char;
X			break;
X		    }
X	    }
X	}
X	else seq_buf[i++] = *s;		/* plain old character */
X	s++;
X    }
X    seq_buf[i] = '\0';
X    return;			/* end of space, return anyway */
X}
X
X/*
X Receive sequence -- see if expected response comes return success
X (or failure) in got_it
X*/ 
Xstatic 
XrecvSeq()  {
X   
X    char *e, got[7], trace[300];
X    int i, l;
X    
X	sequenc();
X	l = strlen(e=seq_buf);		/* no more than 7 chars allowed */
X	if (l > 7) {
X	    e += l-7;
X	    l = 7;
X	}
X
X	tlog(F111,"expecting sequence",e,(long) l);
X	if (l == 0) {		/* null sequence, just delay a little */
X	    sleep (NULL_EXP);
X	    got_it = 1;
X	    tlog(F100,"got it (null sequence)","",0l);
X	    return;
X	}
X	*trace = '\0';
X	for (i=0; i<7; i++) got[i]='\0';
X
X	signal(SIGALRM,timeInt);	/* did we get it? */
X	if (!setjmp(alrmRng)) {	/* not timed out yet */
X	    alarm(EXP_ALRM);
X	    while (!got_it) {
X		for (i=0; i<(l-1); i++) got[i] = got[i+1]; /* shift over one */
X		got[l-1] = ttinc(0) & 0177;		/* next char */
X		if (strlen(trace) < sizeof(trace)-2 ) 
X			strcat(trace,chstr(got[l-1]));
X		got_it = (!strncmp(seq_buf, got, l) ) ;
X	    }
X	} else got_it = 0;		/* timed out here */
X
X	alarm(0);
X	signal(SIGALRM,SIG_IGN);
X	tlog(F110,"received sequence: ",trace,0l);
X	tlog(F101,"returning with got-it code","",(long) got_it);
X	return;
X}
X
X/*
X Output A Sequence starting at pointer s,
X return 0 if okay,
X 1 if failed to read (modem hangup or whatever)
X*/
Xstatic int
XoutSeq()  {
X    char *sb;
X    int l;
X
X    sequenc();
X    l = strlen(seq_buf);
X    tlog(F111,"sending sequence ",seq_buf,(long) l);
X    signal(SIGALRM,timeInt);
X    if (!setjmp(alrmRng)) {
X	alarm(SND_ALRM);
X	if (!strcmp(seq_buf,"EOT")) ttoc(dopar('\004'));
X	else if (!strcmp(seq_buf,"BREAK")) ttsndb();
X 	else {
X	    if (l > 0) {
X		for ( sb=seq_buf; *sb; sb++) *sb = dopar(*sb);
X		ttol(seq_buf,l);		/* with parity */
X	    }
X	    if (!no_cr) ttoc( dopar('\r') );
X	}
X	alarm(0);
X	signal(SIGALRM,SIG_IGN);
X	return(0);
X    }
X    alarm(0);    		/* else -- alarm rang */
X    signal(SIGALRM,SIG_IGN);
X    return( -1 );
X}
X
X/*  L O G I N  --  Login to remote system */
X
Xlogin(cmdstr) char *cmdstr; {
X
X	int (*saveAlm)();	/* save incomming alarm function */
X	char *e;
X
X	s = cmdstr;			/* make global to cklogi.c */
X
X	tlog(F100,loginv,"",0l);
X
X	if (!local) {
X	    printf("Sorry, you must 'set line' first\n");
X	    return(-2);
X	}
X	if (speed < 0) {
X	    printf("Sorry, you must 'set speed' first\n");
X	    return(-2);
X        }
X	if (ttopen(ttname,local,mdmtyp) < 0) {
X	    sprintf(seq_buf,"Sorry, can't open %s",ttname);
X	    perror(seq_buf);
X	    return(-2);
X    	}
X    	printf("Logging on thru %s, speed %d.\r\n",ttname,speed);
X	*seq_buf=0;
X	for (e=s; *e; e++) strcat(seq_buf, chstr(*e) );
X	printf("The logon string is: %s\r\n",seq_buf);
X	tlog(F110,"Logon command string: ",seq_buf, 0l);
X
X/* Condition console terminal and communication line */	    
X
X	if (ttvt(speed,flow) < 0) {
X	    printf("Sorry, Can't condition communication line\n");
X	    return(-2);
X    	}
X				/* save initial timer interrupt value */
X	saveAlm = signal(SIGALRM,SIG_IGN);
X
X	ttflui();		/* flush stale input */
X
X/* cont'd... */
X
X/* ...login, cont'd */
X
X/* start expect - send sequence */
X
X    while (*s) {		/* while not done with buffer */
X
X	while (*s && *s == ' ') s++;	/* skip over separating blanks */
X				/* gather up expect sequence */
X	got_it = 0;
X	recvSeq();
X
X	while (!got_it) {
X				/* no, is there a conditional send */
X	    if (*s++ != '-') goto failRet;    	/* no -- return failure */
X		
X	    		/* start of conditional send */
X	    ttflui();				/* flush out input buffer */
X	    if (outSeq()) goto failRet; 	/* if unable to send! */
X
X	    if (*s++ != '-') goto failRet; 	/* must have condit respon.*/
X	    recvSeq();
X	}	/* loop back and check got_it */
X
X	while (*s && *s++ != ' ') ; 	/* skip over conditionals and spaces */
X	ttflui();			/* Flush */
X	if (*s) if (outSeq()) goto failRet; 	/* if any */
X    }
X    signal(SIGALRM,saveAlm);
X    printf("Logged on!\r\n");
X    tlog(F100,"Logged on!","",0l);
X    return(0);
X
XfailRet:
X    signal(SIGALRM,saveAlm);
X    printf("Sorry, logon failed\r\n");
X    tlog(F100,"Logon failed","",0l);
X    return(-2);
X}
X
X
X/*  C H S T R  --  Make printable string from a character */
X
Xstatic char *
Xchstr(c) char c; {
X    static char sc[4];
X
X    if (c < SP) sprintf(sc, "^%c",ctl(c) );
X    else sprintf(sc, "%c", c);
X  
X    return(sc);
X}
!FUNKY!STUFF!



More information about the Comp.sources.unix mailing list