/* US1_C - QL-Kermit user command routines (Part 1) Based on ckuus[123].c, (C) Columbia University */ /* Include files */ #include "flp1_ctype_h" /* Character type macros */ #include "flp1_fcntl_h" /* File opening modes */ #include "ram1_ker_h" /* Kermit definitions */ #include "ram1_cmd_h" /* Command interpreter definitions */ #include "ram1_usr_h" /* User command definitions */ /* External variables */ extern int slen; /* Send packet size */ extern int rlen; /* Initial receive packet size */ extern int rtmo; /* Timeout we use */ extern int stmo; /* Timeout remote uses */ extern int state; /* Switcher start state */ extern int ttychid; /* QDOS channel ID for serial line */ extern int tlevel; /* TAKE file nesting level */ extern int trans; /* File name translation */ extern int debug; /* Debugging level */ extern int speed; /* Line speed (baud rate) */ extern int xfertyp; /* File transfer type */ extern int retry; /* Retry limit */ extern int delay; /* Delay before SEND starts */ extern int serno; /* Serial port in use */ extern int parity; /* Parity setting */ extern int npad; /* Padding amount remote needs */ extern bool timer; /* Timer enabled flag */ extern bool echo; /* Local echo flag */ extern bool local; /* Operating mode */ extern bool keep; /* Incomplete file disposition */ extern bool tkecho; /* Show TAKE commands flag */ extern bool tkabort; /* Error abort flag */ extern char ssop; /* Packet start remote needs */ extern char rsop; /* Packet start I need */ extern char reol; /* EOL I need */ extern char seol; /* EOL remote needs */ extern char quote; /* Control quote prefix */ extern char pebq; /* 8-bit quote prefix */ extern char enter[]; /* What ENTER sends */ extern unsigned char padch; /* Pad character remote needs */ extern char stype; /* Server command to be done */ extern char ttyname[]; /* Communication device name */ extern char *sourdev; /* Default source device */ extern char *destdev; /* Default destination device */ extern char *takedev; /* Default TAKE file device */ extern char *suffix; /* Sending file suffix */ extern char *vers; /* Program version */ extern char *cmarg,*cmarg2; /* Switcher parameters */ extern FILE *tfile[MAXTAKE]; /* TAKE file stack */ /* External functions */ extern char *ptype(); /* Parity type name */ extern bool test(); /* Bit test */ /* Local variables */ char line[CMDBL+10]; /* General character buffer */ char *lp; /* General pointer */ int n; /* General temporary */ bool repars; /* Reparse flag */ char cmdbuf[CMDBL+4]; /* Command string buffer */ /* Macros */ #define CHKLINE { if (!local) { error("Communication line not set"); return(-2); } } /* Keyword tables */ struct keytab cmdtab[] = /* Top-level commands */ { 0, "connect", XXCON, 0, "do", XXDOC, 0, "exit", XXQUI, 0, "finish", XXFIN, 0, "get", XXGET, 0, "help", XXHELP, CM_INV, "quit", XXQUI, 0, "receive", XXREC, 0, "send", XXSEN, 0, "set", XXSET, 0, "show", XXSHO, 0, "take", XXTAK }; int ncmd = (sizeof(cmdtab) / sizeof(struct keytab)); struct keytab prmtab[] = /* SET parameters */ { 0, "baud", XYSPEE, 0, "control-quote", XYQCTL, 0, "debugging", XYDEB, 0, "delay", XYDEL, 0, "device", XYDEV, 0, "eight-bit-quote", XYEBQ, CM_INV, "end-of-line", XYEOL, 0, "enter", XYENT, 0, "file", XYFILE, 0, "line", XYLINE, 0, "local-echo", XYECHO, CM_INV, "marker", XYMARK, CM_INV, "packet-length", XYLEN, 0, "padding", XYPAD, 0, "parity", XYPARI, 0, "receive", XYRECV, 0, "retries", XYRETR, 0, "send", XYSEND, CM_INV, "speed", XYSPEE, CM_INV, "start-of-packet", XYMARK, 0, "take-abort", XYTKAB, 0, "take-echo", XYTKEC, CM_INV, "timeout", XYTIMO, 0, "timer", XYTIME }; int nprm = (sizeof(prmtab) / sizeof(struct keytab)); struct keytab shotab[] = /* SHOW parameters */ { 0, "all", SHALL, 0, "communication", SHCOM, 0, "devices", SHDEV, 0, "file", SHFILE, 0, "prefix", SHPRE, CM_INV, "quote", SHPRE, 0, "system", SHSYS, 0, "transfer", SHXFER, 0, "version", SHVER }; int nshotab = (sizeof(shotab) / sizeof(struct keytab)); /* CMDINI - Initialize the interactive command parser */ cmdini() { cls(fgetchid(stdout)); /* Clear the screen window */ printf("\n%s\n\n",vers); /* Say who we are */ cmsetp("QLK> "); /* Set up prompt */ tlevel = -1; /* No TAKE files */ if ((tfile[++tlevel] = fopen(DFTAKE,"r"))==NULL) { /* Try startup file */ if (debon) printf("No startup file found\n"); tlevel--; } } /* PARSER - Top-level interactive command parser */ parser(status) bool status; { int xx,cbn; char *cbp; /* Abandon all the TAKE files, if the previous file transfer failed */ if (!status && tkabort && tlevel>-1) { error("Transfer error, TAKE files abandoned"); while (tlevel>-1) tclose(); } status = TRUE; /* state becomes nonzero when a command has been parsed that requires some action from the protocol module. Any non-protocol actions, such as local directory listing or terminal emulation, are invoked directly from below. */ state = 0; /* Begin with no start state */ while (state==0) /* Parse cmds until action requested */ { *cmarg = '\0'; /* Start clean */ *cmarg2 = '\0'; if (tlevel>-1) /* If in TAKE file, */ { cmini(); cbp = cmdbuf; cbn = CMDBL; /* try for next command from there */ if (fgets(line,cbn,tfile[tlevel])==NULL) { if (feof(tfile[tlevel])!=0) /* If end of file, close & pop level */ tclose(); continue; } if (tkecho) printf("TAKE-%d> %s",tlevel,line); lp = line; /* Got one, copy it */ while (*cbp++ = *lp++); } else /* No TAKE file, get user input */ { prompt(); /* Issue interactive prompt */ cmini(); } repars = TRUE; while (repars) /* Repeat until a command done */ { cmres(); /* Reset buffer pointers */ switch (xx = docmd(cmkey(cmdtab,ncmd,"","Command"))) { case -4: doexit(); /* EOF, exit successfully */ case -1: repars = TRUE; /* Reparse needed */ continue; case -2: if (tkabort && tlevel>-1) /* Unknown command */ { /* If in TAKE file, quit */ error("Command error, TAKE files abandoned"); while (tlevel>-1) tclose(); } cmini(); /* Fall through */ case -3: /* Empty command, OK at top level */ default: repars = FALSE; /* Anything else, get new command */ continue; } } } } /* DOEXIT - Exit from the program */ doexit() { cls(fgetchid(stdout)); /* Clear the screen window */ exit(0); /* Exit from the program */ } /* DOCMD - Do a command Returns: -2: user typed an illegal command -1: reparse needed 0: parse was successful (even though command may have failed) */ int docmd(cx) int cx; { int x,y; char *s,*cp; switch (cx) { case -3: return(0); /* Null command */ case -4: /* EOF */ case -2: /* Error */ case -1: return(cx); /* Reparse needed */ case XXCON: /* CONNECT */ if ((x = cmcfm())<0) return(x); CHKLINE; doconnect(); return(0); case XXDOC: /* DO */ if ((x = cmtxt("",&s,"Remote command"))<0) return(x); CHKLINE; strcpy(cmarg,s); stype = 'C'; state = S_COMD; /* Set start state */ return(0); case XXFIN: /* FINISH */ if ((x = cmcfm())<0) return(x); CHKLINE; strcpy(cmarg,"F"); stype = 'G'; state = S_COMD; return(0); case XXGET: /* GET remote [local=F] */ CHKLINE; x = cmfld("",&s,"Remote filename"); /* Get remote name */ if (x==-3) { error("Remote name not specified"); x = -2; } if (x<0) return(x); strcpy(cmarg,s); /* Save remote filename */ if ((y = cmfld("",&s,"Optional local filename"))==-3) s = ""; else if (y<0) return(y); strcpy(cmarg2,s); /* Get & save local name */ if ((x = cmcfm())<0) return(x); /* Confirm end of command */ state = G_INIT; /* All OK, set start state */ return(0); case XXHELP: /* HELP */ if ((x = cmcfm())<0) return(x); printf("\nQL-Kermit control keys:\n"); printf(" Command mode:\n F1 Context-sensitive help\n F3 Delete line\n"); printf(" F4 Complete/default word\n F5 Delete character\n"); printf(" ^R Replay line\n"); printf("\n Terminal mode:\n F2 Return to command mode\n"); printf(" F3 Send a NULL\n F4 Send a ^C\n F5 Send a DEL\n"); printf("\n Transfer mode:\n ^X Interrupt file\n ^Z Interrupt batch\n"); printf(" ^E Interrupt transaction\n ^T Resend packet\n"); printf("\n"); return(0); case XXQUI: /* QUIT or EXIT */ if ((x = cmcfm())>-1) doexit(); else return(x); case XXREC: /* RECEIVE [local=F] */ CHKLINE; x = cmfld("",&s,"Optional local filename"); if ((x==-1) || (x==-2)) return(x); /* Get local name */ if (x==-3) s = ""; /* Can be omitted */ strcpy(cmarg2,s); /* Given, save it away */ if ((x = cmcfm())<0) return(x); /* Confirm end */ printf("Waiting\n"); state = R_INIT; return(0); case XXSEN: /* SEND local [remote=local]*/ CHKLINE; x = cmfld("",&s,"Local filename"); /* Get local name */ if (x==-3) { error("Local name not specified"); x = -2; } if (x<0) return(x); strcpy(cmarg,s); /* Save local name */ y = cmfld("",&s,"Optional remote filename"); if ((y==-1) || (y==-2)) return(y); /* Get remote name */ if (y!=-3) strcpy(cmarg2,s); /* If given, store it away */ if ((y = cmcfm())<0) return(y); printf("Pausing\n"); wait(delay); /* Wait for the set time */ state = S_INIT; /* Set start state */ return(0); case XXSET: /* SET */ x = cmkey(prmtab,nprm,"","What to set"); if (x==-3) { error("SET parameter not specified"); x = -2; } if (x<0) return(x); else return(doprm(x)); case XXSHO: /* SHOW */ x = cmkey(shotab,nshotab,"all","What to show"); if (x<0) return(x); /* Find out what to show */ if (y = (cmcfm())<0) return(y); if (x==SHVER) printf("\nVersion: %s\n\n",vers); else shopar(x); return(0); case XXTAK: /* TAKE */ if (tlevel>MAXTAKE-1) /* Check not too many */ { error("TAKE files nested too deeply"); return(-2); } if ((y = cmfld("",&s,"Command file name"))<0) { /* Get file name */ if (y==-3) { error("Command file not specified"); return(-2); } else return(y); } strcpy(line,s); /* Make a safe copy of the name */ if ((y = cmcfm())<0) return(y); if ((tfile[++tlevel] = fopen(line,"r"))==NULL) { /* Try to open file */ if (debon) printf("Couldn't open TAKE file %s\n",line); strcpy(s,takedev); /* Prepend TAKE device */ cp = line; strncat(s,cp,15); if ((tfile[tlevel] = fopen(s,"r"))==NULL) { /* Try again */ qdoserr(); error("Cannot open %s or %s",line,s); tlevel--; /* Give up if can't */ } } return(0); /* Whether opened or not */ default: error("Invalid command - %s\n",cmdbuf); return(-2); } } /* SHOPAR - Show Parameters */ shopar(f) int f; { if (test(f,SHCOM)) { printf("\nCommunications parameters:\n"); printf(" Line "); if (serno<0) printf("not set"); else printf("%s",ttyname); printf(", speed "); if (speed<0) printf("not set"); else printf("%d",speed); printf(", parity %s\n",ptype(parity)); printf(" Local echo %s\n",(echo ? "on" : "off")); printf(" ENTER sends %s",(enter[0]==CR ? "CR" : "LF")); if (enter[1]!=0) printf("+%s",(enter[1]==CR ? "CR" : "LF")); printf("\n"); } if (test(f,SHXFER)) { printf("\nTransfer parameters: Send Receive\n"); printf(" Timeout %11d%9d\n",stmo,rtmo); printf(" Packet start %11d%9d\n",ssop,rsop); printf(" Packet end %11d%9d\n",seol,reol); printf(" Packet length %11d%9d\n",slen,rlen); printf(" Delay %11d\n",delay); printf(" Padding "); if (npad==0) printf("%12s\n","none"); else printf("%11d\n of 0%o ('%c')\n",npad,padch,padch); } if (test(f,SHFILE)) { printf("\nFile parameters:\n"); printf(" Incomplete files %s\n",keep ? "kept" : "deleted"); printf(" Transfer mode %s\n",xfertyp==FTASC ? "ASCII" : "binary"); printf(" Naming %s\n",trans==FNNORM ? "normal" : "untranslated"); if (strlen(suffix)==0) printf(" No send suffix\n"); else printf(" Send suffix %s\n",suffix); } if (test(f,SHPRE)) { printf("\nPrefix characters:\n"); printf(" Control quote %c\n",quote); printf(" Eight-bit quote %c\n",pebq); } if (test(f,SHSYS)) { printf("\nSystem parameters:\n"); printf(" Mode %s\n",(local ? "local" : "remote")); printf(" Timer %s, retry limit %d\n",timer ? "enabled" : "disabled",retry); printf(" Debugging "); switch (debug) { case DBOFF: printf("off"); endcase; case DBON: printf("on"); endcase; case DBFULL: printf("full"); endcase; } printf("\n TAKE file echo %s,",tkecho ? "on" : "off"); printf(" %s on error\n",tkabort ? "abort" : "continue"); } if (test(f,SHDEV)) { printf("\nDevices:\n"); printf(" Transfer source %s\n",sourdev); printf(" Transfer destination %s\n",destdev); printf(" TAKE file source %s\n",takedev); } printf("\n"); }