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

  1. From: wht@n4hgf.uucp (Warren Tucker)
  2. Newsgroups: comp.sources.misc
  3. Subject: v16i043:  ECU async comm package rev 3.0, Part19/35
  4. Message-ID: <1991Jan6.052351.28255@sparky.IMD.Sterling.COM>
  5. Date: 6 Jan 91 05:23:51 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: df3a6f60 694ef9e3 76392c50 06ed8b55
  8.  
  9. Submitted-by: wht@n4hgf.uucp (Warren Tucker)
  10. Posting-number: Volume 16, Issue 43
  11. Archive-name: ecu3/part19
  12.  
  13. ---- Cut Here and feed the following to sh ----
  14. #!/bin/sh
  15. # This is part 19 of ecu3
  16. if touch 2>&1 | fgrep 'amc' > /dev/null
  17.  then TOUCH=touch
  18.  else TOUCH=true
  19. fi
  20. # ============= z/ecurz.c ==============
  21. if test ! -d 'z'; then
  22.     echo 'x - creating directory z'
  23.     mkdir 'z'
  24. fi
  25. echo 'x - extracting z/ecurz.c (Text)'
  26. sed 's/^X//' << 'SHAR_EOF' > 'z/ecurz.c' &&
  27. Xchar *numeric_revision = "ecurz 3.04";
  28. X/*+-------------------------------------------------------------------------
  29. X    ecurz.c - X/Y/ZMODEM receive program
  30. X  Derived from public domain source by Chuck Forsberg, Omen Technologies
  31. X  Adaptation for ecu 1989 wht@n4hgf.Mt-Park.GA.US
  32. X
  33. X  Defined functions:
  34. X    SIGALRM_handler()
  35. X    arg_token(parsestr,termchars)
  36. X    bye_bye(sig)
  37. X    cancel_transaction(sig)
  38. X    close_and_report()
  39. X    flushline()
  40. X    fname_split(cmd,arg,arg_max_quan,narg_rtn)
  41. X    fname_too_long(fname)
  42. X    fname_truncated()
  43. X    getfree()
  44. X    isanylc(str)
  45. X    main(argc,argv,envp)
  46. X    make_dirs(pathname)
  47. X    mkdir(dpath,dmode)
  48. X    procheader(name)
  49. X    purgeline()
  50. X    readline(timeout)
  51. X    rzfile()
  52. X    rzfiles()
  53. X    send_ZFIN_and_exit()
  54. X    send_cancel(error)
  55. X    sendline(c)
  56. X    substr(str,token)
  57. X    sys2(shellcmd)
  58. X    tryz()
  59. X    uncaps(str)
  60. X    usage(fail_reason)
  61. X    wcgetsec(rxbuf,maxtime)
  62. X    wcreceive(argc,argp)
  63. X    wcrx()
  64. X    wcrxpn(rpn)
  65. X    write_sec_to_disk(buf,n)
  66. X    xsendline(c)
  67. X
  68. X      Usage:    ecurz -Z [-abeuy]    (ZMODEM)
  69. X                ecurz -Y [-abuy]     (YMODEM)
  70. X                ecurz -X [-abc] file (XMODEM or XMODEM-1k)
  71. X
  72. X          -a ASCII transfer (strip CR)
  73. X          -b Binary transfer for all files
  74. X          -c Use 16 bit CRC (XMODEM)
  75. X          -e Escape control characters  (ZMODEM)
  76. X          -p protect local files (ZMODEM)
  77. X          -t <tenths> rx timeout seconds
  78. X          -+ force append
  79. X          -u convert uppercase filenames to lower case
  80. X          -y Yes, clobber existing file if any
  81. X          -. line fd to use
  82. X          -, log protocol packets
  83. X
  84. X--------------------------------------------------------------------------*/
  85. X/*+:EDITS:*/
  86. X/*:12-18-1990-21:26-wht@n4hgf-better output control */
  87. X/*:10-04-1990-14:01-wht@n4hgf-add file finish warning for me */
  88. X/*:09-19-1990-19:36-wht@n4hgf-ecu_log_event now gets pid for log from caller */
  89. X/*:08-23-1990-14:14-wht@n4hgf-sending ZACK was erroneously counted as error */
  90. X/*:08-14-1990-20:40-wht@n4hgf-ecu3.00-flush old edit history */
  91. X
  92. X#include <stdio.h>
  93. X#include <signal.h>
  94. X#include <setjmp.h>
  95. X#include <ctype.h>
  96. X#include <errno.h>
  97. X#include <fcntl.h>
  98. X#include "zmodem.h"
  99. X#include "zlint.h"
  100. X
  101. Xchar *strrchr();
  102. X
  103. X#if defined(M_UNIX)
  104. Xchar *fname_truncated();
  105. X#endif
  106. X
  107. Xextern unsigned short crctab[];
  108. Xextern unsigned long total_data_chars_xfered; /* zcurses.c */
  109. Xextern int force_no_curses;
  110. Xextern int errno;
  111. Xextern char *sys_errlist[];
  112. Xextern char Attn[];        /* Attention string rx sends to tx on err */
  113. Xextern int Crc32;        /* Display flag indicating 32 bit CRC being received */
  114. Xextern int Rxcount;        /* Count of data bytes received */
  115. Xextern char Rxhdr[];    /* Received header */
  116. Xextern char Txhdr[];    /* Transmitted header */
  117. Xextern int Rxtimeout;    /* Tenths of seconds to wait for something */
  118. Xextern char s256[];
  119. X
  120. X/* Max value for VMIN_COUNT is 255.  A larger value reduces system
  121. Xoverhead but may evoke kernel bugs.  133 corresponds to an XMODEM/CRC
  122. Xsector */
  123. X#if !defined(VMIN_COUNT)
  124. X#define VMIN_COUNT 133
  125. X#endif
  126. Xunsigned char vmin_count = VMIN_COUNT;
  127. Xint Readnum = VMIN_COUNT;    /* num bytes to ask for in read() from modem */
  128. X
  129. X#define DEFBYTL 2000000000L    /* default rx file size */
  130. X#define RETRYMAX 5
  131. X
  132. XFILE *fout;
  133. Xchar Lzmanag;        /* Local file management request */
  134. Xchar Pathname[PATHLEN];
  135. Xchar curr_dir[256];
  136. Xchar linbuf[VMIN_COUNT];
  137. Xchar s128[128];
  138. Xchar secbuf[1025];
  139. Xchar zconv;                /* ZMODEM file conversion request */
  140. Xchar zmanag;            /* ZMODEM file management request */
  141. Xchar ztrans;            /* ZMODEM file transport request */
  142. Xint Batch=0;
  143. Xint Blklen;                /* record length of received packets */
  144. Xint Crcflg;
  145. Xint Eofseen;            /* indicates cpm eof (^Z) has been received */
  146. Xint Filcnt=0;            /* count of number of files opened */
  147. Xint Filemode;            /* Unix style mode for incoming file */
  148. Xint Firstsec;
  149. Xint Lastrx;
  150. Xint Lleft=0;            /* number of characters in linbuf */
  151. Xint MakeLCPathname=1;    /* make received pathname lower case */
  152. Xint Nozmodem = 0;        /* If invoked as "rb" */
  153. Xint Rxascii=0;            /* receive files in ascii (translate) mode */
  154. Xint Rxbinary=0;            /* receive all files in bin mode */
  155. Xint Rxclob=0;            /* Clobber existing file */
  156. Xint Thisbinary;            /* current file is to be received in bin mode */
  157. Xint Twostop = 0;        /* use two stop bits */
  158. Xint Zctlesc;            /* Encode control characters */
  159. Xint Zmodem=0;            /* ZMODEM protocol requested */
  160. Xint Zrwindow = 1400;    /* RX window size (controls garbage count) */
  161. Xint ecusz_flag = 0;
  162. Xint skip_count = 0;        /* skipped files */
  163. Xint errors;
  164. Xint iofd = 0;
  165. Xint force_no_curses = 0;
  166. Xint can_on_eof = 0;
  167. Xint log_packets = 0;
  168. Xint npats = 0;
  169. Xint oldBlklen = -1;        /* last block length */
  170. Xint this_file_errors = 0;
  171. Xint tryzhdrtype=ZRINIT;    /* Header type to send corresponding to Last rx close */
  172. Xjmp_buf tohere;            /* For the interrupt on RX timeout */
  173. Xlong Bytesleft;            /* number of bytes of incoming file left */
  174. Xlong Modtime;            /* Unix style mod time for incoming file */
  175. Xlong TotalToReceive = 0L;
  176. Xlong rx_char_count = 0L;
  177. Xlong tx_char_count = 0L;
  178. Xstruct stat fout_stat;
  179. Xtime_t timep[2];
  180. Xunsigned Baudrate;
  181. Xunsigned long this_file_length;
  182. Xint required_type = 0;
  183. Xchar *bottom_label = (char *)0;
  184. X
  185. X/*+-----------------------------------------------------------------------
  186. X    arg_token(parsestr,termchars)
  187. X
  188. XGet next token from string parsestr ((char *)0 on 2nd, 3rd, etc.
  189. Xcalls), where tokens are nonempty strings separated by runs of chars
  190. Xfrom termchars.  Writes nulls into parsestr to end tokens.
  191. Xtermchars need not remain constant from call to call.
  192. X
  193. XTreats multiple occurrences of a termchar as one delimiter (does not
  194. Xallow null fields).
  195. X------------------------------------------------------------------------*/
  196. X#if defined(M_UNIX)
  197. Xstatic char *arg_token_static = (char *)0;
  198. Xchar *arg_token(parsestr,termchars)
  199. Xchar *parsestr;
  200. Xchar *termchars;
  201. X{
  202. Xregister int first = 1;
  203. Xregister char *termptr;
  204. Xregister char *parseptr;
  205. Xchar *token;
  206. X
  207. X    if(parsestr == (char *)0 && arg_token_static == (char *)0)
  208. X        return((char *)0);
  209. X
  210. X    if(parsestr)
  211. X        parseptr = parsestr;
  212. X    else
  213. X       parseptr = arg_token_static;
  214. X
  215. X    while(*parseptr)
  216. X    {
  217. X        if(!strchr(termchars,*parseptr))
  218. X            break;
  219. X        parseptr++;
  220. X    }
  221. X
  222. X    if(!*parseptr)
  223. X    {
  224. X        arg_token_static = (char *)0;
  225. X        return((char *)0);
  226. X    }
  227. X
  228. X    token = parseptr;
  229. X    if(*token == '\'')
  230. X    {
  231. X        token++;
  232. X        parseptr++;
  233. X        while(*parseptr)
  234. X        {
  235. X            if(*parseptr == '\'')
  236. X            {
  237. X                arg_token_static = parseptr + 1;
  238. X                *parseptr = 0;
  239. X                return(token);
  240. X            }
  241. X            parseptr++;
  242. X        }
  243. X        arg_token_static = (char *)0;
  244. X        return(token);
  245. X    }
  246. X    while(*parseptr)
  247. X    {
  248. X        if(strchr(termchars,*parseptr))
  249. X        {
  250. X            *parseptr = 0;
  251. X            arg_token_static = parseptr + 1;
  252. X            while(*arg_token_static)
  253. X            {
  254. X                if(!strchr(termchars,*arg_token_static))
  255. X                    break;
  256. X                arg_token_static++;
  257. X            }
  258. X            return(token);
  259. X        }
  260. X        parseptr++;
  261. X    }
  262. X    arg_token_static = (char *)0;
  263. X    return(token);
  264. X}    /* end of arg_token */
  265. X#endif
  266. X
  267. X/*+-------------------------------------------------------------------------
  268. X    fname_split(cmd,arg,arg_max_quan,&narg)
  269. X--------------------------------------------------------------------------*/
  270. X#if defined(M_UNIX)
  271. Xvoid
  272. Xfname_split(cmd,arg,arg_max_quan,narg_rtn)
  273. Xchar *cmd;
  274. Xchar **arg;
  275. Xint arg_max_quan;
  276. Xint *narg_rtn;
  277. X{
  278. Xregister itmp;
  279. Xregister narg;
  280. X
  281. X    for(itmp = 0; itmp < arg_max_quan; itmp++)
  282. X        arg[itmp] = (char *)0;
  283. X    arg[0] = arg_token(cmd,"/");
  284. X
  285. X    for(narg = 1; narg < arg_max_quan; ++narg)
  286. X    {
  287. X        if((arg[narg] = arg_token((char *)0,"/")) == (char *)0) 
  288. X            break;
  289. X    }
  290. X
  291. X    *narg_rtn = narg;
  292. X
  293. X}    /* end of fname_split */
  294. X#endif
  295. X
  296. X#if defined(M_UNIX)
  297. X#define MAX_COMPONENT_LEN    14
  298. X#define MAX_PATH_COMPONENTS    16
  299. Xstatic char trunc_fname[257];
  300. Xstatic char *trunc_components[MAX_PATH_COMPONENTS];
  301. Xstatic int trunc_components_quan;
  302. Xstatic int trunc_absolute_path;
  303. X#endif
  304. X
  305. X/*+-------------------------------------------------------------------------
  306. X    fname_too_long(fname) - check for any pathname component too long
  307. X--------------------------------------------------------------------------*/
  308. X#if defined(M_UNIX)
  309. Xint
  310. Xfname_too_long(fname)
  311. Xregister char *fname;
  312. X{
  313. Xregister int itmp;
  314. Xregister char **cpptr;
  315. X
  316. X    if(trunc_absolute_path = (*fname == '/'))
  317. X        fname++;
  318. X    strncpy(trunc_fname,fname,sizeof(trunc_fname) - 1);
  319. X    fname_split(trunc_fname,trunc_components,
  320. X        MAX_PATH_COMPONENTS,&trunc_components_quan);
  321. X    itmp = trunc_components_quan;
  322. X    cpptr = trunc_components;
  323. X    while(itmp--)
  324. X    {
  325. X        if(strlen(*cpptr) > MAX_COMPONENT_LEN)
  326. X            return(1);
  327. X        cpptr++;
  328. X    }
  329. X    return(0);
  330. X}    /* end of fname_too_long */
  331. X#endif
  332. X
  333. X/*+-------------------------------------------------------------------------
  334. X    fname_truncated() - build truncated path last checked by fname_too_long
  335. X--------------------------------------------------------------------------*/
  336. X#if defined(M_UNIX)
  337. Xchar *
  338. Xfname_truncated()
  339. X{
  340. Xregister int icomp;
  341. Xchar new_fname[257];
  342. Xregister char *cptr = new_fname;
  343. X
  344. X    if(trunc_absolute_path)
  345. X    {
  346. X        *cptr = '/';
  347. X        *(cptr + 1) = 0;
  348. X    }
  349. X    else
  350. X        *cptr = 0;
  351. X    for(icomp = 0; icomp < trunc_components_quan; icomp++)
  352. X    {
  353. X        if(strlen(trunc_components[icomp]) > MAX_COMPONENT_LEN)
  354. X            *(trunc_components[icomp] + MAX_COMPONENT_LEN) = 0;
  355. X        strcat(cptr,trunc_components[icomp]);
  356. X        if(icomp < trunc_components_quan - 1)
  357. X            strcat(cptr,"/");
  358. X    }
  359. X    strcpy(trunc_fname,cptr);
  360. X    return(trunc_fname);
  361. X
  362. X}    /* end of fname_truncated */
  363. X#endif
  364. X
  365. X/*+-------------------------------------------------------------------------
  366. X    substr(str,token)
  367. X
  368. X  searches for token in string str returns pointer to token within
  369. X  string if found,NULL otherwise
  370. X--------------------------------------------------------------------------*/
  371. Xchar *
  372. Xsubstr(str,token)
  373. Xregister char *str,*token;
  374. X{
  375. Xregister char *ss,*tt;
  376. X
  377. X    /* search for first char of token */
  378. X    for(ss=str; *str; str++)
  379. X        if(*str == *token)
  380. X            /* compare token with substring */
  381. X            for(ss=str,tt=token; ;)
  382. X            {
  383. X                if(*tt == 0)
  384. X                    return(str);
  385. X                if(*ss++ != *tt++)
  386. X                    break;
  387. X            }
  388. X    return(NULL);
  389. X}    /* end of substr */
  390. X
  391. X/*+-------------------------------------------------------------------------
  392. X    getfree()
  393. X
  394. X  Routine to calculate the free bytes on the current file system ~0
  395. X  means many free bytes (unknown)
  396. X--------------------------------------------------------------------------*/
  397. Xlong
  398. Xgetfree()
  399. X{
  400. X    return(~0L);    /* many free bytes ... */
  401. X}    /* end of getfree */
  402. X
  403. X/*+-------------------------------------------------------------------------
  404. X    usage(fail_reason)
  405. X--------------------------------------------------------------------------*/
  406. Xvoid
  407. Xusage(fail_reason)
  408. Xchar *fail_reason;
  409. X{
  410. X    fprintf(stderr,"%s\n",fail_reason);
  411. X    exit(255);
  412. X}    /* end of usage */
  413. X
  414. X/*+-------------------------------------------------------------------------
  415. X    SIGALRM_handler()
  416. X--------------------------------------------------------------------------*/
  417. Xvoid
  418. XSIGALRM_handler()
  419. X{
  420. X    report_tx_ind(0);
  421. X    report_rx_ind(0);
  422. X    longjmp(tohere,-1);
  423. X}    /* end of SIGALRM_handler */
  424. X
  425. X/*+-------------------------------------------------------------------------
  426. X    bye_bye(sig)
  427. X--------------------------------------------------------------------------*/
  428. Xvoid
  429. Xbye_bye(sig)
  430. Xint sig;
  431. X{
  432. X    exit(sig+128);
  433. X}    /* end of bye_bye */
  434. X
  435. X/*+-------------------------------------------------------------------------
  436. X    cancel_transaction(sig)
  437. Xcalled by signal interrupt or terminate to clean things up
  438. X--------------------------------------------------------------------------*/
  439. Xvoid
  440. Xcancel_transaction(sig)
  441. X{
  442. X    if(Zmodem)
  443. X        zmputs(Attn);
  444. X    send_cancel(1);
  445. X    mode(0);
  446. X    if(sig >= 0)
  447. X    {
  448. X        sprintf(s128,"ecurz aborted (signal %d)",sig);
  449. X        report_str(s128,0);
  450. X    }
  451. X    report_tx_ind(0);
  452. X    report_rx_ind(0);
  453. X    report_uninit(0);
  454. X    bye_bye(sig);
  455. X}    /* end of cancel_transaction */
  456. X
  457. X/*+-------------------------------------------------------------------------
  458. X    sendline(c) -  send a character to DCE
  459. X--------------------------------------------------------------------------*/
  460. Xsendline(c)
  461. Xchar c;
  462. X{
  463. X    write(iofd,&c,1);
  464. X    ++tx_char_count;
  465. X}    /* end of sendline */
  466. X
  467. X/*+-------------------------------------------------------------------------
  468. X    xsendline(c)
  469. X--------------------------------------------------------------------------*/
  470. Xxsendline(c)
  471. X{
  472. X    sendline(c);
  473. X}    /* end of xsendline */
  474. X
  475. X/*+-------------------------------------------------------------------------
  476. X    flushline()
  477. X--------------------------------------------------------------------------*/
  478. Xflushline()
  479. X{
  480. X}    /* end of flushline */
  481. X
  482. X/*+-------------------------------------------------------------------------
  483. X    purgeline() - purge the modem input queue of all characters
  484. X--------------------------------------------------------------------------*/
  485. Xpurgeline()
  486. X{
  487. X    Lleft = 0;
  488. X#if defined(M_XENIX) || defined(M_UNIX)
  489. X    ioctl(iofd,TCFLSH,0);
  490. X#else
  491. X    lseek(iofd,0L,2);
  492. X#endif
  493. X}    /* end of purgeline */
  494. X
  495. X/*+-------------------------------------------------------------------------
  496. X    wcreceive(argc,argp)
  497. X--------------------------------------------------------------------------*/
  498. Xwcreceive(argc,argp)
  499. Xint argc;
  500. Xchar **argp;
  501. X{
  502. Xregister c;
  503. X
  504. X    if(Batch || argc==0)
  505. X    {
  506. X        Crcflg=1;
  507. X        c=tryz();
  508. X        if(Zmodem)
  509. X        {
  510. X            report_protocol_type("ZMODEM");
  511. X            report_protocol_crc_type((Crc32) ? "/CRC32" : "/CRC16");
  512. X        }
  513. X        if(c)
  514. X        {
  515. X            if(c == ZCOMPL)
  516. X                return(OK);
  517. X            if(c == ERROR)
  518. X                goto fubar;
  519. X            c = rzfiles();
  520. X            if(c)
  521. X                goto fubar;
  522. X        } else 
  523. X        {
  524. X            report_protocol_type("YMODEM");
  525. X            report_protocol_crc_type((Crcflg) ? "/CRC" : "/CHK");
  526. X            for(;;)
  527. X            {
  528. X                if(wcrxpn(secbuf)== ERROR)
  529. X                    goto fubar;
  530. X                if(secbuf[0]==0)
  531. X                    return(OK);
  532. X                if(procheader(secbuf) == ERROR)
  533. X                    goto fubar;
  534. X                report_str("Receiving data",0);
  535. X                if(wcrx()==ERROR)
  536. X                    goto fubar;
  537. X            }
  538. X        }
  539. X    }
  540. X    else 
  541. X    {
  542. X        report_protocol_type("XMODEM");
  543. X        report_protocol_crc_type((Crcflg) ? "/CRC" : "/CHK");
  544. X        Bytesleft = DEFBYTL;
  545. X        Filemode = 0;
  546. X        Modtime = 0L;
  547. X        procheader("");
  548. X        strcpy(Pathname,*argp);
  549. X#if defined(M_UNIX)
  550. X        if(fname_too_long(Pathname))
  551. X        {
  552. X            strcpy(s128,"truncated: ");
  553. X            strncat(s128,Pathname,sizeof(s128) - 12);
  554. X            ecu_log_event(getppid(),s128);
  555. X            report_str(s128,-1);
  556. X            strcpy(Pathname,fname_truncated());
  557. X        }
  558. X#endif
  559. X        if((fout=fopen(Pathname,"w")) == NULL)
  560. X        {
  561. X            sprintf(s128,"%-0.85s: %-0.40s",Pathname,sys_errlist[errno]);
  562. X            report_str(s128,1);
  563. X            ecu_log_event(getppid(),s128);
  564. X            goto fubar;
  565. X        }
  566. X
  567. X        ++Filcnt;
  568. X        report_file_rcv_started( Pathname,0L,Modtime,Filemode);
  569. X        this_file_length = 0;
  570. X        report_rxpos(0L);
  571. X        report_str("Receiving data",0);
  572. X        if(wcrx()==ERROR)
  573. X            goto fubar;
  574. X    }
  575. X    return(OK);
  576. Xfubar:
  577. X    send_cancel(1);
  578. X    if(fout)
  579. X    {
  580. X        fflush(fout);
  581. X        fstat(fileno(fout),&fout_stat);
  582. X        report_file_byte_io((long)fout_stat.st_size);
  583. X        report_file_close();
  584. X        fclose(fout);
  585. X    }
  586. X    return(ERROR);
  587. X}    /* end of wcreceive */
  588. X
  589. X/*+-------------------------------------------------------------------------
  590. X    wcgetsec(rxbuf,maxtime)
  591. X
  592. X  Wcgetsec fetches a Ward Christensen type sector.  Returns sector
  593. X  number encountered or ERROR if valid sector not received, or CAN CAN
  594. X  received or WCEOT if eot sector time is timeout for first char,set to
  595. X  4 seconds thereafter. NO ACK IS SENT IF SECTOR IS RECEIVED OK. Caller
  596. X  must do that when he is good and ready to get next sector.
  597. X--------------------------------------------------------------------------*/
  598. Xunsigned int
  599. Xwcgetsec(rxbuf,maxtime)
  600. Xchar *rxbuf;
  601. Xint maxtime;
  602. X{
  603. Xregister unsigned int firstch;
  604. Xregister unsigned short oldcrc;
  605. Xregister unsigned char checksum;
  606. Xregister wcj;
  607. Xregister char *p;
  608. Xint sectcurr;
  609. X
  610. X    for(Lastrx=errors=0; errors<RETRYMAX; errors++)
  611. X    {
  612. X
  613. X        firstch=readline(maxtime);
  614. X        if((firstch == STX) || (firstch == SOH))
  615. X        {
  616. X            oldBlklen = Blklen;
  617. X            if(firstch == STX)
  618. X                Blklen=1024;
  619. X            else
  620. X                Blklen=128;
  621. X            if(oldBlklen != Blklen)
  622. X                report_rxblklen(Blklen);
  623. X
  624. X            sectcurr=readline(1);
  625. X            if((sectcurr + (oldcrc=readline(1))) == 0xFF)
  626. X            {
  627. X                oldcrc=checksum=0;
  628. X                for(p=rxbuf,wcj=Blklen; --wcj>=0; )
  629. X                {
  630. X                    if((firstch=readline(1)) < 0)
  631. X                        goto bilge;
  632. X                    oldcrc=updcrc(firstch,oldcrc);
  633. X                    checksum += (*p++ = firstch);
  634. X                }
  635. X                if((firstch=readline(1)) < 0)
  636. X                    goto bilge;
  637. X                if(Crcflg)
  638. X                {
  639. X                    oldcrc=updcrc(firstch,oldcrc);
  640. X                    if((firstch=readline(1)) < 0)
  641. X                        goto bilge;
  642. X                    oldcrc=updcrc(firstch,oldcrc);
  643. X                    if(oldcrc)
  644. X                    {
  645. X                        sprintf(s128,"CRC error = 0x%04x",oldcrc);
  646. X                        report_str(s128,1);
  647. X                    }
  648. X                    else 
  649. X                    {
  650. X                        Firstsec=0;
  651. X                        return(sectcurr);
  652. X                    }
  653. X                }
  654. X                else if((checksum-firstch)==0)
  655. X                {
  656. X                    Firstsec=0;
  657. X                    return(sectcurr);
  658. X                }
  659. X                else
  660. X                    report_str("checksum error",1);
  661. X            }
  662. X            else
  663. X            {
  664. X                report_last_txhdr("Noise",0);
  665. X                sprintf(s128,"Sector garbled 0x%x 0x%x",sectcurr,oldcrc);
  666. X                report_str(s128,1);
  667. X            }
  668. X        }
  669. X        /* make sure eot really is eot and not just mixmash */
  670. X#if defined(NFGVMIN)
  671. X        else if(firstch==EOT && readline(1)==TIMEOUT)
  672. X            return(WCEOT);
  673. X#else
  674. X        else if(firstch==EOT && Lleft==0)
  675. X            return(WCEOT);
  676. X#endif
  677. X        else if(firstch==EOT)
  678. X        {
  679. X            report_str("Noisy EOT",2);
  680. X        }
  681. X        else if(firstch==CAN)
  682. X        {
  683. X            if(Lastrx==CAN)
  684. X            {
  685. X                report_str("Sender CANcelled",1);
  686. X                report_last_rxhdr("CAN",1);
  687. X                return(ERROR);
  688. X            } else 
  689. X            {
  690. X                Lastrx=CAN;
  691. X                continue;
  692. X            }
  693. X        }
  694. X        else if(firstch==TIMEOUT)
  695. X        {
  696. X            if(Firstsec)
  697. X                goto humbug;
  698. Xbilge:
  699. X            report_str("Timeout",1);
  700. X        }
  701. X        else
  702. X        {
  703. X            sprintf(s128,"Got 0x%02x sector header",firstch);
  704. X            report_str(s128,1);
  705. X        }
  706. X
  707. Xhumbug:
  708. X        Lastrx=0;
  709. X        while(readline(1)!=TIMEOUT)
  710. X            ;
  711. X        if(Firstsec)
  712. X        {
  713. X            sendline(Crcflg?WANTCRC:NAK);
  714. X            report_last_txhdr(Crcflg ? "WANTCRC" : "NAK",0);
  715. X            Lleft=0;    /* Do read next time ... */
  716. X        } else 
  717. X        {
  718. X            maxtime=40;
  719. X            sendline(NAK);
  720. X            report_last_txhdr("NAK",1);
  721. X            Lleft=0;    /* Do read next time ... */
  722. X        }
  723. X    }
  724. X    /* try to stop the bubble machine. */
  725. X    send_cancel(1);
  726. X    return(ERROR);
  727. X}    /* end of wcgetsec */
  728. X
  729. X/*+-------------------------------------------------------------------------
  730. X    wcrxpn(rpn)
  731. X
  732. X  Fetch a pathname from the other end.  Length is indeterminate as long
  733. X  as less than Blklen.  During YMODEM xfers, a null string represents no
  734. X  more files.
  735. X--------------------------------------------------------------------------*/
  736. Xwcrxpn(rpn)
  737. Xchar *rpn;    /* receive a pathname */
  738. X{
  739. Xregister c;
  740. X
  741. X#if defined(NFGVMIN)
  742. X    readline(1);
  743. X#else
  744. X    purgeline();
  745. X#endif
  746. X
  747. Xet_tu:
  748. X    Firstsec=1;
  749. X    Eofseen=0;
  750. X    sendline(Crcflg?WANTCRC:NAK);
  751. X    report_last_txhdr(Crcflg ? "WANTCRC" : "NAK",0);
  752. X    Lleft=0;    /* Do read next time ... */
  753. X    while((c = wcgetsec(rpn,100)) != 0)
  754. X    {
  755. X        if(c == WCEOT)
  756. X        {
  757. X            sprintf(s128,"Pathname fetch returned %d",c);
  758. X            report_str(s128,1);
  759. X            sendline(ACK);
  760. X            report_last_txhdr("ACK",0);
  761. X            Lleft=0;    /* Do read next time ... */
  762. X            readline(1);
  763. X            goto et_tu;
  764. X        }
  765. X        return(ERROR);
  766. X    }
  767. X    sendline(ACK);
  768. X    report_last_txhdr("ACK",0);
  769. X    return(OK);
  770. X}    /* end of wcrxpn */
  771. X
  772. X/*+-------------------------------------------------------------------------
  773. X    write_sec_to_disk(buf,n)
  774. X
  775. X  Putsec writes the n characters of buf to receive file fout.  If not in
  776. X  binary mode, carriage returns, and all characters starting with CPMEOF
  777. X  are discarded.
  778. X--------------------------------------------------------------------------*/
  779. Xwrite_sec_to_disk(buf,n)
  780. Xchar *buf;
  781. Xregister n;
  782. X{
  783. Xregister char *p;
  784. X
  785. X    if(n == 0)
  786. X        return(OK);
  787. X    if(Thisbinary)
  788. X    {
  789. X        for(p=buf; --n>=0; )
  790. X            putc( *p++,fout);
  791. X    }
  792. X    else 
  793. X    {
  794. X        if(Eofseen)
  795. X            return(OK);
  796. X        for(p=buf; --n>=0; ++p )
  797. X        {
  798. X            if( *p == '\r')
  799. X                continue;
  800. X            if(*p == CPMEOF)
  801. X            {
  802. X                Eofseen=1;
  803. X                fflush(fout);
  804. X                fstat(fileno(fout),&fout_stat);
  805. X                report_rxpos(fout_stat.st_size);
  806. X                return(OK);
  807. X            }
  808. X            putc(*p ,fout);
  809. X        }
  810. X    }
  811. X    fflush(fout);
  812. X    fstat(fileno(fout),&fout_stat);
  813. X    report_rxpos(fout_stat.st_size);
  814. X    if(this_file_length != 0)
  815. X    {
  816. X    int pct;
  817. X#ifdef WHT
  818. X    FILE *fp;
  819. X#endif
  820. X        sprintf(s128,"Receiving data (%u%% complete)",
  821. X            (unsigned int)(
  822. X            pct = ((unsigned long)fout_stat.st_size * (unsigned long)100)
  823. X            / this_file_length));
  824. X#ifdef WHT
  825. X        if(pct == 90)
  826. X        {
  827. X            fp= fopen("/dev/morse","a");
  828. X            fputs("i",fp);
  829. X            fclose(fp);
  830. X        }
  831. X#endif
  832. X        report_str(s128,0);
  833. X    }
  834. X    return(OK);
  835. X}    /* end of write_sec_to_disk */
  836. X
  837. X/*+-------------------------------------------------------------------------
  838. X    wcrx() - receive an X/YMODEM sector
  839. X
  840. X  Adapted from CMODEM13.C,written by Jack M.  Wierda and Roderick W. Hart
  841. X--------------------------------------------------------------------------*/
  842. Xint
  843. Xwcrx()
  844. X{
  845. Xregister unsigned int sectnum,sectcurr;
  846. Xregister unsigned char sendchar;
  847. Xregister unsigned char *p;
  848. Xint cblklen;            /* bytes to dump this block */
  849. X
  850. X    Firstsec=1;
  851. X    sectnum=0;
  852. X    Eofseen=0;
  853. X    sendchar=Crcflg ? WANTCRC : NAK;
  854. X    report_last_txhdr(Crcflg ? "WANTCRC" : "NAK",0);
  855. X
  856. X    for(;;)
  857. X    {
  858. X        sendline(sendchar);    /* send it now,we're ready! */
  859. X        if(sendchar == ACK)
  860. X            report_last_txhdr("ACK",0);
  861. X        Lleft=0;    /* Do read next time ... */
  862. X        sectcurr=wcgetsec(secbuf,(sectnum&0177)?50:130);
  863. X        sprintf(s128,"Block %d received",sectnum);
  864. X        report_last_rxhdr(s128,0);
  865. X        fstat(fileno(fout),&fout_stat);
  866. X        report_rxpos(fout_stat.st_size);
  867. X        if(sectcurr == (sectnum+1 & 0xFF))
  868. X        {
  869. X            sectnum++;
  870. X            cblklen = Bytesleft>Blklen ? Blklen : Bytesleft;
  871. X            if(write_sec_to_disk(secbuf,cblklen) == ERROR)
  872. X                return(ERROR);
  873. X            if((Bytesleft-=cblklen) < 0)
  874. X                Bytesleft = 0;
  875. X            sendchar=ACK;
  876. X        }
  877. X        else if(sectcurr == sectnum)
  878. X        {
  879. X            report_str("Received duplicate Sector",-1);
  880. X            sendchar = ACK;
  881. X        }
  882. X        else if(sectcurr == WCEOT)
  883. X        {
  884. X            if(close_and_report())
  885. X                return(ERROR);
  886. X            sendline(ACK);
  887. X            report_last_txhdr("ACK",0);
  888. X            Lleft=0;    /* Do read next time ... */
  889. X            return(OK);
  890. X        }
  891. X        else if(sectcurr==ERROR)
  892. X            return(ERROR);
  893. X        else 
  894. X        {
  895. X            report_str( "Sync Error",1);
  896. X            return(ERROR);
  897. X        }
  898. X    }
  899. X}    /* end of wcrx */
  900. X
  901. X/*+-------------------------------------------------------------------------
  902. X    readline(timeout)
  903. X
  904. X  read one or more characters timeout is in tenths of seconds
  905. X--------------------------------------------------------------------------*/
  906. Xreadline(timeout)
  907. Xint timeout;
  908. X{
  909. Xregister n;
  910. Xstatic unsigned char *cdq;    /* pointer for removing chars from linbuf */
  911. X
  912. X    if(--Lleft >= 0)
  913. X        return(*cdq++);
  914. X
  915. X    n = timeout/10;
  916. X    if(n < 2)
  917. X        n = 3;
  918. X    if(setjmp(tohere))
  919. X    {
  920. X        Lleft = 0;
  921. X        return(TIMEOUT);
  922. X    }
  923. X    signal(SIGALRM,SIGALRM_handler);
  924. X    alarm(n);
  925. X    Lleft = read(iofd,cdq = linbuf,Readnum);
  926. X    alarm(0);
  927. X    rx_char_count += Lleft;
  928. X
  929. X    if(Lleft < 1)
  930. X        return(TIMEOUT);
  931. X
  932. X    --Lleft;
  933. X    return(*cdq++);
  934. X
  935. X}    /* end of readline */
  936. X
  937. X/*+-------------------------------------------------------------------------
  938. X    mkdir(dpath,dmode)
  939. X Directory-creating routines from Public Domain TAR by John Gilmore
  940. X Make a directory.  Compatible with the mkdir() system call on 4.2BSD.
  941. X--------------------------------------------------------------------------*/
  942. X#if defined(MD)
  943. X#if (MD != 2)
  944. X#define    TERM_SIGNAL(status)        ((status) & 0x7F)
  945. X#define TERM_COREDUMP(status)    (((status) & 0x80) != 0)
  946. X#define TERM_VALUE(status)        ((status) >> 8)
  947. Xmkdir(dpath,dmode)
  948. Xchar *dpath;
  949. Xint dmode;
  950. X{
  951. Xint cpid,status;
  952. Xstruct stat statbuf;
  953. X
  954. X    if(stat(dpath,&statbuf) == 0)
  955. X    {
  956. X        errno = EEXIST;        /* Stat worked,so it already exists */
  957. X        return(-1);
  958. X    }
  959. X
  960. X    /* If stat fails for a reason other than non-existence,return error */
  961. X    if(errno != ENOENT)
  962. X        return(-1);
  963. X
  964. X    switch(cpid = fork())
  965. X    {
  966. X
  967. X    case -1:            /* Error in fork() */
  968. X        return(-1);        /* Errno is set already */
  969. X
  970. X    case 0:                /* Child process */
  971. X        /*
  972. X         * Cheap hack to set mode of new directory.  Since this
  973. X         * child process is going away anyway,we zap its umask.
  974. X         * FIXME,this won't suffice to set SUID,SGID,etc. on this
  975. X         * directory.  Does anybody care?
  976. X         */
  977. X        status = umask(0);    /* Get current umask */
  978. X        status = umask(status | (0777 & ~dmode)); /* Set for mkdir */
  979. X        execl("/bin/mkdir","mkdir",dpath,(char *)0);
  980. X        _exit(-1);        /* Can't exec /bin/mkdir */
  981. X
  982. X    default:            /* Parent process */
  983. X        while(cpid != wait(&status)) ;    /* Wait for kid to finish */
  984. X    }
  985. X
  986. X    if(TERM_SIGNAL(status) != 0 || TERM_VALUE(status) != 0)
  987. X    {
  988. X        errno = EIO;        /* We don't know why,but */
  989. X        return(-1);        /* /bin/mkdir failed */
  990. X    }
  991. X
  992. X    return(0);
  993. X}    /* end of mkdir */
  994. X#endif /* MD != 2 */
  995. X#endif /* if defined(MD) */
  996. X
  997. X/*+-------------------------------------------------------------------------
  998. X    make_dirs(pathname)
  999. X
  1000. X  Directory-creating routines from Public Domain TAR by John Gilmore
  1001. X  After a file/link/symlink/dir creation has failed, see if it's because
  1002. X  some required directory was not present, and if so, create all
  1003. X  required dirs.
  1004. X--------------------------------------------------------------------------*/
  1005. X#if defined(MD)
  1006. Xmake_dirs(pathname)
  1007. Xregister char *pathname;
  1008. X{
  1009. X    register char *p;            /* Points into path */
  1010. X    int madeone = 0;            /* Did we do anything yet? */
  1011. X    int save_errno = errno;        /* Remember caller's errno */
  1012. X
  1013. X    if(errno != ENOENT)
  1014. X        return(0);        /* Not our problem */
  1015. X
  1016. X    for(p = strchr(pathname,'/'); p != NULL; p = strchr(p+1,'/'))
  1017. X    {
  1018. X        /* Avoid mkdir of empty string,if leading or double '/' */
  1019. X        if(p == pathname || p[-1] == '/')
  1020. X            continue;
  1021. X        /* Avoid mkdir where last part of path is '.' */
  1022. X        if(p[-1] == '.' && (p == pathname+1 || p[-2] == '/'))
  1023. X            continue;
  1024. X        *p = 0;                /* Truncate the path there */
  1025. X        if( !mkdir(pathname,0777))    /* Try to create it as a dir */
  1026. X        {
  1027. X            sprintf(s128,"Made directory %s",pathname);
  1028. X            report_str(s128,-1);
  1029. X            madeone++;        /* Remember if we made one */
  1030. X            *p = '/';
  1031. X            continue;
  1032. X        }
  1033. X        *p = '/';
  1034. X        if(errno == EEXIST)        /* Directory already exists */
  1035. X            continue;
  1036. X        /*
  1037. X         * Some other error in the mkdir.  We return to the caller.
  1038. X         */
  1039. X        break;
  1040. X    }
  1041. X    errno = save_errno;        /* Restore caller's errno */
  1042. X    return(madeone);            /* Tell them to retry if we made one */
  1043. X}    /* end of make_dirs */
  1044. X#endif /* MD */
  1045. X
  1046. X/*+-------------------------------------------------------------------------
  1047. X    uncaps(str) - make string str lower case
  1048. X--------------------------------------------------------------------------*/
  1049. Xvoid
  1050. Xuncaps(str)
  1051. Xregister char *str;
  1052. X{
  1053. Xregister int itmp;
  1054. X
  1055. X    while(itmp = *str)
  1056. X    {
  1057. X        if(isupper(itmp))
  1058. X            *str = tolower(itmp);
  1059. X        str++;
  1060. X    }
  1061. X}    /* end of uncaps */
  1062. X
  1063. X/*+-------------------------------------------------------------------------
  1064. X    isanylc(str) - returns 1 if string str has any lower case letters
  1065. X--------------------------------------------------------------------------*/
  1066. Xint
  1067. Xisanylc(str)
  1068. Xregister char *str;
  1069. X{
  1070. X    while(*str)
  1071. X    {
  1072. X        if(islower(*str))
  1073. X            return(1);
  1074. X        str++;
  1075. X    }
  1076. X    return(0);
  1077. X}    /* end of isanylc */
  1078. X
  1079. X/*+-------------------------------------------------------------------------
  1080. X    procheader(name) - process incoming file information header
  1081. X--------------------------------------------------------------------------*/
  1082. Xint
  1083. Xprocheader(name)
  1084. Xchar *name;
  1085. X{
  1086. Xregister char *openmode,*p,**pp;
  1087. X#if defined(M_UNIX)
  1088. Xchar *cptr;
  1089. Xchar name2[PATHLEN];
  1090. X#endif
  1091. X
  1092. X    /* set default parameters and overrides */
  1093. X    openmode = "w";
  1094. X    Thisbinary = (!Rxascii) || Rxbinary;
  1095. X    if(Lzmanag)
  1096. X        zmanag = Lzmanag;
  1097. X
  1098. X    /*
  1099. X     *  Process ZMODEM remote file management requests
  1100. X     */
  1101. X    if(!Rxbinary && zconv == ZCNL)    /* Remote ASCII override */
  1102. X        Thisbinary = 0;
  1103. X    if(zconv == ZCBIN)    /* Remote Binary override */
  1104. X        Thisbinary = 1;
  1105. X    else if(zmanag == ZMAPND)
  1106. X        openmode = "a";
  1107. X
  1108. X    report_xfer_mode(Thisbinary ? "BINARY" : "ASCII");
  1109. X    this_file_errors = 0;
  1110. X
  1111. X    Bytesleft = DEFBYTL;
  1112. X    Filemode = 0;
  1113. X    Modtime = 0L;
  1114. X    this_file_length = 0;
  1115. X
  1116. X    if(strlen(name))
  1117. X        p = name + 1 + strlen(name);
  1118. X    else
  1119. X        p = name;
  1120. X
  1121. X#if defined(M_UNIX)
  1122. X    if(fname_too_long(name))
  1123. X    {
  1124. X        strcpy(s128,"truncated: ");
  1125. X        strncat(s128,name,sizeof(s128) - 12);
  1126. X        ecu_log_event(getppid(),s128);
  1127. X        report_str(s128,-1);
  1128. X        name = fname_truncated();
  1129. X    }
  1130. X#endif
  1131. X
  1132. X    if(*p)
  1133. X    {    /* file coming from Unix or DOS system */
  1134. X    int sscanf_count;
  1135. X    int SerialNumber;
  1136. X    int Filesleft;
  1137. X    long TotalLeft;
  1138. X
  1139. X        sscanf_count = sscanf(p,"%ld%lo%o%d&d&ld",
  1140. X            &Bytesleft,&Modtime,&Filemode,&SerialNumber,
  1141. X            &Filesleft,&TotalLeft);
  1142. X
  1143. X        switch(sscanf_count)
  1144. X        {
  1145. X        case 6:    /* TotalLeft */
  1146. X            if(!TotalToReceive)
  1147. X                TotalToReceive = TotalLeft;
  1148. X        case 5:    /* Filesleft */
  1149. X            if(!npats)
  1150. X                npats = Filesleft;
  1151. X        default:
  1152. X            break;
  1153. X        }
  1154. X
  1155. X        if((zmanag & ZMMASK) == ZMNEW)
  1156. X        {
  1157. X            if(stat(name,&fout_stat) == 0)            /* if file accessable ... */
  1158. X            {
  1159. X                if(Modtime <= fout_stat.st_mtime)    /* ... and not older */
  1160. X                {
  1161. X                    sprintf(s128,"RECEIVE skipped: %s (same or later date)",
  1162. X                        name);
  1163. X                    report_str(s128 + 8,-1);
  1164. X                    skip_count++;
  1165. X                    report_error_count();
  1166. X#if defined(LOG_SKIP)
  1167. X                    ecu_log_event(getppid(),s128);
  1168. X#endif
  1169. X                    return(ERROR);
  1170. X                }
  1171. X            }
  1172. X        }
  1173. X        /* Check for existing file */
  1174. X        else if(!Rxclob && ((zmanag & ZMMASK) != ZMCLOB) &&
  1175. X            (fout=fopen(name,"r")))
  1176. X        {
  1177. X            fclose(fout);
  1178. X            sprintf(s128,"RECEIVE skipped: %s (already exists)",name);
  1179. X            report_str(s128 + 8,-1);
  1180. X            skip_count++;
  1181. X            report_error_count();
  1182. X#if defined(LOG_SKIP)
  1183. X            ecu_log_event(getppid(),s128);
  1184. X#endif
  1185. X            return(ERROR);
  1186. X        }
  1187. X
  1188. X        if(Filemode & UNIXFILE)
  1189. X            ++Thisbinary;
  1190. X        ++Filcnt;
  1191. X
  1192. X        report_file_rcv_started( name,
  1193. X            (Bytesleft != DEFBYTL) ? Bytesleft : 0,Modtime,Filemode);
  1194. X        report_rxpos(0L);
  1195. X        report_str("",0);    /* get rid of End of File */
  1196. X        if(Bytesleft != DEFBYTL)
  1197. X        {
  1198. X            long min_100;
  1199. X            this_file_length = Bytesleft;
  1200. X            min_100 = 2L + (((Bytesleft * 11L)) * 10L) / (Baudrate * 6L);
  1201. X            sprintf(s128,"Receive time this file ~= %2lu:%02lu",
  1202. X                min_100 / 100,((min_100 % 100) * 60L) / 100L);
  1203. X            if(TotalToReceive)
  1204. X            {
  1205. X                min_100 = 2L +
  1206. X                    (((TotalToReceive * 11L)) * 10L) / (Baudrate * 6L);
  1207. X                if(Baudrate > 4800)
  1208. X                {
  1209. X                    min_100 *= 13;
  1210. X                    min_100 /= 9;    /* yech ... empirical */
  1211. X                }
  1212. X                sprintf(&s128[strlen(s128)],", transaction ~= %2lu:%02lu",
  1213. X                    min_100 / 100,((min_100 % 100) * 60L) / 100L);
  1214. X            }
  1215. X            report_transaction(s128);
  1216. X            sprintf(s128,"Receiving data (%d%% complete)",(int)0);
  1217. X            report_str(s128,0);
  1218. X        }
  1219. X    }
  1220. X    else 
  1221. X    {        /* File coming from CP/M system */
  1222. X    long now;
  1223. X        for(p=name; *p; ++p)        /* change / to _ */
  1224. X        {
  1225. X            if( *p == '/')
  1226. X                *p = '_';
  1227. X        }
  1228. X
  1229. X        if( *--p == '.')        /* zap trailing period */
  1230. X            *p = 0;
  1231. X        time(&now);
  1232. X        ++Filcnt;
  1233. X        report_file_rcv_started( name,
  1234. X            (Bytesleft != DEFBYTL) ? Bytesleft : 0,now,0);
  1235. X    }
  1236. X
  1237. X    if(!Zmodem && MakeLCPathname && !isanylc(name) && !(Filemode&UNIXFILE))
  1238. X        uncaps(name);
  1239. X
  1240. X    strcpy(Pathname,name);
  1241. X    report_xfer_mode(Thisbinary?"BINARY":"ASCII");
  1242. X    fout = fopen(name,openmode);
  1243. X#if defined(MD)
  1244. X    if( !fout)
  1245. X        if(make_dirs(name))
  1246. X            fout = fopen(name,openmode);
  1247. X#endif
  1248. X    if( !fout)
  1249. X        return(ERROR);
  1250. X    this_file_errors = 0;
  1251. X    return(OK);
  1252. X}    /* end of procheader */
  1253. X
  1254. X/*+-------------------------------------------------------------------------
  1255. X    send_cancel(error) - send cancel string
  1256. X--------------------------------------------------------------------------*/
  1257. Xsend_cancel(error)
  1258. Xint error;
  1259. X{
  1260. Xstatic char canistr[] = 
  1261. X{
  1262. X    24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0
  1263. X};
  1264. Xregister char *cptr = canistr;
  1265. X
  1266. X    report_str("",0);
  1267. X    report_last_txhdr("^X CAN",!!error);
  1268. X    while(*cptr)
  1269. X        sendline(*cptr++);
  1270. X    Lleft=0;
  1271. X}    /* end of send_cancel */
  1272. X
  1273. X/*+-------------------------------------------------------------------------
  1274. X    tryz()
  1275. X
  1276. X  Initialize for Zmodem receive attempt, try to activate Zmodem sender
  1277. X  Handles ZSINIT frame
  1278. X  Return ZFILE if Zmodem filename received,-1 on error,
  1279. X         ZCOMPL if transaction finished, else 0
  1280. X--------------------------------------------------------------------------*/
  1281. Xint
  1282. Xtryz()
  1283. X{
  1284. Xregister c,n;
  1285. X
  1286. X    if(Nozmodem)        /* Check for "rb" program name */
  1287. X        return(0);
  1288. X
  1289. X    for(n=Zmodem?15:5; --n>=0; )
  1290. X    {
  1291. X        /* Set buffer length (0) and capability flags */
  1292. X        stohdr(0L);
  1293. X
  1294. X#if defined(CANBREAK)
  1295. X        Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO|CANBRK;
  1296. X#else
  1297. X        Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO;
  1298. X#endif
  1299. X        if(Zctlesc)
  1300. X            Txhdr[ZF0] |= TESCCTL;
  1301. X        zshhdr(tryzhdrtype,Txhdr);
  1302. X        if(tryzhdrtype == ZSKIP)    /* Don't skip too far */
  1303. X            tryzhdrtype = ZRINIT;    /* CAF 8-21-87 */
  1304. Xagain:
  1305. X        switch(zgethdr(Rxhdr,0))
  1306. X        {
  1307. X        case ZRQINIT:
  1308. X            continue;
  1309. X        case ZEOF:
  1310. X            continue;
  1311. X        case TIMEOUT:
  1312. X            continue;
  1313. X        case ZFILE:
  1314. X            zconv = Rxhdr[ZF0];
  1315. X            zmanag = Rxhdr[ZF1];
  1316. X            ztrans = Rxhdr[ZF2];
  1317. X
  1318. X            strcpy(s128,"Transfer: ");
  1319. X            switch(zmanag & ZMMASK)
  1320. X            {
  1321. X            case 0:
  1322. X                strcat(s128,"if destination nonexistent");
  1323. X                break;
  1324. X            case ZMAPND:    /* Append contents to existing file (if any) */
  1325. X                strcat(s128,"append to destination");
  1326. X                break;
  1327. X            case ZMCLOB:    /* Replace existing file */
  1328. X                strcat(s128,"absolute (overwrite)");
  1329. X                break;
  1330. X            case ZMNEW:
  1331. X                strcat(s128,"if source newer");
  1332. X                break;
  1333. X            default:
  1334. X                sprintf(s128 + strlen(s128),
  1335. X                    "absolute (%02x)",zmanag & ZMMASK);
  1336. X                break;
  1337. X            }
  1338. X            report_str(s128,2);
  1339. X
  1340. X            tryzhdrtype = ZRINIT;
  1341. X            c = zrdata(secbuf,1024);
  1342. X            mode(3);
  1343. X            if(c == GOTCRCW)
  1344. X                return(ZFILE);
  1345. X            zshhdr(ZNAK,Txhdr);
  1346. X            goto again;
  1347. X        case ZSINIT:
  1348. X            Zctlesc = TESCCTL & Rxhdr[ZF0];
  1349. X            if(zrdata(Attn,ZATTNLEN) == GOTCRCW)
  1350. X            {
  1351. X                stohdr(1L);
  1352. X                zshhdr(ZACK,Txhdr);
  1353. X                report_str("",-1);
  1354. X                goto again;
  1355. X            }
  1356. X            zshhdr(ZNAK,Txhdr);
  1357. X            goto again;
  1358. X        case ZFREECNT:
  1359. X            stohdr(getfree());
  1360. X            zshhdr(ZACK,Txhdr);
  1361. X            report_str("",-1);
  1362. X            goto again;
  1363. X        case ZCOMMAND:
  1364. X            if(zrdata(secbuf,1024) == GOTCRCW)
  1365. X            {
  1366. X                stohdr(-1L);
  1367. X                purgeline();    /* dump impatient questions */
  1368. X                while(errors < 20)
  1369. X                {
  1370. X                    zshhdr(ZCOMPL,Txhdr);
  1371. X                    if(zgethdr(Rxhdr,1) == ZFIN)
  1372. X                        break;
  1373. X                }
  1374. X                send_ZFIN_and_exit();
  1375. X                return(ZCOMPL);
  1376. X            }
  1377. X            zshhdr(ZNAK,Txhdr);
  1378. X            goto again;
  1379. X        case ZCOMPL:
  1380. X            goto again;
  1381. X        default:
  1382. X            continue;
  1383. X        case ZFIN:
  1384. X            send_ZFIN_and_exit();
  1385. X            return(ZCOMPL);
  1386. X        case ZCAN:
  1387. X            return(ERROR);
  1388. X        }
  1389. X    }
  1390. X    return(0);
  1391. X}    /* end of tryz */
  1392. X
  1393. X/*+-------------------------------------------------------------------------
  1394. X    rzfile() - receive a file with ZMODEM protocol
  1395. X
  1396. X  assumes file name frame is in secbuf
  1397. X--------------------------------------------------------------------------*/
  1398. Xrzfile()
  1399. X{
  1400. Xregister c,n;
  1401. Xlong rxbytes;
  1402. X
  1403. X    Eofseen=0;
  1404. X    if(procheader(secbuf) == ERROR)
  1405. X    {
  1406. X        return(tryzhdrtype = ZSKIP);
  1407. X    }
  1408. X
  1409. X    n = 20;
  1410. X    rxbytes = 0l;
  1411. X
  1412. X    for(;;)
  1413. X    {
  1414. X        if(rxbytes)
  1415. X            report_str("Sending ZRPOS",1);
  1416. X        stohdr(rxbytes);
  1417. X        zshhdr(ZRPOS,Txhdr);
  1418. Xnxthdr:
  1419. X        switch(c = zgethdr(Rxhdr,0))
  1420. X        {
  1421. X        default:
  1422. X            sprintf(s128,"zgethdr returned %02x",c);
  1423. X            report_str(s128,1);
  1424. X            return(ERROR);
  1425. X        case ZNAK:
  1426. X        case TIMEOUT:
  1427. X            if( --n < 0)
  1428. X            {
  1429. X                sprintf(s128,"zgethdr returned %02x",c);
  1430. X                report_str(s128,1);
  1431. X                return(ERROR);
  1432. X            }
  1433. X        case ZFILE:
  1434. X            zrdata(secbuf,1024);
  1435. X            continue;
  1436. X        case ZEOF:
  1437. X            if(rclhdr(Rxhdr) != rxbytes)
  1438. X            {
  1439. X                /*
  1440. X                 * Ignore eof if it's at wrong place - force
  1441. X                 *  a timeout because the eof might have gone
  1442. X                 *  out before we sent our zrpos.
  1443. X                 */
  1444. X                errors = 0;
  1445. X                goto nxthdr;
  1446. X            }
  1447. X            if(can_on_eof)
  1448. X            {
  1449. X                send_cancel(0);
  1450. X                send_cancel(0);
  1451. X                close_and_report();
  1452. X                report_uninit(0);
  1453. X                exit(0);
  1454. X            }
  1455. X            if(close_and_report())
  1456. X            {
  1457. X                tryzhdrtype = ZFERR;
  1458. X                return(ERROR);
  1459. X            }
  1460. X            report_str("End of file",0);
  1461. X            return(c);
  1462. X        case ERROR:    /* Too much garbage in header search error */
  1463. X            if( --n < 0)
  1464. X            {
  1465. X                sprintf(s128,"zgethdr returned %02x",c);
  1466. X                report_str(s128,1);
  1467. X                return(ERROR);
  1468. X            }
  1469. X            zmputs(Attn);
  1470. X            continue;
  1471. X        case ZSKIP:
  1472. X            close_and_report();
  1473. X            sprintf(s128,"rzfile: Sender SKIPPED file");
  1474. X            report_str(s128,1);
  1475. X            return(c);
  1476. X        case ZDATA:
  1477. X            if(rclhdr(Rxhdr) != rxbytes)
  1478. X            {
  1479. X                if( --n < 0)
  1480. X                {
  1481. X                    return(ERROR);
  1482. X                }
  1483. X                zmputs(Attn);
  1484. X                continue;
  1485. X            }
  1486. Xmoredata:
  1487. X            switch(c = zrdata(secbuf,1024))
  1488. X            {
  1489. X            case ZCAN:
  1490. X                sprintf(s128,"zgethdr returned %02x",c);
  1491. X                report_str(s128,1);
  1492. X                return(ERROR);
  1493. X            case ERROR:    /* CRC error */
  1494. X                if( --n < 0)
  1495. X                {
  1496. X                    sprintf(s128,"zgethdr returned %02x",c);
  1497. X                    report_str(s128,1);
  1498. X                    return(ERROR);
  1499. X                }
  1500. X                zmputs(Attn);
  1501. X                continue;
  1502. X            case TIMEOUT:
  1503. X                if( --n < 0)
  1504. X                {
  1505. X                    sprintf(s128,"zgethdr returned %02x",c);
  1506. X                    report_str(s128,1);
  1507. X                    return(ERROR);
  1508. X                }
  1509. X                continue;
  1510. X            case GOTCRCW:
  1511. X                n = 20;
  1512. X                write_sec_to_disk(secbuf,Rxcount);
  1513. X                rxbytes += Rxcount;
  1514. X                stohdr(rxbytes);
  1515. X                zshhdr(ZACK,Txhdr);
  1516. X                sendline(XON);
  1517. X                report_str("",-1);
  1518. X                goto nxthdr;
  1519. X            case GOTCRCQ:
  1520. X                n = 20;
  1521. X                write_sec_to_disk(secbuf,Rxcount);
  1522. X                rxbytes += Rxcount;
  1523. X                stohdr(rxbytes);
  1524. X                zshhdr(ZACK,Txhdr);
  1525. X                report_str("",-1);
  1526. X                goto moredata;
  1527. X            case GOTCRCG:
  1528. X                n = 20;
  1529. X                write_sec_to_disk(secbuf,Rxcount);
  1530. X                rxbytes += Rxcount;
  1531. X                goto moredata;
  1532. X            case GOTCRCE:
  1533. X                n = 20;
  1534. X                write_sec_to_disk(secbuf,Rxcount);
  1535. X                rxbytes += Rxcount;
  1536. X                goto nxthdr;
  1537. X            }
  1538. X        }
  1539. X    }
  1540. X}    /* end of rzfile */
  1541. X
  1542. X/*+-------------------------------------------------------------------------
  1543. X    rzfiles() - receive file(s) with ZMODEM protocol
  1544. X--------------------------------------------------------------------------*/
  1545. Xrzfiles()
  1546. X{
  1547. Xregister c;
  1548. X
  1549. X    for(;;)
  1550. X    {
  1551. X        switch(c = rzfile())
  1552. X        {
  1553. X        case ZEOF:
  1554. X        case ZSKIP:
  1555. X            switch(tryz())
  1556. X            {
  1557. X            case ZCOMPL:
  1558. X                return(OK);
  1559. X            default:
  1560. X                return(ERROR);
  1561. X            case ZFILE:
  1562. X                break;
  1563. X            }
  1564. X            continue;
  1565. X        default:
  1566. X            return(c);
  1567. X        case ERROR:
  1568. X            return(ERROR);
  1569. X        }
  1570. X    }
  1571. X}    /* end of rzfiles */
  1572. X
  1573. X/*+-------------------------------------------------------------------------
  1574. X    close_and_report() - close the received file, set mod time and chmod
  1575. X(specifically exclude set uid and gid from chmod)
  1576. X--------------------------------------------------------------------------*/
  1577. Xclose_and_report()
  1578. X{
  1579. X    fflush(fout);
  1580. X    fstat(fileno(fout),&fout_stat);
  1581. X    report_file_byte_io((long)fout_stat.st_size);
  1582. X    report_file_close();
  1583. X
  1584. X    if(fclose(fout)==ERROR)
  1585. X        return(ERROR);
  1586. X
  1587. X#if defined(LOG_XFER)
  1588. X    sprintf(s256,"RECEIVE success: %s (%ld bytes)",Pathname,fout_stat.st_size);
  1589. X    ecu_log_event(getppid(),s256);
  1590. X#endif
  1591. X
  1592. X    if(Modtime)
  1593. X    {
  1594. X        timep[0] = time(NULL);
  1595. X        timep[1] = Modtime;
  1596. X        utime(Pathname,timep);
  1597. X    }
  1598. X
  1599. X    if((Filemode & S_IFMT) == S_IFREG)
  1600. X    {
  1601. X        Filemode &= ~(S_ISUID | S_ISGID);
  1602. X        chmod(Pathname,(07777 & Filemode));
  1603. X    }
  1604. X
  1605. X    return(OK);
  1606. X
  1607. X}    /* end of close_and_report */
  1608. X
  1609. X/*+-------------------------------------------------------------------------
  1610. X    send_ZFIN_and_exit() - send ZFIN packet and wait for "OO" ack
  1611. X--------------------------------------------------------------------------*/
  1612. Xsend_ZFIN_and_exit()
  1613. X{
  1614. Xregister n;
  1615. X
  1616. X    Readnum = 1;
  1617. X    stohdr(0L);
  1618. X    for(n = 0; n < 4; n++)
  1619. X    {
  1620. X        purgeline();
  1621. X        zshhdr(ZFIN,Txhdr);
  1622. X        switch(readline(100))
  1623. X        {
  1624. X        case 'O':
  1625. X            readline(1);    /* Discard 2nd 'O' */
  1626. X            return;
  1627. X        case RCDO:
  1628. X            return;
  1629. X        case TIMEOUT:
  1630. X        default:
  1631. X            break;
  1632. X        }
  1633. X    }
  1634. X}    /* end of send_ZFIN_and_exit */
  1635. X
  1636. X/*+-------------------------------------------------------------------------
  1637. X    sys2(shellcmd) - execute shell command
  1638. X
  1639. X Strip leading ! if present
  1640. X--------------------------------------------------------------------------*/
  1641. Xsys2(shellcmd)
  1642. Xregister char *shellcmd;
  1643. X{
  1644. X    if(*shellcmd == '!')
  1645. X        ++shellcmd;
  1646. X    return(system(shellcmd));
  1647. X} /* end of sys2 */
  1648. X
  1649. X/*+-------------------------------------------------------------------------
  1650. X    main(argc,argv,envp)
  1651. X--------------------------------------------------------------------------*/
  1652. Xmain(argc,argv,envp)
  1653. Xint argc;
  1654. Xchar **argv;
  1655. Xchar **envp;
  1656. X{
  1657. Xregister char *cp;
  1658. Xchar **patts;
  1659. Xchar *getenv();
  1660. Xint exitcode = 0;
  1661. Xchar **gargv = argv;
  1662. Xint gargc = argc;
  1663. X
  1664. X    signal(SIGINT,bye_bye);
  1665. X    signal(SIGTERM,bye_bye);
  1666. X
  1667. X    get_curr_dir(curr_dir,sizeof(curr_dir));
  1668. X
  1669. X    Rxtimeout = 100;
  1670. X
  1671. X    npats = 0;
  1672. X    while(--argc)
  1673. X    {
  1674. X        cp = *++argv;
  1675. X        if(*cp == '-')
  1676. X        {
  1677. X            while( *++cp)
  1678. X            {
  1679. X                switch(*cp)
  1680. X                {
  1681. X                case 'X':
  1682. X                    required_type = 1;
  1683. X                    Batch = 0;
  1684. X                    break;
  1685. X                case 'Y':
  1686. X                    required_type = 1;
  1687. X                    Nozmodem = 1;
  1688. X                    Batch = 1;
  1689. X                    break;
  1690. X                case 'Z':
  1691. X                    required_type = 1;
  1692. X                    Nozmodem = 0;
  1693. X                    Batch = 1;
  1694. X                    break;
  1695. X                case '+':
  1696. X                    Lzmanag = ZMAPND;
  1697. X                    break;
  1698. X                case 'a':
  1699. X                    Rxascii=1;
  1700. X                    break;
  1701. X                case 'b':
  1702. X                    Rxbinary=1;
  1703. X                    break;
  1704. X                case 'c':
  1705. X                    Crcflg=1;
  1706. X                    break;
  1707. X                case 'e':
  1708. X                    Zctlesc = 1;
  1709. X                    break;
  1710. X                case 'p':
  1711. X                    Lzmanag = ZMPROT;
  1712. X                    break;
  1713. X                case '@':
  1714. X                    force_no_curses = 1;
  1715. X                    break;
  1716. X                case ',':
  1717. X                    log_packets = 1;
  1718. X                    break;
  1719. X                case ':':
  1720. X                    can_on_eof = 1;
  1721. X                    break;
  1722. X                case '.':
  1723. X                    if(--argc < 1)
  1724. X                    {
  1725. X                        usage("no iofd after -.");
  1726. X                    }
  1727. X                    iofd = atoi(*++argv);
  1728. X                    break;
  1729. X                case 't':
  1730. X                    if(--argc < 1)
  1731. X                    {
  1732. X                        usage("no rcvr timeout after -t");
  1733. X                    }
  1734. X                    Rxtimeout = atoi(*++argv);
  1735. X                    if(Rxtimeout<10 || Rxtimeout>1000)
  1736. X                        usage("illegal timeout: must be 10 <= t <= 1000");
  1737. X                    break;
  1738. X                case 'w':
  1739. X                    if(--argc < 1)
  1740. X                    {
  1741. X                        usage("no Zrwindow after -w");
  1742. X                    }
  1743. X                    Zrwindow = atoi(*++argv);
  1744. X                    break;
  1745. X                case 'C':
  1746. X                    if(--argc < 1)
  1747. X                        usage("no label after -C");
  1748. X                    bottom_label = *++argv;
  1749. X                    break;
  1750. X                case 'u':
  1751. X                    MakeLCPathname=0;
  1752. X                    break;
  1753. X                case 'y':
  1754. X                    Rxclob=1;
  1755. X                    break;
  1756. X                default:
  1757. X                    sprintf(s128,"Unknown switch -%c",*cp);
  1758. X                    usage(s128);
  1759. X                }
  1760. X            }
  1761. X        }
  1762. X        else if( !npats && argc>0)
  1763. X        {
  1764. X            if(argv[0][0])
  1765. X            {
  1766. X                npats=argc;
  1767. X                patts=argv;
  1768. X            }
  1769. X        }
  1770. X    }
  1771. X
  1772. X    if(determine_output_mode())
  1773. X    {
  1774. X        setbuf(stdout,NULL);
  1775. X        setbuf(stderr,NULL);
  1776. X    }
  1777. X
  1778. X    if(!required_type || !iofd)
  1779. X    {
  1780. X        printf("can only be run by ecu\n");
  1781. X        exit(255);
  1782. X    }
  1783. X
  1784. X    if(log_packets)
  1785. X    {
  1786. X        char log_packets_name[64];
  1787. X        int iargv;
  1788. X        sprintf(log_packets_name,"/tmp/rz%05d.plog",getpid());
  1789. X        unlink(log_packets_name);
  1790. X        log_packets = open(log_packets_name,O_CREAT|O_WRONLY,0644);
  1791. X        if(log_packets < 0)
  1792. X            log_packets = 0;
  1793. X        else
  1794. X        {
  1795. X            write(log_packets,"exec: ",6);
  1796. X            for(iargv = 0; iargv < gargc; iargv++)
  1797. X            {
  1798. X                write(log_packets,gargv[iargv],strlen(gargv[iargv]));
  1799. X                write(log_packets," ",1);
  1800. X            }
  1801. X            write(log_packets,"\n",1);
  1802. X        }
  1803. X    }
  1804. X
  1805. X
  1806. X    if(Batch && npats)
  1807. X        usage("Cannot specify batch receive and filename");
  1808. X    if(npats > 1)
  1809. X        usage("only one filename allowed");
  1810. X    sprintf(s128,"%s",numeric_revision);
  1811. X    report_init(s128);
  1812. X    mode(1);
  1813. X    signal(SIGINT,cancel_transaction);
  1814. X    signal(SIGTERM,cancel_transaction);
  1815. X    signal(SIGQUIT,cancel_transaction);
  1816. X    if(wcreceive(npats,patts)==ERROR)
  1817. X    {
  1818. X        exitcode=0200;
  1819. X        send_cancel(1);
  1820. X    }
  1821. X    mode(0);
  1822. X    if(exitcode && !Zmodem)    /* bellow again with all thy might. */
  1823. X        send_cancel(1);
  1824. X    report_uninit(0);
  1825. X    exit(exitcode);
  1826. X}
  1827. X
  1828. X/* vi: set tabstop=4 shiftwidth=4: */
  1829. X/* end of ecurz.c */
  1830. SHAR_EOF
  1831. $TOUCH -am 1223021690 'z/ecurz.c' &&
  1832. chmod 0644 z/ecurz.c ||
  1833. echo 'restore of z/ecurz.c failed'
  1834. Wc_c="`wc -c < 'z/ecurz.c'`"
  1835. test 41299 -eq "$Wc_c" ||
  1836.     echo 'z/ecurz.c: original size 41299, current size' "$Wc_c"
  1837. true || echo 'restore of z/ecusz.c failed'
  1838. echo End of part 19, continue with part 20
  1839. exit 0
  1840. --------------------------------------------------------------------
  1841. Warren Tucker, TuckerWare emory!n4hgf!wht or wht@n4hgf.Mt-Park.GA.US
  1842. Hacker Extraordinaire  d' async PADs,  pods,  proteins and protocols
  1843.  
  1844. exit 0 # Just in case...
  1845. -- 
  1846. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  1847. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  1848. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  1849. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  1850.