home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / hp3000st / stkermit.w < prev    next >
Text File  |  2020-01-01  |  92KB  |  2,624 lines

  1. #-h-  kermit.def                    66  ascii   05/30/84  23:45:46
  2. # kermitde ---- defines for kermit
  3. #
  4. #
  5. # Parameters which may need to be changed for your machine:
  6. #     MAXPACK, BRKCHR, MY...
  7.  
  8.  
  9.  
  10. # defines normally in ratdef:
  11. define(NULL,NUL)          # ASCII NUL
  12. #define(SOH,1)             # Start of header
  13. #define(SP,32)             # ASCII space
  14. #define(CR,13)             # ASCII Carriage Return
  15. #define(SHARP,35)
  16. #define(DEL,127)           # Delete (rubout)
  17. #define(strcpy,scopy($1,1,$2,1))     # already defined on many systems
  18.  
  19. # this kermit's init parameters
  20. define(MAXPACK,94)        # Maximum incoming packet size (max 94)
  21. define(MYTIME,10)         # Seconds after which I should be timed out
  22. define(MYPAD,0)           # Number of padding characters I will need (max 94)
  23. define(MYPCHAR,NULL)      # Padding character I need
  24. define(MYEOL,CR)          # End-Of-Line character I need
  25. define(MYQUOTE,SHARP)     # Quote character I will use
  26. define(MYBQUOTE,AMPER)    # Eighth-bit quote char:  BLANK => none
  27. define(MYREPTC,TILDE)     # Repeat prefix:  BLANK => none
  28. define(MYCHECK,DIG1)      # Checksum type: DIG1 => default
  29. define(MYCAPS,arith(CAP_TIMO,+,CAP_SERV)) # capability mask
  30.  define(CAP_TIMO,8%40)    # I can timeouts: 0 => no, 8%40 => yes
  31.  define(CAP_SERV,8%20)    # I have server mode: 0 => no, 8%20 => yes
  32. define(INIT_SIZ,10)       # number of parameters we will look at in an init pak
  33.  
  34. define(MAXTIM,30)         # Maximum timeout interval
  35. define(MINTIM,2)          # Minumum timeout interval
  36. define(MAXTRY,5)          # Times to retry a packet
  37. define(ESCCHR,CARET)      # connect mode escape char
  38.  
  39. define(MAXLIN,100)        # Size of packet buffers
  40. define(MAXNAM,FILENAMESIZE)    # Maximum name file name length
  41. define(PBSIZE,3)               # Pushback buffer size
  42.  
  43. # U1100 DEPENDENT
  44. #define(MAGIC,283)         # Magic character for seting raw mode #1100
  45. #define(CTRL_B,2)          # ASCII Ctrl_B
  46. #define(PADU,511)          # Univac padding character    #1100
  47. #define(CTRLD,4)
  48. #define(ESCCHR,CTRLD)      # Default break-connection character
  49. #define(NUMOPTS,5)         # Number of possible command line options
  50. # END
  51.  
  52. # program macros
  53. define(tochar,($1+BLANK)) # convert a control char to a printing one
  54. define(unchar,($1-BLANK)) # undo tochar
  55. define(INCR, $1 = $1 + 1) # Incrementer for counter variables
  56. define(CHCOPY,{$2($3)=$1;$3=$3+1;$2($3)=EOS})  # appends a char onto a string
  57.  
  58.  define(cant3s,prints($4,"Can't open file '%s'@n.", $3))
  59.  define(eprintf,printf(ERROUT,$1,$2,$3,$4,$5,$6,$7,$8,$9))
  60.  
  61. # HP3000 DEPENDENT
  62. define(cchar,kermitc1)
  63. define(cint,kermitc2)
  64. define(cpb,kermitc3)
  65. define(quit,quitit)       # to avoid name collision
  66. define(TERMTYPE,13)       # 13 for anything but a Series 33
  67.                           #    use 4 for Series 33
  68. # END
  69.  
  70. define(DUM,0)             # used only as dummy argument
  71. #-t-  kermit.def                    66  ascii   05/30/84  23:45:46
  72. #-h-  kermit.c1                    20  ascii   05/30/84  23:45:47
  73. # kermitc1 --- common cchar
  74.  
  75. #
  76. #     Global characters
  77. #
  78.  
  79. common/Cchar/ state, padchar, eol, escchr, quotec, bquote, reptc, lastpk,
  80.       filnam(MAXNAM), recpkt(MAXLIN), packet(MAXLIN),msghdr(MAXLINE)
  81. character state                  # Present state of the automaton
  82. character padchar                # Padding character to send
  83. character eol                    # End-Of-Line character to send
  84. character escchr                 # Connect command escape character
  85. character quotec                 # Incoming quote character for control chars
  86. character bquote                 # Incoming quote character for 8th-bit
  87. character reptc                  # Incoming repeat prefix character
  88. character lastpk                 # Last received packet type
  89. character filnam                 # current file name
  90. character recpkt                 # Receive packet buffer
  91. character packet                 # Packet buffer
  92. character msghdr                 # Message header
  93. #-t-  kermit.c1                    20  ascii   05/30/84  23:45:47
  94. #-h-  kermit.c2                    40  ascii   05/30/84  23:45:47
  95. # kermitc2 --- cint
  96. #
  97. #      Global Variables
  98. #
  99.  
  100. common /Cint/ size, n, rpsiz, spsiz, pad, timint, numtry, oldtry,
  101.      fd, lfdin, lfdout, image, remspd, remote, debug, eoflg, 
  102.      srvflg, sflg, rflg, dobquo, dorept, xonwait, imgflg, binfil, crpend,
  103.      ttype, swait, mypad, nofilconv
  104. integer size                   # Size of present data
  105. integer n                      # Message number
  106. integer rpsiz                  # Maximum receive packet size
  107. integer spsiz                  # Maximum send packet size
  108. integer pad                    # How much padding to send
  109. integer timint                 # Timeout for foreign host on sends
  110. integer numtry                 # Times this packet retried
  111. integer oldtry                 # Times previous packet retried
  112. filedes fd                     # file pointer of file to read/write
  113. filedes lfdin                  # line file descriptor for reads
  114. filedes lfdout                 # line file descriptor for writes
  115. integer image                  # YES means 8-bit mode
  116. integer remspd                 # speed of this tty
  117. integer remote                 # YES means we're a remote host kermit
  118. integer debug                  # YES means debugging
  119. integer eoflg                  # EOF flag for Send Data state
  120. integer srvflg                 # Flag for server mode
  121. integer sflg                   # Flag for send mode
  122. integer rflg                   # Flag for receive mode
  123. integer dobquo                 # YES => do 8th bit quoting
  124. integer dorept                 # YES => do repeat prefixing
  125. integer xonwait                # YES => wait for XON before each packet send
  126. integer imgflg                 # YES => image-mode command flag set
  127. integer binfil                 # YES => do 8 bit i/o on this file
  128. integer crpend                 # YES => CR pending in bufemp
  129.  
  130. # HP3000 DEPENDENT:
  131. integer ttype                  # save terminal type at startup
  132. integer swait                  # milliseconds to wait after sending packet
  133. integer mypad                  # number of pad characters to request
  134. integer nofilconv              # YES => DON'T do incoming filename conversion
  135. #-t-  kermit.c2                    40  ascii   05/30/84  23:45:47
  136. #-h-  kermit.c3                     6  ascii   05/30/84  23:45:48
  137. ## cdefs ---  preprocessor common block to hold input characters
  138. # on kermitc3 on HP 3000
  139.  
  140.  common /Cpb/ bp, buf(PBSIZE)
  141.     integer bp      # next available character; init = 0
  142.     character buf   # pushed-back characters
  143. #-t-  kermit.c3                     6  ascii   05/30/84  23:45:48
  144. #-h-  kermit.r                   2486  ascii   05/30/84  23:45:50
  145. #-h-  main                       5603  local   01/18/84  08:53:22
  146. #
  147. #  K E R M I T   file transfer utility.
  148. #
  149. #  Kendall Tidwell & Allen Cole,   University of Utah Computer Center
  150. #
  151. #
  152. #  When Kermit is invoked without arguments it defaults to a Kermit server.
  153. #  The 's' argument invokes Kermit in the send state and must be followed
  154. #  by the file(s) that are to be sent.  The 'r' puts Kermit in the receive
  155. #  state. The 'r' option is not necessary since the Kermit server will
  156. #  handle both sending and receiveing.  The Kermit server however, cannot
  157. #  send more than one file at a time.  Thus, when sending more than one
  158. #  file it may be desireable to use the 's' option.
  159. #
  160. define(BANNER,"Software Tools Kermit (HP 3000)  Version 1n")
  161. define(USAGE,"usage:  kermit [rdif]  [sdif [file [-as name]]@.@.@.]  [dif].")
  162. # ifnotdef HP3000:  [rdifx]  [sdifx [file [-as name]]...]  [difx]
  163. #
  164. #
  165. #  Revision History:  (3 => change for HP3000, p => portable change)
  166. #
  167. # 5-18-84  kp   fixed prmsg to include cchar (for msghdr)
  168. # 1n            fixed rpack, gnxtfl, quiti to use msghdr
  169. #
  170. # 5-2-84   kp 3 changed setraw to explicitly turn off parity generation
  171. # 1m                 required on Series III hardware
  172. #               changed banner somewhat
  173. #
  174. # 4-27-84  kp 3 updated usage message
  175. # 1l            fixed gnxtfl to not try name translation on 'send' files
  176. #               added error messages for nearly every possible failure
  177. #                    new routine failmsg, called from recsw and sendsw
  178. #                    separated failures into retrys, wrong pkt number,
  179. #                         wrong packet type, other
  180. #               added file closing for aborted transfers:
  181. #                    recsw, sendsw, server
  182. #               changed recsw to delete incompletely transferred files
  183. #               added message upon server startup
  184. #               added 'f' flag: prevents incoming name translation
  185. #
  186. # 4-24-84  kp 3 fixed errors in doc file on use of 'x'
  187. #
  188. # 4-19-84  kp 3 changed rfile and gnxtfl to use new cant3s for better
  189. # 1k                 error messages
  190. #
  191. # 4-15-84  kp p changed outnam to uppercase outgoing filenames
  192. # 1j                 ("-as name" not affected)
  193. #               made server error messages better
  194. #               moved BANNER and USAGE macros to source file
  195. #
  196. # 4-2-84   kp 3 redid filename truncation algorithm (truncate)
  197. # 1i          3 added message for control-y (interrupt) termination
  198. #             p deleted Univac DBLINE debugging stuff
  199. #
  200. # 3-18-84  kp p changes to bufill, bufemp, ctl and rpack to use parity bit when
  201. # 1h                 sending/receiving binary files
  202. #             p fixed bufemp: crpend flag was not reset before starting out
  203. #             p changed getfil to OVERWRITE OLD FILES
  204. #             p minor fix to gnxtfl error msg
  205. #
  206. # 3-16-84  kp p added new routines for error packet handling:
  207. # 1g                 errpkt prints out error packets, errmsg sends error
  208. #                    packets (or prints, if local), prmsg prints a message
  209. #             p consolidated file opening code from sinit, seof, main
  210. #                    into gnxtfl
  211. #             p added -as flag for the send command
  212. #
  213. # 3-14-84  kp p redid some of bufill and bufemp:
  214. # 1f                 bufemp recognizes CR-LF's split across packets (for DEC_20)
  215. #                    CR-LFs are not subject to repeat prefixes
  216. #                    NEWLINE <--> CR-LF mapping turned off for binary files
  217. #             3 added binary file support: '8' flag, checks on file type
  218. #                    not tested yet
  219. #             3 changed setraw to check isatty before calling ffcontrol
  220. #             3 put termtype 13 into define TERMTYPE
  221. #
  222. # 3-11-84  kp p added debug code (a la Unix kermit)
  223. # 1e          p fixed filename bug in server that made 'send' command fail
  224. #             p added pbinit routine
  225. #
  226. # 3-9-84   kp p changed TRUE -> YES, FALSE -> NO
  227. # 1d          p added eighth-bit quoting and repeat prefixing:
  228. #                    rewrote bufill and bufemp
  229. #                    added globals reptc, dorept, dobquo; deleted eoflg
  230. #             p fixed inverted use of MYQUOTE and quote in bufil and bufemp
  231. #                    Unix version is also wrong, see protocol manual
  232. #             p fixed ctl (didn't work on DEL)
  233. #             p redid mask portably using mod function
  234. #             p redid chksum portably using mod function
  235. #             p added 'x' option for talking with 3000's and IBM's 
  236. #                    Causes wait for DC1 (^Q) before sending out a packet
  237. #                    in spack.  Not tested.
  238. #             p put program pause into system-dependent routine sleepm
  239. #
  240. # 2-29-84  kp 3 rewrote filename munging routines for HP3000:
  241. # 1c                 innam, outnam, chgnam, validate, truncate
  242. #             p  changed all usage of chgnam and innam to first
  243. #                    try the 'raw' filename, and then try the munged name:
  244. #                    rfile, seof, sinit, server
  245. #             p changed gnxtfl to call delarg only if there is one
  246. #             p changed getfil to NOT overwrite pre-existing files
  247. #                    rfile sends back a message if this condition occurs
  248. #             p changed routine lderr into routine erpack, which concatenates
  249. #                    two error messages together and sends them out as an
  250. #                    error packet
  251. #
  252. # 2-16-84  kp   PORT TO HP 3000:
  253. #               renamed include files
  254. #               passed thru stfix.scripts (HP 3000 dependent changes)
  255. #                    character -> pcharacter
  256. #                    index -> iindex
  257. #                    create -> creat
  258. #
  259. #             Changes for better portability/functionality:
  260. #               commented out all debugger ifdefs (apparently Univac-dependant)
  261. #               deleted 'external index' declarations
  262. #               changed several 'fd < 0' to 'fd == ERR' (also 'fd > 0')
  263. #               gave all functions at least one parameter
  264. #               added final returns to getfil, gnxtfl, quit
  265. #               changed spack to permit looser parameter checking
  266. #               added cchar include in getfil
  267. #               redid NEWLINE handling in bufill and bufemp
  268. #               changes to delarg's in main to avoid deleting non-existent args
  269. #               changed SINIT to use CR as eol default
  270. #               changed spsiz setting in rpar to be portable
  271. #               changed default quote to SHARP
  272. #               changed handling of files:
  273. #                    remfd -> lfdin is port to read packets from
  274. #                    lfdout is now port to send packets to
  275. #               made tochar and unchar into macros
  276. #               added NAK's for timeouts or mangled packets in rinit, 
  277. #                         rfile, rdata
  278. #               fixed server to terminate on EOF
  279. #               added defines and rpar, spar code for init parameters 7-10
  280. #               added startup banner
  281. #               reorganized routines into portable and nonportable sets
  282. #
  283. #             Changes just for HP3000:
  284. #               changed endst usage to pass OK or ERR (new endst)
  285. #               made necessary local changes to machine dependent routines:
  286. #                    setraw, unsetraw, putbuf
  287. #               changed routine names: mask->chksum, getbit->mask
  288. #               added timeouts: setioc calls in rpack, changes to GET_CH macro
  289. #
  290. #
  291. #  A Note About the Code:
  292. #     This RATFOR version of Kermit has been implemented on the
  293. #  University of Utah Computer Center Univac 1100/60 using the
  294. #  "Software Tools" prepared by the Advanced Research Group,
  295. #  Computer Science and Applied Mathematics Department, Lawrence
  296. #  Berkeley Laboratory, Berkeley, California.  Since this set of "tools"
  297. #  is very robust this implementation has been relatively easy.  
  298.  
  299. #  Due to limitations in the capabilities of the original ST primitves,
  300. #  as well as limitations due to local machine constraints, there
  301. #  are several pieces of code which are adapted for particular machines.
  302. #  These pieces of code have been marked for easy location with variations
  303. #  using the word DEPENDENT, such as:
  304. #
  305. #     *** MACHINE DEPENDENT FUNCTION ***
  306. #
  307. #     HP3000 DEPENDENT
  308. #
  309. #     U1100 DEPENDENT     etc
  310. #
  311. #  The machine dependent code inside of functions and subroutines
  312. #  has been marked as follows :
  313. #
  314. #     #  xxx DEPENDENT
  315. #              .
  316. #              .
  317. #              .
  318. #     #  END MACHINE DEPENDENT
  319. #
  320. #  or
  321. #
  322. #     #ifdef(xxx)
  323. #              .
  324. #              .
  325. #              .
  326. #     #elsedef
  327. #     #        .
  328. #     #        .
  329. #     #        .
  330. #     #enddef
  331. #
  332. #  The latter form is in preparation for the new ratfor preprocessor.
  333. #  The ifdef, elsedef, enddef statements are not functonal yet.
  334. #
  335. #  Single machine dependent statements are commented :
  336. #
  337. #        statement  # MACHINE DEPENDENT
  338. #
  339. #
  340. #  Many of these pieces of code may not be needed for other systems.
  341. #  Other pieces may only need to be modified.  Since there are few
  342. #  pieces of non-portable code, installing Kermit will hopefully be an
  343. #  easy task.
  344. #
  345. #     Binary Data Transmission:
  346. #  This code assumes that using the eighth bit for data transmission
  347. #  is not possible.  (The Unix kermit has provisions for an 'image' mode.)
  348. #  Eighth-bit quoting (as per the Kermit standard) is
  349. #  implemented to allow binary transfers.  (The cost is a 50% transmission 
  350. #  overhead).  See, however, the caveats in bufill and bufemp about
  351. #  the use of getch and putch for binary data.
  352.  
  353.  
  354.  
  355. #
  356. #  M A I N
  357. #
  358. #  This is the main body of Kermit which calls to the other
  359. #  functions and procedures.
  360. #
  361. DRIVER(kermit)
  362. include kermit.def   # ("rkerm.h") # Definitions related to Kermit only
  363. include cint                     # Common block of integers
  364. include cchar                    # Common block of characters
  365.  
  366. integer numarg,junk,retn           # Counter for arguments, dummy
  367. character mode(MAXNAM)             # Holds argument string
  368.  
  369. integer server                     # Server mode state switcher
  370. integer recsw                      # Controlling function in Receive mode
  371. integer sendsw                     # Controlling function in Send mode
  372. integer getarg                     # Gets line of input from STDIN
  373. integer getenv                     # Gets environment values
  374. integer findarg_i    # HP3000
  375.  
  376. string help USAGE
  377. string banner BANNER
  378. string stdhdr "ST "                 # Default header for messages
  379. string s_kerm "Kermit"
  380. string s_kermhdr "kermitheader"     # Environment variable name
  381.  
  382.     call query(USAGE)               # User help
  383.  
  384.     if (getenv (s_kermhdr, msghdr) == NO) # Look for message header in env
  385.       call strcpy (stdhdr, msghdr)  # Use default message header
  386.     call concat (msghdr, s_kerm, msghdr)
  387.  
  388.     spsiz=80                       # default packet size
  389.     timint = 10                    # default timeout for receiving packets
  390.     pad=0                          # No padding
  391.     padchar=NULL                   # Use NULL if any padding wanted
  392.     eol=CR                         # EOL for outgoing packets
  393.     quotec=SHARP                   # Standard control-quote character
  394.     bquote=MYBQUOTE                # Binary quote char
  395.     dobquo = NO                    # Default: no binary quoting
  396.     reptc = MYREPTC                # Repeat prefix
  397.     dorept = NO                    # Default: no repeat prefixing
  398.     escchr=ESCCHR                  # Escape char for connect mode
  399.  
  400.     call pbinit                     # Initialize pushback buffer
  401.     fd = ERR                        # Initialize file descriptor
  402.     xonwait = NO                    # Default: don't do XON wait 
  403.     nofilconv = NO                  # Default: do incoming filename conversion
  404.     image = NO                      # No image mode at present
  405.     debug = 0                       # 0: no debugging, 1: states, 2: verbose
  406.     imgflg = NO                       # Default: not binary mode
  407.     binfil = NO                     # ditto
  408.     
  409.     remote=YES                        # This Kermit is always remote 
  410.     lfdin=STDIN                     # therefore, use standard i/o ports for line
  411.     lfdout=STDOUT                   # May be STDIN on some machines
  412.  
  413.     sflg = 0                        # Turn off parse flags
  414.     rflg = 0
  415.     srvflg = 0
  416.  
  417.     # HP3000 DEPENDENT
  418.     if (findarg_i ("-sw.", swait) == EOF)     # Look for -sw flag (debug)
  419.       swait = 0                     # Default
  420.     if (findarg_i ("-pad.", mypad) ^= EOF)    # Look for -pad flag
  421.       mypad = min(94,max(0,mypad))  # must be in range 0-94
  422.     else
  423.     # END
  424.       mypad = MYPAD                    # Default
  425.  
  426.       #call test_buf                # a way to test just bufill and bufemp
  427.  
  428.     numarg = getarg(1,mode,MAXNAM) # Get first command line argument
  429.     if (numarg == EOF)             # If no argument....
  430.       srvflg = 1                   #  default to server mode.
  431.     else   {
  432.       call upper(mode)             # Make argument completely upper case
  433.       for (i=1; mode(i) ^= EOS; i=i+1) {      # loop through flags
  434.         switch(mode(i))  {
  435.           case BIGR:               # If argument starts with R...
  436.             rflg = 1               #  go to receive state.
  437.           case BIGS:               # If argument starts with S...
  438.             sflg = 1               #  go to send state.
  439.           case BIGD:
  440.             debug = debug + 1      # higher debug level
  441.           case BIGX:
  442.             xonwait = YES          # do wait for ^Q (XON) before sending packets
  443.           case BIGF:
  444.             nofilconv = YES        # DON'T convert incoming filenames
  445.           case BIGI, DIG8:          # '8' is for compatablity only
  446.             imgflg = YES            # force binary (image) mode
  447.           default:                 # Anything else...
  448.             call usage             #  is erroneous.
  449.           }
  450.         }
  451.     }
  452.     if (numarg ^= EOF)
  453.       call delarg(1)               # Delete argument
  454.     if (rflg == 1  &  sflg == 1)
  455.       call usage                   # 'r' and 's' is wrong
  456.     else if (rflg == 0  &  sflg == 0)
  457.       srvflg = 1                   # No 'r' or 's' => server mode
  458.  
  459.   #ifdef (HP3000)
  460.     if (srvflg == 0  &  isatty(lfdin) == NO)
  461.       remote = NO
  462.   #endef
  463.  
  464.     call printf (STDOUT, "%s:  %s@n.", msghdr, banner)  # Ready message
  465.  
  466.     if (srvflg == 1)  {
  467.       call putlin (msghdr, STDOUT)
  468.       call printf (STDOUT, " Server Mode@n   _
  469.       Terminate with the 'finish' command (from your local kermit) or a ^Y@n.")
  470.       call setraw                  # Set raw mode
  471.       retn = server(DUM)           # Invoke server
  472.       call unsetraw                # Restore tty
  473.       }
  474.  
  475.     if (sflg == 1)  {
  476.       numarg = getarg(1,filnam,MAXNAM)  # Check for a file name in command line
  477.       if (numarg == EOF)           # If no name is given...
  478.         call usage                 # Print error message
  479.       call setraw                  # Set raw mode
  480.       retn = sendsw(EOS, BIGS)     # Go to send state (start w/ send-init)
  481.       call unsetraw                # Restore tty
  482.       }
  483.  
  484.     if (rflg == 1)  {
  485.       call setraw                  # Set raw mode
  486.       retn = recsw(DUM)            # Go to receive state
  487.       call unsetraw                # Restore tty
  488.       }
  489.  
  490.     if (retn == LETA  |  retn == NO)# It aborted
  491.       call endst(ERR)               # End kermit with an error status
  492.  
  493.     DRETURN
  494.     end
  495. #-t-  main                       5603  local   01/18/84  08:53:22
  496. #-h-  bufemp                     1116  local   12/29/83  14:15:12
  497. #
  498. #  B U F E M P
  499. #
  500. #  Get data from an incoming packet into a file
  501. #  Control-quoting, 8-bit & repeat prefixes are done.
  502. #  Note that parity stripping was already done in spack.
  503. #
  504. #  Assumes putch (to a file) works with 8-bit data.   HP3000 DEPENDENT
  505. #  If this is not the case, putch call will have to
  506. #  be replaced with some more complicated function that calls writef.
  507. #
  508. # next line is HP3000 DEPENDENT segmentation information
  509.  
  510. subroutine bufemp(buffer,bfd,len)
  511.  
  512. character buffer(ARB)              # Buffer
  513. integer bfd, len                    # File pointer, length
  514.  
  515.   include cchar                    # Common block of characters
  516.   include cint                     # Common block of integers
  517.  
  518.   integer ctl, mask                 # Ctl, mask functions
  519.  
  520.   integer nrep                      # repeat count
  521.   integer i, j                      # Counter
  522.   character t, t8, t7              # Character holders
  523.  
  524.   i = 1                             # Set buffer index
  525.   if (crpend == YES)                # If there is a CR pending from last packet
  526.       if (len >= 2  &  buffer(1) == quotec  &  ctl(buffer(2)) == LF)
  527.            {
  528.            call putch (NEWLINE, bfd) # a CR-LF sequence that was split up
  529.            i = 3                    # skip the LF
  530.            }
  531.       else
  532.            call putch (CR, bfd)     # it was just a CR
  533.   crpend = NO                       # No CR pending anymore
  534.  
  535.   for ( ; i<=len; INCR(i))        # Loop thru data field
  536.       {
  537.       t = buffer(i)                 # Get character
  538.       if (dorept == YES  &  t == reptc)
  539.            {                        # Repeat prefix seen
  540.            nrep = unchar(buffer(i+1))    # Get the count
  541.            i = i + 2
  542.            t = buffer(i)            # Next char
  543.            }
  544.       else
  545.            nrep = 1
  546.  
  547.       if (dobquo == YES  &  t == bquote)
  548.            {                        # Found eighth-bit quote
  549.            t8 = 128                 # save value for eighth bit
  550.            INCR(i)
  551.            t = buffer(i)            # Next char
  552.            }
  553.       else
  554.            t8 = 0
  555.  
  556.       if (t == quotec)
  557.            {                        # A quoted char
  558.            INCR(i)
  559.            t = buffer(i)            # get the next char
  560.            t7 = mask(t)
  561.            if (t7 >= 63  &  t7 <= 95)
  562.                 t = ctl(t)          # Controlify the quoted control char
  563.            }
  564.       t = t + t8                    # Add in eighth bit
  565.  
  566.       if (t == CR  &  
  567.                 binfil == NO  &     # only do CR-LF mapping for ascii files
  568.                 nrep == 1)          # CR-LF does not get a repeat count
  569.            if (i+2 <= len  &  buffer(i+1) == quotec  &  ctl(buffer(i+2)) == LF)
  570.                 {                   # CR, LF sequence
  571.                 t = NEWLINE         # It's a NEWLINE
  572.                 i = i + 2           # skip LF
  573.                 }
  574.            else if (i == len)       # This is CR at the end of the packet
  575.                 {
  576.                 crpend = YES        # Mark it as 'pending'
  577.                 break               # and don't put it out
  578.                 }
  579.  
  580.       for (j=1; j<=nrep; j=j+1)     # Put out the correct number of chars
  581.            call putch (t, bfd)
  582.       }
  583.   return
  584.   end
  585. #-t-  bufemp                     1116  local   12/29/83  14:15:12
  586. #-h-  bufill                     1582  local   12/29/83  14:15:13
  587. #
  588. #  B U F I L L
  589. #
  590. #  Get a bufferful of data from the file that's being sent.
  591. #  Control-quoting, 8-bit & repeat prefixes are done.
  592. #
  593. #  Assumes ngetch returns 8-bit data.     HP3000 DEPENDENT
  594. #  If this is not the case, getch call (in ngetch) will have to
  595. #  be replaced with some more complicated function that calls readf.
  596. #
  597. # next line is HP3000 DEPENDENT segmentation information
  598.  
  599.  
  600. integer function bufill(buffer)
  601.  
  602. character buffer(ARB)              # Buffer
  603.  
  604.   include cchar                    # Common block of characters
  605.   include cint                     # Common block of integers
  606.  
  607.   character c, c1, c7             # Character holder
  608.   character ctl, ngetch           # Functions
  609.   integer mask                     # Function
  610.   integer i, j                     # Loop index
  611.  
  612.   i = 1
  613.   while (ngetch(c,fd) != EOF)       # Loop: Get next character
  614.       {
  615.       if (dorept == YES  &          # repeat prefixing enabled
  616.                 c ^= NEWLINE)       # cannot do repeat counts for CR-LFs
  617.            {
  618.            for (j=1; ngetch(c1,fd) == c; j=j+1)    # look for repeated chars
  619.                 if (j >= 94)        # 94 char repeat limit
  620.                      break
  621.            call putbak(c1)          # put back the one that didn't match
  622.            if (j < 3)               # If less than threshhold for doing repeat
  623.                 for ( ; j>1; j=j-1) #    put them back
  624.                      call putbak(c)
  625.            else
  626.                 {
  627.                 CHCOPY (MYREPTC, buffer, i)   # repeat prefix
  628.                 CHCOPY (tochar(j), buffer, i) # repeat count
  629.                 }
  630.            }
  631.       if (c == NEWLINE)
  632.            {
  633.            if (binfil == NO)
  634.                 {                   # do a CR, LF sequence
  635.                 CHCOPY (MYQUOTE, buffer, i) 
  636.                 CHCOPY (ctl(CR), buffer, i)
  637.                 CHCOPY (MYQUOTE, buffer, i)
  638.                 CHCOPY (ctl(LF), buffer, i)
  639.                 }
  640.            else                     # A NEWLINE in binary mode
  641.                 ;         # Strip NEWLINES in binary mode.    HP3000 DEPENDENT
  642.                           # If using readf and NEWLINE is an ascii char,
  643.                           # this is wrong.
  644.            }
  645.       else
  646.            {
  647.            c = mod (c,256)     # strip down to eight bits (should already be)
  648.            if (c > 127 & dobquo == YES)       # If eighth bit on
  649.                 {
  650.                 CHCOPY (MYBQUOTE, buffer, i)  # add eighth-bit quote
  651.                 c = mask(c)                   # strip down to seven bits
  652.                 }
  653.            else if (binfil == NO)             # If in ascii mode
  654.                 c = mask(c)                   #  strip down to seven bits
  655.            c7 = mask(c)                       # A seven bit version of c
  656.            if (c7<BLANK | c7==DEL | c7==MYQUOTE | 
  657.                      (c7==MYBQUOTE & dobquo==YES) | (c7==MYREPTC & dorept==YES))
  658.                 {                             # need to quote this char
  659.                 CHCOPY (MYQUOTE, buffer, i)   # add quote char
  660.                 if (c7<BLANK | c7==DEL)
  661.                      {
  662.                      c = ctl(c)               # de-controlify control char
  663.                      c7 = ctl(c7)
  664.                      }
  665.                 }
  666.            if (binfil == YES)       # If in binary mode
  667.                 CHCOPY (c, buffer, i)   # Use the eight bit version
  668.            else                     # if in ascii mode
  669.                 CHCOPY (c7, buffer, i)  # Use the seven bit version
  670.            }
  671.       if (i-1 >= spsiz-9) return(i-1)  # Check length
  672.       }
  673.  
  674.   if (i == 1) 
  675.       return(EOF)                   # Wind up here only on EOF
  676.  
  677.   return(i-1)                       # Handle partial buffer before EOF
  678.   end
  679. #-t-  bufill                     1582  local   12/29/83  14:15:13
  680. #-h-  ctl
  681. #
  682. #  C T L
  683. #
  684. #  Turns a control character into a printable charcter and vice versa 
  685. #  by toggling the control bit (ie. ^A becomes  A and A becomes ^A).
  686.  
  687. character function ctl(ch)
  688.  
  689. character ch
  690.  
  691.   integer mask
  692.  
  693.   if (mask(ch)>=64)                # If not control character
  694.     return (ch-64)                 # make it a control character
  695.   else                             # If control character
  696.     return (ch+64)                 # make it a regular character
  697.  
  698.   return                           # dummy for compiler
  699.   end
  700. #-t-  ctl
  701. #-h-  errmsg
  702. #
  703. #  E R R M S G
  704. #
  705. #  Load two part error message, send it or print it.
  706. #
  707.  
  708. subroutine errmsg(mesg,mesg2)
  709.  
  710. character mesg(ARB),mesg2(ARB)        # Messages
  711.  
  712. include cint
  713. include cchar
  714.  
  715. string s_c ": "
  716.  
  717.   i = 1
  718.   call stcopy (msghdr,1,packet,i)
  719.   call stcopy (s_c,1,packet,i)
  720.   call stcopy (mesg,1,packet,i)
  721.   call stcopy (mesg2,1,packet,i)
  722.   packet(MAXLINE) = EOS
  723.   if (remote == YES)                  # If this is a remote kermit
  724.     {                               # send message as an error packet
  725.     packet(MAXPACK-1) = EOS         # truncate to legal size
  726.     call spack (BIGE,n,length(packet),packet)  # Send the error packet
  727.     }
  728.   else
  729.     call prmsg (mesg, mesg2)
  730.  
  731.   return
  732.   end
  733. #-t-  errmsg
  734. #-h-  errpkt
  735. #
  736. #  E R R P K T
  737. #
  738. #  Print an error packet.
  739. #
  740.  
  741. subroutine errpkt(pkt)
  742.  
  743. character pkt(ARB)
  744.  
  745. include cint
  746.  
  747.  
  748.   call eprintf ("Error from remote Kermit: %s@n.", pkt)
  749.  
  750.   return
  751.   end
  752. #-t-  errpkt
  753. #-h-  failmsg
  754. #
  755. #  F A I L M S G
  756. #
  757. #  Send message about a protocol failure.
  758. #
  759. subroutine failmsg(oldstate)
  760.  
  761. character oldstate
  762.  
  763.   include cint
  764.   include cchar
  765.  
  766.   character line(MAXLINE)
  767.   integer i
  768.  
  769.   string retr "Retry limit exceeded"
  770.   string wrong "Wrong packet number received"
  771.   string type1 "Wrong packet type "
  772.   string type2 " received"
  773.   string stat "Illegal internal state "
  774.  
  775.   string while " while in state "
  776.   string infile ", in file "
  777.   string s_0 "  "
  778.  
  779.   i = 1
  780.   switch (state)                    # Find the appropriate error message
  781.       {
  782.       case LETA:  return            # a message was already received or sent
  783.       case LETM:  call stcopy (retr,1,line,i)
  784.       case LETN:  call stcopy (wrong,1,line,i)
  785.       case LETW:  call stcopy (type1,1,line,i)
  786.                   call chcopy (lastpk,line,i)
  787.                   call stcopy (type2,1,line,i)
  788.       default:    call stcopy (stat,1,line,i)
  789.       }
  790.   call stcopy (while,1,line,i)
  791.   call chcopy (oldstate,line,i)        # Give the state
  792.   if (fd ^= ERR) {                  # Give the file, if open
  793.       call stcopy (infile,1,line,i)
  794.       call stcopy (filnam,1,line,i)
  795.       }
  796.  
  797.   call errmsg (line, s_0)           # Send error message to appropriate place
  798.   if (debug > 0  &  remote == YES)
  799.       call prmsg (line, s_0)        # Send a copy to ERROUT if debug is on
  800.  
  801.   return
  802.   end
  803. #-t-  failmsg
  804. #-h-  getcmd
  805. #
  806. #  G E T C M D
  807. #
  808. #  Gets command from G packet.
  809. #
  810.  
  811. character function getcmd(len,cmd)
  812.  
  813. integer len                        # Command length
  814. character cmd(ARB)                 # Command holder
  815.  
  816.   if (len == 1)                    # This Kermit only handles single
  817.     getcmd = cmd(1)                #  character commands
  818.   else if (len > 1)
  819.     getcmd = cmd(1)
  820.  
  821.   return
  822.   end
  823. #-t-  getcmd
  824. #-h-  getfil                      684  local   12/29/83  14:15:14
  825. #
  826. #  G E T F I L
  827. #
  828. #  Open a new file, overwriting any existing file.
  829. #
  830.  
  831. integer function getfil(filenm)
  832.  
  833. character filenm(ARB)              # File name holder
  834.  
  835.   filedes create, open             # create and open functions
  836.   integer gettyp1, setenv         # (or gettyp)
  837.   character getch                
  838.  
  839.   character c                      # character holder
  840.   integer junk
  841.  
  842.   include cint                     # Common block of integers
  843.   include cchar                    # Common block of characters
  844.  
  845. #ifdef (HP3000) 
  846.   string s_deffile "deffile"        # HP3000 environment variable for setting
  847.   string bin_mods "rec=128,1,f,b:disc=4000"   #  default file type for creat
  848. #endef
  849.  
  850.   c = LETA                         # Signal for a non-empty or non-existent file
  851.   fd = open(filenm, READ)           # test whether file already exists
  852.   if (fd ^= ERR) {
  853.     c = getch(c,fd)                 # test for empty file
  854.     call close (fd)
  855.   }
  856.   if (c == EOF)
  857.     fd = open (filenm, APPEND)      # Append to an empty file
  858.   else
  859.     {
  860.   #ifdef (HP3000)
  861.     if (imgflg == YES)
  862.       junk = setenv (s_deffile, bin_mods)
  863.   #endef
  864.     fd = create(filenm,WRITE)        # Otherwise, create a new one
  865.   #ifdef (HP3000)
  866.     if (imgflg == YES)
  867.       call rmenv (s_deffile)        # delete the environment variable
  868.   #endef
  869.     }
  870.  
  871.   crpend = NO                      # Reset crpend flag for bufemp
  872.   if (fd ^= ERR)
  873.       {
  874.       call strcpy (filenm, filnam)  # Remember the name
  875.       if (gettyp1(fd) == BINARY  |  imgflg == YES)
  876.            binfil = YES
  877.       else
  878.            binfil = NO
  879.       return(fd)                     # Return file descriptor
  880.       }
  881.   else                             # If file won't open
  882.     return(NO)                     # Return false
  883.  
  884.   return
  885.   end
  886. #-t-  getfil                      684  local   12/29/83  14:15:14
  887. #-h-  gnxtfl
  888. #
  889. #  G N X T F L
  890. #
  891. #  Get next file from command line.
  892. #
  893. # special compiler control HP3000 DEPENDENT:
  894.  
  895. integer function gnxtfl(sname)
  896.  
  897.   character sname(ARB)
  898.  
  899.   include cchar                    # Common block of characters
  900.   include cint                     # Common block of integers
  901.  
  902.   integer getarg, equal             # Functions
  903.   integer gettyp1                   # gettyp on most machines  HP3000 DEPENDENT
  904.   filedes open
  905.  
  906.   string s_as "-as"                # Flag arg to indicate name to send under
  907.   string cant(MAXLINE) "Can't open file "    # File opening error message
  908.   string s_dum ""
  909.   string noname "No file name after '-as' after "  # -as error message
  910.  
  911.   if (sname(1) ^= EOS)             # If name supplied (server mode)
  912.     call strcpy (sname, filnam)    #  use given file name
  913.   else
  914.     {
  915.     if (getarg(1,filnam,MAXNAM) == EOF) # Otherwise, get next file name
  916.       return(BIGB)                  # No more names - break transmission
  917.     call delarg(1)                  # Delete argument
  918.     }
  919.  
  920.   call pbinit                     # Reset the pushback buffer
  921.   fd = open(filnam,READ)          # Try raw name first
  922.   if (fd == ERR)  {               # If it doesn't exist
  923. #ifdef(HP3000)
  924.     call cant3s (".", 0, filnam, cant) # special error message retrieval
  925.     cant(94) = EOS                  # just to be sure of the length
  926.     call errmsg (cant, s_dum)
  927. #elsedef
  928. #    call errmsg (cant, filnam)     # Send error message
  929. #enddef
  930.     return(LETA)                  # Abort
  931.     }
  932.  
  933.   if (gettyp1(fd) == BINARY  |  imgflg == YES)  # check for whether we should 
  934.     binfil = YES                              # treat this a binary file
  935.   else
  936.     binfil = NO
  937.  
  938.   if (remote == NO)
  939.     call printf (ERROUT, "%s: sending file '%s'.", msghdr, filnam)
  940.  
  941.   call outnam(filnam)               # Put name into standard format
  942.  
  943.   if (getarg(1,packet,MAXNAM) ^= EOF)  # If the next arg 
  944.     if (equal (s_as, packet) == YES)   #    is the '-as' flag
  945.       {
  946.       call delarg(1)                # Delete it
  947.       if (getarg(1,packet,MAXNAM) == EOF)   # If there's not another name
  948.          {
  949.          call errmsg (noname, filnam) # send an error message
  950.          return(LETA)               # and abort
  951.          }
  952.       else
  953.          {
  954.          call delarg(1)             # Delete arg
  955.          call strcpy(packet, filnam)     # copy this into the filename slot
  956.          }
  957.       }
  958.  
  959.   if (remote == NO)
  960.     call printf (ERROUT, " as '%s'@n.", filnam)
  961.   return(BIGF)                      # Ready to send new file.
  962.  
  963.   end
  964. #-t-  gnxtfl
  965. #-h-  ngetch
  966. # ngetch --- get a (possibly pushed back) character
  967.  
  968. # next line is HP3000 DEPENDENT segmentation information
  969.  
  970.    character function ngetch(c, fd)
  971.    character getch
  972.    character c
  973.    integer fd
  974.  
  975.    include cpb
  976.  
  977.    if (bp > 0) {
  978.       c = buf(bp)
  979.       bp = bp - 1
  980.       }
  981.    else
  982.       c = getch(c, fd)
  983.    ngetch = c
  984.    return
  985.    end
  986. #-t-  ngetch
  987. #-h-  pbinit
  988. # pbinit --- initialize the push-back buffer
  989.  
  990. subroutine pbinit
  991.  
  992.   include cpb
  993.  
  994.   bp = 0
  995.  
  996.   return
  997.   end
  998. #-t-  pbinit
  999. #-h-  prmsg
  1000. #
  1001. #  P R M S G
  1002. #
  1003. #  Load two part message and print it.
  1004. #
  1005.  
  1006. subroutine prmsg(mesg,mesg2)
  1007.  
  1008. character mesg(ARB),mesg2(ARB)        # Messages
  1009.  
  1010. include cint
  1011. include cchar
  1012.  
  1013.   if (remote == NO)                   # If this is a local kermit
  1014.     call eprintf ("%s: %s %s@n.", msghdr, mesg, mesg2)   # print the message
  1015.  
  1016.   return
  1017.   end
  1018. #-t-  prmsg
  1019. #-h-  putbak
  1020. # putbak --- push character back onto input
  1021.  
  1022. # next line is HP3000 DEPENDENT segmentation information
  1023.  
  1024.    subroutine putbak(c)
  1025.    character c
  1026.  
  1027.    include cpb
  1028.  
  1029.    bp = bp + 1
  1030.    if (bp > PBSIZE)
  1031.       call error ("too many characters pushed back.")
  1032.    buf(bp) = c
  1033.    return
  1034.    end
  1035. #-t-  putbak
  1036. #-h-  rdata                      2639  local   12/29/83  14:15:15
  1037. #
  1038. #  R D A T A
  1039. #
  1040. #  Receive Data
  1041. #
  1042. # CONTAINS HP3000 DEPENDENT CODE
  1043. #
  1044.  
  1045. character function rdata(dum)
  1046.  
  1047.   integer dum
  1048.  
  1049.   include cchar                    # Common block of chars
  1050.   include cint                     # Common block of integers
  1051.  
  1052.   integer num, len, x              # Packet number, length, dummy
  1053.   character rpack
  1054.  
  1055.   if (numtry > MAXTRY) return(LETM)  # "Abort" if too many tries
  1056.   INCR(numtry)
  1057.   switch(rpack(len,num,packet))  { # Get packet
  1058.     case BIGD:                     # Got Data packet
  1059.       if (num != n)  {             # Right packet ?
  1060.         if (oldtry > MAXTRY) return(LETM) # No. If too many tries
  1061.         INCR(oldtry)               # give up
  1062.         if (n ==0)                 # Else check packet number
  1063.           x = 63
  1064.         else
  1065.           x = n-1
  1066.         if (num == x)  {           # Previous packet again ?
  1067.           call spack(BIGY,num,0,0) # Yes, re-ACK it
  1068.           numtry = 0               # Reset try counter
  1069.           return(state)            # Stay in D, don't write out data!
  1070.           }
  1071.         else  return(LETN)         # Sorry! Wrong number.
  1072.         }
  1073.                                    # Got data with right packet number
  1074.       call bufemp(packet,fd,len)   # Write the data to the file
  1075.       call spack(BIGY,n,0,0)       # Acknowledge the the packet
  1076.       oldtry = numtry              # Reset the try counters
  1077.       numtry = 0                   # ...
  1078.       n = mod(n+1,64)              # Bump the packet number, mod 64
  1079.       return(BIGD)                 # Remain in data state
  1080.  
  1081.     case BIGF:                     # Got a File Header
  1082.       if (oldtry > MAXTRY) return(LETM) # If too many tries, "abort"
  1083.       INCR(oldtry)
  1084.       if (n == 0)                  # Else check packet number
  1085.         x = 63
  1086.       else
  1087.         x = n-1
  1088.       if (num == x)  {             # It was the previous one
  1089.         call spack(BIGY,num,0,0)   # ACK it again
  1090.         numtry = 0                 # Reset try counter
  1091.         return(state)              # Stay in data state
  1092.         }
  1093.       else return(LETN)            # Not previous packet, "abort"
  1094.  
  1095.     case BIGZ:                     # End-Of-File
  1096.       if (num != n)  return(LETN)  # Must have right packet number
  1097.       call spack(BIGY,n,0,0)       # OK, ACK it.
  1098.       call bufemp(packet,fd,0)     # flush possible final CR
  1099.       call flush(fd)               # flush file system buffers
  1100.     #ifdef(HP3000)    DEPENDENT
  1101.       call close_type (fd, %10)    # truncate fixed record file after EOF
  1102.     #elsedef
  1103.       #call close(fd)              # Close the file
  1104.     #enddef
  1105.       fd = ERR                     # Remember that file was closed
  1106.       n = mod(n+1,64)              # Bump the packet number
  1107.       return(BIGF)                 # Go back to Receive File state
  1108.  
  1109.     case LETC,LETT:                # No good packet came
  1110.       call spack (BIGN, n, 0, 0)   # NAK
  1111.       return(state)                # Keep waiting
  1112.     case BIGE:                     # Error packet
  1113.       call errpkt (packet)         # print it
  1114.       return(LETA)                 # Abort
  1115.     default: return(LETW)          # Some other packet, "abort"
  1116.     }
  1117.   return
  1118.   end
  1119. #-t-  rdata                      2639  local   12/29/83  14:15:15
  1120. #-h-  recsw                      1037  local   12/29/83  14:15:17
  1121. #
  1122. # R E C S W
  1123. #
  1124. # This is the state table switcher for receiving files.
  1125. #
  1126.  
  1127. integer function recsw (dum)
  1128.  
  1129.   integer dum
  1130.  
  1131.   include cchar                    # Common block of chars
  1132.   include cint                     # Common block of integers
  1133.  
  1134.   character rinit, rdata, rfile    # Use these functions
  1135.   integer junk
  1136.   character lstate, llstate
  1137.   integer remove
  1138.  
  1139.   if (srvflg == 1)                 # If in server mode
  1140.     state = BIGF                   #  start in F state.
  1141.   else  {
  1142.     state = BIGR                   # Receive is the start state
  1143.     n = 0                          # Initialize message number
  1144.     numtry = 0                     # Say no tries yet
  1145.     }
  1146.  
  1147.   repeat  {                        # Do until done
  1148.     if (debug >= 1)
  1149.       call eprintf ("  recsw %c %d@n.", state, n)
  1150.     switch(state)  {
  1151.       case BIGD: state = rdata(DUM)# Data receive state
  1152.       case BIGF: state = rfile(DUM)# File receive state
  1153.       case BIGR: state = rinit(DUM)# Send initiate state
  1154.       case BIGC: return(YES)       # Complete state
  1155.       default:                     # Anything else is an error
  1156.            call failmsg(llstate)    # Put out an error message
  1157.            if (fd ^= ERR) {         # If file left open
  1158.              call close (fd)        # Close it
  1159.              fd = ERR               # Remember it's closed
  1160.              junk = remove (filnam) # Delete the partial file
  1161.              }
  1162.            return (NO)              # Error return
  1163.       }
  1164.     llstate = lstate               # Remember last state
  1165.     lstate = state
  1166.     }
  1167.   return
  1168.   end
  1169. #-t-  recsw                      1037  local   12/29/83  14:15:17
  1170. #-h-  rfile                      2961  local   02/04/84  14:59:18
  1171. #
  1172. #  R F I L E
  1173. #
  1174. #  Receive File Header
  1175. #
  1176.  
  1177. character function rfile(dum)
  1178.  
  1179.   integer dum
  1180.  
  1181.   include cchar                    # Common block of chars
  1182.   include cint                     # Common block of integers
  1183.  
  1184.   integer num, len, x, g           # Packet length, number, dummy
  1185.   integer getfil                           # functions
  1186.   character rpack                  # Rpack function
  1187.  
  1188.   string cant(MAXLINE) "Can't open file "          # Error message
  1189.   string exists " already exists"
  1190.   string s_dum ""
  1191.  
  1192.   if (numtry > MAXTRY) return(LETM) # If too many tries, "abort"
  1193.   INCR(numtry)
  1194.  
  1195.   switch(rpack(len,num,packet)) {  # Get a packet
  1196.     case BIGS:                     # Send-Init, maybe our ACK lost
  1197.       if (oldtry > MAXTRY) return(LETM) # If too many tries, "abort"
  1198.       INCR(oldtry)
  1199.       if (n==0)
  1200.         x = 63
  1201.       else
  1202.         x = n-1
  1203.       if (num == x)  {             # Previous packet count mod 64?
  1204.         call spar(packet)          # Yes, ACK it again
  1205.         call spack(BIGY,num,INIT_SIZ,packet) # with our Send-Init parameters
  1206.         numtry = 0                 # Reset try counter
  1207.         return(state)              # Stay in this state
  1208.         }
  1209.       else  return(LETN)           # Not previous packet, "abort"
  1210.  
  1211.     case BIGZ:                     # End of File
  1212.       if (oldtry > MAXTRY) return(LETM)
  1213.       INCR(oldtry)
  1214.       if (n == 0)
  1215.         x = 63
  1216.       else
  1217.         x = n-1
  1218.       if (num == x)  {             # Previous packet, mod 64?
  1219.         call spack(BIGY,num,0,0)   # Yes, ACK it again.
  1220.         numtry = 0                 # Reset try counter
  1221.         return(state)              # Stay in this state
  1222.         }
  1223.       else  return(LETN)           # Not previous packet, "abort"
  1224.  
  1225.     case BIGF:                     # File Header
  1226.       if (num != n)  return(LETN)  # which is what we really want
  1227.                                    # The packet number must be right
  1228.       g = getfil(packet)           # Try to open a new file with raw name
  1229.       if (g == NO  &  nofilconv == NO) {# If it failed due to incompatable name
  1230.         call innam(packet)           # Make file name local compatible
  1231.         g = getfil(packet)           # Retry open
  1232.         }
  1233.       if (g == NO) {
  1234.     #ifdef(HP3000)
  1235.         call cant3s (".", 0, packet, cant) # special error message retrieval
  1236.         cant(94) = EOS                # just to be sure
  1237.         call errmsg (cant, s_dum)
  1238.     #elsedef
  1239.     #    call errmsg (cant, packet)     # Send error message
  1240.     #enddef
  1241.         return(LETA)               # Give up if can't
  1242.         }
  1243.       else if (g == LETA) {         # File already exists
  1244.         call errmsg(packet, exists) # Send error message 
  1245.         return(LETA)               # Give up if can't
  1246.         }
  1247.  
  1248.       call spack(BIGY,n,length(packet),packet) # Acknowledge the file header
  1249.       oldtry = numtry              # Reset the try counters
  1250.       numtry = 0                   # ....
  1251.       n = mod(n+1,64)              # Bump packet number, mod 64
  1252.       return(BIGD)                 # Switch to Data state
  1253.  
  1254.     case BIGB:                     # Break transmission (EOT)
  1255.       if (num != n) return(LETN)   # Need right packet number here
  1256.       call spack(BIGY,n,0,0)       # Say OK
  1257.       return(BIGC)                 # Go to complete state
  1258.  
  1259.     case LETC,LETT:                # Couldn't get good packet
  1260.       call spack (BIGN, n, 0, 0)   # NAK
  1261.       return(state)                # Keep Waiting
  1262.     case BIGE:                     # Error packet
  1263.       call errpkt (packet)         # print it
  1264.       return(LETA)                 # Abort
  1265.     default: return(LETW)          # Some other packet, "abort"
  1266.     }
  1267.   return
  1268.   end
  1269. #-t-  rfile                      2961  local   02/04/84  14:59:18
  1270. #-h-  rinit                      1148  local   12/29/83  14:18:07
  1271. #
  1272. #  R I N I T
  1273. #
  1274. #  Receive Initialization
  1275. #
  1276.  
  1277. character function rinit(dum)
  1278.  
  1279.   integer dum
  1280.  
  1281.   include cchar                    # Common block of chars
  1282.   include cint                     # Common block of integers
  1283.  
  1284.   integer len, num                 # Packet length, number
  1285.   character rpack                  # Rpack function
  1286.  
  1287.   if(numtry > MAXTRY) return (LETM) # If too many tries "abort"
  1288.   INCR(numtry)
  1289.   switch(rpack(len,num,packet)) {  # Get a packet
  1290.     case BIGS:                     # Send-Init
  1291.       call rpar(packet)            # Get the other side's init data
  1292.       call spar(packet)            # Fill up packet with my init info
  1293.       call spack(BIGY,n,INIT_SIZ,packet)  # ACK with my parameters
  1294.       oldtry = numtry              # Save old try count
  1295.       numtry = 0                   # Start a new counter
  1296.       n = mod(n+1,64)              # Bump packet number, mod 64
  1297.       return(BIGF)                 # Enter file send state
  1298.  
  1299.     case LETC,LETT:                # Didn't get packet
  1300.       call spack (BIGN, n, 0, 0)   # NAK
  1301.       return(state)                # Keep waiting
  1302.     case BIGE:                     # Error packet
  1303.       call errpkt (packet)         # print it
  1304.       return(LETA)                 # Abort
  1305.     default: return(LETW)          # Some other packet type, "abort"
  1306.     }
  1307.   return
  1308.   end
  1309. #-t-  rinit                      1148  local   12/29/83  14:18:07
  1310. #-h-  rpack                      3595  local   12/29/83  14:15:20
  1311. #
  1312. #  R P A C K
  1313. #
  1314. #  Read a packet
  1315. #  *** CONTAINS MACHINE DEPENDENT CODE ***
  1316. #  A check has been added where the checksum is read from the packet.
  1317. #  This check is for a CR in the spot where a checksum should be found.
  1318. #  This check is implemented to correct for the Univac stripping off
  1319. #  trailing blanks during I/O.  Sometimes the checksum character is
  1320. #  a blank (ascii 32) and is stripped off by the Univac when it is
  1321. #  received leaving a CR to be read in it's place.  This is corrected by
  1322. #  assuming that if a checksum of CR is read, the trailing blank of
  1323. #  the packet (checksum) has been stripped.  In this case the checksum
  1324. #  is set to 32 (blank).
  1325. #
  1326. #  GET_CH is a macro that reads a character and checks for an EOF which
  1327. #  is fatal, or TIMO (timeout), which causes a restart of the packet.
  1328. #  It assumes that if timeouts are allowed, a timeout causes getch to return
  1329. #  the constant TIMO.
  1330. #
  1331. # next line is HP3000 DEPENDENT segmentation information
  1332.  
  1333. character function rpack(len,num,data)
  1334.  
  1335. integer len,num                    # Packet length, number
  1336. character data(ARB)                # Packet data
  1337.  
  1338.   include cchar                    # Common block of type character
  1339.   include cint                     # Common block of type integer
  1340.  
  1341.   integer i, done                  # Data character number, Loop exit
  1342.   character checks, t, type        # Checksum, current char, pkt type
  1343.   character getch                  # Character reading function
  1344.   integer chksum, mask             # checksum, mask functions
  1345.  
  1346. #ifdef(TIMO)              # if timeouts allowed
  1347. define(GET_CH, 
  1348.    t=getch(t,lfdin);
  1349.    if (debug >= 3)
  1350.       call putch (t, ERROUT)
  1351.    if (t == EOF) goto 100           # abort on EOF
  1352.    else if (t == TIMO) goto 200     # timeout return
  1353.    )
  1354. #elsedef                  # no timeouts case
  1355. #define(GET_CH, 
  1356. #   t=getch(t,lfdin);
  1357. #   if (debug >= 3)
  1358. #      call putch (t, ERROUT)
  1359. #   if (t == EOF) goto 100          # abort on EOF
  1360. #   )
  1361. #enddef
  1362.  
  1363. #ifdef(TIMO)
  1364.   call setioc (lfdin, IO_TIMO, timint)   # set timeout  # HP3000 DEPENDENT
  1365. #enddef
  1366.  
  1367.   if (debug >= 3)
  1368.     call eprintf ("      rpack (raw):.")
  1369.  
  1370.   repeat {
  1371.     GET_CH                         # get a character (quit on EOF)
  1372.     if (t == SOH)                  # wait for start of packet
  1373.       break
  1374.     }
  1375.  
  1376.   done = NO                        # Got SOH, init loop
  1377.   while (done != YES)  {           # Loop to get a packet
  1378.     GET_CH                         # Get character
  1379.     if (binfil == NO)              # If in ascii mode
  1380.       t = mask(t)                  # Strip parity
  1381.     if (t == SOH) next             # Resynchronize if SOH
  1382.  
  1383.     checks = t                     # Start the checksum
  1384.     len = unchar(t)-3              # Character count
  1385.  
  1386.     GET_CH                         # Get character
  1387.     if (binfil == NO)              # If in ascii mode
  1388.       t = mask(t)                  # Strip parity
  1389.     if (t == SOH) next             # Resynchronize if SOH
  1390.     checks = checks + t            # Accumulate checksum
  1391.     num = unchar(t)                # Packet number
  1392.  
  1393.     GET_CH                         # Get character
  1394.     if (binfil == NO)              # If in ascii mode
  1395.       t = mask(t)                  # Strip parity
  1396.     if (t == SOH) next             # Resynchronize if SOH
  1397.     checks = checks + t            # Accumulate checksum
  1398.     type = t                       # Packet type
  1399.  
  1400.     for(i=1; i<=len; i=i+1)  {     # The data itself if any
  1401.       GET_CH                       # Get character
  1402.       if (binfil == NO)            # If in ascii mode
  1403.         t = mask(t)                # Strip parity
  1404.       if (t == SOH) next           # Resynch if SOH
  1405.       checks = checks + t          # Accumulate checksum
  1406.       data(i) = t                  # Put it in the data buffer
  1407.       }
  1408.     data(len+1) = EOS              # Mark end of data
  1409.  
  1410.     GET_CH                         # Get last character (checksum)
  1411. # U1100 DEPENDENT
  1412. #    if (t == 10)                   # If checksum character is CR then...
  1413. #      t = 32                       #  Univac has stripped a trailing blank.
  1414. # END MACHINE DEPENDENT
  1415.     if (binfil == NO)              # If in ascii mode
  1416.       t = mask(t)                  # Strip parity
  1417.     if (t == SOH) next             # Resynchronize if SOH
  1418.     done = YES                     # Got checksum, done
  1419.     }
  1420.  
  1421.   if (debug >= 3)
  1422.     call putch (NEWLINE, ERROUT)
  1423.  
  1424. #ifdef(TIMO)
  1425.   call setioc (lfdin, IO_TIMO, 0) # turn off timeout         # HP3000 DEPENDENT
  1426. #enddef
  1427.  
  1428.   if (debug >= 2)                   # debug print (before checksum check)
  1429.       call eprintf ("    rpack: %c %2d '%s'@n.", type, num, data)
  1430.  
  1431.   checks = chksum(checks)           # Perform checksum
  1432.   if (checks != unchar(t))          # Check the checks, fail if bad
  1433.       {
  1434.       if (debug >= 1)
  1435.            call eprintf ("    rpack: checksum fail: %c/%c@n.",t,tochar(checks))
  1436.       else if (remote == NO)
  1437.            {
  1438.            call putch (PERCENT, ERROUT)
  1439.            call flush (ERROUT)
  1440.            }
  1441.       lastpk = LETC
  1442.       return(LETC)                  # indicate checksum failure
  1443.       }
  1444.  
  1445.   lastpk = type
  1446.   return(type)                      # All OK, return packet type
  1447.  
  1448.   100 continue                      # EOF on line
  1449.   if (debug >= 1)
  1450.       call eprintf ("@n%s: EOF read from line@n.", msghdr)
  1451.   lastpk = LETA
  1452.   return (LETA)                     # abort
  1453.  
  1454.   200 continue                      # Timeout (TIMO returned from getch)
  1455.   if (debug >= 1)
  1456.       call eprintf (" timeout@n.")  # timeout message
  1457.   else if (remote == NO)
  1458.       {
  1459.       call putch (PERCENT, ERROUT)  # normal way to indicate a timeout
  1460.       call flush (ERROUT)           # get it out now
  1461.       }
  1462.   lastpk = LETT
  1463.   return(LETT)                      # indicates timeout
  1464.  
  1465.   end
  1466. #-t-  rpack                      3595  local   12/29/83  14:15:20
  1467. #-h-  rpar                       1136  local   12/29/83  14:15:22
  1468. #
  1469. #  R P A R
  1470. #
  1471. #  Get the other side's send-init parameters
  1472. #
  1473.  
  1474. subroutine rpar(data)
  1475.  
  1476. character data(ARB)
  1477.  
  1478.   character ctl                    # Ctl function
  1479.  
  1480.   include cchar                    # Common block of characters
  1481.   include cint                     # Common block of integers
  1482.  
  1483.   define(RPAR_END,if(data($1)==EOS) return)   # End of init parameters
  1484.  
  1485.   dobquo = NO                       # default: no eighth-bit quoting
  1486.   dorept = NO                       # default: no repeat prefixing
  1487.  
  1488.   RPAR_END(1)
  1489.   spsiz = min(MAXPACK,unchar(data(1)))    # Maximum send packet size
  1490.   RPAR_END(2)
  1491.   if (unchar(data(2)) <= 0)               # When I should time out on reads
  1492.       timint = MAXTIM
  1493.   else
  1494.       timint = min(MAXTIM,max(MINTIM,unchar(data(2))))  
  1495.   RPAR_END(3)
  1496.   pad = unchar(data(3))            # Number of pads to send
  1497.   RPAR_END(4)
  1498.   padchar = ctl(data(4))           # Padding character to send
  1499.   RPAR_END(5)
  1500.   eol = unchar(data(5))            # EOL character I must send
  1501.   RPAR_END(6)
  1502.   quotec = data(6)                 # Incoming data quote character
  1503.   RPAR_END(7)
  1504.   bquote = data(7)                 # Incoming binary quote character
  1505.   if ((MYBQUOTE >= 33 & MYBQUOTE <= 62)  |  (MYBQUOTE >= 96 & MYBQUOTE <= 126) |
  1506.                 MYBQUOTE == BIGY)   # If I have quoting compiled in
  1507.       if ((bquote >= 33  &  bquote <=62)  |  (bquote >=96  &  bquote <= 126))
  1508.            dobquo = YES             # Eighth-bit quoting agreed, use his char
  1509.       else if (bquote == BIGY)
  1510.            {
  1511.            dobquo = YES             # Eighth-bit quoting agreed
  1512.            bquote = MYBQUOTE        # Use my char
  1513.            if (MYBQUOTE == BIGY)
  1514.                 bquote = AMPER      # Both said 'Y': use '&'
  1515.            }
  1516.   RPAR_END(8)
  1517.   RPAR_END(9)
  1518.   reptc = data(9)                   # Incoming repeat prefix char
  1519.   if (((reptc >= 33  &  reptc <=62)  |  (reptc >=96  &  reptc <= 126)) &
  1520.            reptc == MYREPTC)
  1521.       dorept = YES                  # Our repeat prefixes agree, so use it
  1522.  
  1523.   return
  1524.   end
  1525. #-t-  rpar                       1136  local   12/29/83  14:15:22
  1526. #-h-  sbreak                     1236  local   12/29/83  14:21:14
  1527. #
  1528. #  S B R E A K
  1529. #
  1530. #  Send Break (EOT)
  1531. #
  1532.  
  1533. character function sbreak(dum)
  1534.  
  1535.   integer dum
  1536.  
  1537.   integer num, len                 # Packet number, length
  1538.  
  1539.   include cchar                    # Common block of characters
  1540.   include cint                     # Common block of integers
  1541.  
  1542.   character rpack                  # Rpack function
  1543.  
  1544.   if (numtry > MAXTRY) return(LETM) # If too many tries "abort"
  1545.   INCR(numtry)
  1546.  
  1547.   call spack(BIGB,n,0,packet)      # Send a B packet
  1548.   switch(rpack(len,num,recpkt))  { # What was the reply
  1549.     case BIGN:                     # NAK, fail
  1550.       num = num-1                  # ...unless for previous packet,
  1551.       if (num < 0)                 # in which case, stay in B state.
  1552.         num = 63
  1553.       if (n != num)
  1554.         return(state)
  1555.  
  1556.     case BIGY:                     # ACK
  1557.       if (n != num) return(state)  # If wrong ACK, fail
  1558.       numtry = 0                   # Reset try counter
  1559.       n = mod(n+1,64)              # and bump packet count
  1560.       return(BIGC)                 # Switch state to Complete
  1561.  
  1562.     case LETC,LETT: return(state)  # Receive failure, stay in state B
  1563.     case BIGE:                     # Error packet
  1564.       call errpkt (recpkt)         # print it
  1565.       return(LETA)                 # Abort
  1566.     default: return(LETW)          # Other, "abort"
  1567.     }
  1568.  
  1569.   return
  1570.   end
  1571. #-t-  sbreak                     1236  local   12/29/83  14:21:14
  1572. #-h-  sdata                      1558  local   12/29/83  14:23:18
  1573. #
  1574. #  S D A T A
  1575. #
  1576. #  Send File Data
  1577. #
  1578.  
  1579. character function sdata(dum)
  1580.  
  1581.   integer dum
  1582.  
  1583.   include cchar                    # Common block of characters
  1584.   include cint                     # Common block of integers
  1585.  
  1586.   integer num, len                 # Packet number ,length
  1587.  
  1588.   character rpack                  # Rpack function
  1589.   integer bufill                   # Bufill function
  1590.  
  1591.   if (numtry > MAXTRY) return(LETM)  # If too many tries, give up
  1592.   INCR(numtry)
  1593.   call spack(BIGD,n,size,packet)   # Send a D packet
  1594.  
  1595.   switch(rpack(len,num,recpkt))  {   # What was the reply
  1596.     case BIGN:                     # NAK, just stay in this state,
  1597.       num = num-1                  #  unless NAK for next packet,
  1598.       if (num < 0)                 #  which is just like an ACK
  1599.         num = 63                   #  for this packet.
  1600.       if (n != num)
  1601.         return(state)
  1602.  
  1603.     case BIGY:                     # ACK
  1604.       if (n != num) return(state)  # If wrong ACK, fail
  1605.       numtry = 0                   # Reset try counter
  1606.       n = mod(n+1,64)              # Bump packet count
  1607.       size = bufill(packet)        # Get data from file
  1608.       if (size == EOF)  {          # If EOF set state to that
  1609.         return(BIGZ)
  1610.         }
  1611.       return(BIGD)                 # Got data, stay in state D
  1612.  
  1613.     case LETC,LETT: return(state)  # Receive failure, stay in D
  1614.     case BIGE:                     # Error packet
  1615.       call errpkt (recpkt)         # print it
  1616.       return(LETA)                 # Abort
  1617.     default: return(LETW)          # Anything else "abort"
  1618.     }
  1619.  
  1620.   return
  1621.   end
  1622. #-t-  sdata                      1558  local   12/29/83  14:23:18
  1623. #-h-  sendsw                     1208  local   12/29/83  14:15:24
  1624. #
  1625. #  S E N D S W
  1626. #
  1627. #  Sendsw is the state table switcher for sending
  1628. #  files.  It loops until either it finishes, or
  1629. #  an error is encountered.  The routines called by
  1630. #  sendsw are responsible for changing the state.
  1631. #
  1632. #
  1633. # special compiler control HP3000 DEPENDENT:
  1634.  
  1635. integer function sendsw (sname, start)
  1636.  
  1637.   character sname(ARB)             # name of file to send (EOS => use args)
  1638.   integer start                     # state to start in - BIGS or BIGF
  1639.  
  1640.   include cchar                    # Common block of characters
  1641.   include cint                     # Common block of integers
  1642.  
  1643.   character sinit, sfile, seof, sdata, sbreak   # Functions
  1644.   character lstate, llstate
  1645.  
  1646.   state = start                    # Use indicated start state (usually BIGS)
  1647.   n = 0                            # Initialize message number
  1648.   numtry = 0                       # Say no tries yet
  1649.  
  1650.   repeat {                         # Do this as long as necessary
  1651.     if (debug >= 1)
  1652.       call eprintf ("  sendsw %c %d@n.", state, n)
  1653.  
  1654.     switch(state)  {
  1655.       case BIGD: state = sdata(DUM)# Data-Send state
  1656.       case BIGF: state = sfile(sname)# File-Send
  1657.       case BIGZ: state = seof(DUM) # End of File
  1658.            if (state == BIGF  &  sname(1) ^= EOS) # If ready for next file
  1659.                 state = BIGB  # Do Break
  1660.       case BIGS: state = sinit(DUM)# Send Init
  1661.       case BIGB: state = sbreak(DUM) # Break-Send
  1662.       case BIGC: return(YES)       # Complete
  1663.       default:                     # Anything else is an error
  1664.            call failmsg(llstate)    # Put out an error message
  1665.            if (fd ^= ERR) {         # If file left open
  1666.              call close (fd)        # Close it
  1667.              fd = ERR               # Remember it's closed
  1668.              }
  1669.            return (NO)              # Error return
  1670.       }
  1671.     llstate = lstate
  1672.     lstate = state                  # Remember last state
  1673.     }
  1674.   return
  1675.   end
  1676. #-t-  sendsw                     1208  local   12/29/83  14:15:24
  1677. #-h-  seof                       2111  local   01/16/84  08:50:37
  1678. #
  1679. #  S E O F
  1680. #
  1681. #  Send End Of File.
  1682. #
  1683.  
  1684. character function seof(dum)
  1685.  
  1686.   integer dum
  1687.  
  1688.   include cchar                    # Common block of characters
  1689.   include cint                     # Common block of integers
  1690.  
  1691.   integer num, len                 # Packet number, length
  1692.   character rpack                  # Rpack function
  1693.  
  1694.   if (numtry > MAXTRY) return(LETM) # If too many tries, give up
  1695.   INCR(numtry)
  1696.   call spack(BIGZ,n,0,packet)      # Send  a Z packet
  1697.  
  1698.   switch(rpack(len,num,recpkt))  { # What was the reply ?
  1699.     case BIGN:                     # NAK, fail
  1700.       num = num-1
  1701.       if (num < 0)                 # ...unless for previous packet,
  1702.         num = 63                   # in which case, stay in this state
  1703.       if (n != num)
  1704.         return(state)
  1705.  
  1706.     case BIGY:                     # ACK
  1707.       if (n != num) return(state)  # If wrong ACK, hold out
  1708.       numtry = 0                   # Reset try counter
  1709.       n = mod(n+1,64)              # Bump packet count
  1710.       call close(fd)               # Close the input file
  1711.       fd = ERR                     # and flag that we did
  1712.       return (BIGF)                   # Go to file header state
  1713.  
  1714.     case LETC,LETT: return(state)  # Receive failure, stay in state Z
  1715.     case BIGE:                     # Error packet
  1716.       call errpkt (recpkt)         # print it
  1717.       return(LETA)                 # Abort
  1718.     default: return(LETW)          # Something else, "abort"
  1719.     }
  1720.  
  1721.   return
  1722.   end
  1723. #-t-  seof                       2111  local   01/16/84  08:50:37
  1724. #-h-  server                     3027  local   02/04/84  14:59:22
  1725. #
  1726. #  S E R V E R
  1727. #
  1728. #  This is the state controller for the server mode of operation.
  1729. #
  1730.  
  1731. integer function server (dum)
  1732.  
  1733.   integer dum
  1734.  
  1735.   include cchar                    # Common block of characters
  1736.   include cint                     # Common block of integers
  1737.  
  1738.   integer len, num, junk           # Packet length, number, dummy
  1739.   integer timeos                   # number of timeouts seen
  1740.   character typ                   # packet typ
  1741.  
  1742.   integer recsw, sendsw             # Functions called by server
  1743.   character getcmd, rpack
  1744.  
  1745.   string badcmd ": not a valid Kermit server command"
  1746.   string badstcmd ": command not implemented by ST Kermit server"
  1747.  
  1748.  
  1749.   n = 0                            # Initialize message number
  1750.   numtry = 0                       # Say no tries yet
  1751.   timeos = 0                       # No timeouts seen yet
  1752.  
  1753.   repeat  {                          # Do until told to quit
  1754.     typ = rpack(len,num,packet)      # Get a packet
  1755.     if (debug >= 1)
  1756.       {
  1757.       if (typ == NO  &  debug >= 3)
  1758.            call putch(NEWLINE, ERROUT)
  1759.       call eprintf ("server %c @n.", typ)
  1760.       }
  1761.     switch(typ) {
  1762.       case BIGS,BIGI:              # The other side wants to initialize
  1763.         call rpar(packet)          # Get other side's initial parameters
  1764.         call spar(packet)          # Get my initial parameters
  1765.         call spack(BIGY,n,INIT_SIZ,packet)  # Send ACK with my init parameters
  1766.         oldtry = numtry            # Reset try counters
  1767.         numtry = 0                 # ....
  1768.         if (typ == BIGS)           # If this was a send-init packet
  1769.           {
  1770.           n = mod(n+1,64)          # Increment packet count
  1771.           junk = recsw(DUM)        # Go to receive state to receive file
  1772.           }
  1773.         n = 0                      # Reset packet count
  1774.  
  1775.       case BIGR:                   # The other side wants to receive
  1776.         call strcpy(packet,filnam) # To let packet array be reused
  1777.         junk = sendsw(filnam,BIGS) # Send the requested file
  1778.         n = 0
  1779.  
  1780.       case BIGG:                  # Other side is sending a command
  1781.         switch(getcmd(len,packet)) {   # What is the command ?
  1782.           case BIGF:              # Finish, shut down Kermit
  1783.             call spack(BIGY,num,0,0)  # Acknowledge receipt of command
  1784.             call quit                # Leave kermit
  1785.           case BIGL:              # Logout: shut down Kermit and logout.
  1786.             call spack(BIGY,num,0,0)  # Acknowledge receipt of command
  1787.             call quit             # Execute session logout (not implemented)
  1788.           default:                # Anything else
  1789.             packet(2) = EOS
  1790.             call errmsg (packet, badstcmd)   # Send error message
  1791.           }
  1792.  
  1793.       case BIGX, BIGC, BIGK:        # Valid, but unimplemented
  1794.         packet(1) = typ
  1795.         packet(2) = EOS
  1796.         call errmsg (packet, badstcmd)   # Send err message
  1797.  
  1798.       case BIGN:                    # NAK: ignore it (some confusion)
  1799.  
  1800.       case LETA:                    # EOF on line: abort
  1801.         return(LETA)
  1802.  
  1803.       case LETC:                    # checksum err:
  1804.         call spack(BIGN,n,0,0)      # NAK it
  1805.         n = 0
  1806.  
  1807.       case LETT:                    # timeout
  1808.         timeos = mod(timeos+1,5)    # increment timeout counter
  1809.         if (timeos == 0)            # If it rolls over (every fifth)
  1810.            call spack(BIGN,n,0,0)   # send out a NAK, just to keep line active
  1811.         n = 0
  1812.  
  1813.       case BIGE:                    # Error packet
  1814.         call errpkt (recpkt)        # print it
  1815.  
  1816.       default:                      # Anything else, reset packet count, retry
  1817.         packet(1) = typ
  1818.         packet(2) = EOS
  1819.         call errmsg (packet, badcmd)    # Send an error message
  1820.         n = 0                       # Reset counter
  1821.       }
  1822.     if (fd ^= ERR)                  # If a file was left open (xfer aborted)
  1823.       {
  1824.       call close (fd)               # Close it
  1825.       fd = ERR                      # Remember closure
  1826.       }
  1827.     }
  1828.   return
  1829.   end
  1830. #-t-  server                     3027  local   02/04/84  14:59:22
  1831. #-h-  sfile                      1533  local   12/29/83  14:27:41
  1832. #
  1833. #  S F I L E
  1834. #
  1835. #  Send File Header.
  1836. #
  1837.  
  1838. character function sfile(sname)
  1839.  
  1840.   character sname(ARB)
  1841.  
  1842.   include cchar                    # Common block of characters
  1843.   include cint                     # Common block of integers
  1844.  
  1845.   integer num, len                 # Packet number, length
  1846.   character g
  1847.   character rpack                 # Rpack function
  1848.   integer bufill, length           # functions
  1849.   character gnxtfl                # function
  1850.  
  1851.   string s_send "file being saved as "
  1852.  
  1853.   g = gnxtfl (sname)                # Open the file to be sent
  1854.   if (g ^= BIGF)                    # BIGF => OK
  1855.     return(g)                       # abort or break states
  1856.  
  1857.   if (numtry > MAXTRY) return(LETM) # If too many tries give up
  1858.   INCR(numtry)
  1859.  
  1860.   len = length(filnam)              # get length of filename
  1861.   call spack(BIGF,n,len,filnam)    # Send an F packet
  1862.   switch(rpack(len,num,recpkt))  { # What was the reply ?
  1863.     case BIGN:                     # NAK, just stay in this state
  1864.       num = num-1                  #  unless NAK for next packet,
  1865.       if (num < 0)                 #  which is just like ACK for
  1866.         num = 63                   #  this packet, fall thru to....
  1867.       if (n != num)
  1868.         return(state)
  1869.  
  1870.     case BIGY:                     # ACK
  1871.       if(n != num) return(state)   # If wrong ACK, stay in F state
  1872.       if (len > 0)                 # If the remote filename was returned
  1873.         call prmsg (s_send, recpkt)#    print it out
  1874.       numtry = 0                   # Reset try counter
  1875.       n = mod(n+1,64)              # Bump packet count
  1876.       size = bufill(packet)        # Get first data from file
  1877.       return(BIGD)                 # Switch to state D
  1878.  
  1879.     case LETC,LETT: return(state)  # Receive failure, stay in F state
  1880.     case BIGE:                     # Error packet
  1881.       call errpkt (recpkt)         # print it
  1882.       return(LETA)                 # Abort
  1883.     default: return(LETW)          # Something else, just "abort"
  1884.     }
  1885.  
  1886.   return
  1887.   end
  1888. #-t-  sfile                      1533  local   12/29/83  14:27:41
  1889. #-h-  sinit                      2560  local   01/04/84  17:49:40
  1890. #
  1891. #  S I N I T
  1892. #
  1893. #  Send Initiate: Send my parameters, get other side's back.
  1894. #  The 10 second wait before sending the first packet gives
  1895. #  the user time to get back to his local Kermit and set it
  1896. #  to receive.
  1897. #
  1898.  
  1899. character function sinit(dum)
  1900.  
  1901.   integer dum
  1902.  
  1903.   include cchar                    # Common block of characters
  1904.   include cint                     # Common block of integers
  1905.  
  1906.   integer num, len                 # Packet number, Length
  1907.   character rpack                  # Rpack function
  1908.  
  1909.   if (numtry > MAXTRY) return (LETM) # If too many tries, give up
  1910.   numtry=numtry+1                  # Increment count of tries
  1911.   call spar(packet)                # Fill packet with init info
  1912.   if (sflg == 1  &  remote == YES) # If in send only (not server) mode
  1913.     call sleepm (10000)            # Wait 10 seconds
  1914.   call spack(BIGS,n,INIT_SIZ,packet)      # Send an S packet
  1915.   switch(rpack(len,num,recpkt)) {  # What was reply ?
  1916.     case BIGN: return(state)       # NAK
  1917.  
  1918.     case BIGY:                     # ACK
  1919.       if (n != num) return(state)  # If wrong ACK, stay in S state
  1920.       call rpar(recpkt)            # Get other sides init info
  1921.       if (eol == 0) eol = CR       # Check and set defaults
  1922.       if (quotec == 0) quotec = SHARP # Control-prefix quote
  1923.       numtry = 0                   # Reset try counter
  1924.       n=mod(n+1,64)                # Bump packet count
  1925.  
  1926.       return (BIGF)                # Go to file header state
  1927.  
  1928.     case LETC,LETT: return(state)  # Receive failure, stay in S state
  1929.     case BIGE:                     # Error packet
  1930.       call errpkt (recpkt)         # print it
  1931.       return(LETA)                 # Abort
  1932.     default: return(LETW)          # Anything else just abort
  1933.     }
  1934.  
  1935.   return
  1936.   end
  1937. #-t-  sinit                      2560  local   01/04/84  17:49:40
  1938. #-h-  spack                      1861  local   12/29/83  14:30:20
  1939. #
  1940. #  S P A C K
  1941. #
  1942. #  Send  a packet
  1943. #
  1944. # HP3000 DEPENDENT to allow calling routine with '0' for 'data' array:
  1945.  
  1946. subroutine spack(type,num,len,data)
  1947.  
  1948. character type, data(ARB)          # Packet type, data
  1949. integer num, len                   # Packet number, length of data
  1950.  
  1951.   include cchar                    # Common block of characters
  1952.   include cint                     # Common block of integers
  1953.  
  1954.   character checks, buffer(100)    # Checksum, packet buffer
  1955.   integer i,bufptr                 # Loop counter, buffer pointer
  1956.   integer chksum                   # Chksum function
  1957.   character getch                 # function
  1958.   character c                     # char holder
  1959.  
  1960.  
  1961.   data(len+1) = EOS                 # just to be sure
  1962.   if (debug >= 2)
  1963.       call eprintf ("    spack: %c %2d '%s'@n.", type, num, data)
  1964.  
  1965.   bufptr = 1                       # Initialize buffer pointer
  1966.  
  1967.   for (i=1; i<=pad; i=i+1)
  1968.     call putch(padchar,lfdout)     # Issue any padding
  1969.  
  1970.   buffer(bufptr) = SOH             # Packet marker, ASCII 1 (SOH)
  1971.   INCR(bufptr)                     # Increment buffer pointer
  1972.   checks = tochar(len+3)           # Initialize the checksum
  1973.   buffer(bufptr) = tochar(len+3)   # Send the character count
  1974.   INCR(bufptr)                     # Increment buffer pointer
  1975.   checks = checks + tochar(num)    # Initialize checksum
  1976.   buffer(bufptr) = tochar(num)     # Packet number
  1977.   INCR(bufptr)
  1978.   checks = checks + type           # Accumulate checksum
  1979.   buffer(bufptr) = type            # Packet type
  1980.   INCR(bufptr)
  1981.  
  1982.   for (i=1; i<=len; i=i+1)  {      # Loop for all data characters
  1983.     buffer(bufptr) = data(i)       # Get a character
  1984.     INCR(bufptr)                   # Increment buffer pointer
  1985.     checks = checks + data(i)      # Accumulate checksum
  1986.     }
  1987.  
  1988.   checks = chksum(checks)          # Perform checksum
  1989.  
  1990.   buffer(bufptr) = tochar(checks)  # Put it in the packet
  1991.   buffer(bufptr + 1) = EOS         # Properly terminate packet
  1992.  
  1993.   if (xonwait == YES)
  1994.       {    # Now wait for DC1 (XON) 'prompt' character
  1995.     #ifdef TIMO
  1996.       call setioc (lfdin, IO_TIMO, timint)   # set timeout  # HP3000 DEPENDENT
  1997.     #enddef
  1998.       repeat 
  1999.            {
  2000.            c = getch(c, lfdin)
  2001.            if (c == DC1  |  c == SOH  |  c == EOF) break
  2002.          #ifdef(TIMO)
  2003.            else if (c == TIMO) break
  2004.          #enddef
  2005.            }
  2006.     #ifdef(TIMO)
  2007.       call setioc (lfdin, IO_TIMO, 0) # turn off timeout    # HP3000 DEPENDENT
  2008.     #enddef
  2009.       }
  2010.  
  2011.   call putbuf(buffer,bufptr,lfdout) # Send the packet
  2012.  
  2013.  
  2014.   return
  2015.   end
  2016. #-t-  spack                      1861  local   12/29/83  14:30:20
  2017. #-h-  spar                        780  local   12/29/83  14:15:30
  2018. #
  2019. #  S P A R
  2020. #
  2021. #  Fill the data array with my send-init parameters
  2022. #  Different machines may require different parameter definitions.
  2023. #
  2024.  
  2025. subroutine spar(data)
  2026.  
  2027. character data(ARB)                # Array of parameters
  2028.  
  2029.   include cint
  2030.  
  2031.   character ctl                   # ctl function
  2032.  
  2033.   data(1) = tochar(MAXPACK)        # Biggest packet I can receive
  2034.   data(2) = tochar(MYTIME)         # When I want to be timed out
  2035.   data(3) = tochar(mypad)          # How much padding I need
  2036.   data(4) = ctl(MYPCHAR)           # Padding character I want
  2037.   data(5) = tochar(MYEOL)          # End of Line character I want
  2038.   data(6) = MYQUOTE                # Control-Quote character I send
  2039.   data(7) = MYBQUOTE               # Binary-Quote character I send
  2040.   data(8) = MYCHECK                # My preferred type of checksum
  2041.   data(9) = MYREPTC                # Repeat-Quote character I send
  2042.   data(10) = tochar(MYCAPS)        # My capabilities mask
  2043.   data(INIT_SIZ+1) = EOS           # in case this gets printed
  2044.  
  2045.   return
  2046.   end
  2047. #-t-  spar                        780  local   12/29/83  14:15:30
  2048. #-h-  usage                       198  local   12/29/83  14:15:30
  2049. #  U S A G E
  2050. #
  2051. subroutine usage
  2052.   call remark("usage:  kermit [ixd].")
  2053.   call remark("        kermit [rixd].")
  2054.   call remark("        kermit [sixd] [file [-as remote_name]]@.@.@..")
  2055.   call unsetraw
  2056.   call endst(ERR)
  2057.   stop
  2058.   end
  2059. #-t-  usage                       198  local   12/29/83  14:15:30
  2060. #-h-  chgnam                     34  ascii   02/19/84  01:48:00
  2061. #
  2062. #
  2063. # MACHINE DEPENDENT ROUTINES APPEAR AFTER THIS POINT
  2064. #
  2065. #
  2066. #
  2067.  
  2068.  
  2069.  
  2070. #
  2071. #  C H G N A M
  2072. #
  2073. #  Change name of file to compatible name
  2074. #  *** MACHINE DEPENDENT SUBROUTINE ***
  2075. #  Many systems use the file naming format 'filename.ext'.
  2076. #  Many systems have a '.' at the end of a file name that does not
  2077. #  have an extension.  This creates problems for the Univac since
  2078. #  usually a Univac element is what is thought of as a file.  The
  2079. #  Univac file is more like a directory on other systems.  The file
  2080. #  name followed by a '.' would be interpreted as a Univac file by
  2081. #  by the 1100.  In most cases what we want to work with is an element.
  2082. #  This routine chops off a trailing '.' .
  2083. #  Other systems may need to make allowances for this
  2084. #  same sort of problem.
  2085. #
  2086.  
  2087. subroutine chgnam(name)
  2088.  
  2089. character name(ARB)                # Name holder
  2090.  
  2091.   integer index
  2092.   integer loc1, loc2               # Indices
  2093.  
  2094.   loc1 = index(name,NULL)          # Check for UNIX NULL on end of name
  2095.   if (loc1 != 0)     # U1100 & name(loc1+1) == EOS)
  2096.     name(loc1) = EOS               # If found strip it off
  2097.   loc1 = index(name,PERIOD)        # Check for '.' in name
  2098.   #loc2 = iindex(name,STAR)          # Check for '*' in name # U1100
  2099.   if (loc1 != 0 & name(loc1+1) == EOS) # & loc2 == 0) # If '.' is last char
  2100.     name(loc1) = EOS               # Strip '.' off
  2101.   return
  2102.   end
  2103. #-t-  chgnam                     34  ascii   02/19/84  01:48:00
  2104. #-h-  chksum                     29  ascii   02/19/84  01:48:01
  2105. #
  2106. #  C H K S U M
  2107. #
  2108. #  Compute checksum.
  2109. #  The Kermit Protocol Manual details how the checksum is formed.
  2110. #
  2111.  
  2112. integer function chksum(sum)
  2113.  
  2114. integer sum                        # Checksum holder
  2115.  
  2116.   integer c                         # Holder of checksum copy
  2117.   #integer mod                      # Mod function       # MACHINE DEPENDENT
  2118.  
  2119.   c = mod(sum,64) + mod(sum/64,4)   # Add the low 6 bits to the next two bits
  2120.   return (mod(c,64))                # Return six bits of that result
  2121.   end
  2122. #-t-  chksum                     29  ascii   02/19/84  01:48:01
  2123. #-h-  hdlprd                     20  ascii   02/19/84  01:48:01
  2124. #
  2125. #  H D L P R D
  2126. #
  2127. #  Handle period in incoming file name.
  2128. #  *** U1100 DEPENDENT SUBROUTINE ***
  2129. #
  2130.  
  2131. subroutine hdlprd(name)
  2132.  
  2133. character name(ARB)
  2134.  
  2135.   integer index
  2136.   integer loc1
  2137.  
  2138.   loc1 = index(name,PERIOD)        # Locate '.' in name
  2139.   if (loc1 != 0)                   # If there, replace it with '/'
  2140.     name(loc1) = SLASH
  2141.   return
  2142.   end
  2143. #-t-  hdlprd                     20  ascii   02/19/84  01:48:01
  2144. #-h-  innam                      33  ascii   02/19/84  01:48:02
  2145. #
  2146. #  I N N A M
  2147. #
  2148. #  Change file name to a local compatible name.
  2149. #
  2150. #  *** MACHINE DEPENDENT SUBROUTINE ***
  2151. #  Makes sure that an incoming file has a name that the local system
  2152. #  recognizes as valid.  
  2153. #
  2154.  
  2155. subroutine innam(name)
  2156.  
  2157. character name(ARB)                # File name holder
  2158.  
  2159.   call chgnam(name)                # Strip trailing NULL  '.'
  2160.   #call hdlprd(name)                # Replace interior '.' with '/' # U1100
  2161.   call validate(name)              # Delete invalid chars
  2162.   call truncate(name)              # Truncate if neeeded
  2163.   return
  2164.   end
  2165. #-t-  innam                      33  ascii   02/19/84  01:48:02
  2166. #-h-  mask                       15  ascii   02/19/84  01:48:02
  2167. #
  2168. #  M A S K
  2169. #
  2170. #  Mask off parity.  Returns 7 low-order bits.
  2171. #
  2172.  
  2173. integer function mask(n)
  2174.  
  2175. integer n
  2176.  
  2177. #integer mod           # Needed on some machines        # MACHINE DEPENDENT
  2178.  
  2179.   return(mod(n,128))  # Mask off all but 7 low bits
  2180.   end
  2181. #-t-  mask                       15  ascii   02/19/84  01:48:02
  2182. #-h-  outnam                     72  ascii   02/19/84  01:48:03
  2183. #
  2184. #  O U T N A M
  2185. #
  2186. #  This routine converts a local file name to a name recognizable to
  2187. #  most other systems.
  2188. #  *** MACHINE DEPENDENT SUBROUTINE ***
  2189. #
  2190. #  The format of the name is :
  2191. #
  2192. #      name.ext
  2193. #
  2194. #  Where "name" can be 8 characters long and "ext" can be 3 characters long
  2195. #  or not even present. (Never present on the HP 3000.)
  2196. #
  2197.  
  2198. subroutine outnam(name)
  2199.  
  2200. character name(ARB)
  2201.  
  2202.   integer i, loc1, loc2            # Counter, array indices
  2203.   integer length                   # Length function
  2204.   integer index
  2205.  
  2206.   # HP3000 DEPENDENT
  2207.   loc1 = index(name,COLON)         # strip off :modifier specifier
  2208.   if (loc1 > 0)
  2209.       name(loc1) = EOS
  2210.   loc1 = index(name,UNDERLINE)     # strip off _machine specifier
  2211.   if (loc1 > 0)
  2212.       name(loc1) = EOS
  2213.   loc1 = index(name,PERIOD)        # strip off .group specifier
  2214.   if (loc1 > 0)
  2215.       name(loc1) = EOS
  2216.   call upper (name)                 # uppercase name
  2217.  
  2218.   # U1100 DEPENDENT
  2219.   #i = 1                            # Initialize counter
  2220.   #loc1 = iindex(name,PERIOD)        # Locate PERIOD
  2221.   #if (name(loc1+1) == EOS)  {      # Name is "qualifier*fileid."
  2222.   #  loc1 = iindex(name,STAR)        # Locate asterisk
  2223.   #  while (name(loc1+1) != EOS) {  # Use "fileid" only
  2224.   #    name(i) = name(loc1+1)       # Remove "qualifier*"
  2225.   #    INCR(i)                      # Increment indices
  2226.   #    INCR(loc1)
  2227.   #    }
  2228.   #  if (i > 9)                     # If name too long ..
  2229.   #    name(9) = EOS                # Truncate it.
  2230.   #  else
  2231.   #    name(i-1) = EOS
  2232.   #  }
  2233.   #else  {                          # Name is an element specification
  2234.   #  if (loc1 != 0)  {              # If name contains '.'
  2235.   #    while (name(loc1+1) != EOS)  {  # Use element name only
  2236.   #      name(i) = name(loc1+1)     # Remove "qualifier*fileid"
  2237.   #      INCR(i)                    # Increment indices
  2238.   #      INCR(loc1)
  2239.   #      }
  2240.   #    name(i) = EOS                # Terminate string
  2241.   #    }
  2242.   #  loc1 = iindex(name,SLASH)       # Locate '/'
  2243.   #  if (loc1 > 9)  {
  2244.   #    name(9) = PERIOD             # Replace '/' with '.'
  2245.   #    i = 10                       # And truncate name to 8 characters
  2246.   #    while (name(loc1+1) != EOS)  {  # Do till end of string
  2247.   #      name(i) = name(loc1+1)     #  Shift characters to left
  2248.   #      INCR(i)                    # Increment indices
  2249.   #      INCR(loc1)
  2250.   #      }
  2251.   #    name(i) = EOS                # Terminate new string
  2252.   #    if (i-9 > 3)                 # If extension is too long ....
  2253.   #      name(13) = EOS             # Truncate it.
  2254.   #    }
  2255.   #  else if (loc1 != 0)  {         # If SLASH is found and length is OK, ..
  2256.   #    name(loc1) = PERIOD          # Replace '/' with '.'
  2257.   #    loc2 = iindex(name,EOS)       # Locate End Of String
  2258.   #    if (loc2-loc1 > 4)           # If extension is too long ...
  2259.   #      name(loc1+4) = EOS         # Truncate it.
  2260.   #    }
  2261.   #  else
  2262.   #    if (length(name) > 8)        # If name too long ...
  2263.   #      name(9) = EOS              # Truncate it.
  2264.   #}
  2265.   # END MACHINE DEPENDENT
  2266.   return
  2267.   end
  2268. #-t-  outnam                     72  ascii   02/19/84  01:48:03
  2269. #-h-  putbuf                     44  ascii   02/19/84  01:48:04
  2270. #
  2271. #  P U T B U F
  2272. #
  2273. #  Put a buffer full of data to given file
  2274. #  *** CONTAINS MACHINE DEPENDENT CODE ***
  2275. #  Because the U of U Univac 1100 strips trailing blanks during I/O
  2276. #  the padding used in this routine ensures that packets with trailing
  2277. #  blanks go out correctly formed.  The computation used makes sure
  2278. #  that the final Univac word is filled.
  2279. #
  2280.  
  2281. subroutine putbuf(line, x, file)
  2282.  
  2283.  
  2284. character line(ARB)                # Array that holds packet
  2285. filedes file                       # File descriptor
  2286. integer x                          # Length of packet
  2287.  
  2288.   include cint                     # Common block of integers
  2289.   include cchar                    # Common block of characters
  2290.  
  2291.   integer i                        # Counter
  2292.  
  2293.   if (debug >= 3)
  2294.     call eprintf ("      spack (raw):%s@n.", line)
  2295.  
  2296.   call putlin(line,file)           # Send packet
  2297.  
  2298. # U1100 DEPENDENT
  2299. #  for (i = (4 - mod(x,4)); i>0; i=i-1)  # Compute padding to fill last word
  2300. #    call putch(PADU,file)          # Put out padding
  2301. # END MACHINE DEPENDENT
  2302.  
  2303.   call putch (eol, file)           # put out requested end-of-line
  2304.  
  2305. # MOST MACHINES
  2306. #  call putch(NEWLINE,file)         # Use NEWLINE to flush output buffer
  2307. # HP3000 DEPENDENT
  2308.   call putch (DC3, file)          # make use of XON-XOFF control if it exists
  2309.                                   #   should be ignored by other end otherwise
  2310.   call flush (file)               # flush output buffer without NEWLINE
  2311.                                   #   to avoid nullifying above XOFF
  2312.  
  2313.   call sleepm (swait)         # debug
  2314.       # This is purely for testing robustness - it simulates a slow machine.
  2315.       # If we can take a few seconds here, we are safe.
  2316. # END MACHINE DEPENDENT
  2317.  
  2318.   return
  2319.   end
  2320. #-t-  putbuf                     44  ascii   02/19/84  01:48:04
  2321. #-h-  quit
  2322. #
  2323. #  Q U I T
  2324. #
  2325. #  Kill Kermit and logout the session.
  2326. #  Session logout doesn't work on the 3000.
  2327. #
  2328.  
  2329. subroutine quit
  2330.  
  2331.   #call atat('term',4)              # @@term command for Univac
  2332.  
  2333.   call unsetraw
  2334.   call endst(OK)                   # Clean up files.
  2335.   return
  2336.   end
  2337. #-t-  quit
  2338. #-h-  quiti
  2339. #
  2340. #  Q U I T I
  2341. #
  2342. #  Kill Kermit.
  2343. #
  2344.  
  2345. subroutine quiti
  2346.  
  2347.   include cint
  2348.   include cchar
  2349.  
  2350.   if (debug > 0)
  2351.       call eprintf ("%s: Control-Y Interrupt@n.", msghdr)
  2352.  
  2353.   call unsetraw
  2354.   call endst(INTERRUPT)            # Clean up files.    # HP3000 DEPENDENT
  2355.   return
  2356.   end
  2357. #-t-  quiti
  2358. #-h-  setraw                     41  ascii   02/19/84  01:48:04
  2359. #
  2360. #  S E T R A W
  2361. #
  2362. #  This routine sets tty line to raw mode.
  2363. #  *** MACHINE DEPENDENT SUBROUTINE ***
  2364. #  By raw mode we mean that the echo to the terminal is turned off and
  2365. #  the computer is configured to accept control characters as input.
  2366. #  Each system will probably have it's own way of accomplishing this.
  2367. #
  2368.  
  2369. subroutine setraw
  2370.  
  2371.       include cint
  2372.  
  2373.       integer isatty
  2374.  
  2375.       # HP3000 DEPENDENT
  2376.       on controly call quiti    # set interrupt trap to cleanup procedure
  2377.  
  2378.       call setioc (lfdin, IO_ECHO, NO)  # turn off echo
  2379.       if (isatty(lfdin) == YES)
  2380.            {
  2381.            call ffcontrol (lfdin, 39, ttype)  # remember term type
  2382.            call ffcontrol (lfdin, 38, TERMTYPE) # set terminal type to 
  2383.                                     # turn off HP's enk-ack handshaking
  2384.            call ffcontrol (lfdout, 36, 0)     # turn off parity generation
  2385.            }
  2386.       #call setioc (lfdin, IO_MODE, RARE)
  2387.  
  2388.       # U1100 DEPENDENT
  2389.       #call atat('cque',4)     # set type-ahead mode
  2390.       #call putch(MAGIC,lfdout)
  2391.       #call putch(MAGIC,lfdout)
  2392.       #call putch(MAGIC,lfdout)
  2393.       #call putch(MAGIC,lfdout)
  2394.       #call putch(NULL,lfdout)
  2395.       #call putch(NULL,lfdout)
  2396.       #call putch(NULL,lfdout)
  2397.       #call putch(SOH,lfdout)
  2398.       #call putch(NULL,lfdout)
  2399.       #call putch(NULL,lfdout)
  2400.       #call putch(NULL,lfdout)
  2401.       #call putch(NULL,lfdout)
  2402.       #call putch(NEWLINE,lfdout)
  2403.       # END OF MACHINE DEPENDENT CODE
  2404.  
  2405.     return
  2406.     end
  2407. #-t-  setraw                     41  ascii   02/19/84  01:48:04
  2408. #-h-  sleepm
  2409. #
  2410. # S L E E P M
  2411. #
  2412. # Sleep (suspend execution) for a given number of milliseconds.
  2413. #
  2414. subroutine sleepm (t)
  2415.  
  2416. integer t                           # time to sleep in milliseconds
  2417.  
  2418.   # MOST MACHINES
  2419.   # call sleep (t/1000)
  2420.  
  2421.   # HP3000 DEPENDENT
  2422.   system intrinsic pause
  2423.    
  2424.   call pause (t/1000.0)
  2425.  
  2426.   # U1100 DEPENDENT
  2427.   # call twait (t)
  2428.   # END MACHINE DEPENDENT
  2429.  
  2430.   return
  2431.   end
  2432. #-t-  sleepm
  2433. #-h-  trunca                     40  ascii   02/19/84  01:48:05
  2434. #
  2435. #  T R U N C A T E
  2436. #
  2437. #  Truncate incoming file name.
  2438. #  *** MACHINE DEPENDENT SUBROUTINE ***
  2439. #  On the HP3000, expects a name consisting only of letters, digits,
  2440. #  and periods.
  2441. #
  2442.  
  2443. subroutine truncate(name)
  2444.  
  2445. character name(ARB)
  2446.  
  2447.   integer index, length
  2448.   integer loc1,loc2, i, l2, l3
  2449.  
  2450.   # HP3000 DEPENDENT
  2451.   loc1 = index (name, PERIOD)
  2452.   if (loc1 == 0)
  2453.       name(9) = EOS                 # Simple truncation
  2454.   else
  2455.       {
  2456.       loc2 = loc1 + index(name(loc1+1), PERIOD)   # look for next period
  2457.       if (loc2 > 0)
  2458.            name(loc2) = EOS         # truncate anything after a second period
  2459.       call scopy (name, loc1+1, name, loc1)   # remove period
  2460.       name (max(9,loc1+2)) = EOS    # truncate extension (leave at least 2 chrs)
  2461.       l2 = length(name)
  2462.       if (l2 > 8)
  2463.            call scopy(name,loc1,name,loc1-(l2-8))  # truncate name part to fit
  2464.       }
  2465.       
  2466.   # U1100 DEPENDENT
  2467.   #loc1 = iindex(name,SLASH)         # Locate '/' in name
  2468.   #if (loc1 > 13)  {                # If location > 13
  2469.   #  name(13) = SLASH               # Truncate name
  2470.   #  i = 14
  2471.   #  while (name(loc1+1) != EOS) {  # Shift extension left
  2472.   #    name(i) = name(loc1+1)
  2473.   #    INCR(i)
  2474.   #    INCR(loc1)
  2475.   #    }
  2476.   #  name(i) = EOS
  2477.   #  if (i > 26)                    # If extension > 12
  2478.   #    name(26) = EOS               # Truncate it
  2479.   #  }
  2480.   #else if (loc1 == 0)  {           # If no '/' in name
  2481.   #  loc1 = length(name)            # Check length of name
  2482.   #  if (loc1 > 12)                 # If name > 12 characters
  2483.   #    name(13) = EOS               # Truncate it
  2484.   #  }
  2485.   #else if (loc1 < 13)  {           # If name has '/' but location < 13
  2486.   #  loc2 = length(name)            # Check length of extension
  2487.   #  if (loc2 - loc1 > 12)          # If extension > 12 characters
  2488.   #    name(loc1+13) = EOS          # Truncate it
  2489.   #  }
  2490.   # END MACHINE DEPENDENT CODE
  2491.   return
  2492.   end
  2493. #-t-  trunca                     40  ascii   02/19/84  01:48:05
  2494. #-h-  unsetr                     34  ascii   02/19/84  01:48:05
  2495. #
  2496. #  U N S E T R A W
  2497. #
  2498. #  This routine undoes the effects of setraw.
  2499. #  *** MACHINE DEPENDENT SUBROUTINE ***
  2500. #
  2501.  
  2502. subroutine unsetraw
  2503.  
  2504.       include cint
  2505.  
  2506.       integer isatty
  2507.  
  2508.       # HP3000 DEPENDENT
  2509.       call setioc (lfdin, IO_ECHO, YES)
  2510.       if (isatty(lfdin) == YES)
  2511.            call ffcontrol (lfdin, 38, ttype)  # restore terminal type
  2512.       #call setioc (lfdin, IO_MODE, COOKED)
  2513.  
  2514.       # U1100 DEPENDENT
  2515.       #call putch(MAGIC,lfdout)
  2516.       #call putch(MAGIC,lfdout)
  2517.       #call putch(MAGIC,lfdout)
  2518.       #call putch(MAGIC,lfdout)
  2519.       #call putch(NULL,lfdout)
  2520.       #call putch(NULL,lfdout)
  2521.       #call putch(NULL,lfdout)
  2522.       #call putch(CTRL_B,lfdout)
  2523.       #call putch(NULL,lfdout)
  2524.       #call putch(NULL,lfdout)
  2525.       #call putch(NULL,lfdout)
  2526.       #call putch(NULL,lfdout)
  2527.       #call putch(NEWLINE,lfdout)
  2528.       # END OF MACHINE DEPENDENT CODE
  2529.  
  2530.     return
  2531.     end
  2532. #-t-  unsetr                     34  ascii   02/19/84  01:48:05
  2533. #-h-  valida                     27  ascii   02/19/84  01:48:05
  2534. #
  2535. #  V A L I D A T E
  2536. #
  2537. #  Make sure name has valid characters.
  2538. #  *** MACHINE DEPENDENT SUBROUTINE ***
  2539. #  On the HP3000, invalid chars are deleted rather than replaced.
  2540. #
  2541.  
  2542. subroutine validate(name)
  2543.  
  2544. character name(ARB)
  2545.  
  2546.   integer index, length
  2547.   integer loc1, i, j
  2548.  
  2549.   # HP3000 DEPENDENT
  2550.   call lower(name)                       # Lowercase name
  2551.   if (IS_DIGIT(name(1)))                 # If it has a leading digit
  2552.       {                                  #  insert a leading 'a'
  2553.       for (i=length(name)+1; i >= 1;  i=i-1)
  2554.            name(i+1) = name(i)
  2555.       name(1) = LETA
  2556.       }
  2557.   j = 1
  2558.   for (i=1;  name(i) ^= EOS;  i=i+1)
  2559.       if (IS_LETTER(name(i)) | IS_DIGIT(name(i)) | name(i) == PERIOD)
  2560.            {
  2561.            name(j) = name(i)             # keep letters and digits only
  2562.            j = j + 1
  2563.            }
  2564.   name(j) = EOS                          # terminate the string
  2565.  
  2566.   # U1100 DEPENDENT
  2567.   #string valid "ABCDEFGHIJKLMNOPQRSTUVWXYZ$/1234567890"
  2568.  
  2569.   #i = 1
  2570.   #call upper(name)                 # Uppercase name
  2571.   #while (name(i) != EOS)  {        # Scan name
  2572.   #  loc1 = iindex(valid,name(i))    # Checking for valid characters
  2573.   #  if (loc1 == 0)                 # If invalid character is found
  2574.   #    name(i) = MINUS              # Replace it with '-'
  2575.   #  INCR(i)
  2576.   #  }
  2577.   # END MACHINE DEPENDENT
  2578.  
  2579.   return
  2580.   end
  2581. #-t-  valida                     27  ascii   02/19/84  01:48:05
  2582. #-h-  testbu
  2583. # test_buf --- test kermit's bufill and bufemp functions - debug use only
  2584. # Use of this routine (via call from main) makes kermit
  2585. # copy from STDIN to STDOUT using bufill and bufemp.
  2586. # The intermediate packets are displayed on ERROUT.
  2587.  
  2588.       subroutine test_buf
  2589.  
  2590.       character line(MAXLIN)
  2591.  
  2592.       include cint
  2593.       include cchar
  2594.  
  2595.       integer bufill, length
  2596.  
  2597.       dorept = YES
  2598.       dobquo = YES
  2599.       fd = STDIN
  2600.  
  2601.       repeat
  2602.            {
  2603.            i = bufill(line)
  2604.            if (i == EOF)
  2605.                 break
  2606.            call eprintf ("packet (%d long):%s:@n.", i, line)
  2607.            if (length(line) ^= i)
  2608.                 {
  2609.                 call eprintf ("length = %d  :.", length(line))
  2610.                 for (j=1; j<=i; j=j+1)
  2611.                      call putch(line(j), ERROUT)
  2612.                 call putch (NEWLINE, ERROUT)
  2613.                 }
  2614.            call bufemp (line, STDOUT, i)
  2615.            }
  2616.       call flush(STDOUT)
  2617.  
  2618.       call endst(OK)                # exit program
  2619.       return                        # dummy
  2620.       end
  2621. #-t-  testbu
  2622. #-t-  kermit.r                   2486  ascii   05/30/84  23:45:50
  2623.