[net.sources] RVMACS dialin/dialout system sources for 4.2

ry@cadre.UUCP (05/25/84)

: This is a shar archive.  Extract with sh, not csh.
echo x - Makefile
cat > Makefile << '!Funky!Stuff!'
#
#	Program: culd
#	File: Makefile
#	Version: 1.0
#	Date: Sat Apr 14 03:51:07 EST 1984
#	Machine: cadre
#	Site: Decision Systems Lab., University of Pittsburgh
#	Author: Russell J. Yount (ry@cadre)
#
DST = /usr/local
PGM = culd
TST = remote
ADDR = /dev/cul
LOG = $(DST)/adm/culd-log
LIB = libculd.a

CFLAGS=-O -c -DADDR=\"$(ADDR)\" -DPGM=\"$(PGM)\" -DLOG=\"$(LOG)\" \
	-DCULDS=\"$(DST)/etc/culds\" -DRVMACS=\"$(DST)/etc/rvmacs\" \
	-DLCKDIR=\"$(DST)/etc\"

MAN5= culds.5 rvmacs.5
MAN8= culd.8

OBJS1= culd_load.o culd_conf.o culd_main.o culd_serv.o culd_init.o culd_sig.o\
       culd_busy.o\
	line_callin.o line_init.o line_callout.o line_test.o line_cleanup.o\
	rvmacs_dial.o rvmacs_load.o

OBJS2 =remote_lib.o

OBJS3 =remote_lib.o remote_test.o

all: $(PGM) $(LIB) $(TST) $(MAN5) $(MAN8)

$(PGM): $(OBJS1)
	cc -O $(OBJS1) -o $(PGM)

$(LIB):	$(OBJS2)
	ar cru $(LIB) $(OBJS2)
	ranlib $(LIB)

$(TST): $(OBJS3)
	cc -O $(OBJS3) -o $(TST)

install: $(PGM) $(LIB) $(MAN5) $(MAN8)
	rm -f $(DST)/etc/$(PGM)
	rm -f $(DST)/lib/$(LIB)
	cd $(DST)/man/man8; rm -f $(MAN8)
	cp $(PGM) $(DST)/etc
	ln $(LIB) $(DST)/lib
	cp $(MAN5) $(DST)/man/man5
	cp $(MAN8) $(DST)/man/man8

remove:
	rm -f $(DST)/etc/$(PGM) $(DST)/lib/$(LIB)
	cd $(DST)/man/man5; rm -f $(MAN5)
	cd $(DST)/man/man8; rm -f $(MAN8)
	
clean:
	rm -f $(PGM) $(LIB) $(TST) $(OBJS1) $(OBJS2) $(OBJS3) $(MAN5) $(MAN8)
	rm -f .emacs_[0-9]* \#CKP* \#BAK*


culd.8: culd.8.t
	sed -e 's,%ROOT,$(DST),' -e 's,%ADDRESS,$(ADDR),' < culd.8.t > culd.8

culds.5: culds.5.t
	sed -e 's,%ROOT,$(DST),' < culds.5.t > culds.5

rvmacs.5: rvmacs.5.t
	sed -e 's,%ROOT,$(DST),' < rvmacs.5.t > rvmacs.5

culd_busy.o:			culd_defs.h			remote_defs.h
culd_conf.o:	line_defs.h
culd_init.o:
culd_load.o:	line_defs.h	culd_defs.h
culd_main.o:			culd_defs.h
culd_serv.o:	line_defs.h	culd_defs.h
culd_sig.o:	line_defs.h

line_callin.o:	line_defs.h	culd_defs.h
line_callout.o:	line_defs.h	culd_defs.h			remote_defs.h
line_cleanup.o:	line_defs.h	culd_defs.h
line_init.o:	line_defs.h	culd_defs.h
line_test.o:	line_defs.h	culd_defs.h

rvmacs_dial.o:			culd_defs.h	rvmacs_defs.h
rvmacs_load.o:			culd_defs.h	rvmacs_defs.h

remote_lib.o:							remote_defs.h




!Funky!Stuff!
echo x - README
cat > README << '!Funky!Stuff!'
RVMACS CULD dialin/dialout system for 4.2 BSD

(c) 1984, Russell J. Yount, Permission granted for non-profit distribution.

EXPAINATION OF OPERATION: (look at manuals and code for more info.)

	The program CULD acts in a manner similar to init.
It is executed once at boot time by /etc/rc or /etc/rc.local. Culd reads
the files culds and rvmacs for system configuration information, listens
to socket /dev/cul for dial requests and also forks a process for each
dialin/dialout line to detect carrier. Two scenarios than can happen.

	 Case one: Either uucp or tip will connect to /dev/cul and request a
number be dialed. Culd will then find a free line and then proceed to
dial the number, passing line selected and status information through socket
to requesting process. Once a call has been completed CULD will wait
until socket is closed before using the line again.

	Case two: A carrier will be established on a line and CULD
will execute /etc/getty to permit login, and wait for the process to die
in a manner similiar to init before using the line again.

	In either case system files /usr/adm/wtmp and /etc/utmp
will be updated correctly.



INSTALLATION OF RVMACS CULD SYSTEM:

LOOK OVER MAKEFILE and make any appropriate changes necessary for
your system. We at cadre prefer to put all non-generic 4.2 changes
on the /usr/local. However this can be easily changed by redefining DST.
Compile and install the system. Make sure that the dialin/dial lines are
contained in /etc/ttys and are disabled (0 in first column.) Kill
any gettys currently on the dialin/dialout lines.

	Make culs configuration files. (culds and rvmacs)
READ MANUAL ENTRIES: They explain the formats of the configuration files.


EXAMPLE:

/usr/local/etc/CULDs: (four lines enabled for dialin/dialout)
c3:3:a
c2:3:a
c1:3:a
c0:3:a

/usr/local/etc/CULDs: (four lines one dialer, see modem/dial manuals too)
c0:0:4:0
c1:0:4:2
c2:0:4:4
c3:0:4:6



	Install tip and uucp changes. Both must be recompiled with
CULD library routines.

	The file uucp.condevs.diff contains the changes to condevs.c
in uucp sources. The distributed RVMACS code has been fixed and
an additional dialer CULD has been added. I define both RVMACS and
CULD, but only CULD is really needed. (I used RVMACS until we got CULD
running here.) Remember to recompile uucp with CULD library.
The following is an example L.sys line when using CULD. (Not really correct.)

cadre Any CULD 1200 91=3919500 "" "" in:-\b-in:-\b-in: uucp word: fatchance1

	The file tip.CULD.c is the dialer code added to tip when using CULD.
Remember to add the CULD dialer declarations and the corresponding table
entry to acutab.c. Also it seems that tip has a function called connect
in it already, Rename it connectX. (since connect is a system call used
in CULD library.) Recompile tip with CULD library and install.

Execute culd as root. (I recommend using debug option.) 
Add execution of culd in either /etc/rc or /etc/rc.local.

NOTE:
Make sure your getty/login will timeout if no user logs in within a few
minutes. (edit /etc/gettycap if necessary.) This is needed to force
hangup of line if call is aborted just before completion.


TUNING/BUGS:
	The timeout limits are very conservitive and should be lengthened.
	Culd should handle redialing, but for now uucp/tip do it.


	I am sorry there is little documentation.
	Please send me any fixes/enhancements.
	Good luck. 

		Russ

		{pitt,mi-cec,idis,cmucsg,cmcl2,sun,sunrise,vax135}!cadre!ry
		
	"Computers are not here to stay"

		Russell J. Yount
		Decision System Laboratory
		University of Pittsburgh
		Pgh PA, 15261
		(412) 624-3490
