home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d1xx
/
d145
/
dnet.lha
/
Dnet
/
unix
/
dnet
/
subs.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-05-26
|
7KB
|
334 lines
/*
* 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);
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 = (getenv("DNETDIR"))?getenv("DNETDIR"):"./";
char buf[256];
char path[128];
char cdir[128];
long portno;
FILE *fi;
sprintf(buf, "%sdnet.servers", dir);
if (!port || (fi = fopen(buf, "r")) == NULL)
return;
while (fgets(buf, 256, fi)) {
if (sscanf(buf, "%ld %s %s", &portno, path, cdir) == 3) {
if (portno == port) {
if (!fork()) {
int i;
fclose(fi);
/*
if (chdir(cdir) < 0) {
fprintf(stderr, "Unable to set server dir %s\n", cdir);
_exit(1);
}
*/
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);
_exit(1);
}
sleep(4); /* is a hack */
break;
}
}
}
fclose(fi);
}