add directory study

This commit is contained in:
gohigh
2024-02-19 00:25:23 -05:00
parent b1306b38b1
commit f3774e2f8c
4001 changed files with 2285787 additions and 0 deletions

View File

@@ -0,0 +1,73 @@
# CKUMNX.MAK, Version 2.11, 29 January 1988
#
# -- Makefile to build C-Kermit for Minix. This is a separate file
# because Minix uses .s instead of .o for its object files. This
# means that not one line of the file is the same as the standard
# Unix makefile, so it seems silly to clutter the common file.
###########################################################################
#
# Compile and Link variables:
#
LNKFLAGS= -i -T.
CC= cc
CC2= cc
CFLAGS=-DV7 -DMINIX -i -D_MINIX -D_POSIX_SOURCE
#
###########################################################################
#
# Dependencies Section:
#
wermit: ckcmai.s ckucmd.s ckuusr.s ckuus2.s ckuus3.s ckcpro.s ckcfns.s \
ckcfn2.s ckucon.s ckutio.s ckufio.s ckudia.s ckuscr.s
$(CC2) $(LNKFLAGS) -o wermit ckcmai.s ckutio.s \
ckufio.s ckcfns.s \
ckcfn2.s ckcpro.s ckucmd.s ckuus2.s ckuus3.s ckuusr.s \
ckucon.s ckudia.s ckuscr.s
ckcmai.s: ckcmai.c ckcker.h ckcdeb.h ckcsym.h
ckuusr.s: ckuusr.c ckucmd.h ckcker.h ckuusr.h ckcdeb.h
ckuus2.s: ckuus2.c ckucmd.h ckcker.h ckuusr.h ckcdeb.h
ckuus3.s: ckuus3.c ckucmd.h ckcker.h ckuusr.h ckcdeb.h
ckucmd.s: ckucmd.c ckucmd.h ckcdeb.h
ckcpro.s: ckcpro.c ckcker.h ckcdeb.h
# I'm using the distributed copy of ckcpro.c. Unfortunately
# wart won't compile. If you need to change ckcpro.w, you'll have
# to find a way to reduce the number of strings in ckwart.c
#
# ckcpro.c: ckcpro.w wart
# ./wart ckcpro.w ckcpro.c
ckcfns.s: ckcfns.c ckcker.h ckcdeb.h ckcsym.h
ckcfn2.s: ckcfn2.c ckcker.h ckcdeb.h ckcsym.h
ckufio.s: ckufio.c ckcker.h ckcdeb.h
ckutio.s: ckutio.c ckcdeb.h
ckucon.s: ckucon.c ckcker.h ckcdeb.h
wart: ckwart.s
$(CC) $(LNKFLAGS) -o wart ckwart.s
ckwart.s: ckwart.c
ckudia.s: ckudia.c ckcker.h ckcdeb.h ckucmd.h
ckuscr.s: ckuscr.c ckcker.h ckcdeb.h
#Clean up intermediate and object files
clean:
@rm -f *.s *.bak wermit
#Run Lint on this mess for the BSD version.
lint:
-lint -x -DBSD4 -DDEBUG -DTLOG ck[cu]*.[hc] > ck.lint.bsd4

View File

@@ -0,0 +1,75 @@
# CKUMNX.MAK, Version 2.11, 29 January 1988
#
# -- Makefile to build C-Kermit for Minix. This is a separate file
# because Minix uses .o instead of .o for its object files. This
# means that not one line of the file is the same as the standard
# Unix makefile, so it seems silly to clutter the common file.
###########################################################################
#
# Compile and Link variables:
#
LNKFLAGS=
CC= cc
CC2= cc
CFLAGS=-DV7 -DMINIX -O
#
###########################################################################
#
# Dependencies Section:
#
wermit: ckcmai.o ckucmd.o ckuusr.o ckuus2.o ckuus3.o ckcpro.o ckcfns.o \
ckcfn2.o ckucon.o ckutio.o ckufio.o ckudia.o ckuscr.o
$(CC2) $(LNKFLAGS) -o wermit ckcmai.o ckutio.o \
ckufio.o ckcfns.o \
ckcfn2.o ckcpro.o ckucmd.o ckuus2.o ckuus3.o ckuusr.o \
ckucon.o ckudia.o ckuscr.o
ckcmai.o: ckcmai.c ckcker.h ckcdeb.h ckcsym.h
ckuusr.o: ckuusr.c ckucmd.h ckcker.h ckuusr.h ckcdeb.h
ckuus2.o: ckuus2.c ckucmd.h ckcker.h ckuusr.h ckcdeb.h
ckuus3.o: ckuus3.c ckucmd.h ckcker.h ckuusr.h ckcdeb.h
ckucmd.o: ckucmd.c ckucmd.h ckcdeb.h
ckcpro.o: ckcpro.c ckcker.h ckcdeb.h
# I'm using the distributed copy of ckcpro.c. Unfortunately
# wart won't compile. If you need to change ckcpro.w, you'll have
# to find a way to reduce the number of strings in ckwart.c
#
# ckcpro.c: ckcpro.w wart
# ./wart ckcpro.w ckcpro.c
ckcfns.o: ckcfns.c ckcker.h ckcdeb.h ckcsym.h
ckcfn2.o: ckcfn2.c ckcker.h ckcdeb.h ckcsym.h
ckufio.o: ckufio.c ckcker.h ckcdeb.h
ckutio.o: ckutio.c ckcdeb.h
ckucon.o: ckucon.c ckcker.h ckcdeb.h
wart: ckwart.o
$(CC) $(LNKFLAGS) -o wart ckwart.o
ckwart.o: ckwart.c
ckudia.o: ckudia.c ckcker.h ckcdeb.h ckucmd.h
ckuscr.o: ckuscr.c ckcker.h ckcdeb.h
#Clean up intermediate and object files
clean:
-rm -f ckcmai.o ckucmd.o ckuusr.o ckuus2.o ckuus3.o ckcpro.o \
ckcfns.o ckcfn2.o ckucon.o ckutio.o ckufio.o ckudia.o ckuscr.o \
ckwart.o ckcpro.c
#Run Lint on this mess for the BSD version.
lint:
-lint -x -DBSD4 -DDEBUG -DTLOG ck[cu]*.[hc] > ck.lint.bsd4

View File

@@ -0,0 +1,4 @@
It is hard to compile kermit on PC MINIX. The linker (asld) runs
out of space while linking. You can try to greatly reduce the size of
libc.a by removing every module not actually used. That might or might
not work.

View File

@@ -0,0 +1,159 @@
/* C K C D E B . H */
/*
For release 4E of C-Kermit, July 87. Incorporates changes from Phil Julian
and Jack Rouse of SAS Institute for DG, Apollo, and Amiga support, and from
Jim Noble of Planning Research Corp for Macintosh Megamax C support.
*/
/*
This file is included by all C-Kermit modules, including the modules
that aren't specific to Kermit (like the command parser and the ck?tio and
ck?fio modules. It specifies format codes for debug(), tlog(), and similar
functions, and includes any necessary typedefs to be used by all C-Kermit
modules, and also includes some feature selection compile-time switches.
*/
/*
Copyright (C) 1987 Trustees of Columbia University in the City of New York.
Permission is granted to any individual or institution to use, copy, or
redistribute this software so long as it is not sold for profit, provided this
copyright notice is retained.
*/
/*
DEBUG and TLOG should be defined in the Makefile if you want debugging
and transaction logs. Don't define them if you want to save the space
and overhead.
*/
#ifndef DEBUG
#define debug(a,b,c,d) {}
#endif
#ifndef TLOG
#define tlog(a,b,c,d) {}
#endif
/* Formats for debug(), tlog(), etc */
#define F000 0
#define F001 1
#define F010 2
#define F011 3
#define F100 4
#define F101 5
#define F110 6
#define F111 7
/* Unix Kernel Dependencies */
#ifdef SVR3
/* Sys V R3 declares signal() differently from other systems. */
typedef void SIGTYP;
#else
typedef int SIGTYP;
#endif
/* C Compiler Dependencies */
#ifdef ZILOG
#define setjmp setret
#define longjmp longret
#define jmp_buf ret_buf
typedef int ret_buf[10];
#endif /* zilog */
#ifdef PROVX1
typedef char CHAR;
typedef long LONG;
typedef int void;
#else
#ifdef V7
typedef char CHAR;
typedef long LONG;
#else
#ifdef C70
typedef char CHAR;
typedef long LONG;
#else
#ifdef BSD29
typedef char CHAR;
typedef long LONG;
#else
typedef unsigned char CHAR;
typedef long LONG;
#endif
#endif
#endif
#endif
#ifdef TOWER1
typedef int void;
#endif
/* Line delimiter for text files */
/*
If the system uses a single character for text file line delimitation,
define NLCHAR to the value of that character. For text files, that
character will be converted to CRLF upon output, and CRLF will be converted
to that character on input during text-mode (default) packet operations.
*/
#ifdef MAC /* Macintosh */
#define NLCHAR 015
#else /* All Unix-like systems */
#define NLCHAR 012
#endif
/*
At this point, if there's a system that uses ordinary CRLF line
delimitation AND the C compiler actually returns both the CR and
the LF when doing input from a file, then #undef NLCHAR.
*/
/* The device name of a job's controlling terminal */
/* Special for VMS, same for all Unixes (?), not used by Macintosh */
#ifdef vax11c
#define CTTNAM "TT:"
#else
#ifdef datageneral
#define CTTNAM "@output"
#else
#define CTTNAM "/dev/tty"
#endif
#endif
/* Some special includes for VAX/VMS */
#ifndef vax11c
/* The following #includes cause problems for some preprocessors. */
/*
#endif
#ifdef vax11c
#include ssdef
#include stsdef
#endif
#ifndef vax11c
*/
#endif
/* Program return codes for VMS, DECUS C, and Unix */
#ifdef vax11c
#define GOOD_EXIT (SS$_NORMAL | STS$M_INHIB_MSG)
#define BAD_EXIT SS$_ABORT
#else
#ifdef decus
#define GOOD_EXIT IO_NORMAL
#define BAD_EXIT IO_ERROR
#else
#define GOOD_EXIT 0
#define BAD_EXIT 1
#endif
#endif
/* Special hack for Fortune, which doesn't have <sys/file.h>... */
#ifdef FT18
#define FREAD 0x01
#define FWRITE 0x10
#endif

View File