!Funky!Stuff!
echo x - culd.8.t
cat > culd.8.t << '!Funky!Stuff!'
.TH CULD 8 LOCAL
.UC 4
.SH NAME
culd \- process control for rvmacs lines
.SH SYNOPSIS
.B %ROOT/etc/culd [-d] [-llogfile] [-asocket] [-pprogram]
.SH DESCRIPTION
.I Culd
is invoked once by /etc/rc.local to enable dialin/dialout capabilities
for rvmacs dialer system lines. Once started 
.I culd
coordinates dialout and dialin activity on special rvmacs.
Programs that dialout like
.I
tip(1)
and
.I
uucp(1)
talk to 
.I
culd
thur
on a socket in the UNIX domain.
.PP
Explanation of options:
.TP
.B \-d
Enable debugging.
.TP
.B \-plogfile
Logfile is used instead of default.
.TP
.B \-asocket
Socket is used instead of default.
.TP
.B \-pprogram
Program is used as program name in logfile.
.SH FILES
.br
%ROOT/etc/culds - line configuration file
.br
%ROOT/etc/rvmacs - dialer configuration file
.br
%ADDRESS - default socket address.
.br
%ROOT/adm/culd-log - default logfile.
.br
%ROOT/lib/libculd.a - C library.
.br
%ROOT/etc/cua*.lck - dialer lock files
.br
/dev/ttyc* - dialin/dialout lines
.br
/dev/cua* - dialers.
.SH AUTHOR
Russell J. Yount
.SH "SEE ALSO"
culds(5), rvmacs(5), init(8), uucp(1), tip(1)
.SH BUGS
There should be some way to reconfigure system while it is running.
!Funky!Stuff!
echo x - culd_busy.c
cat > culd_busy.c << '!Funky!Stuff!'
/*
 *	Program: culd
 *	File: culd_busy.c
 *	Version: 1.0
 *	Date: Sat Apr 14 03:51:07 EST 1984
 *	Machine: cadre
 *	Site: Decision Systems Lab., University of Pittsburgh
 *	Author: Russell J. Yount (ry@cadre)
 */
#include "culd_defs.h"
#include "remote_defs.h"

busy() { int pid; CMD cmd; RSP rsp; int cnt;
	pid = fork();
	if (pid != 0)
		return;

	if (debug) {
		sprintf(log_buf,
			"%s: START DEBUG BUSY pid = %d)\n",
				program,getpid());
		write(log_desc,log_buf,strlen(log_buf));		
		}
		
	for (;;) {

		cnt = read(remote_desc,&cmd,sizeof(CMD));
		
		if (cnt == 0) {
			if (debug) {
				sprintf(log_buf,
					"%s: END DEBUG BUSY pid = %d)\n",
						program,getpid());
				write(log_desc,log_buf,strlen(log_buf));		
				}
			_exit(0);
			}
			
		if (cnt != sizeof(CMD)) {
			sprintf(log_buf,"%s: read %s; %s\n",
				program,address,sys_errlist[errno]);
			write(log_desc,log_buf,strlen(log_buf));
			_exit(1);			
			}

		sprintf(rsp.explain,"Error: all lines busy\n",program);
		
		cnt = write(remote_desc,&rsp,sizeof(RSP));
		if (cnt != sizeof(RSP)) {
			sprintf(log_buf,"%s: write %s; %s\n",
				program,address,sys_errlist[errno]);
			write(log_desc,log_buf,strlen(log_buf));
			_exit(1);
			}
		}
}
		
!Funky!Stuff!
echo x - culd_conf.c
cat > culd_conf.c << '!Funky!Stuff!'
/*
 *	Program: culd
 *	File: culd_conf.c
 *	Version: 1.0
 *	Date: Sat Apr 14 03:51:07 EST 1984
 *	Machine: cadre
 *	Site: Decision Systems Lab., University of Pittsburgh
 *	Author: Russell J. Yount (ry@cadre)
 */
#include <signal.h>
#include "line_defs.h"

extern sig();

conf() { TTY *l; int blocked;

	signal(SIGCHLD,sig);

	blocked = sigblock(1 << (SIGCHLD-1));

	for (l = ttys; l < &ttys[MAXTTY]; l++)
		if (l->enable & CALLIN) {
			line_init(l,0,0,0600);
			line_test(l);
			}

	sigsetmask(blocked);
}

!Funky!Stuff!
echo x - culd_defs.h
cat > culd_defs.h << '!Funky!Stuff!'
/*
 *	Program: culd
 *	File: culd_defs.h
 *	Version: 1.0
 *	Date: Sat Apr 14 03:51:07 EST 1984
 *	Machine: cadre
 *	Site: Decision Systems Lab., University of Pittsburgh
 *	Author: Russell J. Yount (ry@cadre)
 */
char *address;
char *program;
char *log_file;
char  log_buf[80];
int   log_desc;
int	  remote_desc;
int	  server_desc;
int	  debug;

extern char *sys_errlist[];
extern int  errno;
!Funky!Stuff!
echo x - culd_init.c
cat > culd_init.c << '!Funky!Stuff!'
/*
 *	Program: culd
 *	File: culd_init.c
 *	Version: 1.0
 *	Date: Sat Apr 14 03:51:07 EST 1984
 *	Machine: cadre
 *	Site: Decision Systems Lab., University of Pittsburgh
 *	Author: Russell J. Yount (ry@cadre)
 */
char *address = ADDR;
char *program = PGM;
char *log_file = LOG;
int   log_desc = -1;
int	  remote_desc = -1;
int	  server_desc = -1;


!Funky!Stuff!
echo x - culd_load.c
cat > culd_load.c << '!Funky!Stuff!'
/*
 *	Program: culd
 *	File: culd_load.c
 *	Version: 1.0
 *	Date: Sat Apr 14 03:51:07 EST 1984
 *	Machine: cadre
 *	Site: Decision Systems Lab., University of Pittsburgh
 *	Author: Russell J. Yount (ry@cadre)
 */
#include <stdio.h>
#include "line_defs.h"
#include "culd_defs.h"

/*
 *	format of CULDS
 *
 *	one per line:
 *
 *		line:type:mode
 *
 *	where line is suffix part of ttyXX
 *
 *	and type refers to /etc/gettycap tty types
 *
 *	and mode one of:
 *		d - disabled
 *		i - callin
 *		o - callout
 *		a - automatic (callin/callout)
 */

#define	MAX_LINE_LEN	132

