C-KERMIT (Part 5 of 10)
gregg at okstate.UUCP
gregg at okstate.UUCP
Fri Mar 8 17:47:00 AEST 1985
echo x - ckuser.c
sed '1,$s/^X//' <<\!FUNKY!STUFF! > ckuser.c
Xchar *userv = "User Interface V4.2(038), 5 Mar 85";
X
X/* C K U S E R -- "User Interface" for Unix Kermit (Part 1) */
X
X/* Frank da Cruz, Columbia University Center for Computing Activities, 1985 */
X/*
X The ckuser module contains the terminal input and output functions for Unix
X Kermit. It includes a simple Unix-style command line parser as well as
X an interactive prompting keyword command parser. It depends on the existence
X of Unix facilities like fopen, fgets, feof, (f)printf, argv/argc, etc. Other
X functions that are likely to vary among Unix implementations -- like setting
X terminal modes or interrupts -- are invoked via calls to functions that are
X defined in the system-dependent modules, ck[xz]*.c.
X
X The command line parser processes any arguments found on the command line,
X as passed to main() via argv/argc. The interactive parser uses the facilities
X of the cmd package (developed for this program, but usable by any program).
X
X Any command parser may be substituted for this one. The only requirements
X for the Kermit command parser are these:
X
X 1. Set parameters via global variables like duplex, speed, ttname, etc.
X See ckmain.c for the declarations and descriptions of these variables.
X
X 2. If a command can be executed without the use of Kermit protocol, then
X execute the command directly and set the variable sstate to 0. Examples
X include 'set' commands, local directory listings, the 'connect' command.
X
X 3. If a command requires the Kermit protocol, set the following variables:
X
X sstate string data
X 'x' (enter server mode) (none)
X 'r' (send a 'get' command) cmarg, cmarg2
X 'v' (enter receive mode) cmarg2
X 'g' (send a generic command) cmarg
X 's' (send files) nfils, cmarg & cmarg2 OR cmlist
X 'c' (send a remote host command) cmarg
X
X cmlist is an array of pointers to strings.
X cmarg, cmarg2 are pointers to strings.
X nfils is an integer.
X
X cmarg can be a filename string (possibly wild), or
X a pointer to a prefabricated generic command string, or
X a pointer to a host command string.
X cmarg2 is the name to send a single file under, or
X the name under which to store an incoming file; must not be wild.
X cmlist is a list of nonwild filenames, such as passed via argv.
X nfils is an integer, interpreted as follows:
X -1: argument string is in cmarg, and should be expanded internally.
X 0: stdin.
X >0: number of files to send, from cmlist.
X
X The screen() function is used to update the screen during file transfer.
X The tlog() function maintains a transaction log.
X The debug() function maintains a debugging log.
X The intmsg() and chkint() functions provide the user i/o for interrupting
X file transfers.
X*/
X
X/* Includes */
X
X#include "ckermi.h"
X#include "ckcmd.h"
X#include "ckuser.h"
X
X/* External Kermit Variables, see ckmain.c for description. */
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 *ckxsys, *ckzsys, *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/* Declarations from ckz??? module */
X
Xextern char *SPACMD, *zhome(); /* Space command, home directory. */
Xextern int backgrd; /* Kermit executing in background */
X
X/* The background flag is set by ckxunx.c (via conint() ) to note whether */
X/* this kermit is executing in background ('&' on shell command line). */
X
X
X/* Variables and symbols local to this module */
X
Xchar line[100], *lp; /* Character buffer for anything */
Xchar debfil[50]; /* Debugging log file name */
Xchar pktfil[50]; /* Packet log file name */
Xchar sesfil[50]; /* Session log file name */
Xchar trafil[50]; /* Transaction log file name */
X
Xint n, /* General purpose int */
X cflg, /* Command-line connect cmd given */
X action, /* Action selected on command line*/
X ncmd, /* Number of commands */
X nprm, /* Number of parameters */
X nrmt, /* Number of remote commands */
X repars, /* Reparse needed */
X tlevel, /* Take command level */
X cwdf = 0; /* CWD has been done */
X
X#define MAXTAKE 20 /* Maximum nesting of TAKE files */
XFILE *tfile[MAXTAKE]; /* File pointers for TAKE command */
X
Xchar *homdir; /* Pointer to home directory string */
Xchar cmdstr[100];
X
X/* C M D L I N -- Get arguments from command line */
X/*
X Simple Unix-style command line parser, conforming with 'A Proposed Command
X Syntax Standard for Unix Systems', Hemenway & Armitage, Unix/World, Vol.1,
X No.3, 1984.
X*/
Xcmdlin() {
X char x;
X cmarg = ""; /* Initialize. */
X cmarg2 = "";
X action = cflg = 0;
X
X while (--xargc > 0) { /* Go through command line words */
X *xargv++;
X debug(F111,"xargv",*xargv,xargc);
X if (**xargv == '-') { /* Got an option (begins with dash) */
X x = *(*xargv+1); /* Get the option letter */
X x = doarg(x); /* Go handle the option */
X if (x < 0) exit(0);
X } else { /* No dash where expected */
X usage();
X exit(1);
X }
X }
X debug(F101,"action","",action);
X if (!local) {
X if ((action == 'g') || (action == 'r') ||
X (action == 'c') || (cflg != 0))
X fatal("-l and -b required");
X }
X if (*cmarg2 != 0) {
X if ((action != 's') && (action != 'r') &&
X (action != 'v'))
X fatal("-a without -s, -r, or -g");
X }
X if ((action == 'v') && (stdouf) && (!local)) {
X if (isatty(1))
X fatal("unredirected -k can only be used in local mode");
X }
X if ((action == 's') || (action == 'v') ||
X (action == 'r') || (action == 'x')) {
X if (local) displa = 1;
X if (stdouf) displa = 0;
X }
X
X if (quiet) displa = 0; /* No display if quiet requested */
X
X if (cflg) {
X conect(); /* Connect if requested */
X if (action == 0) {
X if (cnflg) conect(); /* And again if requested */
X doexit(0); /* exit with status = 0 */
X }
X }
X if (displa) concb(escape); /* (for console "interrupts") */
X return(action); /* Then do any requested protocol */
X}
X
X/* D O A R G -- Do a command-line argument. */
X
Xdoarg(x) char x; {
X int z; char *xp;
X
X xp = *xargv+1; /* Pointer for bundled args */
X while (x) {
X switch (x) {
X
Xcase 'x': /* server */
X if (action) fatal("conflicting actions");
X action = 'x';
X break;
X
Xcase 'f':
X if (action) fatal("conflicting actions");
X action = setgen('F',"","","");
X break;
X
Xcase 'r': /* receive */
X if (action) fatal("conflicting actions");
X action = 'v';
X break;
X
Xcase 'k': /* receive to stdout */
X if (action) fatal("conflicting actions");
X stdouf = 1;
X action = 'v';
X break;
X
Xcase 's': /* send */
X if (action) fatal("conflicting actions");
X if (*(xp+1)) fatal("invalid argument bundling after -s");
X z = nfils = 0; /* Initialize file counter, flag */
X cmlist = xargv+1; /* Remember this pointer */
X while (--xargc > 0) { /* Traverse the list */
X *xargv++;
X if (**xargv == '-') { /* Check for sending stdin */
X if (strcmp(*xargv,"-") != 0) break;
X z++;
X }
X nfils++; /* Bump file counter */
X }
X xargc++, *xargv--; /* Adjust argv/argc */
X if (nfils < 1) fatal("missing filename for -s");
X if (z > 1) fatal("-s: too many -'s");
X if (z == 1) {
X if (nfils == 1) nfils = 0;
X else fatal("invalid mixture of filenames and '-' in -s");
X }
X if (nfils == 0) {
X if (isatty(0)) fatal("sending from terminal not allowed");
X }
X debug(F101,*xargv,"",nfils);
X action = 's';
X break;
X
X/* cont'd... */
X
X/* ...doarg(), cont'd */
X
Xcase 'g': /* get */
X if (action) fatal("conflicting actions");
X if (*(xp+1)) fatal("invalid argument bundling after -g");
X *xargv++, xargc--;
X if ((xargc == 0) || (**xargv == '-'))
X fatal("missing filename for -g");
X cmarg = *xargv;
X action = 'r';
X break;
X
Xcase 'c': /* connect before */
X cflg = 1;
X break;
X
Xcase 'n': /* connect after */
X cnflg = 1;
X break;
X
Xcase 'h': /* help */
X usage();
X return(-1);
X
Xcase 'a': /* "as" */
X if (*(xp+1)) fatal("invalid argument bundling after -a");
X *xargv++, xargc--;
X if ((xargc < 1) || (**xargv == '-'))
X fatal("missing name in -a");
X cmarg2 = *xargv;
X break;
X
Xcase 'l': /* set line */
X if (*(xp+1)) fatal("invalid argument bundling after -l");
X *xargv++, xargc--;
X if ((xargc < 1) || (**xargv == '-'))
X fatal("communication line device name missing");
X strcpy(ttname,*xargv);
X if (strcmp(ttname,dftty) == 0) local = dfloc; else local = 1;
X break;
X
Xcase 'b': /* set baud */
X if (*(xp+1)) fatal("invalid argument bundling");
X *xargv++, xargc--;
X if ((xargc < 1) || (**xargv == '-'))
X fatal("missing baud");
X z = atoi(*xargv); /* Convert to number */
X if (chkspd(z) > -1) speed = z; /* Check it */
X else fatal("unsupported baud rate");
X break;
X
Xcase 'i': /* Treat files as binary */
X binary = 1;
X break;
X
X/* cont'd... */
X
X/* ...doarg(), cont'd */
X
X
Xcase 'w': /* File warning */
X warn = 1;
X break;
X
Xcase 'q': /* Quiet */
X quiet = 1;
X break;
X
Xcase 'd': /* debug */
X debopn("debug.log");
X break;
X
Xcase 'p': /* set parity */
X if (*(xp+1)) fatal("invalid argument bundling");
X *xargv++, xargc--;
X if ((xargc < 1) || (**xargv == '-'))
X fatal("missing parity");
X switch(x = **xargv) {
X case 'e':
X case 'o':
X case 'm':
X case 's': parity = x; break;
X case 'n': parity = 0; break;
X default: fatal("invalid parity");
X }
X break;
X
Xcase 't':
X turn = 1; /* Line turnaround handshake */
X turnch = XON; /* XON is turnaround character */
X duplex = 1; /* Half duplex */
X flow = 0; /* No flow control */
X break;
X
Xdefault:
X fatal("invalid argument, type 'kermit -h' for help");
X }
X
X x = *++xp; /* See if options are bundled */
X }
X return(0);
X}
X
X/* Misc */
X
Xfatal(msg) char *msg; { /* Fatal error message */
X fprintf(stderr,"\r\nFatal: %s\n",msg);
X tlog(F110,"Fatal:",msg,0l);
X doexit(1); /* exit with status = 1 */
X}
X
X
Xermsg(msg) char *msg; { /* Print error message */
X if (!quiet) fprintf(stderr,"\r\nError - %s\n",msg);
X tlog(F110,"Error -",msg,0l);
X}
X
X/* Interactive command parser */
X
X
X/* Top-Level Keyword Table */
X
Xstruct keytab cmdtab[] = {
X "!", XXSHE, 0,
X "bye", XXBYE, 0,
X "c", XXCON, CM_INV,
X "close", XXCLO, 0,
X "connect", XXCON, 0,
X "cwd", XXCWD, 0,
X "dial", XXDIAL, 0,
X "directory", XXDIR, 0,
X "echo", XXECH, 0,
X "exit", XXEXI, 0,
X "finish", XXFIN, 0,
X "get", XXGET, 0,
X "help", XXHLP, 0,
X "log", XXLOG, 0,
X "quit", XXQUI, 0,
X "r", XXREC, CM_INV,
X "receive", XXREC, 0,
X "remote", XXREM, 0,
X "s", XXSEN, CM_INV,
X "script", XXLOGI, 0,
X "send", XXSEN, 0,
X "server", XXSER, 0,
X "set", XXSET, 0,
X "show", XXSHO, 0,
X "space", XXSPA, 0,
X "statistics", XXSTA, 0,
X "take", XXTAK, 0
X};
Xint ncmd = (sizeof(cmdtab) / sizeof(struct keytab));
X
X/* Parameter keyword table */
X
Xstruct keytab prmtab[] = {
X "baud", XYSPEE, CM_INV,
X "block-check", XYCHKT, 0,
X "delay", XYDELA, 0,
X "duplex", XYDUPL, 0,
X "end-of-packet", XYEOL, 0,
X "escape-character", XYESC, 0,
X "file", XYFILE, 0,
X "flow-control", XYFLOW, 0,
X "handshake", XYHAND, 0,
X "line", XYLINE, 0,
X "modem-dialer", XYMODM, 0,
X "packet-length", XYLEN, 0,
X "pad-character", XYPADC, 0,
X "padding", XYNPAD, 0,
X "parity", XYPARI, 0,
X "prompt", XYPROM, 0,
X "speed", XYSPEE, 0,
X "start-of-packet", XYMARK, 0,
X "timeout", XYTIMO, 0
X};
Xint nprm = (sizeof(prmtab) / sizeof(struct keytab)); /* How many parameters */
X
X
X/* Remote Command Table */
X
Xstruct keytab remcmd[] = {
X "cwd", XZCWD, 0,
X "delete", XZDEL, 0,
X "directory", XZDIR, 0,
X "help", XZHLP, 0,
X "host", XZHOS, 0,
X "space", XZSPA, 0,
X "type", XZTYP, 0,
X "who", XZWHO, 0
X};
Xint nrmt = (sizeof(remcmd) / sizeof(struct keytab));
X
Xstruct keytab logtab[] = {
X "debugging", LOGD, 0,
X "packets", LOGP, 0,
X "session", LOGS, 0,
X "transactions", LOGT, 0
X};
Xint nlog = (sizeof(logtab) / sizeof(struct keytab));
X
X/* Show command arguments */
X
X#define SHPAR 0 /* Parameters */
X#define SHVER 1 /* Versions */
X
Xstruct keytab shotab[] = {
X "parameters", SHPAR, 0,
X "versions", SHVER, 0
X};
X
X/* C M D I N I -- Initialize the interactive command parser */
X
Xcmdini() {
X
X printf("%s,%s\nType ? for help\n",versio,ckxsys);
X cmsetp("C-Kermit>"); /* Set default prompt. */
X
X tlevel = -1; /* Take file level */
X
X/* Look for init file ".kermrc" in home or current directory. */
X
X homdir = zhome();
X lp = line;
X if (homdir)
X sprintf(lp,"%s/.kermrc",homdir);
X else
X sprintf(lp,".kermrc");
X if ((tfile[0] = fopen(line,"r")) != NULL) {
X tlevel = 0;
X debug(F110,"init file",line,0);
X }
X if (homdir && (tlevel < 0)) {
X sprintf(lp,".kermrc");
X if ((tfile[0] = fopen(line,"r")) != NULL) {
X tlevel = 0;
X debug(F110,"init file",line,0);
X } else {
X debug(F100,"no init file","",0);
X }
X }
X
X congm(); /* Get console tty modes */
X}
X
X
X/* T R A P -- Terminal interrupt handler */
X
Xtrap() {
X debug(F100,"terminal interrupt...","",0);
X doexit(0); /* exit with status = 0 */
X}
X
X/* P A R S E R -- Top-level interactive command parser. */
X
Xparser() {
X int xx;
X concb(escape); /* Put console in cbreak mode. */
X conint(trap); /* Turn on console terminal interrupts. */
X/*
X sstate becomes nonzero when a command has been parsed that requires some
X action from the protocol module. Any non-protocol actions, such as local
X directory listing or terminal emulation, are invoked directly from below.
X*/
X if (local) printf("\n"); /*** Temporary kludge ***/
X sstate = 0; /* Start with no start state. */
X while (sstate == 0) { /* Parse cmds until action requested */
X while ((tlevel > -1) && feof(tfile[tlevel])) { /* If end of take */
X fclose(tfile[tlevel]); /* file, close it */
X tlevel--; /* and forget about it. */
X cmini(ckxech); /* and clear the cmd buffer. */
X }
X if (tlevel > -1) {
X if (fgets(cmdbuf,CMDBL,tfile[tlevel]) == NULL) continue;
X stripq(cmdbuf); /* Strip any quotes. */
X } else { /* Otherwise. */
X prompt(); /* Issue interactive prompt. */
X cmini(ckxech);
X }
X repars = 1;
X displa = 0;
X while (repars) {
X cmres(); /* Reset buffer pointers. */
X xx = cmkey(cmdtab,ncmd,"Command","");
X debug(F101,"top-level cmkey","",xx);
X switch (docmd(xx)) {
X case -4: /* EOF */
X doexit(0); /* exit with status 0 */
X case -1: /* Reparse needed */
X repars = 1;
X continue;
X case -2: /* Invalid command given */
X if (backgrd) /* if in background, terminate */
X fatal("Kermit command error in background execution");
X if (tlevel > -1) { /* If in take file, quit */
X ermsg("Kermit command error: take file terminated.");
X fclose(tfile[tlevel]);
X tlevel--;
X }
X cmini(ckxech); /* (fall thru) */
X case -3: /* Empty command OK at top level */
X default: /* Anything else (fall thru) */
X repars = 0; /* No reparse, get new command. */
X continue;
X }
X }
X }
X/* Got an action command; disable terminal interrupts and return start state */
X
X if (!local) connoi(); /* Interrupts off only if remote */
X return(sstate);
X}
X
X/* D O E X I T -- Exit from the program. */
X
Xdoexit(exitstat) int exitstat; {
X
X ttclos(); /* Close external line, if any */
X if (local) {
X strcpy(ttname,dftty); /* Restore default tty */
X local = dfloc; /* And default remote/local status */
X }
X if (!quiet) conres(); /* Restore console terminal. */
X if (!quiet) connoi(); /* Turn off console interrupt traps. */
X
X if (deblog) { /* Close any open logs. */
X debug(F100,"Debug Log Closed","",0);
X *debfil = '\0';
X deblog = 0;
X zclose(ZDFILE);
X }
X if (pktlog) {
X *pktfil = '\0';
X pktlog = 0;
X zclose(ZPFILE);
X }
X if (seslog) {
X *sesfil = '\0';
X seslog = 0;
X zclose(ZSFILE);
X }
X if (tralog) {
X tlog(F100,"Transaction Log Closed","",0l);
X *trafil = '\0';
X tralog = 0;
X zclose(ZTFILE);
X }
X exit(exitstat); /* Exit from the program. */
X}
X
X/* B L D L E N -- Make length-encoded copy of string */
X
Xchar *
Xbldlen(str,dest) char *str, *dest; {
X int len;
X len = strlen(str);
X *dest = tochar(len);
X strcpy(dest+1,str);
X return(dest+len+1);
X}
X
X
X/* S E T G E N -- Construct a generic command */
X
Xsetgen(type,arg1,arg2,arg3) char type, *arg1, *arg2, *arg3; {
X char *upstr, *cp;
X
X cp = cmdstr;
X *cp++ = type;
X *cp = NUL;
X if (*arg1 != NUL) {
X upstr = bldlen(arg1,cp);
X if (*arg2 != NUL) {
X upstr = bldlen(arg2,upstr);
X if (*arg3 != NUL) bldlen(arg3,upstr);
X }
X }
X cmarg = cmdstr;
X debug(F110,"setgen",cmarg,0);
X
X return('g');
X}
X
X/* D O C M D -- Do a command */
X
X/*
X Returns:
X -2: user typed an illegal command
X -1: reparse needed
X 0: parse was successful (even tho command may have failed).
X*/
X
Xdocmd(cx) int cx; {
X int x, y;
X char *s;
X
X switch (cx) {
X
Xcase -4: /* EOF */
X if (!quiet) printf("\r\n");
X doexit(0);
Xcase -3: /* Null command */
X return(0);
Xcase -2: /* Error */
Xcase -1: /* Reparse needed */
X return(cx);
X
Xcase XXBYE: /* bye */
X if ((x = cmcfm()) < 0) return(x);
X if (!local) {
X printf("You have to 'set line' first\n");
X return(0);
X }
X sstate = setgen('L',"","","");
X return(0);
X
Xcase XXCON: /* connect */
X if ((x = cmcfm()) < 0) return(x);
X conres(); /* restore tty to normal mode */
X x = conect();
X concb(escape); /* tty back in character mode */
X return(x);
X
Xcase XXCWD:
X if (cmtxt("Name of local directory, or carriage return",homdir,&s) < 0)
X return(-1);
X if (chdir(s)) perror(s);
X cwdf = 1;
X system("pwd");
X return(0);
X
Xcase XXCLO:
X x = cmkey(logtab,nlog,"Which log to close","");
X if (x == -3) {
X printf("?You must tell which log\n");
X return(-2);
X }
X if (x < 0) return(x);
X if ((y = cmcfm()) < 0) return(y);
X switch (x) {
X
X case LOGD:
X if (deblog == 0) {
X printf("?Debugging log wasn't open\n");
X return(0);
X }
X *debfil = '\0';
X deblog = 0;
X return(zclose(ZDFILE));
X
X case LOGP:
X if (pktlog == 0) {
X printf("?Packet log wasn't open\n");
X return(0);
X }
X *pktfil = '\0';
X pktlog = 0;
X return(zclose(ZPFILE));
X
X case LOGS:
X if (seslog == 0) {
X printf("?Session log wasn't open\n");
X return(0);
X }
X *sesfil = '\0';
X seslog = 0;
X return(zclose(ZSFILE));
X
X case LOGT:
X if (tralog == 0) {
X printf("?Transaction log wasn't open\n");
X return(0);
X }
X *trafil = '\0';
X tralog = 0;
X return(zclose(ZTFILE));
X
X default:
X printf("\n?Unexpected log designator - %ld\n", x);
X return(0);
X }
X
Xcase XXDIAL: /* dial number */
X if ((x = cmtxt("Number to be dialed","",&s)) < 0) return(x);
X return( dial(s) ); /* return success 0=connected -2=fail*/
X
Xcase XXDIR: /* directory */
X if ((x = cmtxt("Directory/file specification","*",&s)) < 0) return(x);
X lp = line;
X sprintf(lp,"ls -l %s",s);
X system(line);
X return(0);
X
Xcase XXECH: /* echo */
X x = cmtxt("Material to be echoed","",&s);
X if (x < 0) return(x);
X printf("%s\n",s);
X return(0);
X
Xcase XXQUI: /* quit, exit */
Xcase XXEXI:
X if ((x = cmcfm()) > -1) doexit(0); /* exit with status 0 */
X else return(x);
X
Xcase XXFIN: /* finish */
X if ((x = cmcfm()) < 0) return(x);
X if (!local) {
X printf("You have to 'set line' first\n");
X return(0);
X }
X sstate = setgen('F',"","","");
X return(0);
X
Xcase XXGET: /* Get */
X if (!local) {
X printf("\nYou have to 'set line' first\n");
X return(0);
X }
X x = cmtxt("Name of remote file(s), or carriage return","",&cmarg);
X if ((x == -2) || (x == -1)) return(x);
X
X/* If foreign file name omitted, get foreign and local names separately */
X
X if (*cmarg == NUL) {
X
X if (tlevel > -1) { /* Input is from take file */
X
X if (fgets(line,100,tfile[tlevel]) == NULL)
X fatal("take file ends prematurely in 'get'");
X stripq(line);
X cmarg = line;
X if (fgets(cmdbuf,CMDBL,tfile[tlevel]) == NULL)
X fatal("take file ends prematurely in 'get'");
X stripq(cmdbuf);
X if (*cmdbuf == NUL) cmarg2 = line; else cmarg2 = cmdbuf;
X
X } else { /* Input is from terminal */
X
X char psave[40]; /* Save old prompt */
X cmsavp(psave,40);
X cmsetp(" Remote file specification: "); /* Make new one */
X cmini(ckxech);
X x = -1;
X while (x < 0) { /* Prompt till they answer */
X prompt();
X x = cmtxt("Name of remote file(s)","",&cmarg);
X if (*cmarg == NUL) x = -1;
X }
X strcpy(line,cmarg); /* Make a safe copy */
X cmarg = line;
X cmsetp(" Local name to store it under: "); /* New prompt */
X cmini(ckxech);
X x = -1;
X while (x < 0) { /* Again, prompt till answered */
X prompt();
X x = cmofi("Local file name",cmarg,&cmarg2);
X if (x == -2) return(x);
X }
X cmsetp(psave); /* Restore old prompt. */
X if ((x == cmcfm()) < 0) return(-2);
X }
X }
X sstate = 'r'; /* All ok, set start state. */
X if (local) displa = 1;
X return(0);
X
Xcase XXHLP: /* Help */
X x = cmkey(cmdtab,ncmd,"C-Kermit command","help");
X return(dohlp(x));
X
Xcase XXLOG: /* Log */
X x = cmkey(logtab,nlog,"What to log","");
X if (x == -3) {
X printf("?You must specify what is to be logged\n");
X return(-2);
X }
X if (x < 0) return(x);
X return(dolog(x));
X
Xcase XXLOGI: /* login to remote system */
X if ((x = cmtxt("Text of login script","",&s)) < 0) return(x);
X return( login(s) ); /* return success 0=completed -2=fail*/
X
Xcase XXREC: /* Receive */
X cmarg2 = "";
X x = cmofi("Name under which to store the file, or CR","",&cmarg2);
X if ((x == -1) || (x == -2)) return(x);
X debug(F111,"cmofi cmarg2",cmarg2,x);
X if ((x = cmcfm()) < 0) return(x);
X sstate = 'v';
X if (local) displa = 1;
X return(0);
X
Xcase XXREM: /* Remote */
X if (!local) {
X printf("\nYou have to 'set line' first\n");
X return(-2);
X }
X x = cmkey(remcmd,nrmt,"Remote Kermit server command","");
X if (x == -3) {
X printf("?You must specify a command for the remote server\n");
X return(-2);
X }
X return(dormt(x));
X
Xcase XXSEN: /* Send */
X cmarg = cmarg2 = "";
X if ((x = cmifi("File(s) to send","",&s,&y)) < 0) {
X if (x == -3) {
X printf("?A file specification is required\n");
X return(-2);
X }
X return(x);
X }
X nfils = -1; /* Files come from internal list. */
X strcpy(line,s); /* Save copy of string just parsed. */
X debug(F101,"Send: wild","",y);
X *cmarg2 = '\0'; /* Initialize send-as name */
X if (y == 0) {
X if ((x = cmfld("Name to send it with",line,&cmarg2)) < 0) return(x);
X }
X if ((x = cmcfm()) < 0) return(x);
X cmarg = line; /* File to send */
X debug(F110,"Sending:",cmarg,0);
X debug(F110," as:",cmarg2,0);
X sstate = 's'; /* Set start state */
X if (local) displa = 1;
X return(0);
X
Xcase XXSER: /* Server */
X if (x = (cmcfm()) < 0) return(x);
X sstate = 'x';
X if (local) displa = 1;
X return(0);
X
Xcase XXSET: /* Set */
X x = cmkey(prmtab,nprm,"Parameter","");
X if (x == -3) {
X printf("?You must specify a parameter to set\n");
X return(-2);
X }
X if (x < 0) return(x);
X return(doprm(x));
X
Xcase XXSHE: /* Local shell command */
X if (cmtxt("Unix shell command to execute","",&s) < 0) return(-1);
X conres(); /* Make console normal */
X system(s); /* Execute the command */
X concb(escape); /* Console back in cbreak mode */
X return(0);
X
Xcase XXSHO: /* Show */
X x = cmkey(shotab,2,"","parameters");
X if (x < 0) return(x);
X if (y = (cmcfm()) < 0) return(y);
X switch (x) {
X
X case SHPAR:
X shopar();
X break;
X
X case SHVER:
X printf("\nVersions:\n %s\n %s\n %s\n",versio,protv,fnsv);
X printf(" %s\n %s\n %s for%s\n",cmdv,userv,ckxv,ckxsys);
X printf(" %s for%s\n %s\n\n",ckzv,ckzsys,connv);
X break;
X
X default:
X printf("\nNothing to show...\n");
X break;
X }
X return(0);
X
Xcase XXSPA: /* space */
X if (x = (cmcfm()) < 0) return(x);
X system(SPACMD);
X return(0);
X
Xcase XXSTA: /* statistics */
X if (x = (cmcfm()) < 0) return(x);
X printf("\nMost recent transaction --\n");
X printf(" files: %ld\n",filcnt);
X printf(" total file characters : %ld\n",tfc);
X printf(" communication line in : %ld\n",tlci);
X printf(" communication line out : %ld\n\n",tlco);
X printf(" block check type used : %d\n",bctu);
X printf(" compression : ");
X if (rptflg) printf("yes\n"); else printf("no\n");
X printf(" 8th bit prefixing : ");
X if (ebqflg) printf("yes\n"); else printf("no\n\n");
X return(0);
X
Xcase XXTAK: /* take */
X if (tlevel > MAXTAKE-1) {
X printf("?Take files nested too deeply\n");
X return(-2);
X }
X if ((y = cmifi("C-Kermit command file","",&s,&x)) < 0) {
X if (y == -3) {
X printf("?A file specification is required\n");
X return(-2);
X } else return(y);
X }
X if (x != 0) {
X printf("?Wildcards not allowed in command file name\n");
X return(-2);
X }
X strcpy(line,s); /* Make a safe copy of the string */
X if ((y = cmcfm()) < 0) return(y);
X if ((tfile[++tlevel] = fopen(line,"r")) == NULL) {
X perror("take");
X printf("Can't open command file - %s\n",line);
X debug(F110,"Failure to open",line,0);
X tlevel--;
X return(0);
X }
X return(0);
X
Xdefault:
X printf("Not available yet - %s\n",cmdbuf);
X return(-2);
X }
X}
X
X/* S H O P A R -- Show Parameters */
X
Xshopar() {
X
X printf("\nLine: %s, speed: %d, mode: ",ttname,speed);
X if (local) printf("local"); else printf("remote");
X printf(", modem-dialer: ");
X if (mdmtyp == 1) printf("hayes");
X else if (mdmtyp == 2) printf("ventel");
X else printf("direct");
X printf("\n Parity: ");
X switch (parity) {
X case 'e': printf("even"); break;
X case 'o': printf("odd"); break;
X case 'm': printf("mark"); break;
X case 's': printf("space"); break;
X case 0: printf("none"); break;
X default: printf("invalid - %d",parity); break;
X }
X printf(", duplex: ");
X if (duplex) printf("half, "); else printf("full, ");
X printf("flow: ");
X if (flow == 1) printf("xon/xoff");
X else if (flow == 0) printf("none");
X else printf("%d",flow);
X printf(", handshake: ");
X if (turn) printf("%d\n",turnch); else printf("none\n");
X printf(" Timeout: %d, delay: %d\n",timint,delay);
X printf(" Padding: %d, pad character: %d\n",mypadn,mypadc);
X printf(" Packet start: %d, end: %d, length: %d",mystch,eol,spsiz);
X printf(", block check: %d\n",bctr);
X printf("\nFile parameters:\n");
X printf(" Names: ");
X if (fncnv) printf("converted\n"); else printf("literal\n");
X printf(" Type: ");
X if (binary) printf("binary\n"); else printf("text\n");
X printf(" Warning: ");
X if (warn) printf("on\n"); else printf("off\n");
X printf(" Display: ");
X if (quiet) printf("off\n"); else printf("on\n");
X printf("\nLogs:");
X printf("\n Debugging: ");
X if (deblog) printf("%s",debfil); else printf("none");
X printf("\n Packets: ");
X if (pktlog) printf("%s",pktfil); else printf("none");
X printf("\n Session: ");
X if (seslog) printf("%s",sesfil); else printf("none");
X printf("\n Transactions: ");
X if (tralog) printf("%s",trafil); else printf("none");
X printf("\n\n");
X}
X
X/* D O L O G -- */
X
Xdolog(x) int x; {
X int y; char *s;
X
X switch (x) {
X
X case LOGD:
X y = cmofi("Name of debugging log file","debug.log",&s);
X break;
X
X case LOGP:
X y = cmofi("Name of packet log file","packet.log",&s);
X break;
X
X case LOGS:
X y = cmofi("Name of session log file","session.log",&s);
X break;
X
X case LOGT:
X y = cmofi("Name of transaction log file","transaction.log",&s);
X break;
X
X default:
X printf("\n?Unexpected log designator - %d\n",x);
X return(-2);
X }
X if (y < 0) return(y);
X
X strcpy(line,s);
X s = line;
X if ((y = cmcfm()) < 0) return(y);
X
X/* cont'd... */
X
X/* ...dolog, cont'd */
X
X
X switch (x) {
X
X case LOGD:
X return(deblog = debopn(s));
X
X case LOGP:
X zclose(ZPFILE);
X y = zopeno(ZPFILE,s);
X if (y > 0) strcpy(pktfil,s); else *pktfil = '\0';
X return(pktlog = y);
X
X case LOGS:
X zclose(ZSFILE);
X y = zopeno(ZSFILE,s);
X if (y > 0) strcpy(sesfil,s); else *sesfil = '\0';
X return(seslog = y);
X
X case LOGT:
X zclose(ZTFILE);
X tralog = zopeno(ZTFILE,s);
X if (tralog > 0) {
X strcpy(trafil,s);
X tlog(F110,"Transaction Log:",versio,0l);
X tlog(F100,ckxsys,"",0);
X ztime(&s);
X tlog(F100,s,"",0l);
X }
X else *trafil = '\0';
X return(tralog);
X
X default:
X return(-2);
X }
X}
X
X
X/* D E B O P N -- Open a debugging file */
X
Xdebopn(s) char *s; {
X char *tp;
X zclose(ZDFILE);
X deblog = zopeno(ZDFILE,s);
X if (deblog > 0) {
X strcpy(debfil,s);
X debug(F110,"Debug Log ",versio,0);
X debug(F100,ckxsys,"",0);
X ztime(&tp);
X debug(F100,tp,"",0);
X } else *debfil = '\0';
X return(deblog);
X}
X
!FUNKY!STUFF!
More information about the Comp.sources.unix
mailing list