|
|
1.1 root 1: char *userv = "User Interface 4C(052), 2 Aug 85";
2:
3: /* C K U U S R -- "User Interface" for Unix Kermit (Part 1) */
4:
5: /*
6: Author: Frank da Cruz (SY.FDC@CU20B),
7: Columbia University Center for Computing Activities, January 1985.
8: Copyright (C) 1985, Trustees of Columbia University in the City of New York.
9: Permission is granted to any individual or institution to use, copy, or
10: redistribute this software so long as it is not sold for profit, provided this
11: copyright notice is retained.
12: */
13:
14: /*
15: The ckuser module contains the terminal input and output functions for Unix
16: Kermit. It includes a simple Unix-style command line parser as well as
17: an interactive prompting keyword command parser. It depends on the existence
18: of Unix facilities like fopen, fgets, feof, (f)printf, argv/argc, etc. Other
19: functions that are likely to vary among Unix implementations -- like setting
20: terminal modes or interrupts -- are invoked via calls to functions that are
21: defined in the system-dependent modules, ck?[ft]io.c.
22:
23: The command line parser processes any arguments found on the command line,
24: as passed to main() via argv/argc. The interactive parser uses the facilities
25: of the cmd package (developed for this program, but usable by any program).
26:
27: Any command parser may be substituted for this one. The only requirements
28: for the Kermit command parser are these:
29:
30: 1. Set parameters via global variables like duplex, speed, ttname, etc.
31: See ckmain.c for the declarations and descriptions of these variables.
32:
33: 2. If a command can be executed without the use of Kermit protocol, then
34: execute the command directly and set the variable sstate to 0. Examples
35: include 'set' commands, local directory listings, the 'connect' command.
36:
37: 3. If a command requires the Kermit protocol, set the following variables:
38:
39: sstate string data
40: 'x' (enter server mode) (none)
41: 'r' (send a 'get' command) cmarg, cmarg2
42: 'v' (enter receive mode) cmarg2
43: 'g' (send a generic command) cmarg
44: 's' (send files) nfils, cmarg & cmarg2 OR cmlist
45: 'c' (send a remote host command) cmarg
46:
47: cmlist is an array of pointers to strings.
48: cmarg, cmarg2 are pointers to strings.
49: nfils is an integer.
50:
51: cmarg can be a filename string (possibly wild), or
52: a pointer to a prefabricated generic command string, or
53: a pointer to a host command string.
54: cmarg2 is the name to send a single file under, or
55: the name under which to store an incoming file; must not be wild.
56: cmlist is a list of nonwild filenames, such as passed via argv.
57: nfils is an integer, interpreted as follows:
58: -1: argument string is in cmarg, and should be expanded internally.
59: 0: stdin.
60: >0: number of files to send, from cmlist.
61:
62: The screen() function is used to update the screen during file transfer.
63: The tlog() function maintains a transaction log.
64: The debug() function maintains a debugging log.
65: The intmsg() and chkint() functions provide the user i/o for interrupting
66: file transfers.
67: */
68:
69: /* Includes */
70:
71: #include "ckcdeb.h"
72: #include <stdio.h>
73: #include <ctype.h>
74: #include <signal.h>
75: #include "ckcker.h"
76: #include "ckucmd.h"
77: #include "ckuusr.h"
78:
79: #ifdef vax11c
80: #define KERMRC "kermit.ini"
81: #else
82: #define KERMRC ".kermrc"
83: #endif
84:
85: /* External Kermit Variables, see ckmain.c for description. */
86:
87: extern int size, spsiz, rpsiz, npad, timint, rtimo, speed, local, server,
88: displa, binary, fncnv, delay, parity, deblog, escape, xargc, flow,
89: turn, duplex, cxseen, czseen, nfils, ckxech, pktlog, seslog, tralog, stdouf,
90: turnch, chklen, bctr, bctu, dfloc, mdmtyp, keep,
91: rptflg, rptq, ebqflg, ebq, warn, quiet, cnflg, timef, spsizf, mypadn, tsecs;
92:
93: extern long filcnt, tlci, tlco, ffc, tfc, fsize;
94:
95: extern char *versio, *protv, *ckxv, *ckzv, *fnsv, *connv, *dftty, *cmdv;
96: extern char *dialv, *loginv;
97: extern char *ckxsys, *ckzsys, *cmarg, *cmarg2, **xargv, **cmlist;
98: extern CHAR mystch, stchr, sstate, mypadc, padch, eol, seol, ctlq, filnam[],
99: ttname[];
100: extern char *DIRCMD, *PWDCMD, cmerrp[];
101: char *strcpy(), *getenv();
102:
103: /* Declarations from cmd package */
104:
105: extern char cmdbuf[]; /* Command buffer */
106:
107: /* Declarations from ck?fio.c module */
108:
109: extern char *SPACMD, *zhome(); /* Space command, home directory. */
110: extern int backgrd; /* Kermit executing in background */
111:
112: /* The background flag is set by ckutio.c (via conint() ) to note whether */
113: /* this kermit is executing in background ('&' on shell command line). */
114:
115:
116: /* Variables and symbols local to this module */
117:
118: char line[CMDBL+10], *lp; /* Character buffer for anything */
119: char debfil[50]; /* Debugging log file name */
120: char pktfil[50]; /* Packet log file name */
121: char sesfil[50]; /* Session log file name */
122: char trafil[50]; /* Transaction log file name */
123:
124: int n, /* General purpose int */
125: cflg, /* Command-line connect cmd given */
126: action, /* Action selected on command line*/
127: repars, /* Reparse needed */
128: tlevel, /* Take command level */
129: cwdf = 0; /* CWD has been done */
130:
131: #define MAXTAKE 20 /* Maximum nesting of TAKE files */
132: FILE *tfile[MAXTAKE]; /* File pointers for TAKE command */
133:
134: char *homdir; /* Pointer to home directory string */
135: char cmdstr[100];
136:
137: /* C M D L I N -- Get arguments from command line */
138: /*
139: Simple Unix-style command line parser, conforming with 'A Proposed Command
140: Syntax Standard for Unix Systems', Hemenway & Armitage, Unix/World, Vol.1,
141: No.3, 1984.
142: */
143: cmdlin() {
144: char x; /* Local general-purpose int */
145: cmarg = ""; /* Initialize globals */
146: cmarg2 = "";
147: action = cflg = 0;
148:
149: while (--xargc > 0) { /* Go through command line words */
150: xargv++;
151: debug(F111,"xargv",*xargv,xargc);
152: if (**xargv == '-') { /* Got an option (begins with dash) */
153: x = *(*xargv+1); /* Get the option letter */
154: x = doarg(x); /* Go handle the option */
155: if (x < 0) exit(GOOD_EXIT);
156: } else { /* No dash where expected */
157: usage();
158: exit(BAD_EXIT);
159: }
160: }
161: debug(F101,"action","",action);
162: if (!local) {
163: if ((action == 'g') || (action == 'r') ||
164: (action == 'c') || (cflg != 0))
165: fatal("-l and -b required");
166: }
167: if (*cmarg2 != 0) {
168: if ((action != 's') && (action != 'r') &&
169: (action != 'v'))
170: fatal("-a without -s, -r, or -g");
171: }
172: if ((action == 'v') && (stdouf) && (!local)) {
173: if (isatty(1))
174: fatal("unredirected -k can only be used in local mode");
175: }
176: if ((action == 's') || (action == 'v') ||
177: (action == 'r') || (action == 'x')) {
178: if (local) displa = 1;
179: if (stdouf) displa = 0;
180: }
181:
182: if (quiet) displa = 0; /* No display if quiet requested */
183:
184: if (cflg) {
185: conect(); /* Connect if requested */
186: if (action == 0) {
187: if (cnflg) conect(); /* And again if requested */
188: doexit(GOOD_EXIT); /* Then exit indicating success */
189: }
190: }
191: if (displa) concb(escape); /* (for console "interrupts") */
192: return(action); /* Then do any requested protocol */
193: }
194:
195: /* D O A R G -- Do a command-line argument. */
196:
197: doarg(x) char x; {
198: int z; char *xp;
199:
200: xp = *xargv+1; /* Pointer for bundled args */
201: while (x) {
202: switch (x) {
203:
204: case 'x': /* server */
205: if (action) fatal("conflicting actions");
206: action = 'x';
207: break;
208:
209: case 'f':
210: if (action) fatal("conflicting actions");
211: action = setgen('F',"","","");
212: break;
213:
214: case 'r': /* receive */
215: if (action) fatal("conflicting actions");
216: action = 'v';
217: break;
218:
219: case 'k': /* receive to stdout */
220: if (action) fatal("conflicting actions");
221: stdouf = 1;
222: action = 'v';
223: break;
224:
225: case 's': /* send */
226: if (action) fatal("conflicting actions");
227: if (*(xp+1)) fatal("invalid argument bundling after -s");
228: z = nfils = 0; /* Initialize file counter, flag */
229: cmlist = xargv+1; /* Remember this pointer */
230: while (--xargc > 0) { /* Traverse the list */
231: *xargv++;
232: if (**xargv == '-') { /* Check for sending stdin */
233: if (strcmp(*xargv,"-") != 0) break;
234: z++;
235: }
236: nfils++; /* Bump file counter */
237: }
238: xargc++, *xargv--; /* Adjust argv/argc */
239: if (nfils < 1) fatal("missing filename for -s");
240: if (z > 1) fatal("-s: too many -'s");
241: if (z == 1) {
242: if (nfils == 1) nfils = 0;
243: else fatal("invalid mixture of filenames and '-' in -s");
244: }
245: if (nfils == 0) {
246: if (isatty(0)) fatal("sending from terminal not allowed");
247: }
248: debug(F101,*xargv,"",nfils);
249: action = 's';
250: break;
251:
252: /* cont'd... */
253:
254: /* ...doarg(), cont'd */
255:
256: case 'g': /* get */
257: if (action) fatal("conflicting actions");
258: if (*(xp+1)) fatal("invalid argument bundling after -g");
259: *xargv++, xargc--;
260: if ((xargc == 0) || (**xargv == '-'))
261: fatal("missing filename for -g");
262: cmarg = *xargv;
263: action = 'r';
264: break;
265:
266: case 'c': /* connect before */
267: cflg = 1;
268: break;
269:
270: case 'n': /* connect after */
271: cnflg = 1;
272: break;
273:
274: case 'h': /* help */
275: usage();
276: return(-1);
277:
278: case 'a': /* "as" */
279: if (*(xp+1)) fatal("invalid argument bundling after -a");
280: *xargv++, xargc--;
281: if ((xargc < 1) || (**xargv == '-'))
282: fatal("missing name in -a");
283: cmarg2 = *xargv;
284: break;
285:
286: case 'l': /* set line */
287: if (*(xp+1)) fatal("invalid argument bundling after -l");
288: *xargv++, xargc--;
289: if ((xargc < 1) || (**xargv == '-'))
290: fatal("communication line device name missing");
291: strcpy(ttname,*xargv);
292: /* if (strcmp(ttname,dftty) == 0) local = dfloc; else local = 1; */
293: local = (strcmp(ttname,CTTNAM) != 0); /* (better than old way) */
294: debug(F101,"local","",local);
295: ttopen(ttname,&local,0);
296: break;
297:
298: case 'b': /* set baud */
299: if (*(xp+1)) fatal("invalid argument bundling");
300: *xargv++, xargc--;
301: if ((xargc < 1) || (**xargv == '-'))
302: fatal("missing baud");
303: z = atoi(*xargv); /* Convert to number */
304: if (chkspd(z) > -1) speed = z; /* Check it */
305: else fatal("unsupported baud rate");
306: break;
307:
308: case 'i': /* Treat files as binary */
309: binary = 1;
310: break;
311:
312: /* cont'd... */
313:
314: /* ...doarg(), cont'd */
315:
316:
317: case 'w': /* File warning */
318: warn = 1;
319: break;
320:
321: case 'q': /* Quiet */
322: quiet = 1;
323: break;
324:
325: case 'd': /* debug */
326: debopn("debug.log");
327: break;
328:
329: case 'p': /* set parity */
330: if (*(xp+1)) fatal("invalid argument bundling");
331: *xargv++, xargc--;
332: if ((xargc < 1) || (**xargv == '-'))
333: fatal("missing parity");
334: switch(x = **xargv) {
335: case 'e':
336: case 'o':
337: case 'm':
338: case 's': parity = x; break;
339: case 'n': parity = 0; break;
340: default: fatal("invalid parity");
341: }
342: break;
343:
344: case 't':
345: turn = 1; /* Line turnaround handshake */
346: turnch = XON; /* XON is turnaround character */
347: duplex = 1; /* Half duplex */
348: flow = 0; /* No flow control */
349: break;
350:
351: default:
352: fatal("invalid argument, type 'kermit -h' for help");
353: }
354:
355: x = *++xp; /* See if options are bundled */
356: }
357: return(0);
358: }
359:
360: /* Misc */
361:
362: fatal(msg) char *msg; { /* Fatal error message */
363: fprintf(stderr,"\r\nFatal: %s\n",msg);
364: tlog(F110,"Fatal:",msg,0l);
365: doexit(BAD_EXIT); /* Exit indicating failure */
366: }
367:
368:
369: ermsg(msg) char *msg; { /* Print error message */
370: if (!quiet) fprintf(stderr,"\r\n%s - %s\n",cmerrp,msg);
371: tlog(F110,"Error -",msg,0l);
372: }
373:
374: /* Interactive command parser */
375:
376:
377: /* Top-Level Keyword Table */
378:
379: struct keytab cmdtab[] = {
380: "!", XXSHE, 0,
381: "%", XXCOM, CM_INV,
382: "bye", XXBYE, 0,
383: "c", XXCON, CM_INV,
384: "close", XXCLO, 0,
385: "connect", XXCON, 0,
386: "cwd", XXCWD, 0,
387: "dial", XXDIAL, 0,
388: "directory", XXDIR, 0,
389: "echo", XXECH, 0,
390: "exit", XXEXI, 0,
391: "finish", XXFIN, 0,
392: "get", XXGET, 0,
393: "help", XXHLP, 0,
394: "log", XXLOG, 0,
395: "quit", XXQUI, 0,
396: "r", XXREC, CM_INV,
397: "receive", XXREC, 0,
398: "remote", XXREM, 0,
399: "s", XXSEN, CM_INV,
400: "script", XXLOGI, 0,
401: "send", XXSEN, 0,
402: "server", XXSER, 0,
403: "set", XXSET, 0,
404: "show", XXSHO, 0,
405: "space", XXSPA, 0,
406: "statistics", XXSTA, 0,
407: "take", XXTAK, 0
408: };
409: int ncmd = (sizeof(cmdtab) / sizeof(struct keytab));
410:
411: /* Parameter keyword table */
412:
413: struct keytab prmtab[] = {
414: "baud", XYSPEE, CM_INV,
415: "block-check", XYCHKT, 0,
416: "delay", XYDELA, 0,
417: "duplex", XYDUPL, 0,
418: "end-of-packet", XYEOL, CM_INV, /* moved to send/receive */
419: "escape-character", XYESC, 0,
420: "file", XYFILE, 0,
421: "flow-control", XYFLOW, 0,
422: "handshake", XYHAND, 0,
423: "incomplete", XYIFD, 0,
424: "line", XYLINE, 0,
425: "modem-dialer", XYMODM, 0,
426: "packet-length", XYLEN, CM_INV, /* moved to send/receive */
427: "pad-character", XYPADC, CM_INV, /* moved to send/receive */
428: "padding", XYNPAD, CM_INV, /* moved to send/receive */
429: "parity", XYPARI, 0,
430: "prompt", XYPROM, 0,
431: "receive", XYRECV, 0,
432: "send", XYSEND, 0,
433: "speed", XYSPEE, 0,
434: "start-of-packet", XYMARK, CM_INV, /* moved to send/receive */
435: "timeout", XYTIMO, CM_INV /* moved to send/receive */
436: };
437: int nprm = (sizeof(prmtab) / sizeof(struct keytab)); /* How many parameters */
438:
439:
440: /* Remote Command Table */
441:
442: struct keytab remcmd[] = {
443: "cwd", XZCWD, 0,
444: "delete", XZDEL, 0,
445: "directory", XZDIR, 0,
446: "help", XZHLP, 0,
447: "host", XZHOS, 0,
448: "space", XZSPA, 0,
449: "type", XZTYP, 0,
450: "who", XZWHO, 0
451: };
452: int nrmt = (sizeof(remcmd) / sizeof(struct keytab));
453:
454: struct keytab logtab[] = {
455: "debugging", LOGD, 0,
456: "packets", LOGP, 0,
457: "session", LOGS, 0,
458: "transactions", LOGT, 0
459: };
460: int nlog = (sizeof(logtab) / sizeof(struct keytab));
461:
462: /* Show command arguments */
463:
464: #define SHPAR 0 /* Parameters */
465: #define SHVER 1 /* Versions */
466:
467: struct keytab shotab[] = {
468: "parameters", SHPAR, 0,
469: "versions", SHVER, 0
470: };
471:
472: /* C M D I N I -- Initialize the interactive command parser */
473:
474: cmdini() {
475:
476: printf("%s,%s\nType ? for help\n",versio,ckxsys);
477: cmsetp("C-Kermit>"); /* Set default prompt. */
478:
479: tlevel = -1; /* Take file level */
480:
481: /* Look for init file in home or current directory. */
482:
483: homdir = zhome();
484: lp = line;
485: lp[0] = '\0';
486: if (homdir) {
487: strcpy(lp,homdir);
488: if (lp[0] == '/') strcat(lp,"/");
489: }
490: strcat(lp,KERMRC);
491: if ((tfile[0] = fopen(line,"r")) != NULL) {
492: tlevel = 0;
493: debug(F110,"init file",line,0);
494: }
495: if (homdir && (tlevel < 0)) {
496: strcpy(lp,KERMRC);
497: if ((tfile[0] = fopen(line,"r")) != NULL) {
498: tlevel = 0;
499: debug(F110,"init file",line,0);
500: } else {
501: debug(F100,"no init file","",0);
502: }
503: }
504:
505: congm(); /* Get console tty modes */
506: }
507:
508:
509: /* T R A P -- Terminal interrupt handler */
510:
511: trap() {
512: debug(F100,"terminal interrupt...","",0);
513: doexit(GOOD_EXIT); /* Exit indicating success */
514: }
515:
516: /* P A R S E R -- Top-level interactive command parser. */
517:
518: parser() {
519: int xx, cbn;
520: char *cbp;
521:
522: concb(escape); /* Put console in cbreak mode. */
523: conint(trap); /* Turn on console terminal interrupts. */
524: /*
525: sstate becomes nonzero when a command has been parsed that requires some
526: action from the protocol module. Any non-protocol actions, such as local
527: directory listing or terminal emulation, are invoked directly from below.
528: */
529: if (local) printf("\n"); /*** Temporary kludge ***/
530: sstate = 0; /* Start with no start state. */
531: while (sstate == 0) { /* Parse cmds until action requested */
532: while ((tlevel > -1) && feof(tfile[tlevel])) { /* If end of take */
533: fclose(tfile[tlevel]); /* file, close it */
534: tlevel--; /* and forget about it. */
535: cmini(ckxech); /* and clear the cmd buffer. */
536: }
537: if (tlevel > -1) { /* If in take file */
538: cbp = cmdbuf; /* Get the next line. */
539: cbn = CMDBL;
540:
541: /* Loop to get next command line and all continuation lines from take file. */
542:
543: again: if (fgets(line,cbn,tfile[tlevel]) == NULL) continue;
544: lp = line; /* Got one, copy it. */
545: while (*cbp++ = *lp++)
546: if (--cbn < 1) fatal("Command too long for internal buffer");
547: if (*(cbp - 3) == '\\') { /* Continued on next line? */
548: cbp -= 3; /* If so, back up pointer, */
549: goto again; /* go back, get next line. */
550: }
551: stripq(cmdbuf); /* Strip any quotes from cmd buffer. */
552:
553: } else { /* No take file, get typein. */
554:
555: prompt(); /* Issue interactive prompt. */
556: cmini(ckxech);
557: }
558: repars = 1;
559: displa = 0;
560: while (repars) {
561: cmres(); /* Reset buffer pointers. */
562: xx = cmkey(cmdtab,ncmd,"Command","");
563: debug(F101,"top-level cmkey","",xx);
564: switch (docmd(xx)) {
565: case -4: /* EOF */
566: doexit(GOOD_EXIT); /* ...exit successfully */
567: case -1: /* Reparse needed */
568: repars = 1;
569: continue;
570: case -2: /* Invalid command given */
571: if (backgrd) /* if in background, terminate */
572: fatal("Kermit command error in background execution");
573: if (tlevel > -1) { /* If in take file, quit */
574: ermsg("Kermit command error: take file terminated.");
575: fclose(tfile[tlevel]);
576: tlevel--;
577: }
578: cmini(ckxech); /* (fall thru) */
579: case -3: /* Empty command OK at top level */
580: default: /* Anything else (fall thru) */
581: repars = 0; /* No reparse, get new command. */
582: continue;
583: }
584: }
585: }
586: /* Got an action command; disable terminal interrupts and return start state */
587:
588: if (!local) connoi(); /* Interrupts off only if remote */
589: return(sstate);
590: }
591:
592: /* D O E X I T -- Exit from the program. */
593:
594: doexit(exitstat) int exitstat; {
595:
596: ttclos(); /* Close external line, if any */
597: if (local) {
598: strcpy(ttname,dftty); /* Restore default tty */
599: local = dfloc; /* And default remote/local status */
600: }
601: if (!quiet) conres(); /* Restore console terminal. */
602: if (!quiet) connoi(); /* Turn off console interrupt traps. */
603:
604: if (deblog) { /* Close any open logs. */
605: debug(F100,"Debug Log Closed","",0);
606: *debfil = '\0';
607: deblog = 0;
608: zclose(ZDFILE);
609: }
610: if (pktlog) {
611: *pktfil = '\0';
612: pktlog = 0;
613: zclose(ZPFILE);
614: }
615: if (seslog) {
616: *sesfil = '\0';
617: seslog = 0;
618: zclose(ZSFILE);
619: }
620: if (tralog) {
621: tlog(F100,"Transaction Log Closed","",0l);
622: *trafil = '\0';
623: tralog = 0;
624: zclose(ZTFILE);
625: }
626: exit(exitstat); /* Exit from the program. */
627: }
628:
629: /* B L D L E N -- Make length-encoded copy of string */
630:
631: char *
632: bldlen(str,dest) char *str, *dest; {
633: int len;
634: len = strlen(str);
635: *dest = tochar(len);
636: strcpy(dest+1,str);
637: return(dest+len+1);
638: }
639:
640:
641: /* S E T G E N -- Construct a generic command */
642:
643: setgen(type,arg1,arg2,arg3) char type, *arg1, *arg2, *arg3; {
644: char *upstr, *cp;
645:
646: cp = cmdstr;
647: *cp++ = type;
648: *cp = NUL;
649: if (*arg1 != NUL) {
650: upstr = bldlen(arg1,cp);
651: if (*arg2 != NUL) {
652: upstr = bldlen(arg2,upstr);
653: if (*arg3 != NUL) bldlen(arg3,upstr);
654: }
655: }
656: cmarg = cmdstr;
657: debug(F110,"setgen",cmarg,0);
658:
659: return('g');
660: }
661:
662: /* D O C M D -- Do a command */
663:
664: /*
665: Returns:
666: -2: user typed an illegal command
667: -1: reparse needed
668: 0: parse was successful (even tho command may have failed).
669: */
670:
671: docmd(cx) int cx; {
672: int x, y;
673: char *s;
674:
675: switch (cx) {
676:
677: case -4: /* EOF */
678: if (!quiet) printf("\r\n");
679: doexit(GOOD_EXIT);
680: case -3: /* Null command */
681: return(0);
682: case -2: /* Error */
683: case -1: /* Reparse needed */
684: return(cx);
685:
686: case XXBYE: /* bye */
687: if ((x = cmcfm()) < 0) return(x);
688: if (!local) {
689: printf("You have to 'set line' first\n");
690: return(0);
691: }
692: sstate = setgen('L',"","","");
693: return(0);
694:
695: case XXCOM: /* comment */
696: if ((x = cmtxt("Text of comment line","",&s)) < 0) return(x);
697: return(0);
698:
699: case XXCON: /* connect */
700: if ((x = cmcfm()) < 0) return(x);
701: return(doconect());
702:
703: case XXCWD:
704: if (cmtxt("Name of local directory, or carriage return",homdir,&s) < 0)
705: return(-1);
706: if (chdir(s)) perror(s);
707: cwdf = 1;
708: system(PWDCMD);
709: return(0);
710:
711: case XXCLO:
712: x = cmkey(logtab,nlog,"Which log to close","");
713: if (x == -3) {
714: printf("?You must tell which log\n");
715: return(-2);
716: }
717: if (x < 0) return(x);
718: if ((y = cmcfm()) < 0) return(y);
719: switch (x) {
720:
721: case LOGD:
722: if (deblog == 0) {
723: printf("?Debugging log wasn't open\n");
724: return(0);
725: }
726: *debfil = '\0';
727: deblog = 0;
728: return(zclose(ZDFILE));
729:
730: case LOGP:
731: if (pktlog == 0) {
732: printf("?Packet log wasn't open\n");
733: return(0);
734: }
735: *pktfil = '\0';
736: pktlog = 0;
737: return(zclose(ZPFILE));
738:
739: case LOGS:
740: if (seslog == 0) {
741: printf("?Session log wasn't open\n");
742: return(0);
743: }
744: *sesfil = '\0';
745: seslog = 0;
746: return(zclose(ZSFILE));
747:
748: case LOGT:
749: if (tralog == 0) {
750: printf("?Transaction log wasn't open\n");
751: return(0);
752: }
753: *trafil = '\0';
754: tralog = 0;
755: return(zclose(ZTFILE));
756:
757: default:
758: printf("\n?Unexpected log designator - %ld\n", x);
759: return(0);
760: }
761:
762: case XXDIAL: /* dial number */
763: if ((x = cmtxt("Number to be dialed","",&s)) < 0) return(x);
764: return(dial(s));
765:
766: case XXDIR: /* directory */
767: if ((x = cmtxt("Directory/file specification",".",&s)) < 0) return(x);
768: lp = line;
769: sprintf(lp,"%s %s",DIRCMD,s);
770: system(line);
771: return(0);
772:
773:
774: case XXECH: /* echo */
775: if ((x = cmtxt("Material to be echoed","",&s)) < 0) return(x);
776: for ( ; *s; s++) {
777: if ((x = *s) == 0134) { /* Convert octal escapes */
778: s++; /* up to 3 digits */
779: for (x = y = 0; *s >= '0' && *s <= '7' && y < 3; s++,y++) {
780: x = x * 8 + (int) *s - 48;
781: }
782: s--;
783: }
784: putchar(x);
785: }
786: printf("\n");
787: return(0);
788:
789: case XXQUI: /* quit, exit */
790: case XXEXI:
791: if ((x = cmcfm()) > -1) doexit(GOOD_EXIT);
792: else return(x);
793:
794: case XXFIN: /* finish */
795: if ((x = cmcfm()) < 0) return(x);
796: if (!local) {
797: printf("You have to 'set line' first\n");
798: return(0);
799: }
800: sstate = setgen('F',"","","");
801: return(0);
802:
803: case XXGET: /* get */
804: if (!local) {
805: printf("\nYou have to 'set line' first\n");
806: return(0);
807: }
808: x = cmtxt("Name of remote file(s), or carriage return","",&cmarg);
809: if ((x == -2) || (x == -1)) return(x);
810:
811: /* If foreign file name omitted, get foreign and local names separately */
812:
813: if (*cmarg == NUL) {
814:
815: if (tlevel > -1) { /* Input is from take file */
816:
817: if (fgets(line,100,tfile[tlevel]) == NULL)
818: fatal("take file ends prematurely in 'get'");
819: stripq(line);
820: cmarg = line;
821: if (fgets(cmdbuf,CMDBL,tfile[tlevel]) == NULL)
822: fatal("take file ends prematurely in 'get'");
823: stripq(cmdbuf);
824: if (*cmdbuf == NUL) cmarg2 = line; else cmarg2 = cmdbuf;
825:
826: } else { /* Input is from terminal */
827:
828: char psave[40]; /* Save old prompt */
829: cmsavp(psave,40);
830: cmsetp(" Remote file specification: "); /* Make new one */
831: cmini(ckxech);
832: x = -1;
833: prompt();
834: while (x == -1) { /* Prompt till they answer */
835: x = cmtxt("Name of remote file(s)","",&cmarg);
836: debug(F111," cmtxt",cmarg,x);
837: }
838: if (x < 0) {
839: cmsetp(psave);
840: return(x);
841: }
842: if (*cmarg == NUL) { /* If user types a bare CR, */
843: printf("(cancelled)\n"); /* Forget about this. */
844: cmsetp(psave); /* Restore old prompt, */
845: return(0); /* and return. */
846: }
847: strcpy(line,cmarg); /* Make a safe copy */
848: cmarg = line;
849: cmsetp(" Local name to store it under: "); /* New prompt */
850: cmini(ckxech);
851: x = -1;
852: prompt(); /* Prompt */
853: while (x < 0) { /* Again, parse till answered */
854: x = cmofi("Local file name","",&cmarg2);
855: if (x == -2) return(x);
856: if (x == -3) { /* If bare CR, */
857: printf("(cancelled)\n"); /* escape from this... */
858: cmsetp(psave); /* restore old prompt, */
859: return(0); /* and return. */
860: }
861: }
862: cmsetp(psave); /* Restore old prompt. */
863: if ((x == cmcfm()) < 0) return(-2);
864: }
865: }
866: sstate = 'r'; /* All ok, set start state. */
867: if (local) displa = 1;
868: return(0);
869:
870: case XXHLP: /* Help */
871: x = cmkey(cmdtab,ncmd,"C-Kermit command","help");
872: return(dohlp(x));
873:
874: case XXLOG: /* Log */
875: x = cmkey(logtab,nlog,"What to log","");
876: if (x == -3) {
877: printf("?You must specify what is to be logged\n");
878: return(-2);
879: }
880: if (x < 0) return(x);
881: return(dolog(x));
882:
883: case XXLOGI: /* Send script remote system */
884: if ((x = cmtxt("Text of login script","",&s)) < 0) return(x);
885: return( login(s) ); /* Return 0=completed, -2=failed */
886:
887: case XXREC: /* Receive */
888: cmarg2 = "";
889: x = cmofi("Name under which to store the file, or CR","",&cmarg2);
890: if ((x == -1) || (x == -2)) return(x);
891: debug(F111,"cmofi cmarg2",cmarg2,x);
892: if ((x = cmcfm()) < 0) return(x);
893: sstate = 'v';
894: if (local) displa = 1;
895: return(0);
896:
897: case XXREM: /* Remote */
898: if (!local) {
899: printf("\nYou have to 'set line' first\n");
900: return(-2);
901: }
902: x = cmkey(remcmd,nrmt,"Remote Kermit server command","");
903: if (x == -3) {
904: printf("?You must specify a command for the remote server\n");
905: return(-2);
906: }
907: return(dormt(x));
908:
909: case XXSEN: /* Send */
910: cmarg = cmarg2 = "";
911: if ((x = cmifi("File(s) to send","",&s,&y)) < 0) {
912: if (x == -3) {
913: printf("?A file specification is required\n");
914: return(-2);
915: }
916: return(x);
917: }
918: nfils = -1; /* Files come from internal list. */
919: strcpy(line,s); /* Save copy of string just parsed. */
920: debug(F101,"Send: wild","",y);
921: *cmarg2 = '\0'; /* Initialize send-as name */
922: if (y == 0) {
923: if ((x = cmtxt("Name to send it with","",&cmarg2)) < 0) return(x);
924: } else {
925: if ((x = cmcfm()) < 0) return(x);
926: }
927: cmarg = line; /* File to send */
928: debug(F110,"Sending:",cmarg,0);
929: if (*cmarg2 != '\0') debug(F110," as:",cmarg2,0);
930: sstate = 's'; /* Set start state */
931: if (local) displa = 1;
932: return(0);
933:
934: case XXSER: /* Server */
935: if ((x = cmcfm()) < 0) return(x);
936: sstate = 'x';
937: if (local) displa = 1;
938: return(0);
939:
940: case XXSET: /* Set */
941: x = cmkey(prmtab,nprm,"Parameter","");
942: if (x == -3) {
943: printf("?You must specify a parameter to set\n");
944: return(-2);
945: }
946: if (x < 0) return(x);
947: return(doprm(x));
948:
949: /* XXSHE code by H. Fischer; copyright rights assigned to Columbia Univ */
950: /*
951: Adapted to use getpwuid to find login shell because many systems do not
952: have SHELL in environment, and to use direct calling of shell rather
953: than intermediate system() call. -- H. Fischer
954: */
955: case XXSHE: /* Local shell command */
956: {
957: int pid;
958: if (cmtxt("Unix shell command to execute","",&s) < 0) return(-1);
959: conres(); /* Make console normal */
960: #ifdef MSDOS
961: zxcmd(s);
962: #else
963: #ifdef vax11c
964:
965: system(s); /* Best we can do for VMS? */
966:
967: #else /* All Unix systems... */
968:
969: if ((pid = fork()) == 0) { /* Make child */
970: char *shpath, *shname, *shptr; /* For finding desired shell */
971: struct passwd *p;
972: extern struct passwd * getpwuid();
973: extern int getuid();
974: char *defShel = "/bin/sh"; /* Default */
975:
976: p = getpwuid( getuid() ); /* Get login data */
977: if ( p == (struct passwd *) NULL || !*(p->pw_shell) )
978: shpath = defShel;
979: else
980: shpath = p->pw_shell;
981: shptr = shname = shpath;
982: while (*shptr != '\0')
983: if (*shptr++ == '/') shname = shptr;
984: if (*s == NUL) /* Interactive shell requested? */
985: execl(shpath,shname,"-i",(char *)0); /* Yes, do that */
986: else /* Otherwise, */
987: execl(shpath,shname,"-c",s,(char *)0); /* exec the given command */
988: exit(GOOD_EXIT); } /* Just punt if it didnt work */
989:
990: else { /* Parent */
991:
992: int wstat; /* Kermit must wait for child */
993: int (*istat)(), (*qstat)();
994:
995: istat = signal(SIGINT,SIG_IGN); /* Let the fork handle keyboard */
996: qstat = signal(SIGQUIT,SIG_IGN); /* interrupts itself... */
997:
998: while (((wstat = wait(0)) != pid) && (wstat != -1)) /* Wait for fork */
999: ;
1000: signal(SIGINT,istat); /* Restore interrupts */
1001: signal(SIGQUIT,qstat);
1002: }
1003: #endif
1004: #endif
1005: concb(escape); /* Console back in cbreak mode */
1006: return(0);
1007: }
1008:
1009: case XXSHO: /* Show */
1010: x = cmkey(shotab,2,"","parameters");
1011: if (x < 0) return(x);
1012: if (y = (cmcfm()) < 0) return(y);
1013: switch (x) {
1014:
1015: case SHPAR:
1016: shopar();
1017: break;
1018:
1019: case SHVER:
1020: printf("\nVersions:\n %s\n %s\n",versio,protv);
1021: printf(" %s\n",fnsv);
1022: printf(" %s\n %s\n %s for%s\n",cmdv,userv,ckxv,ckxsys);
1023: printf(" %s for%s\n %s\n",ckzv,ckzsys,connv);
1024: printf(" %s\n %s\n\n",dialv,loginv);
1025: break;
1026:
1027: default:
1028: printf("\nNothing to show...\n");
1029: break;
1030: }
1031: return(0);
1032:
1033: case XXSPA: /* space */
1034: if ((x = cmcfm()) < 0) return(x);
1035: system(SPACMD);
1036: return(0);
1037:
1038: case XXSTA: /* statistics */
1039: if ((x = cmcfm()) < 0) return(x);
1040: printf("\nMost recent transaction --\n");
1041: printf(" files: %ld\n",filcnt);
1042: printf(" total file characters : %ld\n",tfc);
1043: printf(" communication line in : %ld\n",tlci);
1044: printf(" communication line out : %ld\n",tlco);
1045: printf(" elapsed time : %d sec\n",tsecs);
1046: if (filcnt > 0) {
1047: if (tsecs > 0) {
1048: long lx;
1049: lx = (tfc / tsecs) * 10;
1050: printf(" effective baud rate : %ld\n",lx);
1051: if (speed > 0) {
1052: lx = (lx * 100) / speed;
1053: printf(" efficiency : %ld %%\n",lx);
1054: }
1055: }
1056: printf(" block check type used : %d\n",bctu);
1057: printf(" compression : ");
1058: if (rptflg) printf("yes [%c]\n",rptq); else printf("no\n");
1059: printf(" 8th bit prefixing : ");
1060: if (ebqflg) printf("yes [%c]\n",ebq); else printf("no\n\n");
1061: } else printf("\n");
1062: return(0);
1063:
1064: case XXTAK: /* take */
1065: if (tlevel > MAXTAKE-1) {
1066: printf("?Take files nested too deeply\n");
1067: return(-2);
1068: }
1069: if ((y = cmifi("C-Kermit command file","",&s,&x)) < 0) {
1070: if (y == -3) {
1071: printf("?A file specification is required\n");
1072: return(-2);
1073: } else return(y);
1074: }
1075: if (x != 0) {
1076: printf("?Wildcards not allowed in command file name\n");
1077: return(-2);
1078: }
1079: strcpy(line,s); /* Make a safe copy of the string */
1080: if ((y = cmcfm()) < 0) return(y);
1081: if ((tfile[++tlevel] = fopen(line,"r")) == NULL) {
1082: perror(line);
1083: debug(F110,"Failure to open",line,0);
1084: tlevel--;
1085: }
1086: return(0);
1087:
1088: default:
1089: printf("Not available - %s\n",cmdbuf);
1090: return(-2);
1091: }
1092: }
1093:
1094: /* S H O P A R -- Show Parameters */
1095:
1096: shopar() {
1097:
1098: int i;
1099: extern struct keytab mdmtab[]; extern int nmdm;
1100:
1101: puts("\nCommunications Parameters:");
1102: printf(" Line: %s, speed: %d, mode: ",ttname,speed);
1103: if (local) printf("local"); else printf("remote");
1104:
1105: for (i = 0; i < nmdm; i++) {
1106: if (mdmtab[i].val == mdmtyp) {
1107: printf(", modem-dialer: %s",mdmtab[i].kwd);
1108: break;
1109: }
1110: }
1111: printf("\n Parity: ");
1112: switch (parity) {
1113: case 'e': printf("even"); break;
1114: case 'o': printf("odd"); break;
1115: case 'm': printf("mark"); break;
1116: case 's': printf("space"); break;
1117: case 0: printf("none"); break;
1118: default: printf("invalid - %d",parity); break;
1119: }
1120: printf(", duplex: ");
1121: if (duplex) printf("half, "); else printf("full, ");
1122: printf("flow: ");
1123: if (flow == 1) printf("xon/xoff");
1124: else if (flow == 0) printf("none");
1125: else printf("%d",flow);
1126: printf(", handshake: ");
1127: if (turn) printf("%d\n",turnch); else printf("none\n");
1128:
1129: printf("\nProtocol Parameters: Send Receive");
1130: if (timef || spsizf) printf(" (* = override)");
1131: printf("\n Timeout: %11d%9d", rtimo, timint);
1132: if (timef) printf("*");
1133: printf("\n Padding: %11d%9d\n", npad, mypadn);
1134: printf( " Pad Character:%11d%9d\n", padch, mypadc);
1135: printf( " Packet Start: %11d%9d\n", mystch, stchr);
1136: printf( " Packet End: %11d%9d\n", seol, eol);
1137: printf( " Packet Length:%11d", spsiz);
1138: printf( spsizf ? "*" : " " ); printf("%8d\n", rpsiz);
1139:
1140: printf("\nBlock Check Type: %d, Delay: %d\n",bctr,delay);
1141: if (ebqflg) printf("8th-Bit Prefix: '%c'\n",ebq);
1142: if (rptflg) printf("Repeat-Count Prefix: '%c'\n",rptq);
1143:
1144: printf("\nFile parameters:\n File Names: ");
1145: if (fncnv) printf("%-12s","converted"); else printf("%-12s","literal");
1146: #ifdef DEBUG
1147: printf(" Debugging Log: ");
1148: if (deblog) printf("%s",debfil); else printf("none");
1149: #endif
1150: printf("\n File Type: ");
1151: if (binary) printf("%-12s","binary"); else printf("%-12s","text");
1152: printf(" Packet Log: ");
1153: if (pktlog) printf(pktfil); else printf("none");
1154: printf("\n File Warning: ");
1155: if (warn) printf("%-12s","on"); else printf("%-12s","off");
1156: printf(" Session Log: ");
1157: if (seslog) printf(sesfil); else printf("none");
1158: printf("\n File Display: ");
1159: if (quiet) printf("%-12s","off"); else printf("%-12s","on");
1160: #ifdef TLOG
1161: printf(" Transaction Log: ");
1162: if (tralog) printf(trafil); else printf("none");
1163: #endif
1164: printf("\n\nIncomplete File Disposition: ");
1165: if (keep) printf("keep"); else printf("discard");
1166: #ifdef KERMRC
1167: printf(", Init file: %s",KERMRC);
1168: #endif
1169: puts("\n");
1170: }
1171:
1172: /* D O C O N E C T -- Do the connect command */
1173:
1174: /* Note, we don't call this directly from dial, because we need to give */
1175: /* the user a chance to change parameters (e.g. parity) after the */
1176: /* connection is made. */
1177:
1178: doconect() {
1179: int x;
1180: conres(); /* Put console back to normal */
1181: x = conect(); /* Connect */
1182: concb(escape); /* Put console into cbreak mode, */
1183: return(x); /* for more command parsing. */
1184: }
1185:
1186:
1187: /* D O L O G -- Do the log command */
1188:
1189: dolog(x) int x; {
1190: int y; char *s;
1191:
1192: switch (x) {
1193:
1194: case LOGD:
1195: #ifdef DEBUG
1196: y = cmofi("Name of debugging log file","debug.log",&s);
1197: #else
1198: y = -2; s = "";
1199: printf("%s","- Sorry, debug log not available\n");
1200: #endif
1201: break;
1202:
1203: case LOGP:
1204: y = cmofi("Name of packet log file","packet.log",&s);
1205: break;
1206:
1207: case LOGS:
1208: y = cmofi("Name of session log file","session.log",&s);
1209: break;
1210:
1211: case LOGT:
1212: #ifdef TLOG
1213: y = cmofi("Name of transaction log file","transact.log",&s);
1214: #else
1215: y = -2; s = "";
1216: printf("%s","- Sorry, transaction log not available\n");
1217: #endif
1218: break;
1219:
1220: default:
1221: printf("\n?Unexpected log designator - %d\n",x);
1222: return(-2);
1223: }
1224: if (y < 0) return(y);
1225:
1226: strcpy(line,s);
1227: s = line;
1228: if ((y = cmcfm()) < 0) return(y);
1229:
1230: /* cont'd... */
1231:
1232: /* ...dolog, cont'd */
1233:
1234:
1235: switch (x) {
1236:
1237: case LOGD:
1238: return(deblog = debopn(s));
1239:
1240: case LOGP:
1241: zclose(ZPFILE);
1242: y = zopeno(ZPFILE,s);
1243: if (y > 0) strcpy(pktfil,s); else *pktfil = '\0';
1244: return(pktlog = y);
1245:
1246: case LOGS:
1247: zclose(ZSFILE);
1248: y = zopeno(ZSFILE,s);
1249: if (y > 0) strcpy(sesfil,s); else *sesfil = '\0';
1250: return(seslog = y);
1251:
1252: case LOGT:
1253: zclose(ZTFILE);
1254: tralog = zopeno(ZTFILE,s);
1255: if (tralog > 0) {
1256: strcpy(trafil,s);
1257: tlog(F110,"Transaction Log:",versio,0l);
1258: tlog(F100,ckxsys,"",0);
1259: ztime(&s);
1260: tlog(F100,s,"",0l);
1261: }
1262: else *trafil = '\0';
1263: return(tralog);
1264:
1265: default:
1266: return(-2);
1267: }
1268: }
1269:
1270:
1271: /* D E B O P N -- Open a debugging file */
1272:
1273: debopn(s) char *s; {
1274: #ifdef DEBUG
1275: char *tp;
1276: zclose(ZDFILE);
1277: deblog = zopeno(ZDFILE,s);
1278: if (deblog > 0) {
1279: strcpy(debfil,s);
1280: debug(F110,"Debug Log ",versio,0);
1281: debug(F100,ckxsys,"",0);
1282: ztime(&tp);
1283: debug(F100,tp,"",0);
1284: } else *debfil = '\0';
1285: return(deblog);
1286: #else
1287: return(0);
1288: #endif
1289: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.