culd_load() { int ntty; FILE *culds; char buf[MAX_LINE_LEN];
	if (debug) {
		sprintf(log_buf,"%s: START CULD LOAD pid = %d\n",program,getpid());
		write(log_desc,log_buf,strlen(log_buf));		
		}
	ntty = 0;
	culds = fopen(CULDS,"r");
	if (culds == NULL) {
		sprintf(log_buf,
			"%s: Can't open %s, pid = %d\n",program,CULDS,getpid());
		write(log_desc,log_buf,strlen(log_buf));				

		sprintf(log_buf,
			"%s: ABORT, pid = %d\n",program,getpid());
		write(log_desc,log_buf,strlen(log_buf));
		exit(1);
		}
	while (fgets(buf,MAX_LINE_LEN,culds) != NULL) { TTY *l;
		if (buf[0] == 0 || buf[1] == 0 || buf[2] != ':' 
		 || buf[3] == 0 || buf[4] != ':'
		 || (buf[5] != 'd' && buf[5] != 'i' && buf[5] != 'o' && buf[5] != 'a')
		 || buf[6] != '\n' || buf[7] != 0) {
			sprintf(log_buf,
				"%s: BAD line in %s (%s), pid = %d\n",program,CULDS,buf,
				getpid());
			write(log_desc,log_buf,strlen(log_buf));
			continue;
			}
		if (ntty >= MAXTTY) {
			sprintf(log_buf,
				"%s: too many ttys in %s (%s), pid = %d\n",program,CULDS,buf,
				getpid());
			write(log_desc,log_buf,strlen(log_buf));
			continue;
			}
		l = &ttys[ntty++];
		buf[2] = buf[4] = buf[6] = 0;
		strcpy(l->line,&buf[0]);
		strcpy(l->getty_arg,&buf[3]);
		switch (buf[5]) {
			case 'i': l->enable = CALLIN; break;
			case 'o': l->enable = CALLOUT; break;
			case 'd': /* l->enable = 0; */ break;
			case 'a': l->enable = CALLIN|CALLOUT; break;
			}
		}
	fclose(culds);
	if (debug) {
		sprintf(log_buf,"%s: END CULD LOAD (ntty = %d), pid = %d\n",
			ntty,program,getpid());
		write(log_desc,log_buf,strlen(log_buf));		
		}
}

!Funky!Stuff!
echo x - culd_main.c
cat > culd_main.c << '!Funky!Stuff!'
/*
 *	Program: culd
 *	File: culd_main.c
 *	Version: 1.0
 *	Date: Sat Apr 14 03:51:07 EST 1984
 *	Machine: cadre
 *	Site: Decision Systems Lab., University of Pittsburgh
 *	Author: Russell J. Yount (ry@cadre)
 */
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <signal.h>
#include "culd_defs.h"

main(argc,argv) int argc; char **argv; {
  struct sockaddr name, from; int namelen, fromlen, fd, pid;

	for (fd = getdtablesize(); fd >= 3; fd--)
		close(fd);  

	close(0);
	close(1);
	log_desc = fcntl(2,F_DUPFD,10);
	close(2);
	
	fd = open("/dev/null",O_RDWR,0);
	fcntl(fd,F_DUPFD,0);
	fcntl(fd,F_DUPFD,1);
	
	while (--argc > 0) {
		if (argv[argc][0] == '-')
			switch (argv[argc][1]) {
				case 'l':
					log_file = &argv[argc][2];
					continue;
				case 'a':
					address = &argv[argc][2];
					continue;
				case 'p':
					program = &argv[argc][2];
					continue;
				case 'd':
					debug = 1;
					continue;
				}
		sprintf(log_buf,
			"Usage: %s [-lLOGFILE] [-aADDRESS] [-pPROGRAM]\n",program);
		write(log_desc,log_buf,strlen(log_buf));
		_exit(1);
		}

	fd = open(log_file,O_WRONLY|O_APPEND|O_CREAT,0644);
	if (fd < 0) {
		sprintf(log_buf,
			"%s: create %s; %s\n",program,log_file,sys_errlist[errno]);
		write(log_desc,log_buf,strlen(log_buf));
		_exit(1);		
		}
	close(log_desc);
	log_desc = fd;

	if (debug) {
		sprintf(log_buf,
			"%s: START DEBUG PARENT pid = %d\n",program,getpid());
		write(log_desc,log_buf,strlen(log_buf));		
		}
	pid = fork();
	if (pid < 0) {
		sprintf(log_buf,
			"%s: fork; %s\n",program,sys_errlist[errno]);
		write(log_desc,log_buf,strlen(log_buf));
		_exit(1);
		}
	if (pid != 0) {
		if (debug) {
			sprintf(log_buf,
				"%s: END DEBUG DEAMON pid = %d)\n",program,getpid());
			write(log_desc,log_buf,strlen(log_buf));		
			}		
		_exit(0);
		}

	if (debug) {
		sprintf(log_buf,
			"%s: START DEBUG DEAMON pid = %d)\n",program,getpid());
		write(log_desc,log_buf,strlen(log_buf));		
		}
		
	signal(SIGHUP,SIG_IGN);
	signal(SIGINT,SIG_IGN);
	signal(SIGTSTP,SIG_IGN);
	signal(SIGPIPE,SIG_IGN);
	signal(SIGTTIN,SIG_IGN);
	signal(SIGTTOU,SIG_IGN);	

	
	setpgrp(0,getpid());
	
	fd = open("/dev/tty",O_RDWR,0);
	if (fd >= 0) {
		ioctl(fd,TIOCNOTTY,0);
		close(fd);
		}
		
	umask(077);
	
	server_desc = socket(AF_UNIX,SOCK_STREAM,0);
	if (server_desc < 0) {
		sprintf(log_buf,"%s: socket; %s\n",program,sys_errlist[errno]);
		write(log_desc,log_buf,strlen(log_buf));
		_exit(1);
		}
		
	unlink(address);
	name.sa_family = AF_UNIX;
	strcpy(name.sa_data,address);
	namelen = strlen(address) + sizeof(u_short);
	if (bind(server_desc,&name,namelen) < 0) {
		sprintf(log_buf,
			"%s: bind %s; %s\n",program,address,sys_errlist[errno]);
		write(log_desc,log_buf,strlen(log_buf));
		_exit(1);		
		}
		
	if (listen(server_desc,4) < 0) {
		sprintf(log_buf,
			"%s: listen %s; %s\n",program,address,sys_errlist[errno]);
		write(log_desc,log_buf,strlen(log_buf));
		_exit(1);		
		}

	culd_load();
	rvmacs_load();
	conf();
	
	for (;;) {
	    fromlen = sizeof from;
    	remote_desc = accept(server_desc,from,&fromlen);
		if (remote_desc < 0) {
			if (errno == EINTR)
				continue;
			sprintf(log_buf,
				"%s: accept %s; %s\n",program,address,sys_errlist[errno]);
			write(log_desc,log_buf,strlen(log_buf));
			_exit(1);				
			}
		serv();
		close(remote_desc);
		}
}



!Funky!Stuff!
echo x - culd_serv.c
cat > culd_serv.c << '!Funky!Stuff!'
/*
 *	Program: culd
 *	File: culd_serv.c
 *	Version: 1.0
 *	Date: Sat Apr 14 03:51:07 EST 1984
 *	Machine: cadre
 *	Site: Decision Systems Lab., University of Pittsburgh
 *	Author: Russell J. Yount (ry@cadre)
 */
#include <signal.h>
#include "line_defs.h"
#include "culd_defs.h"

serv() { TTY *l; int blocked;

	blocked = sigblock(1 << (SIGCHLD-1));

	if (debug) {
		sprintf(log_buf,
			"%s: SERV DEBUG DEAMON pid = %d)\n",program,getpid());
		write(log_desc,log_buf,strlen(log_buf));		
		}
	for (l = ttys; l < &ttys[MAXTTY]; l++)
		if (l->enable & CALLOUT) {
			switch (l->status) {
				case CALLIN:
				case CALLOUT:
					continue;
					
				case TESTIN:
				case ERROR:
					kill(l->pid,SIGKILL);
					if (debug) {
						sprintf(log_buf,"%s: FOUND DEBUG DEAMON pid = %d)\n",
							program,getpid());
						write(log_desc,log_buf,strlen(log_buf));
						}
					line_callout(l);
					sigsetmask(blocked);					
					return;

				default:
					continue;
				}
			}

	busy();
	sigsetmask(blocked);
}










