Imported from conserver-GNAC-6.05.tar.gz

This commit is contained in:
Bryan Stansell 1998-12-18 15:12:55 -08:00
commit decc2f8c4f
52 changed files with 9872 additions and 0 deletions

64
autologin/INSTALL Normal file
View File

@ -0,0 +1,64 @@
# $Id: INSTALL,v 1.3 94/07/11 12:38:19 ksb Exp $
To install this program you need root access and access to the physical
console of the machine (either through the console server or via the physical
world).
First compile this program and install it as /etc/autologin or
/usr/local/etc/autologin. If `/' is the only file system mounted sometimes
you'll have to use the /etc directory.
OK. Then login on the console as root and run
# exec /etc/autologin -l root
if you get a prompt back with no warnings things look good. Next try
to force *your* account on the console (replace `ME' with your account):
# finger -s
...
# exec /etc/autologin -l ME
$ finger -s
...
You should have seen root on the console the first time you ran finger and
`ME' on the console the second.
If you got this far we are ready to make the leap. Exit the autologin shell
as `ME' and login as root *on another terminal*. Edit /etc/inittab on a
System V machine
cons2:2:respawn:/usr/local/etc/autologin -t/dev/tty0 -lroot >/dev/console 2>&1
or
co:2:respawn:/usr/local/etc/autologin -t/dev/console -lroot
or on an RIOS run commands like:
mkitab "cons0:013456789:respawn:/etc/getty /dev/console"
mkitab "cons2:2:respawn:/usr/local/etc/autologin -t/dev/tty0 -lroot -gsystem >/dev/console 2>&1"
chitab "cons:0123456789:off:/etc/getty /dev/console"
chcons -a login=disable
if you are running SunOS edit /etc/ttytab and comment out the line for the
console and add a new one for autologin:
#console "/usr/etc/getty cons8" unknown on local
console "/usr/local/etc/autologin -lroot -t" xterm on local secure
In either case restart init on the port now
kill -1 1
or
telinit 2
or what ever local custom sez.
One of these will look right to you.
You should get a root shell on the console that you can exit and it will just
come back. When the machine reboots it should stick the same shell up. You
can make the login name here be `ops' or some other `operator' account to run
backups. We use `root'.
--
"We've got all your slack" -- net.flamer
kayessbee, Kevin Braunsdorf, ksb@cc.purdue.edu, pur-ee!ksb, purdue!ksb

83
autologin/Makefile Normal file
View File

@ -0,0 +1,83 @@
#
# $Id: Make.host,v 1.13 94/06/03 15:32:46 nuspl Exp $
#
# Makefile for autologin
#
# Jeff W. Stewart, Purdue University Computing Center
#
DESTDIR=
BINDIR= ${DESTDIR}/usr/local/etc
INCLUDE=
DEBUG= -g
DEFS= -DPUCC -DSUN5
CFLAGS= ${DEBUG} ${DEFS} ${INCLUDE}
GENC= main.c
GENH= main.h
GEN= ${GENC} ${GENH}
HDR=
SRC= autologin.c
OBJ= autologin.o main.o
SOURCE= README autologin.man autologin.m Makefile ${SRC} ${HDR}
all: autologin
autologin: ${OBJ}
${CC} ${CFLAGS} -o autologin ${OBJ}
main.h: main.c
main.c: autologin.m
mkcmd std_help.m std_version.m autologin.m
-(cmp -s prog.c main.c || (cp prog.c main.c && echo main.c updated))
-(cmp -s prog.h main.h || (cp prog.h main.h && echo main.h updated))
rm -f prog.[ch]
# On keep (EPIX), putenv.o is extracted (ar x) from /usr/lib/libc.a
# and setgroups.o is extracted from libbsd.a
#
putenv.o:
ar x /usr/lib/libc.a $@
setgroups.o:
ar x /usr/lib/libbsd.a $@
getut.o:
ar x /sysv/usr/lib/libc.a $@
clean: FRC
rm -f autologin *.o errs core Makefile.bak a.out lint.errs ${GEN}
lint: ${HDR} ${SRC} ${GEN} FRC
lint -h ${CDEFS} ${INCLUDE} ${GEN} ${SRC}
install: all
install -c -s -m 755 autologin ${BINDIR}
distrib:
distrib -c ${BINDIR}/autologin
depend: ${HDR} ${SRC} ${GEN}
maketd -a ${HDR} ${SRC} ${GEN}
spotless: clean
rcsclean Makefile ${HDR} ${SRC}
source: ${SOURCE}
${SOURCE}:
co -q $@
FRC:
# DO NOT DELETE THIS LINE - maketd DEPENDS ON IT
main.o: main.c
autologin.o: autologin.c main.h
# *** Do not add anything here - It will go away. ***

13
autologin/README Normal file
View File

@ -0,0 +1,13 @@
# $Id: README,v 1.3 93/04/21 16:13:37 ksb Exp $
This program can be used to put a root shell on the console at boot time.
See the manual page.
ksb
Ports to: HOST OS CDEFS
SUN3 4.1.1 -DSUNOS
SUN4 4.1.2 -DSUNOS
V386 ? -DSRM
EPIX ? -DEPIX -systype posix -I/usr/include (+ extra .o files)
IBMR2 -DIBMR2

654
autologin/autologin.c Normal file
View File

@ -0,0 +1,654 @@
/*
* Perform an auto-login on a specified tty port.
*
* autologin [-u] [-c<command>] [-e<env=val>] [-g<group>] -l<login> -t<tty>
*
* Jeff W. Stewart - Purdue University Computing Center
*
* some of the ideas in this code are based on the Ohio State
* console server as re-coded by Kevin Braunsdorf (PUCC)
*
* This program was written to be run out of inittab.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <grp.h>
#include <pwd.h>
#include <utmp.h>
#include <string.h>
#include <errno.h>
#if !defined IBMR2
extern char *sys_errlist[];
#define strerror(Me) (sys_errlist[Me])
#endif
#define NEED_PUTENV (!(defined(IBMR2) || defined(EPIX) || defined(SUNOS) || defined(SUN5)))
#if S81
#include <sys/vlimit.h>
#else
#include <limits.h>
#endif
#if SUN5
#define USE_UTENT 1
#include <sys/time.h>
#include <sys/resource.h>
static int
getdtablesize()
{
auto struct rlimit rl;
(void)getrlimit(RLIMIT_NOFILE, &rl);
return rl.rlim_cur;
}
#endif
/* yucky kludges
*/
#ifdef EPIX
#include "/bsd43/usr/include/ttyent.h"
#include <posix/sys/termios.h>
#define NGROUPS_MAX 8
#define getsid(Mp) (Mp)
#define getdtablesize() 64
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* and microseconds */
};
typedef int mode_t;
extern struct passwd *getpwnam();
extern struct group *getgrnam();
#define USE_TC 1
#define USE_UTENT 1
#else
#if defined IBMR2
#include <termios.h>
#define setsid() getpid()
#define getsid(Mp) (Mp)
#define HAVE_GETUSERATTR 1
#define USE_TC 1
#define USE_UTENT 1
#else
#if defined V386
typedef int mode_t;
#define getdtablesize() OPEN_MAX
#define setsid() getpid()
#define getsid(Mp) (Mp)
#define setgroups(x, y) 0
#include <sys/ttold.h>
#include <sys/ioctl.h>
#define USE_IOCTL 1
#define USE_TC 1
#else
#if defined S81
#include <sys/time.h>
#include <sys/ioctl.h>
typedef int mode_t;
#define setsid() getpid()
#define getsid(Mp) (Mp)
#define USE_IOCTL 1
#define USE_TC 0
#define USE_OLD_UTENT 1
#else
#if defined(NETBSD)
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <sys/proc.h>
#include <sys/ioctl_compat.h>
#define setsid() getpid()
#define getsid(Mp) (Mp)
#define USE_IOCTL 1
#define USE_OLD_UTENT 1
#define PATH_SU "/usr/ucb/su"
#define UTMP_PATH "/var/run/utmp"
#else
#if defined(FREEBSD)
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <sys/proc.h>
#include <sys/ioctl_compat.h>
#define setsid() getpid()
#define getsid(Mp) (Mp)
#define USE_IOCTL 1
#define USE_OLD_UTENT 1
#define PATH_SU "/usr/ucb/su"
#else
#include <sys/termios.h>
#endif /* NETBSD */
#endif /* 386bsd or equiv */
#endif /* sequent */
#endif /* intel v386 */
#endif /* find termios */
#endif /* find any term stuff */
#ifdef SUNOS
#include <sys/time.h>
#include <ttyent.h>
#define setsid() getpid()
#define getsid(Mp) (Mp)
#endif
#if ! defined V386
#include <sys/vnode.h>
#endif
#ifdef IBMR2
#include <sys/ioctl.h>
#include <usersec.h>
#endif /* IBMR2 */
#include "main.h"
#define TTYMODE 0600
#ifndef O_RDWR
#define O_RDWR 2
#endif
#ifndef NGROUPS_MAX
#define NGROUPS_MAX 8
#endif
#if !defined(UTMP_FILE)
#if defined(_PATH_UTMP)
#define UTMP_FILE _PATH_UTMP
#else
#define UTMP_FILE "/etc/utmp"
#endif
#endif
#if !defined(PATH_SU)
#define PATH_SU "/bin/su"
#endif
/*
* Global variables
*/
#ifndef lint
char *rcsid = "$Id: autologin.c,v 1.22 93/09/04 21:48:41 ksb Exp $";
#endif /* not lint */
char *progname;
gid_t awGrps[NGROUPS_MAX];
int iGrps = 0;
/*
* External variables
*/
extern int optind;
extern char *optarg;
void make_utmp();
void usage();
int
Process()
{
register int c;
int iErrs = 0;
int i, iNewGrp;
gid_t wGid;
uid_t wUid;
char *pcCmd = (char *)0,
*pcDevTty = (char *)0;
char *pcTmp;
#ifdef IBMR2
char *pcGrps;
#endif /* IBMR2 */
struct passwd *pwd;
struct stat st;
#if USE_IOCTL
auto struct sgttyb n_sty;
#if USE_TC
auto struct tc n_tchars;
#else
auto struct tchars n_tchars;
#endif
#if HAVE_JOBS
auto struct ltchars n_ltchars;
#endif
#else
struct termios n_tio;
#endif
if ((char *)0 != pcCommand) {
if ((char *)0 == (pcCmd = (char *)malloc(strlen(pcCommand) + 4))) {
(void) fprintf(stderr, "%s: malloc: %s\n", progname, strerror(errno));
exit(1);
/* NOTREACHED */
}
(void)strcpy(pcCmd, "-c ");
(void)strcat(pcCmd, pcCommand);
}
if ( (char *)0 != pcGroup ) {
iErrs += addgroup(pcGroup);
}
if ( (char *)0 == pcLogin ) {
static char acLogin[17];
if ((struct passwd *)0 == (pwd = getpwuid(geteuid()))) {
(void) fprintf(stderr, "%s: %d: uid unknown\n", progname, geteuid());
exit(1);
/* NOTREACHED */
}
pcLogin = strcpy(acLogin, pwd->pw_name);
} else if ((struct passwd *)0 == (pwd = getpwnam(pcLogin))) {
(void) fprintf(stderr, "%s: %s: login name unknown\n", progname, pcLogin);
exit(1);
/* NOTREACHED */
}
wUid = pwd->pw_uid;
wGid = pwd->pw_gid;
#ifdef HAVE_GETUSERATTR
/* getuserattr() returns a funny list of groups:
* "grp1\0grp2\0grp3\0\0"
*/
if (0 == getuserattr(pcLogin, S_SUGROUPS, &pcGrps, SEC_LIST)) {
while ('\000' != *pcGrps) {
/* ignore "ALL" and any group beginning with '!' */
if ('!' == *pcGrps || 0 != strcmp(pcGrps, "ALL")) {
iErrs += addgroup(pcGrps);
}
pcGrps = pcGrps + strlen(pcGrps) + 1;
}
}
#endif /* HAVE_GETUSERATTR */
if ((char *)0 != pcTty) {
if ( '/' == *pcTty ) {
pcDevTty = pcTty;
} else {
if ( (char *)0 == (pcDevTty = (char *)malloc(strlen(pcTty)+5+1) ) ) {
(void) fprintf(stderr, "%s: malloc: %s\n", progname, strerror(errno));
exit(1);
}
sprintf(pcDevTty, "/dev/%s", pcTty);
}
if (0 != stat(pcDevTty, &st)) {
(void) fprintf(stderr, "%s: Can't stat %s: %s\n", progname, pcDevTty, strerror(errno));
++iErrs;
#ifdef IBMR2
} else if (VCHR != st.st_type && VMPC != st.st_type) {
(void) fprintf(stderr, "%s: %s is not a character device\n", progname, pcDevTty);
++iErrs;
#endif
}
} else {
pcDevTty = (char *)0;
}
if (iErrs) {
usage();
exit(1);
/* NOTREACHED */
}
if (0 != geteuid()) {
(void) fprintf(stderr, "%s: Must be root!!!\n", progname);
exit(1);
/* NOTREACHED */
}
if (iGrps && 0 < setgroups(iGrps, awGrps)) {
(void) fprintf(stderr, "%s: Can't setgroups(): %s\n", progname, strerror(errno));
exit(1);
/* NOTREACHED */
}
/* Close open files
*/
for (i = (char *)0 == pcTty ? 3 : 0; i < getdtablesize(); ++i) {
(void) close(i);
}
/* Make us a session leader so that when we open /dev/tty
* it will become our controlling terminal.
*/
if (-1 == (iNewGrp = getsid(getpid()))) {
if (-1 == (iNewGrp = setsid())) {
(void) fprintf(stderr, "%s: setsid: %d: %s\n", progname, iNewGrp, strerror(errno));
iNewGrp = getpid();
}
}
/* Open the TTY for stdin, stdout and stderr
*/
if ((char *)0 != pcDevTty) {
#ifdef TIOCNOTTY
if (-1 != (i = open("/dev/tty", 2, 0))) {
if ( ioctl(i, TIOCNOTTY, (char *)0) )
(void) fprintf(stderr, "%s: ioctl(%d, TIOCNOTTY, (char *)0): %s\n", progname, i, strerror(errno));
(void) close(i);
}
#endif
if (0 != open(pcDevTty, O_RDWR, 0666)) {
exit(1);
/* NOTREACHED */
}
dup(0);
dup(0);
}
/* put the tty in out process group
*/
#if ! (EPIX || SUN5)
#if USE_TC
if (-1 >= (i = tcgetpgrp(0))){
(void) fprintf(stderr, "%s: tcgetpgrp: %s\n", progname, strerror(errno));
}
#endif
#if USE_SETPGRP
if (-1 != i && setpgrp(0, i) ){
(void) fprintf(stderr, "%s: setpgrp: %s, i = %d\n", progname, strerror(errno), i);
}
#endif
#if USE_TC
if (tcsetpgrp(0, iNewGrp)){
(void) fprintf(stderr, "%s: tcsetpgrp: %s\n", progname, strerror(errno));
}
#endif
#if USE_SETPGRP
if (-1 != iNewGrp && setpgrp(0, iNewGrp)){
(void) fprintf(stderr, "%s: setpgrp: %s, iNewGrp = %d\n", progname, strerror(errno), iNewGrp);
}
#endif
#endif
/* put the tty in the correct mode
*/
#if USE_IOCTL
if (0 != ioctl(0, TIOCGETP, (char *)&n_sty)) {
fprintf(stderr, "%s: iotcl: getp: %s\n", progname, strerror(errno));
exit(10);
}
#if USE_TC
n_sty.sg_flags &= ~(O_CBREAK);
n_sty.sg_flags |= (O_CRMOD|O_ECHO);
#else
n_sty.sg_flags &= ~(CBREAK);
n_sty.sg_flags |= (CRMOD|ECHO);
#endif
n_sty.sg_kill = '\025'; /* ^U */
n_sty.sg_erase = '\010'; /* ^H */
if (0 != ioctl(0, TIOCSETP, (char *)&n_sty)) {
fprintf(stderr, "%s: iotcl: setp: %s\n", progname, strerror(errno));
exit(10);
}
/* stty undef all tty chars
*/
#if 0
if (-1 == ioctl(0, TIOCGETC, (char *)&n_tchars)) {
fprintf(stderr, "%s: ioctl: getc: %s\n", progname, strerror(errno));
return;
}
n_tchars.t_intrc = -1;
n_tchars.t_quitc = -1;
if (-1 == ioctl(0, TIOCSETC, (char *)&n_tchars)) {
fprintf(stderr, "%s: ioctl: setc: %s\n", progname, strerror(errno));
return;
}
#endif
#if HAVE_JOBS
if (-1 == ioctl(0, TIOCGLTC, (char *)&n_ltchars)) {
fprintf(stderr, "%s: ioctl: gltc: %s\n", progname, strerror(errno));
return;
}
n_ltchars.t_suspc = -1;
n_ltchars.t_dsuspc = -1;
n_ltchars.t_flushc = -1;
n_ltchars.t_lnextc = -1;
if (-1 == ioctl(0, TIOCSLTC, (char *)&n_ltchars)) {
fprintf(stderr, "%s: ioctl: sltc: %s\n", progname, strerror(errno));
return;
}
#endif
#else /* not using ioctl, using POSIX or sun stuff */
#if USE_TC
if (0 != tcgetattr(0, &n_tio)) {
(void) fprintf(stderr, "%s: tcgetattr: %s\n", progname, strerror(errno));
exit(1);
/* NOTREACHED */
}
#else
if (0 != ioctl(0, TCGETS, &n_tio)) {
(void) fprintf(stderr, "%s: iotcl: TCGETS: %s\n", progname, strerror(errno));
exit(1);
/* NOTREACHED */
}
#endif
n_tio.c_iflag &= ~(IGNCR|IUCLC);
n_tio.c_iflag |= ICRNL|IXON|IXANY;
n_tio.c_oflag &= ~(OLCUC|ONOCR|ONLRET|OFILL|NLDLY|CRDLY|TABDLY|BSDLY);
n_tio.c_oflag |= OPOST|ONLCR|TAB3;
n_tio.c_lflag &= ~(XCASE|NOFLSH|ECHOK|ECHONL);
n_tio.c_lflag |= ISIG|ICANON|ECHO;
n_tio.c_cc[VEOF] = '\004'; /* ^D */
n_tio.c_cc[VEOL] = '\000'; /* EOL */
n_tio.c_cc[VERASE] = '\010'; /* ^H */
n_tio.c_cc[VINTR] = '\003'; /* ^C */
n_tio.c_cc[VKILL] = '\025'; /* ^U */
/* MIN */
n_tio.c_cc[VQUIT] = '\034'; /* ^\ */
n_tio.c_cc[VSTART] = '\021'; /* ^Q */
n_tio.c_cc[VSTOP] = '\023'; /* ^S */
n_tio.c_cc[VSUSP] = '\032'; /* ^Z */
#if USE_TC
if (0 != tcsetattr(0, TCSANOW, &n_tio)) {
(void) fprintf(stderr, "%s: tcsetattr: %s\n", progname, strerror(errno));
exit(1);
/* NOTREACHED */
}
#else
if (0 != ioctl(0, TCSETS, &n_tio)) {
(void) fprintf(stderr, "%s: ioctl: TCSETS: %s\n", progname, strerror(errno));
exit(1);
/* NOTREACHED */
}
#endif
#endif /* setup tty */
if (fMakeUtmp) {
extern char *ttyname();
make_utmp(pcLogin, (char *)0 != pcTty ? pcTty : ttyname(0));
}
/* Change ownership and modes on the tty.
*/
if ((char *)0 != pcDevTty) {
(void) chown(pcDevTty, wUid, wGid);
(void) chmod(pcDevTty, (mode_t) TTYMODE);
}
if ((char *)0 != pcCmd) {
execl(PATH_SU, "su", "-", pcLogin, pcCmd, (char *)0);
} else {
execl(PATH_SU, "su", "-", pcLogin, (char *)0);
}
}
#if NEED_PUTENV
int
putenv(pcAssign)
char *pcAssign;
{
register char *pcEq;
if ((char *)0 != (pcEq = strchr(pcAssign, '='))) {
*pcEq++ = '\000';
(void)setenv(pcAssign, pcEq, 1);
*--pcEq = '=';
} else {
unsetenv(pcAssign);
}
}
#endif
int
addgroup(pcGrp)
char *pcGrp;
{
struct group *grp;
grp = getgrnam(pcGrp);
if ((struct group *)0 == grp) {
(void) fprintf(stderr, "%s: Unknown group: %s\n", progname, pcGrp);
return(1);
}
if (iGrps >= NGROUPS_MAX) {
(void) fprintf(stderr, "%s: Too many groups specified with \"%s\".\n", progname, pcGrp);
return(1);
}
awGrps[iGrps++] = grp->gr_gid;
return(0);
}
/* install a utmp entry to show the use we know is here is here (ksb)
*/
void
make_utmp(pclogin, pctty)
char *pclogin;
char *pctty;
{
register int iFound, iPos;
register int fdUtmp;
register char *pcDev;
register struct utmp *up;
auto struct utmp outmp, utmp;
if ((char *)0 == pctty) {
return;
}
if ((fdUtmp = open(UTMP_FILE, O_RDWR, 0664)) < 0) {
return;
}
/* create empty utmp entry
*/
(void)memset(&utmp, 0, sizeof(struct utmp));
/* Only the last portion of the tty is saved, unless it's
* all digits. Then back up and include the previous part
* /dev/pty/02 -> pty/02 (not just 02)
*/
if ((char *)0 != (pcDev = strrchr(pctty, '/'))) {
if (! *(pcDev + strspn(pcDev, "/0123456789"))) {
while (pcDev != pctty && *--pcDev != '/') {
}
}
if (*pcDev == '/') {
++pcDev;
}
} else {
pcDev = pctty;
}
#if USE_OLD_UTENT
/* look through /etc/utmp by hand (sigh)
*/
iFound = iPos = 0;
while (sizeof(utmp) == read(fdUtmp, & utmp, sizeof(utmp))) {
if (0 == strncmp(utmp.ut_line, pcDev, sizeof(utmp.ut_line))) {
++iFound;
break;
}
iPos++;
}
(void)strncpy(utmp.ut_name, pclogin, sizeof(utmp.ut_name));
#else
#if USE_UTENT
/* look through getutent's by pid
*/
(void)setutent();
utmp.ut_pid = getpid();
iFound = iPos = 0;
while ((up = getutent()) != NULL) {
if (up->ut_pid == utmp.ut_pid) {
utmp = *up;
++iFound;
break;
}
iPos++;
}
(void)endutent();
/* we were an initprocess, now we are a login shell
*/
utmp.ut_type = USER_PROCESS;
(void)strncpy(utmp.ut_user, pclogin, sizeof(utmp.ut_user));
if ('\000' == utmp.ut_line[0]) {
(void)strncpy(utmp.ut_line, pcDev, sizeof(utmp.ut_line));
}
#else
{
register struct ttyent *ty;
/* look through ttyslots by line?
*/
(void)setttyent();
iFound = iPos = 0;
while ((ty = getttyent()) != NULL) {
if (strcmp(ty->ty_name, pcDev) == 0) {
++iFound;
break;
}
iPos++;
}
/* fill in utmp from ty ZZZ */
(void)endttyent();
}
(void)strncpy(utmp.ut_line, pcDev, sizeof(utmp.ut_line));
(void)strncpy(utmp.ut_name, pclogin, sizeof(utmp.ut_name));
(void)strncpy(utmp.ut_host, "(autologin)", sizeof(utmp.ut_host));
#endif
#endif
utmp.ut_time = time((time_t *) 0);
if (0 == iFound) {
fprintf(stderr, "%s: %s: no ttyslot\n", progname, pctty);
} else if (-1 == lseek(fdUtmp, (off_t)(iPos*sizeof(utmp)), 0)) {
fprintf(stderr, "%s: lseek: %s\n", progname, strerror(errno));
} else {
(void)write(fdUtmp, (char *)&utmp, sizeof(utmp));
}
(void)close(fdUtmp);
}
void
usage()
{
char *u_pch;
int u_loop;
for (u_loop = 0; (char *)0 != (u_pch = au_terse[u_loop]); ++u_loop) {
fprintf(stdout, "%s: usage%s\n", progname, u_pch);
}
for (u_loop = 0; (char *)0 != (u_pch = u_help[u_loop]); ++u_loop) {
fprintf(stdout, "%s\n", u_pch);
}
}

57
autologin/autologin.m Normal file
View File

@ -0,0 +1,57 @@
# mkcmd parser for autologin program
%%
static char *rcsid =
"$Id: autologin.m,v 1.2 92/07/28 13:18:34 ksb Exp $";
%%
integer variable "iErrs" {
init "0"
}
char* 'c' {
named "pcCommand"
param "cmd"
init '(char *)0'
help "command to run"
}
function 'e' {
named "putenv"
param "env=value"
update "if (%n(%N) != 0) { (void) fprintf(stderr, \"%%s: putenv(\\\"%%s\\\"): failed\\n\", %b, %N);exit(1);}"
help "environment variable to set"
}
char* 'g' {
named "pcGroup"
param "group"
init '(char *)0'
help "initial group"
}
char* 'l' {
named "pcLogin"
param "login"
init '(char *)0'
help "login name"
}
char* 't' {
named "pcTty"
param "tty"
init '(char *)0'
help "attach to this terminal"
}
boolean 'u' {
named "fMakeUtmp"
init "1"
update "%run = 0;"
help "do no make utmp entry"
}
exit {
named "Process"
update "%n();"
aborts "exit(iErrs);"
}

141
autologin/autologin.man Normal file
View File

@ -0,0 +1,141 @@
.\" $Id: autologin.man,v 1.3 93/03/16 16:41:45 ksb Exp $
.TH AUTOLOGIN 8L PUCC
.SH NAME
autologin \- create an automatic login session from /etc/inittab
.SH SYNOPSIS
.B /usr/local/etc/autologin
[
.B \-u
] [
.B \-c
.I command
] [
.B \-e
.IB env = val
] [
.B \-g
.I group
] [
.B \-l
.I login
] [
.B \-t
.I tty
]
.SH DESCRIPTION
.I Autologin
creates a login session for
.I login
by running an
.RB ` "su \-
.IR login '
on the specified device
.RI ( tty ).
If a
.I command
is given, that command is executed via
.RB ` "su \-
.IB login " \-c
.IR command .'
.PP
.I Autologin
also changes the ownership of the tty port to the user and sets the
mode to 0600.
.PP
On AIX,
.I autologin
uses
.IR getuserattr ( 3 )
to determine which groups are required to su to
.I login
and sets those groups for the process before executing the
.IR su ( 1 )
command.
.SH OPTIONS
.TP \w'command'u+4
.BI \-c command
Execute the command
.IR command .
The default action is to create a login shell.
.TP
.BI \-e env = val
Add the evironment variable assignment
.IB env = val
to the environment.
.TP
.BI \-g group
Add
.I group
to current process group set before running
.IR su ( 1 ).
This option probably isn't necessary since the group set should be
properly handled through the use of
.IR getuserattr ( 3 ).
.TP
.BI \-l login
Create the login process for the user
.IR login .
If none is given the effective uid is used.
.TP
.BI \-t tty
.I tty
is the name of the character-special file that corresponds to the terminal
to be logged in.
If none is given the current controlling terminal is used.
.TP
.B \-u
Don't create a utmp entry. Normally, an entry is written to
.I /etc/utmp
to maintain a record of users logged into the system.
.SH EXAMPLES
Adding the following line to
.I /etc/inittab
on an AIX machine establishes a root login on the console terminal
.RI ( /dev/tty0 )
with any error messages directed to
.IR /dev/console :
.br
.na
cons2:2:respawn:/usr/local/etc/autologin \-t/dev/tty0 \-lroot > /dev/console 2>&1
.ad
.PP
Adding the following line to
.I /etc/inittab
on an AIX machine causes ssinfo to be logged in on
.I /dev/tty10
with the
.B TERM
environment variable set to
.IR reg20 :
.br
.na
ss10:2:respawn:/usr/local/etc/autologin \-e TERM=reg20 \-t/dev/tty10 \-lssinfo
.ad
.PP
Adding the following line to \fI/etc/ttytab\fP on a Sun 4.1.\fIx\fP
machine establishes a root login on the console device:
.na
console "/usr/local/etc/autologin \-lroot \-t" xterm on local secure
.ad
Note that \fIinit\fP provides the \fItty\fP argument on the end of the command.
.SH FILES
/bin/su
.br
/etc/inittab
.br
/etc/passwd
.br
/etc/utmp
.SH "SEE ALSO"
su(1),
getuserattr(3),
inittab(5),
init(8).
.SH AUTHOR
Jeff W\. Stewart \- Purdue University Computing Center
.SH BUGS
Doesn't add entries to /usr/adm/wtmp??
.br
Doesn't add utmp entry unless it's been setup by init(8).
.br
Only runs on SUN4, EPIX, SUN3, IBMR2 (currently).

354
autologin/main.c Normal file
View File

@ -0,0 +1,354 @@
/*
* machine generated cmd line parser
* built by mkcmd version 7.6 Gamma
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
extern int errno;
extern char *malloc(), *calloc(), *realloc();
#define ENVOPT 0
#define GETARG 0
#define GETOPT 1
/* from std_help.m */
/* from std_version.m */
/* from autologin.m */
/* $Id: T.c,v 7.2 94/07/11 00:42:06 ksb Exp $
* literal text included from a tempate
* based on Keith Bostic's getopt in comp.sources.unix volume1
* modified for mkcmd use.... by ksb@cc.purdue.edu (Kevin Braunsdorf)
*/
#if GETOPT || GETARG
/* IBMR2 (AIX in the real world) defines
* optind and optarg in <stdlib.h> and confuses the hell out
* of the C compiler. So we use those externs. I guess we will
* have to stop using the old names. -- ksb
*/
#ifdef _AIX
#include <stdlib.h>
#else
static int
optind = 1; /* index into parent argv vector */
static char
*optarg; /* argument associated with option */
#endif
#endif /* only if we use them */
#if ENVOPT
/* breakargs - break a string into a string vector for execv.
*
* Note, when done with the vector, merely "free" the vector.
* Written by Stephen Uitti, PUCC, Nov '85 for the new version
* of "popen" - "nshpopen", that doesn't use a shell.
* (used here for the as filters, a newer option).
*
* breakargs is copyright (C) Purdue University, 1985
*
* Permission is hereby given for its free reproduction and
* modification for All purposes.
* This notice and all embedded copyright notices be retained.
*/
/* this trys to emulate shell quoting, but I doubt it does a good job (ksb)
* [[ but not substitution -- that would be silly ]]
*/
static char *
u_mynext(u_pcScan, u_pcDest)
register char *u_pcScan, *u_pcDest;
{
register int u_fQuote;
for (u_fQuote = 0; *u_pcScan != '\000' && (u_fQuote||(*u_pcScan != ' ' && *u_pcScan != '\t')); ++u_pcScan) {
switch (u_fQuote) {
default:
case 0:
if ('"' == *u_pcScan) {
u_fQuote = 1;
continue;
} else if ('\'' == *u_pcScan) {
u_fQuote = 2;
continue;
}
break;
case 1:
if ('"' == *u_pcScan) {
u_fQuote = 0;
continue;
}
break;
case 2:
if ('\'' == *u_pcScan) {
u_fQuote = 0;
continue;
}
break;
}
if ((char*)0 != u_pcDest) {
*u_pcDest++ = *u_pcScan;
}
}
if ((char*)0 != u_pcDest) {
*u_pcDest = '\000';
}
return u_pcScan;
}
/* given an envirionment variable insert it in the option list (ksb)
* (exploded with the above routine)
*/
static int
u_envopt(cmd, pargc, pargv)
char *cmd, *(**pargv);
int *pargc;
{
register char *p; /* tmp */
register char **v; /* vector of commands returned */
register unsigned sum; /* bytes for malloc */
register int i, j; /* number of args */
register char *s; /* save old position */
while (*cmd == ' ' || *cmd == '\t')
cmd++;
p = cmd; /* no leading spaces */
i = 1 + *pargc;
sum = sizeof(char *) * i;
while (*p != '\000') { /* space for argv[]; */
++i;
s = p;
p = u_mynext(p, (char *)0);
sum += sizeof(char *) + 1 + (unsigned)(p - s);
while (*p == ' ' || *p == '\t')
p++;
}
++i;
/* vector starts at v, copy of string follows NULL pointer
* the extra 7 bytes on the end allow use to be alligned
*/
v = (char **)malloc(sum+sizeof(char *)+7);
if (v == NULL)
return 0;
p = (char *)v + i * sizeof(char *); /* after NULL pointer */
i = 0; /* word count, vector index */
v[i++] = (*pargv)[0];
while (*cmd != '\000') {
v[i++] = p;
cmd = u_mynext(cmd, p);
p += strlen(p)+1;
while (*cmd == ' ' || *cmd == '\t')
++cmd;
}
for (j = 1; j < *pargc; ++j)
v[i++] = (*pargv)[j];
v[i] = NULL;
*pargv = v;
*pargc = i;
return i;
}
#endif /* u_envopt called */
#if GETARG
/*
* return each non-option argument one at a time, EOF for end of list
*/
static int
u_getarg(nargc, nargv)
int nargc;
char **nargv;
{
if (nargc <= optind) {
optarg = (char *) 0;
return EOF;
}
optarg = nargv[optind++];
return 0;
}
#endif /* u_getarg called */
#if GETOPT
static int
optopt; /* character checked for validity */
/* get option letter from argument vector, also does -number correctly
* for nice, xargs, and stuff (these extras by ksb)
* does +arg if you give a last argument of "+", else give (char *)0
*/
static int
u_getopt(nargc, nargv, ostr, estr)
int nargc;
char **nargv, *ostr, *estr;
{
register char *oli; /* option letter list index */
static char EMSG[] = ""; /* just a null place */
static char *place = EMSG; /* option letter processing */
if ('\000' == *place) { /* update scanning pointer */
if (optind >= nargc)
return EOF;
if (nargv[optind][0] != '-') {
register int iLen;
if ((char *)0 != estr && 0 == strncmp(estr, nargv[optind], iLen = strlen(estr))) {
optarg = nargv[optind++]+iLen;
return '+';
}
return EOF;
}
place = nargv[optind];
if ('\000' == *++place) /* "-" (stdin) */
return EOF;
if (*place == '-' && '\000' == place[1]) {
/* found "--" */
++optind;
return EOF;
}
} /* option letter okay? */
/* if we find the letter, (not a `:')
* or a digit to match a # in the list
*/
if ((optopt = *place++) == ':' ||
((char *)0 == (oli = strchr(ostr,optopt)) &&
(!(isdigit(optopt)||'-'==optopt) || (char *)0 == (oli = strchr(ostr, '#'))))) {
if(!*place) ++optind;
return('?');
}
if ('#' == *oli) { /* accept as -digits */
optarg = place -1;
++optind;
place = EMSG;
return '#';
}
if (*++oli != ':') { /* don't need argument */
optarg = NULL;
if ('\000' == *place)
++optind;
} else { /* need an argument */
if (*place) { /* no white space */
optarg = place;
} else if (nargc <= ++optind) { /* no arg!! */
place = EMSG;
return '*';
} else {
optarg = nargv[optind]; /* white space */
}
place = EMSG;
++optind;
}
return optopt; /* dump back option letter */
}
#endif /* u_getopt called */
#undef ENVOPT
#undef GETARG
#undef GETOPT
char
*progname = "$Id$",
*au_terse[] = {
" [-u] [-c cmd] [-e env=value] [-g group] [-l login] [-t tty]",
" -h",
" -V",
(char *)0
},
*u_help[] = {
"c cmd command to run",
"e env=value environment variable to set",
"g group initial group",
"h print this help message",
"l login login name",
"t tty attach to this terminal",
"u do no make utmp entry",
"V show version information",
(char *)0
},
*pcCommand = (char *)0,
*pcGroup = (char *)0,
*pcLogin = (char *)0,
*pcTty = (char *)0;
int
fMakeUtmp = 1,
iErrs = 0;
#ifndef u_terse
#define u_terse (au_terse[0])
#endif
/* from std_help.m */
/* from std_version.m */
/* from autologin.m */
static char *rcsid =
"$Id: autologin.m,v 1.2 92/07/28 13:18:34 ksb Exp $";
/*
* parser
*/
int
main(argc, argv)
int argc;
char **argv;
{
static char
sbOpt[] = "c:e:g:hl:t:uV",
*u_pch = (char *)0;
static int
u_loop = 0;
register int u_curopt;
extern int atoi();
progname = strrchr(argv[0], '/');
if ((char *)0 == progname)
progname = argv[0];
else
++progname;
while (EOF != (u_curopt = u_getopt(argc, argv, sbOpt, (char *)0))) {
switch (u_curopt) {
case '*':
fprintf(stderr, "%s: option `-%c\' needs a parameter\n", progname, optopt);
exit(1);
case '?':
fprintf(stderr, "%s: unknown option `-%c\', use `-h\' for help\n", progname, optopt);
exit(1);
case 'c':
pcCommand = optarg;
continue;
case 'e':
if (putenv(optarg) != 0) {
(void) fprintf(stderr, "%s: putenv(\"%s\"): failed\n", progname, optarg);
exit(1);
}
continue;
case 'g':
pcGroup = optarg;
continue;
case 'h':
for (u_loop = 0; (char *)0 != (u_pch = au_terse[u_loop]); ++u_loop) {
if ('\000' == *u_pch) {
fprintf(stdout, "%s: with no parameters\n", progname);
continue;
}
fprintf(stdout, "%s: usage%s\n", progname, u_pch);
}
for (u_loop = 0; (char *)0 != (u_pch = u_help[u_loop]); ++u_loop) {
fprintf(stdout, "%s\n", u_pch);
}
exit(0);
case 'l':
pcLogin = optarg;
continue;
case 't':
pcTty = optarg;
continue;
case 'u':
fMakeUtmp = 0;
continue;
case 'V':
printf("%s: %s\n", progname, rcsid);
exit(0);
}
break;
}
Process();
exit(iErrs);
}

