home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #20 / NN_1992_20.iso / spool / comp / sources / misc / 3911 < prev    next >
Encoding:
Text File  |  1992-09-08  |  63.2 KB  |  2,360 lines

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