!Funky!Stuff!
echo x - culd_sig.c
cat > culd_sig.c << '!Funky!Stuff!'
/*
 *	Program: culd
 *	File: culd_sig.c
 *	Version: 1.0
 *	Date: Sat Apr 14 03:51:07 EST 1984
 *	Machine: cadre
 *	Site: Decision Systems Lab., University of Pittsburgh
 *	Author: Russell J. Yount (ry@cadre)
 */
#include <sys/wait.h>
#include <signal.h>
#include "line_defs.h"

sig() { TTY *l; union wait flags; int pid;
	for (;;) {
		pid = wait3(&flags,WUNTRACED|WNOHANG,0);
		if (pid <= 2)
			break;
		if (WIFSTOPPED(flags)) {
			kill(pid,SIGKILL);
			continue;
			}
		for (l = ttys; l < &ttys[MAXTTY]; l++)
			if (pid == l->pid) {
				switch (l->status) {
					case TESTIN:
						if (l->enable & CALLIN) {
							if (WIFEXITED(flags) && flags.w_retcode == 0) {
								line_callin(l->line);
								break;
								}
							line_test(l);
							break;
							}
						l->status = NONE;
						break;



					case CALLIN:
					case CALLOUT:
						line_cleanup(l);
						if (l->enable & CALLIN) {						
							line_test(l);
							break;
							}
						l->status = NONE;
						break;
					}
				break;
				}
		}
}





!Funky!Stuff!
echo x - culds.5.t
cat > culds.5.t << '!Funky!Stuff!'
.TH CULDS 5 LOCAL
.SH NAME
culds \- culd line configuration file
.SH DESCRIPTION
The
.I culds
file contains the line configuration for
.I culd(8).
Each line of
.I culds
is in the format "line:gettyarg:mode" ; where line refers to the
tty suffix (e.g. c0 for ttyc0), gettyarg refers to the argument passed
to getty(8) (one char) and mode is one of the characters 'a','i','o' and 'd'
meaning automatic (dialin/dialout), dialin, dialout, and
disabled respectively.
.SH FILES
%ROOT/etc/culds
.SH "SEE ALSO"
culd(8), rvmacs(5)

!Funky!Stuff!
echo x - line_callin.c
cat > line_callin.c << '!Funky!Stuff!'
/*
 *	Program: culd
 *	File: line_callin.c
 *	Version: 1.0
 *	Date: Sat Apr 14 03:51:07 EST 1984
 *	Machine: cadre
 *	Site: Decision Systems Lab., University of Pittsburgh
 *	Author: Russell J. Yount (ry@cadre)
 */
#include <sys/file.h>
#include <sys/time.h>
#include <signal.h>
#include <setjmp.h>
#include <errno.h>
#include "culd_defs.h"
#include "line_defs.h"

#define	GETTY		"/etc/getty"


static jmp_buf timeout_jmp;
static struct itimerval timeout = { { 0, 0 }, { 10, 0 } };
static struct itimerval notimeout = { { 0,0 }, { 0, 0 } };


static sigalrm() {
	longjmp(sigalrm,1);
}

int line_callin(l) TTY *l; { int fd; char device[32];

	sprintf(device,"/dev/tty%s",l->line);

	l->pid = fork();
	if (l->pid != 0) {
		l->status = (l->pid < 0) ? ERROR : CALLOUT;		
		return;
		}
	if (debug) {
		sprintf(log_buf,
			"%s: START DEBUG CALLIN %s pid = %d)\n",
				program,l->line,getpid());
		write(log_desc,log_buf,strlen(log_buf));		
		}
	signal(SIGALRM,sigalrm);
	if (setjmp(timeout_jmp)) {
		sprintf(log_buf,"%s: open %s; %s\n",
			program,device,"timeout");
		write(log_desc,log_buf,strlen(log_buf));
		_exit(2);
		}
	setitimer(ITIMER_REAL,&timeout,0);
	close(0);
	close(1);
	close(2);
	close(server_desc);
	close(remote_desc);
	fcntl(log_desc,F_SETFL,1);

	setpgrp(0,0);

	fd = open(device,O_RDWR);
	if (fd < 0 && errno == ENXIO) {
		sprintf(log_buf,"%s: open %s; %s\n",
			program,device,sys_errlist[errno]);
		write(log_desc,log_buf,strlen(log_buf));
		sleep(5);
		_exit(1);
		}

	setitimer(ITIMER_REAL,&notimeout,0);
	
	fcntl(fd,F_DUPFD,1);
	fcntl(fd,F_DUPFD,2);
	
	execl(GETTY,"-",l->getty_arg,0);
	
	sprintf(log_buf,"%s: exec %s %s; %s\n",
		GETTY,l->getty_arg,sys_errlist[errno]);
	write(log_desc,log_buf,strlen(log_buf));
	sleep(5);
	_exit(1);
}
!Funky!Stuff!
echo x - line_callout.c
cat > line_callout.c << '!Funky!Stuff!'
/*
 *	Program: culd
 *	File: line_callout.c
 *	Version: 1.0
 *	Date: Sat Apr 14 03:51:07 EST 1984
 *	Machine: cadre
 *	Site: Decision Systems Lab., University of Pittsburgh
 *	Author: Russell J. Yount (ry@cadre)
 */
#include <sys/file.h>
#include <sys/ioctl.h>
#include "culd_defs.h"
#include "line_defs.h"
#include "remote_defs.h"

static struct sgttyb hangup;

int line_callout(l) TTY *l; {
  char device[32]; CMD cmd; RSP rsp; int cnt, desc;

	sprintf(device,"/dev/tty%s",l->line);
  
	l->pid = fork();
	if (l->pid != 0) {
		l->status = (l->pid < 0) ? ERROR : CALLOUT;
		return;
		}
		
	if (debug) {
		sprintf(log_buf,
			"%s: START DEBUG CALLOUT %s pid = %d)\n",
				program,l->line,getpid());
		write(log_desc,log_buf,strlen(log_buf));		
		}
		
	close(server_desc);

	strcpy(rsp.line,l->line);

	desc = -1;
	for (;;) {
		
		cnt = read(remote_desc,&cmd,sizeof(CMD));
		
		if (cnt == 0) {
			if (debug) {
				sprintf(log_buf,
					"%s: END DEBUG CALLOUT %s pid = %d)\n",
						program,l->line,getpid());
				write(log_desc,log_buf,strlen(log_buf));		
				}
			_exit(0);
			}
			
		if (cnt != sizeof(CMD)) {
			sprintf(log_buf,"%s: read %s; %s\n",
				program,address,sys_errlist[errno]);
			write(log_desc,log_buf,strlen(log_buf));
			_exit(1);			
			}
			
		chown(device,cmd.uid,cmd.gid);
		chmod(device,cmd.mode);

		if (desc >= 0) {
			sprintf(log_buf,"disconnected: %s\n",l->line);
			write(log_desc,log_buf,strlen(log_buf));
			vhangup();
			ioctl(desc,TIOCSETP,&hangup);
			sleep(1);
			close(desc);
			}

		
		desc = rvmacs_dial(l->line,cmd.number,rsp.explain);

		if (desc >= 0) {
			sprintf(log_buf,"connected: %s; %s\n",cmd.number,l->line);
			write(log_desc,log_buf,strlen(log_buf));
			}
		
		cnt = write(remote_desc,&rsp,sizeof(RSP));
		if (cnt != sizeof(RSP)) {
			sprintf(log_buf,"%s: write %s; %s\n",
				program,address,sys_errlist[errno]);
			write(log_desc,log_buf,strlen(log_buf));
			_exit(1);
			}
		}
}
!Funky!Stuff!
echo x - line_cleanup.c
cat > line_cleanup.c << '!Funky!Stuff!'
/*
 *	Program: culd
 *	File: line_cleanup.c
 *	Version: 1.0
 *	Date: Sat Apr 14 03:51:07 EST 1984
 *	Machine: cadre
 *	Site: Decision Systems Lab., University of Pittsburgh
 *	Author: Russell J. Yount (ry@cadre)
 */