15
autologin/main.h Normal file
View File

@ -0,0 +1,15 @@
/*
* parse options
*/
extern char *progname, *au_terse[4], *u_help[9];
#ifndef u_terse
#define u_terse (au_terse[0])
#endif
extern int main();
extern int fMakeUtmp, iErrs;
extern char *pcCommand, *pcGroup, *pcLogin, *pcTty;
/* from std_help.m */
/* from std_version.m */
/* from autologin.m */

26
conserver.cf/INSTALL Normal file
View File

@ -0,0 +1,26 @@
# $Id: INSTALL,v 4.1 91/06/19 14:20:54 ksb Exp $
Prep:
Start in the conserver directory.
Now read conserver.cf.5l (if you have mk(1L) installed just mk it).
Run:
$ tbl conserver.cf.5l |nroff -man |${PAGER-more}
Now edit dummy.cf and follow the instructions there.
[If you are just shopping stop here.]
Now edit conserver.cf and put your real hosts in there.
Edit the Makefile and change LIB.
Compile:
None.
Install:
Make install.

59
conserver.cf/Makefile Normal file
View File

@ -0,0 +1,59 @@
# $Id: Make.host,v 4.3 92/07/10 15:57:32 dru Exp $
#
# Makefile for conserver data base
#
# if you edit LIB below you have to change cons.hs default config define.
PROG= conserver.cf
LIB= ${DESTDIR}/usr/local/lib
DOC= ${DESTDIR}/usr/man
SRCs= conserver.cf
MAN= conserver.cf.5l
OTHER= README
SOURCE= Makefile ${OTHER} ${MAN} ${SRCl} ${SRCs}
all: ${SRCl} ${PROG}
${PROG}: ${SRCs}
clean: FRC
rm -f Makefile.bak a.out core errs lint.out tags
deinstall: ${MAN} ${DOC} FRC
install -R ${LIB}/${PROG}
mkcat -r${DOC} -D ${MAN}
depend: FRC
dirs: ${LIB} ${DOC}
install: all dirs FRC
install -c ${PROG} ${LIB}/${PROG}
lint: FRC
mkcat: ${MAN} ${DOC} FRC
mkcat -r${DOC} ${MAN}
print: source FRC
lpr -J"${PROG} source" ${SOURCE}
source: ${SOURCE}
spotless: clean
rcsclean ${SOURCE}
tags: FRC
/ ${LIB} ${LIB}:
install -dr $@
${SOURCE}:
co -q $@
FRC:
# DO NOT DELETE THIS LINE - make depend DEPENDS ON IT
# *** Do not add anything here - It will go away. ***

16
conserver.cf/README Normal file
View File

@ -0,0 +1,16 @@
# $Id: README,v 4.1 91/06/19 14:21:06 ksb Exp $
This configuration file has been extended from the Ohio State version. We
allow parity and baud to be set, as well as more than one console server
machine to be in play at a time. We have too many console servers to use
just a single Sun3... :-).
We also allow another section for trusted hosts. We allow our operators root
access by physical access to a workstation.
--
"So I try to say `Goodbye, my friend.'
I'd like to leave you with something more..."
kayessbee, Kevin Braunsdorf, ksb@cc.purdue.edu, pur-ee!ksb, purdue!ksb

76
conserver.cf/conserver.cf Normal file
View File

@ -0,0 +1,76 @@
# conserver config file
#
# $Id: conserver.cf,v 4.20 94/05/22 11:17:26 ksb Exp $
#
# list of consoles we serve
# name : tty[@host] : baud[parity] : device : group
# our local console
console:|@console.cc.purdue.edu:9600p:/usr/adm/consoles/console:0
nextwatch:|@console.cc.purdue.edu:9600p:/usr/adm/consoles/nextwatch:0
# real machine
speedy:/dev/ttyC12@console.cc.purdue.edu:9600s:/usr/adm/consoles/speedy:1
nis35:/dev/ttyC13@console.cc.purdue.edu:9600s:/usr/adm/consoles/nis35:1
sun3watch:/dev/ttyC40@console.cc.purdue.edu:9600p:/usr/adm/consoles/sun3watch:1
keep:/dev/ttyC29@console.cc.purdue.edu:9600s:/usr/adm/consoles/keep:1
dart:/dev/ttyC32@console.cc.purdue.edu:9600s:/usr/adm/consoles/dart:1
lively:/dev/ttyC10@console.cc.purdue.edu:9600s:/usr/adm/consoles/lively:2
sentinel:/dev/ttyC11@console.cc.purdue.edu:9600s:/usr/adm/consoles/sentinel:2
ipscgate:/dev/ttyC26@console.cc.purdue.edu:9600e:/usr/adm/consoles/ipscgate:2
snap.stat:/dev/ttyC27@console.cc.purdue.edu:9600s:/usr/adm/consoles/snap.stat:2
b.stat:/dev/ttyC33@console.cc.purdue.edu:9600s:/usr/adm/consoles/b.stat:2
expert:/dev/ttyC14@console.cc.purdue.edu:9600e:/usr/adm/consoles/expert:3
quick:/dev/ttyC15@console.cc.purdue.edu:9600s:/usr/adm/consoles/quick:3
helios:/dev/ttyC31@console.cc.purdue.edu:9600s:/usr/adm/consoles/helios:3
probe:/dev/ttyC34@console.cc.purdue.edu:9600s:/usr/adm/consoles/probe:3
mace:/dev/ttyC8@console.cc.purdue.edu:4800s:/usr/adm/consoles/mace:4
sage:/dev/ttyC9@console.cc.purdue.edu:9600e:/usr/adm/consoles/sage:4
flash:/dev/ttyC24@console.cc.purdue.edu:9600s:/usr/adm/consoles/flash:4
labwatch:/dev/ttyC25@console.cc.purdue.edu:9600s:/usr/adm/consoles/labwatch:4
dash:/dev/ttyC35@console.cc.purdue.edu:9600s:/usr/adm/consoles/dash:4
icd92:/dev/ttyC4@console.cc.purdue.edu:9600s:/usr/adm/consoles/icd92:5
pop.stat:/dev/ttyC5@console.cc.purdue.edu:9600s:/usr/adm/consoles/pop.stat:5
icd94:/dev/ttyC20@console.cc.purdue.edu:9600s:/usr/adm/consoles/icd94:5
oasis:/dev/ttyC21@console.cc.purdue.edu:9600s:/usr/adm/consoles/oasis:5
deft:/dev/ttyC36@console.cc.purdue.edu:9600s:/usr/adm/consoles/deft:5
mentor:/dev/ttyC2@console.cc.purdue.edu:9600e:/usr/adm/consoles/mentor:6
icd84:/dev/ttyC3@console.cc.purdue.edu:9600s:/usr/adm/consoles/icd84:6
franklin:/dev/ttyC18@console.cc.purdue.edu:9600s:/usr/adm/consoles/franklin:6
icd82:/dev/ttyC19@console.cc.purdue.edu:9600s:/usr/adm/consoles/icd82:6
prism:/dev/ttyC38@console.cc.purdue.edu:9600s:/usr/adm/consoles/prism:6
rapid:/dev/ttyC6@console.cc.purdue.edu:9600s:/usr/adm/consoles/rapid:7
tyro:/dev/ttyC7@console.cc.purdue.edu:9600e:/usr/adm/consoles/tyro:7
staff:/dev/ttyC22@console.cc.purdue.edu:9600s:/usr/adm/consoles/staff:7
swift:/dev/ttyC23@console.cc.purdue.edu:9600s:/usr/adm/consoles/swift:7
quest:/dev/ttyC37@console.cc.purdue.edu:9600s:/usr/adm/consoles/quest:7
icd96:/dev/ttyC0@console.cc.purdue.edu:9600s:/usr/adm/consoles/icd96:8
fleet:/dev/ttyC1@console.cc.purdue.edu:9600s:/usr/adm/consoles/fleet:8
feserve:/dev/ttyC16@console.cc.purdue.edu:9600s:/usr/adm/consoles/feserve:8
curator:/dev/ttyC17@console.cc.purdue.edu:9600s:/usr/adm/consoles/curator:8
soltest:/dev/ttyC39@console.cc.purdue.edu:9600s:/usr/adm/consoles/soltest:8
mozo:/dev/ttyC41@console.cc.purdue.edu:9600s:/usr/adm/consoles/mozo:9
notus:/dev/ttyC42@console.cc.purdue.edu:9600s:/usr/adm/consoles/notus:
eurus:/dev/ttyC43@console.cc.purdue.edu:9600s:/usr/adm/consoles/eurus:
boreas:/dev/ttyC44@console.cc.purdue.edu:9600s:/usr/adm/consoles/boreas:
zephyrus:/dev/ttyC45@console.cc.purdue.edu:9600s:/usr/adm/consoles/zephyrus:
fegrader:/dev/ttyC46@console.cc.purdue.edu:9600s:/usr/adm/consoles/fegrader:
galaxy:/dev/ttyC47@console.cc.purdue.edu:9600s:/usr/adm/consoles/galaxy:
# ups monitor connection (ksb -- testing)
ups:/dev/ttyb@console.cc.purdue.edu:9600e:/usr/adm/consoles/ups:10
# VM Group consoles
tag:/dev/ttyC30@console.cc.purdue.edu:9600s:/usr/adm/consoles/tag:11:R85ONdmDqSwQ6
# All remote consoles
# on staff.cc.purdue.edu
extra:/dev/ttyb@staff.cc.purdue.edu:9600s:/usr/adm/extra.log:0
vet:/dev/tty0d@staff.cc.purdue.edu:9600s:/usr/adm/vet.log:1:5m6N/RqJcay6I
bull:/dev/tty0e@staff.cc.purdue.edu:9600s:/usr/adm/bull.log:
serval:/dev/tty0f@staff.cc.purdue.edu:9600s:/usr/adm/serval.log:
# virtual consoles on remote hosts
tbtape:|su - informix@oasis.cc.purdue.edu:9600p:/usr/adm/tbtape.log:0
# so we can write on mace.cc
wmace:|/bin/csh -i@mace.cc.purdue.edu:9600p:/usr/adm/mace.log:0
%%
# list of clients we allow
# type machines
trusted: console.cc.purdue.edu
allowed: cc.purdue.edu stat.purdue.edu
allowed: 128.210.10.8 128.210.33.1 128.210.7.49 127.0.0.1

View File

@ -0,0 +1,96 @@
.\" $Id: conserver.cf.5l,v 1.4 93/02/11 13:06:32 ksb Exp $
.\" @(#)constab.5 01/06/91 OSU CIS; Thomas A. Fine
.TH CONSERVER.CF 5L "15 February 1991" "OSU/CIS"
.SH NAME
conserver.cf \- table of server console terminals used by conserver(8L)
.SH SYNOPSIS
.B /usr/local/lib/conserver.cf
.br
\fIaccess hosts\fP
.br
\fB%%\fP
.br
\fIserver\fP:\fIdevice\fP:\fIbaud\fP:\fIlogfile\fP:\fIgroup\fP
.SH DESCRIPTION
.B Conserver.cf
is the configuration file for
.IR conserver (8L).
All lines starting with the pound sign `#' are considered comment lines.
Blank lines are ignored.
.PP
The first section of the file has lines that are separated into
six colon-separated fields:
.PP
\fIServer\fP name - this doesn't have to be the name of the server;
it is used to refer to the server when using the console program.
.PP
\fIDevice\fP file name - the full path name of the device for this server.
This may contain a remote host name as \fItty\fP@\fIhost\fP in which case
the conserver will send connections for this server to \fIhost\fP.
.PP
\fIBaud\fP is the speed and parity for this console.
Speed may be given as an integer,
parity only requires the first letter of any of: even, odd, mark, space.
.PP
\fILog\fP file name - the full path name of file where all output from
this server is logged.
.PP
\fIGroup\fP number - defines which group of servers this server is with. There
will be one process running for each group of servers in this file.
If this field is empty the conserver program will fill groups automatically.
.PP
\fIPassword\fP encrypted password - allows access to any member console in
this group. That is to say only one console in any group should set a
password. If none set a password the superuser password is taken.
.PP
This section is terminated with a `%%' token on a line by itself.
.PP
The next section of the file contains a list of hosts and addresses
which are allowed to connect to the console server.
Three levels of access all allowed, ``trust'', ``allow'',
and ``refuse''.
The access modifier is followed by a colon and a list of addresses or
host names.
Any complete suffix of a host name my be used to allow access for all hosts
in that subdomain.
For example `cc.purdue.edu' will allow `mentor.cc.purdue.edu'
and `mace.cc.purdue.edu', but not `pucc.purdue.edu' or `hack.purdue.edu'.
.SH LIMITS
.PP
Groups should be numbered from 0, all members of a group should be contiguous
in the file.
The current hard limits are 20 groups, with 10 members per group.
.SH EXAMPLE
# server:/dev/file:baud:/usr/adm/logfile:group_num
.br
tree:/dev/ttyj0:9600e:/tmp/treelog:0
.br
fish:/dev/ttyj1:4800e:/tmp/fishlog:1
.br
bird:/dev/ttyj2:4800m:/tmp/birdlog:1
.br
solar:/dev/ttyj3:9600e:/tmp/solarlog:2
.br
stellar:/dev/ttyj4:9600e:/tmp/stellarlog:
.br
shell:/dev/ttyj5:1200e:/tmp/shelllog:3:NLKyxm2KjHrzE
.br
tribe:/dev/ttyj6:1200e:/tmp/tribelog:4
.br
reptile:/dev/ttyj7:1200e:/tmp/reptilelog:
.br
flower:/dev/ttyj8:1200e:/tmp/flowerlog:
.br
mentor:/dev/ttyh0@extra.cc.purdue.edu:2400e:/tmp/mentor.log:
%%
.br
# access restrictions
.br
trusted: console.cc.purdue.edu 128.210.7.90
.br
allow: cc.purdue.edu stat.cc.purdue.edu
.sp
Notice that the console `shell' has a special password, all the others
use the superuser's password.
.SH "SEE ALSO"
console(1L), conserver(8L)

22
conserver.cf/dummy.cf Normal file
View File

@ -0,0 +1,22 @@
# dummy conserver config file
#
# $Id: dummy.cf,v 4.3 92/07/27 12:23:59 ksb Exp $
#
# 1. change the `/dev/ttya' to any tty device you can put a serial device on
# that you could talk to with kermit/cu. Put in the baud rate and parity.
#
# 2. change the `cc.purdue.edu' to your local domain.
#
# 3. !! do not leave this up, as it can give local users a root shell (login)
# !! for extended testing change the `|' to `|su - tst' where tst is a
# !! vanilla test acount, or comment out the `login' console.
#
# list of consoles we serve
# name : tty[@host] : baud[parity] : device : group
dumb:/dev/ttya:9600p:/tmp/dummy.log:1
login:|:9600p:/tmp/login.log:1
%%
# list of clients we allow
# type machines
trusted: 127.0.0.1
allowed: cc.purdue.edu

