@CH-FOR18p  )@vNO NAME FAT12 3м|PPPPPiP:3S|Sr &>}Uu˾t223 uV^FDBOOT Version 1.8 No Systemdisk. Booting from harddisk. Cannot load from harddisk. Insert Systemdisk and press any key. U./usr/include/sys/stermio.h 644 2 3 4715 5555203766 11100 rder 5 */ /* bits of dev specify the minor dev number */ /* of the KMC and bits 5-7 specify the line */ /* (if it's a KMS). */ char st_devaddr; /* BISYNC device add.(e.g. ' ', 'A', 'B'..) */ int st_csidev; /* csi index number a la "vpmset -s" */ }; struct stcntrs { char st_lrc; char st_xnaks; char st_rnaks; char st_xwaks; char st_rwaks; char st_scc; }; /* trace message definitions */ #define LOC 113 /* loss of carrier */ he PCD */ /* line being used; on DEC, the low o/* ******************************************************************************** * Copyright (c) 1985 AT&T * * All Rights Reserved * * * * * * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T * * The copyright ./usr/opt/src/ 40775 0 3 0 5555216210 6331 notice above does not evidence any actual * * or intended publication of such source code. * ******************************************************************************** */ /* <@(#)stermio.h 6.2> */ /* * ioctl commands for control channels */ #define STSTART 1 /* start protocol */ #define STHALT 2 /* cease protocol */ #define STPRINT 3 /* assign device to printer */ #define STENABLE 4 /* enable polling */ #define STDISABLE 5 /* disable polling */ #defin./usr/opt/src/kermit/ 40775 0 3 0 5555215356 7636 e STPOLL 6 /* set polling rate */ #define STCNTRS 7 /* poke for status reports */ #define STTCHAN 8 /* set trace channel number */ /* * ioctl commands for terminal and printer channels */ #define STGET (('X'<<8)|0) /* get line options */ #define STSET (('X'<<8)|1) /* set line options */ #define STTHROW (('X'<<8)|2) /* throw away queued input */ #define STWLINE (('X'<<8)|3) /* get synchronous line # */ #define STTSV (('X'<<8)|4) /* get all line information */ struct stio { unsigned short ttyid; char./usr/opt/src/kermit/KERMIT_INFO 644 0 3 16253 5555215353 11432 row; char col; char orow; char ocol; char tab; char aid; char ss1; char ss2; unsigned short imode; unsigned short lmode; unsigned short omode; }; /* ** Mode Definitions. */ #define STFLUSH 00400 /* FLUSH mode; lmode */ #define STWRAP 01000 /* WRAP mode; lmode */ #define STAPPL 02000 /* APPLICATION mode; lmode */ struct sttsv { char st_minor; /* synchronous device minor dev */ short st_pcdnum; /* on 3B20S, dev has major/minor of the PCD */ /* line being used; on DEC, the low o For your convenience, and also to facilitate support-related activities, a copy of KERMIT is included in this distribution. KERMIT is a terminal emulator and file transfer program, capable of transferring text and binary files with error checking and recovery. KERMIT was developed at the Columbia University Center for Computing Activities, and carries the following copyright notice: Copyright (c) 1985, Trustees of Columbia University in search list specified by the PATH variable. The file can be used on both the Professional 380 and the Professional 350. Page 2 If you wish to use KERMIT to do file transfers, you will need to get a version of KERMIT running on the host as well. The easiest way is probably to get a magnetic tape from Columbia, or possibly from a users' group or from a network (e.g., USENET). You can also o The linker, ld(1), will issue a warning about switching to a -m option when "wermit" is linked using a "make sys3nid" command. Again, do not be concerned. In addition to information in the KERMIT files included in the kit you should note the following when using KERMIT with VMS: o Contrary to the file-naming conventions mentioned in CKAAAA.HLP, VMS C-KERMIT is built using some of the "UNIX" files as well a 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 that no support of KERMIT is provided by Digital Equipment Corporation. Also note that this is a preliminary version of KERMIT, that changes are still being made to it, and that you may encounter some problems withsend the C sources, assuming they are appropriate, from your Professional to the host. Send them to the host using cu(1), which does no error checking. Then either send them again (while maintaining the first set) and compare the second set with the first set and correct any problems, or use the sum(1) command (if available) on the local and remote copies to see if any of the files need to be resent. Once this bootstrapping procedure is completed, you it. You may write to the following address to inquire about obtaining an up-to-date collection of Kermit programs: Kermit Distribution Columbia University Center for Computing Activities 612 West 115th Street New York, New York 10025 The KERMIT distribution you are receiving includes two diskettes, both in tar(1) format. The first one, labelled "KERMIT 4C(053)+ diskette #1", contains sources and related files for building C-Kercan then use KERMIT to get updated sources or binaries of itself from your Professional, from dial-in networks, etc. In addition to information in the KERMIT files included in the kit (e.g., ckaaaa.hlp, ckuker.bwr, DECnotes), you should note the following when using KERMIT with PRO/VENIX V2.0: o When using KERMIT to do terminal emulation, type Control-S to "freeze" the display and Control-Q to restore it, rather than usingmit on a UNIX or UNIX-like system. The second one, labelled "KERMIT 4C(053)+ diskette #2", contains an executable KERMIT image for use with PRO/VENIX V2.0, some documentation on using and building KERMIT, and also additional sources and related files for building C-Kermit for VMS. For information on using and building KERMIT, change your default directory if desired using cd(1), insert the second diskette in drive zero, and issue the following co the HOLD SCREEN key. o To build a version of KERMIT that will run on both the Professional 380 and the Professional 350, extract all the files from the first diskette, rename ckuker.mak to makefile, and issue a "make sys3nid" command. make(1) will produce an executable file named "wermit", which you can rename to /usr/bin/kermit after testing it. o If using a Professional 380, you may inmmand: tar xvf /dev/f0 ckaaaa.hlp Then use more(1), lp(1), or some other utility, to read the ckaaaa.hlp file that you just extracted from the diskette. To extract the executable KERMIT for use with PRO/VENIX V2.0 from the kit, insert the second diskette in drive zero and issue the following command: (cd /usr/bin; tar xvf /dev/f0 kermit) This will place the executable file in the /usr/bin directory, which is normally included in the stead issue a "make sys3" command to produce a version of KERMIT with slightly better performance, and also one that can be debugged using adb(1). KERMIT cannot easily be debugged on the Professional 350 because adb cannot be used with code-mapped programs. o The C optimizer will issue a warning about running out of space when compiling ckuus2.c. Do not be concerned. rings in the modem's memory and invoke them from KERMIT (e.g., DIAL $WORK, DIAL B). UNIX is a trademark of AT&T. VENIX is a trademark of VenturCom, Inc. igital has made, and also includes some problem reports, suggestions, etc. KERMIT now supports Digital's DF03-AC, DF100 series, and DF200 series modems. You may redial the last number dialed on the DF100 and DF200 modems by simply issuing the DIAL command without any arguments. You can also store dialing sts Perkin-Elmer 3230. Others will probably be /unix. PROCNAME=proc # is the name of the structure assigned to each process on okstate's system. # This may be "_proc" or some other variation. See for more info # on your systems name conventions. NPROCNAME=nproc is the name of a # Kernal variable that tells how many "proc" structures there are. Again # this may be different on your system, but nproc will probably be somewhere. # The variable NPTYPE is the type of the nproc variable -- i./usr/opt/src/kermit/Makefile 644 0 3 15071 5555215353 11336 nt, short, etc. # which can probably be gleaned from . # The definition of DIRECT is a little more in depth. If nlist() returns, # for "proc" only, the address of the array, then you should define DIRECT # as it is below. If however, nlist() returns the address of a pointer to # the array, then you should give DIRECT a null definition (DIRECT= ). The # extern declaration in should clarify this for you. If it # is "extern struct proc *proc", then you should NOT define DIRs the VMS-specific ones. Page 3 o If you have problems running CKWART, try compiling CKWART.C without optimization. Alternatively, you can omit the use of CKWART and use the CKCPRO.C file that is included in the kit. o VMS C-KERMIT appears not to be interruptable. You will have to send it a FINISH command from a local KERMIT, or abort the VMS process # CKUKER.MAK, Version 2.00 # # Makefile to build C-Kermit for various Unix and Unix-like systems # # Rename to "makefile" or "Makefile" before using, then: # # for Berkeley Unix 4.x, "make bsd" # for Berkeley Unix 2.9 (PDP-11), "make bsd29" # for AT&T 3Bx systems, "make 3bx" # for AT&T generic System III/System V, "make sys3" # for Bell Unix Version 7 (aka 7th Edition), "make v7" # for Microsoft Xenix (/286, PC/AT, etc), "make xenix" # for Interactive (PC/IX) on PC/XT, "make pcix" # for Interactive on otherfrom another terminal line. o There is also a BLISS-32 (and hence MACRO-32) version of KERMIT for VMS. It has been around a while and is somewhat faster and more stable than the C version. Contact Columbia University if you want a copy of it. Digital has recently made some changes to the KERMIT files and has sent those changes to Columbia University. This kit includes the changed versions, which have not yet been " systems, "make is3" # for DEC Pro-350 with Pro/Venix V1.x, "make provx1" # for DEC Pro-350 with Pro/Venix V2.0 (Sys V), "make sys3nid" # for DEC Pro-380 with Pro/Venix V2.0 (Sys V), "make sys3" or "make sys3nid" # for NCR Tower 1632, OS 1.02, "make tower1" # ############################################################################## # # Notes: # # In many cases, the -O (optimize) compiler switch is omitted. Feel free # to add it if you trust your optimizer. # # "make bsd" should produce a working Cofficially" accepted by Columbia. The DECnotes file on the second diskette contains some information that was sent to Columbia about the changes that Digital has made, and also includes some problem reports, suggestions, etc. KERMIT now supports Digital's DF03-AC, DF100 series, and DF200 series modems. You may redial the last number dialed on the DF100 and DF200 modems by simply issuing the DIAL command without any arguments. You can also store dialing st-Kermit for both 4.1 and 4.2bsd # on VAX, SUN, and Pyramid computers. # # "make sys3" seems to produce a working version on any ATT System III # or System V system, including Motorola Four Phase, Callan Unistar, Cadmus, # NCR Tower, HP9836 Series 200, Plexus, Masscomp/RTU, etc etc (for # exceptions, see below; AT&T 3Bx systems have their own entry). # # For version 7, several variables must be defined to the values # associated with your system. BOOTNAME=/edition7 is the kernel image on # okstate'###################### # # V7-specific variables. # These are set up for Perkin-Elmer 3230 V7 Unix: # PROC=proc DIRECT= NPROC=nproc NPTYPE=int BOOTFILE=/edition7 # # ( For TRS-80 Xenix, use PROC=_proc, DIRECT=-DDIRECT, NPROC=_Nproc, # NPTYPE=short, BOOTFILE=/xenix ) # ########################################################################### # # Compile and Link variables: # LNKFLAGS= CC= cc CC2= cc # ########################################################################### # make: @echo 'Make wlain old Bell System III or System V without strange things (with I&D space) sys3: make wermit "CFLAGS = -DUXIII -DDEBUG -DTLOG -i -O" "LNKFLAGS = -i" #plain old Bell System III or System V without strange things (no I&D space) sys3nid: make wermit "CFLAGS = -DUXIII -DDEBUG -DTLOG -O" "LNKFLAGS =" #DEC Pro-3xx with Pro/Venix V1.0 or V1.1 provx1: make wart "CFLAGS= -DPROVX1" "LNKFLAGS= " make wermit "CFLAGS = -DPROVX1 -DDEBUG -DTLOG -md780" \ "LNKFLAGS= -u _sleep -lc -md780" #NCR Tower 1632, OS 1.02hat? You must tell which system to make C-Kermit for.' 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 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. tower1: make wermit "CFLAGS = -DDEBUG -DTLOG -DTOWER1" gs (with I&D space) sys3: make wermit "CFLAGS = -DUXIII -DDEBUG -DTLOG -i -O" "LNKFLAGS = -i" #plain old Bell System III or System V without strange things (no I&D space) sys3nid: make wermit "CFLAGS = -DUXIII -DDEBUG -DTLOG -O" "LNKFLAGS =" #DEC Pro-3xx with Pro/Venix V1.0 or V1.1 provx1: make wart "CFLAGS= -DPROVX1" "LNKFLAGS= " make wermit "CFLAGS = -DPROVX1 -DDEBUG -DTLOG -md780" \ "LNKFLAGS= -u _sleep -lc -md780" #NCR Tower 1632, OS 1.02c ckucmd.h ckcker.h ckuusr.h ckcdeb.h ckucmd.o: ckucmd.c ckucmd.h ckcdeb.h ckcpro.o: ckcpro.c ckcker.h ckcdeb.h ckcpro.c: ckcpro.w wart ./wart ckcpro.w ckcpro.c ckcfns.o: ckcfns.c ckcker.h ckcdeb.h ckcfn2.o: ckcfns.c ckcker.h ckcdeb.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 ckuscr.o: ckuscr.c ckcker.h ckcdeb.h #Version 7 Unix v./usr/opt/src/kermit/ckcdeb.h 644 0 3 4755 5555215353 11251 ECT. If it # is "extern struct proc proc[]", then you should probably define DIRECT as # it is below. See ckuv7.hlp for further information. # # For 2.9bsd, the makefile uses pcc rather than cc for compiles; that's what # the CC and CC2 definitions are for. 2.9 support basically follows the 4.2 # path, except with a normal file system (file names 14 chars max). # # The v7 and 2.9bsd versions assume I&D space on a PDP-11. When building # C-Kermit for v7 on a PDP-11, you should probably add the -i 7: make wermit "CFLAGS=-DV7 -DDEBUG -DTLOG -DPROCNAME=\\\"$(PROC)\\\" \ -DBOOTNAME=\\\"$(BOOTFILE)\\\" -DNPROCNAME=\\\"$(NPROC)\\\" \ -DNPTYPE=$(NPTYPE) $(DIRECT)" #Berkeley Unix 4.1 or 4.2 bsd: make wermit "CFLAGS= -DBSD4 -DDEBUG -DTLOG" #Berkeley Unix 2.9 for PDP-11s with I&D space bsd29: make wermit "CFLAGS= -DV7 -DDEBUG -DTLOG" "LNKFLAGS= -i" "CC= pcc " \ "CC2= cc" #Microsoft "Xenix/286" e.g. for IBM PC/AT xenix: make wermit "CFLAGS= -DXENIX -DUXIII -DDEBUG -DTLOG -F 3000 -i" \ "LNKFLAGS =option to # the link flags. Without I&D space, overlays would probably have to be # used (or code mapping a`la Pro/Venix if that's available). # # For HP9000 series 500, use "make sys3nid", but # 1. In ckutio.c, don't #include or ioctl.h. # 2. In ckufio.c, don't #include . # # For Ridge32 (ROS3.2), use "make sys3", but # 1. Use "CFLAGS = -DUXIII -i -O" "LNKFLAGS = -i" # 2. Don't #include in cku[tf]io.c. # ######################################################## -F 3000 -i" #PC/IX, Interactive Corp System III for IBM PC/XT pcix: make wermit \ "CFLAGS= -DPCIX -DUXIII -DISIII -DDEBUG -DTLOG -Dsdata=sdatax -O -i" \ "LNKFLAGS = -i" #Interactive Corp System III port in general -- is3: make wermit \ "CFLAGS = -DISIII -DUXIII -DDEBUG -DTLOG -Ddata=datax -O -i" \ "LNKFLAGS = -i" #AT&T 3B-series computers running System V #...only difference from sys3 is lock file stuff... # 3bx: make wermit "CFLAGS = -DUXIII -D3BX -DDEBUG -DTLOG -i -O" \ "LNKFLAGS = -i" #py 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/* C K C F N 2 -- System-independent Kermit protocol support functions... */ /* ...Part 2 (continued from ckcfns.c) */ /* 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 -- F011 3 #define F100 4 #define F101 5 #define F110 6 #define F111 7 /* Compiler dependencies */ #ifdef PROVX1 typedef char CHAR; typedef long LONG; typedef int void; #else #ifdef V7 typedef char CHAR; typedef long LONG; #else typedef unsigned char CHAR; typedef long LONG; #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 if you change this file, please amend the version number and date at the top of ckcfns.c accordingly. */ #include "ckcker.h" #include "ckcdeb.h" extern int spsiz, rpsiz, timint, npad, chklen, ebq, ebqflg, rpt, rptq, rptflg, capas; extern int pktnum, prvpkt, sndtyp, bctr, bctu, size, osize, maxsize, spktl, nfils, stdouf, warn, timef; extern int parity, speed, turn, turnch, delay, displa, pktlog, tralog, seslog, xflg, mypadn; extern long filcnt, ffc, flci, flco, tlci, tlco, tfc, fsize; extern int deblcharacter will be converted to CRLF upon output, and CRLF will be converted to that character on input. */ #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 (og, hcflg, binary, fncnv, local, server, cxseen, czseen; extern char padch, mypadc, eol, seol, ctlq, myctlq, sstate, *hlptxt; extern char filnam[], sndpkt[], recpkt[], data[], srvcmd[], *srvptr, stchr, mystch; extern char *cmarg, *cmarg2, **cmlist; char *strcpy(); CHAR dopar(); /* 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 ?), not used by Macintosh */ #ifdef vax11c #define CTTNAM "TT:" #else #define CTTNAM "/dev/tty" #endif /* Some special includes for VAX/VMS */ #ifdef vax11c #include ssdef #include stsdef #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 me for all Unixes (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 len, num, type, numtry; if (sstate != 0) { /* If a start state is in effect, */ type = sstate; /* r/* C K C D E B . H */ /* 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) 1985, Trustees of Columbia University in the City of New York. Permission is granted to an./usr/opt/src/kermit/ckcfn2.c 644 0 3 32436 5555215353 11214 eturn it like a packet type, */ sstate = 0; /* and then nullify it. */ *data = '\0'; return(type); } else type = rpack(&len,&num,data); /* Else, try to read a packet. */ /* If it's the same packet we just sent, it's an echo. Read another. */ if (type == sndtyp) type = rpack(&len,&num,data); chkint(); /* Check for console interrupts. */ /* If previous packet again, a timeout pseudopacket, or a bad packet, try again. */ for (numtry = 0; (num == prvpkt || type == 'T' || type the packet just built */ flco += spktl; /* Count the characters */ tlco += spktl; if (pktlog) zsoutl(ZPFILE,sndpkt); /* If logging packets, log it */ screen(SCR_PT,type,(long)num,sndpkt); /* Update screen */ } /* D O P A R -- Add an appropriate parity bit to a character */ CHAR dopar(ch) char ch; { int a, b; if (!parity) return(ch); else ch &= 0177; switch (parity) { case 'm': return(ch | 128); /* Mark */ case 's': return(ch & 127); /* Space */ case 'o': /== 'Q' || type == 'N'); numtry++) { if (numtry > MAXTRY) { /* If too many tries, give up */ strcpy(data,"Timed out."); /* and send a timeout error packet. */ return('E'); } 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(&len,&num,data); /* Else, try to read a packet. */ chkint(); * Odd (fall thru) */ case 'e': /* Even */ a = (ch & 15) ^ ((ch >> 4) & 15); a = (a & 3) ^ ((a >> 2) & 3); a = (a & 1) ^ ((a >> 1) & 1); if (parity == 'o') a = 1 - a; /* Switch sense for odd */ return(ch | (a << 7)); default: return(ch); } } /* C H K 1 -- Compute a type-1 Kermit 6-bit checksum. */ chk1(pkt) char *pkt; { int chk; chk = chk2(pkt); return((((chk & 0300) >> 6) + chk) & 077); } /* C H K 2 -- Compute the numeric sum of all the byte/* Look again for interruptions. */ if (type == sndtyp) type = rpack(&len,&num,data); } return(type); /* Success, return packet type. */ } /* S P A C K -- Construct and send a packet */ spack(type,num,len,dat) char type, *dat; int num, len; { int i,j; j = dopar(padch); for (i = 0; i < npad; sndpkt[i++] = j) /* Do any requested padding */ ; sndpkt[i++] = dopar(mystch); /* Start packet with the start char */ sndpkt[i++] = dopar(tochar(len+bctu+2)); /* Put in ts in the packet. */ chk2(pkt) char *pkt; { unsigned int chk; int p; for (chk = 0; *pkt != '\0'; *pkt++) { p = (parity) ? *pkt & 0177 : *pkt; chk += p; } return(chk); } /* 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 coulhe length */ sndpkt[i++] = dopar(tochar(num)); /* The packet number */ sndpkt[i++] = sndtyp = dopar(type); /* Packet type */ for (j = len; j > 0; j-- ) sndpkt[i++] = dopar(*dat++); /* Data */ sndpkt[i] = '\0'; /* Mark end for block check */ switch(bctu) { case 1: /* Type 1 - 6 bit checksum */ sndpkt[i++] = dopar(tochar(chk1(sndpkt+1))); break; case 2: /* Type 2 - 12 bit checksum*/ j = chk2(sndpkt+1); sndpkt[i++] = dopar(tochar((j & 07700) >> 6)); snd be adapted for strings containing imbedded 0's by including a length argument. */ chk3(s) char *s; { unsigned int c, q; LONG crc = 0; while ((c = *s++) != '\0') { if (parity) c &= 0177; 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. */ spackdpkt[i++] = dopar(tochar(j & 077)); break; case 3: /* Type 3 - 16 bit CRC-CCITT */ j = chk3(sndpkt+1); sndpkt[i++] = dopar(tochar(( (unsigned)(j & 0170000)) >> 12)); sndpkt[i++] = dopar(tochar((j & 07700) >> 6)); sndpkt[i++] = dopar(tochar(j & 077)); break; } for (j = npad; j > 0; j-- ) sndpkt[i++] = dopar(padch); /* Padding */ sndpkt[i++] = dopar(seol); /* EOL character */ sndpkt[i] = '\0'; /* End of the packet */ ttol(sndpkt,spktl=i); /* Send ('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. */ int w; for (w = 0; == 2) doexit(0); ***/ if (t == eol) return('Q'); *l = unchar(t); /* Packet length */ debug(F101," pkt len","",*l); /* sequence number */ if ((t = recpkt[i++]) == stchr) continue; if (t == eol) return('Q'); *n = unchar(t); debug(F101,"rpack: n","",*n); /* cont'd... */ /* ...rpack(), cont'd */ /* type */ if ((type = recpkt[i++]) == stchr) continue; if (type == eol) return('Q'); debug(F101,"rpack: type","",type); if ((type == 'S') || (type == 'I')) pbl = 1; /* Heuristics for */ else e","",0); screen(SCR_PT,'Q',(long)n,recpkt); return('Q'); } break; } /* Good packet, return its type */ ttflui(); /* Done, flush any remaining. */ screen(SCR_PT,type,(long)(*n),recpkt); /* Update screen */ return(type); } /* I N C H R -- Input character from communication line, with timeout */ inchr(timo) int timo; { int c; c = ttinc(timo); debug(F101,"inchr ttinc","",c); if (c < 0) return(c); /* Get a character */ if (parity)w < timint - 2; w++) { /* Be extra sure no stuff is */ ttflui(); /* still coming in. */ sleep(1); if (!ttchk() ) ttinc(1); /* be extra sure no stuff in SIII/V */ if (!ttchk() ) break; } if (*sndpkt) ttol(sndpkt,spktl); /* Resend if buffer not empty */ screen(SCR_PT,'%',(long)pktnum,sndpkt); /* Display that resend occurred */ if (pktlog && *sndpkt) zsoutl(ZPFILE,sndpkt); /* Log packet if desired */ } errpkt(reason) char *reason; { /* Send an error packet. */ encstr(reason); sif (type == 'N') pbl = *l - 2; /* syncing block check type */ else pbl = bctu; *l -= (pbl + 2); /* Now compute data length */ debug(F101,"rpack: bctu","",bctu); debug(F101," pbl","",pbl); debug(F101," data length","",*l); /* data */ dat[0] = '\0'; /* Return null string if no data */ for (j=0; j<*l; i++,j++) if ((dat[j] = recpkt[i]) == stchr) continue; else if (dat[j] == eol) return('Q'); dat[j] = '\0'; /* get the block check */ debug(F110," packet chk",recpkt+i,0); for (jpack('E',pktnum,size,data); 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() { /* Ter = 0; j < pbl; j++) { chk[j] = recpkt[i]; debug(F101," chk[j]","",chk[j]); if (chk[j] == stchr) break; if (chk[j] == eol) return('Q'); recpkt[i++] = '\0'; } chk[j] = 0; debug(F111," chk array, j",chk,j); if (j != pbl) continue; /* Block check right length? */ done = 1; /* Yes, done. */ } /* cont'd... */ /* ...rpack(), cont'd */ /* Got packet, now check the block check */ switch (pbl) { case 1: xchk[0] = tochar(chk1(&recpkt[pstart])); if (chk[0] != xminal interrupt handler */ errpkt("User typed ^C"); doexit(GOOD_EXIT); /* Exit program */ } /* R P A C K -- Read a Packet */ rpack(l,n,dat) int *l, *n; char *dat; { int i, j, x, done, pstart, pbl; char chk[4], xchk[4], t, type; chk[3] = xchk[3] = 0; i = inlin(); /* Read a line */ if (i != 0) { debug(F101,"rpack: inlin","",i); screen(SCR_PT,'T',(long)pktnum,""); return('T'); } debug(F110,"rpack: inlin ok, recpkt",recpkt,0); /* Look for start of packet */ chk[0]) { if (deblog) { debug(F000,"rpack: chk","",chk[0]); debug(F000," should be ","",xchk[0]); } screen(SCR_PT,'Q',(long)n,recpkt); return('Q'); } break; case 2: x = chk2(&recpkt[pstart]); xchk[0] = tochar((x & 07700) >> 6); xchk[1] = tochar(x & 077); if (deblog) { debug(F000," xchk[0]","=",xchk[0]); debug(F000," xchk[1]","=",xchk[1]); } if ((xchk[0] != chk[0]) || (xchk[1] != chk[1])) { debug(F100," bct2's don't compare","",0); screen(S for (i = 0; ((t = recpkt[i]) != stchr) && (i < RBUFL) ; i++) ; if (++i >= RBUFL) return('Q'); /* Skip rest if not found */ /* now "parse" the packet */ debug(F101,"entering rpack with i","",i); done = 0; while (!done) { debug(F101,"rpack starting at i","",i); pstart = i; /* remember where packet started */ /* length */ if ((t = recpkt[i++]) == stchr) continue; /* Resynch if SOH */ /*** this allows ^A^B to cause exit, comment it out when not debugging ***/ /*** if (tCR_PT,'Q',(long)n,recpkt); return('Q'); } break; case 3: x = chk3(&recpkt[pstart]); xchk[0] = tochar(( (unsigned)(x & 0170000)) >> 12); xchk[1] = tochar((x & 07700) >> 6); xchk[2] = tochar(x & 077); if (deblog) { debug(F000," xchk[0]","=",xchk[0]); debug(F000," xchk[1]","=",xchk[1]); debug(F000," xchk[2]","=",xchk[2]); } if ((xchk[0] != chk[0]) || (xchk[1] != chk[1]) || (xchk[2] != chk[2])) { debug(F100," bct3's don't compar./usr/opt/src/kermit/ckcfns.c 644 0 3 64043 5555215353 11314 tead of getpkt() if source is a string, rather than a file. */ encstr(s) char* s; { int m; char *p; m = memstr; p = memptr; /* Save these. */ memptr = s; /* Point to the string. */ memstr = 1; /* Flag memory string as source. */ next = -1; /* Initialize character lookahead. */ getpkt(spsiz); /* Fill a packet from the string. */ memstr = m; /* Restore memory string flag */ memptr = p; /* and pointer */ next = -1; /* Put this back as we found it. */ char *fnsv = "C-Kermit functions, 4C(041)+1 25 Jun 85"; /* C K C F N S -- System-independent Kermit protocol support functions. */ /* ...Part 1 (others moved to ckcfn2 to make this module small enough) */ /* 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 } /* E N C O D E - Kermit packet encoding procedure */ encode(a) int a; { /* The current character */ int a7; /* Low order 7 bits of character */ int b8; /* 8th bit of character */ if (rptflg) { /* Repeat processing? */ if (a == next) { /* Got a run... */ if (++rpt < 94) /* Below max, just count */ return; else if (rpt == 94) { /* Reached max, must dump */ data[size++] = rptq; data[size++] = tochar(rpt); c = c & 0177; /* If parity on, discard parity bit. */ debug(F101," after parity","",c); return(c); } /* I N L I N -- Input a line (up to break char) from communication line */ /* Returns 0 on success, nonzero on failure */ inlin() { int i, j, k, maxt; CHAR e; maxt = (speed >= 110) ? (MAXTRY * 9600 / speed) : MAXTRY; debug(F101,"inlin: speed","",speed); debug(F101," maxt","",maxt); e = (turn) ? turnch : eol; i = j = k = 0; if (parity) { while ((j != e)it is not sold for profit, provided this copyright notice is retained. */ /* System-dependent primitives defined in: ck?tio.c -- terminal i/o cx?fio.c -- file i/o, directory structure */ #include "ckcker.h" /* Symbol definitions for Kermit */ #include "ckcdeb.h" /* Debug formats, typedefs, etc. */ #ifndef NULL #define NULL 0 #endif /* Externals from ckcmai.c */ extern int spsiz, rpsiz, timint, rtimo, npad, chklen, ebq, ebqflg, rpt, rptq, rptflg, capas; extern int pktnum, prvpkt, sndtyp, bct && (i < RBUFL) && (k < maxt)) { j = inchr(1); /* Get char, 1 second timeout */ debug(F101,"inlin inchr","",j); if (j < 0) k++; /* Timed out. */ else { if (j) recpkt[i++] = j; /* Save it */ k = 0; /* Reset timeout counter. */ } } } else { i = ttinl(recpkt,RBUFL,timint,e); /* Get them all at once */ if (i < 0) k = 1; } recpkt[i+1] = '\0'; /* Terminate near end of packet */ debug(F111,"inlin",recpkt,i); /* Debug report... */ debug(F101," timeouts",r, bctu, size, osize, maxsize, spktl, nfils, stdouf, warn, timef; extern int parity, speed, turn, turnch, delay, displa, pktlog, tralog, seslog, xflg, mypadn; extern long filcnt, ffc, flci, flco, tlci, tlco, tfc, fsize; extern int deblog, hcflg, binary, fncnv, local, server, cxseen, czseen; extern char padch, mypadc, eol, ctlq, myctlq, sstate, *hlptxt; extern char filnam[], sndpkt[], recpkt[], data[], srvcmd[], *srvptr, stchr, mystch; extern char *cmarg, *cmarg2, **cmlist; long zchki(); char *strcpy();"",k); if (i < 1) return(1); /* No characters, return. */ if (pktlog) zsoutl(ZPFILE,recpkt); /* Log any we got, if logging. */ if (k > maxt) return(1); /* If too many tries, give up. */ tlci += i; /* All OK, Count the characters. */ flci += i; return(0); } ttinl(recpkt,RBUFL,timint,e); /* Get them all at once */ if (i < 0) k = 1; } recpkt[i+1] = '\0'; /* Terminate near end of packet */ debug(F111,"inlin",recpkt,i); /* Debug report... */ debug(F101," timeouts", /* Variables local to this module */ static char *memptr; /* Pointer for memory strings */ static char cmdstr[100]; /* Unix system command string */ static int sndsrc; /* Flag for where to send from: */ /* -1: name in cmdata */ /* 0: stdin */ /* >0: list in cmlist */ static int memstr, /* Flag for input from memory string */ t, /* Current character */ next; /* Next character */ /* E N C S T R -- Encode a string from memory. */ /* Call this ins /* quote it if doing repeat counts. */ if ((ebqflg) && (a7 == ebq)) /* Prefix the 8th bit prefix */ data[size++] = myctlq; /* if doing 8th-bit prefixes */ data[size++] = a; /* Finally, insert the character */ data[size] = '\0'; /* itself, and mark the end. */ } /* D E C O D E -- Kermit packet decoding procedure */ /* Call with string to be decoded and an output function. */ /* Returns 0 on success, -1 on failure (e.g. disk full). */ decode(buf,fn) char *buf; int (*fn)(); he packet, filling the packet optimally. Uses global variables: t -- current character. next -- next character. data -- the packet data buffer. size -- number of characters in the data buffer. Returns the size as value of the function, and also sets global size, and fills (and null-terminates) the global data array. Before calling getpkt the first time for a given source (file or string), set the variable 'next' to -1. */ getpkt(maxsize) int maxsize; { /* Fill one packet buffer */ int i{ unsigned int a, a7, b8; /* Low order 7 bits, and the 8th bit */ rpt = 0; /* Initialize repeat count. */ while ((a = *buf++) != '\0') { if (rptflg) { /* Repeat processing? */ if (a == rptq) { /* Yes, got a repeat prefix? */ rpt = unchar(*buf++); /* Yes, get the repeat count, */ a = *buf++; /* and get the prefixed character. */ } } b8 = 0; /* Check high order "8th" bit */ if (ebqflg) { /* 8th-bit prefixing? */ if (a == ebq) { /* Yes, got an 8th-bit prefix? ; /* Loop index. */ static char leftover[6] = { '\0', '\0', '\0', '\0', '\0', '\0' }; debug(F101,"getpkt, entering with next","",next); debug(F101," t","",t); if (next < 0) { /* If first time through, */ t = getch(); /* get first character of file, */ *leftover = '\0'; /* discard any interrupted leftovers. */ } /* Do any leftovers */ for (size = 0; (data[size] = leftover[size]) != '\0'; size++) ; *leftover = '\0'; /* Now fill up the rest of the packet*/ b8 = 0200; /* Yes, remember this, */ a = *buf++; /* and get the prefixed character. */ } } if (a == ctlq) { /* If control prefix, */ a = *buf++; /* get its operand. */ a7 = a & 0177; /* Only look at low 7 bits. */ if ((a7 >= 0100 && a7 <= 0137) || a7 == '?') /* Uncontrollify */ a = ctl(a); /* if in control range. */ } a |= b8; /* OR in the 8th bit */ if (rpt == 0) rpt = 1; /* If no repeats, then one */ #ifdef NLCHAR if (!binary) { /* If in text mode, */ . */ rpt = 0; /* Clear out any old repeat count. */ while(t >= 0) { /* Until EOF... */ next = getch(); /* Get next character for lookahead. */ osize = size; /* Remember current position. */ encode(t); /* Encode the current character. */ t = next; /* Next is now current. */ next = 0; /* No more next. */ if (size == maxsize) { /* If the packet is exactly full, */ debug(F101,"getpkt exact fit","",size); return(size); /* and return. */ } if (siz rpt = 0; } } else if (rpt == 1) { /* Run broken, only 2? */ rpt = 0; /* Yes, reset repeat flag & count. */ encode(a); /* Do the character twice. */ if (size <= maxsize) osize = size; rpt = 0; encode(a); return; } else if (rpt > 1) { /* More than two */ data[size++] = rptq; /* Insert the repeat prefix */ data[size++] = tochar(++rpt); /* and count. */ rpt = 0; /* Reset repeat counter. */ } } a if (a == CR) continue; /* discard carriage returns, */ if (a == LF) a = NLCHAR; /* convert LF to system's newline. */ } #endif for (; rpt > 0; rpt--) { /* Output the char RPT times */ ffc++, tfc++; /* Count the character */ if ((*fn)(a) < 0) return(-1); /* Send it to the output function. */ } } return(0); } /* Output functions passed to 'decode': */ putsrv(c) char c; { /* Put character in server command buffer */ *srvptr++ = c; *srvptr = '\0'; /* Make su7 = a & 0177; /* Isolate ASCII part */ b8 = a & 0200; /* and 8th (parity) bit. */ if (ebqflg && b8) { /* Do 8th bit prefix if necessary. */ data[size++] = ebq; a = a7; } if ((a7 < SP) || (a7==DEL)) { /* Do control prefix if necessary */ data[size++] = myctlq; a = ctl(a); } if (a7 == myctlq) /* Prefix the control prefix */ data[size++] = myctlq; if ((rptflg) && (a7 == rptq)) /* If it's the repeat prefix, */ data[size++] = myctlq; re buffer is null-terminated */ return(0); } puttrm(c) char c; { /* Output character to console. */ conoc(c); return(0); } putfil(c) char c; { /* Output char to file. */ if (zchout(ZOFILE,c) < 0) { czseen = 1; /* If write error... */ debug(F101,"putfil zchout write error, setting czseen","",1); return(-1); } return(0); } /* G E T P K T -- Fill a packet data field */ /* Gets characters from the current source -- file or memory string. Encodes the data into the Macintosh, etc, that use a single character (NLCHAR, defined in ckcdeb.h) to separate lines in text files, and when in text/ascii mode (binary == 0), this function maps the newline character to CRLF. If NLCHAR is not defined, then this mapping is not done, even in text mode. */ getch() { /* Get next character */ int x; CHAR a; /* The character to return. */ static int b = 0; /* A character to remember. */ if (b > 0) { /* Do we have a LF saved? */ b = 0; /* Yes, return tp,0l); /* Make transaction log entry */ debug(F101,"sinit: sndsrc","",sndsrc); if (sndsrc < 0) { /* Must expand from 'send' command */ nfils = zxpand(cmarg); /* Look up literal name. */ if (nfils < 0) { screen(SCR_EM,0,0l,"Too many files"); return(0); } else if (nfils == 0) { /* If none found, */ char xname[100]; /* convert the name. */ zrtol(cmarg,xname); nfils = zxpand(xname); /* Look it up again. */ } if (nfils < 1) { /* If no match, report error. */ hat. */ return(LF); } if (memstr) /* Try to get the next character */ x = ((a = *memptr++) == '\0'); /* from the appropriate source, */ else /* memory or the current file. */ x = (zchin(ZIFILE,&a) == -1); if (x) return(-1); /* No more, return -1 for EOF. */ else { /* Otherwise, read the next char. */ ffc++, tfc++; /* Count it. */ #ifdef NLCHAR if (!binary && (a == NLCHAR)) { /* If nl and we must do nl-CRLF */ b = 1; /* mapping, remember a linefeed, if (server) errpkt("File not found"); else screen(SCR_EM,0,0l,"File not found"); return(0); } x = gnfile(); /* Position to first file. */ if (x < 1) { if (!server) screen(SCR_EM,0,0l,"No readable file to send"); else errpkt("No readable file to send"); return(0); } } else if (sndsrc > 0) { /* Command line arglist -- */ x = gnfile(); /* Get the first file from it. */ if (x < 1) return(0); /* (if any) */ } else if (sndsrc == 0) { */ return(CR); /* and return a carriage return. */ } else return(a); /* General case, return the char. */ #else return(a); #endif } } /* C A N N E D -- Check if current file transfer cancelled */ canned(buf) char *buf; { if (*buf == 'X') cxseen = 1; if (*buf == 'Z') czseen = 1; debug(F101,"canned: cxseen","",cxseen); debug(F101," czseen","",czseen); return((czseen || cxseen) ? 1 : 0); } /* T I N I T -- Initialize a transaction */ tinit() { xflg = 0; /* stdin or memory always exist... */ if ((cmarg2 != NULL) && (*cmarg2)) { strcpy(filnam,cmarg2); /* If F packet, filnam is used */ cmarg2 = ""; /* if provided, */ } else /* otherwise */ strcpy(filnam,"stdin"); /* just use this. */ tlog(F110,"Sending from",cmdstr,0l); /* If X packet, cmdstr is used. */ } debug(F101,"sinit: nfils","",nfils); debug(F110," filnam",filnam,0); debug(F110," cmdstr",cmdstr,0); ttflui(); /* Flush input buffer. */ x = rpar(d /* Reset x-packet flag */ memstr = 0; /* Reset memory-string flag */ memptr = NULL; /* and pointer */ bctu = 1; /* Reset block check type to 1 */ filcnt = 0; /* Reset file counter */ tfc = tlci = tlco = 0; /* Reset character counters */ prvpkt = -1; /* Reset packet number */ pktnum = 0; cxseen = czseen = 0; /* Reset interrupt flags */ *filnam = '\0'; /* Clear file name */ if (server) { /* If acting as server, */ timint = 30; /* Use 30 second tata); /* Send a Send-Init packet. */ if (!local && !server) sleep(delay); spack('S',pktnum,x,data); return(1); } sipkt() { int x; ttflui(); /* Flush pending input. */ x = rpar(data); /* Send an I-Packet. */ spack('I',pktnum,x,data); } /* R C V F I L -- Receive a file */ rcvfil() { int x; ffc = flci = flco = 0; /* Init per-file counters */ srvptr = srvcmd; /* Decode file name from packet. */ decode(data,putsrv); if (*srvcmd == '\0') *srvcmd = 'e > maxsize) { /* If too big, save some for next. */ for (i = 0; (leftover[i] = data[osize+i]) != '\0'; i++) ; debug(F111,"getpkt leftover",leftover,size); debug(F101," osize","",osize); size = osize; /* Return truncated packet. */ data[size] = '\0'; return(size); } } debug(F101,"getpkt eof/eot","",size); return(size); /* Return any partial final buffer. */ } /* G E T C H -- Get the next character from file (or pipe). */ /* On systems like Unix, timeout, */ nack(); /* Send first NAK */ } } /* R I N I T -- Respond to S packet */ rinit(d) char *d; { char *tp; ztime(&tp); tlog(F110,"Transaction begins",tp,0l); /* Make transaction log entry */ tfc = tlci = tlco = 0; spar(d); rpar(d); ack1(d); } /* S I N I T -- Make sure file exists, then send Send-Init packet */ sinit() { int x; char *tp; sndsrc = nfils; /* Where to look for files to send */ ztime(&tp); tlog(F110,"Transaction begins",tx'; /* Watch out for null F packet. */ screen(SCR_FN,0,0l,srvcmd); /* Put it on screen */ tlog(F110,"Receiving",srvcmd,0l); /* Transaction log entry */ if (cmarg2 != NULL) { /* Check for alternate name */ if (*cmarg2 != '\0') { strcpy(srvcmd,cmarg2); /* Got one, use it. */ *cmarg2 = '\0'; } } x = openo(srvcmd,filnam); /* Try to open it */ if (x) { tlog(F110," as",filnam,0l); screen(SCR_AN,0,0l,filnam); intmsg(++filcnt); } else { } tlog(F110,"Sending",filnam,0l); /* Transaction log entry */ tlog(F110," as",pktnam,0l); next = -1; /* Init file character lookahead. */ return(1); } /* Send an X Packet -- Like SFILE, but with Text rather than File header */ sxpack() { /* Send an X packet */ debug(F110,"sxpack",cmdstr,0); encstr(cmdstr); /* Encode any data. */ rpt = flci = flco = ffc = 0; /* Init counters, etc. */ next = -1; /* Init file character lookahead. */ nxtpkt(&pktnum); /* Inc tlog(F110,"Failure to open",filnam,0l); screen(SCR_EM,0,0l,"Can't open file"); } return(x); /* Pass on return code from openo */ } /* R E O F -- Receive End Of File */ reof() { if (cxseen == 0) cxseen = (*data == 'D'); clsof(); if (cxseen || czseen) { tlog(F100," *** Discarding","",0l); } else { tlog(F100," end of file","",0l); tlog(F101," file characters ","",ffc); tlog(F101," communication line in ","",flci); tlog(F101," communication line out ",rement the packet number */ spack('X',pktnum,size,data); /* No incrementing pktnum */ screen(SCR_XD,'X',(long)pktnum,cmdstr); /* Update screen. */ intmsg(++filcnt); tlog(F110,"Sending from:",cmdstr,0l); return(1); } /* S D A T A -- Send a data packet */ sdata() { int len; if (cxseen || czseen) return(0); /* If interrupted, done. */ if ((len = getpkt(spsiz-chklen-3)) == 0) return(0); /* If no data, done. */ nxtpkt(&pktnum); /* Increment the packet number */ spac"",flco); } } /* R E O T -- Receive End Of Transaction */ reot() { char *tp; cxseen = czseen = 0; ztime(&tp); tlog(F110,"End of transaction",tp,0l); if (filcnt > 1) { tlog(F101," files","",filcnt); tlog(F101," total file characters ","",tfc); tlog(F101," communication line in ","",tlci); tlog(F101," communication line out ","",tlco); } } /* S F I L E -- Send File header packet for global "filnam" */ sfile() { char pktnam[100]; /* Local copy of name */ k('D',pktnum,len,data); /* Send the packet */ return(1); } /* S E O F -- Send an End-Of-File packet */ seof() { nxtpkt(&pktnum); /* Increment the packet number */ if (czseen || cxseen) { spack('Z',pktnum,1,"D"); cxseen = 0; /* Clear this now */ tlog(F100," *** interrupted, sending discard request","",0l); } else { spack('Z',pktnum,0,""); tlog(F100," end of file","",0l); tlog(F101," file characters ","",ffc); tlog(F101," communication line in ","",flci); tlog(F101," if (*cmarg2 != '\0') { /* If we have a send-as name, */ strcpy(pktnam,cmarg2); /* copy it literally, */ cmarg2 = ""; /* and blank it out for next time. */ } else { /* Otherwise use actual file name: */ if (fncnv) { /* If converting names, */ zltor(filnam,pktnam); /* convert it to common form, */ } else { /* otherwise, */ strcpy(pktnam,filnam); /* copy it literally. */ } } debug(F110,"sfile",filnam,0); debug(F110," pktnam",pktnam,0); if (openi(filnam) communication line out ","",flco); } } /* S E O T -- Send an End-Of-Transaction packet */ seot() { char *tp; nxtpkt(&pktnum); /* Increment the packet number */ spack('B',pktnum,0,""); cxseen = czseen = 0; ztime(&tp); tlog(F110,"End of transaction",tp,0l); if (filcnt > 1) { tlog(F101," files","",filcnt); tlog(F101," total file characters ","",tfc); tlog(F101," communication line in ","",tlci); tlog(F101," communication line out ","",tlco); } } /* R P== 0) /* Try to open the file */ return(0); flci = flco = ffc = 0; /* OK, Init counters, etc. */ encstr(pktnam); /* Encode the name. */ nxtpkt(&pktnum); /* Increment the packet number */ ttflui(); /* Clear pending input */ spack('F',pktnum,size,data); /* Send the F packet */ if (displa) { screen(SCR_FN,'F',(long)pktnum,filnam); /* Update screen */ screen(SCR_AN,0,0l,pktnam); screen(SCR_FS,0,(long)fsize,""); intmsg(++filcnt); /* Count file, give interrupt msg */ A R -- Fill the data array with my send-init parameters */ rpar(data) char data[]; { data[0] = tochar(rpsiz); /* Biggest packet I can receive */ data[1] = tochar(rtimo); /* When I want to be timed out */ data[2] = tochar(mypadn); /* How much padding I need (none) */ data[3] = ctl(mypadc); /* Padding character I want */ data[4] = tochar(eol); /* End-Of-Line character I want */ data[5] = CTLQ; /* Control-Quote character I send */ if (parity || ebqflg) { /* 8-bit quoting debug(F101," ebqflg","",ebqflg); debug(F101," chklen","",chklen); debug(F101," rptq ","",rptq); debug(F101," rptflg","",rptflg); } /* G N F I L E -- Get the next file name from a file group. */ /* Returns 1 if there's a next file, 0 otherwise */ gnfile() { int x; long y; /* If file group interruption (C-Z) occured, fail. */ debug(F101,"gnfile: czseen","",czseen); if (czseen) { tlog(F100,"Transaction cancelled","",0l); return(0); } /* If input was stdin or char xname[100], *xp; if (stdouf) /* Receiving to stdout? */ return(zopeno(ZSTDIO,"")); debug(F110,"openo: name",name,0); if (cxseen || czseen) { /* If interrupted, get out before */ debug(F100," open cancelled","",0); /* destroying existing file. */ return(1); /* Pretend to succeed. */ } xp = xname; /* OK to proceed. */ if (fncnv) /* If desired, */ zrtol(name,xp); /* convert name to local form */ else /* otherwise, */ strcpy(xname,name); /**/ data[6] = '&'; ebqflg = 1; } else { data[6] = 'Y'; } data[7] = bctr + '0'; /* Block check type */ data[8] = MYRPTQ; /* Do repeat counts */ data[9] = '\0'; return(9); /* Return the length. */ } /* S P A R -- Get the other system's Send-Init parameters. */ spar(data) char data[]; { int len, x; len = strlen(data); /* Number of fields */ spsiz = (len-- > 0) ? unchar(data[0]) : DSPSIZ; /* Packet size */ if (spsiz < 10) spsiz = DSPSIZ; xmemory string, there is no next file. */ if (sndsrc == 0) return(0); /* If file list comes from command line args, get the next list element. */ y = -1; while (y < 0) { /* Keep trying till we get one... */ if (sndsrc > 0) { if (nfils-- > 0) { strcpy(filnam,*cmlist++); debug(F111,"gnfile: cmlist filnam",filnam,nfils); } else { *filnam = '\0'; debug(F101,"gnfile cmlist: nfils","",nfils); return(0); } } /* Otherwise, step to next element of internal wildcard expan = (len-- > 0) ? unchar(data[1]) : DMYTIM; /* Timeout */ if (!timef) { /* Only use if not overridden */ timint = x; if (timint < 0) timint = DMYTIM; } npad = 0; padch = '\0'; /* Padding */ if (len-- > 0) { npad = unchar(data[2]); if (len-- > 0) padch = ctl(data[3]); else padch = 0; } eol = (len-- > 0) ? unchar(data[4]) : '\r'; /* Terminator */ if ((eol < 2) || (eol > 037)) eol = '\r'; ctlq = (len-- > 0) ? data[5] : CTLQ; /* Control prefix */sion list. */ if (sndsrc < 0) { x = znext(filnam); debug(F111,"gnfile znext: filnam",filnam,x); if (x == 0) return(0); } /* Get here with a filename. */ y = zchki(filnam); /* Check if file readable */ if (y < 0) { debug(F110,"gnfile skipping:",filnam,0); tlog(F111,filnam,"not sent, reason",(long)y); screen(SCR_ST,ST_SKIP,0l,filnam); } else fsize = y; } return(1); } /* O P E N I -- Open an existing file for input */ openi(name) char *name; { int if (len-- > 0) { ebq = data[6]; if ((ebq > 040 && ebq < 0100) || (ebq > 0140 && ebq < 0177)) { ebqflg = 1; } else if ((parity || ebqflg) && (ebq == 'Y')) { ebqflg = 1; ebq = '&'; } else if (ebq == 'N') { ebqflg = 0; } else ebqflg = 0; } else ebqflg = 0; chklen = 1; /* Block check */ if (len-- > 0) { chklen = data[7] - '0'; if ((chklen < 1) || (chklen > 3)) chklen = 1; } bctr = chklen; if (len-- > 0) { /* Repeat prefix */ rp x, filno; if (memstr) return(1); /* Just return if file is memory. */ debug(F110,"openi",name,0); debug(F101," sndsrc","",sndsrc); filno = (sndsrc == 0) ? ZSTDIO : ZIFILE; /* ... */ debug(F101," file number","",filno); if (zopeni(filno,name)) { /* Otherwise, try to open it. */ debug(F110," ok",name,0); return(1); } else { /* If not found, */ char xname[100]; /* convert the name */ zrtol(name,xname); /* to local form and then */ x = zopeni(filno,xname); /* tq = data[8]; rptflg = ((rptq > 040 && rptq < 0100) || (rptq > 0140 && rptq < 0177)); } else rptflg = 0; if (deblog) sdebu(len); } /* S D E B U -- Record spar results in debugging log */ sdebu(len) int len; { debug(F111,"spar: data",data,len); debug(F101," spsiz ","",spsiz); debug(F101," timint","",timint); debug(F101," npad ","",npad); debug(F101," padch ","",padch); debug(F101," eol ","",eol); debug(F101," ctlq ","",ctlq); debug(F101," ebq ","",ebq);try opening it again. */ debug(F101," zopeni","",x); if (x) { debug(F110," ok",xname,0); return(1); /* It worked. */ } else { screen(SCR_EM,0,0l,"Can't open file"); /* It didn't work. */ tlog(F110,xname,"could not be opened",0l); debug(F110," openi failed",xname,0); return(0); } } } /* O P E N O -- Open a new file for output. */ /* Returns actual name under which the file was opened in string 'name2'. */ openo(name,name2) char *name, *name2; { and current file name. */ } /* S N D H L P -- Routine to send builtin help */ sndhlp() { nfils = 0; /* No files, no lists. */ xflg = 1; /* Flag we must send X packet. */ strcpy(cmdstr,"help text"); /* Data for X packet. */ next = -1; /* Init getch lookahead */ memstr = 1; /* Just set the flag. */ memptr = hlptxt; /* And the pointer. */ return(sinit()); } /* C W D -- Change current working directory */ /* String passed has first byte as length of di/* 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 Nulrectory name, rest of string is name. Fails if can't connect, else ACKs (with name) and succeeds. */ cwd(vdir) char *vdir; { vdir[unchar(*vdir) + 1] = '\0'; /* End with a null */ if (zchdir(vdir+1)) { encstr(vdir+1); ack1(data); tlog(F110,"Changed directory to",vdir+1,0l); return(1); } else { tlog(F110,"Failed to change directory to",vdir+1,0l); return(0); } } /* S Y S C M D -- Do a system command */ /* Command string is formed by concatenating the two arguments. */ syscl */ #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) */ /* Kermit parameters and defaults */ #define MAXPACK 94 /* Maximum packet size */ #define RBUFL 200 /* Receive buffer l use it literally */ debug(F110,"openo: xname",xname,0); if (warn) { /* File collision avoidance? */ if (zchki(xname) != -1) { /* Yes, file exists? */ znewn(xname,&xp); /* Yes, make new name. */ strcpy(xname,xp); debug(F110," exists, new name ",xname,0); } } if (zopeno(ZOFILE,xname) == 0) { /* Try to open the file */ debug(F110,"openo failed",xname,0); tlog(F110,"Failure to open",xname,0l); return(0); } else { strcpy(name2,xname); debug(F110,"openo ok, md(prefix,suffix) char *prefix, *suffix; { char *cp; if (prefix == NULL || *prefix == '\0') return(0); for (cp = cmdstr; *prefix != '\0'; *cp++ = *prefix++) ; while (*cp++ = *suffix++) ; debug(F110,"syscmd",cmdstr,0); if (zopeni(ZSYSFN,cmdstr) > 0) { debug(F100,"syscmd zopeni ok",cmdstr,0); nfils = sndsrc = 0; /* Flag that input from stdin */ xflg = hcflg = 1; /* And special flags for pipe */ return (sinit()); /* Send S packet */ } else { debug(F100,"syscmd zopeni failname2",name2,0); return(1); } } /* O P E N T -- Open the terminal for output, in place of a file */ opent() { ffc = tfc = 0; return(zopeno(ZCTERM,"")); } /* C L S I F -- Close the current input file. */ clsif() { if (memstr) { /* If input was memory string, */ memstr = 0; /* indicate no more. */ } else zclose(ZIFILE); /* else close input file. */ if (czseen || cxseen) screen(SCR_ST,ST_DISC,0l,""); else screen(SCR_ST,ST_OK,0l,""); cxseen = hcflged",cmdstr,0); return(0); } } ffix; { char *cp; if (prefix == NULL || *prefix == '\0') return(0); for (cp = cmdstr; *prefix != '\0'; *cp++ = *prefix++) ; while (*cp++ = *suffix++) ; debug(F110,"syscmd",cmdstr,0); if (zopeni(ZSYSFN,cmdstr) > 0) { debug(F100,"syscmd zopeni ok",cmdstr,0); nfils = sndsrc = 0; /* Flag that input from stdin */ xflg = hcflg = 1; /* And special flags for pipe */ return (sinit()); /* Send S packet */ } else { debug(F100,"syscmd zopeni fail = 0; /* Reset flags, */ *filnam = '\0'; /* and current file name */ } /* C L S O F -- Close an output file. */ clsof() { zclose(ZOFILE); /* Close it. */ if (czseen || cxseen) { if (*filnam) zdelet(filnam); /* Delete it if interrupted. */ debug(F100,"Discarded","",0); tlog(F100,"Discarded","",0l); screen(SCR_ST,ST_DISC,0l,""); } else { debug(F100,"Closed","",0); screen(SCR_ST,ST_OK,0l,""); } cxseen = 0; /* Reset file interruption flag */ *filnam = '\0'; /*./usr/opt/src/kermit/ckcker.h 644 0 3 7101 5555215353 11264 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 char *versio = "C-Kermit, 4C(053)+1 21 Jun 85"; /* Edit History * +1 21 Jun 85 MM Added initial call to hack_vms_open_console() * so error messages can be ouput while parsing * command arguments. Frank will clean this up! */ /* C K C M A I -- C-Kermit Main program */ /* Authors: Frank da Cruz, Bill Catchings, Jeff Damens; Columbia University Center for Computing Activities, 1984-85. Copyright (C) 1985, Trustees of Columbia University in the City of New York. Permission is granted to any /* 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 *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/ #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 unchar(ch) ((ch) - SP ) /* Character to number */ #define ctl(ch) ((ch) ^ 64 ) /* Controllify/Uncontro following people for their contributions over the years: Larry Afrin, Clemson U Charles Brooks, EDN Bob Cattani & Chris Maio, Columbia CS Dept Alan Crosswell, CUCCA Carl Fongheiser, CWRU Yekta Gursel, MIT Jim Guyton, Rand Corp Stan Hanks, Rice U. Ken Harrenstein, SRI Steve Hemminger, Tektronix Randy Huntziger, NLM Martin Minow, DEC Tony Movshon, NYU Ken Poulton, HP Labs Frank Prindle, NADC Stew Rubenstein, Harvard Dan Schullman, DEC Bradley Smith, UCLAength */ #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 llify */ #define unpar(ch) ((ch) & 127) /* Clear parity bit */ * 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 unchar(ch) ((ch) - SP ) /* Character to number */ #define ctl(ch) ((ch) ^ 64 ) /* Controllify/Uncontro 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 ./usr/opt/src/kermit/ckcmai.c 644 0 3 20317 5555215353 11270 :\n\ \n\ GET filespec REMOTE CWD [directory] REMOTE SPACE [directory]\n\ SEND filespec REMOTE DIRECTORY [filespec] REMOTE HOST command\n\ FINISH REMOTE DELETE filespec REMOTE WHO [user]\n\ REMOTE HELP REMOTE TYPE filespec BYE\n\ \n\0"; #endif 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 /* 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 reconnect.\n\ \r\n\0"; /* Declarations for Send-Init Parameters */ int spsiz = DSPSIZ, /* Biggest packet size we can send */ rpsiz = DRPSIZ, /* Biggest we want to receive */ 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 */ chklen = 1, /* Length of block check */ bctr */ delay = DDELAY, /* Initial delay before sending */ mdmtyp = 0; /* Modem type (initially none) */ /* 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 */ /* Flags */= 1, /* Block check type requested */ bctu = 1, /* Block check type used */ ebq = MYEBQ, /* 8th bit prefix */ ebqflg = 0, /* 8th-bit quoting flag */ rpt = 0, /* Repeat count */ rptq = MYRPTQ, /* Repeat prefix */ rptflg = 0, /* Repeat processing flag */ capas = 0; /* Capabilities */ char padch = MYPADC, /* Padding character to send */ mypadc = MYPADC, /* Padding character to ask for */ seol = MYEOL, /* End-Of-Line character to send */ eol 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 */ warn = 0, /*= 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 */ size, /* Current size of output pkt data */ osize, /* Previous output packet data size */ maxsize, /* Max size for building data field */ spktl 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 */ /* Variables passed from command parser to protocol module */ char parser(); /* The parser itself */ char sstate = 0; /* Starting state for automaton Dave Tweten, AMES-NAS Walter Underwood, Ford Aerospace Pieter Van Der Linden, Centre Mondial (Paris) Mark Vasoll & Gregg Wonderly, Oklahoma State University Lauren Weinstein, Vortex and many others. */ #include "ckcker.h" #include "ckcdeb.h" /* Text message definitions.. each should be 256 chars long, or less. */ #ifdef MAC char *hlptxt = "C-Kermit Server Commands:\n\ \n\ GET filespec, SEND filespec, FINISH, REMOTE HELP\n\ \n\0"; #else char *hlptxt = "C-Kermit Server Commands Supported; /* Length packet being sent */ char sndpkt[MAXPACK*2], /* Entire packet being sent */ recpkt[RBUFL], /* Packet most recently received */ data[MAXPACK+4], /* Packet data buffer */ srvcmd[MAXPACK*2], /* Where to decode server command */ *srvptr, /* Pointer to above */ mystch = SOH, /* Outbound packet-start character */ stchr = SOH; /* Incoming packet-start character */ /* File-related variables */ char filnam[50]; /* Name of current file. */ int nfils; */ 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 * /* WARNING -- This C source program generated by Wart preprocessor. */ /* Do not edit this file; edit the Wart-format source file instead, */ /* and then run it through Wart to produce a new C source file. */ /* Wart Version Info: */ char *wartv = "Wart Version 1A(003) 27 May 85"; char *protv = "C-Kermit Protocol Module 4C(026), 12 Jun 85"; /* -*-C-*- */ /* C K C P R O -- C-Kermit Protocol Module, in Wart preprocessor notation. */ /* Author: Frank da Cruz (SY.FDC@CU20B), Columbia University Cente/ main(argc,argv) int argc; char **argv; { char *strcpy(); #ifdef vms hack_vms_open_console(); /* Make sure error message routines */ /* have somewhere to write */ #endif /* 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 inir 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. */ #include "ckcdeb.h" #include "ckcker.h" /* Note -- This file may also be preprocessed by the Unix Lex program, but you must indent the above #include statement before using Lex, and then restore it totial parity, */ flow = dfflow; /* and flow control. */ /* 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 the left margin in the resulting C program before compilation. Also, the invocation of the "wart()" function below must be replaced by an invocation of the "yylex()" function. It might also be necessary to remove comments in the %%...%% section. */ /* State definitions for Wart (or Lex) */ #define ipkt 1 #define rfile 2 #define rdata 3 #define ssinit 4 #define ssdata 5 #define sseof 6 #define sseot 7 #define serve 8 #define generic 9 #define get 10 #define rgen 11 /* External C-Kermit variable decla, enter interactive parser */ cmdini(); /* Initialize command parser */ while(sstate = parser()) { /* Loop getting commands. */ if (sstate) proto(); /* Enter protocol if requested. */ } } 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 linerations */ extern char sstate, *versio, *srvtxt, *cmarg, *cmarg2; extern char data[], filnam[], srvcmd[], ttname[], *srvptr; extern int pktnum, timint, nfils, image, hcflg, xflg, speed, flow, mdmtyp; extern int prvpkt, cxseen, czseen, server, local, displa, bctu, bctr, quiet; extern int putsrv(), puttrm(), putfil(), errpkt(); extern char *DIRCMD, *DELCMD, *TYPCMD, *SPACMD, *SPACM2, *WHOCMD; /* Local variables */ static char vstate = 0; /* Saved State */ static char vcmd = 0; /* Sa./usr/opt/src/kermit/ckcpro.c 644 0 3 34106 5555215353 11323 ved Command */ static int x; /* General-purpose integer */ /* Macros - Note, BEGIN is predefined by Wart (and Lex) */ #define SERVE tinit(); BEGIN serve #define RESUME if (server) { SERVE; } else return #define BEGIN state = int state = 0; wart() { int c,actno; extern int tbl[]; while (1) { c = input(); if ((actno = tbl[c + state*128]) != -1) switch(actno) { case 1: { tinit(); /* Do Send command */ if (sinit()) BEGIN ssinit; else RESUME; } break; case 2: { tinn(SCR_TC,0,0l,""); return(zkself()); } break; case 21: { if (sndhlp()) BEGIN ssinit; else { errpkt("Can't send help"); SERVE; } } break; case 22: { if (syscmd(TYPCMD,srvcmd+2)) BEGIN ssinit; else { errpkt("Can't type file"); SERVE; } } break; case 23: { x = *(srvcmd+1); /* Disk Usage query */ x = ((x == '\0') || (x == unchar(0))); x = (x ? syscmd(SPACMD,"") : syscmd(SPACM2,srvcmd+2)); if (x) BEGIN ssinit; else { errpkt("Can't check space"); SERVE; }} break; ca, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 10, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 9, 37, 37, 37, 37, 37, 37, 37, 7, 37, 4, 37, 37, 37, 5, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 3, 1, 37, 37, 2, 37, 6, 37, 37, 37, 37, 37, 37, 37, -1, 37, 37, 37, it(); sleep(1); nack(); BEGIN get; } break; case 3: { tinit(); vstate = get; vcmd = 0; sipkt(); BEGIN ipkt; } break; case 4: { tinit(); vstate = rgen; vcmd = 'C'; sipkt(); BEGIN ipkt; } break; case 5: { tinit(); vstate = rgen; vcmd = 'G'; sipkt(); BEGIN ipkt; } break; case 6: { sleep(1); SERVE; } break; case 7: { errpkt("User cancelled transaction"); /* Tell other side what's going on */ x = quiet; quiet = 1; /* Close files silently */ clsif(); clsof(); quiet = x; return(0); } break; case se 24: { if (syscmd(WHOCMD,srvcmd+2)) BEGIN ssinit; else { errpkt("Can't do who command"); SERVE; } } break; case 25: { errpkt("Unimplemented generic server function"); SERVE; } break; case 26: { decode(data,puttrm); RESUME; } break; case 27: { if (rcvfil()) { ack(); BEGIN rdata; } /* A file is coming */ else { errpkt("Can't open file"); RESUME; } } break; case 28: { opent(); ack(); BEGIN rdata; } break; case 29: { ack(); reot(); RESUME; } break; case 30: { if (cxseen) ack1("X"); /* Got data. */8: { rinit(data); bctu = bctr; BEGIN rfile; } break; case 9: { spar(data); /* Get ack for I-packet */ if (vcmd) { scmd(vcmd,cmarg); vcmd = 0; } if (vstate == get) srinit(); BEGIN vstate; } break; case 10: { if (vcmd) scmd(vcmd,cmarg); /* Get E for I-packet (ignore) */ vcmd = 0; if (vstate == get) srinit(); BEGIN vstate; } break; case 11: { srvptr = srvcmd; decode(data,putsrv); /* Get Receive-Init */ cmarg = srvcmd; nfils = -1; if (sinit()) BEGIN ssinit; else { else if (czseen) ack1("Z"); else ack(); decode(data,putfil); } break; case 31: { ack(); reof(); BEGIN rfile; } break; case 32: { int x; char *s; /* Got ACK to Send-Init */ spar(data); bctu = bctr; if (xflg) { x = sxpack(); s = "Can't execute command"; } else { x = sfile(); s = "Can't open file"; } if (x) BEGIN ssdata; else { errpkt(s); RESUME; } } break; case 33: { if (canned(data) || !sdata()) { /* Got ACK to data */ clsif(); seof(); SERVE; } } break; case 12: { spar(data); rpar(data); ack1(data); /* Get Init Parameters */ pktnum = 0; prvpkt = -1; } break; case 13: { srvptr = srvcmd; decode(data,putsrv); /* Get & decode command. */ putsrv('\0'); putsrv('\0'); sstate = srvcmd[0]; BEGIN generic; } break; case 14: { srvptr = srvcmd; /* Get command for shell */ decode(data,putsrv); putsrv('\0'); if (syscmd(srvcmd,"")) BEGIN ssinit; else { errpkt("Can't do system command"); SERVE; } } break; case 15: { errpkt(BEGIN sseof; } } break; case 34: { if (gnfile() > 0) { /* Got ACK to EOF, get next file */ if (sfile()) BEGIN ssdata; else { errpkt("Can't open file") ; RESUME; } } else { /* If no next file, EOT */ seot(); BEGIN sseot; } } break; case 35: { RESUME; } break; case 36: { ermsg(data); /* Error packet, issue message */ x = quiet; quiet = 1; /* Close files silently */ clsif(); clsof(); quiet = x; RESUME; } break; case 37: { nack(); } break; } } } int tbl[] = { -1, 37, 37, 3"Unimplemented server function"); SERVE; } break; case 16: { if (!cwd(srvcmd+1)) errpkt("Can't change directory"); /* CWD */ SERVE; } break; case 17: { if (syscmd(DIRCMD,srvcmd+2)) BEGIN ssinit; /* Directory */ else { errpkt("Can't list directory"); SERVE; } } break; case 18: { if (syscmd(DELCMD,srvcmd+2)) BEGIN ssinit; /* Erase */ else { errpkt("Can't remove file"); SERVE; } } break; case 19: { ack(); screen(SCR_TC,0,0l,""); return(0); } break; case 20: { ack(); ttres(); scree7, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 7, 37, 4, 37, 37, 37, 5, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 3, 1, 37, 37, 2, 37, 6, 37, 37, 37, 37, 37, 37, 37, -1, 37, 37, 377, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 33, 37, 37, 37, 37, 37, 37, 37, 7, 37, 4, 37, 37, 37, 5, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 3, 1, 37, 37, 2, 37, 6, 37, 37, 37, 37, 37, 37, 37, -1, 37, 37, 37, 377, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 8, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 7, 37, 4, 37, 37, 37, 5, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 3, 1, 37, 37, 2, 37, 6, 37, 37, 37, 37, 37, 37, 37, 0, 37, 37, 37, 37, 37, , 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 34, 37, 37, 37, 37, 37, 37, 37, 7, 37, 4, 37, 37, 37, 5, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 3, 1, 37, 37, 2, 37, 6, 37, 37, 37, 37, 37, 37, 37, -1, 37, 37, 37, 37,37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 27, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 8, 37, 37, 37, 37, 28, 26, 37, 37, 37, 37, 37, 37, 37, 7, 37, 4, 37, 37, 37, 5, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 3, 1, 37, 37, 2, 37, 6, 37, 37, 37, 37, 37, 37, 37, }; /* P R O T O -- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 29, 37, 37, 36, 27, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 28, 37, 37, 37, 37, 37, 37, 37, 37, 7, 37, 4, 37, 37, 37, 5, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 3, 1, 37, 37, 2, 37, 6, 37, 37, 37, 37, 37, 37, 37, -1, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 35, 37, 37, 37, 37, 37, 37, 37, 7, 37, 4, 37, 37, 37, 5, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 3, 1, 37, 37, 2, 37, 6, 37, 37, 37, 37, 37, 37, 37, -1, 15, 15, 15, 15,37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 30, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 31, 37, 37, 37, 37, 37, 37, 7, 37, 4, 37, 37, 37, 5, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 3, 1, 37, 37, 2, 37, 6, 37, 37, 37, 37, 37, 37, 37, -1, 37, 37, 37, 3 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 14, 15, 15, 15, 13, 15, 12, 15, 15, 15, 15, 15, 15, 15, 15, 11, 8, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 7, 15, 4, 15, 15, 15, 5, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 3, 1, 15, 15, 2, 15, 6, 15, 15, 15, 15, 15, 15, 15, -1, 25, 25, 25, 25, 27, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 32, 37, 37, 37, 37, 37, 37, 37, 7, 37, 4, 37, 37, 37, 5, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 3, 1, 37, 37, 2, 37, 6, 37, 37, 37, 37, 37, 37, 37, -1, 37, 37, 37, 35, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 16, 17, 18, 19, 25, 21, 25, 25, 25, 20, 25, 25, 25, 25, 25, 25, 25, 22, 23, 25, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 7, 25, 4, 25, 25, 25, 5, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 3, 1, 25, 25, 2, 25, 6, 25, 25, 25, 25, 25, 25, 25, -1, 37, 37, 37, 37, 3wart program. It gets a character from the input() routine and then based on that character and the current state, selects the appropriate action, according to the state table above, which is transformed by the wart program into a big case statement. The function is active for one transaction. */ wart(); /* Enter the state table switcher. */ if (server) { /* Back from packet protocol. */ server = 0; if (!quiet) /* Give appropriate message */ conoll("C-Kermit server do Lex) */ %states ipkt rfile rdata ssinit ssdata sseof sseot serve generic get rgen /* External C-Kermit variable declarations */ extern char sstate, *versio, *srvtxt, *cmarg, *cmarg2; extern char data[], filnam[], srvcmd[], ttname[], *srvptr; extern int pktnum, timint, nfils, image, hcflg, xflg, speed, flow, mdmtyp; extern int prvpkt, cxseen, czseen, server, local, displa, bctu, bctr, quiet; extern int putsrv(), puttrm(), putfil(), errpkt(); extern char *DIRCMD, *DELCMD, *TYPCMD, *SPACMD, *SPACne"); } screen(SCR_TC,0,0l,""); /* Transaction complete */ } based on that character and the current state, selects the appropriate action, according to the state table above, which is transformed by the wart program into a big case statement. The function is active for one transaction. */ wart(); /* Enter the state table switcher. */ if (server) { /* Back from packet protocol. */ server = 0; if (!quiet) /* Give appropriate message */ conoll("C-Kermit server doM2, *WHOCMD; /* Local variables */ static char vstate = 0; /* Saved State */ static char vcmd = 0; /* Saved Command */ static int x; /* General-purpose integer */ /* Macros - Note, BEGIN is predefined by Wart (and Lex) */ #define SERVE tinit(); BEGIN serve #define RESUME if (server) { SERVE; } else return %% /* Protocol entry points, one for each start state (sstate) */ s { tinit(); /* Do Send command */ if (sinit()) BEGIN ssinit; else RESUME; } v { tinit()./usr/opt/src/kermit/ckcpro.w 644 0 3 17414 5555215354 11353 ; sleep(1); nack(); BEGIN get; } /* Receive */ r { tinit(); vstate = get; vcmd = 0; sipkt(); BEGIN ipkt; } /* Get */ c { tinit(); vstate = rgen; vcmd = 'C'; sipkt(); BEGIN ipkt; } /* Host */ g { tinit(); vstate = rgen; vcmd = 'G'; sipkt(); BEGIN ipkt; } /* Generic */ x { sleep(1); SERVE; } /* Be a Server */ a { errpkt("User cancelled transaction"); /* Tell other side what's going on */ x = quiet; quiet = 1; /* Close files silently */ clsif(); clsof(); quiet = x; retuProtocol entry function */ proto() { extern int sigint(); int x; conint(sigint); /* Enable console interrupts */ /* Set up the communication line for file transfer. */ if (local && (speed < 0)) { screen(SCR_EM,0,0l,"Sorry, you must 'set speed' first"); return; } x = -1; if (ttopen(ttname,&x,mdmtyp) < 0) { debug(F111,"proto ttopen local",ttname,local); screen(SCR_EM,0,0l,"Can't open line"); return; } if (x > -1) local = x; debug(F111,"proto ttopen local",char *protv = "C-Kermit Protocol Module 4C(026), 12 Jun 85"; /* -*-C-*- */ /* C K C P R O -- C-Kermit Protocol Module, in Wart preprocessor notation. */ /* 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 noticttname,local); x = (local) ? speed : -1; if (ttpkt(x,flow) < 0) { /* Put line in packet mode, */ screen(SCR_EM,0,0l,"Can't condition line"); return; } if (sstate == 'x') { /* If entering server mode, */ server = 1; /* set flag, */ if (!quiet) { if (!local) /* and issue appropriate message. */ conol(srvtxt); else { conol("Entering server mode on "); conoll(ttname); } } } else server = 0; sleep(1); /* The 'wart()' function is generated by the e is retained. */ #include "ckcdeb.h" #include "ckcker.h" /* Note -- This file may also be preprocessed by the Unix Lex program, but you must indent the above #include statement before using Lex, and then restore it to the left margin in the resulting C program before compilation. Also, the invocation of the "wart()" function below must be replaced by an invocation of the "yylex()" function. It might also be necessary to remove comments in the %%...%% section. */ /* State definitions for Wart (or; decode(data,putsrv); /* Get Receive-Init */ cmarg = srvcmd; nfils = -1; if (sinit()) BEGIN ssinit; else { SERVE; } } I { spar(data); rpar(data); ack1(data); /* Get Init Parameters */ pktnum = 0; prvpkt = -1; } G { srvptr = srvcmd; decode(data,putsrv); /* Get & decode command. */ putsrv('\0'); putsrv('\0'); sstate = srvcmd[0]; BEGIN generic; } C { srvptr = srvcmd; /* Get command for shell */ decode(data,putsrv); putsrv('\0'); if (syscmd(srvcmlse { x = sfile(); s = "Can't open file"; } if (x) BEGIN ssdata; else { errpkt(s); RESUME; } } Y { if (canned(data) || !sdata()) { /* Got ACK to data */ clsif(); seof(); BEGIN sseof; } } Y { if (gnfile() > 0) { /* Got ACK to EOF, get next file */ if (sfile()) BEGIN ssdata; else { errpkt("Can't open file") ; RESUME; } } else { /* If no next file, EOT */ seot(); BEGIN sseot; } } Y { RESUME; } /* Got ACK to EOT */ E { ermsg(data); /* Error pd,"")) BEGIN ssinit; else { errpkt("Can't do system command"); SERVE; } } . { errpkt("Unimplemented server function"); SERVE; } /* Other */ C { if (!cwd(srvcmd+1)) errpkt("Can't change directory"); /* CWD */ SERVE; } D { if (syscmd(DIRCMD,srvcmd+2)) BEGIN ssinit; /* Directory */ else { errpkt("Can't list directory"); SERVE; } } E { if (syscmd(DELCMD,srvcmd+2)) BEGIN ssinit; /* Erase */ else { errpkt("Can't remove file"); SERVE; } } F { ack(); screen(SCR_TC,0,0l,""); return(0); } /* Finish and Bye */ L { ack(); ttres(); screen(SCR_TC,0,0l,""); return(zkself()); } H { if (sndhlp()) BEGIN ssinit; else { errpkt("Can't send help"); SERVE; } } T { if (syscmd(TYPCMD,srvcmd+2)) BEGIN ssinit; else { errpkt("Can't type file"); SERVE; } } U { x = *(srvcmd+1); /* Disk Usage query */ x = ((x == '\0') || (x == unchar(0))); x = (x ? syscmd(SPACMD,"") : syscmd(SPACM2,sttopen(ttname,&x,mdmtyp) < 0) { debug(F111,"proto ttopen local",ttname,local); screen(SCR_EM,0,0l,"Can't open line"); return; } if (x > -1) local = x; debug(F111,"proto ttopen local",ttname,local); x = (local) ? speed : -1; if (ttpkt(x,flow) < 0) { /* Put line in packet mode, */ screen(SCR_EM,0,0l,"Can't condition line"); return; } if (sstate == 'x') { /* If entering server mode, */ server = 1; /* set flag, */ if (!quiet) { if (!local) /* and issue appropriate rvcmd+2)); if (x) BEGIN ssinit; else { errpkt("Can't check space"); SERVE; }} W { if (syscmd(WHOCMD,srvcmd+2)) BEGIN ssinit; else { errpkt("Can't do who command"); SERVE; } } . { errpkt("Unimplemented generic server function"); SERVE; } /* Dynamic states, cont'd */ Y { decode(data,puttrm); RESUME; } /* Got reply in ACK data */ F { if (rcvfil()) { ack(); BEGIN rdata; } /* A file is coming */ else { errpkt("Can't open file"); RESUME; } } input-character { action } */ S { rinit(data); bctu = bctr; BEGIN rfile; } /* Send-Init */ Y { spar(data); /* Get ack for I-packet */ if (vcmd) { scmd(vcmd,cmarg); vcmd = 0; } if (vstate == get) srinit(); BEGIN vstate; } E { if (vcmd) scmd(vcmd,cmarg); /* Get E for I-packet (ignore) */ vcmd = 0; if (vstate == get) srinit(); BEGIN vstate; } R { srvptr = srvcmdgen,rfile>X { opent(); ack(); BEGIN rdata; } /* Screen data is coming */ B { ack(); reot(); RESUME; } /* Got End Of Transmission */ D { if (cxseen) ack1("X"); /* Got data. */ else if (czseen) ack1("Z"); else ack(); decode(data,putfil); } Z { ack(); reof(); BEGIN rfile; } /* Got End Of File */ Y { int x; char *s; /* Got ACK to Send-Init */ spar(data); bctu = bctr; if (xflg) { x = sxpack(); s = "Can't execute command"; } e); /* Enter the state table switcher. */ if (server) { /* Back from packet protocol. */ server = 0; if (!quiet) /* Give appropriate message */ conoll("C-Kermit server done"); } screen(SCR_TC,0,0l,""); /* Transaction complete */ } based on that character and the current state, selects the appropriate action, according to the state table above, which is transformed by the wart program into a big case statement. The function is active for one transaction. */ wart( individual functions for greater detail. Before using these routines, the caller should #include ckucmd.h, and set the program's prompt by calling cmsetp(). If the file parsing functions cmifi and cmofi are to be used, this module must be linked with a ck?fio file system support module for the appropriate system, e.g. ckufio for Unix. If the caller puts the terminal in character wakeup ("cbreak") mode with no echo, then these functions will provide line editing -- character, word, and line deleti./usr/opt/src/kermit/ckucmd.c 644 0 3 63622 5555215354 11316 on, as well as keyword and filename completion upon ESC and help strings, keyword, or file menus upon '?'. If the caller puts the terminal into character wakeup/noecho mode, care should be taken to restore it before exit from or interruption of the program. If the character wakeup mode is not set, the system's own line editor may be used. Author: Frank da Cruz (SY.FDC@CU20B), Columbia University Center for Computing Activities, January 1985. Copyright (C) 1985, Trustees of Columbia University in char *cmdv = "Unix cmd package V1A(021), 19 Jun 85"; /* C K U C M D -- Interactive command package for Unix */ /* Modelled after the DECSYSTEM-20 command parser (the COMND JSYS) Features: . parses and verifies keywords, text strings, numbers, and other data . displays appropriate menu or help message when user types "?" . does keyword and filename completion when user types ESC . accepts any unique abbreviation for a keyword . allows keywords to have attributes, like "invisible" . can supply dthe 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. */ /* Includes */ #include /* Standard C I/O package */ #include /* Character types */ #include "ckucmd.h" /* Command parsing definitions */ #include "ckcdeb.h" /* Formats for debug() */ /* Local variables */ int psetf = 0, /* Flag that prompt has been set */ cc =efaults for fields omitted by user . provides command line editing (character, word, and line deletion) . accepts input from keyboard, command files, or redirected stdin . allows for full or half duplex operation, character or line input . settable prompt, protected from deletion Functions: cmsetp - Set prompt (cmprom is prompt string, cmerrp is error msg prefix) cmsavp - Save current prompt prompt - Issue prompt cmini - Clear the command buffer (before parsing a new command) cmres - Rese 0, /* Character count */ dpx = 0; /* Duplex (0 = full) */ int hw = HLPLW, /* Help line width */ hc = HLPCW, /* Help line column width */ hh, /* Current help column number */ hx; /* Current help line position */ #define PROML 60 /* Maximum length for prompt */ char cmprom[PROML+1]; /* Program's prompt */ char *dfprom = "Command? "; /* Default prompt */ char cmerrp[PROML+1]; /* Program's error message prefix */ int cmflgs; /* Command flags */ char cmdbuf[CMt command buffer pointers (before reparsing) cmkey - Parse a keyword cmnum - Parse a number cmifi - Parse an input file name cmofi - Parse an output file name cmfld - Parse an arbitrary field cmtxt - Parse a text string cmcfm - Parse command confirmation (end of line) stripq - Strip out backslash quotes from a string. Return codes: -3: no input provided when required -2: input was invalid -1: reparse required (user deleted into a preceding field) 0 or greater: success SeeDBL+4]; /* Command buffer */ char hlpbuf[HLPBL+4]; /* Help string buffer */ char atmbuf[ATMBL+4]; /* Atom buffer */ char filbuf[ATMBL+4]; /* File name buffer */ /* Command buffer pointers */ static char *bp, /* Current command buffer position */ *pp, /* Start of current field */ *np; /* Start of next field */ long zchki(); /* From ck?fio.c. */ /* C M S E T P -- Set the program prompt. */ cmsetp(s) char *s; { char *sx, *sy, *strncpy(); psetf = 1; /* Flag thatx); /* Parse a field */ if (digits(atmbuf)) { /* Convert to number */ *n = atoi(atmbuf); return(x); } else { printf("\n?not a number - %s\n",s); return(-2); } } /* C M O F I -- Parse the name of an output file */ /* Depends on the external function zchko(); if zchko() not available, use cmfld() to parse output file names. Returns -3 if no input present when required, -2 if permission would be denied to create the file, -1 if reparse needed, 0 or 1 otherwise, w = zxpand(*xp); if (y == 0) { printf("\n?No files match - %s\n",*xp); return(-2); } else if (y < 0) { printf("\n?Too many files match - %s\n",*xp); return(-2); } else return(x); } /* If not wild, see if it exists and is readable. */ y = zchki(*xp); if (y == -3) { printf("\n?Read permission denied - %s\n",*xp); return(-2); } else if (y == -2) { printf("\n?File not readable - %s\n",*xp); return(-2); } else if (y < 0) { printf("\n?File n prompt has been set. */ strncpy(cmprom,s,PROML - 1); /* Copy the string. */ cmprom[PROML] = NUL; /* Ensure null terminator. */ sx = cmprom; sy = cmerrp; /* Also use as error message prefix. */ while (*sy++ = *sx++) ; /* Copy. */ sy -= 2; if (*sy == '>') *sy = NUL; /* Delete any final '>'. */ } /* C M S A V P -- Save a copy of the current prompt. */ cmsavp(s,n) int n; char s[]; { extern char *strncpy(); /* +1 */ strncpy(s,cmprom,n-1); s[n] = NUL; } /* P R O M Pith xp pointing to name. */ cmofi(xhlp,xdef,xp) char *xhlp, *xdef, **xp; { int x; char *s; if (*xhlp == NUL) xhlp = "Output file"; *xp = ""; if ((x = cmfld(xhlp,xdef,&s)) < 0) return(x); if (chkwld(s)) { printf("\n?Wildcards not allowed - %s\n",s); return(-2); } if (zchko(s) < 0) { printf("\n?Write permission denied - %s\n",s); return(-2); } else { *xp = s; return(x); } } /* C M I F I -- Parse the name of an existing file */ /* This function depends on T -- Issue the program prompt. */ prompt() { if (psetf == 0) cmsetp(dfprom); /* If no prompt set, set default. */ printf("\r%s",cmprom); /* Print the prompt. */ } /* C M R E S -- Reset pointers to beginning of command buffer. */ cmres() { cc = 0; /* Reset character counter. */ pp = np = bp = cmdbuf; /* Point to command buffer. */ cmflgs = -5; /* Parse not yet started. */ } /* C M I N I -- Clear the command and atom buffers, reset pointers. */ /* The argument sthe external functions: zchki() - Check if input file exists and is readable. zxpand() - Expand a wild file specification into a list. znext() - Return next file name from list. If these functions aren't available, then use cmfld() to parse filenames. */ /* Returns -4 EOF -3 if no input present when required, -2 if file does not exist or is not readable, -1 if reparse needed, 0 or 1 otherwise, with: xp pointing to name, wild = 1 if name contains '*' or '?', 0 otherwise. */pecifies who is to echo the user's typein -- 1 means the cmd package echoes 0 somebody else (system, front end, terminal) echoes */ cmini(d) int d; { for (bp = cmdbuf; bp < cmdbuf+CMDBL; bp++) *bp = NUL; *atmbuf = NUL; dpx = d; cmres(); } stripq(s) char *s; { /* Function to strip '\' quotes */ char *t; while (*s) { if (*s == '\\') { for (t = s; *t != '\0'; t++) *t = *(t+1); } s++; } } /* C M N U M -- Parse a number in the indicated radix */ /* For now, on cmifi(xhlp,xdef,xp,wild) char *xhlp, *xdef, **xp; int *wild; { int i, x, xc; long y; char *sp; cc = xc = 0; /* Initialize counts & pointers */ *xp = ""; if ((x = cmflgs) != 1) { /* Already confirmed? */ x = getwd(); /* No, get a word */ } else { cc = setatm(xdef); /* If so, use default, if any. */ } *xp = atmbuf; /* Point to result. */ *wild = chkwld(*xp); while (1) { xc += cc; /* Count the characters. */ debug(F111,"cmifi: getwd",atmbuf,xc); switch ly works for positive numbers in base 10. */ /* Returns -3 if no input present when required, -2 if user typed an illegal number, -1 if reparse needed, 0 otherwise, with n set to number that was parsed */ cmnum(xhlp,xdef,radix,n) char *xhlp, *xdef; int radix, *n; { int x; char *s; if (radix != 10) { /* Just do base 10 for now */ printf("cmnum: illegal radix - %d\n",radix); return(-1); } x = cmfld(xhlp,xdef,&s); debug(F101,"cmnum: cmfld","",x); if (x < 0) return((x) { case -4: /* EOF */ case -2: /* Out of space. */ case -1: /* Reparse needed */ return(x); /* cont'd... */ /* ...cmifi(), cont'd */ case 0: /* SP or NL */ case 1: if (xc == 0) *xp = xdef; /* If no input, return default. */ else *xp = atmbuf; if (**xp == NUL) return(-3); /* If field empty, return -3. */ /* If filespec is wild, see if there are any matches */ *wild = chkwld(*xp); debug(F101," *wild","",*wild); if (*wild != 0) { y(atmbuf); *sp = '\0'; if (y == 0) { printf("\n?No files match - %s\n",atmbuf); return(-2); } else if (y < 0) { printf("\n?Too many file match - %s\n",atmbuf); return(-2); } else { printf(", one of the following:\n"); clrhlp(); for (i = 0; i < y; i++) { znext(filbuf); addhlp(filbuf); } dmphlp(); } } else printf("\n"); printf("%s%s",cmprom,cmdbuf); break; } x = getwd(); } } /* C H K W L D -- Check for wildcard chdef,xp) char *xhlp; char *xdef; char **xp; { int x; static int xc; debug(F101,"cmtxt, cmflgs","",cmflgs); cc = 0; /* Start atmbuf counter off at 0 */ if (cmflgs == -1) { /* If reparsing, */ xc = strlen(*xp); /* get back the total text length, */ } else { /* otherwise, */ *xp = ""; /* start fresh. */ xc = 0; } *atmbuf = NUL; /* And empty atom buffer. */ if ((x = cmflgs) != 1) { x = getwd(); /* Get first word. */ *xp = pp; /* Save pointeraracters '*' or '?' */ chkwld(s) char *s; { for ( ; *s != '\0'; s++) { if ((*s == '*') || (*s == '?')) return(1); } return(0); } /* C M F L D -- Parse an arbitrary field */ /* Returns -3 if no input present when required, -2 if field too big for buffer, -1 if reparse needed, 0 otherwise, xp pointing to string result. */ cmfld(xhlp,xdef,xp) char *xhlp, *xdef, **xp; { int x, xc; cc = xc = 0; /* Initialize counts & pointers */ *xp = ""; if ((x = to it. */ } while (1) { xc += cc; /* Char count for all words. */ debug(F111,"cmtxt: getwd",atmbuf,xc); debug(F101," x","",x); switch (x) { case -4: /* EOF */ case -2: /* Overflow */ case -1: /* Deletion */ return(x); case 0: /* Space */ xc++; /* Just count it */ break; case 1: /* CR or LF */ if (xc == 0) *xp = xdef; return(x); case 2: /* ESC */ if (xc == 0) { printf("%s ",xdef); cc = addbuf(xdef); } eot found - %s\n",*xp); return(-2); } return(x); /* cont'd... */ /* ...cmifi(), cont'd */ case 2: /* ESC */ if (xc == 0) { if (*xdef != '\0') { printf("%s ",xdef); /* If at beginning of field, */ addbuf(xdef); /* supply default. */ cc = setatm(xdef); } else { /* No default */ putchar(BEL); } break; } if (*wild = chkwld(*xp)) { /* No completion if wild */ putchar(BEL); break; } sp = atmbuf + cc; *sp++ = '*'; *sp-- = '\ cmflgs) != 1) { /* Already confirmed? */ x = getwd(); /* No, get a word */ } else { cc = setatm(xdef); /* If so, use default, if any. */ } *xp = atmbuf; /* Point to result. */ while (1) { xc += cc; /* Count the characters. */ debug(F111,"cmfld: getwd",atmbuf,xc); debug(F101," x","",x); switch (x) { case -4: /* EOF */ case -2: /* Out of space. */ case -1: /* Reparse needed */ return(x); case 0: /* SP or NL */ case 1: if (xc == 00'; y = zxpand(atmbuf); /* Add * and expand list. */ *sp = '\0'; /* Remove *. */ if (y == 0) { printf("\n?No files match - %s\n",atmbuf); return(-2); } else if (y < 0) { printf("\n?Too many files match - %s\n",atmbuf); return(-2); } else if (y > 1) { /* Not unique, just beep. */ putchar(BEL); } else { /* Unique, complete it. */ znext(filbuf); /* Get whole name of file. */ sp = filbuf + cc; /* Point past what user typed. */ printf("%s ",sp); /* ) *xp = xdef; /* If no input, return default. */ else *xp = atmbuf; if (**xp == NUL) x = -3; /* If field empty, return -3. */ return(x); case 2: /* ESC */ if (xc == 0) { printf("%s ",xdef); /* If at beginning of field, */ addbuf(xdef); /* supply default. */ cc = setatm(xdef); /* Return as if whole field */ return(0); /* typed, followed by space. */ } else { putchar(BEL); /* Beep if already into field. */ } break; case 3: /* QComplete the name. */ addbuf(sp); /* Add the characters to cmdbuf. */ setatm(pp); /* And to atmbuf. */ *xp = atmbuf; /* Return pointer to atmbuf. */ return(cmflgs = 0); } break; /* cont'd... */ /* ...cmifi(), cont'd */ case 3: /* Question mark */ if (*xhlp == NUL) printf(" Input file specification"); else printf(" %s",xhlp); if (xc > 0) { sp = atmbuf + cc; /* Insert * at end */ *sp++ = '*'; *sp-- = '\0'; y = zxpanduestion mark */ if (*xhlp == NUL) printf(" Please complete this field"); else printf(" %s",xhlp); printf("\n%s%s",cmprom,cmdbuf); break; } x = getwd(); } } /* C M T X T -- Get a text string, including confirmation */ /* Print help message 'xhlp' if ? typed, supply default 'xdef' if null string typed. Returns -1 if reparse needed or buffer overflows. 1 otherwise. with cmflgs set to return code, and xp pointing to result string. */ cmtxt(xhlp,x= 1) /* Command already entered? */ setatm(xdef); else zz = getwd(); debug(F101,"cmkey: table length","",n); debug(F101," cmflgs","",cmflgs); debug(F101," zz","",zz); while (1) { xc += cc; debug(F111,"cmkey: getwd",atmbuf,xc); switch(zz) { case -4: /* EOF */ case -2: /* Buffer overflow */ case -1: /* Or user did some deleting. */ return(zz); case 0: /* User terminated word with space */ case 1: /* or newline */ if (cc == 0) setatm(xdef); y = lookup(lgs","",cmflgs); xc = cc = 0; if (cmflgs == 1) return(0); while (1) { x = getwd(); xc += cc; debug(F111,"cmcfm: getwd",atmbuf,xc); switch (x) { case -4: /* EOF */ case -2: case -1: return(x); case 0: /* Space */ continue; case 1: /* End of line */ if (xc > 0) { printf("?Not confirmed - %s\n",atmbuf); return(-2); } else return(0); case 2: putchar(BEL); continue; case 3: if (xc > table,atmbuf,n,&z); switch (y) { case -2: printf("\n?Ambiguous - %s\n",atmbuf); return(cmflgs = -2); case -1: printf("\n?Invalid - %s\n",atmbuf); return(cmflgs = -2); default: break; } return(y); /* cont'd... */ /* ...cmkey(), cont'd */ case 2: /* User terminated word with ESC */ if (cc == 0) { if (*xdef != NUL) { /* Nothing in atmbuf */ printf("%s ",xdef); /* Supply default if any */ addbuf(xdef); cc = setatm(xdef); 0) { printf("\n?Not confirmed - %s\n",atmbuf); return(-2); } printf("\n Type a carriage return to confirm the command\n"); printf("%s%s",cmprom,cmdbuf); continue; } } } /* Keyword help routines */ /* C L R H L P -- Initialize/Clear the help line buffer */ clrhlp() { /* Clear the help buffer */ hlpbuf[0] = NUL; hh = hx = 0; } /* A D D H L P -- Add a string to the help line buffer */ addhlp(s) char *s; { /* Add a word to the help buffer */ int j debug(F111,"cmkey: default",atmbuf,cc); } else { putchar(BEL); /* No default, just beep */ break; } } y = lookup(table,atmbuf,n,&z); /* Something in atmbuf */ debug(F111,"cmkey: esc",atmbuf,y); if (y == -2) { putchar(BEL); break; } if (y == -1) { printf("\n?Invalid - %s\n",atmbuf); return(cmflgs = -2); } xp = table[z].kwd + cc; printf("%s ",xp); addbuf(xp); debug(F110,"cmkey: addbuf",cmdbuf,0); return(y); /* co; hh++; /* Count this column */ for (j = 0; (j < hc) && (*s != NUL); j++) { /* Fill the column */ hlpbuf[hx++] = *s++; } if (*s != NUL) /* Still some chars left in string? */ hlpbuf[hx-1] = '+'; /* Mark as too long for column. */ if (hh < (hw / hc)) { /* Pad col with spaces if necessary */ for (; j < hc; j++) { hlpbuf[hx++] = SP; } } else { /* If last column, */ hlpbuf[hx++] = NUL; /* no spaces. */ dmphlp(); /* Print it. */ return; } } /*lse { putchar(BEL); } break; case 3: /* Question Mark */ if (*xhlp == NUL) printf(" Text string"); else printf(" %s",xhlp); printf("\n%s%s",cmprom,cmdbuf); break; default: printf("\n?Unexpected return code from getwd() - %d\n",x); return(-2); } x = getwd(); } } /* C M K E Y -- Parse a keyword */ /* Call with: table -- keyword table, in 'struct keytab' format; n -- number of entries in table; xhlp -- nt'd... */ /* ...cmkey(), cont'd */ case 3: /* User terminated word with "?" */ y = lookup(table,atmbuf,n,&z); if (y > -1) { printf(" %s\n%s%s",table[z].kwd,cmprom,cmdbuf); break; } else if (y == -1) { printf("\n?Invalid\n"); return(cmflgs = -2); } if (*xhlp == NUL) printf(" One of the following:\n"); else printf(" %s, one of the following:\n",xhlp); clrhlp(); for (i = 0; i < n; i++) { if (!strncmp(table[i].kwd,atmbuf,cc) && !t pointer to help string; xdef -- pointer to default keyword; Returns: -3 -- no input supplied and no default available -2 -- input doesn't uniquely match a keyword in the table -1 -- user deleted too much, command reparse required n >= 0 -- value associated with keyword */ cmkey(table,n,xhlp,xdef) struct keytab table[]; int n; char *xhlp, *xdef; { int i, y, z, zz, xc; char *xp; xc = cc = 0; /* Clear character counters. */ if ((zz = cmflgs) =est(table[i].flgs,CM_INV)) addhlp(table[i].kwd); } dmphlp(); printf("%s%s", cmprom, cmdbuf); break; default: printf("\n%d - Unexpected return code from getwd\n",zz); return(cmflgs = -2); } zz = getwd(); } } /* C M C F M -- Parse command confirmation (end of line) */ /* Returns -2: User typed anything but whitespace or newline -1: Reparse needed 0: Confirmation was received */ cmcfm() { int x, xc; debug(F101,"cmcfm: cmfble must be arranged in ascending alphabetical order, and all letters must be lowercase. Returns the keyword's associated value ( zero or greater ) if found, with the variable x set to the array index, or: -3 if nothing to look up (target was null), -2 if ambiguous, -1 if not found. A match is successful if the target matches a keyword exactly, or if the target is a prefix of exactly one keyword. It is ambiguous if the target matches two or more keywords from the table. */ lookup(table,cmd, system("clear"); /* and clear the screen. */ } if (c == HT) c = SP; /* Substitute space for tab. */ /* cont'd... */ /* ...getwd(), cont'd */ if (c == SP) { /* If space */ *bp++ = c; /* deposit it in buffer. */ if (echof) putchar(c); /* echo it. */ if (inword == 0) { /* If leading, gobble it. */ pp++; continue; } else { /* If terminating, return. */ np = bp; setatm(pp); inword = 0; return(cmflgs = 0); } } if (c == NL ||n,x) char *cmd; struct keytab table[]; int n, *x; { int i, v, cmdlen; /* Lowercase & get length of target, if it's null return code -3. */ if ((((cmdlen = lower(cmd))) == 0) || (n < 1)) return(-3); /* Not null, look it up */ for (i = 0; i < n-1; i++) { if (!strcmp(table[i].kwd,cmd) || ((v = !strncmp(table[i].kwd,cmd,cmdlen)) && strncmp(table[i+1].kwd,cmd,cmdlen))) { *x = i; return(table[i].val); } if (v) return(-2); } /* Last (or only) element */ c == CR) { /* CR, LF */ *bp = NUL; /* End the string */ if (echof) { /* If echoing, */ putchar(c); /* echo the typein */ #ifdef aegis if (c == CR) putchar(NL); #endif } np = bp; /* Where to start next field. */ setatm(pp); /* Copy this field to atom buffer. */ inword = 0; return(cmflgs = 1); } if (!ignore && (c == '?')) { /* Question mark */ putchar(c); *bp = NUL; setatm(pp); return(cmflgs = 3); } if (c == ESC) { /* ESC */ *bp = NUL; set if (!strncmp(table[n-1].kwd,cmd,cmdlen)) { *x = n-1; return(table[n-1].val); } else return(-1); } /* G E T W D -- Gets a "word" from the command input stream */ /* Usage: retcode = getwd(); Returns: -4 if end of file (e.g. pipe broken) -2 if command buffer overflows -1 if user did some deleting 0 if word terminates with SP or tab 1 if ... CR 2 if ... ESC 3 if ... ? With: pp pointing to beginning of word in buffer bp pointing to after current position atmbuf containing a atm(pp); return(cmflgs = 2); } if (c == BS || c == RUB) { /* Character deletion */ if (bp > cmdbuf) { /* If still in buffer... */ printf("\b \b"); /* erase character from screen, */ bp--; /* point behind it, */ if (*bp == SP) inword = 0; /* Flag if current field gone */ *bp = NUL; /* Erase character from buffer. */ } else { /* Otherwise, */ putchar(BEL); /* beep, */ cmres(); /* and start parsing a new command. */ } if (pp < bp) continue; else recopy of the word cc containing the number of characters in the word copied to atmbuf */ getwd() { int c; /* Current char */ static int inword = 0; /* Flag for start of word found */ int quote = 0; /* Flag for quote character */ int echof = 0; /* Flag for whether to echo */ int ignore = 0; pp = np; /* Start of current field */ debug(F101,"getwd: cmdbuf","",(int) cmdbuf); debug(F101," bp","",(int) bp); debug(F101," pp","",(int) pp); debug(F110," cmdbuf",cturn(cmflgs = -1); } if (c == LDEL) { /* ^U, line deletion */ while ((bp--) > cmdbuf) { printf("\b \b"); *bp = NUL; } cmres(); /* Restart the command. */ inword = 0; return(cmflgs = -1); } /* cont'd... */ /* ...getwd(), cont'd */ if (c == WDEL) { /* ^W, word deletion */ if (bp <= cmdbuf) { /* Beep if nothing to delete */ putchar(BEL); cmres(); return(cmflgs = -1); } bp--; for ( ; (bp >= cmdbuf) && (*bp == SP) ; bp D M P H L P -- Dump the help line buffer */ dmphlp() { /* Print the help buffer */ hlpbuf[hx++] = NUL; printf(" %s\n",hlpbuf); clrhlp(); } /* L O O K U P -- Lookup the string in the given array of strings */ /* Call this way: v = lookup(table,word,n,&x); table - a 'struct keytab' table. word - the target string to look up in the table. n - the number of elements in the table. x - address of an integer for returning the table array index. The keyword tamdbuf,0); while (bp < cmdbuf+CMDBL) { /* Loop */ ignore = echof = 0; /* Flag for whether to echo */ if ((c = *bp) == NUL) { /* Get next character */ if (dpx) echof = 1; /* from reparse buffer */ c = getchar(); /* or from tty. */ if (c == EOF) return(-4); } else ignore = 1; if (quote == 0) { if (!ignore && (c == '\\')) { /* Quote character */ quote = 1; continue; } if (c == FF) { /* Formfeed. */ c = NL; /* Replace with newline */ --) { printf("\b \b"); *bp = NUL; } for ( ; (bp >= cmdbuf) && (*bp != SP) ; bp--) { printf("\b \b"); *bp = NUL; } bp++; inword = 0; return(cmflgs = -1); } if (c == RDIS) { /* ^R, redisplay */ *bp = NUL; printf("\n%s%s",cmprom,cmdbuf); continue; } } if (echof) putchar(c); /* If tty input, echo. */ inword = 1; /* Flag we're in a word. */ if (quote == 0 || c != NL) *bp++ = c; /* And deposit it. */ quote = 0; /* Turn off quote. */ } /* 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 /* end of big while */ putchar(BEL); /* Get here if... */ printf("\n?Buffer full\n"); return(cmflgs = -2); } /* Utility functions */ /* A D D B U F -- Add the string pointed to by cp to the command buffer */ addbuf(cp) char *cp; { int len = 0; while ((*cp != NUL) && (bp < cmdbuf+CMDBL)) { *bp++ = *cp++; /* Copy and */ len++; /* count the characters. */ } *bp++ = SP; /* Put a space at the end */ *bp = NUL; /* Terminate with a null */ np = () #endif #ifdef aegis #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 bp; /* Update the next-field pointer */ return(len); /* Return the length */ } /* S E T A T M -- Deposit a string in the atom buffer */ setatm(cp) char *cp; { char *ap; cc = 0; ap = atmbuf; *ap = NUL; while (*cp == SP) cp++; while ((*cp != SP) && (*cp != NL) && (*cp != NUL) && (*cp != CR)) { *ap++ = *cp++; cc++; } *ap++ = NUL; return(cc); /* Return length */ } /* D I G I T S -- Verify that all the characters in line are digits */ digits(s) char *s'\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 */ str; { while (*s) { if (!isdigit(*s)) return(0); s++; } return(1); } /* L O W E R -- Lowercase a string */ lower(s) char *s; { int n = 0; while (*s) { if (isupper(*s)) *s = tolower(*s); s++, n++; } return(n); } /* T E S T -- Bit test */ test(x,m) int x, m; { /* Returns 1 if any bits from m are on in x, else 0 */ return((x & m) ? 1 : 0); } turn length */ } /* D I G I T S -- Verify that all the characters in line are digits */ digits(s) char *suct keytab { /* Keyword table */ char *kwd; /* Pointer to keyword string */ int val; /* Associated value */ int flgs; /* Flags (as defined above) */ }; (^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 */ str./usr/opt/src/kermit/ckucmd.h 644 0 3 3260 5555215354 11273 ./usr/opt/src/kermit/ckucon.c 644 0 3 16265 5555215354 11333 [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, spee parent. */ } c &= 0177; /* 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] &= 0177; /* Strip */ conxo(n,lbuf); /* Output */ if (seslog) zsoutx(ZSFILE,lbuf,n); /* Log */ } char *connv = "Connect Command for Unix, V4C(012)+2 27 Jun 85"; /* 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. Permid %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("ssion 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 #include /* Character types *Sorry, Can't condition communication line\n"); return(-2); } /* cont'd... */ /* ...connect, cont'd */ parent_id = getpid(); /* get parent id for signalling */ pid = fork(); /* All ok, make a fork */ 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) & 0177; /* Get character from keyboard */ if (c == / #include "ckcdeb.h" #include "ckcker.h" #include #include #ifndef SIGUSR1 #define SIGUSR1 16 #endif extern int local, speed, escape, duplex, parity, flow, seslog, mdmtyp; 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 erescape) { /* 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 orors */ 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 errmsgn death of child */ kill(pid,9); /* Done, kill inferior fork. */ wait(0); /* Wait till gone. */ conres(); /* Reset the console. */ printf("[Back at Local System]\n"); return(0); } else { /* Inferior reads, prints port input */ while (1) { /* Fresh read, wait for a character */ if ((c = ttinc(0)) < 0) { /* Comm line hangup detected */ perror("\r\nCan't get character"); kill(parent_id,SIGUSR1); /* notify parent. */ pause(); /* Wait to be killed by (speed >= 0) { sprintf(temp,", speed %d",speed); conol(temp); } 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';g waitFor. * -- Dan Schullman * * 26-Jun-85 Allow interrupts to be used to abort dialing, * and ring the bell when a connection is made. * Reorganized some of the failure paths to use the * same code, and now close the line on failures. * Allow use of stored numbers with the DF100 and * DF200 modems. Handlers now declared after the * call to setjmp. * -- Dan Schullman * * 24-May-85 DF03, DF100-series, DF200-series, and "unknown" modem * support added. Also restructur d = dopar(c); ttoc(d); return; case SP: /* Space, ignore */ return; default: /* Other */ conoc(BEL); return; /* Invalid esc arg, beep */ } } } 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';ed the various data * tables, fixed some bugs related to missing data and * missing case labels, and modified the failure message * to display the "reason" given by the modem. * -- Dan Schullman */ /* * To add support for another modem, do the following: * * Define a modem number symbol (n_XXX) for it, keeping the list * in alphabetical and numerical order, and renumbering the values * as necessary. * * Create a MDMINF structure for it, again keeping the list alphabetical * for san } } } } /* 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 B to send a BREAK", "\r\n H to hang up the phone", "\r\n S for status", "\r\n 0 to send a null", "\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); conoc(c); ./usr/opt/src/kermit/ckudia.c 644 0 3 55016 5555215354 11306 /* Echo it. */ conoll(""); c &= 0177; /* Strip any parity. */ 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; c &= 0177; while (1) { if (c == escape) { /* char *dialv = "Dial Command, V2.0(007) 28 Jun 85"; /* C K U D I A -- Dialing program for connection to remote system */ /* This module should work under all versions of Unix. It calls externally defined system-depended functions for i/o, but depends upon the existence of various modem control functions. Author: Herm Fischer (HFISCHER@USC-ECLB) Contributed to Columbia University for inclusion in C-Kermit. Copyright (C) 1985, Herman Fischer, 16400 Ventura Blvd #201, Encino CA 91436 Permission isSend 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 */ case '\02': ttsndb(); return; case 'h': /* Hangup */ case '\08': tthang(); active = 0; conol("\r\n"); return; case 's': /* Status */ case '\023': conol("\r\nConnected thru "); conol(ttname); if 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. */ /* * Modifications: * * 28-Jun-85 Fixed bug with defaulting the modem-failure message * in LBUF. * -- Dan Schullman * * 27-Jun-85 Merged in code from Joe Orost at Berkeley for * supporting the US Robotics modem, which included * changing the single characters in MDMINF into * multi-character strings and modifyinCH EARLIER, SIMPLY READING USER INPUT AND * SENDING IT TO THE MODEM AND ECHOING MODEM RESPONSES BACK TO THE USER, * ALL THE TIME LOOKING FOR CARRIER. OF COURSE, THE PROBLEM THEN BECOMES * ONE OF ALLOWING THE USER TO ABORT THE DIALING. WE COULD CHOOSE SOME * PHRASE THAT WOULD PRESUMABLY NEVER BE A PART OF A VALID AUTODIAL SEQUENCE * (E.G., "QUIT" and "quit"). -- DS */ #include "ckcdeb.h" #include #include #include #include #include "ckcker.h" #include "ckucmdEK = /* information for "Cermetek Info-Mate 212 A" modem */ { 20, /* dial_time */ "BbPpTt", /* pause_chars */ 0, /* pause_time */ /** unknown -- DS **/ " XY\016R\r", /* wake_str */ 200, /* wake_rate */ "", /* wake_prompt */ "", /* dmode_str */ "", /* dmode_prompt */ "\016D '%s'\r", /* dial_str */ 200 /* dial_rate */ }; static MDMINF DF03 = /* information for "DEC DF03-AC" modem */ { 27, /* dial_time */ "=", /* pause_chars */ /* .h" extern int flow, local, mdmtyp, quiet, speed; extern char ttname[], sesfil[]; #define MDMINF struct mdminf MDMINF /* structure for modem-specific information */ { int dial_time; /* time modem allows for dialing (secs) */ char *pause_chars; /* character(s) to tell modem to pause */ int pause_time; /* time associated with pause chars (secs) */ char *wake_str; /* string to wakeup modem & put in cmd mode */ int wake_rate; /* delay between wake_str characters (msecs) */ chwait for second dial tone */ 15, /* pause_time */ "\001\002", /* wake_str */ 0, /* wake_rate */ "", /* wake_prompt */ "", /* dmode_str */ "", /* dmode_prompt */ "%s", /* dial_str */ 0 /* dial_rate */ }; static MDMINF DF100 = /* information for "DEC DF100-series" modem */ /* * The telephone "number" can include "P"s and/or "T"s * within it to indicate that subsequent digits are * to be dialed using pulse or tone dialing. The * modem defaar *wake_prompt; /* string prompt after wake_str */ char *dmode_str; /* string to put modem in dialing mode */ char *dmode_prompt; /* string prompt for dialing mode */ char *dial_str; /* dialing string, with "%s" for number */ int dial_rate; /* delay between dialing characters (msecs) */ }; /* * Define symbolic modem numbers. * * The numbers MUST correspond to the ordering of entries * within the ptrtab array, and start at one (1). * * It is assumed that there are relatively few ults to pulse dialing. You may modify * the dial string below to explicitly default all * dialing to pulse or tone, but doing so prevents * the use of phone numbers that you may have stored * in the modem's memory. */ { 30, /* dial_time */ "=", /* pause_chars */ /* wait for second dial tone */ 15, /* pause_time */ "\001", /* wake_str */ 0, /* wake_rate */ "", /* wake_prompt */ "", /* dmode_str */ "", /* dmode_prompt */ "%s#", /* diaity's sake. * * Add the address of the MDMINF structure to the ptrtab array, again * in alphabetical and numerical order. * * Add the "user visible" modem name and corresponding modem number to * the mdmtab array, again in alphabetical order. * * Read through the code and add modem-specific sections as necessary. */ /* * The intent of the "unknown" modem is hopefully to allow KERMIT to support * unknown modems by having the user type the entire autodial sequence * (possibly including control chof these * values, and that the high(er) bytes of the value may * be used for modem-specific mode information. * * REMEMBER that only the first eight characters of these * names are guaranteed to be unique. */ #define n_CERMETEK 1 #define n_DF03 2 #define n_DF100 3 #define n_DF200 4 #define n_GDC 5 #define n_HAYES 6 #define n_PENRIL 7 #define n_RACAL 8 #define n_UNKNOWN 9 #define n_USROBOT 10 #define n_VENTEL 11 /* * Declare modem "variant" numbers for any of the above foraracters, etc.) as the "phone number". * The only reason that the CONNECT command cannot be used to do this is * that a remote line cannot normally be opened unless carrier is present. * * The protocol and other characteristics of this modem are unknown, with * some "reasonable" values being chosen for some of them. The only way to * detect if a connection is made is to look for carrier present. * * SUPPORT IS CURRENTLY ONLY PARTIALLY SKETCHED OUT FOR THIS. ALSO, IT * SHOULD PERHAPS BE HANDLED MU which it is * necessary to note various operational modes, using the second byte * of a modem number. * * It is assumed that such modem modes share the same modem-specific * information (see MDMINF structure) but may differ in some of the actions * that are performed. */ #define n_HAYESNV ( n_HAYES + ( 1<<8 ) ) /* * Declare structures containing modem-specific information. * * REMEMBER that only the first SEVEN characters of these * names are guaranteed to be unique. */ static MDMINF CERMEThe modem's memory. */ { 30, /* dial_time */ "=W", /* pause_chars */ /* =: second tone; W: 5 secs */ 15, /* pause_time */ /* worst case */ "\002", /* wake_str */ /* allow stored number usage */ 0, /* wake_rate */ "", /* wake_prompt */ "", /* dmode_str */ "", /* dmode_prompt */ "%s!", /* dial_str */ 0 /* dial_rate */ }; static MDMINF GDC = /* information for "GeneralDataComm 212A/ED" modem */ { 32, /* dial_time */ "%", /* pon for "Ventel" modem */ { 20, /* dial_time */ "%", /* pause_chars */ 5, /* pause_time */ "\r\r\r", /* wake_str */ 300, /* wake_rate */ "$", /* wake_prompt */ "", /* dmode_str */ "", /* dmode_prompt */ "", /* dial_str */ 0 /* dial_rate */ }; /* * Declare table for converting modem numbers to information pointers. * * The entries MUST be in ascending order by modem number, without any * "gaps" in the numbers, and starting from one (1ause_chars */ 3, /* pause_time */ "\r\r", /* wake_str */ 500, /* wake_rate */ "$", /* wake_prompt */ "D\r", /* dmode_str */ ":", /* dmode_prompt */ "T%s\r", /* dial_str */ 0 /* dial_rate */ }; static MDMINF HAYES = /* information for "Hayes" modem */ { 35, /* dial_time */ ",", /* pause_chars */ 2, /* pause_time */ "AT\r", /* wake_str */ 0, /* wake_rate */ "", /* wake_prompt */ "", /* dmode_str */ "", /* dmode_p). * * This table should NOT include entries for the "variant" modem numbers, * since it is assumed that they share the same information as the normal * value. */ static MDMINF *ptrtab[] = { &CERMETEK, &DF03, &DF100, &DF200, &GDC, &HAYES, &PENRIL, &RACAL, &UNKNOWN, &USROBOT, &VENTEL }; /* * Declare modem names and associated pointers for command parsing, * and also for doing number-to-name translation. * * The entries MUST be in alphabetical orderompt */ "AT DT %s\r", /* dial_str */ 0 /* dial_rate */ }; static MDMINF PENRIL = /* information for "Penril" modem */ { 50, /* dial_time */ "", /* pause_chars */ /** unknown -- HF **/ 0, /* pause_time */ "\r\r", /* wake_str */ 300, /* wake_rate */ ">", /* wake_prompt */ "k\r", /* dmode_str */ ":", /* dmode_prompt */ "%s\r", /* dial_str */ 0 /* dial_rate */ }; static MDMINF RACAL = /* information for "Racal Vadic" modem */ {r by modem name. */ struct keytab mdmtab[] = { "cermetek", n_CERMETEK, 0, "df03-ac", n_DF03, 0, "df100-series", n_DF100, 0, "df200-series", n_DF200, 0, "direct", 0, 0, "gendatacomm", n_GDC, 0, "hayes", n_HAYES, 0, "penril", n_PENRIL, 0, "racalvadic", n_RACAL, 0, "unknown", n_UNKNOWN, 0, "usrobotics-212a", n_USROBOT, 0, "ventel", n_VENTEL, 0 }; int nmdm = (sizeof(mdmtab) / sizeof(struct keytab)); /* number of modems */ #define DIALING 4 / 35, /* dial_time */ "Kk", /* pause_chars */ 5, /* pause_time */ "\005\r", /* wake_str */ 50, /* wake_rate */ "*", /* wake_prompt */ "D\r", /* dmode_str */ "?", /* dmode_prompt */ "%s\r", /* dial_str */ 0 /* dial_rate */ }; static MDMINF UNKNOWN = /* information for "Unknown" modem */ { 30, /* dial_time */ "", /* pause_chars */ 0, /* pause_time */ "", /* wake_str */ 0, /* wake_rate */ "", /* wake_prompt */ * for ttvt parameter */ #define CONNECT 5 #define CONNECTED 1 /* for completion status */ #define FAILED 2 /* * Failure reasons for use with the 'longjmp' exit. */ #define F_time 1 /* timeout */ #define F_int 2 /* interrupt */ #define F_modem 3 /* modem-detected failure */ #define F_minit 4 /* cannot initialize modem */ static int tries = 0; #define LBUFL 100 static char lbuf[LBUFL]; static jmp_buf sjbuf; static int (*savAlrm)(); /* for saving alarm handler */ static int (*savInt)(); /* for l_str */ 0 /* dial_rate */ }; static MDMINF DF200 = /* information for "DEC DF200-series" modem */ /* * The telephone "number" can include "P"s and/or "T"s * within it to indicate that subsequent digits are * to be dialed using pulse or tone dialing. The * modem defaults to pulse dialing. You may modify * the dial string below to explicitly default all * dialing to pulse or tone, but doing so prevents * the use of phone numbers that you may have stored * in t "", /* dmode_str */ "", /* dmode_prompt */ "%s\r", /* dial_str */ 0 /* dial_rate */ }; static MDMINF USROBOT = /* information for "US Robotics 212A" modem */ { 30, /* dial_time */ ",", /* pause_chars */ 2, /* pause_time */ "ATS2=01\r", /* wake_str */ 0, /* wake_rate */ "OK\r", /* wake_prompt */ "", /* dmode_str */ "", /* dmode_prompt */ "ATTD%s\r", /* dial_str */ 0 /* dial_rate */ }; static MDMINF VENTEL = /* informatisaving interrupt handler */ dialtime() { /* timer interrupt handler */ longjmp( sjbuf, F_time ); } dialint() /* user-interrupt handler */ { longjmp( sjbuf, F_int ); } static ttolSlow(s,millisec) char *s; int millisec; { /* output s-l-o-w-l-y */ for (; *s; s++) { ttoc(*s); msleep(millisec); } } /* * Wait for a string of characters. * * The characters are waited for individually, and other characters may * be received "in between". This merely guarantees that the charaf (*i == *j) { waitct += pmdminf->pause_time; break; } printf("Dialing thru %s, speed %d, number %s.\r\n",ttname,speed,telnbr); printf("The timeout for completing the call is %d seconds.\r\n",waitct); printf("Type the interrupt character to abort the dialing.\r\n"); /* Hang up the modem (in case it wasn't "on hook") */ if ( tthang() < 0 ) { printf("Sorry, Can't hang up tty line\n"); return(-2); } /* Condition console terminal and communication linecters * ARE received, and in the order specified. */ static waitFor(s) char *s; { register char *c; while ( c = *s++ ) /* while more characters remain... */ while ( ( ttinc(0) & 0177 ) != c ) ; /* wait for the character */ } static didWeGet(s,r) char *s, *r; { /* Looks in string s for response r */ int lr = strlen(r); /* 0 means not found, 1 means found it */ int i; for (i = strlen(s)-lr; i >= 0; i--) if ( s[i] == r[0] ) if ( !strncmp(s+i,r,lr) ) return( 1 ); ret */ /* place line into "clocal" dialing state */ if ( ttpkt(speed,DIALING) < 0 ) { printf("Sorry, Can't condition communication line\n"); return(-2); } /* * Establish jump vector, or handle "failure" jumps. */ if ( n = setjmp(sjbuf) ) /* if a "failure jump" was taken... */ { reset (); /* reset alarms, etc. */ switch ( n ) /* type of failure */ { case F_time: /* timed out */ { printf ( "No connection made within the allotted time.\r\n" ); break; } urn( 0 ); } /* R E S E T -- Reset alarms, etc. on exit. */ static reset () { alarm(0); signal(SIGALRM,savAlrm); /* restore alarm handler */ signal(SIGINT,savInt); /* restore interrupt handler */ } /* D I A L -- Dial up the remote system */ dial(telnbr) char *telnbr; { char c; char *i, *j; int waitct, status; char errmsg[50], *erp; MDMINF *pmdminf; /* pointer to modem-specific info */ int augmdmtyp; /* "augmented" modem type, to handle modem mode case F_int: /* dialing interrupted */ { printf ( "Dialing interrupted.\r\n" ); break; } case F_modem: /* modem detected a failure */ { printf ( "Failed (\"" ); for ( pc=lbuf; *pc; pc++ ) if ( isprint(*pc) ) putchar(*pc); /* display printable reason */ printf ( "\").\r\n" ); break; } case F_minit: /* cannot initialize modem */ { printf ( "Cannot initialize modem.\r\n" ); break; } } ttclos (); /* hangup and close the line */ return(-2); } s */ int mdmEcho = 0; /* assume modem does not echo */ int n; char *pc; /* pointer to a character */ if (!mdmtyp) { printf("Sorry, you must 'set modem' first\n"); return(-2); } 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) {/* Open, no wait for carrier */ erp = errmsg; sprintf(erp,"Sorry, can't open /* * Set timer and interrupt handlers. */ savAlrm = signal(SIGALRM,dialtime); /* set alarm handler */ if ( ( savInt = signal ( SIGINT, SIG_IGN ) ) != SIG_IGN ) signal ( SIGINT, dialint ); /* set int handler if not ignored */ alarm(10); /* give modem 10 seconds to wake up */ ttflui(); /* flush input buffer if any */ /* * Put modem in command mode. */ #define OKAY 1 /* modem attention attempt status */ #define IGNORE 2 #define GOT_O -2 #define GOT_A -3 switch (augmdmtyp) { %s",ttname); perror(errmsg); return(-2); } pmdminf = ptrtab[mdmtyp-1]; /* set pointer to modem info */ augmdmtyp = mdmtyp; /* initialize "augmented" modem type */ /* cont'd... */ /* interdigit waits for tone dial */ /* ...dial, cont'd */ waitct = 1*strlen(telnbr) ; /* compute time to dial worst case */ waitct += pmdminf->dial_time; /* dialtone + completion wait times */ for (i=telnbr; *i; i++) /* add in pause characters time */ for (j=pmdminf->pause_chars; *j; j++) i case n_HAYES: case n_HAYESNV: while(tries++ < 4) { ttol( HAYES.wake_str, strlen(HAYES.wake_str) ); /* wakeup */ status = 0; while ( status <= 0 ) { switch (ttinc(0) & 0177) { case 'A': /* echoing, ignore */ status = GOT_A; break; case 'T': if (status == GOT_A) { mdmEcho = 1; /* expect echoing later */ status = 0; break; } status = IGNORE; break; case '\n': case '\r': status = 0; break; case '0': /* numericen made. -- DS */ status = 0; strcpy(lbuf,"No Connection"); /* default failure reason */ while (status == 0) { switch (augmdmtyp) { default: for (n=0; n < LBUFL; n++) { /* accumulate response */ lbuf[n] = (ttinc(0) & 0177); if ( lbuf[n] == '\r' || lbuf[n] == '\n' ) break; } lbuf[n] = '\0'; /* terminate response from modem */ if (n) { /* if one or more characters present */ switch (augmdmtyp) { case n_CERMETEK: if (didWeGet(lbuf,"\016A")) { status if (didWeGet(lbuf,"DEAD PHONE")) status = FAILED; break; } } break; case n_DF03: /* because response lacks CR or NL */ c = ttinc(0) & 0177; if ( c == 'A' ) status = CONNECTED; if ( c == 'B' ) status = FAILED; break; case n_HAYESNV: c = ttinc(0) & 0177; if (mdmEcho) { /* sponge up dialing string */ mdmEcho = c!='\r'; /* until return is echoed */ break; } if (c == '1') status = CONNECTED; if (c == '3') status = FAILED; if (c == ' result code */ augmdmtyp = n_HAYESNV; /* nonverbal result codes */ status = OKAY; break; case 'O': /* maybe English result code*/ status = GOT_O; break; case 'K': if (status == GOT_O) { augmdmtyp = n_HAYES; status = OKAY; break; } /* else its default anyway */ default: status = IGNORE; break; } } if (status == OKAY) break; if (status == IGNORE) ttflui(); sleep(1); /* wait before retrying */ } if (status ! = CONNECTED; ttolSlow("\016U 1\r",200); /* make transparent*/ } break; case n_DF100: /* DF100 won't generate some of these */ case n_DF200: if (didWeGet(lbuf,"Attached")) status = CONNECTED; /* * The DF100 will respond with "Attached" even if DTR * and/or carrier are not present. Another reason to * (also) wait for carrier? */ if (didWeGet(lbuf,"Busy")) status = FAILED; if (didWeGet(lbuf,"Disconnected")) status = FAILED; i= 0) break; longjmp( sjbuf, F_minit ); /* modem-initialization failure */ /* cont'd... */ /* interdigit waits for tone dial */ /* ...dial, cont'd */ default: /* place modem into command mode */ ttolSlow(pmdminf->wake_str, pmdminf->wake_rate); if (pmdminf->wake_prompt) waitFor(pmdminf->wake_prompt); break; } alarm(0); /* turn off alarm */ msleep(500); /* give things settling time */ alarm(10); /* alarm on dialing prompts */ /* Dial the number */ /* put modem if (didWeGet(lbuf,"Error")) status = FAILED; if (didWeGet(lbuf,"No answer")) status = FAILED; if (didWeGet(lbuf,"No dial tone")) status = FAILED; if (didWeGet(lbuf,"Speed:")) status = FAILED; /* * It appears that the "Speed:..." response comes after an * "Attached" response, so this is never seen. HOWEVER, * it would be very handy to detect this and temporarily * reset the speed, since it's a nuiscance otherwise. * If we wait for some more input fronto dialing mode */ ttolSlow(pmdminf->dmode_str, pmdminf->dial_rate); if (pmdminf->dmode_prompt) { /* wait for prompt, if any expected */ waitFor(pmdminf->dmode_prompt); msleep(300); } alarm(0); /* turn off alarm on dialing prompts */ alarm(waitct); /* time to allow for connecting */ ttflui(); /* clear out stuff from waking modem up */ sprintf(lbuf, pmdminf->dial_str, telnbr); /* form dialing string */ ttolSlow(lbuf,pmdminf->dial_rate); /* send dialing string */ ifm the modem, how do * we know if it's from the remote host or the modem? * Carrier reportedly doesn't get set until after the * "Speed:..." response (if any) is sent. Another reason * to (also) wait for carrier. */ break; case n_GDC: if (didWeGet(lbuf,"ON LINE")) status = CONNECTED; if (didWeGet(lbuf,"NO CONNECT")) status = FAILED; break; case n_HAYES: case n_USROBOT: if (didWeGet(lbuf,"CONNECT")) status = CONNECTED; if (did (augmdmtyp == n_RACAL) { /* acknowledge printout of dialing string */ sleep(3); ttflui(); ttoc('\r'); } /* cont'd... */ /* interdigit waits for tone dial */ /* ...dial, cont'd */ /* Check for connection */ /* * I believe we also need to look for carrier in order to determine if a * connection has been made. In fact, for many we may only want to look for * the "failure" responses in order to short-circuit the timeout, and let * carrier be the determination of whether a connection has beWeGet(lbuf,"NO CARRIER")) status = FAILED; break; case n_PENRIL: if (didWeGet(lbuf,"OK")) status = CONNECTED; if (didWeGet(lbuf,"BUSY")) status = FAILED; if (didWeGet(lbuf,"NO RING")) status = FAILED; break; case n_RACAL: if (didWeGet(lbuf,"ON LINE")) status = CONNECTED; if (didWeGet(lbuf,"FAILED CALL")) status = FAILED; break; case n_VENTEL: if (didWeGet(lbuf,"ONLINE!")) status = CONNECTED; if (didWeGet(lbuf,"BUSY")) status = FAILED; char *ckzv = "Unix file support, 4C(028) 18 Jun 85"; /* C K U F I O -- Kermit file system support for Unix systems */ /* 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. */ /* Includes */he predefined file numbers from ckermi.h): zopeni(n,name) -- Opens an existing file for input. zopeno(n,name) -- Opens a new file for output. zclose(n) -- Closes a file. zchin(n,&c) -- Gets the next character from an input file. zsout(n,s) -- Write a null-terminated string to output file, buffered. zsoutl(n,s) -- Like zsout, but appends a line terminator. zsoutx(n,s,x) -- Write x characters to output file, unbuffered. zchout(n,c) -- Add a character #include "ckcker.h" /* Kermit definitions */ #include "ckcdeb.h" /* Typedefs, debug formats, etc */ #include /* Character types */ #include /* Standard i/o */ #include /* Data types */ #include /* Directory structure */ #include /* File status */ #include /* Password file for shell name */ /* Berkeley Unix Version 4.x */ /* 4.1bsd support added by Charles E Brooks, EDN-VAX */ #ifdef BSD4 #ifdef MAXNAMLEN #define BSD42 cha to an output file, unbuffered. zchki(name) -- Check if named file exists and is readable, return size. zchko(name) -- Check if named file can be created. znewn(name,s) -- Make a new unique file name based on the given name. zdelet(name) -- Delete the named file. zxpand(string) -- Expands the given wildcard string into a list of files. znext(string) -- Returns the next file from the list in "string". zxcmd(cmd) -- Execute the command in a lower fork. zclos5') status = CONNECTED; break; case n_UNKNOWN: /** SHOULD WAIT FOR CARRIER OR TIMEOUT -- DS **/ break; } /* switch (augmdmtyp) */ } /* while status == 0 */ if ( status != CONNECTED ) /* modem-detected failure */ longjmp( sjbuf, F_modem ); /* exit (with reason in LBUF) */ if ( ! quiet ) printf ( "Call completed.\07\r\n" ); reset (); /* reset alarms, etc. */ ttpkt(speed,CONNECT); /* cancel dialing state ioctl */ return ( 0 ); /* return, and presumablyr *ckzsys = " 4.2 BSD"; #else #define BSD41 char *ckzsys = " 4.1 BSD"; #endif #endif /* 2.9bsd support contributed by Bradley Smith, UCLA */ #ifdef BSD29 char *ckzsys = " 2.9 BSD"; #endif /* Version 7 Unix */ #ifdef V7 char *ckzsys = " Version 7 Unix"; #endif /* DEC Professional-300 series with Venturcom Venix v1 */ #ifdef PROVX1 char *ckzsys = " DEC Pro-3xx/Venix v1"; #endif /* NCR Tower support contributed by John Bray, Auburn, AL. */ /* Tower OS is like Sys III but with BSD features -- mostly follow connect */ } ONNECTED; break; case n_UNKNOWN: /** SHOULD WAIT FOR CARRIER OR TIMEOUT -- DS **/ break; } /* switch (augmdmtyp) */ } /* while status == 0 */ if ( status != CONNECTED ) /* modem-detected failure */ longjmp( sjbuf, F_modem ); /* exit (with reason in LBUF) */ if ( ! quiet ) printf ( "Call completed.\07\r\n" ); reset (); /* reset alarms, etc. */ ttpkt(speed,CONNECT); /* cancel dialing state ioctl */ return ( 0 ); /* return, and presumablys BSD. */ #ifdef TOWER1 char *ckzsys = " NCR Tower 1632, OS 1.02"; #endif /* Sys III/V, Xenix, PC/IX,... support by Herm Fischer, Litton Data Systems */ #ifdef UXIII #ifdef XENIX char *ckzsys = " Xenix/286"; #else #ifdef PCIX char *ckzsys = " PC/IX"; #else #ifdef ISIII char *ckzsys = " Interactive Systems Corp, System III"; #else char *ckzsys = " AT&T System III/System V"; #endif #endif #endif #endif /* Definitions of some Unix system commands */ char *DIRCMD = "ls -l "; /* For directory listing */ char./usr/opt/src/kermit/ckufio.c 644 0 3 57710 5555215354 11331 *DELCMD = "rm -f "; /* For file deletion */ char *TYPCMD = "cat "; /* For typing a file */ char *PWDCMD = "pwd "; /* For saying where I am */ #ifdef BSD4 char *SPACMD = "pwd ; quota ; df ."; /* Space/quota of current directory */ #else char *SPACMD = "df "; #endif char *SPACM2 = "df "; /* For space in specified directory */ #ifdef BSD4 char *WHOCMD = "finger "; /* For seeing who's logged in */ #else char *WHOCMD = "who "; /* For seeing who's logged in */ #endif /* Functions (n is one of t */ NULL, NULL, NULL, NULL, NULL, NULL, NULL }; static int pid; /* pid of child fork */ static int fcount; /* Number of files in wild group */ char *malloc(), *getenv(), *strcpy(); /* System functions */ extern errno; /* System error code */ static char *mtchs[MAXWLD], /* Matches found for filename */ **mtchptr; /* Pointer to current match */ /* Z K S E L F -- Kill Self: log out own job, if possible. */ zkself() { /* For "bye", but no guarantee! */ #ifdef PROVX1 retF, 0 otherwise with character returned in argument */ zchin(n,c) int n; char *c; { int a; if (chkfn(n) < 1) return(-1); a = getc(fp[n]); if (a == EOF) return(-1); *c = a & 0377; return(0); } /* Z S O U T -- Write a string to the given file, buffered. */ zsout(n,s) int n; char *s; { if (chkfn(n) < 1) return(-1); fputs(s,fp[n]); return(0); } /* Z S O U T L -- Write string to file, with line terminator, buffered */ zsoutl(n,s) int n; char *s; { if (chkfn(urn(kill(0,9)); #else #ifdef V7 return(kill(0,9)); #else #ifdef TOWER1 return(kill(0,9)); #else return(kill(getppid(),1)); #endif #endif #endif } /* Z O P E N I -- Open an existing file for input. */ zopeni(n,name) int n; char *name; { debug(F111," zopeni",name,n); debug(F101," fp","",(int) fp[n]); if (chkfn(n) != 0) return(0); if (n == ZSYSFN) { /* Input from a system function? */ debug(F110," invoking zxcmd",name,0); return(zxcmd(name)); /* Try to fork the cn) < 1) return(-1); fputs(s,fp[n]); fputs("\n",fp[n]); return(0); } /* Z S O U T X -- Write x characters to file, unbuffered. */ zsoutx(n,s,x) int n, x; char *s; { if (chkfn(n) < 1) return(-1); return(write(fp[n]->_file,s,x)); } /* Z C H O U T -- Add a character to the given file. */ /* Should return 0 or greater on success, -1 on failure (e.g. disk full) */ zchout(n,c) int n; char c; { if (chkfn(n) < 1) return(-1); if (n == ZSFILE) return(write(fp[n]->_file,ommand */ } if (n == ZSTDIO) { /* Standard input? */ if (isatty(0)) { ermsg("Terminal input not allowed"); debug(F110,"zopeni: attempts input from unredirected stdin","",0); return(0); } fp[ZIFILE] = stdin; return(1); } fp[n] = fopen(name,"r"); /* Real file. */ debug(F111," zopeni", name, (int) fp[n]); if (fp[n] == NULL) perror("zopeni"); return((fp[n] != NULL) ? 1 : 0); } /* Z O P E N O -- Open a new file for output. */ zopeno(n,name) int n; char *nam&c,1)); /* Use unbuffered for session log */ else { /* Buffered for everything else */ if (putc(c,fp[n]) == EOF) /* If true, maybe there was an error */ return(ferror(fp[n])); /* Check to make sure */ else /* Otherwise... */ return(0); /* There was no error. */ } } /* C H K F N -- Internal function to verify file number is ok */ /* Returns: -1: File number n is out of range 0: n is in range, but file is not open 1: n in range and file is open */ chkfn(n) int n; {f() -- Close input file associated with zxcmd()'s lower fork. zrtol(n1,n2) -- Convert remote filename into local form. zltor(n1,n2) -- Convert local filename into remote form. zchdir(dirnam) -- Change working directory. zhome() -- Return pointer to home directory name string. zkself() -- Kill self, log out own job. */ #ifndef PROVX1 #include /* File access */ #endif /* Some systems define these in include files, others don't... */ #ifndee; { debug(F111," zopeno",name,n); if (chkfn(n) != 0) return(0); if ((n == ZCTERM) || (n == ZSTDIO)) { /* Terminal or standard output */ fp[ZOFILE] = stdout; debug(F101," fp[]=stdout", "", (int) fp[n]); return(1); } fp[n] = fopen(name,"w"); /* A real file, try to open */ if (fp[n] == NULL) { perror("zopeno can't open"); } else { chown(name, getuid(), getgid()); /* In case set[gu]id */ if (n == ZDFILE) setbuf(fp[n],NULL); /* Debugging file unbuffered */ f R_OK #define R_OK 4 /* For access */ #endif #ifndef W_OK #define W_OK 2 #endif #ifdef PROVX1 #define MAXNAMLEN DIRSIZ /* Max file name length */ #endif #ifdef UXIII #include #define MAXNAMLEN DIRSIZ #endif #ifndef O_RDONLY #define O_RDONLY 000 #endif #ifndef MAXNAMLEN #define MAXNAMLEN 14 /* If still not defined... */ #endif #ifdef PROVX1 #define MAXWLD 100 /* Maximum wildcard filenames */ #else #define MAXWLD 500 #endif /* Declarations */ FILE *fp[ZNFILS] = { /* File pointers } debug(F101, " fp[n]", "", (int) fp[n]); return((fp[n] != NULL) ? 1 : 0); } /* Z C L O S E -- Close the given file. */ zclose(n) int n; { if (chkfn(n) < 1) return(0); /* Check range of n */ if ((n == ZIFILE) && fp[ZSYSFN]) { /* If system function */ zclosf(); /* do it specially */ } else { if ((fp[n] != stdout) && (fp[n] != stdin)) fclose(fp[n]); fp[n] = NULL; } return(1); } /* Z C H I N -- Get a character from the input file. */ /* Returns -1 if EOn't be accessed, -2 if file exists but is not readable (e.g. a directory file). -3 if file exists but protected against read access. */ /* For Berkeley Unix, a file must be of type "regular" to be readable. Directory files, special files, and symbolic links are not readable. */ long zchki(name) char *name; { struct stat buf; int x; long y; x = stat(name,&buf); if (x < 0) { debug(F111,"zchki stat fails",name,errno); return(-1); } x = buf.st_mode & S_IFMT; /* Isolatlower(*cp)) *pp++ = toupper(*cp); /* Uppercase letters */ else if (*cp == '~') *pp++ = 'X'; /* Change tilde to 'X' */ else if (*cp == '#') *pp++ = 'X'; /* Change number sign to 'X' */ else if ((*cp == '.') && (++dc > 1)) *pp++ = 'X'; /* & extra dots */ else *pp++ = *cp; } *pp = '\0'; /* Tie it off. */ cp = name2; /* If nothing before dot, */ if (*work == '.') *cp++ = 'X'; /* insert 'X' */ strcpy(cp,work); debug(F110," name2",name2,0); } /* Z C H D I R -- Change dire file format field */ if ((x != 0) && (x != S_IFREG)) { debug(F111,"zchki skipping:",name,x); return(-2); } debug(F111,"zchki stat ok:",name,x); if ((x = access(name,R_OK)) < 0) { /* Is the file accessible? */ debug(F111," access failed:",name,x); /* No */ return(-3); } else { y = buf.st_size; debug(F111," access ok:",name,(int) y); /* Yes */ return( (y > -1) ? y : 0 ); } } /* Z C H K O -- Check if output file can be created */ /* Returns -1 if write permissectory */ zchdir(dirnam) char *dirnam; { char *hd; if (*dirnam == '\0') hd = getenv("HOME"); else hd = dirnam; return((chdir(hd) == 0) ? 1 : 0); } /* Z H O M E -- Return pointer to user's home directory */ char * zhome() { return(getenv("HOME")); } /* Z X C M D -- Run a system command so its output can be read like a file */ zxcmd(comand) char *comand; { int pipes[2]; if (pipe(pipes) != 0) return(0); /* can't make pipe, fail */ if ((pid = fork()) == 0) { /* chiion for the file would be denied, 0 otherwise. */ zchko(name) char *name; { int i, x; char s[50], *sp; sp = s; /* Make a copy, get length */ x = 0; while ((*sp++ = *name++) != '\0') x++; if (x == 0) return(-1); /* If no filename, fail. */ debug(F101," length","",x); for (i = x; i > 0; i--) /* Strip filename. */ if (s[i-1] == '/') break; debug(F101," i","",i); if (i == 0) /* If no path, use current directory */ strcpy(s,"./"); else ld */ /*#if BSD4*/ /* Code from Dave Tweten@AMES-NAS */ /* readapted to use getpwuid to find login shell */ /* -- H. Fischer */ char *shpath, *shname, *shptr; /* to find desired shell */ struct passwd *p; extern struct passwd * getpwuid(); extern int getuid(); char *defShel = "/bin/sh"; /* default shell */ /*#endif*/ close(pipes[0]); /* close input side of pipe */ close(0); /* close stdin */ if (open("/dev/null",0) < 0) return(0); /* replace input by null */ #ifndef UXIII dup2(pipes[/* Otherwise, use given one. */ s[i] = '\0'; x = access(s,W_OK); /* Check access of path. */ if (x < 0) { debug(F111,"zchko access failed:",s,errno); return(-1); } else { debug(F111,"zchko access ok:",s,x); return(0); } } /* Z D E L E T -- Delete the named file. */ zdelet(name) char *name; { unlink(name); } /* Z R T O L -- Convert remote filename into local form */ /* For UNIX, this means changing uppercase letters to lowercase. */ zrtol(name,name2) char 1],1); /* replace stdout & stderr */ dup2(pipes[1],2); /* by the pipe */ #else close(1); /* simulate dup2 */ if (dup(pipes[1]) != 1 ) conol("trouble duping stdout in routine zxcmd\n"); close(2); /* simulate dup2 */ if (dup(pipes[1]) != 2 ) conol("trouble duping stderr in routine zxcmd\n"); #endif close(pipes[1]); /* get rid of this copy of the pipe */ /**** shptr = shname = shpath = getenv("SHELL"); /* What shell? */ p = getpwuid( getuid() ); /* get login data */ if ( p == (stru switch (n) { case ZCTERM: case ZSTDIO: case ZIFILE: case ZOFILE: case ZDFILE: case ZTFILE: case ZPFILE: case ZSFILE: case ZSYSFN: break; default: debug(F101,"chkfn: file number out of range","",n); fprintf(stderr,"?File number out of range - %d\n",n); return(-1); } return( (fp[n] == NULL) ? 0 : 1 ); } /* Z C H K I -- Check if input file exists and is readable */ /* Returns: >= 0 if the file can be read (returns the size). -1 if file doesn't exist or ca*name, *name2; { for ( ; *name != '\0'; name++) { *name2++ = isupper(*name) ? tolower(*name) : *name; } *name2 = '\0'; } /* Z L T O R -- Local TO Remote */ /* Convert filename from local format to common (remote) form. */ zltor(name,name2) char *name, *name2; { char work[100], *cp, *pp; int dc = 0; debug(F110,"zltor",name,0); pp = work; for (cp = name; *cp != '\0'; cp++) { /* strip path name */ if (*cp == '/') { dc = 0; pp = work; } else if (isct passwd *) NULL || !*(p->pw_shell) ) shpath = defShel; else shpath = p->pw_shell; shptr = shname = shpath; while (*shptr != '\0') if (*shptr++ == '/') shname = shptr; debug(F100,"zxcmd...","",0); debug(F110,shpath,shname,0); execl(shpath,shname,"-c",comand,0); /* Execute the command */ /**** execl("/bin/sh","sh","-c",comand,0); /* Execute the command */ exit(0); /* just punt if it didnt work */ } close(pipes[1]); /* don't need the output side */ fp[ZIFILE] = fdopen(pipes[0],"r")arated segment of the name is kept in one * such structure, and they are linked together, to make * traversing the name easier. */ struct path { char npart[MAXNAMLEN]; /* name part of path segment */ struct path *fwd; /* forward ptr */ }; #define SSPACE 2000 /* size of string-generating buffer */ static char sspace[SSPACE]; /* buffer to generate names in */ static char *freeptr,**resptr; /* copies of caller's arguments */ static int remlen; /* open a stream for it */ fp[ZSYSFN] = fp[ZIFILE]; /* Remember. */ return(1); } /* Z C L O S F - wait for the child fork to terminate and close the pipe. */ zclosf() { int wstat; fclose(fp[ZIFILE]); fp[ZIFILE] = fp[ZSYSFN] = NULL; while ((wstat = wait(0)) != pid && wstat != -1) ; } /* Z X P A N D -- Expand a wildcard string into an array of strings */ /* Returns the number of files that match fn1, with data structures set up so that first file (if any) will be retu; /* remaining length in caller's array*/ static int numfnd; /* number of matches found */ /* * splitpath: * takes a string and splits the slash-separated portions into * a list of path structures. Returns the head of the list. The * structures are allocated by malloc, so they must be freed. * Splitpath is used internally by the filename generator. * * Input: A string. * Returns: A linked list of the slash-separated segments of the input. */ struct rned by the next znext() call. */ zxpand(fn) char *fn; { fcount = fgen(fn,mtchs,MAXWLD); /* Look up the file. */ if (fcount > 0) { mtchptr = mtchs; /* Save pointer for next. */ } debug(F111,"zxpand",mtchs[0],fcount); return(fcount); } /* Z N E X T -- Get name of next file from list created by zxpand(). */ /* Returns >0 if there's another file, with its name copied into the arg string, or 0 if no more files in list. */ znext(fn) char *fn; { if (fcount-- > 0) strcpy(fn,*mtchptpath * splitpath(p) char *p; { struct path *head,*cur,*prv; int i; head = prv = NULL; if (*p == '/') p++; /* skip leading slash */ while (*p != '\0') { cur = (struct path *) malloc(sizeof (struct path)); if (!cur) fatal("malloc fails in splitpath()"); cur -> fwd = NULL; if (head == NULL) head = cur; else prv -> fwd = cur; /* link into chain */ prv = cur; for (i=0; i < MAXNAMLEN && *p != '/' && *p != '\0'; i++) cur -> npart[i] = *p++; cur -> npart[i] = '\0'r++); else *fn = '\0'; debug(F111,"znext",fn,fcount+1); return(fcount+1); } /* Z N E W N -- Make a new name for the given file */ znewn(fn,s) char *fn, **s; { static char buf[100]; char *bp, *xp; int len = 0, n = 0, d = 0, t; #ifdef MAXNAMLEN int max = MAXNAMLEN; #else int max = 14; #endif bp = buf; while (*fn) { /* Copy name into buf */ *bp++ = *fn++; len++; } if (len > max-3) bp -= 3; /* Don't let it get too long */ *bp++ = '*'; /* Put a ; /* end this segment */ if (i >= MAXNAMLEN) while (*p != '/' && *p != '\0') p++; if (*p == '/') p++; } return(head); } /* * fgen: * This is the actual name generator. It is passed a string, * possibly containing wildcards, and an array of character pointers. * It finds all the matching filenames and stores them into the array. * The returned strings are allocated from a static buffer local to * this module (so the caller doesn't have to worry about deallocating * them); this mstar on the end */ *bp-- = '\0'; n = zxpand(buf); /* Expand the resulting wild name */ while (n-- > 0) { /* Find any existing name~d files */ xp = *mtchptr++; xp += len; if (*xp == '~') { t = atoi(xp+1); if (t > d) d = t; /* Get maximum d */ } } sprintf(bp,"~%d",d+1); /* Make name~(d+1) */ *s = buf; } /* Directory Functions for Unix, written by Jeff Damens, CUCCA, 1984. */ /* * The path structure is used to represent the name to match. * Each slash-sepeans that successive calls to fgen will wipe out * the results of previous calls. This isn't a problem here * because we process one wildcard string at a time. * * Input: a wildcard string, an array to write names to, the * length of the array. * Returns: the number of matches. The array is filled with filenames * that matched the pattern. If there wasn't enough room in the * array, -1 is returned. * By: Jeff Damens, CUCCA, 1984. */ fgen(pat,resarry,len) char *pat,*resarrruct direct dir_entry; struct direct *dirbuf = &dir_entry; #endif struct stat statbuf; if (pl == NULL) { *--endcur = '\0'; /* end string, overwrite trailing / */ addresult(sofar); return; } if (!iswild(pl -> npart)) { strcpy(endcur,pl -> npart); endcur += strlen(pl -> npart); *endcur = '\0'; /* end current string */ if (stat(sofar,&statbuf) == 0) /* if current piece exists */ { *endcur++ = '/'; /* add slash to end */ rue if the pattern * matches the string, false otherwise. * by: Jeff Damens, CUCCA * * Input: a string and a wildcard pattern. * Returns: 1 if match, 0 if no match. */ match(pattern,string) char *pattern,*string; { char *psave,*ssave; /* back up pointers for failure */ psave = ssave = NULL; while (1) { for (; *pattern == *string; pattern++,string++) /* skip first */ if (*string == '\0') return(1); /* end of strings, succeed */ if (*string != '\0' && *pattern == '?') { patty[]; int len; { struct path *head; char scratch[100],*sptr; head = splitpath(pat); if (*pat == '/') { scratch[0] = '/'; sptr = scratch+1; } else { strcpy(scratch,"./"); sptr = scratch+2; } /* init buffer correctly */ numfnd = 0; /* none found yet */ freeptr = sspace; /* this is where matches are copied */ resptr = resarry; /* static copies of these so*/ remlen = len; /* recursive calls can alter them */ traverse(head,scratch,sptr); /* go walk the *endcur = '\0'; /* and end the string */ traverse(pl -> fwd,sofar,endcur); } return; } /* cont'd... */ /*...traverse, cont'd */ /* segment contains wildcards, have to search directory */ *endcur = '\0'; /* end current string */ if (stat(sofar,&statbuf) == -1) return; /* doesn't exist, forget it */ if ((statbuf.st_mode & S_IFDIR) == 0) return; /* not a directory, skip */ #ifdef BSD42 /* ==BSD4 */ if ((fd = opendir(sofar)) == NULL) return; /* can't open, fdirectory tree */ for (; head != NULL; head = head -> fwd) free(head); /* return the path segments */ return(numfnd); /* and return the number of matches */ } /* traverse: * Walks the directory tree looking for matches to its arguments. * The algorithm is, briefly: * If the current pattern segment contains no wildcards, that * segment is added to what we already have. If the name so far * exists, we call ourselves recursively with the next segment * in the pattern string; otherorget it */ while (dirbuf = readdir(fd)) #else if ((fd = open(sofar,O_RDONLY)) < 0) return; /* can't open, forget it */ while ( read(fd,dirbuf,sizeof dir_entry) ) #endif if (dirbuf->d_ino != 0 && match(pl -> npart,dirbuf->d_name)) { char *eos; strcpy(endcur,dirbuf->d_name); eos = endcur + strlen(dirbuf->d_name); *eos = '/'; /* end this segment */ traverse(pl -> fwd,sofar,eos+1); } #ifdef BSD42 /* ==BSD4 */ closedir(fd); #else close(fd); #endif } /* * awise, we just return. * * If the current pattern segment contains wildcards, we open the name * we've accumulated so far (assuming it is really a directory), then read * each filename in it, and, if it matches the wildcard pattern segment, add * that filename to what we have so far and call ourselves recursively on the * next segment. * * Finally, when no more pattern segments remain, we add what's accumulated * so far to the result array and increment the number of matches. * * Inddresult: * Adds a result string to the result array. Increments the number * of matches found, copies the found string into our string * buffer, and puts a pointer to the buffer into the caller's result * array. Our free buffer pointer is updated. If there is no * more room in the caller's array, the number of matches is set to -1. * Input: a result string. * Returns: nothing. */ addresult(str) char *str; { int l; if (strncmp(str,"./",2) == 0) str += 2; if (--remlen < 0) { numfnd = -1put: a pattern path list (as generated by splitpath), a string * pointer that points to what we've traversed so far (this * can be initialized to "/" to start the search at the root * directory, or to "./" to start the search at the current * directory), and a string pointer to the end of the string * in the previous argument. * Returns: nothing. */ traverse(pl,sofar,endcur) struct path *pl; char *sofar,*endcur; { #ifdef BSD42 DIR *fd, *opendir(); struct direct *dirbuf; #else int fd; st; return; } l = strlen(str) + 1; /* size this will take up */ if ((freeptr + l) > &sspace[SSPACE]) { numfnd = -1; /* do not record if not enough space */ return; } strcpy(freeptr,str); *resptr++ = freeptr; freeptr += l; numfnd++; } iswild(str) char *str; { char c; while ((c = *str++) != '\0') if (c == '*' || c == '?') return(1); return(0); } /* * match: * pattern matcher. Takes a string and a pattern possibly containing * the wildcard characters '*' and '?'. Returns t systems, "make is3" # for DEC Pro-350 with Pro/Venix V1.x, "make provx1" # for DEC Pro-350 with Pro/Venix V2.0 (Sys V), "make sys3nid" # for DEC Pro-380 with Pro/Venix V2.0 (Sys V), "make sys3" or "make sys3nid" # for NCR Tower 1632, OS 1.02, "make tower1" # ############################################################################## # # Notes: # # In many cases, the -O (optimize) compiler switch is omitted. Feel free # to add it if you trust your optimizer. # # "make bsd" should produce a working Coption to # the link flags. Without I&D space, overlays would probably have to be # used (or code mapping a`la Pro/Venix if that's available). # # For HP9000 series 500, use "make sys3nid", but # 1. In ckutio.c, don't #include or ioctl.h. # 2. In ckufio.c, don't #include . # # For Ridge32 (ROS3.2), use "make sys3", but # 1. Use "CFLAGS = -DUXIII -i -O" "LNKFLAGS = -i" # 2. Don't #include in cku[tf]io.c. # ########################################################-Kermit for both 4.1 and 4.2bsd # on VAX, SUN, and Pyramid computers. # # "make sys3" seems to produce a working version on any ATT System III # or System V system, including Motorola Four Phase, Callan Unistar, Cadmus, # NCR Tower, HP9836 Series 200, Plexus, Masscomp/RTU, etc etc (for # exceptions, see below; AT&T 3Bx systems have their own entry). # # For version 7, several variables must be defined to the values # associated with your system. BOOTNAME=/edition7 is the kernel image on # okstate'###################### # # V7-specific variables. # These are set up for Perkin-Elmer 3230 V7 Unix: # PROC=proc DIRECT= NPROC=nproc NPTYPE=int BOOTFILE=/edition7 # # ( For TRS-80 Xenix, use PROC=_proc, DIRECT=-DDIRECT, NPROC=_Nproc, # NPTYPE=short, BOOTFILE=/xenix ) # ########################################################################### # # Compile and Link variables: # LNKFLAGS= CC= cc CC2= cc # ########################################################################### # make: @echo 'Make wern++; /* '?', let it match */ string++; } else if (*pattern == '*') { /* '*' ... */ psave = ++pattern; /* remember where we saw it */ ssave = string; /* let it match 0 chars */ } else if (ssave != NULL && *ssave != '\0') { /* if not at end */ /* ...have seen a star */ string = ++ssave; /* skip 1 char from string */ pattern = psave; /* and back up pattern */ } else return(0); /* otherwise just fail */ } } */ if (*string != '\0' && *pattern == '?') { patts Perkin-Elmer 3230. Others will probably be /unix. PROCNAME=proc # is the name of the structure assigned to each process on okstate's system. # This may be "_proc" or some other variation. See for more info # on your systems name conventions. NPROCNAME=nproc is the name of a # Kernal variable that tells how many "proc" structures there are. Again # this may be different on your system, but nproc will probably be somewhere. # The variable NPTYPE is the type of the nproc variable -- i./usr/opt/src/kermit/ckuker.mak 644 0 3 15071 5555215354 11655 nt, short, etc. # which can probably be gleaned from . # The definition of DIRECT is a little more in depth. If nlist() returns, # for "proc" only, the address of the array, then you should define DIRECT # as it is below. If however, nlist() returns the address of a pointer to # the array, then you should give DIRECT a null definition (DIRECT= ). The # extern declaration in should clarify this for you. If it # is "extern struct proc *proc", then you should NOT define DIR# CKUKER.MAK, Version 2.00 # # Makefile to build C-Kermit for various Unix and Unix-like systems # # Rename to "makefile" or "Makefile" before using, then: # # for Berkeley Unix 4.x, "make bsd" # for Berkeley Unix 2.9 (PDP-11), "make bsd29" # for AT&T 3Bx systems, "make 3bx" # for AT&T generic System III/System V, "make sys3" # for Bell Unix Version 7 (aka 7th Edition), "make v7" # for Microsoft Xenix (/286, PC/AT, etc), "make xenix" # for Interactive (PC/IX) on PC/XT, "make pcix" # for Interactive on otherECT. If it # is "extern struct proc proc[]", then you should probably define DIRECT as # it is below. See ckuv7.hlp for further information. # # For 2.9bsd, the makefile uses pcc rather than cc for compiles; that's what # the CC and CC2 definitions are for. 2.9 support basically follows the 4.2 # path, except with a normal file system (file names 14 chars max). # # The v7 and 2.9bsd versions assume I&D space on a PDP-11. When building # C-Kermit for v7 on a PDP-11, you should probably add the -i 7: make wermit "CFLAGS=-DV7 -DDEBUG -DTLOG -DPROCNAME=\\\"$(PROC)\\\" \ -DBOOTNAME=\\\"$(BOOTFILE)\\\" -DNPROCNAME=\\\"$(NPROC)\\\" \ -DNPTYPE=$(NPTYPE) $(DIRECT)" #Berkeley Unix 4.1 or 4.2 bsd: make wermit "CFLAGS= -DBSD4 -DDEBUG -DTLOG" #Berkeley Unix 2.9 for PDP-11s with I&D space bsd29: make wermit "CFLAGS= -DV7 -DDEBUG -DTLOG" "LNKFLAGS= -i" "CC= pcc " \ "CC2= cc" #Microsoft "Xenix/286" e.g. for IBM PC/AT xenix: make wermit "CFLAGS= -DXENIX -DUXIII -DDEBUG -DTLOG -F 3000 -i" \ "LNKFLAGS =char *loginv = "Script Command, V2.0(006)+1 26 Jun 85"; /* 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 ke -F 3000 -i" #PC/IX, Interactive Corp System III for IBM PC/XT pcix: make wermit \ "CFLAGS= -DPCIX -DUXIII -DISIII -DDEBUG -DTLOG -Dsdata=sdatax -O -i" \ "LNKFLAGS = -i" #Interactive Corp System III port in general -- is3: make wermit \ "CFLAGS = -DISIII -DUXIII -DDEBUG -DTLOG -Ddata=datax -O -i" \ "LNKFLAGS = -i" #AT&T 3B-series computers running System V #...only difference from sys3 is lock file stuff... # 3bx: make wermit "CFLAGS = -DUXIII -D3BX -DDEBUG -DTLOG -i -O" \ "LNKFLAGS = -i" #pyword 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. lain old Bell System III or System V without strange things (with I&D space) sys3: make wermit "CFLAGS = -DUXIII -DDEBUG -DTLOG -i -O" "LNKFLAGS = -i" #plain old Bell System III or System V without strange things (no I&D space) sys3nid: make wermit "CFLAGS = -DUXIII -DDEBUG -DTLOG -O" "LNKFLAGS =" #DEC Pro-3xx with Pro/Venix V1.0 or V1.1 provx1: make wart "CFLAGS= -DPROVX1" "LNKFLAGS= " make wermit "CFLAGS = -DPROVX1 -DDEBUG -DTLOG -md780" \ "LNKFLAGS= -u _sleep -lc -md780" #NCR Tower 1632, OS 1.02 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 #include #include #include #include "ckcker.h" extern int local, speed, hat? You must tell which system to make C-Kermit for.' 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 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. tower1: make wermit "CFLAGS = -DDEBUG -DTLOG -DTOWER1" gs (with I&D space) sys3: make wermit "CFLAGS = -DUXIII -DDEBUG -DTLOG -i -O" "LNKFLAGS = -i" #plain old Bell System III or System V without strange things (no I&D space) sys3nid: make wermit "CFLAGS = -DUXIII -DDEBUG -DTLOG -O" "LNKFLAGS =" #DEC Pro-3xx with Pro/Venix V1.0 or V1.1 provx1: make wart "CFLAGS= -DPROVX1" "LNKFLAGS= " make wermit "CFLAGS = -DPROVX1 -DDEBUG -DTLOG -md780" \ "LNKFLAGS= -u _sleep -lc -md780" #NCR Tower 1632, OS 1.02c ckucmd.h ckcker.h ckuusr.h ckcdeb.h ckucmd.o: ckucmd.c ckucmd.h ckcdeb.h ckcpro.o: ckcpro.c ckcker.h ckcdeb.h ckcpro.c: ckcpro.w wart ./wart ckcpro.w ckcpro.c ckcfns.o: ckcfns.c ckcker.h ckcdeb.h ckcfn2.o: ckcfns.c ckcker.h ckcdeb.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 ckuscr.o: ckuscr.c ckcker.h ckcdeb.h #Version 7 Unix v./usr/opt/src/kermit/ckuscr.c 644 0 3 20525 5555215354 11335 _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)","",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 (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); s; i 0) { for ( sb=seq_buf; *sb; sb++) *sb = dopar(*sb); ttol(seq_buf,l); /* with parity */ } if (!no_cr) ttoc( 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 */ } } /* L O G I(++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); N -- Login to remote system */ login(cmdstr) char *cmdstr; { int (*saveAlm)(); /* save incomming 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); retflow, seslog, mdmtyp; 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 300 /* Login Sequence buffer */ static char seq_buf[SBUFL], *s; static int got_it, no_cr; /* connect state parent/child communication signal handlers */ static jmp /* 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[300]; 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 sequenceurn(-2); } printf("Executing script thru %s, speed %d.\r\n",ttname,speed); *seq_buf=0; for (e=s; *e; e++) strcat(seq_buf, chstr(*e) ); printf("The logon string is: %s\r\n",seq_buf); tlog(F110,"Logon command 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); ttflui()char *ckxv = "Unix tty I/O, 4C(029)+1, 26 Jun 85"; /* C K U T I O */ /* C-Kermit interrupt, terminal control & i/o functions for Unix systems */ /* 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 ; /* 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 */ ttflui(); /* flush out input buffer */ retained. */ /* Includes for all Unixes (conditional includes come later) */ #include /* Types */ #include /* Directory */ #include /* Character types */ #include /* Unix Standard i/o */ #include /* Interrupts */ #include /* Longjumps */ #include "ckcdeb.h" /* Typedefs, formats for debug() */ /* Maximum length for the name of a tty device */ #ifndef DEVNAMLEN #define DEVNAMLEN 25 #endif /* 4.1 BSD support added by Charles 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 */ ttflui(); /* Flush */ if (*s) if (outSeq()) goto failRet; /* if any */ } signal(SIGALRM,saveAlm); printf("Logged on!\r\n"); tlog(F100,"Logged on!","",0l); return(0); failRet: E. Brooks, EDN-VAX */ #ifdef BSD4 #define ANYBSD #undef DIRSIZ #define DIRSIZ (sizeof(struct direct)) #ifdef MAXNAMLEN #define BSD42 char *ckxsys = " 4.2 BSD"; #else #define BSD41 char *ckxsys = " 4.1 BSD"; #endif #endif /* 2.9bsd support contributed by Bradley Smith, UCLA */ #ifdef BSD29 #define ANYBSD char *ckxsys = " 2.9 BSD"; #endif /* Version 7 UNIX support contributed by Gregg Wonderly, Oklahoma State University: gregg@okstate.csnet */ #ifdef V7 char *ckxsys = " Version 7 UNIX (tm)"; #endif V7 signal(SIGALRM,saveAlm); printf("Sorry, logon failed\r\n"); tlog(F100,"Logon failed","",0l); return(-2); } /* C H S T R -- Make printable string from a character */ 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); } (*s) if (outSeq()) goto failRet; /* if any */ } signal(SIGALRM,saveAlm); printf("Logged on!\r\n"); tlog(F100,"Logged on!","",0l); return(0); failRet: #ifdef PROVX1 char *ckxsys = " Pro-3xx Venix v1"; #endif /* Tower support contributed by John Bray, Auburn, Alabama */ #ifdef TOWER1 char *ckxsys = " NCR Tower 1632, OS 1.02"; #endif /* Sys III/V, Xenix, PC/IX support by Herm Fischer, Encino, CA */ #ifdef UXIII #ifdef XENIX char *ckxsys = " Xenix/286"; #else #ifdef PCIX char *ckxsys = " PC/IX"; #else #ifdef ISIII char *ckxsys = " Interactive Systems Corp System III"; #else char *ckxsys = " AT&T System III/System V"; #endif #endif #endif #endif /* Note ./usr/opt/src/kermit/ckutio.c 644 0 3 122074 5555215354 11363 - KERLD is the Berkeley Unix Berknet line driver, modified to pass through all 8 bits, and to allow an arbitrary break character to be set. Don't define this symbol unless you have made this modification to your 4.2BSD kernel! */ #ifdef BSD4 /* #define KERLD */ /* <-- note, commented out */ #endif /* Variables available to outside world: dftty -- Pointer to default tty name string, like "/dev/tty". dfloc -- 0 if dftty is console, 1 if external line. dfprty -- Default parity dfflow --bin(esc) -- Put the console in binary (raw) mode. conres() -- Restore the console to mode obtained by congm(). conoc(c) -- Unbuffered output, one character to console. conol(s) -- Unbuffered output, null-terminated string to the console. conola(s) -- Unbuffered output, array of strings to the console. conxo(n,s) -- Unbuffered output, n characters to the console. conchk() -- Check if characters available at console (bsd 4.2). Check if escape char (^\) typed at console (System III/V). scriptor */ static char escchr; /* Escape or attn character */ #ifdef KERLD static int kerld = 1; /* Special Kermit line discipline... */ struct tchars oldc, newc; /* Special characters */ int ld = NETLDISC; /* Special Kermit line discipline */ int oldld; /* Old discipline */ #else static int kerld = 0; /* for 4.2BSD only, */ #endif #ifdef BSD42 static struct timeval tv; /* For getting time, from sys/time.h */ static struct timezone tz; #endif #ifdef BSD29 stati Default flow control ckxech -- Flag for who echoes console typein: 1 - The program (system echo is turned off) 0 - The system (or front end, or terminal). functions that want to do their own echoing should check this flag before doing so. flfnam -- Name of lock file, including its path, e.g., "/usr/spool/uucp/LCK..cul0" or "/etc/locks/tty77" hasLock -- Flag set if this kermit established a uucp lock. inbufc -- number of tty line rawmode unread characters (system III/V unix coninc(timo) -- Timed get a character from the console. conint() -- Enable terminal interrupts on the console if not background. connoi() -- Disable terminal interrupts on the console if not background. Time functions msleep(m) -- Millisecond sleep ztime(&s) -- Return pointer to date/time string */ /* Conditional Includes */ #ifndef PROVX1 #include /* File information */ #endif #ifdef UXIII #include #include #include /* directory res) backgrd -- Flag indicating program executing in background ( & on end of shell command). Used to ignore INT and QUIT signals. Functions for assigned communication line (either external or console tty): ttopen(ttname,local,mdmtyp) -- Open the named tty for exclusive access. ttclos() -- Close & reset the tty, releasing any access lock. ttpkt(speed,flow) -- Put the tty in packet mode and set the speed. ttvt(speed,flow) -- Put the tty in virtual terminal modeeading for locking */ #include /* error numbers for system returns */ extern int errno; /* system call error return */ #endif #ifndef UXIII #include /* Set/Get tty modes */ #ifndef PROVX1 #ifndef V7 #ifndef BSD41 #include /* Clock info (for break generation) */ #endif #endif #endif #endif #ifdef BSD41 #include /* BSD 4.1 ... ceb */ #endif #ifdef TOWER1 #include /* Clock info for NCR Tower */ #endif /* Declarations */ #ifdef V7 i. or in DIALING or CONNECTED modem control state. ttinl(dest,max,timo) -- Timed read line from the tty. ttinc(timo) -- Timed read character from tty. myread() -- System 3 raw mode bulk buffer read, gives -- subsequent chars one at a time and simulates -- FIONREAD! myunrd(c) -- Places c back in buffer to be read (one only) ttchk() -- See how many characters in tty input buffer. ttxin(n,buf) -- Read n characters from tty (nt kmem[2] = { -1, -1}; char *initrawq(), *qaddr[2]={0,0}; #define CON 0 #define TTY 1 #endif /* dftty is the device name of the default device for file transfer */ /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */ #ifdef PROVX1 char *dftty = "/dev/com1.dout"; int dfloc = 1; #else char *dftty = CTTNAM; int dfloc = 0; #endif int dfprty = 0; /* Parity (0 = none) */ int dfflow = 1; /* Xon/Xoff flow control */ int backgrd = 0; /* Assume in foreguntimed). ttol(string,length) -- Write a string to the tty. ttoc(c) -- Write a character to the tty. ttflui() -- Flush tty input buffer. ttlock(ttname) -- Lock against uucp collisions (Sys III) ttunlck() -- Unlock " " " look4lk(ttname) -- Check if a lock file exists */ /* Functions for console terminal: congm() -- Get console terminal modes. concb(esc) -- Put the console in single-character wakeup mode with no echo. conround (no '&' ) */ int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */ /* Declarations of variables global within this module */ static char *brnuls = "\0\0\0\0\0\0\0"; /* A string of nulls */ static jmp_buf sjbuf, jjbuf; /* Longjump buffer */ static int lkf = 0, /* Line lock flag */ conif = 0, /* Console interrupts on/off flag */ cgmf = 0, /* Flag that console modes saved */ xlocal = 0, /* Flag for tty local or remote */ ttyfd = -1; /* TTY file de the job's controlling terminal. But watch out: if a line is already open, or if requested line can't be opened, then lcl remains (and is returned as) -1. */ ttopen(ttname,lcl,modem) char *ttname; int *lcl, modem; { #ifdef UXIII char *ctermid(); /* Wish they all had this! */ #endif char *x; extern char* ttyname(); char cname[DEVNAMLEN]; if (ttyfd > -1) return(0); /* If already open, ignore this call */ xlocal = *lcl; /* Make this available to other fns */ #ifndef UXIII tt *lcl = xlocal; /* Some special stuff for v7... */ #ifdef V7 if (kmem[TTY] < 0) { /* If open, then skip this. */ qaddr[TTY] = initrawq(ttyfd); /* Init the queue. */ if ((kmem[TTY] = open("/dev/kmem", 0)) < 0) { fprintf(stderr, "Can't read /dev/kmem in ttopen.\n"); perror("/dev/kmem"); exit(1); } } #endif V7 #ifdef TOWER1 if (ioctl(ttyfd,TIOCEXCL, NULL) < 0) fprintf(stderr,"Warning, problem getting exclusive access\n"); #endif #ifdef PROVX1 if (ioctl(ttyfd,TIOCEXCL, NULL)yfd = open(ttname,2); /* Try to open for read/write */ #else /* if modem connection, don't wait for carrier */ ttyfd = open(ttname,O_RDWR | (modem ? O_NDELAY : 0) ); #endif if (ttyfd < 0) { /* If couldn't open, fail. */ return(-1); } strncpy(ttnmsv,ttname,DEVNAMLEN); /* Open, keep copy of name locally. */ /* Caller wants us to figure out if line is controlling tty */ debug(F111,"ttopen",ttname,*lcl); if (*lcl == -1) { if (strcmp(ttname,CTTNAM) == 0) { /* "/dev/tty" alwa < 0) fprintf(stderr,"Warning, problem getting exclusive access\n"); #endif #ifdef V7 if (ioctl(ttyfd,TIOCEXCL, NULL) < 0) fprintf(stderr,"Warning, problem getting exclusive access\n"); #endif #ifndef UXIII gtty(ttyfd,&ttold); /* Get sgtty info */ gtty(ttyfd,&ttraw); /* And a copy of it for packets*/ gtty(ttyfd,&tttvt); /* And one for virtual tty service */ #else ioctl(ttyfd,TCGETA,&ttold); /* Same deal for Sys III, Sys V */ ioctl(ttyfd,TCGETA,&ttraw); ioctl(ttc struct timeval tv; /* For getting time, from sys/time.h */ static struct timezone tz; /* Same as 4.2 */ #endif #ifdef BSD41 static long clock; /* For getting time from sys/time.h */ static struct timeb ftp; /* And from sys/timeb.h */ #endif #ifdef TOWER1 static long clock; /* For getting time from sys/time.h */ static struct timeb ftp; /* And from sys/timeb.h */ #endif #ifdef V7 static long clock; #endif #ifdef UXIII static struct termio /* sgtty info... */ ttold, ttraw, tys remote */ debug(F110," Same as CTTNAM",ttname,0); xlocal = 0; } else if (isatty(0)) { /* Else, if stdin not redirected */ x = ttyname(0); /* then compare its device name */ strncpy(cname,x,DEVNAMLEN); /* (copy from internal static buf) */ debug(F110," ttyname(0)",x,0); x = ttyname(ttyfd); /* ...with real name of ttname. */ xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1; debug(F111," ttyname",x,xlocal); } else { /* Else, if stdin redirected... */ #ifdef Uttvt, /* for communication line */ ccold, ccraw, cccbrk; /* and for console */ #else static struct sgttyb /* sgtty info... */ ttold, ttraw, tttvt, ttbuf, /* for communication line */ ccold, ccraw, cccbrk; /* and for console */ #endif static char flfnam[80]; /* uucp lock file path name */ static int hasLock = 0; /* =1 if this kermit locked uucp */ static int inbufc = 0; /* stuff for efficient SIII raw line */ static int ungotn = -1; /* pushback to unread character */ static int XIII /* Sys III/V provides nice ctermid() function to get name of controlling tty */ ctermid(cname); /* Get name of controlling terminal */ debug(F110," ctermid",cname,0); x = ttyname(ttyfd); /* Compare with name of comm line. */ xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1; debug(F111," ttyname",x,xlocal); #else /* Just assume local, so "set speed" and similar commands will work */ /* If not really local, how could it work anyway?... */ xlocal = 1; debug(F101,conesc = 0; /* set to 1 if esc char (^\) typed */ static int ttlock(); /* definition of ttlock subprocedure */ static int ttunlck(); /* and unlock subprocedure */ static char ttnmsv[DEVNAMLEN]; /* copy of open path for tthang */ /* T T O P E N -- Open a tty for exclusive access. */ /* Returns 0 on success, -1 on failure. */ /* If called with lcl < 0, sets value of lcl as follows: 0: the terminal named by ttname is the job's controlling terminal. 1: the terminal named by ttname is not" redirected stdin","",xlocal); #endif } } /* Now check if line is locked -- if so fail, else lock for ourselves */ lkf = 0; /* Check lock */ if (xlocal > 0) { if (ttlock(ttname) < 0) { fprintf(stderr,"Exclusive access to %s denied\n",ttname); close(ttyfd); ttyfd = -1; debug(F110," Access denied by lock",ttname,0); return(-1); /* Not if already locked */ } else lkf = 1; } /* Got the line, now set the desired value for local. */ if (*lcl < 0)/* let things settle */ ttraw.c_cflag = ttc_save; /*** #ifdef PCIX ***/ ttc_save = fcntl(ttyfd,F_GETFL,0); close(ttyfd); /* close/reopen file descriptor */ if ((ttyfd = open(ttnmsv, ttc_save)) < 0) return(-1); /*** #endif ***/ if (ioctl(ttyfd,TCSETAF,&ttraw) < 0) return(-1); /* un-do it */ #endif return (0); } /* T T R E S -- Restore terminal to "normal" mode. */ ttres() { /* Restore the tty to normal. */ if (ttyfd < 0) return(-1); /* Not open. */ #ifndef UXIII /* irectory denied\n"); return( 1 ); } return( 0 ); /* okay to go ahead and lock */ } /* T T L O C K */ static ttlock(ttyfd) char *ttyfd; { /* lock uucp if possible */ #ifdef ATT3BX FILE *lck_fild; #endif int lck_fil, l4l; int pid_buf = getpid(); /* pid to save in lock file */ hasLock = 0; /* not locked yet */ l4l = look4lk(ttyfd); if (l4l < 0) return (-1); /* already locked */ if (l4l == 1) return (0); /* can't read/write lock directory */ lck_fil = crexcept for sIII, */ sleep(1); /* Wait for pending i/o to finish. */ #endif /* (sIII does wait in ioctls) */ #ifdef KERLD if (kerld) ioctl(ttyfd,TIOCSETD,&oldld); /* Restore old line discipline. */ #endif #ifdef UXIII if (ioctl(ttyfd,TCSETAW,&ttold) < 0) return(-1); /* restore termio stuff */ #else if (stty(ttyfd,&ttold) < 0) return(-1); /* Restore sgtty stuff */ #endif #ifdef KERLD if (kerld) ioctl(ttyfd,TIOCSETC,&oldc); /* Restore old special chars. */ #endif return(0); } eat(flfnam, 0444); /* create lock file ... */ if (lck_fil < 0) return (-1); /* create of lockfile failed */ /* creat leaves file handle open for writing -- hf */ #ifdef ATT3BX fprintf((lck_fild = fdopen(lck_fil, "w")), "%10d\n", pid_buf); fflush(lck_fild); #else write (lck_fil, &pid_buf, sizeof(pid_buf) ); /* uucp expects int in file */ #endif close (lck_fil); hasLock = 1; /* now is locked */ return(0); } /* T T U N L O C K */ static ttunlck() { /* kill uucp lock if po /* Exclusive uucp file locking control */ /* by H. Fischer, creative non-Bell coding ! copyright rights for lock modules assigned to Columbia University */ static char * xxlast(s,c) char *s; char c; { /* Equivalent to strrchr() */ int i; for (i = strlen(s); i > 0; i--) if ( s[i-1] == c ) return( s + (i - 1) ); return(NULL); } static look4lk(ttname) char *ttname; { extern char *strcat(), *strcpy(); char *device, *devname; char lockfil[DIRSIZ+1]; #ifdef ISIII char ssible */ if (hasLock) unlink( flfnam ); } /* T T P K T -- Condition the communication line for packets. */ /* or for modem dialing */ #define DIALING 4 /* flags (via flow) for modem handling */ #define CONNECT 5 /* If called with speed > -1, also set the speed. */ /* Returns 0 on success, -1 on failure. */ ttpkt(speed,flow) int speed, flow; { extern char ttname[]; int s; if (ttyfd < 0) return(-1); /* Not open. */ #ifdef KERLD if (kerld) { ioctl(ttyfd,TIOCGETD,&oldld);yfd,TCGETA,&tttvt); #endif debug(F101,"ttopen, ttyfd","",ttyfd); debug(F101," lcl","",*lcl); debug(F111," lock file",flfnam,lkf); return(0); } /* T T C L O S -- Close the TTY, releasing any lock. */ ttclos() { if (ttyfd < 0) return(0); /* Wasn't open. */ if (xlocal) tthang(); /* hang up phone line */ if (xlocal) ttunlck(); ttres(); /* Reset modes. */ close(ttyfd); /* Close it. */ ttyfd = -1; /* Mark it as closed. */ return(0); } /* T T H A N G *lockdir = "/etc/locks"; #else #ifdef ATT3BX char *lockdir = "/usr/spool/locks"; #else char *lockdir = "/usr/spool/uucp"; #endif #endif device = ( (devname=xxlast(ttname,'/')) != NULL ? devname+1 : ttname); #ifdef ISIII (void) strcpy( lockfil, device ); #else strcat( strcpy( lockfil, "LCK.." ), device ); #endif if (access( lockdir, 04 ) < 0) { /* read access denied on lock dir */ fprintf(stderr,"Warning, read access to lock directory denied\n"); return( 1 ); /* cannot check or-- Hangup phone line */ tthang() { #ifdef UXIII unsigned short ttc_save; #endif if (ttyfd < 0) return(0); /* Not open. */ #ifdef ANYBSD ioctl(ttyfd,TIOCCDTR,0); /* drop DTR, hangup line */ msleep(100); /* let things settle */ ioctl(ttyfd,TIOCSDTR,0); /* put things back to normal */ #endif #ifdef UXIII ttc_save = ttraw.c_cflag; ttraw.c_cflag &= ~CBAUD; /* swa: set baud rate to 0 to hangup */ if (ioctl(ttyfd,TCSETAF,&ttraw) < 0) return(-1); /* do it */ msleep(100); set lock file */ } strcat(strcat(strcpy(flfnam,lockdir),"/"), lockfil); debug(F110,"look4lk",flfnam,0); if ( ! access( flfnam, 00 ) ) { /* print out lock file entry */ char lckcmd[40] ; strcat( strcpy(lckcmd, "ls -l ") , flfnam); system(lckcmd); if (access(flfnam,02) == 0) printf("(You may type \"! rm %s\" to remove this file)\n",flfnam); return( -1 ); } if ( access( lockdir, 02 ) < 0 ) { /* lock file cannot be written */ fprintf(stderr,"Warning, write access to lock dg_flags &= ~TANDEM; ttraw.sg_flags |= RAW; /* Go into raw mode */ ttraw.sg_flags &= ~(ECHO|CRMOD); /* Use CR for break character */ #ifdef TOWER1 ttraw.sg_flags &= ~ANYP; /* Must tell Tower no parityr */ #endif if (s > -1) ttraw.sg_ispeed = ttraw.sg_ospeed = s; /* Do the speed */ if (stty(ttyfd,&ttraw) < 0) return(-1); /* Set the new modes. */ #endif #ifdef UXIII if (flow == 1) ttraw.c_iflag |= (IXON|IXOFF); if (flow == 0) ttraw.c_iflag &= ~(IXON|IXOFF); if (flow == DIALIUCLC|BRKINT|INPCK|ISTRIP|IXANY); tttvt.c_oflag &= ~OPOST; tttvt.c_cflag &= ~(CSIZE|PARENB); tttvt.c_cflag |= (CS8|CREAD); tttvt.c_cc[4] = 1; tttvt.c_cc[5] = 0; if (s > -1) tttvt.c_cflag &= ~CBAUD, tttvt.c_cflag |= s; /* set speed */ if (ioctl(ttyfd,TCSETAW,&tttvt) < 0) return(-1); /* set new modes . */ if (flow == DIALING) { if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 ) return(-1); close( open(ttname,2) ); /* magic to force file open!!! */ } ING) ttraw.c_cflag |= CLOCAL|HUPCL; if (flow == CONNECT) ttraw.c_cflag &= ~CLOCAL; ttraw.c_lflag &= ~(ICANON|ECHO); ttraw.c_lflag |= ISIG; /* do check for interrupt */ ttraw.c_iflag |= (BRKINT|IGNPAR); ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY); ttraw.c_oflag &= ~OPOST; ttraw.c_cflag &= ~(CSIZE|PARENB); ttraw.c_cflag |= (CS8|CREAD); ttraw.c_cc[4] = 1; ttraw.c_cc[5] = 0; if (s > -1) ttraw.c_cflag &= ~CBAUD, ttraw.c_cflag |= s; /* set return(0); #endif } /* T T S S P D -- Return the internal baud rate code for 'speed'. */ ttsspd(speed) { int s, spdok; if (speed < 0) return(-1); spdok = 1; /* Assume arg ok */ switch (speed) { case 0: s = B0; break; /* Just the common ones. */ case 110: s = B110; break; /* The others from ttydev.h */ case 150: s = B150; break; /* could also be included if */ case 300: s = B300; break; /* necessary... */ case 600: s = B600; break; case 1200: speed */ if (ioctl(ttyfd,TCSETAW,&ttraw) < 0) return(-1); /* set new modes . */ if (flow == DIALING) { if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 ) return(-1); close( open(ttname,2) ); /* magic to force file open!!! */ } #endif #ifdef KERLD if (kerld) { if (ioctl(ttyfd,TIOCSETD,&ld) < 0) return(-1); /* Set line discpline. */ } #endif ttflui(); /* Flush any pending input */ return(0); } /* T T V T -- Condition communication line for use a s = B1200; break; case 1800: s = B1800; break; case 2400: s = B2400; break; case 4800: s = B4800; break; case 9600: s = B9600; break; #ifdef PLEXUS case 19200: s = EXTA; break; #endif default: spdok = 0; fprintf(stderr,"Unsupported line speed - %d\n",speed); fprintf(stderr,"Current speed not changed\n"); break; } if (spdok) return(s); else return(-1); } /* T T F L U I -- Flush tty input buffer */ ttflui() { #ifndef UXIII long n; #endif if (ts virtual terminal */ ttvt(speed,flow) int speed, flow; { extern char ttname[]; int s; if (ttyfd < 0) return(-1); /* Not open. */ s = ttsspd(speed); /* Check the speed */ #ifndef UXIII if (flow == 1) tttvt.sg_flags |= TANDEM; /* XON/XOFF if selected */ if (flow == 0) tttvt.sg_flags &= ~TANDEM; tttvt.sg_flags |= RAW; /* Raw mode */ #ifdef TOWER1 tttvt.sg_flags &= ~(ECHO|ANYP); /* No echo or system III ??? parity */ #else tttvt.sg_flags &= ~ECHO; /* No echo */ #endtyfd < 0) return(-1); /* Not open. */ ungotn = -1; /* Initialize myread() stuff */ inbufc = 0; #ifdef UXIII if (ioctl(ttyfd,TCFLSH,0) < 0) perror("flush failed"); #else #ifdef ANYBSD n = FREAD; /* Specify read queue */ if (ioctl(ttyfd,TIOCFLUSH,&n) < 0) perror("flush failed"); #else if (ioctl(ttyfd,TIOCFLUSH,0) < 0) perror("flush failed"); #endif #endif return(0); } /* Interrupt Functions */ /* Timeout handler for communication line input functions */ timerh() { /* Get line discipline */ ioctl(ttyfd,TIOCGETC,&oldc); /* Get special chars */ newc = oldc; /* Copy special chars */ newc.t_brkc = '\r'; /* Set CR to be break character */ if(ioctl(ttyfd,TIOCSETC,&newc) < 0) return(-1); } #endif /* cont'd... */ /* ...ttpkt(), cont'd */ /* Note, KERLD ignores the TANDEM, ECHO, and CRMOD bits */ s = ttsspd(speed); /* Check the speed */ #ifndef UXIII if (flow == 1) ttraw.sg_flags |= TANDEM; /* Use XON/XOFF if selected */ if (flow == 0) ttraw.sif if (s > -1) tttvt.sg_ispeed = tttvt.sg_ospeed = s; /* Do the speed */ /* NOTE-- bsd code needs clocal and o_Ndelay stuff here */ return(stty(ttyfd,&tttvt)); #else if (flow == 1) tttvt.c_iflag |= (IXON|IXOFF); if (flow == 0) tttvt.c_iflag &= ~(IXON|IXOFF); if (flow == DIALING) tttvt.c_cflag |= CLOCAL|HUPCL; if (flow == CONNECT) tttvt.c_cflag &= ~CLOCAL; tttvt.c_lflag &= ~(ISIG|ICANON|ECHO); tttvt.c_iflag |= (IGNBRK|IGNPAR); tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL| longjmp(sjbuf,1); } /* Set up terminal interrupts on console terminal */ #ifdef UXIII esctrp() { /* trap console escapes (^\) */ conesc = 1; signal(SIGQUIT,SIG_IGN); /* ignore until trapped */ } #endif #ifdef V7 esctrp() { /* trap console escapes (^\) */ conesc = 1; signal(SIGQUIT,SIG_IGN); /* ignore until trapped */ } #endif /* C O N I N T -- Console Interrupt setter */ conint(f) int (*f)(); { /* Set an interrupt trap. */ if (backgrd) return; /* must ignore signalp to read /DEV/KMEM for character count. */ #ifdef V7 /* Used in Version 7 to simulate Bezerkly's FIONREAD ioctl call. This eliminates blocking on a read, because we can read /dev/kmem to get the number of characters available for raw input. If your system can't or you won't let it read /dev/kmem (the world that is) then you must figure out a different way to do the counting of characters available, or else replace this by a dummy function that always returns 0. */ /* * Call this routine as: inis in bkgrd */ /* Except for special cases below, ignore keyboard quit signal. ^\ too easily confused with connect escape, and besides, we don't want to leave lock files around. (Frank Prindle) */ signal(SIGQUIT,SIG_IGN); #ifdef UXIII signal(SIGQUIT,esctrp); /* console escape in pkt modes */ if (conesc) { /* clear out pending escapes */ conesc = 0; } #endif #ifdef V7 signal(SIGQUIT,esctrp); /* console escape in pkt modes */ if (conesc) { /* clear out pending escapes */ trawq(tty) * where tty is the file descriptor of a terminal. It will return * (as a char *) the kernel-mode memory address of the rawq character * count, which may then be read. It has the side-effect of flushing * input on the terminal. */ /* * John Mackin, Physiology Dept., University of Sydney (Australia) * ...!decvax!mulga!physiol.su.oz!john * * Permission is hereby granted to do anything with this code, as * long as this comment is retained unmodified and no commercial * advantage is gainconesc = 0; } #endif if (conif) return; /* Nothing to do if already on. */ /* check if invoked in background -- if so signals set to be ignored */ if (signal(SIGINT,SIG_IGN) == SIG_IGN) { backgrd = 1; /* means running in background */ #ifdef UXIII signal(SIGQUIT,SIG_IGN); /* must leave signals ignored */ #endif #ifdef V7 signal(SIGQUIT,SIG_IGN); /* must leave signals ignored */ #endif return; } signal(SIGINT,f); /* Function to trap to on interrupt. */ signal(SIGHUPed. */ #include #include char *initrawq(tty) int tty; { long lseek(); static struct nlist nl[] = { {PROCNAME}, {NPROCNAME}, {""} }; static struct proc *pp; char *malloc(), *qaddr, *p, c; int m, pid, me; NPTYPE xproc; /* Its type is defined in makefile. */ int catch(); me = getpid(); if ((m = open("/dev/kmem", 0)) < 0) err("kmem"); nlist(BOOTNAME, nl); if (nl[0].n_type == 0) err("proc array"); if (nl[1].n_type == 0) err("nproc"); lseek(m, (long)(nl[1].n_,f); /* Or hangup, so lock file cleared. */ conif = 1; /* Flag console interrupts on. */ } /* C O N N O I -- Reset console terminal interrupts */ connoi() { /* Console-no-interrupts */ if (backgrd) return; /* Ignore signals in background */ signal(SIGINT,SIG_DFL); signal(SIGHUP,SIG_DFL); signal(SIGQUIT,SIG_DFL); conif = 0; /* Flag interrupt trapping off */ } /* myread() -- System III raw read buffer to block input up */ myread() { /* return character or -1 value), 0); read (m, &xproc, sizeof(xproc)); signal(SIGALRM, catch); if ((pid = fork()) == 0) { while(1) read(tty, &c, 1); } alarm(2); if(setjmp(jjbuf) == 0) { while(1) read(tty, &c, 1); } signal(SIGALRM, SIG_DFL); #ifdef DIRECT pp = (struct proc *) nl[0].n_value; #else if (lseek(m, (long)(nl[0].n_value), 0) < 0L) err("seek"); if (read(m, &pp, sizeof(pp)) != sizeof(pp)) err("no read of proc ptr"); #endif lseek(m, (long)(nl[1].n_value), 0); reif disconnected */ static int inbuf_item; static CHAR inbuf[257]; CHAR readit; if (ungotn >= 0) readit = ungotn; else { if (inbufc > 0) readit = inbuf[++inbuf_item]; else { if ((inbufc=read(ttyfd,inbuf,256)) == 0 ) return(-1); readit = inbuf[inbuf_item=0]; } inbufc--; } ungotn = -1; return(readit ); } myunrd(ch) CHAR ch; { /* push back up to one character */ ungotn = ch; } /* I N I T R A W Q -- Set uad(m, &xproc, sizeof(xproc)); if (lseek(m, (long)pp, 0) < 0L) err("Can't seek to proc"); if ((p = malloc(xproc * sizeof(struct proc))) == NULL) { err("malloc"); } if (read(m,p,xproc * sizeof(struct proc)) != xproc*sizeof(struct proc)) { err("read proc table"); } for (pp = (struct proc *)p; xproc > 0; --xproc, ++pp) { if (pp -> p_pid == (short) pid) goto iout; } err("no such proc"); iout: close(m); qaddr = (char *)(pp -> p_wchan); free (p); kill(pid, SI T T I N L -- Read a record (up to break character) from comm line. */ /* If no break character encountered within "max", return "max" characters, with disposition of any remaining characters undefined. Otherwise, return the characters that were read, including the break character, in "dest" and the number of characters read as the value of function, or 0 upon end of file, or -1 if an error occurred. Times out & returns error if not completed within "timo" seconds. */ ttinl(dest,max,timo, ttsndb() { int x; char spd; if (ttyfd < 0) return(-1); /* Not open. */ #ifdef PROVX1 gtty(ttyfd,&ttbuf); /* Get current tty flags */ spd = ttbuf.sg_ospeed; /* Save speed */ ttbuf.sg_ospeed = B50; /* Change to 50 baud */ stty(ttyfd,&ttbuf); /* ... */ write(ttyfd,brnuls,3); /* Send 3 nulls */ ttbuf.sg_ospeed = spd; /* Restore speed */ stty(ttyfd,&ttbuf); /* ... */ return(0); #else #ifdef UXIII if (ioctl(ttyfd,TCSBRK,(char *)0) < 0) { /* Send a BREAKGKILL); wait((int *)0); /* Destroy the ZOMBIEs! */ return (qaddr); } static err(s) char *s; { char buf[200]; sprintf(buf, "fatal error in initrawq: %s", s); perror(buf); doexit(1); } static catch() { longjmp(jjbuf, -1); } /* G E N B R K -- Simulate a modem break. */ #define BSPEED B150 genbrk(fn) int fn; { struct sgttyb ttbuf; int ret, sospeed; ret = ioctl(fn, TIOCGETP, &ttbuf); sospeed = ttbuf.sg_ospeed; ttbuf.sg_ospeed = BSPEED; ret = ioctl(fn, TIeol) int max,timo; char *dest; { int x, y; CHAR c; if (ttyfd < 0) return(-1); /* Not open. */ if (timo <= 0) { /* Untimed. */ #ifndef UXIII x = read(ttyfd,dest,max); /* Try to read. */ #else for (x = c = 0; (x < max) && (c != eol); x++) { c = myread(); dest[x] = c; } #endif return(x); /* Return the count. */ } signal(SIGALRM,timerh); /* Timed, set up timeout action. */ alarm(timo); /* Set the timer. */ if (setjmp(sjbuf)) x = -1; /* Do this if timer OCSETP, &ttbuf); ret = write(fn, "\0\0\0\0\0\0\0\0\0\0\0\0", 8); ttbuf.sg_ospeed = sospeed; ret = ioctl(fn, TIOCSETP, &ttbuf); ret = write(fn, "@", 1); return; } #endif V7 /* T T C H K -- Tell how many characters are waiting in tty input buffer */ ttchk() { int x; long n; #ifdef ANYBSD x = ioctl(ttyfd, FIONREAD, &n); debug(F101,"ttchk","",n); return((x < 0) ? 0 : n); #else #ifdef V7 lseek(kmem[TTY], (long) qaddr[TTY], 0); x = read(kmem[TTY], &n, sizeof(intwent off. */ else if (kerld) { x = read(ttyfd,dest,max); /* Try to read. */ } else { for (x = c = y = 0; (x < max) && (c != eol); x++) { #ifndef UXIII while ( !(y = read(ttyfd,&c,1))) ; /* skip null reads */ if (y < 0) { alarm(0); /* Error, turn off timer, */ signal(SIGALRM,SIG_DFL); /* and associated interrupt. */ return(y); /* Return the error indication. */ } #else c = myread(); /* always do multi-char reads */ #endif dest[x] = c; } x++; } al)); return((x == sizeof(int))? n: 0); #else V7 #ifdef UXIII return(inbufc + (ungotn >= 0) ); #else #ifdef PROVX1 x = ioctl(ttyfd, TIOCQCNT, &ttbuf); n = ttbuf.sg_ispeed & 0377; return((x < 0) ? 0 : n); #else return(0); #endif #endif #endif #endif } /* T T X I N -- Get n characters from tty input buffer */ ttxin(n,buf) int n; char *buf; { int x; #ifdef UXIII for( x=0; x 0) ? (ch & 0377) : n ); #else /* comm line failure returns (F101," x","",x); #endif if (x > 0) buf[x] = '\0'; return(x); } /* T T O L -- Similar to "ttinl", but for writing. */ ttol(s,n) int n; char *s; { int x; if (ttyfd < 0) return(-1); /* Not open. */ x = write(ttyfd,s,n); debug(F111,"ttol",s,n); if (x < 0) debug(F101,"ttol failed","",x); return(x); } /* T T O C -- Output a character to the communication line */ ttoc(c) char c; { if (ttyfd < 0) return(-1); /* Not open. */ return(write(ttyfd,&c,1)); } /*-1 thru myread, so no &= 0377 */ return( myread() ); #endif } signal(SIGALRM,timerh); /* Timed, set up timer. */ alarm(timo); if (setjmp(sjbuf)) n = -1; else { #ifndef UXIII n = read(ttyfd,&ch,1); /* Read a character. */ #else ch = myread(); n = 1; #endif } alarm(0); /* Turn off timer, */ signal(SIGALRM,SIG_DFL); /* and interrupt. */ if (n > 0) return(ch & 0377); else return(n); /* Return char or -1. */ } /* T T S N D B -- Send a BREAK signal */times(); long t1, t2, tarray[4]; int t3; if ((t1 = times(tarray)) < 0) return(-1); while (1) { if ((t2 = times(tarray)) < 0) return(-1); t3 = ((int)(t2 - t1)) * CLOCK_TICK; if (t3 > m) return(t3); } #endif #ifdef TOWER1 int t1, t3; if (ftime(&ftp) < 0) return(-1); /* Get current time. */ t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm; while (1) { ftime(&ftp); /* new time */ t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1; if (t3 > m) return (t3); } #enICANON|ECHO); cccbrk.c_cc[0] = 003; /* interrupt char is control-c */ cccbrk.c_cc[1] = escchr; /* escape during packet modes */ cccbrk.c_cc[4] = 1; cccbrk.c_cc[5] = 1; x = ioctl(0,TCSETAW,&cccbrk); /* set new modes . */ #endif if (x > -1) setbuf(stdout,NULL); /* Make console unbuffered. */ #ifdef V7 if (kmem[CON] < 0) { qaddr[CON] = initrawq(0); if((kmem[CON] = open("/dev/kmem", 0)) < 0) { fprintf(stderr, "Can't read /dev/kmem in concb.\n"); perror("/dev/kmem"); dif } /* Z T I M E -- Return date/time string */ ztime(s) char **s; { #ifdef UXIII extern long time(); /* Sys III/V way to do it */ char *ctime(); long clock_storage; clock_storage = time( (long *) 0 ); *s = ctime( &clock_storage ); #endif #ifdef PROVX1 int utime[2]; /* Venix way */ time(utime); *s = ctime(utime); #endif #ifdef ANYBSD char *asctime(); /* Berkeley way */ struct tm *localtime(); struct tm *tp; #ifndef BSD41 gettimeofday(&tv, &t exit(1); } } #endif V7 return(x); } /* C O N B I N -- Put console in binary mode */ /* Returns 0 if ok, -1 if not */ conbin(esc) char esc; { if (cgmf == 0) congm(); /* Get modes if necessary. */ escchr = esc; /* Make this available to other fns */ ckxech = 1; /* Program can echo characters */ #ifndef UXIII ccraw.sg_flags |= (RAW|TANDEM); /* Set rawmode, XON/XOFF */ ccraw.sg_flags &= ~(ECHO|CRMOD); /* Set char wakeup, no echo */ return(stty(0,&ccraw) */ conol("Can't send BREAK"); return(-1); } return(0); #else #ifdef ANYBSD if (ioctl(ttyfd,TIOCSBRK,(char *)0) < 0) { /* Turn on BREAK */ conol("Can't send BREAK"); return(-1); } x = msleep(275); /* Sleep for so many milliseconds */ if (ioctl(ttyfd,TIOCCBRK,(char *)0) < 0) { /* Turn off BREAK */ conol("BREAK stuck!!!"); doexit(1); /* Get out, closing the line. */ /* with exit status = 1 */ } return(x); #else #ifdef V7 genbrk(ttyfd); /* Simulatez); /* BSD 2.9, 4.2 ... */ time(&tv.tv_sec); tp = localtime(&tv.tv_sec); #else time(&clock); /* BSD 4.1 ... ceb */ tp = localtime(&clock); #endif *s = asctime(tp); #endif #ifdef TOWER1 char *asctime(); /* Tower way */ struct tm *localtime(); struct tm *tp; time(&clock); tp = localtime(&clock); *s = asctime(tp); #endif #ifdef V7 char *asctime(); /* V7 way */ struct tm *localtime(); struct tm *tp; time(&clock); tp = localtime(&clock); a BREAK */ return(x); #endif #endif #endif #endif } /* M S L E E P -- Millisecond version of sleep(). */ /* Intended only for small intervals. For big ones, just use sleep(). */ msleep(m) int m; { #ifdef PROVX1 sleep(-((m * 60 + 500) / 1000)); return(0); #endif #ifdef ANYBSD int t1, t3, t4; #ifdef BSD41 if (ftime(&ftp) < 0) return(-1); /* Get current time. */ t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm; while (1) { ftime(&ftp); /* new time */ t3 = (((ftp.time *s = asctime(tp); #endif } /* C O N G M -- Get console terminal modes. */ /* Saves current console mode, and establishes variables for switching between current (presumably normal) mode and other modes. */ congm() { #ifndef UXIII gtty(0,&ccold); /* Structure for restoring */ gtty(0,&cccbrk); /* For setting CBREAK mode */ gtty(0,&ccraw); /* For setting RAW mode */ #else ioctl(0,TCGETA,&ccold); ioctl(0,TCGETA,&cccbrk); ioctl(0,TCGETA,&ccraw); #endif cgmf& 0xff) * 1000) + ftp.millitm) - t1; if (t3 > m) return (t3); } #else /* 2.9 and 4.1 BSD do it this way */ if (gettimeofday(&tv, &tz) < 0) return(-1); /* Get current time. */ t1 = tv.tv_sec; /* Seconds */ tv.tv_sec = 0; /* Use select() */ tv.tv_usec = m * 1000; return(select( 0, (int *)0, (int *)0, (int *)0, &tv) ); #endif #endif #ifdef UXIII #ifdef XENIX #define CLOCK_TICK 50 /* millisecs per clock tick */ #else #define CLOCK_TICK 17 /* 1/60 sec */ #endif extern long = 1; /* Flag that we got them. */ } /* C O N C B -- Put console in cbreak mode. */ /* Returns 0 if ok, -1 if not */ concb(esc) char esc; { int x; if (cgmf == 0) congm(); /* Get modes if necessary. */ escchr = esc; /* Make this available to other fns */ ckxech = 1; /* Program can echo characters */ #ifndef UXIII cccbrk.sg_flags |= CBREAK; /* Set to character wakeup, */ cccbrk.sg_flags &= ~ECHO; /* no echo. */ x = stty(0,&cccbrk); #else cccbrk.c_lflag &= ~( == 0) return(0); /* Don't do anything if modes */ #ifndef UXIII /* except for sIII, */ sleep(1); /* not known! */ #endif /* (sIII does wait in ioctls) */ ckxech = 0; /* System should echo chars */ #ifndef UXIII return(stty(0,&ccold)); /* Restore controlling tty */ #else return(ioctl(0,TCSETAW,&ccold)); #endif } /* C O N O C -- Output a character to the console terminal */ conoc(c) char c; { write(1,&c,1); } /* C O N X O -- Write x characters to the console can't be ^c, sigint never returns */ #endif return(-1); } signal(SIGALRM,timerh); /* Timed read, so set up timer */ alarm(timo); if (setjmp(sjbuf)) n = -2; else { n = read(0, &ch, 1); ch &= 0377; } alarm(0); /* Stop timing, we got our character */ signal(SIGALRM,SIG_DFL); if (n > 0) return(ch); else #ifdef UXIII if (n == -1 && errno == EINTR) /* If read interrupted by QUIT, */ return(escchr); /* user entered escape character, */ else /*terminal */ conxo(x,s) char *s; int x; { write(1,s,x); } /* C O N O L -- Write a line to the console terminal */ conol(s) char *s; { int len; len = strlen(s); write(1,s,len); } /* C O N O L A -- Write an array of lines to the console terminal */ conola(s) char *s[]; { int i; for (i=0 ; *s[i] ; i++) conol(s[i]); } /* C O N O L L -- Output a string followed by CRLF */ conoll(s) char *s; { conol(s); write(1,"\r\n",2); } /* C O N C H K -- Check if characte./usr/opt/src/kermit/ckuus2.c 644 0 3 35373 5555215354 11266 rs available at console */ conchk() { int x; long n; #ifdef PROVX1 x = ioctl(0, TIOCQCNT, &ttbuf); n = ttbuf.sg_ispeed & 0377; return((x < 0) ? 0 : n); #else #ifdef V7 lseek(kmem[CON], (long) qaddr[CON], 0); x = read(kmem[CON], &n, sizeof(int)); return((x == sizeof(int))? n: 0); #else #ifndef UXIII x = ioctl(0, FIONREAD, &n); return((x < 0) ? 0 : n); #else if (conesc) { /* Escape typed */ conesc = 0; signal(SIGQUIT,esctrp); /* restore escape */ return(1); /* C K U U S 2 -- "User Interface" STRINGS module for Unix 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. */ /* This module separates long strings from the body of the c); #else ccraw.c_lflag &= ~(ISIG|ICANON|ECHO); ccraw.c_iflag |= (BRKINT|IGNPAR); ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXANY|IXOFF |INPCK|ISTRIP); ccraw.c_oflag &= ~OPOST; /*** Kermit used to put the console in 8-bit raw mode, but some users have *** pointed out that this should not be done, since some sites actually *** use terminals with parity settings on their Unix systems, and if we *** override the current settings and stop doing parity, then their terminals ** } return(0); #endif #endif #endif } /* C O N I N C -- Get a character from the console */ coninc(timo) int timo; { int n = 0; char ch; if (timo <= 0 ) { /* untimed */ n = read(0, &ch, 1); /* Read a character. */ ch &= 0377; if (n > 0) return(ch); /* Return the char if read */ else #ifdef UXIII if (n < 0 && errno == EINTR) /* if read was interrupted by QUIT */ return(escchr); /* user entered escape character */ else /* couldnt be ^c, sigint never returns */ #* will display blotches for characters whose parity is wrong. Therefore, *** the following two lines are commented out (Larry Afrin, Clemson U): *** *** ccraw.c_cflag &= ~(PARENB|CSIZE); *** ccraw.c_cflag |= (CS8|CREAD); *** *** Sys III/V sites that have trouble with this can restore these lines. ***/ ccraw.c_cc[4] = 1; ccraw.c_cc[5] = 1; return(ioctl(0,TCSETAW,&ccraw) ); /* set new modes . */ #endif } /* C O N R E S -- Restore the console terminal */ conres() { if (cgmfendif return(-1); /* Return the char, or -1. */ } signal(SIGALRM,timerh); /* Timed read, so set up timer */ alarm(timo); if (setjmp(sjbuf)) n = -2; else { n = read(0, &ch, 1); ch &= 0377; } alarm(0); /* Stop timing, we got our character */ signal(SIGALRM,SIG_DFL); if (n > 0) return(ch); else #ifdef UXIII if (n == -1 && errno == EINTR) /* If read interrupted by QUIT, */ return(escchr); /* user entered escape character, */ else /*send (use '-s -' to send from stdin)\n", " -r receive\n", " -k receive to stdout\n", " * -g file(s) get remote file(s) from server (quote wildcards)\n", " -a name alternate name, used with -s, -r, -g\n", " -x enter server mode\n", " * -f finish remote server\n", " * -c connect before transaction\n", " * -n connect after transaction\n", " -h help - print this message\n", " settings -ermit packets, to help track down protocol problems.\n\ (packet.log)\n\n", " session Terminal session, during CONNECT command.\n\ (session.log)\n\n\ transactions Names and statistics about files transferred.\n\ (transact.log)\n", "" } ; static char *hmxxlogi[] = { "\ Syntax: script text\n\n", "Login to a remote system using the text provided. The login script\n", "is intended to operate similarly to uucp \"L.sys\" entries.\n", "A login script is a sequence of the form:\n\-\n", " -l line communication line device\n", " -b baud line speed, e.g. 1200\n", " -i binary file or Unix-to-Unix\n", " -p x parity, x is one of e,o,m,s,n\n", " -t line turnaround handshake = xon, half duplex\n", " -w don't write over preexisting files\n", " -q be quiet during file transfer\n", " -d log debugging info to debug.log\n", " If no action command is included, enter interactive dialn", " expect send [expect send] . . .\n\n", "where 'expect' is a prompt or message to be issued by the remote site, and\n", "'send' is the names, numbers, etc, to return. The send may also be the\n", "keyword EOT, to send control-d, or BREAK, to send a break. Letters in\n", "send may be prefixed by ~ to send special characters. These are:\n", "~b backspace, ~s space, ~q '?', ~n linefeed, ~r return, ~c don\'t\n", "append a return, and ~o[o[o]] for octal of a character. As with some \n", "uucp systems, seog.\n", "" }; /* U S A G E */ usage() { conola(hlp1); } /* Help string definitions */ static char *tophlp[] = { "\n\ Type ? for a list of commands, type 'help x' for any command x.\n\ While typing commands, use the following special characters:\n\n\ DEL, RUBOUT, BACKSPACE, CTRL-H: Delete the most recent character typed.\n\ CTRL-W: Delete the most recent word typed.\n", "\ CTRL-U: Delete the current line.\n\ CTRL-R: Redisplay the current line.\n\ ? (question mark) display help on thnt strings are followed by ~r unless they end with ~c.\n\n", "Only the last 7 characters in each expect are matched. A null expect,\n", "e.g. ~0 or two adjacent dashes, causes a short delay. If you expect\n", "that a sequence might not arrive, as with uucp, conditional sequences\n", "may be expressed in the form:\n\n", " -send-expect[-send-expect[...]]\n\n", "where dashed sequences are followed as long as previous expects fail.\n", "" }; static char *hmxxrc[] = { "\ Format: 'receive [filespec]'. Wait foe current command or field.\n\ ESC (Escape or Altmode) Attempt to complete the current field.\n", "\ \\ (backslash) include the following character literally.\n\n\ From system level, type 'kermit -h' to get help about command line args.\ \n", "" }; static char *hmxxbye = "\ Shut down and log out a remote Kermit server"; static char *hmxxclo = "\ Close one of the following logs:\n\ session, transaction, packet, debugging -- 'help log' for further info."; static char *hmxxcon = "\ Connect to r a file to arrive from the other\n\ Kermit, which must be given a 'send' command. If the optional filespec is\n", "given, the (first) incoming file will be stored under that name, otherwise\n\ it will be stored under the name it arrives with.", "" } ; static char *hmxxsen = "\ Format: 'send file1 [file2]'. File1 may contain wildcard characters '*' or\n\ '?'. If no wildcards, then file2 may be used to specify the name file1 is\n\ sent under; if file2 is omitted, file1 is sent under its own name."; stakuser module. */ #include "ckcdeb.h" #include #include #include "ckcker.h" #include "ckucmd.h" #include "ckuusr.h" extern char cmdbuf[]; extern int nrmt, nprm, dfloc; extern char *dftty; extern struct keytab prmtab[]; extern struct keytab remcmd[]; static char *hlp1[] = { "\n", " Usage: kermit [-x arg [-x arg]...[-yyy]..]]\n", " x is an option that requires an argument, y an option with no argument:\n", " actions (* options also require -l and -b) --\n", " -s file(s) a remote system via the tty device given in the\n\ most recent 'set line' command"; static char *hmxxget = "\ Format: 'get filespec'. Tell the remote Kermit server to send the named\n\ files. If filespec is omitted, then you are prompted for the remote and\n\ local filenames separately."; static char *hmxxlg[] = { "\ Record information in a log file:\n\n\ debugging Debugging information, to help track down\n\ (default debug.log) bugs in the C-Kermit program.\n\n\ packets Ktic char *hmxxser = "\ Enter server mode on the currently selected line. All further commands\n\ will be taken in packet form from the other Kermit program."; static char *hmhset[] = { "\ The 'set' command is used to establish various communication or file\n", "parameters. The 'show' command can be used to display the values of\n", "'set' parameters. Help is available for each individual parameter;\n", "type 'help set ?' to see what's available.\n", "" } ; static char *hmxychkt[] = { "\ Type of packet case XXDEL: return(hmsg("Delete a local file or files")); case XXDIAL: return(hmsg("Dial a number using modem autodialer")); case XXDIR: return(hmsg("Display a directory of local files")); case XXECH: return(hmsg("Display the rest of the command on the terminal,\n\ useful in command files.")); case XXEXI: case XXQUI: return(hmsg("Exit from the Kermit program, closing any open logs.")); case XXFIN: return(hmsg("\ Tell the remote Kermit server to shut down without logging out.")block check to be used for error detection, 1, 2, or 3.\n", "Type 1 is standard, and catches most errors. Types 2 and 3 specify more\n", "rigorous checking at the cost of higher overhead. Not all Kermit programs\n", "support types 2 and 3.\n", "" } ; static char *hmxyf[] = { "\set file: names, type, warning, display.\n\n", "'names' are normally 'converted', which means file names are converted\n", "to 'common form' during transmission; 'literal' means use filenames\n", "literally (useful between like ); case XXGET: return(hmsg(hmxxget)); case XXHLP: return(hmsga(tophlp)); case XXLOG: return(hmsga(hmxxlg)); case XXLOGI: return(hmsga(hmxxlogi)); case XXREC: return(hmsga(hmxxrc)); case XXREM: if ((y = cmkey(remcmd,nrmt,"Remote command","")) == -2) return(y); if (y == -1) return(y); if (x = (cmcfm()) < 0) return(x); return(dohrmt(y)); case XXSEN: return(hmsg(hmxxsen)); case XXSER: return(hmsg(hmxxser)); case XXSET: if ((y = cmkey(prmtab,nprm,"Paramsystems).\n\n", "'type' is normally 'text', in which conversion is done between Unix\n", "newlines and CRLF line delimiters; 'binary' means to do no conversion.\n", "Use 'binary' for executable programs or binary data.\n\n", "'warning' is 'on' or 'off', normally off. When off, incoming files will\n", "overwrite existing files of the same name. When on, new names will be\n", "given to incoming files whose names are the same as existing files.\n", "\n\ 'display' is normally 'on', causing file transfer progreter","")) == -2) return(y); if (y == -2) return(y); if (x = (cmcfm()) < 0) return(x); return(dohset(y)); case XXSHE: #ifdef vms return(hmsg("\ Issue a command to VMS (space required after '!')")); #else return(hmsg("\ Issue a command to the Unix shell (space required after '!')")); #endif case XXSHO: return(hmsg("\ Display current values of 'set' parameters; 'show version' will display\n\ program version information for each of the C-Kermit modules.")); case XXSPA: return(hmsess to be displayed\n", "on your screen when in local mode. 'set display off' is useful for\n", "allowing file transfers to proceed in the background.\n\n", "" } ; static char *hmhrmt[] = { "\ The 'remote' command is used to send file management instructions to a\n", "remote Kermit server. There should already be a Kermit running in server\n", "mode on the other end of the currently selected line. Type 'remote ?' to\n", "see a list of available remote commands. Type 'help remote x' to get\n", "further g("Display disk usage in current device, directory")); case XXSTA: return(hmsg("Display statistics about most recent file transfer")); case XXTAK: return(hmsg("\ Take Kermit commands from the named file. Kermit command files may\n\ themselves contain 'take' commands, up to a reasonable depth of nesting.")); default: if (x = (cmcfm()) < 0) return(x); printf("Not available yet - %s\n",cmdbuf); break; } return(0); } /* H M S G -- Get confirmation, then print the given mesinformation about a particular remote command 'x'.\n", "" } ; /* D O H L P -- Give a help message */ dohlp(xx) int xx; { int x,y; if (xx < 0) return(xx); switch (xx) { case XXBYE: return(hmsg(hmxxbye)); case XXCLO: return(hmsg(hmxxclo)); case XXCON: return(hmsg(hmxxcon)); case XXCWD: #ifdef vms return(hmsg("\ Change Working Directory, equivalent to VMS SET DEFAULT command")); #else return(hmsg("Change Working Directory, equivalent to Unix 'cd' command")); #endifsage */ hmsg(s) char *s; { int x; if (x = (cmcfm()) < 0) return(x); puts(s); return(0); } hmsga(s) char *s[]; { /* Same function, but for arrays */ int x, i; if ( x = (cmcfm()) < 0) return(x); for ( i = 0; *s[i] ; i++ ) fputs(s[i], stdout); fputc( '\n', stdout); return(0); } /* D O H S E T -- Give help for SET command */ dohset(xx) int xx; { if (xx == -3) return(hmsga(hmhset)); if (xx < 0) return(xx); switch (xx) { case XYCHKT: return(hng for this program, normally 'C-Kermit>'."); return(0); case XYSPEE: puts("\ Communication line speed for external tty line specified in most recent"); puts("\ 'set line' command. Any of the common baud rates:"); puts(" 0, 110, 150, 300, 600, 1200, 1800, 2400, 4800, 9600."); return(0); case XYRECV: puts("\ Specify parameters for inbound packets:"); puts("\ End-Of-Packet (ASCII value), Packet-Length (94 or less),"); puts("\ Padding (amount, 94 or less), Pad-Character (AS./usr/opt/src/kermit/ckuus3.c 644 0 3 51142 5555215355 11260 msga(hmxychkt)); case XYDELA: puts("\ Number of seconds to wait before sending first packet after 'send' command."); return(0); case XYDUPL: puts("\ During 'connect': 'full' means remote host echoes, 'half' means this program"); puts("does its own echoing."); return(0); case XYESC: printf("%s","\ Decimal ASCII value for escape character during 'connect', normally 28\n\ (Control-\\)\n"); return(0); case XYFILE: return(hmsga(hmxyf)); case XYFLOW: puts("\ Type of flow CII value),"); puts("\ Start-Of-Packet (ASCII value), and Timeout (94 seconds or less),"); puts("\ all specified as decimal numbers."); return(0); case XYSEND: puts("\ Specify parameters for outbound packets:"); puts("\ End-Of-Packet (ASCII value), Packet-Length (94 or less),"); puts("\ Padding (amount, 94 or less), Pad-Character (ASCII value),"); puts("\ Start-Of-Packet (ASCII value), and Timeout (94 seconds or less),"); puts("\ all specified as decimal numbers."); retucontrol to be used. Choices are 'xon/xoff' and 'none'."); puts("normally xon/xoff."); return(0); case XYHAND: puts("\ Decimal ASCII value for character to use for half duplex line turnaround"); puts("handshake. Normally, handshaking is not done."); return(0); case XYLINE: printf("\ Device name of communication line to use. Normally %s.\n",dftty); if (!dfloc) { printf("\ If you set the line to other than %s, then Kermit\n",dftty); printf("\ will be in 'local' mode; 'set lrn(0); default: printf("%s","Not available yet - %s\n",cmdbuf); return(0); } } /* D O H R M T -- Give help about REMOTE command */ dohrmt(xx) int xx; { int x; if (xx == -3) return(hmsga(hmhrmt)); if (xx < 0) return(xx); switch (xx) { case XZCWD: return(hmsg("\ Ask remote Kermit server to change its working directory.")); case XZDEL: return(hmsg("\ Ask remote Kermit server to delete the named file(s).")); case XZDIR: return(hmsg("\ Ask remote Kermit serverine' will reset Kermit to remote mode.\n"); puts("\ If the line has a modem, and if the modem-dialer is set to direct, this"); puts("\ command causes waiting for a carrier detect (e.g. on a hayes type modem)."); puts("\ This can be used to wait for incoming calls."); puts("\ To use the modem to dial out, first set modem-dialer (e.g., to hayes), then"); puts("set line, next issue the dial command, and finally connect."); } return(0); case XYMODM: puts("\ Type of modem for dia to provide directory listing of the named file(s).")); case XZHLP: return(hmsg("\ Ask remote Kermit server to tell you what services it provides.")); case XZHOS: return(hmsg("\ Send a command to the remote system in its own command language\n\ through the remote Kermit server.")); case XZSPA: return(hmsg("\ Ask the remote Kermit server to tell you about its disk space.")); case XZTYP: return(hmsg("\ Ask the remote Kermit server to type the named file(s) on your screen.")); case XZWHO: ling remote connections. Needed to indicate modem can"); puts("\ be commanded to dial without 'carrier detect' from modem. Many recently"); puts("\ manufactured modems use 'hayes' protocol. Type 'set modem ?' to see what"); puts("\ types of modems are supported by this program."); return(0); case XYPARI: puts("Parity to use during terminal connection and file transfer:"); puts("even, odd, mark, space, or none. Normally none."); return(0); case XYPROM: puts("Prompt stri return(hmsg("\ Ask the remote Kermit server to list who's logged in, or to give information\n\ about the specified user.")); default: if (x = (cmcfm()) < 0) return(x); printf("%s","not working yet - %s\n",cmdbuf); return(-2); } } \n\ through the remote Kermit server.")); case XZSPA: return(hmsg("\ Ask the remote Kermit server to tell you about its disk space.")); case XZTYP: return(hmsg("\ Ask the remote Kermit server to type the named file(s) on your screen.")); case XZWHO: l[50], /* Packet log file name */ sesfil[50], /* Session log file name */ trafil[50]; /* Transaction log file name */ extern int tlevel; /* Take Command file level */ extern FILE *tfile[]; /* Array of take command fd's */ /* Keyword tables for SET commands */ /* Block checks */ struct keytab blktab[] = { "1", 1, 0, "2", 2, 0, "3", 3, 0 }; /* Duplex keyword table */ struct keytab dpxtab[] = { "full", 0, 0, "half", 1, 0 }; struct keytab filtab[] = { "di0) return(x); ttclos(); /* close old line, if any was open */ x = strcmp(s,dftty) ? -1 : dfloc; /* Maybe let ttopen figure it out... */ if (ttopen(s,&x,mdmtyp) < 0 ) { /* Can we open the new line? */ perror("Sorry, can't open line"); return(-2); /* If not, give bad return */ } if (x > -1) local = x; /* Set local/remote status. */ strcpy(ttname,s); /* OK, copy name into real place. */ if (!local) speed = -1; /* If remote, say speed unknown. */ debug(F111,"set linesplay", XYFILD, 0, "names", XYFILN, 0, "type", XYFILT, 0, "warning", XYFILW, 0 }; int nfilp = (sizeof(filtab) / sizeof(struct keytab)); /* Send/Receive Parameters */ struct keytab srtab[] = { "end-of-packet", XYEOL, 0, "packet-length", XYLEN, 0, "pad-character", XYPADC, 0, "padding", XYNPAD, 0, "start-of-packet", XYMARK, 0, "timeout", XYTIMO, 0 }; int nsrtab = (sizeof(srtab) / sizeof(struct keytab)); /* Flow Control */ struct keytab flotab[] = { "none", 0 ",ttname,local); return(0); case XYCHKT: if ((y = cmkey(blktab,3,"","1")) < 0) return(y); if ((x = cmcfm()) < 0) return(x); bctr = y; return(0); case XYDEBU: return(seton(&deblog)); case XYDELA: y = cmnum("Number of seconds before starting to send","5",10,&x); debug(F101,"XYDELA: y","",y); return(setnum(&delay,x,y)); case XYDUPL: if ((y = cmkey(dpxtab,2,"","full")) < 0) return(y); if ((x = cmcfm()) < 0) return(x); duplex = y; return(0); case XYESC: /* C K U U S 3 -- "User Interface" for Unix Kermit, part 3 */ /* 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. */ /* SET and REMOTE commands; screen, debug, interrupt, and logging fu, 0, "xon/xoff", 1, 0 }; int nflo = (sizeof(flotab) / sizeof(struct keytab)); /* Handshake characters */ struct keytab hshtab[] = { "bell", 007, 0, "cr", 015, 0, "esc", 033, 0, "lf", 012, 0, "none", 999, 0, /* (can't use negative numbers) */ "xoff", 023, 0, "xon", 021, 0 }; int nhsh = (sizeof(hshtab) / sizeof(struct keytab)); struct keytab fntab[] = { /* File naming */ "converted", 1, 0, "literal", 0, 0 }; struct keytab fttab[] = { /* File types nctions */ /* Includes */ #include "ckcdeb.h" #include #include #include "ckcker.h" #include "ckucmd.h" #include "ckuusr.h" /* Variables */ extern int size, spsiz, rpsiz, npad, timint, rtimo, speed, local, server, image, flow, displa, binary, fncnv, delay, parity, deblog, escape, xargc, turn, duplex, cxseen, czseen, nfils, ckxech, pktlog, seslog, tralog, stdouf, turnch, chklen, bctr, bctu, dfloc, mdmtyp, rptflg, ebqflg, warn, quiet, cnflg, timef, mypadn; extern long filcnt,*/ "binary", 1, 0, "text", 0, 0 }; extern struct keytab mdmtab[] ; /* Modem types (in module ckudia.c) */ extern int nmdm; /* Parity keyword table */ struct keytab partab[] = { "even", 'e', 0, "mark", 'm', 0, "none", 0, 0, "odd", 'o', 0, "space", 's', 0 }; int npar = (sizeof(partab) / sizeof(struct keytab)); /* On/Off table */ struct keytab onoff[] = { "off", 0, 0, "on", 1, 0 }; /* D O P R M -- Set a parameter. */ /* R tlci, tlco, ffc, tfc, fsize; extern char *versio, *protv, *ckxv, *ckzv, *fnsv, *connv, *dftty, *cmdv; extern char *cmarg, *cmarg2, **xargv, **cmlist; extern char stchr, mystch, sstate, padch, mypadc, eol, seol, ctlq; extern char filnam[], ttname[]; char *strcpy(); /* Declarations from cmd package */ extern char cmdbuf[]; /* Command buffer */ /* From main ckuser module... */ extern char line[100], *lp; /* Character buffer for anything */ extern char debfil[50], /* Debugging log file name */ pktfieturns: -2: illegal input -1: reparse needed 0: success */ doprm(xx) int xx; { int x, y, z; char *s; switch (xx) { case XYEOL: /* These have all been moved to set send/receive... */ case XYLEN: /* Let the user know what to do. */ case XYMARK: case XYNPAD: case XYPADC: case XYTIMO: printf("...Use 'set send' or 'set receive' instead.\n"); printf("Type 'help set send' or 'help set receive' for more info.\n"); return(0); case XYLINE: if ((x = cmtxt("Device name",dftty,&s)) < shake */ if ((y = cmkey(hshtab,nhsh,"","none")) < 0) return(y); if ((x = cmcfm()) < 0) return(x); turn = (y > 0127) ? 0 : 1 ; turnch = y; return(0); case XYMODM: if ((x=cmkey(mdmtab,nmdm,"type of modem, direct means none","direct")) < 0) return(x); if ((z = cmcfm()) < 0) return(z); mdmtyp = x; return(0); case XYPARI: if ((y = cmkey(partab,npar,"","none")) < 0) return(y); if ((x = cmcfm()) < 0) return(x); parity = y; ebqflg = 1; /* Flag we want 8th-b("%s: %d baud\n",ttname,speed); } return(0); default: if ((x = cmcfm()) < 0) return(x); printf("Not working yet - %s\n",cmdbuf); return(0); } } /* C H K S P D -- Check if argument is a valid baud rate */ chkspd(x) int x; { switch (x) { case 0: case 110: case 150: case 300: case 600: case 1200: case 1800: case 2400: case 4800: case 9600: return(x); default: return(-1); } } /* S E T O N -- Parse on/off (default on), set parameter to result it prefixing */ return(0); case XYPROM: if ((x = cmtxt("Program's command prompt","C-Kermit>",&s)) < 0) return(x); cmsetp(s); return(0); /* SET SEND/RECEIVE... */ case XYRECV: case XYSEND: if (xx == XYRECV) strcpy(line,"Parameter for inbound packets"); else strcpy(line,"Parameter for outbound packets"); if ((y = cmkey(srtab,nsrtab,line,"")) < 0) return(y); switch (y) { case XYEOL: y = cmnum("Decimal ASCII code for packet terminator","0",10,&x); if (( */ seton(prm) int *prm; { int x, y; if ((y = cmkey(onoff,2,"","on")) < 0) return(y); if ((x = cmcfm()) < 0) return(x); *prm = y; return(0); } /* S E T N U M -- Set parameter to result of cmnum() parse. */ /* Call with x - number from cnum parse, y - return code from cmnum */ setnum(prm,x,y) int x, y, *prm; { debug(F101,"setnum","",y); if (y < 0) return(y); if (x > 94) { printf("\n?Sorry, 94 is the maximum\n"); return(-2); } if ((y = cmcfm()) < 0) return(y); y = setcc(&z,x,y)) < 0) return(y); if (xx == XYRECV) eol = z; else seol = z; return(y); case XYLEN: y = cmnum("Maximum number of characters in a packet","90",10,&x); if ((y = setnum(&z,x,y)) < 0) return(y); if (xx == XYRECV) rpsiz = z; else spsiz = z; return(y); case XYMARK: y = cmnum("Decimal ASCII code for packet-start character","1",10,&x); if ((y = setcc(&z,x,y)) < 0) return(y); if (xx == XYRECV) stchr = z; else mystch = z; return(y); case XYNPAD: y = cmnum *prm = x; return(0); } /* S E T C C -- Set parameter to an ASCII control character value. */ setcc(prm,x,y) int x, y, *prm; { if (y < 0) return(y); if ((x > 037) && (x != 0177)) { printf("\n?Not in ASCII control range - %d\n",x); return(-2); } if ((y = cmcfm()) < 0) return(y); *prm = x; return(0); } /* D O R M T -- Do a remote command */ dormt(xx) int xx; { int x; char *s, sbuf[50], *s2; if (xx < 0) return(xx); switch (xx) { case XZCWD: / y = cmnum("Decimal ASCII code for escape character","",10,&x); return(setcc(&escape,x,y)); case XYFILE: if ((y = cmkey(filtab,nfilp,"File parameter","")) < 0) return(y); switch (y) { int z; case XYFILD: /* Display */ y = seton(&z); if (y < 0) return(y); quiet = !z; return(0); case XYFILN: /* Names */ if ((x = cmkey(fntab,2,"how to handle filenames","converted")) < 0) return(x); if ((z = cmcfm()) < 0) return(z); fncnv = x; return(0); c("How many padding characters for inbound packets","0",10,&x); if ((y = setnum(&z,x,y)) < 0) return(y); if (xx == XYRECV) npad = z; else mypadn = z; return(y); case XYPADC: y = cmnum("Decimal ASCII code for inbound pad character","0",10,&x); if ((y = setcc(&z,x,y)) < 0) return(y); if (xx == XYRECV) padch = z; else mypadc = z; return(y); case XYTIMO: y = cmnum("Interpacket timeout interval","5",10,&x); if ((y = setnum(&z,x,y)) < 0) return(y); if (xx == XYRECV) { timase XYFILT: /* Type */ if ((x = cmkey(fttab,2,"type of file","text")) < 0) return(x); if ((z = cmcfm()) < 0) return(z); binary = x; return(0); case XYFILW: /* Warning/Write-Protect */ return(seton(&warn)); default: printf("?unexpected file parameter\n"); return(-2); } case XYFLOW: /* Flow control */ if ((y = cmkey(flotab,nflo,"","xon/xoff")) < 0) return(y); if ((x = cmcfm()) < 0) return(x); flow = y; return(0); case XYHAND: /* Handef = 1; timint = z; } else rtimo = z; return(y); } case XYSPEE: if (!local) { printf("\nSpeed setting can only be done on an external line\n"); printf("You must 'set line' before issuing this command\n"); return(0); } lp = line; sprintf(lp,"Baud rate for %s",ttname); if ((y = cmnum(line,"",10,&x)) < 0) return(y); if (y = (cmcfm()) < 0) return(y); y = chkspd(x); if (y < 0) printf("?Unsupported line speed - %d\n",x); else { speed = y; printff(" Password: "); /* get a password */ while (((x = getchar()) != NL) && (x != CR)) { /* with no echo */ if ((x &= 0177) == '?') { printf("? Password of remote directory\n Password: "); s2 = sbuf; *sbuf = NUL; } else if (x == ESC) /* Mini command line editor... */ putchar(BEL); else if (x == BS || x == 0177) s2--; else if (x == 025) { s2 = sbuf; *sbuf = NUL; } else *s2++ = x; } *s2 = NUL; putch */ char buf[80]; /* Output buffer */ len = strlen(s); /* Length of string */ if (!displa || quiet) return; /* No update if display flag off */ switch (f) { case SCR_FN: /* filename */ conoll(""); conol(s); conoc(SP); p = len + 1; return; case SCR_AN: /* as-name */ if (p + len > 75) { conoll(""); p = 0; } conol("=> "); conol(s); if ((p += (len + 3)) > 78) { conoll(""); p = 0; } return; case SCR_FS: /* file-size */ sprintf(buf,", Size: %ld",n); conar('\n'); } s2 = sbuf; } else s2 = ""; debug(F110," password",s2,0); sstate = setgen('C',s,s2,""); return(0); case XZDEL: /* Delete */ if ((x = cmtxt("Name of remote file(s) to delete","",&s)) < 0) return(x); return(sstate = rfilop(s,'E')); case XZDIR: /* Directory */ if ((x = cmtxt("Remote directory or file specification","",&s)) < 0) return(x); return(sstate = setgen('D',s,"","")); case XZHLP: /* Help */ if (x = (cmcfm()) < 0) return(oll(buf); p = 0; return; case SCR_XD: /* x-packet data */ conoll(""); conoll(s); p = 0; return; case SCR_ST: /* File status */ switch (c) { case ST_OK: /* Transferred OK */ if ((p += 5) > 78) { conoll(""); p = 0; } conoll(" [OK]"); p += 5; return; case ST_DISC: /* Discarded */ if ((p += 12) > 78) { conoll(""); p = 0; } conoll(" [discarded]"); p += 12; return; case ST_INT: /* Interrupted */ if ((p += 14) > 78) { conoll(""); p = x); sstate = setgen('H',"","",""); return(0); case XZHOS: /* Host */ if ((x = cmtxt("Command for remote system","",&cmarg)) < 0) return(x); return(sstate = 'c'); case XZPRI: /* Print */ if ((x = cmtxt("Remote file(s) to print on remote printer","",&s)) < 0) return(x); return(sstate = rfilop(s,'S')); case XZSPA: /* Space */ if ((x = cmtxt("Confirm, or remote directory name","",&s)) < 0) return(x); return(sstate = setgen('U',s,"","")); case XZTYP: /* Ty0; } conoll(" [interrupted]"); p += 14; return; case ST_SKIP: /* Skipped */ conoll(""); conol("Skipping "); conoll(s); p = 0; return; default: conoll("*** screen() called with bad status ***"); p = 0; return; } case SCR_PN: /* Packet number */ sprintf(buf,"%s: %ld",s,n); conol(buf); p += strlen(buf); return; case SCR_PT: /* Packet type or pseudotype */ if (c == 'Y') return; /* Don't bother with ACKs */ if (c == 'D') { /* Only show everpe */ if ((x = cmtxt("Remote file specification","",&s)) < 0) return(x); return(sstate = rfilop(s,'T')); case XZWHO: if ((x = cmtxt("Remote user name, or carriage return","",&s)) < 0) return(x); return(sstate = setgen('W',s,"","")); default: if (x = (cmcfm()) < 0) return(x); printf("not working yet - %s\n",cmdbuf); return(-2); } } /* R F I L O P -- Remote File Operation */ rfilop(s,t) char *s, t; { if (*s == NUL) { printf("?File specification required\n");y 4th data packet */ if (n % 4) return; c = '.'; } if (p++ > 78) { /* If near right margin, */ conoll(""); /* Start new line */ p = 0; /* and reset counter. */ } conoc(c); /* Display the character. */ return; case SCR_TC: /* transaction complete */ conoc(BEL); return; case SCR_EM: /* Error message */ conoll(""); conoc('?'); conoll(s); p = 0; return; /* +1 */ case SCR_WM: /* Warning message */ conoll(""); conoll(s); p = 0; return; case SCR_TU: * CWD */ if ((x = cmtxt("Remote directory name","",&s)) < 0) return(x); debug(F111,"XZCWD: ",s,x); *sbuf = NUL; s2 = sbuf; if (*s != NUL) { /* If directory name given, */ /* get password on separate line. */ if (tlevel > -1) { /* From take file... */ *line = NUL; if (fgets(sbuf,50,tfile[tlevel]) == NULL) ermsg("take file ends prematurely in 'remote cwd'"); debug(F110," pswd from take file",s2,0); } else { /* From terminal... */ print return(-2); } debug(F111,"rfilop",s,t); return(setgen(t,s,"","")); } /* S C R E E N -- Screen display function */ /* screen(f,c,n,s) f - argument descriptor c - a character or small integer n - a long integer s - a string. Fill in this routine with the appropriate display update for the system. This version is for a dumb tty. */ screen(f,c,n,s) int f; long n; char c; char *s; { static int p = 0; /* Screen position */ int len; /* Length of string /* Undelimited text */ if ((p += len) > 78) { conoll(""); p = len; } conol(s); return; case SCR_TN: /* Text delimited at beginning */ conoll(""); conol(s); p = len; return; case SCR_TZ: /* Text delimited at end */ if ((p += len) > 78) { conoll(""); p = len; } conoll(s); return; case SCR_QE: /* Quantity equals */ sprintf(buf,"%s: %ld",s,n); conoll(buf); p = 0; return; default: conoll("*** screen() called with bad object ***"); p = 0; return; } } /* I the debugging log */ /* Call with a format, two strings, and a number: f - Format, a bit string in range 0-7. If bit x is on, then argument number x is printed. s1 - String, argument number 1. If selected, printed as is. s2 - String, argument number 2. If selected, printed in brackets. n - Int, argument 3. If selected, printed preceded by equals sign. f=0 is special: print s1,s2, and interpret n as a char. */ #ifdef DEBUG debug(f,s1,s2,n) int f, n; char *s1, *s2; { stati N T M S G -- Issue message about terminal interrupts */ intmsg(n) long n; { extern char *chstr(); char buf[80]; if ((!displa) || (quiet)) return; #ifdef UXIII (void) conchk(); /* clear out pending escape-signals in ckxbsd.c */ #endif if (n == 1) { #ifdef UXIII /* we need to signal before kb input */ sprintf(buf,"Type escape (%s) followed by:",chstr(escape)); screen(SCR_TN,0,0l,buf); #endif screen(SCR_TN,0,0l,"CTRL-F to cancel file, CTRL-R to resend current packet"); screenc char s[200]; char *sp = s; if (!deblog) return; /* If no debug log, don't */ switch (f) { case F000: /* 0, print both strings, */ sprintf(sp,"%s%s%c\n",s1,s2,n); /* and interpret n as a char */ zsout(ZDFILE,s); break; case F001: /* 1, "=n" */ sprintf(sp,"=%d\n",n); zsout(ZDFILE,s); break; case F010: /* 2, "[s2]" */ sprintf(sp,"[%s]\n",s2); zsout(ZDFILE,""); break; case F011: /* 3, "[s2]=n" */ sprintf(sp,"[%s]=%d\n(SCR_TN,0,0l,"CTRL-B to cancel batch, CTRL-A for status report: "); } else screen(SCR_TU,0,0l," "); } /* C H K I N T -- Check for console interrupts */ /*** should rework not to destroy typeahead ***/ chkint() { int ch, cn; if ((!local) || (quiet)) return(0); /* Only do this if local & not quiet */ cn = conchk(); /* Any input waiting? */ debug(F101,"conchk","",cn); while (cn > 0) { /* Yes, read it. */ cn--; /* give read 5 seconds for interrupt character */ if",s2,n); zsout(ZDFILE,s); break; case F100: /* 4, "s1" */ zsoutl(ZDFILE,s1); break; case F101: /* 5, "s1=n" */ sprintf(sp,"%s=%d\n",s1,n); zsout(ZDFILE,s); break; case F110: /* 6, "s1[s2]" */ sprintf(sp,"%s[%s]\n",s1,s2); zsout(ZDFILE,s); break; case F111: /* 7, "s1[s2]=n" */ sprintf(sp,"%s[%s]=%d\n",s1,s2,n); zsout(ZDFILE,s); break; default: sprintf(sp,"\n?Invalid format for debug() - %d\n",n); zsout(ZDF ((ch = coninc(5)) < 0) return(0); switch (ch & 0177) { case 0001: /* CTRL-A */ screen(SCR_TN,0,0l,"^A Status report:"); screen(SCR_TN,0,0l," file type: "); if (binary) screen(SCR_TZ,0,0l,"binary"); else screen(SCR_TZ,0,0l,"text"); screen(SCR_QE,0,(long)filcnt," file number"); screen(SCR_QE,0,(long)ffc, " characters "); screen(SCR_QE,0,(long)bctu, " block check"); screen(SCR_QE,0,(long)rptflg," compression"); screen(SCR_QE,0,(long)ebqflg," 8th-bit prefixing"); continueILE,s); } } #endif #ifdef TLOG /* T L O G -- Log a record in the transaction file */ /* Call with a format and 3 arguments: two strings and a number: f - Format, a bit string in range 0-7, bit x is on, arg #x is printed. s1,s2 - String arguments 1 and 2. n - Int, argument 3. */ tlog(f,s1,s2,n) int f; long n; char *s1, *s2; { static char s[200]; char *sp = s; int x; if (!tralog) return; /* If no transaction log, don't */ switch (f) { case F000: /* 0 (speci; case 0002: /* CTRL-B */ screen(SCR_TN,0,0l,"^B - Cancelling Batch "); czseen = 1; continue; case 0006: /* CTRL-F */ screen(SCR_TN,0,0l,"^F - Cancelling File "); cxseen = 1; continue; case 0022: /* CTRL-R */ screen(SCR_TN,0,0l,"^R - Resending "); resend(); return(1); default: /* Anything else, just ignore */ screen(SCR_TU,0,0l," [Ignored] "); continue; } } return(0); } /* D E B U G -- Enter a record inal) "s1 n s2" */ sprintf(sp,"%s %ld %s\n",s1,n,s2); zsout(ZTFILE,s); break; case F001: /* 1, " n" */ sprintf(sp," %ld\n",n); zsout(ZTFILE,s); break; case F010: /* 2, "[s2]" */ x = strlen(s2); if (s2[x] == '\n') s2[x] = '\0'; sprintf(sp,"[%s]\n",s2); zsout(ZTFILE,""); break; case F011: /* 3, "[s2] n" */ x = strlen(s2); if (s2[x] == '\n') s2[x] = '\0'; sprintf(sp,"[%s] %ld\n",s2,n); zsout(ZTFILE,s); break; r module contains the terminal input and output functions for Unix Kermit. It includes a simple Unix-style command line parser as well as an interactive prompting keyword command parser. It depends on the existence of Unix facilities like fopen, fgets, feof, (f)printf, argv/argc, etc. Other functions that are likely to vary among Unix implementations -- like setting terminal modes or interrupts -- are invoked via calls to functions that are defined in the system-dependent modules, ck?[ft]io.c. Ths provide the user i/o for interrupting file transfers. */ /* Includes */ #include "ckcdeb.h" #include #include #include #include "ckcker.h" #include "ckucmd.h" #include "ckuusr.h" #ifdef vax11c #define KERMRC "kermit.ini" #else #define KERMRC ".kermrc" #endif /* External Kermit Variables, see ckmain.c for description. */ extern int size, spsiz, rpsiz, npad, timint, rtimo, speed, local, server, displa, binary, fncnv, delay, parity, deblog, escape, xargc, flow, t case F100: /* 4, "s1" */ zsoutl(ZTFILE,s1); break; case F101: /* 5, "s1: n" */ sprintf(sp,"%s: %ld\n",s1,n); zsout(ZTFILE,s); break; case F110: /* 6, "s1 s2" */ x = strlen(s2); if (s2[x] == '\n') s2[x] = '\0'; sprintf(sp,"%s %s\n",s1,s2); zsout(ZTFILE,s); break; case F111: /* 7, "s1 s2: n" */ x = strlen(s2); if (s2[x] == '\n') s2[x] = '\0'; sprintf(sp,"%s %s: %ld\n",s1,s2,n); zsout(ZTFILE,s); break; defaulte command line parser processes any arguments found on the command line, as passed to main() via argv/argc. The interactive parser uses the facilities of the cmd package (developed for this program, but usable by any program). Any command parser may be substituted for this one. The only requirements for the Kermit command parser are these: 1. Set parameters via global variables like duplex, speed, ttname, etc. See ckmain.c for the declarations and descriptions of these variables. 2. If a comm: sprintf(sp,"\n?Invalid format for tlog() - %ld\n",n); zsout(ZTFILE,s); } } #endif */ sprintf(sp,"%s: %ld\n",s1,n); zsout(ZTFILE,s); break; case F110: /* 6, "s1 s2" */ x = strlen(s2); if (s2[x] == '\n') s2[x] = '\0'; sprintf(sp,"%s %s\n",s1,s2); zsout(ZTFILE,s); break; case F111: /* 7, "s1 s2: n" */ x = strlen(s2); if (s2[x] == '\n') s2[x] = '\0'; sprintf(sp,"%s %s: %ld\n",s1,s2,n); zsout(ZTFILE,s); break; defaultand can be executed without the use of Kermit protocol, then execute the command directly and set the variable sstate to 0. Examples include 'set' commands, local directory listings, the 'connect' command. 3. If a command requires the Kermit protocol, set the following variables: sstate string data 'x' (enter server mode) (none) 'r' (send a 'get' command) cmarg, cmarg2 'v' (enter receive mode) cmarg2 'g' (send a ./usr/opt/src/kermit/ckuusr.c 644 0 3 103111 5555215355 11371 generic command) cmarg 's' (send files) nfils, cmarg & cmarg2 OR cmlist 'c' (send a remote host command) cmarg cmlist is an array of pointers to strings. cmarg, cmarg2 are pointers to strings. nfils is an integer. cmarg can be a filename string (possibly wild), or a pointer to a prefabricated generic command string, or a pointer to a host command string. cmarg2 is the name to send a single file under, or the name under whicchar *userv = "User Interface 4C(048)+, 26 Jun 85"; /* C K U U S R -- "User Interface" for Unix Kermit (Part 1) */ /* 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. */ /* The ckuseh to store an incoming file; must not be wild. cmlist is a list of nonwild filenames, such as passed via argv. nfils is an integer, interpreted as follows: -1: argument string is in cmarg, and should be expanded internally. 0: stdin. >0: number of files to send, from cmlist. The screen() function is used to update the screen during file transfer. The tlog() function maintains a transaction log. The debug() function maintains a debugging log. The intmsg() and chkint() functionKE 20 /* Maximum nesting of TAKE files */ FILE *tfile[MAXTAKE]; /* File pointers for TAKE command */ char *homdir; /* Pointer to home directory string */ char cmdstr[100]; /* C M D L I N -- Get arguments from command line */ /* Simple Unix-style command line parser, conforming with 'A Proposed Command Syntax Standard for Unix Systems', Hemenway & Armitage, Unix/World, Vol.1, No.3, 1984. */ cmdlin() { char x; cmarg = ""; /* Initialize. */ cmarg2 = ""; action = cflg = 0; icting actions"); if (*(xp+1)) fatal("invalid argument bundling after -s"); z = nfils = 0; /* Initialize file counter, flag */ cmlist = xargv+1; /* Remember this pointer */ while (--xargc > 0) { /* Traverse the list */ *xargv++; if (**xargv == '-') { /* Check for sending stdin */ if (strcmp(*xargv,"-") != 0) break; z++; } nfils++; /* Bump file counter */ } xargc++, *xargv--; /* Adjust argv/argc */ if (nfils < 1) fatal("missing filename for -s"); while (--xargc > 0) { /* Go through command line words */ xargv++; debug(F111,"xargv",*xargv,xargc); if (**xargv == '-') { /* Got an option (begins with dash) */ x = *(*xargv+1); /* Get the option letter */ x = doarg(x); /* Go handle the option */ if (x < 0) exit(GOOD_EXIT); } else { /* No dash where expected */ usage(); exit(BAD_EXIT); } } debug(F101,"action","",action); if (!local) { if ((action == 'g') || (action == 'r') || (action == 'c') if (z > 1) fatal("-s: too many -'s"); if (z == 1) { if (nfils == 1) nfils = 0; else fatal("invalid mixture of filenames and '-' in -s"); } if (nfils == 0) { if (isatty(0)) fatal("sending from terminal not allowed"); } debug(F101,*xargv,"",nfils); action = 's'; break; /* cont'd... */ /* ...doarg(), cont'd */ case 'g': /* get */ if (action) fatal("conflicting actions"); if (*(xp+1)) fatal("invalid argument bundling after -g"); *xargv++, xargc--; if ((xaurn, duplex, cxseen, czseen, nfils, ckxech, pktlog, seslog, tralog, stdouf, turnch, chklen, bctr, bctu, dfloc, mdmtyp, rptflg, ebqflg, warn, quiet, cnflg, timef, mypadn; extern long filcnt, tlci, tlco, ffc, tfc, fsize; extern char *versio, *protv, *ckxv, *ckzv, *fnsv, *connv, *dftty, *cmdv; extern char *dialv, *loginv; extern char *ckxsys, *ckzsys, *cmarg, *cmarg2, **xargv, **cmlist; extern char mystch, stchr, sstate, mypadc, padch, eol, seol, ctlq, filnam[], ttname[]; extern char *DIRCMD, *PWDCMD, || (cflg != 0)) fatal("-l and -b required"); } if (*cmarg2 != 0) { if ((action != 's') && (action != 'r') && (action != 'v')) fatal("-a without -s, -r, or -g"); } if ((action == 'v') && (stdouf) && (!local)) { if (isatty(1)) fatal("unredirected -k can only be used in local mode"); } if ((action == 's') || (action == 'v') || (action == 'r') || (action == 'x')) { if (local) displa = 1; if (stdouf) displa = 0; } if (quiet) displa = 0; /* No dicmerrp[]; char *strcpy(), *getenv(); /* Declarations from cmd package */ extern char cmdbuf[]; /* Command buffer */ /* Declarations from ck?fio.c module */ extern char *SPACMD, *zhome(); /* Space command, home directory. */ extern int backgrd; /* Kermit executing in background */ /* The background flag is set by ckutio.c (via conint() ) to note whether */ /* this kermit is executing in background ('&' on shell command line). */ /* Variables and symbols local to this module */ char line[CMDBLsplay if quiet requested */ if (cflg) { conect(); /* Connect if requested */ if (action == 0) { if (cnflg) conect(); /* And again if requested */ doexit(GOOD_EXIT); /* Then exit indicating success */ } } if (displa) concb(escape); /* (for console "interrupts") */ return(action); /* Then do any requested protocol */ } /* D O A R G -- Do a command-line argument. */ doarg(x) char x; { int z; char *xp; xp = *xargv+1; /* Pointer for bundled args */ while+10], *lp; /* Character buffer for anything */ char debfil[50]; /* Debugging log file name */ char pktfil[50]; /* Packet log file name */ char sesfil[50]; /* Session log file name */ char trafil[50]; /* Transaction log file name */ int n, /* General purpose int */ cflg, /* Command-line connect cmd given */ action, /* Action selected on command line*/ repars, /* Reparse needed */ tlevel, /* Take command level */ cwdf = 0; /* CWD has been done */ #define MAXTA (x) { switch (x) { case 'x': /* server */ if (action) fatal("conflicting actions"); action = 'x'; break; case 'f': if (action) fatal("conflicting actions"); action = setgen('F',"","",""); break; case 'r': /* receive */ if (action) fatal("conflicting actions"); action = 'v'; break; case 'k': /* receive to stdout */ if (action) fatal("conflicting actions"); stdouf = 1; action = 'v'; break; case 's': /* send */ if (action) fatal("confllid argument bundling"); *xargv++, xargc--; if ((xargc < 1) || (**xargv == '-')) fatal("missing baud"); z = atoi(*xargv); /* Convert to number */ if (chkspd(z) > -1) speed = z; /* Check it */ else fatal("unsupported baud rate"); break; case 'i': /* Treat files as binary */ binary = 1; break; /* cont'd... */ /* ...doarg(), cont'd */ case 'w': /* File warning */ warn = 1; break; case 'q': /* Quiet */ quiet = 1; break; case 'd': /* deXXSET, 0, "show", XXSHO, 0, "space", XXSPA, 0, "statistics", XXSTA, 0, "take", XXTAK, 0 }; int ncmd = (sizeof(cmdtab) / sizeof(struct keytab)); /* Parameter keyword table */ struct keytab prmtab[] = { "baud", XYSPEE, CM_INV, "block-check", XYCHKT, 0, "delay", XYDELA, 0, "duplex", XYDUPL, 0, "end-of-packet", XYEOL, CM_INV, /* moved to send/receive */ "escape-character", XYESC, 0, "file", XYFILE, 0, "flow-bug */ debopn("debug.log"); break; case 'p': /* set parity */ if (*(xp+1)) fatal("invalid argument bundling"); *xargv++, xargc--; if ((xargc < 1) || (**xargv == '-')) fatal("missing parity"); switch(x = **xargv) { case 'e': case 'o': case 'm': case 's': parity = x; break; case 'n': parity = 0; break; default: fatal("invalid parity"); } break; case 't': turn = 1; /* Line turnaround handshake */ turnch = XON; /* XON is turnaround character */ control", XYFLOW, 0, "handshake", XYHAND, 0, "line", XYLINE, 0, "modem-dialer", XYMODM, 0, "packet-length", XYLEN, CM_INV, /* moved to send/receive */ "pad-character", XYPADC, CM_INV, /* moved to send/receive */ "padding", XYNPAD, CM_INV, /* moved to send/receive */ "parity", XYPARI, 0, "prompt", XYPROM, 0, "receive", XYRECV, 0, "send", XYSEND, 0, "speed", XYSPEE, 0, " duplex = 1; /* Half duplex */ flow = 0; /* No flow control */ break; default: fatal("invalid argument, type 'kermit -h' for help"); } x = *++xp; /* See if options are bundled */ } return(0); } /* D O C O N N E C T -- invoke the "connect" code */ static doconnect () { int x; conres(); /* restore tty to normal mode */ x = conect(); concb(escape); /* tty back in character mode */ return(x); } /* Misc */ fatal(msg) char *msg; start-of-packet", XYMARK, CM_INV, /* moved to send/receive */ "timeout", XYTIMO, CM_INV /* moved to send/receive */ }; int nprm = (sizeof(prmtab) / sizeof(struct keytab)); /* How many parameters */ /* Remote Command Table */ struct keytab remcmd[] = { "cwd", XZCWD, 0, "delete", XZDEL, 0, "directory", XZDIR, 0, "help", XZHLP, 0, "host", XZHOS, 0, "space", XZSPA, 0, "type", XZTYP, 0, "who", XZWHO, 0 }; int nrmt = (sizeof(remcmd)rgc == 0) || (**xargv == '-')) fatal("missing filename for -g"); cmarg = *xargv; action = 'r'; break; case 'c': /* connect before */ cflg = 1; break; case 'n': /* connect after */ cnflg = 1; break; case 'h': /* help */ usage(); return(-1); case 'a': /* "as" */ if (*(xp+1)) fatal("invalid argument bundling after -a"); *xargv++, xargc--; if ((xargc < 1) || (**xargv == '-')) fatal("missing name in -a"); cmarg2 = *xargv; break; c{ /* Fatal error message */ fprintf(stderr,"\r\nFatal: %s\n",msg); tlog(F110,"Fatal:",msg,0l); doexit(BAD_EXIT); /* Exit indicating failure */ } ermsg(msg) char *msg; { /* Print error message */ if (!quiet) fprintf(stderr,"\r\n%s - %s\n",cmerrp,msg); tlog(F110,"Error -",msg,0l); } /* Interactive command parser */ /* Top-Level Keyword Table */ struct keytab cmdtab[] = { "!", XXSHE, 0, "bye", XXBYE, 0, "c", XXCON, CM_INV, "close", XXCLase 'l': /* set line */ if (*(xp+1)) fatal("invalid argument bundling after -l"); *xargv++, xargc--; if ((xargc < 1) || (**xargv == '-')) fatal("communication line device name missing"); strcpy(ttname,*xargv); /* if (strcmp(ttname,dftty) == 0) local = dfloc; else local = 1; */ local = (strcmp(ttname,CTTNAM) != 0); /* (better than old way) */ debug(F101,"local","",local); ttopen(ttname,&local,0); break; case 'b': /* set baud */ if (*(xp+1)) fatal("invaO, 0, "connect", XXCON, 0, "cwd", XXCWD, 0, "dial", XXDIAL, 0, "directory", XXDIR, 0, "echo", XXECH, 0, "exit", XXEXI, 0, "finish", XXFIN, 0, "get", XXGET, 0, "help", XXHLP, 0, "log", XXLOG, 0, "quit", XXQUI, 0, "r", XXREC, CM_INV, "receive", XXREC, 0, "remote", XXREM, 0, "s", XXSEN, CM_INV, "script", XXLOGI, 0, "send", XXSEN, 0, "server", XXSER, 0, "set", \nType ? for help\n",versio,ckxsys); cmsetp("C-Kermit> "); /* Set default prompt. */ tlevel = -1; /* Take file level */ /* Look for init file in home or current directory. */ homdir = zhome(); lp = line; lp[0] = '\0'; if (homdir) { strcpy(lp,homdir); if (lp[0] == '/') strcat(lp,"/"); } strcat(lp,KERMRC); if ((tfile[0] = fopen(line,"r")) != NULL) { tlevel = 0; debug(F110,"init file",line,0); } if (homdir && (tlevel < 0)) { strcpy(lp,KERMRC); if ((tfab,ncmd,"Command",""); debug(F101,"top-level cmkey","",xx); switch (docmd(xx)) { case -4: /* EOF */ doexit(GOOD_EXIT); /* ...exit successfully */ case -1: /* Reparse needed */ repars = 1; continue; case -2: /* Invalid command given */ if (backgrd) /* if in background, terminate */ fatal("Kermit command error in background execution"); if (tlevel > -1) { /* If in take file, quit */ ermsg("Kermit command error: take file terminated."); fcloile[0] = fopen(line,"r")) != NULL) { tlevel = 0; debug(F110,"init file",line,0); } else { debug(F100,"no init file","",0); } } congm(); /* Get console tty modes */ } /* T R A P -- Terminal interrupt handler */ trap() { debug(F100,"terminal interrupt...","",0); doexit(GOOD_EXIT); /* Exit indicating success */ } /* P A R S E R -- Top-level interactive command parser. */ parser() { int xx, cbn; char *cbp; concb(escape); /* Put consolse(tfile[tlevel]); tlevel--; } cmini(ckxech); /* (fall thru) */ case -3: /* Empty command OK at top level */ default: /* Anything else (fall thru) */ repars = 0; /* No reparse, get new command. */ continue; } } } /* Got an action command; disable terminal interrupts and return start state */ if (!local) connoi(); /* Interrupts off only if remote */ return(sstate); } /* D O E X I T -- Exit from the program. */ doexit(exitstat) ie in cbreak mode. */ conint(trap); /* Turn on console terminal interrupts. */ /* sstate 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. */ if (local) printf("\n"); /*** Temporary kludge ***/ sstate = 0; /* Start with no start state. */ while (sstate == 0) { /* Parse cmds until action requested */ while ((tlevel > -1) &nt exitstat; { ttclos(); /* Close external line, if any */ if (local) { strcpy(ttname,dftty); /* Restore default tty */ local = dfloc; /* And default remote/local status */ } if (!quiet) conres(); /* Restore console terminal. */ if (!quiet) connoi(); /* Turn off console interrupt traps. */ if (deblog) { /* Close any open logs. */ debug(F100,"Debug Log Closed","",0); *debfil = '\0'; deblog = 0; zclose(ZDFILE); } if (pktlog) { *pktfil = '\0'; pktlog = 0;& feof(tfile[tlevel])) { /* If end of take */ fclose(tfile[tlevel]); /* file, close it */ tlevel--; /* and forget about it. */ cmini(ckxech); /* and clear the cmd buffer. */ } if (tlevel > -1) { /* If in take file */ cbp = cmdbuf; /* Get the next line. */ cbn = CMDBL; /* Loop to get next command line and all continuation lines from take file. */ again: if (fgets(line,cbn,tfile[tlevel]) == NULL) continue; lp = line; /* Got one, copy it. */ while (*cbp++ = *lp++) zclose(ZPFILE); } if (seslog) { *sesfil = '\0'; seslog = 0; zclose(ZSFILE); } if (tralog) { tlog(F100,"Transaction Log Closed","",0l); *trafil = '\0'; tralog = 0; zclose(ZTFILE); } exit(exitstat); /* Exit from the program. */ } /* B L D L E N -- Make length-encoded copy of string */ char * bldlen(str,dest) char *str, *dest; { int len; len = strlen(str); *dest = tochar(len); strcpy(dest+1,str); return(dest+len+1); } /* S E T G E N -- Co / sizeof(struct keytab)); struct keytab logtab[] = { "debugging", LOGD, 0, "packets", LOGP, 0, "session", LOGS, 0, "transactions", LOGT, 0 }; int nlog = (sizeof(logtab) / sizeof(struct keytab)); /* Show command arguments */ #define SHPAR 0 /* Parameters */ #define SHVER 1 /* Versions */ struct keytab shotab[] = { "parameters", SHPAR, 0, "versions", SHVER, 0 }; /* C M D I N I -- Initialize the interactive command parser */ cmdini() { printf("%s,%s if (--cbn < 1) fatal("Command too long for internal buffer"); if (*(cbp - 3) == '\\') { /* Continued on next line? */ cbp -= 3; /* If so, back up pointer, */ goto again; /* go back, get next line. */ } stripq(cmdbuf); /* Strip any quotes from cmd buffer. */ } else { /* No take file, get typein. */ prompt(); /* Issue interactive prompt. */ cmini(ckxech); } repars = 1; displa = 0; while (repars) { cmres(); /* Reset buffer pointers. */ xx = cmkey(cmdtnstruct a generic command */ setgen(type,arg1,arg2,arg3) char type, *arg1, *arg2, *arg3; { char *upstr, *cp; cp = cmdstr; *cp++ = type; *cp = NUL; if (*arg1 != NUL) { upstr = bldlen(arg1,cp); if (*arg2 != NUL) { upstr = bldlen(arg2,upstr); if (*arg3 != NUL) bldlen(arg3,upstr); } } cmarg = cmdstr; debug(F110,"setgen",cmarg,0); return('g'); } /* D O C M D -- Do a command */ /* Returns: -2: user typed an illegal command -1: reparse needed IR: /* directory */ if ((x = cmtxt("Directory/file specification",".",&s)) < 0) return(x); lp = line; sprintf(lp,"%s %s",DIRCMD,s); system(line); return(0); case XXECH: /* echo */ x = cmtxt("Material to be echoed","",&s); if (x < 0) return(x); printf("%s\n",s); return(0); case XXQUI: /* quit, exit */ case XXEXI: if ((x = cmcfm()) > -1) doexit(GOOD_EXIT); else return(x); case XXFIN: /* finish */ if ((x = cmcfm()) < 0) return(x); if (!local) {0: parse was successful (even tho command may have failed). */ docmd(cx) int cx; { int x, y; char *s; switch (cx) { case -4: /* EOF */ if (!quiet) printf("\r\n"); doexit(GOOD_EXIT); case -3: /* Null command */ return(0); case -2: /* Error */ case -1: /* Reparse needed */ return(cx); case XXBYE: /* bye */ if ((x = cmcfm()) < 0) return(x); if (!local) { printf("You have to 'set line' first\n"); return(0); } sstate = setgen('L',"","",""); re printf("You have to 'set line' first\n"); return(0); } sstate = setgen('F',"","",""); return(0); case XXGET: /* Get */ if (!local) { printf("\nYou have to 'set line' first\n"); return(0); } x = cmtxt("Name of remote file(s), or carriage return","",&cmarg); if ((x == -2) || (x == -1)) return(x); /* If foreign file name omitted, get foreign and local names separately */ if (*cmarg == NUL) { if (tlevel > -1) { /* Input is from take file */ if (fgets(line,10turn(0); case XXCON: /* connect */ if ((x = cmcfm()) < 0) return(x); return ( doconnect () ); case XXCWD: if (cmtxt("Name of local directory, or carriage return",homdir,&s) < 0) return(-1); if (chdir(s)) perror(s); cwdf = 1; system(PWDCMD); return(0); case XXCLO: x = cmkey(logtab,nlog,"Which log to close",""); if (x == -3) { printf("?You must tell which log\n"); return(-2); } if (x < 0) return(x); if ((y = cmcfm()) < 0) ret0,tfile[tlevel]) == NULL) fatal("take file ends prematurely in 'get'"); stripq(line); cmarg = line; if (fgets(cmdbuf,CMDBL,tfile[tlevel]) == NULL) fatal("take file ends prematurely in 'get'"); stripq(cmdbuf); if (*cmdbuf == NUL) cmarg2 = line; else cmarg2 = cmdbuf; } else { /* Input is from terminal */ char psave[40]; /* Save old prompt */ cmsavp(psave,40); cmsetp(" Remote file specification: "); /* Make new one */ cmini(ckxech); x = -1urn(y); switch (x) { case LOGD: if (deblog == 0) { printf("?Debugging log wasn't open\n"); return(0); } *debfil = '\0'; deblog = 0; return(zclose(ZDFILE)); case LOGP: if (pktlog == 0) { printf("?Packet log wasn't open\n"); return(0); } *pktfil = '\0'; pktlog = 0; return(zclose(ZPFILE)); case LOGS: if (seslog == 0) { printf("?Session log wasn't open\n"); return(0); } *sesfil = '\0'; seslog = 0; return(zclose(ZSFI; prompt(); while (x == -1) { /* Prompt till they answer */ x = cmtxt("Name of remote file(s)","",&cmarg); debug(F111," cmtxt",cmarg,x); } if (x < 0) { cmsetp(psave); return(x); } if (*cmarg == NUL) { /* If user types a bare CR, */ printf("(cancelled)\n"); /* Forget about this. */ cmsetp(psave); /* Restore old prompt, */ return(0); /* and return. */ } strcpy(line,cmarg); /* Make a safe copy */ cmarg = line; cmsetp(" Local name tLE)); case LOGT: if (tralog == 0) { printf("?Transaction log wasn't open\n"); return(0); } *trafil = '\0'; tralog = 0; return(zclose(ZTFILE)); default: printf("\n?Unexpected log designator - %ld\n", x); return(0); } case XXDIAL: /* dial number */ if ( ( x = cmtxt( "Number to be dialed", "", &s ) ) >= 0 ) if ( ( x = dial(s) ) == 0 ) /* if dialing was successful */ x = doconnect (); /* automatically do a connect */ return ( x ); case XXDo store it under: "); /* New prompt */ cmini(ckxech); x = -1; prompt(); /* Prompt */ while (x < 0) { /* Again, parse till answered */ x = cmofi("Local file name","",&cmarg2); if (x == -2) return(x); if (x == -3) { /* If bare CR, */ printf("(cancelled)\n"); /* escape from this... */ cmsetp(psave); /* restore old prompt, */ return(0); /* and return. */ } } cmsetp(psave); /* Restore old prompt. */ if ((x == cmcfm()rn(x); sstate = 'x'; if (local) displa = 1; return(0); case XXSET: /* Set */ x = cmkey(prmtab,nprm,"Parameter",""); if (x == -3) { printf("?You must specify a parameter to set\n"); return(-2); } if (x < 0) return(x); return(doprm(x)); /* XXSHE code by H. Fischer; copyright rights assigned to Columbia Univ */ /* Adapted to use getpwuid to find login shell because many systems don't have SHELL in environment, and to use direct calling of shell rather than intermed printf("\nNothing to show...\n"); break; } return(0); case XXSPA: /* space */ if ((x = cmcfm()) < 0) return(x); system(SPACMD); return(0); case XXSTA: /* statistics */ if ((x = cmcfm()) < 0) return(x); printf("\nMost recent transaction --\n"); printf(" files: %ld\n",filcnt); printf(" total file characters : %ld\n",tfc); printf(" communication line in : %ld\n",tlci); printf(" communication line out : %ld\n\n",tlco); printf(" block check t) < 0) return(-2); } } sstate = 'r'; /* All ok, set start state. */ if (local) displa = 1; return(0); case XXHLP: /* Help */ x = cmkey(cmdtab,ncmd,"C-Kermit command","help"); return(dohlp(x)); case XXLOG: /* Log */ x = cmkey(logtab,nlog,"What to log",""); if (x == -3) { printf("?You must specify what is to be logged\n"); return(-2); } if (x < 0) return(x); return(dolog(x)); case XXLOGI: /* login to remote system */ if ((x = cmtxt("Texiate system() call. -- H. Fischer */ case XXSHE: /* Local shell command */ { int pid; if (cmtxt("Unix shell command to execute","",&s) < 0) return(-1); conres(); /* Make console normal */ #ifdef MSDOS zxcmd(s); #else #ifdef vax11c system(s); /* Best we can do for VMS? */ #else /* All Unix systems... */ if ((pid = fork()) == 0) { /* Make child */ char *shpath, *shname, *shptr; /* For finding desired shell */ struct passwd *p; extern struct passwd * getpwuid();t of login script","",&s)) < 0) return(x); return( login(s) ); /* return success 0=completed -2=fail*/ case XXREC: /* Receive */ cmarg2 = ""; x = cmofi("Name under which to store the file, or CR","",&cmarg2); if ((x == -1) || (x == -2)) return(x); debug(F111,"cmofi cmarg2",cmarg2,x); if ((x = cmcfm()) < 0) return(x); sstate = 'v'; if (local) displa = 1; return(0); case XXREM: /* Remote */ if (!local) { printf("\nYou have to 'set line' first\n"); return(-2) extern int getuid(); char *defShel = "/bin/sh"; /* Default */ p = getpwuid( getuid() ); /* Get login data */ if ( p == (struct passwd *) NULL || !*(p->pw_shell) ) shpath = defShel; else shpath = p->pw_shell; shptr = shname = shpath; while (*shptr != '\0') if (*shptr++ == '/') shname = shptr; if (*s == NUL) /* Interactive shell requested? */ execl(shpath,shname,"-i",0); /* Yes, do that */ else /* Otherwise, */ execl(shpath,shname,"-c",s,0); /* execute the given com; } x = cmkey(remcmd,nrmt,"Remote Kermit server command",""); if (x == -3) { printf("?You must specify a command for the remote server\n"); return(-2); } return(dormt(x)); case XXSEN: /* Send */ cmarg = cmarg2 = ""; if ((x = cmifi("File(s) to send","",&s,&y)) < 0) { if (x == -3) { printf("?A file specification is required\n"); return(-2); } return(x); } nfils = -1; /* Files come from internal list. */ strcpy(line,s); /* Save copy of string justmand */ exit(GOOD_EXIT); } /* Just punt if it didn't work */ else { /* Parent */ int wstat; /* Kermit must wait for child */ int (*istat)(), (*qstat)(); istat = signal(SIGINT,SIG_IGN); /* Let the fork handle keyboard */ qstat = signal(SIGQUIT,SIG_IGN); /* interrupts itself... */ while (((wstat = wait(0)) != pid) && (wstat != -1)) /* Wait for fork */ ; signal(SIGINT,istat); /* Restore interrupts */ signal(SIGQUIT,qstat); } #endif #endif concb(escape); /* Console parsed. */ debug(F101,"Send: wild","",y); *cmarg2 = '\0'; /* Initialize send-as name */ if (y == 0) { if ((x = cmtxt("Name to send it with","",&cmarg2)) < 0) return(x); } else { if ((x = cmcfm()) < 0) return(x); } cmarg = line; /* File to send */ debug(F110,"Sending:",cmarg,0); if (*cmarg2 != '\0') debug(F110," as:",cmarg2,0); sstate = 's'; /* Set start state */ if (local) displa = 1; return(0); case XXSER: /* Server */ if ((x = cmcfm()) < 0) retuback in cbreak mode */ return(0); } case XXSHO: /* Show */ x = cmkey(shotab,2,"","parameters"); if (x < 0) return(x); if (y = (cmcfm()) < 0) return(y); switch (x) { case SHPAR: shopar(); break; case SHVER: printf("\nVersions:\n %s\n %s\n",versio,protv); printf(" %s\n",fnsv); printf(" %s\n %s\n %s for%s\n",cmdv,userv,ckxv,ckxsys); printf(" %s for%s\n %s\n",ckzv,ckzsys,connv); printf(" %s\n %s\n\n",dialv,loginv); break; default: e 's': printf("space"); break; case 0: printf("none"); break; default: printf("invalid - %d",parity); break; } printf(", duplex: "); if (duplex) printf("half, "); else printf("full, "); printf("flow: "); if (flow == 1) printf("xon/xoff"); else if (flow == 0) printf("none"); else printf("%d",flow); printf(", handshake: "); if (turn) printf("%d\n",turnch); else printf("none\n"); printf(" Delay: %d\n",delay); printf(" Send timeout: %d, receive timeout: %d\n",rtimo, if ((y = cmcfm()) < 0) return(y); /* cont'd... */ /* ...dolog, cont'd */ switch (x) { case LOGD: return(deblog = debopn(s)); case LOGP: zclose(ZPFILE); y = zopeno(ZPFILE,s); if (y > 0) strcpy(pktfil,s); else *pktfil = '\0'; return(pktlog = y); case LOGS: zclose(ZSFILE); y = zopeno(ZSFILE,s); if (y > 0) strcpy(sesfil,s); else *sesfil = '\0'; return(seslog = y); case LOGT: zclose(ZTFILE); tralog = zopeno(ZTFILE,s); if (tralog > 0)timint); printf(" Send padding: %d, pad character: %d\n",npad,padch); printf(" Receive padding: %d pad character: %d\n",mypadn,mypadc); printf(" Send Packet start: %d, end: %d, length: %d\n",mystch,eol,spsiz); printf(" Receive Packet start: %d, end: %d, length: %d\n",stchr,seol,rpsiz); printf("Block check: %d\n",bctr); printf("\nFile parameters:\n"); printf(" Names: "); if (fncnv) printf("converted\n"); else printf("literal\n"); printf(" Type: "); if (b { strcpy(trafil,s); tlog(F110,"Transaction Log:",versio,0l); tlog(F100,ckxsys,"",0); ztime(&s); tlog(F100,s,"",0l); } else *trafil = '\0'; return(tralog); default: return(-2); } } /* D E B O P N -- Open a debugging file */ debopn(s) char *s; { #ifdef DEBUG char *tp; zclose(ZDFILE); deblog = zopeno(ZDFILE,s); if (deblog > 0) { strcpy(debfil,s); debug(F110,"Debug Log ",versio,0); debug(F100,ckxsys,"",0); ztime(&tp); debug(F100,tp,"",0); ype used : %d\n",bctu); printf(" compression : "); if (rptflg) printf("yes\n"); else printf("no\n"); printf(" 8th bit prefixing : "); if (ebqflg) printf("yes\n"); else printf("no\n\n"); return(0); case XXTAK: /* take */ if (tlevel > MAXTAKE-1) { printf("?Take files nested too deeply\n"); return(-2); } if ((y = cmifi("C-Kermit command file","",&s,&x)) < 0) { if (y == -3) { printf("?A file specification is required\n"); return(-2); } else retinary) printf("binary\n"); else printf("text\n"); printf(" Warning: "); if (warn) printf("on\n"); else printf("off\n"); printf(" Display: "); if (quiet) printf("off\n"); else printf("on\n"); #ifdef KERMRC printf("\nInit File: %s",KERMRC); #endif printf("\nLogs:"); #ifdef DEBUG printf("\n Debugging: "); if (deblog) printf("%s",debfil); else printf("none"); #endif printf("\n Packets: "); if (pktlog) printf("%s",pktfil); else printf("none"); urn(y); } if (x != 0) { printf("?Wildcards not allowed in command file name\n"); return(-2); } strcpy(line,s); /* Make a safe copy of the string */ if ((y = cmcfm()) < 0) return(y); if ((tfile[++tlevel] = fopen(line,"r")) == NULL) { perror("take"); printf("Can't open command file - %s\n",line); debug(F110,"Failure to open",line,0); tlevel--; return(0); } return(0); default: printf("Not available - %s\n",cmdbuf); return(-2); } } /* S H O P A R -- Sh printf("\n Session: "); if (seslog) printf("%s",sesfil); else printf("none"); #ifdef TLOG printf("\n Transactions: "); if (tralog) printf("%s",trafil); else printf("none"); #endif printf("\n\n"); } /* D O L O G -- */ dolog(x) int x; { int y; char *s; switch (x) { case LOGD: #ifdef DEBUG y = cmofi("Name of debugging log file","debug.log",&s); #else y = -2; s = ""; printf("%s","- Sorry, debug log not available\n"); #endif break; case LOGP:ow Parameters */ shopar() { int i; extern struct keytab mdmtab[]; extern int nmdm; printf("\nLine: %s, speed: %d, mode: ",ttname,speed); if (local) printf("local"); else printf("remote"); for (i = 0; i < nmdm; i++) { if (mdmtab[i].val == mdmtyp) { printf(", modem-dialer: %s",mdmtab[i].kwd); break; } } printf("\n Parity: "); switch (parity) { case 'e': printf("even"); break; case 'o': printf("odd"); break; case 'm': printf("mark"); break; cas y = cmofi("Name of packet log file","packet.log",&s); break; case LOGS: y = cmofi("Name of session log file","session.log",&s); break; case LOGT: #ifdef TLOG y = cmofi("Name of transaction log file","transact.log",&s); #else y = -2; s = ""; printf("%s","- Sorry, transaction log not available\n"); #endif break; default: printf("\n?Unexpected log designator - %d\n",x); return(-2); } if (y < 0) return(y); strcpy(line,s); s = line; /* 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. */ #ifndef vax11c #include #endif /* Values associAND 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 2ated 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 */ 2 /* 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 */ /* REMOTE command sy#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 */ #mbols */ #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 1} else *debfil = '\0'; return(deblog); #else return(0); #endif } F100,ckxsys,"",0); ztime(&s); tlog(F100,s,"",0l); } else *trafil = '\0'; return(tralog); default: return(-2); } } /* D E B O P N -- Open a debugging file */ debopn(s) char *s; { #ifdef DEBUG char *tp; zclose(ZDFILE); deblog = zopeno(ZDFILE,s); if (deblog > 0) { strcpy(debfil,s); debug(F110,"Debug Log ",versio,0); debug(F100,ckxsys,"",0); ztime(&tp); debug(F100,tp,"",0); 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) logon */ /* SET parameters */ #define XYBREA 0 /* BREAK simulati./usr/opt/src/kermit/ckuusr.h 644 0 3 10371 5555215355 11363 on */ #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 XYH./usr/opt/src/kermit/ckwart.c 644 0 3 30411 5555215355 11332 d 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 char *wartv = "Wart Version 1A(003) 27 May 85"; /* 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 * %% * | CHAR { actions } * ... * %% */ #include "ckcdeb.h" /* Includes */ #include #include #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 ofn 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 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,ns== '%') { 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 all6 /* 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 */ 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 1tates,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 associateowable */ 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) co bcnt = 1; putc(c,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,"\nbreak;\n"); } /* * find the action associated with a given character and state. * returns -1 if one can't be found. * */ faction(hd,state,chr) Trntinue; /* 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; istates[i] = 0; new->anyst = 0; new->nxt = NULL; return(new); } /* * read all the rules. * ans 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; ianyst = 1; } (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; i++) { fprintf(fp,"%d, ",cont[i]); if ((i % 20) == 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' 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("missingt 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),stat 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)) != '\n') && (isspace(c) || c == C_L)); if (c == '{') { e,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(out* next on collision chain */ *htab[HASHSIZE]; /* the hash table */ /* * empty the hash table before using it... * */ clrhash() { int i; for (i=0; iname = copy(name); cur->val = svalue; cur->hnxt = htab[h]; htab[h] = cur; } fp) 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; { intf 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; } 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); / /* * 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); } (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; } * skip over the comment */ continue; } /* and keep looping */ else { ungetc(c); /* 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)) { ./usr/opt/src/uucp/ 40775 0 3 0 5555215426 7315 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; } /./usr/opt/src/uucp/Makefile 664 0 3 577 5555215425 10766 #include #include #include #include /* single character decode */ #define DEC(c) (((c) - ' ') & 077) main(argc, argv) char **argv; { FILE *in, *out; int mode; char dest[128]; char buf[80]; /* optional input arg */ if (argc > 1) { if ((in = fopen(argv[1], "r")) == NULL) { perror(argv[1]); exit(1); } argv++; argc--; } else in = stdin; if (argc != 1) { printf("Usage: uudecode [infile]\n"); exit(2); } /* search for header line */ for./usr/opt/src/uucp/uuencode.c 664 0 3 4672 5555215425 11321 (;;) { if (fgets(buf, sizeof buf, in) == NULL) { fprintf(stderr, "No begin line\n"); exit(3); } if (strncmp(buf, "begin ", 6) == 0) break; } sscanf(buf, "begin %o %s", &mode, dest); /* handle ~user/file format */ if (dest[0] == '~') { char *sl; struct passwd *getpwnam(); struct passwd *user; char dnbuf[100], *index(), *strcat(), *strcpy(); sl = index(dest, '/'); if (sl == NULL) { fprintf(stderr, "Illegal ~user\n"); exit(3); } *sl++ = 0; user = getpwnam(dest+1); /* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to./usr/opt/src/uucp/uudecode.c 664 0 3 6440 5555215425 11302 if (user == NULL) { fprintf(stderr, "No such user as %s\n", dest); exit(4); } strcpy(dnbuf, user->pw_dir); strcat(dnbuf, "/"); strcat(dnbuf, sl); strcpy(dest, dnbuf); } /* create output file */ out = fopen(dest, "w"); if (out == NULL) { perror(dest); exit(4); } chmod(dest, mode); decode(in, out); if (fgets(buf, sizeof buf, in) == NULL || strcmp(buf, "end\n")) { fprintf(stderr, "No end line\n"); exit(5); } exit(0); } /* * copy from in to out, decoding as you go along./* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to */ decode(in, out) FILE *in; FILE *out; { char buf[80]; char *bp; int n; for (;;) { /* for each input line */ if (fgets(buf, sizeof buf, in) == NULL) { printf("Short file\n"); exit(10); } n = DEC(buf[0]); if (n <= 0) break; bp = &buf[1]; while (n > 0) { outdec(bp, out, n); bp += 4; n -= 3; } } } /* * output a group of 3 bytes (4 input characters). * the input chars are pointed to by p, they are to * be output to file f. n is used to tell us not to * output al endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef lint static char sccsid[] = "@(#)uudecode.c 5.5 (Berkeley) 7/6/88"; #endif /* not lint */ /* * uudecode [input] * * create the specified file, decoding as you go. * used with uuencode. */ l of them at the end of the file. */ outdec(p, f, n) char *p; FILE *f; { int c1, c2, c3; c1 = DEC(*p) << 2 | DEC(p[1]) >> 4; c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2; c3 = DEC(p[2]) << 6 | DEC(p[3]); if (n >= 1) putc(c1, f); if (n >= 2) putc(c2, f); if (n >= 3) putc(c3, f); } outdec(bp, out, n); bp += 4; n -= 3; } } } /* * output a group of 3 bytes (4 input characters). * the input chars are pointed to by p, they are to * be output to file f. n is used to tell us not to * output al /* figure out the input file mode */ if (fstat(fileno(in), &sbuf) < 0 || !isatty(fileno(in))) mode = 0666 & ~umask(0666); else mode = sbuf.st_mode & 0777; printf("begin %o %s\n", mode, argv[1]); encode(in, stdout); printf("end\n"); exit(0); } /* * copy from in to out, encoding as you go along. */ encode(in, out) register FILE *in; register FILE *out; { char buf[80]; register int i, n; for (;;) { /* 1 (up to) 45 character line */ n = fread(buf, 1, 45, in); putc(ENC(n), out); for./usr/opt/src/ucb/clear.c 640 0 3 1255 5555215524 10361 (i=0; i> 2; c2 = (*p << 4) & 060 | (p[1] >> 4) & 017; c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 03; c4 = p[2] & 077; putc(ENC(c1), f); putc(ENC(c2), f); putc(ENC(c3), f); putc(ENC(c4), f); } acter line */ n = fread(buf, 1, 45, in); putc(ENC(n), out); for/* load me with -ltermlib */ /* #include on version 6 */ /* * clear - clear the screen */ #include #include char *getenv(); char *tgetstr(); char PC; short ospeed; #undef putchar int putchar(); main() { char *cp = getenv("TERM"); char clbuf[20]; char pcbuf[20]; char *clbp = clbuf; char *pcbp = pcbuf; char *clear; char buf[1024]; char *pc; struct sgttyb tty; gtty(1, &tty); ospeed = tty.sg_ospeed; if (cp == (char *) 0) exit(1); if (tgetent(buf, cp) != 1) ./usr/opt/src/ucb/ 40775 0 3 0 5555215676 7121 exit(1); pc = tgetstr("pc", &pcbp); if (pc) PC = *pc; clear = tgetstr("cl", &clbp); if (clear) tputs(clear, tgetnum("li"), putchar); exit (clear != (char *) 0); } r(); char PC; short ospeed; #undef putchar int putchar(); main() { char *cp = getenv("TERM"); char clbuf[20]; char pcbuf[20]; char *clbp = clbuf; char *pcbp = pcbuf; char *clear; char buf[1024]; char *pc; struct sgttyb tty; gtty(1, &tty); ospeed = tty.sg_ospeed; if (cp == (char *) 0) exit(1); if (tgetent(buf, cp) != 1) endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef lint static char sccsid[] = "@(#)uuencode.c 5.6 (Berkeley) 7/6/88"; #endif /* not lint */ /* * uuencode [input] output * * Encode a file so it can be mailed to a remote system. */ #include ./usr/opt/src/ucb/Makefile 644 0 3 263 5555215611 10546 #include #include /* ENC is the basic 1 character encoding function to make a char printing */ #define ENC(c) ((c) ? ((c) & 077) + ' ': '`') main(argc, argv) char **argv; { FILE *in; struct stat sbuf; int mode; /* optional 1st argument */ if (argc > 2) { if ((in = fopen(argv[1], "r")) == NULL) { perror(argv[1]); exit(1); } argv++; argc--; } else in = stdin; if (argc != 2) { fprintf(stderr,"Usage: uuencode [infile] remotefile\n"); exit(2); } all: clear clear: $(CC) clear.c -o clear -lcurses strip clear clean: rm -f *.o rm -f clear install: cp clear /usr/bin chown bin /usr/bin/clear chgrp bin /usr/bin/clear ster char *p; register FILE *f; { register int c1, c2, c3, c4; c1 = *p >> 2; c2 = (*p << 4) & 060 | (p[1] >> 4) & 017; c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 03; c4 = p[2] & 077; putc(ENC(c1), f); putc(ENC(c2), f); putc(ENC(c3), f); putc(ENC(c4), f); } acter line */ n = fread(buf, 1, 45, in); putc(ENC(n), out); for./usr/opt/src/dhrystone/Makefile 644 0 3 415 5555216635 12022 umber to 500000 to * get better accuracy. Please select the way to * measure the execution time using the TIME define. * For single user machines, time(2) is adequate. For * multi-user machines where you cannot get single-user * access, use the times(2) function. If you have * neither, use a stopwatch in the dead of night. * Use a "printf" at the point marked "start timer" * to begin your timings. DO NOT use the UNIX "time(1)" * command, as this will measure the total time to * all: drynr dryr drynr: $(CC) -O dry.c -o drynr strip drynr dryr: $(CC) -O -DREG=register dry.c -o dryr strip dryr clean: rm -f *.o rm -f drynr dryr install: cp dryr /usr/bin cp drynr /usr/bin chown bin dryr chown bin drynr chgrp bin dryr chgrp bin drynr char clbuf[20]; char pcbuf[20]; char *clbp = clbuf; char *pcbp = pcbuf; char *clear; char buf[1024]; char *pc; struct sgttyb tty; gtty(1, &tty); ospeed = tty.sg_ospeed; if (cp == (char *) 0) exit(1); if (tgetent(buf, cp) != 1) run this program, which will (erroneously) include * the time to malloc(3) storage and to compute the * time it takes to do nothing. * * Run: drynr; dryr * * Results: If you get any new machine/OS results, please send to: * * ihnp4!castor!pcrat!rick * * and thanks to all that do. Space prevents listing * the names of those who have provided some of these * results. I'll be forwarding these results to * Rheinhold Weicker. * * Note: I order the list in increasing performan./usr/opt/src/dhrystone/dry.c 644 0 3 67362 5555216261 11375 ce of the * "with registers" benchmark. If the compiler doesn't * provide register variables, then the benchmark * is the same for both REG and NOREG. * * PLEASE: Send complete information about the machine type, * clock speed, OS and C manufacturer/version. If * the machine is modified, tell me what was done. * On UNIX, execute uname -a and cc -V to get this info. * * 80x8x NOTE: 80x8x benchers: please try to do all memory models * for a particular compiler. * * APOLOGY (1/30//***** hpda:net.sources / homxb!gemini / 1:58 am Apr 1, 1986*/ /* EVERBODY: Please read "APOLOGY" below. -rick 01/06/85 * See introduction in net.arch, or net.micro * * "DHRYSTONE" Benchmark Program * * Version: C/1.1, 12/01/84 * * Date: PROGRAM updated 01/06/86, RESULTS updated 03/31/86 * * Author: Reinhold P. Weicker, CACM Vol 27, No 10, 10/84 pg. 1013 * Translated from ADA by Rick Richardson * Every method to preserve ADA-likeness has been used, * at the expense of C-ness. * *86): * Well, I goofed things up! As pointed out by Haakon Bugge, * the line of code marked "GOOF" below was missing from the * Dhrystone distribution for the last several months. It * *WAS* in a backup copy I made last winter, so no doubt it * was victimized by sleepy fingers operating vi! * * The effect of the line missing is that the reported benchmarks * are 15% too fast (at least on a 80286). Now, this creates * a dilema - do I throw out ALL the data so far collected * and use only./usr/opt/src/dhrystone/ 40775 0 3 0 5555217245 10361 Compile: cc -O dry.c -o drynr : No registers * cc -O -DREG=register dry.c -o dryr : Registers * * Defines: Defines are provided for old C compiler's * which don't have enums, and can't assign structures. * The time(2) function is library dependant; Most * return the time in seconds, but beware of some, like * Aztec C, which return other units. * The LOOPS define is initially set for 50000 loops. * If you have a machine with large integers and is * very fast, please change this n results from this (corrected) version, or * do I just keep collecting data for the old version? * * Since the data collected so far *is* valid as long as it * is compared with like data, I have decided to keep * TWO lists- one for the old benchmark, and one for the * new. This also gives me an opportunity to correct one * other error I made in the instructions for this benchmark. * My experience with C compilers has been mostly with * UNIX 'pcc' derived compilers, where the 'optimizer' si1 1650 1640 * Ridge 32C V1 - ROS 3.3 Ridge C (older) 1628 1695 * Gould PN6005 - UTX 1.1c+ (4.2) cc 1732 1884 * Gould PN9080 custom ECL UTX-32 1.1C cc 4745 4992 * VAX-784 - Mach/4.3 cc 5263 5555 &4 * VAX 8600 - 4.3 BSD cc 6329 6423 * Amdahl 5860 - UTS sysV cc 1.22 28735 28846 * IBM3090/200 - ? ? 31250 31250 * * *----------------DHRYSTONE VERSION 1.0 RESULTS BEGIN-------------------------- * * MACHINE MICROPROCESSOR OPERATING COMPILER DHRYSTONES/SEC. * TYPE SYSTEmply * fixes sloppy code generation (peephole optimization). * But today, there exist C compiler optimizers that will actually * perform optimization in the Computer Science sense of the word, * by removing, for example, assignments to a variable whose * value is never used. Dhrystone, unfortunately, provides * lots of opportunities for this sort of optimization. * * I request that benchmarkers re-run this new, corrected * version of Dhrystone, turning off or bypassing optimizers * whichM NO REG REGS * -------------------------- ------------ ----------- --------------- * Commodore 64 6510-1MHz C64 ROM C Power 2.8 36 36 * HP-110 8086-5.33Mhz MSDOS 2.11 Lattice 2.14 284 284 * IBM PC/XT 8088-4.77Mhz PC/IX cc 271 294 * CCC 3205 - Xelos(SVR2) cc 558 592 * Perq-II 2901 bitslice Accent S5c cc (CMU) 301 301 * IBM PC/XT 8088-4.77Mhz COHERENT 2.3.43 MarkWilliams cc 296 317 * Cosmos 68000-8Mhz UniSoft cc 305 322 * IBM PC/XT 8088-4.77Mhz Venix/86 2.0 cc 297 324 perform more than peephole optimization. Please * indicate the version of Dhrystone used when reporting the * results to me. * * RESULTS BEGIN HERE * *----------------DHRYSTONE VERSION 1.1 RESULTS BEGIN-------------------------- * * MACHINE MICROPROCESSOR OPERATING COMPILER DHRYSTONES/SEC. * TYPE SYSTEM NO REG REGS * -------------------------- ------------ ----------- --------------- * Apple IIe 65C02-1.02Mhz DOS 3.3 Aztec CII v1.05i 37 37 * - Z80-2.5Mhz CPM-80 v2.2 Aztec CII v1 * DEC PRO 350 11/23 Venix/PRO SVR2 cc 299 325 * IBM PC 8088-4.77Mhz MSDOS 2.0 b16cc 2.0 310 340 * PDP11/23 11/23 Venix (V7) cc 320 358 * Commodore Amiga ? Lattice 3.02 368 371 * PC/XT 8088-4.77Mhz Venix/86 SYS V cc 339 377 * IBM PC 8088-4.77Mhz MSDOS 2.0 CI-C86 2.20M 390 390 * IBM PC/XT 8088-4.77Mhz PCDOS 2.1 Wizard 2.1 367 403 * IBM PC/XT 8088-4.77Mhz PCDOS 3.1 Lattice 2.15 403 403 @ * Colex DM-.05g 91 91 * - 8086-8Mhz RMX86 V6 Intel C-86 V2.0 197 203LM?? * IBM PC/XT 8088-4.77Mhz COHERENT 2.3.43 Mark Wiiliams 259 275 * - 8086-8Mhz RMX86 V6 Intel C-86 V2.0 287 304 ?? * Fortune 32:16 68000-6Mhz V7+sys3+4.1BSD cc 360 346 * PDP-11/34A w/FP-11C UNIX V7m cc 406 449 * Macintosh512 68000-7.7Mhz Mac ROM O/S DeSmet(C ware) 625 625 * VAX-11/750 w/FPA UNIX 4.2BSD cc 831 852 * DataMedia 932 68000-10Mhz UNIX sysV cc 837 888 * Plexus P35 68000-12.5Mhz UNIX sysIII cc 835 8946 68010-8Mhz Unisoft SYSV cc 378 410 * IBM PC 8088-4.77Mhz PCDOS 3.1 Datalight 1.10 416 416 * IBM PC NEC V20-4.77Mhz MSDOS 3.1 MS 3.1 387 420 * IBM PC/XT 8088-4.77Mhz PCDOS 2.1 Microsoft 3.0 390 427 * IBM PC NEC V20-4.77Mhz MSDOS 3.1 MS 3.1 (186) 393 427 * PDP-11/34 - UNIX V7M cc 387 438 * IBM PC 8088, 4.77mhz PC-DOS 2.1 Aztec C v3.2d 423 454 * Tandy 1000 V20, 4.77mhz MS-DOS 2.11 Aztec C v3.2d 423 458 * Tandy TRS-16B 68000-6Mhz Xenix 1.3.5 cc 438 458 * PDP-11/34 - RSTS/E * ATT PC7300 68010-10Mhz UNIX 5.0.3 cc 973 1034 * Compaq II 80286-8Mhz MSDOS 3.1 MS C 3.0 1086 1140 LM * IBM PC/AT 80286-7.5Mhz Venix/286 SVR2 cc 1159 1254 *15 * Compaq II 80286-8Mhz MSDOS 3.1 MS C 3.0 1190 1282 MM * MicroVAX II - Mach/4.3 cc 1361 1385 * DEC uVAX II - Ultrix-32m v1.1 cc 1385 1399 * Compaq II 80286-8Mhz MSDOS 3.1 MS C 3.0 1351 1428 * VAX 11/780 - UNIX 4.2BSD cc 1417 1441 * VAX-780/MA780 Mach/4.3 cc 1428 1470 * VAX 11/780 - UNIX 5.0.1 cc 4.1.1.3decus c 438 495 * Onyx C8002 Z8000-4Mhz IS/1 1.1 (V7) cc 476 511 * Tandy TRS-16B 68000-6Mhz Xenix 1.3.5 Green Hills 609 617 * DEC PRO 380 11/73 Venix/PRO SVR2 cc 577 628 * FHL QT+ 68000-10Mhz Os9/68000 version 1.3 603 649 FH * Apollo DN550 68010-?Mhz AegisSR9/IX cc 3.12 666 666 * HP-110 8086-5.33Mhz MSDOS 2.11 Aztec-C 641 676 * ATT PC6300 8086-8Mhz MSDOS 2.11 b16cc 2.0 632 684 * IBM PC/AT 80286-6Mhz PCDOS 3.0 CI-C86 2.1 666 684 * Tandy 6000 68000-81 892 980 C1 * IBM PC/XT 8086-9.54Mhz PCDOS 3.1 Lattice 2.15 980 980 C1 * Plexus P35 68000-10Mhz UNIX System III cc 984 980 * PDP-11/73 KDJ11-AA 15Mhz UNIX V7M 2.1 cc 862 981 * VAX 11/750 w/FPA UNIX 4.3bsd cc 994 997 * IRIS-1400 68010-10Mhz UNIX System V cc 909 1000 * IBM PC/AT 80286-6Mhz Venix/86 2.1 cc 961 1000 * IBM PC/AT 80286-6Mhz PCDOS 3.0 b16cc 2.0 943 1063 * Zilog S8000/11 Z8001-5.5Mhz Zeus 3.2 cc 1011 1084 * NSC ICM-3216 NSC 32016-10Mhz UNIX SVR2 cc 1041 1084 * IBMenix 3.0 cc 1384 1477 * MicroVAX II - Mach/4.3 cc 1513 1536 * WICAT MB 68000-12.5Mhz System V WICAT C 4.1 1246 1537 ~ * IBM PC/AT 80286-9Mhz SCO Xenix V cc 1540 1556 *18 * Cyb DataMate 68010-12.5Mhz Uniplus 5.0 Unisoft cc 1470 1562 S * VAX 11/780 - UNIX 5.2 cc 1515 1562 * MicroVAX-II - - - 1562 1612 * VAX-780/MA780 Mach/4.3 cc 1587 1612 * VAX 11/780 - UNIX 4.3bsd cc 1646 1662 * Apollo DN660 - AegisSR9/IX cc 3.12 1666 1666 * ATT 3B20 - UNIX 5.2 cc 15Mhz Xenix 3.0 cc 694 694 * IBM PC/AT 80286-6Mhz Xenix 3.0 cc 684 704 MM * Macintosh 68000-7.8Mhz 2M Mac Rom Mac C 32 bit int 694 704 * Macintosh 68000-7.7Mhz - MegaMax C 2.0 661 709 * Macintosh512 68000-7.7Mhz Mac ROM O/S DeSmet(C ware) 714 714 * IBM PC/AT 80286-6Mhz Xenix 3.0 cc 704 714 LM * Codata 3300 68000-8Mhz UniPlus+ (v7) cc 678 725 * WICAT MB 68000-8Mhz System V WICAT C 4.1 585 731 ~ * Cadmus 9000 68010-10Mhz UNIX cc 714 735 * AT&T 6300 8086-8Mhz Venix/86 S PC/AT 80286-6Mhz PCDOS 3.0 MS 3.0(small) 1063 1086 * VAX 11/750 w/FPA VMS VAX-11 C 2.0 958 1091 * Stride 68000-10Mhz System-V/68 cc 1041 1111 * Plexus P/60 MC68000-12.5Mhz UNIX SYSIII Plexus 1111 1111 * ATT PC7300 68010-10Mhz UNIX 5.0.2 cc 1041 1111 * CCC 3230 - Xelos R01(SVR2) cc 1040 1126 * Stride 68000-12Mhz System-V/68 cc 1063 1136 * IBM PC/AT 80286-6Mhz Venix/286 SVR2 cc 1056 1149 * Plexus P/60 MC68000-12.5Mhz UNIX SYSIII Plexus 1111 1163 T * IBM PC/AT 802VR2 cc 668 743 * Cadmus 9790 68010-10Mhz 1MB SVR0,Cadmus3.7 cc 720 747 * NEC PC9801F 8086-8Mhz PCDOS 2.11 Lattice 2.15 768 - @ * ATT PC6300 8086-8Mhz MSDOS 2.11 CI-C86 2.20M 769 769 * Burroughs XE550 68010-10Mhz Centix 2.10 cc 769 769 CT1 * EAGLE/TURBO 8086-8Mhz Venix/86 SVR2 cc 696 779 * ALTOS 586 8086-10Mhz Xenix 3.0b cc 724 793 * DEC 11/73 J-11 micro Ultrix-11 V3.0 cc 735 793 * ATT 3B2/300 WE32000-?Mhz UNIX 5.0.2 cc 735 806 * A86-6Mhz PCDOS 3.0 Datalight 1.10 1190 1190 * ATT PC6300+ 80286-6Mhz MSDOS 3.1 b16cc 2.0 1111 1219 * IBM PC/AT 80286-6Mhz PCDOS 3.1 Wizard 2.1 1136 1219 * Sun2/120 68010-10Mhz Sun 4.2BSD cc 1136 1219 * IBM PC/AT 80286-6Mhz PCDOS 3.0 CI-C86 2.20M 1219 1219 * WICAT PB 68000-8Mhz System V WICAT C 4.1 998 1226 ~ * MASSCOMP 500 68010-10MHz RTU V3.0 cc (V3.2) 1156 1238 * Alliant FX/8 IP (68012-12Mhz) Concentrix cc -ip;exec -i 1170 1243 FX * Cyb DataMate 68010-12.5Mhz Uniplus 5.0 Unisoft cc 1162 1250 * pollo DN320 68010-?Mhz AegisSR9/IX cc 3.12 806 806 * IRIS-2400 68010-10Mhz UNIX System V cc 772 829 * Atari 520ST 68000-8Mhz TOS DigResearch 839 846 * IBM PC/AT 80286-6Mhz PCDOS 3.0 MS 3.0(large) 833 847 LM * WICAT MB 68000-8Mhz System V WICAT C 4.1 675 853 S~ * VAX 11/750 - Ultrix 1.1 4.2BSD cc 781 862 * CCC 7350A 68000-8MHz UniSoft V.2 cc 821 875 * VAX 11/750 - UNIX 4.2bsd cc 862 877 * Fast Mac 68000-7.7Mhz - MegaMax C 2.0 839 904 + * IBM PC/XT 8PDP 11/70 - UNIX 5.2 cc 1162 1250 * IBM PC/AT 80286-6Mhz PCDOS 3.1 Lattice 2.15 1250 1250 * IBM PC/AT 80286-7.5Mhz Venix/86 2.1 cc 1190 1315 *15 * Sun2/120 68010-10Mhz Standalone cc 1219 1315 * Intel 380 80286-8Mhz Xenix R3.0up1 cc 1250 1315 *16 * Sequent Balance 8000 NS32032-10MHz Dynix 2.0 cc 1250 1315 N12 * IBM PC/DSI-32 32032-10Mhz MSDOS 3.1 GreenHills 2.14 1282 1315 C3 * ATT 3B2/400 WE32100-?Mhz UNIX 5.2 cc 1315 1315 * CCC 3250XP - Xelos R01(SVR2) cc 1215 1318 * IBM PC/RT 032 RISC(801?086-9.54Mhz PCDOS 3.1 Microsoft 3.0 833 909 C1 * DEC 11/44 Ultrix-11 V3.0 cc 862 909 * Macintosh 68000-7.8Mhz 2M Mac Rom Mac C 16 bit int 877 909 S * CCC 3210 - Xelos R01(SVR2) cc 849 924 * CCC 3220 - Ed. 7 v2.3 cc 892 925 * IBM PC/AT 80286-6Mhz Xenix 3.0 cc -i 909 925 * AT&T 6300 8086, 8mhz MS-DOS 2.11 Aztec C v3.2d 862 943 * IBM PC/AT 80286-6Mhz Xenix 3.0 cc 892 961 * VAX 11/750 w/FPA Eunice 3.2 cc 914 976 * IBM PC/XT 8086-9.54Mhz PCDOS 3.1 Wizard 2.)?Mhz BSD 4.2 cc 1248 1333 RT * DG MV4000 - AOS/VS 5.00 cc 1333 1333 * IBM PC/AT 80286-8Mhz Venix/86 2.1 cc 1275 1380 *16 * IBM PC/AT 80286-6Mhz MSDOS 3.0 Microsoft 3.0 1250 1388 * ATT PC6300+ 80286-6Mhz MSDOS 3.1 CI-C86 2.20M 1428 1428 * COMPAQ/286 80286-8Mhz Venix/286 SVR2 cc 1326 1443 * IBM PC/AT 80286-7.5Mhz Venix/286 SVR2 cc 1333 1449 *15 * WICAT PB 68000-8Mhz System V WICAT C 4.1 1169 1464 S~ * Tandy II/6000 68000-8Mhz X4386 * NCR Tower32 68020-16.67Mhz SYS 5.0 Rel 2.0 cc 3846 4545 * MC 5600/5700 68020-16.67MHz RTU V3.0 cc (V4.0) 4504 4746 % * Intel 386/20 80386-12.5Mhz PMON debugger Intel C386v0.2 4534 4794 i1 * Intel 386/20 80386-16Mhz PMON debugger Intel C386v0.2 5304 5607 * Gould PN9080 custom ECL UTX-32 1.1C cc 5369 5676 * Gould 1460-342 ECL proc UTX/32 1.1/c cc 5342 5677 G1 * VAX-784 - Mach/4.3 cc 5882 5882 &4 * Intel 386/20 80386-16Mhz PMON debugger Intel C386v0.2 58system consisting of 1-8 CEs (computation * engines) and 1-12 IPs (interactive processors). Note N8 applies. * RT This is one of the RT's that CMU has been using for awhile. I'm * not sure that this is identical to the machine that IBM is selling * to the public. * i1 Normally, the 386/20 starter kit has a 16k direct mapped cache * which inserts 2 or 3 wait states on a write thru. These results * were obtained by disabling the write-thru, or essentially turning * the cache into 0 wait 01 6133 i1 * VAX 8600 - UNIX 4.3bsd cc 7024 7088 * VAX 8600 - VMS VAX-11 C 2.0 7142 7142 * Alliant FX/8 CE Concentrix cc -ce;exec -c 6952 7655 FX * CCI POWER 6/32 COS(SV+4.2) cc 7500 7800 * CCI POWER 6/32 POWER 6 UNIX/V cc 8236 8498 * CCI POWER 6/32 4.2 Rel. 1.2b cc 8963 9544 * Sperry (CCI Power 6) 4.2BSD cc 9345 10000 * CRAY-X-MP/12 105Mhz COS 1.14 Cray C 10204 10204 * IBM-3083 - UTS 5.0 Rel 1 cc 16666 12500 * CRAY-1A 80Mhz CTSS Cray C 2.0 12100 state memory. * Nnn This machine has multiple processors, allowing "nn" copies of the * benchmark to run in the same time as 1 copy. * &nn This machine has "nn" processors, and the benchmark results were * obtained by having all "nn" processors working on 1 copy of dhrystone. * (Note, this is different than Nnn. Salesmen like this measure). * ? I don't trust results marked with '?'. These were sent to me with * either incomplete info, or with times that just don't make sense. * ??15 1724 * NEC PC-98XA 80286-8Mhz PCDOS 3.1 Lattice 2.15 1724 1724 @ * HP9000-500 B series CPU HP-UX 4.02 cc 1724 - * Ridge 32C V1 - ROS 3.3 Ridge C (older) 1776 - * IBM PC/STD 80286-8Mhz MSDOS 3.0 Microsoft 3.0 1724 1785 C2 * WICAT MB 68000-12.5Mhz System V WICAT C 4.1 1450 1814 S~ * WICAT PB 68000-12.5Mhz System V WICAT C 4.1 1530 1898 ~ * DEC-2065 KL10-Model B TOPS-20 6.1FT5 Port. C Comp. 1937 1946 * Gould PN6005 - UTX 1.1(4.2BSD) cc 1675 1964 * DEC2060 KL-10 TOPS-20 cc 2000 2000 NM * I13888 * IBM-3083 - VM/CMS HPO 3.4 Waterloo C 1.2 13889 13889 * Amdahl 470 V/8 UTS/V 5.2 cc v1.23 15560 15560 * CRAY-X-MP/48 105Mhz CTSS Cray C 2.0 15625 17857 * Amdahl 580 - UTS 5.0 Rel 1.2 cc v1.5 23076 23076 * Amdahl 5860 UTS/V 5.2 cc v1.23 28970 28970 * * NOTE * * Crystal changed from 'stock' to listed value. * + This Macintosh was upgraded from 128K to 512K in such a way that * the new 384K of memory is not slowed down by vintel 310AP 80286-8Mhz Xenix 3.0 cc 1893 2009 * VAX 11/785 - UNIX 5.2 cc 2083 2083 * VAX 11/785 - VMS VAX-11 C 2.0 2083 2083 * VAX 11/785 - UNIX SVR2 cc 2123 2083 * VAX 11/785 - ULTRIX-32 1.1 cc 2083 2091 * VAX 11/785 - UNIX 4.3bsd cc 2135 2136 * WICAT PB 68000-12.5Mhz System V WICAT C 4.1 1780 2233 S~ * Pyramid 90x - OSx 2.3 cc 2272 2272 * Pyramid 90x FPA,cache,4Mb OSx 2.5 cc no -O 2777 2777 * Pyramid 90x w/cache OSx 2.5 cc w/-O 3333 3333 * IBM-4341-II - VM/deo generator accesses. * % Single processor; MC == MASSCOMP * NM A version 7 C compiler written at New Mexico Tech. * @ vanilla Lattice compiler used with MicroPro standard library * S Shorts used instead of ints * T with Chris Torek's patches (whatever they are). * ~ For WICAT Systems: MB=MultiBus, PB=Proprietary Bus * LM Large Memory Model. (Otherwise, all 80x8x results are small model) * MM Medium Memory Model. (Otherwise, all 80x8x results are small model) * C1 USP3 Waterloo C 1.2 3333 3333 * IRIS-2400T 68020-16.67Mhz UNIX System V cc 3105 3401 * Celerity C-1200 ? UNIX 4.2BSD cc 3485 3468 * SUN 3/75 68020-16.67Mhz SUN 4.2 V3 cc 3333 3571 * IBM-4341 Model 12 UTS 5.0 ? 3685 3685 * SUN-3/160 68020-16.67Mhz Sun 4.2 V3.0A cc 3381 3764 * Sun 3/180 68020-16.67Mhz Sun 4.2 cc 3333 3846 * IBM-4341 Model 12 UTS 5.0 ? 3910 3910 MN * MC 5400 68020-16.67MHz RTU V3.0 cc (V4.0) 3952 4054 * Intel 386/20 80386-12.5Mhz PMON debugger Intel C386v0.2 4149 nivation PC TURBO Co-processor; 9.54Mhz 8086, 640K RAM * C2 Seattle Telecom STD-286 board * C3 Definicon DSI-32 coprocessor * C? Unknown co-processor board? * CT1 Convergent Technologies MegaFrame, 1 processor. * MN Using Mike Newtons 'optimizer' (see net.sources). * G1 This Gould machine has 2 processors and was able to run 2 dhrystone * Benchmarks in parallel with no slowdown. * FH FHC == Frank Hogg Labs (Hazelwood Uniquad 2 in an FHL box). * FX The Alliant FX/8 is a lines */ /*#define LOOPS 5000 /* Use this for slow or 16 bit machines */ #define LOOPS 50000 /* Use this for slow or 16 bit machines */ /*#define LOOPS 500000 /* Use this for faster machines */ /* Compiler dependent options */ #undef NOENUM /* Define if compiler has no enum's */ #undef NOSTRUCTASSIGN /* Define if compiler can't assign structures */ /* define only one of the next three defines */ /*#define GETRUSAGE /* Use getrusage(2) time function */ /*#define TIMES /* Use times(2) time function = time( (long *) 0) - starttime; /* Computes o'head of loop */ #endif #ifdef TIMES time_t starttime; time_t benchtime; time_t nulltime; struct tms tms; times(&tms); starttime = tms.tms_utime; for (i = 0; i < LOOPS; ++i); times(&tms); nulltime = tms.tms_utime - starttime; /* Computes overhead of looping */ #endif #ifdef GETRUSAGE struct rusage starttime; struct rusage endtime; struct timeval nulltime; getrusage(RUSAGE_SELF, &starttime); for (i = 0; i < LOOPS; ++i); getrusage(RUSAGE_SE */ #define TIME /* Use time(2) time function */ /* define the granularity of your times(2) function (when used) */ /*#define HZ 60 /* times(2) returns 1/60 second (most) */ /*#define HZ 100 /* times(2) returns 1/100 second (WECo) */ /* for compatibility with goofed up version */ /*#define GOOF /* Define if you want the goofed up version */ #ifdef GOOF char Version[] = "1.0"; #else char Version[] = "1.1"; #endif #ifdef NOSTRUCTASSIGN #define structassign(d, s) memcpy(&(d), &(s), sizeof(d)) #else #LF, &endtime); nulltime.tv_sec = endtime.ru_utime.tv_sec - starttime.ru_utime.tv_sec; nulltime.tv_usec = endtime.ru_utime.tv_usec - starttime.ru_utime.tv_usec; #endif PtrGlbNext = (RecordPtr) malloc(sizeof(RecordType)); PtrGlb = (RecordPtr) malloc(sizeof(RecordType)); PtrGlb->PtrComp = PtrGlbNext; PtrGlb->Discr = Ident1; PtrGlb->EnumComp = Ident3; PtrGlb->IntComp = 40; strcpy(PtrGlb->StringComp, "DHRYSTONE PROGRAM, SOME STRING"); #ifndef GOOF strcpy(String1Loc, "DHRYSTONE PROGRAM, 1'ST STRING")define structassign(d, s) d = s #endif #ifdef NOENUM #define Ident1 1 #define Ident2 2 #define Ident3 3 #define Ident4 4 #define Ident5 5 typedef int Enumeration; #else typedef enum {Ident1, Ident2, Ident3, Ident4, Ident5} Enumeration; #endif typedef int OneToThirty; typedef int OneToFifty; typedef char CapitalLetter; typedef char String30[31]; typedef int Array1Dim[51]; typedef int Array2Dim[51][51]; struct Record { struct Record *PtrComp; Enumeration Discr; Enumeration EnumComp; OneToFifty IntC; /*GOOF*/ #endif Array2Glob[8][7] = 10; /* Was missing in published program */ /***************** -- Start Timer -- *****************/ #ifdef TIME starttime = time( (long *) 0); #endif #ifdef TIMES times(&tms); starttime = tms.tms_utime; #endif #ifdef GETRUSAGE getrusage (RUSAGE_SELF, &starttime); #endif for (i = 0; i < LOOPS; ++i) { Proc5(); Proc4(); IntLoc1 = 2; IntLoc2 = 3; strcpy(String2Loc, "DHRYSTONE PROGRAM, 2'ND STRING"); EnumLoc = Ident2; BoolGlob = ! Func2(String1Loc, String means I think the performance is too poor, ?! means too good. * If anybody can confirm these figures, please respond. * * ABBREVIATIONS * CCC Concurrent Computer Corp. (was Perkin-Elmer) * MC Masscomp * *--------------------------------RESULTS END---------------------------------- * * The following program contains statements of a high-level programming * language (C) in a distribution considered representative: * * assignments 53% * control statements 32% * procedure, function callomp; String30 StringComp; }; typedef struct Record RecordType; typedef RecordType * RecordPtr; typedef int boolean; #define NULL 0 #define TRUE 1 #define FALSE 0 #ifndef REG #define REG #endif extern Enumeration Func1(); extern boolean Func2(); #ifdef TIMES #include #include #include #endif #ifdef GETRUSAGE #include #include #endif main() { Proc0(); exit(0); } /* * Package 1 */ int IntGlob; boolean BoolGlob; char Cs 15% * * 100 statements are dynamically executed. The program is balanced with * respect to the three aspects: * - statement type * - operand type (for simple data types) * - operand access * operand global, local, parameter, or constant. * * The combination of these three aspects is balanced only approximately. * * The program does not compute anything meaningfull, but it is * syntactically and semantically correct. * */ /* Accuracy of timings and human fatigue controlled by next two har1Glob; char Char2Glob; Array1Dim Array1Glob; Array2Dim Array2Glob; RecordPtr PtrGlb; RecordPtr PtrGlbNext; Proc0() { OneToFifty IntLoc1; REG OneToFifty IntLoc2; OneToFifty IntLoc3; REG char CharLoc; REG char CharIndex; Enumeration EnumLoc; String30 String1Loc; String30 String2Loc; extern char *malloc(); register unsigned int i; #ifdef TIME long time(); long starttime; long benchtime; long nulltime; starttime = time( (long *) 0); for (i = 0; i < LOOPS; ++i); nulltime***/ #ifdef TIME benchtime = time( (long *) 0) - starttime - nulltime; printf("Dhrystone(%s) time for %ld passes = %ld\n", Version, (long) LOOPS, benchtime); printf("This machine benchmarks at %ld dhrystones/second\n", ((long) LOOPS) / benchtime); #endif #ifdef TIMES times(&tms); benchtime = tms.tms_utime - starttime - nulltime; printf("Dhrystone(%s) time for %ld passes = %ld\n", Version, (long) LOOPS, benchtime/HZ); printf("This machine benchmarks at %ld dhrystones/second\n", ((long) LOEnumParOut = Ident3; } } Proc7(IntParI1, IntParI2, IntParOut) OneToFifty IntParI1; OneToFifty IntParI2; OneToFifty *IntParOut; { REG OneToFifty IntLoc; IntLoc = IntParI1 + 2; *IntParOut = IntParI2 + IntLoc; } Proc8(Array1Par, Array2Par, IntParI1, IntParI2) Array1Dim Array1Par; Array2Dim Array2Par; OneToFifty IntParI1; OneToFifty IntParI2; { REG OneToFifty IntLoc; REG OneToFifty IntIndex; IntLoc = IntParI1 + 5; Array1Par[IntLoc] = IntParI2; Array1Par[IntLoc+1] = Array1Par[IntLoc]; Array1Par[IntOPS) * HZ / benchtime); #endif #ifdef GETRUSAGE getrusage(RUSAGE_SELF, &endtime); { double t = (double)(endtime.ru_utime.tv_sec - starttime.ru_utime.tv_sec - nulltime.tv_sec) + (double)(endtime.ru_utime.tv_usec - starttime.ru_utime.tv_usec - nulltime.tv_usec) * 1e-6; printf("Dhrystone(%s) time for %ld passes = %.1f\n", Version, (long)LOOPS, t); printf("This machine benchmarks at %.0f dhrystones/second\n", (double)LOOPS / t); } #endif } Proc1(PtrLoc+30] = IntLoc; for (IntIndex = IntLoc; IntIndex <= (IntLoc+1); ++IntIndex) Array2Par[IntLoc][IntIndex] = IntLoc; ++Array2Par[IntLoc][IntLoc-1]; Array2Par[IntLoc+20][IntLoc] = Array1Par[IntLoc]; IntGlob = 5; } Enumeration Func1(CharPar1, CharPar2) CapitalLetter CharPar1; CapitalLetter CharPar2; { REG CapitalLetter CharLoc1; REG CapitalLetter CharLoc2; CharLoc1 = CharPar1; CharLoc2 = CharLoc1; if (CharLoc2 != CharPar2) return (Ident1); else return (Ident2); } boolean Func2(StrParI1, StrPParIn) REG RecordPtr PtrParIn; { #define NextRecord (*(PtrParIn->PtrComp)) structassign(NextRecord, *PtrGlb); PtrParIn->IntComp = 5; NextRecord.IntComp = PtrParIn->IntComp; NextRecord.PtrComp = PtrParIn->PtrComp; Proc3(NextRecord.PtrComp); if (NextRecord.Discr == Ident1) { NextRecord.IntComp = 6; Proc6(PtrParIn->EnumComp, &NextRecord.EnumComp); NextRecord.PtrComp = PtrGlb->PtrComp; Proc7(NextRecord.IntComp, 10, &NextRecord.IntComp); } else structassign(*PtrParIn, NextRecord); #undef NexarI2) String30 StrParI1; String30 StrParI2; { REG OneToThirty IntLoc; REG CapitalLetter CharLoc; IntLoc = 1; while (IntLoc <= 1) if (Func1(StrParI1[IntLoc], StrParI2[IntLoc+1]) == Ident1) { CharLoc = 'A'; ++IntLoc; } if (CharLoc >= 'W' && CharLoc <= 'Z') IntLoc = 7; if (CharLoc == 'X') return(TRUE); else { if (strcmp(StrParI1, StrParI2) > 0) { IntLoc += 7; return (TRUE); } else return (FALSE); } } boolean Func3(EnumParIn) REG Enumeration EnumParIn; { REG EnumeratRecord } Proc2(IntParIO) OneToFifty *IntParIO; { REG OneToFifty IntLoc; REG Enumeration EnumLoc; IntLoc = *IntParIO + 10; for(;;) { if (Char1Glob == 'A') { --IntLoc; *IntParIO = IntLoc - IntGlob; EnumLoc = Ident1; } if (EnumLoc == Ident1) break; } } Proc3(PtrParOut) RecordPtr *PtrParOut; { if (PtrGlb != NULL) *PtrParOut = PtrGlb->PtrComp; else IntGlob = 100; Proc7(10, IntGlob, &PtrGlb->IntComp); } Proc4() { REG boolean BoolLoc; BoolLoc = Char1Glob == 'A'; BoolLoc tion EnumLoc; EnumLoc = EnumParIn; if (EnumLoc == Ident3) return (TRUE); return (FALSE); } #ifdef NOSTRUCTASSIGN memcpy(d, s, l) register char *d; register char *s; register int l; { while (l--) *d++ = *s++; } #endif /* ---------- */ arLoc >= 'W' && CharLoc <= 'Z') IntLoc = 7; if (CharLoc == 'X') return(TRUE); else { if (strcmp(StrParI1, StrParI2) > 0) { IntLoc += 7; return (TRUE); } else return (FALSE); } } boolean Func3(EnumParIn) REG Enumeration EnumParIn; { REG Enumera2Loc); while (IntLoc1 < IntLoc2) { IntLoc3 = 5 * IntLoc1 - IntLoc2; Proc7(IntLoc1, IntLoc2, &IntLoc3); ++IntLoc1; } Proc8(Array1Glob, Array2Glob, IntLoc1, IntLoc3); Proc1(PtrGlb); for (CharIndex = 'A'; CharIndex <= Char2Glob; ++CharIndex) if (EnumLoc == Func1(CharIndex, 'C')) Proc6(Ident1, &EnumLoc); IntLoc3 = IntLoc2 * IntLoc1; IntLoc2 = IntLoc3 / IntLoc1; IntLoc2 = 7 * (IntLoc3 - IntLoc2) - IntLoc1; Proc2(&IntLoc1); } /***************** -- Stop Timer -- **************|= BoolGlob; Char2Glob = 'B'; } Proc5() { Char1Glob = 'A'; BoolGlob = FALSE; } extern boolean Func3(); Proc6(EnumParIn, EnumParOut) REG Enumeration EnumParIn; REG Enumeration *EnumParOut; { *EnumParOut = EnumParIn; if (! Func3(EnumParIn) ) *EnumParOut = Ident4; switch (EnumParIn) { case Ident1: *EnumParOut = Ident1; break; case Ident2: if (IntGlob > 100) *EnumParOut = Ident1; else *EnumParOut = Ident4; break; case Ident3: *EnumParOut = Ident2; break; case Ident4: break; case Ident5: *./usr/src/ 40775 2 2 0 5555220157 5535 rc ] then i=$B.rc elif [ -f $B.c -o -f $LSRC/cmd/$B.c ] then i=$B.c elif [ -f $B.y -o -f $LSRC/cmd/$B.y ] then i=$B.y elif [ -f $B.l -o -f $LSRC/cmd/$B.l ] then i=$B.l elif [ -f $B.s -o -f $LSRC/cmd/$B.s ] then i=$B.s elif [ -f $B.sh -o -f $LSRC/cmd/$B.sh ] then i=$B.sh elif [ -f $B.ex -o -f $LSRC/cmd/$B.ex ] then i=$B.ex elif [ -f $B.o -o -f $LSRC/cmd/$B.o ] then rm -f $B.o fi fi if [ $source = $SRC -a -f ${LSRC}/cmd/$i ] then source=$LSRC cd ${source}./usr/src/:mkcmd 775 2 2 13744 3172123647 6721 /cmd fi case $i in *.mk) command="sed -e 's/$B //'" if [ -r ${LDFILE} ] then ldflags=`eval grep "'^$B '" $LDFILE` fi ldflags=`echo $ldflags | eval $command` if [ x$sflag = x-s ] then command="sed -e 's/-i//'" ldflags=`echo $ldflags | eval $command` else command="sed -e 's/-f//'" ldflags=`echo $ldflags | eval $command` if [ `expr x$ldflags : '.*-i'` != 0 ] then command="sed -e 's/-n//'" ldflags=`echo $ldflags | eval $command` fi fi COMP="make -b -f $B.# @(#):mkcmd 1.4 CLEAN="rm -f *.o" asource=$source places=${places-/etc/places} if test ! -r /bin/vax -o ! -r /bin/pdp11 -o ! -r /bin/u3b -o ! -r /bin/u3b5 then echo 'Link /bin/vax to /bin/true or /bin/false,' echo 'and /bin/pdp11 to /bin/true or /bin/false.' echo 'and /bin/u3b to /bin/true or /bin/false.' echo 'and /bin/u3b5 to /bin/true or /bin/false.' echo 'Then try again' exit 1 fi if [ -r $places ] then . $places else SRC=${SRC-/usr/src} LSRC=${LSRC-/usr/lsrc} BIN=${BIN-/bin} UBINmk $iflag $fflag install" if [ "x$ldflags" != x ] then COMP="$COMP LDFLAGS='$ldflags'" fi COMP="$COMP && make -b -f $B.mk $iflag $yaccrm clobber" echo $COMP eval $COMP ;; *.rc) sh -x ${i} ;; *.y) if [ x$sflag != x-s -o x$yflag = x-y ] then echo yacc $i if yacc $i then echo mv y.tab.c ${B}.c mv y.tab.c ${B}.c lib=-ly places=$places LDFILE=$LDFILE ${SRC}/:mkcmd $sflag $yflag ${B}.c else echo "yacc failed" fi if [ x$sflag != x-s ] then rm -f ${B}.c else =${UBIN-/usr/bin} LBIN=${LBIN-/usr/lbin} fi LDFILE=${LDFILE-${SRC}/ldflags} cd ${SRC}/cmd arguments=$* pflag= ldflags= for A in $* do case $A in -y) yflag=-y ;; -f) fflag=FFLAG=-f ;; -s) sflag=-s yaccrm=YACCRM=: iflag=IFLAG= ;; -p) pflag=-p command="sed -e 's/-p //'" arguments=`echo $arguments | eval $command` command= ;; esac done for A in $arguments do( if [ x$A = x-s -o x$A = x-y -o x$A = x-f ] then continue fi if [ $asource ] then source=$asource elif [ -f ${LSRC} mv ${B}.c ${B}.x fi else mv ${B}.x ${B}.c lib=-ly places=$places LDFILE=$LDFILE ${SRC}/:mkcmd $sflag $yflag ${B}.c mv ${B}.c ${B}.x fi ;; *.l) if [ x$sflag != x-s -o x$yflag = x-y ] then echo lex $i if lex $i then echo mv lex.yy.c ${B}.c mv lex.yy.c ${B}.c lib=-ll places=$places LDFILE=$LDFILE ${SRC}/:mkcmd $sflag $yflag ${B}.c else echo "lex failed" fi if [ x$sflag != x-s ] then rm -f ${B}.c else mv ${B}.c ${B}.x fi else mv ${B}.x ${/cmd/$A -o -d ${LSRC}/cmd/$A ] then source=$LSRC else source=$SRC fi cd ${source}/cmd NAME= TEST=./ B=`echo $A ^ sed -e 's/.*\///' ` case $B in *.c | *.o | *.s) _BASENAME_=`basename $B ".[cso]"` if [ -f ${_BASENAME_}.mk -o -f ${_BASENAME_}.rc ] then continue fi ;; esac echo ======== $B i=$B if [ -d $B ] then echo "******** directory $B" else B=`echo $i | sed -e 's/\(.*\)\..*/\1/'` if [ -f $B.mk -o -f $LSRC/cmd/$B.mk ] then i=$B.mk elif [ -f $B.rc -o -f $LSRC/cmd/$B.B}.c lib=-ll places=$places LDFILE=$LDFILE ${SRC}/:mkcmd $sflag $yflag ${B}.c mv ${B}.c ${B}.x fi ;; *.x) : ;; *.c) command="sed -e 's/$B //'" if [ -r ${LDFILE} ] then ldflags=`eval grep "'^$B '" $LDFILE` fi ldflags=`echo $ldflags | eval $command` if [ x$fflag = x ] then command="sed -e 's/-f//'" ldflags=`echo $ldflags | eval $command` fi if [ x$sflag = x-s ] then command="sed -e 's/-i//'" ldflags=`echo $ldflags | eval $command` else if [ `expr "x$ldfla./usr/src/cmd/ 40775 2 2 0 5555217613 6303 gs" : '.*-i'` != 0 ] then command="sed -e 's/-n//'" ldflags=`echo $ldflags | eval $command` fi fi COMP="cc -O $ldflags -s $i -o $TEST$B $lib" echo $COMP if eval $COMP then NAME=$B else echo $B: cc failed rm -f $B fi lib= ;; *.s) echo "as -o $TEST$B.o /usr/include/sys.s $i && ld -s -o $TEST$B $TEST$B.o" if as -o $TEST$B.o /usr/include/sys.s $i && ld -s -o $TEST$B $TEST$B.o then NAME=$B else echo $B: as failed fi rm -f $TEST$B.o ;; *.ex) echo "$i is m./usr/src/cmd/ar/ 40775 2 2 0 5555210244 6676 erely a sample." echo "You should use it as a prototype for your own current situation" continue ;; *.sh) echo cp $i $B if cp $i $B then NAME=$B else echo $B: cp failed fi ;; *.o) rm -f $i continue ;; *) NAME= TEST= command="sed -e 's/$i //'" if [ -r ${LDFILE} ] then ldflags=`eval grep "'^$i '" $LDFILE` fi; ldflags=`echo $ldflags | eval $command` if [ x$sflag = x-s ] then command="sed -e 's/-i//'" ldflags=`echo $ldflags | eval $command` else command="sed -e './usr/src/cmd/ar/pdp11/ 40775 2 2 0 5555210244 7623 s/-f//'" ldflags=`echo $ldflags | eval $command` if [ `expr x$ldflags : '.*-i'` != 0 ] then command="sed -e 's/-n//'" ldflags=`echo $ldflags | eval $command` fi fi if [ -d $i ] then echo cd $i cd $i if [ -f ${i}.mk ] then COMP="make -b -f ${i}.mk ARGS=\"${ARGS}\" $iflag $fflag install" if [ "x$ldflags" != x ] then COMP="$COMP LDFLAGS='$ldflags'" fi echo $COMP if eval $COMP then make -b -f ${i}.mk $iflag $fflag $yaccrm clobber else echo MAKE ERROR fi elif [ -f ${i}.rc ] then sh -x ${i}.rc else echo XXXXXXXX Do Not Know How to MAKE $B fi $CLEAN else echo "XXXXXXXX Cannot make $B" fi esac : Install binary just made in appropriate bin case $NAME in "") : ;; *) cd $TEST if [ $source = $LSRC ] then echo /etc/install -n ${LBIN} $NAME /etc/install -n ${LBIN} $NAME else echo /etc/install -n ${UBIN} $NAME /etc/install -n ${UBIN} $NAME fi rm -f $NAME ;; esac );done ccrm clobber else echo M