home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * SUBS.C
- *
- * DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved
- *
- * Support subroutines
- *
- */
-
- #include "dnet.h"
-
- /*
- * WRITESTREAM()
- *
- * Queues new SCMD_?? level commands to be sent
- */
-
- WriteStream(sdcmd, buf, len, chan)
- ubyte *buf;
- uword chan;
- {
- register XIOR *ior = (XIOR *)malloc(sizeof(XIOR));
-
- if (DDebug)
- fprintf(stderr, "**SEND MPX CMD %ld (%ld bytes on channel %ld)\n",
- sdcmd, len, chan
- );
-
- ior->io_Data = (ubyte *)malloc(len);
- ior->io_Length = len;
- ior->io_Actual = 0;
- ior->io_Command = sdcmd;
- ior->io_Error = 0;
- ior->io_Channel = chan;
- ior->io_Pri = (chan > MAXCHAN) ? 126 : Chan[chan].pri;
- bcopy(buf, ior->io_Data, len);
- Enqueue(&TxList, ior);
- /*
- * REMOVED 21 SEPT 1988
- * do_wupdate();
- */
- }
-
- /*
- * ALLOC_CHANNEL()
- *
- * Allocate a free channel. Used in SCMD_OPEN and SCMD_ACKCMD
- */
-
- alloc_channel()
- {
- static ulong ran = 13;
- register uword i;
-
- ran = ((ran * 13) + 1) ^ (ran >> 9) + time(0);
- for (i = ran % MAXCHAN; i < MAXCHAN; ++i) {
- if (Chan[i].state == 0)
- return(i);
- }
- for (i = ran % MAXCHAN; i < MAXCHAN; --i) {
- if (Chan[i].state == 0)
- return(i);
- }
- return(-1);
- }
-
- /*
- * Remove all nodes with the given channel ID.
- */
-
- ClearChan(list, chan, all)
- LIST *list;
- uword chan;
- {
- register XIOR *io, *in;
-
- for (io = (XIOR *)list->lh_Head; io != (XIOR *)&list->lh_Tail; io = in) {
- in = (XIOR *)io->io_Node.ln_Succ;
- if (io->io_Channel == chan) {
- if (all || io->io_Command == SCMD_DATA) {
- io->io_Node.ln_Succ->ln_Pred = io->io_Node.ln_Pred;
- io->io_Node.ln_Pred->ln_Succ = io->io_Node.ln_Succ;
- free(io->io_Data);
- free(io);
- }
- }
- }
- }
-
- /*
- * Queue a packet into a prioritized list. FIFO is retained for packets
- * of the same priority. This implements one level of channel priorities,
- * before the packets actually get queued to the network. Since up to
- * 4 packets might be queued (200 * 4 = 800 bytes of data or 4 seconds @
- * 2400 baud), a second level of prioritization will also reduce the
- * physical packet size when two channels at relatively large differing
- * priorities are in use.
- *
- * These and other list routines compatible with Amiga list routines.
- */
-
- Enqueue(list, ior)
- LIST *list;
- XIOR *ior;
- {
- register XIOR *io;
- char pri = ior->io_Pri;
-
- io = (XIOR *)list->lh_Head;
- while (io != (XIOR *)&list->lh_Tail) {
- if (pri > io->io_Pri)
- break;
- io = (XIOR *)io->io_Node.ln_Succ;
- }
- ior->io_Node.ln_Succ = (NODE *)io;
- ior->io_Node.ln_Pred = io->io_Node.ln_Pred;
- ior->io_Node.ln_Succ->ln_Pred = (NODE *)ior;
- ior->io_Node.ln_Pred->ln_Succ = (NODE *)ior;
- }
-
- AddTail(list, node)
- LIST *list;
- NODE *node;
- {
- node->ln_Succ = (NODE *)&list->lh_Tail;
- node->ln_Pred = list->lh_TailPred;
- node->ln_Succ->ln_Pred = node;
- node->ln_Pred->ln_Succ = node;
- }
-
- AddHead(list, node)
- LIST *list;
- NODE *node;
- {
- node->ln_Succ = list->lh_Head;
- node->ln_Pred = (NODE *)list;
- node->ln_Succ->ln_Pred = node;
- node->ln_Pred->ln_Succ = node;
- }
-
- ubyte *
- RemHead(list)
- LIST *list;
- {
- NODE *node;
-
- node = list->lh_Head;
- if (node->ln_Succ == NULL)
- return(NULL);
- node->ln_Succ->ln_Pred = node->ln_Pred;
- node->ln_Pred->ln_Succ = node->ln_Succ;
- return((ubyte *)node);
- }
-
- NewList(list)
- LIST *list;
- {
- list->lh_Head = (NODE *)&list->lh_Tail;
- list->lh_Tail = NULL;
- list->lh_TailPred = (NODE *)&list->lh_Head;
- }
-
- GetNext(node)
- NODE *node;
- {
- register NODE *next = node->ln_Succ;
- if (*(long *)next)
- return((long)next);
- return(NULL);
- }
-
- /*
- * CHKBUF
- *
- * Checksum a buffer. Uses a simple, but supposedly very good
- * scheme.
- */
-
- chkbuf(buf, bytes)
- register ubyte *buf;
- register uword bytes;
- {
- register uword i;
- register ubyte c1,c2;
-
- for (i = c1 = c2 = 0; i < bytes; ++i) {
- c1 += buf[i];
- c2 += c1;
- }
- c1 = -(c1 + c2);
- return((c1<<8)|c2);
- }
-
- /*
- * Write timeout signal handler.
- */
-
- sigwto()
- {
- WTimedout = 1;
- Wto_act = 0;
- }
-
- TimerOpen()
- {
- static struct sigvec SA = { sigwto, 0, 0 };
- sigvec(SIGALRM, &SA, NULL);
- }
-
- TimerClose()
- {
- signal(SIGALRM, SIG_IGN);
- }
-
- WTimeout(us)
- {
- static struct itimerval itv;
- struct itimerval ov;
- long mask;
-
- itv.it_value.tv_sec = us / 1000000;
- itv.it_value.tv_usec= (us % 1000000);
-
- mask = sigblock(sigmask(SIGALRM));
- setitimer(ITIMER_REAL, &itv, &ov);
- Wto_act = 1;
- WTimedout = 0;
- sigsetmask(mask);
- if (DDebug)
- fprintf(stderr, "WTimeout set\n");
- }
-
- dneterror(str)
- char *str;
- {
- register short i;
-
- NetClose();
- TimerClose();
- exit(1);
- }
-
- /*
- * setenv(name, str). name must be of the form "NAME="
- */
-
- setenv(name, str)
- char *name;
- char *str;
- {
- extern char **environ;
- static char **elist;
- static int elen;
- char *ptr;
- int i, len;
-
- len = strlen(name);
- if (elist == NULL) {
- for (i = 0; environ[i]; ++i);
- elist = (char **)malloc((i+3)*sizeof(char *));
- elen = i + 3;
- bcopy(environ, elist, i*sizeof(char *));
- environ = elist;
- }
- for (i = 0; elist[i]; ++i) {
- if (strncmp(elist[i], name, len) == 0)
- break;
- }
- if (i == elen) {
- elen += 4;
- elist = environ = (char **)realloc(elist, elen*sizeof(char *));
- }
- ptr = (char *)malloc(len + strlen(str) + 1);
- sprintf(ptr, "%s%s", name, str);
- if (elist[i]) {
- elist[i] = ptr;
- } else {
- elist[i] = ptr;
- elist[i+1] = NULL;
- elen = i + 1;
- }
- }
-
- void
- startserver(port)
- uword port;
- {
- char dir[MAXPATHLEN];
- struct passwd pw_info;
- FILE *fi;
-
- if (!port)
- return;
- if (getenv("DNETDIR")) {
- strcpy(dir, getenv("DNETDIR"));
- strcat(dir, "dnet.servers");
- if (fi = fopen(dir, "r")) {
- if (scan_for_server(fi, port))
- return;
- }
- }
- pw_info = *getpwuid(getuid());
- strcpy(dir, pw_info.pw_dir);
- strcat(dir, "/.dnet/dnet.servers");
- if (fi = fopen(dir, "r")) {
- if (scan_for_server(fi, port))
- return;
- }
- /*
- * LAST TRY
- */
- if (fi = fopen(LASTTRYDNETSERVERS, "r")) {
- if (scan_for_server(fi, port))
- return;
- }
- fprintf(stderr, "Unable to find one of (1) dnet.servers or (2) server\n");
- fprintf(stderr, "entry for port %d\n", port);
- fflush(stderr);
- return;
- }
-
- scan_for_server(fi, port)
- FILE *fi;
- short port;
- {
- char buf[256];
- char path[MAXPATHLEN];
- char cdir[MAXPATHLEN];
- long portno;
- short found = 0;
- void checktilda();
-
- while (fgets(buf, 256, fi)) {
- if (sscanf(buf, "%ld %s %s", &portno, path, cdir) == 3) {
- checktilda(path);
- checktilda(cdir);
- if (portno == port) {
- if (!fork()) {
- int i;
- fclose(fi);
- setuid(getuid());
- signal(SIGHUP, SIG_DFL);
- signal(SIGINT, SIG_DFL);
- signal(SIGQUIT, SIG_DFL);
- signal(SIGTERM, SIG_DFL);
- signal(SIGCHLD, SIG_DFL);
- signal(SIGTSTP, SIG_IGN);
- ioctl(open("/dev/tty", 2), TIOCNOTTY, NULL);
- i = open("/dev/null", O_RDWR, 0);
- dup2(i, 0);
- dup2(i, 1);
- for (i = 3; i < 256; ++i)
- close(i);
- sprintf(buf, "server.%ld.%ld", port, getuid());
- execl(path, buf, cdir, NULL);
- fprintf(stderr, "Unable to exec server: %s\n", path);
- fflush(stderr);
- _exit(1);
- }
- sleep(4); /* is a hack */
- found = 1;
- break;
- }
- }
- }
- fclose(fi);
- return(found);
- }
-
- void
- checktilda(buf)
- char *buf;
- {
- if (buf[0] == '~') {
- short bindex = 1;
- short pathlen;
- struct passwd pw_info, *pw;
-
- pw_info.pw_dir = getenv("HOME");
- if (buf[1] && buf[1] != '/') {
- char username[128];
- while (buf[bindex] && buf[bindex] != '/')
- ++bindex;
- bcopy(buf+1, username, bindex-1);
- username[bindex-1] = 0;
- if (pw = getpwnam(username)) {
- pw_info = *pw;
- } else {
- fprintf(stderr, "Unable to find password entry for %s\n",
- username
- );
- fprintf(stderr, "passing /tmp as dir for server");
- fflush(stderr);
- pw_info.pw_dir = "/tmp";
- }
- }
-
- /*
- * ~[username]<rest of path> -> <basedir><rest of path>
- */
-
- pathlen = strlen(pw_info.pw_dir);
- bcopy(buf + bindex, buf + pathlen, strlen(buf + bindex) + 1);
- bcopy(pw_info.pw_dir, buf, pathlen);
- }
- fflush(stderr);
- }
-
-