188
conserver.cf/label.ps Normal file
View File

@ -0,0 +1,188 @@
%!PS-Adobe-2.0 EPSF-1.2
%%$Id: label.ps,v 1.8 94/01/21 09:37:42 ksb Exp $
%%Title: RJ-11
%%Creator: A Braunsdorf
%%CreationDate:
%%For: ab
%%BoundingBox: 0 0 243 148.5
%%EndComments
% Add new hosts in the parens that match the port number
/hosts
[
(icd96) % C0
(fleet)
(mentor)
(icd84)
(icd92) % C4
(pop.stat)
(rapid)
(tyro)
(mace) % C8
(sage)
(lively)
(sentinel)
(speedy) % C12
(nis35)
(expert)
(quick)
(feserve) % C16
(curator)
(franklin)
(icd82)
(icd94) % C20
(oasis)
(staff)
(swift)
(flash) % C24
(labwatch)
(ipscgate)
(snap.stat)
(_28) % C28
(keep)
(tag)
(assist)
] def
% The relative co-ords of the various RJ11 jacks
/coords
[
% j# x y jack number, +x, +y
[ 13 0.5 1.25 ]
[ 11 1.0 1.25 ]
[ 8 1.5 1.25 ]
[ 14 0.5 0.625 ]
[ 10 1.0 0.625 ]
[ 9 1.5 0.625 ]
[ 15 0.5 0 ]
[ 12 1.0 0 ]
[ 7 2.1875 1.25 ]
[ 5 2.6875 1.25 ]
[ 3 3.1875 1.25 ]
[ 6 2.1875 0.625 ]
[ 4 2.6875 0.625 ]
[ 0 3.1875 0.625 ]
[ 2 2.6875 0 ]
[ 1 3.1875 0 ]
] def
/str 20 string def
% how to build an RJ11 connector diagram
/rj11
{
gsave
1 150 div setlinewidth
0 0 moveto
1 2 div 0 lineto
0 1 2 div rlineto
1 2 div neg 0 rlineto
closepath
stroke
1 16 div 1 8 div moveto
0 1 4 div rlineto
1 16 div 0 rlineto
0 1 16 div rlineto
3 16 div 0 rlineto
0 2 32 div neg rlineto
1 16 div 0 rlineto
0 1 16 div neg rlineto
1 16 div 0 rlineto
0 2 16 div neg rlineto
1 16 div neg 0 rlineto
0 1 16 div neg rlineto
1 16 div neg 0 rlineto
0 1 16 div neg rlineto
3 16 div neg 0 rlineto
0 1 16 div rlineto
closepath
stroke
0 1 7
{
36 div 9 64 div add 1 16 div exch moveto
0 1 72 div rlineto
1 72 div 0 rlineto
0 1 72 div neg rlineto
closepath
fill
} for
grestore
/Courier findfont 1.5 8 div scalefont setfont
2 16 div 3 16 div moveto
str cvs
dup length 1 eq { ( )show } if show
} def
% Page layout stuff
72 72 scale
-90 rotate
-11 0 translate
/jack 28 def
/fudge 1 32 div def
/Courier findfont 10 72 div scalefont
setfont
0 setlinewidth
% label the lines on the left
1 1 8
{
9 div 6 mul 0.25 exch moveto
gsave fudge dup rmoveto jack str cvs show ( ) show hosts jack
get show grestore
/jack jack 1 add def
gsave 15 16 div 0 rlineto stroke grestore
1 0 rmoveto
gsave fudge dup rmoveto jack str cvs show ( ) show hosts jack
get show grestore
/jack jack 1 add def
gsave 15 16 div 0 rlineto stroke grestore
1 0 rmoveto
gsave fudge dup rmoveto jack str cvs show ( ) show hosts jack
get show grestore
/jack jack 1 add def
gsave 15 16 div 0 rlineto stroke grestore
1 0 rmoveto
gsave fudge dup rmoveto jack str cvs show ( ) show hosts jack
get show grestore
/jack jack 1 add def
gsave 15 16 div 0 rlineto stroke grestore
1 0 rmoveto
/jack jack 8 sub def
} for
% Diddle the page and layout the RJ11s
4.5 0.75 translate
9 8 div dup scale
0 1 coords length 1 sub
{
gsave
coords exch get
aload pop
translate
rj11
grestore
} for
0 1 coords length 1 sub
{
gsave
coords exch get
aload pop
2.5 add % for the second back up 2.5 inches
translate
16 add rj11 % ... add 16 to the RJ11 number
grestore
} for
showpage

23
conserver.cf/test.cf Normal file
View File

@ -0,0 +1,23 @@
# dummy conserver config file
#
# $Id: dummy.cf,v 4.3 92/07/27 12:23:59 ksb Exp $
#
# 1. change the `/dev/ttya' to any tty device you can put a serial device on
# that you could talk to with kermit/cu. Put in the baud rate and parity.
#
# 2. change the `cc.purdue.edu' to your local domain.
#
# 3. !! do not leave this up, as it can give local users a root shell (login)
# !! for extended testing change the `|' to `|su - tst' where tst is a
# !! vanilla test acount, or comment out the `login' console.
#
# list of consoles we serve
# name : tty[@host] : baud[parity] : device : group
DOMAINHACK=
LOGDIR=/tmp
login3:|:9600p:&:10m
test:!ts4:10002:&:1m
%%
# list of clients we allow
# type machines
allowed: 127.0.0.1

114
conserver/INSTALL Normal file
View File

@ -0,0 +1,114 @@
# $Id: INSTALL,v 4.4 94/07/19 14:48:29 ksb Exp $
#
# lpr this file, you need to read it with other stuff on the screen.
#
Basic installation:
First off, this stuff isn't guaranteed to work, or compile or anything.
Second, the Makefile doesn't even really do that much, because most people
with large networks don't have very normal configurations (that's a lot like
an excuse :-). Third, I assume you have the hardware set up done, and don't
need any help there (just use normal serial lines, or see Sun-serial).
With that out of the way, let's get started.
Prep:
If you are a serious kinda guy you will want to add the console service to
/etc/services, here is the line we use:
console 782/tcp conserver # console server
Otherwise you'll have to hard code a PORT in cons.h (there are a comments
at the apropos points.
If you do not have the PUCC ptyd daemon (and I'll bet you don't) you have
to edit the Makefile, look at the block that sets HAVE_PTYD.
Later, on the console server you will have to add a line to /etc/rc.local,
or an atboot/cronboot job to start the console server
nice --4 /usr/local/etc/conserver >/dev/console 2>&1 </dev/null &
[we run it from roots .profile on an auto-login port.]
Compiling:
Save a copy of cons.h and edit the one in this directory to your desires.
It should be self-explanatory.
Edit Makefile, setting BIN and PROG.
Type "make". This compiles the server. If you fail on `XTABS' in
group.c either change XTABS to TAB3 or #if 0 the block. I've not
had time to track this down.
cd ../conserver.cf and follow the INSTALL there. (Then come back here.)
cd ../console and follow INSTALL there. (Then come back here.)
If you changed from using /usr/local/{bin,etc} you may want to change the
"FILES" section in the man page "conserver.8L".
If everything went well, type "make install" in each directory. You will
probably need to run this as root, depending on where you're putting stuff.
This only installs things on the local machine (unless you have a kinky
system configuration). You will have to distribute at least the client
program to your other machines. {Compile on unlike CPU types, of course.}
How did we do?
Now run:
conserver -V
You should get something like:
conserver: $Id: INSTALL,v 4.4 94/07/19 14:48:29 ksb Exp $
conserver: default access type `r'
conserver: default escape sequence `\005\143'
conserver: configuration in `/usr/local/lib/conserver.cf'
conserver: limited to 20 groups with 10 members
conserver: service name `conserver'
Testing the console server:
To test it (us the dummy config you build in ../conserver.cf) run
# conserver -C ../conserve.cf/dummy.cf -v &
You should get an output that looks like:
conserver: 1: dumb is on /dev/ttya (9600e) logged to /tmp/dummy.log
conserver: group 1 on port 1270
conserver: access type 't' for "127.0.0.1"
conserver: access type 'a' for "cc.purdue.edu"
In another login window (or this one, I guess)
$ console -vA dumb
You should get an output like this:
console: attach to dumb (on localhost)
conserver: dumb: login root@nostromo.cc.purdue.edu
Enter `^Ec?' for help.
[ok, attached]
[replay]
You can type to your device now, and it should answer you. Use
^Ec? for help and ^Ec. to hangup on it.
If that worked...
You can check over the real conserver.cf and start a real console server.
You are set.
Details/limits/bugs:
The log files grow without bound. Move the log files to OLD (with PUCC
install) and HUP the conserver process to get him to re-open the log files.
Here is the install cmd we use:
install -cq /dev/null /usr/adm/his.console
You might wanna start stamper with the console server, but it doesn't
re-open log files -- some later version of the console server will assume
stampers job.

109
conserver/Makefile Normal file
View File

@ -0,0 +1,109 @@
# $Id: Makefile,v 1.3 1998-11-17 23:45:05-08 bryan Exp $
#
# Makefile for console server
#
# two steps (1) and (2)
# (1) change ETC below to where you would like the console server installed
# I would not change the name, you have to much with the docs then...
PROG= conserver
ETC= ${DESTDIR}/usr/local/etc
DOC= ${DESTDIR}/usr/local/man
# if we have to PUCC ptyd daemon we can use it to get ptys, else use fallback.o
# and change the CDEFS line below to =0
FALLBACK=fallback.o
PUCCLIB=
#FALLBACK=
#PUCCLIB=-lpucc
I=/usr/include
S=/usr/include/sys
L=/usr/local/include
P=
INCLUDE=
DEBUG=-O
CDEFS= -DSUN5 -DHAVE_PTYD=0 -DDO_VIRTUAL=1
CFLAGS= ${DEBUG} ${CDEFS} ${INCLUDE}
HDR= cons.h \
access.h client.h consent.h group.h main.h master.h \
readcfg.h
SRC= access.c client.c consent.c group.c main.c master.c \
readcfg.c fallback.c
OBJ= access.o client.o consent.o group.o main.o master.o \
readcfg.o ${FALLBACK}
MAN= conserver.man
OTHER= README Sun-serial
SOURCE= Makefile ${OTHER} ${MAN} ${HDR} ${SRC}
all: ${PROG}
${PROG}:$P ${OBJ}
${CC} -o $@ ${CFLAGS} ${OBJ} ${PUCCLIB} -lsocket -lnsl
clean: FRC
rm -f Makefile.bak ${PROG} a.out *.o core errs lint.out tags
deinstall: ${MAN} ${DOC} FRC
install -R ${ETC}/${PROG}
mkcat -r${DOC} -D ${MAN}
depend: ${HDR} ${SRC} FRC
maketd ${CDEFS} ${INCLUDE} ${SRC}
dirs: ${ETC} ${LIB}
distrib: FRC
distrib -c ${ETC}/${PROG}
install: all dirs FRC
install -c -s ${PROG} ${ETC}/${PROG}
lint: ${HDR} ${SRC} FRC
lint -h ${CDEFS} ${INCLUDE} ${SRC}
mkcat: ${MAN} ${DOC} FRC
mkcat -r${DOC} ${MAN}
print: source FRC
lpr -J"${PROG} source" ${SOURCE}
source: ${SOURCE}
spotless: clean
rcsclean ${SOURCE}
tags: ${HDR} ${SRC}
ctags -t ${HDR} ${SRC}
/ ${ETC} ${LIB}:
install -dr $@
${SOURCE}:
co -q $@
FRC:
# DO NOT DELETE THIS LINE - maketd DEPENDS ON IT
access.o: access.c access.h client.h cons.h consent.h group.h main.h readcfg.h
client.o: client.c client.h cons.h consent.h
consent.o: client.h cons.h consent.c consent.h main.h
group.o: access.h client.h cons.h consent.h group.c group.h main.h version.h
main.o: access.h client.h cons.h consent.h group.h main.c master.h readcfg.h version.h
master.o: access.h client.h cons.h consent.h group.h main.h master.c master.h \
readcfg.h version.h
readcfg.o: access.h client.h cons.h consent.h group.h main.h master.h \
readcfg.c readcfg.h
fallback.o: fallback.c
# *** Do not add anything here - It will go away. ***

73
conserver/README Normal file
View File

@ -0,0 +1,73 @@
# $Id: README,v 4.1 91/06/19 15:23:03 ksb Exp $
#
The general idea...
The idea is you have a big network. You have several machines whose consoles
you want to access remotely. You connect the console lines of these machines
to serial ports on another machine, which runs the server half of this
software. Then you can use the client program to get at the consoles from
anywhere in the network. It also provides log file of the consoles and
an operator stream.
Who will help me?
Send questions, comments, and bug reports to:
ksb@cc.purdue.edu (Kevin S Braunsdorf)
fine@cis.ohio-state.edu (Tom Fine)
Permissions needed to run this?
The console server does not need to be run as root. As long as it
has permission to write to all the log files, any id will be fine.
Keep in mind, though, that log files occasionally end up with
sensitive data in them (like root passwords when people don't watch
for the pasword prompt).
Console server process management.
The conserver (usually) ends up running several process: one master and
several children. Each of the children is responsible for some of the
consoles. Occasionally, we've had problems with one of the children becoming
"stuck" in one sense or another. To make dealing with this easier here
is the plan:
1. If you need to restart everything, run
console -q
which will terminate the console server on all master hosts.
2. If you need to restart on one host, killing the master process (on
that host) with a SIGTERM (the default for kill) will tell the master
process to kill everything (including itself).
3. If any child dies, the master process will start another one to replace
it. So if you have a process which is "stuck" it is easy to restart.
{Send it a TERM and let conserver respawn it.}
4. If a console is spewing trash use the down (`d') command to make the
server ignore it. Use the reopen (`o') command to restore it to
working order.
5. If all else fails get a real tty on a cart and push it to the poor
machine :-). [Keep one handy -- we don't claim this software is
any better than any other *FREE* product.]
Log file time stamping
We use a simple script like stamper.sh, which we start from rc.local, to
time-stamp the files from all the machines that don't do this already.
Using this script has the advantage over crontab entries that it doesn't
interrupt what is happening on the console, if someone is using it.
Use
stamper /usr/adm/target.console /usr/adm/other.console
to add time stamps to the log file for the `target' and `other' machines.
[ This stamper script will go away someday soon. -- ksb]
--
"When the head an heart of it finally alope!"
kayessbee, Kevin Braunsdorf, ksb@cc.purdue.edu, pur-ee!ksb, purdue!ksb

44
conserver/Sun-serial Normal file
View File

@ -0,0 +1,44 @@
# $Id: Sun-serial,v 2.1 93/02/09 11:45:12 ldv Exp $
If you are going to be hooking Sun consoles to your console server, you
will run into a problem: The sun will halt whenever the cable is unplugged.
It will also halt when the the console server is powered off and on. To
prevent this we modified the wiring of our serial cables at the end that
attaches to the suns.
The server can still be halted by generating a software line break, which
is can be done by sending an escape sequence to the console server.
WE WILL NOT BE HELD RESPONSIBLE FOR ANY DAMAGES CAUSED BY ATTEMPTING A
PARTIAL OR COMPLETE IMPLEMENTATION OF THIS MODIFICATION.
"WE" refers to The Ohio State University and
specifically, the employees of CIS Department of Ohio State.
This is a diagram of the cable we use.
Sun file Console
Server Server
Side Side
2 Tx ------------------------- ------------------------- 2 Tx
\/
/\
3 Rx ------+------------------ ------------------------- 3 Rx
|
Z 4.7K resistor
|
25 -5v ------+ 25 -5v
7 GND ---------------------------------------------------- 7 GND
4 RTS --+ 4 RTS
|
5 CTS --+ 5 CTS
6 DSR --+ 6 DSR
|
20 DTR --+ 20 DTR
I'm not a hardware person, but I think the important part is adding the
resistor. The rest is icing, more or less.

8
conserver/TODO Normal file
View File

@ -0,0 +1,8 @@
# $Id: TODO,v 5.7 92/02/18 09:52:33 ksb Exp $
Just finish some #if's for TERMIO/TERMIOS/V7 ttys.
kayessbee
--
"This may be a new sense of the word `robust' for you."
kayessbee, Kevin Braunsdorf, ksb@cc.purdue.edu, pur-ee!ksb, purdue!ksb

181
conserver/access.c Normal file
View File

@ -0,0 +1,181 @@
/*
* $Id: access.c,v 5.9 1993-05-17 07:36:01-07 ksb Exp $
*
* Copyright 1992 Purdue Research Foundation, West Lafayette, Indiana
* 47907. All rights reserved.
*
* Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb
*
* This software is not subject to any license of the American Telephone
* and Telegraph Company or the Regents of the University of California.
*
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
*
* 1. Neither the authors nor Purdue University are responsible for any
* consequences of the use of this software.
*
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Credit to the authors and Purdue
* University must appear in documentation and sources.
*
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 4. This notice may not be removed or altered.
*/
#ifndef lint
static char copyright[] =
"@(#) Copyright 1992 Purdue Research Foundation.\nAll rights reserved.\n";
#endif
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <pwd.h>
#include "cons.h"
#include "access.h"
#include "consent.h"
#include "client.h"
#include "group.h"
#include "readcfg.h"
#include "main.h"
#if USE_STRINGS
#include <strings.h>
#else
#include <string.h>
#endif
/* in the routines below (the init code) we can bomb if malloc fails (ksb)
*/
void
OutOfMem()
{
static char acNoMem[] = ": out of memory\n";
write(2, progname, strlen(progname));
write(2, acNoMem, sizeof(acNoMem)-1);
exit(45);
}
/* return the access type for a given host entry (ksb)
*/
char
AccType(hp)
struct hostent *hp;
{
register int i;
register unsigned char *puc;
register char *pcName;
auto char acAddr[4*3+2];
register int len;
puc = (unsigned char *)hp->h_addr;
sprintf(acAddr, "%d.%d.%d.%d", puc[0], puc[1], puc[2], puc[3]);
for (i = 0; i < iAccess; ++i) {
if (isdigit(pACList[i].pcwho[0])) {
/* we could allow 128.210.7 to match all on that subnet
* here...
*/
if (0 == strcmp(acAddr, pACList[i].pcwho)) {
return pACList[i].ctrust;
}
continue;
}
pcName = hp->h_name;
len = strlen(pcName);
while (len >= pACList[i].ilen) {
if (0 == strcmp(pcName, pACList[i].pcwho)) {
return pACList[i].ctrust;
}
pcName = strchr(pcName, '.');
if ((char *)0 == pcName) {
break;
}
++pcName;
len = strlen(pcName);
}
}
return chDefAcc;
}
/* we know iAccess == 0, we want to setup a nice default access list (ksb)
*/
void
SetDefAccess(hpLocal)
struct hostent *hpLocal;
{
register char *pcWho, *pcDomain;
register unsigned char *puc;
register int iLen;
pACList = (ACCESS *)calloc(3, sizeof(ACCESS));
if ((ACCESS *)0 == pACList) {
OutOfMem();
}
if ((char *)0 == (pcWho = malloc(4*3+1))) {
OutOfMem();
}
puc = (unsigned char *)hpLocal->h_addr;
sprintf(pcWho, "%d.%d.%d.%d", puc[0], puc[1], puc[2], puc[3]);
pACList[iAccess].ctrust = 'a';
pACList[iAccess].ilen = strlen(pcWho);
pACList[iAccess++].pcwho = pcWho;
if ((char *)0 == (pcDomain = strchr(hpLocal->h_name, '.'))) {
return;
}
++pcDomain;
iLen = strlen(pcDomain);
pcWho = malloc(iLen+1);
pACList[iAccess].ctrust = 'a';
pACList[iAccess].ilen = iLen;
pACList[iAccess++].pcwho = strcpy(pcWho, pcDomain);
}
/* thread ther list of uniq console server machines, aliases for (ksb)
* machines will screw us up
*/
REMOTE *
FindUniq(pRCAll)
register REMOTE *pRCAll;
{
register REMOTE *pRC;
/* INV: tail of the list we are building always contains only
* uniq hosts, or the empty list.
*/
if ((REMOTE *)0 == pRCAll) {
return (REMOTE *)0;
}
pRCAll->pRCuniq = FindUniq(pRCAll->pRCnext);
/* if it is in the returned list of uniq hosts, return that list
* else add us by returning our node
*/
for (pRC = pRCAll->pRCuniq; (REMOTE *)0 != pRC; pRC = pRC->pRCuniq) {
if (0 == strcmp(pRC->rhost, pRCAll->rhost)) {
return pRCAll->pRCuniq;
}
}
return pRCAll;
}

48
conserver/access.h Normal file
View File

@ -0,0 +1,48 @@
/*
* $Id: access.h,v 5.6 1993-02-09 03:53:43-08 ldv Exp $
*
* Copyright 1992 Purdue Research Foundation, West Lafayette, Indiana
* 47907. All rights reserved.
*
* Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb
*
* This software is not subject to any license of the American Telephone
* and Telegraph Company or the Regents of the University of California.
*
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
*
* 1. Neither the authors nor Purdue University are responsible for any
* consequences of the use of this software.
*
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Credit to the authors and Purdue
* University must appear in documentation and sources.
*
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 4. This notice may not be removed or altered.
*/
/*
* keep track of network access and peer console servers (ksb)
*/
typedef struct access {
char ctrust; /* how much do we trust the host */
int ilen; /* length (strlen) of pcwho */
char *pcwho; /* what is the hosts name/ip number */
} ACCESS;
typedef struct remote { /* console at another host */
struct remote *pRCnext; /* next remote console we know about */
struct remote *pRCuniq; /* list of uniq remote servers */
char rserver[32]; /* remote server name */
char rhost[256]; /* remote host to call to get it */
} REMOTE;
extern void OutOfMem();
extern REMOTE *FindUniq();
extern char AccType();
extern void SetDefAccess();

297
conserver/client.c Normal file
View File