@@ -0,0 +1,416 @@
/* C K C F N 2 -- System-independent Kermit protocol support functions... */
/* ...Part 2 (continued from ckcfns.c) */
/*
Modified July 87 to incorporate changes from Jim Noble of
Planning Research Corp for Macintosh Megamax C support.
*/
/*
Author: Frank da Cruz (SY.FDC@CU20B),
Columbia University Center for Computing Activities, January 1985.
Copyright (C) 1985, Trustees of Columbia University in the City of New York.
Permission is granted to any individual or institution to use, copy, or
redistribute this software so long as it is not sold for profit, provided this
copyright notice is retained.
*/
/*
Note -- if you change this file, please amend the version number and date at
the top of ckcfns.c accordingly.
*/
#include "ckcsym.h" /* Conditional compilation (for Macintosh) */
#include "ckcker.h"
#include "ckcdeb.h"
extern int spsiz, rpsiz, timint, npad, ebq, ebqflg, rpt, rptq, rptflg, capas;
extern int pktnum, prvpkt, sndtyp, bctr, bctu, rsn, rln, maxtry, size;
extern int osize, maxsize, spktl, nfils, stdouf, warn, timef, parity, speed;
extern int turn, turnch, delay, displa, pktlog, tralog, seslog, xflg, mypadn;
extern int deblog, hcflg, binary, fncnv, local, server, cxseen, czseen;
extern long filcnt, ffc, flci, flco, tlci, tlco, tfc, fsize;
extern char *cmarg, *cmarg2, **cmlist;
extern CHAR padch, mypadc, eol, seol, ctlq, myctlq, sstate, *hlptxt;
extern CHAR filnam[], sndpkt[], recpkt[], data[], srvcmd[];
extern CHAR *srvptr, stchr, mystch, *rdatap;
char *strcpy(); /* Forward declarations */
unsigned chk2(); /* of non-int functions */
CHAR dopar(); /* ... */
static CHAR partab[] = { /* Even parity table for dopar() */
'\000', '\201', '\202', '\003', '\204', '\005', '\006', '\207',
'\210', '\011', '\012', '\213', '\014', '\215', '\216', '\017',
'\220', '\021', '\022', '\223', '\024', '\225', '\226', '\027',
'\030', '\231', '\232', '\033', '\234', '\035', '\036', '\237',
'\240', '\041', '\042', '\243', '\044', '\245', '\246', '\047',
'\050', '\251', '\252', '\053', '\254', '\055', '\056', '\257',
'\060', '\261', '\262', '\063', '\264', '\065', '\066', '\267',
'\270', '\071', '\072', '\273', '\074', '\275', '\276', '\077',
'\300', '\101', '\102', '\303', '\104', '\305', '\306', '\107',
'\110', '\311', '\312', '\113', '\314', '\115', '\116', '\317',
'\120', '\321', '\322', '\123', '\324', '\125', '\126', '\327',
'\330', '\131', '\132', '\333', '\134', '\335', '\336', '\137',
'\140', '\341', '\342', '\143', '\344', '\145', '\146', '\347',
'\350', '\151', '\152', '\353', '\154', '\355', '\356', '\157',
'\360', '\161', '\162', '\363', '\164', '\365', '\366', '\167',
'\170', '\371', '\372', '\173', '\374', '\175', '\176', '\377'
};
/* I N P U T -- Attempt to read packet number 'pktnum'. */
/*
This is the function that feeds input to Kermit's finite state machine.
If a special start state is in effect, that state is returned as if it were
the type of an incoming packet. Otherwise:
. If the desired packet arrives within MAXTRY tries, return its type,
with its data stored in the global 'data' array.
. If the previous packet arrives again, resend the last packet and wait for
another to come in.
. If the desired packet does not arrive within MAXTRY tries, return indicating
that an error packet should be sent.
*/
input() {
int type, numtry;
if (sstate != 0) { /* If a start state is in effect, */
type = sstate; /* return it like a packet type, */
sstate = 0; /* and then nullify it. */
return(type);
} else type = rpack(); /* Else, try to read a packet. */
debug(F111,"input",rdatap,type);
/* If it's the same packet we just sent, it's an echo. Read another. */
if (type == sndtyp) type = rpack();
chkint(); /* Check for console interrupts. */
/*
If previous packet again, a timeout pseudopacket, or a bad packet, try again.
*/
for (numtry = 0;
(rsn == prvpkt || type == 'T' || type == 'Q' || type == 'N');
numtry++) {
if (numtry > maxtry) { /* If too many tries, give up */
strcpy(data,"Timed out."); /* and send a timeout error packet, */
rdatap = data; /* and pretend we read one. */
return('E');
}
if (type == 'E') return('E'); /* Don't even bother about seq no */
if ((type == 'N') && (rsn == ((pktnum+1) & 63))) {
/* NAK for next packet */
return('Y'); /* is ACK for current. */
} else {
resend(); /* Else, send last packet again, */
}
if (sstate != 0) { /* If an interrupt routine has set */
type = sstate; /* sstate behind our back, return */
sstate = 0; /* that. */
*data = '\0';
return(type);
} else type = rpack(); /* Else try to read a packet. */
chkint(); /* Look again for interruptions. */
if (type == sndtyp) type = rpack();
}
ttflui(); /* Got what we want, clear input buffer. */
return(type); /* Success, return packet type. */
}
/* S P A C K -- Construct and send a packet */
/*
spack() sends a packet of the given type, sequence number n, with len
data characters pointed to by d, in either a regular or extended-
length packet, depending on length. Returns the number of bytes
actually sent, or else -1 upon failure. Uses global npad, padch,
mystch, bctu. Leaves packet in null-terminated global sndpkt[] array for
later retransmission. Updates global sndpktl (send-packet length).
*/
spack(type,n,len,d) char type, *d; int n, len; {
int i, j, lp; CHAR *sohp = sndpkt; CHAR pc;
spktl = 0;
pc = dopar(padch); /* The pad character, if any. */
for (i = 0; i < npad; sndpkt[i++] = pc) /* Do any requested padding */
sohp++;
sndpkt[i++] = dopar(mystch); /* MARK */
lp = i++; /* Position of LEN, fill in later */
sndpkt[i++] = dopar(tochar(n)); /* SEQ field */
sndpkt[i++] = dopar(sndtyp = type); /* TYPE field */
j = len + bctu; /* True length */
if (j > 95) { /* Long packet? */
sndpkt[lp] = dopar(tochar(0)); /* Set LEN to zero */
sndpkt[i++] = dopar(tochar(j / 95)); /* High part */
sndpkt[i++] = dopar(tochar(j % 95)); /* Low part */
sndpkt[i] = '\0'; /* Header checksum */
sndpkt[i++] = dopar(tochar(chk1(sndpkt+lp)));
} else sndpkt[lp] = dopar(tochar(j+2)); /* Normal LEN */
while (len-- > 0) sndpkt[i++] = dopar(*d++); /* Packet data */
sndpkt[i] = '\0'; /* Null-terminate */
switch (bctu) { /* Block check */
case 1: /* 1 = 6-bit chksum */
sndpkt[i++] = dopar(tochar(chk1(sndpkt+lp)));
break;
case 2: /* 2 = 12-bit chksum */
j = chk2(sndpkt+lp);
sndpkt[i++] = dopar( (unsigned) tochar((j >> 6) & 077));
sndpkt[i++] = dopar( (unsigned) tochar(j & 077));
break;
case 3: /* 3 = 16-bit CRC */
j = chk3(sndpkt+lp);
sndpkt[i++] = dopar(tochar(( (unsigned)(j & 0170000)) >> 12));
sndpkt[i++] = dopar(tochar((j >> 6) & 077));
sndpkt[i++] = dopar(tochar(j & 077));
break;
}
sndpkt[i++] = dopar(seol); /* End of line (packet terminator) */
sndpkt[i] = '\0'; /* Terminate string */
if (ttol(sndpkt,i) < 0) return(-1); /* Send the packet */
spktl = i; /* Remember packet length */
flco += spktl; /* Count the characters */
tlco += spktl;
if (pktlog) { /* If logging packets, log it */
zsout(ZPFILE,"s-");
if (*sndpkt) zsoutl(ZPFILE,sndpkt); else zsoutl(ZPFILE,sohp);
}
screen(SCR_PT,type,(long)n,sohp); /* Update screen */
return(i); /* Return length */
}
/* D O P A R -- Add an appropriate parity bit to a character */
CHAR
dopar(ch) CHAR ch; {
int a;
if (!parity) return(ch & 255); else a = ch & 127;
switch (parity) {
case 'e': return(partab[a]) & 255; /* Even */
case 'm': return(a | 128); /* Mark */
case 'o': return(partab[a] ^ 128) & 255; /* Odd */
case 's': return(a & 127); /* Space */
default: return(a);
}
}
/* C H K 1 -- Compute a type-1 Kermit 6-bit checksum. */
chk1(pkt) char *pkt; {
unsigned int chk;
chk = chk2(pkt);
chk = (((chk & 0300) >> 6) + chk) & 077;
return(chk);
}
/* C H K 2 -- Compute the numeric sum of all the bytes in the packet. */
unsigned
chk2(pkt) CHAR *pkt; {
long chk; unsigned int m;
m = (parity) ? 0177 : 0377;
for (chk = 0; *pkt != '\0'; pkt++)
chk += *pkt & m;
return(chk & 07777);
}
/* C H K 3 -- Compute a type-3 Kermit block check. */
/*
Calculate the 16-bit CRC of a null-terminated string using a byte-oriented
tableless algorithm invented by Andy Lowry (Columbia University). The
magic number 010201 is derived from the CRC-CCITT polynomial x^16+x^12+x^5+1.
Note - this function could be adapted for strings containing imbedded 0's
by including a length argument. Another note - Replacing this function by
a table lookup version might speed things up.
*/
chk3(s) char *s; {
unsigned int c, q;
LONG crc = 0;
while ((c = *s++) != '\0') {
if (parity) c &= 0177; /* Strip any parity */
q = (crc ^ c) & 017; /* Low-order nibble */
crc = (crc >> 4) ^ (q * 010201);
q = (crc ^ (c >> 4)) & 017; /* High order nibble */
crc = (crc >> 4) ^ (q * 010201);
}
return(crc);
}
/* Functions for sending various kinds of packets */
ack() { /* Send an ordinary acknowledgment. */
spack('Y',pktnum,0,""); /* No data. */
nxtpkt(&pktnum); /* Increment the packet number. */
} /* Note, only call this once! */
ack1(s) char *s; { /* Send an ACK with data. */
spack('Y',pktnum,strlen(s),s); /* Send the packet. */
nxtpkt(&pktnum); /* Increment the packet number. */
} /* Only call this once! */
nack() { /* Negative acknowledgment. */
spack('N',pktnum,0,""); /* NAK's never have data. */
}
resend() { /* Send the old packet again. */
if (spktl) /* If buffer has something, */
ttol(sndpkt,spktl); /* resend it, */
else nack(); /* otherwise send a NAK. */
debug(F111,"resend",sndpkt,spktl);
screen(SCR_PT,'%',(long)pktnum,"(resend)"); /* Say resend occurred */
if (pktlog) {
zsout(ZPFILE,"s-");
zsoutl(ZPFILE,"(resend)"); /* Log packet if desired */
}
}
errpkt(reason) char *reason; { /* Send an error packet. */
encstr(reason);
spack('E',pktnum,size,data);
clsif(); clsof(1);
screen(SCR_TC,0,0l,"");
}
scmd(t,dat) char t, *dat; { /* Send a packet of the given type */
encstr(dat); /* Encode the command string */
spack(t,pktnum,size,data);
}
srinit() { /* Send R (GET) packet */
encstr(cmarg); /* Encode the filename. */
spack('R',pktnum,size,data); /* Send the packet. */
}
nxtpkt(num) int *num; {
prvpkt = *num; /* Save previous */
*num = (*num + 1) % 64; /* Increment packet number mod 64 */
}
sigint() { /* Terminal interrupt handler */
errpkt("User typed ^C");
doexit(GOOD_EXIT); /* Exit program */
}
/* R P A C K -- Read a Packet */
/*
rpack reads a packet and returns the packet type, or else Q if the
packet was invalid, or T if a timeout occurred. Upon successful return, sets
the values of global rsn (received sequence number), rln (received
data length), and rdatap (pointer to null-terminated data field).
*/
rpack() {
int i, j, x, try, type, lp; /* Local variables */
CHAR pbc[4]; /* Packet block check */
CHAR *sohp = recpkt; /* Pointer to SOH */
CHAR e; /* Packet end character */
rsn = rln = -1; /* In case of failure. */
*recpkt = '\0'; /* Clear receive buffer. */
rdatap = "";
e = (turn) ? turnch : eol; /* Use any handshake char for eol */
/* Try several times to get a "line". This allows for hosts that echo our */
/* normal CR packet terminator as CRLF. Don't diagnose CRLF as an */
/* invalid packet. */
#define TTITRY 3
for (try = 0; try < TTITRY; try++) { /* Try x times to get a "line". */
j = ttinl(recpkt,MAXRP,timint,e);
if (j < 0) {
if (j < -1) doexit(BAD_EXIT); /* Bail out if ^C^C typed. */
debug(F101,"rpack: ttinl fails","",j);
screen(SCR_PT,'T',(long)pktnum,"");
return('T'); /* Otherwise, call it a timeout. */
}
tlci += j; /* All OK, Count the characters. */
flci += j;
for (i = 0; (recpkt[i] != stchr) && (i < j); i++)
sohp++; /* Find mark */
if (i++ < j) break; /* Found it. */
}
if (try >= TTITRY) return('Q'); /* Diagnose bad packet. */
debug(F111,"ttinl",sohp,j); /* Log packet if requested. */
if (pktlog) {
zsout(ZPFILE,"r-");
zsoutl(ZPFILE,sohp);
}
lp = i; /* Remember LEN position. */
if ((j = xunchar(recpkt[i++])) == 0) {
if ((j = lp+5) > MAXRP) return('Q'); /* Long packet */
x = recpkt[j]; /* Header checksum. */
recpkt[j] = '\0'; /* Calculate & compare. */
if (xunchar(x) != chk1(recpkt+lp)) return('Q');
recpkt[j] = x; /* Checksum ok. */
rln = xunchar(recpkt[j-2]) * 95 + xunchar(recpkt[j-1]) - bctu;
j = 3; /* Data offset. */
} else if (j < 3) {
debug(F101,"rpack packet length less than 3","",j);
return('Q');
} else {
rln = j - bctu - 2; /* Regular packet */
j = 0; /* No extended header */
}
rsn = xunchar(recpkt[i++]); /* Sequence number */
type = recpkt[i++]; /* Packet type */
i += j; /* Where data begins */
rdatap = recpkt+i; /* The data itself */
if ((j = rln + i) > MAXRP ) {
debug(F101,"packet sticks out too far","",j);
return('Q'); /* Find block check */
}
/** debug(F101,"block check at","",j); **/
for (x = 0; x < bctu; x++) /* Copy it */
pbc[x] = recpkt[j+x];
pbc[x] = '\0';
/** debug(F110,"block check",pbc,bctu); **/
recpkt[j] = '\0'; /* Null-terminate data */
switch (bctu) { /* Check the block check */
case 1:
if (xunchar(*pbc) != chk1(recpkt+lp)) {
debug(F110,"checked chars",recpkt+lp,0);
debug(F101,"block check","",xunchar(*pbc));
debug(F101,"should be","",chk1(recpkt+lp));
return('Q');
}
break;
case 2:
x = xunchar(*pbc) << 6 | xunchar(pbc[1]);
if (x != chk2(recpkt+lp)) {
debug(F110,"checked chars",recpkt+lp,0);
debug(F101,"block check","", x);
debug(F101,"should be","", chk2(recpkt+lp));
return('Q');
}
break;
case 3:
x = xunchar(*pbc) << 12 | xunchar(pbc[1]) << 6 | xunchar(pbc[2]);
if (x != chk3(recpkt+lp)) {
debug(F110,"checked chars",recpkt+lp,0);
debug(F101,"block check","",xunchar(*pbc));
debug(F101,"should be","",chk1(recpkt+lp));
return('Q');
}
break;
default: return('Q');
}
screen(SCR_PT,type,(long)rsn,sohp); /* Update screen */
return(type); /* Return packet type */
}