#include <utmp.h>
#include <sys/file.h>
#include "line_defs.h"
#include "culd_defs.h"

#define	UTMP "/etc/utmp"
#define	WTMP "/usr/adm/wtmp"
#define	TTYS "/etc/ttys"

line_cleanup(l) TTY *l; {
  int fd, gotit; struct utmp wtmp; char device[32];

	if (debug) {
		sprintf(log_buf,
			"%s: START DEBUG CLEANUP %s pid = %d)\n",
				program,l->line,getpid());
		write(log_desc,log_buf,strlen(log_buf));		
		}
		
	sprintf(device,"/dev/tty%s",l->line);

	chown(device,0,0);
	chmod(device,0600);
	
	gotit = 0;
	fd = open(UTMP,O_RDWR,0644);
	if (fd < 0) {
		sprintf(log_buf,"%s: open %s; %s\n",program,UTMP,sys_errlist[errno]);
		write(log_desc,log_buf,strlen(log_buf));
		return;
		}
		
	while (read(fd,(char *)&wtmp,sizeof(wtmp)) == sizeof(wtmp)) {
		if (strcmpn(wtmp.ut_line,&device[sizeof("/dev/")-1],
		  sizeof(wtmp.ut_line)))
			continue;
		if (wtmp.ut_name[0] == 0)
			continue;
		lseek(fd,-(long)sizeof(wtmp),1);
		strcpyn(wtmp.ut_name,"",sizeof(wtmp.ut_name));
		strcpyn(wtmp.ut_host,"",sizeof(wtmp.ut_host));
		time(&wtmp.ut_time);
		write(fd,(char *)&wtmp,sizeof(wtmp));
		gotit++;
		}
		
	close(fd);
	if (gotit == 0)
		return;
		
	fd = open(WTMP,O_WRONLY|O_APPEND,0644);
	if (fd < 0) {
		sprintf(log_buf,"%s: open %s; %s\n",program,WTMP,sys_errlist[errno]);
		write(log_desc,log_buf,strlen(log_buf));
		return;
		}

	strcpyn(wtmp.ut_line,&device[sizeof("/dev/")-1],sizeof(wtmp.ut_line));
	strcpyn(wtmp.ut_name,"",sizeof(wtmp.ut_name));
	strcpyn(wtmp.ut_host,"",sizeof(wtmp.ut_host));
	time(&wtmp.ut_time);
	write(fd,(char *)&wtmp,sizeof(wtmp));
	close(fd);
}


!Funky!Stuff!
echo x - line_defs.h
cat > line_defs.h << '!Funky!Stuff!'
/*
 *	Program: culd
 *	File: line_defs.h
 *	Version: 1.0
 *	Date: Sat Apr 14 03:51:07 EST 1984
 *	Machine: cadre
 *	Site: Decision Systems Lab., University of Pittsburgh
 *	Author: Russell J. Yount (ry@cadre)
 */
#define	MAXTTY	8

#define	NONE	0
#define	CALLIN	1
#define	CALLOUT	2
#define	TESTIN	4
#define	ERROR	8

typedef struct {
	char	line[3];
	char	getty_arg[2];
	int		pid;
	int		status;
	int		enable;
	}
	TTY;

TTY	ttys[MAXTTY];


!Funky!Stuff!
echo x - line_init.c
cat > line_init.c << '!Funky!Stuff!'
/*
 *	Program: culd
 *	File: line_init.c
 *	Version: 1.0
 *	Date: Sat Apr 14 03:51:07 EST 1984
 *	Machine: cadre
 *	Site: Decision Systems Lab., University of Pittsburgh
 *	Author: Russell J. Yount (ry@cadre)
 */
#include "line_defs.h"
#include "culd_defs.h"

line_init(l,uid,gid,mode) TTY *l; int uid, gid; { char device[32];

	if (debug) {
		sprintf(log_buf,
			"%s: INIT DEBUG %s pid = %d)\n",
				program,l->line,getpid());
		write(log_desc,log_buf,strlen(log_buf));		
		}
		
	sprintf(device,"/dev/tty%s",l->line);
	
	chown(device,uid,gid);
	chmod(device,mode);
}



!Funky!Stuff!
echo x - line_test.c
cat > line_test.c << '!Funky!Stuff!'
/*
 *	Program: culd
 *	File: line_test.c
 *	Version: 1.0
 *	Date: Sat Apr 14 03:51:07 EST 1984
 *	Machine: cadre
 *	Site: Decision Systems Lab., University of Pittsburgh
 *	Author: Russell J. Yount (ry@cadre)
 */
#include <sys/file.h>
#include "culd_defs.h"
#include "line_defs.h"

int line_test(l) TTY *l; { int fd; char device[32];

	sprintf(device,"/dev/tty%s",l->line);

	l->pid = fork();
	if (l->pid != 0) {
		l->status = (l->pid < 0) ? ERROR : TESTIN;
		return;
		}

	if (debug) {
		sprintf(log_buf,
			"%s: START DEBUG TEST %s pid = %d)\n",
				program,l->line,getpid());
		write(log_desc,log_buf,strlen(log_buf));		
		}
		
	close(server_desc);
	close(remote_desc);
	
	fd = open(device,O_RDWR,0);
	if (fd < 0) {
		sprintf(log_buf,
			"%s: open %s; %s\n",program,device,sys_errlist[errno]);
		write(log_desc,log_buf,strlen(log_buf));
		sleep(5);
		_exit(1);
		}
		
	vhangup();
	_exit(0);
}
!Funky!Stuff!
echo x - remote_defs.h
cat > remote_defs.h << '!Funky!Stuff!'
/*
 *	Program: culd
 *	File: remote_defs.h
 *	Version: 1.0
 *	Date: Sat Apr 14 03:51:07 EST 1984
 *	Machine: cadre
 *	Site: Decision Systems Lab., University of Pittsburgh
 *	Author: Russell J. Yount (ry@cadre)
 */
#define	N_PHONE_NO	32
#define	N_EXPLAIN	64

typedef struct {
	char	number[N_PHONE_NO];
	int		uid,
			gid,
			mode;
	}
	CMD;

typedef struct {
	char	line[3],
			explain[N_EXPLAIN];	
	}
	RSP;
!Funky!Stuff!
echo x - remote_lib.c
cat > remote_lib.c << '!Funky!Stuff!'
/*
 *	Program: culd
 *	File: remote_lib.c
 *	Version: 1.0
 *	Date: Sat Apr 14 03:51:07 EST 1984
 *	Machine: cadre
 *	Site: Decision Systems Lab., University of Pittsburgh
 *	Author: Russell J. Yount (ry@cadre)
 */
#include <sys/types.h>
#include <sys/socket.h>
#include "remote_defs.h"

extern int errno;
extern char *sys_errlist[];