@ -0,0 +1,297 @@
/*
* $Id: client.c,v 5.18 1998-11-19 14:32:20-08 bryan Exp $
*
* Copyright 1992 Purdue Research Foundation, West Lafayette, Indiana
* 47907. All rights reserved.
*
* Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb
*
* This software is not subject to any license of the American Telephone
* and Telegraph Company or the Regents of the University of California.
*
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
*
* 1. Neither the authors nor Purdue University are responsible for any
* consequences of the use of this software.
*
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Credit to the authors and Purdue
* University must appear in documentation and sources.
*
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 4. This notice may not be removed or altered.
*/
#ifndef lint
static char copyright[] =
"@(#) Copyright 1992 Purdue Research Foundation.\nAll rights reserved.\n";
#endif
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <pwd.h>
#include "cons.h"
#include "consent.h"
#include "client.h"
#if USE_STRINGS
#include <strings.h>
#else
#include <string.h>
#endif
/* find the next guy who wants to write on the console (ksb)
*/
CLIENT *
FindWrite(pCL)
CLIENT *pCL;
{
/* return the first guy to have the `want write' bit set
* (tell him of the promotion, too) we could look for the
* most recent or some such... I guess it doesn't matter that
* much.
*/
for (/*passed in*/; (CLIENT *)0 != pCL; pCL = pCL->pCLnext) {
if (!pCL->fwantwr)
continue;
if (!pCL->pCEto->fup || pCL->pCEto->fronly)
break;
pCL->fwantwr = 0;
pCL->fwr = 1;
if ( pCL->pCEto->nolog ) {
CSTROUT(pCL->fd, "\r\n[attached (nologging)]\r\n");
} else {
CSTROUT(pCL->fd, "\r\n[attached]\r\n");
}
return pCL;
}
return (CLIENT *)0;
}
#if HAVE_IDENTD
/* use identd to verify a user at a host (ksb)
* we have a list of login@host:passwd:trust after the general host
* limits. We call identd/tap/auth to get info and compare
*/
IdentifyMe(pCL)
CLIENT *pCL;
{
/* ZZZ */
/* we would have to getsockname(fdClient)
* getpeername(fdClient)
* identd_client(addr, addr, acBuffer
* check for identifier in allowed list
* return the permision (modify in pCL)
*/
}
#endif
/* show a character as a string so the user cannot mistake it for (ksb)
* another
*
* must pass us at least 16 characters to put fill with text
*/
char *
FmtCtl(ci, pcIn)
int ci;
char *pcIn;
{
register char *pcOut = pcIn;
unsigned char c;
c = ci & 0xff;
if (c > 127) {
c -= 128;
*pcOut++ = 'M';
*pcOut++ = '-';
}
if (c < ' ' || c == '\177') {
*pcOut++ = '^';
*pcOut++ = c ^ 0100;
*pcOut = '\000';
} else if (c == ' ') {
(void)strcpy(pcOut, "<space>");
} else if (c == '^') {
(void)strcpy(pcOut, "<circumflex>");
} else if (c == '\\') {
(void)strcpy(pcOut, "<backslash>");
} else {
*pcOut++ = c;
*pcOut = '\000';
}
return pcIn;
}
/* replay last iBack lines of the log file upon connect to console (ksb)
*
* NB: we know the console might be spewing when the replay happens,
* we want to just output what is in the log file and get out,
* so we don't drop chars...
*/
void
Replay(fdLog, fdOut, iBack)
int fdLog, fdOut, iBack;
{
register int tot, nCr;
register char *pc;
register off_t where;
auto char bf[MAXREPLAY+2];
auto struct stat stLog;
if (-1 == fdLog) {
CSTROUT(fdOut, "[no log file on this console]\r\n");
return;
}
/* find the size of the file
*/
if (0 != fstat(fdLog, & stLog)) {
return;
}
if (MAXREPLAY > stLog.st_size) {
where = 0L;
} else {
where = stLog.st_size - MAXREPLAY;
}
#if defined(SEEK_SET)
/* PTX and maybe other Posix systems
*/
if (lseek(fdLog, where, SEEK_SET) < 0) {
return;
}
#else
if (lseek(fdLog, where, L_SET) < 0) {
return;
}
#endif
if ((tot = read(fdLog, bf, MAXREPLAY)) <= 0) {
return;
}
bf[tot] = '@';
pc = & bf[tot];
nCr = 0;
while (--pc != bf) {
if ('\n' == *pc && iBack == nCr++) {
++pc; /* get rid of a blank line */
break;
}
}
(void)write(fdOut, pc, tot-(pc - bf));
}
/* these bit tell us which parts of the Truth to tell the client (ksb)
*/
#define WHEN_SPY 0x01
#define WHEN_ATTACH 0x02
#define WHEN_VT100 0x04
#define WHEN_EXPERT 0x08 /* ZZZ no way to set his yet */
#define WHEN_ALWAYS 0x40
#define HALFLINE 40
typedef struct HLnode {
int iwhen;
char actext[HALFLINE];
} HELP;
static HELP aHLTable[] = {
{ WHEN_ALWAYS, ". disconnect"},
{ WHEN_ALWAYS, "a attach read/write"},
{ WHEN_ATTACH, "c toggle flow control"},
{ WHEN_ATTACH, "d down a console"},
{ WHEN_ALWAYS, "e change escape sequence"},
{ WHEN_ALWAYS, "f force attach read/write"},
{ WHEN_ALWAYS, "g group info"},
{ WHEN_ATTACH, "L toggle logging on/off"},
{ WHEN_ATTACH, "l1 send break (halt host!)"},
{ WHEN_ALWAYS, "o (re)open the tty and log file"},
{ WHEN_ALWAYS, "p replay the last 60 lines"},
{ WHEN_ALWAYS, "r replay the last 20 lines"},
{ WHEN_ATTACH, "s spy read only"},
{ WHEN_ALWAYS, "u show host status"},
{ WHEN_ALWAYS, "v show version info"},
{ WHEN_ALWAYS, "w who is on this console"},
{ WHEN_ALWAYS, "x show console baud info"},
{ WHEN_ALWAYS, "z suspend the connection"},
{ WHEN_ALWAYS, "<cr> ignore/abort command"},
{ WHEN_ALWAYS, "? print this message"},
{ WHEN_ALWAYS, "^R short replay"},
{ WHEN_ATTACH, "\\ooo send character by octal code"},
{ WHEN_EXPERT, "^I toggle tab expansion"},
{ WHEN_EXPERT, "; change to another console"},
{ WHEN_EXPERT, "+(-) do (not) drop line"},
{ WHEN_VT100, "PF1 print this message"},
{ WHEN_VT100, "PF2 disconnect"},
{ WHEN_VT100, "PF3 replay the last 20 lines"},
{ WHEN_VT100, "PF4 spy read only"}
};
/* list the commands we know for the user (ksb)
*/
void
HelpUser(pCL)
CLIENT *pCL;
{
register int i, j, iCmp;
static char
acH1[] = "help]\r\n",
acH2[] = "help spy mode]\r\n",
acEoln[] = "\r\n";
auto char acLine[HALFLINE*2+3];
iCmp = WHEN_ALWAYS|WHEN_SPY;
if (pCL->fwr) {
(void)write(pCL->fd, acH1, sizeof(acH1)-1);
iCmp |= WHEN_ATTACH;
} else {
(void)write(pCL->fd, acH2, sizeof(acH2)-1);
}
if ('\033' == pCL->ic[0] && 'O' == pCL->ic[1]) {
iCmp |= WHEN_VT100;
}
acLine[0] = '\000';
for (i = 0; i < sizeof(aHLTable)/sizeof(HELP); ++i) {
if (0 == (aHLTable[i].iwhen & iCmp)) {
continue;
}
if ('\000' == acLine[0]) {
acLine[0] = ' ';
(void)strcpy(acLine+1, aHLTable[i].actext);
continue;
}
for (j = strlen(acLine); j < HALFLINE+1; ++j) {
acLine[j] = ' ';
}
(void)strcpy(acLine+j, aHLTable[i].actext);
(void)strcat(acLine+j, acEoln);
(void)write(pCL->fd, acLine, strlen(acLine));
acLine[0] = '\000';
}
if ('\000' != acLine[0]) {
(void)strcat(acLine, acEoln);
(void)write(pCL->fd, acLine, strlen(acLine));
}
}

72
conserver/client.h Normal file
View File

@ -0,0 +1,72 @@
/*
* $Id: client.h,v 5.10 1998-11-18 00:17:12-08 bryan Exp $
*
* Copyright 1992 Purdue Research Foundation, West Lafayette, Indiana
* 47907. All rights reserved.
*
* Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb
*
* This software is not subject to any license of the American Telephone
* and Telegraph Company or the Regents of the University of California.
*
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
*
* 1. Neither the authors nor Purdue University are responsible for any
* consequences of the use of this software.
*
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Credit to the authors and Purdue
* University must appear in documentation and sources.
*
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 4. This notice may not be removed or altered.
*/
/* states for a server fsm
*/
#define S_NORMAL 0 /* just pass character */
#define S_ESC1 1 /* first escape character received */
#define S_CMD 2 /* second interrupt character received */
#define S_CATTN 3 /* change 1 escape character to next input char */
#define S_CESC 4 /* change 2 escape character to next input char */
#define S_HALT1 5 /* we have a halt sequence in progress */
#define S_SUSP 6 /* we are suspened, first char wakes us up */
#define S_IDENT 7 /* probational connection (who is this) */
#define S_HOST 8 /* still needs a host name to connect */
#define S_PASSWD 9 /* still needs a passwd to connect */
#define S_QUOTE 10 /* send any character we can spell */
typedef struct client { /* Connection Information: */
int fd; /* file descriptor */
short fcon; /* currently connect or not */
short fwr; /* (client) write enable flag */
short fwantwr; /* (client) wants to write */
short fecho; /* echo commands (not set by machines) */
char acid[128]; /* login and location of client */
long tym; /* time of connect */
long typetym; /* time of last keystroke */
char actym[32]; /* pre-formatted time */
struct consent
*pCEwant, /* what machine we would like to be on */
*pCEto; /* host a client gets output from */
struct client
**ppCLbscan, /* back link for scan ptr */
*pCLscan, /* next client fd to scan after select */
**ppCLbnext, /* back link for next ptr */
*pCLnext; /* next person on this list */
char ic[2]; /* two character escape sequence */
char iState; /* state for fsm in server */
char caccess; /* did we trust the remote machine */
char accmd[MAXSERVLEN+1];/* the command the user issued */
int icursor; /* the length of the command issused */
struct sockaddr_in
cnct_port; /* where from */
} CLIENT;
extern char *FmtCtl();
extern void Replay();
extern void HelpUser();
extern CLIENT *FindWrite();

350
conserver/cons-gnac.h Normal file
View File

@ -0,0 +1,350 @@
/*
* $Id: cons-gnac.h,v 5.38 1998-11-17 18:43:39-08 bryan Exp $
*
* Copyright 1992 Purdue Research Foundation, West Lafayette, Indiana
* 47907. All rights reserved.
*
* Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb
*
* This software is not subject to any license of the American Telephone
* and Telegraph Company or the Regents of the University of California.
*
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
*
* 1. Neither the authors nor Purdue University are responsible for any
* consequences of the use of this software.
*
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Credit to the authors and Purdue
* University must appear in documentation and sources.
*
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 4. This notice may not be removed or altered.
*/
/*
* this is the configuration file for the Ohio State/PUCC console
* server. Just define the macros below to somehting that looks good
* and give it a go. It'll complain (under conserver -V) if things
* look really bad.
*
* all PTX, PTX2, and PTX4 code added by gregf@sequent.com (gregf)
*/
/* #define IBMR2 1 /**/
/* #define HPUX7 1 /**/
/* #define SUN4 1 /**/
/* #define SUN5 1 /**/
/* #define PTX2 1 /* DYNIX/ptx v2.X */
/* #define PTX4 1 /* DYNIX/ptx v4.0 */
#if (defined(PTX2) || defined(PTX4))
#define PTX
#endif
/* some machine specific details
*/
#if !defined(USE_OLDSEL)
#if defined(IBMR2)
#include <sys/select.h>
#endif
#endif
#if !defined(HAVE_UWAIT)
#define HAVE_UWAIT !(defined(IBMR2)||defined(SUN5)||defined(HPUX8)||defined(HPUX9)||defined(PTX)||defined(IRIX5))
#endif
#if !defined(HAVE_WAIT3)
#define HAVE_WAIT3 !(defined(SUN5)||defined(PTX))
#endif
/* This is the port number used in the connection. It can use either
* /etc/services or a hardcoded port (SERVICE name has precedence).
* (You can -D one in the Makefile to override these.)
*/
/* #define PORT 782 /* only if you cannot put in /etc/services */
#if !defined(SERVICE)
#if !defined(PORT)
#define SERVICE "conserver"
#endif
#endif
/* Wait for a part of a second before slapping console server.
* Good for CISCO terminal servers that get upset when you
* attack with intense socket connections
*/
#if !defined(USLEEP_FOR_SLOW_PORTS)
#define USLEEP_FOR_SLOW_PORTS 100000
#endif
/* The name of the host which will act as the console server
*/
#if !defined(HOST)
#define HOST "console"
#endif
/* the default escape sequence used to give meta commands
*/
#define DEFATTN '\005'
#define DEFESC 'c'
/* Location of the configuration file
*/
#if !defined(CONFIG)
#define CONFIG "/etc/conserver.cf"
#endif
/* Location of ANL designed passwd file */
#if !defined(PASSWD_FILE)
#define PASSWD_FILE "/etc/conserver.passwd"
#endif
/* The maximum number of serial lines that can be handled by a child process
*/
#if !defined(MAXMEMB)
#define MAXMEMB 8
#endif
/* The maximum number of child processes spawned.
*/
#if !defined(MAXGRP)
#define MAXGRP 32
#endif
/* the max number of characters conserver will replay for you (the r command)
*/
#if !defined(MAXREPLAY)
#define MAXREPLAY (80*25)
#endif
/* if the encrypted passwd is in a shadow file, define HAVE_SHADOW (gregf)
*/
#if !defined(HAVE_SHADOW)
#define HAVE_SHADOW (defined(PTX)||defined(SUN5))
#endif
/* we'd like to line buffer our output, if we know how
*/
#if !defined(USE_SETLINEBUF)
#define USE_SETLINEBUF (!(defined(HPUX7)||defined(HPUX8)||defined(HPUX9)||defined(PTX)))
#endif
/* we'd like to line buffer our output, if we know how; PTX uses setvbuf (gregf)
*/
#if !defined(USE_SETVBUF)
#define USE_SETVBUF (defined(PTX))
#endif
/* hpux doesn't have getdtablesize() and they don't provide a macro
* in non-KERNEL cpp mode
*/
#if defined(HPUX7)||defined(HPUX8)||defined(HPUX9)
#define getdtablesize() 64
#endif
/* the console server will provide a pseudo-device console which
* allows operators to run backups and such without a hard wired
* line (this is also good for testing the server to see if you
* might wanna use it). Turn this on only if you (might) need it.
*/
#if !defined(DO_VIRTUAL)
#define DO_VIRTUAL 1
#endif
#if DO_VIRTUAL
/* if the virtual console option is on we need a source to ptys,
* the PUCC ptyd daemon is the best source be know, else fall back
* on some emulation code?? (XXX)
*/
#if !defined(HAVE_PTYD)
#define HAVE_PTYD (defined(S81)||defined(VAX8800))
#endif
#if !defined(HAVE_GETPSEUDO)
#define HAVE_GETPSEUDO (defined(PTX2))
#endif
#if !defined(HAVE_PTSNAME)
#define HAVE_PTSNAME (defined(PTX4))
#endif
#if !defined(HAVE_LDTERM)
#define HAVE_LDTERM (defined(SUN5))
#endif
#if !defined(HAVE_STTY_LD)
#define HAVE_STTY_LD (defined(IRIX5))
#endif
#endif /* virtual (process on a pseudo-tty) console support */
#if !defined(HAVE_SETSID)
#define HAVE_SETSID (defined(IBMR2)||defined(SUN5)||defined(HPUX7)||defined(HPUX8)||defined(HPUX9)||defined(PTX)||defined(IRIX5))
#endif
/* should we use flock to keep multiple conservers from hurting each other?
* PTX has lockf... should probably port code to work with this (gregf)
*/
#if !defined(USE_FLOCK)
#define USE_FLOCK (!(defined(IBMR2)||defined(SUN5)||defined(HPUX7)||defined(HPUX8)||defined(HPUX9)||defined(PTX)))
#endif
/* should we try to pop streams modules off?
*/
#if !defined(USE_STREAMS)
#define USE_STREAMS (defined(SUN4)||defined(SUN5)||defined(PTX)||defined(IRIX5))
#endif
/* if we do not have old style tty emulation use termios.h
*/
#if !defined(USE_TERMIO)
#define USE_TERMIO (defined(ETA10)||defined(V386))
#endif
#if !defined(USE_TERMIOS)
#define USE_TERMIOS (defined(HPUX7)||defined(HPUX8)||defined(HPUX9)||defined(SUN5)||defined(PTX)||defined(IRIX5))
#endif
#if !defined(USE_TCBREAK)
#define USE_TCBREAK (defined(SUN4)||defined(PTX))
#endif
/* if we have <strings.h> define this to 1, else define to 0
*/
#if !defined(USE_STRINGS)
#define USE_STRINGS (defined(SUN4)||defined(DYNIX)||defined(EPIX)||defined(IRIX5))
#endif
#if !defined(NEED_UNISTD_H)
#define NEED_UNISTD_H (defined(SUN5)||defined(PTX))
#endif
#if !defined(USE_SYS_TIME_H)
#define USE_SYS_TIME_H (!defined(PTX))
#endif
#if USE_STRINGS
#define strchr index
#define strrchr rindex
#endif
/* used to force the server process to clear parity, which is for farmers
*/
#define CPARITY 1
/* if you do not have fd_set's here is a possible emulation
*/
#if USE_OLDSEL
typedef long fd_set;
#define FD_ZERO(a) {*(a)=0;}
#define FD_SET(d,a) {*(a) |= (1 << (d));}
#define FD_CLR(d,a) {*(a) &= ~(1 << (d));}
#define FD_ISSET(d,a) (*(a) & (1 << (d)))
#endif
#if USE_TERMIOS
#if defined(HPUX7)||defined(HPUX8)||defined(HPUX9)
#define TCGETS _IOR('T', 16, struct termios)
#define TCSETS _IOW('T', 17, struct termios)
#endif
#if defined(PTX2)
#define TCGETS TCGETP
#define TCSETS TCSETP
#endif
#endif
/* which type does wait(2) take for status location
*/
#if HAVE_UWAIT
#define WAIT_T union wait
#if ! defined WEXITSTATUS
#define WEXITSTATUS(x) ((x).w_retcode)
#endif
#else
#define WAIT_T int
#endif
/* which type signal handlers return on this machine
*/
#if defined(sun) || defined(NEXT2) || defined(SUN5) || defined(PTX) || defined(IRIX5)
#define SIGRETS void
#else
#define SIGRETS int
#endif
/* do we have a (working) setsockopt call
*/
#if !defined(HAVE_SETSOCKOPT)
#define HAVE_SETSOCKOPT (defined(sun)||defined(PTX))
#endif
/* does this system have the ANSI strerror() function?
*/
#if !defined(HAVE_STRERROR)
#define HAVE_STRERROR (defined(IBMR2)||defined(ETA10)||defined(V386)||defined(SUN5)||defined(NEXT2)||defined(HPUX8)||defined(HPUX9)||defined(PTX)||defined(IRIX5))
#endif
#if ! HAVE_STRERROR
extern int errno;
extern char *sys_errlist[];
#define strerror(Me) (sys_errlist[Me])
#endif
#if !defined(HAVE_H_ERRLIST)
#define HAVE_H_ERRLIST (defined(SUN4)||defined(SUN3)||defined(FREEBSD)|defined(NETBSD)||defined(PTX)||defined(IRIX5))
#endif
#if HAVE_H_ERRLIST
extern int h_errno;
extern char *h_errlist[];
#define hstrerror(Me) (h_errlist[Me])
#else
#define hstrerror(Me) "host lookup error"
#endif
#if !defined(HAVE_RLIMIT)
#if (defined(SUN5)||defined(PTX4))
#define HAVE_RLIMIT 1
#else
#define HAVE_RLIMIT 0
#endif
#endif
/* that's all. just run
* make
* ./conserver -V
*/
/* communication constants
*/
#define OB_SUSP 'Z' /* suspended by server */
#define OB_DROP '.' /* dropped by server */
/* Due to C's poor man's macros the macro below would break if statements,
* What we want
* macro() { stuff }
* but the syntax gives us
* macro() { stuff };
*
* the extra semicolon breaks if statements!
* Of course, the one we use makes lint scream:
* macro() do { stuff } while (0)
*
* which is a statement and makes if statements safe
*/
#if defined(lint)
extern int shut_up_lint;
#else
#define shut_up_lint 0
#endif
/* this macro efficently outputs a constant string to a fd
* of course it doesn't check the write :-(
*/
#define CSTROUT(Mfd, Mstr) do { \
static char _ac[] = Mstr; \
write(Mfd, _ac, sizeof(_ac)-1); \
} while (shut_up_lint)
extern char *calloc(), *malloc(), *realloc();

351
conserver/cons-test.h Normal file
View File

@ -0,0 +1,351 @@
/*
* $Id: cons-gnac.h,v 5.35 1997-02-23 18:32:38-08 bryan Exp $
*
* Copyright 1992 Purdue Research Foundation, West Lafayette, Indiana
* 47907. All rights reserved.
*
* Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb
*
* This software is not subject to any license of the American Telephone
* and Telegraph Company or the Regents of the University of California.
*
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
*
* 1. Neither the authors nor Purdue University are responsible for any
* consequences of the use of this software.
*
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Credit to the authors and Purdue
* University must appear in documentation and sources.
*
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 4. This notice may not be removed or altered.
*/
/*
* this is the configuration file for the Ohio State/PUCC console
* server. Just define the macros below to somehting that looks good
* and give it a go. It'll complain (under conserver -V) if things
* look really bad.
*
* all PTX, PTX2, and PTX4 code added by gregf@sequent.com (gregf)
*/
/* #define IBMR2 1 /**/
/* #define HPUX7 1 /**/
/* #define SUN4 1 /**/
/* #define SUN5 1 /**/
/* #define PTX2 1 /* DYNIX/ptx v2.X */
/* #define PTX4 1 /* DYNIX/ptx v4.0 */
#if (defined(PTX2) || defined(PTX4))
#define PTX
#endif
/* some machine specific details
*/
#if !defined(USE_OLDSEL)
#if defined(IBMR2)
#include <sys/select.h>
#endif
#endif
#if !defined(HAVE_UWAIT)
#define HAVE_UWAIT !(defined(IBMR2)||defined(SUN5)||defined(HPUX8)||defined(HPUX9)||defined(PTX)||defined(IRIX5))
#endif
#if !defined(HAVE_WAIT3)
#define HAVE_WAIT3 !(defined(SUN5)||defined(PTX))
#endif
/* This is the port number used in the connection. It can use either
* /etc/services or a hardcoded port (SERVICE name has precedence).
* (You can -D one in the Makefile to override these.)
*/
/* #define PORT 782 /* only if you cannot put in /etc/services */
#define PORT 7777
#if !defined(SERVICE)
#if !defined(PORT)
#define SERVICE "conserver"
#endif
#endif
/* Wait for a part of a second before slapping console server.
* Good for CISCO terminal servers that get upset when you
* attack with intense socket connections
*/
#if !defined(USLEEP_FOR_SLOW_PORTS)
#define USLEEP_FOR_SLOW_PORTS 100000
#endif
/* The name of the host which will act as the console server
*/
#if !defined(HOST)
#define HOST "localhost"
#endif
/* the default escape sequence used to give meta commands
*/
#define DEFATTN '\005'
#define DEFESC 'c'
/* Location of the configuration file
*/
#if !defined(CONFIG)
#define CONFIG "../conserver.cf/test.cf"
#endif
/* Location of ANL designed passwd file */
#if !defined(PASSWD_FILE)
#define PASSWD_FILE "./conserver.passwd"
#endif
/* The maximum number of serial lines that can be handled by a child process
*/
#if !defined(MAXMEMB)
#define MAXMEMB 8
#endif
/* The maximum number of child processes spawned.
*/
#if !defined(MAXGRP)
#define MAXGRP 32
#endif
/* the max number of characters conserver will replay for you (the r command)
*/
#if !defined(MAXREPLAY)
#define MAXREPLAY (80*25)
#endif
/* if the encrypted passwd is in a shadow file, define HAVE_SHADOW (gregf)
*/
#if !defined(HAVE_SHADOW)
#define HAVE_SHADOW (defined(PTX)||defined(SUN5))
#endif
/* we'd like to line buffer our output, if we know how
*/
#if !defined(USE_SETLINEBUF)
#define USE_SETLINEBUF (!(defined(HPUX7)||defined(HPUX8)||defined(HPUX9)||defined(PTX)))
#endif
/* we'd like to line buffer our output, if we know how; PTX uses setvbuf (gregf)
*/
#if !defined(USE_SETVBUF)
#define USE_SETVBUF (defined(PTX))
#endif
/* hpux doesn't have getdtablesize() and they don't provide a macro
* in non-KERNEL cpp mode
*/
#if defined(HPUX7)||defined(HPUX8)||defined(HPUX9)
#define getdtablesize() 64
#endif
/* the console server will provide a pseudo-device console which
* allows operators to run backups and such without a hard wired
* line (this is also good for testing the server to see if you
* might wanna use it). Turn this on only if you (might) need it.
*/
#if !defined(DO_VIRTUAL)
#define DO_VIRTUAL 1
#endif
#if DO_VIRTUAL
/* if the virtual console option is on we need a source to ptys,
* the PUCC ptyd daemon is the best source be know, else fall back
* on some emulation code?? (XXX)
*/
#if !defined(HAVE_PTYD)
#define HAVE_PTYD (defined(S81)||defined(VAX8800))
#endif
#if !defined(HAVE_GETPSEUDO)
#define HAVE_GETPSEUDO (defined(PTX2))
#endif
#if !defined(HAVE_PTSNAME)
#define HAVE_PTSNAME (defined(PTX4))
#endif
#if !defined(HAVE_LDTERM)
#define HAVE_LDTERM (defined(SUN5))
#endif
#if !defined(HAVE_STTY_LD)
#define HAVE_STTY_LD (defined(IRIX5))
#endif
#endif /* virtual (process on a pseudo-tty) console support */
#if !defined(HAVE_SETSID)
#define HAVE_SETSID (defined(IBMR2)||defined(SUN5)||defined(HPUX7)||defined(HPUX8)||defined(HPUX9)||defined(PTX)||defined(IRIX5))
#endif
/* should we use flock to keep multiple conservers from hurting each other?
* PTX has lockf... should probably port code to work with this (gregf)
*/
#if !defined(USE_FLOCK)
#define USE_FLOCK (!(defined(IBMR2)||defined(SUN5)||defined(HPUX7)||defined(HPUX8)||defined(HPUX9)||defined(PTX)))
#endif
/* should we try to pop streams modules off?
*/
#if !defined(USE_STREAMS)
#define USE_STREAMS (defined(SUN4)||defined(SUN5)||defined(PTX)||defined(IRIX5))
#endif
/* if we do not have old style tty emulation use termios.h
*/
#if !defined(USE_TERMIO)
#define USE_TERMIO (defined(ETA10)||defined(V386))
#endif
#if !defined(USE_TERMIOS)
#define USE_TERMIOS (defined(HPUX7)||defined(HPUX8)||defined(HPUX9)||defined(SUN5)||defined(PTX)||defined(IRIX5))
#endif
#if !defined(USE_TCBREAK)
#define USE_TCBREAK (defined(SUN4)||defined(PTX))
#endif
/* if we have <strings.h> define this to 1, else define to 0
*/
#if !defined(USE_STRINGS)
#define USE_STRINGS (defined(SUN4)||defined(DYNIX)||defined(EPIX)||defined(IRIX5))
#endif
#if !defined(NEED_UNISTD_H)
#define NEED_UNISTD_H (defined(SUN5)||defined(PTX))
#endif
#if !defined(USE_SYS_TIME_H)
#define USE_SYS_TIME_H (!defined(PTX))
#endif
#if USE_STRINGS
#define strchr index
#define strrchr rindex
#endif
/* used to force the server process to clear parity, which is for farmers
*/
#define CPARITY 1
/* if you do not have fd_set's here is a possible emulation
*/
#if USE_OLDSEL
typedef long fd_set;
#define FD_ZERO(a) {*(a)=0;}
#define FD_SET(d,a) {*(a) |= (1 << (d));}
#define FD_CLR(d,a) {*(a) &= ~(1 << (d));}
#define FD_ISSET(d,a) (*(a) & (1 << (d)))
#endif
#if USE_TERMIOS
#if defined(HPUX7)||defined(HPUX8)||defined(HPUX9)
#define TCGETS _IOR('T', 16, struct termios)
#define TCSETS _IOW('T', 17, struct termios)
#endif
#if defined(PTX2)
#define TCGETS TCGETP
#define TCSETS TCSETP
#endif
#endif
/* which type does wait(2) take for status location
*/
#if HAVE_UWAIT
#define WAIT_T union wait
#if ! defined WEXITSTATUS
#define WEXITSTATUS(x) ((x).w_retcode)
#endif
#else
#define WAIT_T int
#endif
/* which type signal handlers return on this machine
*/
#if defined(sun) || defined(NEXT2) || defined(SUN5) || defined(PTX) || defined(IRIX5)
#define SIGRETS void
#else
#define SIGRETS int
#endif
/* do we have a (working) setsockopt call
*/
#if !defined(HAVE_SETSOCKOPT)
#define HAVE_SETSOCKOPT (defined(sun)||defined(PTX))
#endif
/* does this system have the ANSI strerror() function?
*/
#if !defined(HAVE_STRERROR)
#define HAVE_STRERROR (defined(IBMR2)||defined(ETA10)||defined(V386)||defined(SUN5)||defined(NEXT2)||defined(HPUX8)||defined(HPUX9)||defined(PTX)||defined(IRIX5))
#endif
#if ! HAVE_STRERROR
extern int errno;
extern char *sys_errlist[];
#define strerror(Me) (sys_errlist[Me])
#endif
#if !defined(HAVE_H_ERRLIST)
#define HAVE_H_ERRLIST (defined(SUN4)||defined(SUN3)||defined(FREEBSD)|defined(NETBSD)||defined(PTX)||defined(IRIX5))
#endif
#if HAVE_H_ERRLIST
extern int h_errno;
extern char *h_errlist[];
#define hstrerror(Me) (h_errlist[Me])
#else
#define hstrerror(Me) "host lookup error"
#endif
#if !defined(HAVE_RLIMIT)
#if (defined(SUN5)||defined(PTX4))
#define HAVE_RLIMIT 1
#else
#define HAVE_RLIMIT 0
#endif
#endif
/* that's all. just run
* make
* ./conserver -V
*/
/* communication constants
*/
#define OB_SUSP 'Z' /* suspended by server */
#define OB_DROP '.' /* dropped by server */
/* Due to C's poor man's macros the macro below would break if statements,
* What we want
* macro() { stuff }
* but the syntax gives us
* macro() { stuff };
*
* the extra semicolon breaks if statements!
* Of course, the one we use makes lint scream:
* macro() do { stuff } while (0)
*
* which is a statement and makes if statements safe
*/
#if defined(lint)
extern int shut_up_lint;
#else
#define shut_up_lint 0
#endif
/* this macro efficently outputs a constant string to a fd
* of course it doesn't check the write :-(
*/
#define CSTROUT(Mfd, Mstr) do { \
static char _ac[] = Mstr; \
write(Mfd, _ac, sizeof(_ac)-1); \
} while (shut_up_lint)
extern char *calloc(), *malloc(), *realloc();

