From: gwoho liu (gwoho@ucrmath.ucr.edu)
Date: 10/28/92


From: gwoho@ucrmath.ucr.edu (gwoho liu)
Subject: modem multiplexer
Date: 28 Oct 1992 23:57:27 GMT

someone mentioned a modem multiplexer. here is the one i wrote.
i dont know if he was talking about this one or not.
compile it with -DMASTER and run that on linux.
you need a link /dev/modem to the modem. it'll only work at 38400 or whatever
unless you change it. it probably wont work with your modem because i
dunno what kind of modem you have. it works perfectly with mine.

compile it without -DMASTER on other machine. run vm on linux in the /etc/rc.
run kermit with /dev/ttyp0 or whatever. call the other computer. run it on
the other computer. then run kermit on /dev/ttyp0 and the rest.

you might have to change things like GETTY. its easy to figure out.

gwoho

/* vm.c */

#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <fcntl.h>
#include <termios.h>

void *malloc();

#define ESCAPECHAR (']'-'@')
#define MAXVM 24
#define BUFSIZE 64

#define LSIZE 64
#define MINLISTS 100
#define MAXLISTS 1000

int vmfd[MAXVM];
int mfd;

struct list {
        struct list *n,*p;
        int nchars,start;
        char c[LSIZE];
} lists[MINLISTS],flist,vmq[MAXVM],mq;

int nlists = 0;

char *ptynames[] = {
        "/dev/ptyp0","/dev/ptyp1","/dev/ptyp2","/dev/ptyp3",
        "/dev/ptyp4","/dev/ptyp5","/dev/ptyp6","/dev/ptyp7",
        "/dev/ptyp8","/dev/ptyp9","/dev/ptypa","/dev/ptypb",
        "/dev/ptypc","/dev/ptypd","/dev/ptype","/dev/ptypf",
        "/dev/ptyq0","/dev/ptyq1","/dev/ptyq2","/dev/ptyq3",
        "/dev/ptyq4","/dev/ptyq5","/dev/ptyq6","/dev/ptyq7",
        "/dev/ptyq8","/dev/ptyq9","/dev/ptyqa","/dev/ptyqb",
        "/dev/ptyqc","/dev/ptyqd","/dev/ptyqe","/dev/ptyqf",
        "/dev/ptyr0","/dev/ptyr1","/dev/ptyr2","/dev/ptyr3",
        "/dev/ptyr4","/dev/ptyr5","/dev/ptyr6","/dev/ptyr7",
        "/dev/ptyr8","/dev/ptyr9","/dev/ptyra","/dev/ptyrb",
        "/dev/ptyrc","/dev/ptyrd","/dev/ptyre","/dev/ptyrf",
        "/dev/ptys0","/dev/ptys1","/dev/ptys2","/dev/ptys3",
        "/dev/ptys4","/dev/ptys5","/dev/ptys6","/dev/ptys7",
        "/dev/ptys8","/dev/ptys9","/dev/ptysa","/dev/ptysb",
        "/dev/ptysc","/dev/ptysd","/dev/ptyse","/dev/ptysf",
        NULL
};

#ifdef MASTER

#define MODEMNAME "/dev/modem"

#else

#include <sys/wait.h>

#define MODEMNAME "/dev/tty"
#define GETTY "/usr/etc/getty"

int names[MAXVM];

