home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume16 / ecu3 / part23 < prev    next >
Internet Message Format  |  1991-01-06  |  41KB

  1. From: wht@n4hgf.uucp (Warren Tucker)
  2. Newsgroups: comp.sources.misc
  3. Subject: v16i047:  ECU async comm package rev 3.0, Part23/35
  4. Message-ID: <1991Jan6.052529.28483@sparky.IMD.Sterling.COM>
  5. Date: 6 Jan 91 05:25:29 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: f5c49eb2 2c0b2e71 9ce4a289 ae62436c
  8.  
  9. Submitted-by: wht@n4hgf.uucp (Warren Tucker)
  10. Posting-number: Volume 16, Issue 47
  11. Archive-name: ecu3/part23
  12.  
  13. ---- Cut Here and feed the following to sh ----
  14. #!/bin/sh
  15. # This is part 23 of ecu3
  16. if touch 2>&1 | fgrep 'amc' > /dev/null
  17.  then TOUCH=touch
  18.  else TOUCH=true
  19. fi
  20. # ============= sea/ecusea.c ==============
  21. if test ! -d 'sea'; then
  22.     echo 'x - creating directory sea'
  23.     mkdir 'sea'
  24. fi
  25. echo 'x - extracting sea/ecusea.c (Text)'
  26. sed 's/^X//' << 'SHAR_EOF' > 'sea/ecusea.c' &&
  27. X
  28. Xchar *revision = "1.10";    /* cannot be longer than 7 chars (blk0.sender) */
  29. X
  30. X/* #define TABLE_CRC16 */
  31. X#ifdef M_XENIX
  32. X#define NO_SELECT
  33. X#endif
  34. X
  35. X/*+-------------------------------------------------------------------------
  36. X    ecusea.c - SEAlink - Sliding window file transfer protocol
  37. X
  38. X  Defined functions:
  39. X    arg_token(parsestr,termchars)
  40. X    cancel_transaction(sig)
  41. X    crc_update(c,crc)
  42. X    fname_split(cmd,arg,arg_max_quan,narg_rtn)
  43. X    fname_too_long(fname)
  44. X    fname_truncated()
  45. X    getspeed(code)
  46. X    lgetc_timeout(tenths)
  47. X    lgetc_timeout_SIGALRM()
  48. X    main(argc,argv,envp)
  49. X    receive_block(buf)
  50. X    receive_file()
  51. X    send_comm_block(blk,blknum)
  52. X    send_file(name)
  53. X    send_file_block(fp,blknum)
  54. X    set_sf_state(place,new_state)
  55. X    set_utime_1980(filename,secs_since_1980)
  56. X    sf_state_text(state)
  57. X    wait_for_rcvr_response()
  58. X    xmit_ack(blknum)
  59. X    xmit_cancel()
  60. X    xmit_nak(blknum)
  61. X
  62. Xecu adaptation by W. Tucker
  63. Xmodelled after MSDOS sealink.c, which carried the following proviso:
  64. X
  65. X              MS-DOS Version 1.20, created on 08/05/87
  66. X              at 17:51:40 (C) COPYRIGHT 1986,87 by
  67. X              System Enhancement Associates; ALL RIGHTS
  68. X              RESERVED By: Thom Henderson
  69. X
  70. X              You are granted a license to use this
  71. X              code in your programs, and to adapt it to
  72. X              your particular situation and needs,
  73. X              subject only to the following conditions:
  74. X              1) You must refer to it as the SEAlink
  75. X              protocol, and you must give credit to
  76. X              System Enhancement Associates.  2) If you
  77. X              modify it in such a way that your version
  78. X              cannot converse with the original code as
  79. X              supplied by us, then you should refer to
  80. X              it as "SEAlink derived", or as a
  81. X              "variation of SEAlink", or words to that
  82. X              effect.  In short, we're not asking for
  83. X              any money, but we'd like to get some
  84. X              credit for our work.
  85. X
  86. X--------------------------------------------------------------------------*/
  87. X/*+:EDITS:*/
  88. X/*:08-14-1990-20:40-wht@n4hgf-ecu3.00-flush old edit history */
  89. X
  90. X#include <stdio.h>
  91. X#include <string.h>
  92. X#include <ctype.h>
  93. X#include <signal.h>
  94. X#include <setjmp.h>
  95. X#include <fcntl.h>
  96. X#include <termio.h>
  97. X#include <sys/ioctl.h>
  98. X#include <sys/types.h>
  99. X#include <sys/stat.h>
  100. X#include <time.h>
  101. X#include <sys/timeb.h>
  102. X#include <memory.h>
  103. X#if !defined(NO_SELECT)
  104. X#include <sys/select.h>
  105. X#endif
  106. X
  107. X#include "lint_args.h"
  108. X
  109. X/* Various system constants */
  110. X#define WINDOW        6                    /* maximum size of window */
  111. X#define TIMEOUT    0x0FFF
  112. X#define OFFSET_1980    (time_t)315547200    /* time offset for 1970 <-> 1980 */
  113. X
  114. X/*
  115. X * The section of code that is compiled when NAKEOT is defined is in the
  116. X * original MS-DOS version 1.16 routine.  Its purpose is to send a NAK when
  117. X * an EOT is received during receive_file(), apparently to confirm that this is
  118. X * indeed the end of file.  However, in certain (apparently non - standard)
  119. X * versions of the protocol, it is possible that the program will report an
  120. X * error when in fact there isn't one.  Comment this out at your discretion.
  121. X */
  122. X#define NAKEOT
  123. X
  124. X/* SEAlink block zero data structure */
  125. Xtypedef struct blk0
  126. X{
  127. X    long length;            /* length */
  128. X    time_t secs_since_1980;    /* creation/last mod in secs since 1/1/80 */
  129. X    char filename[17];        /* file name */
  130. X    char sender[15];        /* sending program */
  131. X    char send_no_acks;        /* true if rcvr need not ack */
  132. X    char filler[87];        /* fill to 128 bytes */
  133. X}    BLK0;
  134. X
  135. X/* protocol characters */
  136. X#define SOH    0x01
  137. X#define EOT    0x04
  138. X#define ACK    0x06
  139. X#define NAK    0x15
  140. X#define CAN    0x18
  141. X
  142. X/*  send_file state (sf_state) values */
  143. X#define SFS_GND        0    /* Ground state, ACK or NAK expected */
  144. X#define SFS_ACK        1    /* ACK received */
  145. X#define SFS_NAK        2    /* NAK received */
  146. X#define SFS_ACKW    3    /* ACK, block# received */
  147. X#define SFS_NAKW    4    /* NAK, block# received */
  148. X#define SFS_RGND    5    /* Returning to ground state */
  149. Xint sf_state;
  150. X
  151. Xint allow_slide = 1;    /* sliding windows allowed */
  152. Xint crc_in_use;            /* check type, 1 = CRC, 0 = checksum */
  153. Xchar *dfile = "/tmp/ecuSEA.log";
  154. Xint error_count = 0;    /* total number of errors */
  155. Xint iofd = 0;            /* file descriptor to use */
  156. Xint no_ack_mode = 1;    /* true of ACKs not required */
  157. Xint rf_done = 0;        /* receive file done */
  158. Xint sf_ackw_count;        /* count of sliding ACKs seen */
  159. Xint sf_ackblk;            /* number of last block ACKed */
  160. Xint sf_blknum;            /* number of next block to send */
  161. Xint sf_lastnum;            /* number of last block sent */
  162. Xint sf_nakquan;            /* number of sequential NAKs */
  163. Xint sf_slide;            /* true if sliding window */
  164. X
  165. Xint sending_flag = -1;        /* send == 1, receive == 0, bad usage == -1 */
  166. Xint log_packets = 0;
  167. Xlong rx_char_count = 0;
  168. Xlong tx_char_count = 0;
  169. Xint Filcnt = 0;
  170. Xint npaths = 0;
  171. Xchar curr_dir[256];
  172. Xchar s128[128];
  173. Xunsigned baud_rate;
  174. Xint exit_code;
  175. Xint sent_EOT = 0;
  176. X
  177. Xstruct termio tio;
  178. Xstruct termio tio0;
  179. X
  180. Xjmp_buf    lgetc_timeout_setjmp;
  181. X
  182. X/* CRC16 routine; finish CRC calculation for compare */
  183. X
  184. X#ifdef TABLE_CRC16
  185. X
  186. X/* crctab calculated by Mark G. Mendel,Network Systems Corporation */
  187. Xunsigned short crctab[256] = 
  188. X{
  189. X    0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,
  190. X    0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,
  191. X    0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6,
  192. X    0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,
  193. X    0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,
  194. X    0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,
  195. X    0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4,
  196. X    0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,
  197. X    0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,
  198. X    0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b,
  199. X    0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,
  200. X    0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,
  201. X    0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,
  202. X    0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49,
  203. X    0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,
  204. X    0xFF9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,
  205. X    0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f,
  206. X    0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067,
  207. X    0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,
  208. X    0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,
  209. X    0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d,
  210. X    0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,
  211. X    0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,
  212. X    0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,
  213. X    0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,
  214. X    0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,
  215. X    0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,
  216. X    0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92,
  217. X    0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,
  218. X    0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,
  219. X    0xef1f,0xFF3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,
  220. X    0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0
  221. X};
  222. X
  223. X/*+-------------------------------------------------------------------------
  224. X  updcrc macro derived from article Copyright (C) 1986 Stephen Satchell. 
  225. X  NOTE: First argument must be in range 0 to 255.
  226. X        Second argument is referenced twice.
  227. X  Programmers may incorporate any or all code into their programs, giving
  228. X  proper credit within the source.  Publication of the source routines is
  229. X  permitted so long as proper credit is given to Stephen Satchell,
  230. X  Satchell Evaluations and Chuck Forsberg, Omen Technology.
  231. X--------------------------------------------------------------------------*/
  232. X#define crc_update(ch,crc) ( crctab[((crc >> 8) & 255)] ^ (crc << 8) ^ ch)
  233. X
  234. X#else /* calculated crc */
  235. X
  236. X/*+-------------------------------------------------------------------------
  237. X    crc_update(c,crc)
  238. X--------------------------------------------------------------------------*/
  239. Xunsigned short
  240. Xcrc_update(c,crc)
  241. Xregister c;
  242. Xregister unsigned crc;
  243. X{
  244. Xregister count;
  245. X
  246. X    for(count = 8; --count >= 0;)
  247. X    {
  248. X        if(crc & 0x8000)
  249. X        {
  250. X            crc <<= 1;
  251. X            crc += (((c <<= 1) & 0400) != 0);
  252. X            crc ^= 0x1021;
  253. X        }
  254. X        else 
  255. X        {
  256. X            crc <<= 1;
  257. X            crc += (((c <<= 1) & 0400) != 0);
  258. X        }
  259. X    }
  260. X    return(crc);
  261. X}    /* end of crc_update */
  262. X#endif /* crc calc selection */
  263. X
  264. X/*+-----------------------------------------------------------------------
  265. X    arg_token(parsestr,termchars)
  266. X
  267. XGet next token from string parsestr ((char *)0 on 2nd, 3rd, etc.
  268. Xcalls), where tokens are nonempty strings separated by runs of chars
  269. Xfrom termchars.  Writes nulls into parsestr to end tokens.
  270. Xtermchars need not remain constant from call to call.
  271. X
  272. XTreats multiple occurrences of a termchar as one delimiter (does not
  273. Xallow null fields).
  274. X------------------------------------------------------------------------*/
  275. X#if defined(M_UNIX)
  276. Xstatic char *arg_token_static = (char *)0;
  277. Xchar *arg_token(parsestr,termchars)
  278. Xchar *parsestr;
  279. Xchar *termchars;
  280. X{
  281. Xregister int first = 1;
  282. Xregister char *termptr;
  283. Xregister char *parseptr;
  284. Xchar *token;
  285. X
  286. X    if(parsestr == (char *)0 && arg_token_static == (char *)0)
  287. X        return((char *)0);
  288. X
  289. X    if(parsestr)
  290. X        parseptr = parsestr;
  291. X    else
  292. X       parseptr = arg_token_static;
  293. X
  294. X    while(*parseptr)
  295. X    {
  296. X        if(!strchr(termchars,*parseptr))
  297. X            break;
  298. X        parseptr++;
  299. X    }
  300. X
  301. X    if(!*parseptr)
  302. X    {
  303. X        arg_token_static = (char *)0;
  304. X        return((char *)0);
  305. X    }
  306. X
  307. X    token = parseptr;
  308. X    if(*token == '\'')
  309. X    {
  310. X        token++;
  311. X        parseptr++;
  312. X        while(*parseptr)
  313. X        {
  314. X            if(*parseptr == '\'')
  315. X            {
  316. X                arg_token_static = parseptr + 1;
  317. X                *parseptr = 0;
  318. X                return(token);
  319. X            }
  320. X            parseptr++;
  321. X        }
  322. X        arg_token_static = (char *)0;
  323. X        return(token);
  324. X    }
  325. X    while(*parseptr)
  326. X    {
  327. X        if(strchr(termchars,*parseptr))
  328. X        {
  329. X            *parseptr = 0;
  330. X            arg_token_static = parseptr + 1;
  331. X            while(*arg_token_static)
  332. X            {
  333. X                if(!strchr(termchars,*arg_token_static))
  334. X                    break;
  335. X                arg_token_static++;
  336. X            }
  337. X            return(token);
  338. X        }
  339. X        parseptr++;
  340. X    }
  341. X    arg_token_static = (char *)0;
  342. X    return(token);
  343. X}    /* end of arg_token */
  344. X#endif
  345. X
  346. X/*+-------------------------------------------------------------------------
  347. X    fname_split(cmd,arg,arg_max_quan,&narg)
  348. X--------------------------------------------------------------------------*/
  349. X#if defined(M_UNIX)
  350. Xvoid
  351. Xfname_split(cmd,arg,arg_max_quan,narg_rtn)
  352. Xchar *cmd;
  353. Xchar **arg;
  354. Xint arg_max_quan;
  355. Xint *narg_rtn;
  356. X{
  357. Xregister itmp;
  358. Xregister narg;
  359. X
  360. X    for(itmp = 0; itmp < arg_max_quan; itmp++)
  361. X        arg[itmp] = (char *)0;
  362. X    arg[0] = arg_token(cmd,"/");
  363. X
  364. X    for(narg = 1; narg < arg_max_quan; ++narg)
  365. X    {
  366. X        if((arg[narg] = arg_token((char *)0,"/")) == (char *)0) 
  367. X            break;
  368. X    }
  369. X
  370. X    *narg_rtn = narg;
  371. X
  372. X}    /* end of fname_split */
  373. X#endif
  374. X
  375. X#if defined(M_UNIX)
  376. X#define MAX_COMPONENT_LEN    14
  377. X#define MAX_PATH_COMPONENTS    16
  378. Xstatic char trunc_fname[257];
  379. Xstatic char *trunc_components[MAX_PATH_COMPONENTS];
  380. Xstatic int trunc_components_quan;
  381. Xstatic int trunc_absolute_path;
  382. X#endif
  383. X
  384. X/*+-------------------------------------------------------------------------
  385. X    fname_too_long(fname) - check for any pathname component too long
  386. X--------------------------------------------------------------------------*/
  387. X#if defined(M_UNIX)
  388. Xint
  389. Xfname_too_long(fname)
  390. Xregister char *fname;
  391. X{
  392. Xregister int itmp;
  393. Xregister char **cpptr;
  394. X
  395. X    if(trunc_absolute_path = (*fname == '/'))
  396. X        fname++;
  397. X    strncpy(trunc_fname,fname,sizeof(trunc_fname) - 1);
  398. X    fname_split(trunc_fname,trunc_components,
  399. X        MAX_PATH_COMPONENTS,&trunc_components_quan);
  400. X    itmp = trunc_components_quan;
  401. X    cpptr = trunc_components;
  402. X    while(itmp--)
  403. X    {
  404. X        if(strlen(*cpptr) > MAX_COMPONENT_LEN)
  405. X            return(1);
  406. X        cpptr++;
  407. X    }
  408. X    return(0);
  409. X}    /* end of fname_too_long */
  410. X#endif
  411. X
  412. X/*+-------------------------------------------------------------------------
  413. X    fname_truncated() - build truncated path last checked by fname_too_long
  414. X--------------------------------------------------------------------------*/
  415. X#if defined(M_UNIX)
  416. Xchar *
  417. Xfname_truncated()
  418. X{
  419. Xregister int icomp;
  420. Xchar new_fname[257];
  421. Xregister char *cptr = new_fname;
  422. X
  423. X    if(trunc_absolute_path)
  424. X    {
  425. X        *cptr = '/';
  426. X        *(cptr + 1) = 0;
  427. X    }
  428. X    else
  429. X        *cptr = 0;
  430. X    for(icomp = 0; icomp < trunc_components_quan; icomp++)
  431. X    {
  432. X        if(strlen(trunc_components[icomp]) > MAX_COMPONENT_LEN)
  433. X            *(trunc_components[icomp] + MAX_COMPONENT_LEN) = 0;
  434. X        strcat(cptr,trunc_components[icomp]);
  435. X        if(icomp < trunc_components_quan - 1)
  436. X            strcat(cptr,"/");
  437. X    }
  438. X    strcpy(trunc_fname,cptr);
  439. X    return(trunc_fname);
  440. X
  441. X}    /* end of fname_truncated */
  442. X#endif
  443. X
  444. X/*+-------------------------------------------------------------------------
  445. X    xmit_cancel()
  446. X--------------------------------------------------------------------------*/
  447. Xvoid
  448. Xxmit_cancel()
  449. X{
  450. Xchar *cancel_msg = "\030\030\030\030\030\030\030\030\b\b\b\b\b\b\b\b";
  451. X
  452. X    ioctl(iofd,TCFLSH,(char *)1);
  453. X    write(iofd,cancel_msg,16);
  454. X    tx_char_count += 16;
  455. X    report_str("CANCELling transfer",1);
  456. X    report_last_txhdr("CAN",0);
  457. X
  458. X}    /* end of xmit_cancel */
  459. X
  460. X/*+-------------------------------------------------------------------------
  461. X    xmit_ack(blknum)
  462. X--------------------------------------------------------------------------*/
  463. Xvoid
  464. Xxmit_ack(blknum)
  465. Xregister int blknum;            /* block number */
  466. X{
  467. Xchar s16[16];
  468. X
  469. X    sprintf(s16,"ACK %3d",blknum);
  470. X    report_last_txhdr(s16,0);
  471. X
  472. X    s16[0] = ACK;
  473. X    s16[1] = blknum;            /* block number */
  474. X    s16[2] = blknum ^ 0xFF;    /* block number check */
  475. X    write(iofd,s16,3);
  476. X    tx_char_count += 3;
  477. X}    /* end of xmit_ack */
  478. X
  479. X/*+-------------------------------------------------------------------------
  480. X    xmit_nak(blknum)
  481. X--------------------------------------------------------------------------*/
  482. Xvoid
  483. Xxmit_nak(blknum)
  484. Xregister int blknum;            /* block number */
  485. X{
  486. Xchar s16[16];
  487. X
  488. X    sprintf(s16,"NAK %d",blknum);
  489. X    report_last_txhdr(s16,1);
  490. X
  491. X    if(crc_in_use)
  492. X        s16[0] = 'C';
  493. X    else
  494. X        s16[0] = NAK;
  495. X
  496. X    s16[1] = blknum;            /* block number */
  497. X    s16[2] = blknum ^ 0xFF;    /* block number check */
  498. X    write(iofd,s16,3);
  499. X    tx_char_count += 3;
  500. X
  501. X}    /* end of xmit_nak */
  502. X
  503. X/*+-------------------------------------------------------------------------
  504. X    lgetc_timeout_SIGALRM() - called when alarm is caught by lgetc_timeout
  505. X--------------------------------------------------------------------------*/
  506. X#if defined(NO_SELECT)
  507. Xvoid
  508. Xlgetc_timeout_SIGALRM()
  509. X{
  510. X    longjmp(lgetc_timeout_setjmp,TIMEOUT);
  511. X}    /* end of lgetc_timeout_SIGALRM */
  512. X#endif
  513. X
  514. X/*+-------------------------------------------------------------------------
  515. X    lgetc_timeout(tenths)
  516. X
  517. X reads one character from line unless timeout in tenths passes
  518. X with no receipt.
  519. X--------------------------------------------------------------------------*/
  520. Xunsigned int
  521. Xlgetc_timeout(tenths)
  522. Xint tenths;
  523. X{
  524. X#if defined(NO_SELECT)
  525. Xunsigned char rdchar;
  526. Xlong msec;
  527. Xint seconds;
  528. Xlong nap(long);
  529. X#else
  530. Xint fdmask;
  531. Xstruct timeval tval;
  532. Xunsigned char rdchar;
  533. X#endif
  534. X
  535. X    if(!tenths)
  536. X    {
  537. X        if(!rdchk(iofd))
  538. X            return(TIMEOUT);
  539. X        else
  540. X        {
  541. X            read(iofd,&rdchar,1);
  542. X            rx_char_count++;
  543. X            return((unsigned int)rdchar);
  544. X        }
  545. X    }
  546. X
  547. X#if defined(NO_SELECT)
  548. X
  549. X/* there is a timeout ... if less than 2 secs, nap it out */
  550. X    if(tenths <= 20)
  551. X    {
  552. X        msec = (tenths < 6) ? 60L : (long)tenths * 10;
  553. X        while(msec)
  554. X        {
  555. X            msec -= nap(20L);
  556. X            if(rdchk(iofd))
  557. X            {
  558. X                read(iofd,&rdchar,1);
  559. X                rx_char_count++;
  560. X                return((unsigned int)rdchar);
  561. X            }
  562. X        }
  563. X        report_last_rxhdr("TIMEOUT",0);
  564. X        return(TIMEOUT);
  565. X    }
  566. X
  567. X/* timeout is > 2 seconds use sleep */
  568. X
  569. X    seconds = (tenths / 10) + 1;
  570. X
  571. X    if(setjmp(lgetc_timeout_setjmp))
  572. X    {
  573. X        report_last_rxhdr("TIMEOUT",0);
  574. X        return(TIMEOUT);
  575. X    }
  576. X
  577. X    signal(SIGALRM,lgetc_timeout_SIGALRM);
  578. X    alarm(seconds);
  579. X    while(read(iofd,&rdchar,1) != 1)
  580. X        ;
  581. X    alarm(0);
  582. X    signal(SIGALRM,SIG_DFL);
  583. X
  584. X#else
  585. X
  586. X    if(tenths < 6)
  587. X        tenths = 6;
  588. X    tval.tv_sec = tenths / 10L;
  589. X    tval.tv_usec = (tenths % 10L) * 100000L;
  590. X    fdmask = 1 << iofd;
  591. X    if(select(32,&fdmask,(int *)0,(int *)0,&tval) != 1)
  592. X    {
  593. X        report_last_rxhdr("TIMEOUT",0);
  594. X        return(TIMEOUT);
  595. X    }
  596. X    if((!rdchk(iofd)) || (read(iofd,&rdchar,1) < 0))
  597. X    {
  598. X        report_last_rxhdr("TIMEOUT",0);
  599. X        return(TIMEOUT);
  600. X    }
  601. X
  602. X#endif
  603. X
  604. X    rx_char_count++;
  605. X    return((unsigned int)rdchar);
  606. X
  607. X}    /* end of lgetc_timeout */
  608. X
  609. X/*+-------------------------------------------------------------------------
  610. X    sf_state_text(state)
  611. X--------------------------------------------------------------------------*/
  612. Xchar *
  613. Xsf_state_text(state)
  614. Xregister state;
  615. X{
  616. Xchar unrecog[16];
  617. X
  618. X    switch(state)
  619. X    {
  620. X        case SFS_GND:    return("GND");
  621. X        case SFS_ACK:    return("ACK");
  622. X        case SFS_NAK:    return("NAK");
  623. X        case SFS_ACKW:    return("ACKW");
  624. X        case SFS_NAKW:    return("NAKW");
  625. X        case SFS_RGND:    return("RGND");
  626. X        default:
  627. X            sprintf(unrecog,"SFS_%d",state);
  628. X            return(unrecog);
  629. X    }
  630. X
  631. X}    /* end of sf_state_text */
  632. X
  633. X/*+-------------------------------------------------------------------------
  634. X    set_sf_state(place,new_state)
  635. X--------------------------------------------------------------------------*/
  636. Xvoid
  637. Xset_sf_state(place,new_state)
  638. Xint place;
  639. Xint new_state;
  640. X{
  641. X    if(log_packets)
  642. X    {
  643. X        sprintf(s128,"state from %s to %s (%d)",
  644. X            sf_state_text(sf_state),sf_state_text(new_state),place);
  645. X        report_str(s128,0);
  646. X    }
  647. X    sf_state = new_state;
  648. X}    /* end of set_sf_state */
  649. X
  650. X/*+-------------------------------------------------------------------------
  651. X    wait_for_rcvr_response() - check for ACK or NAK
  652. X sets 'sf_state' to SFS_... value depending on response from file rcvr
  653. X returns 1 if TIMEOUT at state other than ground, else 0
  654. X--------------------------------------------------------------------------*/
  655. Xint
  656. Xwait_for_rcvr_response()
  657. X{
  658. Xint c;                        /* one byte of data */
  659. Xstatic int rawblk = 0;        /* raw block number */
  660. X
  661. X    while((c = lgetc_timeout((sf_state == SFS_GND) ? 0 : 6)) != TIMEOUT)
  662. X    {
  663. X        if(c == CAN)
  664. X        {                                    /* CANcel received? */
  665. X            if((c = lgetc_timeout(20)) == CAN)
  666. X            {
  667. X                sf_nakquan = 11;
  668. X                report_last_rxhdr("CAN",0);    /* error counted at cancel time */
  669. X            }
  670. X            break;
  671. X        }
  672. X        if(sf_state == SFS_ACKW || sf_state == SFS_NAKW)    /* windowed */
  673. X        {
  674. X            sf_slide = 0;                        /* assume this will fail */
  675. X            /* see if we believe the number */
  676. X            if(rawblk == (c ^ 0xFF))
  677. X            {
  678. X                rawblk = sf_blknum - ((sf_blknum - rawblk) & 0xFF);
  679. X                if((rawblk >= 0) && (rawblk <= sf_blknum) &&
  680. X                    (rawblk > (sf_blknum - 128)))
  681. X                {                /* we have sliding window! */
  682. X                    if(sf_state == SFS_ACKW)
  683. X                    {
  684. X                        sf_ackblk = (sf_ackblk > rawblk) ? sf_ackblk : rawblk;
  685. X                        sf_slide = 1;
  686. X                        if(no_ack_mode && (++sf_ackw_count > 10))
  687. X                        {
  688. X                            no_ack_mode = 0;
  689. X                            report_str("Overdrive disengaged",0);
  690. X                        }
  691. X                    }
  692. X                    else 
  693. X                    {
  694. X                        sf_blknum = (rawblk < 0) ? 0 : rawblk;
  695. X                        sf_slide = (sf_nakquan < 4);
  696. X                    }
  697. X                    sprintf(s128,"%s %5d",
  698. X                        (sf_state == SFS_ACKW) ? "ACKW" : "NAKW",rawblk);
  699. X                    report_last_rxhdr(s128,(sf_state != SFS_ACKW) && rawblk);
  700. X                }
  701. X            }
  702. X            set_sf_state(1,SFS_RGND);    /* return to ground state */
  703. X        }
  704. X
  705. X        if(sf_state == SFS_ACK || sf_state == SFS_NAK)
  706. X        {
  707. X            rawblk = c;
  708. X            if(sf_state == SFS_ACK)
  709. X                set_sf_state(2,SFS_ACKW);
  710. X            else
  711. X                set_sf_state(3,SFS_NAKW);
  712. X        }
  713. X
  714. X        if(!sf_slide || sf_state == SFS_GND)
  715. X        {
  716. X            if(c == ACK)
  717. X            {
  718. X                if(!sf_slide)
  719. X                {
  720. X                    sprintf(s128,"ACK %3d",sf_ackblk);
  721. X                    report_last_rxhdr(s128,0);
  722. X                    sf_ackblk++;
  723. X                }
  724. X                set_sf_state(4,SFS_ACK);
  725. X                sf_nakquan = 0;
  726. X            }
  727. X            else if(c == 'C' || c == NAK)
  728. X            {
  729. X                /* if method not determined yet */
  730. X                if(crc_in_use > 1)    /* then do what rcvr wants */
  731. X                {
  732. X                    crc_in_use = (c == 'C');
  733. X                    report_protocol_crc_type(crc_in_use ? "/CRC16" : "/CHK");
  734. X                }
  735. X                ioctl(iofd,TCFLSH,(char *)1);
  736. X                if(!sf_slide)
  737. X                {
  738. X                    sf_blknum = sf_ackblk + 1;
  739. X                    sprintf(s128,"NAK %3d",sf_blknum);
  740. X                    report_last_rxhdr(s128,(!!sf_blknum));
  741. X                }
  742. X                set_sf_state(5,SFS_NAK);
  743. X                sf_nakquan++;
  744. X                if(sf_lastnum)
  745. X                    error_count++;
  746. X            }
  747. X        }
  748. X
  749. X        if(sf_state == SFS_RGND)
  750. X            set_sf_state(6,SFS_GND);
  751. X    }
  752. X    return((sf_state != SFS_GND) && (c == TIMEOUT));
  753. X}    /* end of wait_for_rcvr_response */
  754. X
  755. X/*+-------------------------------------------------------------------------
  756. X    send_comm_block(blk,blknum) - format and transmit block
  757. X--------------------------------------------------------------------------*/
  758. Xint
  759. Xsend_comm_block(blk,blknum)
  760. Xchar *blk;                /* data to be shipped */
  761. Xint blknum;                /* number of block */
  762. X{
  763. Xregister unsigned short rUINT16 = 0;
  764. Xregister int itmp;
  765. Xunsigned char chksum;
  766. Xchar *cptr = blk;
  767. Xchar s3[3];
  768. X
  769. X    s3[0] = SOH;                /* block header */
  770. X    s3[1] = blknum;                /* block number */
  771. X    s3[2] = blknum ^ 0xFF;        /* block number check value */
  772. X
  773. X/* calculate the crc or checksum */
  774. X    itmp = 128;
  775. X    if(crc_in_use)
  776. X    {
  777. X        while(itmp--)
  778. X        {
  779. X            rUINT16 = crc_update(*cptr,rUINT16);
  780. X            cptr++;
  781. X        }
  782. X        rUINT16 = crc_update(0,rUINT16);
  783. X        rUINT16 = crc_update(0,rUINT16);
  784. X    }
  785. X    else 
  786. X    {
  787. X        while(itmp--)
  788. X            rUINT16 += *cptr++;
  789. X    }
  790. X
  791. X/* write the block */
  792. X
  793. X    write(iofd,s3,3);                        /* the header */
  794. X    write(iofd,blk,128);                    /* the block */
  795. X    if(crc_in_use)                            /* the crc or checksum */
  796. X    {
  797. X        s3[0] = rUINT16 >> 8;
  798. X        s3[1] = rUINT16 & 0xFF;
  799. X        write(iofd,s3,2);
  800. X        tx_char_count += 133;
  801. X    }
  802. X    else
  803. X    {
  804. X        chksum = rUINT16;
  805. X        write(iofd,&chksum,1);
  806. X        tx_char_count += 132;
  807. X    }
  808. X
  809. X    return(1);
  810. X}    /* end of send_comm_block */
  811. X
  812. X/*+-------------------------------------------------------------------------
  813. X    send_file_block(fp,blknum) - read a block from file and send it
  814. X--------------------------------------------------------------------------*/
  815. Xvoid
  816. Xsend_file_block(fp,blknum)
  817. XFILE *fp;
  818. Xint blknum;
  819. X{
  820. Xlong fileaddr;
  821. Xchar buf[128];
  822. X
  823. X    fileaddr = (long)(blknum - 1) * 128L;
  824. X    if(blknum != sf_lastnum + 1)
  825. X        fseek(fp,fileaddr,0);    /* move where to */
  826. X    sf_lastnum = blknum;
  827. X    report_txpos(fileaddr);
  828. X
  829. X    memset(buf,0x1A,sizeof(buf));    /* fill buffer with control Zs */
  830. X    fread(buf,1,sizeof(buf),fp);    /* read in some data */
  831. X    send_comm_block(buf,blknum);    /* pump it out to the receiver */
  832. X}    /* end of send_file_block */
  833. X
  834. X/*+-------------------------------------------------------------------------
  835. X    send_file(name) - transmit a file
  836. X--------------------------------------------------------------------------*/
  837. Xint
  838. Xsend_file(name)
  839. Xchar *name;
  840. X{
  841. Xregister int endblk;    /* block number of EOT */
  842. XFILE *fp;                /* file to send */
  843. Xstruct stat fst;
  844. XBLK0 blk0;
  845. Xchar *basename;            /* base filename */
  846. Xchar eot = EOT;
  847. X
  848. X    Filcnt++;
  849. X    if(name && *name)            /* if sending a file */
  850. X    {
  851. X        if((fp = fopen(name,"r")) == NULL)
  852. X        {
  853. X            sprintf(s128,"Cannot open %s",name);
  854. X            report_str(s128,1);
  855. X            exit_code = 253;
  856. X            return(0);
  857. X        }
  858. X
  859. X        memset((char *)&blk0,0,sizeof(blk0)); /* clear out data block */
  860. X
  861. X        stat(name,&fst);    /* get file statistics */
  862. X        blk0.length = (long)fst.st_size;
  863. X
  864. X        /* cnvt time from 1970 base to 1980 */
  865. X        if((blk0.secs_since_1980 = fst.st_mtime-OFFSET_1980) < 0L)
  866. X            blk0.secs_since_1980 = 0;
  867. X
  868. X        if((basename = strrchr(name,'/')) == NULL) /* find basename */
  869. X            strcpy(blk0.filename,name);
  870. X        else 
  871. X        {
  872. X            basename++;
  873. X            strcpy(blk0.filename,basename);
  874. X        }
  875. X
  876. X        strcpy(blk0.sender,"ecusea ");
  877. X        strcat(blk0.sender,revision);
  878. X        blk0.send_no_acks = no_ack_mode;
  879. X
  880. X        endblk = (int)((blk0.length + 127L) / 128L) + 1;
  881. X        report_file_send_open(name,&fst);
  882. X    }
  883. X    else 
  884. X    {
  885. X        endblk = 0;                        /* fake for no file */
  886. X        report_str("sending EOT indication",-1);
  887. X        report_txpos(blk0.length);
  888. X    }
  889. X
  890. X
  891. X    sf_blknum = 1;                        /* set starting state */
  892. X    sf_ackblk = -1;
  893. X    sf_state = SFS_GND;
  894. X    sf_lastnum = 0;
  895. X    sf_slide = 0;
  896. X    sf_nakquan = 0;
  897. X    error_count = 0;
  898. X    sf_ackw_count = 0;
  899. X    crc_in_use = 2;                        /* undetermined */
  900. X
  901. X    while(sf_ackblk < endblk)            /* while not all there yet */
  902. X    {
  903. X        sent_EOT = 0;
  904. X        if(sf_blknum <= sf_ackblk + ((sf_slide && allow_slide) ? WINDOW : 1))
  905. X        {
  906. X            if(sf_blknum < endblk)
  907. X            {
  908. X                if(sf_blknum > 0)
  909. X                {
  910. X                    sprintf(s128,"sending block %d",sf_blknum);
  911. X                    report_last_txhdr(s128,0);
  912. X                    send_file_block(fp,sf_blknum);
  913. X                }
  914. X                else
  915. X                {
  916. X                    sprintf(s128,"sending filename",sf_blknum);
  917. X                    report_last_txhdr(s128,0);
  918. X                    send_comm_block((char *)&blk0,0);
  919. X                    report_txpos(0L);
  920. X                }
  921. X                if(no_ack_mode && sf_slide && allow_slide)
  922. X                    sf_ackblk = sf_blknum;
  923. X            }
  924. X            else if(sf_blknum == endblk)
  925. X            {
  926. X                report_last_txhdr("EOT",0);
  927. X                write(iofd,&eot,1);
  928. X                sent_EOT = 1;
  929. X                nap(500L);
  930. X                tx_char_count++;
  931. X            }
  932. X            sf_blknum++;
  933. X        }
  934. X
  935. X        if(wait_for_rcvr_response() && sent_EOT)
  936. X        {
  937. X            report_str("Receiver did not ACK our EOT",-1);
  938. X            break;
  939. X        }
  940. X
  941. X        if(sf_nakquan > 10)
  942. X            goto CANCEL_TRANSFER;
  943. X    }
  944. X
  945. X    if(endblk)    /* if sending file, not EOT */
  946. X        fclose(fp);
  947. X    return(1);                            /* exit with good status */
  948. X
  949. XCANCEL_TRANSFER:
  950. X    if(endblk)    /* if sending file, not EOT */
  951. X        fclose(fp);
  952. X    xmit_cancel();
  953. X    return(0);                          /* exit with bad status */
  954. X}    /* end of send_file */
  955. X
  956. X/*+-------------------------------------------------------------------------
  957. X    set_utime_1980(filename,secs_since_1980)
  958. X--------------------------------------------------------------------------*/
  959. Xvoid
  960. Xset_utime_1980(filename,secs_since_1980)
  961. Xchar *filename;                        /* file to set stamp on */
  962. Xlong secs_since_1980;
  963. X{
  964. Xtime_t times[2];
  965. Xtime_t time();
  966. X
  967. X    times[0] = time((long *) 0);                /* accessed */
  968. X    times[1] = secs_since_1980 + OFFSET_1980;    /* modified (convert time) */
  969. X    utime(filename,times);
  970. X}    /* end of set_utime_1980 */
  971. X
  972. X/*+-------------------------------------------------------------------------
  973. X    receive_block(buf) - get block from line
  974. Xreturn 0 if good chk/CRC, 1 if bad
  975. X--------------------------------------------------------------------------*/
  976. Xint
  977. Xreceive_block(buf)
  978. Xchar *buf;                /* data buffer */
  979. X{
  980. Xregister unsigned int rdchar;    
  981. Xregister unsigned short rUINT16 = 0;    /* calculated CRC or check value */
  982. Xint itmp;
  983. Xint timeout = no_ack_mode ? 200 : 5;    /* short block timeout */
  984. Xunsigned short rcvd_crc;                /* received CRC or check value */
  985. X
  986. X    itmp = 128;
  987. X    while(itmp--)
  988. X    {
  989. X        if((rdchar = lgetc_timeout(timeout)) == TIMEOUT)
  990. X            return(1);
  991. X        if(crc_in_use)
  992. X            rUINT16 = crc_update(rdchar,rUINT16);
  993. X        else
  994. X            rUINT16 += rdchar;
  995. X        *buf++ = rdchar;
  996. X    }
  997. X
  998. X    if(crc_in_use)
  999. X    {
  1000. X        rUINT16 = crc_update(0,rUINT16);
  1001. X        rUINT16 = crc_update(0,rUINT16);
  1002. X        rdchar = lgetc_timeout(timeout);
  1003. X        rcvd_crc = (rdchar << 8) | lgetc_timeout(timeout);
  1004. X    }
  1005. X    else 
  1006. X    {
  1007. X        rUINT16 &= 0xFF;
  1008. X        rcvd_crc = lgetc_timeout(timeout) & 0xFF;
  1009. X    }
  1010. X
  1011. X    if(rUINT16 != rcvd_crc)
  1012. X    {
  1013. X        sprintf(s128,"bad %s calc=%04x rcvd=%04x",
  1014. X            crc_in_use ? "CRC" : "checksum",rcvd_crc,rUINT16);
  1015. X        report_str(s128,-1);
  1016. X    }
  1017. X    return(rUINT16 != rcvd_crc);
  1018. X}    /* end of receive_block */
  1019. X
  1020. X/*+-------------------------------------------------------------------------
  1021. X    receive_file()
  1022. X--------------------------------------------------------------------------*/
  1023. Xchar *
  1024. Xreceive_file()
  1025. X{
  1026. Xint rdchar;            /* received character */
  1027. Xint tries;            /* retry counter */
  1028. Xint blknum;            /* desired block number */
  1029. Xint inblk;            /* this block number */
  1030. XFILE *fp;
  1031. Xchar buf[128];        /* data buffer */
  1032. Xchar tmpname[100];        /* name of temporary file */
  1033. Xstatic char outname[100];    /* name of final file */
  1034. XBLK0 blk0;        /* file header data storage */
  1035. Xint endblk;            /* block number of EOT, if known */
  1036. Xlong left;            /* bytes left to output */
  1037. Xint itmp;                /* index */
  1038. Xint cnvrt;            /* flag -- convert filename? */
  1039. Xchar *onp;            /* use to convert filename to l / rdchar */
  1040. Xchar *basename;        /* base filename */
  1041. Xlong ftell();
  1042. X
  1043. X    *outname = '\0';        /* get name from transmitter */
  1044. X    cnvrt = 1;        /* convert to local is necessary */
  1045. X    sprintf(tmpname,"./SEA%05d.tmp",getpid());    /* use a unique temp filename */
  1046. X
  1047. X    if(!(fp = fopen(tmpname,"w")))
  1048. X    {    /* open temporary file */
  1049. X        sprintf(s128,"Cannot create temp file %s\n",tmpname);
  1050. X        report_str(s128,0);
  1051. X        xmit_cancel();
  1052. X        return(NULL);
  1053. X    }
  1054. X
  1055. X    blknum = 0;
  1056. X    tries = -10;                /* kludge for first time around */
  1057. X    crc_in_use = 1;                /* try for CRC error checking */
  1058. X    error_count = 0;            /* no errors yet */
  1059. X    endblk = 0;                    /* we don't know the size yet */
  1060. X    no_ack_mode = 0;            /* we don't know about this yet */
  1061. X    memset((char *)&blk0,0,sizeof(blk0));    /* or much of anything else */
  1062. X    report_protocol_crc_type("/CRC16");
  1063. X
  1064. XSEND_NAK:                /* we got a bad block */
  1065. X    if(blknum > 1)
  1066. X    {
  1067. X        error_count++;
  1068. X        report_str("bad block",1);
  1069. X    }
  1070. X    if(++tries > 10)
  1071. X        goto CANCEL_TRANSFER;
  1072. X    if(tries == 0)            /* if CRC isn't going */
  1073. X    {
  1074. X        crc_in_use = 0;        /* then give checksum a try */
  1075. X        report_protocol_crc_type("/CHK");
  1076. X    }
  1077. X
  1078. X    xmit_nak(blknum);        /* send the NAK */
  1079. X    if(no_ack_mode && error_count > 20)
  1080. X    {    /* if no_ack_mode mode isn't working */
  1081. X        no_ack_mode = 0;        /* then shut it off */
  1082. X        report_str("Overdrive disengaged",0);
  1083. X    }
  1084. X
  1085. XRECEIVE_NEXT_BLOCK:                /* start of "get a block" */
  1086. X    report_rxpos(ftell(fp));
  1087. X    while((rdchar = lgetc_timeout(30)) != TIMEOUT)
  1088. X    {
  1089. X        if(rdchar == CAN)
  1090. X        {
  1091. X            if((rdchar = lgetc_timeout(30)) == CAN)
  1092. X            {
  1093. X                xmit_cancel();
  1094. X                return(NULL);
  1095. X            }
  1096. X            break;
  1097. X        }
  1098. X        if(rdchar == EOT)
  1099. X        {
  1100. X            if(!endblk || endblk == blknum)
  1101. X                goto RECEIVE_EOT_SEEN;
  1102. X        }
  1103. X        else if(rdchar == SOH)
  1104. X        {
  1105. X            if((inblk = lgetc_timeout(5)) == TIMEOUT)
  1106. X                goto SEND_NAK;
  1107. X            if(lgetc_timeout(5) == (inblk ^ 0xFF))
  1108. X            {
  1109. X                sprintf(s128,"receiving %d",inblk);
  1110. X                report_last_rxhdr(s128,0);
  1111. X                goto GOT_START_OF_BLOCK;    /* we found a start */
  1112. X            }
  1113. X        }
  1114. X    }
  1115. X    goto SEND_NAK;
  1116. X
  1117. XGOT_START_OF_BLOCK:                /* start of block detected */
  1118. X    rdchar = blknum & 0xFF;
  1119. X    if(inblk == 0 && blknum <= 1)
  1120. X    {    /* if this is the header */
  1121. X        if(receive_block((char *)&blk0))
  1122. X            goto SEND_NAK;        /* bad header block */
  1123. X        else 
  1124. X        {
  1125. X            xmit_ack(inblk);    /* ack the header */
  1126. X
  1127. X#if defined(M_UNIX)
  1128. X            if(fname_too_long(blk0.filename))
  1129. X            {
  1130. X                strcpy(s128,"truncated: ");
  1131. X                strncat(s128,blk0.filename,sizeof(s128) - 12);
  1132. X                report_str(s128,-1);
  1133. X                strcpy(outname,fname_truncated());
  1134. X            }
  1135. X            else
  1136. X#endif
  1137. X                strcpy(outname,blk0.filename);
  1138. X            report_file_rcv_started(outname,blk0.length,
  1139. X                blk0.secs_since_1980 + OFFSET_1980);
  1140. X            if(left = blk0.length)    /* length to transfer */
  1141. X                endblk=(int)((left + 127L)/128L)+1;
  1142. X            if(no_ack_mode != blk0.send_no_acks)
  1143. X            {
  1144. X                sprintf(s128,"Overdrive %sengaged",
  1145. X                    (blk0.send_no_acks) ? "" : "dis");
  1146. X                report_str(s128,0);
  1147. X            }
  1148. X            no_ack_mode = blk0.send_no_acks;
  1149. X            blknum = 1;    /* now we want first data block */
  1150. X            goto RECEIVE_NEXT_BLOCK;
  1151. X        }
  1152. X    }
  1153. X
  1154. X    if(inblk == rdchar)
  1155. X    {            /* if this is the one we want */
  1156. X        if(!receive_block(buf))
  1157. X        {        /* else if we get it okay */
  1158. X            if(!no_ack_mode)        /* if we're sending ACKs */
  1159. X                xmit_ack(inblk);    /* then ACK the data */
  1160. X            for(itmp = 0; itmp < 128; itmp++)
  1161. X            {
  1162. X                if(endblk)
  1163. X                {    /* limit file size if known */
  1164. X                    if(!left)
  1165. X                        break;
  1166. X                    left--;
  1167. X                }
  1168. X                if(fputc(buf[itmp],fp) == EOF)
  1169. X                {
  1170. X                    report_str("FILE WRITE ERROR",0);
  1171. X                    goto CANCEL_TRANSFER;
  1172. X                }
  1173. X            }
  1174. X            tries = 0;        /* reset try count */
  1175. X            blknum++;        /* we want the next block */
  1176. X            goto RECEIVE_NEXT_BLOCK;
  1177. X        }
  1178. X        goto SEND_NAK;        /* ask for a resend */
  1179. X    }
  1180. X
  1181. X    if(inblk < rdchar || inblk > rdchar + 100)
  1182. X    {    /* if resending what we have */
  1183. X        receive_block(buf);            /* ignore it */
  1184. X        xmit_ack(inblk);            /* but ack it */
  1185. X    }
  1186. X    goto RECEIVE_NEXT_BLOCK;        /* else if running ahead */
  1187. X
  1188. XRECEIVE_EOT_SEEN:
  1189. X#ifdef NAKEOT
  1190. X    xmit_nak(blknum);                /* NAK the EOT, make sure */
  1191. X    if(lgetc_timeout(20) != EOT)    /* we're all done */
  1192. X        goto SEND_NAK;
  1193. X#endif /* NAKEOT */
  1194. X    xmit_ack(blknum);                /* ACK it and clean up */
  1195. X    report_last_rxhdr("EOT",0);
  1196. X    if(blknum > 1)
  1197. X    {                /* if we really got anything */
  1198. X        fclose(fp);
  1199. X        unlink(outname);        /* rename temp to proper name */
  1200. X        for(onp = outname;cnvrt && *onp;onp++)
  1201. X            /* find out if there's lower- */
  1202. X            if(islower(*onp))    /* case letters filename */
  1203. X                cnvrt = 0;    /*  there are, don't convert */
  1204. X        if(cnvrt)            /* if there aren't, make all */
  1205. X            for(onp = outname;*onp;onp++)    /* into uppercase */
  1206. X                *onp = tolower(*onp);
  1207. X        if(link(tmpname,outname) == 0)
  1208. X            unlink(tmpname);
  1209. X        if(blk0.secs_since_1980)        /* set stamp, if known */
  1210. X            set_utime_1980(outname,blk0.secs_since_1980);
  1211. X        return(outname);
  1212. X    }
  1213. X    else 
  1214. X    {                /* else no real file */
  1215. X        fclose(fp);
  1216. X        unlink(tmpname);        /* discard empty file */
  1217. X        report_str("end of transfer",0);
  1218. X        rf_done = 1;
  1219. X        return(NULL);
  1220. X    }
  1221. X
  1222. XCANCEL_TRANSFER:
  1223. X    fclose(fp);
  1224. X    xmit_cancel();
  1225. X    rf_done = 2;
  1226. X    return(NULL);
  1227. X}    /* end of receive_file */
  1228. X
  1229. X/*+-------------------------------------------------------------------------
  1230. X    cancel_transaction(sig)
  1231. X--------------------------------------------------------------------------*/
  1232. Xcancel_transaction(sig)
  1233. Xint sig;
  1234. X{
  1235. X    xmit_cancel();
  1236. X    sprintf(s128,"signal %d ... exiting",sig);
  1237. X    report_str(s128,1);
  1238. X/*
  1239. X    report_rx_ind(0);
  1240. X    report_tx_ind(0);
  1241. X*/
  1242. X    report_uninit();
  1243. X    if(sig == SIGQUIT)
  1244. X        abort();
  1245. X    exit(128+sig);
  1246. X}    /* end of cancel_transaction */
  1247. X
  1248. X/*+-------------------------------------------------------------------------
  1249. X    getspeed(code)
  1250. X--------------------------------------------------------------------------*/
  1251. Xstruct B_to_baud { unsigned baud; int B_code; };
  1252. Xunsigned
  1253. Xgetspeed(code)
  1254. Xint code;
  1255. X{
  1256. Xregister itmp;
  1257. Xstatic struct B_to_baud speeds[] = 
  1258. X{
  1259. X 50, B50, 75, B75, 110, B110, 300, B300, 600, B600, 1200, B1200,
  1260. X 2400, B2400, 4800, B4800, 9600, B9600, 19200, EXTA, 38400, EXTB, 0
  1261. X};
  1262. X
  1263. X    code &= CBAUD;
  1264. X    for(itmp = 0; speeds[itmp].baud; itmp++)
  1265. X        if(speeds[itmp].B_code == code)
  1266. X            return(speeds[itmp].baud);
  1267. X    return(38400);    /* Assume fifo if ioctl failed */
  1268. X}    /* end of getspeed */
  1269. X
  1270. X/*+-------------------------------------------------------------------------
  1271. X    main(argc,argv,envp)
  1272. X--------------------------------------------------------------------------*/
  1273. Xmain(argc,argv,envp)
  1274. Xint argc;
  1275. Xchar **argv;
  1276. Xchar **envp;
  1277. X{
  1278. Xint ipaths;
  1279. Xint ok;
  1280. X#define MAX_PATHS 512
  1281. Xchar *paths[MAX_PATHS];
  1282. Xchar **ppaths = paths;
  1283. Xchar *cptr;
  1284. Xchar **gargv = argv;
  1285. Xint gargc = argc;
  1286. X
  1287. X    exit_code = 254;
  1288. X    while(--argc)
  1289. X    {
  1290. X        cptr = *++argv;
  1291. X        if(*cptr == '-')
  1292. X        {
  1293. X            cptr++;
  1294. X            switch(*cptr++)
  1295. X            {
  1296. X            case ',':
  1297. X                log_packets = 1;
  1298. X                break;
  1299. X            case '/':
  1300. X                if(--argc < 1)
  1301. X                    exit(255);
  1302. X                strcpy(curr_dir,*++argv);
  1303. X                break;
  1304. X            case '.':
  1305. X                if(--argc < 1)
  1306. X                    exit(255);
  1307. X                iofd = atoi(*++argv);
  1308. X                break;
  1309. X            case 'r':
  1310. X                sending_flag = 0;
  1311. X                break;
  1312. X            case 's':
  1313. X                sending_flag = 1;
  1314. X            }
  1315. X        }
  1316. X        else if(argc > 0)
  1317. X        {
  1318. X            if(npaths < MAX_PATHS)
  1319. X            {
  1320. X                *ppaths++ = cptr;
  1321. X                npaths++;
  1322. X            }
  1323. X            else
  1324. X            {
  1325. X                printf("too many filenames to send\n");
  1326. X                exit(255);
  1327. X            }
  1328. X        }
  1329. X    }
  1330. X
  1331. X    if(sending_flag == -1)
  1332. X    {
  1333. X        printf("no -r or -s\n");
  1334. X        exit(255);
  1335. X    }
  1336. X
  1337. X    if((npaths < 1) && sending_flag)
  1338. X        exit(253);
  1339. X
  1340. X    if(npaths && !sending_flag)
  1341. X        exit(255);
  1342. X
  1343. X    if(log_packets)
  1344. X    {
  1345. X    char log_packets_name[64];
  1346. X    FILE *ftmp;
  1347. X    int iargv;
  1348. X        sprintf(log_packets_name,"/tmp/sea%05d.plog",getpid());
  1349. X        unlink(log_packets_name);
  1350. X        ftmp = fopen(log_packets_name,"w");
  1351. X        fclose(ftmp);
  1352. X        log_packets = open(log_packets_name,O_WRONLY,0644);
  1353. X        if(log_packets < 0)
  1354. X            log_packets = 0;
  1355. X        else
  1356. X        {
  1357. X            write(log_packets,"exec: ",6);
  1358. X            for(iargv = 0; iargv < gargc; iargv++)
  1359. X            {
  1360. X                write(log_packets,gargv[iargv],strlen(gargv[iargv]));
  1361. X                write(log_packets," ",1);
  1362. X            }
  1363. X            write(log_packets,"\n",1);
  1364. X        }
  1365. X    }
  1366. X
  1367. X    sprintf(s128,"ecusea %s",revision);
  1368. X    report_init(s128);
  1369. X    signal(SIGHUP,cancel_transaction);
  1370. X    signal(SIGQUIT,cancel_transaction);
  1371. X    signal(SIGINT,cancel_transaction);
  1372. X    signal(SIGTERM,cancel_transaction);
  1373. X
  1374. X    ioctl(iofd,TCGETA,&tio0);
  1375. X    tio = tio0;
  1376. X
  1377. X    tio.c_oflag = 0;
  1378. X    tio.c_cflag &= ~PARENB;
  1379. X    tio.c_cflag &= ~CSIZE;
  1380. X    tio.c_cflag |= CS8;
  1381. X
  1382. X    baud_rate = getspeed(tio.c_cflag);
  1383. X    ioctl(iofd,TCSETA,&tio);
  1384. X    report_line(baud_rate,"RAW");
  1385. X
  1386. X    switch(sending_flag)
  1387. X    {
  1388. X        case 0:                /* receive files */
  1389. X            while(receive_file() != NULL)
  1390. X                nap(1000L);
  1391. X            ok = (rf_done == 1);
  1392. X            break;
  1393. X
  1394. X        case 1:                /* send files */
  1395. X            ipaths = 0;
  1396. X            while(ipaths < npaths)
  1397. X            {
  1398. X                if(!(ok = send_file(paths[ipaths])))
  1399. X                    break;
  1400. X                nap(1000L);
  1401. X                ipaths++;
  1402. X            }
  1403. X            if(ok)        /* no errors, send end marker */
  1404. X                send_file("");
  1405. X            report_str("end of transfer",0);
  1406. X            break;
  1407. X    }
  1408. X
  1409. X    ioctl(iofd,TCSETA,&tio0);
  1410. X    report_line(baud_rate,"NORMAL");
  1411. X    report_uninit();
  1412. X    exit(ok ? 0 : exit_code);    /* and return error status */
  1413. X
  1414. X}    /* end of main */
  1415. X
  1416. SHAR_EOF
  1417. $TOUCH -am 0814204290 'sea/ecusea.c' &&
  1418. chmod 0644 sea/ecusea.c ||
  1419. echo 'restore of sea/ecusea.c failed'
  1420. Wc_c="`wc -c < 'sea/ecusea.c'`"
  1421. test 35194 -eq "$Wc_c" ||
  1422.     echo 'sea/ecusea.c: original size 35194, current size' "$Wc_c"
  1423. # ============= sea/lint_args.h ==============
  1424. echo 'x - extracting sea/lint_args.h (Text)'
  1425. sed 's/^X//' << 'SHAR_EOF' > 'sea/lint_args.h' &&
  1426. X/*+-----------------------------------------------------------------------
  1427. X    lint_args.h
  1428. X------------------------------------------------------------------------*/
  1429. X/*+:EDITS:*/
  1430. X/*:08-14-1990-21:03-afterlint-creation */
  1431. X
  1432. X#ifndef BUILDING_LINT_ARGS
  1433. X#ifdef LINT_ARGS
  1434. X
  1435. X/* ecusea.c */
  1436. X/* void send_file_block(struct UNNAMED *fp,int blknum); */
  1437. Xchar *arg_token(char *,char *);
  1438. Xchar *fname_truncated(void );
  1439. Xchar *receive_file(void );
  1440. Xchar *sf_state_text(int );
  1441. Xint cancel_transaction(int );
  1442. Xint fname_too_long(char *);
  1443. Xint main(int ,char **,char **);
  1444. Xint receive_block(char *);
  1445. Xint send_comm_block(char *,int );
  1446. Xint send_file(char *);
  1447. Xint wait_for_rcvr_response(void );
  1448. Xunsigned int getspeed(int );
  1449. Xunsigned int lgetc_timeout(int );
  1450. Xunsigned short crc_update(int ,unsigned int );
  1451. Xvoid fname_split(char *,char **,int ,int *);
  1452. Xvoid lgetc_timeout_SIGALRM(void );
  1453. Xvoid set_sf_state(int ,int );
  1454. Xvoid set_utime_1980(char *,long );
  1455. Xvoid xmit_ack(int );
  1456. Xvoid xmit_cancel(void );
  1457. Xvoid xmit_nak(int );
  1458. X/* scurses.c */
  1459. Xchar *get_elapsed_time(long );
  1460. Xchar *get_tod(int ,char *);
  1461. Xint clear_area(struct _win_st *,int ,int ,int );
  1462. Xint clear_area_char(struct _win_st *,int ,int ,int ,char );
  1463. Xint report_error_count(void );
  1464. Xint report_file_byte_io(long );
  1465. Xint report_file_open_length(long );
  1466. Xint report_file_rcv_started(char *,long ,long );
  1467. Xint report_protocol_crc_type(char *);
  1468. Xint report_rx_tx_count(void );
  1469. Xvoid report_file_close(void );
  1470. Xvoid report_file_open_tod(void );
  1471. Xvoid report_file_send_open(char *,struct stat *);
  1472. Xvoid report_init(char *);
  1473. Xvoid report_last_rxhdr(char *,int );
  1474. Xvoid report_last_txhdr(char *,int );
  1475. Xvoid report_line(unsigned int ,char *);
  1476. Xvoid report_rx_ind(int );
  1477. Xvoid report_rxpos(long );
  1478. Xvoid report_str(char *,int );
  1479. Xvoid report_top_line(char *);
  1480. Xvoid report_transaction(char *);
  1481. Xvoid report_tx_ind(int );
  1482. Xvoid report_txpos(long );
  1483. Xvoid report_uninit(void );
  1484. X
  1485. X#else        /* compiler doesn't know about prototyping */
  1486. X
  1487. X/* ecusea.c */
  1488. X/* void send_file_block();
  1489. Xchar *arg_token();
  1490. Xchar *fname_truncated();
  1491. Xchar *receive_file();
  1492. Xchar *sf_state_text();
  1493. Xunsigned int getspeed();
  1494. Xunsigned int lgetc_timeout();
  1495. Xunsigned short crc_update();
  1496. Xvoid fname_split();
  1497. Xvoid lgetc_timeout_SIGALRM();
  1498. Xvoid set_sf_state();
  1499. Xvoid set_utime_1980();
  1500. Xvoid xmit_ack();
  1501. Xvoid xmit_cancel();
  1502. Xvoid xmit_nak();
  1503. X/* scurses.c */
  1504. Xchar *get_elapsed_time();
  1505. Xchar *get_tod();
  1506. Xvoid report_file_close();
  1507. Xvoid report_file_open_tod();
  1508. Xvoid report_file_send_open();
  1509. Xvoid report_init();
  1510. Xvoid report_last_rxhdr();
  1511. Xvoid report_last_txhdr();
  1512. Xvoid report_line();
  1513. Xvoid report_rx_ind();
  1514. Xvoid report_rxpos();
  1515. Xvoid report_str();
  1516. Xvoid report_top_line();
  1517. Xvoid report_transaction();
  1518. Xvoid report_tx_ind();
  1519. Xvoid report_txpos();
  1520. Xvoid report_uninit();
  1521. X
  1522. X#endif /* LINT_ARGS */
  1523. X#endif /* BUILDING_LINT_ARGS */
  1524. X
  1525. X/* end of lint_args.h */
  1526. SHAR_EOF
  1527. $TOUCH -am 0919224990 'sea/lint_args.h' &&
  1528. chmod 0644 sea/lint_args.h ||
  1529. echo 'restore of sea/lint_args.h failed'
  1530. Wc_c="`wc -c < 'sea/lint_args.h'`"
  1531. test 2779 -eq "$Wc_c" ||
  1532.     echo 'sea/lint_args.h: original size 2779, current size' "$Wc_c"
  1533. true || echo 'restore of sea/scurses.c failed'
  1534. echo End of part 23, continue with part 24
  1535. exit 0
  1536. --------------------------------------------------------------------
  1537. Warren Tucker, TuckerWare emory!n4hgf!wht or wht@n4hgf.Mt-Park.GA.US
  1538. Hacker Extraordinaire  d' async PADs,  pods,  proteins and protocols
  1539.  
  1540. exit 0 # Just in case...
  1541. -- 
  1542. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1543. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1544. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1545. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1546.