1
conserver/cons.h Symbolic link
View File

@ -0,0 +1 @@
cons-test.h

710
conserver/consent.c Normal file
View File

@ -0,0 +1,710 @@
/*
* $Id: consent.c,v 5.30 1998-11-20 17:30:45-08 bryan Exp $
*
* Copyright 1992 Purdue Research Foundation, West Lafayette, Indiana
* 47907. All rights reserved.
*
* Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb
*
* This software is not subject to any license of the American Telephone
* and Telegraph Company or the Regents of the University of California.
*
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
*
* 1. Neither the authors nor Purdue University are responsible for any
* consequences of the use of this software.
*
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Credit to the authors and Purdue
* University must appear in documentation and sources.
*
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 4. This notice may not be removed or altered.
*/
/*
* Network console modifications by Robert Olson, olson@mcs.anl.gov.
*/
#ifndef lint
static char copyright[] =
"@(#) Copyright 1992 Purdue Research Foundation.\nAll rights reserved.\n";
#endif
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <pwd.h>
#include "cons.h"
#include "consent.h"
#include "client.h"
#include "main.h"
#if USE_TERMIO
#include <termio.h>
#else
#if USE_TERMIOS
#include <termios.h>
#include <unistd.h>
#else /* use ioctl stuff */
#include <sgtty.h>
#include <sys/ioctl.h>
#endif
#endif
#if USE_STREAMS
#include <stropts.h>
#endif
#if USE_STRINGS
#include <strings.h>
#else
#include <string.h>
#endif
BAUD baud [] = {
{ "Netwk", 0 },
#if defined(B38400)
{ "38400", B38400 },
#endif
#if defined(B19200)
{ "19200", B19200 },
#endif
{ "9600", B9600 },
{ "4800", B4800 },
{ "2400", B2400 },
#if defined(B1800)
{ "1800", B1800 },
#endif
{ "1200", B1200 },
#if defined(B600)
{ "600", B600 },
#endif
};
/* find a baud rate for the string "9600x" -> B9600 (ksb)
*/
BAUD *
FindBaud(pcMode)
char *pcMode;
{
register int i;
for (i = 0; i < sizeof(baud)/sizeof(struct baud); ++i) {
if (0 != strncmp(pcMode, baud[i].acrate, strlen(baud[i].acrate)))
continue;
return baud+i;
}
return baud;
}
PARITY parity[] = {
#if USE_TERMIOS
#if !defined(PAREXT)
#define PAREXT 0
#endif
{' ', 0, 0}, /* Blank for network */
{'e', PARENB|CS7, 0}, /* even */
{'m', PARENB|CS7|PARODD|PAREXT, 0}, /* mark */
{'o', PARENB|CS7|PARODD, 0}, /* odd */
{'p', CS8, 0}, /* pass 8 bits, no parity */
{'s', PARENB|CS7|PAREXT, 0}, /* space */
#else
{' ', 0, 0}, /* Blank for network */
{'e', EVENP, ODDP}, /* even */
{'m', EVENP|ODDP, 0}, /* mark */
{'o', ODDP, EVENP}, /* odd */
#if defined(PASS8)
{'p', PASS8,EVENP|ODDP},/* pass 8 bits, no parity */
#endif
{'s', 0, EVENP|ODDP} /* space */
#endif
};
/* find a parity on the end of a baud "9600even" -> EVEN (ksb)
*/
PARITY *
FindParity(pcMode)
char *pcMode;
{
register int i;
auto char acFirst;
while (isdigit(*pcMode)) {
++pcMode;
}
acFirst = *pcMode;
if (isupper(acFirst))
acFirst = tolower(acFirst);
for (i = 0; i < sizeof(parity)/sizeof(struct parity); ++i) {
if (acFirst != parity[i].ckey)
continue;
return parity+i;
}
return parity;
}
#if USE_TERMIOS
/* setup a tty device (ksb)
*/
static int
TtyDev(pCE)
CONSENT *pCE;
{
struct termios termp;
auto struct stat stPerm;
/* here we should fstat for `read-only' checks
*/
if (-1 == fstat(pCE->fdtty, & stPerm)) {
fprintf(stderr, "%s: fstat: %s: %s\n", progname, pCE->dfile, strerror(errno));
} else if (0 == (stPerm.st_mode & 0222)) {
/* any device that is read-only we won't write to
*/
pCE->fronly = 1;
}
/*
* Get terminal attributes
*/
if (-1 == tcgetattr(pCE->fdtty, &termp)) {
fprintf(stderr, "%s: tcgetattr: %s(%d): %s\n", progname, pCE->dfile, pCE->fdtty, strerror(errno));
return -1;
}
/*
* Turn off: echo
* icrnl
* opost No post processing
* icanon No line editing
* isig No signal generation
* Turn on: ixoff
*/
termp.c_iflag = IXON|IXOFF|BRKINT;
termp.c_oflag = 0;
termp.c_cflag = CREAD;
termp.c_cflag |= pCE->pparity->iset;
termp.c_lflag = 0;
/*
* Set the VMIN == 128
* Set the VTIME == 1 (0.1 sec)
* Don't bother with the control characters as they are not used
*/
termp.c_cc[VMIN] = 128;
termp.c_cc[VTIME] = 1;
if (-1 == cfsetospeed(&termp,pCE->pbaud->irate)) {
fprintf(stderr, "%s: cfsetospeed: %s(%d): %s\n", progname, pCE->dfile, pCE->fdtty, strerror(errno));
return -1;
}
if (-1 == cfsetispeed(&termp,pCE->pbaud->irate)) {
fprintf(stderr, "%s: cfsetispeed: %s(%d): %s\n", progname, pCE->dfile, pCE->fdtty, strerror(errno));
return -1;
}
/*
* Set terminal attributes
*/
if (-1 == tcsetattr(pCE->fdtty, TCSADRAIN, &termp)) {
fprintf(stderr, "%s: tcsetattr: %s(%d): %s\n", progname, pCE->dfile, pCE->fdtty, strerror(errno));
return -1;
}
#if USE_STREAMS
/*
* eat all the streams modules upto and including ttcompat
*/
while (ioctl(pCE->fdtty, I_FIND, "ttcompat") == 0) {
(void)ioctl(pCE->fdtty, I_POP, 0);
}
#endif
pCE->fup = 1;
return 0;
}
#else
/* setup a tty device (ksb)
*/
static int
TtyDev(pCE)
CONSENT *pCE;
{
struct sgttyb sty;
struct tchars m_tchars;
struct ltchars m_ltchars;
auto struct stat stPerm;
/* here we should fstat for `read-only' checks
*/
if (-1 == fstat(pCE->fdtty, & stPerm)) {
fprintf(stderr, "%s: fstat: %s: %s\n", progname, pCE->dfile, strerror(errno));
} else if (0 == (stPerm.st_mode & 0222)) {
/* any device that is read-only we won't write to
*/
pCE->fronly = 1;
}
#if USE_SOFTCAR
#if defined(TIOCSSOFTCAR)
if (-1 == ioctl(pCE->fdtty, TIOCSSOFTCAR, &fSoftcar)) {
fprintf(stderr, "%s: softcar: %d: %s\n", progname, pCE->fdtty, strerror(errno));
return -1;
}
#endif
#endif
/* stty 9600 raw cs7
*/
if (-1 == ioctl(pCE->fdtty, TIOCGETP, (char *)&sty)) {
fprintf(stderr, "%s: ioctl1: %s(%d): %s\n", progname, pCE->dfile, pCE->fdtty, strerror(errno));
return -1;
}
sty.sg_flags &= ~(ECHO|CRMOD|pCE->pparity->iclr);
sty.sg_flags |= (CBREAK|TANDEM|pCE->pparity->iset);
sty.sg_erase = -1;
sty.sg_kill = -1;
sty.sg_ispeed = pCE->pbaud->irate;
sty.sg_ospeed = pCE->pbaud->irate;
if (-1 == ioctl(pCE->fdtty, TIOCSETP, (char *)&sty)) {
fprintf(stderr, "%s: ioctl2: %d: %s\n", progname, pCE->fdtty, strerror(errno));
return -1;
}
/* stty undef all tty chars
* (in cbreak mode we may not need to this... but we do)
*/
if (-1 == ioctl(pCE->fdtty, TIOCGETC, (char *)&m_tchars)) {
fprintf(stderr, "%s: ioctl3: %d: %s\n", progname, pCE->fdtty, strerror(errno));
return -1;
}
m_tchars.t_intrc = -1;
m_tchars.t_quitc = -1;
m_tchars.t_startc = -1;
m_tchars.t_stopc = -1;
m_tchars.t_eofc = -1;
m_tchars.t_brkc = -1;
if (-1 == ioctl(pCE->fdtty, TIOCSETC, (char *)&m_tchars)) {
fprintf(stderr, "%s: ioctl4: %d: %s\n", progname, pCE->fdtty, strerror(errno));
return -1;
}
if (-1 == ioctl(pCE->fdtty, TIOCGLTC, (char *)&m_ltchars)) {
fprintf(stderr, "%s: ioctl5: %d: %s\n", progname, pCE->fdtty, strerror(errno));
return -1;
}
m_ltchars.t_werasc = -1;
m_ltchars.t_flushc = -1;
m_ltchars.t_lnextc = -1;
m_ltchars.t_suspc = -1;
m_ltchars.t_dsuspc = -1;
if (-1 == ioctl(pCE->fdtty, TIOCSLTC, (char *)&m_ltchars)) {
fprintf(stderr, "%s: ioctl6: %d: %s\n", progname, pCE->fdtty, strerror(errno));
return -1;
}
#if USE_STREAMS
/* pop off the un-needed streams modules (on a sun3 machine esp.)
* (Idea by jrs@ecn.purdue.edu)
*/
while (ioctl(pCE->fdtty, I_POP, 0) == 0) {
/* eat all the streams modules */;
}
#endif
pCE->fup = 1;
return 0;
}
#endif
#if DO_VIRTUAL
/* setup a virtual device (ksb)
*/
static int
VirtDev(pCE)
CONSENT *pCE;
{
#if USE_TERMIOS
static struct termios n_tio;
#else
auto struct sgttyb sty;
auto struct tchars m_tchars;
auto struct ltchars m_ltchars;
#endif
#if HAVE_RLIMIT
auto struct rlimit rl;
#endif
auto int i, iNewGrp;
auto int fd;
extern char **environ;
register char *pcShell, **ppcArgv;
(void)fflush(stdout);
switch (pCE->ipid = fork()) {
case -1:
return -1;
case 0:
break;
default:
fprintf(stderr, "%s: %d is the pid on %s\n", progname, pCE->ipid, pCE->acslave);
(void)fflush(stderr);
pCE->fup = 1;
sleep(2); /* chance to open line */
return 0;
}
/* put the signals back that we trap
*/
signal(SIGINT, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
signal(SIGTSTP, SIG_DFL);
/* setup new process with clean filew descriptors
*/
#if HAVE_RLIMIT
getrlimit(RLIMIT_NOFILE, &rl);
i = rl.rlim_cur;
#else
i = getdtablesize();
#endif
for (/* i above */; i-- > 2; ) {
close(i);
}
/* leave 2 until we *have to close it*
*/
close(1);
close(0);
#if defined(TIOCNOTTY)
if (-1 != (i = open("/dev/tty", 2, 0))) {
ioctl(i, TIOCNOTTY, (char *)0);
close(i);
}
#endif
#if HAVE_SETSID
iNewGrp = setsid();
if (-1 == iNewGrp) {
fprintf(stderr, "%s: %s: setsid: %s\n", progname, pCE->server, strerror(errno));
iNewGrp = getpid();
}
#else
iNewGrp = getpid();
#endif
if (0 != open(pCE->acslave, 2, 0) || 1 != dup(0)) {
fprintf(stderr, "%s: %s: fd sync error\n", progname, pCE->server);
exit(1);
}
#if HAVE_PTSNAME
/* SYSVr4 semantics for opening stream ptys (gregf)
* under PTX (others?) we have to push the compatibility
* streams modules `ptem' and `ld'
*/
(void)ioctl(0, I_PUSH, "ptem");
(void)ioctl(0, I_PUSH, "ld");
#endif
#if HAVE_LDTERM
(void)ioctl(0, I_PUSH, "ptem");
(void)ioctl(0, I_PUSH, "ldterm");
#endif
#if HAVE_STTY_LD
(void)ioctl(0, I_PUSH, "stty_ld");
#endif
#if USE_TERMIOS
if (0 != ioctl(0, TCGETS, & n_tio)) {
fprintf(stderr, "%s: iotcl: getsw: %s\n", progname, strerror(errno));
exit(1);
}
n_tio.c_iflag &= ~(IGNCR|IUCLC);
n_tio.c_iflag |= ICRNL|IXON|IXANY;
n_tio.c_oflag &= ~(OLCUC|ONOCR|ONLRET|OFILL|NLDLY|CRDLY|TABDLY|BSDLY);
n_tio.c_oflag |= OPOST|ONLCR;
n_tio.c_lflag &= ~(XCASE|NOFLSH|ECHOK|ECHONL);
n_tio.c_lflag |= ISIG|ICANON|ECHO;
n_tio.c_cc[VEOF] = '\004';
n_tio.c_cc[VEOL] = '\000';
n_tio.c_cc[VERASE] = '\010';
n_tio.c_cc[VINTR] = '\003';
n_tio.c_cc[VKILL] = '@';
/* MIN */
n_tio.c_cc[VQUIT] = '\034';
n_tio.c_cc[VSTART] = '\021';
n_tio.c_cc[VSTOP] = '\023';
n_tio.c_cc[VSUSP] = '\032';
if (0 != ioctl(0, TCSETS, & n_tio)) {
fprintf(stderr, "%s: getarrt: %s\n", progname, strerror(errno));
exit(1);
}
tcsetpgrp(0, iNewGrp);
#else
/* stty 9600 raw cs7
*/
if (-1 == ioctl(0, TIOCGETP, (char *)&sty)) {
fprintf(stderr, "%s: ioctl1: %s: %s\n", progname, pCE->fdtty, strerror(errno));
exit(1);
}
sty.sg_flags &= ~(CBREAK|TANDEM|pCE->pparity->iclr);
sty.sg_flags |= (ECHO|CRMOD|pCE->pparity->iset);
sty.sg_erase = '\b';
sty.sg_kill = '\025';
sty.sg_ispeed = pCE->pbaud->irate;
sty.sg_ospeed = pCE->pbaud->irate;
if (-1 == ioctl(0, TIOCSETP, (char *)&sty)) {
fprintf(stderr, "%s: ioctl2: %s\n", progname, strerror(errno));
exit(1);
}
/* stty undef all tty chars
* (in cbreak mode we may not need to this... but we do)
*/
if (-1 == ioctl(0, TIOCGETC, (char *)&m_tchars)) {
fprintf(stderr, "%s: ioctl3: %s\n", progname, strerror(errno));
exit(1);
}
m_tchars.t_intrc = '\003';
m_tchars.t_quitc = '\034';
m_tchars.t_startc = '\021';
m_tchars.t_stopc = '\023';
m_tchars.t_eofc = '\004';
m_tchars.t_brkc = '\033';
if (-1 == ioctl(0, TIOCSETC, (char *)&m_tchars)) {
fprintf(stderr, "%s: ioctl4: %s\n", progname, strerror(errno));
exit(1);
}
if (-1 == ioctl(0, TIOCGLTC, (char *)&m_ltchars)) {
fprintf(stderr, "%s: ioctl5: %s\n", progname, strerror(errno));
exit(1);
}
m_ltchars.t_werasc = '\027';
m_ltchars.t_flushc = '\017';
m_ltchars.t_lnextc = '\026';
m_ltchars.t_suspc = '\032';
m_ltchars.t_dsuspc = '\031';
if (-1 == ioctl(0, TIOCSLTC, (char *)&m_ltchars)) {
fprintf(stderr, "%s: ioctl6: %s\n", progname, strerror(errno));
exit(1);
}
/* give us a process group to work in
*/
ioctl(0, TIOCGPGRP, (char *)&i);
setpgrp(0, i);
ioctl(0, TIOCSPGRP, (char *)&iNewGrp);
setpgrp(0, iNewGrp);
#endif
close(2);
(void)dup(1); /* better be 2, but it is too late now */
/* if the command is null we should run root's shell, directly
* if we can't find root's shell run /bin/sh
*/
pcShell = "/bin/sh";
if ('\000' == pCE->pccmd[0]) {
static char *apcArgv[] = {
"-shell", "-i", (char *)0
};
register struct passwd *pwd;
if ((struct passwd *)0 != (pwd = getpwuid(0)) && '\000' != pwd->pw_shell[0]) {
pcShell = pwd->pw_shell;
}
ppcArgv = apcArgv;
} else {
static char *apcArgv[] = {
"/bin/sh", "-ce", (char *)0, (char *)0
};
apcArgv[2] = pCE->pccmd;
ppcArgv = apcArgv;
}
execve(pcShell, ppcArgv, environ);
fprintf(stderr, "execve: %s\n", strerror(errno));
exit(1);
/*NOTREACHED*/
}
#endif
/* down a console, virtual or real (ksb)
*/
void
ConsDown(pCE, pfdSet)
CONSENT *pCE;
fd_set *pfdSet;
{
#if DO_VIRTUAL
if (-1 != pCE->ipid) {
if (-1 != kill(pCE->ipid, SIGHUP))
sleep(1);
pCE->ipid = -1;
}
#endif
if (-1 != pCE->fdtty) {
FD_CLR(pCE->fdtty, pfdSet);
#if DO_VIRTUAL
if (0 == pCE->fvirtual) {
(void)close(pCE->fdtty);
pCE->fdtty = -1;
}
#else
(void)close(pCE->fdtty);
pCE->fdtty = -1;
#endif
}
if (-1 != pCE->fdlog) {
if (pCE->nolog) {
CSTROUT(pCE->fdlog, "[Console logging restored]\r\n");
}
(void)close(pCE->fdlog);
pCE->fdlog = -1;
}
pCE->fup = 0;
pCE->nolog = 0;
}
/* set up a console the way it should be for use to work with it (ksb)
* also, recover from silo over runs by dropping the line and re-opening
* We also maintian the select set for the caller.
*/
void
ConsInit(pCE, pfdSet)
CONSENT *pCE;
fd_set *pfdSet;
{
/* clean up old stuff
*/
ConsDown(pCE, pfdSet);
pCE->fronly = 0;
pCE->nolog = 0;
(void)strcpy(pCE->acline, pCE->server);
pCE->inamelen = strlen(pCE->server);
pCE->acline[pCE->inamelen++] = ':';
pCE->acline[pCE->inamelen++] = ' ';
pCE->iend = pCE->inamelen;
/* try to open them again
*/
if (-1 ==
(pCE->fdlog = open(pCE->lfile, O_RDWR|O_CREAT|O_APPEND, 0644)))
{
fprintf(stderr,
"%s: open: %s: %s\n",
progname, pCE->lfile, strerror(errno));
return;
}
#if DO_VIRTUAL
if (0 != pCE->fvirtual)
{
/* still open, never ever close it, but set the bit */
FD_SET(pCE->fdtty, pfdSet);
}
else if (pCE->isNetworkConsole)
{
struct sockaddr_in port;
struct hostent *hp;
int one = 1;
#ifdef USLEEP_FOR_SLOW_PORTS
usleep( USLEEP_FOR_SLOW_PORTS ); /* Sleep for slow network ports */
#endif
bzero(&port, sizeof(port));
if ((hp = gethostbyname(pCE->networkConsoleHost)) == NULL)
{
fprintf(stderr, "%s: gethostbyname %s failed\n",
progname, pCE->networkConsoleHost);
exit(1);
}
bcopy(hp->h_addr, &port.sin_addr, hp->h_length);
port.sin_family = hp->h_addrtype;
port.sin_port = htons(pCE->networkConsolePort);
if ((pCE->fdtty = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
fprintf(stderr, "%s: socket: %s\n", progname, strerror(errno));
exit(1);
}
if (setsockopt(pCE->fdtty, SOL_SOCKET, SO_KEEPALIVE,
(char *) &one, sizeof(one)) < 0)
{
fprintf(stderr, "%s: setsockopt SO_KEEPALIVE: %s\n",
progname, strerror(errno));
}
if (connect(pCE->fdtty,
(struct sockaddr *)&port, sizeof(port)) < 0)
{
fprintf(stderr, "%s: connect: %s (%d@%s): %s: forcing down\n",
progname, pCE->server, ntohs(port.sin_port),
pCE->networkConsoleHost, strerror(errno));
ConsDown(pCE, pfdSet);
return;
}
/*
* Poke the connection to get the annex to wake up and
* register this connection.
*/
#ifdef POKE_ANNEX
write(pCE->fdtty, "\r\n", 2);
#endif
} else if (-1 == (pCE->fdtty = open(pCE->dfile, O_RDWR|O_NDELAY, 0600))) {
fprintf(stderr, "%s: open: %s: %s\n", progname, pCE->dfile, strerror(errno));
(void)close(pCE->fdlog);
pCE->fdlog = -1;
return;
}
FD_SET(pCE->fdtty, pfdSet);
/* ok, now setup the device
*/
if (pCE->fvirtual) {
VirtDev(pCE);
}
else if (pCE->isNetworkConsole)
{
pCE->fup = 1;
}
else
{
TtyDev(pCE);
}
#else
if (-1 == (pCE->fdtty = open(pCE->dfile, O_RDWR|O_NDELAY, 0600))) {
fprintf(stderr, "%s: open: %s: %s\n", progname, pCE->dfile, strerror(errno));
(void)close(pCE->fdlog);
pCE->fdlog = -1;
return;
}
FD_SET(pCE->fdtty, pfdSet);
/* ok, now setup the device
*/
TtyDev(pCE);
#endif
}

89
conserver/consent.h Normal file
View File

@ -0,0 +1,89 @@
/*
* $Id: consent.h,v 5.11 1998-12-14 11:20:15-08 bryan Exp $
*
* Copyright 1992 Purdue Research Foundation, West Lafayette, Indiana
* 47907. All rights reserved.
*
* Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb
*
* This software is not subject to any license of the American Telephone
* and Telegraph Company or the Regents of the University of California.
*
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
*
* 1. Neither the authors nor Purdue University are responsible for any
* consequences of the use of this software.
*
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Credit to the authors and Purdue
* University must appear in documentation and sources.
*
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 4. This notice may not be removed or altered.
*/
/*
* Network console modifications by Robert Olson, olson@mcs.anl.gov.
*/
/* stuff to keep track of a console entry
*/
typedef struct baud { /* a baud rate table */
char acrate[8];
int irate;
} BAUD;
typedef struct parity { /* a parity bits table */
char ckey;
int iset;
int iclr;
} PARITY;
#define MAXSERVLEN 32 /* max length of server name */
#define MAXDEVLEN 512 /* max length of /dev/ttyax */
#define MAXLOGLEN 1024 /* max length of /usr/adm/consoles/foo */
#define MAXTTYLINE (133*2) /* max length of a single buf'd line */
#define ALARMTIME 60 /* time between chimes */
typedef struct consent { /* console information */
char server[MAXSERVLEN];/* server name */
char dfile[MAXDEVLEN]; /* device file */
char lfile[MAXLOGLEN]; /* log file */
BAUD *pbaud; /* the baud on this console port */
PARITY *pparity; /* the parity on this line */
int mark; /* Mark (chime) interval */
long nextMark; /* Next mark (chime) time */
/* Used if network console */
int isNetworkConsole;
char networkConsoleHost[MAXSERVLEN];
int networkConsolePort;
#if DO_VIRTUAL
/* used if virtual console */
char acslave[MAXDEVLEN];/* pseudo-device slave side */
int fvirtual; /* is a pty device we use as a console */
char *pccmd; /* virtual console command */
int ipid; /* pid of virtual command */
#endif
/* only used in child */
int nolog; /* don't log output */
int fdlog; /* the local log file */
int fdtty; /* the port to talk to machine on */
short int fup; /* we setup this line? */
short int fronly; /* we can only read this console */
short int iend; /* like icursor in CLIENT */
short int inamelen; /* strlen(server) */
struct client *pCLon; /* clients on this console */
struct client *pCLwr; /* client that is writting on console */
char acline[132*2+2]; /* max chars we will call a line */
} CONSENT;
extern PARITY *FindParity();
extern BAUD *FindBaud();
extern void ConsInit();
extern void ConsDown();

78
conserver/conserver.8l Normal file
View File

@ -0,0 +1,78 @@
.\" @(#)conserver.8 01/06/91 OSU CIS; Thomas A. Fine
.\" $Id: conserver.8l,v 2.3 93/02/09 11:51:56 ldv Exp $
.TH CONSERVER 8L "LOCAL"
.SH NAME
conserver \- console server daemon
.SH SYNOPSIS
.B conserver [\-\fBnv\fP] [\-\fBC\fP \fIconfig\fP]
.br
.B conserver [\-\fBhV\fP]
.SH DESCRIPTION
.B Conserver
is the daemon for the
.IR console (1L)
program.
It provides remote access to the server consoles,
and logs all console data.
Slave hosts which have no current connection might produce important
error messages, these unloved errors are labeled with a machine name
and output on stdout.
.PP
When started, it forks a child for each group in /usr/local/etc/conserver.cf,
and assigns each process a port number to listen on.
The \fIconsole\fP client program knows how to request port numbers and
forwards to find the various slave hosts.
.PP
.B Conserver
completely controls any connection to a controlled host.
All handling of escape sequenes is done by the server,
except the suspend sequence which is
sent as an out-of-band command to the client.
.PP
The
.B conserver
parent process will automatically respawn any child process that dies.
If the parent process receives a SIGTERM, it will propogate the signal
to its children.
.SH OPTIONS
.TP
.BI \-C config
With this option the invoker may specify an alternate confguration.
The default \fIconfig\fP is /usr/local/lib/conserver.cf.
.TP
.B \-h
Output a brief help message.
.TP
.B \-n
The \fIconserver\fP will \fBnot\fP output unloved console output to
stdout.
.TP
.B \-v
Echo the configuration as it is being read (be verbose).
.TP
.B \-V
Output the version of the console server (only) and exit.
.SH EXAMPLES
conserver: expert: login ksb
.br
tyro: panic: my brain hurts
.br
conserver: ksb shifts from expert to tyro
.br
conserver: tyro: logout ksb
.br
\...
.SH FILES
.TS
l l.
/usr/local/lib/conserver.cf description of console terminal lines
/usr/adm/\fIhost\fP.console log files for \fIhost\fP's console
/dev/tty?? terminal line device files
\fIstdout\fP summary of unloved console errors
.TE
.SH AUTHORS
Thomas A. Fine, Ohio State Computer Science
.br
Kevin S Braunsdorf, Purdue University Computing Center
.SH "SEE ALSO"
console(1L), conserver.cf(5L)

78
conserver/conserver.man Normal file
View File

@ -0,0 +1,78 @@
.\" @(#)conserver.8 01/06/91 OSU CIS; Thomas A. Fine
.\" $Id: conserver.man,v 2.3 93/02/09 11:51:56 ldv Exp $
.TH CONSERVER 8L "LOCAL"
.SH NAME
conserver \- console server daemon
.SH SYNOPSIS
.B conserver [\-\fBnv\fP] [\-\fBC\fP \fIconfig\fP]
.br
.B conserver [\-\fBhV\fP]
.SH DESCRIPTION
.B Conserver
is the daemon for the
.IR console (1L)
program.
It provides remote access to the server consoles,
and logs all console data.
Slave hosts which have no current connection might produce important
error messages, these unloved errors are labeled with a machine name
and output on stdout.
.PP
When started, it forks a child for each group in /usr/local/etc/conserver.cf,
and assigns each process a port number to listen on.
The \fIconsole\fP client program knows how to request port numbers and
forwards to find the various slave hosts.
.PP
.B Conserver
completely controls any connection to a controlled host.
All handling of escape sequenes is done by the server,
except the suspend sequence which is
sent as an out-of-band command to the client.
.PP
The
.B conserver
parent process will automatically respawn any child process that dies.
If the parent process receives a SIGTERM, it will propogate the signal
to its children.
.SH OPTIONS
.TP
.BI \-C config
With this option the invoker may specify an alternate confguration.
The default \fIconfig\fP is /usr/local/lib/conserver.cf.
.TP
.B \-h
Output a brief help message.
.TP
.B \-n
The \fIconserver\fP will \fBnot\fP output unloved console output to
stdout.
.TP
.B \-v
Echo the configuration as it is being read (be verbose).
.TP
.B \-V
Output the version of the console server (only) and exit.
.SH EXAMPLES
conserver: expert: login ksb
.br
tyro: panic: my brain hurts
.br
conserver: ksb shifts from expert to tyro
.br
conserver: tyro: logout ksb
.br
\...
.SH FILES
.TS
l l.
/usr/local/lib/conserver.cf description of console terminal lines
/usr/adm/\fIhost\fP.console log files for \fIhost\fP's console
/dev/tty?? terminal line device files
\fIstdout\fP summary of unloved console errors
.TE
.SH AUTHORS
Thomas A. Fine, Ohio State Computer Science
.br
Kevin S Braunsdorf, Purdue University Computing Center
.SH "SEE ALSO"
console(1L), conserver.cf(5L)

View File

@ -0,0 +1,4 @@
bryan:r71mXjfALB5Ak:any
djs:r71mXjfALB5Ak:login
chogan:*passwd*:foobar,login,shell
hogan:*passwd*:any

234
conserver/fallback.c Normal file
View File

@ -0,0 +1,234 @@
/*
* $Id: fallback.c,v 5.18 1994-07-19 08:25:54-07 ksb Exp $
*
* This is a fake library interface to ptyd (mtr&ksb)
*
* Mike Rowan (mtr@mace.cc.purdue.edu)
*/
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <syslog.h>
#include <signal.h>
#include <netdb.h>
#include <stdio.h>
#include <ctype.h>
#include "cons.h"
#if HAVE_PTSNAME
/* for grantpt() and unlockpt() (gregf)
*/
#include <stdlib.h>
#endif
#if NEED_UNISTD_H
#include <unistd.h>
#endif
#if USE_STRINGS
#include <strings.h>
#else
#include <string.h>
#endif
#if DO_VIRTUAL && ! HAVE_PTYD
extern int errno;
#if !HAVE_STRERROR
extern char *sys_errlist[], *strchr();
#define strerror(Me) (sys_errlist[Me])
#endif
static char *__pty_host;
static char *__pty_fmt;
static int iLogPri = LOG_DEBUG;
/*
* Below is the string for finding /dev/ptyXX. For each architecture we
* leave some pty's world writable because we don't have source for
* everything that uses pty's. For the most part, we'll be trying to
* make /dev/ptyq* the "free" pty's.
*/
#if defined(sun)
static char charone[] =
"prstuvwxyzPQRSTUVWq";
#else
#if defined(dynix)
static char charone[] =
"prstuvwxyzPQRSTUVWq";
#else
#if defined(ultrix)
static char charone[] =
"prstuvwxyzPQRSTUVWq";
#else
/* all the world's a vax ;-) */
static char charone[] =
"prstuvwxyzPQRSTUVWq";
#endif
#endif
#endif
static char chartwo[] =
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
#if (defined(_AIX) || defined(PTX4))
static char acMaster[] =
"/dev/ptc/XXXXXXXXX";
static char acSlave[] =
"/dev/pts/XXXXXXXXX";
#else
static char acMaster[] =
"/dev/ptyXX";
static char acSlave[] =
"/dev/ttyXX";
#endif /* _AIX */
#if !HAVE_GETPSEUDO
#ifdef _AIX
/*
* get a pty for the user (emulate the neato sequent call) (mm)
*/
static int
getpseudotty(slave, master)
char **master, **slave;
{
int fd;
char *pcName, *pcTmp;
if (0 > (fd = open("/dev/ptc", O_RDWR|O_NDELAY, 0))) {
return -1;
}
if ((char *)0 == (pcName = ttyname(fd))) {
return -1;
}
(void)strcpy(acSlave, pcName);
*slave = acSlave;
(void)strcpy(acMaster, pcName);
acMaster[7] = 'c';
*master = acMaster;
return fd;
}
#else
#if HAVE_PTSNAME
/* get a pty for the user -- emulate the neato sequent call under (gregf)
* DYNIX/ptx v4.0
*/
static int
getpseudotty(slave, master)
char **master, **slave;
{
int fd;
char *pcName, *pcTmp;
if (0 > (fd = open("/dev/ptmx", O_RDWR, 0))) {
return -1;
}
grantpt(fd); /* change permission of slave */
unlockpt(fd); /* unlock slave */
if ((char *)0 == (pcName = ttyname(fd))) {
return -1;
}
(void)strcpy(acMaster, pcName);
*master = acMaster;
if ((char *) 0 == (pcName = ptsname(fd))) {
return -1;
}
(void)strcpy(acSlave, pcName);
*slave = acSlave;
return fd;
}
#else
/*
* get a pty for the user (emulate the neato sequent call) (ksb)
*/
static int
getpseudotty(slave, master)
char **master, **slave;
{
static char *pcOne = charone, *pcTwo = chartwo;
auto int fd, iLoop, iIndex = sizeof("/dev/pty")-1;
auto char *pcOld1;
auto struct stat statBuf;
iLoop = 0;
pcOld1 = pcOne;
for (;;) {
if ('\000' == *++pcTwo) {
pcTwo = chartwo;
if ('\000' == *++pcOne) {
pcOne = charone;
if (pcOld1 == pcOne && ++iLoop > 1 || iLoop > 32)
return -1;
}
}
acMaster[iIndex] = *pcOne;
acMaster[iIndex+1] = *pcTwo;
/*
* Remeber we are root - stat the file
* to see if it exists before we open it
* for read/write - if it doesn't we don't
* have any pty's left in the row
*/
if (-1 == stat(acMaster, &statBuf) || S_IFCHR != (statBuf.st_mode&S_IFMT)) {
pcTwo = "l";
continue;
}
if (0 > (fd = open(acMaster, O_RDWR|O_NDELAY, 0))) {
continue;
}
acSlave[iIndex] = *pcOne;
acSlave[iIndex+1] = *pcTwo;
if (-1 == access(acSlave, F_OK)) {
(void) close(fd);
continue;
}
break;
}
*master = acMaster;
*slave = acSlave;
return fd;
}
#endif /* PTX version */
#endif /* _AIX */
#endif /* !HAVE_GETPSEUDO */
/*
* get a Joe pty bacause the daemon is not with us, sadly. (ksb)
*/
int
FallBack(pcSlave, pcMaster)
char *pcSlave, *pcMaster;
{
auto int fd;
auto char *pcTSlave, *pcTMaster;
if (-1 == (fd = getpseudotty(& pcTSlave, & pcTMaster))) {
return -1;
}
(void) strcpy(pcSlave, pcTSlave);
(void) strcpy(pcMaster, pcTMaster);
return fd;
}
#endif /* no code if it is not used */

1643
conserver/group.c Normal file

File diff suppressed because it is too large Load Diff

42
conserver/group.h Normal file
View File

@ -0,0 +1,42 @@
/*
* $Id: group.h,v 5.8 1994-07-19 09:40:23-07 ksb Exp $
*
* Copyright 1992 Purdue Research Foundation, West Lafayette, Indiana
* 47907. All rights reserved.
*
* Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb
*
* This software is not subject to any license of the American Telephone
* and Telegraph Company or the Regents of the University of California.
*
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
*
* 1. Neither the authors nor Purdue University are responsible for any
* consequences of the use of this software.
*
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Credit to the authors and Purdue
* University must appear in documentation and sources.
*
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 4. This notice may not be removed or altered.
*/
#define MAXPSWDLEN 16 /* max length of encrypted password */
typedef struct grpent { /* group info */
int port; /* port group listens on */
int pid; /* pid of server for group */
int imembers; /* number of consoles in this group */
CONSENT *pCElist; /* list of consoles in this group */
CLIENT *pCLall; /* all clients to scan after select */
char passwd[MAXPSWDLEN];/* encrypted password for this group */
} GRPENT;
extern void Spawn();
extern int CheckPass();

179
conserver/identd.c Normal file
View File

@ -0,0 +1,179 @@
/*@Header@*/
/*
* ident_client.c
*
* Identifies the remote user of a given connection.
*
* Written 940112 by Luke Mewburn <lm@rmit.edu.au>
*
* Copyright (C) 1994 by Luke Mewburn.
* This code may be used freely by anyone as long as this copyright remains.
*
* $Compile(*): ${cc-cc} ${cc_debug--g} -DTEST %f -o %F -lsocket -lnls
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include "identd.h"
#define IDENT_PORT 113
/*@Explode cli@*/
/* (lm)
* ident_client
* - user interface to identd
*
* Args:
* peeraddr sockaddr_in struct of peer end, from getpeername(...)
* ouraddr sockaddr_in struct of local end, from getsockname(...)
*
* Returns:
* NULL on failure to identify (for whatever reason), or pointer to
* static character string with the identity.
*/
char *
ident_client(peeraddr, ouraddr, identifier)
struct sockaddr_in peeraddr, ouraddr;
char *identifier/*[1024]*/;
{
struct sockaddr_in authcon;
int authfd, authlen;
struct servent *identserv;
int identport;
FILE *authfpin, *authfpout;
char buffer[8192]; /* XXX: argh! magic numbers */
char reply_type[81];
char opsys_or_err[81];
int rport, lport;
authfd = socket(AF_INET, SOCK_STREAM, 0);
if (authfd == -1)
return NULL;
identserv = getservbyname("ident", "tcp");
if (identserv)
identport = identserv->s_port;
else
identport = ntohs(IDENT_PORT);
memset(&authcon, 0, sizeof(authcon));
authcon.sin_family = AF_INET;
authcon.sin_addr.s_addr = peeraddr.sin_addr.s_addr;
authcon.sin_port = identport;
authlen = sizeof(authcon);
if (connect(authfd, (struct sockaddr *)&authcon, authlen) < 0)
return NULL;
authfpin = fdopen(authfd, "r");
authfpout = fdopen(authfd, "w");
if (!authfpin || !authfpout)
return NULL;
fprintf(authfpout, "%d , %d\n", peeraddr.sin_port, ouraddr.sin_port);
fflush(authfpout);
if (fgets(buffer, sizeof(buffer)-1, authfpin) == NULL)
return NULL;
shutdown(authfd, 1);
authlen = sscanf(buffer, "%d , %d : %[^ \t\n\r:] : %[^ \t\n\r:] : %[^\n\r]",
&lport, &rport, reply_type, opsys_or_err, identifier);
if (authlen < 3)
return NULL;
if (0 == strcasecmp(reply_type, "ERROR")) {
printf("error %s\n", buffer);
return NULL;
}
if (0 != strcasecmp(reply_type, "USERID")) {
printf("no-user %s\n", buffer);
return NULL;
}
return identifier;
} /* ident_client */
/*@Remove@*/
#if defined(TEST)
/*@Explode main@*/
extern int errno;
extern char *sys_errlist[];
#define strerror(Me) (sys_errlist[Me])
static struct sockaddr_in master_port, response_port;
char *progname = "identd-test";
/* test driver for the identd client module (ksb)
* bind to a port, wait for telnets and tell them who they are
*/
int
main(argc, argv, envp)
int argc;
char **argv, **envp;
{
auto struct sockaddr_in hisaddr, ouraddr;
register int mfd, cfd;
auto int true = 1, length, so;
auto char them[1024];
(void)memset((void *)&master_port, 0, sizeof(master_port));
master_port.sin_family = AF_INET;
*(u_long *)&master_port.sin_addr = INADDR_ANY;
master_port.sin_port = htons(7098);
if (-1 == (mfd = socket(AF_INET, SOCK_STREAM, 0))) {
fprintf(stderr, "%s: socket: %s\n", progname, strerror(errno));
exit(1);
}
#if defined(SO_REUSEADDR) && defined(SOL_SOCKET)
if (setsockopt(mfd, SOL_SOCKET, SO_REUSEADDR, (char *)&true, sizeof(true)) < 0) {
fprintf(stderr, "%s: setsockopt: %s\n", progname, strerror(errno));
exit(1);
}
#endif
if (bind(mfd, (struct sockaddr *)&master_port, sizeof(master_port))<0) {
fprintf(stderr, "%s: bind: %s\n", progname, strerror(errno));
exit(1);
}
if (listen(mfd, SOMAXCONN) < 0) {
fprintf(stderr, "%s: listen: %s\n", progname, strerror(errno));
exit(1);
}
length = sizeof(ouraddr);
if (getsockname(mfd, (struct sockaddr *)&ouraddr, &length) < 0) {
fprintf(stderr, "%s: getsockname: %d: %s\n", progname, mfd, strerror(errno));
}
while (so = sizeof(response_port), -1 != (cfd = accept(mfd, (struct sockaddr *)&response_port, &so))) {
printf("%d\n", cfd);
length = sizeof(hisaddr);
if (getpeername(cfd, (struct sockaddr *)&hisaddr, &length) < 0) {
write(cfd, "can't get your addrees?\n", 24);
} else if ((char *)0 != ident_client(hisaddr, ouraddr, them)) {
write(cfd, them, strlen(them));
write(cfd, "\n", 1);
} else {
write(cfd, "no identd?\n", 11);
}
close(cfd);
printf("closed\n");
}
exit(0);
}
/*@Remove@*/
#endif /* test driver */

26
conserver/init.script Executable file
View File

@ -0,0 +1,26 @@
#!/bin/sh
#
# Startup for conserver
#
PATH=/usr/bin:/usr/local/bin
case "$1" in
'start')
LF=/var/log/conserver.log
echo "Starting console server daemon"
[ -f $LF ] && mv $LF $LF.old
conserver -n -d > $LF 2>&1
;;
'stop')
master=`ps -ef | grep conserver | awk '$3 == "1"{print $2}'`
[ "$master" ] && kill -TERM $master
;;
*)
echo "Usage: $0 { start | stop }"
;;
esac
exit 0