char *ttynames[] = {
        "/dev/ttyp0","/dev/ttyp1","/dev/ttyp2","/dev/ttyp3",
        "/dev/ttyp4","/dev/ttyp5","/dev/ttyp6","/dev/ttyp7",
        "/dev/ttyp8","/dev/ttyp9","/dev/ttypa","/dev/ttypb",
        "/dev/ttypc","/dev/ttypd","/dev/ttype","/dev/ttypf",
        "/dev/ttyq0","/dev/ttyq1","/dev/ttyq2","/dev/ttyq3",
        "/dev/ttyq4","/dev/ttyq5","/dev/ttyq6","/dev/ttyq7",
        "/dev/ttyq8","/dev/ttyq9","/dev/ttyqa","/dev/ttyqb",
        "/dev/ttyqc","/dev/ttyqd","/dev/ttyqe","/dev/ttyqf",
        "/dev/ttyr0","/dev/ttyr1","/dev/ttyr2","/dev/ttyr3",
        "/dev/ttyr4","/dev/ttyr5","/dev/ttyr6","/dev/ttyr7",
        "/dev/ttyr8","/dev/ttyr9","/dev/ttyra","/dev/ttyrb",
        "/dev/ttyrc","/dev/ttyrd","/dev/ttyre","/dev/ttyrf",
        "/dev/ttys0","/dev/ttys1","/dev/ttys2","/dev/ttys3",
        "/dev/ttys4","/dev/ttys5","/dev/ttys6","/dev/ttys7",
        "/dev/ttys8","/dev/ttys9","/dev/ttysa","/dev/ttysb",
        "/dev/ttysc","/dev/ttysd","/dev/ttyse","/dev/ttysf",
        NULL
};

int children[MAXVM];

static
startchild(b)
{
        char **n;

        for (n=ptynames; *n; n++)
                if ((vmfd[b]=open(*n,O_RDWR)) != -1) {
                        fcntl(vmfd[b],F_SETFD,1);
                        names[b] = n-ptynames;
                        if ((children[b]=fork()) == 0) {
                                close(0);
                                close(1);
                                close(2);
                                setsid();
                                open(ttynames[names[b]],O_RDWR);
                                dup(0);
                                dup(0);
                                execl(GETTY,GETTY,NULL);
                                exit(0);
                        }
                        if (children[b] == -1) {
                                close(vmfd[b]);
                                vmfd[b] = -1;
                        }
                        break;
                }
}

#endif

static inline struct list *
removelist(a)
struct list *a;
{
        (a->n->p = a->p)->n = a->n;
        return a;
}

static inline struct list *
addtail(new,list)
struct list *new,*list;
{
        return list->p = (new->p = (new->n = list)->p)->n = new;
}

static inline
freelist(a)
struct list *a;
{
        addtail(a,&flist);
}

static inline struct list *
alloclist()
{
        if (flist.n != &flist)
                return removelist(flist.n);
        if (nlists >= (MAXLISTS-MINLISTS))
                return NULL;
        nlists++;
        return malloc(sizeof(struct list));
}

static inline
putcl(c,a)
struct list *a;
{
        struct list *b = a->p;

        if (b->nchars == LSIZE) {
                if ((b=alloclist()) == NULL)
                        return;
                addtail(b,a);
                b->nchars = b->start = 0;
        }
        b->c[b->start+b->nchars++ & LSIZE-1] = c;
}

static inline int
qempty(a)
struct list *a;
{
        return a->nchars==0 && a->n==a;
}

static inline
writeq(fd,a)
struct list *a;
{
        struct list *b = a;
        int l;

        if (b->nchars == 0)
                if ((b = b->n) == a)
                        return;
        l = LSIZE-b->start;
        if (l > b->nchars)
                l = b->nchars;
        if ((l = write(fd,b->c+b->start,l)) <= 0)
                return;
        b->start = b->start+l & LSIZE-1;
        if ((b->nchars-=l) == 0)
                if (b != a)
                        freelist(removelist(b));
}

static inline
dumpq(a)
struct list *a;
{
        while (a->n != a)
                freelist(removelist(a->n));
        a->nchars = a->start = 0;
}

