home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume42 / ecu / part13 < prev    next >
Encoding:
Internet Message Format  |  1994-05-23  |  64.4 KB

  1. From: wht@n4hgf.atl.ga.us (Warren Tucker)
  2. Newsgroups: comp.sources.misc
  3. Subject: v42i111:  ecu - ECU Asynchronous Communications v3.30, Part13/37
  4. Date: 23 May 1994 14:23:07 -0500
  5. Organization: Sterling Software
  6. Sender: kent@sparky.sterling.com
  7. Approved: kent@sparky.sterling.com
  8. Message-ID: <2rqvqr$dnh@sparky.sterling.com>
  9. X-Md4-Signature: 6868e46e2f0cfc48a3f804f382a33193
  10.  
  11. Submitted-by: wht@n4hgf.atl.ga.us (Warren Tucker)
  12. Posting-number: Volume 42, Issue 111
  13. Archive-name: ecu/part13
  14. Environment: SCO,SCOXENIX,MOTOROLA,HP-UX,LINUX,NetBSD,SUNOS,SYSVR4,SOLARIS2
  15. Supersedes: ecu: Volume 32, Issue 36-75
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then feed it
  19. # into a shell via "sh file" or similar.  To overwrite existing files,
  20. # type "sh file -c".
  21. # Contents:  ecu330/fasi/RELEASENOTES ecu330/sea/ecusea.c
  22. # Wrapped by kent@sparky on Mon May 23 13:40:52 1994
  23. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 13 (of 37)."'
  26. if test -f 'ecu330/fasi/RELEASENOTES' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'ecu330/fasi/RELEASENOTES'\"
  28. else
  29.   echo shar: Extracting \"'ecu330/fasi/RELEASENOTES'\" \(23494 characters\)
  30.   sed "s/^X//" >'ecu330/fasi/RELEASENOTES' <<'END_OF_FILE'
  31. XThis is the original RELEASENOTES from FAS 2.08 for reference only.
  32. XRead README.FASI. DO NOT CONTACT UWE DOERING REGARDING THIS HACKED VERSION
  33. X                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  34. X
  35. X     release 1.1a Sat Nov 11, 1989
  36. X
  37. X     This is an unofficial release as I'm not the original author
  38. X     of this async driver.
  39. X
  40. X     Uwe Doering             INET : gemini@geminix.in-berlin.de
  41. X     Billstedter Pfad 17 b   UUCP : ...!unido!fub!geminix.in-berlin.de!gemini
  42. X     1000 Berlin 20
  43. X     Germany
  44. X
  45. X     New Features:
  46. X
  47. X          Added a third minor tty device number for every physical
  48. X          port. See description preceding the asyopen function in
  49. X          asy.c. Changed the behavior of ttyxx, too.
  50. X
  51. X          Added output hardware handshake support for DSR. Now you
  52. X          can do handshake with CTS, DSR or both. Input hardware
  53. X          handshake is on if you use at least one of the output
  54. X          handshake signals.
  55. X
  56. X          More flexible support of additional interrupt registers
  57. X          on mux boards. This is fully configurable now.
  58. X
  59. X          Added support for the CREAD flag. If not set, receiver
  60. X          interrupts are still serviced, but the received characters
  61. X          are simply thrown away. This is not as elegant as disabeling
  62. X          the interrupts themselves, but with the already existing
  63. X          driver it was the easiest way, and the most new-bugs-preventing,
  64. X          too.
  65. X
  66. X          Added a lot of comments to the source so that the curious
  67. X          user can understand why and how things are done.
  68. X
  69. X
  70. X     Bug Fixes:
  71. X
  72. X          The hang-up-on-last-close flag (HUPCL) was ignored. DTR
  73. X          was asserted regardless of this flag.
  74. X
  75. X          Made the detection of CTS and DCD more bullet-proof.
  76. X          Especially because between a close and the next open of
  77. X          a line, where interrupts are ignored, the software copys of
  78. X          CTS and DCD must be set up propperly in the asyopen function
  79. X          or the tty line would be blocked under certain circum-
  80. X          stances. For similar reasons, there is also a setup in the
  81. X          asyparam function.
  82. X
  83. X          Rewrote the input character processing function to work
  84. X          according to the TERMIO(7) man page.
  85. X
  86. X          Changed the behavior of BREAK generation to let the
  87. X          transmitter drain before TX is set to low.
  88. X
  89. X          Changed line hangup procedure so that the closing
  90. X          process returns immediately and doesn't sleep during
  91. X          the hangup delay/time. Instead, if an other process tries
  92. X          to open the line while hangup is still in progress, this
  93. X          process will sleep until hangup is competed.
  94. X
  95. X          With DOS Merge, on MicroPort V/386 3.0e the linker was
  96. X          missing the function `init8250'. Reengineered this from
  97. X          a disassembler listing of MicroPort's original driver and
  98. X          modified it to work with the NS16550A 16-byte FIFO. This
  99. X          funktion was added simply to be able to link the kernel.
  100. X          DOS Merge's virtual COM ports are still unusable with this
  101. X          release, though. To include this function, add a `-DMERGE'
  102. X          to the CFLAGS line in your makefile.
  103. X
  104. X          Made a lot of other corrections and enhancements in both
  105. X          speed and functionallity. As a result of all my effords
  106. X          I think this driver is slightly faster, more versatile
  107. X          and much more stable than the original release.
  108. X
  109. X     ------------------------------------------------------------
  110. X          
  111. X     release 1.1b Sat Nov 25, 1989
  112. X
  113. X     New Features:
  114. X
  115. X          Changed the minor device number scheme again.
  116. X          There are now two main groups: The unblocked open
  117. X          and the blocked open. Every group has four sub-modes
  118. X          and an additional hardware handshake flag. All this
  119. X          is coded in the higher four bits of the minor device
  120. X          number. Because of this, the maximum of 32 ports was
  121. X          reduced to 16 ports so that the port number fits into
  122. X          the remaining lower four bits of the minor device number.
  123. X          32 dumb ports in a single machine would have been overkill
  124. X          anyway. For more details refer to the description in the
  125. X          README file.
  126. X
  127. X     ------------------------------------------------------------
  128. X          
  129. X     release 2.00 Mon Nov 27, 1989
  130. X
  131. X     As this release differs so much from the original version I got,
  132. X     I now declare this as independant from the original author
  133. X     Jim Murray. This allows me to introduce new release levels
  134. X     without wondering whether they will collide with Jim's releases.
  135. X     Of course many credits to Jim for writing this software in the
  136. X     first place. Without his driver as a base I never would have
  137. X     been able to do such kernel driver development.
  138. X
  139. X     Bug Fixes:
  140. X
  141. X          If there were glitches on the hardware handshake lines
  142. X          and the DCD line a getty on this port would sometimes
  143. X          hang and become an immortal process. I think this was
  144. X          because the output buffer wasn't flushed properly
  145. X          on carrier loss. I hope I fixed this now. We'll see.
  146. X
  147. X     ------------------------------------------------------------
  148. X          
  149. X     release 2.01 Tue Nov 28, 1989
  150. X
  151. X     Did some cleanup in the source code.
  152. X
  153. X     I splitted the driver into two parts: The driver itself and
  154. X     the file `space.c'.
  155. X     `space.c' contains all data structures necessary to configure
  156. X     the driver and is compiled at kernel link time. Therefore if you
  157. X     change your serial card configuration you simply change `space.c'
  158. X     directly in the link kit directory and relink the kernel. No
  159. X     driver recompilation or installation is necessary for this.
  160. X     But note that whenever you use `make install' your setup in
  161. X     the link kit directory is overwritten by the original `space.c'
  162. X     file. Therefore you should copy your new `space.c' back to
  163. X     the source directory when you are finished with the configuration.
  164. X
  165. X     Renamed the package to `FAS Final Async Solution'. The following
  166. X     files have been renamed:
  167. X          asy.c          -> fas.c
  168. X          asy.h          -> fas.h
  169. X          asy_conf-xxxxx -> space-xxxxx
  170. X
  171. X     ISC 386/ix is supported now. There are separate makefiles
  172. X     for uPort and ISC to cope with the differences in link kit
  173. X     installation.
  174. X
  175. X     Bug Fixes:
  176. X
  177. X          `getty' still hung sometimes on a line with hardware
  178. X          handshake. Tried to fix it this time.
  179. X
  180. X     ------------------------------------------------------------
  181. X          
  182. X     release 2.02 Thu Nov 30, 1989
  183. X
  184. X     Abandoned the distinction between space-xxxxx files with
  185. X     and without hardware flow control because this is selected
  186. X     by the minor device number now.
  187. X
  188. X     Bug Fixes:
  189. X
  190. X          Set the high and low water marks for hardware input flow
  191. X          control to higher values than software flow control. This
  192. X          gives precedence to software flow control if both methods
  193. X          are used. These marks are self-adjusting and don't need to
  194. X          be changed if some flavor of UNIX has a different buffer
  195. X          size than the standard 256 characters. Before this change
  196. X          concurrent use of both flow controls could cause trouble
  197. X          with some high-speed modems. This is fixed now.
  198. X
  199. X          A flush read or write buffer request now also clears the
  200. X          receiver or transmitter FIFO, respectively. An ioctl
  201. X          call with a TCSETA* command clears the FIFOs, too.
  202. X
  203. X     ------------------------------------------------------------
  204. X          
  205. X     release 2.03 Fri Dec 01, 1989
  206. X
  207. X     Wrote an installation guide. The driver should be quite
  208. X     easy to install now.
  209. X
  210. X     Added tty node configuration files for ISC.
  211. X
  212. X     Hardware input flow control is bound now to the level of the
  213. X     receiver ring buffer instead of the UNIX input buffer. This
  214. X     has the advantage that buffer size and trigger levels are
  215. X     defined in the driver and therefore can be varied as needed.
  216. X
  217. X     New Features:
  218. X
  219. X          Added a boot time status message that shows the init
  220. X          state of each port. This tells you immediately what
  221. X          ports are found and initted by the driver. Useful to
  222. X          determine hardware configuration problems. Look at
  223. X          the description in the README file. Thanks to
  224. X          Kritt Gierlewsen (kritt@einoed.UUCP) for this proposal.
  225. X
  226. X     ------------------------------------------------------------
  227. X          
  228. X     release 2.04 Thu Dec 07, 1989
  229. X
  230. X     Did some cleanup in the source.
  231. X
  232. X     Removed the FIFO clear from the ioctl function. We don't want
  233. X     to do things there that aren't in the book.
  234. X
  235. X     An ioctl call that switches off the CLOCAL flag will create
  236. X     a SIGHUP signal if the carrier is actually missing at this
  237. X     time.
  238. X
  239. X     Every device is tested now quite thoroughly during initialization.
  240. X     If the test fails the corresponding device keeps unconfigured.
  241. X
  242. X     ------------------------------------------------------------
  243. X          
  244. X     release 2.05 Sat Jan 13, 1990
  245. X
  246. X     This is the first public release of the FAS driver.
  247. X
  248. X     Special thanks to the sysops of my test sites, Axel Fischer
  249. X     (fischer@utower.UUCP) and Kritt Gierlewsen (kritt@einoed.UUCP).
  250. X
  251. X     FAS is now an independant driver with its own driver name (`fas'),
  252. X     major device number, link kit directory and other things necessary
  253. X     for a driver. The original asy driver may or may not be linked
  254. X     with the kernel. You only need it if you want to access some
  255. X     serial devices via the virtual COM ports of the DOS emulator
  256. X     (DosMerge or VP/ix) because the FAS driver doesn't have this
  257. X     (really vendor dependant) feature.
  258. X
  259. X     The default prefix for tty device node names is `ttyF' now.
  260. X     This prevents mix-ups with the device names of the original
  261. X     asy driver.
  262. X
  263. X     Dropped the SYSV/AT support. I couldn't test the driver
  264. X     for several release generations on uPort SYSV/AT, and because
  265. X     there are not very much systems left with that flavor of UNIX
  266. X     it doesn't make sense to try to maintain compatibility with it.
  267. X     If someone really wants to use this driver on a 286 he has
  268. X     to port it himself.
  269. X
  270. X     Improved the transmitter FIFO fill procedure. Now it will try
  271. X     harder to fill the FIFO as much as possible to cut down on
  272. X     transmitter interrupts.
  273. X
  274. X     Software input flow control (XON/XOFF) is controlled by the driver now.
  275. X     It is bound to the level of the receiver ring buffer (as is hardware
  276. X     flow control). As usual, it can be switched on and off by the
  277. X     IXOFF flag in the termio(7) structure.
  278. X
  279. X     Changed and speeded up the ring buffer -> unix buffer processing.
  280. X
  281. X     For ISC, the getty lines for the inittab file are installed
  282. X     by the makefile now.
  283. X
  284. X     The conditional compilation of the function `init8250' (for
  285. X     DosMerge) is now controlled by a define in `fas.h'. The compiler
  286. X     switch `-DMERGE' is not used any more.
  287. X
  288. X     Improved the documentation.
  289. X
  290. X     The signals used for modem control and hardware flow control are
  291. X     fully configurable in the `space.c' file now. Look at `fas.h' for
  292. X     possible macros and combinations.
  293. X
  294. X     There are some new modes for hardware flow control, for instance
  295. X     HO_CTS_ON_DSR. This means that CTS is only looked at if DSR is on.
  296. X     If DSR is off output is possible regardless of CTS. The underlying
  297. X     assumption here is that we can expect proper handshake handling
  298. X     only from devices that are in the ready state (indicated by DSR).
  299. X     As a spin-off the problem with the hanging getty on lines with
  300. X     turned-off terminals (mentioned in earlier releases) should be
  301. X     gone if you use this new mode.
  302. X
  303. X     If the XCLUDE-Flag is availabe (SYSV 3.2 because of Xenix
  304. X     compatibility) exclusive open of a device is possible.
  305. X
  306. X     The default size of the input ring buffer is now 5000 bytes.
  307. X     This makes streaming input more likely even on loaded systems.
  308. X
  309. X     Bug Fixes:
  310. X
  311. X          The task state busy flag wasn't reset in some rare cases.
  312. X          This could cause processes to become immortal while waiting
  313. X          for the busy flag.
  314. X
  315. X          Under some special conditions an ioctl call with a TCSETA?
  316. X          command could corrupt the last character in the transmitter
  317. X          shift register. This is fixed now.
  318. X
  319. X          More fixing of the busy flag handling was necessary.
  320. X          Co-ordinating several delayed tasks controlling this flag
  321. X          is kind of tricky.
  322. X
  323. X          After a TCSETA* ioctl command we disable the transmitter
  324. X          for 2 sec (measured from the last transmitted character)
  325. X          if the character format and/or speed has changed. This
  326. X          gives the receiving side some time to do the same changes.
  327. X          This is kind of experimental. There may be applications that
  328. X          suffer from this delay. You may change the #define ADAPT_TIME
  329. X          in `fas.h' to a smaller value.
  330. X
  331. X     ------------------------------------------------------------
  332. X          
  333. X     release 2.06 Fri Mar 16, 1990
  334. X
  335. X     This should have been patch #3 for release 2.05, but there are
  336. X     so many changes now that I decided to make it a new release.
  337. X     Therefor some of the changes are described in the 2.05 release
  338. X     notes above but were never released to the public.
  339. X
  340. X     New Features:
  341. X
  342. X          There is a transmitter ring buffer now to make the output
  343. X          less system load dependent. This really speeds things up
  344. X          because the transmitter FIFO gets filled with more characters
  345. X          at once. The buffer size depends on the actual baud rate to
  346. X          prevent long output buffer drains at low speeds.
  347. X
  348. X          There are also bigger input buffers to make FAS more competitive
  349. X          against "intelligent" cards.
  350. X
  351. X          Lots of speed improvements and many small changes.
  352. X
  353. X     Bug Fixes:
  354. X
  355. X          Fixed input/output buffer flush on carrier loss while close
  356. X          is waiting for the output to drain.
  357. X
  358. X     ------------------------------------------------------------
  359. X          
  360. X     release 2.07 Tue Sep 18, 1990
  361. X
  362. X     This is a major redesign of the previous release. I put most of the
  363. X     time consuming tasks in one function that is invoked asynchronously
  364. X     by timeout calls. Inside this function most of the code runs at
  365. X     a lower system priority level (spl5) than the interrupts. That
  366. X     means that during character processing tty interrupts are allowed.
  367. X     This is the main key to operation at 38400 bps on multiple ports
  368. X     at the same time which is possible now with this release.
  369. X
  370. X     New Features:
  371. X
  372. X          FAS supports the VP/ix DOS emulator!
  373. X          Now you can throw out the vendor's original driver even
  374. X          if you like to have a serial mouse or modem access in DOS.
  375. X          Read the paragraph about VP/ix in the README file.
  376. X
  377. X          The Intel i82510 port chip is supported. It has separate
  378. X          4-character FIFOs for input and output. Although the
  379. X          NS16550A is much better this chip is your second choice
  380. X          if you can't get your hands on the National chips.
  381. X          Thanks to Christian Seyb (cs@gold.UUCP) for sending me
  382. X          patches and the necessary documentation for the Intel
  383. X          chips.
  384. X
  385. X          There is an init sequence in `space.c'. You can put any
  386. X          number of address-data pairs in a null terminated array
  387. X          to program your serial card or other hardware before
  388. X          FAS makes the first access to the ports. AST 4-port cards,
  389. X          for instance, have an additional port that needs to be
  390. X          written to with a certain bit pattern to allow shared
  391. X          interrupts. If you need to read a port to achieve the
  392. X          setting or resetting of flags as a side effect, this
  393. X          is possible, too.
  394. X
  395. X          ESIX is officially supported now.
  396. X
  397. X          SCO UNIX is officially supported, too. FAS needs to be
  398. X          compiled with the command line flag `-DSCO'. The makefile
  399. X          for SCO takes care of that. Thanks to Walter Mecky
  400. X          (walter@mecky.systemware.de) and Frank Simon
  401. X          (terra@sol.north.de) for helping me in making the necessary
  402. X          changes for SCO UNIX.
  403. X
  404. X          SCO Xenix 386 is also officially supported. FAS needs to be
  405. X          compiled with the command line flag `-DXENIX'. The makefile
  406. X          for SCO Xenix takes care of that. Thanks to Andreas
  407. X          Steinmetzler (andreas@oil.UUCP) for doing the port.
  408. X
  409. X          If you have the RTSFLOW and CTSFLOW termio(7) flags,
  410. X          hardware handshake can be controlled by them.
  411. X          Note that enabling handware flow control via the
  412. X          minor device number overrides these flags. If you
  413. X          like to use them you need to create tty device nodes
  414. X          with minor device numbers in which the bit for hardware
  415. X          handshake is set to 0. Look at the description in the
  416. X          README file for more details.
  417. X          Note also that if you choose to use RTSFLOW and CTSFLOW
  418. X          all your programs that do initial access to tty devices
  419. X          (getty, uucico, cu, SLIP dialup program etc.) need to know
  420. X          about these flags or hardware handshake will not be used.
  421. X
  422. X          The `O_EXCL' flag for the open(2) call is honored now.
  423. X          This allowes exclusive access to an FAS device without
  424. X          suffering from race conditions which could occure with
  425. X          the termio(7) XCLUDE flag method.
  426. X
  427. X          The `fas_test_device' function returns a digit now that
  428. X          indicates at which phase the test exited due to an error.
  429. X          This error digit is displayed in the boot message. Thanks
  430. X          to Brian Beattie (beattie@visenix.UUCP) for sending me
  431. X          the necessary patches.
  432. X
  433. X     Bug Fixes:
  434. X
  435. X          Automatic input FIFO flush after unblocking the getty
  436. X          open by the carrier or the unblock signal. This makes sure
  437. X          that there is no chance that there are characters in the
  438. X          FIFO that were received before the open got unblocked.
  439. X
  440. X          The sdevice entry for the AST 4-port card had a wrong
  441. X          I/O address range (`s_fas-mux4'). This didn't affect FAS
  442. X          but is checked by the kernel config program.
  443. X
  444. X          The gcc (GNU cc) support was removed because gcc's object
  445. X          file wants to link in some "helpful" functions that aren't
  446. X          contained in the kernel. But anyway, FAS is tuned so carefully
  447. X          and depends on the optimization behaviour of the AT&T
  448. X          standard C compiler that gcc won't have any advantages.
  449. X
  450. X          I changed the method with which the `fas_test_device' function
  451. X          waits for certain events. The `delay' function was used
  452. X          for that purpose but it turned out that with some flavors
  453. X          of UNIX it is prohibited to use this function during the
  454. X          xxinit phase of the boot process. Now a simple timeout loop
  455. X          is used instead.
  456. X
  457. X          Removed the ADAPT_TIME mechanismn introduced in release 2.05.
  458. X
  459. X          The open() call now returns an `EBUSY' error number if the
  460. X          device is already open and can't be opened in the desired
  461. X          mode at this time.
  462. X
  463. X          The handling of the RING signal needed fixing. Unlike the other
  464. X          three modem status lines RING generates an interrupt only at
  465. X          the trailing edge.
  466. X
  467. X          No SIGHUP signal is sent any more if an ioctl call clears
  468. X          the CLOCAL termio(7) flag while there is no carrier present.
  469. X          SIGHUP is only sent if the actual DCD modem line drops.
  470. X
  471. X          The files *-mux4 were renamed to *-ast4 because this type of
  472. X          card was originally developed by AST (AST 4-port card).
  473. X
  474. X     ------------------------------------------------------------
  475. X          
  476. X     release 2.08 Sun Jan 13, 1991
  477. X
  478. X     New Features:
  479. X
  480. X          Bell Tech/Intel UNIX 3.2 is supported.
  481. X
  482. X          SCO Xenix 286 is also supported now. Thanks to Nickolay Saukh
  483. X          (nms@saukh.rd.jvd.su) for providing the patches.
  484. X
  485. X          The Bell Tech HUB-6 card can be used with FAS. Thanks to
  486. X          Keith Walker (kew@cims2.UUCP) for the patches.
  487. X
  488. X          For AT&T derived flavors of UNIX there is a line automatically
  489. X          added to the kernel description file that makes the adding
  490. X          and removing of FAS possible via the `kconfig' program. Thanks
  491. X          to John Adams (johna@grumpy.boston.ma.us) for this idea.
  492. X
  493. X          There is a mechanismn now that prevents excessive modem status
  494. X          interrupts caused by crosstalking between wires or by a loose
  495. X          cable.
  496. X
  497. X          You can disable the FIFOs in a UART by "oring" the macro
  498. X          `NO_FIFO' to the base port address of this device. This is
  499. X          useful for mouse devices where you need immediate response
  500. X          to the mouse movement.
  501. X
  502. X          The meaning of the bit mapped part of the minor device
  503. X          numbers has changed. Some rather useless functions were
  504. X          removed in favor of more control over the hardware handshake
  505. X          modes. Even systems where the SCO RTSFLOW/CTSFLOW termio(7)
  506. X          flags are not available can now use half duplex hardware
  507. X          flow control (selected via the minor device number).
  508. X
  509. X          The assignment of RS232C lines to certain FAS functions
  510. X          is even more flexible now. This allows to connect two
  511. X          UNIX systems (with FAS) via a null modem cable, running
  512. X          a getty at both ends. For more details, read the paragraph
  513. X          about CABLING in the README file.
  514. X
  515. X          A special handling of the NS16550A input FIFO was introduced.
  516. X          This causes multiple receiver interrupts (on the same IRQ
  517. X          line) to be synchronized so that only one interrupt is
  518. X          necessary to process all receiving ports. This reduces the
  519. X          interrupt handling overhead and therefor results in lower
  520. X          CPU load for concurrent serial input at high speeds.
  521. X
  522. X          The `fas_event' function processes all scheduled events
  523. X          for all units with one single call. Previously, every unit
  524. X          launched its own timeout() call if there was work to
  525. X          do. This could lead to up to 16 timeouts at the same time,
  526. X          resulting in some timeout handling overhead. This overhead
  527. X          is minimized now.
  528. X
  529. X     Bug Fixes:
  530. X
  531. X          There were two bugs that could cause a port to lock up,
  532. X          resulting in an immortal process.
  533. X
  534. X          Almost any kernel sleep is killable now (at least with one or
  535. X          two `kill -9'). Therefor, there should be no more immortal
  536. X          processes. Even killing a process that is hanging in a
  537. X          close-on-exit call is possible.
  538. X
  539. X          The meaning of the RTSFLOW/CTSFLOW termio(7) flags was converted
  540. X          to what SCO had in mind (half duplex flow control). This is for
  541. X          compatibility reasons. Full duplex RTS/CTS hardware flow control
  542. X          is still possible via the minor device number method. Thanks to
  543. X          Dmitry V. Volodin (dvv@hq.demos.su) for providing me with the
  544. X          necessary knowledge.
  545. X
  546. X          If a process is already sleeping in a getty open it will only
  547. X          unblock on DCD low->high. In particular, if in the meantime
  548. X          the device was open for dialout and DCD is still present if
  549. X          the getty open takes over again this won't unblock the getty
  550. X          open any more.
  551. X
  552. X          And there were, as usual, a number of other small bug fixes.
  553. END_OF_FILE
  554.   if test 23494 -ne `wc -c <'ecu330/fasi/RELEASENOTES'`; then
  555.     echo shar: \"'ecu330/fasi/RELEASENOTES'\" unpacked with wrong size!
  556.   fi
  557.   # end of 'ecu330/fasi/RELEASENOTES'
  558. fi
  559. if test -f 'ecu330/sea/ecusea.c' -a "${1}" != "-c" ; then 
  560.   echo shar: Will not clobber existing file \"'ecu330/sea/ecusea.c'\"
  561. else
  562.   echo shar: Extracting \"'ecu330/sea/ecusea.c'\" \(37903 characters\)
  563.   sed "s/^X//" >'ecu330/sea/ecusea.c' <<'END_OF_FILE'
  564. Xchar *version = "@(#)ecusea 3.30";
  565. X
  566. X/* #define TABLE_CRC16 */
  567. X
  568. X/*+-------------------------------------------------------------------------
  569. X    ecusea.c - SEAlink - Sliding window file transfer protocol
  570. X
  571. X  Defined functions:
  572. X    Nap(msec)
  573. X    arg_token(parsestr,termchars)
  574. X    cancel_transaction(sig)
  575. X    crc_update(c,crc)
  576. X    fname_split(cmd,arg,arg_max_quan,narg_rtn)
  577. X    fname_too_long(fname)
  578. X    fname_truncated()
  579. X    getspeed(atty)
  580. X    lgetc_timeout(tenths)
  581. X    main(argc,argv,envp)
  582. X    rdchk(fd)
  583. X    receive_block(buf)
  584. X    receive_file()
  585. X    send_comm_block(blk,blknum)
  586. X    send_file(name)
  587. X    send_file_block(fp,blknum)
  588. X    set_sf_state(place,new_state)
  589. X    set_utime_1980(filename,secs_since_1980)
  590. X    sf_state_text(state)
  591. X    wait_for_rcvr_response()
  592. X    xmit_ack(blknum)
  593. X    xmit_cancel()
  594. X    xmit_nak(blknum)
  595. X
  596. Xecu adaptation by W. Tucker
  597. Xmodelled after MSDOS sealink.c, which carried the following proviso:
  598. X
  599. X              MS-DOS Version 1.20, created on 08/05/87
  600. X              at 17:51:40 (C) COPYRIGHT 1986,87 by
  601. X              System Enhancement Associates; ALL RIGHTS
  602. X              RESERVED By: Thom Henderson
  603. X
  604. X              You are granted a license to use this
  605. X              code in your programs, and to adapt it to
  606. X              your particular situation and needs,
  607. X              subject only to the following conditions:
  608. X              1) You must refer to it as the SEAlink
  609. X              protocol, and you must give credit to
  610. X              System Enhancement Associates.  2) If you
  611. X              modify it in such a way that your version
  612. X              cannot converse with the original code as
  613. X              supplied by us, then you should refer to
  614. X              it as "SEAlink derived", or as a
  615. X              "variation of SEAlink", or words to that
  616. X              effect.  In short, we're not asking for
  617. X              any money, but we'd like to get some
  618. X              credit for our work.
  619. X
  620. X--------------------------------------------------------------------------*/
  621. X/*+:EDITS:*/
  622. X/*:05-04-1994-04:40-wht@n4hgf-ECU release 3.30 */
  623. X/*:04-01-1994-20:56-wht@n4hgf-pedantic what-compatible version */
  624. X/*:04-01-1994-20:46-wht@n4hgf-integrate rdchk here, eliminating srdchk.c */
  625. X/*:12-23-1992-00:19-wht@n4hgf-fix partially bracketed array in getspeed */
  626. X/*:09-10-1992-14:00-wht@n4hgf-ECU release 3.20 */
  627. X/*:08-22-1992-15:39-wht@n4hgf-ECU release 3.20 BETA */
  628. X/*:08-16-1992-03:08-wht@n4hgf-head off another POSIX plot */
  629. X/*:08-10-1992-04:01-wht@n4hgf-use init_Nap */
  630. X/*:07-20-1992-13:30-wht@n4hgf-put hzmsec in AGAIN ?? */
  631. X/*:07-17-1992-18:28-wht@n4hgf-remove Nap() and use common ../nap.o */
  632. X/*:05-11-1992-16:43-wht@gyro-fix WORKING_SELECT nap once and for all */
  633. X/*:05-08-1992-02:42-wht@n4hgf-select-based Nap was buggy */
  634. X/*:09-01-1991-14:22-wht@n4hgf2-on sun, use termios */
  635. X/*:08-30-1991-20:09-wht@n4hgf2-sun Nap was not returning a value */
  636. X/*:08-30-1991-02:34-jdeitch@jadpc.cts.com-fix no hzmsec */
  637. X/*:07-25-1991-12:59-wht@n4hgf-ECU release 3.10 */
  638. X/*:03-18-1991-22:49-wht@n4hgf-ISC 2.2 has struct timeval in sys/time.h */
  639. X/*:08-14-1990-20:40-wht@n4hgf-ecu3.00-flush old edit history */
  640. X
  641. X#include <stdio.h>
  642. X#include <string.h>
  643. X#include <ctype.h>
  644. X#include <signal.h>
  645. X#include <setjmp.h>
  646. X#include <fcntl.h>
  647. X#include <errno.h>
  648. X#include <sys/param.h>
  649. X#include <memory.h>
  650. X#include "../ecu_types.h"
  651. X#include "../ecu_stat.h"
  652. X#include "../ecu_time.h"
  653. X#include "../ecutermio.h"
  654. X
  655. X#ifdef CFG_SelectNap
  656. X#ifdef CFG_HasFdSet
  657. X#define SelBitmask struct fd_set
  658. X#else
  659. X#define SelBitmask int
  660. X#endif /* CFG_HasFdSet */
  661. X#endif /* CFG_SelectNap */
  662. X
  663. X/*
  664. X * for rdchk() below
  665. X */
  666. X#if defined(CFG_FionrdRdchk)
  667. X#undef ECHO
  668. X#undef NL0
  669. X#undef NL1
  670. X#undef TAB0
  671. X#undef TAB1
  672. X#undef TAB2
  673. X#undef XTABS
  674. X#undef CR0
  675. X#undef CR1
  676. X#undef CR2
  677. X#undef CR3
  678. X#undef FF0
  679. X#undef FF1
  680. X#undef BS0
  681. X#undef BS1
  682. X#undef TOSTOP
  683. X#undef FLUSHO
  684. X#undef PENDIN
  685. X#undef NOFLSH
  686. X#include <sys/ioctl.h>
  687. X#if defined (sun) && defined (SVR4)
  688. X#include <sys/filio.h>
  689. X#endif
  690. X#endif /* CFG_FionrdRdchk */
  691. X
  692. X/* Various system constants */
  693. X#define WINDOW        6         /* maximum size of window */
  694. X#define TIMEOUT    0x0FFF
  695. X#define OFFSET_1980    (time_t)315547200    /* time offset for 1970 <-> 1980 */
  696. X
  697. X/*
  698. X * The section of code that is compiled when NAKEOT is defined is in the
  699. X * original MS-DOS version 1.16 routine.  Its purpose is to send a NAK when
  700. X * an EOT is received during receive_file(), apparently to confirm that this is
  701. X * indeed the end of file.  However, in certain (apparently non - standard)
  702. X * versions of the protocol, it is possible that the program will report an
  703. X * error when in fact there isn't one.  Comment this out at your discretion.
  704. X */
  705. X#define NAKEOT
  706. X
  707. X/* SEAlink block zero data structure */
  708. Xtypedef struct blk0
  709. X{
  710. X    long length;             /* length */
  711. X    time_t secs_since_1980;     /* creation/last mod in secs since 1/1/80 */
  712. X    char filename[17];         /* file name */
  713. X    char sender[15];         /* sending program */
  714. X    char send_no_acks;         /* true if rcvr need not ack */
  715. X    char filler[87];         /* fill to 128 bytes */
  716. X}
  717. XBLK0;
  718. X
  719. X/* protocol characters */
  720. X#define SOH    0x01
  721. X#define EOT    0x04
  722. X#define ACK    0x06
  723. X#define NAK    0x15
  724. X#define CAN    0x18
  725. X
  726. X/*  send_file state (sf_state) values */
  727. X#define SFS_GND        0         /* Ground state, ACK or NAK expected */
  728. X#define SFS_ACK        1         /* ACK received */
  729. X#define SFS_NAK        2         /* NAK received */
  730. X#define SFS_ACKW    3         /* ACK, block# received */
  731. X#define SFS_NAKW    4         /* NAK, block# received */
  732. X#define SFS_RGND    5         /* Returning to ground state */
  733. Xint sf_state;
  734. X
  735. Xint allow_slide = 1;         /* sliding windows allowed */
  736. Xint crc_in_use;                 /* check type, 1 = CRC, 0 = checksum */
  737. Xchar *dfile = "/tmp/ecuSEA.log";
  738. Xint error_count = 0;         /* total number of errors */
  739. Xint iofd = 0;                 /* file descriptor to use */
  740. Xint no_ack_mode = 1;         /* true of ACKs not required */
  741. Xint rf_done = 0;             /* receive file done */
  742. Xint sf_ackw_count;             /* count of sliding ACKs seen */
  743. Xint sf_ackblk;                 /* number of last block ACKed */
  744. Xint sf_blknum;                 /* number of next block to send */
  745. Xint sf_lastnum;                 /* number of last block sent */
  746. Xint sf_nakquan;                 /* number of sequential NAKs */
  747. Xint sf_slide;                 /* true if sliding window */
  748. Xint sigint = 0;                 /* dummy for nap.c */
  749. X
  750. Xint sending_flag = -1;         /* send == 1, receive == 0, bad usage == -1 */
  751. Xint log_packets = 0;
  752. Xlong rx_char_count = 0;
  753. Xlong tx_char_count = 0;
  754. Xint Filcnt = 0;
  755. Xint npaths = 0;
  756. Xchar curr_dir[256];
  757. Xchar s128[128];
  758. Xunsigned baud_rate;
  759. Xint exit_code;
  760. Xint sent_EOT = 0;
  761. X
  762. Xstruct termio tio;
  763. Xstruct termio tio0;
  764. X
  765. Xjmp_buf lgetc_timeout_jmpbuf;
  766. X
  767. X/* CRC16 routine; finish CRC calculation for compare */
  768. X
  769. X#ifdef TABLE_CRC16
  770. X
  771. X/* crctab calculated by Mark G. Mendel,Network Systems Corporation */
  772. Xunsigned short crctab[256] =
  773. X{
  774. X    0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
  775. X    0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
  776. X    0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
  777. X    0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
  778. X    0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
  779. X    0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
  780. X    0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
  781. X    0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
  782. X    0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
  783. X    0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
  784. X    0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
  785. X    0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
  786. X    0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
  787. X    0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
  788. X    0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
  789. X    0xFF9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
  790. X    0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
  791. X    0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
  792. X    0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
  793. X    0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
  794. X    0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
  795. X    0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
  796. X    0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
  797. X    0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
  798. X    0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
  799. X    0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
  800. X    0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
  801. X    0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
  802. X    0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
  803. X    0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
  804. X    0xef1f, 0xFF3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
  805. X    0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
  806. X};
  807. X
  808. X/*+-------------------------------------------------------------------------
  809. X  updcrc macro derived from article Copyright (C) 1986 Stephen Satchell.
  810. X  NOTE: First argument must be in range 0 to 255.
  811. X        Second argument is referenced twice.
  812. X  Programmers may incorporate any or all code into their programs, giving
  813. X  proper credit within the source.  Publication of the source routines is
  814. X  permitted so long as proper credit is given to Stephen Satchell,
  815. X  Satchell Evaluations and Chuck Forsberg, Omen Technology.
  816. X--------------------------------------------------------------------------*/
  817. X#define crc_update(ch,crc) ( crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ ch)
  818. X
  819. X#else /* calculated crc */
  820. X
  821. X/*+-------------------------------------------------------------------------
  822. X    crc_update(c,crc)
  823. X--------------------------------------------------------------------------*/
  824. Xunsigned short
  825. Xcrc_update(c, crc)
  826. Xregister c;
  827. Xregister unsigned crc;
  828. X{
  829. X    register count;
  830. X
  831. X    for (count = 8; --count >= 0;)
  832. X    {
  833. X        if (crc & 0x8000)
  834. X        {
  835. X            crc <<= 1;
  836. X            crc += (((c <<= 1) & 0400) != 0);
  837. X            crc ^= 0x1021;
  838. X        }
  839. X        else
  840. X        {
  841. X            crc <<= 1;
  842. X            crc += (((c <<= 1) & 0400) != 0);
  843. X        }
  844. X    }
  845. X    return (crc);
  846. X}                             /* end of crc_update */
  847. X#endif /* crc calc selection */
  848. X
  849. X/*+-------------------------------------------------------------------------
  850. X    rdchk(f)
  851. X--------------------------------------------------------------------------*/
  852. X#if defined(CFG_FionrdRdchk)
  853. Xint
  854. Xrdchk(fd)
  855. Xint fd;
  856. X{
  857. X    int waiting = 0;
  858. X
  859. X    ioctl(fd, FIONREAD, &waiting);
  860. X    return (!!waiting);
  861. X
  862. X}                             /* end of rdchk */
  863. X#endif /* CFG_FionrdRdchk */
  864. X
  865. X/*+-----------------------------------------------------------------------
  866. X    arg_token(parsestr,termchars)
  867. X
  868. XGet next token from string parsestr ((char *)0 on 2nd, 3rd, etc.
  869. Xcalls), where tokens are nonempty strings separated by runs of chars
  870. Xfrom termchars.  Writes nulls into parsestr to end tokens.
  871. Xtermchars need not remain constant from call to call.
  872. X
  873. XTreats multiple occurrences of a termchar as one delimiter (does not
  874. Xallow null fields).
  875. X------------------------------------------------------------------------*/
  876. X#if defined(M_UNIX)
  877. Xstatic char *arg_token_static = (char *)0;
  878. Xchar *
  879. Xarg_token(parsestr, termchars)
  880. Xchar *parsestr;
  881. Xchar *termchars;
  882. X{
  883. X    register char *parseptr;
  884. X    char *token;
  885. X
  886. X    if (parsestr == (char *)0 && arg_token_static == (char *)0)
  887. X        return ((char *)0);
  888. X
  889. X    if (parsestr)
  890. X        parseptr = parsestr;
  891. X    else
  892. X        parseptr = arg_token_static;
  893. X
  894. X    while (*parseptr)
  895. X    {
  896. X        if (!strchr(termchars, *parseptr))
  897. X            break;
  898. X        parseptr++;
  899. X    }
  900. X
  901. X    if (!*parseptr)
  902. X    {
  903. X        arg_token_static = (char *)0;
  904. X        return ((char *)0);
  905. X    }
  906. X
  907. X    token = parseptr;
  908. X    if (*token == '\'')
  909. X    {
  910. X        token++;
  911. X        parseptr++;
  912. X        while (*parseptr)
  913. X        {
  914. X            if (*parseptr == '\'')
  915. X            {
  916. X                arg_token_static = parseptr + 1;
  917. X                *parseptr = 0;
  918. X                return (token);
  919. X            }
  920. X            parseptr++;
  921. X        }
  922. X        arg_token_static = (char *)0;
  923. X        return (token);
  924. X    }
  925. X    while (*parseptr)
  926. X    {
  927. X        if (strchr(termchars, *parseptr))
  928. X        {
  929. X            *parseptr = 0;
  930. X            arg_token_static = parseptr + 1;
  931. X            while (*arg_token_static)
  932. X            {
  933. X                if (!strchr(termchars, *arg_token_static))
  934. X                    break;
  935. X                arg_token_static++;
  936. X            }
  937. X            return (token);
  938. X        }
  939. X        parseptr++;
  940. X    }
  941. X    arg_token_static = (char *)0;
  942. X    return (token);
  943. X}                             /* end of arg_token */
  944. X#endif
  945. X
  946. X/*+-------------------------------------------------------------------------
  947. X    fname_split(cmd,arg,arg_max_quan,&narg)
  948. X--------------------------------------------------------------------------*/
  949. X#if defined(M_UNIX)
  950. Xvoid
  951. Xfname_split(cmd, arg, arg_max_quan, narg_rtn)
  952. Xchar *cmd;
  953. Xchar **arg;
  954. Xint arg_max_quan;
  955. Xint *narg_rtn;
  956. X{
  957. X    register itmp;
  958. X    register narg;
  959. X
  960. X    for (itmp = 0; itmp < arg_max_quan; itmp++)
  961. X        arg[itmp] = (char *)0;
  962. X    arg[0] = arg_token(cmd, "/");
  963. X
  964. X    for (narg = 1; narg < arg_max_quan; ++narg)
  965. X    {
  966. X        if ((arg[narg] = arg_token((char *)0, "/")) == (char *)0)
  967. X            break;
  968. X    }
  969. X
  970. X    *narg_rtn = narg;
  971. X
  972. X}                             /* end of fname_split */
  973. X#endif
  974. X
  975. X#if defined(M_UNIX)
  976. X#define MAX_COMPONENT_LEN    14
  977. X#define MAX_PATH_COMPONENTS    16
  978. Xstatic char trunc_fname[257];
  979. Xstatic char *trunc_components[MAX_PATH_COMPONENTS];
  980. Xstatic int trunc_components_quan;
  981. Xstatic int trunc_absolute_path;
  982. X
  983. X#endif
  984. X
  985. X/*+-------------------------------------------------------------------------
  986. X    fname_too_long(fname) - check for any pathname component too long
  987. X--------------------------------------------------------------------------*/
  988. X#if defined(M_UNIX)
  989. Xint
  990. Xfname_too_long(fname)
  991. Xregister char *fname;
  992. X{
  993. X    register int itmp;
  994. X    register char **cpptr;
  995. X
  996. X    if (trunc_absolute_path = (*fname == '/'))
  997. X        fname++;
  998. X    strncpy(trunc_fname, fname, sizeof(trunc_fname) - 1);
  999. X    fname_split(trunc_fname, trunc_components,
  1000. X        MAX_PATH_COMPONENTS, &trunc_components_quan);
  1001. X    itmp = trunc_components_quan;
  1002. X    cpptr = trunc_components;
  1003. X    while (itmp--)
  1004. X    {
  1005. X        if (strlen(*cpptr) > MAX_COMPONENT_LEN)
  1006. X            return (1);
  1007. X        cpptr++;
  1008. X    }
  1009. X    return (0);
  1010. X}                             /* end of fname_too_long */
  1011. X#endif
  1012. X
  1013. X/*+-------------------------------------------------------------------------
  1014. X    fname_truncated() - build truncated path last checked by fname_too_long
  1015. X--------------------------------------------------------------------------*/
  1016. X#if defined(M_UNIX)
  1017. Xchar *
  1018. Xfname_truncated()
  1019. X{
  1020. X    register int icomp;
  1021. X    char new_fname[257];
  1022. X    register char *cptr = new_fname;
  1023. X
  1024. X    if (trunc_absolute_path)
  1025. X    {
  1026. X        *cptr = '/';
  1027. X        *(cptr + 1) = 0;
  1028. X    }
  1029. X    else
  1030. X        *cptr = 0;
  1031. X    for (icomp = 0; icomp < trunc_components_quan; icomp++)
  1032. X    {
  1033. X        if (strlen(trunc_components[icomp]) > MAX_COMPONENT_LEN)
  1034. X            *(trunc_components[icomp] + MAX_COMPONENT_LEN) = 0;
  1035. X        strcat(cptr, trunc_components[icomp]);
  1036. X        if (icomp < trunc_components_quan - 1)
  1037. X            strcat(cptr, "/");
  1038. X    }
  1039. X    strcpy(trunc_fname, cptr);
  1040. X    return (trunc_fname);
  1041. X
  1042. X}                             /* end of fname_truncated */
  1043. X#endif
  1044. X
  1045. X/*+-------------------------------------------------------------------------
  1046. X    xmit_cancel()
  1047. X--------------------------------------------------------------------------*/
  1048. Xvoid
  1049. Xxmit_cancel()
  1050. X{
  1051. X    char *cancel_msg = "\030\030\030\030\030\030\030\030\b\b\b\b\b\b\b\b";
  1052. X
  1053. X    ecuflush(iofd, TCOFLUSH);
  1054. X    write(iofd, cancel_msg, 16);
  1055. X    tx_char_count += 16;
  1056. X    report_str("CANCELling transfer", 1);
  1057. X    report_last_txhdr("CAN", 0);
  1058. X
  1059. X}                             /* end of xmit_cancel */
  1060. X
  1061. X/*+-------------------------------------------------------------------------
  1062. X    xmit_ack(blknum)
  1063. X--------------------------------------------------------------------------*/
  1064. Xvoid
  1065. Xxmit_ack(blknum)
  1066. Xregister int blknum;         /* block number */
  1067. X{
  1068. X    char s16[16];
  1069. X
  1070. X    sprintf(s16, "ACK %3d", blknum);
  1071. X    report_last_txhdr(s16, 0);
  1072. X
  1073. X    s16[0] = ACK;
  1074. X    s16[1] = blknum;         /* block number */
  1075. X    s16[2] = blknum ^ 0xFF;     /* block number check */
  1076. X    write(iofd, s16, 3);
  1077. X    tx_char_count += 3;
  1078. X}                             /* end of xmit_ack */
  1079. X
  1080. X/*+-------------------------------------------------------------------------
  1081. X    xmit_nak(blknum)
  1082. X--------------------------------------------------------------------------*/
  1083. Xvoid
  1084. Xxmit_nak(blknum)
  1085. Xregister int blknum;         /* block number */
  1086. X{
  1087. X    char s16[16];
  1088. X
  1089. X    sprintf(s16, "NAK %d", blknum);
  1090. X    report_last_txhdr(s16, 1);
  1091. X
  1092. X    if (crc_in_use)
  1093. X        s16[0] = 'C';
  1094. X    else
  1095. X        s16[0] = NAK;
  1096. X
  1097. X    s16[1] = blknum;         /* block number */
  1098. X    s16[2] = blknum ^ 0xFF;     /* block number check */
  1099. X    write(iofd, s16, 3);
  1100. X    tx_char_count += 3;
  1101. X
  1102. X}                             /* end of xmit_nak */
  1103. X
  1104. X/*+-------------------------------------------------------------------------
  1105. X    lgetc_timeout(tenths)
  1106. X
  1107. X reads one character from line unless timeout in tenths passes
  1108. X with no receipt.
  1109. X--------------------------------------------------------------------------*/
  1110. Xunsigned int
  1111. Xlgetc_timeout(tenths)
  1112. Xint tenths;
  1113. X{
  1114. X    unsigned char rdchar;
  1115. X
  1116. X    if (tenths < 0)             /* prevent sadness */
  1117. X        tenths = 0;
  1118. X
  1119. X    if (!tenths)
  1120. X    {
  1121. X        if (!rdchk(iofd))
  1122. X            return (TIMEOUT);
  1123. X        else
  1124. X        {
  1125. X            read(iofd, &rdchar, 1);
  1126. X            rx_char_count++;
  1127. X            return ((unsigned int)rdchar);
  1128. X        }
  1129. X    }
  1130. X
  1131. X    if (tenths < 6)
  1132. X        tenths = 6;
  1133. X
  1134. X#if defined(CFG_SelectNap)
  1135. X
  1136. X    {
  1137. X        struct timeval tval;
  1138. X
  1139. X#ifdef CFG_HasFdSet
  1140. X        struct fd_set fdset;
  1141. X
  1142. X        FD_ZERO(&fdset);
  1143. X        FD_SET(iofd, &fdset);
  1144. X#else
  1145. X        int fdmask;
  1146. X
  1147. X        fdmask = 1 << iofd;
  1148. X#endif
  1149. X
  1150. X        tval.tv_sec = tenths / 10L;
  1151. X        tval.tv_usec = (tenths % 10L) * 100000L;
  1152. X        if ((select(iofd + 1,
  1153. X#ifdef CFG_HasFdSet
  1154. X                    &fdset,
  1155. X#else
  1156. X                    &fdmask,
  1157. X#endif
  1158. X                    (SelBitmask *) 0, (SelBitmask *) 0, &tval) < 0) ||
  1159. X            (!rdchk(iofd)) || (read(iofd, &rdchar, 1) < 0))
  1160. X        {
  1161. X            report_last_rxhdr("TIMEOUT", 0);
  1162. X            return (TIMEOUT);
  1163. X        }
  1164. X        rx_char_count++;
  1165. X        return ((unsigned int)rdchar);
  1166. X    }
  1167. X
  1168. X#else
  1169. X
  1170. X    {
  1171. X        int seconds;
  1172. X        unsigned long msec = tenths * 100;
  1173. X        unsigned long interval = msec / 10;
  1174. X        long Nap();
  1175. X
  1176. X        if (interval < 20)
  1177. X            interval = 20;
  1178. X        else if (interval > 1000)
  1179. X            interval = 1000;
  1180. X
  1181. X        while (msec)
  1182. X        {
  1183. X            msec -= Nap(20L);
  1184. X            if (rdchk(iofd))
  1185. X            {
  1186. X                read(iofd, &rdchar, 1);
  1187. X                rx_char_count++;
  1188. X                return ((unsigned int)rdchar);
  1189. X            }
  1190. X        }
  1191. X        report_last_rxhdr("TIMEOUT", 0);
  1192. X        return (TIMEOUT);
  1193. X    }
  1194. X
  1195. X#endif
  1196. X
  1197. X    /*
  1198. X     * for safety, though should get unreachable code warning
  1199. X     */
  1200. X    _exit(TIMEOUT);             /* should get unreachable code warning */
  1201. X
  1202. X}                             /* end of lgetc_timeout */
  1203. X
  1204. X/*+-------------------------------------------------------------------------
  1205. X    sf_state_text(state)
  1206. X--------------------------------------------------------------------------*/
  1207. Xchar *
  1208. Xsf_state_text(state)
  1209. Xregister state;
  1210. X{
  1211. X    char unrecog[16];
  1212. X
  1213. X    switch (state)
  1214. X    {
  1215. X        case SFS_GND:
  1216. X            return ("GND");
  1217. X        case SFS_ACK:
  1218. X            return ("ACK");
  1219. X        case SFS_NAK:
  1220. X            return ("NAK");
  1221. X        case SFS_ACKW:
  1222. X            return ("ACKW");
  1223. X        case SFS_NAKW:
  1224. X            return ("NAKW");
  1225. X        case SFS_RGND:
  1226. X            return ("RGND");
  1227. X        default:
  1228. X            sprintf(unrecog, "SFS_%d", state);
  1229. X            return (unrecog);
  1230. X    }
  1231. X
  1232. X}                             /* end of sf_state_text */
  1233. X
  1234. X/*+-------------------------------------------------------------------------
  1235. X    set_sf_state(place,new_state)
  1236. X--------------------------------------------------------------------------*/
  1237. Xvoid
  1238. Xset_sf_state(place, new_state)
  1239. Xint place;
  1240. Xint new_state;
  1241. X{
  1242. X    if (log_packets)
  1243. X    {
  1244. X        sprintf(s128, "state from %s to %s (%d)",
  1245. X            sf_state_text(sf_state), sf_state_text(new_state), place);
  1246. X        report_str(s128, 0);
  1247. X    }
  1248. X    sf_state = new_state;
  1249. X}                             /* end of set_sf_state */
  1250. X
  1251. X/*+-------------------------------------------------------------------------
  1252. X    wait_for_rcvr_response() - check for ACK or NAK
  1253. X sets 'sf_state' to SFS_... value depending on response from file rcvr
  1254. X returns 1 if TIMEOUT at state other than ground, else 0
  1255. X--------------------------------------------------------------------------*/
  1256. Xint
  1257. Xwait_for_rcvr_response()
  1258. X{
  1259. X    int c;                     /* one byte of data */
  1260. X    static int rawblk = 0;     /* raw block number */
  1261. X
  1262. X    while ((c = lgetc_timeout((sf_state == SFS_GND) ? 0 : 6)) != TIMEOUT)
  1263. X    {
  1264. X        if (c == CAN)
  1265. X        {                     /* CANcel received? */
  1266. X            if ((c = lgetc_timeout(20)) == CAN)
  1267. X            {
  1268. X                sf_nakquan = 11;
  1269. X                report_last_rxhdr("CAN", 0);    /* error counted at cancel
  1270. X                                                 * time */
  1271. X            }
  1272. X            break;
  1273. X        }
  1274. X        if (sf_state == SFS_ACKW || sf_state == SFS_NAKW)    /* windowed */
  1275. X        {
  1276. X            sf_slide = 0;     /* assume this will fail */
  1277. X            /* see if we believe the number */
  1278. X            if (rawblk == (c ^ 0xFF))
  1279. X            {
  1280. X                rawblk = sf_blknum - ((sf_blknum - rawblk) & 0xFF);
  1281. X                if ((rawblk >= 0) && (rawblk <= sf_blknum) &&
  1282. X                    (rawblk > (sf_blknum - 128)))
  1283. X                {             /* we have sliding window! */
  1284. X                    if (sf_state == SFS_ACKW)
  1285. X                    {
  1286. X                        sf_ackblk = (sf_ackblk > rawblk) ? sf_ackblk : rawblk;
  1287. X                        sf_slide = 1;
  1288. X                        if (no_ack_mode && (++sf_ackw_count > 10))
  1289. X                        {
  1290. X                            no_ack_mode = 0;
  1291. X                            report_str("Overdrive disengaged", 0);
  1292. X                        }
  1293. X                    }
  1294. X                    else
  1295. X                    {
  1296. X                        sf_blknum = (rawblk < 0) ? 0 : rawblk;
  1297. X                        sf_slide = (sf_nakquan < 4);
  1298. X                    }
  1299. X                    sprintf(s128, "%s %5d",
  1300. X                        (sf_state == SFS_ACKW) ? "ACKW" : "NAKW", rawblk);
  1301. X                    report_last_rxhdr(s128, (sf_state != SFS_ACKW) && rawblk);
  1302. X                }
  1303. X            }
  1304. X            set_sf_state(1, SFS_RGND);    /* return to ground state */
  1305. X        }
  1306. X
  1307. X        if (sf_state == SFS_ACK || sf_state == SFS_NAK)
  1308. X        {
  1309. X            rawblk = c;
  1310. X            if (sf_state == SFS_ACK)
  1311. X                set_sf_state(2, SFS_ACKW);
  1312. X            else
  1313. X                set_sf_state(3, SFS_NAKW);
  1314. X        }
  1315. X
  1316. X        if (!sf_slide || sf_state == SFS_GND)
  1317. X        {
  1318. X            if (c == ACK)
  1319. X            {
  1320. X                if (!sf_slide)
  1321. X                {
  1322. X                    sprintf(s128, "ACK %3d", sf_ackblk);
  1323. X                    report_last_rxhdr(s128, 0);
  1324. X                    sf_ackblk++;
  1325. X                }
  1326. X                set_sf_state(4, SFS_ACK);
  1327. X                sf_nakquan = 0;
  1328. X            }
  1329. X            else if (c == 'C' || c == NAK)
  1330. X            {
  1331. X                /* if method not determined yet */
  1332. X                if (crc_in_use > 1)    /* then do what rcvr wants */
  1333. X                {
  1334. X                    crc_in_use = (c == 'C');
  1335. X                    report_protocol_crc_type(crc_in_use ? "/CRC16" : "/CHK");
  1336. X                }
  1337. X                ecuflush(iofd, TCOFLUSH);
  1338. X                if (!sf_slide)
  1339. X                {
  1340. X                    sf_blknum = sf_ackblk + 1;
  1341. X                    sprintf(s128, "NAK %3d", sf_blknum);
  1342. X                    report_last_rxhdr(s128, (!!sf_blknum));
  1343. X                }
  1344. X                set_sf_state(5, SFS_NAK);
  1345. X                sf_nakquan++;
  1346. X                if (sf_lastnum)
  1347. X                    error_count++;
  1348. X            }
  1349. X        }
  1350. X
  1351. X        if (sf_state == SFS_RGND)
  1352. X            set_sf_state(6, SFS_GND);
  1353. X    }
  1354. X    return ((sf_state != SFS_GND) && (c == TIMEOUT));
  1355. X}                             /* end of wait_for_rcvr_response */
  1356. X
  1357. X/*+-------------------------------------------------------------------------
  1358. X    send_comm_block(blk,blknum) - format and transmit block
  1359. X--------------------------------------------------------------------------*/
  1360. Xint
  1361. Xsend_comm_block(blk, blknum)
  1362. Xchar *blk;                     /* data to be shipped */
  1363. Xint blknum;                     /* number of block */
  1364. X{
  1365. X    register unsigned short rUINT16 = 0;
  1366. X    register int itmp;
  1367. X    unsigned char chksum;
  1368. X    char *cptr = blk;
  1369. X    char s3[3];
  1370. X
  1371. X    s3[0] = SOH;             /* block header */
  1372. X    s3[1] = blknum;             /* block number */
  1373. X    s3[2] = blknum ^ 0xFF;     /* block number check value */
  1374. X
  1375. X/* calculate the crc or checksum */
  1376. X    itmp = 128;
  1377. X    if (crc_in_use)
  1378. X    {
  1379. X        while (itmp--)
  1380. X        {
  1381. X            rUINT16 = crc_update(*cptr, rUINT16);
  1382. X            cptr++;
  1383. X        }
  1384. X        rUINT16 = crc_update(0, rUINT16);
  1385. X        rUINT16 = crc_update(0, rUINT16);
  1386. X    }
  1387. X    else
  1388. X    {
  1389. X        while (itmp--)
  1390. X            rUINT16 += *cptr++;
  1391. X    }
  1392. X
  1393. X/* write the block */
  1394. X
  1395. X    write(iofd, s3, 3);         /* the header */
  1396. X    write(iofd, blk, 128);     /* the block */
  1397. X    if (crc_in_use)             /* the crc or checksum */
  1398. X    {
  1399. X        s3[0] = rUINT16 >> 8;
  1400. X        s3[1] = rUINT16 & 0xFF;
  1401. X        write(iofd, s3, 2);
  1402. X        tx_char_count += 133;
  1403. X    }
  1404. X    else
  1405. X    {
  1406. X        chksum = rUINT16;
  1407. X        write(iofd, &chksum, 1);
  1408. X        tx_char_count += 132;
  1409. X    }
  1410. X
  1411. X    return (1);
  1412. X}                             /* end of send_comm_block */
  1413. X
  1414. X/*+-------------------------------------------------------------------------
  1415. X    send_file_block(fp,blknum) - read a block from file and send it
  1416. X--------------------------------------------------------------------------*/
  1417. Xvoid
  1418. Xsend_file_block(fp, blknum)
  1419. XFILE *fp;
  1420. Xint blknum;
  1421. X{
  1422. X    long fileaddr;
  1423. X    char buf[128];
  1424. X
  1425. X    fileaddr = (long)(blknum - 1) * 128L;
  1426. X    if (blknum != sf_lastnum + 1)
  1427. X        fseek(fp, fileaddr, 0);    /* move where to */
  1428. X    sf_lastnum = blknum;
  1429. X    report_txpos(fileaddr);
  1430. X
  1431. X    memset(buf, 0x1A, sizeof(buf));    /* fill buffer with control Zs */
  1432. X    fread(buf, 1, sizeof(buf), fp);    /* read in some data */
  1433. X    send_comm_block(buf, blknum);    /* pump it out to the receiver */
  1434. X}                             /* end of send_file_block */
  1435. X
  1436. X/*+-------------------------------------------------------------------------
  1437. X    send_file(name) - transmit a file
  1438. X--------------------------------------------------------------------------*/
  1439. Xint
  1440. Xsend_file(name)
  1441. Xchar *name;
  1442. X{
  1443. X    register int endblk;     /* block number of EOT */
  1444. X    FILE *fp = (FILE *) 0;     /* file to send */
  1445. X    struct stat fst;
  1446. X    BLK0 blk0;
  1447. X    char *basename;             /* base filename */
  1448. X    char eot = EOT;
  1449. X
  1450. X    Filcnt++;
  1451. X    if (name && *name)         /* if sending a file */
  1452. X    {
  1453. X        if ((fp = fopen(name, "r")) == NULL)
  1454. X        {
  1455. X            sprintf(s128, "Cannot open %s", name);
  1456. X            report_str(s128, 1);
  1457. X            exit_code = 253;
  1458. X            return (0);
  1459. X        }
  1460. X
  1461. X        memset((char *)&blk0, 0, sizeof(blk0));    /* clear out data block */
  1462. X
  1463. X        stat(name, &fst);     /* get file statistics */
  1464. X        blk0.length = (long)fst.st_size;
  1465. X
  1466. X        /* cnvt time from 1970 base to 1980 */
  1467. X        if ((blk0.secs_since_1980 = fst.st_mtime - OFFSET_1980) < 0L)
  1468. X            blk0.secs_since_1980 = 0;
  1469. X
  1470. X        if ((basename = strrchr(name, '/')) == NULL)    /* find basename */
  1471. X            strcpy(blk0.filename, name);
  1472. X        else
  1473. X        {
  1474. X            basename++;
  1475. X            strcpy(blk0.filename, basename);
  1476. X        }
  1477. X
  1478. X        strcat(blk0.sender, version + 4);
  1479. X        blk0.send_no_acks = no_ack_mode;
  1480. X
  1481. X        endblk = (int)((blk0.length + 127L) / 128L) + 1;
  1482. X        report_file_send_open(name, &fst);
  1483. X    }
  1484. X    else
  1485. X    {
  1486. X        endblk = 0;             /* fake for no file */
  1487. X        report_str("sending EOT indication", -1);
  1488. X        report_txpos(blk0.length);
  1489. X    }
  1490. X
  1491. X    sf_blknum = 1;             /* set starting state */
  1492. X    sf_ackblk = -1;
  1493. X    sf_state = SFS_GND;
  1494. X    sf_lastnum = 0;
  1495. X    sf_slide = 0;
  1496. X    sf_nakquan = 0;
  1497. X    error_count = 0;
  1498. X    sf_ackw_count = 0;
  1499. X    crc_in_use = 2;             /* undetermined */
  1500. X
  1501. X    while (sf_ackblk < endblk)    /* while not all there yet */
  1502. X    {
  1503. X        sent_EOT = 0;
  1504. X        if (sf_blknum <= sf_ackblk + ((sf_slide && allow_slide) ? WINDOW : 1))
  1505. X        {
  1506. X            if (sf_blknum < endblk)
  1507. X            {
  1508. X                if (sf_blknum > 0)
  1509. X                {
  1510. X                    sprintf(s128, "sending block %d", sf_blknum);
  1511. X                    report_last_txhdr(s128, 0);
  1512. X                    send_file_block(fp, sf_blknum);
  1513. X                }
  1514. X                else
  1515. X                {
  1516. X                    sprintf(s128, "sending filename", sf_blknum);
  1517. X                    report_last_txhdr(s128, 0);
  1518. X                    send_comm_block((char *)&blk0, 0);
  1519. X                    report_txpos(0L);
  1520. X                }
  1521. X                if (no_ack_mode && sf_slide && allow_slide)
  1522. X                    sf_ackblk = sf_blknum;
  1523. X            }
  1524. X            else if (sf_blknum == endblk)
  1525. X            {
  1526. X                report_last_txhdr("EOT", 0);
  1527. X                write(iofd, &eot, 1);
  1528. X                sent_EOT = 1;
  1529. X                Nap(500L);
  1530. X                tx_char_count++;
  1531. X            }
  1532. X            sf_blknum++;
  1533. X        }
  1534. X
  1535. X        if (wait_for_rcvr_response() && sent_EOT)
  1536. X        {
  1537. X            report_str("Receiver did not ACK our EOT", -1);
  1538. X            break;
  1539. X        }
  1540. X
  1541. X        if (sf_nakquan > 10)
  1542. X            goto CANCEL_TRANSFER;
  1543. X    }
  1544. X
  1545. X    if (endblk)                 /* if sending file, not EOT */
  1546. X        fclose(fp);
  1547. X    return (1);                 /* exit with good status */
  1548. X
  1549. X  CANCEL_TRANSFER:
  1550. X    if (endblk)                 /* if sending file, not EOT */
  1551. X        fclose(fp);
  1552. X    xmit_cancel();
  1553. X    return (0);                 /* exit with bad status */
  1554. X}                             /* end of send_file */
  1555. X
  1556. X/*+-------------------------------------------------------------------------
  1557. X    set_utime_1980(filename,secs_since_1980)
  1558. X--------------------------------------------------------------------------*/
  1559. Xvoid
  1560. Xset_utime_1980(filename, secs_since_1980)
  1561. Xchar *filename;                 /* file to set stamp on */
  1562. Xlong secs_since_1980;
  1563. X{
  1564. X    time_t times[2];
  1565. X    time_t time();
  1566. X
  1567. X    times[0] = time((long *)0);    /* accessed */
  1568. X    times[1] = secs_since_1980 + OFFSET_1980;    /* modified (convert time) */
  1569. X    utime(filename, times);
  1570. X}                             /* end of set_utime_1980 */
  1571. X
  1572. X/*+-------------------------------------------------------------------------
  1573. X    receive_block(buf) - get block from line
  1574. Xreturn 0 if good chk/CRC, 1 if bad
  1575. X--------------------------------------------------------------------------*/
  1576. Xint
  1577. Xreceive_block(buf)
  1578. Xchar *buf;                     /* data buffer */
  1579. X{
  1580. X    register unsigned int rdchar;
  1581. X    register unsigned short rUINT16 = 0;    /* calculated CRC or check
  1582. X                                             * value */
  1583. X    int itmp;
  1584. X    int timeout = no_ack_mode ? 200 : 5;    /* short block timeout */
  1585. X    unsigned short rcvd_crc; /* received CRC or check value */
  1586. X
  1587. X    itmp = 128;
  1588. X    while (itmp--)
  1589. X    {
  1590. X        if ((rdchar = lgetc_timeout(timeout)) == TIMEOUT)
  1591. X            return (1);
  1592. X        if (crc_in_use)
  1593. X            rUINT16 = crc_update(rdchar, rUINT16);
  1594. X        else
  1595. X            rUINT16 += rdchar;
  1596. X        *buf++ = rdchar;
  1597. X    }
  1598. X
  1599. X    if (crc_in_use)
  1600. X    {
  1601. X        rUINT16 = crc_update(0, rUINT16);
  1602. X        rUINT16 = crc_update(0, rUINT16);
  1603. X        rdchar = lgetc_timeout(timeout);
  1604. X        rcvd_crc = (rdchar << 8) | lgetc_timeout(timeout);
  1605. X    }
  1606. X    else
  1607. X    {
  1608. X        rUINT16 &= 0xFF;
  1609. X        rcvd_crc = lgetc_timeout(timeout) & 0xFF;
  1610. X    }
  1611. X
  1612. X    if (rUINT16 != rcvd_crc)
  1613. X    {
  1614. X        sprintf(s128, "bad %s calc=%04x rcvd=%04x",
  1615. X            crc_in_use ? "CRC" : "checksum", rcvd_crc, rUINT16);
  1616. X        report_str(s128, -1);
  1617. X    }
  1618. X    return (rUINT16 != rcvd_crc);
  1619. X}                             /* end of receive_block */
  1620. X
  1621. X/*+-------------------------------------------------------------------------
  1622. X    receive_file()
  1623. X--------------------------------------------------------------------------*/
  1624. Xchar *
  1625. Xreceive_file()
  1626. X{
  1627. X    int rdchar;                 /* received character */
  1628. X    int tries;                 /* retry counter */
  1629. X    int blknum;                 /* desired block number */
  1630. X    int inblk;                 /* this block number */
  1631. X    FILE *fp;
  1632. X    char buf[128];             /* data buffer */
  1633. X    char tmpname[100];         /* name of temporary file */
  1634. X    static char outname[100];/* name of final file */
  1635. X    BLK0 blk0;                 /* file header data storage */
  1636. X    int endblk;                 /* block number of EOT, if known */
  1637. X    long left = 0;             /* bytes left to output */
  1638. X    int itmp;                 /* index */
  1639. X    int cnvrt;                 /* flag -- convert filename? */
  1640. X    char *onp;                 /* use to convert filename to l / rdchar */
  1641. X    long ftell();
  1642. X
  1643. X    *outname = '\0';         /* get name from transmitter */
  1644. X    cnvrt = 1;                 /* convert to local is necessary */
  1645. X    sprintf(tmpname, "./SEA%05d.tmp", getpid());    /* use a unique temp
  1646. X                                                     * filename */
  1647. X
  1648. X    if (!(fp = fopen(tmpname, "w")))
  1649. X    {                         /* open temporary file */
  1650. X        sprintf(s128, "Cannot create temp file %s\n", tmpname);
  1651. X        report_str(s128, 0);
  1652. X        xmit_cancel();
  1653. X        return (NULL);
  1654. X    }
  1655. X
  1656. X    blknum = 0;
  1657. X    tries = -10;             /* kludge for first time around */
  1658. X    crc_in_use = 1;             /* try for CRC error checking */
  1659. X    error_count = 0;         /* no errors yet */
  1660. X    endblk = 0;                 /* we don't know the size yet */
  1661. X    no_ack_mode = 0;         /* we don't know about this yet */
  1662. X    memset((char *)&blk0, 0, sizeof(blk0));    /* or much of anything else */
  1663. X    report_protocol_crc_type("/CRC16");
  1664. X
  1665. X  SEND_NAK:                 /* we got a bad block */
  1666. X    if (blknum > 1)
  1667. X    {
  1668. X        error_count++;
  1669. X        report_str("bad block", 1);
  1670. X    }
  1671. X    if (++tries > 10)
  1672. X        goto CANCEL_TRANSFER;
  1673. X    if (tries == 0)             /* if CRC isn't going */
  1674. X    {
  1675. X        crc_in_use = 0;         /* then give checksum a try */
  1676. X        report_protocol_crc_type("/CHK");
  1677. X    }
  1678. X
  1679. X    xmit_nak(blknum);         /* send the NAK */
  1680. X    if (no_ack_mode && error_count > 20)
  1681. X    {                         /* if no_ack_mode mode isn't working */
  1682. X        no_ack_mode = 0;     /* then shut it off */
  1683. X        report_str("Overdrive disengaged", 0);
  1684. X    }
  1685. X
  1686. X  RECEIVE_NEXT_BLOCK:         /* start of "get a block" */
  1687. X    report_rxpos(ftell(fp));
  1688. X    while ((rdchar = lgetc_timeout(30)) != TIMEOUT)
  1689. X    {
  1690. X        if (rdchar == CAN)
  1691. X        {
  1692. X            if ((rdchar = lgetc_timeout(30)) == CAN)
  1693. X            {
  1694. X                xmit_cancel();
  1695. X                return (NULL);
  1696. X            }
  1697. X            break;
  1698. X        }
  1699. X        if (rdchar == EOT)
  1700. X        {
  1701. X            if (!endblk || endblk == blknum)
  1702. X                goto RECEIVE_EOT_SEEN;
  1703. X        }
  1704. X        else if (rdchar == SOH)
  1705. X        {
  1706. X            if ((inblk = lgetc_timeout(5)) == TIMEOUT)
  1707. X                goto SEND_NAK;
  1708. X            if (lgetc_timeout(5) == (inblk ^ 0xFF))
  1709. X            {
  1710. X                sprintf(s128, "receiving %d", inblk);
  1711. X                report_last_rxhdr(s128, 0);
  1712. X                goto GOT_START_OF_BLOCK;    /* we found a start */
  1713. X            }
  1714. X        }
  1715. X    }
  1716. X    goto SEND_NAK;
  1717. X
  1718. X  GOT_START_OF_BLOCK:         /* start of block detected */
  1719. X    rdchar = blknum & 0xFF;
  1720. X    if (inblk == 0 && blknum <= 1)
  1721. X    {                         /* if this is the header */
  1722. X        if (receive_block((char *)&blk0))
  1723. X            goto SEND_NAK;     /* bad header block */
  1724. X        else
  1725. X        {
  1726. X            xmit_ack(inblk); /* ack the header */
  1727. X
  1728. X#if defined(M_UNIX)
  1729. X            if (fname_too_long(blk0.filename))
  1730. X            {
  1731. X                strcpy(s128, "truncated: ");
  1732. X                strncat(s128, blk0.filename, sizeof(s128) - 12);
  1733. X                report_str(s128, -1);
  1734. X                strcpy(outname, fname_truncated());
  1735. X            }
  1736. X            else
  1737. X#endif
  1738. X                strcpy(outname, blk0.filename);
  1739. X            report_file_rcv_started(outname, blk0.length,
  1740. X                blk0.secs_since_1980 + OFFSET_1980);
  1741. X            if (left = blk0.length)    /* length to transfer */
  1742. X                endblk = (int)((left + 127L) / 128L) + 1;
  1743. X            if (no_ack_mode != blk0.send_no_acks)
  1744. X            {
  1745. X                sprintf(s128, "Overdrive %sengaged",
  1746. X                    (blk0.send_no_acks) ? "" : "dis");
  1747. X                report_str(s128, 0);
  1748. X            }
  1749. X            no_ack_mode = blk0.send_no_acks;
  1750. X            blknum = 1;         /* now we want first data block */
  1751. X            goto RECEIVE_NEXT_BLOCK;
  1752. X        }
  1753. X    }
  1754. X
  1755. X    if (inblk == rdchar)
  1756. X    {                         /* if this is the one we want */
  1757. X        if (!receive_block(buf))
  1758. X        {                     /* else if we get it okay */
  1759. X            if (!no_ack_mode)/* if we're sending ACKs */
  1760. X                xmit_ack(inblk);    /* then ACK the data */
  1761. X            for (itmp = 0; itmp < 128; itmp++)
  1762. X            {
  1763. X                if (endblk)
  1764. X                {             /* limit file size if known */
  1765. X                    if (!left)
  1766. X                        break;
  1767. X                    left--;
  1768. X                }
  1769. X                if (fputc(buf[itmp], fp) == EOF)
  1770. X                {
  1771. X                    report_str("FILE WRITE ERROR", 0);
  1772. X                    goto CANCEL_TRANSFER;
  1773. X                }
  1774. X            }
  1775. X            tries = 0;         /* reset try count */
  1776. X            blknum++;         /* we want the next block */
  1777. X            goto RECEIVE_NEXT_BLOCK;
  1778. X        }
  1779. X        goto SEND_NAK;         /* ask for a resend */
  1780. X    }
  1781. X
  1782. X    if (inblk < rdchar || inblk > rdchar + 100)
  1783. X    {                         /* if resending what we have */
  1784. X        receive_block(buf);     /* ignore it */
  1785. X        xmit_ack(inblk);     /* but ack it */
  1786. X    }
  1787. X    goto RECEIVE_NEXT_BLOCK; /* else if running ahead */
  1788. X
  1789. X  RECEIVE_EOT_SEEN:
  1790. X#ifdef NAKEOT
  1791. X    xmit_nak(blknum);         /* NAK the EOT, make sure */
  1792. X    if (lgetc_timeout(20) != EOT)    /* we're all done */
  1793. X        goto SEND_NAK;
  1794. X#endif /* NAKEOT */
  1795. X    xmit_ack(blknum);         /* ACK it and clean up */
  1796. X    report_last_rxhdr("EOT", 0);
  1797. X    if (blknum > 1)
  1798. X    {                         /* if we really got anything */
  1799. X        fclose(fp);
  1800. X        unlink(outname);     /* rename temp to proper name */
  1801. X        for (onp = outname; cnvrt && *onp; onp++)
  1802. X            /* find out if there's lower- */
  1803. X            if (islower(*onp))    /* case letters filename */
  1804. X                cnvrt = 0;     /* there are, don't convert */
  1805. X        if (cnvrt)             /* if there aren't, make all */
  1806. X            for (onp = outname; *onp; onp++)    /* into uppercase */
  1807. X                *onp = tolower(*onp);
  1808. X        if (link(tmpname, outname) == 0)
  1809. X            unlink(tmpname);
  1810. X        if (blk0.secs_since_1980)    /* set stamp, if known */
  1811. X            set_utime_1980(outname, blk0.secs_since_1980);
  1812. X        return (outname);
  1813. X    }
  1814. X    else
  1815. X    {                         /* else no real file */
  1816. X        fclose(fp);
  1817. X        unlink(tmpname);     /* discard empty file */
  1818. X        report_str("end of transfer", 0);
  1819. X        rf_done = 1;
  1820. X        return (NULL);
  1821. X    }
  1822. X
  1823. X  CANCEL_TRANSFER:
  1824. X    fclose(fp);
  1825. X    xmit_cancel();
  1826. X    rf_done = 2;
  1827. X    return (NULL);
  1828. X}                             /* end of receive_file */
  1829. X
  1830. X/*+-------------------------------------------------------------------------
  1831. X    cancel_transaction(sig)
  1832. X--------------------------------------------------------------------------*/
  1833. XSIGTYPE
  1834. Xcancel_transaction(sig)
  1835. Xint sig;
  1836. X{
  1837. X    xmit_cancel();
  1838. X    sprintf(s128, "signal %d ... exiting", sig);
  1839. X    report_str(s128, 1);
  1840. X/*
  1841. X    report_rx_ind(0);
  1842. X    report_tx_ind(0);
  1843. X*/
  1844. X    report_uninit();
  1845. X    if (sig == SIGQUIT)
  1846. X        abort();
  1847. X    exit(128 + sig);
  1848. X}                             /* end of cancel_transaction */
  1849. X
  1850. X/*+-------------------------------------------------------------------------
  1851. X    getspeed(code)
  1852. X--------------------------------------------------------------------------*/
  1853. Xstruct B_to_baud
  1854. X{
  1855. X    unsigned baud;
  1856. X    int B_code;
  1857. X};
  1858. Xunsigned
  1859. Xgetspeed(atty)
  1860. Xstruct termio *atty;
  1861. X{
  1862. X    register itmp;
  1863. X    int code = ecugetspeed(atty);
  1864. X    static struct B_to_baud speeds[] =
  1865. X    {
  1866. X        {50, B50},
  1867. X        {75, B75},
  1868. X        {110, B110},
  1869. X        {300, B300},
  1870. X        {600, B600},
  1871. X        {1200, B1200},
  1872. X        {2400, B2400},
  1873. X        {4800, B4800},
  1874. X        {9600, B9600},
  1875. X        {19200, EXTA},
  1876. X        {38400, EXTB},
  1877. X        {0, 0}
  1878. X    };
  1879. X
  1880. X    for (itmp = 0; speeds[itmp].baud; itmp++)
  1881. X        if (speeds[itmp].B_code == code)
  1882. X            return (speeds[itmp].baud);
  1883. X    return (38400);             /* Assume fifo if ioctl failed */
  1884. X}                             /* end of getspeed */
  1885. X
  1886. X/*+-------------------------------------------------------------------------
  1887. X    main(argc,argv,envp)
  1888. X--------------------------------------------------------------------------*/
  1889. Xmain(argc, argv, envp)
  1890. Xint argc;
  1891. Xchar **argv;
  1892. Xchar **envp;
  1893. X{
  1894. X    int ipaths;
  1895. X    int ok = 0;
  1896. X
  1897. X#define MAX_PATHS 512
  1898. X    char *paths[MAX_PATHS];
  1899. X    char **ppaths = paths;
  1900. X    char *cptr;
  1901. X    char **gargv = argv;
  1902. X    int gargc = argc;
  1903. X
  1904. X    exit_code = 254;
  1905. X    while (--argc)
  1906. X    {
  1907. X        cptr = *++argv;
  1908. X        if (*cptr == '-')
  1909. X        {
  1910. X            cptr++;
  1911. X            switch (*cptr++)
  1912. X            {
  1913. X                case ',':
  1914. X                    log_packets = 1;
  1915. X                    break;
  1916. X                case '/':
  1917. X                    if (--argc < 1)
  1918. X                        exit(255);
  1919. X                    strcpy(curr_dir, *++argv);
  1920. X                    break;
  1921. X                case '.':
  1922. X                    if (--argc < 1)
  1923. X                        exit(255);
  1924. X                    iofd = atoi(*++argv);
  1925. X                    break;
  1926. X                case 'r':
  1927. X                    sending_flag = 0;
  1928. X                    break;
  1929. X                case 's':
  1930. X                    sending_flag = 1;
  1931. X            }
  1932. X        }
  1933. X        else if (argc > 0)
  1934. X        {
  1935. X            if (npaths < MAX_PATHS)
  1936. X            {
  1937. X                *ppaths++ = cptr;
  1938. X                npaths++;
  1939. X            }
  1940. X            else
  1941. X            {
  1942. X                printf("too many filenames to send\n");
  1943. X                exit(255);
  1944. X            }
  1945. X        }
  1946. X    }
  1947. X
  1948. X    if (sending_flag == -1)
  1949. X    {
  1950. X        printf("no -r or -s\n");
  1951. X        exit(255);
  1952. X    }
  1953. X
  1954. X    if ((npaths < 1) && sending_flag)
  1955. X        exit(253);
  1956. X
  1957. X    if (npaths && !sending_flag)
  1958. X        exit(255);
  1959. X
  1960. X    if (log_packets)
  1961. X    {
  1962. X        char log_packets_name[64];
  1963. X        FILE *ftmp;
  1964. X        int iargv;
  1965. X
  1966. X        sprintf(log_packets_name, "/tmp/sea%05d.plog", getpid());
  1967. X        unlink(log_packets_name);
  1968. X        ftmp = fopen(log_packets_name, "w");
  1969. X        fclose(ftmp);
  1970. X        log_packets = open(log_packets_name, O_WRONLY, 0644);
  1971. X        if (log_packets < 0)
  1972. X            log_packets = 0;
  1973. X        else
  1974. X        {
  1975. X            write(log_packets, "exec: ", 6);
  1976. X            for (iargv = 0; iargv < gargc; iargv++)
  1977. X            {
  1978. X                write(log_packets, gargv[iargv], strlen(gargv[iargv]));
  1979. X                write(log_packets, " ", 1);
  1980. X            }
  1981. X            write(log_packets, "\n", 1);
  1982. X        }
  1983. X    }
  1984. X
  1985. X    report_init(version + 4);
  1986. X    report_top_line("System Enhancement Associates");
  1987. X    signal(SIGHUP, cancel_transaction);
  1988. X    signal(SIGQUIT, cancel_transaction);
  1989. X    signal(SIGINT, cancel_transaction);
  1990. X    signal(SIGTERM, cancel_transaction);
  1991. X#if    defined(SIGSTOP)
  1992. X
  1993. X    /*
  1994. X     * call Roto-Rooter on POSIX plots
  1995. X     */
  1996. X    signal(SIGSTOP, SIG_IGN);
  1997. X    signal(SIGTSTP, SIG_IGN);
  1998. X    signal(SIGCONT, SIG_IGN);
  1999. X    signal(SIGTTIN, SIG_IGN);
  2000. X    signal(SIGTTOU, SIG_IGN);
  2001. X#endif
  2002. X
  2003. X    ecugetattr(iofd, &tio0);
  2004. X    tio = tio0;
  2005. X
  2006. X    tio.c_oflag = 0;
  2007. X    tio.c_cflag &= ~PARENB;
  2008. X    tio.c_cflag &= ~CSIZE;
  2009. X    tio.c_cflag |= CS8;
  2010. X
  2011. X    /*
  2012. X     * learn tick rate for various timers
  2013. X     */
  2014. X    init_Nap();
  2015. X
  2016. X    baud_rate = getspeed(&tio);
  2017. X    ecusetattr(iofd, TCSETA, &tio);
  2018. X    report_line(baud_rate, "RAW");
  2019. X
  2020. X    switch (sending_flag)
  2021. X    {
  2022. X        case 0:             /* receive files */
  2023. X            while (receive_file() != NULL)
  2024. X                Nap(1000L);
  2025. X            ok = (rf_done == 1);
  2026. X            break;
  2027. X
  2028. X        case 1:             /* send files */
  2029. X            ipaths = 0;
  2030. X            while (ipaths < npaths)
  2031. X            {
  2032. X                if (!(ok = send_file(paths[ipaths])))
  2033. X                    break;
  2034. X                Nap(1000L);
  2035. X                ipaths++;
  2036. X            }
  2037. X            if (ok)             /* no errors, send end marker */
  2038. X                send_file("");
  2039. X            report_str("end of transfer", 0);
  2040. X            break;
  2041. X    }
  2042. X
  2043. X    ecusetattr(iofd, TCSETA, &tio0);
  2044. X    report_line(baud_rate, "NORMAL");
  2045. X    report_uninit();
  2046. X    exit(ok ? 0 : exit_code);/* and return error status */
  2047. X
  2048. X}                             /* end of main */
  2049. END_OF_FILE
  2050.   if test 37903 -ne `wc -c <'ecu330/sea/ecusea.c'`; then
  2051.     echo shar: \"'ecu330/sea/ecusea.c'\" unpacked with wrong size!
  2052.   fi
  2053.   # end of 'ecu330/sea/ecusea.c'
  2054. fi
  2055. echo shar: End of archive 13 \(of 37\).
  2056. cp /dev/null ark13isdone
  2057. MISSING=""
  2058. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 ; do
  2059.     if test ! -f ark${I}isdone ; then
  2060.     MISSING="${MISSING} ${I}"
  2061.     fi
  2062. done
  2063. if test "${MISSING}" = "" ; then
  2064.     echo You have unpacked all 37 archives.
  2065.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2066. else
  2067.     echo You still must unpack the following archives:
  2068.     echo "        " ${MISSING}
  2069. fi
  2070. exit 0
  2071. exit 0 # Just in case...
  2072.