View File

@@ -0,0 +1,95 @@
/* ckcker.h -- Symbol and macro definitions for C-Kermit */
/*
Author: Frank da Cruz (SY.FDC@CU20B),
Columbia University Center for Computing Activities, January 1985.
Copyright (C) 1985, Trustees of Columbia University in the City of New York.
Permission is granted to any individual or institution to use, copy, or
redistribute this software so long as it is not sold for profit, provided this
copyright notice is retained.
*/
/* Mnemonics for ASCII characters */
#define NUL 000 /* ASCII Null */
#define SOH 001 /* ASCII Start of header */
#define BEL 007 /* ASCII Bell (Beep) */
#define BS 010 /* ASCII Backspace */
#define LF 012 /* ASCII Linefeed */
#define CR 015 /* ASCII Carriage Return */
#define XON 021 /* ASCII XON */
#define SP 040 /* ASCII Space */
#define DEL 0177 /* ASCII Delete (Rubout) */
/* Packet buffer and window sizes, will probably need to be #ifdef'd for */
/* each system. */
#define MAXSP 2048 /* Send packet buffer size */
#define MAXRP 1024 /* Receive packet buffer size */
#define MAXWS 1 /* Maximum window size */
/* Kermit parameters and defaults */
#define MAXPACK 94 /* Maximum unextended packet size */
#define CTLQ '#' /* Control char prefix I will use */
#define MYEBQ '&' /* 8th-Bit prefix char I will use */
#define MYRPTQ '~' /* Repeat count prefix I will use */
#define MAXTRY 10 /* Times to retry a packet */
#define MYPADN 0 /* How many padding chars I need */
#define MYPADC '\0' /* Which padding character I need */
#define DMYTIM 7 /* Default timeout interval to use. */
#define URTIME 10 /* Timeout interval to be used on me. */
#define DEFTRN 0 /* Default line turnaround handshake */
#define DEFPAR 0 /* Default parity */
#define MYEOL CR /* End-Of-Line character I need on packets. */
#define DRPSIZ 90 /* Default incoming packet size. */
#define DSPSIZ 90 /* Default outbound packet size. */
#define DDELAY 5 /* Default delay. */
#define DSPEED 9600 /* Default line speed. */
/* Files */
#define ZCTERM 0 /* Console terminal */
#define ZSTDIO 1 /* Standard input/output */
#define ZIFILE 2 /* Current input file */
#define ZOFILE 3 /* Current output file */
#define ZDFILE 4 /* Current debugging log file */
#define ZTFILE 5 /* Current transaction log file */
#define ZPFILE 6 /* Current packet log file */
#define ZSFILE 7 /* Current session log file */
#define ZSYSFN 8 /* Input from a system function */
#define ZNFILS 9 /* How many defined file numbers */
/* Screen functions */
#define SCR_FN 1 /* filename */
#define SCR_AN 2 /* as-name */
#define SCR_FS 3 /* file-size */
#define SCR_XD 4 /* x-packet data */
#define SCR_ST 5 /* File status: */
#define ST_OK 0 /* Transferred OK */
#define ST_DISC 1 /* Discarded */
#define ST_INT 2 /* Interrupted */
#define ST_SKIP 3 /* Skipped */
#define ST_ERR 4 /* Fatal Error */
#define SCR_PN 6 /* packet number */
#define SCR_PT 7 /* packet type or pseudotype */
#define SCR_TC 8 /* transaction complete */
#define SCR_EM 9 /* error message */
#define SCR_WM 10 /* warning message */
#define SCR_TU 11 /* arbitrary undelimited text */
#define SCR_TN 12 /* arbitrary new text, delimited at beginning */
#define SCR_TZ 13 /* arbitrary text, delimited at end */
#define SCR_QE 14 /* quantity equals (e.g. "foo: 7") */
/* Macros */
#define tochar(ch) ((ch) + SP ) /* Number to character */
#define xunchar(ch) ((ch) - SP ) /* Character to number */
#define ctl(ch) ((ch) ^ 64 ) /* Controllify/Uncontrollify */
#define unpar(ch) ((ch) & 127) /* Clear parity bit */

View File

