home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
sinclairqla.zip
/
qlksbr.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-05-08
|
16KB
|
586 lines
/*
SBR_C - QL-Kermit general subroutines
Extracts from ck*.c files, (C) Columbia University
*/
/* Include files */
#include "ram1_ker_h" /* Kermit definitions */
#include "flp1_fcntl_h" /* File opening modes */
#include "flp1_ctype_h" /* Character test macros */
/* External variables */
extern int state; /* Current switcher state */
extern int ttychid; /* QDOS channel ID of comms line */
extern int tvalue; /* Receive timeout (frames) */
extern int debug; /* Debugging level */
extern int serno; /* Serial port in use */
extern int parity; /* Parity setting */
extern int speed; /* Baud rate */
extern int ttyfd; /* FD of communication line */
extern int trans; /* File name translation */
extern int tlevel; /* TAKE file nesting level */
extern int _oserr; /* QDOS error code */
extern int oserr; /* Copy of above */
extern bool timer; /* Timer enabled flag */
extern bool cxseen,czseen; /* Transfer interrupt flags */
extern bool local; /* Operation mode flag */
extern bool keep; /* Incomplete file flag */
extern char *newfilnam; /* Transfer file name */
extern char *errdata; /* Data for E packet */
extern char *suffix; /* Outgoing file suffix */
extern char ttyname[]; /* Name of communication line */
extern int fp; /* Transfer file */
extern FILE *tfile[MAXTAKE]; /* TAKE file stack */
/* External functions */
char *strchr(); /* Find first character */
char *strrchr(); /* Find last character */
/* Local variables */
static char buf[BLKSIZ]; /* Transfer file buffer */
static int bufp; /* Index into above */
static int n; /* Character count */
/* DELCH - Special QL console character delete */
delch()
{
sd_pcol(fgetchid(stdout),1);
putchar(' ');
sd_pcol(fgetchid(stdout),1);
}
/* TREAD - Read a character from line, with timeout */
int tread()
{
unsigned char t;
int e;
int w = 0;
do
{
if (!io_pend(ttychid,1)) /* Check for pending input */
{
io_fbyte(ttychid,0,&t); /* If a byte available, */
if (parity!=PYNONE) t &= 0177; /* remove parity */
return((int) t); /* and return immediately */
}
w++; /* otherwise continue */
} while ((e = chkint())>=0 &&
(w<tvalue || !timer)); /* until timeout or interrupt */
if (e==INTE) return(e); /* ^E interrupt */
if (debon) printf("Receiver timeout\n");
return(BAD); /* Timeout */
}
/* CHKINT - Check for console interrupts */
int chkint()
{
unsigned char ch;
if (!io_pend(fgetchid(stdin),0))
{
io_fbyte(fgetchid(stdin),0,&ch); /* If a key pressed, read it */
switch (ch)
{
case 'B'-'@': /* CTRL-B */
case 'Z'-'@': /* CTRL-Z */
if (state==S_DATA || state==R_DATA)
{
intrpt("Batch aborted");
czseen = TRUE;
}
endcase;
case 'F'-'@': /* CTRL-F */
case 'X'-'@': /* CTRL-X */
if (state==S_DATA || state==R_DATA)
{
intrpt("File aborted");
cxseen = TRUE;
}
endcase;
case 'E'-'@': return(INTE); /* CTRL-E */
case 'T'-'@': intrpt("Forced timeout"); /* ENTER */
return(BAD);
}
}
return(0);
}
/* FLUSHINPUT - Dump all pending input to clear stacked up NAKs */
flushinput()
{
char dump;
if (debon) printf("Flushing input on %s\n",ttyname);
while (io_pend(ttychid,1)==0) io_fbyte(ttychid,0,&dump);
if (debon) printf("Input flushed\n");
}
/* ERROR - Print an error message */
error(fmt,a1,a2,a3,a4,a5)
char *fmt;
{
printf("ERROR: ");
printf(fmt,a1,a2,a3,a4,a5);
printf("\n");
}
/* PRERRPKT - Print contents of error packet received from remote host */
prerrpkt(msg)
char *msg;
{
printf("REMOTE ERROR: %s\n",msg);
}
/* INTRPT - Print a transfer interruption message */
intrpt(msg)
char *msg;
{
printf("INTERRUPT: %s\n",msg);
}
/* STNAME - return a printable state name */
char *stname(st)
int st;
{
switch(st)
{
case ABORT: return("ABORT");
case COMP: return("COMPLETE");
case IDLE: return("IDLE");
case R_INIT: return("REC_INIT");
case R_FILE: return("REC_FILE");
case R_DATA: return("REC_DATA");
case S_INIT: return("SEND_INIT");
case S_FILE: return("SEND_FILE");
case S_DATA: return("SEND_DATA");
case S_EOF: return("SEND_EOF");
case S_BRK: return("SEND_EOT");
case S_COMD: return("SEND_SERVER_CMD");
case G_INIT: return("SEND_SERVER_INIT");
case K_ERR: return("SEND_ERROR");
default: return("UNKNOWN");
}
}
/* RTLIM - Retry limit exceeded */
int rtlim()
{
strcpy(errdata,"Retry limit exceeded");
error(errdata);
return(K_ERR);
}
/* INTERRUPT - CTRL-E pressed to cause error abort */
int interrupt()
{
strcpy(errdata,"CTRL-E interrupt");
intrpt("Transaction aborted");
return(K_ERR);
}
/* ERRSTR - give a description for a QDOS error */
char *errstr(code)
int code;
{
switch (-code)
{
case 0: return("No error");
case 1: return("Not complete");
case 2: return("Invalid job");
case 3: return("Out of memory");
case 4: return("Out of range");
case 5: return("Buffer full");
case 6: return("Channel not found");
case 7: return("Not found");
case 8: return("Already exists");
case 9: return("In use");
case 10: return("End of file");
case 11: return("Drive full");
case 12: return("Bad name");
case 13: return("Transmit error");
case 14: return("Format failed");
case 15: return("Bad parameter");
case 16: return("Bad medium");
case 17: return("Error in expression");
case 18: return("Overflow");
case 19: return("Not implemented");
case 20: return("Read only");
case 21: return("Bad line");
default: return("Unknown error");
}
}
/* QDOSERR - An error from QDOS encountered */
int qdoserr()
{
strcpy(errdata,errstr(oserr));
printf("QDOS: %s\n",errdata);
return(K_ERR);
}
/* CLOSEF - Close transfer file if open */
closef()
{
if (fp>=0) close(fp); /* File open? */
fp = -1;
}
/* TFGET - Get a character from transfer file (from K&R - MCC library
getchar() gives EOF if the file contains more than one $FF byte
in succession!)
*/
int tfget()
{
if (n==0) /* Buffer empty? */
{
n = read(fp,buf,BLKSIZ); /* Read data */
bufp = 0; /* and restore pointer */
}
return((--n>=0) ? buf[bufp++]&0377 : EOF); /* Return data or EOF indication */
}
/* DEVOPEN - open transfer file, using appropriate device if necessary */
int devopen(name,dev,mode)
char *name,*dev;
int mode;
{
strcpy(newfilnam,name); /* Name for first try */
if ((fp = open(newfilnam,mode))<0)
{
oserr = _oserr;
if (debon) printf("Open %s failed\n",newfilnam);
if (oserr==ERR_NF) /* Maybe device name left off */
{
strcpy(newfilnam,dev); /* Add device name */
strcat(newfilnam,name); /* to given name */
if ((fp = open(newfilnam,mode))<0)
{
oserr = _oserr;
if (debon) printf("Open %s failed\n",newfilnam);
}
}
}
n = bufp = 0; /* Initialise read pointers */
return(fp);
}
/* CLS - clear a window */
cls(chan)
char *chan;
{
struct REGS in,out;
in.D0 = 0x20; /* SD.CLEAR */
in.D3 = -1; /* Timeout */
in.A0 = chan; /* Channel */
QDOS3(&in,&out);
}
/* SETBAUD - Set the communication line baud rate */
setbaud(speed)
int speed;
{
struct REGS in,out;
in.D0 = 0x12; /* MT.BAUD */
in.D1 = (short) speed; /* Baud rate */
if (QDOS1(&in,&out)==0) return(speed);
else return(-1);
}
/* WAIT - Delay for d seconds, or until a key pressed */
wait(d)
int d;
{
int i;
for (i = 0; i<d && (io_pend(fgetchid(stdin),0)!=0); i++) mt_susjb(1*50);
}
/* MT_SUSJB - Sleep this job for w frames (1/50s) */
mt_susjb(w)
int w;
{
struct REGS in,out;
in.D0 = 0x08; /* MT.SUSJB */
in.D1 = -1; /* Current job */
in.D3 = (short) w; /* Timeout */
in.A1 = 0; /* No flag byte */
QDOS1(&in,&out);
}
/* PTYPE - return a string for parity type p */
char *ptype(p)
int p;
{
switch(p)
{
case PYNONE: return("none");
case PYEVEN: return("even");
case PYODD: return("odd");
case PYMARK: return("mark");
case PYSPC: return("space");
default: return("UNKNOWN");
}
}
/* MKTTNAM - build a name to open the serial port with */
int mkttnam(line,pty)
int line,pty;
{
int i;
strcpy(ttyname,"ser"); /* First part of name */
i = strlen(ttyname);
ttyname[i++] = line+'0'; /* Port number */
switch (pty) /* Parity setting */
{
case PYEVEN: ttyname[i++] = 'e'; endcase;
case PYODD: ttyname[i++] = 'o'; endcase;
case PYMARK: ttyname[i++] = 'm'; endcase;
case PYSPC: ttyname[i++] = 's'; endcase;
}
ttyname[i++] = 'h'; /* Use handshake */
ttyname[i++] = 'r'; /* Raw data */
ttyname[i] = '\0'; /* Terminate the string */
return(i); /* and return the length */
}
/* NEWTTY - re-open a serial port with the current settings */
int newtty()
{
if (ttyfd>0)
{
close(ttyfd); /* Close old line if open */
if (debon) printf("Closed %s\n",ttyname);
ttyfd = -1;
}
ttyname[0] = '\0'; /* and clear out name */
local = FALSE; /* and status */
if (serno>0) /* New line to be opened? */
{
mkttnam(serno,parity); /* Make new name */
ttyfd = open(ttyname,O_RDWR); /* Open line */
if (ttyfd<0) /* Open failed? */
{
oserr = _oserr; /* Save QDOS error code */
error("Cannot open %s",ttyname); /* Print error messages */
qdoserr();
speed = -1; /* Unset line parameters */
return(-2);
}
local = TRUE; /* Set local/remote status */
ttychid = (int) getchid(ttyfd); /* Reset channel ID */
if (debon) printf("Opened %s\n",ttyname);
}
else speed = -1; /* Remote mode, unset speed */
return(0);
}
/* DISCARD - delete an incomplete file, if appropriate flag set */
discard(fn)
char *fn;
{
if (!keep)
{
unlink(fn);
printf("Discarded %s\n",fn);
}
}
/* CHKQUOTE - Check for a valid quote character */
bool chkquote(c)
char c;
{
return((c>' ' && c<'@') || (c>'a' && c<DEL));
}
/* NAMEPATCH - change our job name from "C-PROG" to something sensible */
namepatch()
{
char *p; /* Destination pointer */
char *s = "Kermit"; /* New job name */
struct REGS in,out;
in.D0 = 0; /* MT.INF */
QDOS1(&in,&out); /* Get our job ID */
in.D0 = 2; /* MT.JINF */
in.D1 = out.D1; /* Job ID */
in.D2 = 0; /* Parent ID */
QDOS1(&in,&out); /* Get our base address */
p = out.A0+8; /* Point to job name length */
if (*((short *) p)==6) /* Check it */
{
p += 2;
while (*s!='\0') *p++ = *s++; /* and copy in new one */
}
}
/* RTOL - convert a filename from Kermit- to QL-format: (a) change '.'s
to '_'s, (b) make letters lower case
*/
rtol(new,old)
char new[],old[];
{
int i;
char c;
if (trans==FNUNTR) strcpy(new,old); /* Literal mode , don't convert */
else
{
for (i = 0; (c = old[i])!='\0'; i++)
{
if (c=='.') new[i] = '_';
else if (isupper(c)) new[i] = tolower(c);
else new[i] = c;
}
new[i] = '\0';
}
if (debon) printf("rtol: converted %s to %s\n",old,new);
}
/* LTOR - convert a filename from QL- to Kermit-format: (a) remove first
component (device name), (b) change last '_' to '.', (c) make letters
upper case. We know that old[] has at least 2 components here (the QL
device name and the file name).
*/
ltor(new,old)
char new[],old[];
{
int l,s,j;
char c;
char wrk[30];
if (trans==FNUNTR) strcpy(new,old); /* Literal mode, don't convert */
else
{
strcpy(wrk,old); /* Take local copy of name */
if (strlen(suffix)>0) /* Suffix to be added? */
{
strcat(wrk,"_"); /* Yes, add seperator */
strcat(wrk,suffix); /* then the suffix */
}
s = (int) (strchr(wrk,'_')-wrk+1); /* Find start of 2nd component */
l = (int) (strrchr(wrk,'_')-wrk); /* and last underscore */
for (j = 0; (c = wrk[s])!='\0'; s++,j++)
{
if (s==l) new[j] = '.';
else if (islower(c)) new[j] = toupper(c);
else new[j] = c;
}
new[j] = '\0';
}
if (debon) printf("ltor: converted %s to %s\n",old,new);
}
/* TCLOSE - close the current TAKE file */
tclose()
{
fclose(tfile[tlevel--]);
if (debon) printf("TAKE file level %d closed\n",tlevel+1);
}