home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff220.lzh / DNet / dnet / subs.c < prev    next >
C/C++ Source or Header  |  1989-06-04  |  8KB  |  410 lines

  1.  
  2. /*
  3.  *  SUBS.C
  4.  *
  5.  *    DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved
  6.  *
  7.  *    Support subroutines
  8.  *
  9.  */
  10.  
  11. #include "dnet.h"
  12.  
  13. /*
  14.  *   WRITESTREAM()
  15.  *
  16.  *    Queues new SCMD_?? level commands to be sent
  17.  */
  18.  
  19. WriteStream(sdcmd, buf, len, chan)
  20. ubyte *buf;
  21. uword chan;
  22. {
  23.     register XIOR *ior = (XIOR *)malloc(sizeof(XIOR));
  24.  
  25.     if (DDebug)
  26.     fprintf(stderr, "**SEND MPX CMD %ld (%ld bytes on channel %ld)\n",
  27.         sdcmd, len, chan
  28.     );
  29.  
  30.     ior->io_Data = (ubyte *)malloc(len);
  31.     ior->io_Length = len;
  32.     ior->io_Actual = 0;
  33.     ior->io_Command = sdcmd;
  34.     ior->io_Error = 0;
  35.     ior->io_Channel = chan;
  36.     ior->io_Pri = (chan > MAXCHAN) ? 126 : Chan[chan].pri;
  37.     bcopy(buf, ior->io_Data, len);
  38.     Enqueue(&TxList, ior);
  39.     /*
  40.      *    REMOVED 21 SEPT 1988
  41.      * do_wupdate();
  42.      */
  43. }
  44.  
  45. /*
  46.  *  ALLOC_CHANNEL()
  47.  *
  48.  *    Allocate a free channel.  Used in SCMD_OPEN and SCMD_ACKCMD
  49.  */
  50.  
  51. alloc_channel()
  52. {
  53.     static ulong ran = 13;
  54.     register uword i;
  55.  
  56.     ran = ((ran * 13) + 1) ^ (ran >> 9) + time(0);
  57.     for (i = ran % MAXCHAN; i < MAXCHAN; ++i) {
  58.     if (Chan[i].state == 0)
  59.         return(i);
  60.     }
  61.     for (i = ran % MAXCHAN; i < MAXCHAN; --i) {
  62.     if (Chan[i].state == 0)
  63.         return(i);
  64.     }
  65.     return(-1);
  66. }
  67.  
  68. /*
  69.  *    Remove all nodes with the given channel ID.
  70.  */
  71.  
  72. ClearChan(list, chan, all)
  73. LIST *list;
  74. uword chan;
  75. {
  76.     register XIOR *io, *in;
  77.  
  78.     for (io = (XIOR *)list->lh_Head; io != (XIOR *)&list->lh_Tail; io = in) {
  79.     in = (XIOR *)io->io_Node.ln_Succ;
  80.     if (io->io_Channel == chan) {
  81.         if (all || io->io_Command == SCMD_DATA) {
  82.         io->io_Node.ln_Succ->ln_Pred = io->io_Node.ln_Pred;
  83.         io->io_Node.ln_Pred->ln_Succ = io->io_Node.ln_Succ;
  84.         free(io->io_Data);
  85.         free(io);
  86.         }
  87.     }
  88.     }
  89. }
  90.  
  91. /*
  92.  *  Queue a packet into a prioritized list.  FIFO is retained for packets
  93.  *  of the same priority.  This implements one level of channel priorities,
  94.  *  before the packets actually get queued to the network.  Since up to
  95.  *  4 packets might be queued (200 * 4 = 800 bytes of data or 4 seconds @
  96.  *  2400 baud), a second level of prioritization will also reduce the
  97.  *  physical packet size when two channels at relatively large differing
  98.  *  priorities are in use.
  99.  *
  100.  *    These and other list routines compatible with Amiga list routines.
  101.  */
  102.  
  103. Enqueue(list, ior)
  104. LIST *list;
  105. XIOR *ior;
  106. {
  107.     register XIOR *io;
  108.     char pri = ior->io_Pri;
  109.  
  110.     io = (XIOR *)list->lh_Head;
  111.     while (io != (XIOR *)&list->lh_Tail) {
  112.     if (pri > io->io_Pri)
  113.         break;
  114.     io = (XIOR *)io->io_Node.ln_Succ;
  115.     }
  116.     ior->io_Node.ln_Succ = (NODE *)io;
  117.     ior->io_Node.ln_Pred = io->io_Node.ln_Pred;
  118.     ior->io_Node.ln_Succ->ln_Pred = (NODE *)ior;
  119.     ior->io_Node.ln_Pred->ln_Succ = (NODE *)ior;
  120. }
  121.  
  122. AddTail(list, node)
  123. LIST *list;
  124. NODE *node;
  125. {
  126.     node->ln_Succ = (NODE *)&list->lh_Tail;
  127.     node->ln_Pred = list->lh_TailPred;
  128.     node->ln_Succ->ln_Pred = node;
  129.     node->ln_Pred->ln_Succ = node;
  130. }
  131.  
  132. AddHead(list, node)
  133. LIST *list;
  134. NODE *node;
  135. {
  136.     node->ln_Succ = list->lh_Head;
  137.     node->ln_Pred = (NODE *)list;
  138.     node->ln_Succ->ln_Pred = node;
  139.     node->ln_Pred->ln_Succ = node;
  140. }
  141.  
  142. ubyte *
  143. RemHead(list)
  144. LIST *list;
  145. {
  146.     NODE *node;
  147.  
  148.     node = list->lh_Head;
  149.     if (node->ln_Succ == NULL)
  150.     return(NULL);
  151.     node->ln_Succ->ln_Pred = node->ln_Pred;
  152.     node->ln_Pred->ln_Succ = node->ln_Succ;
  153.     return((ubyte *)node);
  154. }
  155.  
  156. NewList(list)
  157. LIST *list;
  158. {
  159.     list->lh_Head = (NODE *)&list->lh_Tail;
  160.     list->lh_Tail = NULL;
  161.     list->lh_TailPred = (NODE *)&list->lh_Head;
  162. }
  163.  
  164. GetNext(node)
  165. NODE *node;
  166. {
  167.     register NODE *next = node->ln_Succ;
  168.     if (*(long *)next)
  169.     return((long)next);
  170.     return(NULL);
  171. }
  172.  
  173. /*
  174.  *  CHKBUF
  175.  *
  176.  *    Checksum a buffer.  Uses a simple, but supposedly very good
  177.  *    scheme.
  178.  */
  179.  
  180. chkbuf(buf, bytes)
  181. register ubyte *buf;
  182. register uword bytes;
  183. {
  184.     register uword i;
  185.     register ubyte c1,c2;
  186.  
  187.     for (i = c1 = c2 = 0; i < bytes; ++i) {
  188.     c1 += buf[i];
  189.     c2 += c1;
  190.     }
  191.     c1 = -(c1 + c2);
  192.     return((c1<<8)|c2);
  193. }
  194.  
  195. /*
  196.  *   Write timeout signal handler.
  197.  */
  198.  
  199. sigwto()
  200. {
  201.     WTimedout = 1;
  202.     Wto_act = 0;
  203. }
  204.  
  205. TimerOpen()
  206. {
  207.     static struct sigvec SA = { sigwto, 0, 0 };
  208.     sigvec(SIGALRM, &SA, NULL);
  209. }
  210.  
  211. TimerClose()
  212. {
  213.     signal(SIGALRM, SIG_IGN);
  214. }
  215.  
  216. WTimeout(us)
  217. {
  218.     static struct itimerval itv;
  219.     struct itimerval ov;
  220.     long mask;
  221.  
  222.     itv.it_value.tv_sec = us / 1000000;
  223.     itv.it_value.tv_usec= (us % 1000000);
  224.  
  225.     mask = sigblock(sigmask(SIGALRM));
  226.     setitimer(ITIMER_REAL, &itv, &ov);
  227.     Wto_act = 1;
  228.     WTimedout = 0;
  229.     sigsetmask(mask);
  230.     if (DDebug)
  231.     fprintf(stderr, "WTimeout set\n");
  232. }
  233.  
  234. dneterror(str)
  235. char *str;
  236. {
  237.     register short i;
  238.  
  239.     NetClose();
  240.     TimerClose();
  241.     exit(1);
  242. }
  243.  
  244. /*
  245.  *    setenv(name, str).  name must be of the form "NAME="
  246.  */
  247.  
  248. setenv(name, str)
  249. char *name;
  250. char *str;
  251. {
  252.     extern char **environ;
  253.     static char **elist;
  254.     static int elen;
  255.     char *ptr;
  256.     int i, len;
  257.  
  258.     len = strlen(name);
  259.     if (elist == NULL) {
  260.     for (i = 0; environ[i]; ++i);
  261.     elist = (char **)malloc((i+3)*sizeof(char *));
  262.     elen = i + 3;
  263.     bcopy(environ, elist, i*sizeof(char *));
  264.     environ = elist;
  265.     }
  266.     for (i = 0; elist[i]; ++i) {
  267.     if (strncmp(elist[i], name, len) == 0)
  268.         break;
  269.     }
  270.     if (i == elen) {
  271.     elen += 4;
  272.     elist = environ = (char **)realloc(elist, elen*sizeof(char *));
  273.     }
  274.     ptr = (char *)malloc(len + strlen(str) + 1);
  275.     sprintf(ptr, "%s%s", name, str);
  276.     if (elist[i]) {
  277.     elist[i] = ptr;
  278.     } else {
  279.     elist[i] = ptr;
  280.     elist[i+1] = NULL;
  281.     elen = i + 1;
  282.     }
  283. }
  284.  
  285. void
  286. startserver(port)
  287. uword port;
  288. {
  289.     char dir[MAXPATHLEN];
  290.     struct passwd pw_info;
  291.     FILE *fi;
  292.  
  293.     if (!port)
  294.     return;
  295.     if (getenv("DNETDIR")) {
  296.     strcpy(dir, getenv("DNETDIR"));
  297.     strcat(dir, "dnet.servers");
  298.     if (fi = fopen(dir, "r")) {
  299.         if (scan_for_server(fi, port))
  300.         return;
  301.     }
  302.     }
  303.     pw_info = *getpwuid(getuid());
  304.     strcpy(dir, pw_info.pw_dir);
  305.     strcat(dir, "/.dnet/dnet.servers");
  306.     if (fi = fopen(dir, "r")) {
  307.     if (scan_for_server(fi, port))
  308.         return;
  309.     }
  310.     /*
  311.      *    LAST TRY
  312.      */
  313.     if (fi = fopen(LASTTRYDNETSERVERS, "r")) {
  314.     if (scan_for_server(fi, port))
  315.         return;
  316.     }
  317.     fprintf(stderr, "Unable to find one of (1) dnet.servers or (2) server\n");
  318.     fprintf(stderr, "entry for port %d\n", port);
  319.     fflush(stderr);
  320.     return;
  321. }
  322.  
  323. scan_for_server(fi, port)
  324. FILE *fi;
  325. short port;
  326. {
  327.     char buf[256];
  328.     char path[MAXPATHLEN];
  329.     char cdir[MAXPATHLEN];
  330.     long portno;
  331.     short found = 0;
  332.     void checktilda();
  333.  
  334.     while (fgets(buf, 256, fi)) {
  335.     if (sscanf(buf, "%ld %s %s", &portno, path, cdir) == 3) {
  336.         checktilda(path);
  337.         checktilda(cdir);
  338.         if (portno == port) {
  339.         if (!fork()) {
  340.             int i;
  341.             fclose(fi);
  342.             setuid(getuid());
  343.             signal(SIGHUP, SIG_DFL);
  344.             signal(SIGINT, SIG_DFL);
  345.             signal(SIGQUIT, SIG_DFL);
  346.             signal(SIGTERM, SIG_DFL);
  347.             signal(SIGCHLD, SIG_DFL);
  348.             signal(SIGTSTP, SIG_IGN);
  349.             ioctl(open("/dev/tty", 2), TIOCNOTTY, NULL);
  350.             i = open("/dev/null", O_RDWR, 0);
  351.             dup2(i, 0);
  352.             dup2(i, 1);
  353.             for (i = 3; i < 256; ++i)
  354.             close(i);
  355.             sprintf(buf, "server.%ld.%ld", port, getuid());
  356.             execl(path, buf, cdir, NULL);
  357.             fprintf(stderr, "Unable to exec server: %s\n", path);
  358.                 fflush(stderr);
  359.             _exit(1);
  360.         }
  361.         sleep(4);    /* is a hack */
  362.         found = 1;
  363.         break;
  364.         }
  365.     }
  366.     }
  367.     fclose(fi);
  368.     return(found);
  369. }
  370.  
  371. void
  372. checktilda(buf)
  373. char *buf;
  374. {
  375.     if (buf[0] == '~') {
  376.     short bindex = 1;
  377.     short pathlen;
  378.     struct passwd pw_info, *pw;
  379.  
  380.     pw_info.pw_dir = getenv("HOME");
  381.     if (buf[1] && buf[1] != '/') {
  382.         char username[128];
  383.         while (buf[bindex] && buf[bindex] != '/')
  384.         ++bindex;
  385.         bcopy(buf+1, username, bindex-1);
  386.         username[bindex-1] = 0;
  387.         if (pw = getpwnam(username)) {
  388.         pw_info = *pw;
  389.         } else {
  390.         fprintf(stderr, "Unable to find password entry for %s\n",
  391.             username
  392.         );
  393.         fprintf(stderr, "passing /tmp as dir for server");
  394.             fflush(stderr);
  395.         pw_info.pw_dir = "/tmp";
  396.         }
  397.     }
  398.  
  399.     /*
  400.      * ~[username]<rest of path>     ->   <basedir><rest of path>
  401.      */
  402.  
  403.     pathlen = strlen(pw_info.pw_dir);
  404.     bcopy(buf + bindex, buf + pathlen, strlen(buf + bindex) + 1);
  405.     bcopy(pw_info.pw_dir, buf, pathlen);
  406.     }
  407.     fflush(stderr);
  408. }
  409.  
  410.