home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume18 / fnet / part04 < prev    next >
Encoding:
Internet Message Format  |  1989-03-05  |  59.9 KB

  1. Subject:  v18i005:  Fido/Usenet gateway, Part04/05
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Heikki Suonsivu <hsu@santra.hut.fi>
  7. Posting-number: Volume 18, Issue 5
  8. Archive-name: fnet/part04
  9.  
  10. #!/bin/sh
  11. # this is part 4 of a multipart archive
  12. # do not concatenate these parts, unpack them in order with /bin/sh
  13. # file fio.c continued
  14. #
  15. CurArch=4
  16. if test ! -r s2_seq_.tmp
  17. then echo "Please unpack part 1 first!"
  18.      exit 1; fi
  19. ( read Scheck
  20.   if test "$Scheck" != $CurArch
  21.   then echo "Please unpack part $Scheck next!"
  22.        exit 1;
  23.   else exit 0; fi
  24. ) < s2_seq_.tmp || exit 1
  25. echo "x - Continuing file fio.c"
  26. sed 's/^X//' << 'SHAR_EOF' >> fio.c
  27. X{
  28. X  nchars = 0;
  29. X}
  30. SHAR_EOF
  31. echo "File fio.c is complete"
  32. chmod 0644 fio.c || echo "restore of fio.c fails"
  33. echo "x - extracting xtsend.c (Text)"
  34. sed 's/^X//' << 'SHAR_EOF' > xtsend.c &&
  35. X#ifndef lint
  36. Xstatic char *sccsid = "@(#)%M%  %I%  Teemu Torma %H%";
  37. X#endif
  38. X
  39. X/* Send file(s) unsing Xmodem/TeLink/MODEM7 Batch protocols.
  40. X
  41. X   @(#)Copyright (c) 1987 by Teemu Torma
  42. X
  43. X   Permission is given to distribute this program and alter this code as
  44. X   needed to adapt it to forign systems provided that this header is
  45. X   included and that the original author's name is preserved. */
  46. X
  47. X/* LINTLIBRARY */
  48. X
  49. X#include <stdio.h>
  50. X#include <sys/types.h>
  51. X#include <sys/stat.h>
  52. X#include <string.h>
  53. X#include <time.h>
  54. X#include "fnet.h"
  55. X#include "fio.h"
  56. X#include "crc.h"
  57. X
  58. Xextern time_t time();
  59. Xextern int readline();
  60. Xextern void sendline();
  61. X
  62. X/* General macros to check timeouts. */
  63. X
  64. X#define SetStart()      (stime = time((long *) NULL))
  65. X#define Timeout(t)      (time((long *) NULL) - stime > (t))
  66. X#define BytesSend       (block * BlockSize)
  67. X
  68. X/* General states for finite state machines. These are used to break
  69. X   loops mostly. */
  70. X
  71. X#define Error           (-1)    /* error state */
  72. X#define Done            (-2)    /* state to break loops */
  73. X
  74. X/* XMODEM/TeLink send states. */
  75. X
  76. X#define WaitTeLnk       (0)
  77. X#define WaitStart       (1)
  78. X#define SendBlock       (2)
  79. X#define WaitACK         (3)
  80. X#define WaitEnd         (4)
  81. X
  82. X/* BATCH File sender states. */
  83. X
  84. X#define MoreFiles       (0)
  85. X#define CheckFNm        (1)
  86. X#define CheckFile       (2)
  87. X#define EndSend         (3)
  88. X
  89. X/* States for MODEM7 filename sender. */
  90. X
  91. X#define WaitNak         (0)
  92. X#define WaitChAck       (1)
  93. X#define WaitCksm        (2)
  94. X
  95. X/* Return filename for MS-DOS. Because MS-DOS has many restrictions in
  96. X   filenames (that silly dot in between), we must use something equivalent
  97. X   while sending TeLink. */
  98. X
  99. Xchar *
  100. Xconver_to_msdos_name(filename)
  101. X     char *filename;
  102. X{
  103. X  static char msdos_name[16];
  104. X  register int pos;
  105. X  register char *cp;
  106. X
  107. X  /* strip off pathname */
  108. X  cp = basename(filename);
  109. X
  110. X  /* ignore leading dot */
  111. X  if (*cp == '.')
  112. X    cp++;
  113. X
  114. X  /* create first 8 characters of ms-dos name */
  115. X  for (pos = 0; *cp && *cp != '.' && pos < 8; pos++, cp++)
  116. X    msdos_name[pos] = *cp;
  117. X
  118. X  /* add dot for ms-dos */
  119. X  msdos_name[pos] = '.';
  120. X
  121. X  /* add 3 character type */
  122. X  for (pos = 9; *cp && *cp != '.' && pos < 12; pos++, cp++)
  123. X    msdos_name[pos] = *cp;
  124. X
  125. X  /* null terminate ms-dos name */
  126. X  msdos_name[pos] = 0;
  127. X
  128. X  debug(2, "File %s changed to %s in MS-DOS", filename, msdos_name);
  129. X  return msdos_name;
  130. X}
  131. X
  132. X/* Create special TeLink block. This block will be send as block 0 before
  133. X   all other data will be sent. Return false if it couldn't be created,
  134. X   otherwise true. */
  135. X
  136. Xbool
  137. Xmaketelnk(filename, buffer)
  138. X     char *filename, *buffer;
  139. X{
  140. X  struct stat stbuf;
  141. X  register int cnt;
  142. X  register char *cp;
  143. X
  144. X  /* get status of file */
  145. X  if (stat(filename, &stbuf) == -1)
  146. X    {
  147. X      log("$Cannot stat %s", filename);
  148. X      return False;
  149. X    }
  150. X
  151. X  /* save file length */
  152. X  for (cnt = 0; cnt < 4; cnt++)
  153. X    buffer[cnt] = (stbuf.st_size >> (cnt * 8)) & 0377;
  154. X
  155. X  /* creation time and date will be all zeroes */
  156. X  for (cnt = 4; cnt < 8; cnt++)
  157. X    buffer[cnt] = 0;
  158. X
  159. X  /* save file name */
  160. X  for (cnt = 8, cp = /*msdosname(*/ filename /*)*/ ; *cp; cp++, cnt++)
  161. X    buffer[cnt] = *cp;
  162. X
  163. X  /* if name was shorter that 16 chars, fill rest of it with blanks */
  164. X  while (cnt < 24)
  165. X    buffer[cnt++] = ' ';
  166. X
  167. X  /* don't know why here's zero */
  168. X  buffer[cnt] = 0;
  169. X
  170. X  /* name of sending program... let's ignore */
  171. X  for (cnt = 25; cnt < 41; cnt++)
  172. X    buffer[cnt] = 0;
  173. X  strcpy(&buffer[25], PROGRAMNAME);
  174. X
  175. X  /* crc mode */
  176. X
  177. X  buffer[41] = 1;
  178. X
  179. X  /* rest of buffer will be full of zeroes */
  180. X  for (cnt = 42; cnt < 128; cnt++)
  181. X    buffer[cnt] = 0;
  182. X  return True;
  183. X}
  184. X
  185. X/* Send block to line. Note that intial SOH or SYN is not sent by
  186. X   this routine. */
  187. X
  188. Xvoid
  189. Xxtsendblk(sxbuf, blocknum, crcmode)
  190. X     char *sxbuf;
  191. X     int blocknum;
  192. X     bool crcmode;
  193. X{
  194. X  register unsigned short crc;
  195. X  register int checksum, cnt;
  196. X
  197. X  debug(1, "Send block %d", blocknum);
  198. X
  199. X  /* send block number */
  200. X  sendline(blocknum & 0377);
  201. X  sendline(~(blocknum & 0377));
  202. X
  203. X  /* send the block itself */
  204. X  debug(1, "Send %d bytes", BlockSize);
  205. X  (void) write(line, sxbuf, BlockSize);
  206. X
  207. X  /* count crc and checksum */
  208. X  for (crc = 0, checksum = 0, cnt = 0; cnt < BlockSize; cnt++)
  209. X    {
  210. X      crc = updcrc(sxbuf[cnt], crc);
  211. X      checksum += sxbuf[cnt];
  212. X    }
  213. X
  214. X  if (crcmode)
  215. X    {
  216. X      /* send crc */
  217. X      /* crc = updcrc(0, updcrc(0, crc)); /* What is this for? */
  218. X      debug(1, "Send crc %d", crc);
  219. X      sendline((int) (crc >> 8));
  220. X      sendline((int) crc);
  221. X    }
  222. X  else
  223. X    {
  224. X      /* send checksum */
  225. X      debug(1, "send checksum %d", checksum & 0377);
  226. X      sendline(checksum & 0377);
  227. X    }
  228. X}
  229. X
  230. X/* Send file using XMODEM/TeLink protocol. Return True is everything went
  231. X   fine, otherwise false. */
  232. X
  233. Xbool
  234. Xxtsend(filename, telink)
  235. X     char *filename;
  236. X     bool telink;
  237. X{
  238. X  int state = telink ? WaitTeLnk : WaitStart;
  239. X  struct stat st;
  240. X  time_t stime;
  241. X  int tries, c;
  242. X  char sxbuf[BlockSize];
  243. X  FILE *fp;
  244. X  bool resend = False, lastblock = False;
  245. X  int block = 1, cnt;
  246. X  bool crcmode = True;
  247. X
  248. X  if ((fp = fopen(filename, "r")) == NULL)
  249. X    log("$Can not open %s, sending empty file", filename);
  250. X  else
  251. X    log("Sending %s", filename);
  252. X
  253. X  (void) stat(filename, &st);
  254. X
  255. X  while (state >= WaitTeLnk && state <= WaitEnd)
  256. X    switch (state)
  257. X      {
  258. X      case WaitTeLnk:
  259. X        if (!maketelnk(filename, sxbuf))
  260. X          {
  261. X            log("Unable to send file %s", filename);
  262. X            state = Error;
  263. X          }
  264. X        else
  265. X          {
  266. X            SetStart();
  267. X            for (tries = 0; state == WaitTeLnk; tries++)
  268. X              {
  269. X                if ((c = readline(40)) == NAK || c == 'C')
  270. X                  {
  271. X                    crcmode = c == 'C';
  272. X                    debug(2, "Got %02x, sending TeLink block", c);
  273. X                    sendline(SYN);
  274. X            /* telink block always has checksum */
  275. X                    xtsendblk(sxbuf, 0, False);
  276. X                  }
  277. X                else if (c == ACK)
  278. X                  {
  279. X                    state = WaitStart;
  280. X                    debug(2, "Got ACK, TeLink block sent ok");
  281. X                  }
  282. X        else if (c == NAK)
  283. X          {
  284. X            if (tries > 2)
  285. X              {
  286. X            log("Too many tries on telink block");
  287. X            state = WaitStart;
  288. X              }
  289. X            /* If other stuff, not ack/nak received, just ignore */
  290. X          }
  291. X                else if (Timeout(40))
  292. X                  {
  293. X                    log("Timeout on telink block");
  294. X                    state = WaitStart;
  295. X                  }
  296. X              }
  297. X          }
  298. X        break;
  299. X      case WaitStart:
  300. X        SetStart();
  301. X        for (tries = 0; state == WaitStart; tries++)
  302. X          if ((c = readline(60)) == NAK || c == 'C')
  303. X            {
  304. X          debug(1, "Got NAK, sendblock start");
  305. X              crcmode = True; /* c == 'C'; */
  306. X              state = SendBlock;
  307. X            }
  308. X      else if (Timeout(60))
  309. X            {
  310. X              log("Timeout on xmodem start");
  311. X              state = Error;
  312. X            }
  313. X      else if (tries > 20)
  314. X        {
  315. X          debug(1, "Too many retries on xmodem start");
  316. X          state = Error;
  317. X        }
  318. X        break;
  319. X      case SendBlock:
  320. X        if (!resend)
  321. X          if (lastblock || !fp)
  322. X            {
  323. X              sendline(EOT);
  324. X              state = WaitEnd;
  325. X            }
  326. X          else {
  327. X            for (cnt = 0; cnt < BlockSize; cnt++)
  328. X              {
  329. X                if ((c = getc(fp)) == EOF) {
  330. X                  c = CTRLZ;
  331. X                  lastblock = True;
  332. X                }
  333. X                sxbuf[cnt] = c;
  334. X              }
  335. X            sendline(SOH);
  336. X            xtsendblk(sxbuf, block, crcmode);
  337. X            state = WaitACK;
  338. X          }
  339. X        else {
  340. X          sendline(SOH);
  341. X          xtsendblk(sxbuf, block, crcmode);
  342. X          state = WaitACK;
  343. X          resend = False;
  344. X        }
  345. X        break;
  346. X      case WaitACK:
  347. X        SetStart();
  348. X        for (tries = 0; state == WaitACK; tries++)
  349. X          if ((c = readline(60)) == NAK)
  350. X            {
  351. X              resend = True;
  352. X              state = SendBlock;
  353. X          debug(1, "Got NAK, resend current block");
  354. X          if (tries >= 10)
  355. X        {
  356. X          log("Too many tries on xmodem send");
  357. X          state = Error;
  358. X        }
  359. X            }
  360. X          else if (c == ACK)
  361. X            {
  362. X              debug(1, "Got ACK, send next block");
  363. X              block++;
  364. X              debug(2, "%ld bytes send (%d %%)", BytesSend,
  365. X                    (BytesSend / st.st_size) * 100);
  366. X              state = SendBlock;
  367. X            }
  368. X          else if (Timeout(60))
  369. X            {
  370. X              log("Xodem send timeout");
  371. X              state = Error;
  372. X            }
  373. X        break;
  374. X      case WaitEnd:
  375. X        for (tries = 0; state == WaitEnd; tries++)
  376. X          if ((c = readline(60)) == NAK)
  377. X            {
  378. X              sendline(EOT);
  379. X              debug(2, "Send EOT");
  380. X            }
  381. X          else if (c == ACK)
  382. X            {
  383. X              log("Xmodem/TeLink send successful");
  384. X              state = Done;
  385. X            }
  386. X          else if (Timeout(60))
  387. X            {
  388. X              log("Timeout on xmodem/telink end");
  389. X              state = Error;
  390. X            }
  391. X          else if (tries >= 10)
  392. X            {
  393. X              log("Too many retries on xmodem end");
  394. X              state = Error;
  395. X            }
  396. X        break;
  397. X      }
  398. X
  399. X  return state == Error ? False : True;
  400. X}
  401. X
  402. X/* Send MODEM7 filename. */
  403. X
  404. Xbool
  405. Xsendmdmfn(filename)
  406. X     char *filename;
  407. X{
  408. X  int state = WaitNak;
  409. X  time_t stime;
  410. X  int tries = 0;
  411. X  int c, checksum, cnt;
  412. X
  413. X  SetStart();
  414. X  while (state >= WaitNak && state <= WaitCksm)
  415. X    switch (state)
  416. X      {
  417. X      case WaitNak:
  418. X        for (tries = 0; state == WaitNak; )
  419. X          if ((c = readline(60)) == NAK)
  420. X            {
  421. X              debug(2, "Got NAK for filename %s", filename);
  422. X              sendline(ACK);
  423. X              sendline(*filename);
  424. X              cnt = 1;
  425. X              state = WaitChAck;
  426. X            }
  427. X          else if (Timeout(60))
  428. X            {
  429. X              debug(1, "Timeout on filename");
  430. X              state = Error;
  431. X            }
  432. X          else if (tries >= 20)
  433. X            {
  434. X              debug(1, "Too many retries on filename");
  435. X              state = Error;
  436. X            }
  437. X        break;
  438. X      case WaitChAck:
  439. X        if (readline(2) == ACK)
  440. X          {
  441. X            if (filename[cnt])
  442. X              sendline(filename[cnt++]);
  443. X            else
  444. X              {
  445. X                sendline(SUB);
  446. X                state = WaitCksm;
  447. X              }
  448. X          }
  449. X        else
  450. X          {
  451. X            sendline('u');
  452. X            tries++;
  453. X            state = WaitNak;
  454. X          }
  455. X        break;
  456. X      case WaitCksm:
  457. X        if ((c = readline(2)) == TIMEOUT)
  458. X          {
  459. X            sendline('u');
  460. X            tries++;
  461. X            state = WaitNak;
  462. X          }
  463. X        else
  464. X          {
  465. X            for (cnt = 0, checksum = SUB; filename[cnt]; cnt++)
  466. X              checksum += filename[cnt];
  467. X            if (c != (checksum & 0377))
  468. X              {
  469. X                debug(1, "Checksum error in filename");
  470. X                sendline('u');
  471. X                state = WaitNak;
  472. X                tries++;
  473. X              }
  474. X            else
  475. X              {
  476. X                sendline(ACK);
  477. X                debug(2, "Filename sent ok");
  478. X                state = Done;
  479. X              }
  480. X          }
  481. X        break;
  482. X      }
  483. X
  484. X  return state != Error;
  485. X}
  486. X
  487. X/* Batch file sender. If filename is NULL, no more files to send. */
  488. X
  489. Xbool
  490. Xbatchsend(filename)
  491. X     char *filename;
  492. X{
  493. X  int state = MoreFiles;
  494. X  int c;
  495. X  time_t stime;
  496. X  bool ok;
  497. X
  498. X  while (state >= MoreFiles && state <= EndSend)
  499. X    switch (state)
  500. X      {
  501. X      case MoreFiles:
  502. X        if (filename)
  503. X          {
  504. X            debug(2, "Sending filename for %s", filename);
  505. X            ok = sendmdmfn(filename);
  506. X            state = CheckFNm;
  507. X          }
  508. X        else
  509. X          state = EndSend;
  510. X        break;
  511. X      case CheckFNm:
  512. X        if (ok)
  513. X          {
  514. X            debug(1, "Sending file %s", filename);
  515. X            ok = xtsend(filename, True);
  516. X            state = CheckFile;
  517. X          }
  518. X        else
  519. X          state = Error;
  520. X        break;
  521. X      case CheckFile:
  522. X        if (ok)
  523. X          {
  524. X            debug(1, "File send ok");
  525. X            state = Done;
  526. X          }
  527. X        else
  528. X          {
  529. X            log("TeLink file send failed");
  530. X            state = Error;
  531. X          }
  532. X        break;
  533. X      case EndSend:
  534. X        SetStart();
  535. X        while (!Timeout(10))
  536. X          if ((c = readline(10)) == NAK || c == 'C')
  537. X            {
  538. X              sendline(EOT);
  539. X              log("Batch file send ok");
  540. X              state = Done;
  541. X              break;
  542. X            }
  543. X        if (state != Done)
  544. X          {
  545. X            log("Batch file send failed, no NAK");
  546. X            sendline(EOT);
  547. X            state = Error;
  548. X          }
  549. X        break;
  550. X      }
  551. X
  552. X  return state != Error;
  553. X}
  554. SHAR_EOF
  555. chmod 0644 xtsend.c || echo "restore of xtsend.c fails"
  556. echo "x - extracting xtrec.c (Text)"
  557. sed 's/^X//' << 'SHAR_EOF' > xtrec.c &&
  558. X#ifndef lint
  559. Xstatic char *sccsid = "@(#)%M%  %I%  Teemu Torma %H%";
  560. X#endif
  561. X
  562. X/* Receive file(s) using Xmodem/TeLink/MODEM7 Batch protocols.
  563. X
  564. X   @(#)Copyright (c) 1987 by Teemu Torma
  565. X
  566. X   Permission is given to distribute this program and alter this code as
  567. X   needed to adapt it to forign systems provided that this header is
  568. X   included and that the original author's name is preserved. */
  569. X
  570. X#include <stdio.h>
  571. X#include <sys/types.h>
  572. X#include <string.h>
  573. X#include "hsu.h"
  574. X#include "fnet.h"
  575. X#include "fio.h"
  576. X#include "crc.h"
  577. X
  578. Xextern time_t time();
  579. X
  580. X/* Macros to check timeouts */
  581. X
  582. X#define Timeout(t)      (time((long *) NULL) - stime > t)
  583. X#define SetStart()      (stime = time((long *) NULL))
  584. X
  585. X/* General error states to break the loops. */
  586. X
  587. X#define Error           (-1)
  588. X#define Done            (-2)
  589. X
  590. X/* States for XMODEM/TeLink receiver. */
  591. X
  592. X#define RecStart        (0)
  593. X#define WaitFirst       (1)
  594. X#define WaitBlock       (2)
  595. X
  596. X/* States for BATCH file receiver. */
  597. X
  598. X#define RecvName        (0)
  599. X#define CheckFNm        (1)
  600. X#define CheckFile       (2)
  601. X
  602. X/* States for MODEM7 filename receiver. */
  603. X
  604. X#define SendNak         (0)
  605. X#define WaitAck         (1)
  606. X#define WaitChar        (2)
  607. X#define WaitOkCk        (3)
  608. X
  609. Xstatic received_block_number = 0;
  610. Xint receiving_data = FALSE;
  611. X
  612. Xbool
  613. Xxtrecblk(rxbuf, blocknum, crcmode)
  614. X     char *rxbuf;
  615. X     int blocknum;
  616. X     bool crcmode;
  617. X{
  618. X  register int c, cnt, checksum;
  619. X  register unsigned short crc;
  620. X
  621. X  if (blocknum == -1)
  622. X    debug(1, "Receiving block ignoring block number");
  623. X  else
  624. X    debug(1, "Receiving block %d", blocknum);
  625. X
  626. X  received_block_number = blocknum;
  627. X
  628. X  if ((c = readline(10)) == TIMEOUT || c != (blocknum & 0377))
  629. X    {
  630. X      if (c == TIMEOUT)
  631. X        debug(1, "Timeout on block number receive");
  632. X      else
  633. X    {
  634. X      if (blocknum == -1)
  635. X        if (c == 0 || c == 1) /* Both telink and xmodem allowed */
  636. X          {
  637. X        blocknum = c;
  638. X        received_block_number = blocknum;
  639. X        debug(1, "Setting blocknum to %d", blocknum);
  640. X        goto blockok;
  641. X          }
  642. X
  643. X      debug(1, "Bad block number %d, expected %d", c, blocknum & 0377);
  644. X    }
  645. X      goto blidge;
  646. X    }
  647. X
  648. X blockok:
  649. X  if ((c = readline(10)) == TIMEOUT || c != (~blocknum & 0377))
  650. X    {
  651. X      if (c == TIMEOUT)
  652. X        debug(1, "Timeout on complement block number receive");
  653. X      else
  654. X        debug(1, "Bad ~block number %d, expected %d", c, (~blocknum & 0377));
  655. X      goto blidge;
  656. X    }
  657. X
  658. X  receiving_data = TRUE;
  659. X  for (crc = 0, checksum = 0, cnt = 0; cnt < BlockSize; cnt++)
  660. X    if ((c = readline(5)) == TIMEOUT)
  661. X      {
  662. X        debug(1, "Timeout while receiving block");
  663. X    receiving_data = FALSE;
  664. X        goto blidge;
  665. X      }
  666. X    else
  667. X      {
  668. X        checksum += c;
  669. X        crc = updcrc(c, crc);
  670. X        rxbuf[cnt] = c;
  671. X      }
  672. X  receiving_data = FALSE;
  673. X  debug(5, "Received %d bytes", BlockSize);
  674. X
  675. X  if (crcmode)
  676. X    {
  677. X      if (readline(10) != (int) ((crc >> 8) & 0377)
  678. X          || readline(10) != (int) (crc & 0377))
  679. X        {
  680. X          debug(1, "Crc error");
  681. X          goto blidge;
  682. X        }
  683. X    }
  684. X  else
  685. X    {
  686. X      if (readline(10) != (checksum & 0377))
  687. X        {
  688. X          debug(1, "Checksum error");
  689. X          goto blidge;
  690. X        }
  691. X    }
  692. X  return True;
  693. X
  694. X blidge:
  695. X  debug(1, "Fail, Skipping rest of the block");
  696. X  while (readline(1) != TIMEOUT)
  697. X    /* skip rest of the block */;
  698. X  return False;
  699. X}
  700. X
  701. Xbool
  702. Xxtrec(filename, xmodem)
  703. X     char *filename;
  704. X     int xmodem;
  705. X{
  706. X  int state = RecStart;
  707. X  time_t stime;
  708. X  int tries = 0;
  709. X  bool crcmode = True;
  710. X  FILE *fp;
  711. X  char rxbuf[BlockSize];
  712. X  int cnt, block = 1, c;
  713. X
  714. X  if ((fp = fopen(filename, "w")) == NULL)
  715. X    {
  716. X      log("$Unable to open %s for writing", filename);
  717. X      return False;
  718. X    }
  719. X  log("Receive file %s", filename);
  720. X  SetStart();
  721. X  while (state >= RecStart && state <= WaitBlock)
  722. X    switch (state)
  723. X      {
  724. X      case RecStart:
  725. X    debug(1,"Send %s", crcmode ? "C" : "NAK");
  726. X        sendline(crcmode ? 'C' : NAK);
  727. X    sendline(0);
  728. X    sendline(~0);
  729. X        state = WaitFirst;
  730. X        break;
  731. X      case WaitFirst:
  732. X        if (tries > 10 || Timeout(60))
  733. X          {
  734. X            if (tries > 10)
  735. X              log("Too many tries on xmodem receive");
  736. X            else
  737. X              log("Timeout on xmodem receive start");
  738. X            state = Error;
  739. X          }
  740. X        else if ((c = readline(10)) == EOT)
  741. X          {
  742. X            sendline(ACK);
  743. X            log("No file to receive");
  744. X            state = Done;
  745. X          }
  746. X        else if (c == SYN || c == SOH) /* Probably telink block? */
  747. X          {
  748. X            debug(1, "Startup in %s mode", crcmode ? "crc" : "checksum");
  749. X            if (!xtrecblk(rxbuf, -1 /* c == SYN ? 0 : 1 */ , crcmode))
  750. X              {
  751. X        debug(1, "Retry, bad block");
  752. X                tries++; /* No valid block received */
  753. X        state = RecStart;
  754. X#ifdef NEEDED
  755. X        block = 1; /* Bad block, ignore? */
  756. X                state = WaitBlock;
  757. X#endif
  758. X              }
  759. X            else
  760. X              {
  761. X                if (c == SOH && received_block_number == 1)
  762. X                  {
  763. X                    for (cnt = 0; cnt < BlockSize; cnt++)
  764. X                      (void) putc(c, fp);
  765. X                    block = 2;
  766. X                    debug(2, "Block written onto disk");
  767. X                  }
  768. X                else if (c == SYN || received_block_number == 0)
  769. X                  {
  770. X            sendline(ACK); /* Tell sender we got it */
  771. X            sendline(0);
  772. X            sendline(~0);
  773. X                    block = 1;
  774. X                    debug(1, "TeLink block ignored");
  775. X                  }
  776. X        else
  777. X          {
  778. X            debug(1, "Retry, bad block");
  779. X            tries++;
  780. X            state = RecStart;
  781. X          }
  782. X                state = WaitBlock;
  783. X              }
  784. X          }
  785. X        else if (c == TIMEOUT || c == TSYNCH) /* Tsynch ? Maybe it... */
  786. X          {
  787. X            debug(1, "Timout on Xmodem rcv start");
  788. X            tries++;
  789. X            state = RecStart;
  790. X          }
  791. X        else if (tries > 3 || Timeout(30))
  792. X          {
  793. X        log("Try checksum mode");
  794. X            crcmode = False;
  795. X            state = RecStart;
  796. X        sleep(1);
  797. X          }
  798. X        break;
  799. X      case WaitBlock:
  800. X        SetStart();
  801. X        for (tries = 0; state == WaitBlock; tries++)
  802. X      if (tries > 10 || Timeout(60))
  803. X        {
  804. X          if (tries > 10)
  805. X        log("Too many retries (%d) on %s", tries, filename);
  806. X          else
  807. X        log("Timeout on receive %s, tries %d", filename, tries);
  808. X          state = Error;
  809. X        }
  810. X      else if ((c = readline(10)) == EOT)
  811. X        {
  812. X          log("File %s received ok", filename);
  813. X          state = Done;
  814. X        }
  815. X      else if (c == SOH)
  816. X        {
  817. X          if (xtrecblk(rxbuf, block, crcmode))
  818. X        {
  819. X          for (cnt = 0; cnt < BlockSize; cnt++)
  820. X            (void) putc(rxbuf[cnt], fp);
  821. X          debug(2, "Block written onto disk, tries %d", tries);
  822. X          sendline(ACK);
  823. X          sendline(block);
  824. X          sendline(~block);
  825. X          block++;
  826. X          tries = 0;
  827. X          SetStart();
  828. X        }
  829. X          else
  830. X        {
  831. X          debug(1, "Block not received correctly, tries %d", tries);
  832. X          sendline(NAK);
  833. X          sendline(block);
  834. X          sendline(~block);
  835. X          tries++;
  836. X        }
  837. X        }
  838. X      else if (c == TIMEOUT)
  839. X        {
  840. X          debug(1, "Timeout on block %d, tries %d", block, tries);
  841. X          sendline(NAK);
  842. X          sendline(block);
  843. X          sendline(~block);
  844. X          tries++;
  845. X        }
  846. X      else
  847. X        tries = 0; /* Trash from send-ahead... skip it */
  848. X
  849. X      }
  850. X
  851. X  (void) fclose(fp);
  852. X
  853. X  return state != Error;
  854. X}
  855. X
  856. Xint
  857. Xrecmdmfn(filename)
  858. X     char *filename;
  859. X{
  860. X  int state = SendNak;
  861. X  time_t stime;
  862. X  int tries = 0, c, pos;
  863. X
  864. X  SetStart();
  865. X  while (state >= SendNak && state <= WaitOkCk)
  866. X    switch (state)
  867. X      {
  868. X      case SendNak:
  869. X        if (tries > 20)
  870. X          {
  871. X            log("Too many tries to get filename");
  872. X            state = Error;
  873. X          }
  874. X        else if (Timeout(60))
  875. X          {
  876. X            log("Timeout while getting filename");
  877. X            state = Error;
  878. X          }
  879. X        else
  880. X          {
  881. X            sendline(NAK);
  882. X            state = WaitAck;
  883. X            tries++;
  884. X          }
  885. X        break;
  886. X      case WaitAck:
  887. X        switch (readline(5))
  888. X          {
  889. X          case ACK:
  890. X            pos = 0;
  891. X            state = WaitChar;
  892. X            break;
  893. X          case EOT:
  894. X            pos = 0;
  895. X            state = Done;
  896. X            break;
  897. X          case TIMEOUT:
  898. X            debug(2, "Timout while waiting ACK/EOT on MDM7");
  899. X            state = SendNak;
  900. X            break;
  901. X          default:
  902. X            state = SendNak;
  903. X            debug(2, "Garbage on line while getting filename");
  904. X            (void) sleep((unsigned) 1);
  905. X            flush();
  906. X            break;
  907. X          }
  908. X        break;
  909. X      case WaitChar:
  910. X        switch (c = readline(1))
  911. X          {
  912. X          case EOT:
  913. X            pos = 0;
  914. X            debug(2, "Got EOT in middle of filename, no files left");
  915. X            state = Done;
  916. X            break;
  917. X          case SUB:
  918. X            filename[pos] = 0;
  919. X            debug(2, "Got fn %s, sending checksum", filename);
  920. X            for (pos = 0, c = SUB; filename[pos]; pos++)
  921. X              c += filename[pos];
  922. X            sendline(c & 0377);
  923. X            state = WaitOkCk;
  924. X            break;
  925. X          case 'u':
  926. X            debug(2, "Got 'u', send NAK again");
  927. X            state = SendNak;
  928. X            break;
  929. X          case TIMEOUT:
  930. X            debug(2, "Timeout while waiting char of filename");
  931. X            state = SendNak;
  932. X            break;
  933. X          default:
  934. X            filename[pos++] = c;
  935. X            debug(3, "Got char '%c' of filename", c);
  936. X            break;
  937. X          }
  938. X        break;
  939. X      case WaitOkCk:
  940. X        if (readline(1) == ACK)
  941. X          {
  942. X            debug(1, "Got filename %s ok", filename);
  943. X            state = Done;
  944. X          }
  945. X        else
  946. X          {
  947. X            debug(1, "Checksum faiure in filename %s", filename);
  948. X            state = SendNak;
  949. X          }
  950. X        break;
  951. X      }
  952. X
  953. X  return state == Error ? -1 : pos ? 1 : 0;
  954. X}
  955. X
  956. Xbool
  957. Xbatchrec(filename)
  958. X     char *filename;
  959. X{
  960. X  int state = RecvName;
  961. X  char filen[100];
  962. X  int ok;
  963. X  if (!filename) filename = filen;
  964. X
  965. X  while (state >= RecvName && state <= CheckFile)
  966. X    switch (state)
  967. X      {
  968. X      case RecvName:
  969. X        ok = recmdmfn(filename);
  970. X        state = CheckFNm;
  971. X        break;
  972. X      case CheckFNm:
  973. X        switch (ok)
  974. X          {
  975. X          case -1:
  976. X            debug(1, "Abort batch receive");
  977. X            state = Error;
  978. X            break;
  979. X          case 0:
  980. X            log("All files received successfully");
  981. X            state = Done;
  982. X            break;
  983. X          case 1:
  984. X            ok = xtrec(filename, FALSE);
  985. X            state = CheckFile;
  986. X          }
  987. X        break;
  988. X      case CheckFile:
  989. X        if (ok)
  990. X          {
  991. X            debug(1, "%s received successfully", filename);
  992. X            state = RecvName;
  993. X          }
  994. X        else
  995. X          {
  996. X            log("Batch receive aborted, %s not received", filename);
  997. X            state = Error;
  998. X          }
  999. X        break;
  1000. X      }
  1001. X
  1002. X  return state != Error;
  1003. X}
  1004. SHAR_EOF
  1005. chmod 0644 xtrec.c || echo "restore of xtrec.c fails"
  1006. echo "x - extracting nodelist.c (Text)"
  1007. sed 's/^X//' << 'SHAR_EOF' > nodelist.c &&
  1008. X#ifndef lint
  1009. Xstatic char *sccsid = "@(#)%M%  %I%  Teemu Torma %H%";
  1010. X#endif
  1011. X
  1012. X/* Routines to get and translate information in nodelist.
  1013. X
  1014. X   @(#)Copyright (c) 1987 by Teemu Torma
  1015. X
  1016. X   Permission is given to distribute this program and alter this code as
  1017. X   needed to adapt it to forign systems provided that this header is
  1018. X   included and that the original author's name is preserved. */
  1019. X
  1020. X/*
  1021. X  Sat Oct  8 17:36:11 1988
  1022. X  Rewrote nodelist index handling and reading. Now index is kept
  1023. X  in memory, and has zones also.
  1024. X  */
  1025. X
  1026. X/* LINTLIBRARY */
  1027. X
  1028. X#include <stdio.h>
  1029. X#include <string.h>
  1030. X#include <unistd.h>
  1031. X#include <errno.h>
  1032. X#include <ctype.h>
  1033. X#include <malloc.h>
  1034. X#include <values.h>
  1035. X#include <sys/types.h>
  1036. X#include <sys/stat.h>
  1037. X#include "hsu.h"
  1038. X#include "config.h"
  1039. X#include "fnet.h"
  1040. X#include "nodelist.h"
  1041. X
  1042. Xextern long atol();
  1043. XNode originnode;
  1044. XNODEINDEX *nodeindex = NULL;
  1045. XNAMEINDEX *nameindex = NULL;
  1046. Xint nodes, names, compile_zone, compile_region, compile_net;
  1047. X
  1048. Xfine_convert(name)
  1049. X     char *name;
  1050. X{
  1051. X  int wasspace = TRUE;
  1052. X
  1053. X  for (; *name; name++)
  1054. X    {
  1055. X      if (*name == '_') *name = ' ';
  1056. X      if (isspace(*name))
  1057. X    wasspace = TRUE;
  1058. X      else if (wasspace)
  1059. X    {
  1060. X      *name = toupper(*name);
  1061. X      wasspace = FALSE;
  1062. X    }
  1063. X      else
  1064. X    *name = tolower(*name);
  1065. X    }
  1066. X}
  1067. X
  1068. X/* Strip bad chars from names, ie chars not which may be dangerous in
  1069. X   different networks. Currectly removes all non-alphanumeric chars,
  1070. X   but leaves whitespace alone. Strips 8bit chars also. */
  1071. X
  1072. Xstripbad(name)
  1073. X     char *name;
  1074. X{
  1075. X  char *d;
  1076. X
  1077. X  d = alloca(strlen(name) + 1);
  1078. X  strcpy(d, name);
  1079. X  for (; *d; d++) if (isalpha(*d) || isspace(*d) || strchr("-._", *d))
  1080. X    *name++ = *d;
  1081. X
  1082. X  *name = *d; /* Terminating null, result can be shorter */
  1083. X}
  1084. X
  1085. X/* Compare two strings, considering '_' and ' ', and converting
  1086. X   {|}[\] to aoaAOA instead, and ignoring case.
  1087. X
  1088. X   ascii_convert(string) does conversion.
  1089. X   */
  1090. X
  1091. Xchar *ascii_convert(s)
  1092. X     char *s;
  1093. X{
  1094. X  char *p;
  1095. X
  1096. X  p = s;
  1097. X  while (*s) {
  1098. X    switch (*s) {
  1099. X     case '_':
  1100. X      *s = ' ';
  1101. X      break;
  1102. X     case '{':
  1103. X     case '}':
  1104. X     case '[':
  1105. X     case ']':
  1106. X      *s = 'a';
  1107. X      break;
  1108. X     case '|':
  1109. X     case '\\':
  1110. X      *s = 'o';
  1111. X      break;
  1112. X     default:
  1113. X      *s = tolower(*s);
  1114. X    }
  1115. X    s++;
  1116. X  }
  1117. X  return p;
  1118. X}
  1119. X
  1120. Xstricmp(d, s)
  1121. X     char *d, *s;
  1122. X{
  1123. X  char ds[BUFSIZ], ss[BUFSIZ];
  1124. X
  1125. X  return strcmp(ascii_convert(strcpy(ds, d)),
  1126. X        ascii_convert(strcpy(ss, s)));
  1127. X}
  1128. X
  1129. Xstrnicmp(d, s, n)
  1130. X     char *d, *s;
  1131. X     int n;
  1132. X{
  1133. X  return strncmp(ascii_convert(strcpy(alloca(strlen(d) + 2), d)),
  1134. X         ascii_convert(strcpy(alloca(strlen(s) + 2), s)), n);
  1135. X}
  1136. X
  1137. X/* Compare nodelist index entry (for qsort) */
  1138. Xcmpnodeindex(node1, node2)
  1139. X     NODEINDEX *node1, *node2;
  1140. X{
  1141. X  if (node1->zone < node2->zone) return -1;
  1142. X  if (node1->zone > node2->zone) return 1;
  1143. X  if (node1->net < node2->net) return -1;
  1144. X  if (node1->net > node2->net) return 1;
  1145. X  if (node1->node < node2->node) return -1;
  1146. X  if (node1->node > node2->node) return 1;
  1147. X  return 0; /* Same node */
  1148. X}
  1149. X
  1150. Xcmpnameindex(name1, name2)
  1151. X     NAMEINDEX *name1, *name2;
  1152. X{
  1153. X  int n;
  1154. X  n = stricmp(name1->name, name2->name);
  1155. X  /* debug(9, "name1 %s name2 %s = %d", name1->name, name2->name, n); */
  1156. X  return n;
  1157. X}
  1158. X
  1159. X/* Read file in to a buffer allocating buffer for it */
  1160. X
  1161. Xlong read_file(buffer, name)
  1162. X     char **buffer, *name;
  1163. X{
  1164. X  FILE *fp;
  1165. X  long size = 0;
  1166. X
  1167. X  if (fp = fopen(name, "r")) {
  1168. X    fseek(fp, 0L, SEEK_END);
  1169. X    size = ftell(fp);
  1170. X
  1171. X    /* Apparently we are on 16-bit? */
  1172. X    if (size > MAXINT)
  1173. X      {
  1174. X    log("Brain damaged CPU architecture reading file?");
  1175. X    size = 0;
  1176. X    goto out;
  1177. X      }
  1178. X
  1179. X    fseek(fp, 0L, SEEK_SET);
  1180. X
  1181. X    if (*buffer)
  1182. X      *buffer = realloc( *buffer, (unsigned) size);
  1183. X    else
  1184. X      *buffer = malloc( (unsigned) size);
  1185. X
  1186. X    debug(2, "Reading %d bytes from %s", size, name);
  1187. X    if (fread( *buffer, 1, (int) size, fp) != size) size = 0;
  1188. X    fclose(fp);
  1189. X  }
  1190. X
  1191. X out:
  1192. X  return size;
  1193. X}
  1194. X
  1195. Xwrite_file(buffer, name, size)
  1196. X     char *buffer, *name;
  1197. X     int size;
  1198. X{
  1199. X  FILE *fp;
  1200. X  int rvalue = 0;
  1201. X
  1202. X  if (fp = fopen(name, "w+"))
  1203. X    {
  1204. X      debug(2, "Writing %d bytes to %s", size, name);
  1205. X      if (fwrite(buffer, 1, size, fp) != size) rvalue = -1;
  1206. X      fclose(fp);
  1207. X    }
  1208. X
  1209. X  return rvalue;
  1210. X}
  1211. X
  1212. Xread_nodeindex()
  1213. X{
  1214. X  nodes = read_file( (char **) &nodeindex,
  1215. X            sprintfs("%s/%s", LIBDIR, INODELIST)) / sizeof(NODEINDEX);
  1216. X  return nodes == 0L;
  1217. X}
  1218. X
  1219. Xread_nameindex()
  1220. X{
  1221. X  names = read_file( (char **) &nameindex,
  1222. X            sprintfs("%s/%s", LIBDIR, NAMELIST)) / sizeof(NAMEINDEX);
  1223. X  return names == 0L;
  1224. X}
  1225. X
  1226. Xwrite_nodeindex()
  1227. X{
  1228. X  return write_file( (char *) nodeindex,
  1229. X            sprintfs("%s/%s", LIBDIR, INODELIST),
  1230. X            (int) (nodes * sizeof(NODEINDEX)));
  1231. X}
  1232. X
  1233. Xwrite_nameindex()
  1234. X{
  1235. X  return write_file( (char *) nameindex,
  1236. X            sprintfs("%s/%s", LIBDIR, NAMELIST),
  1237. X            (int) (names * sizeof(NAMEINDEX)));
  1238. X}
  1239. X
  1240. X/* Make nodelist's index-file. That index-file will be used to search
  1241. X   desired net/region from nodelist.
  1242. X   Return NULL if everything was fine, otherwise error-message string. */
  1243. X
  1244. Xchar *
  1245. Xupdate_index()
  1246. X{
  1247. X  struct stat nlstat, inlstat;
  1248. X  FILE *nl = NULL, *nlidx = NULL, *namefp = NULL;
  1249. X  char nodelist[BUFLEN], inodelist[BUFLEN], namelist[BUFLEN];
  1250. X  char buffer[BUFSIZ];
  1251. X  long offset;
  1252. X  char *error;
  1253. X  Node node;
  1254. X  NODEINDEX nodei;
  1255. X  NAMEINDEX namei;
  1256. X  extern void qsort();
  1257. X
  1258. X  /* generate nodelist and index-file names */
  1259. X  (void) sprintf(nodelist, "%s/%s", LIBDIR, NODELIST);
  1260. X  (void) sprintf(inodelist, "%s/%s", LIBDIR, INODELIST);
  1261. X  (void) sprintf(namelist, "%s/%s", LIBDIR, NAMELIST);
  1262. X
  1263. X  /* get statuses of nodelist and index */
  1264. X  if (stat(nodelist, &nlstat) == -1)
  1265. X    return "$Error in getting nodelist status";
  1266. X
  1267. X  errno = 0;
  1268. X  if (stat(inodelist, &inlstat) == -1 && errno != ENOENT)
  1269. X    return "$Error in getting status of existing nodelist-index";
  1270. X
  1271. X  /* If index-file does exists then check modification times and
  1272. X     first lines. If nodelist is older and first lines are the same,
  1273. X     no update is needed. If index-file should be rebuild, assume
  1274. X     also rebuilding namelist. */
  1275. X
  1276. X  if (errno == 0 && nlstat.st_mtime <= inlstat.st_mtime)
  1277. X    {
  1278. X      error = NULL;
  1279. X      goto done;
  1280. X    }
  1281. X  else
  1282. X    log("Update nodelist-index: nodelist is newer than index");
  1283. X
  1284. X  /* open index-file for writing */
  1285. X  if (nlidx != NULL)
  1286. X    (void) fclose(nlidx);
  1287. X  if ((nlidx = fopen(inodelist, "w")) == NULL)
  1288. X    {
  1289. X      error = "$Unable to open nodelist-index for writing";
  1290. X      goto done;
  1291. X    }
  1292. X  if (namefp)
  1293. X    (void) fclose(namefp);
  1294. X  if ((namefp = fopen(namelist, "w")) == NULL)
  1295. X    {
  1296. X      error = "$Unable to open namelist-index for writing";
  1297. X      goto done;
  1298. X    }
  1299. X
  1300. X  if (!nl)
  1301. X    if ((nl = fopen(nodelist, "r")) == NULL)
  1302. X      return "$Unable to open nodelist";
  1303. X
  1304. X  (void) rewind(nl);
  1305. X
  1306. X  compile_zone = MY_ZONE;
  1307. X  compile_region = MY_REGION;
  1308. X  compile_net = MY_NET;
  1309. X  nodes = 0;
  1310. X  names = 0;
  1311. X
  1312. X  /* save host/region offsets */
  1313. X  for (offset = ftell(nl); fgets(buffer, BUFSIZ, nl); offset = ftell(nl))
  1314. X    {
  1315. X      if (*buffer == '\n' || *buffer == ';') continue;
  1316. X
  1317. X      parse_entry(&node, buffer);
  1318. X
  1319. X      nodei.zone = node.zone;
  1320. X      nodei.net = node.net;
  1321. X      nodei.node = node.node;
  1322. X      nodei.offset = offset;
  1323. X
  1324. X#ifdef NEEDED
  1325. X      debug(8, "%s", buffer);
  1326. X      debug(8, "writing %d:%d/%d", node.zone, node.net, node.node);
  1327. X#endif
  1328. X      FWRITE( (char *) &nodei, sizeof(NODEINDEX), 1, nlidx);
  1329. X      if (ferror(nlidx))
  1330. X    {
  1331. X      error = "$Cannot write index, no space?";
  1332. X      goto done;
  1333. X    }
  1334. X
  1335. X      if (node.type != REGION && node.type != HOST &&
  1336. X      node.type != ZONE && node.type != KENL && node.type != HUB)
  1337. X    {
  1338. X      strcpy(namei.name, node.sysop);
  1339. X      namei.offset = offset;
  1340. X      namei.zone = compile_zone;
  1341. X      namei.net = compile_net;
  1342. X      names++;
  1343. X      FWRITE( (char *) &namei, sizeof(NAMEINDEX), 1, namefp);
  1344. X      if (ferror(namefp))
  1345. X        {
  1346. X          error = "$Cannot write name index, no space?";
  1347. X          goto done;
  1348. X        }
  1349. X    }
  1350. X
  1351. X      nodes++;
  1352. X    }
  1353. X  error = NULL;
  1354. X
  1355. X  /* Ok, now get both indices back and qsort them */
  1356. X
  1357. X  (void) fclose(nl);
  1358. X  nl = NULL;
  1359. X  (void) fclose(nlidx);
  1360. X  nlidx = NULL;
  1361. X  (void) fclose(namefp);
  1362. X  namefp = NULL;
  1363. X
  1364. X  if (read_nodeindex())
  1365. X    {
  1366. X      error = "$Cannot read nodelist index";
  1367. X      goto done;
  1368. X    }
  1369. X  if (read_nameindex())
  1370. X    {
  1371. X      error = "$Cannot read name index";
  1372. X      goto done;
  1373. X    }
  1374. X
  1375. X  log("Sorting nodelist index");
  1376. X  (void) qsort( (char *) nodeindex, (unsigned) nodes,
  1377. X           sizeof(NODEINDEX), cmpnodeindex);
  1378. X  log("Sorting name index");
  1379. X  (void) qsort( (char *) nameindex, (unsigned) names,
  1380. X           sizeof(NAMEINDEX), cmpnameindex);
  1381. X  log("Sorted indices");
  1382. X
  1383. X  if (write_nodeindex())
  1384. X    {
  1385. X      error = "$Cannot write nodelist index";
  1386. X      goto done;
  1387. X    }
  1388. X  if (write_nameindex())
  1389. X    {
  1390. X      error = "$Cannot write name index";
  1391. X      goto done;
  1392. X    }
  1393. X
  1394. X  /* done, close files and return error message */
  1395. X done:
  1396. X  if (nl)
  1397. X    (void) fclose(nl);
  1398. X  if (nlidx)
  1399. X    (void) fclose(nlidx);
  1400. X  if (namefp)
  1401. X    (void) fclose(namefp);
  1402. X  return error;
  1403. X}
  1404. X
  1405. X/* Convert underscores in string to spaces. In nodelist there is always
  1406. X   underscore insted of space (flags is special case). */
  1407. X
  1408. Xvoid
  1409. Xconvert_space(s)
  1410. X     register char *s;
  1411. X{
  1412. X  while (*s)
  1413. X    {
  1414. X      if (*s == '_')
  1415. X        *s = ' ';
  1416. X      s++;
  1417. X    }
  1418. X}
  1419. X
  1420. X/* Get one comma-terminated field from buffer, retrun pointer to right
  1421. X   after terminating comma. Convert underscores to spaces in string. */
  1422. X
  1423. Xchar *
  1424. Xparse_field(buffer, entry, size)
  1425. X     char *buffer, *entry;
  1426. X     int size;
  1427. X{
  1428. X  char *np = entry;
  1429. X
  1430. X  /* copy string */
  1431. X  while (--size >= 0 && *buffer && *buffer != ',')
  1432. X    *entry++ = *buffer++;
  1433. X  *entry = 0;
  1434. X
  1435. X  switch (*buffer)
  1436. X    {
  1437. X    case 0:
  1438. X      /* end of buffer */
  1439. X      log("No closing comma in field");
  1440. X      return (char *) 0;
  1441. X    case ',':
  1442. X      /* succesful copy */
  1443. X      convert_space(np);
  1444. X      return buffer + 1;
  1445. X    default:
  1446. X      /* buffer too long, find comma */
  1447. X      while (*buffer && *buffer != ',')
  1448. X        buffer++;
  1449. X      if (*buffer)
  1450. X        {
  1451. X          convert_space(np);
  1452. X          return buffer + 1;
  1453. X        }
  1454. X      else
  1455. X        {
  1456. X          log("Missing comma in field");
  1457. X          return (char *) 0;
  1458. X        }
  1459. X    }
  1460. X  /* NOTREACHED */
  1461. X}
  1462. X
  1463. X/* Parse one line of nodelist to node structure. Return NULL is there
  1464. X   was error's in that line or missing fields. */
  1465. X
  1466. XNode *
  1467. Xparse_entry(entry, buffer)
  1468. X     Node *entry;
  1469. X     char *buffer;
  1470. X{
  1471. X  char *cp;
  1472. X  int n;
  1473. X
  1474. X  /* strip newline if exists */
  1475. X  if (cp = strchr(buffer, '\n'))
  1476. X    *cp = 0;
  1477. X
  1478. X  /* get type of entry */
  1479. X  if (!strncmp("Zone,", buffer, 5))
  1480. X    entry->type = ZONE;
  1481. X  else if (!strncmp("Region,", buffer, 7))
  1482. X    entry->type = REGION;
  1483. X  else if (!strncmp("Host,", buffer, 5))
  1484. X    entry->type = HOST;
  1485. X  else if (!strncmp("Hub,", buffer, 4))
  1486. X    entry->type = HUB;
  1487. X  else if (!strncmp("Pvt,", buffer, 4))
  1488. X    entry->type = PVT;
  1489. X  else if (!strncmp("Hold,", buffer, 5))
  1490. X    entry->type = HOLD;
  1491. X  else if (!strncmp("Down,", buffer, 5))
  1492. X    entry->type = DOWN;
  1493. X  else if (!strncmp("Kenl,", buffer, 5))
  1494. X    entry->type = KENL;
  1495. X  else if (*buffer == ',')
  1496. X    entry->type = NORMAL;
  1497. X  else
  1498. X    {
  1499. X      log("Unknown type in line '%s'", buffer);
  1500. X      return (Node *) 0;
  1501. X    }
  1502. X
  1503. X  /* get net/region/node number */
  1504. X  if ((cp = strchr(buffer, ',')) == NULL)
  1505. X    {
  1506. X      log("Missing zone/net/node/region in line '%s'", buffer);
  1507. X      return (Node *) 0;
  1508. X    }
  1509. X  if ((n = atoi(++cp)) == 0)
  1510. X    {
  1511. X      log("Value of zone/net/node/region is 0 in line '%s'", buffer);
  1512. X      return (Node *) 0;
  1513. X    }
  1514. X  if (entry->type == ZONE)
  1515. X    {
  1516. X      entry->zone = n;
  1517. X      entry->net = 0;
  1518. X      entry->node = 0;
  1519. X      entry->point = 0;
  1520. X      compile_zone = n;
  1521. X      debug(8, "Zone %d", compile_zone);
  1522. X    }
  1523. X  else if (entry->type == REGION)
  1524. X    {
  1525. X      entry->zone = compile_zone;
  1526. X      entry->region = n;
  1527. X      entry->net = n;    /* For compatibility with old version */
  1528. X      entry->node = 0;
  1529. X      entry->point = 0;
  1530. X      compile_region = n;
  1531. X      compile_net = n;    /* For compatibility with old version */
  1532. X      debug(8, "Region %d", compile_region);
  1533. X    }
  1534. X  else if (entry->type == HOST)
  1535. X    {
  1536. X      entry->zone = compile_zone;
  1537. X      entry->region = compile_region;
  1538. X      entry->net = n;
  1539. X      entry->node = 0;
  1540. X      entry->point = 0;
  1541. X      compile_net = n;
  1542. X      debug(8, "Net %d", compile_net);
  1543. X    }
  1544. X  else
  1545. X    {
  1546. X      entry->zone = compile_zone;
  1547. X      entry->region = compile_region;
  1548. X      entry->net = compile_net;
  1549. X      entry->node = n;
  1550. X      entry->point = 0;
  1551. X    }
  1552. X  while (*cp && *cp++ != ',');
  1553. X
  1554. X  /* get node/net/region name */
  1555. X  if ((cp = parse_field(cp, entry->name, sizeof(entry->name))) == NULL)
  1556. X    {
  1557. X      log("Invalid name in line '%s'", buffer);
  1558. X      return (Node *) 0;
  1559. X    }
  1560. X
  1561. X  /* get city */
  1562. X  if ((cp = parse_field(cp, entry->city, sizeof(entry->city))) == NULL)
  1563. X    {
  1564. X      log("Invalid city in line '%s'", buffer);
  1565. X      return (Node *) 0;
  1566. X    }
  1567. X
  1568. X  /* get sysop */
  1569. X  if ((cp = parse_field(cp, entry->sysop, sizeof(entry->sysop))) == NULL)
  1570. X    {
  1571. X      log("Invalid sysop in line '%s'", buffer);
  1572. X      return (Node *) 0;
  1573. X    }
  1574. X
  1575. X  /* get phone number */
  1576. X  if ((cp = parse_field(cp, entry->phone, sizeof(entry->phone))) == NULL)
  1577. X    {
  1578. X      log("Invalid phone-number in line '%s'", buffer);
  1579. X      return (Node *) 0;
  1580. X    }
  1581. X
  1582. X  /* get maximum baud rate */
  1583. X  if ((n = atoi(cp)) == 0)
  1584. X    {
  1585. X      log("Baud rate is 0 in line '%s'", buffer);
  1586. X      return (Node *) 0;
  1587. X    }
  1588. X  entry->speed = n;
  1589. X  while (*cp && *cp++ != ',');
  1590. X
  1591. X  /* get flags */
  1592. X  (void) strncpy(entry->flags, cp, sizeof(entry->flags));
  1593. X  entry->flags[sizeof(entry->flags) - 1] = 0;
  1594. X
  1595. X  /* all done */
  1596. X  return entry;
  1597. X}
  1598. X
  1599. X/* Get entry for one node from nodelist. Return NULL, if there is no
  1600. X   entry for that node. */
  1601. X
  1602. XNode *
  1603. Xnode_entry(node)
  1604. X     Node node;
  1605. X{
  1606. X  static Node entry;
  1607. X  FILE *fp;
  1608. X  char buffer[BUFSIZ];
  1609. X  extern char *bsearch();
  1610. X  long offset;
  1611. X  NODEINDEX *nodeip, nodei;
  1612. X
  1613. X  /* Read index file into memory */
  1614. X
  1615. X  if (!nodeindex)
  1616. X    if (read_nodeindex())
  1617. X      {
  1618. X    log("$Unable to read nodelist");
  1619. X    return (Node *) 0;
  1620. X      }
  1621. X
  1622. X  nodei.zone = node.zone;
  1623. X  nodei.net = node.net;
  1624. X  nodei.node = node.node;
  1625. X
  1626. X  debug(2, "Searching %s from %d nodes", ascnodei(nodei), nodes);
  1627. X  nodeip = (NODEINDEX *) bsearch( (char *) &nodei, (char *) nodeindex,
  1628. X                 (unsigned) nodes, sizeof(NODEINDEX),
  1629. X                 cmpnodeindex);
  1630. X
  1631. X  if (nodeip) {
  1632. X    offset = nodeip->offset;
  1633. X
  1634. X    /* open nodelist */
  1635. X    (void) sprintf(buffer, "%s/%s", LIBDIR, NODELIST);
  1636. X    if ((fp = fopen(buffer, "r")) == NULL)
  1637. X      {
  1638. X    log("$Unable to open %s", buffer);
  1639. X    return (Node *) 0;
  1640. X      }
  1641. X
  1642. X    if (fseek(fp, offset, 0))
  1643. X      {
  1644. X    log("$Seek error on nodelist");
  1645. X    (void) fclose(fp);
  1646. X    return (Node *) 0;
  1647. X      }
  1648. X
  1649. X    fgets(buffer, BUFSIZ, fp);
  1650. X    fclose(fp);
  1651. X
  1652. X    compile_zone = nodeip->zone;
  1653. X    compile_net = nodeip->net;
  1654. X    return parse_entry(&entry, buffer);
  1655. X  }
  1656. X
  1657. X  log("Could not find node %s", ascnodei(nodei));
  1658. X
  1659. X  /* we didn't find net/region */
  1660. X  (void) fclose(fp);
  1661. X  return (Node *) 0;
  1662. X}
  1663. X
  1664. Xchar *dialtable[] = { DIALTABLE };
  1665. X
  1666. Xdial_translation(dest, source)
  1667. X     char *dest, *source;
  1668. X{
  1669. X  register int count = 0;
  1670. X
  1671. X  for (;;) {
  1672. X    if (!*dialtable[count] ||
  1673. X    !strncmp(dialtable[count], source, strlen(dialtable[count]))) {
  1674. X
  1675. X      /* Matched, take prefix, */
  1676. X      strcpy(dest, dialtable[count + 1]);
  1677. X
  1678. X      /* Then add phone number */
  1679. X      strcat(dest, source + strlen(dialtable[count]));
  1680. X      return;
  1681. X    }
  1682. X    count += 2;
  1683. X  }
  1684. X}
  1685. X
  1686. Xstatic char **aliastable = NULL;
  1687. Xstatic allocated = 0;
  1688. Xstatic aliases = 0;
  1689. X
  1690. Xexpand_aliastable()
  1691. X{
  1692. X  if (!aliastable)
  1693. X    {
  1694. X      aliastable = (char **) malloc(sizeof(char *) * 20);
  1695. X      if (aliastable) allocated = 20;
  1696. X    }
  1697. X
  1698. X  if (aliases == allocated) /* Need more pointers */
  1699. X    {
  1700. X      allocated += 20;
  1701. X      aliastable = (char **) realloc( (char *) aliastable,
  1702. X                     sizeof(char *) * allocated);
  1703. X      if (!aliastable)
  1704. X    {
  1705. X      log("Cannot realloc %d bytes", sizeof(char *) * allocated);
  1706. X      return -1;
  1707. X    }
  1708. X    }
  1709. X  return 0;
  1710. X}
  1711. X
  1712. X#define FILENAME_SIZE 256
  1713. X
  1714. Xsearch_name(name)
  1715. X     char *name;
  1716. X{
  1717. X  Node entry;
  1718. X  FILE *fp;
  1719. X  char buffer[BUFSIZ];
  1720. X  extern char *bsearch();
  1721. X  char *nlname;
  1722. X  long offset;
  1723. X  NAMEINDEX *nameip, namei;
  1724. X
  1725. X  if (!nameindex)
  1726. X    if (read_nameindex())
  1727. X      {
  1728. X    log("$Unable to read namelist");
  1729. X    return -1;
  1730. X      }
  1731. X
  1732. X  strncpy(namei.name, name, 36);
  1733. X  namei.name[35] = 0;
  1734. X
  1735. X  nameip = (NAMEINDEX *) bsearch( (char *) &namei, (char *) nameindex,
  1736. X                 (unsigned) names, sizeof(NAMEINDEX),
  1737. X                 cmpnameindex);
  1738. X
  1739. X  if (nameip)
  1740. X    {
  1741. X      offset = nameip->offset;
  1742. X
  1743. X      /* Open nodelist */
  1744. X      if ((fp =
  1745. X       fopen(nlname = sprintfs("%s/%s", LIBDIR, NODELIST), "r")) == NULL)
  1746. X    {
  1747. X      log("$Unable to open nodelist %s", nlname);
  1748. X      return -1;
  1749. X    }
  1750. X
  1751. X      if (fseek(fp, offset, 0))
  1752. X    {
  1753. X      log("$Seek error on nodelist");
  1754. X      (void) fclose(fp);
  1755. X      return -1;
  1756. X    }
  1757. X
  1758. X      fgets(buffer, BUFSIZ, fp);
  1759. X      fclose(fp);
  1760. X
  1761. X      compile_zone = nameip->zone;
  1762. X      compile_net = nameip->net;
  1763. X      if (parse_entry(&entry, buffer) == NULL) return -1;
  1764. X
  1765. X      debug(1, "Search name %s returns %d:%d/%d.%d", name,
  1766. X        entry.zone, entry.net, entry.node, entry.point);
  1767. X      memcpy( (char *) &originnode, (char *) &entry, sizeof(Node));
  1768. X      return 0;
  1769. X    }
  1770. X
  1771. X  debug(1, "Search name %s return no node", name);
  1772. X  return -1;
  1773. X}
  1774. X
  1775. SHAR_EOF
  1776. chmod 0644 nodelist.c || echo "restore of nodelist.c fails"
  1777. echo "x - extracting gethostname.c (Text)"
  1778. sed 's/^X//' << 'SHAR_EOF' > gethostname.c &&
  1779. X#ifndef lint
  1780. Xstatic char *sccsid = "@(#)%M%  %I%  Teemu Torma %H%";
  1781. X#endif
  1782. X
  1783. X/* Get host name. This emulates routine with same name in BSD-Unix.
  1784. X
  1785. X   @(#)Copyright (c) 1987 by Teemu Torma
  1786. X
  1787. X   Permission is given to distribute this program and alter this code as
  1788. X   needed to adapt it to forign systems provided that this header is
  1789. X   included and that the original author's name is preserved. */
  1790. X
  1791. X#include <sys/utsname.h>
  1792. X#include <string.h>
  1793. X
  1794. X/* Get name of this uucp-node. Name is stored in buffer. Len in maximum
  1795. X   length of buffer. Return -1 if can not do uname(2), otherwise 0. */
  1796. X
  1797. Xint
  1798. Xgethostname(buffer, len)
  1799. X     char *buffer;
  1800. X     int len;
  1801. X{
  1802. X  struct utsname name;
  1803. X
  1804. X  if (uname(&name) == -1)
  1805. X    return -1;
  1806. X  (void) strncpy(buffer, name.nodename, len);
  1807. X  buffer[len - 1] = 0;
  1808. X  return 0;
  1809. X}
  1810. SHAR_EOF
  1811. chmod 0644 gethostname.c || echo "restore of gethostname.c fails"
  1812. echo "x - extracting dateconv.c (Text)"
  1813. sed 's/^X//' << 'SHAR_EOF' > dateconv.c &&
  1814. X#ifndef lint
  1815. Xstatic char *sccsid = "@(#)%M%  %I%  Teemu Torma %H%";
  1816. X#endif
  1817. X
  1818. X/* Convert date to type time_t (time in seconds since 1 Jan 1970).
  1819. X
  1820. X   @(#)Copyright (c) 1987 by Teemu Torma
  1821. X
  1822. X   Permission is given to distribute this program and alter this code as
  1823. X   needed to adapt it to forign systems provided that this header is
  1824. X   included and that the original author's name is preserved. */
  1825. X
  1826. X/* LINTLIBRARY */
  1827. X
  1828. X#include <stdio.h>
  1829. X#include <sys/types.h>
  1830. X#include <time.h>
  1831. X#include "fnet.h"
  1832. X
  1833. X#define epoch 1970
  1834. X#define daysec (24l * 60l * 60l)
  1835. X#define AM 1
  1836. X#define PM 2
  1837. X
  1838. X/* days in each month */
  1839. Xstatic int mdays[12] = {
  1840. X  31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
  1841. X};
  1842. X
  1843. X/* Convert hours, minutes and seconds to seconds */
  1844. X
  1845. Xtime_t
  1846. Xtimeconv(hh, mm, ss, mer)
  1847. X     int hh, mm, ss;
  1848. X     int mer;
  1849. X{
  1850. X  /* check correctness of time */
  1851. X  if (mm < 0 || mm > 59 || ss < 0 || ss > 59)
  1852. X    return (time_t) -1;
  1853. X
  1854. X  /* count time */
  1855. X  switch (mer)
  1856. X    {
  1857. X    case AM:
  1858. X      if (hh < 1 || hh > 12)
  1859. X        return(time_t) 1;
  1860. X      return (60L * ((hh % 12) * 60L + mm) + ss);
  1861. X    case PM:
  1862. X      if (hh < 1 || hh > 12)
  1863. X        return(time_t) 1;
  1864. X      return (60L * ((hh % 12 +12) * 60L + mm) + ss);
  1865. X    case 24:
  1866. X      if (hh < 0 || hh > 23)
  1867. X        return (time_t) 1;
  1868. X      return (60L * (hh * 60L + mm) + ss);
  1869. X    default:
  1870. X      return (time_t) 1;
  1871. X    }
  1872. X  /* NOTREACHED */
  1873. X}
  1874. X
  1875. X/* Convert date to seconds from beginning of year 1970 (normal Unix
  1876. X   time). Return -1 if something wen't wrong. */
  1877. X
  1878. X/* ARGSUSED */
  1879. Xtime_t
  1880. Xdateconv(mm, dd, yy, h, m, s, mer, zone, dayflag)
  1881. X     int mm, dd, yy, h, m, s;
  1882. X     int mer, zone;
  1883. X{
  1884. X  time_t tod, jdate;
  1885. X  register int n;
  1886. X
  1887. X  /* if negative year make it positive */
  1888. X  if (yy < 0)
  1889. X    yy = -yy;
  1890. X
  1891. X  /* if year is 00..99 make it right */
  1892. X  if (yy < 100)
  1893. X    yy += 1900;
  1894. X
  1895. X  /* count days for february */
  1896. X  mdays[1] = 28 + (yy % 4 == 0 && (yy % 100 != 0 || yy % 400 == 0));
  1897. X
  1898. X  /* check correctess of date (year 1970..1999) */
  1899. X  if (yy < epoch || yy > 1999 || mm < 1 || mm > 12 || dd < 1 ||
  1900. X      dd > mdays[--mm])
  1901. X    return (time_t) -1;
  1902. X
  1903. X  /* counts days from beginning of year */
  1904. X  jdate = (time_t ) (dd - 1);
  1905. X  for (n = 0; n < mm; n++)
  1906. X    jdate += (time_t) mdays[n];
  1907. X
  1908. X  /* add years to days */
  1909. X  for (n = epoch; n < yy; n++)
  1910. X    jdate += (time_t) (365 + (n % 4 == 0));
  1911. X
  1912. X  /* convert days to seconds */
  1913. X  jdate *= daysec;
  1914. X
  1915. X  /* add time of day */
  1916. X  if ((tod = timeconv(h, m, s, mer)) < 0)
  1917. X    return (time_t) -1;
  1918. X  jdate += tod;
  1919. X
  1920. X  /* add time zone to date */
  1921. X  jdate += (time_t) zone * 60L;
  1922. X
  1923. X  return jdate;
  1924. X}
  1925. SHAR_EOF
  1926. chmod 0644 dateconv.c || echo "restore of dateconv.c fails"
  1927. echo "x - extracting address.c (Text)"
  1928. sed 's/^X//' << 'SHAR_EOF' > address.c &&
  1929. X#ifndef lint
  1930. Xstatic    char    *sccsid = "@(#)%M%  %I%  Teemu Torma %H%";
  1931. X#endif
  1932. X
  1933. X/* Routines to handle fidonet addresses. Currently addres format in outside
  1934. X   fidonet is <name>@<node>.<net>.fidonet. This will propablty change when
  1935. X   zones are coming. Those standards are ready, but I haven't seen them
  1936. X   yet.
  1937. X
  1938. X   Mon Oct  3 02:43:49 1988
  1939. X   zones-format will be <name>@<point>.<node>.<net>.<zone>.fidonet.
  1940. X   Fidonet-like format maybe would be easier to get used to but
  1941. X   parsing it with sendmails etc would be more difficult. Notice that there
  1942. X   certainly will be problems if different number of numbers than 4
  1943. X   is specified. I will use following solution:
  1944. X
  1945. X   case 4: assume point.node.net.zone
  1946. X   case 3: assume node.net.zone (point 0)
  1947. X   case 2: assume node.net (in current zone, point 0)
  1948. X   case 1: assume node (in current net, zone, point 0)
  1949. X
  1950. X   Other way would be to force users to use zones and/or try to check
  1951. X   other possibilities by checking if its on the nodelist. I don't
  1952. X   really like points, they make life difficult, they could just be local
  1953. X   nodes off the nodelist, and no special support would be needed!
  1954. X
  1955. X   @(#)Copyright (c) 1987 by Teemu Torma
  1956. X
  1957. X   Permission is given to distribute this program and alter this code as
  1958. X   needed to adapt it to forign systems provided that this header is
  1959. X   included and that the original author's name is preserved. */
  1960. X
  1961. X/* LINTLIBRARY */
  1962. X
  1963. X#include <stdio.h>
  1964. X#include <ctype.h>
  1965. X#include <string.h>
  1966. X#include <sys/types.h>
  1967. X#include "hsu.h"
  1968. X#include "config.h"
  1969. X#include "fnet.h"
  1970. X#include "nodelist.h"
  1971. X#include "shuffle.h"
  1972. X
  1973. X
  1974. X/* Parse fidonet address to name, net and node. Address contains address,
  1975. X   and name, net and node will be returned. Return NULL is it was valid
  1976. X   fidonet address, otherwise string to error message. */
  1977. X
  1978. Xchar *
  1979. Xparse_address(address, name, node)
  1980. X     char *address, *name;
  1981. X     Node *node;
  1982. X{
  1983. X  static char error[64];
  1984. X  register char *cp;
  1985. X  register int cnt;
  1986. X
  1987. X  /* make address to lowercase */
  1988. X  for (cp = address; *cp; cp++)
  1989. X    if (isupper(*cp))
  1990. X      *cp = tolower(*cp);
  1991. X
  1992. X  /* Get name. We assume that name has space at least 36 charcers (maximum
  1993. X     length of name in fido). First check wheather format is name@domain
  1994. X     of domain!name format. */
  1995. X  if ((cp = strchr(address, '!')) != NULL)
  1996. X    {
  1997. X      debug(2, "Fidonet address domain!name");
  1998. X      for (cp++, cnt = 0; *cp && cnt < 35; cnt++, cp++)
  1999. X        name[cnt] = *cp;
  2000. X      name[cnt] = 0;
  2001. X      cp = address;
  2002. X      debug(3, "Name %s", name);
  2003. X    }
  2004. X  else
  2005. X    {
  2006. X      debug(2, "Fidonet address name@domain");
  2007. X      for (cp = address, cnt = 0; *cp && cnt < 35 && *cp != '@'; cp++, cnt++)
  2008. X        name[cnt] = *cp;
  2009. X      name[cnt] = 0;
  2010. X      debug(3, "Name %s", name);
  2011. X
  2012. X      if (*cp != '@')
  2013. X        {
  2014. X          /* name is too long or address is invalid */
  2015. X          while (*cp && *cp != '@')
  2016. X            cp++;
  2017. X          if (*cp == 0)
  2018. X            {
  2019. X              debug(1, "Invalid address: %s: missing @", address);
  2020. X              (void) sprintf(error, "No @ in address %s", address);
  2021. X              return error;
  2022. X            }
  2023. X        }
  2024. X      cp++;
  2025. X    }
  2026. X
  2027. X  debug(2, "Address %s, up to '!' or end", cp);
  2028. X
  2029. X  if (parseinternode(cp, node))
  2030. X    {
  2031. X      sprintf(error, "Bad address %s", cp);
  2032. X      return error;
  2033. X    }
  2034. X
  2035. X#ifdef NEEDED
  2036. X  /* now parse address, cp points to beginning of it. */
  2037. X  for (*node = 0; isdigit(*cp); cp++)
  2038. X    *node = 10 * *node + *cp - '0';
  2039. X  if (*cp != '.')
  2040. X    {
  2041. X      debug(1, "Invalid address: %s: no . after node", address);
  2042. X      debug(2, "Rest of address %s, node %d", cp, *node);
  2043. X      (void) sprintf(error, "No net number in address %s", address);
  2044. X      return error;
  2045. X    }
  2046. X
  2047. X  /* get net */
  2048. X  for (cp++, *net = 0; isdigit(*cp); cp++)
  2049. X    *net = 10 * *net + *cp - '0';
  2050. X  if (*cp != '.')
  2051. X    {
  2052. X      debug(1, "Invalid address: %s: no . after net", address);
  2053. X      debug(2, "Rest of address %s, net/node %d/%d", *net, *node);
  2054. X      (void) sprintf(error, "No domain in address %s", address);
  2055. X      return error;
  2056. X    }
  2057. X
  2058. X  cp++;
  2059. X  debug(3, "Domain %s", cp);
  2060. X
  2061. X  /* check that .fidonet is present */
  2062. X  if (strncmp(cp, "fidonet", 7) || (cp[7] != 0 && cp[7] != '!'))
  2063. X    {
  2064. X      debug(1, "Invalid address: %s: not .fidonet domain", address);
  2065. X      (void) sprintf(error, "Domain is not .fidonet in address %s", address);
  2066. X      return error;
  2067. X    }
  2068. X
  2069. X#endif
  2070. X  /* we're done */
  2071. X  return NULL;
  2072. X}
  2073. X
  2074. Xreturnbad(errtype, s, node)
  2075. X     char *errtype, *s;
  2076. X     Node *node;
  2077. X{
  2078. X  log("Bad address %s : %s, returning my node", s, errtype);
  2079. X  node->zone = MY_ZONE;
  2080. X  node->net = MY_NET;
  2081. X  node->node = MY_NODE;
  2082. X  node->point = MY_POINT;
  2083. X  return -1;
  2084. X}
  2085. X
  2086. X/* Parse internet format fidonet address */
  2087. X
  2088. Xparseinternode(address, node)
  2089. X     char *address;
  2090. X     Node *node;
  2091. X{
  2092. X  char *p, *s;
  2093. X  int numbers[4], count = 0;
  2094. X
  2095. X  s = alloca(strlen(address) + 1);
  2096. X  strcpy(s, address);
  2097. X  numbers[0] = numbers[1] = numbers[2] = numbers[3] = -1;
  2098. X
  2099. X  if (strlen(s) > strlen(".fidonet"))
  2100. X    if (!strcmp(s + strlen(s) - strlen(".fidonet"), ".fidonet"))
  2101. X      s[strlen(s) - strlen(".fidonet")] = 0;
  2102. X
  2103. X  for (p = strtok(s, "."); p; p = strtok(NULL, "."))
  2104. X    numbers[count++] = atoi(p);
  2105. X
  2106. X  if (!count) return returnbad("empty fidonet address", address, node);
  2107. X  if (count == 4)
  2108. X    {
  2109. X      node->zone = numbers[3];
  2110. X      node->net = numbers[2];
  2111. X      node->node = numbers[1];
  2112. X      node->point = numbers[0];
  2113. X      return 0;
  2114. X    }
  2115. X
  2116. X  if (numbers[0] == -1) return returnbad("no node", address, node);
  2117. X  if (numbers[1] == -1) numbers[1] = MY_NET;
  2118. X  if (numbers[2] == -1) numbers[2] = MY_ZONE;
  2119. X  node->zone = numbers[2];
  2120. X  node->net = numbers[1];
  2121. X  node->node = numbers[0];
  2122. X  node->point = 0;
  2123. X  return 0;
  2124. X}
  2125. X
  2126. X/* It would have been more sensible if
  2127. X   fidonet addresses were down to up, it would be easier to parse.
  2128. X
  2129. X   Fri Oct  7 12:09:21 1988
  2130. X   Removes non-numeric chars at start, Opus puts 'Opus ' there
  2131. X   */
  2132. X
  2133. Xparsefnetaddress(s, node)
  2134. X     char *s;
  2135. X     Node *node;
  2136. X{
  2137. X  char *p, *lastnumber;
  2138. X  char nodenbuf[100];
  2139. X
  2140. X  strncpy(nodenbuf, s, 99);
  2141. X  nodenbuf[99] = 0;
  2142. X  s = nodenbuf;
  2143. X
  2144. X  node->zone = 0;
  2145. X  node->net = 0;
  2146. X  node->node = 0;
  2147. X  node->point = 0;
  2148. X  p = s;
  2149. X
  2150. X  while (!isdigit(*p) && *p) p++;
  2151. X
  2152. X  while (*p) {
  2153. X    switch (*p) {
  2154. X     case '0':
  2155. X     case '1':
  2156. X     case '2':
  2157. X     case '3':
  2158. X     case '4':
  2159. X     case '5':
  2160. X     case '6':
  2161. X     case '7':
  2162. X     case '8':
  2163. X     case '9':
  2164. X      {
  2165. X    lastnumber = p;
  2166. X    while (isdigit(*++p));
  2167. X    continue;
  2168. X      }
  2169. X     case ':':
  2170. X      /* Previous number is zone */
  2171. X      if (node->zone) return returnbad("two zones", s, node);
  2172. X      node->zone = atoi(lastnumber);
  2173. X      lastnumber = p + 1;
  2174. X      break;
  2175. X     case '/':
  2176. X      /* Previous number is net */
  2177. X      if (node->net) return returnbad("two nets", s, node);
  2178. X      node->net = atoi(lastnumber);
  2179. X      lastnumber = p + 1;
  2180. X      break;
  2181. X     case '.':
  2182. X      /* Previous number is node */
  2183. X      if (node->node) return returnbad("two nodes", s, node);
  2184. X      node->node = atoi(lastnumber);
  2185. X      lastnumber = p + 1;
  2186. X      break;
  2187. X     case 0:
  2188. X      /* End: lastnumber should have point (or its at end, which gives us 0) */
  2189. X      node->node = atoi(lastnumber);
  2190. X      if (node->zone == 0) node->zone = MY_ZONE;
  2191. X      if (node->net == 0) node->net = MY_NET;
  2192. X      return 0;
  2193. X     default:
  2194. X      log("Bad char %d in %s", *p, s);
  2195. X      return returnbad("bad char", s, node);
  2196. X    }
  2197. X    p++;
  2198. X  }
  2199. X  if (node->zone == 0) node->zone = MY_ZONE;
  2200. X  if (node->net == 0) return returnbad("no net", s, node);
  2201. X  if (node->node == 0)
  2202. X    node->node = atoi(lastnumber);
  2203. X
  2204. X  return 0;
  2205. X}
  2206. X
  2207. X/* Return address in string format */
  2208. X
  2209. Xchar *ascnode(node)
  2210. X     Node node;
  2211. X{
  2212. X  SHUFFLEBUFFERS;
  2213. X
  2214. X  sprintf(tcharp, "%d:%d/%d.%d", node.zone, node.net, node.node, node.point);
  2215. X  return tcharp;
  2216. X}
  2217. X
  2218. X/* Internet format */
  2219. Xchar *internode(node)
  2220. X     Node node;
  2221. X{
  2222. X  SHUFFLEBUFFERS;
  2223. X
  2224. X  if (node.point)
  2225. X    sprintf(tcharp, "%d.%d.%d.%d.fidonet", node.point, node.node, node.net,
  2226. X        node.zone);
  2227. X  else
  2228. X    sprintf(tcharp, "%d.%d.%d.fidonet", node.node, node.net, node.zone);
  2229. X
  2230. X  return tcharp;
  2231. X}
  2232. X
  2233. X/* same for index node structure */
  2234. X
  2235. Xchar *ascnodei(node)
  2236. X     NODEINDEX node;
  2237. X{
  2238. X  SHUFFLEBUFFERS;
  2239. X
  2240. X  sprintf(tcharp, "%d:%d/%d", node.zone, node.net, node.node);
  2241. X  return tcharp;
  2242. X}
  2243. SHAR_EOF
  2244. chmod 0644 address.c || echo "restore of address.c fails"
  2245. echo "x - extracting crc.c (Text)"
  2246. sed 's/^X//' << 'SHAR_EOF' > crc.c &&
  2247. X#ifndef lint
  2248. Xstatic    char    *sccsid = "@(#)%M%  %I%  Teemu Torma %H%";
  2249. X#endif
  2250. X
  2251. X/*
  2252. X *    @(#)Copyright (C) Teemu Torma 1987
  2253. X */
  2254. X
  2255. X#include    <stdio.h>
  2256. X
  2257. X#ifdef NEEDED
  2258. X/* ARGSUSED */
  2259. Xint        main(argc, argv, envp)
  2260. Xint        argc;
  2261. Xchar    **argv;
  2262. Xchar    **envp;
  2263. X{
  2264. X    exit(0);
  2265. X    /* NOTREACHED */
  2266. X}
  2267. X#endif
  2268. X
  2269. X/* crctab calculated by Mark G. Mendel, Network Systems Corporation */
  2270. Xunsigned short crctab[256] = {
  2271. X    0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
  2272. X    0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
  2273. X    0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
  2274. X    0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
  2275. X    0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
  2276. X    0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
  2277. X    0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
  2278. X    0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
  2279. X    0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
  2280. X    0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
  2281. X    0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
  2282. X    0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
  2283. X    0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
  2284. X    0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
  2285. X    0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
  2286. X    0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
  2287. X    0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
  2288. X    0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
  2289. X    0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
  2290. X    0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
  2291. X    0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
  2292. X    0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
  2293. X    0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
  2294. X    0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
  2295. X    0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
  2296. X    0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
  2297. X    0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
  2298. X    0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
  2299. X    0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
  2300. X    0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
  2301. X    0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
  2302. X    0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
  2303. X};
  2304. X
  2305. X#ifdef NEEDED
  2306. Xstatic long cr3tab[] = { /* CRC polynomial 0xedb88320 */
  2307. X0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
  2308.  0xe963a535, 0x9e6495a3,
  2309. X0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd,
  2310.  0xe7b82d07, 0x90bf1d91,
  2311. X0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb,
  2312.  0xf4d4b551, 0x83d385c7,
  2313. X0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
  2314.  0xfa0f3d63, 0x8d080df5,
  2315. X0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447,
  2316.  0xd20d85fd, 0xa50ab56b,
  2317. X0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75,
  2318.  0xdcd60dcf, 0xabd13d59,
  2319. X0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
  2320.  0xcfba9599, 0xb8bda50f,
  2321. X0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11,
  2322.  0xc1611dab, 0xb6662d3d,
  2323. X0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
  2324.  0x9fbfe4a5, 0xe8b8d433,
  2325. X0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
  2326.  0x91646c97, 0xe6635c01,
  2327. X0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b,
  2328.  0x8208f4c1, 0xf50fc457,
  2329. X0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49,
  2330.  0x8cd37cf3, 0xfbd44c65,
  2331. X0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
  2332.  0xa4d1c46d, 0xd3d6f4fb,
  2333. X0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
  2334.  0xaa0a4c5f, 0xdd0d7cc9,
  2335. X0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3,
  2336.  0xb966d409, 0xce61e49f,
  2337. X0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
  2338.  0xb7bd5c3b, 0xc0ba6cad,
  2339. X0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af,
  2340.  0x04db2615, 0x73dc1683,
  2341. X0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d,
  2342.  0x0a00ae27, 0x7d079eb1,
  2343. X0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
  2344.  0x196c3671, 0x6e6b06e7,
  2345. X0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9,
  2346.  0x17b7be43, 0x60b08ed5,
  2347. X0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767,
  2348.  0x3fb506dd, 0x48b2364b,
  2349. SHAR_EOF
  2350. echo "End of part 4"
  2351. echo "File crc.c is continued in part 5"
  2352. echo "5" > s2_seq_.tmp
  2353. exit 0
  2354.  
  2355.