main()
{
        int out,out2,flag,stat;
        int i,j,c;
        char buf[BUFSIZE],*p;
        struct termios tio;
        fd_set rset,wset;

        for (i=0; i<MINLISTS; i++) {
                lists[i].n = lists+i+1;
                lists[i].p = lists+i-1;
        }
        lists[0].p = lists[MINLISTS-1].n = &flist;
        flist.n = lists;
        flist.p = lists+MINLISTS-1;
        mq.p = mq.n = &mq;
        mq.start = mq.nchars = 0;
        for (i=0; i<MAXVM; i++) {
                vmq[i].p = vmq[i].n = vmq+i;
                vmq[i].start = vmq[i].nchars = 0;
        }
        if ((mfd=open(MODEMNAME,O_RDWR)) == -1) {
                perror(MODEMNAME);
                exit(1);
        }
#ifndef MASTER
        fcntl(mfd,F_SETFD,1);
#endif
        tcgetattr(mfd,&tio);
#ifdef MASTER
        tio.c_cflag &= ~(CBAUD|CSIZE|CSTOPB|HUPCL);
        tio.c_cflag |= B38400|CS8|CREAD|CLOCAL;
#endif
        tio.c_iflag &= ~(INLCR|IGNCR|ICRNL|IUCLC|ISTRIP|IMAXBEL|IXON|IXOFF);
        tio.c_oflag &= ~OPOST;
        tio.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
        tio.c_cc[VMIN] = 1;
        tio.c_cc[VTIME] = 0;
        tcsetattr(mfd,0,&tio);
#ifdef MASTER
        j = 0;
        for (i=0; i<MAXVM; ) {
                if (ptynames[j] == NULL)
                        vmfd[i++] = -1;
                else if ((vmfd[i]=open(ptynames[j++],O_RDWR)) != -1)
                        i++;
        }
#else
        for (i=0; i<MAXVM; i++) {
                vmfd[i] = -1;
                children[i] = -1;
        }
#endif
        flag = out2 = out = 0;
        for (;;) {
#ifndef MASTER
                while ((j = waitpid(-1,&stat,WNOHANG)) > 0)
                        for (i=0; i<MAXVM; i++)
                                if (j == children[i]) {
                                        close(vmfd[i]);
                                        vmfd[i] = -1;
                                        children[i] = -1;
                                        break;
                                }
#endif
                FD_ZERO(&wset);
                FD_ZERO(&rset);
                for (i=0; i<MAXVM; i++) {
#ifndef MASTER
                        if (vmfd[i] == -1) {
                                if (qempty(vmq+i))
                                        continue;
                                startchild(i);
                        }
#endif
                        if (vmfd[i] == -1)
                                continue;
                        if (!qempty(vmq+i))
                                FD_SET(vmfd[i],&wset);
                        FD_SET(vmfd[i],&rset);
                }
                if (!qempty(&mq))
                        FD_SET(mfd,&wset);
                FD_SET(mfd,&rset);
                select(FD_SETSIZE,&rset,&wset,NULL,NULL);
                if (FD_ISSET(mfd,&wset))
                        writeq(mfd,&mq);
                for (i=0; i<MAXVM; i++)
                        if (vmfd[i] != -1) {
                                if (FD_ISSET(vmfd[i],&wset))
                                        writeq(vmfd[i],vmq+i);
                        }
                        else
                                dumpq(vmq+i);
                if (FD_ISSET(mfd,&rset)) {
                        i = read(mfd,buf,BUFSIZE);
                        p = buf;
                        while (--i >= 0) {
                                c = *p++;
                                if (flag) {
                                        flag = 0;
                                        if (c>='A' && c<'A'+MAXVM) {
                                                out = c-'A';
                                                continue;
                                        }
                                }
                                else if (c == ESCAPECHAR) {
                                        flag = 1;
                                        continue;
                                }
                                putcl(c,vmq+out);
                        }
                }
                for (i=0; i<MAXVM; i++)
                        if (vmfd[i] != -1)
                                if (FD_ISSET(vmfd[i],&rset)) {
                                        j = read(vmfd[i],buf,BUFSIZE);
                                        p = buf;
                                        if (j > 0) {
                                                if (out2 != i) {
                                                        putcl(ESCAPECHAR,&mq);
                                                        putcl('A'+i,&mq);
                                                        out2 = i;
                                                }
                                                do {
                                                        putcl(*p,&mq);
                                                        if (*p++ == ESCAPECHAR)
                                                                putcl(ESCAPECHAR,&mq);
                                                } while (--j);
                                        }
                                }
        }
}