home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume13 / tipx / part02 < prev    next >
Text File  |  1990-05-29  |  42KB  |  1,760 lines

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