380
conserver/main.c Normal file
View File

@ -0,0 +1,380 @@
/*
* Copyright (c) 1990 The Ohio State University.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by The Ohio State University and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <pwd.h>
#include "cons.h"
#include "consent.h"
#include "client.h"
#include "group.h"
#include "master.h"
#include "access.h"
#include "readcfg.h"
#include "version.h"
#if USE_STRINGS
#include <strings.h>
#else
#include <string.h>
#endif
char rcsid[] =
"$Id: main.c,v 5.27 1998-11-19 14:32:45-08 bryan Exp $";
char *progname =
rcsid;
int fAll = 1, fVerbose = 0, fSoftcar = 0;
int fDaemon = 0;
char chDefAcc = 'r';
char *pcConfig = CONFIG;
int domainHack = 0;
#if defined(SERVICE)
char acService[] = SERVICE;
#endif
struct sockaddr_in in_port;
char acMyAddr[4]; /* "\200\76\7\1" */
char acMyHost[256]; /* staff.cc.purdue.edu */
/* become a daemon (ksb)
*/
static void
daemonize()
{
int res, td;
(void) signal(SIGQUIT, SIG_IGN);
(void) signal(SIGINT, SIG_IGN);
#if defined(SIGTTOU)
(void) signal(SIGTTOU, SIG_IGN);
#endif
#if defined(SIGTSTP)
(void) signal(SIGTSTP, SIG_IGN);
#endif
switch (res = fork()) {
case -1:
(void) fprintf(stderr, "%s: fork: %m\n", progname, strerror(errno));
exit(1);
case 0:
break;
default:
sleep(1);
exit(0);
}
/* if we read from stdin (by accident) we don't wanna block
*/
close(0);
if (0 != open("/dev/null", 2, 0644)) {
fprintf(stderr, "%s: open: /dev/null: %s\n", progname, strerror(errno));
exit(1);
}
/* Further disassociate this process from the terminal
* Maybe this will allow you to start a daemon from rsh,
* i.e. with no controlling terminal.
*/
#if HAVE_SETSID
(void)setsid();
#else
(void) setpgrp(0, getpid());
/* lose our controlling terminal
*/
if (-1 != (td = open("/dev/tty", O_RDWR, 0600))) {
(void)ioctl(td, TIOCNOTTY, (char *)0);
close(td);
}
#endif
}
static char *apcLong[] = {
"a type set the default access type",
"C config give a new config file to the server process",
"d become a daemon, output to /dev/null",
"h output this message",
"n do not output summary stream to stdout",
"v be verbose on startup",
"V output version info",
(char *)0
};
/* output a long message to the user (ksb)
*/
static void
Usage(fp, ppc)
FILE *fp;
char **ppc;
{
for (/* passed */; (char *)0 != *ppc; ++ppc)
(void)fprintf(fp, "%s\n", *ppc);
}
/* show the user our version info (ksb)
*/
static void
Version()
{
auto char acA1[16], acA2[16];
printf("%s: %s\n", progname, GNAC_VERSION);
printf("%s: default access type `%c\'\n", progname, chDefAcc);
printf("%s: default escape sequence `%s%s\'\n", progname, FmtCtl(DEFATTN, acA1), FmtCtl(DEFESC, acA2));
printf("%s: configuration in `%s\'\n", progname, pcConfig);
printf("%s: password in `%s\'\n", progname, PASSWD_FILE);
printf("%s: limited to %d group%s with %d member%s\n", progname, MAXGRP, MAXGRP == 1 ? "" : "s", MAXMEMB, MAXMEMB == 1 ? "" : "s");
#if defined(SERVICE)
{
struct servent *pSE;
if ((struct servent *)0 == (pSE = getservbyname(acService, "tcp"))) {
fprintf(stderr, "%s: getservbyname: %s: %s\n", progname, acService, strerror(errno));
return;
}
printf("%s: service name `%s\'", progname, pSE->s_name);
if (0 != strcmp(pSE->s_name, acService)) {
printf(" (which we call `%s\')", acService);
}
printf(" on port %d\n", ntohs((u_short)pSE->s_port));
}
#else
#if defined(PORT)
printf("%s: on port %d\n", progname, PORT);
#else
printf("%s: no service or port compiled in\n", progname);
exit(1);
#endif
#endif
}
/* find out where/who we are (ksb)
* parse optons
* read in the config file, open the log file
* spawn the kids to drive the console groups
* become the master server
* shutdown with grace
* exit happy
*/
int
main(argc, argv)
int argc;
char **argv;
{
register int i, j;
register FILE *fpConfig;
auto struct hostent *hpMe;
static char acOpts[] = "a:C:dhnsVv",
u_terse[] = " [-dhnsvV] [-a type] [-C config]";
extern int optopt;
extern char *optarg;
auto REMOTE
*pRCUniq; /* list of uniq console servers */
if ((char *)0 == (progname = strrchr(argv[0], '/'))) {
progname = argv[0];
} else {
++progname;
}
(void)setpwent();
#if USE_SETLINEBUF
setlinebuf(stderr);
#endif
#if USE_SETVBUF
setvbuf(stderr, NULL, _IOLBF, BUFSIZ);
#endif
(void)gethostname(acMyHost, sizeof(acMyHost));
if ((struct hostent *)0 == (hpMe = gethostbyname(acMyHost))) {
fprintf(stderr, "%s: gethostbyname: %s\n", progname, hstrerror(h_errno));
exit(1);
}
if (sizeof(acMyAddr) != hpMe->h_length || AF_INET != hpMe->h_addrtype) {
fprintf(stderr, "%s: wrong address size (%d != %d) or adress family (%d != %d)\n", progname, sizeof(acMyAddr), hpMe->h_length, AF_INET, hpMe->h_addrtype);
exit(1);
}
#if USE_STRINGS
(void)bcopy(hpMe->h_addr, &acMyAddr[0], hpMe->h_length);
#else
(void)memcpy(&acMyAddr[0], hpMe->h_addr, hpMe->h_length);
#endif
while (EOF != (i = getopt(argc, argv, acOpts))) {
switch (i) {
case 'a':
chDefAcc = '\000' == *optarg ? 'r' : *optarg;
if (isupper(chDefAcc)) {
chDefAcc = tolower(chDefAcc);
}
switch (chDefAcc) {
case 'r':
case 'a':
case 't':
break;
default:
fprintf(stderr, "%s: unknown access type `%s\'\n", progname, optarg);
exit(3);
}
break;
case 'C':
pcConfig = optarg;
break;
case 'd':
fDaemon = 1;
break;
case 'h':
fprintf(stderr, "%s: usage%s\n", progname, u_terse);
Usage(stdout, apcLong);
exit(0);
case 'n':
fAll = 0;
break;
case 's':
fSoftcar ^= 1;
break;
case 'V':
Version();
exit(0);
case 'v':
fVerbose = 1;
break;
case '\?':
fprintf(stderr, "%s: usage%s\n", progname, u_terse);
exit(1);
default:
fprintf(stderr, "%s: option %c needs a parameter\n", progname, optopt);
exit(1);
}
}
/* Why force root??? Cause of getsp*() calls... */
if (0 != geteuid()) {
fprintf(stderr, "%s: must be the superuser\n", progname);
exit(1);
}
/* read the config file
*/
if ((FILE *)0 == (fpConfig = fopen(pcConfig, "r"))) {
fprintf(stderr, "%s: fopen: %s: %s\n", progname, pcConfig, strerror(errno));
exit(1);
}
ReadCfg(pcConfig, fpConfig);
#if USE_FLOCK
/* we lock the configuration file so that two identical
* conservers will not be running together (but two with
* different configurations can run on the same host).
*/
if (-1 == flock(fileno(fpConfig), LOCK_NB|LOCK_EX)) {
fprintf(stderr, "%s: %s is locked, won\'t run more than one conserver?\n", progname, pcConfig);
exit(3);
}
#endif
/* if no one can use us we need to come up with a default
*/
if (0 == iAccess) {
SetDefAccess(hpMe);
}
#if USE_SETLINEBUF
setlinebuf(stdout);
#endif
#if USE_SETVBUF
setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
#endif
(void)fflush(stdout);
(void)fflush(stderr);
if (fDaemon) {
daemonize();
}
/* spawn all the children, so fix kids has an initial pid
*/
for (i = 0; i < MAXGRP; ++i) {
if (0 == aGroups[i].imembers)
continue;
if (aGroups[i].imembers) {
Spawn(& aGroups[i]);
}
if (fVerbose) {
printf("%s: group %d on port %d\n", progname, i, ntohs((u_short)aGroups[i].port));
}
for (j = 0; j < aGroups[i].imembers; ++j) {
if (-1 != aGroups[i].pCElist[j].fdtty)
(void)close(aGroups[i].pCElist[j].fdtty);
}
}
if (fVerbose) {
for (i = 0; i < iAccess; ++i) {
printf("%s: access type '%c' for \"%s\"\n", progname, pACList[i].ctrust, pACList[i].pcwho);
}
}
pRCUniq = FindUniq(pRCList);
/* output unique console server peers?
*/
if (fVerbose) {
register REMOTE *pRC;
for (pRC = pRCUniq; (REMOTE *)0 != pRC; pRC = pRC->pRCuniq) {
printf("%s: peer server on `%s'\n", progname, pRC->rhost);
}
}
(void)fflush(stdout);
(void)fflush(stderr);
/*
if (fDaemon) {
daemonize();
}
*/
Master(pRCUniq);
/* stop putting kids back, and shoot them
*/
(void)signal(SIGCHLD, SIG_DFL);
for (i = 0; i < MAXGRP; ++i) {
if (0 == aGroups[i].imembers)
continue;
if (-1 == kill(aGroups[i].pid, SIGTERM)) {
fprintf(stderr, "%s: kill: %s\n", progname, strerror(errno));
}
}
(void)endpwent();
(void)fclose(fpConfig);
exit(0);
}

