home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
sinclairqla.tar.gz
/
sinclairqla.tar
/
qlkus1.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-05-08
|
19KB
|
514 lines
/*
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");
}