home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume32 / xbbs / part05 < prev    next >
Encoding:
Text File  |  1992-09-08  |  63.0 KB  |  2,354 lines

  1. Newsgroups: comp.sources.misc
  2. From: sandy@godzilla.Quotron.COM (Sanford Zelkovitz)
  3. Subject:  v32i020:  xbbs - A Bulletin Board System for System V, Part05/11
  4. Message-ID: <1992Sep9.045151.26348@sparky.imd.sterling.com>
  5. X-Md4-Signature: 01b932c0a97eae78bda5e8f13721cce9
  6. Date: Wed, 9 Sep 1992 04:51:51 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: sandy@godzilla.Quotron.COM (Sanford Zelkovitz)
  10. Posting-number: Volume 32, Issue 20
  11. Archive-name: xbbs/part05
  12. Environment: SYSV, Xenix
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then feed it
  16. # into a shell via "sh file" or similar.  To overwrite existing files,
  17. # type "sh file -c".
  18. # Contents:  bbscsumm.c bbscunzip.c sealink/sealink.c
  19. # Wrapped by kent@sparky on Fri Sep  4 12:48:50 1992
  20. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  21. echo If this archive is complete, you will see the following message:
  22. echo '          "shar: End of archive 5 (of 11)."'
  23. if test -f 'bbscsumm.c' -a "${1}" != "-c" ; then 
  24.   echo shar: Will not clobber existing file \"'bbscsumm.c'\"
  25. else
  26.   echo shar: Extracting \"'bbscsumm.c'\" \(4846 characters\)
  27.   sed "s/^X//" >'bbscsumm.c' <<'END_OF_FILE'
  28. X/* bbscsumm.c         2/5/88 */
  29. X/* This code was derived from newest.c by Rick Richardson */
  30. X
  31. X#include <ftw.h>
  32. X#include <sys/types.h>
  33. X#include <sys/stat.h>
  34. X#include <time.h>
  35. X#include <string.h>
  36. X/*
  37. X#include "bbscdef.h"
  38. X*/
  39. Xextern char msg_text[1482];
  40. Xextern char who_am_I[99];
  41. Xextern char who_am_i[99];
  42. Xextern char jnk[2];
  43. Xextern char buf128[384];
  44. Xextern char x_pathandfile[99];
  45. Xextern char f_pathname[99];
  46. Xextern char x_filename[20];
  47. Xextern int toggle;
  48. X
  49. X#define    DAYSIZE    15
  50. X#define    SIZSIZE    11
  51. X#define    SECS    (60L*60L*24L)
  52. X#define    EPOCH    9999999L
  53. X#define CRLF    "\n\r"
  54. X
  55. Xint    unreadable;
  56. Xlong    mtime;
  57. Xlong    atime;
  58. Xlong    Ctime;
  59. Xlong    bigsize;
  60. Xint    files;
  61. Xlong    bytes;
  62. Xint    bigflag;
  63. Xint    timeflag;
  64. Xchar    *base();
  65. Xstatic long    dayvec[] =
  66. X{
  67. X    0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 10L, 20L, 50L, 100L, 200L, 500L, EPOCH
  68. X};
  69. X
  70. Xstatic long    sizvec[] =
  71. X{
  72. X    0L, 1000L, 5000L, 10000L, 20000L, 50000L, 100000L, 200000L, 500000L,
  73. X    1000000L, EPOCH
  74. X};
  75. X
  76. Xint    afiles[DAYSIZE];
  77. Xint    mfiles[DAYSIZE];
  78. Xint    cfiles[DAYSIZE];
  79. Xint    sizfiles[SIZSIZE];
  80. Xlong    now;
  81. X
  82. Xint
  83. Xin(mindays, maxdays, when)
  84. Xlong    mindays, maxdays;
  85. Xlong    when;
  86. X{
  87. X    long    minsecs = mindays * SECS;
  88. X    long    maxsecs = maxdays * SECS;
  89. X
  90. X    if ( (now-when)<maxsecs && (now-when)>=minsecs) return (1);
  91. X    return (0);
  92. X}
  93. X
  94. Xint
  95. Xsiz(minsiz, maxsiz, thissiz)
  96. Xlong    minsiz, maxsiz;
  97. Xlong    thissiz;
  98. X{
  99. X    if ( thissiz<maxsiz && thissiz>=minsiz) return (1);
  100. X    return (0);
  101. X}
  102. X
  103. Xint
  104. Xfn(name, sp, what)
  105. Xchar    *name;
  106. Xregister struct stat    *sp;
  107. X{
  108. X    register int i;
  109. X
  110. X    if (what != FTW_F && what != FTW_D)
  111. X    {
  112. X        ++unreadable;
  113. X        return (0);
  114. X    }
  115. X    bytes += sp->st_size;
  116. X    if (what != FTW_F) return(0);
  117. X    ++files;
  118. X    for (i = 1; i < DAYSIZE; ++i)
  119. X    {
  120. X        if (in(dayvec[i-1], dayvec[i], sp->st_mtime)) mfiles[i]++;
  121. X        if (in(dayvec[i-1], dayvec[i], sp->st_atime)) afiles[i]++;
  122. X        if (in(dayvec[i-1], dayvec[i], sp->st_ctime)) cfiles[i]++;
  123. X    }
  124. X    for (i = 1; i < SIZSIZE; ++i)
  125. X        if (siz(sizvec[i-1], sizvec[i], sp->st_size)) sizfiles[i]++;
  126. X    if (sp->st_mtime>mtime)
  127. X        {mtime = sp->st_mtime; (void)strcpy(who_am_I, name);}
  128. X    if (sp->st_ctime>Ctime)
  129. X        {Ctime = sp->st_ctime; (void)strcpy(x_pathandfile, name);}
  130. X    if (sp->st_atime>atime)
  131. X        {atime = sp->st_atime; (void)strcpy(who_am_i, name);}
  132. X    if (sp->st_size>bigsize)
  133. X        {bigsize = sp->st_size; (void)strcpy(buf128, name);}
  134. X    return (0);
  135. X}
  136. Xsummary()
  137. X{
  138. X    long    time();
  139. X    register int i, c, errflag = 0;
  140. X    portsout("\n\rCompiling statistics summary .........");
  141. X    now = time( (long *) 0);
  142. X    init();
  143. X    walk(f_pathname);
  144. X    stats(f_pathname);
  145. X    graf(afiles, mfiles, cfiles);
  146. X    return (0);
  147. X}
  148. X
  149. Xinit()
  150. X{
  151. X    register int    i;
  152. X
  153. X    unreadable = 0;
  154. X    mtime = 0;
  155. X    atime = 0;
  156. X    Ctime = 0;
  157. X    bigsize = 0;
  158. X    files = 0;
  159. X    bytes = 0;
  160. X    for (i = 1; i < DAYSIZE; ++i)
  161. X    {
  162. X        afiles[i] = 0;
  163. X        mfiles[i] = 0;
  164. X        cfiles[i] = 0;
  165. X    }
  166. X    for (i = 1; i < SIZSIZE; ++i)
  167. X        sizfiles[i] = 0;
  168. X}
  169. X
  170. Xwalk(name)
  171. Xregister char    *name;
  172. X{
  173. X    while (ftw(name, fn, 10) > 0)
  174. X        ;
  175. X}
  176. X
  177. Xstats(name)
  178. Xchar    *name;
  179. X{
  180. X    portsout("\n\r\n\rDirectory:  ");
  181. X    portsout(name);
  182. X    portsout("\n\rNewest access:  ");
  183. X    portsout(base(who_am_i));
  184. X    portsout(" at ");
  185. X    portsout(ctime(&atime));
  186. X    portsout("\n\rNewest modify:  ");
  187. X    portsout(base(who_am_I));
  188. X    portsout(" at ");
  189. X    portsout(ctime(&mtime));
  190. X    portsout("\n\rNewest change:  ");
  191. X    portsout(base(x_pathandfile));
  192. X    portsout(" at ");
  193. X    portsout(ctime(&Ctime));
  194. X    portsout("\n\rLargest file:   ");
  195. X    portsout(base(buf128));
  196. X    portsout(" is ");
  197. X    sprintf(x_filename, "%ld", bigsize);
  198. X    portsout(x_filename);
  199. X    portsout(CRLF);
  200. X    if (unreadable)
  201. X        portsout("\n\r\n\rUnreadable directories/files found\n\r\n\r");
  202. X}
  203. X
  204. Xchar *base(nm)
  205. Xchar *nm;
  206. X{
  207. X    char *ptr;
  208. X    ptr = strrchr(nm, '/');
  209. X    ptr++;
  210. X    return(ptr);
  211. X}
  212. X
  213. Xgraf(avec, mvec, cvec)
  214. Xint    avec[];
  215. Xint    mvec[];
  216. Xint    cvec[];
  217. X{
  218. X    register int    i;
  219. X        for (i = 1; i < DAYSIZE; ++i)
  220. X        {
  221. X            if (dayvec[i] == EPOCH){
  222. X                (void) sprintf(msg_text,
  223. X        "%5ld - EPOCH days: %5d accessed %5d modified %5d changed\n\r",
  224. X                    dayvec[i-1], avec[i], mvec[i], cvec[i]);
  225. X        portsout(msg_text); }
  226. X            else{
  227. X                (void) sprintf(msg_text,
  228. X        "%5ld - %5ld days: %5d accessed %5d modified %5d changed\n\r",
  229. X                    dayvec[i-1], dayvec[i],
  230. X                    avec[i], mvec[i], cvec[i] );
  231. X        portsout(msg_text); }
  232. X        }
  233. X        (void) sprintf(msg_text,
  234. X        "                    %5d TOTAL FILES, %7ld TOTAL BYTES\n\r\n\r",
  235. X            files, bytes);
  236. X        portsout(msg_text);
  237. X
  238. X    if(toggle)
  239. X        {
  240. X        portsout("*** Depress a key to continue .......");
  241. X        portsin(jnk, 1);
  242. X        portsout("\n\r\n\r");
  243. X        }
  244. X        for (i = 1; i < SIZSIZE; ++i)
  245. X        {
  246. X            if (sizvec[i] == EPOCH){
  247. X                (void)sprintf(msg_text,"%7ld -  ULIMIT bytes: %5d files\n\r",
  248. X                    sizvec[i-1], sizfiles[i] );
  249. X                portsout(msg_text); }
  250. X            else{
  251. X                (void)sprintf(msg_text,"%7ld - %7ld bytes: %5d files\n\r",
  252. X                    sizvec[i-1], sizvec[i], sizfiles[i] );
  253. X                portsout(msg_text); }
  254. X        }
  255. X        (void)sprintf(msg_text,"                    %7ld TOTAL BYTES\n\r", bytes);
  256. X        portsout(msg_text);
  257. X    if(toggle)
  258. X        {
  259. X        portsout("\n\r*** Depress a key to continue .......");
  260. X        portsin(jnk, 1);
  261. X        portsout("\n\r\n\r");
  262. X        }
  263. X}
  264. END_OF_FILE
  265.   if test 4846 -ne `wc -c <'bbscsumm.c'`; then
  266.     echo shar: \"'bbscsumm.c'\" unpacked with wrong size!
  267.   fi
  268.   # end of 'bbscsumm.c'
  269. fi
  270. if test -f 'bbscunzip.c' -a "${1}" != "-c" ; then 
  271.   echo shar: Will not clobber existing file \"'bbscunzip.c'\"
  272. else
  273.   echo shar: Extracting \"'bbscunzip.c'\" \(23004 characters\)
  274.   sed "s/^X//" >'bbscunzip.c' <<'END_OF_FILE'
  275. X
  276. X/*
  277. X    If the computer is BIG ENDIAN, remove the comment from the next
  278. X        line.
  279. X#define BIGEND
  280. X*/
  281. X
  282. Xtypedef unsigned char byte;    /* code assumes UNSIGNED bytes */
  283. Xtypedef long longint;
  284. Xtypedef unsigned short word;
  285. Xtypedef char boolean;
  286. X
  287. X#define STRSIZ 256
  288. X#define BSIZE 512
  289. X
  290. X#include <stdio.h>
  291. X#include <ctype.h>
  292. X
  293. X#ifdef __STDC__
  294. X
  295. X#include <stdlib.h>
  296. X
  297. X#else
  298. X
  299. Xchar *malloc();
  300. X
  301. X#endif
  302. X
  303. X#define min(a,b) ((a) < (b) ? (a) : (b))
  304. X
  305. X/*
  306. X * Zipfile layout declarations
  307. X *
  308. X */
  309. X
  310. X#define LONGIP(l) ((longint *) &((l)[0]))
  311. X#define LONGI(l) (*(LONGIP(l)))
  312. X
  313. Xtypedef longint signature_type;
  314. X
  315. X
  316. X#define LOCAL_FILE_HEADER_SIGNATURE  0x04034b50L
  317. X
  318. X
  319. Xtypedef struct local_file_header {
  320. X    word version_needed_to_extract;
  321. X        word general_purpose_bit_flag;
  322. X    word compression_method;
  323. X    word last_mod_file_time;
  324. X    word last_mod_file_date;
  325. X    byte crc32[4];
  326. X    byte compressed_size[4];
  327. X        byte uncompressed_size[4];
  328. X    word filename_length;
  329. X    word extra_field_length;
  330. X} local_file_header;
  331. X
  332. X
  333. X#define CENTRAL_FILE_HEADER_SIGNATURE  0x02014b50L
  334. X
  335. X
  336. Xtypedef struct central_directory_file_header {
  337. X    word version_made_by;
  338. X    word version_needed_to_extract;
  339. X    word general_purpose_bit_flag;
  340. X    word compression_method;
  341. X    word last_mod_file_time;
  342. X    word last_mod_file_date;
  343. X    byte crc32[4];
  344. X    byte compressed_size[4];
  345. X    byte uncompressed_size[4];
  346. X    word filename_length;
  347. X    word extra_field_length;
  348. X    word file_comment_length;
  349. X    word disk_number_start;
  350. X    word internal_file_attributes;
  351. X    byte external_file_attributes[4];
  352. X    byte relative_offset_local_header[4];
  353. X} central_directory_file_header;
  354. X
  355. X
  356. X#define END_CENTRAL_DIR_SIGNATURE  0x06054b50L
  357. X
  358. X
  359. Xtypedef struct end_central_dir_record {
  360. X    word number_this_disk;
  361. X    word number_disk_with_start_central_directory;
  362. X    word total_entries_central_dir_on_this_disk;
  363. X    word total_entries_central_dir;
  364. X    byte size_central_directory[4];
  365. X    byte offset_start_central_directory[4];
  366. X    word zipfile_comment_length;
  367. X} end_central_dir_record;
  368. X
  369. X
  370. Xchar *fnames[2] = {    /* default filenames vector */
  371. X    "*",
  372. X    NULL
  373. X};
  374. Xchar **fnv = &fnames[0];
  375. X
  376. Xint vflag;        /* -v: view directory */
  377. X
  378. Xint members;
  379. Xlongint csize;
  380. Xlongint ucsize;
  381. Xlongint tot_csize;
  382. Xlongint tot_ucsize;
  383. X
  384. X
  385. X/*
  386. X * input file variables
  387. X *
  388. X */
  389. X
  390. X#define INBUFSIZ BUFSIZ        /* same as stdio uses */
  391. Xbyte *inbufchr;            /* input file buffer - any size is legal */
  392. Xbyte *inptr;
  393. X
  394. Xint incnt;
  395. Xword bitbuf;
  396. Xint bits_left;
  397. Xboolean zipeof;
  398. X
  399. Xint zipfd;
  400. Xchar zipfn[STRSIZ];
  401. Xlocal_file_header lrec;
  402. X
  403. X
  404. X/*
  405. X * output stream variables
  406. X *
  407. X */
  408. X
  409. X#define OUTBUFSIZ 0x2000        /* unImplode needs power of 2, >= 0x2000 */
  410. Xbyte *outbufchr;                   /* buffer for rle look-back */
  411. Xbyte *outptr;
  412. X
  413. Xlongint outpos;            /* absolute position in outfile */
  414. Xint outcnt;            /* current position in outbufchr */
  415. X
  416. Xint outfd;
  417. Xchar filename[STRSIZ];
  418. Xchar extra[STRSIZ];
  419. X
  420. X#define DLE 144
  421. X
  422. X
  423. X/* ----------------------------------------------------------- */
  424. X/*
  425. X * shrink/reduce working storage
  426. X *
  427. X */
  428. X
  429. Xint factor;
  430. X
  431. X#define max_bits 13
  432. X#define init_bits 9
  433. X#define hsize 8192
  434. X#define first_ent 257
  435. X#define clear 256
  436. X
  437. X
  438. Xint codesize;
  439. Xint maxcode;
  440. Xint free_ent;
  441. Xint maxcodemax;
  442. Xint offset;
  443. Xint sizex;
  444. X
  445. X
  446. X
  447. X/* ============================================================= */
  448. X/*
  449. X * Host operating system details
  450. X *
  451. X */
  452. X
  453. X/* On some systems the contents of sys/param.h duplicates the
  454. X   contents of sys/types.h, so you don't need (and can't use)
  455. X   sys/types.h. */
  456. X
  457. X#include <sys/types.h>
  458. X#include <sys/param.h>
  459. X#include <time.h>
  460. Xstruct tm *gmtime(), *localtime();
  461. X#define ZSUFX ".zip"
  462. X
  463. X
  464. Xchar *strchr(), *strrchr();
  465. X
  466. Xlong lseek();
  467. X
  468. X#define SEEK_SET  0
  469. X#define SEEK_CUR  1
  470. X#define SEEK_END  2
  471. X
  472. XFILE *zipFILE;
  473. X
  474. X#include <fcntl.h>
  475. X
  476. Xvoid set_file_time()
  477. X /*
  478. X  * set the output file date/time stamp according to information from the
  479. X  * zipfile directory record for this file 
  480. X  */
  481. X
  482. X{
  483. X    time_t times[2];
  484. X    struct tm *tmbuf;
  485. X    long m_time;
  486. X    int yr, mo, dy, hh, mm, ss, leap, days = 0;
  487. X
  488. X
  489. X    yr = (((lrec.last_mod_file_date >> 9) & 0x7f) + 10);  /* dissect date */
  490. X    mo = ((lrec.last_mod_file_date >> 5) & 0x0f);
  491. X    dy = ((lrec.last_mod_file_date & 0x1f) - 1);
  492. X
  493. X    hh = ((lrec.last_mod_file_time >> 11) & 0x1f);        /* dissect time */
  494. X    mm = ((lrec.last_mod_file_time >> 5) & 0x3f);
  495. X    ss = ((lrec.last_mod_file_time & 0x1f) * 2);
  496. X
  497. X    /* leap = # of leap years from 1970 up to but not including
  498. X       the current year */
  499. X
  500. X    leap = ((yr+1969)/4);              /* Leap year base factor */
  501. X
  502. X    /* How many days from 1970 to this year? */
  503. X    days = (yr * 365) + (leap - 492);
  504. X
  505. X    switch(mo)                   /* calculate expired days this year */
  506. X    {
  507. X    case 12:
  508. X        days += 30;
  509. X    case 11:
  510. X        days += 31;
  511. X    case 10:
  512. X        days += 30;
  513. X    case 9:
  514. X        days += 31;
  515. X    case 8:
  516. X        days += 31;
  517. X    case 7:
  518. X        days += 30;
  519. X    case 6:
  520. X        days += 31;
  521. X    case 5:
  522. X        days += 30;
  523. X    case 4:
  524. X        days += 31;
  525. X    case 3:
  526. X        days += 28;                    /* account for leap years */
  527. X        if (((yr+1970) % 4 == 0) && (yr+1970) != 2000)
  528. X            ++days;
  529. X    case 2:
  530. X        days += 31;
  531. X    }
  532. X
  533. X    /* convert date & time to seconds relative to 00:00:00, 01/01/1970 */
  534. X    m_time = ((days + dy) * 86400) + (hh * 3600) + (mm * 60) + ss;
  535. X
  536. X    tmbuf = localtime(&m_time);
  537. X    hh = tmbuf->tm_hour;
  538. X    tmbuf = gmtime(&m_time);
  539. X    hh = tmbuf->tm_hour - hh;
  540. X    if (hh < 0)
  541. X    hh += 24;
  542. X    m_time += (hh * 3600);             /* account for timezone differences */
  543. X
  544. X    times[0] = m_time;             /* set the stamp on the file */
  545. X    times[1] = m_time;
  546. X    utime(filename, times);
  547. X}
  548. X
  549. X
  550. Xint open_input_file()
  551. X /* return non-0 if open failed */
  552. X{
  553. X    /*
  554. X     * open the zipfile for reading and in BINARY mode to prevent cr/lf
  555. X     * translation, which would corrupt the bitstreams 
  556. X     */
  557. X
  558. X    zipfd = open(zipfn, O_RDONLY);
  559. X    return 0;
  560. X}
  561. X
  562. X
  563. X#ifdef BIGEND
  564. X
  565. Xvoid swap_bytes(wordp)
  566. Xword *wordp;
  567. X /* convert intel style 'short int' variable to host format */
  568. X{
  569. X    char *charp = (char *) wordp;
  570. X    char temp;
  571. X
  572. X    temp = charp[0];
  573. X    charp[0] = charp[1];
  574. X    charp[1] = temp;
  575. X}
  576. X
  577. Xvoid swap_lbytes(longp)
  578. Xlongint *longp;
  579. X /* convert intel style 'long' variable to host format */
  580. X{
  581. X    char *charp = (char *) longp;
  582. X    char temp[4];
  583. X
  584. X    temp[3] = charp[0];
  585. X    temp[2] = charp[1];
  586. X    temp[1] = charp[2];
  587. X    temp[0] = charp[3];
  588. X
  589. X    charp[0] = temp[0];
  590. X    charp[1] = temp[1];
  591. X    charp[2] = temp[2];
  592. X    charp[3] = temp[3];
  593. X}
  594. X
  595. X#endif
  596. X
  597. X
  598. X
  599. X/* ============================================================= */
  600. X
  601. Xint readbuf(fd, buf, size)
  602. Xint fd;
  603. Xchar *buf;
  604. Xregister unsigned size;
  605. X{
  606. X    register int count;
  607. X    int n;
  608. X
  609. X    n = size;
  610. X    while (size)  {
  611. X        if (incnt == 0)  {
  612. X            if ((incnt = read(fd, inbufchr, INBUFSIZ)) <= 0)
  613. X                return(incnt);
  614. X            inptr = inbufchr;
  615. X        }
  616. X        count = min(size, incnt);
  617. X        memcpy(buf, inptr, count);
  618. X        buf += count;
  619. X        inptr += count;
  620. X        incnt -= count;
  621. X        size -= count;
  622. X    }
  623. X    return(n);
  624. X}
  625. X
  626. Xint ReadByte(x)
  627. Xword *x;
  628. X /* read a byte; return 8 if byte available, 0 if not */
  629. X{
  630. X    if (csize-- <= 0)
  631. X        return 0;
  632. X    if (incnt == 0)  {
  633. X        if ((incnt = read(zipfd, inbufchr, INBUFSIZ)) <= 0)
  634. X            return 0;
  635. X        inptr = inbufchr;
  636. X    }
  637. X    *x = *inptr++;
  638. X    --incnt;
  639. X    return 8;
  640. X}
  641. X
  642. X
  643. X/* ------------------------------------------------------------- */
  644. Xstatic word mask_bits[] =
  645. X        {0,     0x0001, 0x0003, 0x0007, 0x000f,
  646. X                0x001f, 0x003f, 0x007f, 0x00ff,
  647. X                0x01ff, 0x03ff, 0x07ff, 0x0fff,
  648. X                0x1fff, 0x3fff, 0x7fff, 0xffff
  649. X        };
  650. X
  651. X
  652. Xint FillBitBuffer(bits)
  653. Xregister int bits;
  654. X{
  655. X    /* get the bits that are left and read the next word */
  656. X        register int result = bitbuf;
  657. X    word temp;
  658. X    int sbits = bits_left;
  659. X    bits -= bits_left;
  660. X
  661. X    /* read next word of input */
  662. X    bits_left = ReadByte(&bitbuf);
  663. X    bits_left += ReadByte(&temp);
  664. X    bitbuf |= (temp << 8);
  665. X    if (bits_left == 0)
  666. X        zipeof = 1;
  667. X
  668. X    /* get the remaining bits */
  669. X        result = result | (int) ((bitbuf & mask_bits[bits]) << sbits);
  670. X        bitbuf >>= bits;
  671. X        bits_left -= bits;
  672. X        return result;
  673. X}
  674. X
  675. X#define READBIT(nbits,zdest) { if (nbits <= bits_left) { zdest = (int)(bitbuf & mask_bits[nbits]); bitbuf >>= nbits; bits_left -= nbits; } else zdest = FillBitBuffer(nbits);}
  676. X
  677. X
  678. X/* ------------------------------------------------------------- */
  679. X
  680. Xunsigned long crc32val;
  681. X
  682. Xvoid UpdateCRC();
  683. X
  684. X
  685. X
  686. X/* ----------------------------------------------------------- */
  687. X/*
  688. X * The Reducing algorithm is actually a combination of two
  689. X * distinct algorithms.  The first algorithm compresses repeated
  690. X * byte sequences, and the second algorithm takes the compressed
  691. X * stream from the first algorithm and applies a probabilistic
  692. X * compression method.
  693. X */
  694. X
  695. Xint L_table[] = {0, 0x7f, 0x3f, 0x1f, 0x0f};
  696. X
  697. Xint D_shift[] = {0, 0x07, 0x06, 0x05, 0x04};
  698. Xint D_mask[]  = {0, 0x01, 0x03, 0x07, 0x0f};
  699. X
  700. Xint B_table[] = {8, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5,
  701. X         5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6,
  702. X         6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  703. X         6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
  704. X         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  705. X         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  706. X         7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
  707. X         7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  708. X         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  709. X         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  710. X         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  711. X         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  712. X         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  713. X         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
  714. X         8, 8, 8, 8};
  715. X
  716. X/* ----------------------------------------------------------- */
  717. X
  718. X
  719. X/*
  720. X Length  Method   Size  Ratio   Date    Time   CRC-32    Name
  721. X ------  ------   ----- -----   ----    ----   ------    ----
  722. X  44004  Implode  13041  71%  11-02-89  19:34  88420727  DIFF3.C
  723. X */
  724. X
  725. Xvoid dir_member()
  726. X{
  727. X    char *method;
  728. X    int ratio;
  729. X    int yr, mo, dy, hh, mm;
  730. X
  731. X    yr = (((lrec.last_mod_file_date >> 9) & 0x7f) + 80);
  732. X    mo = ((lrec.last_mod_file_date >> 5) & 0x0f);
  733. X    dy = (lrec.last_mod_file_date & 0x1f);
  734. X
  735. X    hh = ((lrec.last_mod_file_time >> 11) & 0x1f);
  736. X    mm = ((lrec.last_mod_file_time >> 5) & 0x3f);
  737. X
  738. X    switch (lrec.compression_method)  {
  739. X    case 0:
  740. X        method = "Stored";
  741. X        break;
  742. X    case 1:
  743. X        method = "Shrunk";
  744. X        break;
  745. X    case 2:
  746. X        method = "Reduce1";
  747. X        break;
  748. X    case 3:
  749. X        method = "Reduce2";
  750. X        break;
  751. X    case 4:
  752. X        method = "Reduce3";
  753. X        break;
  754. X    case 5:
  755. X        method = "Reduce4";
  756. X        break;
  757. X    case 6:
  758. X        method = "Implode";
  759. X        break;
  760. X    case 7:
  761. X        method = "Token";
  762. X        break;
  763. X    case 8:
  764. X        method = "Deflate";
  765. X        break;
  766. X    default:
  767. X        method = "Unknown";
  768. X        break;
  769. X    }
  770. X
  771. X    if (ucsize != 0)  {
  772. X        ratio = (int) ((1000L * (ucsize    - csize)) / ucsize);
  773. X        if ((ratio % 10) >= 5)
  774. X            ratio += 10;
  775. X    }
  776. X    else
  777. X        ratio = 0;    /* can .zip contain 0-size file? */
  778. X
  779. X    fprintf(zipFILE, "%7ld  %-7s%7ld %3d%%  %02d-%02d-%02d  %02d:%02d  \
  780. X%08lx  %s\n", ucsize, method, csize,
  781. X        ratio / 10, mo, dy, yr, hh, mm,
  782. X        LONGI(lrec.crc32), filename);
  783. X    tot_ucsize += ucsize;
  784. X    tot_csize += csize;
  785. X    ++members;
  786. X}
  787. X
  788. X/* ---------------------------------------------------------- */
  789. X
  790. Xvoid skip_member()
  791. X{
  792. X    register long pos;
  793. X    long endbuf;
  794. X    int offset;
  795. X
  796. X    endbuf = lseek(zipfd, 0L, SEEK_CUR);    /* 1st byte beyond inbufchr */
  797. X    pos = endbuf - incnt;            /* 1st compressed byte */
  798. X    pos += csize;        /* next header signature */
  799. X    if (pos < endbuf)  {
  800. X        incnt -= csize;
  801. X        inptr += csize;
  802. X    }
  803. X    else  {
  804. X        offset = pos % BSIZE;        /* offset within block */
  805. X        pos = (pos / BSIZE) * BSIZE;    /* block start */
  806. X            lseek(zipfd, pos, SEEK_SET);
  807. X        incnt = read(zipfd, inbufchr, INBUFSIZ);
  808. X        incnt -= offset;
  809. X        inptr = inbufchr + offset;
  810. X    }
  811. X}
  812. X
  813. X/* ---------------------------------------------------------- */
  814. X
  815. Xvoid get_string(len, s)
  816. Xint len;
  817. Xchar *s;
  818. X{
  819. X    readbuf(zipfd, s, len);
  820. X    s[len] = 0;
  821. X}
  822. X
  823. X
  824. X/* ---------------------------------------------------------- */
  825. X
  826. Xvoid process_local_file_header(fnamev)
  827. Xchar **fnamev;
  828. X{
  829. X    int extracted;
  830. X
  831. X    readbuf(zipfd, &lrec, sizeof(lrec));
  832. X
  833. X#ifdef BIGEND
  834. X    swap_bytes(&lrec.filename_length);
  835. X    swap_bytes(&lrec.extra_field_length);
  836. X    swap_lbytes(LONGIP(lrec.compressed_size));
  837. X    swap_lbytes(LONGIP(lrec.uncompressed_size));
  838. X    swap_bytes(&lrec.compression_method);
  839. X    swap_bytes(&lrec.version_needed_to_extract);
  840. X        swap_bytes(&lrec.general_purpose_bit_flag);
  841. X    swap_bytes(&lrec.last_mod_file_time);
  842. X    swap_bytes(&lrec.last_mod_file_date);
  843. X        swap_lbytes(LONGIP(lrec.crc32));
  844. X#endif
  845. X    csize = LONGI(lrec.compressed_size);
  846. X    ucsize = LONGI(lrec.uncompressed_size);
  847. X
  848. X    get_string(lrec.filename_length, filename);
  849. X    get_string(lrec.extra_field_length, extra);
  850. X
  851. X    extracted = 0;
  852. X    for (--fnamev; *++fnamev; )  {
  853. X        if (match(filename, *fnamev))  {
  854. X                dir_member();
  855. X            break;
  856. X        }
  857. X    }
  858. X        skip_member();
  859. X}
  860. X
  861. X
  862. X/* ---------------------------------------------------------- */
  863. X
  864. Xvoid process_central_file_header()
  865. X{
  866. X    central_directory_file_header rec;
  867. X    char filename[STRSIZ];
  868. X    char extra[STRSIZ];
  869. X    char comment[STRSIZ];
  870. X
  871. X    readbuf(zipfd, &rec, sizeof(rec));
  872. X
  873. X#ifdef BIGEND
  874. X    swap_bytes(&rec.filename_length);
  875. X    swap_bytes(&rec.extra_field_length);
  876. X    swap_bytes(&rec.file_comment_length);
  877. X#endif
  878. X
  879. X        get_string(rec.filename_length, filename);
  880. X    get_string(rec.extra_field_length, extra);
  881. X    get_string(rec.file_comment_length, comment);
  882. X}
  883. X
  884. X
  885. X/* ---------------------------------------------------------- */
  886. X
  887. Xvoid process_end_central_dir()
  888. X{
  889. X    end_central_dir_record rec;
  890. X    char comment[STRSIZ];
  891. X
  892. X    readbuf(zipfd, &rec, sizeof(rec));
  893. X
  894. X#ifdef BIGEND
  895. X    swap_bytes(&rec.zipfile_comment_length);
  896. X#endif
  897. X
  898. X    /* There seems to be no limit to the zipfile
  899. X       comment length.  Some zipfiles have comments
  900. X       longer than 256 bytes.  Currently no use is
  901. X       made of the comment anyway.
  902. X     */
  903. X#if 0
  904. X    get_string(rec.zipfile_comment_length, comment);
  905. X#endif
  906. X}
  907. X
  908. X
  909. X/* ---------------------------------------------------------- */
  910. X
  911. Xvoid process_headers()
  912. X{
  913. X    int ratio;
  914. X    longint sig;
  915. X
  916. X    if (vflag)  {
  917. X        members = 0;
  918. X        tot_ucsize = tot_csize = 0;
  919. X        fprintf(zipFILE,"\n Length  Method   Size  Ratio   Date    Time   \
  920. XCRC-32    Name\n ------  ------   ----- -----   ----    ----   ------    \
  921. X----\n");
  922. X    }
  923. X
  924. X    while (1) {
  925. X        if (readbuf(zipfd, &sig, sizeof(sig)) != sizeof(sig))
  926. X            return;
  927. X
  928. X#ifdef BIGEND
  929. X        swap_lbytes(&sig);
  930. X#endif
  931. X
  932. X                if (sig == LOCAL_FILE_HEADER_SIGNATURE)
  933. X            process_local_file_header(fnv);
  934. X                else if (sig == CENTRAL_FILE_HEADER_SIGNATURE)
  935. X            process_central_file_header();
  936. X                else if (sig == END_CENTRAL_DIR_SIGNATURE) {
  937. X            process_end_central_dir();
  938. X            break;
  939. X        }
  940. X                else {
  941. X            fprintf(stderr, "Invalid Zipfile Header\n");
  942. X            return;
  943. X        }
  944. X    }
  945. X    if (vflag)  {
  946. X        if (tot_ucsize != 0)  {
  947. X            ratio = (int) ((1000L * (tot_ucsize-tot_csize))
  948. X                    / tot_ucsize);
  949. X            if ((ratio % 10) >= 5)
  950. X                ratio += 10;
  951. X        }
  952. X        else
  953. X            ratio = 0;
  954. X        fprintf(zipFILE, " ------          ------  \
  955. X---                             -------\n\
  956. X%7ld         %7ld %3d%%                             %7d\n",
  957. X        tot_ucsize, tot_csize, ratio / 10, members);
  958. X    }
  959. X}
  960. X
  961. X
  962. X/* ---------------------------------------------------------- */
  963. X
  964. Xvoid process_zipfile()
  965. X{
  966. X    /*
  967. X     * open the zipfile for reading and in BINARY mode to prevent cr/lf
  968. X     * translation, which would corrupt the bitstreams 
  969. X     */
  970. X
  971. X    if (open_input_file())
  972. X        exit(1);
  973. X
  974. X    process_headers();
  975. X
  976. X    close(zipfd);
  977. X}
  978. X
  979. X/* ---------------------------------------------------------- */
  980. Xvoid listzip (fn, port_id)
  981. Xchar *fn;
  982. Xchar *port_id;
  983. X{
  984. X    char *s;
  985. X    int c;
  986. X    char buu[32];
  987. X
  988. X    ++vflag;
  989. X
  990. X    strcpy(zipfn, fn);
  991. X        /* allocate i/o buffers */
  992. X    inbufchr = (byte *) (malloc(INBUFSIZ));
  993. X    outbufchr = (byte *) (malloc(OUTBUFSIZ));
  994. X    if ((inbufchr == NULL) || (outbufchr == NULL)) {
  995. X        fprintf(stderr, "Can't allocate buffers!\n");
  996. X        exit(1);
  997. X    }
  998. X
  999. X        /* do the job... */
  1000. X    sprintf( buu, "/tmp/ziplst.%s", port_id);
  1001. X    zipFILE = fopen( buu, "w" );
  1002. X        process_zipfile();
  1003. X    free(inbufchr);
  1004. X    free(outbufchr);
  1005. X    fclose(zipFILE);
  1006. X}
  1007. X
  1008. X#include <sys/dir.h>
  1009. X#include <ctype.h>
  1010. X
  1011. X#define ASTERISK '*'        /* The '*' metacharacter */
  1012. X#define QUESTION '?'        /* The '?' metacharacter */
  1013. X#define BACK_SLASH '\\'         /* The '\' metacharacter */
  1014. X#define LEFT_BRACKET '['    /* The '[' metacharacter */
  1015. X#define RIGHT_BRACKET ']'    /* The ']' metacharacter */
  1016. X
  1017. X#define IS_OCTAL(ch) (ch >= '0' && ch <= '7')
  1018. X
  1019. Xtypedef short INT;
  1020. Xtypedef short BOOLEAN;
  1021. X#define TRUE 1
  1022. X#define FALSE 0
  1023. X#define EOS '\000'
  1024. X
  1025. Xstatic BOOLEAN do_list();
  1026. Xstatic char nextch();
  1027. Xstatic void list_parse();
  1028. X
  1029. Xint match(string, pattern)
  1030. Xchar *string;
  1031. Xchar *pattern;
  1032. X{
  1033. X    register int ismatch;
  1034. X
  1035. X    ismatch = FALSE;
  1036. X    switch (*pattern)
  1037. X    {
  1038. X    case ASTERISK:
  1039. X        pattern++;
  1040. X        do
  1041. X        {
  1042. X            ismatch = match (string, pattern);
  1043. X        }
  1044. X        while (!ismatch && *string++ != EOS);
  1045. X        break;
  1046. X    case QUESTION:
  1047. X        if (*string != EOS)
  1048. X            ismatch = match (++string, ++pattern);
  1049. X        break;
  1050. X    case EOS:
  1051. X        if (*string == EOS)
  1052. X            ismatch = TRUE;
  1053. X        break;
  1054. X    case LEFT_BRACKET:
  1055. X        if (*string != EOS)
  1056. X            ismatch = do_list (string, pattern);
  1057. X        break;
  1058. X    case BACK_SLASH:
  1059. X        pattern++;
  1060. X    default:
  1061. X    if (toupper(*string) == toupper(*pattern))
  1062. X        {
  1063. X            string++;
  1064. X            pattern++;
  1065. X            ismatch = match (string, pattern);
  1066. X        }
  1067. X        else
  1068. X            ismatch = FALSE;
  1069. X        break;
  1070. X    }
  1071. X    return(ismatch);
  1072. X}
  1073. X
  1074. Xstatic BOOLEAN do_list (string, pattern)
  1075. Xregister char *string;
  1076. Xchar *pattern;
  1077. X{
  1078. X    register BOOLEAN ismatch;
  1079. X    register BOOLEAN if_found;
  1080. X    register BOOLEAN if_not_found;
  1081. X    auto char lower;
  1082. X    auto char upper;
  1083. X
  1084. X    pattern++;
  1085. X    if (*pattern == '!')
  1086. X    {
  1087. X        if_found = FALSE;
  1088. X        if_not_found = TRUE;
  1089. X        pattern++;
  1090. X    }
  1091. X    else
  1092. X    {
  1093. X        if_found = TRUE;
  1094. X        if_not_found = FALSE;
  1095. X    }
  1096. X    ismatch = if_not_found;
  1097. X    while (*pattern != ']' && *pattern != EOS)
  1098. X    {
  1099. X        list_parse(&pattern, &lower, &upper);
  1100. X        if (*string >= lower && *string <= upper)
  1101. X        {
  1102. X            ismatch = if_found;
  1103. X            while (*pattern != ']' && *pattern != EOS) pattern++;
  1104. X        }
  1105. X    }
  1106. X
  1107. X    if (*pattern++ != ']')
  1108. X    {
  1109. X        fprintf(stderr, "Character class error\n");
  1110. X    return;
  1111. X    }
  1112. X    else
  1113. X        if (ismatch)
  1114. X            ismatch = match (++string, pattern);
  1115. X
  1116. X    return(ismatch);
  1117. X}
  1118. X
  1119. Xstatic void list_parse (patp, lowp, highp)
  1120. Xchar **patp;
  1121. Xchar *lowp;
  1122. Xchar *highp;
  1123. X{
  1124. X    *lowp = nextch (patp);
  1125. X    if (**patp == '-')
  1126. X    {
  1127. X        (*patp)++;
  1128. X        *highp = nextch(patp);
  1129. X    }
  1130. X    else
  1131. X        *highp = *lowp;
  1132. X}
  1133. X
  1134. Xstatic char nextch (patp)
  1135. Xchar **patp;
  1136. X{
  1137. X    register char ch;
  1138. X    register char chsum;
  1139. X    register INT count;
  1140. X
  1141. X    ch = *(*patp)++;
  1142. X    if (ch == '\\')
  1143. X    {
  1144. X        ch = *(*patp)++;
  1145. X        if (IS_OCTAL (ch))
  1146. X        {
  1147. X            chsum = 0;
  1148. X            for (count = 0; count < 3 && IS_OCTAL (ch); count++)
  1149. X            {
  1150. X                chsum *= 8;
  1151. X                chsum += ch - '0';
  1152. X                ch = *(*patp)++;
  1153. X            }
  1154. X            (*patp)--;
  1155. X            ch = chsum;
  1156. X        }
  1157. X    }
  1158. X    return(ch);
  1159. X}
  1160. X
  1161. Xlong crc_32_tab[] = {
  1162. X      0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
  1163. X      0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
  1164. X      0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
  1165. X      0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
  1166. X      0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
  1167. X      0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
  1168. X      0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
  1169. X      0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
  1170. X      0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
  1171. X      0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
  1172. X      0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
  1173. X      0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
  1174. X      0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
  1175. X      0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
  1176. X      0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
  1177. X      0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
  1178. X      0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
  1179. X      0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
  1180. X      0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
  1181. X      0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
  1182. X      0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
  1183. X      0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
  1184. X      0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
  1185. X      0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
  1186. X      0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
  1187. X      0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
  1188. X      0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
  1189. X      0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
  1190. X      0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
  1191. X      0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
  1192. X      0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
  1193. X      0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
  1194. X      0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
  1195. X      0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
  1196. X      0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
  1197. X      0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
  1198. X      0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
  1199. X      0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
  1200. X      0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
  1201. X      0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
  1202. X      0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
  1203. X      0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
  1204. X      0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
  1205. X      0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
  1206. X      0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
  1207. X      0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
  1208. X      0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
  1209. X      0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
  1210. X      0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
  1211. X      0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
  1212. X      0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
  1213. X      0x2d02ef8dL
  1214. X   };
  1215. X
  1216. X
  1217. X#define UPDCRC32(res,oct) res=crc_32_tab[(byte)res^(byte)oct] ^ ((res>>8) & 0x00FFFFFFL)
  1218. X
  1219. X/* ------------------------------------------------------------- */
  1220. X
  1221. Xextern unsigned long crc32val;
  1222. X
  1223. Xvoid UpdateCRC(s, len)
  1224. Xregister unsigned char *s;
  1225. Xregister int len;
  1226. X /* update running CRC calculation with contents of a buffer */
  1227. X{
  1228. X    register unsigned long crcval;
  1229. X
  1230. X    crcval = crc32val;
  1231. X        while (len--) {
  1232. X        crcval = crc_32_tab[(byte)crcval ^ (byte)(*s++)]
  1233. X            ^ (crcval >> 8);
  1234. X        }
  1235. X    crc32val = crcval;
  1236. X}
  1237. X
  1238. X
  1239. END_OF_FILE
  1240.   if test 23004 -ne `wc -c <'bbscunzip.c'`; then
  1241.     echo shar: \"'bbscunzip.c'\" unpacked with wrong size!
  1242.   fi
  1243.   # end of 'bbscunzip.c'
  1244. fi
  1245. if test -f 'sealink/sealink.c' -a "${1}" != "-c" ; then 
  1246.   echo shar: Will not clobber existing file \"'sealink/sealink.c'\"
  1247. else
  1248.   echo shar: Extracting \"'sealink/sealink.c'\" \(31816 characters\)
  1249.   sed "s/^X//" >'sealink/sealink.c' <<'END_OF_FILE'
  1250. X/*****************************************************************************
  1251. X *    SEAlink - Sliding window file transfer protocol
  1252. X *
  1253. X *    @(#) sealink.c 2.9 89/03/02 
  1254. X *    UNIX SVR2 and BSD versions by Scott Reynolds
  1255. X *    uucp: clmqt!scott
  1256. X *
  1257. X *    additional SysV modifications by Sanford Zelkovitz, without whose
  1258. X *    help this couldn't have been accomplished
  1259. X *
  1260. X *    Based on:
  1261. X *    MS-DOS Version 1.20, created on 08/05/87 at 17:51:40
  1262. X *   (C)COPYRIGHT 1986, 87 by System Enhancement Associates ALL RIGHTS RESERVED
  1263. X *    By:  Thom Henderson
  1264. X *
  1265. X *    Mr. Henderson had no hand in this UNIX port; please don't bother
  1266. X *    him with questions about this program!
  1267. X *
  1268. X *    Description:
  1269. X *
  1270. X *    The intent of SEAlink is to provide a file transfer protocol that
  1271. X *    does not suffer from propagation delays, such as are introduced
  1272. X *    by satellite relays or packet switched networks.
  1273. X ****************************************************************************/
  1274. X
  1275. X/*
  1276. X * The following flags are for compiling on different systems.
  1277. X */
  1278. X#define SYSV            /* Compile for SYS V i/o calls    */
  1279. X/* #define BSD            /* Compile for BSD i/o calls    */
  1280. X
  1281. X/*
  1282. X * Define NO_MEM if your system doesn't have a
  1283. X * working memset() function
  1284. X */
  1285. X/* #define NO_MEM        /* memset() doesn't work    */
  1286. X
  1287. X/*
  1288. X * Define NO_NAP if there is no nap() function.
  1289. X *
  1290. X * If you use nap() be aware that it causes a MUCH greater load
  1291. X * on the processor.
  1292. X *
  1293. X * With NO_NAP defined the XModem compatibility is reduced; if
  1294. X * this is not a concern, define this for greater efficiency.
  1295. X */
  1296. X#define NO_NAP            /* nap() doesn't work        */
  1297. X
  1298. X/*
  1299. X * Define CRCTABLE to use the fast table lookup CRC calculation;
  1300. X * a slower calculation-based method can be compiled to reduce the
  1301. X * amount of process memory required by commenting this out.
  1302. X */
  1303. X#define    CRCTABLE        /* use CRC lookup table        */
  1304. X
  1305. X/*
  1306. X * The section of code that is compiled when NAKEOT is defined is in the
  1307. X * original MS-DOS version 1.16 code.  Its purpose is to send a NAK when
  1308. X * an EOT is received during rcvfile(), apparently to confirm that this is
  1309. X * indeed the end of file.  However, in certain (apparently non-standard)
  1310. X * versions of the protocol, it is possible that the program will report an
  1311. X * error when in fact there isn't one.  Comment this out at your discretion.
  1312. X */
  1313. X#define NAKEOT                /* define to NAK EOT's        */
  1314. X
  1315. X#include <stdio.h>
  1316. X#include <string.h>
  1317. X#include <ctype.h>
  1318. X#include <signal.h>
  1319. X#include <setjmp.h>
  1320. X#include <sys/ioctl.h>
  1321. X#include <sys/types.h>
  1322. X#include <sys/stat.h>
  1323. X#include <time.h>
  1324. X#ifdef    SYSV            /* use System V I/O control    */
  1325. X#include <termio.h>
  1326. X#endif    /* SYSV */
  1327. X#ifdef    BSD            /* use BSD I/O control        */
  1328. X#include <sgtty.h>
  1329. X#endif    /* BSD */
  1330. X#ifndef    NO_MEM
  1331. X#include <memory.h>
  1332. X#endif    /* NO_MEM */
  1333. X
  1334. X/* Various system constants */
  1335. X#define    WINDOW    6            /* maximum size of window    */
  1336. X#define    S_NAK    0            /* NAK condition for sendack()    */
  1337. X#define    S_ACK    1            /* ACK condition for sendack()    */
  1338. X#define    NONE    0            /* neither send nor receive    */
  1339. X#define    SEND    1            /* send mode            */
  1340. X#define    RECV    2            /* receive mode            */
  1341. X#define    TENYEAR    (time_t) 315532800L    /* GMT offset for 1970 <-> 1980    */
  1342. X
  1343. X/* SEAlink block zero data structure */
  1344. Xstruct zeros
  1345. X{   
  1346. X    long    flen;            /* file length            */
  1347. X    time_t    fstamp;            /* file date/time stamp        */
  1348. X    char    fnam[17];        /* original file name        */
  1349. X    char    prog[15];        /* sending program name        */
  1350. X    char    noacks;            /* true if ACKing not required    */
  1351. X    char    fill[87];        /* reserved for future use    */
  1352. X};
  1353. X
  1354. X/* ASCII mnemonic values */
  1355. X#define    ACK    0x06
  1356. X#define    NAK    0x15
  1357. X#define    SOH    0x01
  1358. X#define    EOT    0x04
  1359. X#define    CAN    0x18
  1360. X
  1361. Xstatic int    outblk;            /* number of next block to send    */
  1362. Xstatic int    ackblk;            /* number of last block ACKed    */
  1363. Xstatic int    blksnt;            /* number of last block sent    */
  1364. Xstatic int    slide;            /* true if sliding window    */
  1365. Xstatic int    ackst;            /* ACK/NAK state        */
  1366. Xstatic int    numnak;            /* number of sequential NAKs    */
  1367. Xstatic int    chktec;            /* 1 = CRC, 0 = checksum        */
  1368. Xstatic int    toterr;            /* total number of errors    */
  1369. Xstatic int    ackrep;            /* true when ACK, NAK reported    */
  1370. Xstatic int    ackseen;        /* count of sliding ACKs seen    */
  1371. Xstatic int    xferdone = 0;        /* done with transfer (recvr)    */
  1372. Xstatic int    debug = 0;        /* debugging flag        */
  1373. Xstatic int    sld_flag = 1;        /* sliding windows allowed    */
  1374. Xstatic int    ackless = 1;        /* true if ACKs not required    */
  1375. Xstatic char    outb[133];        /* block to use for output    */
  1376. X
  1377. X/* the program name MUST be 14 characters plus a '\0' terminator */
  1378. X#ifdef    SYSV
  1379. Xchar    progname[15] = "SEAlink/SYSV  ";
  1380. X#endif    /* SYSV */
  1381. X#ifdef    BSD
  1382. Xchar    progname[15] = "SEAlink/BSD   ";
  1383. X#endif    /* BSD */
  1384. X
  1385. X/* the debug filename is a local preference */
  1386. Xchar    *dbugfile = "/tmp/sealink.log";
  1387. X
  1388. X
  1389. X#ifdef    NO_NAP
  1390. X/*
  1391. X * Need this to do a (very) rough approximation of nap().
  1392. X * Used by alarm() in com_getc()
  1393. X */
  1394. Xjmp_buf    tohere;
  1395. X#endif
  1396. X
  1397. X/* CRC computation logic */
  1398. X#ifdef    CRCTABLE
  1399. Xunsigned short crc_tab[256] =         /* CRC lookup table */
  1400. X{
  1401. X    0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 
  1402. X    0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 
  1403. X    0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 
  1404. X    0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 
  1405. X    0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 
  1406. X    0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 
  1407. X    0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 
  1408. X    0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 
  1409. X    0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 
  1410. X    0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 
  1411. X    0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 
  1412. X    0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 
  1413. X    0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 
  1414. X    0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 
  1415. X    0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 
  1416. X    0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 
  1417. X    0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 
  1418. X    0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 
  1419. X    0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 
  1420. X    0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 
  1421. X    0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 
  1422. X    0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 
  1423. X    0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 
  1424. X    0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 
  1425. X    0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 
  1426. X    0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 
  1427. X    0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 
  1428. X    0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 
  1429. X    0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 
  1430. X    0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 
  1431. X    0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 
  1432. X    0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
  1433. X};
  1434. X
  1435. X/*
  1436. X * crc_update performs CRC calculation using crc_tab[].
  1437. X * Note:  Don't need to "flush" with zeroes with this formula.
  1438. X */
  1439. X#define    crc_update(CRC, C)    ((CRC << 8) ^ crc_tab[(CRC >> 8)^C])
  1440. X#define    crc_finish(CRC)        (CRC)
  1441. X
  1442. X#else    /* otherwise, don't use CRC table */
  1443. X
  1444. Xunsigned short crc_update(crc, c)    /* calculate a CRC value */
  1445. Xregister unsigned    crc;
  1446. Xregister int    c;
  1447. X{
  1448. X    int    count;
  1449. X
  1450. X    for (count = 8; --count >= 0;) {
  1451. X        if (crc & 0x8000) {
  1452. X            crc <<= 1;
  1453. X            crc += (((c <<= 1) & 0400)   !=  0);
  1454. X            crc ^ = 0x1021;
  1455. X        } else {
  1456. X            crc <<= 1;
  1457. X            crc += (((c <<= 1) & 0400)   !=  0);
  1458. X        }
  1459. X    }
  1460. X    return crc;
  1461. X}
  1462. X
  1463. X/* finish CRC calculation by "flushing" with zeroes */
  1464. X#define crc_finish(C)    crc_update(crc_update(C, 0), 0)
  1465. X#endif
  1466. X
  1467. Xunsigned    alarm();
  1468. Xvoid        sendabort();
  1469. Xvoid        shipblk();
  1470. X
  1471. X#ifdef    NO_MEM
  1472. Xchar        *memset();
  1473. X#endif    /* NO_MEM */
  1474. X
  1475. Xmain(argc, argv)
  1476. Xint    argc;
  1477. Xchar    *argv[];
  1478. X{
  1479. X    int        c;        /* used to get options */
  1480. X    int        mode = NONE;    /* SEND, RECV files */
  1481. X    int        noerr;        /* no error in transmission */
  1482. X    char        *fn;        /* current filename to send/recv */
  1483. X    int        getopt();
  1484. X    unsigned    sleep();
  1485. X    int        xmtfile();
  1486. X    char        *rcvfile();
  1487. X    extern int    opterr;        /* used by getopt() */
  1488. X    extern int    optind;        /*        "         */
  1489. X    extern char    *optarg;    /*        "         */
  1490. X#ifdef    SYSV
  1491. X    struct termio    oldtty, tty;
  1492. X#endif /* SYSV */
  1493. X#ifdef    BSD
  1494. X    struct sgttyb    oldtty, tty;
  1495. X#endif /* BSD */
  1496. X
  1497. X    mode = 0;
  1498. X    fn = NULL;
  1499. X    opterr = 0;
  1500. X    while ((c = getopt(argc, argv, "dfors:")) != EOF) {
  1501. X        switch (c) {
  1502. X        case 'd':
  1503. X            debug = 1;    /* use debug file */
  1504. X            break;
  1505. X        case 'f':
  1506. X            sld_flag = 0;    /* no sliding window */
  1507. X            break;
  1508. X        case 'o':
  1509. X            ackless = 0;    /* no overdrive mode */
  1510. X            break;
  1511. X        case 's':
  1512. X            mode = SEND;
  1513. X            fn = optarg;
  1514. X            break;
  1515. X        case 'r':
  1516. X            mode = RECV;
  1517. X            break;
  1518. X        default:
  1519. X            mode = NONE;
  1520. X            break;
  1521. X        }
  1522. X    }
  1523. X    switch (mode) {
  1524. X    case RECV:
  1525. X        fputs("sealink: ready to receive\n", stderr);
  1526. X        break;
  1527. X    case SEND:
  1528. X        fputs("sealink: ready to send\n", stderr);
  1529. X        break;
  1530. X    default:
  1531. X        if (debug)
  1532. X            printf("%s 2.9 sealink.c 89/03/02\n\n", progname);
  1533. X        printf("   SEAlink sliding window file transfer protocol\n");
  1534. X        printf("v1.20  (C) 1986, 1987 System Enhancement Associates\n");
  1535. X        printf("  ALL RIGHTS RESERVED   written by Thom Henderson\n");
  1536. X        printf("      UNIX version written by Scott Reynolds\n\n");
  1537. X        printf("Usage: sealink -[dfo]s filename...\n");
  1538. X        printf("       sealink -[dfo]r [filename...]\n");
  1539. X        printf("Options:\n");
  1540. X        printf("  -d                Debug output to temporary file\n");
  1541. X        printf("  -f                Force no sliding window\n");
  1542. X        printf("  -o                Shut down overdrive mode\n");
  1543. X        printf("  -s filename...    Send the file(s) specified\n");
  1544. X        printf("  -r [filename...]  Receive file(s)\n");
  1545. X        exit(1);
  1546. X    }
  1547. X    if (debug) {
  1548. X        time_t    tim, time();
  1549. X        char    *ctime();
  1550. X
  1551. X        printf("Sending debug output to %s\n", dbugfile);
  1552. X        freopen(dbugfile, "a", stderr); /* open log file */
  1553. X        setbuf(stderr, NULL);
  1554. X        (void) time(&tim);
  1555. X        fputs(ctime(&tim), stderr);
  1556. X    }
  1557. X    fflush(stdout);            /* flush output before anything else */
  1558. X
  1559. X#ifdef    SYSV
  1560. X    (void) ioctl(0, TCGETA, &oldtty);    /* get terminal parameters */
  1561. X    if (debug)
  1562. X        fputs("tty parameters read\n", stderr);
  1563. X    tty = oldtty;            /* copy them, then set new */
  1564. X    tty.c_iflag = IGNBRK;        /* No input filter; ignore break */
  1565. X    tty.c_oflag = 0;            /* Use transparent output */
  1566. X    tty.c_lflag &= ~(ECHO|ICANON|ISIG);    /* disable echo, signals */
  1567. X    tty.c_cc[VMIN] = 0;        /* AT&T Sys V: return immediately */
  1568. X    tty.c_cc[VTIME] = 0;        /*   if no characters can be read */
  1569. X    tty.c_cflag &= ~PARENB;        /* Leave baud rate, disable parity */
  1570. X    tty.c_cflag &= ~CSIZE;        /* reset data bits */
  1571. X    tty.c_cflag |= CS8;        /* set 8 bit data */
  1572. X    (void) ioctl(0, TCSETAW, &tty);    /* go after setting terminal */
  1573. X#endif /* SYSV */
  1574. X#ifdef BSD
  1575. X    (void) ioctl(0, TIOCGETP, &oldtty);    /* get terminal parameters */
  1576. X    if (debug)
  1577. X        fputs("tty parameters read\n", stderr);
  1578. X    tty = oldtty;            /* copy them, then set new */
  1579. X    tty.sg_flags = RAW;        /* raw mode (8 bit, no processing */
  1580. X    (void) ioctl(0, TIOCSETP, &tty);    /* go after setting terminal */
  1581. X#endif /* BSD */
  1582. X    if (debug)
  1583. X        fputs("tty parameters set\n", stderr);
  1584. X
  1585. X    if (mode == SEND) {
  1586. X        do {
  1587. X            if (noerr = xmtfile(fn))
  1588. X                sleep(2);    /* wait a few before next */
  1589. X            if (optind < argc)
  1590. X                fn = argv[optind++];
  1591. X            else
  1592. X                fn = NULL;
  1593. X        } while (noerr && fn  != NULL);
  1594. X        if (noerr)        /* no errors, send end marker */
  1595. X            (void) xmtfile("");
  1596. X    } else {
  1597. X        do {
  1598. X            if (optind < argc)    /* if filename given, use it */
  1599. X                fn = argv[optind++];
  1600. X            else        /* otherwise get one from remote */
  1601. X                fn = "";
  1602. X            if (noerr = (rcvfile(fn)  != NULL))
  1603. X                sleep(2);    /* wait a few before next */
  1604. X        } while (noerr);    /* go until done/err */
  1605. X        noerr = xferdone;    /* set no error if done */
  1606. X    }
  1607. X
  1608. X#ifdef    SYSV
  1609. X    (void) ioctl(0, TCSBRK, 1);    /* Wait for output to drain */
  1610. X    (void) ioctl(0, TCFLSH, 2);    /* Flush input queue */
  1611. X    (void) ioctl(0, TCSETAW, &oldtty);    /* Restore original modes */
  1612. X    (void) ioctl(0, TCXONC, 1);    /* Restart output */
  1613. X#endif /* SYSV */
  1614. X#ifdef    BSD
  1615. X    (void) ioctl(0, TIOCSETP, &oldtty);
  1616. X#endif /* BSD */
  1617. X    if (debug) {
  1618. X        fputs("tty parameters restored\n", stderr);
  1619. X        (void) fclose(stderr);
  1620. X    }
  1621. X
  1622. X    exit(!noerr);            /* and return error status */
  1623. X    /*NOTREACHED*/
  1624. X}
  1625. X
  1626. X/*
  1627. X * chkout() returns non-zero if stdout and stderr are sending to
  1628. X * different files/devices, zero if the same
  1629. X */
  1630. Xint chkout()
  1631. X{
  1632. X    struct stat    so, se;
  1633. X
  1634. X    (void)fstat(1, &so);
  1635. X    (void)fstat(2, &se);
  1636. X    return (so.st_rdev  != se.st_rdev);
  1637. X}
  1638. X
  1639. X#ifdef    NO_NAP
  1640. X/*
  1641. X * alarmint() is called when an alarm signal is caught.
  1642. X */
  1643. Xint alarmint()
  1644. X{
  1645. X    longjmp(tohere, EOF);        /* return EOF to indicate timeout */
  1646. X}
  1647. X#endif    /* NO_NAP */
  1648. X
  1649. X/*
  1650. X * com_getc(timeout) reads a character from file descriptor 0
  1651. X * timeout is in tenths of seconds
  1652. X * EOF returned if no character was available to read
  1653. X *
  1654. X * If timeout is 0, this routine will return immediately regardless of
  1655. X * the status of the read.  If timeout > 0, there will be a minimum of
  1656. X * one to two seconds before returning if nap() does not work.
  1657. X */
  1658. Xint com_getc(timeout)
  1659. Xregister int    timeout;
  1660. X{
  1661. X    static char    byt[2];        /* buffer to read characters into  */
  1662. X
  1663. X#ifdef    BSD
  1664. X    if (!timeout) {            /* if no timeout then no alarms       */
  1665. X        long        len;    /* number of buffered characters   */
  1666. X
  1667. X        (void) ioctl(0, FIONREAD, &len);    /* check buffer       */
  1668. X                    /* read character if available       */
  1669. X        if (len > 0L && read(0, byt, 1) == 1)
  1670. X            return (byt[0] & 0377);    /* return the character       */
  1671. X        return EOF;        /* error or none available       */
  1672. X    }
  1673. X#endif /* BSD */
  1674. X#ifdef    SYSV
  1675. X    if (!timeout) {            /* if no timeout then no alarms       */
  1676. X        if (read(0, byt, 1) == 1)    /* if character was read,  */
  1677. X            return (byt[0] & 0377);    /* return the character       */
  1678. X        return EOF;        /* error or none available       */
  1679. X    }
  1680. X#endif /* SYSV */
  1681. X
  1682. X#ifdef    NO_NAP
  1683. X/* There's a timeout value, so now we get to use alarm() */
  1684. X    timeout = ((timeout-1)/10)+1;    /* round to seconds           */
  1685. X    if (timeout == 1)        /* minimum of 2 seconds for alarm, */
  1686. X        timeout++;        /*   since 1 may not be any delay  */
  1687. X    if (setjmp(tohere)) {        /* if the alarm went off       */
  1688. X        if (debug)        /* timeout message if debugging       */
  1689. X            fputs("Read: timeout\n", stderr);
  1690. X        return EOF;        /* return EOF (longjmp call)       */
  1691. X    }
  1692. X    signal(SIGALRM, alarmint);    /* set up alarm signal catching       */
  1693. X    alarm((unsigned)timeout);    /* set alarm time           */
  1694. X    while (read(0, byt, 1) != 1)    /* Go until we read a character       */
  1695. X        ;            /*   (or the alarm goes off!)       */
  1696. X    alarm(0);            /* reset alarm               */
  1697. X    signal(SIGALRM, SIG_DFL);    /* and turn off signal catching       */
  1698. X    return (byt[0] & 0377);        /* return the character           */
  1699. X#else    /* NO_NAP undefined -- nap() works */
  1700. X    do {
  1701. X        if (read(0, byt, 1) == 1)    /* did we read a char?       */
  1702. X            return (byt[0] & 0377);    /* yes, return it       */
  1703. X        (void) nap(100L);    /* sleep for a little while       */
  1704. X    } while (--timeout);        /* loop until time runs out       */
  1705. X    if (debug)            /* timeout message if debugging       */
  1706. X        fputs("Read: timeout\n", stderr);
  1707. X    return EOF;
  1708. X#endif    /* NO_NAP */
  1709. X}
  1710. X
  1711. X/*  File transmitter logic */
  1712. X
  1713. Xint xmtfile(name)            /* transmit a file */
  1714. Xchar *name;                /* name of file to send */
  1715. X{
  1716. X    FILE    *f, *fopen();        /* file to send */
  1717. X    int    endblk;            /* block number of EOT */
  1718. X    struct stat    fst;        /* data about file */
  1719. X    struct zeros    zero;        /* block zero data */
  1720. X    char    *basename;        /* base filename */
  1721. X
  1722. X    if (name && *name) {        /* if sending a file */
  1723. X        if ((char *)(f = fopen(name, "r")) == NULL) {
  1724. X            fprintf(stderr, "Can't read %s\n", name);
  1725. X            return 0;
  1726. X        }
  1727. X
  1728. X        memset((char *)&zero, 0, sizeof(zero)); /* clear data block */
  1729. X
  1730. X        tzset();
  1731. X        stat(name, &fst);        /* get file information    */
  1732. X        zero.flen = (long)fst.st_size;
  1733. X        zero.fstamp = fst.st_mtime - timezone;    /* adjust f/TZ    */
  1734. X        if (daylight)            /* if daylight savings,    */
  1735. X            zero.fstamp -= 3600L;    /* subtract an hour    */
  1736. X        if (zero.fstamp < 0L)
  1737. X            zero.fstamp = (time_t) 0;
  1738. X        if ((basename = strrchr(name, '/')) == NULL) {
  1739. X            strcpy(zero.fnam, name);
  1740. X        } else {
  1741. X            basename++;
  1742. X            strcpy(zero.fnam, basename);
  1743. X        }
  1744. X        if (debug)
  1745. X            fprintf(stderr, "basename: %s\n", zero.fnam);
  1746. X        strcpy(zero.prog, progname);
  1747. X        zero.noacks = ackless;
  1748. X
  1749. X        endblk = (int)((zero.flen+127L)/128L)+1;
  1750. X    } else {
  1751. X        endblk = 0;        /* fake for no file */
  1752. X        if (debug)
  1753. X            fputs("send transfer complete\n", stderr);
  1754. X    }
  1755. X
  1756. X    outblk = 1;            /* set starting state */
  1757. X    ackblk = (-1);
  1758. X    blksnt = slide = ackst = numnak = toterr = ackrep = ackseen = 0;
  1759. X    chktec = 2;            /* undetermined */
  1760. X
  1761. X    while (ackblk < endblk) {    /* while not all there yet */
  1762. X        if (outblk <= ackblk + ((slide && sld_flag)? WINDOW : 1)) {    
  1763. X            if (outblk < endblk) {    
  1764. X                if (outblk > 0)
  1765. X                    sendblk(f, outblk);
  1766. X                else
  1767. X                    shipblk((unsigned char *)&zero, 0);
  1768. X                if (ackless && slide && sld_flag)
  1769. X                    ackblk = outblk;
  1770. X            } else if (outblk == endblk) {    
  1771. X                outb[0] = EOT;
  1772. X                write(1, outb, 1);
  1773. X                if (debug)
  1774. X                    fputs("sent EOT\n", stderr);
  1775. X            }
  1776. X            outblk++;
  1777. X        }
  1778. X
  1779. X        ackchk();
  1780. X        if (numnak>10)
  1781. X            goto abort;
  1782. X    }
  1783. X
  1784. X    if (endblk)
  1785. X        (void) fclose(f);
  1786. X    if (debug && toterr>2)
  1787. X        fprintf(stderr, "%d errors/%d blocks\n", toterr, blksnt);
  1788. X    return 1;                          /* exit with good status */
  1789. X
  1790. Xabort:
  1791. X    if (endblk)
  1792. X        (void) fclose(f);
  1793. X    if (debug) {
  1794. X        fputs("TRANSMIT ABORTED\n", stderr);
  1795. X        if (toterr)
  1796. X            fprintf(stderr, "%d errors/%d blocks\n", toterr, blksnt);
  1797. X    }
  1798. X    sendabort();
  1799. X    return 0;                          /* exit with bad status */
  1800. X}
  1801. X
  1802. X/*
  1803. X * The various ACK/NAK states are:
  1804. X *  0:   Ground state, ACK or NAK expected.
  1805. X *  1:   ACK received
  1806. X *  2:   NAK received
  1807. X *  3:   ACK, block# received
  1808. X *  4:   NAK, block# received
  1809. X *  5:   Returning to ground state
  1810. X */
  1811. Xstatic ackchk()                /* check for ACK or NAK */
  1812. X{
  1813. X    int    c;            /* one byte of data */
  1814. X    static int    rawblk;        /* raw block number */
  1815. X
  1816. X    ackrep = 0;            /* nothing reported yet */
  1817. X
  1818. X    while ((c = com_getc(0))  != EOF) {
  1819. X        if (c == CAN) {                /* CANcel received? */
  1820. X            if ((c = com_getc(20)) == CAN) {    /* get two  */
  1821. X                numnak = 11;        /* OK, let's abort! */
  1822. X                ackst = 0;
  1823. X                if (debug)
  1824. X                    fputs("received cancel\n", stderr);
  1825. X            }
  1826. X            return;                /* break out of here */
  1827. X        }
  1828. X        if (ackst == 3 || ackst == 4) {        /* Windowed ACK/NAK */
  1829. X            slide = 0;    /* assume this will fail */
  1830. X                    /* see if we believe the number */
  1831. X            if (rawblk == (c^0xff)) {
  1832. X                rawblk = outblk - ((outblk-rawblk)&0xff);
  1833. X                if (rawblk >= 0 && rawblk <= outblk
  1834. X                        && rawblk > outblk-128) {
  1835. X                    /* we have sliding window! */
  1836. X                    if (ackst == 3) {
  1837. X                        ackblk = ackblk > rawblk ? ackblk : rawblk;
  1838. X                        slide = 1;
  1839. X                        if (ackless && ++ackseen>10) {
  1840. X                            ackless = 0;
  1841. X                            if (debug)
  1842. X                                fputs("- Overdrive disengaged\n", stderr);
  1843. X                        }
  1844. X                    } else {    
  1845. X                        outblk = rawblk<0? 0 : rawblk;
  1846. X                        slide = numnak<4;
  1847. X                    }
  1848. X                    if (debug)
  1849. X                        fprintf(stderr, "%s %d == \n", ackst == 3?"ACK":"NAK", rawblk);
  1850. X                    ackrep = 1;  /* we reported something */
  1851. X                }
  1852. X            }
  1853. X            ackst = 5;    /* return to ground state */
  1854. X        }
  1855. X
  1856. X        if (ackst == 1 || ackst == 2) {    
  1857. X            rawblk = c;
  1858. X            ackst += 2;
  1859. X        }
  1860. X
  1861. X        if (!slide || ackst == 0) {    
  1862. X            if (c == ACK) {    
  1863. X                if (!slide) {    
  1864. X                    ackblk++;
  1865. X                    if (debug)
  1866. X                        fprintf(stderr, "ACK %d --\n", ackblk);
  1867. X                    ackrep = 1;    /* reported an ACK */
  1868. X                }
  1869. X                ackst = 1;
  1870. X                numnak = 0;
  1871. X            } else if (c == 'C' || c == NAK) {    
  1872. X                /* if method not determined yet */
  1873. X                if (chktec>1)    /* then do what rcver wants */
  1874. X                    chktec = (c == 'C');
  1875. X#ifdef    SYSV
  1876. X                (void) ioctl(0, TCFLSH, 1); /* purge output */
  1877. X#endif /* SYSV */
  1878. X#ifdef    BSD
  1879. X/* for now this code is commented out.  It causes more complications to have
  1880. X * it installed -- my wish list would include for a BSD ioctl() to purge only
  1881. X * the output, but at the moment things will just have to stay this way. */
  1882. X/*                (void) ioctl(0, TIOCFLUSH, 0); /* purge i/o */
  1883. X#endif /* BSD */
  1884. X                if (!slide) {    
  1885. X                    outblk = ackblk+1;
  1886. X                    if (debug)
  1887. X                        fprintf(stderr, "NAK %d --\n", ackblk+1);
  1888. X                    ackrep = 1;    /* reported a NAK */
  1889. X                }
  1890. X                ackst = 2;
  1891. X                numnak++;
  1892. X                if (blksnt)
  1893. X                    toterr++;
  1894. X            }
  1895. X        }
  1896. X        if (ackst == 5)
  1897. X            ackst = 0;
  1898. X    }
  1899. X}
  1900. X
  1901. Xstatic sendblk(f, blknum)        /* send one block */
  1902. XFILE *f;                /* file to read from */
  1903. Xint blknum;                                /* block to send */
  1904. X{
  1905. X    long        blkloc;        /* address of start of block */
  1906. X    unsigned char    buf[128];    /* one block of data */
  1907. X
  1908. X    if (blknum  != blksnt+1) {    /* if jumping */
  1909. X        blkloc = (long)(blknum-1) * 128L;
  1910. X        fseek(f, blkloc, 0);    /* move where to */
  1911. X    }
  1912. X    blksnt = blknum;
  1913. X
  1914. X    memset(buf, 26, 128);        /* fill buffer with control Zs */
  1915. X    fread(buf, 1, 128, f);        /* read in some data */
  1916. X    shipblk(buf, blknum);        /* pump it out to the receiver */
  1917. X}
  1918. X
  1919. Xstatic void shipblk(blk, blknum)    /* physically ship a block */
  1920. Xunsigned char    *blk;            /* data to be shipped */
  1921. Xint    blknum;                /* number of block */
  1922. X{
  1923. X    register unsigned short    crc = 0;    /* CRC check value */
  1924. X    register int    n;        /* index */
  1925. X    unsigned char    *b = blk;    /* data pointer */
  1926. X
  1927. X    outb[0] = SOH;            /* block header */
  1928. X    outb[1] = blknum;            /* block number */
  1929. X    outb[2] = blknum^0xff;        /* block number check value */
  1930. X
  1931. X    for(n = 0;n < 128;n++) {    /* ship the data */
  1932. X        if (chktec)
  1933. X            crc = crc_update(crc, *b);
  1934. X        else
  1935. X            crc += *b;
  1936. X        outb[n+3] = (*b++);
  1937. X    }
  1938. X    crc = crc_finish(crc);
  1939. X
  1940. X    if (chktec) {            /* send proper check value */
  1941. X        outb[131] = crc>>8;
  1942. X        outb[132] = crc&0xff;
  1943. X        write(1, outb, 133);
  1944. X    } else {
  1945. X        outb[131] = crc&0xff;
  1946. X        write(1, outb, 132);
  1947. X    }
  1948. X
  1949. X    if (debug)
  1950. X        fprintf(stderr, "sent block %d\n", blknum);
  1951. X
  1952. X    return;
  1953. X}
  1954. X
  1955. X/*  File receiver logic */
  1956. X
  1957. Xchar *rcvfile(name)            /* receive file */
  1958. Xchar    *name;                /* name of file */
  1959. X{
  1960. X    int    c;            /* received character        */
  1961. X    int    tries;            /* retry counter        */
  1962. X    int    blknum;            /* desired block number        */
  1963. X    int    inblk;            /* this block number        */
  1964. X    FILE    *f;            /* file to receive to        */
  1965. X    char    buf[128];        /* data buffer            */
  1966. X    char    tmpname[100];        /* name of temporary file    */
  1967. X    static char    outname[100];    /* name of final file        */
  1968. X    struct zeros    zero;        /* file header data storage    */
  1969. X    int    endblk;            /* block number of EOT if known    */
  1970. X    long    left;            /* bytes left to output        */
  1971. X    int    getblock();        /* block receiver, status    */
  1972. X    int    fcopy();        /* copy source file to dest    */
  1973. X    void    setstamp();        /* set date/time stamp of file    */
  1974. X    int    cnvrt;            /* flag -- convert filename?    */
  1975. X    char    *onp;            /* use to convert filename to l/c */
  1976. X
  1977. X    if (name && *name) {        /* figure out a name to use     */
  1978. X        strcpy(outname, name);    /* user supplied one         */
  1979. X        cnvrt = 0;        /* no conversion should be done     */
  1980. X    } else {    
  1981. X        *outname = '\0';    /* get name from transmitter     */
  1982. X        cnvrt = 1;        /* convert to local is necessary */
  1983. X    }
  1984. X
  1985. X    strcpy(tmpname, ".sl.rcv.XXXXXX");    /* template for mktemp() */
  1986. X    mktemp(tmpname);        /* use a unique temp filename     */
  1987. X    if (debug)
  1988. X        fprintf(stderr, "tmpname: %s\n", tmpname);
  1989. X
  1990. X    if (*outname && (f = fopen(outname, "r"))) {    /* open output file */
  1991. X        (void) fclose(f);
  1992. X        if (!(f = fopen(outname, "r+"))) {
  1993. X            if (debug)
  1994. X                fprintf(stderr, "Cannot write %s\n", tmpname);
  1995. X            sendabort();
  1996. X            return NULL;
  1997. X        } else {
  1998. X            (void) fclose(f);
  1999. X        }
  2000. X    }
  2001. X    if (!(f = fopen(tmpname, "w"))) {    /* open temporary file */
  2002. X        if (debug)
  2003. X            fprintf(stderr, "Cannot create %s\n", tmpname);
  2004. X        sendabort();
  2005. X        return NULL;
  2006. X    }
  2007. X
  2008. X    blknum = *outname ? 1 : 0;    /* first block we must get */
  2009. X    tries = -10;            /* kludge for first time around */
  2010. X    chktec = 1;            /* try for CRC error checking */
  2011. X    toterr = 0;            /* no errors yet */
  2012. X    endblk = 0;            /* we don't know the size yet */
  2013. X    ackless = 0;            /* we don't know about this yet */
  2014. X    memset((char *)&zero, 0, sizeof(zero));    /* or much of anything else */
  2015. X
  2016. X/*
  2017. X    if (com_scan() == EOF)        /+ kludge for adaptive Modem7 +/
  2018. X        goto nextblock;
  2019. X*/
  2020. Xnakblock:                /* we got a bad block */
  2021. X    if (blknum>1)
  2022. X        toterr++;
  2023. X    if (++tries>10)
  2024. X        goto abort;
  2025. X    if (tries == 0)            /* if CRC isn't going */
  2026. X        chktec = 0;        /* then give checksum a try */
  2027. X
  2028. X    sendack(S_NAK, blknum);        /* send the NAK */
  2029. X    if (ackless && toterr > 20) {    /* if ackless mode isn't working */
  2030. X        ackless = 0;        /* then shut it off */
  2031. X        if (debug)
  2032. X            fputs("- Overdrive disengaged\n", stderr);
  2033. X    }
  2034. X    goto nextblock;
  2035. X
  2036. Xackblock:                /* we got a good block */
  2037. Xnextblock:                /* start of "get a block" */
  2038. X    while ((c = com_getc(30))  != EOF) {
  2039. X        if (c == CAN)
  2040. X            if ((c = com_getc(30)) == CAN) {
  2041. X                sendabort();
  2042. X                return NULL;
  2043. X            } else
  2044. X                break;
  2045. X        if (c == EOT) {    
  2046. X            if (!endblk || endblk == blknum)
  2047. X                goto endrcv;
  2048. X        } else if (c == SOH) {    
  2049. X            if ((inblk = com_getc(5)) == EOF)
  2050. X                goto nakblock;
  2051. X            if (com_getc(5) == (inblk^0xff)) { 
  2052. X                if (debug)
  2053. X                    fprintf(stderr, "received #%d\n", inblk);
  2054. X                goto blockstart;    /* we found a start */
  2055. X            }
  2056. X        }
  2057. X    }
  2058. X    goto nakblock;
  2059. X
  2060. Xblockstart:                /* start of block detected */
  2061. X    c = blknum&0xff;
  2062. X    if (inblk == 0 && blknum <= 1) {    /* if this is the header */
  2063. X        if (!getblock((char *)&zero)) {    
  2064. X            sendack(S_ACK, inblk);    /* ack the header */
  2065. X            if (!*name)    /* given name takes precedence */
  2066. X                strcpy(outname, zero.fnam);
  2067. X            if (left = zero.flen)    /* length to transfer */
  2068. X                endblk = (int)((left+127L)/128L)+1;
  2069. X            if (ackless != zero.noacks && debug)
  2070. X                fprintf(stderr, "+ Overdrive %sengaged\n", 
  2071. X                    zero.noacks?"":"dis");
  2072. X            ackless = zero.noacks;
  2073. X
  2074. X            blknum = 1;    /* now we want first data block */
  2075. X            goto ackblock;
  2076. X        } else {
  2077. X            goto nakblock;        /* bad header block */
  2078. X        }
  2079. X    } else if (inblk == c) {        /* if this is the one we want */
  2080. X        if (!getblock(buf)) {        /* else if we get it okay */
  2081. X            if (!ackless)        /* if we're sending ACKs */
  2082. X                sendack(S_ACK, inblk);    /* then ACK the data */
  2083. X    /*
  2084. X     * if file size is not known or more than 128 bytes
  2085. X     * to go, write one block (128 bytes) to the file
  2086. X     */
  2087. X            if (!endblk || left >= 128L) {
  2088. X                if (fwrite(buf, 1, 128, f) != 128) {
  2089. X                    if (debug)
  2090. X                        fputs("- WRITE ERROR\n", stderr);
  2091. X                    goto abort;
  2092. X                }
  2093. X                left -= 128L;    /* 128 less to do... */
  2094. X    /*
  2095. X     * we know the size of the file and there are less than
  2096. X     * 128 bytes to write out; only do the necessary amount
  2097. X     */
  2098. X            } else if (left > 0) {
  2099. X                if (fwrite(buf, 1, (unsigned)left, f) != (int)left) {
  2100. X                    if (debug)
  2101. X                        fputs("- WRITE ERROR\n", stderr);
  2102. X                    goto abort;
  2103. X                }
  2104. X                left = 0;    /* and then there were none */
  2105. X            }
  2106. X            tries = 0;        /* reset try count */
  2107. X            blknum++;        /* we want the next block */
  2108. X            goto ackblock;
  2109. X        } else {
  2110. X            goto nakblock;        /* ask for a resend */
  2111. X        }
  2112. X    } else if (inblk < c || inblk > (c + 100)) {    /* if we have it, */
  2113. X        (void) getblock(buf);        /* ignore it */
  2114. X        sendack(S_ACK, inblk);        /* but ack it */
  2115. X        goto ackblock;
  2116. X    } else
  2117. X        goto nextblock;            /* else if running ahead */
  2118. X
  2119. Xendrcv:
  2120. X#ifdef    NAKEOT
  2121. X    sendack(S_NAK, blknum);            /* NAK the EOT, make sure */
  2122. X    if (com_getc(20) != EOT)        /* we're all done */
  2123. X        goto nakblock;
  2124. X#endif /* NAKEOT */
  2125. X    sendack(S_ACK, blknum);            /* ACK it and clean up */
  2126. X    if (debug)
  2127. X        fputs("received EOT\n", stderr);
  2128. X    if (blknum>1) {                /* if we really got anything */
  2129. X        if (debug && toterr>2)
  2130. X            fprintf(stderr, "%d errors/%d blocks\n", toterr, blknum-1);
  2131. X        (void) fclose(f);
  2132. X        (void) unlink(outname);        /* rename temp to proper name */
  2133. X
  2134. X        for (onp = outname;cnvrt && *onp;onp++)
  2135. X                        /* find out if there's lower */
  2136. X            if (islower(*onp))    /* case letters in filename  */
  2137. X                cnvrt = 0;    /*  there are, don't convert */
  2138. X        if (cnvrt)            /* if there aren't, make all */
  2139. X            for (onp = outname;*onp;onp++)    /* into lowercase */
  2140. X                *onp = tolower(*onp);
  2141. X        if (link(tmpname, outname) == 0 || fcopy(tmpname, outname) == 0)
  2142. X            (void) unlink(tmpname);
  2143. X        else if (debug)
  2144. X            fputs("can't rename or copy file\n", stderr);
  2145. X        if (zero.fstamp)        /* set stamp, if known */
  2146. X            setstamp(outname, zero.fstamp);
  2147. X        if (debug)
  2148. X            fprintf(stderr, "received file: %s\n", outname);
  2149. X        return outname;            /* signal what file we got */
  2150. X    } else {                /* else no real file */
  2151. X        (void) fclose(f);
  2152. X        (void) unlink(tmpname);        /* discard empty file */
  2153. X        if (debug)
  2154. X            fputs("received end\n", stderr);
  2155. X        xferdone = 1;            /* signal end of transfer */
  2156. X        return NULL;
  2157. X    }
  2158. X
  2159. Xabort:
  2160. X    if (debug) {
  2161. X        fputs("RECEIVE ABORTED\n", stderr);
  2162. X        if (toterr)
  2163. X            fprintf(stderr, "%d errors/%d blocks\n", toterr, blknum-1);
  2164. X    }
  2165. X    (void) fclose(f);
  2166. X    xferdone = 1;                /* signal end of transfer */
  2167. X    sendabort();
  2168. X    return NULL;
  2169. X}
  2170. X
  2171. Xint fcopy(file1, file2)        /* copy 'file1' to 'file2'    */
  2172. Xchar    *file1;            /* source filename        */
  2173. Xchar    *file2;            /* destination filename        */
  2174. X{
  2175. X    FILE        *f, *t;    /* files from and to        */
  2176. X    long        size;    /* bytes to copy        */
  2177. X    char        *buf;    /* buffer pointer        */
  2178. X    char        *malloc();    /* buffer allocator    */
  2179. X    unsigned int    bufl;    /* buffer length        */
  2180. X    unsigned int    cpy;    /* bytes being copied        */
  2181. X    struct stat    fst;    /* data about file        */
  2182. X
  2183. X    if (stat(file1, &fst))    /* get file information    */
  2184. X        return EOF;
  2185. X    size = (long)fst.st_size;
  2186. X
  2187. X    if ((char *)(f = fopen(file1, "r")) == NULL)
  2188. X        return EOF;
  2189. X    if ((char *)(t = fopen(file2, "w")) == NULL) {
  2190. X        (void) fclose(f);
  2191. X        return EOF;
  2192. X    }
  2193. X
  2194. X    bufl = 32760;
  2195. X    if (bufl > size)
  2196. X        bufl = size;    /* don't waste space */
  2197. X
  2198. X    while (bufl >= 128 && (buf = malloc(bufl)) == NULL)
  2199. X        bufl >>= 1;    /* keep trying until it's hopeless    */
  2200. X    if (buf == NULL) {    /* if we can't get a buffer, clean up    */
  2201. X        (void) fclose(f);
  2202. X        (void) fclose(t);
  2203. X        (void) unlink(file2);
  2204. X        return EOF;    /* return an error indication        */
  2205. X    }
  2206. X
  2207. X    while (size > 0) {
  2208. X        cpy = fread(buf, sizeof(char),
  2209. X            bufl < size ? bufl : (unsigned short) size, f);
  2210. X        if (fwrite(buf, sizeof(char), cpy, t) != cpy)
  2211. X            break;
  2212. X        size -= cpy;
  2213. X    }
  2214. X
  2215. X    free(buf);
  2216. X    (void) fclose(f);
  2217. X    (void) fclose(t);
  2218. X    return (size > 0);
  2219. X}
  2220. X
  2221. Xstatic void setstamp(f_name, f_time)    /* set a file's date/time stamp    */
  2222. Xchar    *f_name;            /* file to set stamp on        */
  2223. Xlong    f_time;                /* desired date/time        */
  2224. X{
  2225. X    void    tzset();        /* library time zone function    */
  2226. X    time_t    times[2], time();
  2227. X
  2228. X    times[0] = time((time_t *) 0);
  2229. X    tzset();
  2230. X    times[1] = f_time + TENYEAR + timezone;    /* convert time        */
  2231. X    if (daylight)                /* if daylight savings,    */
  2232. X        times[1] += 3600L;        /* add an hour        */
  2233. X    utime(f_name, times);
  2234. X}
  2235. X
  2236. Xstatic int sendack(acknak, blknum)    /* send an ACK or a NAK */
  2237. Xregister int    acknak;            /* 1 = ACK, 0 = NAK */
  2238. Xregister int    blknum;            /* block number */
  2239. X{
  2240. X    if (debug)
  2241. X        fprintf(stderr, "%s %d\n", acknak?"ACK":"NAK", blknum);
  2242. X    if (acknak)            /* send the right signal */
  2243. X        outb[0] = ACK;
  2244. X    else if (chktec)
  2245. X        outb[0] = 'C';
  2246. X    else
  2247. X        outb[0] = NAK;
  2248. X
  2249. X    outb[1] = blknum;        /* block number */
  2250. X    outb[2] = blknum^0xff;        /* block number check */
  2251. X    write(1, outb, 3);
  2252. X}
  2253. X
  2254. Xstatic int getblock(buf)        /* read a block of data */
  2255. Xchar    *buf;                /* data buffer */
  2256. X{
  2257. X    register unsigned short    ourcrc = 0;    /* remote CRC check value */
  2258. X    unsigned short    hiscrc;            /* remote CRC check value */
  2259. X    register int    c;            /* one byte of data */
  2260. X    int    n;                /* index */
  2261. X    int    timeout = ackless ? 200 : 5;    /* short block timeout */
  2262. X
  2263. X    for(n = 0; n<128; n++) {    
  2264. X        if ((c = com_getc(timeout)) == EOF) {
  2265. X            if (debug)
  2266. X                fputs("block received -- short\n", stderr);
  2267. X            return 1;
  2268. X        }
  2269. X        if (chktec)
  2270. X            ourcrc = crc_update(ourcrc, (unsigned char) c);
  2271. X        else
  2272. X            ourcrc += c;
  2273. X        *buf++ = (unsigned char) c;
  2274. X    }
  2275. X
  2276. X    if (chktec) {    
  2277. X        ourcrc = crc_finish(ourcrc);
  2278. X        c = com_getc(timeout);
  2279. X        hiscrc = (c << 8) | com_getc(timeout);
  2280. X    } else {    
  2281. X        ourcrc &= 0xff;
  2282. X        hiscrc = com_getc(timeout) & 0xff;
  2283. X    }
  2284. X
  2285. X    if (debug) {
  2286. X        if (ourcrc == hiscrc)
  2287. X            fputs("block received -- good\n", stderr);
  2288. X        else {
  2289. X            fprintf(stderr, "block received -- bad %s\n", chktec?"CRC":"checksum");
  2290. X            fprintf(stderr, "his = 0x%x  ours = 0x%x\n", hiscrc, ourcrc);
  2291. X        }
  2292. X    }
  2293. X    if (ourcrc == hiscrc)
  2294. X        return 0;        /* block is good */
  2295. X    else
  2296. X        return 1;        /* error in checksum or CRC */
  2297. X}
  2298. X
  2299. Xvoid sendabort()
  2300. X{
  2301. X#ifdef    SYSV
  2302. X    (void) ioctl(0, TCFLSH, 1);    /* purge output */
  2303. X#endif /* SYSV */
  2304. X#ifdef    BSD
  2305. X    (void) ioctl(0, TIOCFLUSH, 0);    /* purge all i/o */
  2306. X#endif /* BSD */
  2307. X    strcpy(outb, "\030\030\030\030\030\030\030\030\b\b\b\b\b\b\b\b");
  2308. X    strcat(outb, "\030\030\030\030\b\b\b\b");    /* set up cancel seq */
  2309. X    write(1, outb, (unsigned)strlen(outb));    /* write it out */
  2310. X}
  2311. X
  2312. X#ifdef    NO_MEM
  2313. X/*
  2314. X *    This routine replicates the function found in the
  2315. X *    System V memory.h module for systems without a proper
  2316. X *    or with no implementation of this function available.
  2317. X */
  2318. Xchar *memset(m, n, c)
  2319. Xchar    *m;
  2320. Xint    n;
  2321. Xchar    c;
  2322. X{
  2323. X    int    i;
  2324. X    for (i = 0;i < n;i++)
  2325. X        *(m+i) = c;
  2326. X    return m;
  2327. X}
  2328. X#endif /* NO_MEM */
  2329. END_OF_FILE
  2330.   if test 31816 -ne `wc -c <'sealink/sealink.c'`; then
  2331.     echo shar: \"'sealink/sealink.c'\" unpacked with wrong size!
  2332.   fi
  2333.   # end of 'sealink/sealink.c'
  2334. fi
  2335. echo shar: End of archive 5 \(of 11\).
  2336. cp /dev/null ark5isdone
  2337. MISSING=""
  2338. for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
  2339.     if test ! -f ark${I}isdone ; then
  2340.     MISSING="${MISSING} ${I}"
  2341.     fi
  2342. done
  2343. if test "${MISSING}" = "" ; then
  2344.     echo You have unpacked all 11 archives.
  2345.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2346. else
  2347.     echo You still must unpack the following archives:
  2348.     echo "        " ${MISSING}
  2349. fi
  2350. exit 0
  2351. exit 0 # Just in case...
  2352.