int remote(number,line,explain) char *number, *line, *explain; {
  int sk, namelen; char *t; struct sockaddr name; CMD cmd; RSP rsp;

	for (t = number; *t; t++)
		if ('0' > *t || *t > '9')
			if (*t != '=' && *t != '-')
				break;
	if ((t - number) < 4 || (t - number) >= N_PHONE_NO || *t != 0) {
		sprintf(explain,"remote: bad number %s\n",number);
		return -1;
		}
	sk = socket(AF_UNIX,SOCK_STREAM,0);
	if (sk < 0) {
		sprintf(explain,"remote: socket; %s\n",sys_errlist[errno]);
		return -1;
		}
	name.sa_family = AF_UNIX;
	strcpy(name.sa_data,ADDR);
	namelen = sizeof(ADDR) - 1 + sizeof(u_short);
	if (connect(sk,&name,namelen) < 0) {
		sprintf(explain,
			"remote: connect %s; %s\n",ADDR,sys_errlist[errno]);
		close(sk);
		return -1;
		}
	strcpy(cmd.number,number);
	cmd.uid = getuid();
	cmd.gid = getgid();
	cmd.mode = 0600;	/* for now use... */
	if (write(sk,&cmd,sizeof(CMD)) != sizeof(CMD)) {
		sprintf(explain,"remote: write; %s\n",sys_errlist[errno]);
		close(sk);
		return -1;		
		}
	if (read(sk,&rsp,sizeof(RSP)) != sizeof(RSP)) {
		sprintf(explain,"remote: read; %s\n",sys_errlist[errno]);
		close(sk);
		return -1;		
		}
	strcpy(explain,rsp.explain);
	if (strcmpn(explain,"Error:",sizeof("Error:")-1) == 0) {
		close(sk);
		return -1;				
		}
	sprintf(line,"/dev/tty%s",rsp.line);
	return sk;
}
!Funky!Stuff!
echo x - remote_test.c
cat > remote_test.c << '!Funky!Stuff!'
/*
 *	Program: culd
 *	File: remote_test.c
 *	Version: 1.0
 *	Date: Sat Apr 14 03:51:07 EST 1984
 *	Machine: cadre
 *	Site: Decision Systems Lab., University of Pittsburgh
 *	Author: Russell J. Yount (ry@cadre)
 */
#include <stdio.h>


main(argc,argv) int argc; char **argv; { char line[3], explain[100]; int fd;
	if (argc != 2) {
		fprintf(stderr,"Usage: remote number\n");
		exit(1);
		}
	fd = remote(argv[1],line,explain);
	fprintf(stderr,explain);
	if (fd < 0)
		exit(2);		
	fprintf(stdout,"remote: hit return to hangup %s\n",line);
	fflush(stdout);
	getc(stdin);
	fprintf(stderr,"remote: hanging up %s\n",line);
	close(fd);
	exit(0);		
}
!Funky!Stuff!
echo x - rvmacs.5.t
cat > rvmacs.5.t << '!Funky!Stuff!'
.TH RVMACS 5 LOCAL
.SH NAME
rvmacs \- culd dialer configuration file
.SH DESCRIPTION
The
.I rvmacs
file contains the dialer configuration for
.I culd(8).
Each line of
.I rvmacs
is in the format "line:dialer:rack:modem" ; where line refers to the
tty suffix (e.g. c0 for ttyc0), dialer refers to the dialer sufix (e.g.
0 for cul0), rack refers to the actual address of dialer and modem refers
to the actual address of modem within rack. (See Rascal Vadic hardware
manuals for details.)
.SH FILES
%ROOT/etc/rvmacs
.SH "SEE ALSO"
culd(8), culds(5)
!Funky!Stuff!
echo x - rvmacs_defs.h
cat > rvmacs_defs.h << '!Funky!Stuff!'
/*
 *	Program: culd
 *	File: rvmacs_defs.h
 *	Version: 1.0
 *	Date: Sat Apr 14 03:51:07 EST 1984
 *	Machine: cadre
 *	Site: Decision Systems Lab., University of Pittsburgh
 *	Author: Russell J. Yount (ry@cadre)
 */
#define	N_RVMACS 8

typedef struct {
	char	line[3],		/*	ttyXX	*/
			dialer[2],		/*	cuaX	*/
			rack,
			modem;
	}
	CUA;
	
CUA	rvmacs[N_RVMACS];

!Funky!Stuff!
echo x - rvmacs_dial.c
cat > rvmacs_dial.c << '!Funky!Stuff!'
/*
 *	Program: culd
 *	File: rvmacs_dial.c
 *	Version: 1.0
 *	Date: Sat Apr 14 03:51:07 EST 1984
 *	Machine: cadre
 *	Site: Decision Systems Lab., University of Pittsburgh
 *	Author: Russell J. Yount (ry@cadre)
 */
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <signal.h>
#include <setjmp.h>
#include "rvmacs_defs.h"
#include "culd_defs.h"

static struct sgttyb dial_sgttyb = { B1200, B1200, -1, -1, ANYP|RAW };
static jmp_buf timeout_jmp;
static struct itimerval ltimeout = { { 0, 0 }, { 240, 0 } };
static struct itimerval mtimeout = { { 0, 0 }, { 40, 0 } };
static struct itimerval stimeout = { { 0, 0 }, { 20, 0 } };
static struct itimerval notimeout = { { 0,0 }, { 0, 0 } };

static int td, ld, dd, pid;

static sigalrm() {
	if (debug) {
		sprintf(log_buf,
			"%s: RVMACS DEBUG alarm pid = %d)\n",
				program,getpid());
		write(log_desc,log_buf,strlen(log_buf));
		}	
	longjmp(timeout_jmp,1);
}


static abort() { int ret;

	setitimer(ITIMER_REAL,&notimeout,0);

	if (debug) {
		sprintf(log_buf,
			"%s: RVMACS DEBUG aborting pid = %d)\n",
				program,getpid());
		write(log_desc,log_buf,strlen(log_buf));
		}
		
	kill(pid,SIGKILL);

	if (td >= 0)
		close(td);
			
	if (dd >= 0) {
		if (setjmp(timeout_jmp) == 0) {	char st;
			if (debug) {
				sprintf(log_buf,
					"%s: RVMACS DEBUG clearing pid = %d)\n",
						program,getpid());
					write(log_desc,log_buf,strlen(log_buf));
					}			
				setitimer(ITIMER_REAL,&mtimeout,0);
				write(dd,"\001",1);
				read(dd,&st,1);
				close(dd);
				}
		setitimer(ITIMER_REAL,&notimeout,0);
		}
			
	if (ld >= 0) {
		flock(ld,LOCK_UN);
		close(ld);
		}

	if (debug) {
		sprintf(log_buf,
			"%s: RVMACS DEBUG waiting pid = %d)\n",
				program,getpid());
		write(log_desc,log_buf,strlen(log_buf));
		}
		
	do {
		ret = wait(0);
		} while (ret > 0 && ret != pid);
		
	if (debug) {
		sprintf(log_buf,
			"%s: RVMACS DEBUG aborted pid = %d)\n",
				program,getpid());
		write(log_desc,log_buf,strlen(log_buf));
		}		
}



