IMD 1.18: 21/04/2022 20:16:29   ¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶müÿ¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m  KERMIT_INFO 644 0 3 16253 3511571445 5575 mmand: 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  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  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 in  officially" 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 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 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 sto 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 ackcdeb.h 644 0 3 4755 3507351140 5405 s 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 /* 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 anfrom 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 "y 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 --== '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();  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 debl/* 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 tcharacter 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; /* rckcfn2.c 644 0 3 32436 3507351140 5350 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': /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); s* 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 bytepack('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() { /* Ters 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 coulminal 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 */ he 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)if (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 (j 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) = 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] != x && (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",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"",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", 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  ckcfns.c 644 0 3 64043 3510607670 5456 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); 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 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. */ } } ar, 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();7 = 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;  /* 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 ihat. */ 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,{ 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 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 sue > 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, tre 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 t  p,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. */  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 ", 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) {"",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 */  */ 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 = 'imeout, */ 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*/ 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; xrement 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 = (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 */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 (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 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); /*memory 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 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, 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; { intname2",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 = hcflg 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); /*  = 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'; /*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 lmd(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 failength */ #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 ed",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 /* 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 ckcker.h 644 0 3 7101 3507351141 5421 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  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  /* 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, UCLAllify */ #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 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 Supportedckcmai.c 644 0 3 20317 3510607670 5432 :\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/ 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 ini */ 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 */tial 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= 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 ; /* 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 Centeit(); 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 r 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 to8: { 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 {  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 declaSERVE; } } 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(, 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; /* Sackcpro.c 644 0 3 34106 3507351142 5461 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: { tin  n(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, 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. */37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 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,  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(); 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 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, 3BEGIN 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, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 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, 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, 37  7, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 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, 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,Protocol 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", 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, 2ttname,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 5, 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, *SPACd,"")) 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; } } 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 = srvcmde 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(srvcm  lse { 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 pckucmd.c 644 0 3 63622 3507351143 5454 acket, issue message */ x = quiet; quiet = 1; /* Close files silently */ clsif(); clsof(); quiet = x; RESUME; } . { nack(); } /* Anything else, send NAK */ %% /* P R O T O -- Protocol 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 (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 dneric>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; } } 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 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 Pon, 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  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 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 =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, onefaults 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 that  x); /* 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 nith 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 ot 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-- = '\the 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. */0'; 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); /*  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 Complete 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 = zxpandly 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); } e 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 == 0lse { 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 -- ) *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: /* Q 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) =uestion 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 > 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 */ 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; } } /*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 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 taest(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 || /* 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 =  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; setbp; /* 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 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) ; bpmdbuf,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_getcharchar *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. Permi() #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 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 *'\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/ #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 er; { 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 */ strckucmd.h 644 0 3 3260 3507351143 5431 ckucon.c 644 0 3 16265 3510607670 5474   [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 */ } d %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(" } } } } /* 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); 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 == /* 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) { /* escape) { /* Look for escape char */ c = coninc(0) & 0177; /* Got esc, get its arg */ doesc(c); /* And process it */ } else { /* Ordinary character */ if (ttoc(dopar(c)) > -1) { if (duplex) { /* Half duplex? */ conoc(c); /* Yes, also echo it. */ if (seslog) /* And maybe log it. */ if (zchout(ZSFILE,c) < 0) seslog = 0; } } else { perror("\r\nCan't send character"); active = 0; } } } } /* Come here oSend 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); ifrors */ 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 sanckudia.c 644 0 3 55016 3510612154 5440 ity'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 chchar *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 isaracters, 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 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 "ckucmd  EK = /* 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 */ /* ause_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.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#", /* diaof 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 forl_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 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 */ "%", /* p  on 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 (1cters * 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). * * 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 ordeurn( 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 moderompt */ "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  "", /* 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 chara  f (*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 line 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 ! */ /* 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; } = 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 i 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); } nto 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 */ ifs */ 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': /* numeric  en 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 == ' = 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; i5') 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 presumablyf (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 fro 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 presumablym 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 (didckufio.c 644 0 3 57710 3507351144 5470  (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. zclosr *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 followf() -- 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... */ #ifndes 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 */ charf 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 *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 ret  F, 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(e 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 permissurn(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; {e; { 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 */  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 } 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; /* Isolat!  lower(*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 dir; /* 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 retuectory */ 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) { /* chirned 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,*mtchption 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*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 remleny[]; 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 ; /* 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 directory 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; otherpath * 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'wise, 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. * * Inr++); 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,*resarr#  ruct 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 == '?') { patt *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, fern++; /* '?', 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 == '?') { pattorget 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 } /* * ackuker.mak 644 0 3 15071 3507351145 6015 ddresult: * 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 = -1# 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 otherput: 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 ws 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 -- ihat? 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.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 DIRc 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 vECT. 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; i #include #include #include #include "ckcker.h" extern int local, speed,  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.02flow, 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 jmpckuscr.c 644 0 3 20525 3510607670 5476 _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; /* 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 */ ignal(SIGALRM,SIG_IGN); tlog(F110,"received sequence: ",trace,0l); tlog(F101,"returning with got-it code","",(long) got_it); return; } /* Output A Sequence starting at pointer s, return 0 if okay, 1 if failed to read (modem hangup or whatever) */ static int outSeq() { char *sb; int l; int delay; int retCode = 0; while(1) { delay = sequenc(); l = strlen(seq_buf); tlog(F111,"sending sequence ",seq_buf,(long) l); signal(SIGALRM,scrtime); if (!setjmp(alrmRng)) 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: case 's': seq_buf[i++] = ' '; break; case 'x': seq_buf[i++] = '\021'; break; case 'c': no_cr = 1; break; case 'd': { /* send what we have and then */ seq_buf[i] = '\0'; /* expect to send rest after */ no_cr = 1; /* sender delays a little */ s++; return(1); } case 'w': { /* wait count */ EXP_ALRM = 15; /* default to 15 sec */ if ( isdigit( *(s+1) ) ) { EXP_ALRM = (*(++s)) & 15; if ( isdigit( *(s+1) ) ) { EXP_ALRM = EXP_ALRM*10 + ( (* { alarm(SND_ALRM); if (!strcmp(seq_buf,"EOT")) ttoc(dopar('\004')); else if (!strcmp(seq_buf,"BREAK")) ttsndb(); else { if (l > 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); ret /* 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  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 unixretained. */ /* 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 Charleses) 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 mode 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 . 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 ( 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 ckutio.c 644 0 3 122074 3510607670 5524 - 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 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 rc 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, teading 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 ittvt, /* 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 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 foregconesc = 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 notuntimed). 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(ttys 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 Uyfd,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 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,-- 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); " 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 = crING) 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; /* setexcept 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);*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 /* 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.s 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 == DIAL+  IUCLC|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!!! */ } s 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 */  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:conesc = 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(SIGHUP 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() { if 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 signal,  p 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: iniGKILL); 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, TItrawq(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 gainOCSETP, &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(inted. */ #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_)); 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) 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 BREAKeol) 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  */ 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); /* Simulatewent 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 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 arm(0); /* Success, turn off timer, */ signal(SIGALRM,SIG_DFL); /* and associated interrupt. */ return(x); /* Return the count. */ } /* T T I N C -- Read a character from the communication line */ ttinc(timo) int timo; { int n; CHAR ch; if (ttyfd < 0) return(-1); /* Not open. */ if (timo <= 0) { /* Untimed. */ #ifndef UXIII while ( !(n = read(ttyfd,&ch,1)) ) ; /* Wait for a character. */ return( (n > 0) ? (ch & 0377) : n ); #else /* comm line failure returns & 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 (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)z); /* 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); ); #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 ** *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* 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 (cgmf = 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 /*-\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 dialterminal */ 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 characteckuus2.c 644 0 3 35373 3510607670 5427 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 } 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 */ #kuser 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) endif 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 -0  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\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 n", " 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, sesystems).\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 progrog.\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."; staa 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 1   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.")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 ); 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,"Paramcontrol 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 leter","")) == -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(hmsine' 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 diaess 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(h2  ng 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 (ASckuus3.c 644 0 3 51142 3507351150 5413 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."); retu/* 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 furn(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 servernctions */ /* 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, 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:  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 */ pktfiling 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: 3  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: , 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  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*/ "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. */ /* Rase 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: /* Handeturns: -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-b4  ("%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 ar('\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(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: /("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) { tim* 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... */ printef = 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; putch5   */ 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); con 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"); screenoll(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 = (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 */ ifx); 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:  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; } } /* I6   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 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; defaultc 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: 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; default",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(ZDFckuusr.c 644 0 3 103111 3510607670 5531  ((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; 7  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, te 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 commurn, 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, and 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 cmerrp[]; 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[CMDBLgeneric 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 whic+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 MAXTAchar *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() function8  KE 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 ((xa || (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 dirgc == 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; csplay 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 */ whilease '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("inva (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': /* de9  XXSET, 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-ile[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 consolbug */ 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){ /* 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", XXCL / 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,%sO, 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 ((tf:  ab,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."); fclo0: 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',"","",""); rese(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) iturn(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) rete 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 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) 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("Tex 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,10t 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)0,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 = -1; } 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 justurn(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 tiate 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();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 ret 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 comurn(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 -- Shmand */ 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 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 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); inary) 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"); } 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);  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:ckuusr.h 644 0 3 10371 3507351151 5517  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 associ>  AND 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 2char *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 <ated 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 1define 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 simulati6 /* 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 1on */ #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 XYHckwart.c 644 0 3 30411 3507351154 5471 ?  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 ntinue; /* 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. * x,rdrules(); lines = 1; /* line counter */ nstates = 0; /* no states */ nacts = 0; /* no actions yet */ fprintf(outfp,"\n%c* WARNING -- This C source program generated by ",'/'); fprintf(outfp,"Wart preprocessor. */\n"); fprintf(outfp,"%c* Do not edit this file; edit the Wart-format ",'/'); fprintf(outfp,"source file instead, */\n"); fprintf(outfp,"%c* and then run it through Wart to produce a new ",'/'); fprintf(outfp,"C source file. */\n\n"); fprintf(outfp,"%c* Wart Versio*/ Trans rdrules(fp,out) FILE *fp,*out; { Trans head,cur,prev; int curtok,i; head = cur = NULL; while ((curtok = gettoken(fp)) != SEP) switch(curtok) { case LBRACK: if (cur == NULL) cur = newtrans(); else fatal("duplicate state list"); statelist(fp,cur);/* set states */ continue; /* prepare to read char */ case WORD: if (strlen(tokval) != 1) fatal("multiple chars in state"); if (cur == NULL) { cur = newtrans(); cur->anyst = 1; } state names...> * %% * | 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 alltates,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) Trfp) 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; { intans hd; int state,chr; { while (hd != NULL) { if (hd->anyst || teststate(state,hd)) if (hd->inchr == '.' || hd->inchr == chr) return(hd->actno); hd = hd->nxt; } return(-1); } /* * empty the table... * */ emptytbl() { int i; for (i=0; i': return(RBRACK); case ',': return(COMMA); case '/': if ((c = getc(fp)) == '*') { rdcmnt(fp); /(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'* 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)) {  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(outA  * 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; } systems).\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 progr /* * 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; } ess 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 information 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")); #endif 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; } /B   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.")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 ); 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,"Paramcontrol 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 leter","")) == -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(hmsine' 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 diag("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 mesling 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 strisage */ 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 (ASC  ckuus3.c 644 0 3 51142 3507351150 5413 splay", 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", 0CII 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."); retu/* 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 furn(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 servernctions */ /* 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, 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:  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 */ pktfi 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[] = { "diD  0) 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 lineit 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 (( ",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: 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, 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  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*/ "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. */ /* Rase 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: /* Handeturns: -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-bE  ("%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 ar('\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( */ 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); 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: /* Ty *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: /pe */ 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");("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) { tim* 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... */ printef = 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; putchF   */ 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); con 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"); screenoll(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 = (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 */ if0; } 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 ever ((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"); continuey 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: ; 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 in 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; } } /* IG   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 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; defaultc 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: 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; default",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(ZDFckuusr.c 644 0 3 103111 3510607670 5531 ILE,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 (specichar *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 ckuseal) "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. ThH  s 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 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')e 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 commurn, 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, and 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 cmerrp[]; 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[CMDBLgeneric 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 whic+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 MAXTAh 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; I  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"); 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 */  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 ((xa 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;  || (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 dirgc == 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; csplay 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 */ whilease '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("inva (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': /* deJ  XXSET, 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-ile[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 consolcontrol", 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, "e 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) &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)& 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++) { /* 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", XXCL / 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,%sO, 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 ((tfK  ab,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."); fclo0: 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',"","",""); rese(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) iturn(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) retnt 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;urn(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 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 -- CoLE)); 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 XXD 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 L  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) 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("Tex 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,10t 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)0,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 = -1; } 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 just; 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 t 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) retuo 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 intermedM   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 ttimint); 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 (biate 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();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 ret 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 comurn(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 -- Shmand */ 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 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; casback 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,N   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) { 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); ¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶minary) 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"); } 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);  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: 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; O  ¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m¶m