home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 239.lha / Unix1src.shar < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-02  |  51.2 KB  |  2,317 lines

  1. #!/bin/sh
  2. # shar: SHell ARchive
  3. # Run the following text through 'sh' to create:
  4. #    CLEAN
  5. #    MAKE
  6. #    README
  7. #    TODO
  8. #    client/getfiles.c
  9. #    client/putfiles.c
  10. #    client/dsoc.c
  11. #    client/draw.c
  12. #    client/dprint.c
  13. #    client/Makefile
  14. #    dnet/channel.h
  15. #    dnet/control.c
  16. #    dnet/TODO3
  17. #    dnet/subs.c
  18. # This is archive 1 of a 2-part kit.
  19. # This archive created: Thu Apr 27 15:41:47 1989
  20. echo "extracting CLEAN"
  21. sed 's/^X//' << \SHAR_EOF > CLEAN
  22. X#!/bin/sh
  23. Xcd dnet
  24. Xmake clean
  25. Xcd ../client
  26. Xmake clean
  27. Xcd ../server
  28. Xmake clean
  29. Xcd ../test
  30. Xmake clean
  31. Xcd ../lib
  32. Xrm -f *.o make.out
  33. Xcd ..
  34. Xrm -f *.o make.out MAKE.out
  35. X
  36. SHAR_EOF
  37. echo "extracting MAKE"
  38. sed 's/^X//' << \SHAR_EOF > MAKE
  39. X#!/bin/sh
  40. Xcd lib
  41. Xmake
  42. Xcd ../dnet
  43. Xmake
  44. Xcd ../client
  45. Xmake
  46. Xcd ../server
  47. Xmake
  48. X
  49. SHAR_EOF
  50. echo "extracting README"
  51. sed 's/^X//' << \SHAR_EOF > README
  52. X
  53. X
  54. X               DNET V2.00 UNIX SIDE
  55. X
  56. X               BSD4.2/4.3 compatible
  57. X               note: 8 bit connection required to run dnet,
  58. X                which isn't always true if talking to the unix
  59. X                box through a port selector or terminal
  60. X                concentrator.
  61. X
  62. X
  63. X
  64. X    DNET (c)Copyright 1987-1989 Matthew Dillon, All Rights Reserved
  65. X
  66. X    Matthew Dillon
  67. X    891 Regal Rd
  68. X    Berkeley, Ca. 94708
  69. X    USA
  70. X
  71. X    ...!ihnp4!ucbvax!dillon     USENET
  72. X    dillon@ucbvax.Berkeley.edu    ARPANET
  73. X    ucbvax.berkeley.edu pub/amiga    ARPANET-FTP
  74. X
  75. X                UNIX SETUP
  76. X
  77. X    The directory structure must remain intact.  simply say MAKE
  78. X    in the main directory and it ought to compile.    There might be
  79. X    minor problems depending on how compatible your UNIX is with
  80. X    BSD4.3 UNIX ..    I have successfully compiled DNet on the following
  81. X    machines:
  82. X
  83. X            Dec Vax 7xx
  84. X            Sun 3
  85. X            Sequent
  86. X
  87. X    (1) Create a directory.  For example, ~/.DNET   WARNING!  This
  88. X        directory must be on a local partition.  DNET uses a unix
  89. X        domain socket and these do not work over network fileservers.
  90. X
  91. X    (2) Modify your .cshrc to add the following line:
  92. X
  93. X        setenv DNETDIR  ~/.DNET/
  94. X
  95. X        (or wherever you put it.  NOTE! You MUST HAVE THE TRAILING
  96. X         SLASH!)
  97. X
  98. X    (3) All binaries are usually kept in dnet.unix/bin, add this
  99. X        directory to your path (in your .cshrc) so DNet can find
  100. X        the clients.
  101. X
  102. X    (4) Place the file 'dnet.servers' in $DNETDIR.  Modify the file
  103. X        according to your home directory and where you have put the
  104. X        servers (usually in dnet.unix/bin).  USE ABSOLUTE PATHS,
  105. X        DNET.SERVERS DOES NOT UNDERSTAND ~.
  106. X
  107. X    NOTE: You may want to chmod $DNETDIR 700 to disallow any
  108. X    unauthorized access to the network.
  109. X
  110. X
  111. X                 DIALING UP FROM AN AMIGA
  112. X
  113. X    Follow the installation instructions for the Amiga side.  When
  114. X    you dial up the UNIX system you will eventually get a prompt.
  115. X    NOTE!  DNET normally uses 7 bit - even parity for dialing up,
  116. X    then switches to 8 bit no parity for the protocol.  Sometimes
  117. X    the modem or port selector will switch into 7 bit + parity mode
  118. X    and NOT SWITCH OUT.  For this reason, you might want to use the
  119. X    -8 option for the Amiga side of DNET (read the docs in the Amiga
  120. X    section).
  121. X
  122. X    From the DNET window's CSH prompt, start the protocol with:
  123. X
  124. X    % dnet
  125. X
  126. X    That was easy.    The DNet window should go away and an FTERM window
  127. X    should open.  This does not mean success!  If the FTERM window
  128. X    closes again with the message "unable to connect", it was unable
  129. X    to connect.  There are several possibilities:
  130. X
  131. X    (a) You do not have an 8 bit connection from your amiga to the
  132. X        UNIX host (DNet must be able to send and receive all 256
  133. X        character codes).
  134. X
  135. X    (b) You did not setup the DNETDIR enviroment variable properly
  136. X
  137. X    (c) You did not copy dnet.servers into $DNETIDR
  138. X
  139. X    (d) The absolute file path in dnet.servers for server #8192 (that
  140. X        FTerm tires to connect to) is not correct.
  141. X
  142. X                    KILLING DNET
  143. X
  144. X    In most cases simply turning off the modem will suffice.  You can
  145. X    kill dnet more cleanly with the following sequence:
  146. X
  147. X    (1) From an Amiga CLI, run the QuitDnet command.  This will kill
  148. X        the packet protocol and cause the remote DNet to exit.
  149. X
  150. X    (2) From an Amiga CLI, BREAK the protocol process.  You should get
  151. X        the original (small) DNet window and the original login shell.
  152. X        If you get the DNet window but not the shell (you can't type),
  153. X        the protocol may still be running on the other end, in which
  154. X        case you forgot to QuitDnet or it didn't work for some
  155. X        unknown reason.  Restart the protocol w/ the appropriate
  156. X        menu option and try again.
  157. X
  158. X    (3) logout normally and close the DNet window.  Turn off your
  159. X        modem.
  160. X
  161. X                 HANGING SERVER PROCESSES
  162. X
  163. X    The UNIX side servers are normally left running when the protocol
  164. X    dies.  These are very very very small and take 0 CPU (they are
  165. X    simply waiting for connections).  These servers will still be
  166. X    there when you log in again and DNet will use them.
  167. X
  168. X    You can kill UNIX side servers at any time.
  169. X
  170. X    Many of the same clients and servers exist on the UNIX end as
  171. X    on the Amiga end.  The UNIX end is missing several.  The UNIX
  172. X    end implements two commands called dsoc and draw which can be
  173. X    used to connect to (in cooked or raw tty mode) specific servers
  174. X    (by port #) on the Amiga side.  For example, to connect to the
  175. X    printer server on the amiga side:
  176. X
  177. X    % dsoc 8198
  178. X    This is a test
  179. X    ^D
  180. X    %
  181. X
  182. X    Dumps to PRT: on the Amiga "This is a test"  Gee Wiz!
  183. X
  184. X                SECURITY W/ UNIX
  185. X
  186. X    DNet will be as secure as your account, assuming you chmod DNETDIR
  187. X    700 (so nobody else has access to the unix domain sockets).  From
  188. X    Home, I usually RUN DNET -X , login, start the protocol, and leave
  189. X    it running all day.
  190. X
  191. X    The -X option turns of security (sets all security levels to 9),
  192. X    thus allowing me to drive to the university and at any time from
  193. X    my UNIX account do a getfiles or putfiles from and to my Amiga.
  194. X
  195. X    Refer to the amiga side documentation for more information.
  196. X
  197. X
  198. X
  199. SHAR_EOF
  200. echo "extracting TODO"
  201. sed 's/^X//' << \SHAR_EOF > TODO
  202. X
  203. X    -current connect is done synchronously.  It should be done asynchronously
  204. X     incase the server is hung, but it really doesn't matter since the
  205. X     servers are so incredibly easy to write and are always accepting new
  206. X     connections (I hope).
  207. X
  208. X    -packet size reduction should also depend on the baud rate
  209. X
  210. SHAR_EOF
  211. if `test ! -d client`
  212. then
  213.   mkdir client
  214.   echo "mkdir client"
  215. fi
  216. echo "extracting client/getfiles.c"
  217. sed 's/^X//' << \SHAR_EOF > client/getfiles.c
  218. X
  219. X/*
  220. X *  GETFILES.C        V1.30
  221. X *
  222. X *  DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
  223. X *
  224. X *  GETFILES [-dlocaldir] [-c] file/dir file/dir file/dir
  225. X *
  226. X *  -dlocaldir    local directory to place files
  227. X *
  228. X *  -c        Continue from where you left off before.  Files that already
  229. X *        exist on the local machine will not be re-transfered.  This
  230. X *        will also re-start in the middle of a file that was
  231. X *        partially transfered previously.
  232. X *
  233. X *        This command assumes the file(s) on both machines have not
  234. X *        been modified since the first attempt.    No other checking
  235. X *        is done at the moment.
  236. X */
  237. X
  238. X#include <stdio.h>
  239. X#include <sys/types.h>
  240. X#include <sys/file.h>
  241. X#include <sys/stat.h>
  242. X#include "../server/servers.h"
  243. X
  244. Xtypedef unsigned char ubyte;
  245. X
  246. Xtypedef struct {
  247. X    char    Cmd;
  248. X    char    Str[64];
  249. X    long    Val;
  250. X} HDR;
  251. X
  252. Xchar *NSpaces();
  253. X
  254. Xchar Buf[1024];
  255. X
  256. Xshort ContMode;
  257. Xchar  *NetId;
  258. Xlong  Chan = -1;
  259. X
  260. Xmain(ac,av)
  261. Xchar *av[];
  262. X{
  263. X    HDR Hdr;
  264. X    short error;
  265. X
  266. X    {
  267. X    char *ldir = ".";
  268. X    struct stat stat;
  269. X    ac = DoOption(ac, av, "N%sd%sc", &NetId, &ldir, &ContMode);
  270. X    if (ac <= 1) {
  271. X        puts("GETFILES [-Nnetid -dlocaldir -c] remotefile/dir ...");
  272. X        fail(22);
  273. X    }
  274. X    if (chdir(ldir) < 0) {
  275. X        mkdir(ldir, 0777);
  276. X        if (chdir(ldir) < 0) {
  277. X        printf("Unable to CD or make local directory: \"%s\"\n",ldir);
  278. X        fail(21);
  279. X        }
  280. X    }
  281. X    }
  282. X    Chan = DOpen(NetId, PORT_GFILECOPY, 126, -80);
  283. X    if (Chan < 0) {
  284. X    puts("Unable to connect");
  285. X    fail(20);
  286. X    }
  287. X    error = WriteHeader('H', "Hello, getfiles client V1.30", 0);
  288. X    if (error)
  289. X    fail(LostChannel());
  290. X    switch(ReadHeader(&Hdr)) {
  291. X    case -1:
  292. X    fail(LostChannel());
  293. X    case 'H':
  294. X    printf("%s\n", Hdr.Str);
  295. X    break;
  296. X    }
  297. X    {
  298. X    register short i;
  299. X    long val;
  300. X
  301. X    for (i = 1; i < ac; ++i) {
  302. X        short error;
  303. X
  304. X        error = WriteHeader('G', av[i], 0);
  305. X        if (error)
  306. X        fail(LostChannel());
  307. X        switch(ReadHeader(&Hdr)) {
  308. X        case -1:
  309. X        fail(LostChannel());
  310. X        case 'N':
  311. X        printf("Remote error on %s: %s\n", av[i], Hdr.Str);
  312. X        break;
  313. X        case 'F':
  314. X        error = CheckNoPath(Hdr.Str);
  315. X        if (!error) {
  316. X            char svpath[1024];
  317. X            getwd(svpath);
  318. X            error = GetFile(&Hdr, 0);
  319. X            chdir(svpath);
  320. X        }
  321. X        break;
  322. X        case 'D':
  323. X        error = CheckNoPath(Hdr.Str);
  324. X        if (!error) {
  325. X            char svpath[1024];
  326. X            getwd(svpath);
  327. X            error = GetDir(&Hdr, 0);
  328. X            chdir(svpath);
  329. X        }
  330. X        break;
  331. X        case 'S':
  332. X        printf("Access Violation: %s\n", Hdr.Str);
  333. X        break;
  334. X        default:
  335. X        error = UnknownCmd(&Hdr);
  336. X        break;
  337. X        }
  338. X        if (error)
  339. X        fail(error);
  340. X    }
  341. X    if (!error) {
  342. X        error = WriteHeader('E', "bye", 0);
  343. X        if (error)
  344. X        fail(LostChannel());
  345. X    }
  346. X    }
  347. X    fail(0);
  348. X}
  349. X
  350. Xfail(code)
  351. X{
  352. X    if (Chan >= 0)
  353. X    close(Chan);
  354. X    exit(code);
  355. X}
  356. X
  357. XCheckNoPath(str)
  358. Xregister char *str;
  359. X{
  360. X    while (*str) {
  361. X    if (*str == '/' || *str == ':') {
  362. X        puts("SECURITY ALERT: Illegal path spec received");
  363. X        return(40);
  364. X    }
  365. X    ++str;
  366. X    }
  367. X    return(0);
  368. X}
  369. X
  370. XLostChannel()
  371. X{
  372. X    puts("DATA CHANNEL LOST");
  373. X    return(10);
  374. X}
  375. X
  376. XUnknownCmd(hdr)
  377. XHDR *hdr;
  378. X{
  379. X    printf("Unrecognized command code: %02x\n", hdr->Cmd);
  380. X}
  381. X
  382. X/*
  383. X *  retrieve a file.  If ContMode set and file exists, try to append to
  384. X *  it.
  385. X */
  386. X
  387. X
  388. X#define BSSTR "\010\010\010\010\010\010\010\010\010\010\010\010\010"
  389. X
  390. XGetFile(hdr, stab)
  391. XHDR *hdr;
  392. X{
  393. X    int fd = -1;
  394. X    long pos = 0;
  395. X    short error = 0;
  396. X
  397. X    printf("%s%-20s ", NSpaces(stab), hdr->Str);
  398. X    fflush(stdout);
  399. X    if (ContMode) {
  400. X    if ((fd = open(hdr->Str, O_WRONLY)) >= 0) {    /*  already exists  */
  401. X        long len;
  402. X
  403. X        len = lseek(fd, 0L, 2);
  404. X        if (len > hdr->Val) {
  405. X        close(fd);
  406. X        printf("Cont Error, local file is larger than remote!: %s\n",
  407. X           hdr->Str
  408. X        );
  409. X        puts("(not downloaded)");
  410. X        return(0);
  411. X        }
  412. X        if (len == hdr->Val) {
  413. X        close(fd);
  414. X        if (error = WriteHeader('S', NULL, 0))
  415. X            return(LostChannel());
  416. X        puts("HAVE IT, SKIP");
  417. X        return(0);
  418. X        }
  419. X        printf("(HAVE %ld/%ld) ", len, hdr->Val);
  420. X        hdr->Val -= len;        /*  that much less  */
  421. X        pos = len;            /*  start at offset */
  422. X    }
  423. X    }
  424. X    if (fd < 0) {
  425. X    fd = open(hdr->Str, O_WRONLY|O_CREAT|O_TRUNC, 0666);
  426. X    if (fd < 0) {
  427. X        error = WriteHeader('N', "open error", 0);
  428. X        printf("Unable to open %s for output\n", hdr->Str);
  429. X        if (error)
  430. X        return(LostChannel());
  431. X        return(1);
  432. X    }
  433. X    }
  434. X    error = WriteHeader('Y', NULL, pos);    /*  yes, gimme gimme    */
  435. X
  436. X    /*
  437. X     *    Retrieve the data
  438. X     */
  439. X
  440. X    if (!error) {
  441. X    register long left = hdr->Val;
  442. X    register long cnt = pos;
  443. X    long total = pos + left;
  444. X
  445. X    printf("             ");
  446. X    while (left) {
  447. X        register long n = (left > sizeof(Buf)) ? sizeof(Buf) : left;
  448. X        printf("%s%6ld/%6ld", BSSTR, cnt, total);
  449. X        fflush(stdout);
  450. X        if (ggread(Chan, Buf, n) != n) {
  451. X        error = 5;
  452. X        break;
  453. X        }
  454. X        if (write(fd, Buf, n) != n) {
  455. X        puts("Local Write failed!");
  456. X        error = 6;
  457. X        break;
  458. X        }
  459. X        left -= n;
  460. X        cnt += n;
  461. X    }
  462. X    printf("%s%6ld/%6ld  %s", BSSTR, cnt, total, 
  463. X        ((cnt == total) ? "OK" : "INCOMPLETE")
  464. X    );
  465. X    }
  466. X    puts("");
  467. X    if (error) {
  468. X    fchmod(fd, 0222);
  469. X    close(fd);
  470. X    return(LostChannel());
  471. X    }
  472. X    close(fd);
  473. X    return(error);
  474. X}
  475. X
  476. X/*
  477. X *  Retrieve a directory.  Create it if necessary.
  478. X */
  479. X
  480. XGetDir(hdr, stab)
  481. XHDR *hdr;
  482. X{
  483. X    short error = 0;
  484. X    long dirlock;
  485. X    static HDR Hdr;        /*    note: static */
  486. X    char svpath[1024];
  487. X
  488. X    printf("%s%-20s(DIR)\n", NSpaces(stab), hdr->Str);
  489. X    getwd(svpath);
  490. X    if (chdir(hdr->Str) < 0) {
  491. X    mkdir(hdr->Str, 0777);
  492. X    if (chdir(hdr->Str) < 0) {
  493. X        error = WriteHeader('N', "couldn't create", 0);
  494. X        printf("Unable to create local directory: %s\n", hdr->Str);
  495. X        if (error)
  496. X            return(LostChannel());
  497. X        return(1);
  498. X    }
  499. X    }
  500. X    error = WriteHeader('Y', NULL, 0);  /*  yes, gimme gimme    */
  501. X    while (!error) {
  502. X    switch(ReadHeader(&Hdr)) {
  503. X    case -1:
  504. X        error = 1;
  505. X        break;
  506. X    case 'E':                   /*  end of directory    */
  507. X        chdir(svpath);
  508. X        return(0);
  509. X        break;
  510. X    case 'F':
  511. X        error = CheckNoPath(Hdr.Str);
  512. X        if (!error) {
  513. X        char svpath2[1024];
  514. X        getwd(svpath2);
  515. X        error = GetFile(&Hdr, stab + 4);
  516. X        chdir(svpath2);
  517. X        }
  518. X        break;
  519. X    case 'D':
  520. X        error = CheckNoPath(Hdr.Str);
  521. X        if (!error) {
  522. X        char svpath2[1024];
  523. X        getwd(svpath2);
  524. X        error = GetDir(&Hdr, stab + 4);
  525. X        chdir(svpath2);
  526. X        }
  527. X        break;
  528. X    case 'S':
  529. X        printf("Access Violation: %s\n", Hdr.Str);
  530. X        break;
  531. X    case 'N':
  532. X        printf("REMOTE ERROR: %s\n", Hdr.Str);
  533. X        error = 10;
  534. X        break;
  535. X    default:
  536. X        error = UnknownCmd(&Hdr);
  537. X        break;
  538. X    }
  539. X    }
  540. X    chdir(svpath);
  541. X    return(LostChannel());
  542. X}
  543. X
  544. XWriteHeader(c, str, len)
  545. Xchar c;
  546. Xchar *str;
  547. Xlong len;
  548. X{
  549. X    ubyte sl;
  550. X
  551. X    if (str == NULL)
  552. X    str = "";
  553. X    sl = strlen(str);
  554. X
  555. X    if (gwrite(Chan, &c, 1) < 0)
  556. X    return(1);
  557. X    if (gwrite(Chan, &sl,1) < 0)
  558. X    return(1);
  559. X    if (gwrite(Chan, str, sl) != sl)
  560. X    return(1);
  561. X    len = htonl68(len);
  562. X    if (gwrite(Chan, &len, 4) != 4)
  563. X    return(1);
  564. X    return(0);
  565. X}
  566. X
  567. XReadHeader(hdr)
  568. XHDR *hdr;
  569. X{
  570. X    ubyte sl;
  571. X    ubyte cmd;
  572. X
  573. X    hdr->Cmd = -1;
  574. X    if (ggread(Chan, &cmd, 1) != 1)
  575. X    return(-1);
  576. X    if (ggread(Chan, &sl, 1) != 1)
  577. X    return(-1);
  578. X    if (sl >= sizeof(hdr->Str)) {
  579. X    puts("Software error: received file name length too long");
  580. X    return(-1);
  581. X    }
  582. X    if (ggread(Chan, hdr->Str, sl) != sl)
  583. X    return(-1);
  584. X    hdr->Str[sl] = 0;
  585. X    if (ggread(Chan, &hdr->Val, 4) != 4)
  586. X    return(-1);
  587. X    hdr->Val = ntohl68(hdr->Val);
  588. X    hdr->Cmd = cmd;
  589. X    return(hdr->Cmd);
  590. X}
  591. X
  592. Xchar *
  593. XNSpaces(n)
  594. Xshort n;
  595. X{
  596. X    static char Buf[128];
  597. X    static short in = 0;
  598. X    static short last;
  599. X
  600. X    if (in == 0) {
  601. X    register short i;
  602. X    in = 1;
  603. X    for (i = 0; i < sizeof(Buf); ++i)
  604. X        Buf[i] = ' ';
  605. X    }
  606. X    Buf[last] = ' ';
  607. X    if (n < 127)
  608. X    Buf[n] = 0;
  609. X    last = n;
  610. X    return(Buf);
  611. X}
  612. X
  613. SHAR_EOF
  614. echo "extracting client/putfiles.c"
  615. sed 's/^X//' << \SHAR_EOF > client/putfiles.c
  616. X
  617. X/*
  618. X *  PUTFILES.C
  619. X *
  620. X *    DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved
  621. X *
  622. X *  Download one or more files from the remote computer
  623. X *
  624. X *  PUTFILES file/dir1 file/dir2 ... file/dirN
  625. X *
  626. X *  placed in directory server ran from on remote host.
  627. X */
  628. X
  629. X#include <sys/types.h>
  630. X#include <sys/stat.h>
  631. X#include <sys/dir.h>
  632. X#include <stdio.h>
  633. X#include <sys/file.h>
  634. X#include "../server/servers.h"
  635. X
  636. Xchar Buf[1024];
  637. X
  638. Xtypedef struct stat STAT;
  639. X
  640. Xmain(ac,av)
  641. Xchar *av[];
  642. X{
  643. X    long chan;
  644. X    long n, len, orig;
  645. X    long fh;
  646. X    short i, j;
  647. X    char fn;
  648. X
  649. X    if (ac == 1) {
  650. X    puts("putfiles V1.00 (c)Copyright 1987, Matthew Dillon, All Rights Reserved");
  651. X    puts("putfiles file/dir file/dir .....");
  652. X    exit(1);
  653. X    }
  654. X
  655. X    chan = DOpen(NULL, PORT_FILECOPY, -80, 126);
  656. X    if (chan < 0) {
  657. X    puts("Unable to connect");
  658. X    exit(1);
  659. X    }
  660. X    ggread(chan, &fn, 1);
  661. X    if (fn != 'Y') {
  662. X    puts("Remote Server Software Error");
  663. X    close(chan);
  664. X    }
  665. X    for (i = 1; i < ac; ++i) {
  666. X    if (strncmp(av[i], "-d", 2) == 0) {/*-ddir or -d dir*/
  667. X        char *dir = av[i]+2;
  668. X        if (*dir == 0 && i+1 < ac) {
  669. X        ++i;
  670. X        dir = av[i];
  671. X        }
  672. X        if (writehdr_nc(chan, 'C', dir, 0) != 'Y') {
  673. X        puts ("unable to go to specified remote directory");
  674. X        break;
  675. X        }
  676. X    } else {
  677. X        if (putname(chan, av[i]) < 0)
  678. X            break;
  679. X    }
  680. X    }
  681. X    printf("\nclosing... ");
  682. X    fflush(stdout);
  683. X    close(chan);
  684. X    puts("done");
  685. X}
  686. X
  687. Xputname(chan, file)
  688. Xchar *file;
  689. X{
  690. X    STAT sstat;
  691. X    char svdir[256];
  692. X    int ret;
  693. X
  694. X    printf("%-20s ", file);
  695. X    if (stat(file, &sstat) < 0) {
  696. X    puts("NOT FOUND");
  697. X    return(1);
  698. X    }
  699. X    if (sstat.st_mode & S_IFDIR) {
  700. X    DIR *dir;
  701. X    struct direct *de;
  702. X
  703. X    getwd(svdir);
  704. X    puts("DIR");
  705. X    chdir(file);
  706. X    if (writehdr(chan, 'X', file, 0) != 'Y') {
  707. X        puts("Remote unable to make directory");
  708. X        goto f1;
  709. X    }
  710. X    if (dir = opendir(".")) {
  711. X        while (de = readdir(dir))  {
  712. X        if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name,"..")==0)
  713. X            continue;
  714. X        if (putname(chan, de->d_name) < 0) {
  715. X            ret = -1;
  716. X            break;
  717. X        }
  718. X        }
  719. X    }
  720. X    writehdr(chan, 'Y', "?", 0);
  721. Xf1:
  722. X    chdir(svdir);
  723. X    } else {
  724. X    ret = putfile(chan, file);
  725. X    }
  726. X    return(ret);
  727. X}
  728. X
  729. Xputfile(chan, file)
  730. Xchar *file;
  731. X{
  732. X    int fd = open(file, O_RDONLY);
  733. X    long n, r, len;
  734. X    long ttl = 0;
  735. X    char co;
  736. X
  737. X    fflush(stdout);
  738. X    if (fd < 0) {
  739. X    puts("FILE NOT FOUND");
  740. X    return(0);
  741. X    }
  742. X    len = ttl = lseek(fd, 0, 2);
  743. X    lseek(fd, 0, 0);
  744. X    if (writehdr(chan, 'W', file, len) != 'Y') {
  745. X    puts("REMOTE UNABLE TO ACCEPT FILE");
  746. X    close(fd);
  747. X    return(0);
  748. X    }
  749. X    printf("%6ld/%-6ld", ttl - len, ttl);
  750. X    while (len) {
  751. X    fflush(stdout);
  752. X    r = (len > sizeof(Buf)) ? sizeof(Buf) : len;
  753. X    n = read(fd, Buf, r);
  754. X    if (n != r) {
  755. X        puts("Local File error");
  756. X        close(fd);
  757. X        return(-1);
  758. X    }
  759. X    if (gwrite(chan, Buf, n) != n) {
  760. X        puts("Remote error");
  761. X        close(fd);
  762. X        return(-1);
  763. X    }
  764. X    len -= n;
  765. X    printf("\010\010\010\010\010\010\010\010\010\010\010\010\010");
  766. X    printf("%6ld/%-6ld", ttl - len, ttl);
  767. X    }
  768. X    close(fd);
  769. X    if (len) {
  770. X    puts("REMOTE ERROR");
  771. X    return(-1);
  772. X    }
  773. X    printf("  Queued, waiting... ");
  774. X    fflush(stdout);
  775. X    ggread(chan, &co, 1);
  776. X    if (co != 'Y') {
  777. X    puts("Remote Server Software Error");
  778. X    return(-1);
  779. X    }
  780. X    puts("OK");
  781. X    return(0);
  782. X}
  783. X
  784. Xwritehdr(chan, c, name, len)
  785. Xunsigned char c;
  786. Xchar *name;
  787. Xlong len;
  788. X{
  789. X    short i;
  790. X    for (i = strlen(name) - 1; i >= 0; --i) {
  791. X    if (name[i] == '/' || name[i] == ':')
  792. X        break;
  793. X    }
  794. X    name += i + 1;
  795. X    return(writehdr_nc(chan, c, name, len));
  796. X}
  797. X
  798. Xwritehdr_nc(chan, c, name, len)
  799. Xunsigned char c;
  800. Xchar *name;
  801. Xlong len;
  802. X{
  803. X    gwrite(chan, &c, 1);
  804. X    c = strlen(name) + 1;
  805. X    gwrite(chan, &c, 1);
  806. X    gwrite(chan, name, c);
  807. X    len = htonl68(len);
  808. X    gwrite(chan, &len, 4);
  809. X    if (ggread(chan, &c, 1) == 1)
  810. X    return(c);
  811. X    return(-1);
  812. X}
  813. X
  814. SHAR_EOF
  815. echo "extracting client/dsoc.c"
  816. sed 's/^X//' << \SHAR_EOF > client/dsoc.c
  817. X
  818. X/*
  819. X *    DSOC.C
  820. X *
  821. X *    DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved
  822. X *
  823. X *    DSOC [port#]
  824. X *
  825. X *      Connect to the specified port# .. Used to connect to a remote CLI
  826. X *    (s_shell server on the Amiga, which requires PIPE: to work, port 8196,
  827. X *    is the default)
  828. X *
  829. X *    Uses standard cooked mode instead of RAW mode.
  830. X */
  831. X
  832. X
  833. X#include <sys/types.h>
  834. X#include <sys/ioctl.h>
  835. X#include <stdio.h>
  836. X#include <sys/file.h>
  837. X#include <signal.h>
  838. X#include <errno.h>
  839. X#include "../server/servers.h"
  840. X
  841. Xint fd;
  842. Xchar buf[2048];
  843. X
  844. Xmain(ac,av)
  845. Xchar *av[];
  846. X{
  847. X    int n;
  848. X    extern int handler();
  849. X    int port = (av[1]) ? atoi(av[1]) : PORT_AMIGASHELL;
  850. X
  851. X    puts("DSOC V1.01 11 March 1988 Connecting");
  852. X    fd = DOpen(NULL, port, 0, 0);
  853. X    if (fd < 0) {
  854. X    perror("DOpen");
  855. X    exit(1);
  856. X    }
  857. X    puts("Connected");
  858. X    signal(SIGIO, handler);
  859. X    fcntl(fd, F_SETOWN, getpid());
  860. X    fcntl(fd, F_SETFL, FNDELAY|FASYNC);
  861. X    while ((n = gread(0, buf, sizeof(buf))) > 0) {
  862. X    gwrite(fd, buf, n);
  863. X    }
  864. X    fprintf(stderr, "EOF\n");
  865. X    DEof(fd);
  866. X    for (;;)
  867. X    pause();
  868. X}
  869. X
  870. Xhandler()
  871. X{
  872. X    int n;
  873. X    char buf[1024];
  874. X
  875. X    while ((n = read(fd, buf, sizeof(buf))) > 0) 
  876. X    write(1, buf, n);
  877. X    if (n == 0) {
  878. X    write(1, "REMEOF\n", 7);
  879. X    exit(1);
  880. X    }
  881. X}
  882. X
  883. SHAR_EOF
  884. echo "extracting client/draw.c"
  885. sed 's/^X//' << \SHAR_EOF > client/draw.c
  886. X
  887. X/*
  888. X *    DRAW.C
  889. X *
  890. X *    DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved
  891. X *
  892. X *    DRAW [port#]
  893. X *
  894. X *    Put terminal into RAW mode and connect to the remote dnet port.
  895. X *    used mainly to test DNET.  Can also be used open a TERM window on
  896. X *    the amiga (via the STERM server), which is the default (port 8195)
  897. X */
  898. X
  899. X
  900. X
  901. X#include <sys/types.h>
  902. X#include <sys/ioctl.h>
  903. X#include <stdio.h>
  904. X#include <sys/file.h>
  905. X#include <signal.h>
  906. X#include <errno.h>
  907. X#include "../server/servers.h"
  908. X
  909. Xint fd;
  910. Xchar buf[4096];
  911. X
  912. Xmain(ac,av)
  913. Xchar *av[];
  914. X{
  915. X    int n;
  916. X    extern int handler();
  917. X    int port = (av[1]) ? atoi(av[1]) : PORT_AMIGATERM;
  918. X
  919. X    puts("DRAW V1.01 11 March 1988 Connecting");
  920. X    fd = DOpen(NULL, port, 0, 0);
  921. X    if (fd < 0) {
  922. X    perror("DOpen");
  923. X    exit(1);
  924. X    }
  925. X    puts("Connected");
  926. X    signal(SIGIO, handler);
  927. X    ttyraw();
  928. X    fcntl(fd, F_SETOWN, getpid());
  929. X    fcntl(fd, F_SETFL, FNDELAY|FASYNC);
  930. X    fcntl(0,  F_SETFL, FNDELAY);
  931. X    while ((n = gread(0, buf, sizeof(buf))) > 0) {
  932. X    gwrite(fd, buf, n);
  933. X    }
  934. X    fprintf(stderr, "EOF\n");
  935. X    DEof(fd);
  936. X    for (;;)
  937. X    pause();
  938. X}
  939. X
  940. Xhandler()
  941. X{
  942. X    int n;
  943. X    char buf[1024];
  944. X
  945. X    while ((n = read(fd, buf, sizeof(buf))) > 0) 
  946. X    write(1, buf, n);
  947. X    if (n == 0) {
  948. X    write(1, "REMEOF\n", 7);
  949. X    ttynormal();
  950. X    exit(1);
  951. X    }
  952. X}
  953. X
  954. Xstatic struct sgttyb ttym;
  955. X
  956. Xttyraw()
  957. X{
  958. X    ioctl (0, TIOCGETP, &ttym);
  959. X    ttym.sg_flags |= RAW;
  960. X    ttym.sg_flags &= ~CBREAK;
  961. X    ttym.sg_flags &= ~ECHO;
  962. X    ioctl (0, TIOCSETP, &ttym);
  963. X}
  964. X
  965. Xttynormal()
  966. X{
  967. X    ioctl (0, TIOCGETP, &ttym);
  968. X    ttym.sg_flags &= ~RAW;
  969. X    ttym.sg_flags |= CBREAK;
  970. X    ttym.sg_flags |= ECHO;
  971. X    ioctl (0, TIOCSETP, &ttym);
  972. X}
  973. X
  974. SHAR_EOF
  975. echo "extracting client/dprint.c"
  976. sed 's/^X//' << \SHAR_EOF > client/dprint.c
  977. X
  978. X/*
  979. X *  DPRINT.C
  980. X *
  981. X *    DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved
  982. X *
  983. X *  send files to the other computer's printer.
  984. X *
  985. X *  DPRINT [files]    (stdin if no files specified)
  986. X */
  987. X
  988. X#include <stdio.h>
  989. X#include "../server/servers.h"
  990. X
  991. Xmain(ac,av)
  992. Xchar *av[];
  993. X{
  994. X    register short i;
  995. X    long chan;
  996. X
  997. X    chan = DOpen(NULL, PORT_PRINTER, -80, 126);
  998. X    if (chan < 0) {
  999. X    puts("Unable to connect");
  1000. X    exit(1);
  1001. X    }
  1002. X    for (i = 1; i < ac; ++i) {
  1003. X    FILE *fi;
  1004. X
  1005. X    printf("%-20s ", av[i]);
  1006. X    fflush(stdout);
  1007. X    if (fi = fopen(av[i], "r")) {
  1008. X        printf("dumping ");
  1009. X        fflush(stdout);
  1010. X        dump_file(fi, chan);
  1011. X        fclose(fi);
  1012. X        puts("");
  1013. X    }
  1014. X    }
  1015. X    if (ac == 1)
  1016. X    dump_file(stdin, chan);
  1017. X    close(chan);
  1018. X}
  1019. X
  1020. Xdump_file(fi, chan)
  1021. XFILE *fi;
  1022. X{
  1023. X    int n;
  1024. X    char buf[256];
  1025. X
  1026. X    while ((n = fread(buf, 1, sizeof(buf), fi)) > 0) {
  1027. X    gwrite(chan, buf, n);
  1028. X    }
  1029. X}
  1030. X
  1031. SHAR_EOF
  1032. echo "extracting client/Makefile"
  1033. sed 's/^X//' << \SHAR_EOF > client/Makefile
  1034. X
  1035. X#    DNET CLIENTS
  1036. X#
  1037. X#   DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
  1038. X#
  1039. X
  1040. XNETLIB = ../lib/dnetlib.o
  1041. XBIN = ../bin
  1042. X
  1043. X
  1044. Xall:    $(NETLIB) $(BIN)/draw $(BIN)/dsoc $(BIN)/putfiles $(BIN)/dprint \
  1045. X    $(BIN)/getfiles
  1046. X
  1047. X$(BIN)/draw:        draw.o
  1048. X    cc draw.o $(NETLIB) -o $(BIN)/draw
  1049. X
  1050. X$(BIN)/dsoc:        dsoc.o
  1051. X    cc dsoc.o $(NETLIB) -o $(BIN)/dsoc
  1052. X
  1053. X$(BIN)/getfiles:        getfiles.o 
  1054. X    cc getfiles.o $(NETLIB) -o $(BIN)/getfiles
  1055. X
  1056. X$(BIN)/putfiles:        putfiles.o 
  1057. X    cc putfiles.o $(NETLIB) -o $(BIN)/putfiles
  1058. X
  1059. X$(BIN)/dprint:        dprint.o
  1060. X    cc dprint.o $(NETLIB) -o $(BIN)/dprint
  1061. X
  1062. Xclean:
  1063. X    rm -f *.o make.out
  1064. X
  1065. SHAR_EOF
  1066. if `test ! -d dnet`
  1067. then
  1068.   mkdir dnet
  1069.   echo "mkdir dnet"
  1070. fi
  1071. echo "extracting dnet/channel.h"
  1072. sed 's/^X//' << \SHAR_EOF > dnet/channel.h
  1073. X
  1074. X/*
  1075. X *  CHANNEL.H
  1076. X *
  1077. X *    DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved
  1078. X *
  1079. X *  Channel structures for SCMD_* channel commands.
  1080. X *
  1081. X *  NOTE: These structures may be ONLY 0,2,4, or 6 bytes in size.
  1082. X */
  1083. X
  1084. X#define CSWITCH struct _CSWITCH
  1085. X#define COPEN    struct _COPEN
  1086. X#define CCLOSE    struct _CCLOSE
  1087. X#define CACKCMD struct _CACKCMD
  1088. X#define CEOFCMD struct _CEOFCMD
  1089. X#define CIOCTL  struct _CIOCTL
  1090. X
  1091. XCSWITCH {        /*  SWITCH current data channel */
  1092. X    ubyte   chanh;    /*  channel to switch to    */
  1093. X    ubyte   chanl;
  1094. X};
  1095. X
  1096. XCOPEN {         /*  OPEN port on channel    */
  1097. X    ubyte   chanh;    /*  try to use this channel     */
  1098. X    ubyte   chanl;
  1099. X    ubyte   porth;    /*  requested port from client  */
  1100. X    ubyte   portl;
  1101. X    ubyte   error;    /*  error return 0=ok        */
  1102. X    char    pri;    /*  chan. priority -127 to 126  */
  1103. X};
  1104. X
  1105. XCCLOSE {        /*  CLOSE a channel        */
  1106. X    ubyte   chanh;    /*  channel to close        */
  1107. X    ubyte   chanl;
  1108. X};
  1109. X
  1110. XCACKCMD {        /*  Acknowledge an open            */
  1111. X    ubyte   chanh;    /*  channel               */
  1112. X    ubyte   chanl;
  1113. X    ubyte   error;    /*  0=ok 1=fail 33=retry w/ different channel    */
  1114. X    ubyte   filler;
  1115. X};
  1116. X
  1117. XCEOFCMD {        /*  Send [R/W] EOF        */
  1118. X    ubyte   chanh;    /*  channel to send EOF on    */
  1119. X    ubyte   chanl;
  1120. X    ubyte   flags;    /*  CHANF_ROK/WOK (bits to clear)  */
  1121. X    ubyte   filler;
  1122. X};
  1123. X
  1124. XCIOCTL {
  1125. X    ubyte   chanh;    /* channel            */
  1126. X    ubyte   chanl;
  1127. X    ubyte   cmd;    /* ioctl command        */
  1128. X    ubyte   valh;    /* ioctl value            */
  1129. X    ubyte   vall;
  1130. X    ubyte   valaux;    /* auxillary field        */
  1131. X};
  1132. X
  1133. X#define CIO_SETROWS    1    /* PTY's only            */
  1134. X#define CIO_SETCOLS    2    /* PTY's only            */
  1135. X#define CIO_STOP    3    /* any channel, flow control    */
  1136. X#define CIO_START    4    /* any channel, flow control    */
  1137. X#define CIO_FLUSH    5    /* any channel, flush pending     */  
  1138. X                /* writes down the toilet    */
  1139. X
  1140. X#define CHAN    struct _CHAN
  1141. X
  1142. XCHAN {
  1143. X    int        fd;        /*    file descriptor for channel        */
  1144. X    uword   port;    /*    port#  (used in open sequence)        */
  1145. X    ubyte   state;    /*    state of channel            */
  1146. X    ubyte   flags;    /*    channel flags                */
  1147. X    char    pri;    /*    priority of channel            */
  1148. X};
  1149. X
  1150. SHAR_EOF
  1151. echo "extracting dnet/control.c"
  1152. sed 's/^X//' << \SHAR_EOF > dnet/control.c
  1153. X
  1154. X/*
  1155. X *  CONTROL.C
  1156. X *
  1157. X *    DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved
  1158. X *
  1159. X *  -handle various actions:
  1160. X *    RTO    - read timeout
  1161. X *    WTO    - write timeout (a packet not acked)
  1162. X *    RNET    - state machine for raw receive packet
  1163. X *    WNET    - starts timeout sequence if Write occured
  1164. X *    WUPDATE - update write windows, send packets
  1165. X *    RUPDATE - execute received packets in correct sequence
  1166. X *    RECCMD    - execute decoded SCMD commands obtained from received
  1167. X *            packets.
  1168. X */
  1169. X
  1170. X#include "dnet.h"
  1171. X#include <stdio.h>
  1172. X
  1173. Xextern void do_cmd();
  1174. X
  1175. X/*
  1176. X *  RTO:    read timeout.   Timeout occured while waiting for the rest of
  1177. X *        a packet.  Reset state and restart read.
  1178. X */
  1179. X
  1180. Xdo_rto()
  1181. X{
  1182. X    RState = 0;
  1183. X    RcvData = 0;
  1184. X    if (DDebug)
  1185. X    fprintf(stderr, "RTO\n");
  1186. X}
  1187. X
  1188. X/*
  1189. X *  WTO:    Write timeout (unresolved output windows exist).  Resend a CHECK
  1190. X *        command for all unresolved (READY) output windows
  1191. X */
  1192. X
  1193. Xvoid
  1194. Xdo_wto()
  1195. X{
  1196. X    register short i;
  1197. X    register PKT *pkt;
  1198. X    register uword len = 0;
  1199. X
  1200. X    if (DDebug)
  1201. X    fprintf(stderr, "WTO\n");
  1202. X    if (Restart) {
  1203. X    WCBuf[0] = SYNC;
  1204. X    WCBuf[1] = PKCMD_RESTART;
  1205. X    WCBuf[2] = (WCBuf[0]<<1)^WCBuf[1];
  1206. X    NetWrite(WCBuf, 3, 1);
  1207. X    WTimeout(WTIME);
  1208. X    return;
  1209. X    }
  1210. X    for (i = 0; i < WPUsed; ++i) {
  1211. X    pkt = WPak[i];
  1212. X    if (pkt->state == READY) {  /*  send check  */
  1213. X        WCBuf[len+0] = SYNC;
  1214. X        WCBuf[len+1] = PKCMD_CHECK | ((WPStart + i) << 5);
  1215. X        WCBuf[len+2] = (WCBuf[len+0] << 1) ^ WCBuf[len+1];
  1216. X        len += 3;
  1217. X    }
  1218. X    }
  1219. X    if (len) {
  1220. X    NetWrite(WCBuf, len, 1);
  1221. X    WTimeout(WTIME);
  1222. X    }
  1223. X}
  1224. X
  1225. X/*
  1226. X *  RNET:   Receved data ready from network.  The RNet request will
  1227. X *        automagically be reissued on return.
  1228. X */
  1229. X
  1230. Xdo_rnet()
  1231. X{
  1232. X    register ubyte *ptr = RcvBuf;
  1233. X    register long len  = RcvData;
  1234. X    long lrd = len;
  1235. X    long mark;
  1236. X    static uword dlen;
  1237. X    static uword dblen;
  1238. X    static ubyte dctl;
  1239. X
  1240. X    if (DDebug)
  1241. X    fprintf(stderr, "NETREAD %08lx %ld\n", RcvBuf, RcvData);
  1242. X    while (len) {
  1243. X    switch(RState) {
  1244. X    case RS_SYNC:
  1245. X        --len;
  1246. X        if (*ptr++ == SYNC)
  1247. X        RState = RS_CTL;
  1248. X        break;
  1249. X    case RS_CTL:
  1250. X        --len;
  1251. X        dctl = *ptr++;
  1252. X        RState = RS_CCHK;
  1253. X        break;
  1254. X    case RS_CCHK:
  1255. X        /* warning: (ubyte) cast not implemented properly for some
  1256. X         * compilers
  1257. X         */
  1258. X        if ((((SYNC<<1)^dctl) & 0xFF) == *ptr) {
  1259. X        ++ptr;
  1260. X        --len;
  1261. X        if (dctl & PKF_DATA) {
  1262. X            RState = RS_LEN1;
  1263. X            break;
  1264. X        }
  1265. X        RState = RS_SYNC;
  1266. X        if (DDebug)
  1267. X            fprintf(stderr, "DO COMMAND (0DATA) 0x%02lx\n", dctl);
  1268. X        do_cmd(dctl, NULL, 0);
  1269. X        } else {
  1270. X        if (DDebug)
  1271. X            fprintf(stderr, "RS_CCHK FAILED\n");
  1272. X        if (len) {      /*  Resync at earliest point    */
  1273. X            ++len;
  1274. X            --ptr;
  1275. X        }
  1276. X        }
  1277. X        RState = RS_SYNC;
  1278. X        break;
  1279. X    case RS_LEN1:
  1280. X        dlen = *ptr;
  1281. X        ++ptr;
  1282. X        --len;
  1283. X        RState = RS_LEN2;
  1284. X        break;
  1285. X    case RS_LEN2:
  1286. X        dlen = (dlen << 8) + *ptr + 2;
  1287. X        ++ptr;
  1288. X        --len;
  1289. X        if (dlen > MAXPKT+2) {
  1290. X        if (DDebug)
  1291. X            fprintf(stderr,"RAW DATA: LENGTH FAILURE (cmd %02x) %ld\n",
  1292. X            dctl, dlen
  1293. X            );
  1294. X        RState = RS_SYNC;
  1295. X        break;
  1296. X        }
  1297. X        RState = RS_DATA;
  1298. X        break;
  1299. X    case RS_DATA:
  1300. X        if (DDebug)
  1301. X        fprintf(stderr, "RS_DATA->");
  1302. X        if (dlen <= len) {
  1303. X        register uword chk = chkbuf(ptr, dlen - 2);
  1304. X        if ((chk >> 8) == ptr[dlen-2] && (chk & 0xFF) == ptr[dlen-1]) {
  1305. X            if (DDebug)
  1306. X            fprintf(stderr, "DO MPX (%ld DATA) 0x%02lx\n",
  1307. X                dlen-2, dctl
  1308. X            );
  1309. X            do_cmd(dctl, ptr, dlen-2);
  1310. X            len -= dlen;
  1311. X            ptr += dlen;
  1312. X        } else {
  1313. X            if (DDebug)
  1314. X            fprintf(stderr, "RS_DATA: FAILED\n");
  1315. X        }
  1316. X        RState = RS_SYNC;
  1317. X        } else {
  1318. X        if (DDebug)
  1319. X            fprintf(stderr, "RS_DATA: INCOMPLETE READ\n");
  1320. X        goto break2;    /*  incomplete read  */
  1321. X        }
  1322. X        break;
  1323. X    }
  1324. X    }
  1325. Xbreak2:
  1326. X    switch(RState) {
  1327. X    case RS_DATA:
  1328. X    RExpect = dlen - len;
  1329. X    if (RExpect < 0) {
  1330. X        fprintf(stderr, "panic, RExpect = %ld\n", RExpect);
  1331. X        exit(1);
  1332. X    }
  1333. X    break;
  1334. X    default:
  1335. X    RExpect = 0;
  1336. X    break;
  1337. X    }
  1338. X    do_cmd(-1, NULL, 0);
  1339. X    mark = len;
  1340. X    {
  1341. X    if (len && ptr != RcvBuf)
  1342. X        bcopy(ptr, RcvBuf, len);
  1343. X    RcvData = len;
  1344. X    }
  1345. X    if (RState == RS_DATA) {
  1346. X    ;
  1347. X    /*
  1348. X     *RDisable();
  1349. X     *RTimeout(RTIME/1000);
  1350. X     */
  1351. X    }
  1352. X    /*    REMOVED 21 Sept 1988
  1353. X     * do_wupdate();
  1354. X     */
  1355. X    return(mark);
  1356. X}
  1357. X
  1358. X/*
  1359. X *  WNET:   The last data packet has been sent to the network...  Start a
  1360. X *        timeout sequence (1 second).  If this times out we will send
  1361. X *        a CHECK packet for all unresolved transmission windows.
  1362. X */
  1363. X
  1364. Xdo_wnet()
  1365. X{
  1366. X    if (DidWrite) {
  1367. X    DidWrite = 0;
  1368. X    if (DDebug)
  1369. X        fprintf(stderr, "WNET-STARTTO\n");
  1370. X    WTimeout(WTIME);
  1371. X    } else {
  1372. X    if (DDebug)
  1373. X        fprintf(stderr, "WNET-NOP\n");
  1374. X    }
  1375. X}
  1376. X
  1377. X/*
  1378. X *  DO_WUPDATE()
  1379. X *
  1380. X *  (1) Remove EMPTY windows at head of transmit queue.
  1381. X *  (2) Fill up transmit queue with pending requests, if any.
  1382. X *
  1383. X *  First two bits determine CMD as follows:
  1384. X *        0bbbbbbb        DATA        0-127 bytes of DATA
  1385. X *        10bbbccc        DATA        0-7 bytes of DATA, ccc=channel
  1386. X *                                  command.
  1387. X *        11bbbbbb bbbbbbbb    DATA        0-1023 bytes of DATA
  1388. X */
  1389. X
  1390. Xdo_wupdate()
  1391. X{
  1392. X    static short XPri;
  1393. X    int maxpktsize;
  1394. X    register XIOR *ior;
  1395. X    register PKT *pkt;
  1396. X    register long len;
  1397. X
  1398. X    while (WPUsed && WPak[0]->state == EMPTY) {
  1399. X    pkt = WPak[0];
  1400. X    WPak[0] = WPak[1];
  1401. X    WPak[1] = WPak[2];
  1402. X    WPak[2] = WPak[3];
  1403. X    WPak[3] = pkt;
  1404. X    --WPUsed;
  1405. X    ++WPStart;
  1406. X    }
  1407. X    if (Restart)
  1408. X    return(0);
  1409. X
  1410. X    while (WPUsed != 4 && (ior = (XIOR *)RemHead(&TxList))) {
  1411. X    register long offset = 0;
  1412. X
  1413. X    {
  1414. X        short npri;
  1415. X
  1416. X        if (ior->io_Command == SCMD_DATA)
  1417. X        npri = ior->io_Pri << 2;
  1418. X        else
  1419. X        npri = XPri;
  1420. X        if (npri >= XPri)  {
  1421. X        XPri = npri;
  1422. X        } else {
  1423. X        if (XPri - npri > 100)
  1424. X            XPri -= 10;
  1425. X        else if (XPri - npri > 50)
  1426. X            XPri -= 5;
  1427. X        else
  1428. X            --XPri;
  1429. X        }
  1430. X        maxpktsize = MAXPKT - (XPri - npri);
  1431. X        if (DDebug)
  1432. X        fprintf(stderr, "**MAXPKTSIZE = %ld  XPri %ld npri %ld\n",
  1433. X            maxpktsize, XPri, npri
  1434. X        );
  1435. X        if (maxpktsize < MINPKT)
  1436. X        maxpktsize = MINPKT;
  1437. X    }
  1438. X
  1439. X    pkt = WPak[WPUsed];
  1440. X    pkt->state = READY;
  1441. X    pkt->sync  = SYNC;
  1442. X    pkt->ctl   = PKCMD_WRITE | PKF_DATA | ((WPStart + WPUsed)<<5);
  1443. X    pkt->cchk = (pkt->sync << 1) ^ pkt->ctl;
  1444. X    for (;;) {
  1445. X        if (offset > (maxpktsize-8))                /*  not enough room */
  1446. X        break;
  1447. X        if (ior->io_Command == SCMD_DATA && ior->io_Channel != WChan) {
  1448. X        /*  CSWITCH */
  1449. X        WChan = ior->io_Channel;
  1450. X        pkt->data[offset+0] = 0x80|SCMD_SWITCH|(2<<3);
  1451. X        pkt->data[offset+1] = WChan >> 8;
  1452. X        pkt->data[offset+2] = WChan;
  1453. X        offset += 3;
  1454. X        if (DDebug)
  1455. X            fprintf(stderr, "SEND SWITCH %ld\n", WChan);
  1456. X        }
  1457. X        len = ior->io_Length - ior->io_Actual;
  1458. X        if (ior->io_Command == SCMD_DATA) {     /*  DATA    */
  1459. X        if (DDebug)
  1460. X            fprintf(stderr, "SEND DATA %ld bytes\n", len);
  1461. X        if (offset + len > (maxpktsize-4))
  1462. X            len = (maxpktsize-4) - offset;
  1463. X        if (len < 128) {
  1464. X            pkt->data[offset] = len;
  1465. X            ++offset;
  1466. X        } else {
  1467. X            pkt->data[offset+0] = (len>>8)|0xC0;
  1468. X            pkt->data[offset+1] = len;
  1469. X            offset += 2;
  1470. X        }
  1471. X        } else {                    /*    COMMAND */
  1472. X        pkt->data[offset] = 0x80|ior->io_Command|(len<<3);
  1473. X        ++offset;
  1474. X        }
  1475. X        bcopy((char *)ior->io_Data+ior->io_Actual,pkt->data+offset,len);
  1476. X        offset += len;
  1477. X        ior->io_Actual += len;
  1478. X        if (ior->io_Actual == ior->io_Length) {
  1479. X        free(ior->io_Data);
  1480. X        free(ior);
  1481. X        ior = (XIOR *)RemHead(&TxList);          /* Next packet      */
  1482. X        if (ior == NULL)
  1483. X            break;
  1484. X        }
  1485. X    }
  1486. X    pkt->iolength = offset + OVERHEAD;
  1487. X    pkt->lenh = offset >> 8;
  1488. X    pkt->lenl = offset;
  1489. X    {
  1490. X        register uword chksum = chkbuf(pkt->data, offset);
  1491. X        pkt->data[offset+0] = chksum >> 8;
  1492. X        pkt->data[offset+1] = chksum;
  1493. X    }
  1494. X    NetWrite(&pkt->sync, pkt->iolength, 1);
  1495. X    if (ior) {
  1496. X        ++ior->io_Pri;
  1497. X        Enqueue(&TxList, ior);
  1498. X        --ior->io_Pri;
  1499. X    }
  1500. X    ++WPUsed;
  1501. X    }
  1502. X}
  1503. X
  1504. Xvoid
  1505. Xdumpcheck(ptr)
  1506. Xregister ubyte *ptr;
  1507. X{
  1508. X    register short i;
  1509. X    for (i = 0;i < 8; ++i) {
  1510. X    if (ptr[i])
  1511. X        replywindow(i);
  1512. X    ptr[i] = 0;
  1513. X    }
  1514. X}
  1515. X
  1516. Xvoid
  1517. Xdo_cmd(ctl, buf, bytes)
  1518. Xshort ctl;    /* actually a ubyte */
  1519. Xubyte *buf;
  1520. X{
  1521. X    ubyte window = ctl >> 5;
  1522. X    ubyte rwindow;
  1523. X    static ubyte Chk, Chkwin[8];    /* remember window checks */
  1524. X
  1525. X    if (ctl == -1)  {                           /* end of sequence */
  1526. X    dumpcheck(Chkwin);
  1527. X    Chk = 0;
  1528. X    return;
  1529. X    }
  1530. X    if ((ctl & PKF_MASK) == PKCMD_CHECK) {      /* CHECK packet    */
  1531. X    Chkwin[window] = 1;
  1532. X    Chk = 1;
  1533. X    return;
  1534. X    }
  1535. X    if (Chk) {                                  /* NON-CHECK packet*/
  1536. X    dumpcheck(Chkwin);
  1537. X    Chk = 0;
  1538. X    }
  1539. X    switch(ctl & PKF_MASK) {
  1540. X    case PKCMD_WRITE:
  1541. X    rwindow = (window - RPStart) & 7;
  1542. X    if (rwindow < 4) {
  1543. X        bcopy(buf, RPak[rwindow]->data, bytes);
  1544. X        RPak[rwindow]->iolength = bytes;
  1545. X        RPak[rwindow]->state = READY;
  1546. X        if (rwindow == 0)
  1547. X        do_rupdate();
  1548. X    }
  1549. X    replywindow(window);
  1550. X    break;
  1551. X    case PKCMD_ACK:
  1552. X    rwindow = (window - WPStart) & 7;
  1553. X    if (rwindow < WPUsed)       /*  mark as sent    */
  1554. X        WPak[rwindow]->state = EMPTY;
  1555. X    break;
  1556. X    case PKCMD_NAK:            /*    resend        */
  1557. X    rwindow = (window - WPStart) & 7;
  1558. X    if (rwindow < WPUsed) {     /*  resend          */
  1559. X        NetWrite(&WPak[rwindow]->sync, WPak[rwindow]->iolength, 0);
  1560. X    } else {
  1561. X        fprintf(stderr, "Soft Error: Illegal NAK\n");
  1562. X    }
  1563. X    break;
  1564. X    case PKCMD_ACKRSTART:
  1565. X    case PKCMD_RESTART:
  1566. X    {
  1567. X        uword chan;
  1568. X        uword chksum;
  1569. X        int len;
  1570. X        int fd;
  1571. X
  1572. X        if ((ctl & PKF_MASK) == PKCMD_ACKRSTART)
  1573. X        Restart = 0;
  1574. X        do_netreset();
  1575. X        if ((ctl & PKF_MASK) == PKCMD_RESTART) {
  1576. X        gethostname(WCBuf+5, sizeof(WCBuf)-5-3);
  1577. X        len = strlen(WCBuf+5)+1;
  1578. X        WCBuf[0] = SYNC;
  1579. X        WCBuf[1] = PKCMD_ACKRSTART | PKF_DATA;
  1580. X        WCBuf[2] = (SYNC << 1) ^ WCBuf[1];
  1581. X        WCBuf[3] = 0;
  1582. X        WCBuf[4] = len;
  1583. X        chksum = chkbuf(WCBuf+5, len);
  1584. X        WCBuf[5+len] = chksum >> 8;
  1585. X        WCBuf[6+len] = chksum;
  1586. X        NetWrite(WCBuf, 7+len, 1);
  1587. X        }
  1588. X        if (bytes)
  1589. X        setlistenport(buf);
  1590. X        else
  1591. X        setlistenport("");
  1592. X        do_wupdate();
  1593. X        WTimeout(WTIME);
  1594. X    }
  1595. X    break;
  1596. X    }
  1597. X    do_rupdate();
  1598. X}
  1599. X
  1600. Xdo_rupdate()
  1601. X{
  1602. X    while (RPak[0]->state == READY) {
  1603. X    register PKT *pkt = RPak[0];
  1604. X    register ubyte *ptr = pkt->data;
  1605. X    register uword len;
  1606. X    uword iolen = pkt->iolength;
  1607. X    ubyte cmd;
  1608. X
  1609. X    if (DDebug)
  1610. X        fprintf(stderr, "Interpret Received Commands\n");
  1611. X    while (iolen) {
  1612. X        cmd = SCMD_DATA;
  1613. X        len = ptr[0];
  1614. X        ++ptr;
  1615. X        --iolen;
  1616. X        if (len >= 128) {
  1617. X        if (len < 0xC0) {
  1618. X            cmd = len & 7;
  1619. X            len = (len >> 3) & 7;
  1620. X        } else {
  1621. X            len = ((len << 8) | *ptr) & 0x3FFF;
  1622. X            ++ptr;
  1623. X            --iolen;
  1624. X        }
  1625. X        }
  1626. X        iolen -= len;
  1627. X        if (DDebug)
  1628. X        fprintf(stderr, " MPXCMD %ld (%ld bytes)\n", cmd, len);
  1629. X        do_reccmd(cmd, ptr, len);
  1630. X        ptr += len;
  1631. X    }
  1632. X    RPak[0] = RPak[1];
  1633. X    RPak[1] = RPak[2];
  1634. X    RPak[2] = RPak[3];
  1635. X    RPak[3] = pkt;
  1636. X    pkt->state = EMPTY;
  1637. X    ++RPStart;
  1638. X    }
  1639. X}
  1640. X
  1641. Xdo_reccmd(cmd, ptr, len)
  1642. Xubyte *ptr;
  1643. X{
  1644. X    switch(cmd) {
  1645. X    case SCMD_DATA:
  1646. X    if (RChan < MAXCHAN && (Chan[RChan].flags & CHANF_ROK))
  1647. X        gwrite(Chan[RChan].fd, ptr, len);
  1648. X    break;
  1649. X    case SCMD_SWITCH:
  1650. X    RChan = (ptr[0]<<8)|ptr[1];
  1651. X    break;
  1652. X    case SCMD_OPEN:
  1653. X    {
  1654. X        register COPEN *cop = (COPEN *)ptr;
  1655. X        CACKCMD ack;
  1656. X        uword chan = (cop->chanh << 8) | cop->chanl;
  1657. X
  1658. X        ack.chanh = cop->chanh;
  1659. X        ack.chanl = cop->chanl;
  1660. X        ack.error = 0;
  1661. X
  1662. X        if (chan >= MAXCHAN || Chan[chan].state) {
  1663. X        ack.error = 33;     /* magic */
  1664. X        WriteStream(SCMD_ACKCMD, &ack, sizeof(CACKCMD), chan);
  1665. X        break;
  1666. X        }
  1667. X        {
  1668. X        int error;
  1669. X        int s;
  1670. X        uword port = (cop->porth<<8)|cop->portl;
  1671. X
  1672. X        if (isinternalport(port)) {
  1673. X            error = iconnect(&s, port);
  1674. X        } else {
  1675. X            struct sockaddr sa;
  1676. X            s = socket(PF_UNIX, SOCK_STREAM, 0);
  1677. X            if (DDebug)
  1678. X            fprintf(stderr, " REC OPEN, CONNECTING ch%d po%d\n",
  1679. X                chan, port
  1680. X            );
  1681. X            sa.sa_family = AF_INET;
  1682. X            sprintf(sa.sa_data,".PORT.%ld", port);
  1683. X            error = connect(s, &sa, sizeof(sa));
  1684. X            if (error < 0) {
  1685. X            startserver(port);
  1686. X            error = connect(s, &sa, sizeof(sa));
  1687. X            }
  1688. X            if (DDebug)
  1689. X            fprintf(stderr, " CONNECTED err=%ld\n", error);
  1690. X        }
  1691. X        if (error < 0) {
  1692. X            ack.error = 2;
  1693. X        } else {
  1694. X            extern void do_open();
  1695. X            fcntl(s, F_SETFL, FNDELAY);
  1696. X            Chan[chan].state = CHAN_OPEN;
  1697. X            Chan[chan].flags = CHANF_ROK|CHANF_WOK;
  1698. X            Chan[chan].fd = s;
  1699. X            Chan[chan].pri= cop->pri;
  1700. X            FD_SET(s, &Fdread);
  1701. X            FD_SET(s, &Fdexcept);
  1702. X            FdChan[s] = chan;
  1703. X            Fdstate[s] = do_open;
  1704. X        }
  1705. X        WriteStream(SCMD_ACKCMD, &ack, sizeof(CACKCMD), -1);
  1706. X        }
  1707. X    }
  1708. X    break;
  1709. X    case SCMD_CLOSE:    /*  receive close   */
  1710. X    {
  1711. X        extern void nop();
  1712. X        register CCLOSE *clo = (CCLOSE *)ptr;
  1713. X        uword chan = (clo->chanh<<8)|clo->chanl;
  1714. X        int fd = Chan[chan].fd;
  1715. X
  1716. X        if (DDebug)
  1717. X        fprintf(stderr, " SCMD_CLOSE\n");
  1718. X        if (chan >= MAXCHAN || Chan[chan].state == CHAN_FREE)
  1719. X        break;
  1720. X        /*
  1721. X        Chan[chan].state = CHAN_CLOSE;
  1722. X        Chan[chan].flags |= CHANF_RCLOSE;
  1723. X        */
  1724. X        Chan[chan].flags &= ~(CHANF_ROK|CHANF_WOK);
  1725. X        FD_CLR(fd, &Fdread);
  1726. X        FD_CLR(fd, &Fdexcept);
  1727. X        Chan[chan].state = CHAN_FREE;
  1728. X        Chan[chan].fd = -1;
  1729. X        Fdstate[fd] = nop;
  1730. X        close(fd);
  1731. X        ClearChan(&TxList, chan, 0);
  1732. X
  1733. X        if (Chan[chan].flags & CHANF_LCLOSE) {
  1734. X        if (DDebug)
  1735. X            fprintf(stderr," REMOTE CLOSE %ld, LOCAL ALREADY CLOSED\n",
  1736. X            fd
  1737. X            );
  1738. X        } else {
  1739. X        CCLOSE cc;
  1740. X        char dummy;
  1741. X        cc.chanh = chan >> 8;
  1742. X        cc.chanl = chan;
  1743. X        WriteStream(SCMD_CLOSE, &cc, sizeof(CCLOSE), chan);
  1744. X        /*
  1745. X        shutdown(Chan[chan].fd, 2);
  1746. X        write(Chan[chan].fd, &dummy, 0);
  1747. X        */
  1748. X        if (DDebug)
  1749. X            fprintf(stderr," REMOTE CLOSE %ld, LOCAL NOT YET CLOSED\n",
  1750. X            fd
  1751. X            );
  1752. X        }
  1753. X    }
  1754. X    break;
  1755. X    case SCMD_ACKCMD:    /*  acknowledge of my open    */
  1756. X    {
  1757. X        register CACKCMD *cack = (CACKCMD *)ptr;
  1758. X        uword chan = (cack->chanh<<8)|cack->chanl;
  1759. X        if (chan >= MAXCHAN || Chan[chan].state != CHAN_LOPEN)
  1760. X        break;
  1761. X        if (DDebug)
  1762. X        fprintf(stderr, "ackerr = %ld\n", cack->error);
  1763. X        if (cack->error == 33) {
  1764. X        uword newchan = alloc_channel();
  1765. X        COPEN co;
  1766. X        if (newchan < MAXCHAN) {
  1767. X            Chan[newchan] = Chan[chan];
  1768. X            Chan[chan].state = CHAN_FREE;
  1769. X            Chan[chan].fd = -1;
  1770. X            co.chanh = newchan >> 8;
  1771. X            co.chanl = newchan;
  1772. X            co.porth = Chan[chan].port >> 8;
  1773. X            co.portl = Chan[chan].port;
  1774. X            co.error = 0;
  1775. X            co.pri   = Chan[chan].pri;
  1776. X            WriteStream(SCMD_OPEN, &co, sizeof(COPEN), newchan);
  1777. X            break;
  1778. X        }
  1779. X        }
  1780. X        if (cack->error) {
  1781. X        extern void nop();
  1782. X        ubyte error = cack->error;
  1783. X        int fd = Chan[chan].fd;
  1784. X
  1785. X        gwrite(fd, &error, 1);
  1786. X        Fdstate[fd] = nop;
  1787. X        Chan[chan].fd = -1;
  1788. X        Chan[chan].state = CHAN_FREE;
  1789. X        FD_CLR(fd, &Fdread);
  1790. X        FD_CLR(fd, &Fdexcept);
  1791. X        close(fd);
  1792. X        } else {
  1793. X        ubyte error = 0;
  1794. X        extern void do_open();
  1795. X        gwrite(Chan[chan].fd, &error, 1);
  1796. X        Chan[chan].state = CHAN_OPEN;
  1797. X        Chan[chan].flags = CHANF_ROK|CHANF_WOK;
  1798. X        Fdstate[Chan[chan].fd] = do_open;
  1799. X        }
  1800. X    }
  1801. X    break;
  1802. X    case SCMD_EOFCMD:    /*  EOF on channel        */
  1803. X    {
  1804. X        register CEOFCMD *eof = (CEOFCMD *)ptr;
  1805. X        uword chan = (eof->chanh<<8)|eof->chanl;
  1806. X
  1807. X        if (chan < MAXCHAN && Chan[chan].state == CHAN_OPEN) {
  1808. X        Chan[chan].flags &= ~eof->flags;
  1809. X        if (eof->flags & CHANF_ROK) {
  1810. X            char dummy;
  1811. X            shutdown(Chan[chan].fd, 1);
  1812. X            write(Chan[chan].fd, &dummy, 0);
  1813. X        }
  1814. X        }
  1815. X    }
  1816. X    break;
  1817. X    case SCMD_QUIT:
  1818. X    dneterror("QUIT");
  1819. X    break;
  1820. X    case SCMD_IOCTL:
  1821. X    {
  1822. X        register CIOCTL *cio = (CIOCTL *)ptr;
  1823. X        uword chan = (cio->chanh<<8)|cio->chanl;
  1824. X
  1825. X        if (chan < MAXCHAN && Chan[chan].state == CHAN_OPEN) {
  1826. X        switch(cio->cmd) {
  1827. X        case CIO_SETROWS:
  1828. X            isetrows(Chan[chan].fd, (cio->valh<<8)|cio->vall);
  1829. X            break;
  1830. X        case CIO_SETCOLS:
  1831. X            isetcols(Chan[chan].fd, (cio->valh<<8)|cio->vall);
  1832. X            break;
  1833. X        case CIO_STOP:
  1834. X            break;
  1835. X        case CIO_START:
  1836. X            break;
  1837. X        case CIO_FLUSH:
  1838. X            ClearChan(&TxList, chan, 0);
  1839. X            break;
  1840. X        }
  1841. X        }
  1842. X    }
  1843. X    break;
  1844. X    default:
  1845. X    break;
  1846. X    }
  1847. X}
  1848. X
  1849. Xreplywindow(window)
  1850. X{
  1851. X    ubyte rwindow = (window - RPStart) & 7;
  1852. X    WCBuf[0] = SYNC;
  1853. X
  1854. X    if (DDebug) {
  1855. X    if (rwindow >= 4 || RPak[rwindow]->state == READY)
  1856. X        fprintf(stderr, " ACK WINDOW %ld\n", window);
  1857. X    else
  1858. X        fprintf(stderr, " NAK WINDOW %ld\n", window);
  1859. X    }
  1860. X    if (rwindow >= 4 || RPak[rwindow]->state == READY)  /* data ready */
  1861. X    WCBuf[1] = PKCMD_ACK | (window << 5);           /* ack it     */
  1862. X    else
  1863. X    WCBuf[1] = PKCMD_NAK | (window << 5);           /* nack it    */
  1864. X    WCBuf[2] = (SYNC << 1) ^ WCBuf[1];
  1865. X    NetWrite(WCBuf, 3, 0);
  1866. X}
  1867. X
  1868. SHAR_EOF
  1869. echo "extracting dnet/TODO3"
  1870. sed 's/^X//' << \SHAR_EOF > dnet/TODO3
  1871. XFrom tlm@newton.physics.purdue.edu Mon Mar 14 13:05:30 1988
  1872. XReceived: by cory (5.57/1.26)
  1873. X    id AA00614; Mon, 14 Mar 88 13:00:13 PST
  1874. XReceived: by newton.physics.purdue.edu (5.54/2.1)
  1875. X    id AA12775; Mon, 14 Mar 88 15:59:30 EST
  1876. XDate: Mon, 14 Mar 88 15:59:30 EST
  1877. XFrom: tlm@newton.physics.purdue.edu (Timothy Lee Meisenheimer)
  1878. XMessage-Id: <8803142059.AA12775@newton.physics.purdue.edu>
  1879. XApparently-To: dnet@cory.berkeley.edu
  1880. X
  1881. XThanks Matt, but no dice. I still couldn't get it to work in
  1882. Xlocal mode??? What I did do was get the latest version (time
  1883. Xstamp of March 11) and recompiled everything. The host name
  1884. Xproblem is now gone (newton.physics.purdure.edu= --> newton.physics.
  1885. Xpurdue.ed=) but I found that the environment DNETHOST must get
  1886. Xset in the child process when using "dtest" but not in the
  1887. Xparent process. Consequently it was still no go until I set
  1888. Xit by hand. Now I can do the local net just dandy!! I'm playing
  1889. Xaround with how to get the responce .vs. baud right (mucking
  1890. Xaround in control.c). Will let you know what I find out. Bye
  1891. Xthe way does this latest version still have problems with all
  1892. Xthose interupts on the select which was bringing the vaxen to
  1893. Xtheir knees? Guess I'll find out tonight :-).
  1894. X
  1895. X            tim.
  1896. X
  1897. X
  1898. SHAR_EOF
  1899. echo "extracting dnet/subs.c"
  1900. sed 's/^X//' << \SHAR_EOF > dnet/subs.c
  1901. X
  1902. X/*
  1903. X *  SUBS.C
  1904. X *
  1905. X *    DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved
  1906. X *
  1907. X *    Support subroutines
  1908. X *
  1909. X */
  1910. X
  1911. X#include "dnet.h"
  1912. X
  1913. X/*
  1914. X *   WRITESTREAM()
  1915. X *
  1916. X *    Queues new SCMD_?? level commands to be sent
  1917. X */
  1918. X
  1919. XWriteStream(sdcmd, buf, len, chan)
  1920. Xubyte *buf;
  1921. Xuword chan;
  1922. X{
  1923. X    register XIOR *ior = (XIOR *)malloc(sizeof(XIOR));
  1924. X
  1925. X    if (DDebug)
  1926. X    fprintf(stderr, "**SEND MPX CMD %ld (%ld bytes on channel %ld)\n",
  1927. X        sdcmd, len, chan
  1928. X    );
  1929. X
  1930. X    ior->io_Data = (ubyte *)malloc(len);
  1931. X    ior->io_Length = len;
  1932. X    ior->io_Actual = 0;
  1933. X    ior->io_Command = sdcmd;
  1934. X    ior->io_Error = 0;
  1935. X    ior->io_Channel = chan;
  1936. X    ior->io_Pri = (chan > MAXCHAN) ? 126 : Chan[chan].pri;
  1937. X    bcopy(buf, ior->io_Data, len);
  1938. X    Enqueue(&TxList, ior);
  1939. X    /*
  1940. X     *    REMOVED 21 SEPT 1988
  1941. X     * do_wupdate();
  1942. X     */
  1943. X}
  1944. X
  1945. X/*
  1946. X *  ALLOC_CHANNEL()
  1947. X *
  1948. X *    Allocate a free channel.  Used in SCMD_OPEN and SCMD_ACKCMD
  1949. X */
  1950. X
  1951. Xalloc_channel()
  1952. X{
  1953. X    static ulong ran = 13;
  1954. X    register uword i;
  1955. X
  1956. X    ran = ((ran * 13) + 1) ^ (ran >> 9) + time(0);
  1957. X    for (i = ran % MAXCHAN; i < MAXCHAN; ++i) {
  1958. X    if (Chan[i].state == 0)
  1959. X        return(i);
  1960. X    }
  1961. X    for (i = ran % MAXCHAN; i < MAXCHAN; --i) {
  1962. X    if (Chan[i].state == 0)
  1963. X        return(i);
  1964. X    }
  1965. X    return(-1);
  1966. X}
  1967. X
  1968. X/*
  1969. X *    Remove all nodes with the given channel ID.
  1970. X */
  1971. X
  1972. XClearChan(list, chan, all)
  1973. XLIST *list;
  1974. Xuword chan;
  1975. X{
  1976. X    register XIOR *io, *in;
  1977. X
  1978. X    for (io = (XIOR *)list->lh_Head; io != (XIOR *)&list->lh_Tail; io = in) {
  1979. X    in = (XIOR *)io->io_Node.ln_Succ;
  1980. X    if (io->io_Channel == chan) {
  1981. X        if (all || io->io_Command == SCMD_DATA) {
  1982. X        io->io_Node.ln_Succ->ln_Pred = io->io_Node.ln_Pred;
  1983. X        io->io_Node.ln_Pred->ln_Succ = io->io_Node.ln_Succ;
  1984. X        free(io->io_Data);
  1985. X        free(io);
  1986. X        }
  1987. X    }
  1988. X    }
  1989. X}
  1990. X
  1991. X/*
  1992. X *  Queue a packet into a prioritized list.  FIFO is retained for packets
  1993. X *  of the same priority.  This implements one level of channel priorities,
  1994. X *  before the packets actually get queued to the network.  Since up to
  1995. X *  4 packets might be queued (200 * 4 = 800 bytes of data or 4 seconds @
  1996. X *  2400 baud), a second level of prioritization will also reduce the
  1997. X *  physical packet size when two channels at relatively large differing
  1998. X *  priorities are in use.
  1999. X *
  2000. X *    These and other list routines compatible with Amiga list routines.
  2001. X */
  2002. X
  2003. XEnqueue(list, ior)
  2004. XLIST *list;
  2005. XXIOR *ior;
  2006. X{
  2007. X    register XIOR *io;
  2008. X    char pri = ior->io_Pri;
  2009. X
  2010. X    io = (XIOR *)list->lh_Head;
  2011. X    while (io != (XIOR *)&list->lh_Tail) {
  2012. X    if (pri > io->io_Pri)
  2013. X        break;
  2014. X    io = (XIOR *)io->io_Node.ln_Succ;
  2015. X    }
  2016. X    ior->io_Node.ln_Succ = (NODE *)io;
  2017. X    ior->io_Node.ln_Pred = io->io_Node.ln_Pred;
  2018. X    ior->io_Node.ln_Succ->ln_Pred = (NODE *)ior;
  2019. X    ior->io_Node.ln_Pred->ln_Succ = (NODE *)ior;
  2020. X}
  2021. X
  2022. XAddTail(list, node)
  2023. XLIST *list;
  2024. XNODE *node;
  2025. X{
  2026. X    node->ln_Succ = (NODE *)&list->lh_Tail;
  2027. X    node->ln_Pred = list->lh_TailPred;
  2028. X    node->ln_Succ->ln_Pred = node;
  2029. X    node->ln_Pred->ln_Succ = node;
  2030. X}
  2031. X
  2032. XAddHead(list, node)
  2033. XLIST *list;
  2034. XNODE *node;
  2035. X{
  2036. X    node->ln_Succ = list->lh_Head;
  2037. X    node->ln_Pred = (NODE *)list;
  2038. X    node->ln_Succ->ln_Pred = node;
  2039. X    node->ln_Pred->ln_Succ = node;
  2040. X}
  2041. X
  2042. Xubyte *
  2043. XRemHead(list)
  2044. XLIST *list;
  2045. X{
  2046. X    NODE *node;
  2047. X
  2048. X    node = list->lh_Head;
  2049. X    if (node->ln_Succ == NULL)
  2050. X    return(NULL);
  2051. X    node->ln_Succ->ln_Pred = node->ln_Pred;
  2052. X    node->ln_Pred->ln_Succ = node->ln_Succ;
  2053. X    return((ubyte *)node);
  2054. X}
  2055. X
  2056. XNewList(list)
  2057. XLIST *list;
  2058. X{
  2059. X    list->lh_Head = (NODE *)&list->lh_Tail;
  2060. X    list->lh_Tail = NULL;
  2061. X    list->lh_TailPred = (NODE *)&list->lh_Head;
  2062. X}
  2063. X
  2064. XGetNext(node)
  2065. XNODE *node;
  2066. X{
  2067. X    register NODE *next = node->ln_Succ;
  2068. X    if (*(long *)next)
  2069. X    return((long)next);
  2070. X    return(NULL);
  2071. X}
  2072. X
  2073. X/*
  2074. X *  CHKBUF
  2075. X *
  2076. X *    Checksum a buffer.  Uses a simple, but supposedly very good
  2077. X *    scheme.
  2078. X */
  2079. X
  2080. Xchkbuf(buf, bytes)
  2081. Xregister ubyte *buf;
  2082. Xregister uword bytes;
  2083. X{
  2084. X    register uword i;
  2085. X    register ubyte c1,c2;
  2086. X
  2087. X    for (i = c1 = c2 = 0; i < bytes; ++i) {
  2088. X    c1 += buf[i];
  2089. X    c2 += c1;
  2090. X    }
  2091. X    c1 = -(c1 + c2);
  2092. X    return((c1<<8)|c2);
  2093. X}
  2094. X
  2095. X/*
  2096. X *   Write timeout signal handler.
  2097. X */
  2098. X
  2099. Xsigwto()
  2100. X{
  2101. X    WTimedout = 1;
  2102. X    Wto_act = 0;
  2103. X}
  2104. X
  2105. XTimerOpen()
  2106. X{
  2107. X    static struct sigvec SA = { sigwto, 0, 0 };
  2108. X    sigvec(SIGALRM, &SA, NULL);
  2109. X}
  2110. X
  2111. XTimerClose()
  2112. X{
  2113. X    signal(SIGALRM, SIG_IGN);
  2114. X}
  2115. X
  2116. XWTimeout(us)
  2117. X{
  2118. X    static struct itimerval itv;
  2119. X    struct itimerval ov;
  2120. X    long mask;
  2121. X
  2122. X    itv.it_value.tv_sec = us / 1000000;
  2123. X    itv.it_value.tv_usec= (us % 1000000);
  2124. X
  2125. X    mask = sigblock(sigmask(SIGALRM));
  2126. X    setitimer(ITIMER_REAL, &itv, &ov);
  2127. X    Wto_act = 1;
  2128. X    WTimedout = 0;
  2129. X    sigsetmask(mask);
  2130. X    if (DDebug)
  2131. X    fprintf(stderr, "WTimeout set\n");
  2132. X}
  2133. X
  2134. Xdneterror(str)
  2135. Xchar *str;
  2136. X{
  2137. X    register short i;
  2138. X
  2139. X    NetClose();
  2140. X    TimerClose();
  2141. X    exit(1);
  2142. X}
  2143. X
  2144. X/*
  2145. X *    setenv(name, str).  name must be of the form "NAME="
  2146. X */
  2147. X
  2148. Xsetenv(name, str)
  2149. Xchar *name;
  2150. Xchar *str;
  2151. X{
  2152. X    extern char **environ;
  2153. X    static char **elist;
  2154. X    static int elen;
  2155. X    char *ptr;
  2156. X    int i, len;
  2157. X
  2158. X    len = strlen(name);
  2159. X    if (elist == NULL) {
  2160. X    for (i = 0; environ[i]; ++i);
  2161. X    elist = (char **)malloc((i+3)*sizeof(char *));
  2162. X    elen = i + 3;
  2163. X    bcopy(environ, elist, i*sizeof(char *));
  2164. X    environ = elist;
  2165. X    }
  2166. X    for (i = 0; elist[i]; ++i) {
  2167. X    if (strncmp(elist[i], name, len) == 0)
  2168. X        break;
  2169. X    }
  2170. X    if (i == elen) {
  2171. X    elen += 4;
  2172. X    elist = environ = (char **)realloc(elist, elen*sizeof(char *));
  2173. X    }
  2174. X    ptr = (char *)malloc(len + strlen(str) + 1);
  2175. X    sprintf(ptr, "%s%s", name, str);
  2176. X    if (elist[i]) {
  2177. X    elist[i] = ptr;
  2178. X    } else {
  2179. X    elist[i] = ptr;
  2180. X    elist[i+1] = NULL;
  2181. X    elen = i + 1;
  2182. X    }
  2183. X}
  2184. X
  2185. Xvoid
  2186. Xstartserver(port)
  2187. Xuword port;
  2188. X{
  2189. X    char dir[MAXPATHLEN];
  2190. X    struct passwd pw_info;
  2191. X    FILE *fi;
  2192. X
  2193. X    if (!port)
  2194. X    return;
  2195. X    if (getenv("DNETDIR")) {
  2196. X    strcpy(dir, getenv("DNETDIR"));
  2197. X    strcat(dir, "dnet.servers");
  2198. X    if (fi = fopen(dir, "r")) {
  2199. X        if (scan_for_server(fi, port))
  2200. X        return;
  2201. X    }
  2202. X    }
  2203. X    pw_info = *getpwuid(getuid());
  2204. X    strcpy(dir, pw_info.pw_dir);
  2205. X    strcat(dir, "/.dnet/dnet.servers");
  2206. X    if (fi = fopen(dir, "r")) {
  2207. X    if (scan_for_server(fi, port))
  2208. X        return;
  2209. X    }
  2210. X    /*
  2211. X     *    LAST TRY
  2212. X     */
  2213. X    if (fi = fopen(LASTTRYDNETSERVERS, "r")) {
  2214. X    if (scan_for_server(fi, port))
  2215. X        return;
  2216. X    }
  2217. X    fprintf(stderr, "Unable to find one of (1) dnet.servers or (2) server\n");
  2218. X    fprintf(stderr, "entry for port %d\n", port);
  2219. X    fflush(stderr);
  2220. X    return;
  2221. X}
  2222. X
  2223. Xscan_for_server(fi, port)
  2224. XFILE *fi;
  2225. Xshort port;
  2226. X{
  2227. X    char buf[256];
  2228. X    char path[MAXPATHLEN];
  2229. X    char cdir[MAXPATHLEN];
  2230. X    long portno;
  2231. X    short found = 0;
  2232. X    void checktilda();
  2233. X
  2234. X    while (fgets(buf, 256, fi)) {
  2235. X    if (sscanf(buf, "%ld %s %s", &portno, path, cdir) == 3) {
  2236. X        checktilda(path);
  2237. X        checktilda(cdir);
  2238. X        if (portno == port) {
  2239. X        if (!fork()) {
  2240. X            int i;
  2241. X            fclose(fi);
  2242. X            setuid(getuid());
  2243. X            signal(SIGHUP, SIG_DFL);
  2244. X            signal(SIGINT, SIG_DFL);
  2245. X            signal(SIGQUIT, SIG_DFL);
  2246. X            signal(SIGTERM, SIG_DFL);
  2247. X            signal(SIGCHLD, SIG_DFL);
  2248. X            signal(SIGTSTP, SIG_IGN);
  2249. X            ioctl(open("/dev/tty", 2), TIOCNOTTY, NULL);
  2250. X            i = open("/dev/null", O_RDWR, 0);
  2251. X            dup2(i, 0);
  2252. X            dup2(i, 1);
  2253. X            for (i = 3; i < 256; ++i)
  2254. X            close(i);
  2255. X            sprintf(buf, "server.%ld.%ld", port, getuid());
  2256. X            execl(path, buf, cdir, NULL);
  2257. X            fprintf(stderr, "Unable to exec server: %s\n", path);
  2258. X                fflush(stderr);
  2259. X            _exit(1);
  2260. X        }
  2261. X        sleep(4);    /* is a hack */
  2262. X        found = 1;
  2263. X        break;
  2264. X        }
  2265. X    }
  2266. X    }
  2267. X    fclose(fi);
  2268. X    return(found);
  2269. X}
  2270. X
  2271. Xvoid
  2272. Xchecktilda(buf)
  2273. Xchar *buf;
  2274. X{
  2275. X    if (buf[0] == '~') {
  2276. X    short bindex = 1;
  2277. X    short pathlen;
  2278. X    struct passwd pw_info, *pw;
  2279. X
  2280. X    pw_info.pw_dir = getenv("HOME");
  2281. X    if (buf[1] && buf[1] != '/') {
  2282. X        char username[128];
  2283. X        while (buf[bindex] && buf[bindex] != '/')
  2284. X        ++bindex;
  2285. X        bcopy(buf+1, username, bindex-1);
  2286. X        username[bindex-1] = 0;
  2287. X        if (pw = getpwnam(username)) {
  2288. X        pw_info = *pw;
  2289. X        } else {
  2290. X        fprintf(stderr, "Unable to find password entry for %s\n",
  2291. X            username
  2292. X        );
  2293. X        fprintf(stderr, "passing /tmp as dir for server");
  2294. X            fflush(stderr);
  2295. X        pw_info.pw_dir = "/tmp";
  2296. X        }
  2297. X    }
  2298. X
  2299. X    /*
  2300. X     * ~[username]<rest of path>     ->   <basedir><rest of path>
  2301. X     */
  2302. X
  2303. X    pathlen = strlen(pw_info.pw_dir);
  2304. X    bcopy(buf + bindex, buf + pathlen, strlen(buf + bindex) + 1);
  2305. X    bcopy(pw_info.pw_dir, buf, pathlen);
  2306. X    }
  2307. X    fflush(stderr);
  2308. X}
  2309. X
  2310. SHAR_EOF
  2311. echo "End of archive 1 (of 2)"
  2312. # if you want to concatenate archives, remove anything after this line
  2313. exit
  2314.  
  2315.  
  2316.  
  2317.