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);
}
}
}
}