43
conserver/main.h Normal file
View File

@ -0,0 +1,43 @@
/*
* $Id: main.h,v 5.8 1998-11-17 18:42:27-08 bryan Exp $
*
* Copyright 1992 Purdue Research Foundation, West Lafayette, Indiana
* 47907. All rights reserved.
*
* Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb
*
* This software is not subject to any license of the American Telephone
* and Telegraph Company or the Regents of the University of California.
*
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
*
* 1. Neither the authors nor Purdue University are responsible for any
* consequences of the use of this software.
*
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Credit to the authors and Purdue
* University must appear in documentation and sources.
*
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 4. This notice may not be removed or altered.
*/
/* program options and stuff
*/
extern char rcsid[];
extern char *progname;
extern int fAll, fVerbose, fSoftcar, fInteractive;
extern char chDefAcc;
extern char *pcConfig;
extern struct sockaddr_in in_port;
extern char acMyHost[];
extern int domainHack;
#if defined(SERVICE)
extern char acService[];
#endif

453
conserver/master.c Normal file
View File

@ -0,0 +1,453 @@
/*
* $Id: master.c,v 5.19 1998-11-17 23:14:51-08 bryan Exp $
*
* Copyright (c) 1990 The Ohio State University.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by The Ohio State University and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <pwd.h>
#include "cons.h"
#include "consent.h"
#include "client.h"
#include "group.h"
#include "access.h"
#include "master.h"
#include "readcfg.h"
#include "version.h"
#include "main.h"
#if USE_STRINGS
#include <strings.h>
#else
#include <string.h>
#endif
#if USE_SYS_TIME_H
#include <sys/time.h>
#else
#include <time.h>
#endif
#include <sys/resource.h>
extern char *crypt();
extern time_t time();
/* check all the kids and respawn as needed. (fine)
* Called when master process receives SIGCHLD
*/
static SIGRETS
FixKids(arg)
int arg;
{
register int i, pid;
auto long tyme;
auto WAIT_T UWbuf;
#if HAVE_WAIT3
while (-1 != (pid = wait3(& UWbuf, WNOHANG, (struct rusage *)0))) {
#else
while (-1 != (pid = wait(& UWbuf))) {
#endif
if (0 == pid) {
break;
}
/* stopped child is just continuted
*/
if (WIFSTOPPED(UWbuf) && 0 == kill(pid, SIGCONT)) {
continue;
}
for (i = 0; i < MAXGRP; ++i) {
if (0 == aGroups[i].imembers)
continue;
if (pid != aGroups[i].pid)
continue;
/* this kid kid is dead, start another
*/
Spawn(& aGroups[i]);
tyme = time((long *)0);
printf("%s: %s: exit(%d), restarted %s", progname, aGroups[i].pCElist[0].server, WEXITSTATUS(UWbuf), ctime(&tyme));
}
}
}
static int fSawQuit;
/* kill all the kids and exit.
* Called when master process receives SIGTERM
*/
static SIGRETS
QuitIt(arg)
int arg;
{
++fSawQuit;
}
/* this routine is used by the master console server process (ksb)
*/
void
Master(pRCUniq)
REMOTE
*pRCUniq; /* list of uniq console servers */
{
register char *pcArgs;
register int i, j, cfd;
register REMOTE *pRC, *pRCFound;
register int nr, prnum, found, msfd;
register struct hostent *hpPeer;
auto char cType;
auto int so;
auto fd_set rmask, rmaster;
auto char acIn[1024], acOut[BUFSIZ];
auto struct sockaddr_in master_port, response_port;
int true = 1;
/* set up signal handler */
(void)signal(SIGCHLD, FixKids);
(void)signal(SIGTERM, QuitIt);
/* set up port for master to listen on
*/
#if USE_STRINGS
(void)bzero((char *)&master_port, sizeof(master_port));
#else
(void)memset((void *)&master_port, 0, sizeof(master_port));
#endif
master_port.sin_family = AF_INET;
*(u_long *)&master_port.sin_addr = INADDR_ANY;
#if defined(SERVICE)
{
struct servent *pSE;
if ((struct servent *)0 == (pSE = getservbyname(acService, "tcp"))) {
fprintf(stderr, "%s: getservbyname: %s: %s\n", progname, acService, strerror(errno));
return;
}
master_port.sin_port = pSE->s_port;
}
#else
#if defined(PORT)
master_port.sin_port = htons((u_short)PORT);
#else
fprintf(stderr, "%s: no port or service compiled in?\n", progname);
#endif
#endif
if ((msfd=socket(AF_INET, SOCK_STREAM, 0)) < 0) {
fprintf(stderr, "%s: socket: %s\n", progname, strerror(errno));
return;
}
#if HAVE_SETSOCKOPT
if (setsockopt(msfd, SOL_SOCKET, SO_REUSEADDR, (char *)&true, sizeof(true))<0) {
fprintf(stderr, "%s: setsockopt: %s\n", progname, strerror(errno));
return;
}
#endif
if (bind(msfd, (struct sockaddr *)&master_port, sizeof(master_port))<0) {
fprintf(stderr, "%s: bind: %s\n", progname, strerror(errno));
return;
}
if (listen(msfd, SOMAXCONN) < 0) {
fprintf(stderr, "%s: listen: %s\n", progname, strerror(errno));
}
FD_ZERO(&rmaster);
FD_SET(msfd, &rmaster);
for (fSawQuit = 0; !fSawQuit; /* can't close here :-( */) {
rmask = rmaster;
if (-1 == select(msfd+1, &rmask, (fd_set *)0, (fd_set *)0, (struct timeval *)0)) {
fprintf(stderr, "%s: select: %s\n", progname, strerror(errno));
continue;
}
if (!FD_ISSET(msfd, &rmask)) {
continue;
}
so = sizeof(response_port);
cfd = accept(msfd, (struct sockaddr *)&response_port, &so);
if (cfd < 0) {
fprintf(stderr, "%s: accept: %s\n", progname, strerror(errno));
continue;
}
so = sizeof(in_port);
if (-1 == getpeername(cfd, (struct sockaddr *)&in_port, &so)) {
CSTROUT(cfd, "getpeername failed\r\n");
(void)close(cfd);
continue;
}
so = sizeof(in_port.sin_addr);
if ((struct hostent *)0 == (hpPeer = gethostbyaddr((char *)&in_port.sin_addr, so, AF_INET))) {
CSTROUT(cfd, "unknown peer name\r\n");
(void)close(cfd);
continue;
}
if ('r' == (cType = AccType(hpPeer))) {
CSTROUT(cfd, "access from your host refused\r\n");
(void)close(cfd);
continue;
}
#if TEST_FORK
/* we should fork here, or timeout
*/
switch(fork()) {
default:
(void)close(cfd);
continue;
case -1:
CSTROUT(cfd, "fork failed, try again\r\n");
(void)close(cfd);
continue;
case 0:
break;
}
#endif
/* handle the connection
* (port lookup, who, users, or quit)
*/
CSTROUT(cfd, "ok\r\n");
for (i = 0; i < sizeof(acIn); /* i+=nr */) {
if (0 >= (nr = read(cfd, &acIn[i], sizeof(acIn)-1-i))) {
i = 0;
break;
}
i += nr;
if ('\n' == acIn[i-1]) {
acIn[i] = '\000';
--i;
break;
}
}
if (i > 0 && '\n' == acIn[i-1]) {
acIn[--i] = '\000';
}
if (i > 0 && '\r' == acIn[i-1]) {
acIn[--i] = '\000';
}
if (0 == i) {
fprintf(stderr, "%s: lost connection\n", progname);
(void)close(cfd);
#if TEST_FORK
exit(1);
#else
continue;
#endif
}
if ((char *)0 != (pcArgs = strchr(acIn, ':'))) {
*pcArgs++ = '\000';
} else if ((char *)0 != (pcArgs = strchr(acIn, ' '))) {
*pcArgs++ = '\000';
}
if (0 == strcmp(acIn, "help")) {
static char *apcHelp[] = {
"call provide port for given machine\r\n",
"groups provide ports for group leaders\r\n",
"help this help message\r\n",
"master provide a list of master servers\r\n",
"pid provide pid of master process\r\n",
"quit terminate conserver\r\n",
"version provide version info for server\r\n",
(char *)0
};
register char **ppc;
for (ppc = apcHelp; (char *)0 != *ppc; ++ppc) {
(void)write(cfd, *ppc, strlen(*ppc));
}
(void)close(cfd);
#if TEST_FORK
exit(0);
#else
continue;
#endif
}
if (0 == strcmp(acIn, "quit")) {
register struct passwd *pwd;
if ('t' == cType) {
CSTROUT(cfd, "trusted -- terminated\r\n");
#if TEST_FORK
kill(getppid(), SIGTERM);
#else
fSawQuit = 1;
#endif
} else if ((char *)0 == pcArgs) {
CSTROUT(cfd, "must be trusted to terminate\r\n");
} else if ((struct passwd *)0 == (pwd = getpwuid(0))) {
CSTROUT(cfd, "no root passwd?\r\n");
} else if (0 == CheckPass(pwd, (char *)0, pcArgs)) {
CSTROUT(cfd, "Sorry.\r\n");
} else {
CSTROUT(cfd, "ok -- terminated\r\n");
#if TEST_FORK
kill(getppid(), SIGTERM);
#else
fSawQuit = 1;
#endif
}
(void)close(cfd);
#if TEST_FORK
exit(0);
#else
continue;
#endif
}
if (0 == strcmp(acIn, "pid")) {
#if TEST_FORK
sprintf(acOut, "%d\r\n", getppid());
(void)write(cfd, acOut, strlen(acOut));
exit(0);
#else
sprintf(acOut, "%d\r\n", getpid());
(void)write(cfd, acOut, strlen(acOut));
continue;
#endif
}
if (0 == strcmp(acIn, "groups")) {
register int iSep = 1;
for (i = 0; i < MAXGRP; ++i) {
if (0 == aGroups[i].imembers)
continue;
sprintf(acOut, ":%d"+iSep, ntohs((u_short)aGroups[i].port));
(void)write(cfd, acOut, strlen(acOut));
iSep = 0;
}
CSTROUT(cfd, "\r\n");
(void)close(cfd);
#if TEST_FORK
exit(0);
#else
continue;
#endif
}
if (0 == strcmp(acIn, "master")) {
register int iSep = 1;
if (0 != iLocal) {
sprintf(acOut, "@%s", acMyHost);
(void)write(cfd, acOut, strlen(acOut));
iSep = 0;
}
for (pRC = pRCUniq; (REMOTE *)0 != pRC; pRC = pRC->pRCuniq) {
sprintf(acOut, ":@%s"+iSep, pRC->rhost);
(void)write(cfd, acOut, strlen(acOut));
iSep = 0;
}
CSTROUT(cfd, "\r\n");
(void)close(cfd);
#if TEST_FORK
exit(0);
#else
continue;
#endif
}
if (0 == strcmp(acIn, "version")) {
sprintf(acOut, "version `%s\'\r\n", GNAC_VERSION);
(void)write(cfd, acOut, strlen(acOut));
#if TEST_FORK
exit(0);
#else
continue;
#endif
}
if (0 != strcmp(acIn, "call")) {
CSTROUT(cfd, "unknown command\r\n");
(void)close(cfd);
#if TEST_FORK
exit(0);
#else
continue;
#endif
}
/* look up the machine to call
*/
found = 0;
pRCFound = (REMOTE *)0;
/* look for a local machine */
for (i = 0; i < MAXGRP; ++i) {
if (0 == aGroups[i].imembers)
continue;
for (j = 0; j < aGroups[i].imembers; ++j) {
if (0 != strcmp(pcArgs, aGroups[i].pCElist[j].server)) {
continue;
}
prnum = ntohs((u_short)aGroups[i].port);
++found;
}
}
if ( found == 0 ) { /* Then look for substring matches */
for (i = 0; i < MAXGRP; ++i) {
if (0 == aGroups[i].imembers)
continue;
for (j = 0; j < aGroups[i].imembers; ++j) {
if (0 != strncmp(pcArgs, aGroups[i].pCElist[j].server, strlen(pcArgs))) {
continue;
}
prnum = ntohs((u_short)aGroups[i].port);
++found;
}
}
}
/* look for a remote server */
for (pRC = pRCList; (REMOTE *)0 != pRC; pRC = pRC->pRCnext) {
if (0 != strncmp(pcArgs, pRC->rserver, strlen(pcArgs))) {
continue;
}
++found;
pRCFound = pRC;
}
switch (found) {
case 0:
sprintf(acOut, "server %s not found\r\n", pcArgs);
break;
case 1:
if ((REMOTE *)0 != pRCFound) {
sprintf(acOut, "@%s\r\n", pRCFound->rhost, pcArgs);
} else {
sprintf(acOut, "%d\r\n", prnum);
}
break;
default:
sprintf(acOut, "ambigous server abbreviation, %s\r\n", pcArgs);
break;
}
(void)write(cfd, acOut, strlen(acOut));
(void)close(cfd);
#if TEST_FORK
exit(0);
#endif
}
}

32
conserver/master.h Normal file
View File

@ -0,0 +1,32 @@
/*
* $Id: master.h,v 5.6 1993-02-09 04:01:31-08 ldv Exp $
*
* Copyright 1992 Purdue Research Foundation, West Lafayette, Indiana
* 47907. All rights reserved.
*
* Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb
*
* This software is not subject to any license of the American Telephone
* and Telegraph Company or the Regents of the University of California.
*
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
*
* 1. Neither the authors nor Purdue University are responsible for any
* consequences of the use of this software.
*
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Credit to the authors and Purdue
* University must appear in documentation and sources.
*
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 4. This notice may not be removed or altered.
*/
/*
* stuff the master process needs
*/
extern void Master();

384
conserver/readcfg.c Normal file
View File

@ -0,0 +1,384 @@
/*
* $Id: readcfg.c,v 5.21 1998-12-14 11:20:15-08 bryan Exp $
*
* Copyright (c) 1990 The Ohio State University.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by The Ohio State University and its contributors''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software. Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/*
* Network console modifications by Robert Olson, olson@mcs.anl.gov.
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <signal.h>
#include <pwd.h>
#include "cons.h"
#include "consent.h"
#include "client.h"
#include "group.h"
#include "access.h"
#include "readcfg.h"
#include "master.h"
#include "main.h"
#if USE_STRINGS
#include <strings.h>
#else
#include <string.h>
#endif
GRPENT
aGroups[MAXGRP]; /* even spread is OK */
CONSENT
aConsoles[MAXGRP*MAXMEMB]; /* gross over allocation */
REMOTE
*pRCList; /* list of remote consoles we know about */
int
iLocal; /* number of local consoles */
ACCESS
*pACList; /* `who do you love' (or trust) */
int
iAccess; /* how many access restrictions we have */
/* read in the configuration file, fill in all the structs we use (ksb)
* to manage the consoles
*/
void
ReadCfg(pcFile, fp)
char *pcFile;
register FILE *fp;
{
register GRPENT *pGE;
register int iG, minG;
auto int iLine;
auto char acIn[BUFSIZ];
register GRPENT *pGEAll;
register CONSENT *pCE;
register REMOTE **ppRC;
char LogDirectory[MAXLOGLEN];
long tyme;
tyme = time((long *)0);
LogDirectory[0] = '\000';
pGEAll = aGroups; /* fill in these structs */
pCE = aConsoles;
ppRC = & pRCList;
iLocal = 0;
iG = minG = 0;
iLine = 0;
while (fgets(acIn, sizeof(acIn)-1, fp) != NULL) {
register char *pcLine, *pcMode, *pcLog, *pcRem, *pcStart, *pcMark;
++iLine;
for (pcRem = acIn+strlen(acIn)-1; pcRem >= acIn; --pcRem) {
if (!isspace(*pcRem))
break;
*pcRem = '\000';
if (pcRem == acIn)
break;
}
if ('#' == acIn[0] || '\000' == acIn[0]) {
continue;
}
if ('%' == acIn[0] && '%' == acIn[1] && '\000' == acIn[2]) {
break;
}
if ( (char *)0 == strchr(acIn, ':') &&
(char *)0 != (pcLine = strchr(acIn, '=')) ) {
*pcLine = '\000';
if ( 0 == strcmp(acIn, "LOGDIR") ) {
(void)strcpy(LogDirectory, ++pcLine);
} else if ( 0 == strcmp(acIn, "DOMAINHACK") ) {
domainHack = 1;
} else {
*pcLine = '=';
fprintf(stderr, "%s: %s(%d) bad variable line `%s'\n", progname, pcFile, iLine, acIn);
}
continue;
}
if ( (char *)0 == (pcLine = strchr(acIn, ':')) ||
(char *)0 == (pcMode = strchr(pcLine+1, ':')) ||
(char *)0 == (pcLog = strchr(pcMode+1, ':'))) {
fprintf(stderr, "%s: %s(%d) bad config line `%s'\n", progname, pcFile, iLine, acIn);
continue;
}
*pcLine++ = '\000';
*pcMode++ = '\000';
*pcLog++ = '\000';
if ((char *)0 != (pcMark = strchr(pcLog, ':'))) {
*pcMark++ = '\000';
/* Skip null intervals */
if ( pcMark[0] == '\000' ) pcMark = (char *)0;
}
/* if this server remote?
* (contains an '@host' where host is not us)
* if so just add it to a linked list of remote hosts
* I'm sure most sites will never use this code (ksb)
*/
if ((char *)0 != (pcRem = strchr(pcLine, '@')) &&
((*pcRem++ = '\000'), 0 != strcmp(acMyHost, pcRem))) {
register REMOTE *pRCTemp;
pRCTemp = (REMOTE *)calloc(1, sizeof(REMOTE));
if ((REMOTE *)0 == pRCTemp) {
CSTROUT(2, "out of memory!\n");
exit(32);
}
(void)strcpy(pRCTemp->rhost, pcRem);
(void)strcpy(pRCTemp->rserver, acIn);
*ppRC = pRCTemp;
ppRC = & pRCTemp->pRCnext;
if (fVerbose) {
printf("%s: %s remote on %s\n", progname, acIn, pcRem);
}
continue;
}
/* take the same group as the last line, by default
*/
if (MAXMEMB == pGEAll[iG].imembers) {
++iG;
}
if (iG < minG || iG >= MAXGRP) {
fprintf(stderr, "%s: %s(%d) group number out of bounds %d <= %d < %d\n", progname, pcFile, iLine, minG, iG, MAXGRP);
exit(1);
}
minG = iG;
pGE = pGEAll+iG;
if (0 == pGE->imembers++) {
pGE->pCElist = pCE;
}
if (pGE->imembers > MAXMEMB) {
fprintf(stderr, "%s: %s(%d) group %d has more than %d members -- but we'll give it a spin\n", progname, pcFile, iLine, iG, MAXMEMB);
}
/* fill in the console entry
*/
if (sizeof(aConsoles)/sizeof(CONSENT) == iLocal) {
fprintf(stderr, "%s: %s(%d) %d is too many consoles for hard coded tables, adjust MAXGRP or MAXMEMB\n", progname, pcFile, iLine, iLocal);
exit(1);
}
(void)strcpy(pCE->server, acIn);
/*
* Here we substitute the console name for any '&' character in the
* logfile name. That way you can just have something like
* "/var/console/&" for each of the conserver.cf entries.
*/
*(pCE->lfile) = '\000';
pcStart = pcLog;
while ((char *)0 != (pcRem = strchr(pcStart, '&'))) {
*pcRem = '\000';
(void)strcat(pCE->lfile, pcStart);
(void)strcat(pCE->lfile, acIn);
pcStart = pcRem + 1;
}
(void)strcat(pCE->lfile, pcStart);
if ( LogDirectory[0] && (pCE->lfile)[0] != '/' ) {
char lfile[MAXLOGLEN];
strcpy( lfile, pCE->lfile );
strcpy( pCE->lfile, LogDirectory );
strcat( pCE->lfile, "/" );
strcat( pCE->lfile, lfile );
}
if ( pcMark ) {
int factor;
char *p;
p = pcMark + strlen(pcMark) - 1;
if ( *p == 'm' ) {
factor = 60;
} else if ( *p == 'h' ) {
factor = 60 * 60;
} else if ( *p == 'd' ) {
factor = 60 * 60 * 24;
} else {
fprintf(stderr, "%s: %s(%d) bad mark specification `%s'\n", progname, pcFile, iLine, pcMark);
pcMark = 0;
factor = 0;
}
if ( factor ) {
*p = '\000';
pCE->mark = atoi(pcMark) * factor;
pCE->nextMark = tyme + pCE->mark;
if ( pCE->mark < 0 ) {
fprintf(stderr, "%s: %s(%d) negative mark specification `%s'\n", progname, pcFile, iLine, pcMark);
pcMark = 0;
}
}
}
if ( !pcMark ) {
pCE->nextMark = pCE->mark = 0;
}
#if DO_VIRTUAL
if (pcLine[0] == '!')
{
pCE->isNetworkConsole = 1;
strcpy(pCE->networkConsoleHost, pcLine + 1);
pCE->networkConsolePort = atoi(pcMode);
if (fVerbose) {
printf("%s: %d: %s is network on %s/%d logged to %s\n",
progname, iG, acIn, pCE->networkConsoleHost,
pCE->networkConsolePort, pCE->lfile);
}
pCE->fvirtual = 0;
sprintf( pCE->dfile, "%s/%d", pCE->networkConsoleHost, pCE->networkConsolePort );
pCE->pbaud = FindBaud("Netwk");
pCE->pparity = FindParity(" ");
}
else if ('|' == pcLine[0]) {
pCE->isNetworkConsole = 0;
pCE->fvirtual = 1;
if ((char *)0 == (pCE->pccmd = malloc((strlen(pcLine)|7)+1))) {
OutOfMem();
}
(void)strcpy(pCE->pccmd, pcLine+1);
(void)strcpy(pCE->dfile, "/dev/null");
} else {
pCE->isNetworkConsole = 0;
pCE->fvirtual = 0;
(void)strcpy(pCE->dfile, pcLine);
}
pCE->ipid = -1;
#else
if ('|' == pcLine[0]) {
fprintf(stderr, "%s: %s(%d) this server doesn't provide any virtual console support\n", progname, pcFile, iLine);
exit(9);
}
(void)strcpy(pCE->dfile, pcLine);
#endif
if (!pCE->isNetworkConsole)
{
/* find user baud and parity
* default to first table entry for baud and parity
*/
pCE->pbaud = FindBaud(pcMode);
pCE->pparity = FindParity(pcMode);
if (fVerbose) {
#if DO_VIRTUAL
if (pCE->fvirtual)
printf("%s: %d: %s with command `%s' logged to %s\n", progname, iG, acIn, pCE->pccmd, pCE->lfile);
else
#endif
printf("%s: %d: %s is on %s (%s%c) logged to %s\n", progname, iG, acIn, pCE->dfile, pCE->pbaud->acrate, pCE->pparity->ckey, pCE->lfile);
}
}
++pCE, ++iLocal;
}
*ppRC = (REMOTE *)0;
/* make a vector of access restructions
*/
iG = iAccess = 0;
pACList = (ACCESS *)0;
while (fgets(acIn, sizeof(acIn)-1, fp) != NULL) {
register char *pcRem, *pcMach, *pcNext, *pcMem;
auto char cType;
auto int iLen;
++iLine;
for (pcRem = acIn+strlen(acIn); pcRem >= acIn; --pcRem) {
if (!isspace(*pcRem))
break;
*pcRem = '\000';
if (pcRem == acIn)
break;
}
if ('#' == acIn[0] || '\000' == acIn[0]) {
continue;
}
if ('%' == acIn[0] && '%' == acIn[1] && '\000' == acIn[2]) {
break;
}
if ((char *)0 == (pcNext = strchr(acIn, ':'))) {
fprintf(stderr, "%s: %s(%d) missing colon?\n", progname, pcFile, iLine);
exit(3);
}
do {
*pcNext++ = '\000';
} while (isspace(*pcNext));
switch (acIn[0]) {
case 'a': /* allowed, allow, allows */
case 'A':
cType = 'a';
break;
case 'r': /* rejected, refused, refuse */
case 'R':
cType = 'r';
break;
case 't': /* trust, trusted, trusts */
case 'T':
cType = 't';
break;
default:
fprintf(stderr, "%s: %s(%d) unknown access key `%s\'\n", progname, pcFile, iLine, acIn);
exit(3);
}
while ('\000' != *(pcMach = pcNext)) {
while (!isspace(*pcNext)) {
++pcNext;
}
while ('\000' != *pcNext && isspace(*pcNext)) {
*pcNext++ = '\000';
}
if (iAccess < iG) {
/* still have room */;
} else if (0 != iG) {
iG += 8;
pACList = (ACCESS *)realloc((char *)pACList, iG * sizeof(ACCESS));
} else {
iG = MAXGRP;
pACList = (ACCESS *)malloc(iG * sizeof(ACCESS));
}
if ((ACCESS *)0 == pACList) {
OutOfMem();
}
/* use loopback interface for local connections
if (0 == strcmp(pcMach, acMyHost)) {
pcMach = "127.0.0.1";
}
*/
iLen = strlen(pcMach);
if ((char *)0 == (pcMem = malloc(iLen+1))) {
OutOfMem();
}
pACList[iAccess].ctrust = cType;
pACList[iAccess].ilen = iLen;
pACList[iAccess].pcwho = strcpy(pcMem, pcMach);
++iAccess;
}
}
}

47
conserver/readcfg.h Normal file
View File

@ -0,0 +1,47 @@
/*
* $Id: readcfg.h,v 5.6 1993-02-09 03:59:25-08 ldv Exp $
*
* Copyright 1992 Purdue Research Foundation, West Lafayette, Indiana
* 47907. All rights reserved.
*
* Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb
*
* This software is not subject to any license of the American Telephone
* and Telegraph Company or the Regents of the University of California.
*
* Permission is granted to anyone to use this software for any purpose on
* any computer system, and to alter it and redistribute it freely, subject
* to the following restrictions:
*
* 1. Neither the authors nor Purdue University are responsible for any
* consequences of the use of this software.
*
* 2. The origin of this software must not be misrepresented, either by
* explicit claim or by omission. Credit to the authors and Purdue
* University must appear in documentation and sources.
*
* 3. Altered versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
*
* 4. This notice may not be removed or altered.
*/
/* we read in which hosts to trust and which ones we proxy for
* from a file, into these structures
*/
extern GRPENT
aGroups[MAXGRP]; /* group info */
extern CONSENT
aConsoles[MAXGRP*MAXMEMB]; /* console list */
extern REMOTE
*pRCList; /* list of remote consoles we know about */
extern ACCESS
*pACList; /* `who do you love' (or trust) */
extern int
iAccess; /* how many access restrictions we have */
extern int
iLocal; /* how many local consoles we have */
extern void ReadCfg();

44
conserver/stamper.sh Normal file
View File

@ -0,0 +1,44 @@
#!/bin/sh
# $Id: stamper.sh,v 4.1 91/06/19 14:40:46 ksb Exp $
#
# The outputs a time stamp once an hour (on the hour, we hope).
# We take a list of logfiles to stamp
#
PROGNAME=`basename $0 .sh`
if [ "$#" -eq 0 ]
then
echo "$PROGNAME: usage files" 1>&2
exit 1
fi
# sleep until the top of the hour
# output a mark on each log file
# sleep for nearly an hour
while true
do
(
IFS="$IFS:"
# _ Wed Jun 19 14:31:02 EST 1991
# $1 $2 $3 $4 $5 $6 $7 $8 $9
set _ `date`
#sleep `expr 3600 - \( $6 \* 60 + $7 \)`
)
mark="[-- MARK -- `date`]"
for file
do
if [ _"-" = _"$file" ]
then
echo "$mark"
else
echo "$mark" >>$file
fi
done
sleep 3530
done
# NOTREACHED
exit 0

1
conserver/version.h Normal file
View File

@ -0,0 +1 @@
#define GNAC_VERSION "GNAC version 6.05"

35
console/INSTALL Normal file
View File

@ -0,0 +1,35 @@
# $Id: INSTALL,v 4.1 91/06/19 15:27:49 ksb Exp $
#
Prep:
Did you do the prep work in ../conserver yet? If not please start there.
Compiling:
Try a
make
in this directory. If cons.h is correct this should just compile.
First test:
Run a version command:
./console -V
and see something like:
console: $Id: INSTALL,v 4.1 91/06/19 15:27:49 ksb Exp $
console: initial master server `staff.cc.purdue.edu'
console: default escape sequence `^Ec'
console: loopback address for mentor.cc.purdue.edu is 127.0.0.1
Finish the INSTALL in conserver now.
Connect to the conserver on your dumb port,
Try all the commands. Especially ^Ecz and ^Ecd/^Eco.
Try two connections to the same console, note the cool way you can force
the other guy off (^Ecf).

81
console/Makefile Normal file
View File

@ -0,0 +1,81 @@
# $Id: Make.host,v 5.10 94/07/26 11:06:26 ksb Exp $
#
# Makefile for console client progran
#
# edit the ETC directory below to change where the console client
# is installed.
PROG= console
ETC= ${DESTDIR}/usr/local/etc
DOC= ${DESTDIR}/usr/local/man
I=/usr/include
S=/usr/include/sys
L=/usr/local/include
C=../conserver
P=
INCLUDE= -I$C
DEBUG=-O
CDEFS= -DSUN5
CFLAGS= ${DEBUG} ${CDEFS} ${INCLUDE}
HDR=
ONEC= console.c
MAN= console.man
OTHER= README
SOURCE= Makefile ${OTHER} ${MAN} ${HDR} ${ONEC}
all: ${PROG}
${PROG}:
${CC} -o $@ ${CFLAGS} ${ONEC} -lsocket -lnsl
clean: FRC
rm -f Makefile.bak ${PROG} a.out *.o core errs lint.out tags
deinstall: ${MAN} ${DOC} FRC
install -R ${ETC}/${PROG}
mkcat -r${DOC} -D ${MAN}
depend: ${HDR} ${ONEC} FRC
maketd -b ${CDEFS} ${INCLUDE} ${ONEC}
dirs: ${ETC}
distrib: FRC
distrib -c ${ETC}/${PROG}
install: all dirs FRC
install -cs ${PROG} ${ETC}/${PROG}
lint: ${HDR} ${ONEC} FRC
lint -h ${CDEFS} ${INCLUDE} ${ONEC}
mkcat: ${MAN} ${DOC} FRC
mkcat -r${DOC} ${MAN}
print: source FRC
lpr -J"${PROG} source" ${SOURCE}
source: ${SOURCE}
spotless: clean
rcsclean ${SOURCE}
tags: ${HDR} ${ONEC}
ctags -t ${HDR} ${ONEC}
/ ${ETC}:
install -dr $@
${SOURCE}:
co -q $@
FRC:
# DO NOT DELETE THIS LINE - maketd DEPENDS ON IT
console: $C/cons.h console.c
# *** Do not add anything here - It will go away. ***

67
console/README Normal file
View File

@ -0,0 +1,67 @@
# $Id: README,v 4.2 92/07/27 08:47:14 ksb Exp $
BUGS:
This program depends on a header file in ../conserver/cons.h,
which is dones't know how to make.
What does it do?
The console switch (conserver) uses some tty ports on a `switch machine' to
read the output of many host machines. Admins can use a client program
(console) to connect to any console under control of the `switch'. Thus from
my terminal here on the second floor I can control the console for each of
the machines in the machine room 3 floors below me!
The `switch' host is monitored by an operator who sees all the error output
from all the consoles (in a xterm here at PUCC). This operator can call up a
console on any machine in a flash and respond to problems. He is aware of
problems without having to poll many CRTs stacked out in the machine room --
he and the tape drives can be in a quiet place.
What platforms?
It runs under 4.2/4.3bsd, IBM's AIX6000, SunOS 4.X, and HPUX.
Only the client runs under HPUX at this release. It depends on
select(2) and sockets.
What do I need to evaluate it?
I believe a modem could be used in a pinch as a `host', anything that you can
trick into producing tty I/O. Even a dumb tty, but then you must do the
echo. Another port on the same machine was used for testing at one point...
and an EPROM programmer might even work.
Who would be interested in this kind of thing?
Anyone with more than one machine with a glass tty would love it, it also
gets rid of the need for paper consoles.
Is this software restricted in distribution?
Tom has an Ohio State copyright on the stuff, I'm sure that there will be no
problem with distribution. {He ripped the Purdue ECN copyright off the code
he got, I didn't change his.} Tom has not replied to any of my email in ~3
months....
Why this version rather than any other?
The PUCC version supports many more features (multiple `switch' machines for
when you run out of ports; job control; down'd consoles, etc) than either the
Ohio State or Purdue ECN versions.
How much trouble is it to port?
The code is ~2000 lines for the server and ~1150 for the client. Not too
hard to read in ~3 hours. It should work with a little push on any BSD type
UNIX.
--
"When you find me here, at the end of my rope!"
kayessbee, Kevin Braunsdorf, ksb@cc.purdue.edu, pur-ee!ksb, purdue!ksb

185
console/console.8l Normal file
View File

@ -0,0 +1,185 @@
.\" $Id: console.8l,v 5.0 92/01/13 14:44:36 ksb Exp $
.TH CONSOLE 8L "Local"
.SH NAME
console \- console server client program
.SH SYNOPSIS
\fBconsole\fP [\-\fBrv\fP] [\-\fBAFSafs\fP] [\-\fBe\fP \fIesc\fP] [\-\fBM\fP \fIserver\fP] \fIhost\fP
.br
\fBconsole\fP [\-\fBdDqQ\fP] [\-\fBv\fP] [\-\fBM\fP \fIserver\fP] \fIhost\fP
.br
\fBconsole\fP [\-\fBv\fP] [\-\fBhuVwx\fP]
.SH DESCRIPTION
.B Console
is used to manipulate console terminals remotely or poll running
\fIconserver\fP(8L) daemons for status information.
.PP
.B Console
queries the user for the root passwd before
granting interactive access to a console (on a non-trusted system)
since such a session may provide single-user access.
.PP
In the non-interactive mode
.B console
outputs only the requested information.
.SH OPTIONS
.TP
.B \-a
Access a console with a two-way connection (this is the default).
.TP
.B \-d
Display daemon versions. The \fIconsole\fP client connects to each
server to request its version information. The uppercase varient of
this option only requests the primary server's version.
.TP
.BI \-e esc
Set the initial two character escape sequence to
those represented by \fIesc\fP.
Any of the forms output by \fIcat\fP(1)'s \-\fBv\fP option
are accepted. The default value is ``^Ec''.
.TP
.B \-f
Same as
.I \-a
except it will force any existing connection into spy mode.
.TP
.B \-h
Display a brief help message.
.TP
.BI \-M server
The \fIconsole\fP client program polls \fIserver\fP as the primary server,
rather than the hard coded default (``console.cc.purdue.edu'').
.TP
.B \-q
The \fIconsole\fP client requests the server daemon quit (shutdown).
A password is sent in the protocol stream, if none is required for
the local host to shutdown the server just press return. The uppercase
varient of this command just acts on the primary server.
.TP
.B \-r
Request a raw connection to the group control virtual console,
this is only useful for learning the protocol used by the
interactive sequence.
.TP
.B \-s
Requests a read-only (spy mode) connection.
If this mode all the escape sequences (below) work, or report errors,
but all other keyboard input is discarded.
.TP
.B \-V
Output the version of the console client program.
.TP
.B \-v
Be more verbose during when building the connection(s).
Use this option in combination with any of `show' options (below)
for added benefit.
.TP
.B \-u
Show a list of consoles and the users on each.
.TP
.B \-w
Show a list of all connections to all consoles.
.TP
.B \-x
Show a list of consoles and devices.
.PP
The \-\fBA\fP, \-\fBF\fP, or \-\fBS\fP options have the same effect as
their lower case variants.
In addition they each request the last 20 lines of the console output after
making the connection.
.PP
Any default (\-\fBa\fP) connection is dropped to spy mode if
someone else is attached read-write.
.SH "ESCAPE SEQUENCES"
The connection can be controlled by a two character escape sequence, followed
by a command. The default escape sequence is ``control-E c''
(octal 005 143). Commands are:
.sp
.TS
c l.
a switch to attach mode
c toggle flow control (don't do this)
d down the current console
e change the escape sequence to the next two characters
f force a switch to attach mode
l1 send a 3 second serial line break (might halt a Sun)
o reopen the line to clear errors (silo overflows)
r replay the last 20 lines of output
s switch to spy mode
u show other users on this port
v show the version of the group server
w who is using this console
x examine this group's devices and modes.
z suspend this connection
? display list of commands
^I toggle tab expansion
^J continue, ignore the escape sequence
^R replay the last line only
\. disconnect
; provide a new login or shift to a new console
+(-) be more (less) free with newlines
.TE
.sp
.PP
If any other character is hit after the escape sequence, all three characters
will be discarded.
Note that a line break or a down command
can only be sent from a full two-way attachment.
To send the escape sequence through the connection one must redefine
the outer escape sequence.
.PP
In the \-u output, the login \fB<none>\fP indicates no one is
viewing that console, the login \fB<spies>\fP indicates that
no one has a full two-way attachment. When no one is attached to
a console its output is cloned to the stdout of the server process.
.SH EXAMPLES
.TP
console \-u
Outputs something like:
.sp
.RS
.TS
l18 l l.
dumb up <none>
expert up ksb@mentor
tyro up <spies>
mentor up <none>
sage up fine@cis
.TE
.RE
.sp
The \fB<none>\fP indicates no one is viewing \fIdumb\fP or \fImentor\fP,
the \fB<spies>\fP indicates only read-only connections exist for \fItyro\fP,
other \fIlogin\fP@\fIhost\fP entries are the currently attached
\fIsage\fP and \fIexpert\fP.
.TP
console \-w
Outputs something like:
.sp
.RS
.TS
l l l.
ksb@extra on expert Fri Feb 15 16:40:36 1991
file@cis on sage Thu Feb 14 1:04:10 1991
dmr@alice spy tyro Thu Feb 7 10:09:59 1991
.TE
.RE
.sp
.TP
console \-e \*(lq^[1\*(rq lv426
Requests a connection to the host ``lv426'' with the escape characters
set to ``escape one''.
.SH BUGS
Connections suspended under Dynix sometimes break the kernel when
resumed. Suspended connections are a poor idea in general, just
disconnect instead.
.PP
It is possible to create a loop of console connections, with ugly results.
Never run \fIconsole\fP from within a console connection.
.PP
The \-\fBr\fP option doesn't help to explain how connections get built.
.SH AUTHORS
Thomas A. Fine, Ohio State Computer Science.
.br
Kevin Braunsdorf, Purdue University Computing Center
.SH "SEE ALSO"
conserver.cf(5L), conserver(8L)

1317
console/console.c Normal file

File diff suppressed because it is too large Load Diff

185
console/console.man Normal file
View File

@ -0,0 +1,185 @@
.\" $Id: console.man,v 5.0 92/01/13 14:44:36 ksb Exp $
.TH CONSOLE 8L "Local"
.SH NAME
console \- console server client program
.SH SYNOPSIS
\fBconsole\fP [\-\fBrv\fP] [\-\fBAFSafs\fP] [\-\fBe\fP \fIesc\fP] [\-\fBM\fP \fIserver\fP] \fIhost\fP
.br
\fBconsole\fP [\-\fBdDqQ\fP] [\-\fBv\fP] [\-\fBM\fP \fIserver\fP] \fIhost\fP
.br
\fBconsole\fP [\-\fBv\fP] [\-\fBhuVwx\fP]
.SH DESCRIPTION
.B Console
is used to manipulate console terminals remotely or poll running
\fIconserver\fP(8L) daemons for status information.
.PP
.B Console
queries the user for the root passwd before
granting interactive access to a console (on a non-trusted system)
since such a session may provide single-user access.
.PP
In the non-interactive mode
.B console
outputs only the requested information.
.SH OPTIONS
.TP
.B \-a
Access a console with a two-way connection (this is the default).
.TP
.B \-d
Display daemon versions. The \fIconsole\fP client connects to each
server to request its version information. The uppercase varient of
this option only requests the primary server's version.
.TP
.BI \-e esc
Set the initial two character escape sequence to
those represented by \fIesc\fP.
Any of the forms output by \fIcat\fP(1)'s \-\fBv\fP option
are accepted. The default value is ``^Ec''.
.TP
.B \-f
Same as
.I \-a
except it will force any existing connection into spy mode.
.TP
.B \-h
Display a brief help message.
.TP
.BI \-M server
The \fIconsole\fP client program polls \fIserver\fP as the primary server,
rather than the hard coded default (``console.cc.purdue.edu'').
.TP
.B \-q
The \fIconsole\fP client requests the server daemon quit (shutdown).
A password is sent in the protocol stream, if none is required for
the local host to shutdown the server just press return. The uppercase
varient of this command just acts on the primary server.
.TP
.B \-r
Request a raw connection to the group control virtual console,
this is only useful for learning the protocol used by the
interactive sequence.
.TP
.B \-s
Requests a read-only (spy mode) connection.
If this mode all the escape sequences (below) work, or report errors,
but all other keyboard input is discarded.
.TP
.B \-V
Output the version of the console client program.
.TP
.B \-v
Be more verbose during when building the connection(s).
Use this option in combination with any of `show' options (below)
for added benefit.
.TP
.B \-u
Show a list of consoles and the users on each.
.TP
.B \-w
Show a list of all connections to all consoles.
.TP
.B \-x
Show a list of consoles and devices.
.PP
The \-\fBA\fP, \-\fBF\fP, or \-\fBS\fP options have the same effect as
their lower case variants.
In addition they each request the last 20 lines of the console output after
making the connection.
.PP
Any default (\-\fBa\fP) connection is dropped to spy mode if
someone else is attached read-write.
.SH "ESCAPE SEQUENCES"
The connection can be controlled by a two character escape sequence, followed
by a command. The default escape sequence is ``control-E c''
(octal 005 143). Commands are:
.sp
.TS
c l.
a switch to attach mode
c toggle flow control (don't do this)
d down the current console
e change the escape sequence to the next two characters
f force a switch to attach mode
l1 send a 3 second serial line break (might halt a Sun)
o reopen the line to clear errors (silo overflows)
r replay the last 20 lines of output
s switch to spy mode
u show other users on this port
v show the version of the group server
w who is using this console
x examine this group's devices and modes.
z suspend this connection
? display list of commands
^I toggle tab expansion
^J continue, ignore the escape sequence
^R replay the last line only
\. disconnect
; provide a new login or shift to a new console
+(-) be more (less) free with newlines
.TE
.sp
.PP
If any other character is hit after the escape sequence, all three characters
will be discarded.
Note that a line break or a down command
can only be sent from a full two-way attachment.
To send the escape sequence through the connection one must redefine
the outer escape sequence.
.PP
In the \-u output, the login \fB<none>\fP indicates no one is
viewing that console, the login \fB<spies>\fP indicates that
no one has a full two-way attachment. When no one is attached to
a console its output is cloned to the stdout of the server process.
.SH EXAMPLES
.TP
console \-u
Outputs something like:
.sp
.RS
.TS
l18 l l.
dumb up <none>
expert up ksb@mentor
tyro up <spies>
mentor up <none>
sage up fine@cis
.TE
.RE
.sp
The \fB<none>\fP indicates no one is viewing \fIdumb\fP or \fImentor\fP,
the \fB<spies>\fP indicates only read-only connections exist for \fItyro\fP,
other \fIlogin\fP@\fIhost\fP entries are the currently attached
\fIsage\fP and \fIexpert\fP.
.TP
console \-w
Outputs something like:
.sp
.RS
.TS
l l l.
ksb@extra on expert Fri Feb 15 16:40:36 1991
file@cis on sage Thu Feb 14 1:04:10 1991
dmr@alice spy tyro Thu Feb 7 10:09:59 1991
.TE
.RE
.sp
.TP
console \-e \*(lq^[1\*(rq lv426
Requests a connection to the host ``lv426'' with the escape characters
set to ``escape one''.
.SH BUGS
Connections suspended under Dynix sometimes break the kernel when
resumed. Suspended connections are a poor idea in general, just
disconnect instead.
.PP
It is possible to create a loop of console connections, with ugly results.
Never run \fIconsole\fP from within a console connection.
.PP
The \-\fBr\fP option doesn't help to explain how connections get built.
.SH AUTHORS
Thomas A. Fine, Ohio State Computer Science.
.br
Kevin Braunsdorf, Purdue University Computing Center
.SH "SEE ALSO"
conserver.cf(5L), conserver(8L)