This file, NCRKER.JAR, is a "join archive". It contains the following files for NCR 9800 Kermit: CKCDEB H IVS / MCS-Kermit header file CKVFN2 C IVS / MCS-Kermit C source module CKVFNS C IVS / MCS-Kermit C source module CKCKER H IVS / MCS-Kermit header file CKVMAI C IVS / MCS-Kermit C source module CKVPRO C IVS / MCS-Kermit C source module CKUSYM H IVS / MCS-Kermit header file CKVCMD C IVS / MCS-Kermit C source module CKUCMD H IVS / MCS-Kermit header file CKVCON C IVS / MCS-Kermit C source module CKVDIA C IVS / MCS-Kermit C source module CKVFI2 C IVS / MCS-Kermit C source module CKVSCR C IVS / MCS-Kermit C source module CKVTIO C IVS / MCS-Kermit C source module CKVUS2 C IVS / MCS-Kermit C source module CKVUS3 C IVS / MCS-Kermit C source module CKVUSR C IVS / MCS-Kermit C source module CKUUSR H IVS / MCS-Kermit header file CKVFIO C IVS / MCS-Kermit C source module CKVMCS C MCS-Kermit C source module MCSONLY MCS system I/F routines CKVBUF C MCS-Kermit C source module Buffering routines for MCS I/F COMPILE INS Compilation instructions KERMISC H IVS / MCS-Kermit header file IVSKPM PRO SCL routine to execute IVS-Kermit MCS H MCS-Kermit header file: used to redefine fgets, fputs, etc. MCS_DEFS H MCS control structures MCSKJ N3 SCL jobfile to execute MCS-Kermit PWD H IVS / MCS-Kermit header file* SGTTY H IVS / MCS-Kermit header file* SIGNAL H IVS / MCS-Kermit header file* TYPES H IVS / MCS-Kermit header file* VKNCRLIO NCR IVS / MCS-Kermit C source module VRX H IVS / MCS-Kermit header file MCSKNDLJ N3 NDL compilation jobfile to specify terminal / queue characterisitics, and produce NDL object. LINKMCS PRO LinkEdit SCL procedure file used to link MCS-Kermit LNK1KSRC N3 LinkEdit jobfile used to link IVS-Kermit * These files do not exist on a VRX/VE system, they are placed in either the compilation catalog node or disk. Each file begins with a line having the filename enclosed in triple angle brackets, for example <<< kerm.doc >>>. All the lines up to the next <<< filename >>> line are the contents of the file. You can break up this "jar" file into its consituent files using a text editor, or with a program like the following one, which is written in the C language. If you call this program "unjoin" and you have a "jar" file called foo.jar, then you would break up the jar file by typing "unjoin < foo.jar". ---(cut here)--------------------------- /* unjoin -- Split a "jar file" up into its original component files. */ /* The jar file is read from standard input. */ /* /* This program can be used on UNIX systems, and with Microsoft C */ /* /* Authors: F. da Cruz, C. Gianone, Columbia University, 1988 */ #include int files = 0; FILE *fd; char *name; #define BUFLEN 1000 char buf[BUFLEN]; char msg[100]; main() { while(1) { if (gets(buf) == NULL) doexit(0); if (chkhdr()) { if (files > 0) fclose(fd); if ((fd = fopen(name,"w")) == NULL) { sprintf(msg,"Fatal - Can't create %s",name); perror(msg); doexit(1); } else files++; } else { if (files == 0) { fprintf(stderr,"Fatal - not a joined file!\n"); doexit(1); } else { fprintf(fd,"%s\n",buf); } } } } chkhdr() { /* Look for "<<< filename >>>" */ int i; if (buf[0] != '<') return(0); if (buf[1] != '<') return(0); if (buf[2] != '<') return(0); if (buf[3] != ' ') return(0); for (i = 4; (buf[i] != '\0') && (i < BUFLEN); i++) ; if (buf[i-1] != '>') return(0); if (buf[i-2] != '>') return(0); if (buf[i-3] != '>') return(0); if (buf[i-4] != ' ') return(0); buf[i-4] = '\0'; name = buf+4; return; } doexit(x) int x; { /* Exit from program */ if (files > 0) fclose(fd); fprintf(stderr, "Done, unjoined %d file%c\n",files,(files == 1) ? ' ' : 's'); exit(x); } <<< ckcdeb.h >>> /* C K C D E B . H */ ]/********************************************************************** * * * IVS / MCS-Kermit REL 2 * * source code * * * * Change History: * * * * 1. Modify C-Kermit(4E) source code to * * produce new module for MCS/IVS-Kermit * * ORIGINAL RELEASE * * June 22, 1990 * * * * * ***********************************************************************/ /* This file is included by all C-Kermit modules, including the modules that aren't specific to Kermit (like the command parser and the ck?tio and ck?fio modules. It specifies format codes for debug(), tlog(), and similar functions, and includes any necessary typedefs to be used by all C-Kermit modules, and also includes some feature selection compile-time switches. */ /* Copyright (C) 1987, 1989, Trustees of Columbia University in the City of New York. Permission is granted to any individual or institution to use, copy, or redistribute this software so long as it is not sold for profit, provided this copyright notice is retained. */ /* DEBUG and TLOG should be defined in the Makefile if you want debugging and transaction logs. Don't define them if you want to save the space overhead. */ #ifndef DEBUG #define debug(a,b,c,d) {} #endif #ifndef TLOG #define tlog(a,b,c,d) {} #endif /* Formats for debug(), tlog(), etc */ #define F000 0 #define F001 1 #define F010 2 #define F011 3 #define F100 4 #define F101 5 #define F110 6 #define F111 7 /* Unix Version Dependencies */ /* signal() type, void or int? */ #ifdef SVR3 typedef void SIGTYP; /* System V R3 and later */ #else #ifdef SUNOS4 typedef void SIGTYP; /* SUNOS V 4.0 and later */ #else typedef int SIGTYP; #endif #endif /* C Compiler Dependencies */ #ifdef ZILOG #define setjmp setret #define longjmp longret #define jmp_buf ret_buf typedef int ret_buf[10]; #endif /* zilog */ #ifdef PROVX1 typedef char CHAR; typedef long LONG; typedef int void; #else #ifdef V7 typedef char CHAR; typedef long LONG; #else #ifdef C70 typedef char CHAR; typedef long LONG; #else #ifdef BSD29 typedef char CHAR; typedef long LONG; #else typedef unsigned char CHAR; typedef long LONG; #endif #endif #endif #endif #ifdef TOWER1 typedef int void; #endif /* Line delimiter for text files */ /* If the system uses a single character for text file line delimitation, define NLCHAR to the value of that character. For text files, that character will be converted to CRLF upon output, and CRLF will be converted to that character on input during text-mode (default) packet operations. */ #ifdef MAC /* Macintosh */ #define NLCHAR 015 #else /* All Unix-like systems */ #define NLCHAR 012 #endif /* At this point, if there's a system that uses ordinary CRLF line delimitation AND the C compiler actually returns both the CR and the LF when doing input from a file, then #undef NLCHAR. */ /* The device name of a job's controlling terminal */ /* Special for VMS, same for all Unixes (?), not used by Macintosh */ #ifdef vms #define CTTNAM "TT:" #else #ifdef datageneral #define CTTNAM "@output" #else #define CTTNAM "/dev/tty" #endif #endif /* Some special includes for VAX/VMS */ #ifndef vms /* The following #includes cause problems for some preprocessors. */ /* #endif #ifdef vms #include ssdef #include stsdef #endif #ifndef vms */ #endif /* Program return codes for VMS, DECUS C, and Unix */ #ifdef vms #define GOOD_EXIT (SS$_NORMAL | STS$M_INHIB_MSG) #define BAD_EXIT SS$_ABORT #else #ifdef decus #define GOOD_EXIT IO_NORMAL #define BAD_EXIT IO_ERROR #else #define GOOD_EXIT 0 #define BAD_EXIT 1 #endif #endif /* Special hack for Fortune, which doesn't have ... */ #ifdef FT18 #define FREAD 0x01 #define FWRITE 0x10 #endif <<< ckcker.h >>> /* ckcker.h -- Symbol and macro definitions for C-Kermit */ /********************************************************************** * * * IVS / MCS-Kermit REL 2 * * source code * * * * Change History: * * * * 1. Modify C-Kermit(4E) source code to * * produce new module for MCS/IVS-Kermit * * ORIGINAL RELEASE * * June 22, 1990 * * * * * ***********************************************************************/ /* Author: Frank da Cruz (SY.FDC@CU20B), Columbia University Center for Computing Activities, January 1985. Copyright (C) 1985, Trustees of Columbia University in the City of New York. Permission is granted to any individual or institution to use, copy, or redistribute this software so long as it is not sold for profit, provided this copyright notice is retained. */ /* Mnemonics for ASCII characters */ #define NUL 000 /* ASCII Null */ #define SOH 001 /* ASCII Start of header */ #define BEL 007 /* ASCII Bell (Beep) */ #define BS 010 /* ASCII Backspace */ #define LF 012 /* ASCII Linefeed */ #define CR 015 /* ASCII Carriage Return */ #define XON 021 /* ASCII XON */ #define SP 040 /* ASCII Space */ #define DEL 0177 /* ASCII Delete (Rubout) */ /* Packet buffer and window sizes, will probably need to be #ifdef'd for */ /* each system. */ #define MAXSP 2048 /* Send packet buffer size */ #define MAXRP 1024 /* Receive packet buffer size */ #define MAXWS 1 /* Maximum window size */ /* Kermit parameters and defaults */ #define MAXPACK 94 /* Maximum unextended packet size */ #define CTLQ '#' /* Control char prefix I will use */ #define MYEBQ '&' /* 8th-Bit prefix char I will use */ #define MYRPTQ '~' /* Repeat count prefix I will use */ #define MAXTRY 10 /* Times to retry a packet */ #define MYPADN 0 /* How many padding chars I need */ #define MYPADC '\0' /* Which padding character I need */ #define DMYTIM 7 /* Default timeout interval to use. */ #define URTIME 10 /* Timeout interval to be used on me. */ #define DEFTRN 0 /* Default line turnaround handshake */ #define DEFPAR 0 /* Default parity */ #define MYEOL CR /* End-Of-Line character I need on packets. */ #define DRPSIZ 90 /* Default incoming packet size. */ #define DSPSIZ 90 /* Default outbound packet size. */ #define DDELAY 5 /* Default delay. */ #define DSPEED 9600 /* Default line speed. */ /* Files */ #define ZCTERM 0 /* Console terminal */ #define ZSTDIO 1 /* Standard input/output */ #define ZIFILE 2 /* Current input file */ #define ZOFILE 3 /* Current output file */ #define ZDFILE 4 /* Current debugging log file */ #define ZTFILE 5 /* Current transaction log file */ #define ZPFILE 6 /* Current packet log file */ #define ZSFILE 7 /* Current session log file */ #define ZSYSFN 8 /* Input from a system function */ #define ZNFILS 9 /* How many defined file numbers */ /* Screen functions */ #define SCR_FN 1 /* filename */ #define SCR_AN 2 /* as-name */ #define SCR_FS 3 /* file-size */ #define SCR_XD 4 /* x-packet data */ #define SCR_ST 5 /* File status: */ #define ST_OK 0 /* Transferred OK */ #define ST_DISC 1 /* Discarded */ #define ST_INT 2 /* Interrupted */ #define ST_SKIP 3 /* Skipped */ #define ST_ERR 4 /* Fatal Error */ #define SCR_PN 6 /* packet number */ #define SCR_PT 7 /* packet type or pseudotype */ #define SCR_TC 8 /* transaction complete */ #define SCR_EM 9 /* error message */ #define SCR_WM 10 /* warning message */ #define SCR_TU 11 /* arbitrary undelimited text */ #define SCR_TN 12 /* arbitrary new text, delimited at beginning */ #define SCR_TZ 13 /* arbitrary text, delimited at end */ #define SCR_QE 14 /* quantity equals (e.g. "foo: 7") */ /* Macros */ #define tochar(ch) ((ch) + SP ) /* Number to character */ #define xunchar(ch) ((ch) - SP ) /* Character to number */ #define ctl(ch) ((ch) ^ 64 ) /* Controllify/Uncontrollify */ #define unpar(ch) ((ch) & 127) /* Clear parity bit */ <<< ckucmd.h >>> /* C K U C M D . H -- Header file for Unix cmd package */ /********************************************************************** * * * IVS / MCS-Kermit REL 2 * * source code * * * * Change History: * * * * 1. Modify C-Kermit(4E) source code to * * produce new module for MCS/IVS-Kermit * * ORIGINAL RELEASE * * June 22, 1990 * * * * * ***********************************************************************/ /* Author: Frank da Cruz (SY.FDC@CU20B), Columbia University Center for Computing Activities, January 1985. Copyright (C) 1985, Trustees of Columbia University in the City of New York. Permission is granted to any individual or institution to use, copy, or redistribute this software so long as it is not sold for profit, provided this copyright notice is retained. */ /* Special getchars... */ #ifdef vax11c #define getchar() vms_getchar() #endif #ifdef aegis #undef getchar #define getchar() coninc(0) #endif #ifdef AMIGA #undef getchar #define getchar() coninc(0) #endif /* Sizes of things */ #define HLPLW 78 /* Width of ?-help line */ #define HLPCW 19 /* Width of ?-help column */ #define CMDBL 200 /* Command buffer length */ #define HLPBL 100 /* Help string buffer length */ #define ATMBL 100 /* Command atom buffer length*/ /* Special characters */ #ifndef NUL #define NUL '\0' /* Null */ #endif #define HT '\t' /* Horizontal Tab */ #define NL '\n' /* Newline */ #ifndef CR #define CR '\r' #endif #define FF 0014 /* Formfeed (^L) */ #define RDIS 0022 /* Redisplay (^R) */ #define LDEL 0025 /* Delete line (^U) */ #define WDEL 0027 /* Delete word (^W) */ #define ESC 0033 /* Escape */ #define RUB 0177 /* Rubout */ #ifndef BEL #define BEL 0007 /* Bell */ #endif #ifndef BS #define BS 0010 /* Backspace */ #endif #ifndef SP #define SP 0040 /* Space */ #endif /* Keyword table flags */ #define CM_INV 1 /* Invisible keyword */ /* Keyword Table Template */ struct keytab { /* Keyword table */ char *kwd; /* Pointer to keyword string */ int val; /* Associated value */ int flgs; /* Flags (as defined above) */ }; <<< ckusym.h >>> /********************************************************************** * * * IVS / MCS-Kermit REL 2 * * source code * * * * Change History: * * * * 1. Modify C-Kermit(4E) source code to * * produce new module for MCS/IVS-Kermit * * ORIGINAL RELEASE * * June 22, 1990 * * * * * ***********************************************************************/ /* This file is for use with compilers that don't have the capability to * #define symbols on the C compiler command line. This file must * be #include'd before all other ck*.h files so that the symbols #define'd * here can be used for any subsequent conditional code. Symbols should be * #define'd as 1 if TRUE and 0 if FALSE. This implies, of course, that they * be tested with #if's, not #ifdef's and #ifndef's. */ /* * For example, this file was required to compile Macintosh Kermit under * Megamax C (which we don't do any more), because Megamax did not have * a mechanism for defining symbols on the command line, so this file was * used to define the symbol MAC. */ <<< ckuusr.h >>> /* C K U U S R . H -- Symbol definitions for V-Kermit ckuus*.c modules */ /********************************************************************** * * * IVS / MCS-Kermit REL 2 * * source code * * * * Change History: * * * * 1. Modify C-Kermit(4E) source code to * * produce new module for MCS/IVS-Kermit * * ORIGINAL RELEASE * * June 22, 1990 * * * * * ***********************************************************************/ /* Author: Frank da Cruz (SY.FDC@CU20B), Columbia University Center for Computing Activities, January 1985. Copyright (C) 1985, Trustees of Columbia University in the City of New York. Permission is granted to any individual or institution to use, copy, or redistribute this software so long as it is not sold for profit, provided this copyright notice is retained. */ /* Name of C-Kermit program initialization file. */ #ifdef vax11c #define KERMRC "kermit.ini" #else #define KERMRC "kermrc" #endif #ifndef AMIGA #ifndef vax11c #ifndef datageneral #include "pwd.h" #endif #endif #endif /* Values associated with top-level commands, must be 0 or greater. */ #define XXBYE 0 /* BYE */ #define XXCLE 1 /* CLEAR */ #define XXCLO 2 /* CLOSE */ #define XXCON 3 /* CONNECT */ #define XXCPY 4 /* COPY */ #define XXCWD 5 /* CWD (Change Working Directory) */ #define XXDEF 6 /* DEFINE (a command macro) */ #define XXDEL 7 /* (Local) DELETE */ #define XXDIR 8 /* (Local) DIRECTORY */ #define XXDIS 9 /* DISCONNECT */ #define XXECH 10 /* ECHO */ #define XXEXI 11 /* EXIT */ #define XXFIN 12 /* FINISH */ #define XXGET 13 /* GET */ #define XXHLP 14 /* HELP */ #define XXINP 15 /* INPUT */ #define XXLOC 16 /* LOCAL */ #define XXLOG 17 /* LOG */ #define XXMAI 18 /* MAIL */ #define XXMOU 19 /* (Local) MOUNT */ #define XXMSG 20 /* (Local) MESSAGE */ #define XXOUT 21 /* OUTPUT */ #define XXPAU 22 /* PAUSE */ #define XXPRI 23 /* (Local) PRINT */ #define XXQUI 24 /* QUIT */ #define XXREC 25 /* RECEIVE */ #define XXREM 26 /* REMOTE */ #define XXREN 27 /* (Local) RENAME */ #define XXSEN 28 /* SEND */ #define XXSER 29 /* SERVER */ #define XXSET 30 /* SET */ #define XXSHE 31 /* Command for SHELL */ #define XXSHO 32 /* SHOW */ #define XXSPA 33 /* (Local) SPACE */ #define XXSTA 34 /* STATISTICS */ #define XXSUB 35 /* (Local) SUBMIT */ #define XXTAK 36 /* TAKE */ #define XXTRA 37 /* TRANSMIT */ #define XXTYP 38 /* (Local) TYPE */ #define XXWHO 39 /* (Local) WHO */ #define XXDIAL 40 /* (Local) DIAL */ #define XXLOGI 41 /* (Local) SCRIPT */ #define XXCOM 42 /* Comment */ #define XXHAN 43 /* HANGUP */ /* SET parameters */ #define XYBREA 0 /* BREAK simulation */ #define XYCHKT 1 /* Block check type */ #define XYDEBU 2 /* Debugging */ #define XYDELA 3 /* Delay */ #define XYDUPL 4 /* Duplex */ #define XYEOL 5 /* End-Of-Line (packet terminator) */ #define XYESC 6 /* Escape character */ #define XYFILE 7 /* File Parameters */ #define XYFILN 0 /* Naming */ #define XYFILT 1 /* Type */ #define XYFILW 2 /* Warning */ #define XYFILD 3 /* ... */ /* empty space to add something */ #define XYFLOW 9 /* Flow Control */ #define XYHAND 10 /* Handshake */ #define XYIFD 11 /* Incomplete File Disposition */ #define XYIMAG 12 /* "Image Mode" */ #define XYINPU 13 /* INPUT command parameters */ #define XYLEN 14 /* Maximum packet length to send */ #define XYLINE 15 /* Communication line to use */ #define XYLOG 16 /* Log file */ #define XYMARK 17 /* Start of Packet mark */ #define XYNPAD 18 /* Amount of padding */ #define XYPADC 19 /* Pad character */ #define XYPARI 20 /* Parity */ #define XYPAUS 21 /* Interpacket pause */ #define XYPROM 22 /* Program prompt string */ #define XYQBIN 23 /* 8th-bit prefix */ #define XYQCTL 24 /* Control character prefix */ #define XYREPT 25 /* Repeat count prefix */ #define XYRETR 26 /* Retry limit */ #define XYSPEE 27 /* Line speed (baud rate) */ #define XYTACH 28 /* Character to be doubled */ #define XYTIMO 29 /* Timeout interval */ #define XYMODM 30 /* Modem type */ #define XYSEND 31 /* SEND parameters, used with some of the above */ #define XYRECV 32 /* RECEIVE parameters, ditto */ #define XYTERM 34 /* Terminal parameters */ #define XYID 35 /* SPUR file id-fields */ #define XYNUM 36 /* SPUR file line numbers */ #define XYRNUM 37 /* SPUR file line renumbering */ #define XYADD 38 /* SPUR file line number adding */ /* REMOTE command symbols */ #define XZCPY 0 /* Copy */ #define XZCWD 1 /* Change Working Directory */ #define XZDEL 2 /* Delete */ #define XZDIR 3 /* Directory */ #define XZHLP 4 /* Help */ #define XZHOS 5 /* Host */ #define XZKER 6 /* Kermit */ #define XZLGI 7 /* Login */ #define XZLGO 8 /* Logout */ #define XZMAI 9 /* Mail */ #define XZMOU 10 /* Mount */ #define XZMSG 11 /* Message */ #define XZPRI 12 /* Print */ #define XZREN 13 /* Rename */ #define XZSET 14 /* Set */ #define XZSPA 15 /* Space */ #define XZSUB 16 /* Submit */ #define XZTYP 17 /* Type */ #define XZWHO 18 /* Who */ /* Symbols for logs */ #define LOGD 0 /* Debugging */ #define LOGP 1 /* Packets */ #define LOGS 2 /* Session */ #define LOGT 3 /* Transaction */ <<< ckvbuf.c >>> /* CKVBUF_C 12 June 90 */ /*********************************************************************** * MCS-Kermit REL 2 * * source code * * * * Change History: * * * * 1. Modify C-Kermit(4E) source code to * * produce new module for MCS/IVS-Kermit * * ORIGINAL RELEASE * * June 22, 1990 * * * * * ***********************************************************************/ #include #include #include #include "mcs_defs_h" #include "ckcdeb.h" /* DRE 030690 */ #include "ckcker.h" /* DRE 060690 */ extern FILE *Log; extern int server; /* DRE 020890 */ extern int deblog; /* DRE 030690 */ static char _inbuffer[MAXRP] = { '\0' }; static char _outbuffer[MAXSP] = { '\0' }; static char *_instart = &_inbuffer[0]; static char *_inend = &_inbuffer[0]; static char *_outstart = &_outbuffer[0]; static char *_outend = &_outbuffer[0]; static char mcsstr[MAXSP]; static char buf[MAXRP]; #define _insize (_inend - _instart) #define _outsize (_outend - _outstart) /***************************************************************************** ***************************************************************************** ********* OUTPUT ROUTINES ******** ***************************************************************************** *****************************************************************************/ mcs_printf(tmp_string) char *tmp_string; { if (deblog) debug (F110, "funct: mcs_printf", tmp_string, 0); if (_myprnt(tmp_string)) return strlen(tmp_string); else return EOF; } mcs_fprintf(stream, tmp_string) FILE *stream; char *tmp_string; { if (deblog) debug (F110, "funct: mcs_fprintf", tmp_string, 0); if (stream == stdout) { if (_myprnt(tmp_string)) return strlen(tmp_string); else return EOF; } else return(fprintf(stream, tmp_string)); } mcs_puts(tmp_string) char *tmp_string; { if (deblog) debug (F110, "funct: mcs_puts", tmp_string, 0); if (!_myprnt(tmp_string)) return EOF; if (!_myprnt("\n")) return EOF; else return '\n'; } mcs_fputs(tmp_string, stream) char *tmp_string; FILE *stream; { if (deblog) debug (F110, "funct: mcs_fputs", tmp_string, 0); if (stream == stdout) { /* DRE 1/24/90 */ if (_myprnt(tmp_string)) return 0; else return EOF; } else return(fputs(tmp_string, stream)); } mcs_fputc(ch, stream) int ch; FILE *stream; { char tmp_string[5]; if (deblog) debug (F101, "funct: mcs_fputc", "", ch); if (stream == stdout) { /* DRE 1/24/90 */ tmp_string[0] = ch; tmp_string[1] = '\0'; if (_myprnt(tmp_string)) return tmp_string[0]; else return EOF; } else return(fputc(ch, stream)); } mcs_fputchar(ch) int ch; { char tmp_string[5]; if (deblog) debug (F101, "funct: mcs_fputchar", "", ch); tmp_string[0] = ch; tmp_string[1] = '\0'; if (_myprnt(tmp_string)) return tmp_string[0]; else return EOF; } mcs_putchar(tmp_char) char tmp_char; { char tmp_string[5]; if (deblog) debug (F101, "funct: mcs_putchar", "", tmp_char); tmp_string[0] = tmp_char; tmp_string[1] = '\0'; if (_myprnt(tmp_string)) return tmp_string[0]; else return EOF; } mcs_fflush() { int mesg_len; char status[3]; if (deblog) debug (F100, "funct: mcs_fflush", "", 0); if (_outend != _outstart) { mesg_len = _outend - _outstart + 1; strncpy(mcsstr, _outstart, mesg_len); mcsstr[mesg_len] = '\0'; mcs_send(QUEUENAME, mcsstr, mesg_len, OUT_TERM, status); _outstart = &_outbuffer[0]; _outend = _outstart; } } mcs_clrbuf() { if (deblog) debug (F100, "funct: mcs_clrbuf", "", 0); _instart = &_inbuffer[0]; _inend = _instart; } mcs_write(fildes, buffer, nbyte) int fildes; char *buffer; unsigned nbyte; { int mesg_len = nbyte; char status[3]; if (deblog) debug (F100, "funct: mcs_write", "", 0); if (fildes == 1) { mcs_send(QUEUENAME, buffer, mesg_len, OUT_TERM, status); return(nbyte); /* NEED A RETURN STATUS */ } else return(write(fildes, buffer, nbyte)); } /***************************************************************************** ***************************************************************************** ********* INPUT ROUTINES ******** ***************************************************************************** *****************************************************************************/ mcs_gets(tmp_string) char *tmp_string; { int mesg_len; if (deblog) debug (F100, "funct: mcs_gets", "", 0); mesg_len = _myread(tmp_string, 0); if (mesg_len == 0) return NULL; tmp_string[mesg_len - 1] = '\0'; return (int)tmp_string; } mcs_getchar() { char tmp_string[5]; int mesg_len; if (deblog) debug (F100, "funct: mcs_getchar", "", 0); mesg_len = _myread(tmp_string, 1); if (mesg_len == 0) return EOF; return(tmp_string[0]); } char *mcs_fgets(str, num, stream) char *str; int num; FILE *stream; { int mesg_len; if (deblog) debug (F100, "funct: mcs_fgets", "", 0); if (stream == stdin) { mesg_len = _myread(str, num - 1); if (mesg_len == 0) return NULL; return str; } else return(fgets(str, num, stream)); } mcs_fgetc(stream) FILE *stream; { char tmp_string[5]; int mesg_len; if (deblog) debug (F100, "funct: mcs_fgetc", "", 0); if (stream == stdin) { mesg_len = _myread(tmp_string, 1); if (mesg_len == 0) return EOF; return(tmp_string[0]); } else return(fgetc(stream)); } mcs_read(fildes, buffer, nbyte) int fildes; char *buffer; unsigned nbyte; { int mesg_len = nbyte; int num = 0, i; char status[3]; if (deblog) debug (F100, "funct: mcs_read", "", 0); if (fildes == 0) { /* WHAT IS THE MINIMUM BYTES ALLOWED TO BE READ? - 80 chars */ /* msleep(500); */ for (; num < nbyte; num++) { *(buffer + num) = mcs_getchar(); if (*(buffer + num) == '\n') { num++; break; } } buffer[num] = '\0'; /* NEED A RETURN STATUS */ return(num); } else return(read(fildes, buffer, nbyte)); } _myprnt(str) char *str; { register char *p; char status[3], tmp_c; register int mesg_len, size; int outcome; /* DRE 060690 */ if (deblog) debug (F110, "funct: _myprnt", str, 0); outcome = 1; /* start with good outcome */ for (p = str; *p != '\0'; ) *_outend++ = *p++; /* append string to buffer */ *_outend = *p; /* put null character at end */ for (p = _outstart; *p; ) { if (*p == '\n') { /* if newline found, send line */ p++; mesg_len = p - _outstart; tmp_c = *p; *p = '\0'; mcs_send(QUEUENAME, _outstart, mesg_len, OUT_TERM, status); if ((strncmp(status, "00", 2) != 0) && (strncmp(status, "98", 2) != 0)) { /* log the message then throw it away */ fprintf(stderr,"_myprnt: mcs_send failed\n"); fprintf(stderr," ==> %s", _outstart); outcome = 0; /* bad outcome */ } *p = tmp_c; _outstart = p; } else p++; } if (_outstart != &_outbuffer[0]) { /* we must have sent a msg */ if (_outstart != _outend) { /* reset the buffer */ size = _outsize; /* The strcpy function call was removed on 6-12-90 because it was causing some type of buffer corruption problem. The exact cause was not determined, but the problem disappeared when strcpy was replaced by the sprintf function call. strcpy(_outbuffer, _outstart); */ sprintf(_outbuffer,"%s",_outstart); _outstart = &_outbuffer[0]; _outend = _outstart + size; } else { _outstart = &_outbuffer[0]; _outend = _outstart; } } return (outcome); } _myread(str, num) char *str; int num; { register char *p; char status[3], *endstr; register int i, size; int mesg_len; if (deblog) debug (F100, "funct: _myread", "", 0); if (_insize == 0) { if (!server) mcs_fflush(); mcs_recv(QUEUENAME, buf, &mesg_len, IN_TERM, status); if ((strncmp(status, "00", 2) != 0) && (strncmp(status, "98", 2) != 0)) { if (!server) mcs_send(QUEUENAME, "\n", 1, OUT_TERM, status); return 0; } if (!server) mcs_send(QUEUENAME, "\n", 1, OUT_TERM, status); memcpy(_instart,buf,(mesg_len+1)); /* * _inend = _instart + mesg_len + 1; */ _inend = _instart + mesg_len; } if (num == 0) { for (p = _instart; *p != '\n'; ) *str++ = *p++; *str++ = *p++; *str = '\0'; mesg_len = p - _instart; _instart = p; } else { for (i = 0; i < num; i++) { str[i] = _instart[i]; if (str[i] == '\n') { i++; break; } } mesg_len = i; str[mesg_len] = '\0'; _instart = _instart + mesg_len; } if (_instart != &_inbuffer[0]) { if (_instart != _inend) { size = _insize; memcpy(_inbuffer, _instart,size); _instart = &_inbuffer[0]; _inend = _instart + size; } else { _instart = &_inbuffer[0]; _inend = _instart; } } return mesg_len; } <<< ckvcmd.c >>> char *cmdv = "VRX/E cmd package V2(023), 06 June 90"; /* C K V C M D -- Interactive command package for NCR-VRX */ /********************************************************************** * * * IVS / MCS-Kermit REL 2 * * source code * * * * Change History: * * * * 1. Modify C-Kermit(4E) source code to * * produce new module for MCS/IVS-Kermit * * ORIGINAL RELEASE * * June 22, 1990 * * * * * ***********************************************************************/ /* V2 adds support for Data General and Apollo Aegis. */ /* 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 defaults 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 - Reset 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 See 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 NCR-VRX. 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 deletion, 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 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 */ #include /* Standard C I/O package */ #include /* Character types */ #include "ckucmd.h" /* Command parsing definitions */ #include "ckcdeb.h" /* Formats for debug() */ #ifdef MCS_FLAG #include "mcs.h" #endif /* external variables */ extern int deblog; extern void errhdlr(); /* replaces perror */ extern int debug(); extern int ncmd; extern struct keytab cmdtab[]; /* Local variables */ int psetf = 0, /* Flag that prompt has been set */ cc = 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[CMDBL+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 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 P T -- Issue the program prompt. */ prompt() { if (psetf == 0) cmsetp(dfprom); /* If no prompt set, set default. */ #ifndef MCS_FLAG printf("\r%s", cmprom); /* Print the prompt. */ #else sprintf(print_str,"\r%s", cmprom); mcs_printf(print_str); /* Print the prompt. */ #endif } /* 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 specifies 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, only 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; /* will point to atmbuf or xdef */ if (radix != 10) { /* Just do base 10 for now */ #ifndef MCS_FLAG printf("cmnum: illegal radix - %d\n", radix); #else sprintf(print_str,"cmnum: illegal radix - %d\n", radix); mcs_printf(print_str); #endif return(-1); } x = cmfld(xhlp, xdef, &s); if (deblog) debug(F101, "cmnum: cmfld", "", x); if (x < 0) return(x); /* Parse a field */ if (digits(s)) { /* Convert to number */ *n = atoi(s); return(x); } else { #ifndef MCS_FLAG /* In IVS-Kermit, back spaces are handled by IVS, so there is * no chance of encountering a back space character. */ printf("\n?not a number - %s\n", s); return(-2); #else /* In MCS-Kermit, the kermit logic itself handles back space * characters. So, if the current field is not a number, * then maybe the user entered back spaces later on in the * command line. In order to reparse the command, we will * dummy up the return value and integer pointer. The setnum * routine will see the changes and put out an error message * if no back spaces were entered. If back spaces were * entered, then the setnum routine will return a value that * will cause the entire command to be reparsed. */ /* sprintf(print_str,"\n?not a number - %s\n", s); * mcs_printf(print_str); */ *n = -562; /* unusual number to signify error */ return(0); #endif } } /* 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, with 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)) { #ifndef MCS_FLAG printf("\n?Wildcards not allowed - %s\n", s); #else sprintf(print_str,"\n?Wildcards not allowed - %s\n", s); mcs_printf(print_str); #endif return(-2); } if (zchko(s) < 0) { #ifndef MCS_FLAG printf("\n?Write permission denied - %s\n", s); #else sprintf(print_str,"\n?Write permission denied - %s\n", s); mcs_printf(print_str); #endif return(-2); } else { *xp = s; return(x); } } /* C M I F I -- Parse the name of an existing file */ /* This function depends on 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. */ 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 = gtword(); /* 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. */ if (deblog) debug(F111, "cmifi: gtword", atmbuf, xc); 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 == 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); if (deblog) debug(F101, " *wild", "", *wild); if (*wild != 0) { y = zxpand(*xp); if (y == 0) { #ifndef MCS_FLAG printf("\n?No files match - %s\n", *xp); #else sprintf(print_str,"\n?No files match - %s\n", *xp); mcs_printf(print_str); #endif return(-2); } else if (y < 0) { #ifndef MCS_FLAG printf("\n?Too many files match - %s\n", *xp); #else sprintf(print_str,"\n?Too many files match - %s\n", *xp); mcs_printf(print_str); #endif return(-2); } else return(x); } /* If not wild, see if it exists and is readable. */ y = zchki(*xp); if (y == -3) { #ifndef MCS_FLAG printf("\n?Read permission denied - %s\n", *xp); #else sprintf(print_str,"\n?Read permission denied - %s\n", *xp); mcs_printf(print_str); #endif return(-2); } else if (y == -2) { #ifndef MCS_FLAG printf("\n?File not readable - %s\n", *xp); #else sprintf(print_str,"\n?File not readable - %s\n", *xp); mcs_printf(print_str); #endif return(-2); } else if (y < 0) { #ifndef MCS_FLAG printf("\n?File not found - %s\n", *xp); #else sprintf(print_str,"\n?File not found - %s\n", *xp); mcs_printf(print_str); #endif return(-2); } return(x); /* 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-- = '\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); * 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; */ case 3: /* Question mark */ if (*xhlp == NUL) #ifndef MCS_FLAG printf(" Input file specification"); #else mcs_printf(" Input file specification"); #endif else #ifndef MCS_FLAG printf(" %s", xhlp); #else sprintf(print_str," %s", xhlp); mcs_printf(print_str); #endif if (xc > 0) { sp = atmbuf + cc; /* Insert * at end */ *sp++ = '*'; *sp-- = '\0'; y = zxpand(atmbuf); *sp = '\0'; if (y == 0) { #ifndef MCS_FLAG printf("\n?No files match - %s\n", atmbuf); #else sprintf(print_str,"\n?No files match - %s\n", atmbuf); mcs_printf(print_str); #endif return(-2); } else if (y < 0) { #ifndef MCS_FLAG printf("\n?Too many file match - %s\n", atmbuf); #else sprintf(print_str,"\n?Too many file match - %s\n", atmbuf); mcs_printf(print_str); #endif return(-2); } else { #ifndef MCS_FLAG printf(", one of the following:\n"); #else mcs_printf(", one of the following:\n"); #endif clrhlp(); for (i = 0; i < y; i++) { znext(filbuf); addhlp(filbuf); } dmphlp(); } } else #ifndef MCS_FLAG printf("\n"); #else mcs_printf("\n"); #endif #ifndef MCS_FLAG printf("%s%s", cmprom, cmdbuf); #else sprintf(print_str,"%s%s", cmprom, cmdbuf); mcs_printf(print_str); #endif break; } x = gtword(); } } /* C H K W L D -- Check for wildcard characters '*' 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 = cmflgs) != 1) { /* Already confirmed? */ x = gtword(); /* 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. */ if (deblog) debug(F111, "cmfld: gtword", atmbuf, xc); if (deblog) 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 == 0) *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: /* Question mark */ if (*xhlp == NUL) #ifndef MCS_FLAG printf(" Please complete this field"); #else mcs_printf(" Please complete this field"); #endif else #ifndef MCS_FLAG printf(" %s", xhlp); #else sprintf(print_str," %s", xhlp); mcs_printf(print_str); #endif #ifndef MCS_FLAG printf("\n%s%s", cmprom, cmdbuf); #else sprintf(print_str,"\n%s%s", cmprom, cmdbuf); mcs_printf(print_str); #endif break; } x = gtword(); } } /* 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, xdef, xp) char *xhlp; char *xdef; char **xp; { int x; static int xc; if (deblog) 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 = gtword(); /* Get first word. */ *xp = pp; /* Save pointer to it. */ } while (1) { xc += cc; /* Char count for all words. */ if (deblog) debug(F111, "cmtxt: gtword", atmbuf, xc); if (deblog) 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); * } else { * putchar(BEL); * } * break; */ case 3: /* Question Mark */ if (*xhlp == NUL) #ifndef MCS_FLAG printf(" Text string"); #else mcs_printf(" Text string"); #endif else #ifndef MCS_FLAG printf(" %s", xhlp); #else sprintf(print_str," %s", xhlp); mcs_printf(print_str); #endif #ifndef MCS_FLAG printf("\n%s%s", cmprom, cmdbuf); #else sprintf(print_str,"\n%s%s", cmprom, cmdbuf); mcs_printf(print_str); #endif break; default: #ifndef MCS_FLAG printf("\n?Unexpected return code from gtword() - %d\n", x); #else sprintf(print_str, "\n?Unexpected return code from gtword() - %d\n",x); mcs_printf(print_str); #endif return(-2); } x = gtword(); } } /* C M K E Y -- Parse a keyword */ /* Call with: table -- keyword table, in 'struct keytab' format; n -- number of entries in table; xhlp -- 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) == 1) /* Command already entered? */ setatm(xdef); else zz = gtword(); if (deblog) { debug(F101, "cmkey: table length", "", n); debug(F101, " cmflgs", "", cmflgs); debug(F101, " zz", "", zz); } while (1) { xc += cc; if (deblog) debug(F111, "cmkey: gtword", 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(table, atmbuf, n, &z); switch (y) { case -2: #ifndef MCS_FLAG printf("\n?Ambiguous - %s\n", atmbuf); #else sprintf(print_str,"\n?Ambiguous - %s\n", atmbuf); mcs_printf(print_str); #endif return(cmflgs = -2); case -1: /* User entered an item not in the current table. * They might have entered a help command like, * 'SET ?' but have backspaced to enter a new * command. In IVS-Kermit, we don't see the * space characters, so we need to handle the * situation here. Check the command table. If * a match is found, reset the command table and * reparse the whole command again. */ y = lookup(cmdtab,atmbuf,ncmd,&z); if (y >= 0) { /* must be new command */ cmres(); /* reset buffer pointers */ strcpy(cmdbuf,atmbuf); /* move new cmd into buf */ strcat(cmdbuf," "); /* space is word terminator */ np = cmdbuf + strlen(cmdbuf); /* reset next field ptr */ return(cmflgs = -1); /* reparse the command */ } /* user entered invalid command */ #ifndef MCS_FLAG printf("\n?Invalid - %s\n", atmbuf); #else sprintf(print_str,"\n?Invalid - %s\n", atmbuf); mcs_printf(print_str); #endif return(cmflgs = -2); default: break; } return(y); /* 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); * if (deblog) debug(F111,"cmkey: default",atmbuf,cc); * } else { * putchar(BEL); * No default, just beep * * break; * } * } * y = lookup(table,atmbuf,n,&z); * Something in atmbuf * * if (deblog) 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); * if (deblog) debug(F110,"cmkey: addbuf",cmdbuf,0); * return(y); */ case 3: /* User terminated word with "?" */ y = lookup(table, atmbuf, n, &z); if (y > -1) { #ifndef MCS_FLAG printf(" %s\n%s%s", table[z].kwd, cmprom, cmdbuf); #else sprintf(print_str," %s\n%s%s", table[z].kwd, cmprom, cmdbuf); mcs_printf(print_str); #endif break; } else if (y == -1) { #ifndef MCS_FLAG printf("\n?Invalid\n"); #else mcs_printf("\n?Invalid\n"); #endif return(cmflgs = -2); } if (*xhlp == NUL) #ifndef MCS_FLAG printf(" One of the following:\n"); #else mcs_printf(" One of the following:\n"); #endif else #ifndef MCS_FLAG printf(" %s, one of the following:\n", xhlp); #else sprintf(print_str," %s, one of the following:\n", xhlp); mcs_printf(print_str); #endif clrhlp(); for (i = 0; i < n; i++) { if (!strncmp(table[i].kwd, atmbuf, cc) && !test(table[i].flgs, CM_INV)) addhlp(table[i].kwd); } dmphlp(); #ifndef MCS_FLAG printf("%s%s", "Again>", cmdbuf); #else sprintf(print_str,"%s%s", "Again>",cmdbuf); mcs_printf(print_str); #endif break; default: #ifndef MCS_FLAG printf("\n%d - Unexpected return code from gtword\n", zz); #else sprintf(print_str, "\n%d - Unexpected return code from gtword\n", zz); mcs_printf(print_str); #endif return(cmflgs = -2); } zz = gtword(); } } /* 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; if (deblog) debug(F101, "cmcfm: cmflgs", "", cmflgs); xc = cc = 0; if (cmflgs == 1) return(0); while (1) { x = gtword(); xc += cc; if (deblog) debug(F111, "cmcfm: gtword", 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) { #ifndef MCS_FLAG printf("?Not confirmed - %s\n", atmbuf); #else sprintf(print_str,"?Not confirmed - %s\n", atmbuf); mcs_printf(print_str); #endif return(-2); } else return(0); /* case 2: * putchar(BEL); * continue; */ case 3: if (xc > 0) { #ifndef MCS_FLAG printf("\n?Not confirmed - %s\n", atmbuf); #else sprintf(print_str,"\n?Not confirmed - %s\n", atmbuf); mcs_printf(print_str); #endif return(-2); } #ifndef MCS_FLAG printf("\n Type a carriage return to confirm the command\n"); printf("%s%s", cmprom, cmdbuf); #else mcs_printf("\n Type a carriage return to confirm the command\n"); sprintf(print_str,"%s%s", cmprom, cmdbuf); mcs_printf(print_str); #endif 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; 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; } } /* D M P H L P -- Dump the help line buffer */ dmphlp() { /* Print the help buffer */ hlpbuf[hx++] = NUL; #ifndef MCS_FLAG printf(" %s\n", hlpbuf); #else sprintf(print_str," %s\n", hlpbuf); mcs_printf(print_str); #endif 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 table 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, 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 */ 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 = gtword(); 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 3 if ... ? With: pp pointing to beginning of word in buffer bp pointing to after current position atmbuf containing a copy of the word cc containing the number of characters in the word copied to atmbuf */ gtword() { 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 */ if (deblog) { debug(F101, "gtword: cmdbuf", "", (int) cmdbuf); debug(F101, " bp", "", (int) bp); debug(F101, " pp", "", (int) pp); debug(F110, " cmdbuf", cmdbuf, 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) { errhdlr("ckucmd: gtword getchar"); return(-4); } c &= 127; /* Strip any parity bit. */ } else ignore = 1; if (quote == 0) { if (!ignore && (c == '\\')) { /* Quote character */ quote = 1; continue; } if (c == FF) { /* Formfeed. */ c = NL; /* Replace with newline */ SYSTEM("clear"); /* and clear the screen. */ } if (c == HT) c = ESC; /* Substitute ESC for tab */ 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 || c == CR) { /* CR, LF */ *bp = NUL; /* End the string */ if (echof) { /* If echoing, */ putchar(c); /* echo the typein */ if (c == CR) putchar(NL); } 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); /* Question mark triggers help message. So, we want to flush the rest of the input line including the new line so that the command is not accidently executed after the help message. */ while ((c = getchar()) != NL && c != CR) ; return(cmflgs = 3); } /* if (c == ESC) { * ESC * * *bp = NUL; * setatm(pp); * return(cmflgs = 2); * } */ if (c == BS || c == RUB) { /* Character deletion */ if (bp > cmdbuf) { /* If still in buffer... */ #ifndef MCS_FLAG printf("\b \b"); /* erase character from screen, */ #else mcs_printf("\b \b"); #endif 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 { cmres(); /* DRE 5-16-90 Test */ return(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); * } * * if (c == WDEL) { * ^W, word deletion * * if (bp <= cmdbuf) { * Beep if nothing to delete * * putchar(BEL); * cmres(); * return(cmflgs = -1); * } * bp--; * for ( ; (bp >= cmdbuf) && (*bp == SP) ; bp--) { * 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. */ } /* end of big while */ putchar(BEL); /* Get here if... */ #ifndef MCS_FLAG printf("\n?Buffer full\n"); #else mcs_printf("\n?Buffer full\n"); #endif 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 = bp; /* Update the next-field pointer */ return(len); /* Return the length */ } /* S E T A T M -- Deposit a string in the atom buffer */ setatm(cp) char *cp; { char *ap; cc = 0; ap = atmbuf; *ap = NUL; while (*cp == SP) cp++; while ((*cp != SP) && (*cp != NL) && (*cp != NUL) && (*cp != CR)) { *ap++ = *cp++; cc++; } *ap++ = NUL; return(cc); /* Return length */ } /* D I G I T S -- Verify that all the characters in line are digits */ digits(s) char *s; { 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); } <<< ckvcon.c >>> char *connv = "Connect Command for VRX/E, V4E(017) 10 May 90"; /* C K V C O N -- Dumb terminal connection to remote system, for NCR-VRX */ /********************************************************************** * * * IVS / MCS-Kermit REL 2 * * source code * * * * Change History: * * * * 1. Modify C-Kermit(4E) source code to * * produce new module for MCS/IVS-Kermit * * ORIGINAL RELEASE * * June 22, 1990 * * * * * ***********************************************************************/ /* This module should work under all versions of NCR-VRX. It calls externally defined system-dependent functions for i/o, but depends upon the existence of the FORK() function. Author: Frank da Cruz (SY.FDC@CU20B), Columbia University Center for Computing Activities, January 1985. Copyright (C) 1985, Trustees of Columbia University in the City of New York. Permission is granted to any individual or institution to use, copy, or redistribute this software so long as it is not sold for profit, provided this copyright notice is retained. Enhanced by H. Fischer to detect when child process (modem reader) reports that the communications line has been broken and hang up. Also enhanced to allow escaping from connect state to command interpreter, to allow sending/receiving without breaking connection. */ #include #include /* Character types */ #include "ckcdeb.h" #include "ckcker.h" #include #include "kermisc.h" #include /* Longjumps */ #ifdef MCS_FLAG #include "mcs.h" #endif #ifndef SIGUSR1 #define SIGUSR1 16 #endif extern int local, speed, escape, duplex, parity, flow, seslog, mdmtyp; extern int errno, cmask, fmask, deblog; extern char ttname[], sesfil[]; extern CHAR dopar(); extern void errhdlr(); int i, active; /* Variables global to this module */ int io_retry = 0; char *chstr(); char temp[50]; #define LBUFL 200 /* Line buffer */ char lbuf[LBUFL]; /* Connect state parent/child communication signal handlers */ static jmp_buf env_con; /* Envir ptr for connect errors */ static conn_int() { /* Modem read failure handler, */ longjmp(env_con, 1); /* notifies parent process to stop */ } /* C O N E C T -- Perform terminal connection */ conect() { int pid, /* process id of child (modem reader) */ parent_id, /* process id of parent (keyboard reader) */ n; int c; /* c is a character, but must be signed integer to pass thru -1, which is the modem disconnection signal, and is different from the character 0377 */ char errmsg[50], *erp; if (!local) { #ifndef MCS_FLAG printf("Sorry, you must 'set line' first\n"); #else mcs_printf("Sorry, you must 'set line' first\n"); #endif return(-2); } if (speed < 0) { #ifndef MCS_FLAG printf("Sorry, you must 'set speed' first\n"); #else mcs_printf("Sorry, you must 'set speed' first\n"); #endif return(-2); } if ((escape < 0) || (escape > 0177)) { #ifndef MCS_FLAG printf("Your escape character is not ASCII - %d\n", escape); #else sprintf(print_str,"Your escape character is not ASCII - %d\n", escape); mcs_printf(print_str); #endif return(-2); } if (ttopen(ttname, &local, mdmtyp) < 0) { erp = errmsg; sprintf(erp, "conect: Sorry, can't open %s", ttname); errhdlr(errmsg); return(-2); } #ifndef MCS_FLAG printf("Connecting thru %s, speed %d.\r\n", ttname, speed); printf("The escape character is %s (%d).\r\n", chstr(escape), escape); printf("Type the escape character followed by C to get back,\r\n"); printf("or followed by ? to see other options.\r\n"); #else sprintf(print_str,"Connecting thru %s, speed %d.\r\n", ttname, speed); mcs_printf(print_str); sprintf(print_str,"The escape character is %s (%d).\r\n", chstr(escape), escape); mcs_printf(print_str); mcs_printf("Type the escape character followed by C to get back,\r\n"); mcs_printf("or followed by ? to see other options.\r\n"); #endif /* Condition console terminal and communication line */ if (conbin(escape) < 0) { #ifndef MCS_FLAG printf("Sorry, can't condition console terminal\n"); #else mcs_printf("Sorry, can't condition console terminal\n"); #endif return(-2); } if (ttvt(speed, flow) < 0) { conres(); #ifndef MCS_FLAG printf("Sorry, Can't condition communication line\n"); #else mcs_printf("Sorry, Can't condition communication line\n"); #endif return(-2); } parent_id = getpid(); /* Get parent id for signalling */ SIGNAL(SIGUSR1, SIG_IGN); /* Don't KILL parent */ pid = FORK(); /* All ok, make a FORK */ if (pid == -1) { conres(); /* Reset the console. */ errhdlr("conect: Can't create keyboard FORK"); #ifndef MCS_FLAG printf("[Back at Local System]\n"); #else mcs_printf("[Back at Local System]\n"); #endif return(0); } io_retry = 0; if (pid) { active = 1; /* This FORK reads, sends keystrokes */ if (!setjmp(env_con)) { /* comm error in child process */ SIGNAL(SIGUSR1, conn_int); /* routine for child process exit */ while (active) { c = coninc(0) & cmask; /* Get character from keyboard */ if ((c & 0177) == escape) { /* Look for escape char */ c = coninc(0) & 0177; /* Got esc, get its arg */ doesc(c); /* And process it */ } else { /* Ordinary character */ if (ttoc(dopar(c)) > -1) { if (duplex) { /* Half duplex? */ conoc(c); /* Yes, also echo it. */ if (seslog) /* And maybe log it. */ /* code folded from here */ if (zchout(ZSFILE, c) < 0) seslog = 0; /* unfolding */ } } else { errhdlr("conect: Can't send character"); active = 0; } } } } /* Come here on death of child */ KILL(pid, 9); /* Done, KILL inferior FORK. */ WAIT((int *)0); /* Wait till gone. */ conres(); /* Reset the console. */ #ifndef MCS_FLAG printf("\r[Back at Local System]\n"); #else mcs_printf("\r[Back at Local System]\n"); #endif return(0); } else { /* Inferior reads, prints port input */ sleep(1); /* Wait for parent's handler setup */ while (1) { /* Fresh read, WAIT for a character */ if ((c = ttinc(0)) < 0) { /* Comm line hangup detected */ if (errno == 9999) /* this value set by myread() */ #ifndef MCS_FLAG printf("\r\nCommunications disconnect "); #else mcs_printf("\r\nCommunications disconnect "); #endif else if (io_retry++ < 3) { tthang(); continue; } errhdlr("conect: Can't get character"); KILL(parent_id, SIGUSR1); /* notify parent. */ PAUSE(); /* Wait to be KILLed by parent. */ } c &= cmask; /* Got a char, strip parity, etc */ conoc(c); /* Put it on the screen. */ if (seslog) zchout(ZSFILE, c); /* If logging, log it. */ while ((n = ttchk()) > 0) { /* Any more left in buffer? */ if (n > LBUFL) n = LBUFL; /* Get them all at once. */ if ((n = ttxin(n, lbuf)) > 0) { for (i = 0; i < n; i++) lbuf[i] &= cmask; /* Strip */ conxo(n, lbuf); /* Output */ if (seslog) zsoutx(ZSFILE, lbuf, n); /* Log */ } } } } } /* H C O N N E -- Give help message for connect. */ hconne() { int c; static char *hlpmsg[] = { "\r\n C to close the connection, or:", "\r\n 0 (zero) to send a null", "\r\n B to send a BREAK", "\r\n H to hangup and close connection", "\r\n S for status", "\r\n ? for help", "\r\n escape character twice to send the escape character.\r\n\r\n", "" }; conola(hlpmsg); /* Print the help message. */ conol("Command>"); /* Prompt for command. */ c = coninc(0) & 0177; /* Get character, strip any parity. */ conoc(c); /* Echo it. */ conoll(""); return(c); /* Return it. */ } /* C H S T R -- Make a printable string out of a character */ char * chstr(c) int c; { static char s[8]; char *cp = s; if (c < SP) { sprintf(cp, "CTRL-%c", ctl(c)); } else sprintf(cp, "'%c'\n", c); cp = s; return(cp); } /* D O E S C -- Process an escape character argument */ doesc(c) char c; { CHAR d; while (1) { if (c == escape) { /* Send escape character */ d = dopar(c); ttoc(d); return; } else if /* Or else look it up below. */ (isupper(c)) c = tolower(c); switch (c) { case 'c': /* Close connection */ case '\03': active = 0; conol("\r\n"); return; case 'b': /* Send a BREAK signal */ case '\02': ttsndb(); return; case 'h': /* Hangup */ case '\010': tthang(); active = 0; conol("\r\n"); return; case 's': /* Status */ conol("\r\nConnected thru "); conol(ttname); if (speed >= 0) { sprintf(temp, ", speed %d", speed); conol(temp); } sprintf(temp, ", %d bits", (cmask == 0177) ? 7 : 8); if (parity) { conol(", "); switch (parity) { case 'e': conol("even"); break; case 'o': conol("odd"); break; case 's': conol("space"); break; case 'm': conol("mark"); break; } conol(" parity"); } if (seslog) { conol(", logging to "); conol(sesfil); } conoll(""); return; case '?': /* Help */ c = hconne(); continue; case '0': /* Send a null */ c = '\0'; d = dopar(c); ttoc(d); return; case SP: /* Space, ignore */ return; default: /* Other */ conoc(BEL); return; /* Invalid esc arg, beep */ } } } <<< ckvdia.c >>> char *dialv = "Dial Command, V2.0(010) 10 May 90"; /* C K V D I A -- Dialing program for connection to remote system */ /********************************************************************** * * * IVS / MCS-Kermit REL 2 * * source code * * * * Change History: * * * * 1. Modify C-Kermit(4E) source code to * * produce new module for MCS/IVS-Kermit * * ORIGINAL RELEASE * * June 22, 1990 * * * * * ***********************************************************************/ /* Original author: Herm Fischer (HFISCHER@USC-ECLB). Contributed to Columbia University for inclusion in C-Kermit. Copyright (C) 1985, Herman Fischer, 16400 Ventura Blvd, Encino CA 91436. Permission is granted to any individual or institution to use, copy, or redistribute this software so long as it is not sold for profit, provided this copyright notice is retained. ------ This module should work under all versions of NCR-VRX. It calls externally defined system-depended functions for i/o, but depends upon the existence of various modem control functions. This module, and the supporting routines in the ckutio.c module, assume that the computer and modem properly utilize the following data communi- cations signals (that means one should prepare the modem to use, not circumvent, these signals): Data Terminal Ready: This signal is asserted by the computer when Kermit is about to ask the modem to dial a call, and is removed when Kermit wishes to have the modem hang up a call. The signal is asserted both while Kermit is asking the modem to dial a specific number, and after connection, while Kermit is in a data exchange mode. Carrier detect: This signal must be asserted by the modem when a carrier is detected from a remote modem on a communications circuit. It must be removed by the modem when the circuit disconnects or is hung up. (Carrier detect is ignored while Kermit is asking the modem to dial the call, because there is no consistant usage of this signal during the dialing phase among different modem manufacturers.) */ /* * Modifications: * * 21-Jul-85 Fixed failure returns hanging on no carrier signal * Requires tthang change too (ckutio.c revision) * -- Herm Fischer * * 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 modifying 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 restructured 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 * 16-Mar-87 Support for the ATT7300 UNIX PC internal modem was * added. * -- Richard E. Hill * * 14-Mar-88 Rewrite code for ATT7300 (here and in ckutio.c) * Avoids dial(3c) with it's LCK files, hangs up line * correctly, enables user interrupts and timeouts, * turns on/off the system getty() login procedure. * Correct Hayes command sequence at little. * Procedures: attdial, atthang, ongetty, offgetty. * Parts adapted from work of Richard E. Hill and * Kevin O'Gorman. * -- Joe R. Doupnik * * 13-Jan-89 Add IBM/Siemens/Rolm CBX dialing support. - F. da Cruz * */ /* * 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 sanity'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 characters, 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 MUCH 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 CANCEL 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 "ckcker.h" #include "ckucmd.h" #include "kermisc.h" #include /* Longjumps */ #ifdef MCS_FLAG #include "mcs.h" #endif extern int flow, local, mdmtyp, quiet, speed, parity, seslog, ttyfd; extern char ttname[], sesfil[], deblog; extern void errhdlr(); #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) */ char *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 of 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 #define n_CONCORD 12 #define n_ATTUPC 13 /* aka NCR-VRX PC and ATT7300 */ #define n_ROLM 14 /* Rolm CBX */ /* * Declare modem "variant" numbers for any of the above for 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 CERMETEK = /* 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 */ /* wait 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 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 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#", /* dial_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 the 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 */ "%", /* pause_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_prompt */ "ATD%s\r", /* dial_str, note: user can supply D or T */ 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 */ { 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 */ "", /* 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 = /* information 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 */ }; static MDMINF CONCORD = /* Info for Condor CDS 220 2400b modem */ { 35, /* dial_time */ ",", /* pause_chars */ 2, /* pause_time */ "\r\r", /* wake_str */ 20, /* wake_rate */ "CDS >", /* wake_prompt */ "", /* dmode_str */ "", /* dmode_prompt */ "", /* dial_str */ 0 /* dial_rate */ }; static MDMINF ATTUPC = /* dummy information for "ATT7300/NCR-VRX PC" internal modem */ { 20, /* dial_time */ "", /* pause_chars */ 0, /* pause_time */ "", /* wake_str */ 0, /* wake_rate */ "", /* wake_prompt */ "", /* dmode_str */ "", /* dmode_prompt */ "%s\r", /* dial_str */ 0 /* dial_rate */ }; static MDMINF ROLM = /* IBM (Siemens) / Rolm CBX */ { 60, /* dial_time */ "", /* pause_chars */ 0, /* pause_time */ "\r\r", /* wake_str */ 5, /* wake_rate */ "MODIFY?", /* wake_prompt */ "", /* dmode_str */ "", /* dmode_prompt */ "CALL %s\r", /* 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 (1). * * 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, &CONCORD, &ATTUPC, /* ATT7300 internal modem, jrd*/ &ROLM /* Rolm CBX, fdc */ }; /* * Declare modem names and associated numbers for command parsing, * and also for doing number-to-name translation. * * The entries MUST be in alphabetical order by modem name. */ struct keytab mdmtab[] = { "att7300", n_ATTUPC, 0, "cermetek", n_CERMETEK, 0, "concord", n_CONCORD, 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, "rolm", n_ROLM, 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 /* for ttpkt 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 char *F_reason[5] = { /* failure reasons for message */ "Unknown", "Timeout", "Interrupt", "Modem", "Initialize" }; static int tries = 0; #define LBUFL 100 static char lbuf[LBUFL]; static jmp_buf sjbuf; static SIGTYP (*savAlrm)(); /* for saving alarm handler */ static SIGTYP (*savInt)(); /* for saving 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 characters * ARE received, and in the order specified. */ static waitFor(s) char *s; { 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; if (deblog) debug(F110, "didWeGet", r, 0); if (deblog) debug(F110, " in", s, 0); for (i = strlen(s) - lr; i >= 0; i--) if ( s[i] == r[0] ) if ( !strncmp(s + i, r, lr) ) return( 1 ); return( 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 */ } /* C K D I A L -- Dial up the remote system */ ckdial(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 modes */ int mdmEcho = 0; /* assume modem does not echo */ int n, n1; char *pc; /* pointer to a character */ if (!mdmtyp) { #ifndef MCS_FLAG printf("Sorry, you must 'set modem' first\n"); #else mcs_printf("Sorry, you must 'set modem' first\n"); #endif return(-2); } if (!local) { #ifndef MCS_FLAG printf("Sorry, you must 'set line' first\n"); #else mcs_printf("Sorry, you must 'set line' first\n"); #endif return(-2); } if (speed < 0) { #ifndef MCS_FLAG printf("Sorry, you must 'set speed' first\n"); #else mcs_printf("Sorry, you must 'set speed' first\n"); #endif return(-2); } if (deblog) debug(F110, "dial", telnbr, 0); /* Carrier no-wait can be invalidated by ckutio fun and games, jrd */ if (ttopen(ttname, &local, mdmtyp) < 0) { /* Open, no carrier wait */ erp = errmsg; sprintf(erp, "ckdail: Can't open %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++) if (*i == *j) { waitct += pmdminf->pause_time; break; } #ifndef MCS_FLAG 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 (^C) to cancel the dialing.\r\n"); #else sprintf(print_str,"Dialing thru %s, speed %d, number %s.\r\n", ttname, speed, telnbr); mcs_printf(print_str); mcs_printf("The timeout for completing the call is %d seconds.\r\n", waitct); mcs_printf( "Type the interrupt character (^C) to cancel the dialing.\r\n"); #endif if (deblog) debug(F101, ttname, "", speed); if (deblog) debug(F101, "timeout", "", waitct); /* Hang up the modem (in case it wasn't "on hook") */ if ( tthang() < 0 ) { #ifndef MCS_FLAG printf("Sorry, Can't hang up tty line\n"); #else mcs_printf("Sorry, Can't hang up tty line\n"); #endif return(-2); } /* Condition console terminal and communication line */ /* place line into "clocal" dialing state */ if ( ttpkt(speed, DIALING, parity) < 0 ) { #ifndef MCS_FLAG printf("Sorry, Can't condition communication line\n"); #else mcs_printf("Sorry, Can't condition communication line\n"); #endif return(-2); } /* * Establish jump vector, or handle "failure" jumps. */ if ( n = setjmp(sjbuf) ) /* if a "failure jump" was taken... */ { ALARM ( 0 ); /* disable timeouts */ if ( n1 = setjmp(sjbuf) ) /* failure while handling failure */ { #ifndef MCS_FLAG printf ( "%s failure while handling failure.\r\n", F_reason[n1] ); #else mcs_printf ( "%s failure while handling failure.\r\n", F_reason[n1] ); #endif } else /* first (i.e., non-nested) failure */ { SIGNAL ( SIGALRM, dialtime ); /* be sure to catch signals */ if ( SIGNAL ( SIGINT, SIG_IGN ) != SIG_IGN ) SIGNAL ( SIGINT, dialint ); ALARM ( 10 ); /* be sure to exit this section */ ttclos (); /* hangup and close the line */ } switch ( n ) /* type of failure */ { case F_time: /* timed out */ { #ifndef MCS_FLAG printf("No connection made in the allotted time.\r\n"); #else mcs_printf("No connection made in the allotted time.\r\n"); #endif if (deblog) debug(F110, "dial", "timeout", 0); break; } case F_int: /* dialing interrupted */ { #ifndef MCS_FLAG printf ( "Dialing interrupted.\r\n" ); #else mcs_printf ( "Dialing interrupted.\r\n" ); #endif if (deblog) debug(F110, "dial", "interrupted", 0); break; } case F_modem: /* modem detected a failure */ { #ifndef MCS_FLAG printf ( "Failed (\"" ); #else mcs_printf ( "Failed (\"" ); #endif for ( pc = lbuf; *pc; pc++) if ( isprint(*pc) ) putchar(*pc); /* display printable reason */ #ifndef MCS_FLAG printf ( "\").\r\n" ); #else mcs_printf ( "\").\r\n" ); #endif if (deblog) debug(F110, "dial", lbuf, 0); break; } case F_minit: /* cannot initialize modem */ { #ifndef MCS_FLAG printf ( "Cannot initialize modem.\r\n" ); #else mcs_printf ( "Cannot initialize modem.\r\n" ); #endif if (deblog) debug(F110, "dial", "modem init", 0); break; } } reset(); /* reset alarms, etc. */ return ( -2 ); /* exit with failure code */ } /* * Set timer and interrupt handlers. */ ttflui(); /* flush input buffer if any */ 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 */ /* * 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) { 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 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 != 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); 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 into 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 */ if (deblog) debug(F110, "dialing", lbuf); ttolSlow(lbuf, pmdminf->dial_rate); /* send dialing string */ if (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 been 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 (deblog) debug(F110, "dial modem response", lbuf, 0); if (n) { /* if one or more characters present */ switch (augmdmtyp) { case n_CERMETEK: if (didWeGet(lbuf, "\016A")) { status = CONNECTED; ttolSlow("\016U 1\r", 200); /* make transparent*/ } break; case n_DF100: /* DF100 won't generate some of these */ case n_DF200: if (didWeGet(lbuf, "Attached")) status = CONNECTED; /* * The DF100 will respond with "Attached" even if DTR * and/or carrier are not present. Another reason to * (also) wait for carrier? */ if (didWeGet(lbuf, "Busy")) status = FAILED; if (didWeGet(lbuf, "Disconnected")) status = FAILED; if (didWeGet(lbuf, "Error")) status = FAILED; if (didWeGet(lbuf, "No answer")) status = FAILED; if (didWeGet(lbuf, "No dial tone")) status = FAILED; if (didWeGet(lbuf, "Speed:")) status = FAILED; /* * It appears that the "Speed:..." response comes after an * "Attached" response, so this is never seen. HOWEVER, * it would be very handy to detect this and temporarily * reset the speed, since it's a nuiscance otherwise. * If we wait for some more input from 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 (didWeGet(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_ROLM: if (didWeGet(lbuf, "CALLING")) status = 0; if (didWeGet(lbuf, "COMPLETE")) status = CONNECTED; if (didWeGet(lbuf, "FAILED")) status = FAILED; if (didWeGet(lbuf, "NOT AVAILABLE")) status = FAILED; if (didWeGet(lbuf, "LACKS PERMISSION")) status = FAILED; /* The Rolm CBX does not give a CALL COMPLETE indication when dialing an outpool number, but it does seem to return a long string of DELs at that point. */ if (didWeGet(lbuf, "\177\177\177")) status = CONNECTED; break; case n_VENTEL: if (didWeGet(lbuf, "ONLINE!")) status = CONNECTED; if (didWeGet(lbuf, "BUSY")) status = FAILED; if (didWeGet(lbuf, "DEAD PHONE")) status = FAILED; break; case n_CONCORD: if (didWeGet(lbuf, "INITIATING")) status = CONNECTED; if (didWeGet(lbuf, "BUSY")) status = FAILED; if (didWeGet(lbuf, "CALL FAILED")) 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 == '5') status = CONNECTED; break; case n_UNKNOWN: /** SHOULD WAIT FOR CARRIER OR TIMEOUT -- DS **/ break; } /* switch (augmdmtyp) */ } /* while status == 0 */ ALARM(0); /* turn off alarm on connecting */ if ( status != CONNECTED ) /* modem-detected failure */ longjmp( sjbuf, F_modem ); /* exit (with reason in lbuf) */ msleep(500); /* allow some time... */ ALARM(3); /* precaution in case of trouble */ if (deblog) debug(F110, "dial", "succeeded", 0); if (augmdmtyp != n_ROLM) /* Rolm has wierd modem signaling */ ttpkt(speed, CONNECT, parity); /* cancel dialing state ioctl */ reset (); /* reset alarms, etc. */ if ( !quiet ) #ifndef MCS_FLAG printf ( "Call completed.\07\r\n" ); #else mcs_printf ( "Call completed.\07\r\n" ); #endif return ( 0 ); /* return, and presumably connect */ } <<< ckvfi2.c >>> char *ckzv = "VRX/VE file support, 4E(038) 30 May 90"; /* C K U F I 2 -- Kermit file system support for VRX/VE systems */ /********************************************************************** * * * IVS / MCS-Kermit REL 2 * * source code * * * * Change History: * * * * 1. Modify C-Kermit(4E) source code to * * produce new module for MCS/IVS-Kermit * * ORIGINAL RELEASE * * June 22, 1990 * * * * * ***********************************************************************/ /* 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. */ /* ****************************************************************** DO NOT COMPILE THIS MODULE WITH #include THIS INCLUDE CAUSES A PERFORMANCE DEGRADATION PEG May 04, 1990 ********************************************************************* */ /* ********************************************************************* May 9, 1990 The following features were removed from the user display and disabled from use. add-linenum id-fields line-numbers renumber May 21, 1990 We added reset logic for errno == EMINR. This (?)error appends spaces characters to line end. Earlier releases we treated this as corruption. This release (V-KERMIT 2.01) we are treating it as normal for the VRX / VE file systems. I did not test for errno (EMINR) directly, I reset it when say an fputs terminates normally, and errno != EMINR. *********************************************************************/ /* Includes */ #include "ckcker.h" /* Kermit definitions */ #include "ckcdeb.h" /* Typedefs, debug formats, etc */ #include "vrx.h" /* VRX SPUR File definitions */ #include /* Character types */ #include /* Standard i/o */ #include /* String routines */ #include #include char *ckzsys = " NCR VRX/VE"; /* Functions (n is one of the 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 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. zclosf() -- 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. */ /* Some systems define these symbols in include files, others don't... */ #ifndef MAXNAMLEN #define MAXNAMLEN 14 /* If still not defined... */ #endif #define MAXWLD 500 #define SRCLNLEN 82 /* source or control string max line length March 8, 1990 */ #define OPEN 1 /* resetopen processing */ #define CLOSE 0 /* Declarations */ extern long time(); extern int debug(); extern int fncnv, send_id, recv_id, send_num, recv_num, recv_renum, keep; extern int server, recv_addnum, send_addnum, send_renum, deblog, binary; extern char *sys_errlist[]; extern int sys_nerr; extern void perror(); /* ^ extern int errno already declared in errno.h. | why they didnot declare these three are anyone's | guess. March 7, 1990 */ /* forward declarations */ void errhdlr(), resetopen(); int lenchk(); FILE *fp[ZNFILS] = { /* File pointers */ NULL, NULL, NULL, NULL, NULL, NULL, NULL }; static int list_count; /* # matches file names == 1 */ static int pid = 0; /* pid of child fork */ static int fcount; /* Number of files in wild group */ static char nambuf[MAXNAMLEN+2]; /* Buffer for a filename */ char *malloc(), *strcpy(); /* System functions */ static char *mtchs[MAXWLD], /* Matches found for filename */ **mtchptr; /* Pointer to current match */ static char file_type[9]; /* type of current file */ static int char_count; /* number of characters written */ static int spur_type; /* 1=NCRL 2=BASIC 3=FORTB 4=FORTI 5=FORTF 6=FORTV 7=NEAT/3 */ /* 8=NEAT/VS 9=NEAT/C 10=COBOL 11=COBOL/6 12=COBOL/7 13=COBOL/8 */ /* 14=HEADCS 15=PROC,16=PROCN,17=COBOL1,18=COBOL1/6 19=COBOL1/7 */ /* 20=COBOL1/8 21=COBOL4 */ static char language[7]; static int suffix; static int spur_eof = 0; static int linenumber; static char spur_data[400]; /* Area to hold packet data */ static char *nxtspur_data; static char pcard[100]; /* VRX Control String header record */ static int objopen = CLOSE; /* incomplete object files left open by aborted transfers */ static char fn_temp[10]; /* to DELETE incomplete files leftover from interuptions */ /* Z K S E L F -- Kill Self: log out own job, if possible. */ /* Note, should get current pid, but if your system doesn't have */ /* getppid(), then just kill(0,9)... */ zkself() { /* For "bye", but no guarantee! */ return(0); } /* Z O P E N I -- Open an existing file for input. */ zopeni(n, name) int n; char *name; { char buff[100]; if (deblog) { debug(F111, " zopeni", name, n); debug(F101, " fp", "", (int) fp[n]); } if (n == ZIFILE) resetopen(); if (access(name, 0) != 0) { errhdlr("zopeni"); fprintf(stderr,"file does not exist: %s\n",name); return(-1); } if ((suffix == BINARY || suffix == L_BINARY) && !(binary) && (n == ZIFILE)) { errhdlr("file mismatch see STDERR"); fprintf(stderr,"FILE TYPE is set to TEXT\n"); fprintf(stderr,"BINARY file type requested\n"); fprintf(stderr,"set file type to binary 8\n"); fprintf(stderr,"file transport will proceed\n"); return(-1); } if (chkfn(n) != 0) return(0); if (n == ZSYSFN || n == ZSTDIO) /* Input from a system function or stdio */ return(0); /* VRX invailid */ /* * VKERMIT code: * Special handling open required for object files on NCR's VRX/E */ if (*file_type == 'O' && n == ZIFILE) { /* note difference in return numbers for voopen and zopen */ if (voopeni(n, name) == 0) { /* OK */ fp[n] = (FILE *) 1; /* bogus fp to keep ckermit happy */ strcpy(fn_temp, name); objopen = OPEN; fprintf(stderr, "downloading to PC\n"); return(1); } else { errhdlr("zopeni vopeni bad outcome"); return(0); } } /* end VKERMIT code */ if (binary) fp[n] = fopen(name, "rb"); /* Real binary file. */ else fp[n] = fopen(name, "r"); /* Real file. */ if (fp[n] == NULL) { errhdlr("zopeni fp NULL see STDERR"); fprintf(stderr,"input file open failure: %s\n",name); if (binary) { fprintf(stderr,"check V-Kermit set up...an input text file\n"); fprintf(stderr,"can not be opened as a binary file\n"); fprintf(stderr,"text files include source, control\n"); fprintf(stderr,"string, and data file types...\n"); } } else { spur_data[0] = '\0'; nxtspur_data = &spur_data[0]; linenumber = INCREMENT; spur_eof = 0; strcpy(fn_temp, name); fprintf(stderr, "downloading to PC\n"); } if (deblog) debug(F111, " zopeni", name, (int) fp[n]); return((fp[n] != NULL) ? 1 : 0); } /* Z O P E N O -- Open a new file for output. */ zopeno(n, name) int n; char *name; { if (deblog) debug(F111, " zopeno", name, n); if (n == ZOFILE) resetopen(); if ((suffix == BINARY || suffix == L_BINARY) && !(binary) && (n == ZOFILE)) { errhdlr("file mismatch see STDERR"); fprintf(stderr,"FILE TYPE is set to TEXT\n"); fprintf(stderr,"BINARY file type requested\n"); fprintf(stderr,"set file type to binary 8\n"); fprintf(stderr,"file transport will proceed\n"); return(-1); } if (chkfn(n) != 0) return(0); if ((n == ZCTERM) || (n == ZSTDIO) || (n == ZSFILE)) /* Terminal or standard output */ /* or SESIONLOG */ return (0); /* Invalid for VRX */ /* * VKERMIT code: * Use special open for object files on NCR's VRX/E */ if (*file_type == 'O' && n == ZOFILE) { /* note difference in return numbers in voopen and zopen */ if (voopeno(n, name) == 0) { /* OK */ /* bogus file pointer to keep ckermit happy */ fp[n] = (FILE *) 1; strcpy(fn_temp, name); objopen = OPEN; fprintf(stderr, "uploading from PC\n"); return(1); } else { errhdlr("voopeno can't open"); fprintf(stderr, "Error opening upload file %s\n", name); return(0); } } /* end VKERMIT code */ /* FCL references for the log files April 5, 1990 */ switch (n) { char vtmp [45]; case ZTFILE: { sprintf(vtmp, "LOGTRANS(NAME=%s)", name); fp[n] = fopen(vtmp, "w"); } break; case ZDFILE: { sprintf(vtmp, "LOGDEBUG(NAME=%s)", name); fp[n] = fopen(vtmp, "w"); } break; case ZPFILE: { sprintf(vtmp, "LOGPACKET(NAME=%s)", name); fp[n] = fopen(vtmp, "w"); } break; default: if (binary && n == ZOFILE) fp[n] = fopen(name, "wb"); else fp[n] = fopen(name, "w"); if (fp[n] != NULL) { strcpy(fn_temp, name); fprintf(stderr, "uploading from PC\n"); } else { errhdlr("zopeno can't open"); fprintf(stderr, "Error opening: %s\n", name); return (0); } break; } if ((*file_type == 'C' || *file_type == 'S') && n == ZOFILE) { fputc(0, fp[n]); /* space count = 0 on pcard */ if (ferror(fp[n]) != 0 && errno != EMAXR && errno != EMINR) { errhdlr("zopeno PCARD"); fprintf(stderr, "write error: space count PCARD\n"); return(0); } else errno = 0; /* reset errno = EMAXR for pcard write no big deal happens half the time errno EMAXR is the message Maximum record length error (line truncated) April 12, 1990 */ if (zsoutl(n, pcard) == -1) return (0); char_count = 0; } spur_data[0] = '\0'; nxtspur_data = &spur_data[0]; linenumber = INCREMENT; if (deblog) debug(F101, " fp[n]", "", (int) fp[n]); return((fp[n] != NULL) ? 1 : 0); } /* Z C L O S E -- Close the given file. */ /* Returns 0 if arg out of range, 1 if successful, -1 if close failed. */ zclose(n) int n; { int x; if (chkfn(n) < 1) return(0); /* Check range of n */ /* * VKERMIT code: * Use special close for NCR's VRX/E object files */ if (*file_type == 'O' && (n == ZIFILE || n == ZOFILE)) { if (voclose(n) == 0) { fp[n] = NULL; /* March 7, 1990 */ objopen = CLOSE; return(1); } else { fp[n] = NULL; objopen = CLOSE; return(-1); } } /* end VKERMIT code */ if ((fp[n] != stdin) && (fp[n] != stdout)) x = fclose(fp[n]); fp[n] = NULL; if (x == EOF) { errhdlr("zclose"); fprintf(stderr,"Can't close file fclose returned: EOF\n"); } strcpy(fn_temp, "\0"); return((x == EOF) ? -1 : 1); } /* Z C H I N -- Get a character from the input file. */ /* Returns -1 if EOF, 0 otherwise with character returned in argument */ /* removes NULL and DEL characters in Control String and Source files */ zchin(n, c) int n; char *c; { int a; int i = 10; if (*file_type == 'S' || *file_type == 'C') { if (*nxtspur_data == '\0') { spur_data[0] = '\0'; switch (zsreci(n)) { case 0: spur_eof++; break; case 1: break; case -1: return(-1); } if ((spur_eof) && (strlen(spur_data) == 0)) return(-1); nxtspur_data = &spur_data[0]; } a = *nxtspur_data++; } else if (*file_type == 'O') { /* VKERMIT code for VRX/E object files */ /* vogetc returns -1 on end of file and also on error conditions after outputing an appropriate error message. */ if ((a = vogetc(n)) == -1) return(-1); } else { if (chkfn(n) < 1) /* check file address */ return(-1); a = getc(fp[n]); /* place character in a */ if (ferror(fp[n]) != 0) { errhdlr("zchin"); fprintf(stderr, "read error: zchin\n"); return(-1); } if (a == EOF) /* if EOF, return -1 */ return(-1); } *c = a & 0xFF; /* strip top bit */ 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); if ((*file_type == 'C' || *file_type == 'S') && n == ZOFILE) { char *sptr; sptr = s; if (sptr == NULL) return(0); while (*sptr++ != '\0') { if (*sptr == '\n') { if (putc('\377', fp[n]) == EOF) { errhdlr("zsout/377"); return((ferror(fp[n]) == 0) ? 0 : -1); } if (putc('\n', fp[n]) == EOF) { errhdlr("zsout NL"); return((ferror(fp[n]) == 0) ? 0 : -1); } if (putc('\000', fp[n]) == EOF) { errhdlr("zsout/000"); return((ferror(fp[n]) == 0) ? 0 : -1); } } else if (putc(*sptr, fp[n]) == EOF) { errhdlr("zsout/*sptr"); return((ferror(fp[n]) == 0) ? 0 : -1); } } } else if (fputs(s, fp[n]) == NULL) { errhdlr("zsout/fputs"); return((ferror(fp[n]) == 0) ? 0 : -1); } return(0); } /* Z S O U T L -- Write string to file, with line terminator, buffered */ zsoutl(n, s) int n; char *s; { char *ptr; if (chkfn(n) < 1) return(-1); if (lenchk(s, n)) { switch (spur_type) { case 9: case 11: errhdlr("zsoutl: writing ln > max len"); fprintf(stderr, "writing line > %d char\n", SRCLNLEN + 1); fprintf(stderr, "line length was %d\n", strlen(s)); fprintf(stderr, "%s\n", s); return(-1); default: errhdlr("zsoutl: writing ln > max len"); fprintf(stderr, "writing line > %d char\n", SRCLNLEN); fprintf(stderr, "line length was %d\n", strlen(s)); fprintf(stderr, "%s\n", s); return(-1); } } if (fputs(s, fp[n]) == NULL) { errhdlr("zsoutl/fputs"); return(-1); } if ((*file_type == 'C' || *file_type == 'S') && n == ZOFILE) { if (putc('\377', fp[n]) == EOF) { /* end sentinal character */ errhdlr("zsoutl/377"); return((ferror(fp[n]) == 0) ? 0 : -1); } if (putc('\n', fp[n]) == EOF) { errhdlr("zsoutl/LN CS"); return((ferror(fp[n]) == 0) ? 0 : -1); } } else if (putc('\n', fp[n]) == EOF) { errhdlr("zsoutl/LN"); return((ferror(fp[n]) == 0) ? 0 : -1); } return(0); } /* Z S O U T X -- Write x characters to file, unbuffered. */ zsoutx(n, s, x) int n, x; char *s; { int i; if (chkfn(n) < 1) return(-1); if ((i = write(fp[n]->_file, s, x)) == -1) { errhdlr("zsoutx"); return(-1); } else { return(i); } } /* 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; { int i; if (chkfn(n) < 1) return(-1); /* April 5, 1990 This switch statement is courtesy of the corruption in ZSFILE (sessionlog). We now check every character we write to verify it is a printable character. If SET FILE TYPE TEXT is set: (int binary == 0) we verify character for ZOFILE (output file) IF a LOG file we verify whether binary set or not. if a nonprintable character is encountered output to stderr return -1 */ switch (n) { char err_tmp[35]; case ZOFILE: if (binary) break; if (c == 0x1A) return(0); if (!(isprint(c) || isspace(c))) { sprintf(err_tmp, "zchout nonprint char: %X", c); errhdlr(err_tmp); return(-1); } break; case ZSFILE: case ZTFILE: case ZDFILE: case ZPFILE: if (!(isprint(c) || isspace(c))) { sprintf(err_tmp, "zchout: nonprint char: %X", c); errhdlr(err_tmp); fprintf(stderr, "error writing log file: %X\n", n); return(-1); } break; default: /* we should never execute this BUT if I do not put in in I'll be sorry later */ errhdlr("zchout dead code"); fprintf(stderr, "Executing in dead code area: %d\n", n); return(-1); } if (n == ZSFILE) /* Use unbuffered for session log */ return(write(fp[n]->_file, &c, 1)); else { /* Buffered for everything else */ if (*file_type == 'O' && n == ZOFILE) return(voputc(c, n)); else if ((*file_type == 'C' || *file_type == 'S') && n == ZOFILE) { if (c == '\n') { if (zsreco(n) == -1) return (-1); spur_data[0] = '\0'; nxtspur_data = &spur_data[0]; } else { *nxtspur_data++ = c; *nxtspur_data = '\0'; } return(0); } else { if (putc(c, fp[n]) == EOF) { /* If true, maybe an error */ errhdlr("ZCHOUT"); /* Check to make sure */ return((ferror(fp[n]) == 0) ? 0 : -1); } } } } /* 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; { switch (n) { case ZCTERM: case ZSTDIO: case ZIFILE: case ZOFILE: case ZDFILE: case ZTFILE: case ZPFILE: case ZSFILE: case ZSYSFN: break; default: if (deblog) debug(F101, "chkfn: file number out of range", "", n); errhdlr("chkfn"); 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 can'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. */ long zchki(name) char *name; { FILE * fptr; long length; if (access(name, 0) != 0) return(-1); if ((fptr = fopen(name, "r")) != NULL) { fseek(fptr, 0L, 2); length = ftell(fptr); close(fptr); return(length); } else return(-1); } /* Z C H K O -- Check if output file can be created */ /* Returns -1 if write permission for the file would be denied, 0 otherwise. */ zchko(name) char *name; { 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 VRX, this means: * truncating to 8/10 characters * changing lowercase to upper case * changing periods (.) to underscore (_) * If the filename contains an extension of the form: filename.extension * then the parameter "type" is set the file type. If there is no extension, * "type" is set to type DATA. * possible extensions are: * .OBJ - object files * .BIN - binary data file * .CS - Control String file * .PRO - Procedure file * .DAT - default data file * .NCR - NCRL SPUR file * .BAS - BASIC SPUR file * .FB - Fortran/B SPUR file * .FI - Fortran/I SPUR file * .FF - Fortran/F SPUR file * .FV - Fortran/V SPUR file * .N3 - NEAT/3 SPUR file * .NVS - NEAT/VS SPUR file * .NC - NEAT/C SPUR file * .CO - COBOL/0 SPUR file * .CO6 - COBOL/6 SPUR file * .CO7 - COBOL/7 SPUR file * .CO1 - COBOL1/0 SPUR file * .C16 - COBOL1/6 SPUR file * .C17 - COBOL1/7 SPUR file * .C18 - COBOL1/8 SPUR file * .CO4 - COBOL4 SPUR file * .D100 - fixed length data file with 100 byte records * .D1-100 - variable length data file with 1 to 100 byte records */ #define REC_SIZE(ptr) { for(fptr = ((ptr) + 1); *fptr != '\0'; fptr++) {\ if (*fptr == '-') *fptr = '/';\ else if (*fptr < '0' || *fptr > '9') break;\ }\ if (*fptr == '\0') record_sized++;\ } zrtol(name, name2) char *name, *name2; { char *ftype, *subtype, *fptr, *namep, *strrchr(); int suffix_len, i, n, max, record_sized = 0; long stamp; spur_type = 0; suffix = 0; *name2 = '\0'; if (deblog) debug(F100, "funct: zrtol ", "", 0); /* time stamp stderr output */ /* May 4, 1990 */ stamp = time((long *) 0); fprintf(stderr, "\n%s", ctime(&stamp)); fprintf(stderr, "name = <%s>\n", name); if ((ftype = strrchr(name, '.')) == NULL) { strcpy(file_type, "DATAFILE"); /* peg 0190 */ max = 10; } else { suffix_len = strlen(++ftype); for (i = 0; i < 4; i++) { if (i >= suffix_len) n = 0; else n = ftype[i]; suffix = (suffix << 8) | n; } switch (suffix) { case L_OBJECT: case OBJECT: strcpy(file_type, "OBJFILE"); /* peg 0190 */ max = 8; *(ftype - 1) = '\0'; break; case L_BINARY: case BINARY: strcpy(file_type, "DATAFILE"); /* peg 0190 */ max = 10; *(ftype - 1) = '\0'; break; case L_DATA: case DATA: strcpy(file_type, "DATAFILE"); max = 10; *(ftype - 1) = '\0'; break; case L_NCRL: case NCRL: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 1; strcpy(language, "NCRL "); max = 8; *(ftype - 1) = '\0'; break; case L_BASIC: case BASIC: strcmp(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 2; strcpy(language, "BASIC "); max = 8; *(ftype - 1) = '\0'; break; case L_FORTB: case FORTB: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 3; strcpy(language, "FORT/B"); max = 8; *(ftype - 1) = '\0'; break; case L_FORTI: case FORTI: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 4; strcpy(language, "FORT/I"); max = 8; *(ftype - 1) = '\0'; break; case L_FORTF: case FORTF: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 5; strcpy(language, "FORT/F"); max = 8; *(ftype - 1) = '\0'; break; case L_FORTV: case FORTV: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 6; strcpy(language, "FORT/V"); max = 8; *(ftype - 1) = '\0'; break; case L_NEAT3: case NEAT3: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 7; strcpy(language, "NEAT/3"); max = 8; *(ftype - 1) = '\0'; break; case L_NEATVS: case NEATVS: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 8; strcpy(language, "NEATVS"); max = 8; *(ftype - 1) = '\0'; break; case L_NEATC: case NEATC: strcpy(file_type, "SRCFILE"); spur_type = 9; strcpy(language, "NEAT/C"); max = 8; *(ftype - 1) = '\0'; break; case L_COBOL: case COBOL: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 10; strcpy(language, "COBOL "); max = 8; *(ftype - 1) = '\0'; break; case L_COBOL6: case COBOL6: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 11; strcpy(language, "COBOL "); max = 8; *(ftype - 1) = '\0'; break; case L_COBOL7: case COBOL7: strcmp(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 12; strcpy(language, "COBOL "); max = 8; *(ftype - 1) = '\0'; break; case L_COBOL8: case COBOL8: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 13; strcpy(language, "COBOL "); max = 8; *(ftype - 1) = '\0'; break; case L_CS: case CS: strcpy(file_type, "CSFILE"); /* peg 0190 */ spur_type = 14; strcpy(language, "HEADCS"); max = 8; *(ftype - 1) = '\0'; break; case L_PROC: case PROC: strcpy(file_type, "CSFILE"); /* peg 0190 */ spur_type = 15; strcpy(language, "HEADCS"); max = 8; *(ftype - 1) = '\0'; break; case L_PROCN: case PROCN: strcmp(file_type, "CSFILE"); /* peg 0190 */ spur_type = 16; strcpy(language, "HEADCS"); max = 8; *(ftype - 1) = '\0'; break; case L_COBOL1: case COBOL1: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 17; strcpy(language, "COBOL1"); max = 8; *(ftype - 1) = '\0'; break; case L_COBOL16: case COBOL16: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 18; strcpy(language, "COBOL1"); max = 8; *(ftype - 1) = '\0'; break; case L_COBOL17: case COBOL17: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 19; strcpy(language, "COBOL1"); max = 8; *(ftype - 1) = '\0'; break; case L_COBOL18: case COBOL18: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 20; strcpy(language, "COBOL1"); max = 8; *(ftype - 1) = '\0'; break; case L_COBOL4: case COBOL4: strcpy(file_type, "SRCFILE"); /* peg 0190 */ spur_type = 21; strcpy(language, "COBOL4"); max = 8; *(ftype - 1) = '\0'; break; default: if (*ftype == 'B' || *ftype == 'b') { suffix = BINARY; if (*(ftype + 1) != '\0') REC_SIZE(ftype); if (record_sized) { *(ftype) = '\0'; } } if ((*ftype == 'd') || (*ftype == 'D')) { if (*(ftype + 1) != '\0') REC_SIZE(ftype); if (record_sized) *(ftype) = '\0'; } strcpy(file_type, "DATAFILE"); max = 10; break; } } /* convert periods to underscores, lowercase to uppercase */ namep = name; for (i = 0; *namep != '\0', i < max; namep++, i++) { if (*namep == '.') *namep = '_'; if (*namep == '~') *namep = 'X'; if (*namep == '$') *namep = '_'; else if (islower(*namep) && fncnv) toupper(*namep); } *namep = '\0'; if (record_sized) { /* first the recordsize is truncated now the displayed name contains additional underscores, this fix truncates everything past the FINAL underscore April 13, 1990 */ char *s_tmp; s_tmp = strrchr(name, '_'); if (s_tmp != NULL) *s_tmp = '\0'; sprintf(name2, "%s(NAME=%s,RECORDSIZE=%s)", file_type, name, (ftype + 1)); } else sprintf(name2, "%s(NAME=%s)", file_type, name); if (*file_type == 'S' || *file_type == 'C') zpcrd(name); if (spur_type != 0) fprintf(stderr, "final name2 = <%s> spur_type=%d\n", name2, spur_type); else fprintf(stderr, "final name2 = <%s>\n", name2); if (deblog) debug(F110, "zrtol:", 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; if (deblog) { debug(F100, "funct: zltor ", "", 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 (islower(*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 == '.') *pp++ = '_'; */ /* & extra dots */ else if (*cp == '$') *pp++ = '_'; else *pp++ = *cp; } *pp = '\0'; /* Tie it off. */ cp = name2; /* If nothing before dot, */ if (*work == '.') *cp++ = 'X'; /* insert 'X' */ strcpy(cp, work); if (deblog) debug(F110, "zltor", name2, 0); } /* Z C H D I R -- Change directory */ zchdir(dirnam) char *dirnam; { /* not implemented */ } /* Z H O M E -- Return pointer to user's home directory */ char * zhome() { return("home"); } /* Z G T D I R -- Return pointer to user's current directory */ char * zgtdir() { return("(directory unknown)"); } /* Z X C M D -- Run a system command so its output can be read like a file */ zxcmd(comand) char *comand; { return(0); /* not implemented */ } /* Z C L O S F - wait for the child fork to terminate and close the pipe. */ zclosf() { int wstat; if (deblog) debug(F100, "funct: zclosf ", "", 0); fclose(fp[ZIFILE]); fp[ZIFILE] = fp[ZSYSFN] = NULL; while ((wstat = WAIT(0)) != pid && wstat != -1) ; return(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 returned by the next znext() call. */ zxpand(fn) char *fn; { mtchs[0] = (char *) malloc(sizeof(char)*strlen(fn)); strcpy(mtchs[0], fn); list_count = 1; return(1); } /* 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; { int temp; temp = list_count; if (list_count) list_count = 0; strcpy(fn, mtchs[0]); return(temp); } /* Z N E W N -- Make a new name for the given file */ znewn(fn, s) char *fn, **s; { } /* Directory Functions for Unix, written by Jeff Damens, CUCCA, 1984. */ /* * The path structure is used to represent the name to match. * Each slash-separated segment of the name is kept in one * such structure, and they are linked together, to make * traversing the name easier. */ /* * 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 path * splitpath(p) char *p; { } /* * 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 means 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) /* VRX version, no expansion of file names */ char *pat, *resarry[]; int len; { } /* 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; otherwise, 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. * * Input: 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; { } /* * addresult: * 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; { } iswild(str) char *str; { char c; if (deblog) debug(F100, "funct: iswild ", "", 0); 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 true 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; if (deblog) debug(F100, "funct: matck ", "", 0); while (1) { for (; *pattern == *string; pattern++, string++) /* skip first */ if (*string == '\0') return(1); /* end of strings, succeed */ if (*string != '\0' && *pattern == '?') { pattern++; /* '?', 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 */ } } /* Z P C R D -- Make a pcard for a CSFILE or a SRCFILE */ zpcrd(name) char *name; { int i; pcard[0] = '\0'; strcat(pcard, "000000"); if ((spur_type == 14) || (spur_type == 15) || (spur_type == 16)) { if (!recv_num && (spur_type == 16)) spur_type = 15; strcat(pcard, "P"); strcat(pcard, name); for (i = 0; i < (10 - strlen(name)); i++) strcat(pcard, " "); strcat(pcard, language); strcat(pcard, " "); switch (spur_type) { case 14: strcat(pcard, " "); break; case 15: strcat(pcard, "PROC-01"); break; case 16: strcat(pcard, "PROC-07"); break; } strcat(pcard, " "); } else { strcat(pcard, " "); strcat(pcard, "P"); strcat(pcard, name); for (i = 0; i < (10 - strlen(name)); i++) strcat(pcard, " "); strcat(pcard, language); strcat(pcard, " "); switch (spur_type) { case 10: strcat(pcard, "0"); break; case 11: strcat(pcard, "6"); break; case 12: strcat(pcard, "7"); break; default: strcat(pcard, " "); break; } strcat(pcard, " "); } } /* Z S R E C I -- Gather SPUR records for input */ zsreci(n) int n; { char idfield[MAX_FIELD+2]; char line[LINE_LEN]; char tail[TAIL_LEN]; char oldnum[10]; int id_start = spur_info[MAX_SPURTYPE*ID_START + spur_type -1]; int id_len = spur_info[MAX_SPURTYPE*ID_LEN + spur_type -1]; int rec_len = spur_info[MAX_SPURTYPE*REC_LEN + spur_type -1]; int num_field_len = spur_info[MAX_SPURTYPE*NUM_FIELD_LEN + spur_type -1]; int spaces; int length; int i; if (deblog) debug(F111, "zsreci: ", "n", n); /**************************************************************** * Initialize the array 'spur_data' and begin to add to this * * array the "V-Kermit-prepared" records from the file fp[n]. * ****************************************************************/ spur_data[0] = '\0'; while (strlen(spur_data) < 315) { if ((spaces = fgetc(fp[n])) == EOF) { if (deblog) fprintf(stderr, "zsreci: fgetc == EOF\n"); return((ferror(fp[n]) == 0) ? 0 : -1); } if (fgets(line, LINE_LEN, fp[n]) == NULL) { errhdlr("zsreci / NULL"); fprintf(stderr, "zsreci: fgets == NULL\n"); return(-1); } if (lenchk(line, n)) { switch (spur_type) { case 9: case 11: { errhdlr("zsreci"); fprintf(stderr, "reading line > %d char\n", SRCLNLEN+1); fprintf(stderr, "line length was %d\n", strlen(line)); fprintf(stderr, "%s\n", line); return(-1); } default: { errhdlr("zsreci"); fprintf(stderr, "reading line > %d char\n", SRCLNLEN); fprintf(stderr, "line length was %d\n", strlen(line)); fprintf(stderr, "%s\n", line); return(-1); } } } if (strncmp(line, "000000", 6) == 0) { if (deblog) fprintf(stderr, "zsreci: Throwing away Pcard.\n"); /* throw away the Pcard */ continue; } /**************************************************************** * If we get this far, a record was successfully read from the * * file pointer fp[n]. * ****************************************************************/ length = rec_len - spaces; if (deblog) { debug(F111, " ", "record length", length); debug(F111, " ", "id start", id_start); debug(F111, " ", "id len", id_len); } /**************************************************************** * If the file has an id field (i.e. id_start != 0), then * * copy it into 'idfield' and let 'tail' point to the rest * * of the record after the id field. If there is no id field, * * let 'tail' point at the remaining record after the line * * number field. * ****************************************************************/ if (id_start) { strncpy(idfield, &line[id_start], id_len); strcpy(tail, &line[id_start+id_len]); if (deblog) debug(F111, " id field", idfield, 0); } else { strcpy(tail, &line[HEAD_END]); } if (deblog) debug(F110, " tail", tail, 0); /**************************************************************** * If !send_addnum && ...... * * send_num && !send_renum - use the first six * * characters of the * * record. * * send_num && send_renum - replace the first six * * characters of the * * record with a multi- * * ple of INCREMENT. * * !send_num - do not use the first * * six characters of the * * record. * * send_addnum - Add a multiple * ****************************************************************/ if (!send_addnum) { if (send_num) { if (send_renum) { sprintf(line, "%0.*d", num_field_len, linenumber); if (num_field_len == 5) strcat(line, " "); linenumber += INCREMENT; } else { line[HEAD_END] = '\0'; } } else { line[0] = '\0'; } } else { strncpy(oldnum, line, HEAD_END); sprintf(line, "%0.*d", num_field_len, linenumber); if (num_field_len == 5) strcat(line, " "); linenumber += INCREMENT; strncat(line, oldnum, HEAD_END); length += 6; } if (deblog) debug(F110, " line number", line, 0); /**************************************************************** * Add the data to the line. * ****************************************************************/ strcat(line, tail); /**************************************************************** * If sending the id field, pad the line with spaces and add * * the id field to the end of the line. * ****************************************************************/ if (send_id) { for (i = length - 6 + ((send_addnum || send_num) *6); i < (80 - id_len); i++) line[i] = ' '; line[80-id_len] = '\0'; idfield[id_len] = '\n'; idfield[id_len+1] = '\0'; strcat(line, idfield); } else { line[length-6+((send_addnum || send_num)*6)] = '\n'; line[length-6+((send_addnum || send_num)*6)+1] = 0; } strcat(spur_data, line); } return(1); } /* Z S R E C O -- Prepare data to output into SPUR records */ zsreco(n) int n; { int id_start = spur_info[MAX_SPURTYPE*ID_START + spur_type - 1]; int id_len = spur_info[MAX_SPURTYPE*ID_LEN + spur_type - 1]; int num_field_len = spur_info[MAX_SPURTYPE*NUM_FIELD_LEN+spur_type-1]; char idfield[10]; char linefield[8]; char record[100]; char data[DATA_LEN]; char temp[DATA_LEN]; int number_len, i, len_char, nulls, data_len = strlen(spur_data); /**************************************************************** * Get id field at the end of the line if there is one. * * If the spur_type has an id field and there are no characters * * in columns (80 - id_len) to 80, the new id field will be * * spaces. If recv_id = 0, the new id field will be spaces. * ****************************************************************/ if (deblog) { debug(F111, "zsreco: ", "n", n); debug(F111, " ", "data length", data_len); debug(F111, " ", "id start", id_start); debug(F111, " ", "id len", id_len); } if (id_start) { if ((data_len > 72) && recv_id) { strncpy(idfield, &spur_data[80-id_len], id_len); if ((i = strlen(idfield)) < id_len) { for (; i < id_len; i++) idfield[i] = ' '; } idfield[id_len] = '\0'; } else { for (i = 0; i < id_len; i++) idfield[i] = ' '; idfield[id_len] = '\0'; } spur_data[80-id_len] = '\0'; if (data_len > 6) strncpy(data, &spur_data[NUM_LEN], 80); else data[0] = '\0'; } else { idfield[0] = '\0'; if (data_len > 6) strcpy(data, &spur_data[NUM_LEN]); else data[0] = '\0'; } if (deblog) debug(F110, " id field", idfield, 0); /********************************************************************** * If => !recv_addnum && ..... * * recv_num && !recv_renum - Keep the original first six * * columns from the incoming * * record. * * recv_num && recv_renum - Replace the first six columns * * with linenumber and increment * * by the constant INCREMENT. * * !recv_num - Replace the first six columns * * with spaces. (ASCII 0x20) * * recv_addnum - Insert new line numbers at * * the beginning of every new * **********************************************************************/ linefield[0] = '\0'; if (recv_num && !recv_addnum) { if (recv_renum) { sprintf(linefield, "%0.*d", num_field_len, linenumber); if (num_field_len == 5) strcat(linefield, " "); linenumber += INCREMENT; } else { strncpy(linefield, spur_data, NUM_LEN); if ((i = strlen(linefield)) < 6) { for (; i < 6; i++) strcat(linefield, " "); } linefield[NUM_LEN] = 0; } } else if (recv_addnum) { sprintf(linefield, "%0.*d", num_field_len, linenumber); if (num_field_len == 5) strcat(linefield, " "); linenumber += INCREMENT; strncpy(temp, spur_data, NUM_LEN); temp[NUM_LEN] = '\0'; strcat(temp, data); strcpy(data, temp); } if (deblog) { debug(F110, " line number", linefield, 0); debug(F110, " data", data, 0); } /********************************************************************** * peel off the spaces at the end of the remaining data unless we * * have a Control String or a Procedure file (spur_type=14,15,16) * **********************************************************************/ if ((spur_type == 14) || (spur_type == 15) || (spur_type == 16)) { i = strlen(data); for (; i < (80 - (6 * recv_num)); i++) data[i] = ' '; data[i] = '\0'; len_char = 0; } else { i = strlen(data); while (i && (data[i-1] == ' ')) i--; data[i] = '\0'; if ((!recv_num) && ((i = strlen(data)) < 6)) { for (; i < 6; i++) strcat(data, " "); } if (recv_num || recv_addnum) number_len = 6; else number_len = 0; len_char = 80 - id_len - strlen(data) - number_len; if (deblog) fprintf(stderr, "zsreco: len_char = %d.\n", len_char); /**************************************************************** * The following must be done since we can not output the ASCII * * characters 0x09 and 0x0a * ****************************************************************/ if (len_char == 9) { if (deblog) fprintf(stderr, "zsreco: app 1 (0x20) on rec end.\n"); strcat(data, " "); len_char = 8; if (deblog) fprintf(stderr, "zsreco: len_char is now %d.\n", len_char); } if (len_char == 10) { if (deblog) fprintf(stderr, "zsreco: app 2 (0x20) on rec end.\n"); strcat(data, " "); len_char = 8; if (deblog) fprintf(stderr, "zsreco: len_char is now %d.\n", len_char); } } /* output the space character to column 1 */ fputc(len_char, fp[n]); if (ferror(fp[n]) != 0) { errhdlr("zsrceo"); fprintf(stderr, "write error: zsrceo len_char\n"); return(-1); } /* build the record and output it */ record[0] = '\0'; if (recv_num || recv_addnum) strcat(record, linefield); else strncat(record, data, NUM_LEN); switch (spur_type) { case 9: case 11: nulls = 2; break; case 12: nulls = 1; break; default: nulls = 0; } for (i = 0; i < nulls; i++) strcat(record, " "); strcat(record, idfield); if (recv_num || recv_addnum) strcat(record, data); else strcat(record, &data[NUM_LEN]); return(zsoutl(n, record)); } /* E R R H D L R - errhdlr for all unpleasant outcomes PEG May 14, 1990 */ void errhdlr(wherefrm) char *wherefrm; { char s[90]; long errclk; int geterr = errno; /* we grab the error number due the timestamp fprintf setting errno to EMINR May 22, 1990 */ /* time stamp stderr output */ /* May 4, 1990 */ errclk = time((long *) 0); fprintf(stderr, "\n%s", ctime(&errclk)); /* we do not want to print anymore EMINR messages */ if ((geterr) && (geterr != EMINR)) { sprintf(s, "%s: %s", wherefrm, sys_errlist[geterr]); perror(wherefrm); if (!server) screen(SCR_EM, 0, 0l, s); else errpkt(s); errno = 0; return; } else { sprintf(s, "Error occured: %s", wherefrm); fprintf(stderr, "%s\n", s); if (!server) screen(SCR_EM, 0, 0l, s); else errpkt(s); errno = 0; return; } } /* errhdlr end */ /* L E N C H K - lenchk: checks spur records after read or before right to verify that they do not exceed maximum values defined by SRCLNLEN */ int lenchk(s, n) char *s; /* string ptr for examing line length */ int n; /* file number... index into fp[] */ { if ((n != ZIFILE && n != ZOFILE) || binary) return(0); if ((*file_type == 'C') || (*file_type == 'S')) { switch (spur_type) { case 9: case 11: { if (strlen(s) > SRCLNLEN + 1) return (-1); else return(0); } default: { if (strlen(s) > SRCLNLEN) return (-1); else return(0); } } } else return(0); } /* end lenchk */ /* R E S E T O P E N resetopen: closes ZOFILE or ZIFILE left open from previous aborted file transfers May 30, 1990 */ void resetopen() { int n; if ((fp[ZOFILE] == NULL) && (fp[ZIFILE] == NULL)) return; if (fp[ZOFILE] != NULL) n = ZOFILE; else n = ZIFILE; if (objopen) { /* March 12, 1990 */ if (voclose(n) == 0) { if ((!keep) && (n == ZOFILE)) { if (unlink(fn_temp) != 0) { errhdlr("resetopen UNLINK"); fprintf(stderr, "unlink failed %s\n", fn_temp); } } } objopen = CLOSE; } else { if (fclose(fp[n]) == EOF) { errhdlr("resetopen fclose error"); fprintf(stderr,"file name: %s\n",fn_temp); } if ((!keep) && (n == ZOFILE)) if (unlink(fn_temp) != 0) { errhdlr("resetopen UNLINK"); fprintf(stderr, "unlink failed %s\n", fn_temp); } } strcpy(fn_temp, "\0"); fp[n] = NULL; return; } <<< ckvfio.c >>> /* C K V F I O object module transfer */ /********************************************************************** * * * IVS / MCS-Kermit REL 2 * * source code * * * * Change History: * * * * 1. Modify C-Kermit(4E) source code to * * produce new module for MCS/IVS-Kermit * * ORIGINAL RELEASE * * June 22, 1990 * * * * * ***********************************************************************/ /* update May 10, 1990 PEG Modified error handling to reflect changes to other modules to use errhdlr() update May 23, 1990 OBJECT FILE message flawed PEG VKOFIO - Object file I/O for VKERMIT. This module interfaces to and does buffering for VRX/E object files. In order for object file transfer to work, the file type must be set to binary for both sides of the kermit file transfer. No translation of CR or LF can be allowed. Vkermit can only receive and create object files which have been sent previously by vkermit. It cannot handle object files transferred to the remote system by some other means. Nor is the format of a vkermit sent object file suitable for ANY use other than being transferred back to a VRX system by vkermit. FCL is necessary to properly open the object file. The default file reference name is OBJFILE. The VRX file type must be set to object and the record size must be set to 1/490. The following routines are to be called by the ckufio module when it detects that a VRX object file is being transported. voopeni - to open an object file for input (download) Called by zopeni. voopeno - to open an object file for output (upload) Called by zopeno. vogetc - to get the next character from a VRX object file. Called by zchin. voputc - to put the next character to a vrx object. Called by zchout. voclose - to close a VRX object file. Called by zclose. This module contains data structures to buffer the characters and keep track of the object file(s) currently open. In this implementation, there is only one VRX object file open at a time. Since VRX object files are variable length, a two byte VLI is prepended to each data record. This module creates the VLI for downloading and interprets the VLI for uploading. The rest of kermit does not even know these VLIs are there and treats them as data. Since binary file type transfer is being used, the non-ASCII nature of these VLIs is unimportant. Using VLIs as part of the data stream is the only way to recreate the object file on VRX. Object files must be written with variable length records. When an object file is written, the VLI is stripped off of the buffer and the rest of the buffer is written as the record. The implicit length of the string determines the record size and VRX file management takes care of the internals necessary for variable length records. Although buffering is done by this module, the actual I/O's are done by a separate module written in NCRL which uses NCRL IO. */ #include #include "ckcker.h" /* March 2, 1990 */ #include /* * Constants used by this module */ /* * Errors returned by NCRL I/O service routines */ #define NIOOK 0 #define NIOBAD 1 #define NIOEOF 2 /* * Sizes of various structures and strings */ #define LEGRECSIZ 200 /* The size of the NCRL legible type */ /* Actual size is probably less - e.g. 134 bytes on 4-85, but the size is not guaranteed to remain constant from release to release. */ #define MAXOBJDAT 490 /* Max size of object record data */ #define REFSIZ 31 /* Standard size for VRX file reference */ #define OBJREFSIZ 7 /* Size of default reference name */ #define VLISIZE 2 /* The size of the added VLIs */ #define MAXOBJREC MAXOBJDAT+VLISIZE /* The maximum size of the buffer used for objects including the vli * / /* dummy type for access() */ #define file_EXIST 0 /* * Types declared for this module */ /* legible - This is an NCRL type used for I/O. */ typedef char legible[LEGRECSIZ]; /* objrec - This type allows access of the buffer as a string and also direct reference of the VLI and data portions of the buffer. The NCRL IO routines actually fill in the VLI and data, but this module must have access of the number of bytes in order to determine when a new record must be read or written. */ typedef union objrec { char buffer[MAXOBJREC]; struct { short vli; /* does not include size of the vli itself */ /* must be on a two byte boundary */ char data[MAXOBJREC - VLISIZE]; } vlianddata; }; /* * This series of types is declared so that variable length strings can be passed to an NCRL routine. A NCRL string consists of a four byte length indicator and a pointer to the text of the string. The C strings passed as parameters must be translated into this form in order for NCRL IO to work properly. NCRLptr - a definition of NCRL's 3 byte pointers. ptr_param - a definition of the 4 byte pointer format of NCRL pointers used when passing pointers as parameters (the first byte is ignored as serves only to align the pointer). c2vrx_ptr - a union constructs that allows casting of integers into the four byte pointer format. ncrl_string - a definition of NCRL variable strings as a four byte length and a four byte pointer. */ struct NCRLptr { char byte1; char byte2; char byte3; }; struct ptr_param { char zero_fill; struct NCRLptr ptr; }; union c2vrx_ptr { int *int_ptr; struct ptr_param ncr_ptr; }; struct ncrl_string { int len; union c2vrx_ptr ptr; }; /* * Global variables - * These variables are directly referenced only be this module but * must retain their values until changed (if at all) by this module. */ /* objref - The default reference name. A different reference name can be passed in as part of the name parameter of the open routines. An FCL file reference must be used on the invocation of vkermit in order to open the file correctly. */ char objref[OBJREFSIZ+1] = "OBJFILE"; /* The default reference name */ union objrec buf; /* The buffer used for object IO */ struct ncrl_string buffer_string; /* The NCRL string used to pass the buffer to the NCRL IO routines (see discussion under types). */ int nBufSiz, nBufNdx; /* Current buffer size (including VLI) and current char in buffer being accessed */ legible objf; /* The object file definition structure The legible construct is filled in by the NCRL OPEN and is then used to refer to the file for all subsequent IO operations. */ /* There is only ONE object file open at a time */ /* * Declaration of all procedures in the NCRL IO service module. * This module must be compiled with COPT='-Xv' to avoid * adding an additional return parameter to these void declared * procedures. */ extern void OBJOPENI(); extern void OBJOPENO(); extern void OBJCLOSE(); extern void OBJRECIN(); /* Reads an entire object record, prepending data with a VLI. */ extern void OBJRECOUT(); /* Writes one variable record */ extern int errhdlr(); extern int access(); int ERRCELL; /* set in VKNCRLIO by bad vrxoutcome */ /* forward procedure declaration */ setupvbuf(); voopeni(n, in_name) int n; /* file number*/ char *in_name; /* voopeni - prepare for open of VRX object file by NCRL I/O refandname may be of the form "fileref(NAME=filename)" or may just contain the file name. If the complex form is present, it must be broken into its components for usage by NCRL I/O. The n parameter is the file number and is ignored since only one object file is opened at a time. Return values: 0 if open successful -1 if unsuccessful */ { char result; struct ncrl_string ncrl_name, ncrl_refname; char name[REFSIZ+1]; char refname[REFSIZ+1]; char refandname[REFSIZ+4]; char *temp; int i; /* before we go through several levels of code, parsing the final file name, etc, etc. Let's save some processing time and some nasty errors by verifying the file is present. In order for this to work the FCL reference OBJFILE must exist. Otherwise we maybe back at square one. PEG March 7, 1990 */ if (in_name != NULL) strcpy(refandname,in_name); else return(-1); if ((i = access(refandname, file_EXIST)) != 0) return(-1); if (in_name != NULL) strcpy(refandname,in_name); else return(-1); /* determine type of format of refandname and parse it */ if ((temp = strrchr(refandname, ')')) != NULL) { /* complex form */ /* eliminate final parenthesis */ temp[0] = '\0'; if ((temp = strrchr(refandname, '=')) != NULL) { /* now temp points just before file name */ temp++; strcpy(name, temp); /* continue to parse for refname */ if ((temp = strchr(refandname, '(')) != NULL) { /* eliminate first parenthesis - what is left is refname */ temp[0] = '\0'; strcpy(refname, refandname); } else { /* error! */ errhdlr("voopeni"); fprintf(stderr,"voopeni: name format1 error: %s", refandname); return(-1); } } else { /* error ! */ errhdlr("voopeni"); fprintf(stderr, "name format2 error: %s", refandname); return(-1); } } else { /* must be in simple format - use parameter as filename and use default refname */ strcpy(name, refandname); strcpy(refname, objref); } ncrl_name.len = strlen(name); ncrl_name.ptr.int_ptr = (int *) name; ncrl_refname.len = strlen(refname); ncrl_refname.ptr.int_ptr = (int *) refname; OBJOPENI(&ncrl_name, &ncrl_refname, objf, &result); if (result != NIOOK) { /* When a lousy outcome is returned from VKNCRLIO we output an error message PEG March 6, 1990 */ errhdlr("voopeni"); fprintf(stderr, "objfile (i)open failure outcome: %d\n", ERRCELL); return(-1); } setupvbuf(); return(0); } voopeno(n, in_name) int n; /* file number*/ char *in_name; /* voopeno - prepare for open of VRX object file by NCRL I/O refandname may be of the form "fileref(NAME=filename)" or may just contain the file name. If the complex form is present, it must be broken into its components for usage by NCRL I/O. The n parameter is the file number and is ignored since file numbers are not used when files are opend by NCRL IO. Return values: 0 if open successful -1 if unsuccessful */ { char result; struct ncrl_string ncrl_name, ncrl_refname; char name[REFSIZ+1]; char refname[REFSIZ+1]; char refandname[REFSIZ+1]; char *temp; if (in_name != NULL) strcpy(refandname,in_name); else return(-1); /* determine type of format of refandname and parse it */ if ((temp = strrchr(refandname, ')')) != NULL) { /* complex form */ /* eliminate final parenthesis */ temp[0] = '\0'; if ((temp = strrchr(refandname, '=')) != NULL) { /* now temp points just before file name */ temp++; strcpy(name, temp); /* continue to parse for refname */ if ((temp = strchr(refandname, '(')) != NULL) { /* eliminate first parenthesis - what is left is refname */ temp[0] = '\0'; strcpy(refname, refandname); } else { /* error! */ errhdlr("voopeno"); fprintf(stderr, "name format1 error: %s\n", refandname); return(-1); } } else { /* error ! */ errhdlr("voopeno"); fprintf(stderr, "name format2 error: %s\n", refandname); return(-1); } } else { /* must be in simple format - use parameter as filename and use default refname */ strcpy(name, refandname); strcpy(refname, objref); } ncrl_name.len = strlen(name); ncrl_name.ptr.int_ptr = (int *) name; ncrl_refname.len = strlen(refname); ncrl_refname.ptr.int_ptr = (int *) refname; OBJOPENO(&ncrl_name, &ncrl_refname, objf, &result); if (result != NIOOK) { /* When a lousy outcome is returned from VKNCRLIO we output an error message PEG March 6, 1990 */ errhdlr("voopeno"); fprintf(stderr,"object (o)file failure outcome: %d\n",ERRCELL); return(-1); } setupvbuf(); return(0); } setupvbuf() { /* SETUPVBUF - * Initialize buffer variables in preparation for IO */ buffer_string.len = MAXOBJREC; buffer_string.ptr.int_ptr = (int *) & buf; nBufSiz = nBufNdx = 0; } /* VOGETC - * Return the next characters from the object file. * In most cases, this just returns the next character in the object * record buffer. When the last character in the buffer has been * used, objrecin is called to read in another record. Note that * the VLI itself is returned to the caller as part of the data. * The calling kermit routine does not need to know this. * The VLI must be made part of the data in order to reconstruct * an object file when the file is later received by vkermit (see voputc). * * Return values: * -1 if error or EOF * otherwise the character read */ vogetc(n) int n; { char result; if (nBufNdx < nBufSiz) { nBufNdx++; return(buf.buffer[nBufNdx-1]); } else { /* get new buffer */ OBJRECIN(objf, &buffer_string, &nBufSiz, &result); if (result != NIOOK) { if (result != NIOEOF) { /* When a lousy outcome is returned from VKNCRLIO we output an error message PEG March 6, 1990 */ errhdlr("vogetc"); fprintf(stderr,"READ FAILURE OUTCOME: %d\n",ERRCELL); return(-1); } else /* end of file */ return(-1); /* DRE 030990 */ } else { /* good i-o */ if (buf.vlianddata.vli > MAXOBJDAT) { /* March 2, 1990 */ char errbuf[40]; sprintf(errbuf,"vogetc: obj vli exceeds max: %#X", buf.vlianddata.vli); errhdlr(errbuf); fprintf(stderr,"current vli maximum: %#X\n", MAXOBJDAT); return(-1); } nBufNdx = 1; nBufSiz += VLISIZE; return(buf.buffer[0]); } } } /* VOPUTC - * Put a single character into the destination object file. * The first two characters are used to calculate the size of * the record next to be written. When that many characters have * been transferred into the buffer, the buffer is written using * OBJRECOUT. A ncrl_string type must be used to create a string * with a known (to NCRL) length. * * Return values: * 0 if successful * -1 if failure */ voputc(c, n) char c; int n; { char result; /* check if we just got a full vli */ if (nBufNdx == 1) { /*calculate size of record to write */ /* Note that the buffer size includes the size of the VLI but the VLI itself does not include the size of the VLI */ buf.buffer[1] = c; if (buf.vlianddata.vli > MAXOBJDAT) { /* March 2, 1990 */ char errbuf[40]; sprintf(errbuf,"voputc: obj vli exceeds max: %#X", buf.vlianddata.vli); errhdlr(errbuf); fprintf(stderr,"current vli maximum: %#X\n", MAXOBJDAT); return(-1); } nBufSiz = buf.vlianddata.vli + VLISIZE; } buf.buffer[nBufNdx] = c; /* when nBufNdx = 1 c is written twice */ nBufNdx++; if (nBufNdx >= nBufSiz) { /* clear the current buffer by writing it out */ /* unless it is the first time */ if (nBufSiz > 0) { /* March 2, 1990 */ OBJRECOUT(objf, &buffer_string, &result); if (result != NIOOK) { /* When a lousy outcome is returned from VKNCRLIO we output an error message PEG March 6, 1990 */ errhdlr("voputc"); fprintf(stderr,"write failure outcome: %d\n",ERRCELL); return(-1); } nBufNdx = 0; /* Note actual size of buffer is not calculated until second byte arrives. */ } } return(0); } voclose(n) int n; { char result; OBJCLOSE(objf, result); if (result == NIOBAD) { /* When a lousy outcome is returned from VKNCRLIO we output an error message PEG March 6, 1990 */ errhdlr("voclose"); fprintf(stderr,"error closing file outcome: %d\n",ERRCELL); return(-1); } else return(0); } <<< ckvfn2.c >>> /* C K v F N 2 -- System-independent Kermit protocol support functions... */ /********************************************************************** * * * IVS / MCS-Kermit REL 2 * * source code * * * * Change History: * * * * 1. Modify C-Kermit(4E) source code to * * produce new module for MCS/IVS-Kermit * * ORIGINAL RELEASE * * June 22, 1990 * * * * * ***********************************************************************/ /* ...Part 2 (continued from ckcfns.c) */ /* Author: Frank da Cruz (fdc@cunixc.cc.columbia.edu, FDCCU@CUVMA.BITNET), Columbia University Center for Computing Activities. First released January 1985. Copyright (C) 1985, 1989, Trustees of Columbia University in the City of New York. Permission is granted to any individual or institution to use, copy, or redistribute this software so long as it is not sold for profit, provided this copyright notice is retained. */ /* Note -- if you change this file, please amend the version number and date at the top of ckcfns.c accordingly. */ #include #include "ckcsym.h" /* Conditional compilation (for Macintosh) */ #include "ckcker.h" #include "ckcdeb.h" extern long time(); extern int spsiz, rpsiz, timint, npad, ebq, ebqflg, rpt, rptq, rptflg, capas; extern int osize, pktnum, prvpkt, sndtyp, bctr, bctu, rsn, rln, maxtry, size; extern int maxsize, spktl, nfils, stdouf, /* warn,*/ timef, parity, speed; extern int turn, turnch, delay, displa, pktlog, tralog, seslog, xflg, mypadn, userpad; extern int deblog, hcflg, binary, fncnv, local, server, cxseen, czseen; extern long filcnt, ffc, flci, flco, tlci, tlco, tfc, fsize; extern char *cmarg, *cmarg2, **cmlist; extern CHAR padch, mypadc, eol, seol, ctlq, myctlq, sstate, *hlptxt; extern CHAR filnam[], sndpkt[], recpkt[], data[], srvcmd[]; extern CHAR *srvptr, stchr, mystch, *rdatap; char *strcpy(); /* Forward declarations */ unsigned int chk2(); /* of non-int functions */ unsigned int chk3(); CHAR dopar(); /* ... */ static CHAR partab[] = { /* Even parity table for dopar() */ '\000', '\201', '\202', '\003', '\204', '\005', '\006', '\207', '\210', '\011', '\012', '\213', '\014', '\215', '\216', '\017', '\220', '\021', '\022', '\223', '\024', '\225', '\226', '\027', '\030', '\231', '\232', '\033', '\234', '\035', '\036', '\237', '\240', '\041', '\042', '\243', '\044', '\245', '\246', '\047', '\050', '\251', '\252', '\053', '\254', '\055', '\056', '\257', '\060', '\261', '\262', '\063', '\264', '\065', '\066', '\267', '\270', '\071', '\072', '\273', '\074', '\275', '\276', '\077', '\300', '\101', '\102', '\303', '\104', '\305', '\306', '\107', '\110', '\311', '\312', '\113', '\314', '\115', '\116', '\317', '\120', '\321', '\322', '\123', '\324', '\125', '\126', '\327', '\330', '\131', '\132', '\333', '\134', '\335', '\336', '\137', '\140', '\341', '\342', '\143', '\344', '\145', '\146', '\347', '\350', '\151', '\152', '\353', '\154', '\355', '\356', '\157', '\360', '\161', '\162', '\363', '\164', '\365', '\366', '\167', '\170', '\371', '\372', '\173', '\374', '\175', '\176', '\377' }; /* CRC generation tables */ static unsigned int crcta[16] = { 0, 010201, 020402, 030603, 041004, 051205, 061406, 071607, 0102010, 0112211, 0122412, 0132613, 0143014, 0153215, 0163416, 0173617}; static unsigned int crctb[16] = { 0, 010611, 021422, 031233, 043044, 053655, 062466, 072277, 0106110, 0116701, 0127532, 0137323, 0145154, 0155745, 0164576, 0174367}; /* I N P U T -- Attempt to read packet number 'pktnum'. */ /* This is the function that feeds input to Kermit's finite state machine. If a special start state is in effect, that state is returned as if it were the type of an incoming packet. Otherwise: . If the desired packet arrives within MAXTRY tries, return its type, with its data stored in the global 'data' array. . If the previous packet arrives again, resend the last packet and wait for another to come in. . If the desired packet does not arrive within MAXTRY tries, return indicating that an error packet should be sent. */ input() { int type, numtry; if (sstate != 0) { /* If a start state is in effect, */ type = sstate; /* return it like a packet type, */ sstate = 0; /* and then nullify it. */ return(type); } else type = rpack(); /* Else, try to read a packet. */ if (deblog) debug(F111, "input", rdatap, type); /* If it's the same packet we just sent, it's an echo. Read another. */ if (type == sndtyp) type = rpack(); chkint(); /* Check for console interrupts. */ /* If previous packet again, a timeout pseudopacket, or a bad packet, try again. */ for (numtry = 0; (rsn == prvpkt || type == 'T' || type == 'Q' || type == 'N'); numtry++) { if (numtry > maxtry) { /* If too many tries, give up */ strcpy(data, "Timed out."); /* and send a timeout */ /* error packet, */ rdatap = data; /* and pretend we read one. */ return('E'); } if (type == 'E') return('E'); /* Don't even bother about seq no */ if ((type == 'N') && (rsn == ((pktnum + 1) & 63))) { /* NAK for next packet */ return('Y'); /* is ACK for current. */ } else { resend(); /* Else, send last packet again, */ } if (sstate != 0) { /* If an interrupt routine has set */ type = sstate; /* sstate behind our back, return */ sstate = 0; /* that. */ *data = '\0'; return(type); } else type = rpack(); /* Else try to read a packet. */ chkint(); /* Look again for interruptions. */ if (type == sndtyp) type = rpack(); } ttflui(); /* Got what we want, clear input buffer. */ return(type); /* Success, return packet type. */ } /* S P A C K -- Construct and send a packet */ /* spack() sends a packet of the given type, sequence number n, with len data characters pointed to by d, in either a regular or extended- length packet, depending on length. Returns the number of bytes actually sent, or else -1 upon failure. Uses global npad, padch, mystch, bctu. Leaves packet in null-terminated global sndpkt[] array for later retransmission. Updates global sndpktl (send-packet length). */ spack(type, n, len, d) char type, *d; int n, len; { int i, j, lp; CHAR * sohp = sndpkt; CHAR pc; unsigned crc; if (padch == 0) padch = userpad; /* we can not allow binary zero (NULL) pad characters due to the usage of the string functions in mcs functions. */ if (deblog) { debug(F100, "funct: spack", "", 0); debug(F111, "spack", "type", type); debug(F111, "spack", "n", n); debug(F111, "spack", "len", len); } spktl = 0; pc = dopar(padch); /* The pad character, if any. */ for (i = 0; i < npad; sndpkt[i++] = pc) /* Do any requested padding */ sohp++; sndpkt[i++] = dopar(mystch); /* MARK */ lp = i++; /* Position of LEN, fill in later */ sndpkt[i++] = dopar(tochar(n)); /* SEQ field */ sndpkt[i++] = dopar(sndtyp = type); /* TYPE field */ j = len + bctu; /* Length of data + block check */ if (j + 2 > MAXPACK) { /* Long packet? */ sndpkt[lp] = dopar(tochar(0)); /* Yes, set LEN to zero */ sndpkt[i++] = dopar(tochar(j / 95)); /* High part */ sndpkt[i++] = dopar(tochar(j % 95)); /* Low part */ sndpkt[i] = '\0'; /* Header checksum */ sndpkt[i++] = dopar(tochar(chk1(sndpkt + lp))); } else sndpkt[lp] = dopar(tochar(j + 2)); /* Normal LEN */ if (deblog) debug(F110, "spack: data=", d, 0); while (len-- > 0) sndpkt[i++] = dopar(*d++); /* Packet data */ sndpkt[i] = '\0'; /* Null-terminate */ if (deblog) debug(F110, "spack: packet data=", sndpkt + lp + 6, 0); switch (bctu) { /* Block check */ case 1: /* 1 = 6-bit chksum */ sndpkt[i++] = dopar(tochar(chk1(sndpkt + lp))); if (deblog) debug(F111, "spack", "checksum", sndpkt[i-1]); break; case 2: /* 2 = 12-bit chksum */ j = chk2(sndpkt + lp); sndpkt[i++] = dopar((unsigned)tochar((j >> 6) & 077)); sndpkt[i++] = dopar((unsigned)tochar(j & 077)); break; case 3: /* 3 = 16-bit CRC */ crc = chk3(sndpkt + lp); sndpkt[i++] = dopar((unsigned)tochar(((crc & 0170000)) >> 12)); sndpkt[i++] = dopar((unsigned)tochar((crc >> 6) & 077)); sndpkt[i++] = dopar((unsigned)tochar(crc & 077)); break; } sndpkt[i++] = dopar(seol); /* End of line (packet terminator) */ sndpkt[i] = '\0'; /* Terminate string */ if (ttol(sndpkt, i) < 0) return(-1); /* Send the packet */ spktl = i; /* Remember packet length */ flco += spktl; /* Count the characters */ tlco += spktl; if (pktlog) { /* If logging packets, log it */ long stamp; /* time stamp for packet logging */ stamp = time((long *) 0); /* get the time */ zsoutl(ZPFILE,ctime(&stamp)); /* this for loop transforms cntl chars to their printable form */ zsout(ZPFILE, "s-"); if (*sndpkt) zsoutl(ZPFILE,sndpkt); else zsoutl(ZPFILE, sohp); } screen(SCR_PT, type, (long)n, sohp); /* Update screen */ return(i); /* Return length */ } /* D O P A R -- Add an appropriate parity bit to a character */ CHAR dopar(ch) CHAR ch; { unsigned int a; if (!parity) return(ch & 255); else a = ch & 127; switch (parity) { case 'e': return(partab[a]); /* Even */ case 'm': return(a | 128); /* Mark */ case 'o': return(partab[a] ^ 128); /* Odd */ case 's': return(a); /* Space */ default: return(a); } } /* C H K 1 -- Compute a type-1 Kermit 6-bit checksum. */ chk1(pkt) char *pkt; { unsigned int chk; chk = chk2(pkt); chk = (((chk & 0300) >> 6) + chk) & 077; return(chk); } /* C H K 2 -- Compute the numeric sum of all the bytes in the packet. */ unsigned int chk2(pkt) CHAR *pkt; { long chk; unsigned int m; m = (parity) ? 0177 : 0377; for (chk = 0; *pkt != '\0'; pkt++) { chk += *pkt & m; } return(chk & 07777); } /* C H K 3 -- Compute a type-3 Kermit block check. */ /* Calculate the 16-bit CRC-CCITT of a null-terminated string using a lookup table. Assumes the argument string contains no embedded nulls. */ unsigned int chk3(pkt) CHAR *pkt; { LONG c, crc; unsigned int m; m = (parity) ? 0177 : 0377; for (crc = 0; *pkt != '\0'; pkt++) { c = (*pkt & m) ^ crc; crc = (crc >> 8) ^ (crcta[(c & 0xF0) >> 4] ^ crctb[c & 0x0F]); } return(crc & 0xFFFF); } /* Functions for sending various kinds of packets */ ack() { /* Send an ordinary acknowledgment. */ spack('Y', pktnum, 0, ""); /* No data. */ nxtpkt(&pktnum); /* Increment the packet number. */ } /* Note, only call this once! */ ack1(s) char *s; { /* Send an ACK with data. */ spack('Y', pktnum, strlen(s), s); /* Send the packet. */ nxtpkt(&pktnum); /* Increment the packet number. */ } /* Only call this once! */ nack() { /* Negative acknowledgment. */ spack('N', pktnum, 0, ""); /* NAK's never have data. */ } resend() { /* Send the old packet again. */ if (spktl) /* If buffer has something, */ ttol(sndpkt, spktl); /* resend it, */ else nack(); /* otherwise send a NAK. */ if (deblog) debug(F111, "resend", sndpkt, spktl); screen(SCR_PT, '%', (long)pktnum, "(resend)"); /* Say resend occurred */ if (pktlog) { long sstamp; /* time stamp for packet logging */ sstamp = time((long *) 0); /* get the time */ zsoutl(ZPFILE,ctime(&sstamp)); zsout(ZPFILE, "s-"); zsoutl(ZPFILE, "(resend)"); /* Log packet if desired */ } } errpkt(reason) char *reason; { /* Send an error packet. */ encstr(reason); spack('E', pktnum, size, data); clsif(); clsof(1); screen(SCR_TC, 0, 0l, ""); } scmd(t, dat) char t, *dat; { /* Send a packet of the given type */ encstr(dat); /* Encode the command string */ spack(t, pktnum, size, data); } srinit() { /* Send R (GET) packet */ encstr(cmarg); /* Encode the filename. */ spack('R', pktnum, size, data); /* Send the packet. */ } nxtpkt(num) int *num; { prvpkt = *num; /* Save previous */ *num = (*num + 1) % 64; /* Increment packet number mod 64 */ } sigint() { /* Terminal interrupt handler */ errpkt("User typed ^C"); doexit(GOOD_EXIT); /* Exit program */ } /* R P A C K -- Read a Packet */ /* rpack reads a packet and returns the packet type, or else Q if the packet was invalid, or T if a timeout occurred. Upon successful return, sets the values of global rsn (received sequence number), rln (received data length), and rdatap (pointer to null-terminated data field). */ rpack() { int i, j, x, try, type, lp; /* Local variables */ int amtread, pktstart, pktlength; unsigned crc; CHAR pbc[4]; /* Packet block check */ CHAR * sohp = recpkt; /* Pointer to SOH */ CHAR e; /* Packet end character */ rsn = rln = -1; /* In case of failure. */ *recpkt = '\0'; /* Clear receive buffer. */ rdatap = recpkt; /* Initialize this. */ amtread = pktstart = pktlength = 0; /* Initialize */ e = (turn) ? turnch : eol; /* Use any handshake char for eol */ /* Try several times to get a "line". This allows for hosts that echo our normal CR packet terminator as CRLF. Don't diagnose CRLF as an invalid packet. */ #define TTITRY 3 for (try = 0; try < TTITRY; try++) { /* Try x times to get a "line" */ j = ttinl(recpkt, MAXRP, timint, e); if (j < 0) { if (j < -1) doexit(BAD_EXIT); /* Bail out if ^C^C typed. */ if (deblog) debug(F101, "rpack: ttinl fails", "", amtread); screen(SCR_PT, 'T', (long)pktnum, ""); return('T'); /* Otherwise, call it a timeout. */ } amtread = j - 2; /* forget eol and null character */ tlci += amtread; /* All OK, Count the characters. */ flci += amtread; for (i = 0; (recpkt[i] != stchr) && (i < amtread); i++) sohp++; /* Find mark */ pktstart = i; if (i++ < amtread) break; /* Found it */ } if (try >= TTITRY) return('Q'); /* Diagnose bad packet */ lp = i; /* Remember LEN position. */ if ((j = xunchar(recpkt[i++])) == 0) { /* Long packet */ if ((j = lp + 5) > MAXRP) return('Q'); x = recpkt[j]; /* Header checksum. */ recpkt[j] = '\0'; /* Calculate & compare. */ if (xunchar(x) != chk1(recpkt + lp)) return('Q'); recpkt[j] = x; /* Checksum ok. */ rln = xunchar(recpkt[j-2]) * 95 + xunchar(recpkt[j-1]) - bctu; pktlength = rln + bctu + 6; /* packet length */ j = 3; /* Data offset. */ } else if (j < 3) { if (deblog) debug(F101, "rpack: packet length less than 3", "", j); return('Q'); } else { rln = j - bctu - 2; /* Regular packet */ pktlength = rln + bctu + 3; /* packet length */ j = 0; /* No extended header */ } rsn = xunchar(recpkt[i++]); /* Sequence number */ type = recpkt[i++]; /* Packet type */ i += j; /* Where data begins */ rdatap = recpkt + i; /* The data itself */ while (amtread < (pktstart + pktlength)) { /* If we didn't initially read the entire packet, then we'll keep reading here until we get it into the buffer. */ j = ttinl(recpkt + amtread, MAXRP, timint, e); if (j < 0) { /* bad read */ if (j < -1) doexit(BAD_EXIT); if (deblog) debug(F101,"rpack: ttinl fails","",j); return('T'); } amtread += (j - 2); /* bump up amount read */ tlci += (j - 2); /* forget eol and null */ flci += (j - 2); } if (deblog) debug(F111,"rpack: ttinl",sohp,amtread); if (pktlog) { /* log packet if requested */ long rstamp; rstamp = time((long *) 0); zsoutl(ZPFILE,ctime(&rstamp)); /* time stamp for packet */ zsout(ZPFILE,"r-"); zsoutl(ZPFILE,sohp); } if ((j = rln + i) > MAXRP ) { if (deblog) debug(F101, "rpack: packet sticks out too far", "", j); return('Q'); } for (x = 0; x < bctu; x++) /* Copy block check */ pbc[x] = recpkt[j+x]; pbc[x] = '\0'; recpkt[j] = '\0'; /* Null-terminate data */ switch (bctu) { /* Check the block check */ case 1: if (xunchar(*pbc) != chk1(recpkt + lp)) { if (deblog) { debug(F110, "checked chars", recpkt + lp, 0); debug(F101, "block check", "", xunchar(*pbc)); debug(F101, "should be", "", chk1(recpkt + lp)); } return('Q'); } break; case 2: x = xunchar(*pbc) << 6 | xunchar(pbc[1]); if (x != chk2(recpkt + lp)) { if (deblog) { debug(F110, "checked chars", recpkt + lp, 0); debug(F101, "block check", "", x); debug(F101, "should be", "", chk2(recpkt + lp)); } return('Q'); } break; case 3: crc = (xunchar(pbc[0]) << 12) | (xunchar(pbc[1]) << 6) | (xunchar(pbc[2])); if (crc != chk3(recpkt + lp)) { if (deblog) { debug(F110, "checked chars", recpkt + lp, 0); debug(F101, "block check", "", xunchar(*pbc)); debug(F101, "should be", "", chk3(recpkt + lp)); } return('Q'); } break; default: return('Q'); } screen(SCR_PT, type, (long)rsn, sohp); /* Update screen */ return(type); /* Return packet type */ } <<< ckvfns.c >>> char *fnsv = "V-Kermit functions, 4E(054) 29 May 90"; /* C K V F N S -- System-independent Kermit protocol support functions. */ /********************************************************************** * * * IVS / MCS-Kermit REL 2 * * source code * * * * Change History: * * * * 1. Modify C-Kermit(4E) source code to * * produce new module for MCS/IVS-Kermit * * ORIGINAL RELEASE * * June 22, 1990 * * * * * ***********************************************************************/ /* ...Part 1 (others moved to ckcfn2 to make this module small enough) */ /* Author: Frank da Cruz (fdc@cunixc.cc.columbia.edu, FDCCU@CUVMA.BITNET), Columbia University Center for Computing Activities. First released January 1985. Copyright (C) 1985, 1989, 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. */ /* System-dependent primitives defined in: ck?tio.c -- terminal i/o ck?fio.c -- file i/o, directory structure */ #include "ckcsym.h" /* Need this for Mac */ #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, ebq, ebqflg, rpt, rptq, rptflg, capas, keep; extern int pktnum, prvpkt, sndtyp, bctr, bctu, fmask, size, osize, maxsize, spktl, nfils, stdouf, /* warn, */ timef, spsizf; 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 tsecs; extern int deblog, hcflg, binary, savmod, fncnv, local, server, cxseen, czseen; extern int rq, rqf, sq, wsize, urpsiz, rln; extern int atcapr, atcapb, atcapu; extern int lpcapr, lpcapb, lpcapu; extern int swcapr, swcapb, swcapu; extern CHAR padch, mypadc, eol, seol, ctlq, myctlq, sstate; extern CHAR filnam[], sndpkt[], recpkt[], data[], srvcmd[], stchr, mystch; extern char *cmarg, *cmarg2, *hlptxt, **cmlist; extern CHAR *srvptr; extern char *rdatap; long zchki(); char *strcpy(); CHAR *rpar(); /* Variables local to this module */ static char *memptr; /* Pointer for memory strings */ static char cmdstr[100]; /* NCR-VRX 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 */ first; /* Flag for first char from input */ static CHAR t, /* Current character */ next; /* Next character */ /* E N C S T R -- Encode a string from memory. */ /* Call this instead 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. */ first = 1; /* Initialize character lookahead. */ getpkt(spsiz-bctu-3); /* Fill a packet from the string. */ memstr = m; /* Restore memory string flag */ memptr = p; /* and pointer */ first = 1; /* Put this back as we found it. */ } /* E N C O D E - Kermit packet encoding procedure */ encode(a) CHAR 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 && (first == 0)) { /* 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); 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. */ } } a7 = 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; /* 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)(); { 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 = xunchar(*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? */ 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, */ 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 */ if ((*fn)(a) < 0) return(-1); /* Send it to the output function. */ ffc++, tfc++; /* Count the character */ } } return(0); } /* Output functions passed to 'decode': */ putsrv(c) char c; { /* Put character in server command buffer */ *srvptr++ = c; *srvptr = '\0'; /* Make sure 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 & fmask) < 0) { czseen = 1; /* If write error... */ if (deblog) 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 packet, filling the packet optimally. Set first = 1 when calling for the first time on a given input stream (string or file). Uses global variables: t -- current character. first -- flag: 1 to start up, 0 for input in progress, -1 for EOF. 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. Returns 0 upon eof. */ getpkt(bufmax) int bufmax; { /* Fill one packet buffer */ int i, x; /* Loop index. */ static char leftover[6] = { '\0', '\0', '\0', '\0', '\0', '\0' }; if (deblog) debug(F111,"getpkt","bufmax",bufmax); if (first == 1) { /* If first time thru... */ first = 0; /* remember, */ *leftover = '\0'; /* discard any interrupted leftovers, */ x = getchx(&t); /* get first character of file into t, */ if (x == 0) { /* watching out for null file, */ first = -1; return(size = 0); } } else if ((first == -1) && (*leftover == '\0')) /* EOF from last time? */ return(size = 0); /* Do any leftovers */ for (size = 0; (data[size] = leftover[size]) != '\0'; size++) ; *leftover = '\0'; if (first == -1) return(size); /* Handle final leftovers leftovers */ /* Now fill up the rest of the packet. */ rpt = 0; /* Clear out any old repeat count. */ while (first > -1) { /* Until EOF... */ x = getchx(&next); /* Get next character for lookahead. */ if (x == 0) first = -1; /* Flag eof for next time. */ osize = size; /* Remember current position. */ encode(t); /* Encode the current character. */ t = next; /* Next is now current. */ if (size == bufmax) { /* If the packet is exactly full, */ if (deblog) debug(F101,"getpkt exact fit","",size); return(size); /* ... return. */ } if (size > bufmax) { /* If too big, save some for next. */ for (i = 0; (leftover[i] = data[osize+i]) != '\0'; i++) ; if (deblog) debug(F111,"getpkt leftover",leftover,size); if (deblog) debug(F101," osize","",osize); size = osize; /* Return truncated packet. */ data[size] = '\0'; return(size); } } /* Otherwise, keep filling. */ if (deblog) debug(F111,"getpkt eof/eot",data,size); /* Fell thru before packet full, */ return(size); /* return partially filled last packet. */ } /* G E T C H X -- Get the next character from file (or pipe). */ /* On systems like NCR-VRX, 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. Returns 1 on success with ch set to the character, or 0 on failure (EOF) */ getchx(ch) char *ch; { /* 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 that. */ *ch = LF; return(1); } 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(0); /* No more, return 0 for EOF. */ else { /* Otherwise, read the next char. */ ffc++, tfc++; /* Count it. */ a &= fmask; /* Bytesize mask. */ #ifdef NLCHAR if (!binary && (a == NLCHAR)) { /* If nl and we must do nl-CRLF */ b = 1; /* mapping, remember a linefeed, */ *ch = CR; /* and return a carriage return. */ return(1); } else { *ch = a; /* General case, return the char. */ return(1); } #else *ch = a; return(1); #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; if (deblog) debug(F101,"canned: cxseen","",cxseen); if (deblog) debug(F101," czseen","",czseen); return((czseen || cxseen) ? 1 : 0); } /* R E S E T C -- Reset per-transaction character counters */ resetc() { tfc = tlci = tlco = 0; /* Total file chars, line chars in & out */ } /* T I N I T -- Initialize a transaction */ tinit() { xflg = 0; /* Reset x-packet flag */ rqf = -1; /* Reset 8th-bit-quote request flag */ memstr = 0; /* Reset memory-string flag */ memptr = NULL; /* and pointer */ bctu = 1; /* Reset block check type to 1 */ ebq = ebqflg = 0; /* Reset 8th-bit quoting stuff */ if (savmod) { /* If binary file mode was saved, */ binary = 1; /* restore it, */ savmod = 0; /* unsave it. */ } prvpkt = -1; /* Reset packet number */ pktnum = 0; cxseen = czseen = 0; /* Reset interrupt flags */ *filnam = '\0'; /* Clear file name */ *sndpkt = '\0'; /* Clear retransmission buffer */ if (server) /* If acting as server, */ timint = 30; /* Use 30 second timeout, */ } /* 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 */ filcnt = 0; /* Init file counter */ spar(d); ack1(rpar()); } /* S I N I T -- Make sure file exists, then send Send-Init packet */ sinit() { int x; char *tp; int type; filcnt = 0; sndsrc = nfils; /* Where to look for files to send */ ztime(&tp); tlog(F110,"Transaction begins",tp,0l); /* Make transaction log entry */ if (deblog) 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, &type); nfils = zxpand(xname); /* Look it up again. */ } if (nfils < 1) { /* If no match, report error. */ 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) { /* stdin or memory always exist... */ if ((cmarg2 != NULL) && (*cmarg2)) { strcpy(filnam,cmarg2); /* If F packet, "as" name is used */ cmarg2 = ""; /* if provided, */ } else /* otherwise */ strcpy(filnam,"stdin"); /* just use this. */ } if (deblog) debug(F101,"sinit: nfils","",nfils); if (deblog) debug(F110," filnam",filnam,0); if (deblog) debug(F110," cmdstr",cmdstr,0); ttflui(); /* Flush input buffer. */ if (!local && !server) sleep(delay); sipkt('S'); /* Send the Send-Init packet. */ return(1); } sipkt(c) char c; { /* Send S or I packet. */ CHAR *rp; ttflui(); /* Flush pending input. */ rp = rpar(); /* Get parameters. */ spack(c,pktnum,strlen(rp),rp); } /* 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(rdatap,putsrv); if (*srvcmd == '\0') /* Watch out for null F packet. */ strcpy(srvcmd,"NONAME"); 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,"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() { int x; if (cxseen == 0) cxseen = (*rdatap == 'D'); /* Got discard directive? */ x = clsof(cxseen | czseen); if (cxseen || czseen) { tlog(F100," *** Discarding","",0l); cxseen = 0; } else fstats(); return(x); } /* R E O T -- Receive End Of Transaction */ reot() { cxseen = czseen = 0; /* Reset interruption flags */ tstats(); } /* S F I L E -- Send File header or teXt header packet */ /* Call with x nonzero for X packet, zero for F packet */ /* Returns 1 on success, 0 on failure */ sfile(x) int x; { char pktnam[100]; /* Local copy of name */ char *s; if (x == 0) { /* F-Packet setup */ 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. */ } } if (deblog) debug(F110,"sfile",filnam,0); /* Log debugging info */ if (deblog) debug(F110," pktnam",pktnam,0); if (openi(filnam) == 0) /* Try to open the file */ return(0); s = pktnam; /* Name for packet data field */ } else { /* X-packet setup */ if (deblog) debug(F110,"sxpack",cmdstr,0); /* Log debugging info */ s = cmdstr; /* Name for data field */ } flci = flco = ffc = 0; /* Init counters, etc. */ encstr(s); /* Encode the name into data[]. */ nxtpkt(&pktnum); /* Increment the packet number */ spack(x ? 'X' : 'F', pktnum, size, data); /* Send the F or X packet */ if (x == 0) { /* Display for F packet */ if (displa) { /* Screen */ screen(SCR_FN,'F',(long)pktnum,filnam); screen(SCR_AN,0,0l,pktnam); screen(SCR_FS,0,(long)fsize,""); } tlog(F110,"Sending",filnam,0l); /* Transaction log entry */ tlog(F110," as",pktnam,0l); } else { /* Display for X-packet */ screen(SCR_XD,'X',(long)pktnum,cmdstr); /* Screen */ tlog(F110,"Sending from:",cmdstr,0l); /* Transaction log */ } intmsg(++filcnt); /* Count file, give interrupt msg */ first = 1; /* Init file character lookahead. */ return(1); } /* S D A T A -- Send a data packet */ /* Return -1 if no data to send, else send packet and return length */ sdata() { int len; if (deblog) debug(F111,"sdata","spsiz",spsiz); if (cxseen || czseen) return(-1); /* If interrupted, done. */ if ((len = getpkt(spsiz-bctu-3)) == 0) /* Done if no data. */ return(-1); nxtpkt(&pktnum); /* Increment the packet number */ spack('D',pktnum,len,data); /* Send the packet */ return(len); } /* S E O F -- Send an End-Of-File packet */ /* Call with a string pointer to character to put in the data field, */ /* or else a null pointer or "" for no data. */ seof(s) char *s; { nxtpkt(&pktnum); /* Increment the packet number */ if ((s != NULL) && (*s != '\0')) { spack('Z',pktnum,1,s); tlog(F100," *** interrupted, sending discard request","",0l); } else { spack('Z',pktnum,0,""); fstats(); } } /* S E O T -- Send an End-Of-Transaction packet */ seot() { nxtpkt(&pktnum); /* Increment the packet number */ spack('B',pktnum,0,""); /* Send the EOT packet */ cxseen = czseen = 0; /* Reset interruption flags */ tstats(); /* Log timing info */ } /* R P A R -- Fill the data array with my send-init parameters */ CHAR * rpar() { if (rpsiz > MAXPACK) /* Biggest normal packet I want. */ data[1] = tochar(MAXPACK); /* If > 94, use 94, but specify */ else /* extended packet length below... */ data[1] = tochar(rpsiz); /* else use what the user said. */ data[2] = tochar(rtimo); /* When I want to be timed out */ data[3] = tochar(mypadn); /* How much padding I need (none) */ data[4] = ctl(mypadc); /* Padding character I want */ if (eol == LF) data [5] = tochar (CR); /* for vrx ivs use only */ else data[5] = tochar(eol); /* End-Of-Line character I want */ data[6] = '#'; /* Control-Quote character I send */ switch (rqf) { /* 8th-bit prefix */ case -1: case 1: if (parity) ebq = sq = '&'; break; case 0: case 2: break; } data[7] = sq; data[8] = bctr + '0'; /* Block check type */ if (rptflg) /* Run length encoding */ data[9] = rptq; /* If receiving, agree. */ else data[9] = '~'; data[10] = tochar((atcapr?atcapb:0)|(lpcapr?lpcapb:0)|(swcapr?swcapb:0)); data[capas+1] = tochar(swcapr ? wsize : 0); /* Window size */ rpsiz = urpsiz; /* Long packets ... */ data[capas+2] = tochar(rpsiz / 95); /* Long packet size, big part */ data[capas+3] = tochar(rpsiz % 95); /* Long packet size, little part */ data[capas+4] = '\0'; /* Terminate the init string */ if (deblog) { if (deblog) debug(F110,"rpar",data+1,0); rdebu(capas+2); } return(data+1); /* Return pointer to string. */ } /* S P A R --Get the other system's Send-Init parameters */ spar(s) char *s; { /* Set parameters */ int x, lpsiz; s--; /* Line up with field numbers. */ if (deblog) debug(F101,"spar rln","",rln); /* Limit on size of outbound packets */ x = (rln >= 1) ? xunchar(s[1]) : 80; lpsiz = spsiz; /* Remember what they SET. */ if (spsizf) { /* SET-command override? */ if (x < spsiz) spsiz = x; /* Ignore LEN unless smaller */ } else { /* otherwise */ spsiz = (x < 10) ? 80 : x; /* believe them if reasonable */ } /* Timeout on inbound packets */ if (!timef) { /* Only if not SET-cmd override */ x = (rln >= 2) ? xunchar(s[2]) : 5; timint = (x < 0) ? 5 : x; } /* Outbound Padding */ npad = 0; padch = SNDPADC; if (rln >= 3) { npad = xunchar(s[3]); if (rln >= 4) padch = ctl(s[4]); else padch = SNDPADC; } /* Outbound Packet Terminator */ seol = (rln >= 5) ? xunchar(s[5]) : '\r'; if ((seol < 2) || (seol > 31)) seol = '\r'; if (seol == '\r') seol = '\n'; /* VRX IVS ONLY */ /* Control prefix */ x = (rln >= 6) ? s[6] : '#'; myctlq = ((x > 32 && x < 63) || (x > 95 && x < 127)) ? x : '#'; /* 8th-bit prefix */ rq = (rln >= 7) ? s[7] : 0; if (rq == 'Y') rqf = 1; else if ((rq > 32 && rq < 63) || (rq > 95 && rq < 127)) rqf = 2; else rqf = 0; switch (rqf) { case 0: ebqflg = 0; break; case 1: if (parity) { ebqflg = 1; ebq = '&'; } break; case 2: if (ebqflg = (ebq == sq || sq == 'Y')) ebq = rq; } /* Block check */ x = 1; if (rln >= 8) { x = s[8] - '0'; if ((x < 1) || (x > 3)) x = 1; } bctr = x; /* Repeat prefix */ if (rln >= 9) { rptq = s[9]; rptflg = ((rptq > 32 && rptq < 63) || (rptq > 95 && rptq < 127)); } else rptflg = 0; /* Capabilities */ atcapu = lpcapu = swcapu = 0; if (rln >= 10) { x = xunchar(s[10]); atcapu = (x & atcapb) && atcapr; lpcapu = (x & lpcapb) && lpcapr; swcapu = (x & swcapb) && swcapb; for (capas = 10; (xunchar(s[capas]) & 1) && (rln >= capas); capas++) ; } /* Long Packets */ if (lpcapu) { if (rln > capas+2) { x = xunchar(s[capas+2]) * 95 + xunchar(s[capas+3]); if (spsizf) { /* If overriding negotiations */ spsiz = (x < lpsiz) ? x : lpsiz; /* do this, */ } else { /* otherwise */ spsiz = (x > MAXSP) ? MAXSP : x; /* do this. */ } if (spsiz < 10) spsiz = 80; /* Be defensive... */ } } /* Sliding Windows */ if (swcapu) { if (rln > capas+1) { x = xunchar(s[capas+1]); wsize = x > MAXWS ? MAXWS : x; } else wsize = 1; } if (deblog) sdebu(rln); /* Record parameters in debug log */ } /* 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. */ if (deblog) debug(F101,"gnfile: czseen","",czseen); if (czseen) { tlog(F100,"Transaction cancelled","",0l); return(0); } /* If input was stdin or 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++); * if (deblog) debug(F111,"gnfile: cmlist filnam",filnam,nfils); * * } else { * *filnam = '\0'; * if (deblog) debug(F101,"gnfile cmlist: nfils","",nfils); * return(0); * } * } */ /* Otherwise, step to next element of internal wildcard expansion list. */ /* if (sndsrc < 0) { * x = znext(filnam); * if (deblog) 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) { * if (deblog) debug(F110,"gnfile skipping:",filnam,0); * tlog(F111,filnam,"not sent, reason",(long)y); * screen(SCR_ST,ST_SKIP,0l,filnam); * } else fsize = y; * } */ /* ********************************************************** the two lines added above the return statement were not ported correctly during the 4E code port to VRX. I confess I did it with diff output. If maybe appropriate to mention, when using diff (unix) care must be exercised to prevent missed code lines as these. PEG 01/26/90 ********************************************************** */ y = -1; /* this line probably useless but MCDAID ported it, so why change */ x = znext(filnam); return(x); } /* O P E N I -- Open an existing file for input */ openi(name) char *name; { int x, filno; int type; char xname [100]; if (memstr) return(1); /* Just return if file is memory. */ if (deblog) debug(F110,"openi",name,0); if (deblog) debug(F101," sndsrc","",sndsrc); filno = (sndsrc == 0) ? ZSTDIO : ZIFILE; /* ... */ if (deblog) debug(F101," file number","",filno); zrtol(name,xname,&type); /* to local form and then */ x = zopeni(filno,xname,type); /* try opening it again. */ if (deblog) debug(F101," zopeni","",x); if (x) { if (deblog) 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); if (deblog) 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; { char xname[100], *xp; int type; if (stdouf) /* Receiving to stdout? */ return(zopeno(ZSTDIO,"",0)); if (deblog) debug(F110,"openo: name",name,0); if (cxseen || czseen) { /* If interrupted, get out before */ if (deblog) debug(F100," open cancelled","",0); /* destroying existing file. */ return(1); /* Pretend to succeed. */ } xp = xname; /* OK to proceed. */ zrtol (name,xp,&type); /* convert name to local form */ if (deblog) 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); * if (deblog) debug(F110," exists, new name ",xname,0); * } * } */ if (zopeno(ZOFILE,xname,type) == 0) { /* Try to open the file */ if (deblog) debug(F110,"openo failed",xname,0); tlog(F110,"Failure to open",xname,0l); return(0); } else { strcpy(name2,xname); if (deblog) debug(F110,"openo ok, name2",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,"",0)); } /* 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 = 0; /* Reset flags, */ *filnam = '\0'; /* and current file name */ } /* C L S O F -- Close an output file. */ /* Call with disp != 0 if file is to be discarded. */ /* Returns -1 upon failure to close, 0 or greater on success. */ clsof(disp) int disp; { int x; if ((x = zclose(ZOFILE)) < 0) { /* Try to close the file */ tlog(F100,"Failure to close",filnam,0l); screen(SCR_ST,ST_ERR,0l,""); } else if (disp && (keep == 0)) { /* Delete it if interrupted, */ if (*filnam) zdelet(filnam); /* and not keeping incomplete files */ if (deblog) debug(F100,"Discarded","",0); tlog(F100,"Discarded","",0l); screen(SCR_ST,ST_DISC,0l,""); } else { /* Nothing wrong, just keep it */ if (deblog) debug(F100,"Closed","",0); /* and give comforting messages. */ screen(SCR_ST,ST_OK,0l,""); } *filnam = '\0'; /* Zero the current file name. */ return(x); /* Send back zclose() return code. */ } /* 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. */ first = 1; /* Init getchx lookahead */ memstr = 1; /* Just set the flag. */ memptr = hlptxt; /* And the pointer. */ if (binary) { /* If file mode is binary, */ binary = 0; /* turn it back to text for this, */ savmod = 1; /* remember to restore it later. */ } return(sinit()); } /* C W D -- Change current working directory */ /* String passed has first byte as length of directory name, rest of string is name. Fails if can't connect, else ACKs (with name) and succeeds. */ cwd(vdir) char *vdir; { char *cdd, *zgtdir(); vdir[xunchar(*vdir) + 1] = '\0'; /* End with a null */ if (zchdir(vdir+1)) { cdd = zgtdir(); /* Get new working directory. */ encstr(cdd); ack1(data); tlog(F110,"Changed directory to",cdd,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. */ syscmd(prefix,suffix) char *prefix, *suffix; { char *cp; if (prefix == NULL || *prefix == '\0') return(0); for (cp = cmdstr; *prefix != '\0'; *cp++ = *prefix++) ; while (*cp++ = *suffix++) ; if (deblog) debug(F110,"syscmd",cmdstr,0); if (zopeni(ZSYSFN,cmdstr,0) > 0) { if (deblog) debug(F100,"syscmd zopeni ok",cmdstr,0); nfils = sndsrc = 0; /* Flag that input from stdin */ xflg = hcflg = 1; /* And special flags for pipe */ if (binary) { /* If file mode is binary, */ binary = 0; /* turn it back to text for this, */ savmod = 1; /* remember to restore it later. */ } return (sinit()); /* Send S packet */ } else { if (deblog) debug(F100,"syscmd zopeni failed",cmdstr,0); return(0); } } <<< ckvmai.c >>> #ifndef MCS_FLAG char *versio = "IVS-Kermit, 4E(072) 06 June 90"; #else char *versio = "MCS-Kermit, 4E(072) 06 June 90"; #endif /* C K V M A I -- V-Kermit Main program */ /********************************************************************** * * * IVS / MCS-Kermit REL 2 * * source code * * * * Change History: * * * * 1. Modify C-Kermit(4E) source code to * * produce new module for MCS/IVS-Kermit * * ORIGINAL RELEASE * * June 22, 1990 * * * * * ***********************************************************************/ /* 4E, add long packet support, plus changes for Apollo and Data General support from SAS Institute, and for Macintosh from Planning Research Corp, plus several important bug fixes. Author: Frank da Cruz (fdc@cunixc.cc.columbia.edu, FDCCU@CUVMA.BITNET), Columbia University Center for Computing Activities. First released January 1985. Copyright (C) 1985, 1989, Trustees of Columbia University in the City of New York. Permission is granted to any individual or institution to use, copy, or redistribute this software so long as it is not sold for profit, provided this copyright notice is retained. The Kermit file transfer protocol was developed at Columbia University. It is named after Kermit the Frog, star of the television series THE MUPPET SHOW; the name is used by permission of Henson Associates, Inc. "Kermit" is also Celtic for "free". Thanks to Herm Fischer of Encino CA for extensive contributions to version 4, and to the following people for their contributions over the years: Larry Afrin, Clemson U Robert Andersson, Oslo, Norway Stan Barber, Rice U Charles Brooks, EDN Mike Brown, Purdue U Bill Catchings, formerly of CUCCA Bob Cattani, Columbia U CS Dept Howard Chu, U of Michigan Bill Coalson, McDonnell Douglas Alan Crosswell, CUCCA Jeff Damens, formerly of CUCCA Joe R. Doupnik, Utah State U Glenn Everhart, RCA Labs Carl Fongheiser, CWRU John Gilmore, UC Berkeley Yekta Gursel, MIT Jim Guyton, Rand Corp Stan Hanks, Rice U. Ken Harrenstein, SRI Chuck Hedrick, Rutgers U Ron Heiby, Motorola Micromputer Division Steve Hemminger, Tektronix Randy Huntziger, NLM Phil Julian, SAS Institute Jim Knutson, U of Texas at Austin John Kunze, UC Berkeley David Lawyer, UC Irvine S.O. Lidie, Lehigh U Chris Maio, Columbia U CS Dept Leslie Mikesall, American Farm Bureau Martin Minow, DEC Ray Moody, Purdue U Tony Movshon, NYU Dan Murphy, ??? Jim Noble, Planning Research Corporation Paul Placeway, Ohio State U Ken Poulton, HP Labs Frank Prindle, NADC Anton Rang, ??? Scott Ribe, ??? Jack Rouse, SAS Institute Stew Rubenstein, Harvard Dan Schullman, DEC Gordon Scott, Micro Focus, Newbury UK David Sizeland, U of London Medical School Bradley Smith, UCLA Andy Tanenbaum, THE, Netherlands Markku Toijala, Helsinki U of Technology Dave Tweten, AMES-NAS Walter Underwood, Ford Aerospace Pieter Van Der Linden, Centre Mondial (Paris) Wayne Van Pelt, GE/CRD Mark Vasoll & Gregg Wonderly, Oklahoma State University Stephen Walton, Ametek Computer Lauren Weinstein Joachim Wiesel, U of Karlsruhe Dave Woolley, CAP Communication Systems, London John Zeeff, Ann Arbor, MI Paul E. Gladden, NCR Corp., E&M San Diego Darrell Edwards, NCR Corp., E&M San Diego Paul Shaffer, NCR Corp., E&M San Diego and many others. */ #include "ckcsym.h" #include "ckcker.h" #include "ckcdeb.h" #ifdef MCS_FLAG #include "mcs_defs_h" #endif char *hlptxt="VRX Kermit Commands Supported: GET, SEND FINISH\r\n\0"; char *srvtxt = "\r\n Kermit-VRX server starting. \r\n\0"; /* Declarations for Send-Init Parameters */ int spsiz = DSPSIZ, /* Biggest packet size we can send */ spsizf = 0, /* Flag to override what you ask for */ rpsiz = DRPSIZ, /* Biggest we want to receive */ urpsiz = DRPSIZ, /* User-requested rpsiz */ maxrps = MAXRP, /* Maximum incoming long packet size */ maxsps = MAXSP, /* Maximum outbound l.p. size */ maxtry = MAXTRY, /* Maximum retries per packet */ wsize = 1, /* Window size */ timint = DMYTIM, /* Timeout interval I use */ rtimo = URTIME, /* Timeout I want you to use */ timef = 0, /* Flag to override what you ask */ npad = MYPADN, /* How much padding to send */ mypadn = MYPADN, /* How much padding to ask for */ bctr = 1, /* Block check type requested */ bctu = 1, /* Block check type used */ ebq = MYEBQ, /* 8th bit prefix */ ebqflg = 0, /* 8th-bit quoting flag */ rqf = -1, /* Flag used in 8bq negotiation */ rq = 0, /* Received 8bq bid */ sq = 'Y', /* Sent 8bq bid */ rpt = 0, /* Repeat count */ rptq = MYRPTQ, /* Repeat prefix */ rptflg = 0; /* Repeat processing flag */ int capas = 10, /* Position of Capabilities */ atcapb = 8, /* Attribute capability */ atcapr = 0, /* requested */ atcapu = 0, /* used */ swcapb = 4, /* Sliding Window capability */ swcapr = 0, /* requested */ swcapu = 0, /* used */ lpcapb = 2, /* Long Packet capability */ lpcapr = 1, /* requested */ lpcapu = 0; /* used */ CHAR padch = SNDPADC, /* Padding character to send */ mypadc = MYPADC, /* Padding character to ask for */ seol = MYEOL, /* End-Of-Line character to send */ eol = LF, /* End-Of-Line character to look for */ ctlq = CTLQ, /* Control prefix in incoming data */ myctlq = CTLQ; /* Outbound control character prefix */ /* Packet-related variables */ int pktnum = 0, /* Current packet number */ prvpkt = -1, /* Previous packet number */ sndtyp, /* Type of packet just sent */ rsn, /* Received packet sequence number */ rln, /* Received packet length */ size, /* Current size of output pkt data */ osize, /* Previous output packet data size */ maxsize, /* Max size for building data field */ spktl = 0; /* Length packet being sent */ CHAR sndpkt[MAXSP+100], /* Entire packet being sent */ recpkt[MAXRP+200], /* Packet most recently received */ *rdatap, /* Pointer to received packet data */ data[MAXSP+4], /* Packet data buffer */ srvcmd[MAXRP+4], /* Where to decode server command */ *srvptr, /* Pointer to above */ mystch = SOH, /* Outbound packet-start character */ stchr = SOH; /* Incoming packet-start character */ /* File-related variables */ CHAR filnam[50]; /* Name of current file. */ int nfils; /* Number of files in file group */ long fsize; /* Size of current file */ /* Communication line variables */ CHAR ttname[50]; /* Name of communication line. */ int parity, /* Parity specified, 0,'e','o',etc */ flow, /* Flow control, 1 = xon/xoff */ speed = -1, /* Line speed */ turn = 0, /* Line turnaround handshake flag */ turnch = XON, /* Line turnaround character */ duplex = 0, /* Duplex, full by default */ escape = 034, /* Escape character for connect */ delay = DDELAY, /* Initial delay before sending */ mdmtyp = 0; /* Modem type (initially none) */ int tlevel = -1; /* Take-file command level */ /* Statistics variables */ long filcnt, /* Number of files in transaction */ flci, /* Characters from line, current file */ flco, /* Chars to line, current file */ tlci, /* Chars from line in transaction */ tlco, /* Chars to line in transaction */ ffc, /* Chars to/from current file */ tfc; /* Chars to/from files in transaction */ int tsecs; /* Seconds for transaction */ /* Flags */ int deblog = 0, /* Flag for debug logging */ pktlog = 0, /* Flag for packet logging */ seslog = 0, /* Session logging */ tralog = 0, /* Transaction logging */ displa = 0, /* File transfer display on/off */ stdouf = 0, /* Flag for output to stdout */ xflg = 0, /* Flag for X instead of F packet */ hcflg = 0, /* Doing Host command */ fncnv = 1, /* Flag for file name conversion */ binary = 0, /* Flag for binary file */ savmod = 0, /* Saved file mode */ cmask = 0177, /* Connect byte mask */ fmask = 0377, /* File byte mask */ /* warn = 0, Flag for file warning */ quiet = 0, /* Be quiet during file transfer */ local = 0, /* Flag for external tty vs stdout */ server = 0, /* Flag for being a server */ cnflg = 0, /* Connect after transaction */ cxseen = 0, /* Flag for cancelling a file */ czseen = 0, /* Flag for cancelling file group */ send_id = 1, /* Flag for keeping id-fields in SPUR files */ recv_id = 1, /* Flag for keeping id-fields in SPUR files */ send_num = 1, /* Flag for keeping line numbers in SPUR files */ recv_num = 1, /* Flag for keeping line numbers in SPUR files */ send_renum = 0, /* Flag for renumbering line numbers in SPUR files */ recv_renum = 0, /* Flag for renumbering line numbers in SPUR files */ send_addnum = 0, recv_addnum = 0, keep = 0; /* Keep incomplete files */ /* Variables passed from command parser to protocol module */ char parser(); /* The parser itself */ char sstate = 0; /* Starting state for automaton */ char *cmarg = ""; /* Pointer to command data */ char *cmarg2 = ""; /* Pointer to 2nd command data */ char **cmlist; /* Pointer to file list in argv */ /* Miscellaneous */ char **xargv; /* Global copies of argv */ int xargc; /* and argc */ extern char *dftty; /* Default tty name from ckx???.c */ extern int dfloc; /* Default location: remote/local */ extern int dfprty; /* Default parity */ extern int dfflow; /* Default flow control */ /* M A I N -- C-Kermit main program */ main(argc, argv) int argc; char **argv; { char *strcpy(); #ifdef MCS_FLAG char status[3]; #endif /* Do some initialization */ #ifdef MCS_FLAG mcs_enable("r",QUEUENAME,status); mcs_enable("w",QUEUENAME,status); #endif xargc = argc; /* Make global copies of argc */ xargv = argv; /* ...and argv. */ sstate = 0; /* No default start state. */ strcpy(ttname, dftty); /* Set up default tty name. */ local = dfloc; /* And whether it's local or remote. */ parity = dfprty; /* Set initial parity, */ flow = dfflow; /* and flow control. */ if (sysinit() < 0) doexit(BAD_EXIT); /* And system-dependent things. */ /*** attempt to take ini file before doing command line ***/ cmdini(); /* Sets tlevel */ while (tlevel > -1) { /* Execute init file. */ sstate = parser(); /* Loop getting commands. */ if (sstate) proto(); /* Enter protocol if requested. */ } /* Look for a UNIX-style command line... */ if (argc > 1) { /* Command line arguments? */ sstate = cmdlin(); /* Yes, parse. */ if (sstate) { proto(); /* Take any requested action, then */ if (!quiet) conoll(""); /* put cursor back at left margin, */ if (cnflg) conect(); /* connect if requested, */ doexit(GOOD_EXIT); /* and then exit with status 0. */ } } /* If no action requested on command line, enter interactive parser */ herald(); /* Display program herald. */ while (1) { /* Loop getting commands. */ sstate = parser(); if (sstate) proto(); /* Enter protocol if requested. */ } } <<< ckvmcs.c >>> /* CKVMCS_C MCS I/F routines June 14, 1990 */ /********************************************************************** * * * MCS-Kermit REL 2 * * source code * * * * Change History: * * * * 1. Modify C-Kermit(4E) source code to * * produce new module for MCS/IVS-Kermit * * ORIGINAL RELEASE * * June 22, 1990 * * * * * ***********************************************************************/ #include #include #include #include #include #include #include "mcs_defs_h" #include "ckcdeb.h" /* DRE 020190 */ #include "ckcker.h" /* DRE 060690 */ #define SCR_EM 9 /* PEG 013090 */ #define MCSLIMIT 200 extern int server; /* PEG 013090 */ extern char *free(); extern char *malloc(); extern int deblog; /* DRE 021690 */ extern int doexit(); static struct OutputCD *OCDptr = &OutCD; static struct InputCD *ICDptr = &InCD; static struct SParBlck *SPBptr = &SParBlock; static struct RParBlck *RPBptr = &RParBlock; static struct ParBlck *PBptr = &ParBlock; static char mcs_tmpstr[MCSLIMIT]; static char *blanks = " "; static char *spb_param = NULL; /* DRE 020190 */ static char realmesg[MAXSP]; /* DRE 060690 */ /******************************************************************* * * * str_convert * * * * converts non-printable MCS structures to a hex format * * * * PEG June 4, 1990 * * * ********************************************************************/ void str_convert(mcs_ptr, lgth) char *mcs_ptr; int lgth; { char *cptr; int i, j, flag = 0; static char hexchar[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; if ((lgth * 2) > MCSLIMIT) { fprintf(stderr, "\nstr_convert lgth over MCSLIMIT...\n\n"); mcs_tmpstr[0] = '\0'; return; } for (j = 0, cptr = mcs_ptr; j < lgth; j++, cptr++) if (!isprint(*cptr)) flag = 1; if (!flag) { strncpy(mcs_tmpstr, mcs_ptr, lgth); *(mcs_ptr + lgth + 1) = '\0'; return; } else { for (j = 0, i = 0; j < lgth; j++) { if (*cptr < 0x10) /* high order bits */ mcs_tmpstr[i++] = '0'; else mcs_tmpstr[i++] = hexchar[*cptr++ / 0x10]; if (*cptr == 0x00) /* low order bits */ mcs_tmpstr[i++] = '0'; else mcs_tmpstr[i++] = hexchar[*cptr++ % 0x10]; } mcs_tmpstr[i] = '\0'; if (i + 25 > MCSLIMIT) fprintf(stderr, "Next line converted to HEX...\n"); else strcat(mcs_tmpstr, " *** converted to hex *** "); } } /******************************************************************* * * * dump routines * * * * dumps MCS control structures for mcs_send * * mcs_recv * * * * PEG June 4, 1990 * * * ********************************************************************/ void dump_OCD() { fprintf(stderr, "\nDumping OCDptr...\n"); str_convert(OCDptr->destcnt, 4); fprintf(stderr, "OCDptr->destcnt: %s\n", mcs_tmpstr); str_convert(OCDptr->textlen, 4); fprintf(stderr, "OCDptr->textlen: %s\n", mcs_tmpstr); str_convert(OCDptr->statkey, 2); fprintf(stderr, "OCDptr->statkey: %s\n", mcs_tmpstr); fprintf(stderr, "OCDptr->errkey: %#X\n", OCDptr->errkey); str_convert(OCDptr->symdest, 12); fprintf(stderr, "OCDptr->symdest: %s\n", mcs_tmpstr); fprintf(stderr, "OCDptr->ExOutCD.xoformat: %#X\n", OCDptr->ExOutCD.xoformat); str_convert(OCDptr->ExOutCD.tcfunction, 3); fprintf(stderr, "OCDptr->ExOutCD.tcfunction: %s\n", mcs_tmpstr); str_convert(OCDptr->ExOutCD.tcqualifier, 3); fprintf(stderr, "OCDptr->ExOutCD.tcqualifier: %s\n", mcs_tmpstr); fprintf(stderr, "OCDptr->ExOutCD.tcoutput_reset: %#X\n", OCDptr->ExOutCD.tcoutput_reset); } void dump_ICD() { fprintf(stderr, "\nDumping ICDptr...\n"); str_convert(ICDptr->q, 12); fprintf(stderr, "ICDptr->q: %s\n", mcs_tmpstr); str_convert(ICDptr->symq1, 12); fprintf(stderr, "ICDptr->symq1: %s\n", mcs_tmpstr); str_convert(ICDptr->symq2, 12); fprintf(stderr, "ICDptr->symq2: %s\n", mcs_tmpstr); str_convert(ICDptr->symq3, 12); fprintf(stderr, "ICDptr->symq3: %s\n", mcs_tmpstr); str_convert(ICDptr->mdate, 6); fprintf(stderr, "ICDptr->mdate: %s\n", mcs_tmpstr); str_convert(ICDptr->mtime, 8); fprintf(stderr, "ICDptr->mtime: %s\n", mcs_tmpstr); str_convert(ICDptr->source, 12); fprintf(stderr, "ICDptr->source: %s\n", mcs_tmpstr); str_convert(ICDptr->len, 4); fprintf(stderr, "ICDptr->len: %s\n", mcs_tmpstr); fprintf(stderr, "ICDptr->endkey: %#X\n", ICDptr->endkey); str_convert(ICDptr->statkey, 2); fprintf(stderr, "ICDptr->statkey: %s\n", mcs_tmpstr); str_convert(ICDptr->msgcnt, 6); fprintf(stderr, "ICDptr->msgcnt: %s\n", mcs_tmpstr); fprintf(stderr, "ICDptr->ExInCD.xiformat: %#X\n", ICDptr->ExInCD.xiformat); str_convert(ICDptr->ExInCD.xistatus, 2); fprintf(stderr, "ICDptr->ExInCD.xistatus: %s\n", mcs_tmpstr); str_convert(ICDptr->ExInCD.xipassthru, 10); fprintf(stderr, "ICDptr->ExInCD.xipassthru: %s\n", mcs_tmpstr); } void dump_SPB() { fprintf(stderr, "\nDumping SDBptr...\n"); fprintf(stderr, "SPBptr->length: %d\n", SPBptr->length); fprintf(stderr, "SPBptr->complver: % #X\n", SPBptr->complver); fprintf(stderr, "SPBptr->linenum: %#X\n", SPBptr->linenum); fprintf(stderr, "SPBptr->indicator: %#X\n", SPBptr->indicator); fprintf(stderr, "SPBptr->advancing: %#X\n", SPBptr->advancing); fprintf(stderr, "SPBptr->position: %#X\n", SPBptr->position); fprintf(stderr, "SPBptr->sendcount: %#X\n", SPBptr->sendcount); str_convert(SPBptr->mnemonic, 4); fprintf(stderr, "SPBptr->mnemonic: %s\n", mcs_tmpstr); } void dump_RPB() { fprintf(stderr, "\nDumping RPBptr...\n"); fprintf(stderr, "RPBptr->length: %d\n", RPBptr->length); fprintf(stderr, "RPBptr->complver: %#X\n", RPBptr->complver); fprintf(stderr, "RPBptr->avail: %#X\n", RPBptr->avail); fprintf(stderr, "RPBptr->indicator: %#X\n", RPBptr->indicator); } /******************************************************************** * * * Function mcserr * * called when status returned by MCS * * routines return anything other than 00 * * outputs an error message * * * * Paul E. Gladden * * May 3, 1990 * * June 14, 1990 update dump ICD / OCD struct * * * * assumes status bytes are ascii * * chars * * * *********************************************************************/ void mcserr(cin, status, errsend) char cin; char status[2]; char errsend; { char str1[100]; long errclk; char *cptr; str1[0] = '\0'; errclk = time((long *) 0); /* time stamping mcs errors */ sprintf(str1, "\n%s", ctime(&errclk)); cptr = strrchr(str1, '\n'); if (cptr != NULL) { *cptr++ = ' '; /* removing \n put in by ctime */ *cptr = '\0'; } switch (cin) { case 'd' : strcat(str1, "MCS Error Status: Disable "); break; case 'e' : strcat(str1, "MCS Error Status: Enable "); break; case 'a' : strcat(str1, "MCS Error Status: Accept "); break; case 's' : strcat(str1, "MCS Error Status: Send "); break; case 'r' : strcat(str1, "MCS Error Status: Receive "); break; default : strcat(str1, "MCS Error Status: Unknown "); break; } strncat (str1, status, 2); if ( cin == 's' ) { /* moves errorkey char into error output */ char valtmp[3]; /* with an error condition occurs with a */ /* mcs_send PEG 020590 */ valtmp[0] = ' '; valtmp[1] = errsend; valtmp[2] = '\0'; strncat(str1, valtmp, 2); } strncat(str1, "\n", 1); /* DRE 021690 */ write(2, str1, (unsigned)(strlen(str1))); if (deblog) debug(F110, "funct: mcserr> ", str1, 0); if (cin == 'e' && !(strncmp(status, "00", 2))) { /* enable failed exiting... */ if (!(strncmp(status, "12", 2))) return; sprintf(str1, "MCSENABLE failed...program exiting...\n"); write(2, str1, (unsigned)(strlen(str1))); doexit(BAD_EXIT); } if (deblog) { if ( cin == 's' ) { dump_OCD(); dump_SPB(); } if ( cin == 'r' ) { dump_ICD(); dump_RPB(); } } } mcs_disable(io, qname, status) char *io; char *qname; char status[3]; { char passwd[PWDLEN]; init_pwd(passwd); if (deblog) debug(F100, "funct: mcs_disable", "", 0); if ((*io == 'r') || (*io == 'R')) { /* disable the input queue */ init_ipb(); init_icd(qname); MCS\:DSABLE(ICDptr, passwd, PBptr); /* DRE 013190 */ status[0] = ICDptr->statkey[0]; /* DRE 013190 */ status[1] = ICDptr->statkey[1]; /* DRE 013190 */ status[2] = '\0'; /* DRE 013190 */ } else { /* disable the output */ init_opb(); /* DRE 012990 */ init_ocd(); /* DRE 012990 */ MCS\:DSABLE(OCDptr, passwd, PBptr); /* DRE 013190 */ status[0] = OCDptr->statkey[0]; /* DRE 013190 */ status[1] = OCDptr->statkey[1]; /* DRE 013190 */ status[2] = '\0'; /* DRE 013190 */ } if ((status[0] != '0') || (status[1] != '0')) /* PEG 013090 */ mcserr ('d', status, 'x'); } mcs_enable(io, qname, status) char *io; char *qname; char status[3]; { char passwd[PWDLEN]; init_pwd(passwd); if (deblog) debug(F100, "funct: mcs_enable", "", 0); if ((*io == 'r') || (*io == 'R')) { /* enable the input */ init_ipb(); init_icd(qname); init_rpb(); /* DRE 021690 - Done here for performance */ MCS\:ENABLE(ICDptr, passwd, PBptr); /* DRE 013190 */ status[0] = ICDptr->statkey[0]; /* DRE 013190 */ status[1] = ICDptr->statkey[1]; /* DRE 013190 */ status[2] = '\0'; /* DRE 013190 */ } else { /* enable the output */ init_opb(); /* DRE 012990 */ init_ocd(); /* DRE 012990 */ init_spb(); /* DRE 021690 - Done here for performance */ MCS\:ENABLE(OCDptr, passwd, PBptr); /* DRE 013190 */ status[0] = OCDptr->statkey[0]; /* DRE 013190 */ status[1] = OCDptr->statkey[1]; /* DRE 013190 */ status[2] = '\0'; /* DRE 013190 */ } if ((status[0] != '0') || (status[1] != '0')) /* PEG 013090 */ mcserr ('e', status, 'x'); } init_pwd(passwd) char *passwd; { strncpy(passwd, blanks, PWDLEN); strncpy(passwd, PASSWD, strlen(PASSWD)); } init_icd(qname) char *qname; { strncpy(ICDptr->q, blanks, 12); strncpy(ICDptr->q, qname, strlen(qname)); strncpy(ICDptr->symq1, blanks, 12); strncpy(ICDptr->symq2, blanks, 12); strncpy(ICDptr->symq3, blanks, 12); strncpy(ICDptr->mdate, blanks, 6); strncpy(ICDptr->mtime, blanks, 8); strncpy(ICDptr->source, blanks, 12); strncpy(ICDptr->source, IN_TERM, strlen(IN_TERM)); strncpy(ICDptr->len, blanks, 4); strncpy(ICDptr->statkey, blanks, 2); strncpy(ICDptr->msgcnt, blanks, 6); /* DRE 020290 */ /* DRE 012990 - removed reference to filler and msgcnt3 parameters */ strncpy(ICDptr->ExInCD.xistatus, blanks, 2); strncpy(ICDptr->ExInCD.xipassthru, blanks, 3); ICDptr->endkey = 0x20; ICDptr->ExInCD.xiformat = 0x20; strncpy(ICDptr->ExInCD.xifiller, blanks, 27); /* DRE 012990 */ } init_recv_icd() { ICDptr->endkey = 0x32; strncpy(ICDptr->statkey, "00", 2); ICDptr->ExInCD.xiformat = 0x30; strncpy(ICDptr->ExInCD.xistatus, blanks, 2); strncpy(ICDptr->ExInCD.xipassthru, blanks, 10); } init_ocd() { strncpy(OCDptr->destcnt, "0001", 4); strncpy(OCDptr->textlen, blanks, 4); strncpy(OCDptr->statkey, blanks, 2); OCDptr->errkey = 0x20; strncpy(OCDptr->symdest, blanks, 12); /* DRE 012990 */ strncpy(OCDptr->symdest, OUT_TERM, strlen(OUT_TERM)); OCDptr->ExOutCD.xoformat = 0x30; strncpy(OCDptr->ExOutCD.tcfunction, blanks, 3); strncpy(OCDptr->ExOutCD.tcqualifier, blanks, 3); strncpy(OCDptr->ExOutCD.xofiller, blanks, 33); /* DRE 012990 */ OCDptr->ExOutCD.tcoutput_reset = 0x20; /* DRE 012990 */ } init_write_ocd(mesglength, destination) int mesglength; char *destination; { char len[5]; sprintf(len, "%0.4d", mesglength); strncpy(OCDptr->textlen, len, 4); SPBptr->length = (short)mesglength; strncpy(OCDptr->statkey, "00", 2); OCDptr->errkey = 0x30; strncpy(OCDptr->symdest, blanks, 12); strncpy(OCDptr->symdest, destination, strlen(destination)); } init_ipb() { PBptr->denabltyp = IPPHASE; PBptr->passwdlen = PWDLEN; PBptr->complver = COMPVER; PBptr->destcount = 0x00; strncpy(PBptr->filler, blanks, 8); /* DRE 012990 */ /* DRE 012990 - remove references to indicator, advancing, position, sendcount, and mnemonic fields */ } init_opb() { PBptr->denabltyp = OPPHASE; PBptr->passwdlen = PWDLEN; PBptr->complver = COMPVER; PBptr->destcount = 0x00; strncpy(PBptr->filler, blanks, 8); /* DRE 012990 */ /* DRE 012990 - remove references to indicator, advancing, position, sendcount, and mnemonic fields */ } init_rpb() { RPBptr->length = 0x0050; RPBptr->complver = COMPVER; RPBptr->avail = 0x02; /* suspend if input Q empty */ RPBptr->indicator = EMI; strncpy(RPBptr->filler, blanks, 7); /* DRE 012990 */ /* DRE 012990 - remove references to advancing and position fields */ } init_spb() { /* length field set by init_write_ocd */ SPBptr->complver = COMPVER; SPBptr->linenum = 0x00; SPBptr->indicator = EMI; /* SPBptr->advancing = AFTER; */ SPBptr->advancing = 0x00; /* DRE 020990 */ SPBptr->position = 0x00; /* DRE 020990 */ /* SPBptr->position = LINE; */ SPBptr->sendcount = 0x01; /* DRE 012990 */ /* SPBptr->mnemonic.type = 0x01; */ SPBptr->mnemonic[0] = 0x01; /* mnemonic type */ if (spb_param == NULL) { spb_param = (char *) malloc(6 * sizeof(char)); *spb_param = 0x04; *(spb_param + 1) = '\0'; strcat(spb_param, "UNFM"); } /* SPBptr->mnemonic.address = spb_param; */ SPBptr->mnemonic[1] = *((char *) & spb_param + 1); /* set address */ SPBptr->mnemonic[2] = *((char *) & spb_param + 2); SPBptr->mnemonic[3] = *((char *) & spb_param + 3); } mcs_accept(qname) char *qname; { char msgcnt[7]; int mesg_no; char status[2]; if (deblog) debug(F100, "funct: mcs_accept", "", 0); init_icd(qname); #ifndef lint MCS\:ACCEPT(ICDptr); #endif if ((ICDptr->statkey[0] != '0') || (ICDptr->statkey[1] != '0')) { status[0] = ICDptr->statkey[0]; status[1] = ICDptr->statkey[1]; status[2] = '\0'; mcserr ('a', status, 'x'); } strncpy(msgcnt, ICDptr->msgcnt, 6); msgcnt[6] = '\0'; mesg_no = atoi(msgcnt); return mesg_no; } mcs_recv(qname, mesg, mesglength, source, status) char *qname; char *mesg; int *mesglength; char *source; char status[3]; { char len_str[5]; if (deblog) debug(F100, "funct:mcs_recv", "", 0); init_icd(qname); init_recv_icd(); /* init_rpb(); */ #ifndef lint MCS\:RECEIV(ICDptr, mesg, RPBptr); #else fgets(mesg, 200, stdin); sprintf(len_str, "%0.4d", strlen(mesg)); strncpy(ICDptr->len, len_str, 4); *mesglength = strlen(mesg); strcpy(status, "00"); #endif strncpy(len_str, ICDptr->len, 4); len_str[4] = '\0'; *mesglength = atoi(len_str); if (mesg[*mesglength - 1] == '\r') mesg[*mesglength - 1] = '\n'; mesg[*mesglength] = '\0'; /* * mesg[*mesglength] = '\n'; * mesg[*mesglength+1] = '\0'; */ source = ICDptr->source; status[0] = ICDptr->statkey[0]; status[1] = ICDptr->statkey[1]; status[2] = '\0'; if (deblog) debug(V110, "mcs_recv:mesg ", mesg, *mesglength); /* PEG 042490 */ if (deblog) debug(F111, "funct:mcs_recv", "mesglength", *mesglength); if ((status[0] != '0') || (status[1] != '0')) /* PEG 013090 */ mcserr ('r', status, 'x'); } mcs_send(qname, mesg, mesglength, destination, status) char *qname; char *mesg; int mesglength; char *destination; char status[3]; { char source[80]; int i, j, mesg_no, count; i = j = 0; while (mesg[i] != '\0') { realmesg[j] = mesg[i]; if (realmesg[j] == '\n') { mesglength++; realmesg[++j] = '\r'; } i++; j++; } realmesg[j] = '\0'; if (deblog) debug(F110, "funct: mcs_send ", realmesg, 0); init_write_ocd(mesglength, destination); #ifndef lint MCS\:SEND(OCDptr, realmesg, SPBptr); #else for (count = 0; count < mesglength; count++) { if (mesg[count] != '\r') putchar(mesg[count]); } strcpy(status, "00"); #endif /* This code removed the returned statuses passed back from MCS from the respective queues. At present we check the status from MCS returned from the system call. But we do NOT check any statuses placed on the queues. McDaid threw the statuses away after removing them from the queue. MCS now never places the statuses on the queue. This was done by changing MCSKNDLJ OPRTN parameter from BOTH to NONE. MCS now does the work we use to do. A small performance gain should result. PEG April 19, 1990 mesg_no = mcs_accept(qname); for (i=0;istatkey[0]; status[1] = OCDptr->statkey[1]; status[2] = '\0'; if ((status[0] != '0') || (status[1] != '0')) /* PEG 013090 */ mcserr ('s', status, OCDptr->errkey); } <<< ckvpro.c >>> /* 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(006) May 1990"; #ifndef MCS_FLAG char *protv = "IVS-Kermit Protocol Module 4E(032), 31 May 90"; #else char *protv = "MCS-Kermit Protocol Module 4E(032), 31 May 90"; #endif /* -*-C-*- */ /* C K V P R O -- C-Kermit Protocol Module, in Wart preprocessor notation. */ /********************************************************************** * * * IVS / MCS-Kermit REL 2 * * source code * * * * Change History: * * * * 1. Modify C-Kermit(4E) source code to * * produce new module for MCS/IVS-Kermit * * ORIGINAL RELEASE * * June 22, 1990 * * * * * ***********************************************************************/ /* Authors: Frank da Cruz (SY.FDC@CU20B), Bill Catchings, Jeff Damens; 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. */ #include "ckcdeb.h" #include "ckcker.h" /* Note -- This file may also be preprocessed by the NCR-VRX Lex program, but you must indent the above #include statements before using Lex, and then restore them 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 Lex) */ #define ipkt 1 #define rfile 2 #define rdata 3 #define ssinit 4 #define ssfile 5 #define ssdata 6 #define sseof 7 #define sseot 8 #define serve 9 #define generic 10 #define get 11 #define rgen 12 /* External C-Kermit variable declarations */ extern char sstate, deblog, *versio, *srvtxt, *cmarg, *cmarg2, *rpar(); extern char data[], filnam[], srvcmd[], ttname[], *srvptr; extern int pktnum, timint, nfils, hcflg, xflg, speed, flow, mdmtyp; extern int prvpkt, cxseen, czseen, server, local, displa, bctu, bctr, quiet; extern int tsecs, parity, backgrd; extern int putsrv(), puttrm(), putfil(), errpkt(); extern char *rdatap; /* Local variables */ static char vstate = 0; /* Saved State */ static char vcmd = 0; /* Saved Command */ int x; /* General-purpose integer */ char *s; /* General-purpose string pointer */ /* Macros - Note, BEGIN is predefined by Wart (and Lex) */ #define SERVE tinit(); BEGIN serve #define RESUME if (server) { SERVE; } else { sleep(2); return; } #define BEGIN state = int state = 0; wart() { int c, actno; extern short 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: { tinit(); BEGIN get; } break; case 3: { tinit(); vstate = get; vcmd = 0; sipkt('I'); BEGIN ipkt; } break; case 4: { tinit(); vstate = rgen; vcmd = 'C'; sipkt('I'); BEGIN ipkt; } break; case 5: { tinit(); vstate = rgen; vcmd = 'G'; sipkt('I'); BEGIN ipkt; } break; case 6: { sleep(1); SERVE; } break; case 7: { /* "Abort" -- Tell other side. */ errpkt("User cancelled transaction"); x = quiet; quiet = 1; /* Close files silently. */ clsif(); clsof(1); quiet = x; return(0); } break; case 8: { rinit(rdatap); bctu = bctr; /* Get Send-Init */ resetc(); /* Reset counters */ rtimer(); /* Reset timer */ BEGIN rfile; } break; case 9: { spar(rdatap); /* Get ack for I-packet */ if (vcmd) { scmd(vcmd, cmarg); vcmd = 0; } if (vstate == get) srinit(); BEGIN vstate; } break; case 10: { if (vcmd) /* Get E for I-packet (ignore) */ scmd(vcmd, cmarg); vcmd = 0; if (vstate == get) srinit(); BEGIN vstate; } break; case 11: { srinit(); } break; case 12: { srvptr = srvcmd; decode(rdatap, putsrv); /* Get Receive-Init */ cmarg = srvcmd; nfils = -1; if (sinit()) BEGIN ssinit; else { SERVE; } } break; case 13: { spar(rdatap); ack1(rpar()); /* Get Init Parameters */ pktnum = 0; prvpkt = -1; } break; case 14: { srvptr = srvcmd; decode(rdatap, putsrv); /* Get & decode command. */ putsrv('\0'); putsrv('\0'); sstate = srvcmd[0]; BEGIN generic; } break; case 15: { srvptr = srvcmd; /* Get command for shell */ decode(rdatap, putsrv); putsrv('\0'); if (syscmd(srvcmd, "")) BEGIN ssinit; else { errpkt("Can't do system command"); SERVE; } } break; case 16: { errpkt("Unimplemented server function"); SERVE; } break; case 17: { if (!cwd(srvcmd + 1)) errpkt("Can't change directory"); /* CWD */ SERVE; } break; case 18: { errpkt("Can't list directory"); SERVE; } break; case 19: { errpkt("Can't remove file"); SERVE; } break; case 20: { ack(); screen(SCR_TC, 0, 0l, ""); return(0); } break; case 21: { ack(); ttres(); screen(SCR_TC, 0, 0l, ""); return(zkself()); } break; case 22: { if (sndhlp()) BEGIN ssinit; else { errpkt("Can't send help"); SERVE; } } break; case 23: { errpkt("Can't type file"); SERVE; } break; case 24: { errpkt("Can't check space"); SERVE; } break; case 25: { errpkt("Can't do who command"); SERVE; } break; case 26: { errpkt("Unimplemented generic server function"); SERVE; } break; case 27: { decode(rdatap, puttrm); RESUME; } break; case 28: { if (rcvfil()) /* File header */ { encstr(filnam); ack1(data); BEGIN rdata; } else { errpkt("Can't open file"); RESUME; } } break; case 29: { opent(); ack(); BEGIN rdata; } break; case 30: { ack(); tsecs = gtimer(); reot(); RESUME; } break; case 31: { if (cxseen) ack1("X"); /* Got data. */ else if (czseen) ack1("Z"); else ack(); decode(rdatap, putfil); } break; case 32: { if (reof() < 0) { /* Got End Of File */ errpkt("Can't close file"); RESUME; } else { ack(); BEGIN rfile; } } break; case 33: { spar(rdatap); bctu = bctr; /* Got ACK to Send-Init */ x = sfile(xflg); /* Send X or F header packet */ if (x) { resetc(); rtimer(); BEGIN ssfile; } else { s = xflg ? "Can't execute command" : "Can't open file"; errpkt(s); RESUME; } } break; case 34: { srvptr = srvcmd; /* Got ACK to F */ decode(rdatap, putsrv); putsrv('\0'); if (*srvcmd) tlog(F110, " stored as", srvcmd, 0); if (sdata() < 0) { clsif(); seof(""); BEGIN sseof; } else BEGIN ssdata; } break; case 35: { if (canned(rdatap)) { clsif(); seof("D"); BEGIN sseof; } else if (sdata() < 0) { clsif(); seof(""); BEGIN sseof; } } break; case 36: { if (gnfile() > 0) { /* Got ACK to EOF, get next file */ if (sfile(xflg)) BEGIN ssdata; else { errpkt("Can't open file") ; RESUME; } } else { /* If no next file, EOT */ tsecs = gtimer(); seot(); BEGIN sseot; } } break; case 37: { RESUME; } break; case 38: { /* Error packet, issue message. * ermsg(rdatap); / x = quiet; quiet = 1; /* Close files silently, */ clsif(); clsof(1); /* discarding any output file. */ tsecs = gtimer(); quiet = x; if (backgrd && !server) fatal("Protocol error"); RESUME; } break; case 39: { errpkt("Unknown packet type-> Please retry"); RESUME; } break; } } } short tbl[] = { -1, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 7, 39, 4, 39, 39, 39, 5, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 3, 1, 39, 39, 2, 39, 6, 39, 39, 39, 39, 39, 39, 39, -1, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 10, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 9, 39, 39, 39, 39, 39, 39, 39, 7, 39, 4, 39, 39, 39, 5, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 3, 1, 39, 39, 2, 39, 6, 39, 39, 39, 39, 39, 39, 39, -1, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 30, 39, 39, 38, 28, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 29, 39, 39, 39, 39, 39, 39, 39, 39, 7, 39, 4, 39, 39, 39, 5, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 3, 1, 39, 39, 2, 39, 6, 39, 39, 39, 39, 39, 39, 39, -1, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 31, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 32, 39, 39, 39, 39, 39, 39, 7, 39, 4, 39, 39, 39, 5, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 3, 1, 39, 39, 2, 39, 6, 39, 39, 39, 39, 39, 39, 39, -1, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 33, 39, 39, 39, 39, 39, 39, 39, 7, 39, 4, 39, 39, 39, 5, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 3, 1, 39, 39, 2, 39, 6, 39, 39, 39, 39, 39, 39, 39, -1, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 34, 39, 39, 39, 39, 39, 39, 39, 7, 39, 4, 39, 39, 39, 5, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 3, 1, 39, 39, 2, 39, 6, 39, 39, 39, 39, 39, 39, 39, -1, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 35, 39, 39, 39, 39, 39, 39, 39, 7, 39, 4, 39, 39, 39, 5, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 3, 1, 39, 39, 2, 39, 6, 39, 39, 39, 39, 39, 39, 39, -1, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 36, 39, 39, 39, 39, 39, 39, 39, 7, 39, 4, 39, 39, 39, 5, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 3, 1, 39, 39, 2, 39, 6, 39, 39, 39, 39, 39, 39, 39, -1, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 37, 39, 39, 39, 39, 39, 39, 39, 7, 39, 4, 39, 39, 39, 5, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 3, 1, 39, 39, 2, 39, 6, 39, 39, 39, 39, 39, 39, 39, -1, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 16, 16, 16, 14, 16, 13, 16, 16, 16, 16, 16, 16, 16, 16, 12, 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 7, 16, 4, 16, 16, 16, 5, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 3, 1, 16, 16, 2, 16, 6, 16, 16, 16, 16, 16, 16, 16, -1, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 17, 18, 19, 20, 26, 22, 26, 26, 26, 21, 26, 26, 26, 26, 26, 26, 26, 23, 24, 26, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 7, 26, 4, 26, 26, 26, 5, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 3, 1, 26, 26, 2, 26, 6, 26, 26, 26, 26, 26, 26, 26, -1, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 38, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 8, 39, 39, 39, 39, 39, 11, 39, 39, 39, 39, 39, 39, 39, 7, 39, 4, 39, 39, 39, 5, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 3, 1, 39, 39, 2, 39, 6, 39, 39, 39, 39, 39, 39, 39, 0, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 38, 28, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 8, 39, 39, 39, 39, 29, 27, 39, 39, 39, 39, 39, 39, 39, 7, 39, 4, 39, 39, 39, 5, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 3, 1, 39, 39, 2, 39, 6, 39, 39, 39, 39, 39, 39, 39, }; /* 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 (ttopen(ttname, &x, mdmtyp) < 0) { if (deblog) debug(F111, "failed: proto ttopen local", ttname, local); screen(SCR_EM, 0, 0l, "Can't open line"); return; } if (x > -1) local = x; if (deblog) debug(F111, "proto ttopen local", ttname, local); x = (local) ? speed : -1; if (ttpkt(x, flow, parity) < 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; if (sstate == 'v' && !local && !quiet) conoll("ESC back to local system and give a SEND command..."); if (sstate == 's' && !local && !quiet) conoll("ESC back to local system and give a RECEIVE command..."); sleep(1); /* The 'wart()' function is generated by the wart 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 */ #ifndef MCS_FLAG conoll("IVS-Kermit server done"); #else conoll("MCS-Kermit server done"); #endif } ttres(); screen(SCR_TC, 0, 0l, ""); /* Transaction complete */ } <<< ckvscr.c >>> char *loginv = "Script Command, V2.0(007) 11 May 90"; /* C K U S C R -- Login script for logging onto remote system */ /********************************************************************** * * * IVS / MCS-Kermit REL 2 * * source code * * * * Change History: * * * * 1. Modify C-Kermit(4E) source code to * * produce new module for MCS/IVS-Kermit * * ORIGINAL RELEASE * * June 22, 1990 * * * * * ***********************************************************************/ /* This module should work under all versions of NCR-VRX. It calls externally defined system-depended functions for i/o. The module expects a login string of the expect send [expect send] ... format. It is intended to operate similarly to the way the common uucp "L.sys" login entries work. Conditional responses are supported expect[-send-expect[...]] as with uucp. The send keyword EOT sends a control-d, and the keyword BREAK sends a break. Letters prefixed by '~' are '~b' backspace, '~s' space, '~n' linefeed, '~r' return, '~x' xon, '~t' tab, '~q' ? (not allowed on kermit command lines), '~' ~, '~'', '~"', '~c' don't append return, '~o[o[o]]' octal character. As with some uucp systems, sent strings are followed by ~r (not ~n) unless they end with ~c. Null expect strings (e.g., ~0 or --) cause a short delay, and are useful for sending sequences requiring slight pauses. Author: Herm Fischer (HFISCHER@USC-ECLB) Contributed to Columbia University for inclusion in C-Kermit. Copyright (C) 1985, Herman Fischer, 16400 Ventura Blvd, Encino CA 91436 Permission is granted to any individual or institution to use, copy, or redistribute this software so long as it is not sold for profit, provided this copyright notice is retained. */ #include "ckcdeb.h" #include #include #include #include #include "ckcker.h" #include "kermisc.h" #ifdef MCS_FLAG #include "mcs.h" #endif extern int local, speed, flow, seslog, mdmtyp, quiet, duplex, deblog; extern char ttname[]; extern CHAR dopar(); static char *chstr(); static int EXP_ALRM = 15; /* Time to wait for expect string */ #define SND_ALRM 15 /* Time to allow for sending string */ #define NULL_EXP 2 /* Time to pause on null expect strg*/ #define DEL_MSEC 300 /* milliseconds to pause on ~d */ #define SBUFL 512 static char seq_buf[SBUFL], *s; /* Login Sequence buffer */ static char fls_buf[SBUFL]; /* Flush buffer */ static int got_it, no_cr; /* connect state parent/child communication signal handlers */ static jmp_buf alrmRng; /* Envir ptr for connect errors */ scrtime() { /* modem read failure handler, */ longjmp(alrmRng, 1); /* notifies parent process to stop */ } /* Sequence interpreter -- pick up next sequence from command string, decode escapes and place into seq_buf If string contains a ~d (delay) then sequenc returns a 1 expecting to be called again after the ~d executes. */ static sequenc() { int i; char c, oct_char; no_cr = 0; /* output needs cr appended */ for (i = 0; i < SBUFL; ) { if (*s == '\0' || *s == '-' || isspace(*s) ) { /* done */ seq_buf[i] = '\0'; return(0) ; } if (*s == '~') { /* escape character */ switch (c = *(++s) ) { case 'n': seq_buf[i++] = '\n'; break; case 'r': seq_buf[i++] = '\r'; break; case 't': seq_buf[i++] = '\t'; break; case 'b': seq_buf[i++] = '\b'; break; case 'q': seq_buf[i++] = '?'; break; case '~': seq_buf[i++] = '~'; break; case '\'': seq_buf[i++] = '\''; break; case '\"': seq_buf[i++] = '\"'; break; case 's': seq_buf[i++] = ' '; break; case 'x': seq_buf[i++] = '\021'; break; case 'c': no_cr = 1; break; case 'd': { /* send what we have & then */ /* expect to send rest after */ seq_buf[i] = '\0'; /* sender delays a little */ no_cr = 1; s++; return(1); } case 'w': { /* wait count */ EXP_ALRM = 15; /* default to 15 sec */ if ( isdigit( *(s + 1) ) ) { EXP_ALRM = (*(++s)) & 15; if ( isdigit( *(s + 1) ) ) { EXP_ALRM = EXP_ALRM *10 + ( (*(++s)) & 15 ); } } break; } default: if ( isdigit(c) ) { /* octal character */ oct_char = (c & 7); /* most significant digit */ if (isdigit( *(s + 1) ) ) { oct_char = (oct_char << 3) | ( (*(++s)) & 7 ) ; if (isdigit( *(s + 1) ) ) { oct_char = (oct_char << 3) | ( (*(++s)) & 7 ) ; } } seq_buf[i++] = oct_char; break; } } } else seq_buf[i++] = *s; /* plain old character */ s++; } seq_buf[i] = '\0'; return(0); /* end of space, return anyway */ } /* Receive sequence -- see if expected response comes return success (or failure) in got_it */ static recvSeq() { char *e, got[7], trace[SBUFL]; int i, l; sequenc(); l = strlen(e = seq_buf); /* no more than 7 chars allowed */ if (l > 7) { e += l - 7; l = 7; } tlog(F111, "expecting sequence", e, (long) l); if (l == 0) { /* null sequence, just delay a little */ sleep (NULL_EXP); got_it = 1; tlog(F100, "got it (null sequence)", "", 0l); return; } *trace = '\0'; for (i = 0; i < 7; i++) got[i] = '\0'; SIGNAL(SIGALRM, scrtime); /* did we get it? */ if (!setjmp(alrmRng)) { /* not timed out yet */ ALARM(EXP_ALRM); while (!got_it) { for (i = 0; i < (l - 1); i++) got[i] = got[i+1]; /* shift over one */ got[l-1] = ttinc(0) & 0177; /* next char */ if (seslog) /* Log in session log */ zchout(ZSFILE, got[l-1]); if (strlen(trace) < sizeof(trace) - 2 ) strcat(trace, chstr(got[l-1])); got_it = (!strncmp(seq_buf, got, l) ) ; } } else got_it = 0; /* timed out here */ ALARM(0); SIGNAL(SIGALRM, SIG_IGN); tlog(F110, "received sequence: ", trace, 0l); tlog(F101, "returning with got-it code", "", (long) got_it); return; } /* Output A Sequence starting at pointer s, return 0 if okay, 1 if failed to read (modem hangup or whatever) */ static int outSeq() { char *sb; int l; int delay; int retCode = 0; while (1) { delay = sequenc(); l = strlen(seq_buf); tlog(F111, "sending sequence ", seq_buf, (long) l); SIGNAL(SIGALRM, scrtime); if (!setjmp(alrmRng)) { ALARM(SND_ALRM); if (!strcmp(seq_buf, "EOT")) { ttoc(dopar('\004')); if (seslog && duplex) zsout(ZSFILE, "{EOT}"); } else if (!strcmp(seq_buf, "BREAK")) { ttsndb(); zsout(ZSFILE, "{BREAK}"); } else { if (l > 0) { for ( sb = seq_buf; *sb; sb++) *sb = dopar(*sb); ttol(seq_buf, l); /* with parity */ if (seslog && duplex) zsout(ZSFILE, seq_buf); } if (!no_cr) { ttoc( dopar('\r') ); if (seslog && duplex) zchout(ZSFILE, dopar('\r')); } } } else retCode |= -1; /* else -- alarm rang */ ALARM(0); SIGNAL(SIGALRM, SIG_IGN); if (!delay) return ( retCode ); msleep(DEL_MSEC); /* delay, and loop to next stuff to send */ } } /* L O G I N -- Login to remote system */ login(cmdstr) char *cmdstr; { SIGTYP (*saveAlm)(); /* save incoming alarm function */ char *e; s = cmdstr; /* make global to ckuscr.c */ tlog(F100, loginv, "", 0l); if (!local) { #ifndef MCS_FLAG printf("Sorry, you must 'set line' first\n"); #else mcs_printf("Sorry, you must 'set line' first\n"); #endif return(-2); } if (speed < 0) { #ifndef MCS_FLAG printf("Sorry, you must 'set speed' first\n"); #else mcs_printf("Sorry, you must 'set speed' first\n"); #endif return(-2); } if (ttopen(ttname, &local, mdmtyp) < 0) { sprintf(seq_buf, "Sorry, can't open %s", ttname); perror(seq_buf); return(-2); } #ifndef MCS_FLAG if (!quiet) printf("Executing script thru %s, speed %d.\r\n", ttname, speed); #else if (!quiet) { sprintf(print_str,"Executing script thru %s, speed %d.\r\n", ttname, speed); mcs_printf(print_str); } #endif *seq_buf = 0; for (e = s; *e; e++) strcat(seq_buf, chstr(*e) ); #ifndef MCS_FLAG if (!quiet) printf("Script string: %s\r\n", seq_buf); #else if (!quiet) { sprintf(print_str,"Script string: %s\r\n", seq_buf); mcs_printf(print_str); } #endif tlog(F110, "Script string: ", seq_buf, 0l); /* Condition console terminal and communication line */ if (ttvt(speed, flow) < 0) { #ifndef MCS_FLAG printf("Sorry, Can't condition communication line\n"); #else mcs_printf("Sorry, Can't condition communication line\n"); #endif return(-2); } /* save initial timer interrupt value */ saveAlm = SIGNAL(SIGALRM, SIG_IGN); flushi(); /* flush stale input */ /* start expect - send sequence */ while (*s) { /* while not done with buffer */ while (*s && isspace(*s)) s++; /* skip over separating whitespaces */ /* gather up expect sequence */ got_it = 0; recvSeq(); while (!got_it) { /* no, is there a conditional send */ if (*s++ != '-') goto failRet; /* no -- return failure */ /* start of conditional send */ flushi(); /* flush out input buffer */ if (outSeq()) goto failRet; /* if unable to send! */ if (*s++ != '-') goto failRet; /* must have condit respon.*/ recvSeq(); } /* loop back and check got_it */ while (*s && !isspace(*s++) ) ; /* Skip over conditionals */ while (*s && isspace(*s)) s++; /* Skip over separating whitespaces */ flushi(); /* Flush */ if (*s) if (outSeq()) goto failRet; /* If any */ } SIGNAL(SIGALRM, saveAlm); if (!quiet) #ifndef MCS_FLAG printf("Script successful.\r\n"); #else mcs_printf("Script successful.\r\n"); #endif tlog(F100, "Script successful.", "", 0l); return(0); failRet: SIGNAL(SIGALRM, saveAlm); #ifndef MCS_FLAG printf("Sorry, script failed\r\n"); #else mcs_printf("Sorry, script failed\r\n"); #endif tlog(F100, "Script 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); } /* F L U S H I -- Flush, but log, input buffer */ flushi() { int n; if (seslog) { /* Logging session? */ n = ttchk(); /* Yes, anything in buffer? */ if (n > 0) { /* If so, */ if (n > SBUFL) n = SBUFL; /* make sure not too much, */ n = ttxin(n, fls_buf); /* then read it, */ zsout(ZSFILE, fls_buf); /* and log it. */ } } else ttflui(); /* Otherwise just flush. */ } <<< ckvtio.c >>> char *ckxv = "NCR-VRX tty I/O, 4E, 01 June 90"; /* C K V T I O */ /********************************************************************** * * * IVS / MCS-Kermit REL 2 * * source code * * * * Change History: * * * * 1. Modify C-Kermit(4E) source code to * * produce new module for MCS/IVS-Kermit * * ORIGINAL RELEASE * * June 22, 1990 * * * * * ***********************************************************************/ /* C-Kermit interrupt, terminal control & i/o functions for NCR-VRX 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 for all NCR-VRXes (conditional includes come later) */ #include /* Types */ #include /* Character types */ #include /* NCR-VRX Standard i/o */ #include /* Interrupts */ #include /* Longjumps */ #include "ckcdeb.h" /* Typedefs, formats for debug() */ #include #include "ckuusr.h" #include /* Clock info (for break generation) */ #ifdef MCS_FLAG #include "mcs.h" #define read mcs_read #define write mcs_write #endif /* DUMMY DEFINES FOR COMPILE */ #define DIRSIZ 10 #define B0 1 #define B110 1 #define B150 1 #define B300 1 #define B600 1 #define B1200 1 #define B1800 1 #define B2400 1 #define B4800 1 #define B9600 1 #define SIGQUIT 1 #define SIGINT 1 #define SIGHUP 1 #define SIGALRM 1 /* Maximum length for the name of a tty device */ #ifndef DEVNAMLEN #define DEVNAMLEN 25 #endif char *ckxsys = " NCR VRX/VE"; /* Features... */ /* Do own buffering, using unbuffered read() calls... */ /* 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 -- 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 unixes) 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): sysinit() -- System dependent program initialization 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. 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 (untimed). 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. conbin(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). 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 rtimer() -- Reset timer gtimer() -- Get elapsed time since last call to rtimer() */ /* Declarations */ long time(); /* All NCR-VRXes should have this... */ char *dftty = CTTNAM; /* Remote by default, use normal */ int dfloc = 0; /* controlling terminal name. */ extern int errno; /* System call error return */ extern int deblog; /* 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 */ int dfprty = 0; /* Parity (0 = none) */ int dfflow = 1; /* Xon/Xoff flow control */ int backgrd = 0; /* Assume in foreground (no '&' ) */ int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */ /* Declarations of variables global within this module */ static long tcount; /* Elapsed time counter */ 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 descriptor */ static char escchr; /* Escape or attn character */ /* Special line discipline, 4.2bsd only, and only with kernel mods... */ static int kerld = 0; /* Not selected, no special l.d. */ /* dummy struct for compilw **** */ struct sgttyb { int sg_ispeed; int sg_ospeed; }; static struct sgttyb /* sgtty info... */ ttold, ttraw, tttvt, ttbuf, /* for communication line */ ccold, ccraw, cccbrk; /* and for console */ 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 conesc = 0; /* set to 1 if esc char (^\) typed */ static int ttlock(); /* definition of ttlock subprocedure */ static int ttunlck(); /* and unlock subprocedure */ static char ttnmsv[DEVNAMLEN]; /* copy of open path for tthang */ /* S Y S I N I T -- System-dependent program initialization. */ sysinit() { /* for now, nothing... */ if (deblog) debug(F100, "funct: sysinit ", "", 0); } /* T T Y N A M E -- Set default tty name. */ char * ttyname(x) int x; { char *xx; if (deblog) debug(F100, "funct: ttyname ", "", 0); xx = "/dev/tty"; return(xx); } /* T T O P E N -- Open a tty for exclusive access. */ /* Returns 0 on success, -1 on failure. */ /* If called with lcl < 0, sets value of lcl as follows: 0: the terminal named by ttname is the job's controlling terminal. 1: the terminal named by ttname is not 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; { char *x; char cname[DEVNAMLEN]; if (deblog) debug(F100, "funct: ttopen ", "", 0); if (ttyfd > -1) return(0); /* If already open, ignore this call */ xlocal = *lcl; /* Make this available to other fns */ ttyfd = open(ttname, O_TTY); /* Try to open for read/write */ 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 */ if (deblog) debug(F111, "ttopen", ttname, *lcl); if (*lcl == -1) { if (strcmp(ttname, CTTNAM) == 0) { /* "/dev/tty" always remote */ if (deblog) 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) */ if (deblog) debug(F110, " ttyname(0)", x, 0); x = ttyname(ttyfd); /* ...with real name of ttname. */ xlocal = (strncmp(x, cname, DEVNAMLEN) == 0) ? 0 : 1; if (deblog) debug(F111, " ttyname", x, xlocal); } else { /* Else, if stdin redirected... */ /* Just assume local, so "set speed" and similar commands will work */ /* If not really local, how could it work anyway?... */ xlocal = 1; if (deblog) debug(F101, " redirected stdin", "", xlocal); } } /* 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; if (deblog) 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) *lcl = xlocal; /* Some special stuff for v7... */ /* Request exclusive access on systems that allow it. */ /* Get tty device settings */ 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 */ if (deblog) debug(F101, "ttopen, ttyfd", "", ttyfd); if (deblog) debug(F101, " lcl", "", *lcl); if (deblog) debug(F111, " lock file", flfnam, lkf); return(0); } /* T T C L O S -- Close the TTY, releasing any lock. */ ttclos() { if (deblog) debug(F100, "funct: ttclos ", "", 0); if (ttyfd < 0) return(0); /* Wasn't open. */ if (xlocal) { if (tthang()) /* Hang up phone line */ fprintf(stderr, "Warning, problem hanging up the phone\n"); if (ttunlck()) /* Release uucp-style lock */ fprintf(stderr, "Warning, problem releasing lock\n"); } ttres(); /* Reset modes. */ /* Relinquish exclusive access if we might have had it... */ close(ttyfd); /* Close it. */ ttyfd = -1; /* Mark it as closed. */ return(0); } /* T T H A N G -- Hangup phone line */ tthang() { if (deblog) debug(F100, "funct: tthang ", "", 0); if (ttyfd < 0) return(0); /* Not open. */ return (0); } /* T T R E S -- Restore terminal to "normal" mode. */ ttres() { /* Restore the tty to normal. */ if (deblog) debug(F100, "funct: ttres ", "", 0); if (ttyfd < 0) return(-1); /* Not open. */ sleep(1); /* Wait for pending i/o to finish. */ if (STTY(ttyfd, &ttold) < 0) return(-1); /* Restore sgtty stuff */ return(0); } /* 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; if (deblog) debug(F100, "funct: xxlast ", "", 0); 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]; char *lockdir = "/usr/spool/uucp"; device = ( (devname = xxlast(ttname, '/')) != NULL ? devname + 1 : ttname); strcat( strcpy( lockfil, "LCK.." ), device ); 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 set lock file */ } strcat(strcat(strcpy(flfnam, lockdir), "/"), lockfil); if (deblog) 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) #ifndef MCS_FLAG printf("(Use \"DEL %s\" to remove this file)\n", flfnam); #else mcs_printf("(Use \"DEL %s\" to remove this file)\n", flfnam); #endif return( -1 ); } if ( access( lockdir, 02 ) < 0 ) { /* lock file cannot be written */ fprintf(stderr, "Warning, write access to lock directory 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 */ int lck_fil, l4l; int pid_buf = getpid(); /* pid to save in lock file */ hasLock = 0; /* not locked yet */ l4l = look4lk(ttyfd); if (deblog) debug(F100, "funct: ttlock ", "", 0); if (l4l < 0) return (-1); /* already locked */ if (l4l == 1) return (0); /* can't read/write lock directory */ lck_fil = creat(flfnam, 0444); /* create lock file ... */ if (lck_fil < 0) return (-1); /* create of lockfile failed */ /* creat leaves file handle open for writing -- hf */ write (lck_fil, &pid_buf, sizeof(pid_buf) ); /* uucp expects int in file */ close (lck_fil); hasLock = 1; /* now is locked */ return(0); } /* T T U N L O C K */ static ttunlck() { /* kill uucp lock if possible */ if (deblog) debug(F100, "funct: ttunlock", "", 0); if (hasLock) return( 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; { int s; if (deblog) debug(F100, "funct: ttpkt ", "", 0); if (ttyfd < 0) return(-1); /* Not open. */ s = ttsspd(speed); /* Check the speed */ ttflui(); /* Flush any pending input */ return(0); } /* T T V T -- Condition communication line for use as virtual terminal */ ttvt(speed, flow) int speed, flow; { int s; if (deblog) debug(F100, "funct: ttvt ", "", 0); if (ttyfd < 0) return(-1); /* Not open. */ s = ttsspd(speed); /* Check the speed */ if (s > -1) tttvt.sg_ispeed = tttvt.sg_ospeed = s; /* Do the speed */ if (STTY(ttyfd, &tttvt) < 0) return(-1); } /* T T S S P D -- Return the internal baud rate code for 'speed'. */ ttsspd(speed) { int s, spdok; if (deblog) debug(F100, "funct: ttsspd ", "", 0); 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: s = B1200; break; case 1800: s = B1800; break; case 2400: s = B2400; break; case 4800: s = B4800; break; case 9600: s = B9600; break; 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() { long n; if (deblog) debug(F100, "funct: ttflui ", "", 0); if (ttyfd < 0) return(-1); /* Not open. */ ungotn = -1; /* Initialize myread() stuff */ inbufc = 0; return(0); } /* Interrupt Functions */ /* Timeout handler for communication line input functions */ timerh() { longjmp(sjbuf, 1); } /* Set up terminal interrupts on console terminal */ /* C O N I N T -- Console Interrupt setter */ conint(f) int (*f)(); { /* Set an interrupt trap. */ if (deblog) debug(F100, "funct: conint ", "", 0); if (backgrd) return; /* must ignore signals 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); 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 */ return; } SIGNAL(SIGINT, f); /* Function to trap to on interrupt. */ SIGNAL(SIGHUP, f); /* Or hangup, so lock file cleared. */ conif = 1; /* Flag console interrupts on. */ } /* C O N N O I -- Reset console terminal interrupts */ connoi() { /* Console-no-interrupts */ if (deblog) debug(F100, "funct: connoi ", "", 0); if (backgrd) return; /* Ignore signals in background */ SIGNAL(SIGINT, SIG_DFL); SIGNAL(SIGHUP, SIG_DFL); SIGNAL(SIGQUIT, SIG_DFL); conif = 0; /* Flag interrupt trapping off */ } /* myread() -- For use by systems that can do nonblocking read() calls */ /* Returns: -1 if no characters available, -2 upon error (such as disconnect), otherwise value of character (0 or greater) */ myread() { static int inbuf_item; static CHAR inbuf[257]; CHAR readit; if (ungotn >= 0) { readit = ungotn; } else { if (inbufc > 0) { readit = inbuf[++inbuf_item]; } else { if ((inbufc = read(0, inbuf, 256)) == 0) { /* end of file */ /* means carrier dropped on modem connection */ errno = 9999; /* magic number for no carrier */ return(-2); /* end of file has no errno */ } if (inbufc < 0) return(-2); readit = inbuf[inbuf_item = 0]; } inbufc--; } ungotn = -1; return(readit); } myunrd(ch) CHAR ch; { /* push back up to one character */ ungotn = ch; } /* T T C H K -- Tell how many characters are waiting in tty input buffer */ ttchk() { int x; long n; if (deblog) debug(F100, "funct: ttchk ", "", 0); return(0); } /* T T X I N -- Get n characters from tty input buffer */ /* Returns number of characters actually gotten, or -1 on failure */ /* Intended for use only when it is known that n characters are actually */ /* Available in the input buffer. */ ttxin(n, buf) int n; char *buf; { int x; CHAR c; if (deblog) debug(F100, "funct: ttxin ", "", 0); if (deblog) debug(F101, "ttxin: n", "", n); x = read(0, buf, n); if (deblog) debug(F101, " x", "", x); if (x > 0) buf[x] = '\0'; if (x < 0) x = -1; return(x); } /* T T O L -- Similar to "ttinl", but for writing. */ ttol(s, n) int n; char *s; { int x; char *str; int nbr; if (deblog) debug(F100, "funct: ttol ", "", 0); if (ttyfd < 0) return(-1); /* Not open. */ if (deblog) debug(F111, "ttol", "string length", n); x = write(1, s, n); if (deblog) debug(F110, "ttol: packet ", s, 0); if (x < 0 && deblog) debug(F101, "ttol failed", "", x); return(x); } /* T T O C -- Output a character to the communication line */ ttoc(c) char c; { if (deblog) debug(F100, "funct: ttoc ", "", 0); if (ttyfd < 0) return(-1); /* Not open. */ return(write(1, &c, 1)); } /* 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, eol) int max, timo; char *dest; char eol; { int x, y; CHAR c; if (deblog) debug(F101, "funct: ttinl timo ", "", timo); if (ttyfd < 0) return(-1); /* Not open. */ if (timo <= 0) { /* Untimed read... */ x = read(0, dest, max); /* Try to read. */ return(x); /* Return the count. */ } /* Timed read... */ SIGNAL(SIGALRM, timerh); /* Set up timeout action. */ ALARM(timo); /* Set the timer. */ if (setjmp(sjbuf)) /* Do this if timer went off. */ x = -1; else if (kerld) { /* Efficient Kermit line discipline */ x = read(0, dest, max); /* for 4.2bsd only... */ } else { /* Normal case... */ if (deblog) debug(F101, "ttinl, starting for loop, max ", "", max); if (deblog) debug(F101, " eol ", "", eol); for (x = c = y = 0; (x < max) && (c != eol); x++) { while ((y = read(0, &c, 1)) == 0) /* Else call system */ ; /* ...for each character. */ if (deblog) debug(F101, "ttinl, read character ", "", c); if (y < 0) { ALARM(0); /* Error, turn off timer, */ SIGNAL(SIGALRM, SIG_DFL); /* and associated interrupt. */ return(y); /* Return the error indication. */ } dest[x] = c; } x++; } dest[x] = '\0'; /* DRE 041890 - null terminate input line */ ALARM(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 = 0; CHAR ch = 0; if (deblog) debug(F100, "funct: tinc ", "", 0); if (ttyfd < 0) return(-1); /* Not open. */ if (timo <= 0) { /* Untimed. */ while ((n = read(0, &ch, 1)) == 0) ; /* Wait for a character. */ if (n == 46) { /* Break and exit if ':' is typed. */ conoll("BREAK"); doexit(BAD_EXIT); } return( (n > 0) ? (ch & 0377) : n ); } SIGNAL(SIGALRM, timerh); /* Timed, set up timer. */ ALARM(timo); if (setjmp(sjbuf)) { n = -1; } else { n = read(0, &ch, 1); /* Otherwise call the system. */ } ALARM(0); /* Turn off timer, */ SIGNAL(SIGALRM, SIG_DFL); /* and interrupt. */ return( (n > 0) ? (ch & 0377) : n ); /* Return char or -1. */ } /* T T S N D B -- Send a BREAK signals */ ttsndb() { int x; long n; char spd; if (deblog) debug(F100, "funct: ttsndb ", "", 0); if (ttyfd < 0) return(-1); /* Not open. */ } /* 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; { if (deblog) debug(F100, "funct: msleep ", "", 0); } /* R T I M E R -- Reset elapsed time counter */ rtimer() { if (deblog) debug(F100, "funct: rtimer ", "", 0); tcount = time( (long *) 0 ); } /* G T I M E R -- Get current value of elapsed time counter in seconds */ gtimer() { int x; if (deblog) debug(F100, "funct: gtimer ", "", 0); x = (int) (time( (long *) 0 ) - tcount); rtimer(); return( (x < 0) ? 0 : x ); } /* Z T I M E -- Return date/time string */ ztime(s) char **s; { long clk; clk=time((long *) 0); *s=ctime(&clk); } /* 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() { if (deblog) debug(F100, "funct: congm ", "", 0); GTTY(0, &ccold); /* Structure for restoring */ GTTY(0, &cccbrk); /* For setting CBREAK mode */ GTTY(0, &ccraw); /* For setting RAW mode */ 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 (deblog) debug(F100, "funct: concb ", "", 0); if (cgmf == 0) congm(); /* Get modes if necessary. */ escchr = esc; /* Make this available to other fns */ ckxech = 1; /* Program can echo characters */ if (x > -1) setbuf(stdout, NULL); /* Make console unbuffered. */ 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 */ } /* C O N R E S -- Restore the console terminal */ conres() { if (deblog) debug(F100, "funct: conres ", "", 0); if (cgmf == 0) return(0); /* Don't do anything if modes */ sleep(1); /* not known! */ ckxech = 0; /* System should echo chars */ return(STTY(0, &ccold)); /* Restore controlling tty */ } /* C O N O C -- Output a character to the console terminal */ conoc(c) char c; { if (deblog) debug(F100, "funct: conoc ", "", 0); write(1, &c, 1); } /* C O N X O -- Write x characters to the console terminal */ conxo(x, s) char *s; int x; { if (deblog) debug(F100, "funct: conxo ", "", 0); 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); if (deblog) debug(F100, "funct: conol ", "", 0); 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; if (deblog) debug(F100, "funct: conola ", "", 0); 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); if (deblog) debug(F100, "funct: conoll ", "", 0); write(1, "\r\n", 2); } /* C O N C H K -- Return how many characters available at console */ conchk() { int x; long n; if (deblog) debug(F100, "funct: conchk ", "", 0); return(0); /* Others can't do. */ } /* C O N I N C -- Get a character from the console */ coninc(timo) int timo; { int n = 0; char ch; if (deblog) debug(F100, "funct: coninc ", "", 0); 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 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 return(-1); } /* A L A R M - this is a dummy alarm() */ ALARM(sec) unsigned sec; { return(1); } /* C H D I R - this is a dummy chdir() */ CHDIR(path) char *path; { return(0); } /* F O R K - this is a dummy fork() */ FORK() { return(1); } /* G T T Y - this is a dummy gtty() */ GTTY(arg1, arg2) int arg1, arg2; { return(0); } /* I O C T L - this is a dummy ioctl() */ IOCTL(fildes, request, arg) int fildes, request, arg; { return(1); } /* K I L L - this is a dummy kill() */ KILL(pid, sig) int pid, sig; { return(0); } /* P A U S E - this is a dummy pause() */ PAUSE() { return(0); } /* S I G N A L - this is a dummy signal() */ SIGNAL(arg1, arg2) int arg1, arg2; { return(0); } /* S T T Y - this is a dummy for stty() */ STTY(arg1, arg2) int arg1, arg2; { return(1); } /* S Y S T E M - this is a dummy for system() */ SYSTEM(cmd) char *cmd; { return(1); } /* W A I T - this is a dummy for wait() */ WAIT(stat_loc) int *stat_loc; { return(1); } /* S Y S C L E A N U P -- System-dependent program cleanup. */ syscleanup() { /* for now, nothing... */ return(0); } /* G E T P W U I D - this is a dummy for getpwuid() */ struct passwd *GETPWUID (uid) int uid; { return ( (struct passwd *) NULL); } /* G E T U I D - this is a dummy for getuid() */ unsigned short GETUID() { return (1); } /* E X E C L - dummy for execl() */ int EXECL (path, arg0, arg1, arg2, arg3, arg4) char *path, *arg0, *arg1, *arg2, *arg3, *arg4; { return (1); } <<< ckvus2.c >>> /* C K U U S 2 -- "User Interface" STRINGS module for NCR-VRX Kermit */ /********************************************************************** * * * IVS / MCS-Kermit REL 2 * * source code * * * * Change History: * * * * 1. Modify C-Kermit(4E) source code to * * produce new module for MCS/IVS-Kermit * * ORIGINAL RELEASE * * June 22, 1990 * * * * * ***********************************************************************/ /* 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 ckuser module. */ #include "ckcdeb.h" #include #include #include "ckcker.h" #include "ckucmd.h" #include "ckuusr.h" #ifdef MCS_FLAG #include "mcs.h" #endif extern CHAR mystch, stchr, eol, seol, padch, mypadc, ctlq; extern CHAR data[], *rdatap, ttname[]; extern char cmdbuf[], line[], debfil[], pktfil[], sesfil[], trafil[]; extern int nrmt, nprm, dfloc, deblog, seslog, speed, local, parity, duplex; extern int send_id, recv_id, send_num, recv_num, send_renum, recv_renum; extern int send_addnum, recv_addnum, rptflg; extern int turn, turnch, pktlog, tralog, mdmtyp, flow, cmask, timef, spsizf; extern int rtimo, timint, npad, mypadn, bctr, delay; extern int maxtry, spsiz, urpsiz, maxsps, maxrps, ebqflg, ebq; extern int rptflg, rptq, fncnv, binary, pktlog, /* warn,*/ quiet, fmask, keep; extern int tsecs, bctu, len, atcapu, lpcapu, swcapu, wsize, sq, rpsiz; extern int capas; extern long filcnt, tfc, tlci, tlco, ffc, flci, flco; extern char *dftty, *versio, *ckxsys; extern struct keytab prmtab[]; extern struct keytab remcmd[]; static char *hlp1[] = { /* unless the kermit CNTLSTR is set up properly this message will never be output */ "\n", " Usage: kermit [-x arg [-x arg]...[-yyy]..]]\n", " x requires an argument, y requires option with no argument:\n", " actions (* options also require -l and -b) --\n", " -s file(s) send\n", " -r receive\n", " -k receive to stdout\n", " -a name alternate name, used with -s, -r, -g\n", " -x enter server mode\n", " * -c connect before transaction\n", " * -n connect after transaction\n", " settings --\n", " -l line communication line device\n", " -b baud line speed, e.g. 1200\n", " -i binary file or NCR-VRX-to-PC (text by default)\n", " -p x parity, x is one of e,o,m,s,n\n", " -t line turnaround handshake = xon, half duplex\n", " -q be quiet during file transfer\n", " -d log debugging info to debuglog\n", " -e length (extended) receive packet length\n", " If no action command is included, enter interactive dialog.\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", " ? (question mark) display help on the current command or field.\n", " \\ (backslash) include the following character literally.\n\n", "\n", "" }; static char *hmxxbye = "V-Kermit does not support this functionality"; static char *hmxxclo = "Close logs: 'help log' for further info."; static char *hmxxcon = "V-Kermit does not support this functionality"; static char *hmxxget = "V-Kermit does not support this functionality"; static char *hmxxlg[] = { "Record information in a log file:\n\n", " debugging Debugging information, to help track down\n", " (default debuglog) bugs in the V-Kermit program.\n\n", " packets Kermit packets, to help track down protocol problems.\n", " (packetlog)\n\n", " transactions Names and statistics about files transferred.\n", " (transactlog)\n", "" }; static char *hmxxlogi[] = { "V-Kermit does not support this functionality\n", "" }; static char *hmxxrc[] = { "V-Kermit does not support this functionality", "" }; static char *hmxxsen = "V-Kermit does not support this functionality"; static char *hmxxser = "Enter server mode. Commands are in packet form from 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 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, 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 systems).\n\n", "'type' is normally 'text', in which conversion is done between NCR-VRX\n", "newlines and CRLF line delimiters; 'binary' means to do no conversion.\n", "Use 'binary' for executable programs or binary data.\n\n", "\n'display' is normally 'on', causing file transfer ", "progress 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[] = { "V-Kermit does not support this functionality", "" }; /* 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: return(hmsg( "Change Working Directory, equivalent to VRX filen command")); */ /* 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.")); 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.")); */ /* case XXGET: return(hmsg(hmxxget)); */ /* case XXHAN: return(hmsg("Hang up the phone.")); */ 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, "Parameter", "")) == -2) return(y); if (y == -2) return(y); if (x = (cmcfm()) < 0) return(x); return(dohset(y)); /* case XXSHE: return(hmsg( "Issue a command to the VRX shell (space req.after '!')")); */ case XXSHO: return(hmsg("Display current values of 'set' parameters.")); /* case XXSPA: return(hmsg("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.")); default: if (x = (cmcfm()) < 0) return(x); #ifndef MCS_FLAG printf("V-Kermit does not support: %s\n", cmdbuf); #else sprintf(print_str,"V-Kermit does not support: %s\n", cmdbuf); mcs_printf(print_str); #endif break; } return(0); } /* H M S G -- Get confirmation, then print the given message */ 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(hmsga(hmxychkt)); /* case XYDELA: puts( "\# of secs to wait before SND first packet after 'send' command."); return(0); */ case XYDUPL: puts("During 'connect': 'full' means remote echoes, "); puts("'half' means this program does its own echoing."); return(0); /* case XYESC: printf( "Dec ASCII for ESC char during 'connect',\n(Control-\\)\n"); return(0); */ case XYFILE: return(hmsga(hmxyf)); case XYFLOW: puts("Type of flow control used. Choices 'xon/xoff' and 'none'."); puts("normally xon/xoff."); return(0); case XYHAND: puts("Dec ASCII for char 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 line' will reset Kermit "); printf("to remote mode.\n"); } return(0); */ /* case XYMODM: puts("Type of modem for dialing remote connections. "); puts(" Needed to indicate modem can"); puts(" be commanded to dial without 'CD' from modem. "); puts(" Many recently") ; puts("manufactured modems use 'hayes' protocol. "); puts("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: #ifndef MCS_FLAG puts("Prompt string for this program, normally 'IVS-Kermit>'."); #else puts("Prompt string for this program, normally 'MCS-Kermit>'."); #endif return(0); case XYRETR: puts("How many times to retransmit a packet before giving up"); return(0); case XYSPEE: puts("Communication line speed for external tty line "); puts("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, 19200."); return(0); case XYRECV: /* puts("Specify parameters for inbound packets:"); puts("End-Of-Packet (ASCII value), Id-Fields ('keep' or 'discard'),"); puts("Line-Numbers ('keep' or 'discard'), Renumber ('on' or 'off'),"); puts("Packet-Length (1000 or less), Padding (amount, 94 or less),"); puts("Pad-Character (ASCII value), Start-Of-Packet (ASCII value),"); puts("and Timeout (94 seconds or less), all specified as decimal numbers"); puts("except for Id-Fields, Line-Numbers and Renumber."); return(0); */ puts("Specify parameters for inbound packets:"); puts(" End-of-Packet (ASCII value), Packet-Length (1000 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."); return(0); case XYSEND: /* puts("Specify parameters for outbound packets:"); puts("End-Of-Packet (ASCII value), Id-Fields ('keep' or 'discard'),"); puts("Line-Numbers ('keep' or 'discard'), Renumber ('on' or 'off'),"); puts("Packet-Length (1000 or less), Padding (amount, 94 or less),"); puts("Pad-Character (ASCII value), Start-Of-Packet (ASCII value),"); puts("and Timeout (94 seconds or less), all specified as decimal numbers"); puts("except for Id-Fields, Line-Numbers and Renumber."); return(0); */ puts("Specify parameters for outbound packets:"); puts(" End-of-Packet (ASCII value), Packet-Length (1000 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."); return(0); default: #ifndef MCS_FLAG printf("V-Kermit does not support: %s\n", cmdbuf); #else sprintf(print_str,"V-Kermit does not support: %s\n", cmdbuf); mcs_printf(print_str); #endif 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); if (x = (cmcfm()) < 0) return(x); #ifndef MCS_FLAG printf("V-Kermit does not support this functionality- %s\n", cmdbuf); #else sprintf(print_str,"V-Kermit does not support this functionality- %s\n", cmdbuf); mcs_printf(print_str); #endif return(-2); } /* D O L O G -- Do the log command */ dolog(x) int x; { int y; char *s; switch (x) { case LOGD: y = cmofi("Name of debugging log file", "debuglog", &s); break; case LOGP: y = cmofi("Name of packet log file", "packetlog", &s); break; /* case LOGS: y = cmofi("Name of session log file","sessionlog",&s); break; */ case LOGT: y = cmofi("Name of transaction log file", "transactlog", &s); break; default: #ifndef MCS_FLAG printf("\n?Unexpected log designator - %d\n", x); #else sprintf(print_str,"\n?Unexpected log designator - %d\n", x); mcs_printf(print_str); #endif return(-2); } if (y < 0) return(y); strcpy(line, s); s = line; if ((y = cmcfm()) < 0) return(y); 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; { char *tp; zclose(ZDFILE); deblog = zopeno(ZDFILE, s); if (deblog > 0) { strcpy(debfil, s); if (deblog) debug(F110, "Debug Log ", versio, 0); if (deblog) debug(F100, ckxsys, "", 0); ztime(&tp); if (deblog) debug(F100, tp, "", 0); } else *debfil = '\0'; return(deblog); } /* S H O P A R -- Show Parameters */ shopar() { int i; extern struct keytab mdmtab[]; extern int nmdm; #ifndef MCS_FLAG printf("\n%s, %s\n", versio, ckxsys); printf("Communications Parameters:\n"); #else sprintf(print_str,"\n%s, %s\n", versio, ckxsys); mcs_printf(print_str); mcs_printf("Communications Parameters:\n"); #endif /* printf(" Line: %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; } } */ #ifndef MCS_FLAG printf(" Bits: %d", (parity) ? 7 : 8); printf(", Parity: "); #else sprintf(print_str," Bits: %d", (parity) ? 7 : 8); mcs_printf(print_str); mcs_printf(", Parity: "); #endif switch (parity) { case 'e': #ifndef MCS_FLAG printf("even"); #else mcs_printf("even"); #endif break; case 'o': #ifndef MCS_FLAG printf("odd"); #else mcs_printf("odd"); #endif break; case 'm': #ifndef MCS_FLAG printf("mark"); #else mcs_printf("mark"); #endif break; case 's': #ifndef MCS_FLAG printf("space"); #else mcs_printf("space"); #endif break; case 0: #ifndef MCS_FLAG printf("none"); #else mcs_printf("none"); #endif break; default: #ifndef MCS_FLAG printf("invalid - %d", parity); #else sprintf(print_str,"invalid - %d", parity); mcs_printf(print_str); #endif break; } #ifndef MCS_FLAG printf(", Duplex: "); #else mcs_printf(", Duplex: "); #endif if (duplex) #ifndef MCS_FLAG printf("half, "); #else mcs_printf("half, "); #endif else #ifndef MCS_FLAG printf("full, "); printf("Flow: "); #else mcs_printf("full, "); mcs_printf("Flow: "); #endif if (flow == 1) #ifndef MCS_FLAG printf("xon/xoff"); #else mcs_printf("xon/xoff"); #endif else if (flow == 0) #ifndef MCS_FLAG printf("none"); #else mcs_printf("none"); #endif else #ifndef MCS_FLAG printf("%d", flow); #else sprintf(print_str,"%d",flow); mcs_printf(print_str); #endif #ifndef MCS_FLAG printf(", Handshake: "); #else mcs_printf(", Handshake: "); #endif #ifndef MCS_FLAG if (turn) printf("%d\n", turnch); #else if (turn) { sprintf(print_str,"%d\n", turnch); mcs_printf(print_str); } #endif else #ifndef MCS_FLAG printf("none\n"); #else mcs_printf("none\n"); #endif /* printf(" Terminal emulation: %d bits\n", (cmask == 0177) ? 7 : 8); */ #ifndef MCS_FLAG printf("\nProtocol & Transfer Parameters: Send Receive"); #else mcs_printf("\nProtocol & Transfer Parameters: Send Receive"); #endif if (timef || spsizf) #ifndef MCS_FLAG printf(" (* = override)"); #else mcs_printf(" (* = override)"); #endif #ifndef MCS_FLAG printf("\n Timeout: %23d%12d", rtimo, timint); #else sprintf(print_str,"\n Timeout: %23d%12d",rtimo,timint); mcs_printf(print_str); #endif if (timef) #ifndef MCS_FLAG printf("*"); #else mcs_printf("*"); #endif #ifndef MCS_FLAG printf("\n Padding: %23d%12d\n", npad, mypadn); printf( " Pad Character:%23d%12d\n", padch, mypadc); printf( " Packet Start: %23d%12d\n", mystch, stchr); printf( " Packet End: %23d%12d\n", seol, eol); printf( " Packet Length:%23d", spsiz); printf( spsizf ? "*" : " " ); #else sprintf(print_str,"\n Padding: %23d%12d\n", npad, mypadn); mcs_printf(print_str); sprintf(print_str," Pad Character:%23d%12d\n", padch, mypadc); mcs_printf(print_str); sprintf(print_str," Packet Start: %23d%12d\n", mystch, stchr); mcs_printf(print_str); sprintf(print_str," Packet End: %23d%12d\n", seol, eol); mcs_printf(print_str); sprintf(print_str," Packet Length:%23d", spsiz); mcs_printf(print_str); sprintf(print_str,(spsizf ? "*" : " ")); mcs_printf(print_str); #endif /* printf("%11d\n", rpsiz); */ #ifndef MCS_FLAG if (urpsiz > 94) printf("%11d (%d)\n", urpsiz, rpsiz); #else if (urpsiz > 94) { sprintf(print_str,"%11d (%d)\n", urpsiz, rpsiz); mcs_printf(print_str); } #endif #ifndef MCS_FLAG else printf("%11d\n", rpsiz); #else else { sprintf(print_str,"%11d\n", rpsiz); mcs_printf(print_str); } #endif /* printf( " ID Fields: "); if (send_id) printf("%23s","keep"); else printf("%23s","discard"); if (recv_id) printf("%12s\n","keep"); else printf("%12s\n","discard"); printf( " Line Numbers: "); if (send_num) printf("%23s","keep"); else printf("%23s","discard"); if (recv_num) printf("%12s\n","keep"); else printf("%12s\n","discard"); printf( " Renumbering: "); if (send_renum) printf("%23s","on"); else printf("%23s","off"); if (recv_renum) printf("%12s\n","on"); else printf("%12s\n","off"); printf( " Number Adding:"); if (send_addnum) printf("%23s","on"); else printf("%23s","off"); if (recv_addnum) printf("%12s\n","on"); else printf("%12s\n","off"); printf(" Block Check Type: %d, Delay: %d\n",bctr,delay); */ #ifndef MCS_FLAG printf(" Block Check Type: %d\n", bctr); #else sprintf(print_str," Block Check Type: %d\n", bctr); mcs_printf(print_str); #endif #ifndef MCS_FLAG if (ebqflg) printf(" 8th-Bit Prefix: '%c'\n", ebq); #else if (ebqflg) { sprintf(print_str," 8th-Bit Prefix: '%c'\n", ebq); mcs_printf(print_str); } #endif #ifndef MCS_FLAG if (rptflg) printf(" Repeat-Count Prefix: '%c'\n", rptq); #else if (rptflg) { sprintf(print_str," Repeat-Count Prefix: '%c'\n", rptq); mcs_printf(print_str); } #endif #ifndef MCS_FLAG printf("\nFile Parameters:\n File Names: "); #else mcs_printf("\nFile Parameters:\n File Names: "); #endif #ifndef MCS_FLAG if (fncnv) printf("%-12s", "converted"); #else if (fncnv) { sprintf(print_str,"%-12s", "converted"); mcs_printf(print_str); } #endif #ifndef MCS_FLAG else printf("%-12s", "literal"); #else else { sprintf(print_str,"%-12s", "literal"); mcs_printf(print_str); } #endif #ifndef MCS_FLAG printf(" Debugging Log: "); #else sprintf(print_str," Debugging Log: "); mcs_printf(print_str); #endif #ifndef MCS_FLAG if (deblog) printf("%s", debfil); #else if (deblog) { sprintf(print_str,"%s", debfil); mcs_printf(print_str); } #endif else #ifndef MCS_FLAG printf("none"); #else mcs_printf("none"); #endif #ifndef MCS_FLAG printf("\n File Type: "); #else mcs_printf("\n File Type: "); #endif #ifndef MCS_FLAG if (binary) printf("%-12s", "binary"); #else if (binary) { sprintf(print_str,"%-12s", "binary"); mcs_printf(print_str); } #endif #ifndef MCS_FLAG else printf("%-12s", "text"); #else else { sprintf(print_str,"%-12s", "text"); mcs_printf(print_str); } #endif #ifndef MCS_FLAG printf(" Packet Log: "); #else mcs_printf(" Packet Log: "); #endif if (pktlog) #ifndef MCS_FLAG printf(pktfil); #else mcs_printf(pktfil); #endif else #ifndef MCS_FLAG printf("none"); #else mcs_printf("none"); #endif /* printf("\n File Warning: "); if (warn) printf("%-12s","on"); else printf("%-12s","off"); printf(" Session Log: "); if (seslog) printf(sesfil); else printf("none"); printf("\n File Display: "); if (quiet) printf("%-12s","off"); else printf("%-12s","on"); printf(" Session Log: "); if (seslog) printf(sesfil); else printf("none"); */ #ifndef MCS_FLAG printf("\n File Byte Size: %-12d", (fmask == 0177) ? 7 : 8); printf(" Transaction Log: "); #else sprintf(print_str,"\n File Byte Size: %-12d", (fmask == 0177) ? 7 : 8); mcs_printf(print_str); mcs_printf(" Transaction Log: "); #endif if (tralog) #ifndef MCS_FLAG printf(trafil); #else mcs_printf(trafil); #endif else #ifndef MCS_FLAG printf("none"); #else mcs_printf("none"); #endif /* printf("\n\nFile Byte Size: %d",(fmask == 0177) ? 7 : 8); */ #ifndef MCS_FLAG printf("\n Incomplete File Disposition: "); #else mcs_printf("\n Incomplete File Disposition: "); #endif if (keep) #ifndef MCS_FLAG printf("keep"); #else mcs_printf("keep"); #endif else #ifndef MCS_FLAG printf("discard"); printf(", Init file: %s", KERMRC); #else mcs_printf("discard"); sprintf(print_str,", Init file: %s", KERMRC); mcs_printf(print_str); #endif puts("\n"); } /* D O S T A T -- Display file transfer statistics. */ dostat() { #ifndef MCS_FLAG 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", tlco); printf(" elapsed time : %d sec\n", tsecs); #else sprintf(print_str,"\nMost recent transaction --\n"); mcs_printf(print_str); sprintf(print_str," files: %ld\n", filcnt); mcs_printf(print_str); sprintf(print_str," total file characters : %ld\n", tfc); mcs_printf(print_str); sprintf(print_str," communication line in : %ld\n", tlci); mcs_printf(print_str); sprintf(print_str," communication line out : %ld\n", tlco); mcs_printf(print_str); sprintf(print_str," elapsed time : %d sec\n", tsecs); mcs_printf(print_str); #endif if (filcnt > 0) { if (tsecs > 0) { long lx; lx = (tfc * 10l) / tsecs; #ifndef MCS_FLAG printf(" effective baud rate : %ld\n", lx); #else sprintf(print_str," effective baud rate : %ld\n", lx); mcs_printf(print_str); #endif if (speed > 0) { lx = (lx * 100l) / speed; #ifndef MCS_FLAG printf(" efficiency : %ld %%\n",lx); #else sprintf(print_str," efficiency : %ld %%\n", lx); mcs_printf(print_str); #endif } } #ifndef MCS_FLAG printf(" packet length : %d (send), %d (receive)\n", spsiz, urpsiz); printf(" block check type used : %d\n", bctu); printf(" compression : "); #else sprintf(print_str, " packet length : %d (send), %d (receive)\n", spsiz, urpsiz); mcs_printf(print_str); sprintf(print_str," block check type used : %d\n", bctu); mcs_printf(print_str); mcs_printf(" compression : "); #endif #ifndef MCS_FLAG if (rptflg) printf("yes [%c]\n", rptq); #else if (rptflg) { sprintf(print_str,"yes [%c]\n", rptq); mcs_printf(print_str); } #endif else #ifndef MCS_FLAG printf("no\n"); printf(" 8th bit prefixing : "); #else mcs_printf("no\n"); mcs_printf(" 8th bit prefixing : "); #endif #ifndef MCS_FLAG if (ebqflg) printf("yes [%c]\n", ebq); #else if (ebqflg) { sprintf(print_str,"yes [%c]\n", ebq); mcs_printf(print_str); } #endif else #ifndef MCS_FLAG printf("no\n\n"); #else mcs_printf("no\n\n"); #endif } else #ifndef MCS_FLAG printf("\n"); #else mcs_printf("\n"); #endif return(0); } /* F S T A T S -- Record file statistics in transaction log */ fstats() { tlog(F100, " end of file", "", 0l); tlog(F101, " file characters ", "", ffc); tlog(F101, " communication line in ", "", flci); tlog(F101, " communication line out ", "", flco); } /* T S T A T S -- Record statistics in transaction log */ tstats() { char *tp; int x; ztime(&tp); /* Get time stamp */ tlog(F110, "End of transaction", tp, 0l); /* Record it */ if (filcnt < 1) return; /* If no files, done. */ /* If multiple files, record character totals for all files */ 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); } /* Record timing info for one or more files */ tlog(F101, " elapsed time (seconds) ", "", (long) tsecs); if (tsecs > 0) { x = (tfc / tsecs) * 10; tlog(F101, " effective baud rate ", "", x); if (speed > 0) { x = (x * 100) / speed; tlog(F101, " efficiency (percent) ", "", x); } } tlog(F100, "", "", 0); /* Leave a blank line */ } /* S D E B U -- Record spar results in debugging log */ sdebu(len) int len; { if (!deblog) return; debug(F111, "spar: data", rdatap, len); debug(F101, " spsiz ", "", spsiz); debug(F101, " timint", "", timint); debug(F101, " npad ", "", npad); debug(F101, " padch ", "", padch); debug(F101, " seol ", "", seol); debug(F101, " ctlq ", "", ctlq); debug(F101, " ebq ", "", ebq); debug(F101, " ebqflg", "", ebqflg); debug(F101, " bctr ", "", bctr); debug(F101, " rptq ", "", rptq); debug(F101, " rptflg", "", rptflg); debug(F101, " atcapu", "", atcapu); debug(F101, " lpcapu", "", lpcapu); debug(F101, " swcapu", "", swcapu); debug(F101, " wsize ", "", wsize); } /* R D E B U -- Debugging display of rpar() values */ rdebu(len) int len; { if (!deblog) return; debug(F111, "spar: data", rdatap, len); debug(F101, " rpsiz ", "", xunchar(data[1])); debug(F101, " rtimo ", "", rtimo); debug(F101, " mypadn", "", mypadn); debug(F101, " mypadc", "", mypadc); debug(F101, " eol ", "", eol); debug(F101, " ctlq ", "", ctlq); debug(F101, " sq ", "", sq); debug(F101, " ebq ", "", ebq); debug(F101, " ebqflg", "", ebqflg); debug(F101, " bctr ", "", bctr); debug(F101, " rptq ", "", data[9]); debug(F101, " rptflg", "", rptflg); debug(F101, " capas ", "", capas); debug(F101, " bits ", "", data[capas]); debug(F101, " atcapu", "", atcapu); debug(F101, " lpcapu", "", lpcapu); debug(F101, " swcapu", "", swcapu); debug(F101, " wsize ", "", wsize); debug(F101, " rpsiz(extended)", "", rpsiz); } <<< ckvus3.c >>> /* C K V U S 3 -- "User Interface" for NCR-VRX Kermit, part 3 */ /********************************************************************** * * * IVS / MCS-Kermit REL 2 * * source code * * * * Change History: * * * * 1. Modify C-Kermit(4E) source code to * * produce new module for MCS/IVS-Kermit * * ORIGINAL RELEASE * * June 22, 1990 * * * * * ***********************************************************************/ /* Author: Frank da Cruz (fdc@cunixc.cc.columbia.edu, FDCCU@CUVMA.BITNET), Columbia University Center for Computing Activities. First released January 1985. Copyright (C) 1985, 1989, 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 functions */ /* Includes */ #include "ckcdeb.h" #include #include #include "ckcker.h" #include "ckucmd.h" #include "ckuusr.h" #ifdef MCS_FLAG #include "mcs.h" #endif /* Variables */ int userpad = SNDPADC; /* storage for the user specified pad char used in spack to reset any SI packet pad char while in server mode */ extern int size, spsiz, rpsiz, urpsiz, npad, timint, rtimo, speed, local, server, lpcapr, fmask, cmask, backgrd, send_id, recv_id, send_num, recv_num, send_renum, recv_renum, send_addnum, recv_addnum, rptflg, flow, displa, binary, fncnv, delay, parity, deblog, escape, xargc, turn, duplex, cxseen, czseen, nfils, ckxech, pktlog, seslog, tralog, stdouf, turnch, bctr, bctu, dfloc, mdmtyp, keep, maxtry, rptflg, ebqflg, /* warn,*/ quiet, cnflg, timef, spsizf, mypadn; extern long filcnt, 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(); extern void errhdlr(); /* Declarations from cmd package */ extern char cmdbuf[]; /* Command buffer */ extern char atmbuf[]; /* Atom buffer */ /* From main ckuser module... */ extern char line[100], *lp; /* Character buffer for anything */ extern char debfil[50], /* Debugging log file name */ pktfil[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[] = { "display", XYFILD, CM_INV, "names", XYFILN, 0, "type", XYFILT, 0 }; int nfilp = (sizeof(filtab) / sizeof(struct keytab ) ); /* Send/Receive Parameters */ struct keytab srtab[] = { "add-linenum", XYADD, CM_INV, "id-fields", XYID, CM_INV, "line-numbers", XYNUM, CM_INV, "end-of-packet", XYEOL, 0, "packet-length", XYLEN, 0, "pad-character", XYPADC, 0, "padding", XYNPAD, 0, "renumber", XYRNUM, CM_INV, "start-of-packet", XYMARK, 0, "timeout", XYTIMO, 0 }; int nsrtab = (sizeof(srtab) / sizeof(struct keytab ) ); /* Flow Control */ struct keytab flotab[] = { "none", 0, 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 */ "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 }; /* Incomplete File Disposition table */ struct keytab ifdtab[] = { "discard", 0, 0, "keep", 1, 0 }; /* Terminal parameters table */ struct keytab trmtab[] = { "bytesize", 0, 0 }; /* D O P R M -- Set a parameter. */ /* Returns: -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: case XYID: case XYNUM: case XYRNUM: case XYADD: #ifndef MCS_FLAG printf("...Use 'set send' or 'set receive' instead.\n"); printf("Type 'help set send' / 'help set receive' for info.\n"); #else mcs_printf("...Use 'set send' or 'set receive' instead.\n"); mcs_printf("Type 'help set send' / 'help set receive' for info.\n"); #endif return(0); case XYIFD: /* Incomplete file disposition */ if ((y = cmkey(ifdtab, 2, "", "discard")) < 0) return(y); if ((x = cmcfm()) < 0) return(x); keep = y; return(0); /* case XYLINE: * if ((x = cmtxt("Device name", dftty, &s)) < 0) * return(x); * ttclos(); * close old line, if any was open * * * * Maybe let ttopen figure it out... * * x = strcmp(s, dftty) ? -1 : dfloc; * if (ttopen(s, &x, mdmtyp) < 0 ) { * Can we open the new line? * * errhdlr("doprm: 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. * * if (deblog) * debug(F111, "set line ", 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); * if (deblog) * debug(F101, "XYDELA: y", "", y); * return(setnum(&delay, x, y, 94)); */ case XYDUPL: if ((y = cmkey(dpxtab, 2, "", "full")) < 0) return(y); if ((x = cmcfm()) < 0) return(x); duplex = y; return(0); case XYESC: 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); case XYFILT: /* Type */ if ((x = cmkey(fttab, 2, "type of file", "text")) < 0) return(x); if ((y = cmnum("file byte size (7 or 8)", "8", 10, &z)) < 0) return(y); if (z != 7 && z != 8) { #ifndef MCS_FLAG printf("\n?The choices are 7 and 8\n"); #else mcs_printf("\n?The choices are 7 and 8\n"); #endif return(-2); } if ((y = cmcfm()) < 0) return(y); binary = x; if (z == 7) fmask = 0177; else if (z == 8) fmask = 0377; return(0); /* case XYFILW: * Warning/Write-Protect * return(seton(&warn)); */ default: #ifndef MCS_FLAG printf("?unexpected file parameter\n"); #else mcs_printf("?unexpected file parameter\n"); #endif 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: /* Handshake */ 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: /* Parity */ if ((y = cmkey(partab, npar, "", "none")) < 0) return(y); if ((x = cmcfm()) < 0) return(x); /* If parity not none, then we also want 8th-bit prefixing */ if (parity = y) ebqflg = 1; else ebqflg = 0; return(0); case XYPROM: #ifndef MCS_FLAG if ((x = cmtxt("Program's command prompt", "IVS-Kermit>", #else if ((x = cmtxt("Program's command prompt", "MCS-Kermit>", #endif &s)) < 0) return(x); if (*s == '\42') { /* Quoted string? */ x = strlen(s) - 1; /* Yes, strip quotes. */ if (*(s + x) == '\42') /* This allows leading or trailing */ *(s + x) = '\0'; /* blanks. */ s++; } cmsetp(s); return(0); case XYRETR: /* Per-packet retry limit */ y = cmnum("Maximum retries per packet", "10", 10, &x); return(setnum(&maxtry, x, y, 94)); case XYTERM: /* Terminal parameters */ if ((y = cmkey(trmtab, 1, "", "bytesize")) < 0) return(y); switch (y) { case 0: if ((y = cmnum("bytesize for terminal connection", "8", 10, &x)) < 0) return(y); if (x != 7 && x != 8) { #ifndef MCS_FLAG printf("\n?The choices are 7 and 8\n"); #else mcs_printf("\n?The choices are 7 and 8\n"); #endif return(-2); } if ((y = cmcfm()) < 0) return(y); if (x == 7) cmask = 0177; else if (x == 8) cmask = 0377; return(y); default: /* Add more cases when we think of more parameters */ return(-2); } /* 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", "13", 10, &x); if ((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 (xx == XYRECV) { /* Receive... */ if ((y = setnum(&z, x, y, MAXRP)) < 0) return(y); urpsiz = z; rpsiz = (z > 94) ? 94 : z; } else { /* Send... */ if ((y = setnum(&z, x, y, MAXSP)) < 0) return(y); spsiz = z; /* Set it and flag that it was set */ spsizf = 1; /* to allow overriding Send-Init. */ } if (z > 94 && !backgrd) #ifndef MCS_FLAG printf("Extended-length packets requested\n"); #else mcs_printf("Extended-length packets requested\n"); #endif 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: /* Padding */ y = cmnum("How many padding characters for inbound packets", "0", 10, &x); if ((y = setnum(&z, x, y, 94)) < 0) return(y); if (xx == XYRECV) mypadn = z; else npad = z; return(y); case XYPADC: /* Pad character */ y = cmnum("Decimal ASCII code for inbound pad character", "0", 10, &x); if ((y = setcc(&z, x, y)) < 0) return(y); if (xx == XYRECV) mypadc = z; else { /* disabling \0 padd char to prevent mcs errors PEG May 16, 1990 */ if (z == 0) { #ifndef MCS_FLAG printf("\nvalid send pad-char 1 - 31 and 127.\n"); #else mcs_printf("\nvalid send pad-char 1 - 31 and 127.\n"); #endif return (-2); } else padch = userpad = z; } return(y); case XYTIMO: y = cmnum("Interpacket timeout interval", "5", 10, &x); if ((y = setnum(&z, x, y, 94)) < 0) return(y); if (xx == XYRECV) { timef = 1; timint = z; } else rtimo = z; return(y); /* case XYID: * Flag for id-fields in SPUR files * * if ((y = cmkey(ifdtab, 2, "", "keep")) < 0) * return(y); * if ((x = cmcfm()) < 0) * return(x); * if (xx == XYRECV) * recv_id = y; * else * send_id = y; * return(0); * case XYNUM: * Flag for line number fields in SPUR files * * if ((y = cmkey(ifdtab, 2, "", "keep")) < 0) * return(y); * if ((x = cmcfm()) < 0) * return(x); * if (xx == XYRECV) * recv_num = y; * else * send_num = y; * return(0); * * * Flag for renumbering line number fields in SPUR files * * case XYRNUM: * if ((y = cmkey(onoff, 2, "", "off")) < 0) * return(y); * if ((x = cmcfm()) < 0) * return(x); * if (xx == XYRECV) * recv_renum = y; * else * send_renum = y; * return(0); * case XYADD: * Flag for adding line number fields in SPUR files * * if ((y = cmkey(onoff, 2, "", "off")) < 0) * return(y); * if ((x = cmcfm()) < 0) * return(x); * if (xx == XYRECV) * recv_addnum = y; * else * send_addnum = y; * return(0); */ } /* 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; * if (!backgrd) * printf("%s: %d baud\n", ttname, speed); * } */ return(0); default: if ((x = cmcfm()) < 0) return(x); #ifndef MCS_FLAG printf("V-Kermit does not support: %s\n", cmdbuf); #else sprintf(print_str,"V-Kermit does not support: %s\n", cmdbuf); mcs_printf(print_str); #endif 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: case 19200: return(x); default: return(-1); } } /* S E T O N -- Parse on/off (default on), set parameter to result */ 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, max) int x, y, *prm, max; { if (deblog) debug(F101, "setnum", "", y); if (y < 0) return(y); if (x > max) { #ifndef MCS_FLAG printf("\n?Sorry, %d is the maximum\n", max); #else sprintf(print_str,"\n?Sorry, %d is the maximum\n", max); mcs_printf(print_str); #endif return(-2); } #ifdef MCS_FLAG if (x == -562) /* value that indicates invalid number */ sprintf(print_str,"\n?not a number - %s\n",atmbuf); #endif if ((y = cmcfm()) < 0) return(y); #ifdef MCS_FLAG /* If we got to here and if something other then a number * was entered, then no back spaces were entered on the line. * So, reparsing is not necessary. Just put out an error msg. */ if (x == -562) { mcs_printf(print_str); return(-2); } #endif *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)) { #ifndef MCS_FLAG printf("\n?Not in ASCII control range - %d\n", x); #else sprintf(print_str,"\n?Not in ASCII control range - %d\n", x); mcs_printf(print_str); #endif 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; { return(-2); /* stub for deleted featured this function should never be called but just in case.. * * int x; * char *s, sbuf[50], *s2; * * if (xx < 0) * return(xx); * switch (xx) { * * case XZCWD: * CWD * * if ((x = cmtxt("Remote directory name", "", &s)) < 0) * return(x); * if (deblog) * 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... * * * if (fgets(sbuf, 50, tfile[tlevel]) == * NULL) * fatal("take file ends prematurely in 'remote cwd'"); * if (deblog) * debug(F110, " pswd from take file", * s2, 0); * for (x = strlen(sbuf); x > 0 && (sbuf[x-1] == * '\n' || sbuf[x-1] == '\r'); x--) * sbuf[x-1] = '\0'; * * } else { * From terminal... * * * printf(" Password: "); * get a password * * while (((x = getchar()) != NL) && (x != * CR)) { * with no echo * * if ((x &= 0177) == '?') { * printf("Remote directory Password: "); * s2 = sbuf; * *sbuf = NUL; * * * Mini command line editor... * * } else if (x == ESC) * putchar(BEL); * else if (x == BS || x == 0177) * s2--; * else if (x == 025) { * Ctrl-U * * s2 = sbuf; * *sbuf = NUL; * } else * *s2++ = x; * } * *s2 = NUL; * putchar('\n'); * } * s2 = sbuf; * } else * s2 = ""; * if (deblog) * 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(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: * Type * * 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) { #ifndef MCS_FLAG printf("?File specification required\n"); #else mcs_printf("?File specification required\n"); #endif return(-2); } if (deblog) 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 */ 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); conoll(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 = 0; } 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 every 4th data packet */ if (n % 4) return; c = '.'; } 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: /* Undelimited text */ if ((p += len) > 78) { conoll(""); p = len; } conol(s); return; case SCR_TN: /* Text delimited at beginning */ conoll(""); conol(s); p = len; return; case SCR_TZ: /* Text delimited at end */ if ((p += len) > 78) { conoll(""); p = len; } conoll(s); return; case SCR_QE: /* Quantity equals */ sprintf(buf, "%s: %ld", s, n); conoll(buf); p = 0; return; default: conoll("*** screen() called with bad object ***"); p = 0; return; } } /* I N T M S G -- Issue message about terminal interrupts */ intmsg(n) long n; { extern char *chstr(); char buf[80]; if ((!displa) || (quiet)) return; if (n == 1) { screen(SCR_TN, 0, 0l, "CTRL-F to cancel file, CTRL-R to resend current packet"); screen(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? */ if (deblog) debug(F101, "conchk", "", cn); while (cn > 0) { /* Yes, read it. */ cn--; /* give read 5 seconds for interrupt character */ if ((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"); continue; 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); } #define TBUFL 300 /* 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[TBUFL]; char *sp = s; int x; if (!tralog) return; /* If no transaction log, don't */ switch (f) { case F000: /* 0 (special) "s1 n s2" */ if (strlen(s1) + strlen(s2) + 15 > TBUFL) sprintf(sp, "?T-Log string too long\n"); else 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'; if (x + 6 > TBUFL) sprintf(sp, "?T-Log string too long\n"); else sprintf(sp, "[%s]\n", s2); zsout(ZTFILE, ""); break; case F011: /* 3, "[s2] n" */ x = strlen(s2); if (s2[x] == '\n') s2[x] = '\0'; if (x + 6 > TBUFL) sprintf(sp, "?T-Log string too long\n"); else sprintf(sp, "[%s] %ld\n", s2, n); zsout(ZTFILE, s); break; case F100: /* 4, "s1" */ zsoutl(ZTFILE, s1); break; case F101: /* 5, "s1: n" */ if (strlen(s1) + 15 > TBUFL) sprintf(sp, "?T-Log string too long\n"); else 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'; if (strlen(s1) + x + 4 > TBUFL) sprintf(sp, "?T-Log string too long\n"); else 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'; if (strlen(s1) + x + 15 > TBUFL) sprintf(sp, "?T-Log string too long\n"); else sprintf(sp, "%s %s: %ld\n", s1, s2, n); zsout(ZTFILE, s); break; default: sprintf(sp, "\n?Invalid format for tlog() - %ld\n", n); zsout(ZTFILE, s); } } /* D E B U G -- Enter a record in 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. */ #define DBUFL 1400 debug(f,s1,s2,n) int f, n; char *s1, *s2; { static char s[DBUFL]; char *sp = s; if (!deblog) return; /* If no debug log, don't */ switch (f) { case F000: /* 0, print both strings, */ if (strlen(s1) + strlen(s2) + 3 > DBUFL) sprintf(sp,"DEBUG string too long\n"); else sprintf(sp,"%s%s%c\n",s1,s2,n); /* 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]" */ if (strlen(s2) + 4 > DBUFL) sprintf(sp,"DEBUG string too long\n"); else sprintf(sp,"[%s]\n",s2); zsout(ZDFILE,""); break; case F011: /* 3, "[s2]=n" */ if (strlen(s2) + 15 > DBUFL) sprintf(sp,"DEBUG string too long\n"); else sprintf(sp,"[%s]=%d\n",s2,n); zsout(ZDFILE,s); break; case F100: /* 4, "s1" */ zsoutl(ZDFILE,s1); break; case F101: /* 5, "s1=n" */ if (strlen(s1) + 15 > DBUFL) sprintf(sp,"DEBUG string too long\n"); else sprintf(sp,"%s=%d\n",s1,n); zsout(ZDFILE,s); break; case F110: /* 6, "s1[s2]" */ if (strlen(s1) + strlen(s2) + 4 > DBUFL) sprintf(sp,"DEBUG string too long\n"); else sprintf(sp,"%s[%s]\n",s1,s2); zsout(ZDFILE,s); break; case F111: /* 7, "s1[s2]=n" */ if (strlen(s1) + strlen(s2) + 15 > DBUFL) sprintf(sp,"DEBUG string too long\n"); else sprintf(sp,"%s[%s]=%d\n",s1,s2,n); zsout(ZDFILE,s); break; /* the interface to call debug() with V110 debug(V110,string1,string2,n); string -> char * n -> strlen(string2) || with binary 0 padding the length returned by MCS */ case V110: { static char stmp[DBUFL]; char *cptr; int i, j; static char hexchar[]={ '0','1','2','3','4','5','6', '7','8','9','A','B','C','D', 'E','F'}; if (n <= 0 || (strlen(s2)+n*2)>DBUFL) sprintf (stmp, "V110 error (n)length=0"); else for (j = 0,i = 0, cptr=s2; j <= n, *cptr=='\0'; j++) { if (*cptr < 0x10) stmp[i++] = '0'; else stmp[i++] = hexchar[(int)*cptr++ / 0x10]; if (*cptr == 0x00) stmp[i++] = '0'; else stmp[i++]= hexchar[(int)*cptr++ % 0x10]; } stmp[i] = '\0'; sprintf(sp, "<%s>%s\n", s1, stmp); } zsout(ZDFILE, s); break; default: sprintf(sp,"\n?Invalid format for debug() - %d\n",n); zsout(ZDFILE,s); } } <<< ckvusr.c >>> char *userv = "User Interface 4E(060), 06 June 90"; /* C K V U S R -- "User Interface" for NCR-VRX Kermit (Part 1) */ /********************************************************************** * * * IVS / MCS-Kermit REL 2 * * source code * * * * Change History: * * * * 1. Modify C-Kermit(4E) source code to * * produce new module for MCS/IVS-Kermit * * ORIGINAL RELEASE * * June 22, 1990 * * * * * ***********************************************************************/ /* 4E, support for Apollo Aegis, Data General added, July 87. */ /* Author: Frank da Cruz (fdc@cunixc.cc.columbia.edu, FDCCU@CUVMA.BITNET), Columbia University Center for Computing Activities. First released January 1985. Copyright (C) 1985, 1989, 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 ckuusr module contains the terminal input and output functions for VRX Kermit. It includes a simple NCR-VRX-style command line parser as well as an interactive prompting keyword command parser. It depends on the existence of VRX facilities like fopen, fgets, feof, (f)printf, argv/argc, etc. Other functions that are likely to vary among VRX 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. The 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 command 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 generic command) cmarg 's' (send files) nfils, cmarg & cmarg2 OR cmlist 'c' (send a remote host command) cmarg cmlist is an array of pointers to strings. cmarg, cmarg2 are pointers to strings. nfils is an integer. cmarg can be a filename string (possibly wild), or a pointer to a prefabricated generic command string, or a pointer to a host command string. cmarg2 is the name to send a single file under, or the name under which 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() functions 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" #include "kermisc.h" #ifdef MCS_FLAG #include "mcs.h" #endif /* External Kermit Variables, see ckmain.c for description. */ extern int EXECL(); extern void errhdlr(); #ifdef MCS_FLAG extern void \:FINISH(); #endif extern int size, rpsiz, urpsiz, speed, local, server, displa, binary, parity, deblog, escape, xargc, flow, turn, duplex, nfils, ckxech, pktlog, seslog, tralog, stdouf, turnch, dfloc, keep, maxrps, /* warn, */ quiet, cnflg, tlevel, send_id, recv_id, send_num, recv_num, send_renum, recv_renum, send_addnum, recv_addnum; extern char *versio, *protv, *ckxv, *ckzv, *fnsv, *connv, *dftty, *cmdv; extern char *dialv, *loginv; extern char *ckxsys, *ckzsys, *cmarg, *cmarg2, **xargv, **cmlist; extern char cmerrp[]; extern CHAR sstate, ttname[]; char *strcpy(), *GETENV(); /* Declarations from cmd package */ extern char cmdbuf[]; /* Command buffer */ extern int cmflgs; /* Command flags */ /* Declarations from ck?fio.c module */ extern char *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[CMDBL+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 */ cwdf = 0; /* CWD has been done */ #define MAXTAKE 20 /* Maximum nesting of TAKE files */ FILE *tfile[MAXTAKE]; /* File pointers for TAKE command */ char *homdir; /* Pointer to home directory string */ char cmdstr[100]; /* Place to build generic command */ /* C M D L I N -- Get arguments from command line */ /* Simple NCR-VRX-style command line parser, conforming with 'A Proposed Command Syntax Standard for NCR-VRX Systems', Hemenway & Armitage, Unix/World, Vol.1, No.3, 1984. */ cmdlin() { char x; /* Local general-purpose int */ cmarg = ""; /* Initialize globals */ cmarg2 = ""; action = cflg = 0; while (--xargc > 0) { /* Go through command line words */ xargv++; if (deblog) 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) doexit(BAD_EXIT); } else { /* No dash where expected */ usage(); doexit(BAD_EXIT); } } if (deblog) debug(F101, "action", "", action); if (!local) { if ((action == 'g') || (action == 'r') || (action == 'c') || (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; quiet = 1; } } if (quiet) displa = 0; /* No display 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; if (deblog) debug(F101,"funct: doarg> x:","",x); xp = *xargv + 1; /* Pointer for bundled args */ while (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("conflicting actions"); * if (*(xp + 1)) * fatal("invalid argument bundling after -s"); * * Initialize file counter, flag * * z = nfils = 0; * * Remember this pointer * * cmlist = xargv + 1; * 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"); * 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"); * } * if (deblog) * debug(F101, *xargv, "", nfils); * action = 's'; * break; * * case 'g': * get * * if (action) * fatal("conflicting actions"); * if (*(xp + 1)) * fatal("invalid argument bundling after -g"); * *xargv++, xargc--; * if ((xargc == 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; * * case '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; * * * * (better than old way) * * local = (strcmp(ttname, CTTNAM) != 0); * if (deblog) * debug(F101, "local", "", local); * ttopen(ttname, &local, 0); * break; * * case 'b': * set baud * * if (*(xp + 1)) * fatal("invalid 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 'e': /* Extended packet length */ if (*(xp + 1)) fatal("invalid argument bundling"); *xargv++, xargc--; if ((xargc < 1) || (**xargv == '-')) fatal("missing length"); z = atoi(*xargv); /* Convert to number */ if (z > 10 && z < maxrps) { rpsiz = urpsiz = z; if (z > 94) rpsiz = 94; /* Fallback if other Kermit can't */ } else fatal("Unsupported packet length"); break; case 'i': /* Treat files as binary */ binary = 1; break; /* case 'w': * File warning * * warn = 1; * break; */ case 'q': /* Quiet */ quiet = 1; break; case 'd': /* debug */ debopn("debuglog"); 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 */ 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); } fatal(msg) char *msg; { /* 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, CM_INV, "%", XXCOM, CM_INV, "bye", XXBYE, CM_INV, "c", XXCON, CM_INV, "cd", XXCWD, CM_INV, "close", XXCLO, 0, "connect", XXCON, CM_INV, "cwd", XXCWD, CM_INV, "dial", XXDIAL, CM_INV, "directory", XXDIR, CM_INV, "echo", XXECH, 0, "exit", XXEXI, 0, "finish", XXFIN, CM_INV, "get", XXGET, CM_INV, "hangup", XXHAN, CM_INV, "help", XXHLP, 0, "log", XXLOG, 0, "quit", XXQUI, 0, "r", XXREC, CM_INV, "receive", XXREC, CM_INV, "remote", XXREM, CM_INV, "s", XXSEN, CM_INV, "script", XXLOGI, CM_INV, "send", XXSEN, CM_INV, "server", XXSER, 0, "set", XXSET, 0, "show", XXSHO, 0, "space", XXSPA, CM_INV, "statistics", XXSTA, 0, "take", XXTAK, 0 }; int ncmd = (sizeof(cmdtab) / sizeof(struct keytab ) ); /* Parameter keyword table */ struct keytab prmtab[] = { "baud", XYSPEE, CM_INV, "add-linenum", XYADD, CM_INV, /* moved to send/receive */ "block-check", XYCHKT, 0, "delay", XYDELA, CM_INV, "duplex", XYDUPL, 0, "end-of-packet", XYEOL, CM_INV, /* moved to send/receive */ "escape-character", XYESC, CM_INV, "file", XYFILE, 0, "flow-control", XYFLOW, 0, "handshake", XYHAND, 0, "id-fields", XYID, CM_INV, /* moved to send/receive */ "incomplete", XYIFD, 0, "line", XYLINE, CM_INV, "line-numbers", XYNUM, CM_INV, /* moved to send/receive */ "modem-dialer", XYMODM, CM_INV, "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, "retry", XYRETR, 0, "renumber", XYRNUM, CM_INV, /* moved to send/receive */ "send", XYSEND, 0, "speed", XYSPEE, CM_INV, "start-of-packet", XYMARK, CM_INV, /* moved to send/receive */ "terminal", XYTERM, CM_INV, "timeout", XYTIMO, CM_INV /* moved to send/receive */ }; int nprm = (sizeof(prmtab) / sizeof(struct keytab ) ); /* How many parameters */ /* Remote Command Table */ struct keytab remcmd[] = { "cd", XZCWD, CM_INV, "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) / sizeof(struct keytab ) ); struct keytab logtab[] = { "debugging", LOGD, 0, "packets", LOGP, 0, "session", LOGS, CM_INV, "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() { tlevel = -1; /* Take file level */ #ifndef MCS_FLAG cmsetp("IVS-Kermit>"); /* Set default prompt */ #else cmsetp("MCS-Kermit>"); /* Set default prompt */ #endif /* Look for init file in home or current directory. */ homdir = zhome(); /* home dir not used */ 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; * if (deblog) * debug(F110, "init file", line, 0); * } * if (homdir && (tlevel < 0)) { * strcpy(lp, KERMRC); * if ((tfile[0] = fopen(line, "r")) != NULL) { * tlevel = 0; * if (deblog) * debug(F110, "init file", line, 0); * } else { * if (deblog) * debug(F100, "no init file", "", 0); * } * } */ /* Look for the init file. In the V environment, the file location is controlled by the filelocation parameter. If CAT or CAT/NOCAT is specified, we'll look in the current subcatalog node. If NOCAT is specified, we'll look on disk. If there is no volume assigned, then we could get a resource not available message. */ strcpy(lp, KERMRC); if ((tfile[0] = fopen(line, "r")) != NULL) { tlevel = 0; if (deblog) debug(F110, "init file", line, 0); } else { if (deblog) debug(F100, "no init file", "", 0); } congm(); /* Get console tty modes */ } /* Display version herald and initial prompt */ herald() { if (!backgrd) #ifndef MCS_FLAG printf("%s\nType ? for help\n", versio); #else sprintf("%s\nType ? for help\n", versio); mcs_printf(print_str); #endif } /* T R A P -- Terminal interrupt handler */ trap() { if (deblog) debug(F100, "terminal interrupt...", "", 0); doexit(GOOD_EXIT); /* Exit indicating success */ } /* S T P T R A P -- Handle SIGTSTP signals */ stptrap() { conres(); /* Reset the console */ doexit(GOOD_EXIT); /* Probably won't happen otherwise */ concb(); /* Put console back in Kermit mode */ } /* P A R S E R -- Top-level interactive command parser. */ char parser() { int xx, cbn; char *cbp; concb(escape); /* Put console 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 && !backgrd) #ifndef MCS_FLAG printf("\n"); /*** Temporary kludge ***/ #else mcs_printf("\n"); /*** Temporary kludge ***/ #endif sstate = 0; /* Start with no start state. */ while (sstate == 0) { /* Parse cmds until action requested */ while ((tlevel > -1) && feof(tfile[tlevel])) { /* If end of take */ fclose(tfile[tlevel--]); /* file, close it. */ cmini(ckxech); /* and clear the cmd buffer. */ if (tlevel < 0) { /* Just popped out of cmd files? */ conint(trap); /* Check background stuff again. */ return(0); /* End of init file or whatever. */ } } if (deblog) debug(F101, "tlevel", "", tlevel); 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++) 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. */ } /* Strip any quotes from cmd buffer. */ stripq(cmdbuf); } else { /* No take file, get typein. */ if (!backgrd) prompt(); /* Issue interactive prompt. */ cmini(ckxech); } repars = 1; displa = 0; while (repars) { cmres(); /* Reset buffer pointers. */ xx = cmkey(cmdtab, ncmd, "Command", ""); if (deblog) 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."); fclose(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. */ *cmdbuf = NUL; /* Clear out the command buffer */ 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) int 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. */ if (deblog) debug(F100, "Debug Log Closed", "", 0); *debfil = '\0'; deblog = 0; zclose(ZDFILE); } if (pktlog) { *pktfil = '\0'; pktlog = 0; zclose(ZPFILE); } /* if (seslog) { packet log disabled from opening *sesfil = '\0'; seslog = 0; zclose(ZSFILE); } */ if (tralog) { tlog(F100, "Transaction Log Closed", "", 0l); *trafil = '\0'; tralog = 0; zclose(ZTFILE); } syscleanup(); #ifndef MCS_FLAG exit(exitstat); /* Exit from the program. */ #else \:FINISH(exitstat); #endif } /* 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 -- Construct 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; if (deblog) debug(F110, "setgen", cmarg, 0); return('g'); } /* C M D N O T I -- Command not implemented message */ cmdnoti() { int c; #ifndef MCS_FLAG printf("\nV-Kermit does not support: %s.\n",cmdbuf); #else sprintf(print_str,"\nV-Kermit does not support: %s.\n",cmdbuf); mcs_printf(print_str); #endif if (cmflgs != 1) { /* The command was not terminated with a carriage return. So there must be something following it on the input line. Since the command was not implemented, we'll flush the rest of the input line. */ while ((c = getchar()) != NL && c != CR) ; } return(0); } /* D O C M D -- Do a command */ /* Returns: -2: user typed an illegal command -1: reparse needed 0: parse was successful (even tho command may have failed). */ docmd(cx) int cx; { int x, y; char *s; char temp[400]; switch (cx) { case -4: /* EOF */ if (!quiet && !backgrd) #ifndef MCS_FLAG printf("\r\n"); #else mcs_printf("\r\n"); #endif doexit(GOOD_EXIT); case -3: /* Null command */ return(0); case -2: /* Error */ case -1: /* Reparse needed */ return(cx); case XXBYE: /* bye */ return(cmdnoti()); /* if ((x = cmcfm()) < 0) * return(x); * if (!local) { * printf("You have to 'set line' first\n"); * return(0); * } * sstate = setgen('L', "", "", ""); * return(0); */ case XXCOM: /* comment */ if ((x = cmtxt("Text of comment line", "", &s)) < 0) return(x); return(0); case XXCON: /* connect */ return(cmdnoti()); /* command not implemented */ /* * if ((x = cmcfm()) < 0) * return(x); * return(doconect()); */ case XXCWD: /* change directory */ return(cmdnoti()); /* command not implemented */ /* * if (cmtxt("Name of local directory, or carriage return", * homdir, &s) < 0) * return(-1); * if (CHDIR(s)) { * sprintf(temp, "docmd: %s", s); * errhdlr(s); * } * cwdf = 1; * return(0); */ case XXCLO: x = cmkey(logtab, nlog, "Which log to close", ""); if (x == -3) { #ifndef MCS_FLAG printf("?You must tell which log\n"); #else mcs_printf("?You must tell which log\n"); #endif return(-2); } if (x < 0) return(x); if ((y = cmcfm()) < 0) return(y); switch (x) { case LOGD: if (deblog == 0) { #ifndef MCS_FLAG printf("?Debugging log wasn't open\n"); #else mcs_printf("?Debugging log wasn't open\n"); #endif return(0); } *debfil = '\0'; deblog = 0; return(zclose(ZDFILE)); case LOGP: if (pktlog == 0) { #ifndef MCS_FLAG printf("?Packet log wasn't open\n"); #else mcs_printf("?Packet log wasn't open\n"); #endif 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(ZSFILE)); */ case LOGT: if (tralog == 0) { #ifndef MCS_FLAG printf("?Transaction log wasn't open\n"); #else mcs_printf("?Transaction log wasn't open\n"); #endif return(0); } *trafil = '\0'; tralog = 0; return(zclose(ZTFILE)); default: #ifndef MCS_FLAG printf("\n?Unexpected log designator - %ld\n", x); #else sprintf(print_str,"\n?Unexpected log designator - %ld\n", x); mcs_printf(print_str); #endif return(0); } case XXDIAL: /* dial number */ return(cmdnoti()); /* command not implemented */ /* * if ((x = cmtxt("Number to be dialed", "", &s)) < 0) * return(x); * return(ckdial(s)); */ case XXDIR: /* list directory */ return(cmdnoti()); /* command not implemented */ /* * if ((x = cmtxt("Directory/file specification", ".", * &s)) < 0) * return(x); * lp = line; * SYSTEM(line); * return(0); */ case XXECH: /* echo */ if ((x = cmtxt("Material to be echoed", "", &s)) < 0) return(x); for ( ; *s; s++) { if ((x = *s) == 0134) { /* Convert octal escapes */ s++; /* up to 3 digits */ for (x = y = 0; *s >= '0' && *s <= '7' && y < 3; s++, y++) { x = x * 8 + (int) *s - 48; } s--; } putchar(x); } #ifndef MCS_FLAG printf("\n"); #else mcs_printf("\n"); #endif return(0); case XXQUI: /* quit, exit */ case XXEXI: if ((x = cmcfm()) > -1) doexit(GOOD_EXIT); else return(x); case XXFIN: /* finish */ return(cmdnoti()); /* command not implemented */ /* if ((x = cmcfm()) < 0) * return(x); * if (!local) { * printf("You have to 'set line' first\n"); * return(0); * } * sstate = setgen('F', "", "", ""); */ case XXGET: /* get */ return(cmdnoti()); /* command not implemented */ /* 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 * * * x = 0; * For some reason cmtxt * returns 1 * * if (*cmarg == NUL) { * * if (tlevel > -1) { * Input is from take file * * * if (fgets(line, 100, tfile[tlevel]) == * NULL) * fatal("take file ends prematurely in 'get'"); * if (deblog) * debug(F110, "take-get 2nd line", * line, 0); * stripq(line); * for (x = strlen(line); x > 0 && (line[x-1] == * '\n' || line[x-1] == '\r'); x--) * line[x-1] = '\0'; * cmarg = line; * if (fgets(cmdbuf, CMDBL, tfile[tlevel]) == * NULL) * fatal("take file ends prematurely in 'get'"); * stripq(cmdbuf); * for (x = strlen(cmdbuf); x > 0 && (cmdbuf[x-1] == * '\n' || cmdbuf[x-1] == '\r'); x--) * cmdbuf[x-1] = '\0'; * if (*cmdbuf == NUL) * cmarg2 = line; * else * cmarg2 = cmdbuf; * x = 0; * Return code * * * } 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; * if (!backgrd) * prompt(); * while (x == -1) { * Prompt till they answer * * x = cmtxt("Name of remote file(s)", * "", &cmarg); * if (deblog) * 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; * * New prompt * * cmsetp(" Local name to store it under: "); * cmini(ckxech); * x = -1; * if (!backgrd) prompt(); * while (x == -1) { * Again, parse till answered * * x = cmofi("Local file name", "", &cmarg2); * } * if (x == -3) { * If bare CR, * * printf("(cancelled)\n"); * escape from this * * cmsetp(psave); * Restore old prompt, * * return(0); * and return. * * } else if (x < 0) * return(x); * Handle parse errors. * * * x = -1; * Get confirmation. * * while (x == -1) * x = cmcfm(); * cmsetp(psave); * Restore old prompt. * * } * } * if (x == 0) { * Good return from cmtxt or * cmcfm, * * sstate = 'r'; * set start state. * * if (local) * displa = 1; * } * return(x); */ case XXHLP: /* Help */ #ifndef MCS_FLAG x = cmkey(cmdtab, ncmd, "IVS-Kermit command", "help"); #else x = cmkey(cmdtab, ncmd, "MCS-Kermit command", "help"); #endif return(dohlp(x)); case XXHAN: /* Hangup */ return(cmdnoti()); /* command not implemented */ /* * if ((x = cmcfm()) > -1) * return(tthang()); */ case XXLOG: /* Log */ x = cmkey(logtab, nlog, "What to log", ""); if (x == -3) { #ifndef MCS_FLAG printf("?You must specify what is to be logged\n"); #else mcs_printf("?You must specify what is to be logged\n"); #endif return(-2); } if (x < 0) return(x); return(dolog(x)); case XXLOGI: /* Send script remote system */ return(cmdnoti()); /* command not implemented */ /* * if ((x = cmtxt("Text of login script", "", &s)) < 0) * return(x); * return( login(s) ); * Return 0=completed, * -2=failed * */ case XXREC: /* Receive */ return(cmdnoti()); /* command not implemented */ /* cmarg2 = ""; * x = cmofi("Name under which to store the file, or CR", * "", &cmarg2); * if ((x == -1) || (x == -2)) * return(x); * if (deblog) * debug(F111, "cmofi cmarg2", cmarg2, x); * if ((x = cmcfm()) < 0) * return(x); * sstate = 'v'; * if (local) * displa = 1; * return(0); */ case XXREM: /* Remote */ return(cmdnoti()); /* command not implemented */ /* * if (!local) { * printf("\nYou have to 'set line' first\n"); * return(-2); * } * 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 */ return(cmdnoti()); /* command not implemented */ /* 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 parsed. * * if (deblog) * 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 * * if (deblog) * debug(F110, "Sending:", cmarg, 0); * if (*cmarg2 != '\0' && deblog) * debug(F110, " as:", cmarg2, 0); * sstate = 's'; * Set start state * * if (local) * displa = 1; * return(0); */ case XXSER: /* Server */ if ((x = cmcfm()) < 0) return(x); sstate = 'x'; if (local) displa = 1; return(0); case XXSET: /* Set */ x = cmkey(prmtab, nprm, "Parameter", ""); if (x == -3) { #ifndef MCS_FLAG printf("?You must specify a parameter to set\n"); #else mcs_printf("?You must specify a parameter to set\n"); #endif 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 do not have SHELL in environment, and to use direct calling of shell rather than intermediate system() call. -- H. Fischer */ case XXSHE: /* Local shell command */ return(cmdnoti()); /* command not implemented */ /* * { * int pid; * if (cmtxt("NCR-VRX shell command to execute", * "", &s) < 0) * return(-1); * conres(); * Make console normal * * * SYSTEM("x :cli prefix Kermit_Baby:"); * * if ((pid = FORK()) == 0) { * Make child * * char *shpath, *shname, *shptr; * * For finding desired shell * * struct passwd *p; * extern struct passwd *GETPWUID(); * 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; * * * Remove following uid calls if they cause trouble * * * if (*s == NUL) * Interactive shell requested? * * EXECL(shpath, shname, "-i", * NULL); * Yes, do that * * else * Otherwise, * * EXECL(shpath, shname, "-c", * s, NULL); * exec the given command * * exit(BAD_EXIT); * } * Just punt if it didn't work * * else { * Parent * * * int wstat; * Kermit must wait for child * * SIGTYP (*istat)(), (*qstat)(); * * istat = SIGNAL(SIGINT, SIG_IGN); * Let the fork handle * keyboard * * qstat = SIGNAL(SIGQUIT, SIG_IGN); * interrupts itself * * * while (((wstat = WAIT((int *)0)) != * pid) && (wstat != -1)) * ; * * Wait for fork * * SIGNAL(SIGINT, istat); * Restore interrupts * * SIGNAL(SIGQUIT, qstat); * } * concb(escape); * Console back 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: #ifndef MCS_FLAG printf("\nVersions:\n %s\n %s\n", versio, protv); printf(" %s\n", fnsv); printf(" %s\n %s\n", cmdv, userv); printf(" %s for%s\n", ckxv, ckxsys); printf(" %s for%s\n", ckzv, ckzsys); #else sprintf(print_str,"\nVersions:\n %s\n %s\n", versio, protv); mcs_printf(print_str); sprintf(print_str," %s\n", fnsv); mcs_printf(print_str); sprintf(print_str," %s\n %s\n", cmdv, userv); mcs_printf(print_str); sprintf(print_str," %s for%s\n", ckxv, ckxsys); mcs_printf(print_str); sprintf(print_str," %s for%s\n", ckzv, ckzsys); mcs_printf(print_str); #endif break; default: printf("\nNothing to show...\n"); break; } return(0); case XXSPA: /* space */ return(cmdnoti()); /* command not implemented */ /* * if ((x = cmcfm()) < 0) * return(x); * return(0); */ case XXSTA: /* statistics */ if ((x = cmcfm()) < 0) return(x); return(dostat()); case XXTAK: /* take */ if (tlevel > MAXTAKE - 1) { #ifndef MCS_FLAG printf("?Take files nested too deeply\n"); #else mcs_printf("?Take files nested too deeply\n"); #endif return(-2); } #ifndef MCS_FLAG if ((y = cmifi("IVS-Kermit command file", "", &s, &x)) < #else if ((y = cmifi("MCS-Kermit command file", "", &s, &x)) < #endif 0) { if (y == -3) { #ifndef MCS_FLAG printf("?A file specification is required\n"); #else mcs_printf("?A file specification is required\n"); #endif return(-2); } else return(y); } if (x != 0) { #ifndef MCS_FLAG printf("?Wildcards not allowed in command file name\n"); #else mcs_printf("?Wildcards not allowed in command file name\n"); #endif 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) { sprintf(temp, "docmd: %s", line); errhdlr(temp); if (deblog) debug(F110, "Failure to open", line, 0); tlevel--; } return(0); default: #ifndef MCS_FLAG printf("V-Kermit does not support: %s\n", cmdbuf); #else sprintf(print_str,"V-Kermit does not support: %s.\n",cmdbuf); mcs_printf(print_str); #endif return(-2); } } /* D O C O N E C T -- Do the connect command */ /* Note, we don't call this directly from dial, because we need to give */ /* the user a chance to change parameters (e.g. parity) after the */ /* connection is made. */ doconect() { int x; conres(); /* Put console back to normal */ x = conect(); /* Connect */ concb(escape); /* Put console into cbreak mode, */ return(x); /* for more command parsing. */ } <<< compile.ins >>> IVS-Kermit cOmpilation instructions: From an IVS session or SCL procedure file: REC (L=2500,V=1500,STAC=250,PROT=600); CC(FN=FILENAME_C,LNK=NO,OPTM=TRUE,GLBOPT='-R -o FILENAME_O', POPT='-bo -X1',COPT='-b -Xv');!" ***NOTE*** IVS-Kermit object modules end in _O. MCS-Kermit modules end in _M. This is done to separate MCS-Kermit object from IVS-Kermit object. There are several common object modules between MCS / IVS-Kermit, they do not require the _M convention. Any naming convention is exceptable, as long as the modules are separated. The common object modules are listed below. Common object modules: BIND=CKVFN2_O BIND=CKVFNS_O BIND=CKVFI2_O BIND=CKVFIO_O BIND=VKNCRLIO NCRL source module BIND=CKVMCS_O *** COMPILE USING IVS INSTRUCTIONS BIND=CKVBUF_O *** COMPILE USING IVS INSTRUCTIONS MCS-Kermit compilation instructions: From an IVS session or SCL procedure file: REC (L=2500,V=1500,STAC=250,PROT=600); CC(FN=FILENAME_C,LNK=NO,OPTM=TRUE,GLBOPT='-R -o FILENAME_M', POPT='-bo -X1 -D MCS_FLAG',COPT='-b -Xv');!" <<< ivskpm.pro >>> PROCEDURE IVSKPM(COMMAND : STRING := ' '); % % ************************ % * COPYRIGHT NCR CORP. * % * DAYTON, OHIO * % * 1990 * % ************************ % % ************************************************* % * % * THIS SCL PROCEDURE FILE INITIALIZES IVS-KERMIT % * FOR TRANSFERRING % * FILES TO THE CATALOG OR SUD=D02 % * % * CREATED BY THE V-KERMIT PROJECT TEAM ON 8-18-89 % * % * % ************************************************* % DISPLAY : ' BEGINNING IVSKPM FOR IVS-KERMIT FILE TRANSFERS.'; DISPLAY : ' FOR GENERIC FILE USE.'; DISPLAY : ' UPDATED ON 6-20-90.'; DISPLAY : ' '; DISPLAY : ' IVS-KERMIT 2.01 NOW HANDLES:'; DISPLAY : ' 1000 BYTE PACKETS.'; DISPLAY : ' '; DISPLAY : ' MOVE kermrc TO YOUR'; DISPLAY : ' SOURCE/DESTINATION CATALOG NODE'; DISPLAY : ' AND SUD=D02'; DISPLAY : ' BEFORE CONTINUING.'; DISPLAY : ' '; DISPLAY : ' REFER TO THE V-KERMIT FS FOR MS-DOS FILE NAME EXTENSIONS'; DISPLAY : ' USED FOR VRX FILES.'; DISPLAY : ' '; DISPLAY : ' EXAMPLES ARE: FN.N3(JOB),FN.PRO(SCL PROC),FN.C(C),'; DISPLAY : ' FN.CO(COBOL),FN.NCR(NCRL),FN.NC(NEAT/C),'; DISPLAY : ' FN.BIN(BINARY DATA FILE).'; DISPLAY : ' OBJECT FILES(USE FN.OBJ).'; DISPLAY : ' '; DISPLAY : ' WARNINGS:'; DISPLAY : ' IF YOUR IVS SESSION USES A DSP COMM PORT,'; DISPLAY : ' MAX PACKET SIZE IS 222.'; DISPLAY : ' '; % % ************************************************* % * VARIABLE DEFINITIONS % ************************************************* % LOCAL MSG : STRING, ENV : STRING, VSN : STRING, DTYPE : STRING, VOL_INT : INTEGER, NODE : STRING, NODENAME : NAME, ACTION : STRING, P1 : PROCESS, VMEM_IVSK : INTEGER, LDSA_IVSK : INTEGER, PDSA_IVSK : INTEGER, FILESIZ : STRING, RSTRT_FLAG: BOOLEAN, DEFAULTS : STRING, ORG_CHOICE : STRING, REC_TYPE : STRING; % % ************************************************* % RSTRT_FLAG := FALSE; FILESIZ := '500'; % FILEL CAT/NOCAT; % FILEC CAT; % DISPLAY : ' PLEASE WAIT.'; BEGIN % IF (MYJOB(VMAXMEM) < 800); THEN MYJOB(VMAXMEM) := 800; DISPLAY : ' TOO LITTLE VMAXMEM,'; DISPLAY : ' VMAXMEM HAS BEEN SET TO 800.'; RSTRT_FLAG := TRUE; VMEM_IVSK := 800; ELSE VMEM_IVSK := MYJOB(VMAXMEM); IFEND; % IF (MYJOB(LOCALDSA) < 1000); THEN MYJOB(LOCALDSA) := 1000; DISPLAY : ' TOO LITTLE LOCALDSA,'; DISPLAY : ' LOCALDSA HAS BEEN SET TO 1000.'; RSTRT_FLAG := TRUE; LDSA_IVSK := 1000; ELSE LDSA_IVSK := MYJOB(LOCALDSA); IFEND; % IF (MYJOB(PROTECTDSA) < 800); THEN MYJOB(PROTECTDSA) := 800; DISPLAY : ' TOO LITTLE PROTECTDSA,'; DISPLAY : ' PROTECTDSA HAS BEEN SET TO 800.'; RSTRT_FLAG := TRUE; PDSA_IVSK := 800; ELSE PDSA_IVSK := MYJOB(PROTECTDSA); IFEND; % IF (RSTRT_FLAG = TRUE); THEN RSTRT_FLAG := FALSE; DISPLAY : ' RE-EXECUTE IVSKP.'; REC(V=#VMEM_IVSK,LOCALDSA=#LDSA_IVSK,PROTECTDSA=#PDSA_IVSK); RETURN : ' END OF IVSKP.'; IFEND; % END; % % ********************************************* % * SOLICITATION OF SETUP OPTIONS FOR MICKEY % * USER ACCEPTS DEFAULTS(DEFAULTS IN PARENS)? % * -FILE SOURCE/DEST(CAT) % * -NODE(USER CURRENT) % * -VOLUME/TYPE(CURRENT D02) % * -FILE SPECIFICATIONS FOR REF=DATAFILE % * -PRINTER FONT/FORM UPLOADS(NO) % * -FILESIZE FOR D02 AND FONT/FORMS(500 BLOCKS) % * -FIXED LENGTH DATAFILE RECORDS(NO) % * % ******************************************************* % % DISPLAY : ' PLEASE WAIT.'; BEGIN % % ****************************************************** % * ASKING USER FOR ACCEPTANCE OF DEFAULTS % * % ****************************************************** % DISPLAY : ' '; DISPLAY : ' '; DISPLAY : ' PLEASE SELECT THE IVS-KERMIT ENVIRONMENT.'; DISPLAY : ' '; DISPLAY : ' THE IVS-KERMIT ENVIRONMENT DEFAULTS ARE:'; DISPLAY : ' '; DISPLAY : ' DATA FILES WITH:'; DISPLAY : ' - SEQUENTIAL ORGANIZATION.'; DISPLAY : ' (THERE IS A CHOICE FOR RELATIVE(FONT/FORM) '; DISPLAY : ' FILE STRUCTURE.)'; DISPLAY : ' - FILESIZE OF 500/BLOCKS '; DISPLAY : ' - VARIABLE LENGTH RECORDS '; DISPLAY : ' '; DISPLAY : ' FILE SOURCE/DESTINATION OF:'; DISPLAY : ' - USER CURRENT NODE IN CATALOG.'; DISPLAY : ' '; DISPLAY : ' DO YOU WANT TO ACCEPT THESE DEFAULTS? [Y,N]'; DISPLAY : ' DEFAULT IS YES.'; ACCEPT DEFAULTS; % IF (SUBSTRING(DEFAULTS,0,1) /= 'N') THEN DEFAULTS := 'YES'; ENV := 'CAT'; REC_TYPE := 'VAR'; ORG_CHOICE := 'NO'; FILESIZ := '500'; GOTO TAG5; IFEND; % % % % ******************************************************* % * DEFAULTS NOT ACCEPTED % ******************************************************* DISPLAY : ' WILL YOU UPLOAD PRINTER FONT/FORM FILES? [Y,N]'; DISPLAY : ' IF YES, ALL DATA FILES WILL HAVE'; DISPLAY : ' THE RELATIVE ORGANIZATION.'; DISPLAY : ' DEFAULT IS NO.'; ACCEPT ORG_CHOICE; % IF (SUBSTRING(ORG_CHOICE,0,1) = 'Y') THEN ORG_CHOICE := 'YES'; REC_TYPE := 'VAR'; ELSE ORG_CHOICE := 'NO'; % % **************************************************** % * ASKING FOR FIXED/VARIABLE RECORD TYPE. % **************************************************** DISPLAY : ' DO YOU WANT DATAFILES TO HAVE FIXED OR'; DISPLAY : ' VARIABLE LENGTH RECORDS? [F,V]'; DISPLAY : ' DEFAULT IS VARIABLE.'; ACCEPT REC_TYPE; % IF (SUBSTRING(REC_TYPE,0,1) /= 'F') THEN REC_TYPE := 'VAR'; ELSE REC_TYPE := 'FIX'; IFEND; % IFEND; % % ****************************************************** % * ASKING FOR FILE SOURCE/DESTINATION. % ****************************************************** % $TAG2 DISPLAY : ' SELECT IVS-KERMIT SOURCE/DESTINATION ENVIRONMENT. ' ; MSG := ' DEFAULT ENVIRONMENT IS CATALOG. [CAT,DISK]'; DISPLAY : MSG; ACCEPT ENV; % IF ((SUBSTRING(ENV,0,1) /= 'C') AND (SUBSTRING(ENV,0,1) /= 'D') AND (SUBSTRING(ENV,0,1) /= '')) THEN GOTO TAG2; IFEND; % IF ((SUBSTRING(ENV,0,1) = 'C') OR (SUBSTRING(ENV,0,1) = '')) THEN % ****************************************************** % * CATALOG SELECTED;ASKING FOR NODE. % ****************************************************** $TAG3 DISPLAY : ' PLEASE ENTER SUBCATALOG NODE NAME. ' ; DISPLAY : ' USE SINGLE QUOTES. EX: ''$.NODE.NODE''.'; MSG := ' DEFAULT IS THE USER CURRENT NODE.'; DISPLAY : MSG; ACCEPT NODE; % IF (NODE = '') THEN GOTO TAG5; ELSE NODENAME := #NODE; FILENODE #NODENAME [P1]; IFEND; % IF (P1(STATUS) /= COMPLETED) THEN DISPLAY : ' CANT POSITION TO ' & #NODE & '.'; MSG := ' DO YOU WANT TO TRY ANOTHER SUBCATALOG? [Y,N].'; DISPLAY : MSG; ACCEPT ACTION; % IF (SUBSTRING(ACTION,0,1) = 'N') THEN RETURN : ' END OF IVSKPM'; ELSE GOTO TAG3; IFEND; % IFEND; % $TAG5 DISPLAY : ' '; DISPLAY :' IVS-KERMIT USING CATALOG ENVIRONMENT.' ; % * FILEC OF CAT IS TO KNOW WHERE STDERR WILL BE. FILEC CAT; FILEN; % IF (SUBSTRING(ORG_CHOICE,0,1) = 'Y') THEN % % ********************************************* % * FILE 'REFERENCE' OF 'DATAFILE' IS USED FOR % * FONT/FORM FILES % * % * FILESIZE MUST BE FOR THE LARGEST % * FILE ANTICIPATED BECAUSE RELATIVE FILES ARE NOT RMS. % * % ************************************************ % % IF (DEFAULTS /= 'YES') THEN % ********************************************* % * ASKING ABOUT FILE SIZE % * IN THE CATALOG,VARIABLE,FONT/FORM CASE. % * % * FONT/FORM FILES % * % * FILESIZE MUST BE FOR THE LARGEST % * FILE ANTICIPATED BECAUSE RELATIVE FILES % * ARE NOT RMS. % * % ************************************************ % % DISPLAY : ' '; DISPLAY : ' SPECIFY FILESIZE VALUE FOR DATAFILE REFERENCE'; DISPLAY : ' THAT IS BIG ENOUGH TO HOLD THE LARGEST '; DISPLAY : ' FONT/FORM FILE TO BE UPLOADED.'; DISPLAY : ' DEFAULT FILESIZE IS 500/BLOCKS.'; ACCEPT FILESIZ; % IF ((SUBSTRING(FILESIZ,0,1) = '') OR (SUBSTRING(FILESIZ,0,1) = 'A')) THEN FILESIZ := '500'; IFEND; % IFEND; % % ************************************************ % * ASSIGNING REF=DATAFILE % * IN THE FONT/FORM CASE USING CATALOG. % ************************************************ ASSIGN FILE DATAFILE(REF=DATAFILE, % ************************************ % * THE FOLLOWING 5 PARAMETERS ARE % * FOR FONT/FORM UPLOADS % ************************************ ORGANIZATION=RELATIVE, BLOCKSIZE=1/RECORDS, CAMHEADER, RECORDSIZE=1/485, FILESIZE=#FILESIZ/BLOCKS, DATESCHEME=GEN,FILETYPE=DATA,FREEUP,CATALOG); ELSE % IF (SUBSTRING(REC_TYPE,0,1) = 'F') THEN % % ************************************************ % * ASSIGNING REF=DATAFILE % * IN THE FIXED LENGTH RECORDS, NON FONT/FORM % * CASE USING CATALOG. % ************************************************ ASSIGN FILE DATAFILE(REF=DATAFILE,RMS=YES, % ************************************ % * THE FOLLOWING PARAMETERS ARE % * FOR FIXED LENGTH RECORDS % ************************************ RECORDSIZE=80, DATESCHEME=GEN,FILETYPE=DATA,FREEUP,CATALOG); ELSE % % ******************************************* % * FILE 'REFERENCE' OF 'DATAFILE' IS USED FOR % * BINARY AND TEXT 'DATA' FILES % * % * % ******************************************* % % % ************************************************ % * ASSIGNING REF=DATAFILE % * IN THE VARIABLE LENGTH RECORDS, NON FONT/FORM % * CASE USING CATALOG. % * % * THIS IS CONSIDERED TO BE THE OVERALL % * DEFAULT CASE. % * % ************************************************ ASSIGN FILE DATAFILE(REF=DATAFILE,RMS=YES, RECORDSIZE=1/485, DATESCHEME=GEN,FILETYPE=DATA,FREEUP,CATALOG); IFEND; % IFEND; % **************************************************** % * ASSIGNING THE OTHER FILE REFERENCES IN THE % * CATALOG CASE. % **************************************************** ASSIGN FILE SRCFILE(REF=SRCFILE,RMS=YES,FILESIZE='NO LIMIT', RECORDSIZE=1/83, DATESCHEME=GEN,FILETYPE=SOURCE,FREEUP,CATALOG), FILE OBJFILE(REF=OBJFILE,RMS=YES,FILESIZE='NO LIMIT', RECORDSIZE=1/490, DATESCHEME=GEN,FILETYPE=OBJECT,FREEUP,CATALOG), FILE CSFILE(REF=CSFILE,RMS=YES,FILESIZE='NO LIMIT', FREEUP,DATESCHEME=GEN, RECORDSIZE=1/82, FILETYPE='CONTROL STRING',CATALOG); % **************************************************** % * END OF THE CATALOG CASE. % **************************************************** ELSE % ****************************************************** % * BEGINNING OF THE SUD=D02 CASE. % ****************************************************** DISPLAY : ' '; DISPLAY :' IVS-KERMIT USING NON-CATALOG ENVIRONMENT.' ; $TAG4 % ****************************************************** % * ASKING ABOUT SUD=D02. % ****************************************************** DI PER; DISPLAY : ' PLEASE ENTER(IN QUOTES) VOLUME NUMBER AND DEVICE TYPE.' ; DISPLAY : ' FOR EXAMPLE (''525252/BA'')'; DISPLAY : ' OR [CONTINUE] TO USE CURRENT D02.'; ACCEPT VSN; % IF (SUBSTRING(VSN,0,1) = 'C') THEN DISPLAY : ' IVS-KERMIT USING CURRENT D02.'; ELSE VOL_INT := INT(SUBSTRING(VSN,0,6)); DTYPE := SUBSTRING(VSN,7,2); ASSIGN UNIT D02(SUD=D02,VOL=#VOL_INT,TYPE=#DTYPE) [P1]; % IF (P1(STATUS) /= COMPLETED) THEN DISPLAY : ' CANT ASSIGN VOLUME ' & SUBSTRING(VSN,0,6) & ' WITH DEVICE TYPE ' & DTYPE & '. ' ; MSG := ' DO YOU WANT TO TRY ANOTHER VOLUME? '; DISPLAY : MSG; DISPLAY : ' OR CONTINUE WITH CURRENT D02? [Y,N,CONTINUE]'; ACCEPT ACTION; % IF (SUBSTRING(ACTION,0,1) = 'N') THEN RETURN : ' END OF IVSKPM'; ELSE % IF (SUBSTRING(ACTION,0,1) /= 'C') THEN GOTO TAG4; ELSE VSN := ''; DISPLAY : ' '; DISPLAY : ' IVS-KERMIT USING CURRENT D02.'; IFEND; % IFEND; % ELSE % IF(VSN /= '') THEN DISPLAY : ' '; DISPLAY : ' IVS-KERMIT USING VOLUME ' & #VSN & '.'; IFEND; % IFEND; % IFEND; % ******************************************* % * ASKING ABOUT FILE SIZE % * IN THE D02 CASE. % * % * % * % * % ******************************************* % % % ********************************************* % * FILE 'REFERENCE' OF 'DATAFILE' IS USED FOR % * BINARY AND TEXT 'DATA' FILES % * % * FILESIZE MUST BE FOR THE LARGEST % * FILE ANTICIPATED % * % ************************************************ % % DISPLAY : ' '; DISPLAY : ' ENSURE THAT ENOUGH SPACE EXISTS ON D02'; DISPLAY : ' FOR THE LARGEST UPLOADED FILE.'; DISPLAY : ' ENSURE THAT THE D02 DATAFILE FILESIZE PARAMETER'; DISPLAY : ' IS BIG ENOUGH TO HOLD THE LARGEST FILE.'; DISPLAY : ' '; DISPLAY : ' SPECIFY FILESIZE VALUE FOR D02 DATAFILE REFERENCE'; DISPLAY : ' USED BY DATA FILES.'; DISPLAY : ' DEFAULT FILESIZE IS 500/BLOCKS.'; ACCEPT FILESIZ; % IF ((SUBSTRING(FILESIZ,0,1) = '') OR (SUBSTRING(FILESIZ,0,1) = 'A')) THEN FILESIZ := '500'; IFEND; % IF (SUBSTRING(ORG_CHOICE,0,1) = 'Y') THEN % % % ************************************************ % * ASSIGNING REF=DATAFILE % * IN THE FONT/FORM CASE USING D02. % ************************************************ ASSIGN FILE DATAFILE(REF=DATAFILE,RMS=NO,SUD=D02,FREEUP, DATESCHEME=GEN,NOCAT, FILESIZE=#FILESIZ/BLOCKS, % ************************************ % * THE FOLLOWING 4 PARAMETERS ARE % * FOR FONT/FORM UPLOADS % ************************************ ORGANIZATION=RELATIVE, BLOCKSIZE=1/RECORDS, CAMHEADER, RECORDSIZE=1/485, FILETYPE=DATA); ELSE % IF (SUBSTRING(REC_TYPE,0,1) = 'F') THEN % % % ************************************************ % * ASSIGNING REF=DATAFILE % * IN THE FIXED LENGTH RECORD, NON FONT/FORM CASE % * USING D02. % * % * THIS IS CONSIDERED TO BE THE % * 'FIXED ACQUISITION' CASE. % ************************************************ ASSIGN FILE DATAFILE(REF=DATAFILE,RMS=NO,SUD=D02,FREEUP, DATESCHEME=GEN,NOCAT, FILESIZE=#FILESIZ/BLOCKS, % ************************************ % * THE FOLLOWING PARAMETERS ARE % * FOR FIXED LENGTH RECORDS % ************************************ RECORDSIZE=80, FILETYPE=DATA); ELSE % % % ************************************************ % * ASSIGNING REF=DATAFILE % * IN THE VARIABLE LENGTH RECORD, NON FONT/FORM % * CASE USING D02. % ************************************************ % % ******************************************* % * FILE 'REFERENCE' OF 'DATAFILE' IS USED FOR % * BINARY AND TEXT 'DATA' FILES % * % * % ******************************************* % ASSIGN FILE DATAFILE(REF=DATAFILE,RMS=NO,SUD=D02,FREEUP, DATESCHEME=GEN,NOCAT, FILESIZE=#FILESIZ/BLOCKS, RECORDSIZE=1/485, FILETYPE=DATA); IFEND; % IFEND; % % % % **************************************************** % * ASSIGNING THE OTHER FILE REFERENCES IN THE % * D02 CASE. % **************************************************** % ASSIGN FILE SRCFILE(REF=SRCFILE,RMS=NO,SUD=D02,FREEUP, RECORDSIZE=1/82, FILESIZE=200/BLOCKS,DATESCHEME=GEN,NOCAT, FILETYPE=SOURCE), FILE OBJFILE(REF=OBJFILE,RMS=NO,SUD=D02,FREEUP, FILESIZE=1000/BLOCKS,RECORDSIZE=1/490, DATESCHEME=GEN,FILETYPE=OBJECT,NOCAT), FILE CSFILE(REF=CSFILE,RMS=NO,SUD=D02,FREEUP, FILESIZE=200/BLOCKS,RECORDSIZE=1/82,NOCAT, DATESCHEME=GEN,FILETYPE='CONTROL STRING'); % % % FILEL NOCAT; % * FILEC IS TO KNOW WHERE STDERR WILL BE. FILEC NOCAT; % ****************************************************** % * END OF THE SUD=D02 CASE. % ****************************************************** IFEND; % END; % % ********************************************* TERMCHNG('796401'); DEPOT(UNSOLICITED=DROP); DEPOT(WIDTH=2048); DEPOT(LENGTH=999); DEPOT(WAIT=FALSE); % % ************************************************ % ARGS := #COMMAND & ' 2> STDERR '; DISPLAY : ' '; DISPLAY : ' EXECUTING LOAD MODULE WERMIT.'; % % MUST SPECIFY LOCATION OF LOAD MODULE IVSKERM(ARGS); DISPLAY : ' IVS-KERMIT TERMINATED.'; % BEGIN DISPLAY : ' PRINTING IVS-KERMIT TRANSFER HISTORY LOG(STDERR).'; DISPLAY : ' PLEASE WAIT.'; PUSH; FREE DEFAULT_PRINTER; ASSIGN PRINTER DEFAULT_PRINTER(SUD=P01); % IF (VSN /= '') THEN EXECUTE PRINT,SPEC='(NAME=STDERR,AGE=NEW,SUD=D02,NOCAT' & ') FORMAT=RECORDS,ASCII ONLY;'; ELSE EXECUTE PRINT,SPEC='(NAME=STDERR,AGE=NEW) FORMAT=RECORDS,ASCII ONLY;'; IFEND; % QUEUE DEFAULT_PRINTER; FREE DEFAULT_PRINTER; ASSIGN PRINTER DEFAULT_PRINTER(SUD=P01,TYPE=TERMINAL); POP; DISPLAY : ' END OF PRINTING STDERR.'; END; % IF (VSN /= '') THEN FREE D02; IFEND; % FREE DATAFILE; FREE SRCFILE; FREE OBJFILE; FREE CSFILE; % FILEL CAT/NOCAT; % FILEC CAT; % IF ( NODE = '') THEN FILEN; ELSE FILEN USER; FILEN; IFEND; % DEPOT(UNSOLICITED=NOTIFY); DEPOT(WIDTH=80); DEPOT(LENGTH=23); DEPOT(WAIT=TRUE); DISPLAY : ' END OF IVSKP.'; PROCEND IVSKPM; <<< kermisc.h >>> /********************************************************************** * * * IVS / MCS-Kermit REL 2 * * source code * * * * Change History: * * * * 1. Modify C-Kermit(4E) source code to * * produce new module for MCS/IVS-Kermit * * ORIGINAL RELEASE * * June 22, 1990 * * * * * ***********************************************************************/ #define SIG_DFL (int (*)())0 #define SIG_IGN (int (*)())1 extern int (*ssignal())(); #define SIGINT 2 /* interrupt (rubout) */ #define SIGQUIT 3 /* quit (ASCII FS) */ #define SIGILL 4 /* illegal instruction (not reset when caught)*/ #define SIGTRAP 5 /* trace trap (not reset when caught) */ #define SIGIOT 6 /* IOT instruction */ #define SIGEMT 7 /* EMT instruction */ #define SIGFPE 8 /* floating point exception */ #define SIGKILL 9 /* kill (cannot be caught or ignored) */ #define SIGBUS 10 /* bus error */ #define SIGSEGV 11 /* segmentation violation */ #define SIGSYS 12 /* bad argument to system call */ #define SIGPIPE 13 /* write on a pipe with no one to read it */ #define SIGALRM 14 /* alarm clock */ #define SIGTERM 15 /* software termination signal from kill */ #define SIGUSR1 16 /* user defined signal 1 */ #define SIGUSR2 17 /* user defined signal 2 */ #define SIGCLD 18 /* death of a child */ #define SIGPWR 19 /* power-fail restart */ #define NSIG 20 <<< linkmcs.pro >>> 000010PROCEDURE LINKMCS; 000020LINKEDIT,EDIT( 000030 NAME=MCSKERM, 000035 BIND=MCSKNDL, 000040 BIND=CRT0/D90/CLIB, 000050 BIND=CKVMAI_M, 000060 BIND=CKVFN2_O, 000070 BIND=CKVTIO_M, 000080 BIND=CKVFNS_O, 000090 BIND=CKVPRO_M, 000100 BIND=CKVUSR_M, 000110 BIND=CKVCMD_M, 000120 BIND=CKVCON_M, 000130 BIND=CKVDIA_M, 000140 BIND=CKVFI2_O, 000150 BIND=CKVSCR_M, 000160 BIND=CKVUS2_M, 000170 BIND=CKVUS3_M, 000180 BIND=VKNCRLIO, 000190 BIND=CKVFIO_O, 000200 BIND=CKVMCS_O, 000210 BIND=CKVBUF_O, 000215 AUTOLIB=D90/CLIB, 000220 ATTRSORT,SHARE); 000230PROCEND LINKMCS; <<< lnk1ksrc.n3 >>> 000000CLNKIVS NEAT/3 000010CLNKIVS CATJOB 000020CLNKIVS JOB VMAXMEM=1650,LOCALDSA=3000,PROTECTDSA=256 000030 STACKSIZE=250,SHARE,ACCESS=YES 000040 USERID=XXX,ACCT = XXXXX CPTY=10,JPTY=8 NAME=YOUR_NAME,PASSWORD=XXXXXXXX 000050C UNIT SUD=D01/D02/D03,VOL=525252,TYPE=BA/3A/3B 000090 SPCEND 000100 SCLBGN FILEL CAT/NOCAT;FILEC CAT;FILEN $.XXX.XXXXXX; ASS FLAGS MYFLAGS(MF02=4); MCLBEGIN; 000130 NEXTDOLINKEDIT 000140 FILE REFERENCE=OUTPUTFILE 000150 BLOCK SIZE= 8/RECORDS 000160 EDIT NAME = IVSKERM BIND = CRT0/D90/CLIB BIND = CKVMAI_O BIND = CKVFN2_O BIND = CKVTIO_O BIND = CKVFNS_O BIND = CKVPRO_O BIND = CKVUSR_O BIND = CKVCMD_O BIND = CKVCON_O BIND = CKVDIA_O BIND = CKVFI2_O BIND = VKNCRLIO BIND = CKVFIO_O BIND = CKVSCR_O BIND = CKVUS2_O BIND = CKVUS3_O 000230 AUTOLIB = D90/CLIB ATTRSORT,SHARE 000240 STOPRD 000250 JOB END <<< mcs.h >>> #define puts mcs_puts #define fputs mcs_fputs #define gets mcs_gets #define fputc mcs_fputc #define fputchar mcs_fputchar #define putchar mcs_putchar #define getchar mcs_getchar #define fgetc mcs_fgetc #define putc mcs_fputc #define getc mcs_fgetc #define fgets mcs_fgets static char print_str[200]; <<< mcs_defs.h >>> /* mcs_defs_h */ #include #include #define COMPVER 0x01 /* Compiler version 1. */ #define MESGS 40 /* Number of messages in outmesg array. */ #define BUF 50 #define MSGBUF 80 /* Maximum length of the message buffers */ /* DRE 013190 - changed from 110 TO 80 */ #define PWDLEN 10 /* Password buffer length. */ #define RESP_EOT 0x1e /* Response message End-Of-Text character. */ #define PASSWD "PASSWORD" /* Password for enabling and disabling. */ #define PRT_FILE "SPOOLFILE" #define IN_TERM "INPUT" #define OUT_TERM "OUTPUT" #define QUEUENAME "THE_QUEUE" #define iowriter if (iowrite) prt_iowriter #define printriow if (iowrite) printreciow #define OFF 0 #define ON 1 #define YES 'Y' #define NO 'N' #define MESG 0 /* Boolean for testing messages. */ #define VARESP 1 /* Boolean for testing variable responses. */ #define RESP 2 /* Boolean for testing responses. */ #define S 0 /* Regular send. */ #define SX25 1 /* Send SX25. */ /* Defines for ParBlock structures. */ #define IPPHASE 0x49 /* Input phase. */ #define OPPHASE 0x4f /* Output phase. */ #define TERMPHASE 0x54 /* Input terminal phase. */ #define NODATA(x) x |= 0x01 /* No data was available - return (bit 1 set) */ #define EXITFG(x) x |= 0x02 /* Suspend if data is not available (bit 2 set) */ #define NOENDKEY 0 /* Partial segment, user specified. */ #define INTEGESI 0x01 /* End of segment, user specified. */ #define INTEGEMI 0x02 /* End of message, user specified. */ #define INTEGEGI 0x03 /* End of group, user specified. */ #define ESI 0x53 /* End of segment, compiler generated. */ #define EMI 0x4d /* End of message, compiler generated. */ #define EGI 0x47 /* End of group, compiler generated. * */ #define AFTER 0x41 /* Advance after message display. */ #define BEFORE 0x42 /* Advance before message display. * */ #define LINE 0x4c /* Line advancing. */ #define PAGE 0x50 /* Page advancing. * */ #define HEXMNEM 0 /* Mnemonic is a string of hex. */ #define ASCIIMNEM 1 /* Mnemonic is a string of ascii. * */ #ifndef lint extern void MSGBUILD(); extern void \:FINISH(); extern void MCS\:ENABLE(); extern void MCS\:DSABLE(); extern void MCS\:SEND(); extern void MCS\:RECEIV(); extern void MCS\:ACCEPT(); extern void SESS\:MGT(); #endif /*NOT LINT*/ FILE *fp; /* File pointer for the spool file. */ int iowrite; /* Iowriter. */ int nosends; /* Number of sends in a session. */ char outmesg[MESGS][MSGBUF];/* Array of output messages. */ char outterm[BUF]; /* Output terminal name. */ char interm[BUF]; /* Input terminal name. */ char iobuff[MSGBUF]; /* Buffer for send messages to iowriter. */ char *mcs_fgets(); struct SendSMTD{ char ijn[BUF]; char ihc[BUF]; } SendSMTD; struct OutputCD { /* Output communication descriptor. */ char destcnt[4]; /* Destination count. */ char textlen[4]; /* Text length. */ char statkey[2]; /* Status key. */ char errkey; /* Error key. */ char symdest[12]; /* Symbolic destination. */ struct ExOutCD { /* Extended output CD. */ char xoformat; /* Extended output format. */ char tcfunction[3]; /* TC function. */ char tcqualifier[3]; /* TC qualifier. */ char tcoutput_reset; /* TC output_reset */ char xofiller[33]; /* Extended output filler. */ } ExOutCD; } OutCD; struct InputCD { /* Input communication descriptor. */ char q[12]; /* Input CD queue. */ char symq1[12]; /* Symbolic Sub-queue 1. */ char symq2[12]; /* Symbolic Sub-queue 2. */ char symq3[12]; /* Symbolic Sub-queue 3. */ char mdate[6]; /* Message date. */ char mtime[8]; /* Message time. */ char source[12]; /* Symbolic source. */ char len[4]; /* Text length. */ char endkey; /* End key. */ char statkey[2]; /* Status key. */ char msgcnt[6]; /* Message count */ struct ExInCD { /* Extended input CD. */ char xiformat; /* Extended input format. */ char xistatus[2]; /* TC status. */ char xipassthru[10]; /* TC pass through. */ char xifiller[27]; /* Extended input filler. */ } ExInCD; } InCD; struct mnemonik { /* Mnemonic structure in each parameter block. */ char type; /* Mnemonic type field. */ char *address; /* Address of mnemonic. */ /* DRE 013190 - change to char ptr */ /* CHANGE PEG 012990 */ /* CAUSED AN ALIGNMENT PROBLEM DUE TO RANDOMNESS OF BYTE PLACEMENT */ /* for all purposes a four byte array */ }; struct SParBlck { /* parameter block for sending. */ short length; /* User message area length. */ char complver; /* Compiler version. */ char linenum; /* Number of lines to advance. */ char indicator; /* Send or receive end key. */ char advancing; /* Type of advancing. */ char position; /* Mode of advancing. */ char sendcount; /* Send destination count. */ /* struct mnemonik mnemonic; */ /* Mnemonic structure field. */ char mnemonic[4]; /* DRE 020990 */ } SParBlock; struct RParBlck { /* parameter block for receiving. */ short length; /* User message area length. */ char complver; /* Compiler version. */ char avail; /* Bit flags - receive data availability. */ char indicator; /* Send or receive end key. */ char filler[7]; /* PEG 012990 SIMILAR TO MCDAID'S DELETED SEVEN UNUSED BYTES FOR PROPER DEFINE */ } RParBlock; struct ParBlck { /* parameter block for enable/disable. */ char denabltyp; /* Enable or disable type. */ char passwdlen; /* Password length. */ char complver; /* Compiler version. */ char destcount; /* Enable/disable/purge destination count. */ char filler [8]; } ParBlock; struct SMParBlck { /* Session Management Parameter Block. */ char format; char action[3]; /* EST, DIS, ABT, 1, 2, or 3. */ char pbstatus[4]; /* Parameter block status. */ char symdest[12]; /* Symbolic destination. */ char input; /* Allow input. */ char output; /* Allow output. */ char status[2]; /* Return status. */ char exstatus[4]; /* Return extended status. */ } SMParBlock; <<< mcskj.n3 >>> MCSKJ CATJOB MCSKJ JOB NAME=(MCS-KERMIT) **************************** * COPYRIGHT NCR CORP. * * DAYTON, OHIO * * 1990 * **************************** USERID=PUBLIC ACCT=PUBLICACCTNUMBER *PASSWORD=PUBLIC *USERID=XXX,ACCT=NNNN,PASSWORD=XXX CPTY=7,JPTY=1,CNTLSTKLEN=808 MAXT=INFINITE,IOCT=9999999 VMAXMEM=1000,LOCALDSA=2500 PROTECTDSA=1000,SIZE=124,STACKSIZE=124 JOBCONTROL=SCL SPCEND % % ************************************************* % * % * THIS JOB INITIALIZES MCS-KERMIT % * FOR TRANSFERRING % * FILES TO/FROM THE CATALOG OR SUD=D02 % * % * % * % * UPDATED ON 6-1-90 % * UPDATED ON 6-8-90 % * UPDATED ON 6-15-90 % * % ************************************************* % % % ************************************************* % * VARIABLE DEFINITIONS % ************************************************* % % LOCAL MSG : STRING, LPN : STRING, ENV : STRING, VSN : STRING, DTYPE : STRING, VOL_INT : INTEGER, NODE : STRING, NODENAME : NAME, ACTION : STRING, FILESIZ : STRING, RSTRT_FLAG: BOOLEAN, DEFAULTS : STRING, FONT_FORM : STRING, REC_TYPE : STRING, P1 : PROCESS; % % ******************************************************* % * ASSIGNING THE DEFAULT VALUES % ******************************************************* % LOCAL LPN_DFLT : STRING, ENV_DFLT : STRING, NODE_DFLT : STRING, REC_TYP_DFLT : STRING, FONT_FORM_DFLT : STRING, FILESIZ_DFLT : STRING; % % ******************************************************* % * WARNING: % * DEFAULT STRING LENGTHS CANNOT BE SO LONG AS TO % * CAUSE ANY OF THE 'MSG' STRINGS TO BE > 105 CHARS. % ******************************************************* % LPN_DFLT := '0104'; ENV_DFLT := 'CAT'; NODE_DFLT := '$'; REC_TYP_DFLT := 'VARIABLE'; FONT_FORM_DFLT := 'SEQUENTIAL'; FILESIZ_DFLT := '500'; % FILECREATION CAT; % % ********************************************* % * SOLICITATION OF SETUP OPTIONS % * % * -LPN? % * % * -FILE SOURCE AND DEST? % * -IF CAT, WHICH NODE? % * -IF DISK, WHIC VOLUME AND TYPE? % * % * -FILE SPECIFICATIONS FOR REF=DATAFILE? % * -REGULAR FILE STRUCTURE OR 6437/38 LASER % * PRINTER FONT/FORMS? % * -FILESIZE FOR D02 AND FONT/FORMS? % * % ******************************************************* % % % % ****************************************************** % * ASKING USER FOR ACCEPTANCE OF DEFAULTS % * % * USER ACCEPTS DEFAULTS(DEFAULTS IN PARENS)? % * % * -LPN ( 0150 ) % * % * -FILE SOURCE/DEST ( CAT ) % * -NODE ( $ ) % * % * % * -FILE SPECIFICATIONS FOR REF=DATAFILE % * -FIXED LENGTH DATAFILE RECORDS ( NO ) % * -FONT/FORMS ORGANIZATION ( NO ) % * -FILESIZE FOR D02 AND FONT/FORMS ( 500 BLOCKS ) % * % * % ****************************************************** % % * NOTE: ASKOP WILL ONLY DISPLAY A 105 CHARACTER STRING. % * AND IT LOSES THE 1ST 2 CHARACTERS. % BEGIN MSG := ' ACCEPT DEFAULTS OF LPN=' & #LPN_DFLT & ',SOURCE/DEST=' & #ENV_DFLT & ',' & 'NODE=' & #NODE_DFLT & ',' & SUBSTRING(REC_TYP_DFLT,0,3) & ' RECS,' & SUBSTRING(FONT_FORM_DFLT,0,3) & ' ORG,SIZE=' & #FILESIZ_DFLT & '/BLOCKS' & '?[Y,N]'; ASKPROC (#MSG,/DEFAULTS/); % IF (SUBSTRING(DEFAULTS,0,1) /= 'N') THEN % * SET UP DEFAULT VALUES LPN := LPN_DFLT; ENV := ENV_DFLT; NODE := NODE_DFLT; VSN := ''; REC_TYPE := REC_TYP_DFLT; FONT_FORM := FONT_FORM_DFLT; FILESIZ := FILESIZ_DFLT; DEFAULTS := 'YES'; NODENAME := #NODE; FILENODE #NODENAME; ELSE DEFAULTS := 'NO'; IFEND; % % % ******************************************************* % * DEFAULTS NOT ACCEPTED % * % * THE 'X' RESPONSE STOPS THE QUESTIONS % * % ******************************************************* IF (DEFAULTS = 'NO' ) THEN $TAG1 % ***************************************************** % * ASKING FOR LPN OF SUD=A02. % ***************************************************** MSG := ' SPECIFY LPN FOR MCS-KERMIT COMMUNICATION LINK.' & ' DEFAULT LPN IS ' & #LPN_DFLT & '.' & ' ''X'' TO STOP ASKING.[NNNN,X]'; ASKPROC (#MSG,/LPN/); % IF (LPN = '') THEN LPN := LPN_DFLT; IFEND; % IF (LPN = 'X') THEN DEFAULTS := 'YES'; % * SET UP DEFAULT VALUES LPN := LPN_DFLT; ENV := ENV_DFLT; NODE := NODE_DFLT; VSN := ''; REC_TYPE := REC_TYP_DFLT; FONT_FORM := FONT_FORM_DFLT; FILESIZ := FILESIZ_DFLT; DEFAULTS := 'YES'; NODE := NODE_DFLT; NODENAME := #NODE; FILENODE #NODENAME; IFEND; % IFEND; % % ****************************************************** % * ASSIGN A02 IN BOTH 'DEFAULT' AND 'SOLICITED' CASES. % ****************************************************** ASSIGN UNIT A02(SUD=A02,TYPE=C1,LPN=#LPN) [P1]; % IF (P1(STATUS) /= COMPLETED) THEN MSG := ' LPN ' & #LPN & ' WAS INVALID OR IN USE. DO YOU WANT ' & 'TO TRY ANOTHER LPN? [Y,N]'; ASKPROC (#MSG,/ACTION/); % IF (SUBSTRING(ACTION,0,1) = 'N') THEN BYE; ELSE GOTO TAG1; IFEND; % IFEND; % $TAG2 % IF (DEFAULTS = 'YES' ) THEN GOTO TAG5; IFEND; % % ****************************************************** % * ASKING FOR FILE SOURCE/DESTINATION. % ****************************************************** MSG := ' SELECT MCS-KERMIT SOURCE/DESTINATION ENVIRONMENT.' & ' DEFAULT ENVIRONMENT IS ' & #ENV_DFLT & '.' & '[CAT,DISK,X]'; ASKPROC (#MSG,/ENV/); % IF ((SUBSTRING(ENV,0,1) /= 'C') AND (SUBSTRING(ENV,0,1) /= 'D') AND (SUBSTRING(ENV,0,1) /= 'X') AND (SUBSTRING(ENV,0,1) /= '')) THEN GOTO TAG2; IFEND; % IF (SUBSTRING(ENV,0,1) = 'X') THEN DEFAULTS := 'YES'; % * SET UP DEFAULT VALUES ENV := ENV_DFLT; NODE := NODE_DFLT; VSN := ''; REC_TYPE := REC_TYP_DFLT; FONT_FORM := FONT_FORM_DFLT; FILESIZ := FILESIZ_DFLT; DEFAULTS := 'YES'; NODE := NODE_DFLT; NODENAME := #NODE; FILENODE #NODENAME; GOTO TAG5; IFEND; % IF ((SUBSTRING(ENV,0,1) = 'C') OR (SUBSTRING(ENV,0,1) = '')) THEN $TAG3 % ****************************************************** % * CATALOG SELECTED;ASKING FOR NODE. % ****************************************************** MSG := ' PLEASE ENTER SUBCATALOG NODE NAME. DEFAULT IS' & ' THE ' & #NODE_DFLT & ' NODE.' & '[NODE NAME,X]'; ASKPROC (#MSG,/NODE/); % IF (NODE = '') THEN NODE := NODE_DFLT; IFEND; % IF (NODE = 'X') THEN DEFAULTS := 'YES'; % * SET UP DEFAULT VALUES VSN := ''; REC_TYPE := REC_TYP_DFLT; FONT_FORM := FONT_FORM_DFLT; FILESIZ := FILESIZ_DFLT; DEFAULTS := 'YES'; NODE := NODE_DFLT; NODENAME := #NODE; FILENODE #NODENAME; GOTO TAG5; ELSE NODENAME := #NODE; IFEND; % FILENODE #NODENAME [P1]; % IF (P1(STATUS) /= COMPLETED) THEN MSG := ' CANT POSITION TO ' & #NODE & ' DO YOU WANT' & ' TO TRY ANOTHER SUBCATALOG?[Y,N]'; ASKPROC (#MSG,/ACTION/); % IF (SUBSTRING(ACTION,0,1) = 'N') THEN BYE; ELSE GOTO TAG3; IFEND; % IFEND; % % **************************************************** % * ASKING FOR FIXED/VARIABLE RECORD TYPE. % * IN THE CATALOG CASE. % **************************************************** MSG := ' DO YOU WANT DATAFILES TO HAVE FIXED OR' & ' VARIABLE LENGTH RECORDS?' & ' DEFAULT IS ' & #REC_TYP_DFLT & '.' & '[F,V,X]'; ASKPROC (#MSG,/REC_TYPE/); % IF (SUBSTRING(REC_TYPE,0,1) = 'X') THEN DEFAULTS := 'YES'; % * SET UP DEFAULT VALUES VSN := ''; REC_TYPE := REC_TYP_DFLT; FONT_FORM := FONT_FORM_DFLT; FILESIZ := FILESIZ_DFLT; DEFAULTS := 'YES'; GOTO TAG5; IFEND; % IF (SUBSTRING(REC_TYPE,0,1) /= 'F') THEN REC_TYPE := 'VAR'; % ************************************************** % * ASKING ABOUT THE TRANSFER OF FONT/FORM FILES % * IN THE CATALOG CASE. % ************************************************** MSG := ' WILL YOU UPLOAD FONT/FORM FILES?' & ' IF YES,ALL DATA FILES HAVE' & ' ''REL'' ORGANIZATION;' & 'DEFAULT IS ' & SUBSTRING(FONT_FORM_DFLT,0,3) & '.[Y,N]'; ASKPROC (#MSG,/FONT_FORM/); % IF (SUBSTRING(FONT_FORM,0,1) /= 'Y') THEN % ******************************************* % * FILE 'REFERENCE' OF 'DATAFILE' IS USED FOR % * BINARY AND TEXT 'DATA' FILES % * % * % ******************************************* % $TAG5 % % ************************************************ % * ASSIGNING REF=DATAFILE % * IN THE VARIABLE LENGTH RECORDS, NON FONT/FORM % * CASE USING CATALOG. % * % * THIS IS CONSIDERED TO BE THE OVERALL % * DEFAULT CASE. % * % ************************************************ ASSIGN FILE DATAFILE(REF=DATAFILE,RMS=YES, FILESIZE='NO LIMIT', RECORDSIZE=1/485, DATESCHEME=GEN,FILETYPE=DATA,FREEUP,CATALOG); ELSE % ********************************************* % * ASKING ABOUT FILE SIZE % * IN THE CATALOG,VARIABLE,FONT/FORM CASE. % * % * FONT/FORM FILES % * % * FILESIZE MUST BE FOR THE LARGEST % * FILE ANTICIPATED BECAUSE RELATIVE FILES % * ARE NOT RMS. % * % ************************************************ % % MSG := ' SPECIFY FILESIZE' & ' BIG ENOUGH FOR THE LARGEST' & ' FONT/FORM FILE UPLOADED.' & ' DEFAULT SIZE IS ' & #FILESIZ_DFLT & '/BLOCKS.[NNNN]'; ASKPROC (#MSG,/FILESIZ/); % IF ((SUBSTRING(FILESIZ,0,1) = '') OR (SUBSTRING(FILESIZ,0,1) = 'A')) THEN FILESIZ := FILESIZ_DFLT; IFEND; % % ************************************************ % * ASSIGNING REF=DATAFILE % * IN THE FONT/FORM CASE USING CATALOG. % ************************************************ ASSIGN FILE DATAFILE(REF=DATAFILE,RMS=YES, % ************************************ % * THE FOLLOWING 5 PARAMETERS ARE % * FOR FONT/FORM UPLOADS % ************************************ ORGANIZATION=RELATIVE, BLOCKSIZE=1/RECORDS, CAMHEADER, RECORDSIZE=1/485, FILESIZE=#FILESIZ/BLOCKS, DATESCHEME=GEN,FILETYPE=DATA,FREEUP,CATALOG); IFEND; % ELSE % % ************************************************ % * ASSIGNING REF=DATAFILE % * IN THE FIXED LENGTH RECORDS, NON FONT/FORM % * CASE USING CATALOG. % ************************************************ ASSIGN FILE DATAFILE(REF=DATAFILE,RMS=YES, % ************************************ % * THE FOLLOWING PARAMETERS ARE % * FOR FIXED LENGTH RECORDS % ************************************ RECORDSIZE=80, FILESIZE='NO LIMIT', DATESCHEME=GEN,FILETYPE=DATA,FREEUP,CATALOG); IFEND; % FILEN; % **************************************************** % * ASSIGNING THE OTHER FILE REFERENCES IN THE % * CATALOG CASE. % **************************************************** ASSIGN FILE SRCFILE(REF=SRCFILE,RMS=YES,FILESIZE='NO LIMIT', RECORDSIZE=1/83, DATESCHEME=GEN,FILETYPE=SOURCE,FREEUP,CATALOG), FILE OBJFILE(REF=OBJFILE,RMS=YES,FILESIZE='NO LIMIT', RECORDSIZE=1/490, DATESCHEME=GEN,FILETYPE=OBJECT,FREEUP,CATALOG), FILE CSFILE(REF=CSFILE,RMS=YES,FILESIZE='NO LIMIT', FREEUP,DATESCHEME=GEN, RECORDSIZE=1/82, FILETYPE='CONTROL STRING',CATALOG); FILEL CAT/NOCAT; % **************************************************** % * END OF THE CATALOG CASE. % **************************************************** ELSE % ****************************************************** % * BEGINNING OF THE SUD=D02 CASE. % ****************************************************** DISPLAY :'MCS-KERMIT USING NON-CATALOG ENVIRONMENT' TO JD; $TAG4 % ****************************************************** % * ASKING ABOUT SUD=D02. % ****************************************************** MSG := ' PLEASE ENTER VOLUME NUMBER AND DEVICE TYPE.' & '[NNNNNN/XX]'; ASKPROC (#MSG,/VSN/); VOL_INT := INT(SUBSTRING(VSN,0,6)); DTYPE := SUBSTRING(VSN,7,2); ASSIGN UNIT D02(SUD=D02,VOL=#VOL_INT,TYPE=#DTYPE) [P1]; % IF (P1(STATUS) /= COMPLETED) THEN MSG := ' CANT ASSIGN VOLUME ' & SUBSTRING(VSN,0,6) & ' WITH DEVICE TYPE ' & DTYPE & '. DO YOU WANT' & ' TO TRY ANOTHER VOLUME?[Y,N]'; ASKPROC (#MSG,/ACTION/); % IF (SUBSTRING(ACTION,0,1) = 'N') THEN BYE; ELSE GOTO TAG4; IFEND; % IFEND; % % % **************************************************** % * ASKING FOR FIXED/VARIABLE RECORD TYPE. % * IN THE D02 CASE. % **************************************************** % MSG := ' DO YOU WANT DATAFILES TO HAVE FIXED OR' & ' VARIABLE LENGTH RECORDS?' & ' DEFAULT IS ' & #REC_TYP_DFLT & '.' & '[F,V,X]'; ASKPROC (#MSG,/REC_TYPE/); % % IF (SUBSTRING(REC_TYPE,0,1) = 'X') THEN DEFAULTS := 'YES'; % * SET UP DEFAULT VALUES REC_TYPE := REC_TYP_DFLT; FONT_FORM := FONT_FORM_DFLT; FILESIZ := FILESIZ_DFLT; GOTO TAG6; IFEND; % IF (SUBSTRING(REC_TYPE,0,1) /= 'F') THEN REC_TYPE := 'VAR'; % ************************************************** % * ASKING ABOUT THE TRANSFER OF FONT/FORM FILES % * IN THE D02 CASE. % ************************************************** MSG := ' WILL YOU UPLOAD FONT/FORM FILES?' & ' IF YES,ALL DATA FILES HAVE' & ' ''REL'' ORGANIZATION;' & 'DEFAULT IS ' & SUBSTRING(FONT_FORM_DFLT,0,3) & '.' & '[Y,N,X]'; ASKPROC (#MSG,/FONT_FORM/); % % IF (SUBSTRING(FONT_FORM,0,1) = 'X') THEN DEFAULTS := 'YES'; % * SET UP DEFAULT VALUES FONT_FORM := FONT_FORM_DFLT; FILESIZ := FILESIZ_DFLT; GOTO TAG6; IFEND; % IF (SUBSTRING(FONT_FORM,0,1) /= 'Y') THEN % ******************************************* % * ASKING ABOUT FILE SIZE % * IN THE D02, VARIABLE, NON FONT/FORM CASE. % * % * THIS IS CONSIDERED TO BE THE 'NORMAL' AND % * DEFAULT CASE % * WHEN USING D02. % * % * % * % ******************************************* % MSG := ' SPECIFY FILESIZE' & ' BIG ENOUGH FOR THE LARGEST' & ' DATA FILE UPLOADED.' & ' DEFAULT SIZE IS ' & #FILESIZ_DFLT & '/BLOCKS.' & '[NNNN]'; ASKPROC (#MSG,/FILESIZ/); % IF ((SUBSTRING(FILESIZ,0,1) = '') OR (SUBSTRING(FILESIZ,0,1) = 'A')) THEN FILESIZ := FILESIZ_DFLT; IFEND; $TAG6 % % % ************************************************ % * ASSIGNING REF=DATAFILE % * IN THE VARIABLE LENGTH RECORD, NON FONT/FORM % * CASE USING D02. % * % * THIS IS CONSIDERED TO BE THE 'NORMAL' AND % * DEFAULT CASE % * WHEN USING D02. % * % ************************************************ ASSIGN FILE DATAFILE(REF=DATAFILE,RMS=NO,SUD=D02,FREEUP, RECORDSIZE=1/485, DATESCHEME=GEN, FILESIZE=#FILESIZ/BLOCKS, NOCAT, FILETYPE=DATA); ELSE % ********************************************* % * ASKING ABOUT FILE SIZE % * IN THE D02, VARIABLE, FONT/FORM CASE. % * % * FONT/FORM FILES % * % * FILESIZE MUST BE FOR THE LARGEST % * FONT/FORM FILE ANTICIPATED. % * % ************************************************ % % MSG := ' SPECIFY FILESIZE' & ' BIG ENOUGH FOR THE LARGEST' & ' FONT/FORM FILE UPLOADED.' & ' DEFAULT SIZE IS ' & #FILESIZ_DFLT & '/BLOCKS.' & '[NNNN]'; ASKPROC (#MSG,/FILESIZ/); % IF ((SUBSTRING(FILESIZ,0,1) = '') OR (SUBSTRING(FILESIZ,0,1) = 'A')) THEN FILESIZ := FILESIZ_DFLT; IFEND; % % % ************************************************ % * ASSIGNING REF=DATAFILE % * IN THE FONT/FORM CASE USING D02. % ************************************************ ASSIGN FILE DATAFILE(REF=DATAFILE,RMS=NO,SUD=D02,FREEUP, % ************************************ % * THE FOLLOWING 5 PARAMETERS ARE % * FOR FONT/FORM UPLOADS % ************************************ ORGANIZATION=RELATIVE, BLOCKSIZE=1/RECORDS, CAMHEADER, RECORDSIZE=1/485, FILESIZE=#FILESIZ/BLOCKS, NOCAT, FILETYPE=DATA); IFEND; % ELSE % % ********************************************* % * ASKING ABOUT FILE SIZE % * IN THE D02, FIXED LENGTH RECORDS, NON % * FONT/FORM CASE. % * % * FIXED LENGTH RECORDS. % * % * CUSTOMIZED FOR FIX ACQUISITION USE. % * % * FILE 'REFERENCE' OF 'DATAFILE' IS USED FOR % * DATA FILES % * % * FILESIZE MUST BE FOR THE LARGEST % * FILE ANTICIPATED. % * % ************************************************ % % MSG := ' SPECIFY FILESIZE' & ' BIG ENOUGH FOR THE LARGEST' & ' DATA FILE UPLOADED.' & ' DEFAULT SIZE IS ' & #FILESIZ_DFLT & '/BLOCKS.' & '[NNNN]'; ASKPROC (#MSG,/FILESIZ/); % IF ((SUBSTRING(FILESIZ,0,1) = '') OR (SUBSTRING(FILESIZ,0,1) = 'A')) THEN FILESIZ := FILESIZ_DFLT; IFEND; % % % ************************************************ % * ASSIGNING REF=DATAFILE % * IN THE FIXED LENGTH RECORD, NON FONT/FORM CASE % * USING D02. % * % * THIS IS CONSIDERED TO BE THE % * 'FIXED ACQUISITION' CASE. % ************************************************ ASSIGN FILE DATAFILE(REF=DATAFILE,RMS=NO,SUD=D02,FREEUP, DATESCHEME=GEN,NOCAT, % ************************************ % * THE FOLLOWING PARAMETERS ARE % * FOR FIXED LENGTH RECORDS % ************************************ RECORDSIZE=80, % ************************************ % * THE FOLLOWING PARAMS ARE FOR % * FIX ACQUISITION % ************************************ % NOCAMHEADER, BLOCKSIZE=6/RECORDS, FILESIZE=#FILESIZ/BLOCKS, NOCAT, FILETYPE=DATA); IFEND; % % % **************************************************** % * ASSIGNING THE OTHER FILE REFERENCES IN THE % * D02 CASE. % **************************************************** ASSIGN FILE SRCFILE(REF=SRCFILE,RMS=NO,SUD=D02,FREEUP, RECORDSIZE=1/82, FILESIZE=300/BLOCKS,DATESCHEME=GEN,NOCAT, FILETYPE=SOURCE), FILE OBJFILE(REF=OBJFILE,RMS=NO,SUD=D02,FREEUP, FILESIZE=1000/BLOCKS,RECORDSIZE=1/490, DATESCHEME=GEN,FILETYPE=OBJECT,NOCAT), FILE CSFILE(REF=CSFILE,RMS=NO,SUD=D02,FREEUP, FILESIZE=100/BLOCKS,RECORDSIZE=1/82,NOCAT, DATESCHEME=GEN,FILETYPE='CONTROL STRING'); FILEL NOCAT/CAT; % ****************************************************** % * END OF THE SUD=D02 CASE. % ****************************************************** IFEND; % END; ASSIGN PRINTER P09(SUD=P09); MCLBEGIN; MEMORYREALTIME=YES SWAP OUT TIME=NEVER SCLBGN % MUST SPECIFY LOCATION OF LOAD MODULE EXECUTE MCSKERM; QUEUE P09; FREE P09; % IF (VSN /= '') THEN FREE D02; IFEND; % JOB END <<< mcskndlj.n3 >>> MCSKNDLJ CATJOB MCSKNDLJ JOB NAME=XXXXXX,ACCT=XXXX,SIZE=512 JPTY=4,RMINMEM=42,VMAXMEM=128 USERID=XXX,PASSWORD=XXXXXX LOCALDSA=600,STACKSIZE=250 JOBCONTROL = SCL UNIT SUD=D02,VOL=525252 SPCEND % This job builds the MCSKNDL object module. This module % should be linked into the MCS-KERMIT load object module % MCSKLOBJ. It defines the primary MCS queue and the % communication links that MCS-KERMIT will use. The module % is created using the Network Description Langauge (NDL). FILEL CAT/NOCAT; FILEC CAT; FILEN $.XXXXXXXXX; MCLBEGIN; NEXTDONDLP STOPRD MCSKNDL MCS ENTRY = C_START, QUEUE = 'THE_QUEUE ' OPRTN = NONE, PASSWD = PASSWORD UNSOLIP = 'THE_QUEUE ' LINK SUD=A002, BUFF = 2400 INPUT=5 TERM SPEED = 9600,TIMES=0, NETWORK = P/LB CODE = ASCII/N, RETRY = 0/0/3 NAMES='THE_QUEUE '/'INPUT '/'OUTPUT ' TYPE = 7961 END$ MCSKNDLJ JOB END <<< packing.lst >>> /********************************************************************** * * * Packing List * * * * This floppy contains IVS-Kermit & MCS-Kermit source code, * * compilation instructions, linkedit jobfiles, and user * * documentation. * * * * IVS-Kermit & MCS-Kermit file names use the Unix file naming * * convention as used in C-Kermit. Both products are based on * * C-Kermit(4E) with features added or deleted depending on * * VRX system capabilities, and NCR selected product content. * * Module names reflect the same usage as in C-Kermit(4E). * * New modules have a short explanation. * * * * IVS-Kermit and MCS-Kermit share common source code. MCS-Kermit * * has two additional files to interface to the MCS telecommunications * * facility. MCS modules are labeled MCS ONLY. * * * * June 22, 1990 * * * ***********************************************************************/ CKCDEB H IVS / MCS-Kermit header file CKVFN2 C IVS / MCS-Kermit C source module CKVFNS C IVS / MCS-Kermit C source module CKCKER H IVS / MCS-Kermit header file CKVMAI C IVS / MCS-Kermit C source module CKVPRO C IVS / MCS-Kermit C source module CKUSYM H IVS / MCS-Kermit header file CKVCMD C IVS / MCS-Kermit C source module CKUCMD H IVS / MCS-Kermit header file CKVCON C IVS / MCS-Kermit C source module CKVDIA C IVS / MCS-Kermit C source module CKVFI2 C IVS / MCS-Kermit C source module CKVSCR C IVS / MCS-Kermit C source module CKVTIO C IVS / MCS-Kermit C source module CKVUS2 C IVS / MCS-Kermit C source module CKVUS3 C IVS / MCS-Kermit C source module CKVUSR C IVS / MCS-Kermit C source module CKUUSR H IVS / MCS-Kermit header file CKVFIO C IVS / MCS-Kermit C source module CKVMCS C MCS-Kermit C source module MCSONLY MCS system I/F routines CKVBUF C MCS-Kermit C source module Buffering routines for MCS I/F COMPILE INS Compilation instructions KERMISC H IVS / MCS-Kermit header file IVSKPM PRO SCL routine to execute IVS-Kermit MCS H MCS-Kermit header file: used to redefine fgets, fputs, etc. MCS_DEFS H MCS control structures MCSKJ N3 SCL jobfile to execute MCS-Kermit PWD H IVS / MCS-Kermit header file* SGTTY H IVS / MCS-Kermit header file* SIGNAL H IVS / MCS-Kermit header file* TYPES H IVS / MCS-Kermit header file* VKNCRLIO NCR IVS / MCS-Kermit C source module VRX H IVS / MCS-Kermit header file MCSKNDLJ N3 NDL compilation jobfile to specify terminal / queue characterisitics, and produce NDL object. LINKMCS PRO LinkEdit SCL procedure file used to link MCS-Kermit LNK1KSRC N3 LinkEdit jobfile used to link IVS-Kermit PACKING LST This list VKERMIT DOC VKermit documentation * These files do not exist on a VRX/VE system, they are placed in either the compilation catalog node or disk. <<< pwd.h >>> struct passwd { char *pw_name; char *pw_passwd; int pw_uid; int pw_gid; char *pw_age; char *pw_comment; char *pw_gecos; char *pw_dir; char *pw_shell; }; struct comment { char *c_dept; char *c_name; char *c_acct; char *c_bin; }; <<< sgtty.h >>> struct sgttyb { char sg_ispeed; /* input speed */ char sg_ospeed; /* output speed */ char sg_erase; /* erase character */ char sg_kill; /* kill character */ int sg_flags; /* mode flags */ }; /* * Modes */ #define HUPCL 01 #define XTABS 02 #define LCASE 04 #define ECHO 010 #define CRMOD 020 #define RAW 040 #define ODDP 0100 #define EVENP 0200 #define ANYP 0300 #define NLDELAY 001400 #define TBDELAY 002000 #define CRDELAY 030000 #define VTDELAY 040000 #define BSDELAY 0100000 #define ALLDELAY 0177400 /* * Delay algorithms */ #define CR0 0 #define CR1 010000 #define CR2 020000 #define CR3 030000 #define NL0 0 #define NL1 000400 #define NL2 001000 #define NL3 001400 #define TAB0 0 #define TAB1 002000 #define NOAL 004000 #define FF0 0 #define FF1 040000 #define BS0 0 #define BS1 0100000 /* * Speeds */ #define B0 0 #define B50 1 #define B75 2 #define B110 3 #define B134 4 #define B150 5 #define B200 6 #define B300 7 #define B600 8 #define B1200 9 #define B1800 10 #define B2400 11 #define B4800 12 #define B9600 13 #define EXTA 14 #define EXTB 15 /* * ioctl arguments */ #define FIOCLEX (('f'<<8)|1) #define FIONCLEX (('f'<<8)|2) #define TIOCHPCL (('t'<<8)|2) #define TIOCGETP (('t'<<8)|8) #define TIOCSETP (('t'<<8)|9) #define TIOCEXCL (('t'<<8)|13) #define TIOCNXCL (('t'<<8)|14) <<< signal.h >>> #define SIG_DFL (int (*)())0 #define SIG_IGN (int (*)())1 extern int (*ssignal())(); #ident "@(#)signal.h 5.4" #define SIGINT 2 /* interrupt (rubout) */ #define SIGQUIT 3 /* quit (ASCII FS) */ #define SIGILL 4 /* illegal instruction (not reset when caught)*/ #define SIGTRAP 5 /* trace trap (not reset when caught) */ #define SIGIOT 6 /* IOT instruction */ #define SIGEMT 7 /* EMT instruction */ #define SIGFPE 8 /* floating point exception */ #define SIGKILL 9 /* kill (cannot be caught or ignored) */ #define SIGBUS 10 /* bus error */ #define SIGSEGV 11 /* segmentation violation */ #define SIGSYS 12 /* bad argument to system call */ #define SIGPIPE 13 /* write on a pipe with no one to read it */ #define SIGALRM 14 /* alarm clock */ #define SIGTERM 15 /* software termination signal from kill */ #define SIGUSR1 16 /* user defined signal 1 */ #define SIGUSR2 17 /* user defined signal 2 */ #define SIGCLD 18 /* death of a child */ #define SIGPWR 19 /* power-fail restart */ #define NSIG 20 <<< types.h >>> typedef struct { int r[1]; } * physadr; typedef long daddr_t; typedef char * caddr_t; typedef unsigned int uint; typedef unsigned short ushort; typedef ushort ino_t; typedef short cnt_t; typedef long time_t; typedef int label_t[13]; typedef short dev_t; typedef long off_t; typedef long paddr_t; typedef long key_t; <<< vkncrlio.ncr >>> 000010?? TITLE := 'VKNCRLIO - NCRL I/O FOR OBJECT FILES' ?? 000020module vkncrlio; 000030 " /********************************************************************** * * * IVS / MCS-Kermit REL 2 * * source code * * * * Change History: * * * * 1. Modify C-Kermit(4E) source code to * * produce new module for MCS/IVS-Kermit * * ORIGINAL RELEASE * * June 22, 1990 * * * * * ***********************************************************************/ 000040 This module provides NCRL runtime interfaces to perform 000050 I/O on VRX object files. 000060 " 000070 000080*CALL FOR0307.COMPILATION_CONTROL_DEFINITION,SUD=D04 000090*CALL SYS0015.SYSTEM_DEFINITIONS,SUD=D04 000100*CALL VRXMAIN.VRXNCRL,SUD=D04 000110*CALL SYSPROCS.SET_FILE_REFERENCE,SUD=D04 000120*CALL SYSPROCS.SETOUTCOME,SUD=D04 000130*CALL SYSPROCS.VRXOUTCOME,SUD=D04 000140 000150 000160?? OLDTITLE ?? 000170?? NEWTITLE := 'GLOBAL TYPES AND VARIABLES' ?? 000180?? EJECT ?? 000190 000200 type 000210 legible_type = (leginfile, legoutfile), 000220 nio_result = (nio_ok, nio_bad, nio_eof); 000230 000240 "Dummy types for clean compiles" 000250 type 000260 task_descriptor_block = cell; 000270 000280 var 000290 errcell : [xref] integer; " we pass back bad outcomes to 000300 a global int for output to 000310 screen and stderr " 000320 000330?? OLDTITLE ?? 000340?? NEWTITLE := 'OBJOPENI' ?? 000350?? EJECT ?? 000360 proc [XDCL] objopeni ( 000370 ref 000380 fname: string (*) of char, 000390 fref: string (*) of char, 000400 myfile: legible, 000410 result: nio_result); 000420 000430 var 000440 infile : legible := [#OLD, #IN, fname], 000450 refset : boolean, 000460 transfer_ptr1 : ^string( * ) of char, 000470 transfer_ptr2 : ^string( * ) of char; 000480 000490 result := nio_ok; 000500 000510 " Determine the file operation and set myfile parameter. 000520 This must be done indirectly with bind statements since 000530 NCRL does not allow the direct assignments of legible files. 000540 " 000550 bind transfer_ptr1 : [#size(legible)] to #loc(infile); 000560 000570 bind transfer_ptr2 : [#size(legible)] to #loc(myfile); 000580 transfer_ptr2^ (1, *) := transfer_ptr1^ (1, *); 000590 000600 " 000610 Set the file reference so FCL can be used on the file. 000620 The filetype and recordsize must be set to be appropriate 000630 for object files in FCL as there is no way to do it with 000640 NCRL I/O. 000650 " 000660 set_file_reference($SYSPROCS#FILEREC[LEGF, ^myfile], fref, 000670 refset); 000680 if (not refset) then 000690 result := nio_bad; 000700 return; 000710 ifend; 000720 000730 " all #open, #put, #get, #close 000740 we check the outcome from :CAM with 000750 the vrxoutcome function call. we 000760 do not have to setoutcome to ok or 0 000770 this is done just in case. At least 000780 this way nothing bites us later 000790 PEG March 6, 1990 " 000800 000810 setoutcome(ok); 000820 000830 #open(myfile); 000840 000850 if (vrxoutcome() /= ok ) then 000860 result := nio_bad; 000870 errcell := vrxoutcome(); 000880 return; 000890 ifend; 000900 000910 procend objopeni; 000920?? OLDTITLE ?? 000930?? NEWTITLE := 'OBJOPENO' ?? 000940?? EJECT ?? 000950 proc [XDCL] objopeno ( 000960 ref 000970 fname: string (*) of char, 000980 fref: string (*) of char, 000990 myfile: legible, 001000 result: nio_result); 001010 001020 var 001030 outfile : legible := [#NEW, #OUT, fname], 001040 refset : boolean, 001050 transfer_ptr1 : ^string( * ) of char, 001060 transfer_ptr2 : ^string( * ) of char; 001070 001080 result := nio_ok; 001090 001100 " Determine the file operation and set myfile parameter. 001110 This must be done indirectly with bind statements since 001120 NCRL does not allow the direct assignments of legible files. 001130 " 001140 bind transfer_ptr1 : [#size(legible)] to #loc(outfile); 001150 001160 bind transfer_ptr2 : [#size(legible)] to #loc(myfile); 001170 transfer_ptr2^ (1, *) := transfer_ptr1^ (1, *); 001180 001190 " 001200 Set the file reference so FCL can be used on the file. 001210 The filetype and recordsize must be set to be appropriate 001220 for object files in FCL as there is no way to do it with 001230 NCRL I/O. 001240 " 001250 set_file_reference($SYSPROCS#FILEREC[LEGF, ^myfile], fref, 001260 refset); 001270 if (not refset) then 001280 result := nio_bad; 001290 return; 001300 ifend; 001310 001320 setoutcome(ok); 001330 #open(myfile); 001340 001350 if (vrxoutcome() /= ok ) then 001360 result := nio_bad; 001370 errcell := vrxoutcome(); 001380 return; 001390 ifend; 001400 001410 procend objopeno; 001420?? OLDTITLE ?? 001430?? NEWTITLE := 'OBJCLOSE' ?? 001440?? EJECT ?? 001450 proc [XDCL] objclose ( 001460 ref 001470 closefile: legible, 001480 result : nio_result); 001490 001500 setoutcome(ok); 001510 #close(closefile); 001520 if (vrxoutcome() /= ok ) then 001530 result := nio_bad; 001540 errcell := vrxoutcome(); 001550 return; 001560 ifend; 001570 001580 procend objclose; 001590?? OLDTITLE ?? 001600?? NEWTITLE := 'OBJRECIN' ?? 001610?? EJECT ?? 001620 proc [XDCL] objrecin ( 001630 ref 001640 infile: legible, 001650 buf: string (*) of char, 001660 charsread : integer, 001670 result: nio_result); 001680 001690 " 001700 This routine reads the next record into a buffer. The VLI 001710 is reconstructed and placed at the beginning of the buffer. 001720 The buffer (including room for the VLI) must be allocated by 001730 caller. The file must have been opened by objopen. 001740 " 001750 001760 "Repeat until a good read, skipping over empty records. 001770 Note that one place this may happen is just before EOF 001780 is detected." 001790 001800 repeat 001810 if #EOF(infile) then 001820 result := nio_eof; 001830 return; 001840 else 001850 result := nio_ok; 001860 ifend; 001870 001880 setoutcome(ok); 001890 #GET(infile, charsread, buf(3, *)); 001900 if (vrxoutcome() /= ok ) then 001910 result := nio_bad; 001920 errcell := vrxoutcome(); 001930 return; 001940 ifend; 001950 001960 if (charsread > 0) then 001970 " Add the VLI to the beginning " 001980 buf (2) := $char (charsread mod 256); 001990 buf (1) := $char ((charsread / 256) mod 256); 002000 ifend; 002010 until ((charsread > 0) or (result = nio_eof)); 002020 002030 procend objrecin; 002040?? OLDTITLE ?? 002050?? NEWTITLE := 'OBJRECOUT' ?? 002060?? EJECT ?? 002070 proc [XDCL] objrecout ( 002080 ref 002090 outfile: legible, 002100 buf: string (*) of char, 002110 result: nio_result); 002120 002130 var 002140 charstowrite: integer; 002150 002160 result := nio_ok; 002170 charstowrite := ($integer(buf(1)) * 256) + $integer(buf(2)); 002180 002190 setoutcome(ok); 002200 002210 #PUT(outfile, buf (3, charstowrite) ); 002220 002230 if (vrxoutcome() /= ok ) then 002240 result := nio_bad; 002250 errcell := vrxoutcome(); 002260 return; 002270 ifend; 002280 002290 procend objrecout; 002300modend vkncrlio; <<< vrx.h >>> #define BASIC 1111577344 #define OBJECT 1329744384 #define BINARY 1112100352 #define CS 1129512960 #define DATA 1145132032 #define NCRL 1313034752 #define FORTB 1178730496 #define FORTI 1179189248 #define FORTF 1178992640 #define FORTV 1180041216 #define NEAT3 1311965184 #define NEATVS 1314280192 #define NEATC 1313013760 #define COBOL 1129250816 #define COBOL6 1129264640 #define COBOL7 1129264896 #define COBOL8 1129265152 #define COBOL1 1129263360 #define COBOL16 1127298560 #define COBOL17 1127298816 #define COBOL18 1127299072 #define COBOL4 1129264128 #define PROC 1347571456 #define PROCN 1347571200 #define L_BASIC 1650553600 #define L_OBJECT 1868720640 #define L_BINARY 1651076608 #define L_CS 1668481024 #define L_DATA 1684108288 #define L_NCRL 1852011008 #define L_FORTB 1717698560 #define L_FORTI 1718157312 #define L_FORTF 1717960704 #define L_FORTV 1719009280 #define L_NEAT3 1848836096 #define L_NEATVS 1853256448 #define L_NEATC 1851981824 #define L_COBOL 1668218880 #define L_COBOL6 1668232704 #define L_COBOL7 1668232960 #define L_COBOL8 1668233216 #define L_COBOL1 1668231424 #define L_COBOL16 1664169472 #define L_COBOL17 1664169728 #define L_COBOL18 1664169984 #define L_COBOL4 1668232192 #define L_PROC 1886547712 #define L_PROCN 1886547456 #define ID_START 0 #define ID_LEN 1 #define REC_LEN 2 #define NUM_FIELD_LEN 3 #define MAX_SPURTYPE 21 #define MAX_FIELD 8 #define DATA_LEN 90 #define NUM_LEN 6 #define LINE_LEN 140 #define TAIL_LEN 100 #define HEAD_END 6 #define INCREMENT 10 int spur_info[MAX_SPURTYPE * 4] = { 6, 0, 0, 0, 0, 6, 6, 6, 8, 0, 8, 7, 6, 0, 0, 0, 0, 8, 7, 6, 6, 8, 0, 0, 0, 0, 2, 7, 7, 6, 0, 6, 7, 8, 0, 0, 0, 0, 6, 7, 8, 8, 72,80,80,80,80,78,73,73,74,80,74,73,72,80,80,80,80,74,73,72,72, 6, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 };