SysIII/usr/src/cmd/ct.c
/*
* ct [-h] [-v] [-wn] [-s speed] telno
*
* dials the given telephone number, waits for the
* modem to answer, and initiates a login process.
*
* There must be entries in /etc/inittab of the form:
* 1:cx:k:/etc/getty culx !
*
* Also, the appropriate modification must be made to
* the UNIX/TS 1.1 system in order that /dev/tty is
* reassigned by the setpgrp system call.
* This is done by modifying the setpgrp routine in
* sys4.c as follows:
* The lines
* if (uap->flag)
* u.u_procp->p_pgrp = u.u_procp->p_pid;
* in UNIX/TS 1.1 should be changed to
* if (uap->flag) {
* u.u_procp->p_pgrp = u.u_procp->p_pid;
* u.u_ttyp = NULL;
* }
* This modification to UNIX/TS 1.1 is included in the
* UNIX/TS 1.1.1 update, and will be included in future
* releases of UNIX/TS and PWB/UNIX.
*
* The ct executable should be installed as follows:
* owner = root
* group = bin
* mode = 4775
*/
# include <fcntl.h>
# include <pwd.h>
# include <sgtty.h>
# include <setjmp.h>
# include <signal.h>
# include <stdio.h>
# include <time.h>
# include <sys/types.h>
# include <sys/dir.h>
# if lint
int _null_;
# define IGN _null_ = (int)
# else
# define IGN
# endif
# define ROOT 0
# define SYS 3
# define TTYMOD 0666
# define DEV "/dev/"
# define LCK "/usr/spool/uucp/LCK.."
char log[] = "/usr/adm/ctlog",
getty[] = "/etc/getty",
legal[] = "0123456789-*:#;e<w=f",
acu[sizeof DEV + DIRSIZ - 5] = DEV,
tty[sizeof DEV + DIRSIZ - 5] = DEV,
lock[sizeof LCK + DIRSIZ - 5] = LCK,
devtab[] = "/usr/lib/uucp/L-devices";
int optind;
char *optarg;
FILE *Ldevices, *Log;
int disconnect ();
char *strcpy ();
char *strncpy ();
char *strchr ();
char *asctime ();
long time ();
unsigned sleep ();
extern long timezone;
struct tm *gmtime ();
struct sgttyb arg;
struct passwd *getpwuid ();
struct {
long l_on;
long l_off;
short l_uid;
char l_spd[4];
} ct;
jmp_buf env;
main (argc, argv)
char *argv[]; {
register dn, pid;
register char *dp;
char *num, *aptr;
char *wspeed = "300";
char tbuf[32];
int c, dl, status;
int hangup = 1;
int verbose = 0;
int max = -1;
int count = 0;
IGN signal (SIGHUP, SIG_IGN);
IGN signal (SIGQUIT, SIG_IGN);
if ((Ldevices = fopen (devtab, "r")) == NULL) {
fprintf (stderr, "ct: can't open %s\n", devtab);
exit (1);
}
dn = 0;
while ((c = getopt (argc, argv, "hvw:s:")) != EOF)
switch (c) {
case 'h':
hangup = 0;
break;
case 'v':
verbose = 1;
break;
case 'w':
max = atoi (optarg);
break;
case 's':
wspeed = optarg;
break;
case '?':
dn++;
break;
}
if (dn || optind != argc-1) {
IGN fputs ("Usage: ct [-h] [-v] [-wn] [-s speed] telno\n", stderr);
exit (1);
}
num = argv[optind];
if (strlen (num) >= sizeof tbuf - 1) {
IGN fputs ("ct: phone number too long\n", stderr);
exit (1);
}
if (check (num) < 0) {
IGN fputs ("ct: bad phone number\n", stderr);
exit (1);
}
for (;;) {
dn = gdev (wspeed);
if (count == 0) {
if (dn >= 0)
fprintf (stderr, "Allocated dialer at %s baud\n", wspeed);
else {
fprintf (stderr, "%d busy dialer", -dn);
if (dn < -1)
IGN fputc ('s', stderr);
fprintf (stderr, " at %s baud\n", wspeed);
if (max <= 0) {
if (max < 0) {
IGN fputs ("Wait for dialer? ", stderr);
if (gets (tbuf) == NULL || tolower (*tbuf) != 'y')
exit (1);
IGN fputs ("Time, in minutes? ", stderr);
IGN scanf ("%d", &max);
while (getchar () != '\n');
}
if (max <= 0)
exit (1);
} else
IGN fputs ("Waiting for dialer\n", stderr);
}
if (!isatty (fileno (stdin)))
hangup = 0;
if (hangup) {
IGN fputs ("Confirm hang-up? ", stderr);
if (gets (tbuf) == NULL || tolower (*tbuf) != 'y')
if (dn >= 0)
error ();
else
exit (1);
if (isatty (fileno (stdout)))
verbose = 0;
sleep (2);
IGN stty (0, &arg);
sleep (5);
}
IGN close (2);
IGN dup (1);
}
if (dn >= 0)
break;
if (verbose && count) {
IGN fputs ("Dialer", stderr);
if (dn == -1)
IGN fputs (" is", stderr);
else
IGN fputs ("s are", stderr);
fprintf (stderr, " busy (%d minute", count);
if (count > 1)
IGN fputc ('s', stderr);
IGN fputs (")\n", stderr);
}
if (count++ >= max) {
if (verbose)
IGN fputs ("*** TIMEOUT ***\n", stderr);
exit (1);
}
sleep (60);
}
if (count && verbose)
IGN fputs ("Allocated dialer\n", stderr);
if ((dl = open (tty, O_RDWR | O_NDELAY)) < 0) {
if (!hangup || verbose)
fprintf (stderr, "ct: can't open %s\n", tty);
error ();
}
if ((aptr = strchr (strcpy (tbuf, num), '\0'))[-1] != '-') {
*aptr++ = '-';
*aptr = '\0';
}
if (verbose)
fprintf (stderr, "Dialing %s\n", tbuf);
if (write (dn, num, strlen (num)) < 0) {
if (!hangup || verbose)
fprintf (stderr, "ct: write error on %s\n", acu);
error ();
}
IGN close (dn);
if (verbose)
IGN fputs ("Connected\n", stderr);
if (setjmp (env))
goto disc;
IGN signal (SIGHUP, disconnect);
IGN signal (SIGINT, disconnect);
IGN signal (SIGTERM, disconnect);
sleep (2);
ct.l_on = time ((long *) 0);
IGN close (0);
if ((pid = fork ()) == 0) {
IGN setpgrp ();
if (strcmp (wspeed, "1200") == 0)
dp = "3";
else
dp = "0";
execl (getty, "getty", &tty[5], dp, "60", 0);
}
if (pid <= 0) {
if (pid < 0 && (!hangup || verbose))
IGN fputs ("ct: can't fork for getty\n", stderr);
error ();
}
while (wait (&status) != pid);
if (status < 0) {
if (!hangup || verbose)
IGN fputs ("ct: can't exec getty\n", stderr);
error ();
}
disc:
IGN signal (SIGHUP, SIG_IGN);
IGN signal (SIGINT, SIG_IGN);
IGN signal (SIGTERM, SIG_IGN);
ct.l_off = time ((long *) 0);
IGN unlink (lock);
IGN stty (dl, &arg);
IGN close (dl);
if (verbose)
IGN fputs ("Disconnected\n", stderr);
ct.l_uid = (short) getuid ();
IGN strncpy (ct.l_spd, wspeed, 4);
if (access (log, 0) >= 0 && (Log = fopen (log, "a")) != NULL) {
fprintf (Log, "%-8s ", getpwuid ((int) ct.l_uid)->pw_name);
fprintf (Log, "(%4s) ", ct.l_spd);
ct.l_on -= timezone;
(aptr = asctime (gmtime (&ct.l_on)))[19] = '\0';
fprintf (Log, "%s ", aptr);
ct.l_off -= timezone;
(aptr = asctime (gmtime (&ct.l_off)))[19] = '\0';
fprintf (Log, "%s %s\n", aptr, num);
IGN fclose (Log);
}
if ((pid = fork ()) == 0)
execl (getty, "getty", &tty[5], "!", 0);
if (pid <= 0) {
if (pid < 0 && verbose)
IGN fputs ("Can't fork to clean up utmp\n", stderr);
exit (1);
}
while (wait ((int *) 0) != pid);
if (chown (tty, ROOT, SYS) < 0 || chmod (tty, TTYMOD) < 0) {
if (verbose)
fprintf (stderr, "Can't chown/chmod on %s\n", tty);
exit (1);
}
exit (0);
}
check (num)
char *num; {
register char *ptr1, *ptr2;
if (*(ptr1 = num) == '\0')
return (-1);
do {
ptr2 = legal;
do {
if (*ptr1 == *ptr2)
break;
} while (*++ptr2);
if (*ptr2 == '\0')
return (-1);
} while (*++ptr1);
return (0);
}
error () {
IGN unlink (lock);
exit (1);
}
gdev (wspeed)
register char *wspeed; {
register char *lspeed;
register dn;
char Lbuf[80];
char *getarg ();
int lck, pid, exists = 0;
IGN fseek (Ldevices, (long) 0, 0);
while (fgets (Lbuf, sizeof Lbuf, Ldevices) != NULL) {
if (strcmp (getarg (Lbuf), "ACU"))
continue;
IGN strncpy (&tty[5], getarg ((char *) 0), sizeof tty - 6);
IGN strncpy (&acu[5], getarg ((char *) 0), sizeof acu - 6);
lspeed = getarg ((char *) 0);
if (strcmp (wspeed, lspeed) != 0)
continue;
exists++;
IGN strcpy (&lock[21], &tty[5]);
if ((lck = open (lock, O_WRONLY | O_CREAT | O_EXCL, 0444)) >= 0
&& (dn = open (acu, O_WRONLY)) >= 0) {
IGN signal (SIGINT, error);
IGN signal (SIGTERM, error);
pid = getpid ();
IGN write (lck, (char *) &pid, sizeof (pid));
IGN close (lck);
return (dn);
}
}
if (exists)
return (-exists);
fprintf (stderr, "No %s baud dialers on this system\n", wspeed);
error ();
/*NOTREACHED*/
}
char *
getarg (p)
register char *p; {
register char *q;
static char *savepoint;
if (p == (char *) 0)
p = savepoint;
while (*p == ' ' || *p == '\t')
p++;
q = p;
while (*p != ' ' && *p != '\t' && *p != '\0' && *p != '\n')
p++;
*p = '\0';
savepoint = ++p;
return (q);
}
disconnect () {
longjmp (env, 1);
}