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