rvmacs_dial(line,number,explain) char *line, *number, *explain; {
  int i, cnt, ret; char status, tmp[128], lock[128], dialer[128], device[32];

	if (debug) {
		sprintf(log_buf,
			"%s: RVMACS DEBUG %s dialing %s pid = %d)\n",
				program,line,number,getpid());
		write(log_desc,log_buf,strlen(log_buf));
		}
				
	for (i = 0; i < N_RVMACS && strcmp(rvmacs[i].line,line) != 0; i++);
	
	if (i >= N_RVMACS) {
		sprintf(explain,"Error: can't find dialer for /dev/tty%s\n",line);
		return -1;
		}

	sprintf(device,"/dev/tty%s",line);
	pid = fork();

	if (pid < 0) {
		sprintf(explain,"Error: fork failed\n");
		return -1;		
		}
		
	if (pid == 0) {
		if (debug) {
			sprintf(log_buf,
				"%s: START OPEN DEBUG %s dialing %s pid = %d)\n",
					program,line,number,getpid());
			write(log_desc,log_buf,strlen(log_buf));
			}
		td = open(device,O_RDWR,0);
		if (debug) {
			sprintf(log_buf,
				"%s: END OPEN DEBUG %s pid = %d)\n",
					program,td >= 0 ? "success" : "failure" ,getpid());
			write(log_desc,log_buf,strlen(log_buf));
			}
		_exit(td < 0 ? 1 : 0);
		}

	if (debug) {
		sprintf(log_buf,
			"%s: RVMACS DEBUG setup pid = %d)\n",
				program,getpid());
		write(log_desc,log_buf,strlen(log_buf));
		}
		
	td = ld = dd = -1;

	signal(SIGALRM,sigalrm);
	sigsetmask(sigblock(0) & ~(1 << (SIGALRM-1)));	

	if (setjmp(timeout_jmp) != 0) {
		sprintf(explain,"Error: dial timed out\n");
		abort();
		return -1;
		}
	setitimer(ITIMER_REAL,&ltimeout,0);

	sprintf(tmp,"\002%c%c%s\017\003",rvmacs[i].rack,rvmacs[i].modem,number);
	sprintf(lock,"%s/cua%s.lck",LCKDIR,rvmacs[i].dialer);
	sprintf(dialer,"/dev/cua%s",rvmacs[i].dialer);

	ld = open(lock,O_RDWR|O_CREAT,0600);
	if (ld < 0) {
		sprintf(explain,"Error: open %s failed\n",lock);
		abort();		
		return -1;
		}

	if (flock(ld,LOCK_EX) < 0) {
		sprintf(explain,"Error: flock %s failed\n",lock);
		abort();
		return -1;
		}
	
	dd = open(dialer,O_RDWR,0);
	if (dd < 0) {
		sprintf(explain,"Error: open %s failed\n",dialer);
		abort();		
		return -1;
		}

	if (ioctl(dd,TIOCSETP,&dial_sgttyb) < 0) {
		sprintf(explain,"Error: ioctl TIOCSETP %s failed\n",dialer);
		abort();
		return -1;
		}

	if (debug) {
		sprintf(log_buf,
			"%s: RVMACS DEBUG writing pid = %d)\n",
				program,getpid());
		write(log_desc,log_buf,strlen(log_buf));
		}

	cnt = strlen(tmp);
	if (cnt != write(dd,tmp,cnt)) {
		sprintf(explain,"Error: write %s failed\n",dialer);
		abort();		
		return -1;
		}

	if (debug) {
		sprintf(log_buf,
			"%s: RVMACS DEBUG reading pid = %d)\n",
				program,getpid());
		write(log_desc,log_buf,strlen(log_buf));
		}
		
	if (1 != read(dd,&status,1)) {
		sprintf(explain,"Error: read %s failed\n",dialer);
		abort();
		return -1;
		}

	status &= 0177;
	
	if (debug) {
		sprintf(log_buf,
			"%s: RVMACS DEBUG status from %s is '%c' pid = %d)\n",
				program,dialer,status,getpid());
		write(log_desc,log_buf,strlen(log_buf));
		}
		
	setitimer(ITIMER_REAL,&notimeout,0);

	close(dd);
	flock(ld,LOCK_UN);
	close(ld);
	ld = dd = -1;
	
	switch (status) {
		case 'A':
			if (setjmp(timeout_jmp) != 0) {
				sprintf(explain,"Error: open timed out\n");
				td = -1;
				break;
				}
			setitimer(ITIMER_REAL,&stimeout,0);
			td = open(device,O_RDWR,0);
			setitimer(ITIMER_REAL,&notimeout,0);			
			if (td < 0) {
				sprintf(explain,"Error: open failed\n");
				break;
				}
			if (ioctl(td,TIOCHPCL,0) < 0) {
				sprintf(explain,"Error: ioctl TIOCHPCL %s failed\n",device);
				close(td);
				td = -1;
				}
			sprintf(explain,"Connected\n");
			break;
		
		case 'B':
			sprintf(explain,"Error: abandon call/retry\n");
			break;
		
		case 'D':
			sprintf(explain,"Error: format error\n");
			break;
		
		case 'E':
			sprintf(explain,"Error: parity error\n");
			break;
		
		case 'F':
			sprintf(explain,"Error: ram overflow\n");
			break;
		
		case 'G':
			sprintf(explain,"Error: data line occupied\n");
			break;
		
		default:
			sprintf(explain,"Error: unknown dialer response");
			break;
		}

	if (td < 0)
		kill(pid,SIGKILL);
		
	do {
		ret = wait(0);
		} while (ret > 0 && ret != pid);
		
	return(td);
}

!Funky!Stuff!
echo x - rvmacs_load.c
cat > rvmacs_load.c << '!Funky!Stuff!'
/*
 *	Program: culd
 *	File: rvmacs_load.c
 *	Version: 1.0
 *	Date: Sat Apr 14 03:51:07 EST 1984
 *	Machine: cadre
 *	Site: Decision Systems Lab., University of Pittsburgh
 *	Author: Russell J. Yount (ry@cadre)
 */
#include <stdio.h>
#include "rvmacs_defs.h"
#include "culd_defs.h"

/*
 *	format of RVMACS
 *
 *	one per line
 *
 *	line:dialer:rack:modem
 *
 *	where line is suffix part of ttyXX
 *
 *	and dialer is suffix part of cuaX
 *	
 *	and rack/modem refers to rvmacs hardware configuration (one char each)
 */

#define	MAX_LINE_LEN	132

rvmacs_load() { int nrvmacs; FILE *rvmacsfl; char buf[MAX_LINE_LEN];
	if (debug) {
		sprintf(log_buf,"%s: START RVMACS LOAD pid = %d\n",program,getpid());
		write(log_desc,log_buf,strlen(log_buf));		
		}
	nrvmacs = 0;
	rvmacsfl = fopen(RVMACS,"r");
	if (rvmacs == NULL) {
		sprintf(log_buf,
			"%s: Can't open %s, pid = %d\n",program,RVMACS,getpid());
		write(log_desc,log_buf,strlen(log_buf));				

		sprintf(log_buf,
			"%s: ABORT, pid = %d\n",program,getpid());
		write(log_desc,log_buf,strlen(log_buf));
		exit(1);
		}
	while (fgets(buf,MAX_LINE_LEN,rvmacsfl) != NULL) { CUA *c;
		if (buf[0] == 0 || buf[1] == 0 || buf[2] != ':' 
		 || buf[3] == 0 || buf[4] != ':'
		 || buf[5] == 0 || buf[6] != ':'		 
		 || buf[7] == 0 || buf[8] != '\n' || buf[9] != 0) {
			sprintf(log_buf,
				"%s: BAD line in %s (%s), pid = %d\n",program,RVMACS,buf,
				getpid());
			write(log_desc,log_buf,strlen(log_buf));
			continue;
			}
		if (nrvmacs >= N_RVMACS) {
			sprintf(log_buf,
				"%s: too many ttys in %s (%s), pid = %d\n",program,RVMACS,buf,
				getpid());
			write(log_desc,log_buf,strlen(log_buf));
			continue;
			}
		c = &rvmacs[nrvmacs++];
		buf[2] = buf[4] = 0;
		strcpy(c->line,&buf[0]);
		strcpy(c->dialer,&buf[3]);
		c->rack = buf[5];
		c->modem = buf[7];
		}
	fclose(rvmacsfl);
	if (debug) {
		sprintf(log_buf,"%s: END RVMACS LOAD (nrvmacs = %d), pid = %d\n",
			nrvmacs,program,getpid());
		write(log_desc,log_buf,strlen(log_buf));		
		}
}
!Funky!Stuff!
echo x - tip.culd.c
cat > tip.culd.c << '!Funky!Stuff!'
#include <sys/time.h>