@@ -0,0 +1,330 @@
char *versio = "C-Kermit, 4E(070) 29 Jan 88";
/* C K C M A I -- C-Kermit Main program */
/*
4E, add long packet support, plus changes for Apollo and Data General
support from SAS Institute, and for Macintosh from Planning Research Corp,
plus several important bug fixes.
*/
/*
Author: Frank da Cruz,
Columbia University Center for Computing Activities (CUCCA), 1984-88.
Copyright (C) 1984, 1988, Trustees of Columbia University in the City of New
York. Permission is granted to any individual or institution to use, copy, or
redistribute this software so long as it is not sold for profit, provided this
copyright notice is retained.
*/
/*
The Kermit file transfer protocol was developed at Columbia University.
It is named after Kermit the Frog, star of the television series THE
MUPPET SHOW; the name is used by permission of Henson Associates, Inc.
"Kermit" is also Celtic for "free".
*/
/*
Thanks to Herm Fischer of Encino CA for extensive contributions to version 4,
and to the following people for their contributions over the years:
Larry Afrin, Clemson U
Stan Barber, Rice U
Charles Brooks, EDN
Bill Catchings, formerly of CUCCA
Bob Cattani, Columbia U CS Dept
Howard Chu, U of Michigan
Bill Coalson, McDonnell Douglas
Alan Crosswell, CUCCA
Jeff Damens, formerly of CUCCA
Joe R. Doupnik, Utah State U
Glenn Everhart, RCA Labs
Carl Fongheiser, CWRU
Yekta Gursel, MIT
Jim Guyton, Rand Corp
Stan Hanks, Rice U.
Ken Harrenstein, SRI
Ron Heiby, Motorola Micromputer Division
Steve Hemminger, Tektronix
Randy Huntziger, NLM
Phil Julian, SAS Institute
Jim Knutson, U of Texas at Austin
John Kunze, UC Berkeley
David Lawyer, UC Irvine
S.O. Lidie, Lehigh U
Chris Maio, Columbia U CS Dept
Leslie Mikesall, American Farm Bureau
Martin Minow, DEC
Tony Movshon, NYU
Dan Murphy, ???
Jim Noble, Planning Research Corporation
Paul Placeway, Ohio State U
Ken Poulton, HP Labs
Frank Prindle, NADC
Scott Ribe, ???
Jack Rouse, SAS Institute
Stew Rubenstein, Harvard
Dan Schullman, DEC
Gordon Scott, Micro Focus, Newbury UK
David Sizeland, U of London Medical School
Bradley Smith, UCLA
Markku Toijala, Helsinki U of Technology
Dave Tweten, AMES-NAS
Walter Underwood, Ford Aerospace
Pieter Van Der Linden, Centre Mondial (Paris)
Wayne Van Pelt, GE/CRD
Mark Vasoll & Gregg Wonderly, Oklahoma State University
Stephen Walton, Ametek Computer
Lauren Weinstein
Joachim Wiesel, U of Karlsruhe
Dave Woolley, CAP Communication Systems, London
and many others.
*/
#include "ckcsym.h" /* Macintosh needs this */
#include "ckcker.h"
#include "ckcdeb.h"
/* Text message definitions.. each should be 256 chars long, or less. */
#ifdef MAC
char *hlptxt = "\r\
MacKermit Server Commands:\r\
\r\
BYE\r\
FINISH\r\
GET filespec\r\
REMOTE CWD directory\r\
REMOTE HELP\r\
SEND filespec\r\
\r\0";
#else
#ifdef AMIGA
char *hlptxt = "C-Kermit Server Commands:\n\
\n\
GET filespec, SEND filespec, FINISH, BYE, REMOTE HELP\n\
\n\0";
#else
#ifdef MINIX
char *hlptxt = "C-Kermit Server REMOTE Commands:\n\
BYE CWD DELETE DIRECTORY FINISH GET HELP HOST SEND SPACE TYPE WHO\n\
\n\0";
#else /* MINIX */
char *hlptxt = "C-Kermit Server REMOTE Commands:\n\
\n\
GET files REMOTE CWD [dir] REMOTE DIRECTORY [files]\n\
SEND files REMOTE SPACE [dir] REMOTE HOST command\n\
FINISH REMOTE DELETE files REMOTE WHO [user]\n\
BYE REMOTE HELP REMOTE TYPE files\n\
\n\0";
#endif
#endif
#endif
#ifdef MINIX
char *srvtxt = "\r\n\
C-Kermit server starting.\n\
\r\n\0";
#else
char *srvtxt = "\r\n\
C-Kermit server starting. Return to your local machine by typing\r\n\
its escape sequence for closing the connection, and issue further\r\n\
commands from there. To shut down the C-Kermit server, issue the\r\n\
FINISH or BYE command and then reconnect.\n\
\r\n\0";
#endif
/* Declarations for Send-Init Parameters */
int spsiz = DSPSIZ, /* Biggest packet size we can send */
spsizf = 0, /* Flag to override what you ask for */
rpsiz = DRPSIZ, /* Biggest we want to receive */
urpsiz = DRPSIZ, /* User-requested rpsiz */
maxrps = MAXRP, /* Maximum incoming long packet size */
maxsps = MAXSP, /* Maximum outbound l.p. size */
maxtry = MAXTRY, /* Maximum retries per packet */
wsize = 1, /* Window size */
timint = DMYTIM, /* Timeout interval I use */
rtimo = URTIME, /* Timeout I want you to use */
timef = 0, /* Flag to override what you ask */
npad = MYPADN, /* How much padding to send */
mypadn = MYPADN, /* How much padding to ask for */
bctr = 1, /* Block check type requested */
bctu = 1, /* Block check type used */
ebq = MYEBQ, /* 8th bit prefix */
ebqflg = 0, /* 8th-bit quoting flag */
rqf = -1, /* Flag used in 8bq negotiation */
rq = 0, /* Received 8bq bid */
sq = 'Y', /* Sent 8bq bid */
rpt = 0, /* Repeat count */
rptq = MYRPTQ, /* Repeat prefix */
rptflg = 0; /* Repeat processing flag */
int capas = 10, /* Position of Capabilities */
atcapb = 8, /* Attribute capability */
atcapr = 0, /* requested */
atcapu = 0, /* used */
swcapb = 4, /* Sliding Window capability */
swcapr = 0, /* requested */
swcapu = 0, /* used */
lpcapb = 2, /* Long Packet capability */
lpcapr = 1, /* requested */
lpcapu = 0; /* used */
CHAR padch = MYPADC, /* Padding character to send */
mypadc = MYPADC, /* Padding character to ask for */
seol = MYEOL, /* End-Of-Line character to send */
eol = MYEOL, /* End-Of-Line character to look for */
ctlq = CTLQ, /* Control prefix in incoming data */
myctlq = CTLQ; /* Outbound control character prefix */
/* Packet-related variables */
int pktnum = 0, /* Current packet number */
prvpkt = -1, /* Previous packet number */
sndtyp, /* Type of packet just sent */
rsn, /* Received packet sequence number */
rln, /* Received packet length */
size, /* Current size of output pkt data */
osize, /* Previous output packet data size */
maxsize, /* Max size for building data field */
spktl = 0; /* Length packet being sent */
CHAR sndpkt[MAXSP+100], /* Entire packet being sent */
recpkt[MAXRP+200], /* Packet most recently received */
*rdatap, /* Pointer to received packet data */
data[MAXSP+4], /* Packet data buffer */
srvcmd[MAXRP+4], /* Where to decode server command */
*srvptr, /* Pointer to above */
mystch = SOH, /* Outbound packet-start character */
stchr = SOH; /* Incoming packet-start character */
/* File-related variables */
#ifdef datageneral
CHAR filnam[256]; /* Name of current file. */
#else
CHAR filnam[50]; /* Name of current file. */
#endif
int nfils; /* Number of files in file group */
long fsize; /* Size of current file */
/* Communication line variables */
CHAR ttname[50]; /* Name of communication line. */
int parity, /* Parity specified, 0,'e','o',etc */
flow, /* Flow control, 1 = xon/xoff */
speed = -1, /* Line speed */
turn = 0, /* Line turnaround handshake flag */
turnch = XON, /* Line turnaround character */
duplex = 0, /* Duplex, full by default */
escape = 034, /* Escape character for connect */
delay = DDELAY, /* Initial delay before sending */
mdmtyp = 0; /* Modem type (initially none) */
int tlevel = -1; /* Take-file command level */
/* Statistics variables */
long filcnt, /* Number of files in transaction */
flci, /* Characters from line, current file */
flco, /* Chars to line, current file */
tlci, /* Chars from line in transaction */
tlco, /* Chars to line in transaction */
ffc, /* Chars to/from current file */
tfc; /* Chars to/from files in transaction */
int tsecs; /* Seconds for transaction */
/* Flags */
int deblog = 0, /* Flag for debug logging */
pktlog = 0, /* Flag for packet logging */
seslog = 0, /* Session logging */
tralog = 0, /* Transaction logging */
displa = 0, /* File transfer display on/off */
stdouf = 0, /* Flag for output to stdout */
xflg = 0, /* Flag for X instead of F packet */
hcflg = 0, /* Doing Host command */
fncnv = 1, /* Flag for file name conversion */
binary = 0, /* Flag for binary file */
savmod = 0, /* Saved file mode */
cmask = 0177, /* Connect byte mask */
fmask = 0377, /* File byte mask */
warn = 0, /* Flag for file warning */
quiet = 0, /* Be quiet during file transfer */
local = 0, /* Flag for external tty vs stdout */
server = 0, /* Flag for being a server */
cnflg = 0, /* Connect after transaction */
cxseen = 0, /* Flag for cancelling a file */
czseen = 0, /* Flag for cancelling file group */
keep = 0; /* Keep incomplete files */
/* Variables passed from command parser to protocol module */
char parser(); /* The parser itself */
char sstate = 0; /* Starting state for automaton */
char *cmarg = ""; /* Pointer to command data */
char *cmarg2 = ""; /* Pointer to 2nd command data */
char **cmlist; /* Pointer to file list in argv */
/* Miscellaneous */
char **xargv; /* Global copies of argv */
int xargc; /* and argc */
extern char *dftty; /* Default tty name from ckx???.c */
extern int dfloc; /* Default location: remote/local */
extern int dfprty; /* Default parity */
extern int dfflow; /* Default flow control */
/* M A I N -- C-Kermit main program */
#ifdef apollo
/* On the Apollo, intercept main to insert a cleanup handler */
ckcmai(argc,argv) int argc; char **argv; {
#else
main(argc,argv) int argc; char **argv; {
#endif
char *strcpy();
/* Do some initialization */
xargc = argc; /* Make global copies of argc */
xargv = argv; /* ...and argv. */
sstate = 0; /* No default start state. */
strcpy(ttname,dftty); /* Set up default tty name. */
local = dfloc; /* And whether it's local or remote. */
parity = dfprty; /* Set initial parity, */
flow = dfflow; /* and flow control. */
if (sysinit() < 0) doexit(BAD_EXIT); /* And system-dependent things. */
/*** attempt to take ini file before doing command line ***/
cmdini(); /* Sets tlevel */
while (tlevel > -1) { /* Execute init file. */
sstate = parser(); /* Loop getting commands. */
if (sstate) proto(); /* Enter protocol if requested. */
}
/* Look for a UNIX-style command line... */
if (argc > 1) { /* Command line arguments? */
sstate = cmdlin(); /* Yes, parse. */
if (sstate) {
proto(); /* Take any requested action, then */
if (!quiet) conoll(""); /* put cursor back at left margin, */
if (cnflg) conect(); /* connect if requested, */
doexit(GOOD_EXIT); /* and then exit with status 0. */
}
}
/* If no action requested on command line, enter interactive parser */
herald(); /* Display program herald. */
while(1) { /* Loop getting commands. */
sstate = parser();
if (sstate) proto(); /* Enter protocol if requested. */
}
}

View File

@@ -0,0 +1,14 @@
/* This file is for use with compilers that don't have the capability to
* #define symbols on the C compiler command line. This file must
* be #include'd before all other ck*.h files so that the symbols #define'd
* here can be used for any subsequent conditional code. Symbols should be
* #define'd as 1 if TRUE and 0 if FALSE. This implies, of course, that they
* be tested with #if's, not #ifdef's and #ifndef's.
*/
/*
* For example, this file was required to compile Macintosh Kermit under
* Megamax C (which we don't do any more), because Megamax did not have
* a mechanism for defining symbols on the command line, so this file was
* used to define the symbol MAC.
*/

View File

@@ -0,0 +1,75 @@
/* C K U C M D . H -- Header file for Unix cmd package */
/*
Author: Frank da Cruz (SY.FDC@CU20B),
Columbia University Center for Computing Activities, January 1985.
Copyright (C) 1985, Trustees of Columbia University in the City of New York.
Permission is granted to any individual or institution to use, copy, or
redistribute this software so long as it is not sold for profit, provided this
copyright notice is retained.
*/
/* Special getchars... */
#ifdef vax11c
#define getchar() vms_getchar()
#endif
#ifdef aegis
#undef getchar
#define getchar() coninc(0)
#endif
#ifdef AMIGA
#undef getchar
#define getchar() coninc(0)
#endif
/* Sizes of things */
#define HLPLW 78 /* Width of ?-help line */
#define HLPCW 19 /* Width of ?-help column */
#define CMDBL 200 /* Command buffer length */
#define HLPBL 100 /* Help string buffer length */
#define ATMBL 100 /* Command atom buffer length*/
/* Special characters */
#ifndef NUL
#define NUL '\0' /* Null */
#endif
#define HT '\t' /* Horizontal Tab */
#define NL '\n' /* Newline */
#ifndef CR
#define CR '\r'
#endif
#define FF 0014 /* Formfeed (^L) */
#define RDIS 0022 /* Redisplay (^R) */
#define LDEL 0025 /* Delete line (^U) */
#define WDEL 0027 /* Delete word (^W) */
#define ESC 0033 /* Escape */
#define RUB 0177 /* Rubout */
#ifndef BEL
#define BEL 0007 /* Bell */
#endif
#ifndef BS
#define BS 0010 /* Backspace */
#endif
#ifndef SP
#define SP 0040 /* Space */
#endif
/* Keyword table flags */
#define CM_INV 1 /* Invisible keyword */
/* Keyword Table Template */
struct keytab { /* Keyword table */
char *kwd; /* Pointer to keyword string */
int val; /* Associated value */
int flgs; /* Flags (as defined above) */
};

View File

@@ -0,0 +1,273 @@
char *connv = "Connect Command for Unix, V4E(017) 14 Sep 87";
/* C K U C O N -- Dumb terminal connection to remote system, for Unix */
/*
This module should work under all versions of Unix. It calls externally
defined system-dependent functions for i/o, but depends upon the existence
of the fork() function.
Author: Frank da Cruz (SY.FDC@CU20B),
Columbia University Center for Computing Activities, January 1985.
Copyright (C) 1985, Trustees of Columbia University in the City of New York.
Permission is granted to any individual or institution to use, copy, or
redistribute this software so long as it is not sold for profit, provided this
copyright notice is retained.
Enhanced by H. Fischer to detect when child process (modem reader)
reports that the communications line has been broken and hang up.
Also enhanced to allow escaping from connect state to command
interpreter, to allow sending/receiving without breaking connection.
*/
#include <stdio.h>
#include <ctype.h> /* Character types */
#include "ckcdeb.h"
#include "ckcker.h"
#include <signal.h>
#ifndef ZILOG
#include <setjmp.h> /* Longjumps */
#else
#include <setret.h>
#endif
#ifndef SIGUSR1
#define SIGUSR1 16
#endif
extern int local, speed, escape, duplex, parity, flow, seslog, mdmtyp;
extern int errno, cmask, fmask;
extern char ttname[], sesfil[];
extern CHAR dopar();
int i, active; /* Variables global to this module */
char *chstr();
char temp[50];
#define LBUFL 200 /* Line buffer */
char lbuf[LBUFL];
/* Connect state parent/child communication signal handlers */
static jmp_buf env_con; /* Envir ptr for connect errors */
static
conn_int() { /* Modem read failure handler, */
longjmp(env_con,1); /* notifies parent process to stop */
}
/* C O N E C T -- Perform terminal connection */
conect() {
int pid, /* process id of child (modem reader) */
parent_id, /* process id of parent (keyboard reader) */
n;
int c; /* c is a character, but must be signed
integer to pass thru -1, which is the
modem disconnection signal, and is
different from the character 0377 */
char errmsg[50], *erp;
if (!local) {
printf("Sorry, you must 'set line' first\n");
return(-2);
}
if (speed < 0) {
printf("Sorry, you must 'set speed' first\n");
return(-2);
}
if ((escape < 0) || (escape > 0177)) {
printf("Your escape character is not ASCII - %d\n",escape);
return(-2);
}
if (ttopen(ttname,&local,mdmtyp) < 0) {
erp = errmsg;
sprintf(erp,"Sorry, can't open %s",ttname);
perror(errmsg);
return(-2);
}
printf("Connecting thru %s, speed %d.\r\n",ttname,speed);
printf("The escape character is %s (%d).\r\n",chstr(escape),escape);
printf("Type the escape character followed by C to get back,\r\n");
printf("or followed by ? to see other options.\r\n");
if (seslog) printf("(Session logged to %s.)\r\n",sesfil);
/* Condition console terminal and communication line */
if (conbin(escape) < 0) {
printf("Sorry, can't condition console terminal\n");
return(-2);
}
if (ttvt(speed,flow) < 0) {
conres();
printf("Sorry, Can't condition communication line\n");
return(-2);
}
/* cont'd... */
/* ...connect, cont'd */
parent_id = getpid(); /* Get parent id for signalling */
signal(SIGUSR1,SIG_IGN); /* Don't kill parent */
pid = fork(); /* All ok, make a fork */
if (pid == -1) {
conres(); /* Reset the console. */
perror("Can't create keyboard fork");
printf("[Back at Local System]\n");
return(0);
}
if (pid) {
active = 1; /* This fork reads, sends keystrokes */
if (!setjmp(env_con)) { /* comm error in child process */
signal(SIGUSR1,conn_int); /* routine for child process exit */
while (active) {
c = coninc(0) & cmask; /* Get character from keyboard */
if ((c & 0177) == escape) { /* Look for escape char */
c = coninc(0) & 0177; /* Got esc, get its arg */
doesc(c); /* And process it */
} else { /* Ordinary character */
if (ttoc(dopar(c)) > -1) {
if (duplex) { /* Half duplex? */
conoc(c); /* Yes, also echo it. */
if (seslog) /* And maybe log it. */
if (zchout(ZSFILE,c) < 0) seslog = 0;
}
} else {
perror("\r\nCan't send character");
active = 0;
}
}
}
} /* Come here on death of child */
kill(pid,9); /* Done, kill inferior fork. */
wait((int *)0); /* Wait till gone. */
conres(); /* Reset the console. */
printf("[Back at Local System]\n");
return(0);
} else { /* Inferior reads, prints port input */
sleep(1); /* Wait for parent's handler setup */
while (1) { /* Fresh read, wait for a character */
if ((c = ttinc(0)) < 0) { /* Comm line hangup detected */
if (errno == 9999) /* this value set by ckutio.c myread */
printf("\r\nCommunications disconnect ");
else perror("\r\nCan't get character");
kill(parent_id,SIGUSR1); /* notify parent. */
pause(); /* Wait to be killed by parent. */
}
c &= cmask; /* Got a char, strip parity, etc */
conoc(c); /* Put it on the screen. */
if (seslog) zchout(ZSFILE,c); /* If logging, log it. */
while ((n = ttchk()) > 0) { /* Any more left in buffer? */
if (n > LBUFL) n = LBUFL; /* Get them all at once. */
if ((n = ttxin(n,lbuf)) > 0) {
for (i = 0; i < n; i++) lbuf[i] &= cmask; /* Strip */
conxo(n,lbuf); /* Output */
if (seslog) zsoutx(ZSFILE,lbuf,n); /* Log */
}
}
}
}
}
/* H C O N N E -- Give help message for connect. */
hconne() {
int c;
static char *hlpmsg[] = {"\
\r\nC to close the connection, or:",
"\r\n 0 (zero) to send a null",
"\r\n B to send a BREAK",
"\r\n H to hangup and close connection",
"\r\n S for status",
"\r\n ? for help",
"\r\n escape character twice to send the escape character.\r\n\r\n",
"" };
conola(hlpmsg); /* Print the help message. */
conol("Command>"); /* Prompt for command. */
c = coninc(0) & 0177; /* Get character, strip any parity. */
conoc(c); /* Echo it. */
conoll("");
return(c); /* Return it. */
}
/* C H S T R -- Make a printable string out of a character */
char *
chstr(c) int c; {
static char s[8];
char *cp = s;
if (c < SP) {
sprintf(cp,"CTRL-%c",ctl(c));
} else sprintf(cp,"'%c'\n",c);
cp = s;
return(cp);
}
/* D O E S C -- Process an escape character argument */
doesc(c) char c; {
CHAR d;
while (1) {
if (c == escape) { /* Send escape character */
d = dopar(c); ttoc(d); return;
} else /* Or else look it up below. */
if (isupper(c)) c = tolower(c);
switch (c) {
case 'c': /* Close connection */
case '\03':
active = 0; conol("\r\n"); return;
case 'b': /* Send a BREAK signal */
case '\02':
ttsndb(); return;
case 'h': /* Hangup */
case '\010':
tthang(); active = 0; conol("\r\n"); return;
case 's': /* Status */
conol("\r\nConnected thru ");
conol(ttname);
if (speed >= 0) {
sprintf(temp,", speed %d",speed); conol(temp);
}
sprintf(temp,", %d bits",(cmask == 0177) ? 7 : 8);
if (parity) {
conol(", ");
switch (parity) {
case 'e': conol("even"); break;
case 'o': conol("odd"); break;
case 's': conol("space"); break;
case 'm': conol("mark"); break;
}
conol(" parity");
}
if (seslog) {
conol(", logging to "); conol(sesfil);
}
conoll(""); return;
case '?': /* Help */
c = hconne(); continue;
case '0': /* Send a null */
c = '\0'; d = dopar(c); ttoc(d); return;
case SP: /* Space, ignore */
return;
default: /* Other */
conoc(BEL); return; /* Invalid esc arg, beep */
}
}
}

View File

@@ -0,0 +1,341 @@
char *loginv = "Script Command, V2.0(007) 3 Aug 87";
/* C K U S C R -- Login script for logging onto remote system */
/*
This module should work under all versions of Unix. It calls externally
defined system-depended functions for i/o.
The module expects a login string of the expect send [expect send] ...
format. It is intended to operate similarly to the way the common
uucp "L.sys" login entries work. Conditional responses are supported
expect[-send-expect[...]] as with uucp. The send keyword EOT sends a
control-d, and the keyword BREAK sends a break. Letters prefixed
by '~' are '~b' backspace, '~s' space, '~n' linefeed, '~r' return, '~x' xon,
'~t' tab, '~q' ? (not allowed on kermit command lines), '~' ~, '~'',
'~"', '~c' don't append return, '~o[o[o]]' octal character. As with
some uucp systems, sent strings are followed by ~r (not ~n) unless they
end with ~c. Null expect strings (e.g., ~0 or --) cause a short
delay, and are useful for sending sequences requiring slight pauses.
Author: Herm Fischer (HFISCHER@USC-ECLB)
Contributed to Columbia University for inclusion in C-Kermit.
Copyright (C) 1985, Herman Fischer, 16400 Ventura Blvd, Encino CA 91436
Permission is granted to any individual or institution to use, copy, or
redistribute this software so long as it is not sold for profit, provided this
copyright notice is retained.
*/
#include "ckcdeb.h"
#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#include <setjmp.h>
#include "ckcker.h"
#ifndef MINIX
extern int local, speed, flow, seslog, mdmtyp, quiet, duplex;
extern char ttname[];
extern CHAR dopar();
static char * chstr();
static int EXP_ALRM = 15; /* Time to wait for expect string */
#define SND_ALRM 15 /* Time to allow for sending string */
#define NULL_EXP 2 /* Time to pause on null expect strg*/
#define DEL_MSEC 300 /* milliseconds to pause on ~d */
#define SBUFL 512
static char seq_buf[SBUFL], *s; /* Login Sequence buffer */
static char fls_buf[SBUFL]; /* Flush buffer */
static int got_it, no_cr;
/* connect state parent/child communication signal handlers */
static jmp_buf alrmRng; /* Envir ptr for connect errors */
scrtime() { /* modem read failure handler, */
longjmp(alrmRng,1); /* notifies parent process to stop */
}
/*
Sequence interpreter -- pick up next sequence from command string,
decode escapes and place into seq_buf
If string contains a ~d (delay) then sequenc returns a 1 expecting
to be called again after the ~d executes.
*/
static
sequenc() {
int i;
char c, oct_char;
no_cr = 0; /* output needs cr appended */
for (i=0; i<SBUFL; ) {
if (*s == '\0' || *s == '-' || isspace(*s) ) { /* done */
seq_buf[i] = '\0';
return(0) ;
}
if (*s == '~') { /* escape character */
switch (c = *(++s) ) {
case 'n': seq_buf[i++] = '\n'; break;
case 'r': seq_buf[i++] = '\r'; break;
case 't': seq_buf[i++] = '\t'; break;
case 'b': seq_buf[i++] = '\b'; break;
case 'q': seq_buf[i++] = '?'; break;
case '~': seq_buf[i++] = '~'; break;
case '\'': seq_buf[i++] = '\''; break;
case '\"': seq_buf[i++] = '\"'; break;
case 's': seq_buf[i++] = ' '; break;
case 'x': seq_buf[i++] = '\021'; break;
case 'c': no_cr = 1; break;
case 'd': { /* send what we have & then */
seq_buf[i] = '\0'; /* expect to send rest after */
no_cr = 1; /* sender delays a little */
s++;
return(1);
}
case 'w': { /* wait count */
EXP_ALRM = 15; /* default to 15 sec */
if ( isdigit( *(s+1) ) ) {
EXP_ALRM = (*(++s)) & 15;
if ( isdigit( *(s+1) ) ) {
EXP_ALRM = EXP_ALRM*10 + ( (*(++s)) & 15 );
}
}
break;
}
default:
if ( isdigit(c) ) { /* octal character */
oct_char = (c & 7); /* most significant digit */
if (isdigit( *(s+1) ) ) {
oct_char = (oct_char<<3) | ( (*(++s)) & 7 ) ;
if (isdigit( *(s+1) ) ) {
oct_char = (oct_char<<3) | ( (*(++s)) & 7 ) ;
}
}
seq_buf[i++] = oct_char;
break;
}
}
}
else seq_buf[i++] = *s; /* plain old character */
s++;
}
seq_buf[i] = '\0';
return(0); /* end of space, return anyway */
}
/*
Receive sequence -- see if expected response comes return success
(or failure) in got_it
*/
static
recvSeq() {
char *e, got[7], trace[SBUFL];
int i, l;
sequenc();
l = strlen(e=seq_buf); /* no more than 7 chars allowed */
if (l > 7) {
e += l-7;
l = 7;
}
tlog(F111,"expecting sequence",e,(long) l);
if (l == 0) { /* null sequence, just delay a little */
sleep (NULL_EXP);
got_it = 1;
tlog(F100,"got it (null sequence)","",0l);
return;
}
*trace = '\0';
for (i=0; i<7; i++) got[i]='\0';
signal(SIGALRM,scrtime); /* did we get it? */
if (!setjmp(alrmRng)) { /* not timed out yet */
alarm(EXP_ALRM);
while (!got_it) {
for (i=0; i<(l-1); i++) got[i] = got[i+1]; /* shift over one */
got[l-1] = ttinc(0) & 0177; /* next char */
if (seslog) /* Log in session log */
zchout(ZSFILE,got[l-1]);
if (strlen(trace) < sizeof(trace)-2 )
strcat(trace,chstr(got[l-1]));
got_it = (!strncmp(seq_buf, got, l) ) ;
}
} else got_it = 0; /* timed out here */
alarm(0);
signal(SIGALRM,SIG_IGN);
tlog(F110,"received sequence: ",trace,0l);
tlog(F101,"returning with got-it code","",(long) got_it);
return;
}
/*
Output A Sequence starting at pointer s,
return 0 if okay,
1 if failed to read (modem hangup or whatever)
*/
static int
outSeq() {
char *sb;
int l;
int delay;
int retCode = 0;
while(1) {
delay = sequenc();
l = strlen(seq_buf);
tlog(F111,"sending sequence ",seq_buf,(long) l);
signal(SIGALRM,scrtime);
if (!setjmp(alrmRng)) {
alarm(SND_ALRM);
if (!strcmp(seq_buf,"EOT")) {
ttoc(dopar('\004'));
if (seslog && duplex) zsout(ZSFILE,"{EOT}");
} else if (!strcmp(seq_buf,"BREAK")) {
ttsndb();
zsout(ZSFILE,"{BREAK}");
} else {
if (l > 0) {
for ( sb=seq_buf; *sb; sb++) *sb = dopar(*sb);
ttol(seq_buf,l); /* with parity */
if (seslog && duplex) zsout(ZSFILE,seq_buf);
}
if (!no_cr) {
ttoc( dopar('\r') );
if (seslog && duplex) zchout(ZSFILE,dopar('\r'));
}
}
}
else retCode |= -1; /* else -- alarm rang */
alarm(0);
signal(SIGALRM,SIG_IGN);
if (!delay) return ( retCode );
msleep(DEL_MSEC); /* delay, and loop to next stuff to send */
}
}
#endif /* not MINIX */
/* L O G I N -- Login to remote system */
login(cmdstr) char *cmdstr; {
#ifndef MINIX
SIGTYP (*saveAlm)(); /* save incoming alarm function */
char *e;
s = cmdstr; /* make global to ckuscr.c */
tlog(F100,loginv,"",0l);
if (!local) {
printf("Sorry, you must 'set line' first\n");
return(-2);
}
if (speed < 0) {
printf("Sorry, you must 'set speed' first\n");
return(-2);
}
if (ttopen(ttname,&local,mdmtyp) < 0) {
sprintf(seq_buf,"Sorry, can't open %s",ttname);
perror(seq_buf);
return(-2);
}
if (!quiet)
printf("Executing script thru %s, speed %d.\r\n",ttname,speed);
*seq_buf=0;
for (e=s; *e; e++) strcat(seq_buf, chstr(*e) );
if (!quiet) printf("Script string: %s\r\n",seq_buf);
tlog(F110,"Script string: ",seq_buf, 0l);
/* Condition console terminal and communication line */
if (ttvt(speed,flow) < 0) {
printf("Sorry, Can't condition communication line\n");
return(-2);
}
/* save initial timer interrupt value */
saveAlm = signal(SIGALRM,SIG_IGN);
flushi(); /* flush stale input */
/* cont'd... */
/* ...login, cont'd */
/* start expect - send sequence */
while (*s) { /* while not done with buffer */
while (*s && isspace(*s)) s++; /* skip over separating whitespaces */
/* gather up expect sequence */
got_it = 0;
recvSeq();
while (!got_it) {
/* no, is there a conditional send */
if (*s++ != '-') goto failRet; /* no -- return failure */
/* start of conditional send */
flushi(); /* flush out input buffer */
if (outSeq()) goto failRet; /* if unable to send! */
if (*s++ != '-') goto failRet; /* must have condit respon.*/
recvSeq();
} /* loop back and check got_it */
while (*s && !isspace(*s++) ) ; /* Skip over conditionals */
while (*s && isspace(*s)) s++; /* Skip over separating whitespaces */
flushi(); /* Flush */
if (*s) if (outSeq()) goto failRet; /* If any */
}
signal(SIGALRM,saveAlm);
if (!quiet) printf("Script successful.\r\n");
tlog(F100,"Script successful.","",0l);
#endif /* not MINIX */
return(0);
#ifndef MINIX
failRet:
signal(SIGALRM,saveAlm);
printf("Sorry, script failed\r\n");
tlog(F100,"Script failed","",0l);
return(-2);
#endif /* not MINIX */
}
/* C H S T R -- Make printable string from a character */
#ifndef MINIX
static char *
chstr(c) char c; {
static char sc[4];
if (c < SP) sprintf(sc, "^%c",ctl(c) );
else sprintf(sc, "%c", c);
return(sc);
}
/* F L U S H I -- Flush, but log, input buffer */
flushi() {
int n;
if (seslog) { /* Logging session? */
n = ttchk(); /* Yes, anything in buffer? */
if (n > 0) { /* If so, */
if (n > SBUFL) n = SBUFL; /* make sure not too much, */
n = ttxin(n,fls_buf); /* then read it, */
zsout(ZSFILE,fls_buf); /* and log it. */
}
} else ttflui(); /* Otherwise just flush. */
}
#endif /* not MINIX */

View File

@@ -0,0 +1,144 @@
/* C K U U S R . H -- Symbol definitions for C-Kermit ckuus*.c modules */
/*
Author: Frank da Cruz (SY.FDC@CU20B),
Columbia University Center for Computing Activities, January 1985.
Copyright (C) 1985, Trustees of Columbia University in the City of New York.
Permission is granted to any individual or institution to use, copy, or
redistribute this software so long as it is not sold for profit, provided this
copyright notice is retained.
*/
/* Name of C-Kermit program initialization file. */
#ifdef vax11c
#define KERMRC "kermit.ini"
#else
#define KERMRC ".kermrc"
#endif
#ifndef AMIGA
#ifndef vax11c
#ifndef datageneral
#ifdef MINIX
#include <sys/types.h>
#endif
#include <pwd.h>
#endif
#endif
#endif
/* Values associated with top-level commands, must be 0 or greater. */
#define XXBYE 0 /* BYE */
#define XXCLE 1 /* CLEAR */
#define XXCLO 2 /* CLOSE */
#define XXCON 3 /* CONNECT */
#define XXCPY 4 /* COPY */
#define XXCWD 5 /* CWD (Change Working Directory) */
#define XXDEF 6 /* DEFINE (a command macro) */
#define XXDEL 7 /* (Local) DELETE */
#define XXDIR 8 /* (Local) DIRECTORY */
#define XXDIS 9 /* DISCONNECT */
#define XXECH 10 /* ECHO */
#define XXEXI 11 /* EXIT */
#define XXFIN 12 /* FINISH */
#define XXGET 13 /* GET */
#define XXHLP 14 /* HELP */
#define XXINP 15 /* INPUT */
#define XXLOC 16 /* LOCAL */
#define XXLOG 17 /* LOG */
#define XXMAI 18 /* MAIL */
#define XXMOU 19 /* (Local) MOUNT */
#define XXMSG 20 /* (Local) MESSAGE */
#define XXOUT 21 /* OUTPUT */
#define XXPAU 22 /* PAUSE */
#define XXPRI 23 /* (Local) PRINT */
#define XXQUI 24 /* QUIT */
#define XXREC 25 /* RECEIVE */
#define XXREM 26 /* REMOTE */
#define XXREN 27 /* (Local) RENAME */
#define XXSEN 28 /* SEND */
#define XXSER 29 /* SERVER */
#define XXSET 30 /* SET */
#define XXSHE 31 /* Command for SHELL */
#define XXSHO 32 /* SHOW */
#define XXSPA 33 /* (Local) SPACE */
#define XXSTA 34 /* STATISTICS */
#define XXSUB 35 /* (Local) SUBMIT */
#define XXTAK 36 /* TAKE */
#define XXTRA 37 /* TRANSMIT */
#define XXTYP 38 /* (Local) TYPE */
#define XXWHO 39 /* (Local) WHO */
#define XXDIAL 40 /* (Local) DIAL */
#define XXLOGI 41 /* (Local) SCRIPT */
#define XXCOM 42 /* Comment */
/* SET parameters */
#define XYBREA 0 /* BREAK simulation */
#define XYCHKT 1 /* Block check type */
#define XYDEBU 2 /* Debugging */
#define XYDELA 3 /* Delay */
#define XYDUPL 4 /* Duplex */
#define XYEOL 5 /* End-Of-Line (packet terminator) */
#define XYESC 6 /* Escape character */
#define XYFILE 7 /* File Parameters */
#define XYFILN 0 /* Naming */
#define XYFILT 1 /* Type */
#define XYFILW 2 /* Warning */
#define XYFILD 3 /* ... */
/* empty space to add something */
#define XYFLOW 9 /* Flow Control */
#define XYHAND 10 /* Handshake */
#define XYIFD 11 /* Incomplete File Disposition */
#define XYIMAG 12 /* "Image Mode" */
#define XYINPU 13 /* INPUT command parameters */
#define XYLEN 14 /* Maximum packet length to send */
#define XYLINE 15 /* Communication line to use */
#define XYLOG 16 /* Log file */
#define XYMARK 17 /* Start of Packet mark */
#define XYNPAD 18 /* Amount of padding */
#define XYPADC 19 /* Pad character */
#define XYPARI 20 /* Parity */
#define XYPAUS 21 /* Interpacket pause */
#define XYPROM 22 /* Program prompt string */
#define XYQBIN 23 /* 8th-bit prefix */
#define XYQCTL 24 /* Control character prefix */
#define XYREPT 25 /* Repeat count prefix */
#define XYRETR 26 /* Retry limit */
#define XYSPEE 27 /* Line speed (baud rate) */
#define XYTACH 28 /* Character to be doubled */
#define XYTIMO 29 /* Timeout interval */
#define XYMODM 30 /* Modem type */
#define XYSEND 31 /* SEND parameters, used with some of the above */
#define XYRECV 32 /* RECEIVE parameters, ditto */
#define XYTERM 33 /* Terminal parameters */
/* REMOTE command symbols */
#define XZCPY 0 /* Copy */
#define XZCWD 1 /* Change Working Directory */
#define XZDEL 2 /* Delete */
#define XZDIR 3 /* Directory */
#define XZHLP 4 /* Help */
#define XZHOS 5 /* Host */
#define XZKER 6 /* Kermit */
#define XZLGI 7 /* Login */
#define XZLGO 8 /* Logout */
#define XZMAI 9 /* Mail */
#define XZMOU 10 /* Mount */
#define XZMSG 11 /* Message */
#define XZPRI 12 /* Print */
#define XZREN 13 /* Rename */
#define XZSET 14 /* Set */
#define XZSPA 15 /* Space */
#define XZSUB 16 /* Submit */
#define XZTYP 17 /* Type */
#define XZWHO 18 /* Who */
/* Symbols for logs */
#define LOGD 0 /* Debugging */
#define LOGP 1 /* Packets */
#define LOGS 2 /* Session */
#define LOGT 3 /* Transaction */

View File

@@ -0,0 +1,636 @@
/* Jim Noble at Planning Research Corporation, June 1987. Fixes for */
/* miscellaneous bugs found when reformatting state transititon code in */
/* CKCPRO.W. */
char *wartv = "Wart Version 1A(005) Jan 1988";
/* W A R T */
/*
pre-process a lex-like file into a C program.
Author:Jeff Damens, Columbia University Center for Computing Activites, 11/84.
Copyright (C) 1985, Trustees of Columbia University in the City of New York.
Permission is granted to any individual or institution to use, copy, or
redistribute this software so long as it is not sold for profit, provided this
copyright notice is retained.
* input format is:
* lines to be copied | %state <state names...>
* %%
* <state> | <state,state,...> CHAR { actions }
* ...
* %%
*/
#include "ckcdeb.h" /* Includes */
#include <stdio.h>
#include <ctype.h>
#define C_L 014 /* Formfeed */
#define SEP 1 /* Token types */
#define LBRACK 2
#define RBRACK 3
#define WORD 4
#define COMMA 5
/* Storage sizes */
#define MAXSTATES 50 /* max number of states */
#define MAXWORD 50 /* max # of chars/word */
#define SBYTES ((MAXSTATES+7)/8) /* # of bytes for state bitmask */
/* Name of wart function in generated program */
#ifndef FNAME
#define FNAME "wart"
#endif
/* Structure for state information */
struct trans { CHAR states[SBYTES]; /* included states */
int anyst; /* true if this good from any state */
CHAR inchr; /* input character */
int actno; /* associated action */
struct trans *nxt; }; /* next transition */
typedef struct trans *Trans;
char *malloc(); /* Returns pointer (not int) */
/* Variables and tables */
int lines,nstates,nacts;
char tokval[MAXWORD];
int tbl[MAXSTATES*128];
char *txt1 = "\n#define BEGIN state =\n\nint state = 0;\n\n";
char *fname = FNAME; /* function name goes here */
/* rest of program... */
char *txt2 = "()\n\
{\n\
int c,actno;\n\
extern int tbl[];\n\
while (1) {\n\
c = input();\n\
if ((actno = tbl[c + state*128]) != -1)\n\
switch(actno) {\n";
/* this program's output goes here, followed by final text... */
char *txt3 = "\n }\n }\n\}\n\n";
/*
* turn on the bit associated with the given state
*
*/
setstate(state,t)
int state;
Trans t;
{
int idx,msk;
idx = state/8; /* byte associated with state */
msk = 0x80 >> (state % 8); /* bit mask for state */
t->states[idx] |= msk;
}
/*
* see if the state is involved in the transition
*
*/
teststate(state,t)
int state;
Trans t;
{
int idx,msk;
idx = state/8;
msk = 0x80 >> (state % 8);
return(t->states[idx] & msk);
}
/*
* read input from here...
*
*/
Trans
rdinput(infp,outfp)
FILE *infp,*outfp;
{
Trans x,rdrules();
lines = 1; /* line counter */
nstates = 0; /* no states */
nacts = 0; /* no actions yet */
fprintf(outfp,"\n%c* WARNING -- This C source program generated by ",'/');
fprintf(outfp,"Wart preprocessor. */\n");
fprintf(outfp,"%c* Do not edit this file; edit the Wart-format ",'/');
fprintf(outfp,"source file instead, */\n");
fprintf(outfp,"%c* and then run it through Wart to produce a new ",'/');
fprintf(outfp,"C source file. */\n\n");
fprintf(outfp,"%c* Wart Version Info: */\n",'/');
fprintf(outfp,"char *wartv = \"%s\";\n\n",wartv);
initial(infp,outfp); /* read state names, initial defs */
prolog(outfp); /* write out our initial code */
x = rdrules(infp,outfp); /* read rules */
epilogue(outfp); /* write out epilogue code */
return(x);
}
/*
* initial - read initial definitions and state names. Returns
* on EOF or %%.
*
*/
initial(infp,outfp)
FILE *infp,*outfp;
{
int c;
char wordbuf[MAXWORD];
while ((c = getc(infp)) != EOF) {
if (c == '%') {
rdword(infp,wordbuf);
if (strcmp(wordbuf,"states") == 0)
rdstates(infp,outfp);
else if (strcmp(wordbuf,"%") == 0) return;
else fprintf(outfp,"%%%s",wordbuf);
}
else putc(c,outfp);
if (c == '\n') lines++;
}
}
/*
* boolean function to tell if the given character can be part of
* a word.
*
*/
isin(s,c) char *s; int c; {
for (; *s != '\0'; s++)
if (*s == c) return(1);
return(0);
}
isword(c)
int c;
{
static char special[] = ".%_-$@"; /* these are allowable */
return(isalnum(c) || isin(special,c));
}
/*
* read the next word into the given buffer.
*
*/
rdword(fp,buf)
FILE *fp;
char *buf;
{
int len = 0,c;
while (isword(c = getc(fp)) && ++len < MAXWORD) *buf++ = c;
*buf++ = '\0'; /* tie off word */
ungetc(c,fp); /* put break char back */
}
/*
* read state names, up to a newline.
*
*/
rdstates(fp,ofp)
FILE *fp,*ofp;
{
int c;
char wordbuf[MAXWORD];
while ((c = getc(fp)) != EOF && c != '\n')
{
if (isspace(c) || c == C_L) continue; /* skip whitespace */
ungetc(c,fp); /* put char back */
rdword(fp,wordbuf); /* read the whole word */
enter(wordbuf,++nstates); /* put into symbol tbl */
fprintf(ofp,"#define %s %d\n",wordbuf,nstates);
}
lines++;
}
/*
* allocate a new, empty transition node
*
*/
Trans
newtrans()
{
Trans new;
int i;
new = (Trans) malloc(sizeof (struct trans));
for (i=0; i<SBYTES; i++) new->states[i] = 0;
new->anyst = 0;
new->nxt = NULL;
return(new);
}
/*
* read all the rules.
*
*/
Trans
rdrules(fp,out)
FILE *fp,*out;
{
Trans head,cur,prev;
int curtok,i;
head = cur = NULL;
while ((curtok = gettoken(fp)) != SEP)
switch(curtok) {
case LBRACK: if (cur == NULL) cur = newtrans();
else fatal("duplicate state list");
statelist(fp,cur);/* set states */
continue; /* prepare to read char */
case WORD: if (strlen(tokval) != 1)
fatal("multiple chars in state");
if (cur == NULL) {
cur = newtrans();
cur->anyst = 1;
}
cur->actno = ++nacts;
cur->inchr = tokval[0];
if (head == NULL) head = cur;
else prev->nxt = cur;
prev = cur;
cur = NULL;
copyact(fp,out,nacts);
break;
default: fatal("bad input format");
}
return(head);
}
/*
* read a list of (comma-separated) states, set them in the
* given transition.
*
*/
statelist(fp,t)
FILE *fp;
Trans t;
{
int curtok,sval;
curtok = COMMA;
while (curtok != RBRACK) {
if (curtok != COMMA) fatal("missing comma");
if ((curtok = gettoken(fp)) != WORD) fatal("missing state name");
if ((sval = lkup(tokval)) == -1) {
fprintf(stderr,"state %s undefined\n",tokval);
fatal("undefined state");
}
setstate(sval,t);
curtok = gettoken(fp);
}
}
/*
* copy an action from the input to the output file
*
*/
copyact(inp,outp,actno)
FILE *inp,*outp;
int actno;
{
int c,bcnt;
fprintf(outp,"case %d:\n",actno);
while (c = getc(inp), (isspace(c) || c == C_L))
if (c == '\n') lines++;
if (c == '{') {
bcnt = 1;
fputs(" {",outp);
while (bcnt > 0 && (c = getc(inp)) != EOF) {
if (c == '{') bcnt++;
else if (c == '}') bcnt--;
else if (c == '\n') lines++;
putc(c,outp);
}
if (bcnt > 0) fatal("action doesn't end");
}
else {
while (c != '\n' && c != EOF) {
putc(c,outp);
c = getc(inp);
}
lines++;
}
fprintf(outp,"\n break;\n");
}
/*
* find the action associated with a given character and state.
* returns -1 if one can't be found.
*
*/
faction(hd,state,chr)
Trans hd;
int state,chr;
{
while (hd != NULL) {
if (hd->anyst || teststate(state,hd))
if (hd->inchr == '.' || hd->inchr == chr) return(hd->actno);
hd = hd->nxt;
}
return(-1);
}
/*
* empty the table...
*
*/
emptytbl()
{
int i;
for (i=0; i<nstates*128; i++) tbl[i] = -1;
}
/*
* add the specified action to the output for the given state and chr.
*
*/
addaction(act,state,chr)
int act,state,chr;
{
tbl[state*128 + chr] = act;
}
writetbl(fp)
FILE *fp;
{
warray(fp,"tbl",tbl,128*(nstates+1));
}
/*
* write an array to the output file, given its name and size.
*
*/
warray(fp,nam,cont,siz)
FILE *fp;
char *nam;
int cont[],siz;
{
int i;
fprintf(fp,"int %s[] = {\n",nam);
for (i = 0; i < siz; ) {
fprintf(fp,"%2d, ",cont[i]);
if ((++i % 16) == 0) putc('\n',fp);
}
fprintf(fp,"};\n");
}
main(argc,argv)
int argc;
char *argv[];
{
Trans head;
int state,c;
FILE *infile,*outfile;
if (argc > 1) {
if ((infile = fopen(argv[1],"r")) == NULL) {
fprintf(stderr,"Can't open %s\n",argv[1]);
fatal("unreadable input file"); } }
else infile = stdin;
if (argc > 2) {
if ((outfile = fopen(argv[2],"w")) == NULL) {
fprintf(stderr,"Can't write to %s\n",argv[2]);
fatal("bad output file"); } }
else outfile = stdout;
clrhash(); /* empty hash table */
head = rdinput(infile,outfile); /* read input file */
emptytbl(); /* empty our tables */
for (state = 0; state <= nstates; state++)
for (c = 1; c < 128; c++)
addaction(faction(head,state,c),state,c); /* find actions, add to tbl */
writetbl(outfile);
copyrest(infile,outfile);
printf("%d states, %d actions\n",nstates,nacts);
#ifdef undef
for (state = 1; state <= nstates; state ++)
for (c = 1; c < 128; c++)
if (tbl[state*128 + c] != -1) printf("state %d, chr %d, act %d\n",
state,c,tbl[state*128 + c]);
#endif
exit(GOOD_EXIT);
}
/*
* fatal error handler
*
*/
fatal(msg)
char *msg;
{
fprintf(stderr,"error in line %d: %s\n",lines,msg);
exit(BAD_EXIT);
}
prolog(outfp)
FILE *outfp;
{
int c;
while ((c = *txt1++) != '\0') putc(c,outfp);
while ((c = *fname++) != '\0') putc(c,outfp);
while ((c = *txt2++) != '\0') putc(c,outfp);
}
epilogue(outfp)
FILE *outfp;
{
int c;
while ((c = *txt3++) != '\0') putc(c,outfp);
}
copyrest(in,out)
FILE *in,*out;
{
int c;
while ((c = getc(in)) != EOF) putc(c,out);
}
/*
* gettoken - returns token type of next token, sets tokval
* to the string value of the token if appropriate.
*
*/
gettoken(fp)
FILE *fp;
{
int c;
while (1) { /* loop if reading comments... */
do {
c = getc(fp);
if (c == '\n') lines++;
} while ((isspace(c) || c == C_L)); /* skip whitespace */
switch(c) {
case EOF: return(SEP);
case '%': if ((c = getc(fp)) == '%') return(SEP);
tokval[0] = '%';
tokval[1] = c;
rdword(fp,tokval+2);
return(WORD);
case '<': return(LBRACK);
case '>': return(RBRACK);
case ',': return(COMMA);
case '/': if ((c = getc(fp)) == '*') {
rdcmnt(fp); /* skip over the comment */
continue; } /* and keep looping */
else {
ungetc(c,fp); /* put this back into input */
c = '/'; } /* put character back, fall thru */
default: if (isword(c)) {
ungetc(c,fp);
rdword(fp,tokval);
return(WORD);
}
else fatal("Invalid character in input");
}
}
}
/*
* skip over a comment
*
*/
rdcmnt(fp)
FILE *fp;
{
int c,star,prcnt;
prcnt = star = 0; /* no star seen yet */
while (!((c = getc(fp)) == '/' && star)) {
if (c == EOF || (prcnt && c == '%')) fatal("Unterminated comment");
prcnt = (c == '%');
star = (c == '*');
if (c == '\n') lines++; }
}
/*
* symbol table management for wart
*
* entry points:
* clrhash - empty hash table.
* enter - enter a name into the symbol table
* lkup - find a name's value in the symbol table.
*
*/
#define HASHSIZE 101 /* # of entries in hash table */
struct sym { char *name; /* symbol name */
int val; /* value */
struct sym *hnxt; } /* next on collision chain */
*htab[HASHSIZE]; /* the hash table */
/*
* empty the hash table before using it...
*
*/
clrhash()
{
int i;
for (i=0; i<HASHSIZE; i++) htab[i] = NULL;
}
/*
* compute the value of the hash for a symbol
*
*/
hash(name)
char *name;
{
int sum;
for (sum = 0; *name != '\0'; name++) sum += (sum + *name);
sum %= HASHSIZE; /* take sum mod hashsize */
if (sum < 0) sum += HASHSIZE; /* disallow negative hash value */
return(sum);
}
/*
* make a private copy of a string...
*
*/
char *
copy(s)
char *s;
{
char *new;
new = (char *) malloc(strlen(s) + 1);
strcpy(new,s);
return(new);
}
/*
* enter state name into the hash table
*
*/
enter(name,svalue)
char *name;
int svalue;
{
int h;
struct sym *cur;
if (lkup(name) != -1) {
fprintf(stderr,"state %s appears twice...\n");
exit(BAD_EXIT); }
h = hash(name);
cur = (struct sym *)malloc(sizeof (struct sym));
cur->name = copy(name);
cur->val = svalue;
cur->hnxt = htab[h];
htab[h] = cur;
}
/*
* find name in the symbol table, return its value. Returns -1
* if not found.
*
*/
lkup(name)
char *name;
{
struct sym *cur;
for (cur = htab[hash(name)]; cur != NULL; cur = cur->hnxt)
if (strcmp(cur->name,name) == 0) return(cur->val);
return(-1);
}