#include "tip.h"

int	culd_abort();
static	int alarmtr();
extern	errno;

static jmp_buf jmpbuf;

culd_dialer(num, acu)
        char *num, *acu;
{
		char	explain[128];

        if (boolean(value(VERBOSE)))
                printf("starting call...");
		if ((AC = remote(num,DV,explain))<0) {
			printf(explain);
			return(0);
			}
        /*
         * open line - will return on carrier
         */
        if ((FD = open(DV, O_RDWR)) < 0) {
                if (errno == EIO)
                        printf("lost carrier...");
                else
                        printf("dialup line open failed...");
                alarm(0);
                close(AC);
                return (0);
        }
        alarm(0);
#ifdef notdef
        ioctl(FD, TIOCHPCL, 0);
#endif
        signal(SIGALRM, SIG_DFL);
        return (1);
}

static
alarmtr()
{

        alarm(0);
        longjmp(jmpbuf, 1);
}

/*
 * Insurance, for some reason we don't seem to be
 *  hanging up...
 */
culd_disconnect()
{
        struct sgttyb cntrl;

        sleep(2);
#ifdef DEBUG
        printf("[disconnect: FD=%d]\n", FD);
#endif
		close(AC);
        if (FD > 0) {
                ioctl(FD, TIOCCDTR, 0);
                ioctl(FD, TIOCGETP, &cntrl);
                cntrl.sg_ispeed = cntrl.sg_ospeed = 0;
                ioctl(FD, TIOCSETP, &cntrl);
                ioctl(FD, TIOCNXCL, (struct sgttyb *)NULL);
        }
        close(FD);
}

culd_abort()
{

#ifdef DEBUG
        printf("[abort: AC=%d]\n", AC);
#endif
        sleep(2);
        if (AC > 0)
                close(AC);
        if (FD > 0)
                ioctl(FD, TIOCCDTR, 0);
        close(FD);
}



static char *
sanitize(s)
	register char *s;
{
        static char buf[128];
        register char *cp;

        for (cp = buf; *s; s++) {
		if (!isdigit(*s) && *s == '<' && *s != '_')
			continue;
		if (*s == '_')
			*s = '=';
		*cp++ = *s;
	}
        *cp++ = 0;
        return (buf);
}
!Funky!Stuff!
echo x - uucp.condevs.diff
cat > uucp.condevs.diff << '!Funky!Stuff!'
45,47c45
< #ifdef CULD				/*	added by Russell J. Yount (ry@cadre) 3/11/84	*/
< int culdopn(), culdcls();
< #endif
---
> 
85,87d82
< #ifdef CULD
< { "CULD","culd", culdopn, nulldev, culdcls },
< #endif
121a117
> 
215,224d210
< /***
<  *	culdopn(flds) make a culd connection
<  *
<  *	return codes:
<  *		>0 - file number - ok
<  *		FAIL - failed
<  */
<  
< #ifdef CULD
< #include <sys/file.h>
226,278d211
< #define	CULDTRIES	2
< static int sock;
< int culdopn(flds) 
< char *flds[];
< {
< 	register ret;
< 	char line[32], explain[128];
< 
< 	if (setjmp(Sjbuf))
< 		return(FAIL);
< 	ret = -1;
< 	signal(SIGALRM, alarmtr);
< 	DEBUG(4, "culd %s ", flds[F_PHONE]);
< 	alarm(10*60);
< 	getnextfd();
< 	sock = remote(flds[F_PHONE],line,explain);
< 	explain[strlen(explain)-1] = 0;	/* clear newline */
< 	next_fd = -1;
< 	if (sock >= 0) {
< 		DEBUG(4, "culd remote success %s",explain);
< 		fcntl(sock,F_SETFD,1);
< 		getnextfd();					
< 		ret = open(line,2);
< 		DEBUG(4, "culd open ret %d",ret);
< 		next_fd = -1;
< 		if (ret > -1) {
< 			fixline(ret,1200);
< 			fcntl(ret,F_SETFD,1);
< 			ioctl(ret,TIOCHPCL,0);
< 			}
< 		else {
< 			close(sock);
< 			logent("culd open","FAILED");
< 			}
< 		}
< 	else {
< 		logent(explain,"FAILED");
< 		DEBUG(4, "culd remote failed %s",explain);
< 		}
< 	alarm(0);
< 	CU_end = culdcls;
< 	if (ret < 0)
< 		return(FAIL);
< 	return(ret);	
< }
< 
< culdcls(fd) int fd; {
< 	close(fd);	
< 	close(sock);			/* reenable dialin	*/
< }
< 
< #endif
< 
1430,1432d1362
<  * added dialer locking 12/8/83 Russell J. Yount cadre!ry
<  * fixed modem addressing 12/8/83 Russell J. Yount cadre!ry
<  * lengthened timeout on dialing for toll calls Russell J. Yount cadre!ry
1435,1438c1365,1368
< char STX=02;	/* Access Adaptor */
< char ETX=03;	/* Transfer to Dialer */
< char SI=017;	/* Buffer Empty (end of phone number) */
< char SOH=01;	/* Abort */
---
> #define	STX	02	/* Access Adaptor */
> #define	ETX	03	/* Transfer to Dialer */
> #define	SI	017	/* Buffer Empty (end of phone number) */
> #define	SOH	01	/* Abort */
1446c1376
< 	char c,ch, acu[20], com[20];
---
> 	char c, acu[20], com[20];
1456c1386,1387
< 		goto failret;
---
> 		i = CF_DIAL;
> 		goto ret;
1459,1463d1389
<         if (mlock(dev->D_calldev) == FAIL) {
< 		logent("DIALER", "NO");
< 		i = CF_NODEV;
< 		goto ret;
< 		}
1467c1393
< 	alarm(120);
---
> 	alarm(30);
1470d1395
< 		delock(dev->D_calldev);
1475,1477c1400,1403
< 	write(va,&STX,1);	/* access adaptor */
< 	ch = *p++;
< 	if (ch < '0' || ch > '7') {
---
> 
> 	p_chwrite(va, STX);	/* access adaptor */
> 	i = *p++ - '0';
> 	if (i < 0 || i > 7) {
1481,1484c1407,1409
< 
< 	write(va,&ch,1);		/* Send Dialer Address Digit */
< 	ch = *p;
< 	if (ch < '0' || ch > ('0'+14)) {
---
> 	p_chwrite(va, i);		/* Send Dialer Address Digit */
> 	i = *p - '0';
> 	if (i <= 0 || i > 14) {
1488,1489c1413
< 
< 	write(va,&ch,1);	/* Send Modem Address Digit */
---
> 	p_chwrite(va, i-1);	/* Send Modem Address Digit */
1491,1492c1415,1416
< 	write(va, &SI,1);	/* Send Buffer Empty */
< 	write(va, &ETX,1);	/* Initiate Call */
---
> 	p_chwrite(va, SI);	/* Send Buffer Empty */
> 	p_chwrite(va, ETX);	/* Initiate Call */
1507,1508d1430
< 
< 
1543c1465
< 	goto goodret;
---
> 	goto ret;
1546,1548c1468
< goodret:
< 	delock(dev->D_calldev);
< 	close(va);
---
> ret:
1552c1472
< ret:
---
> 	close(va);
!Funky!Stuff!