pst@anise.acc.com (Paul Traina) (07/16/89)
The following program is a getty that runs under SystemV and is compatible with any one of the three major "popular" uucp programs (4.3bsd, USG, HDB). One nice feature about this getty is it has a ringback mode which can allow you to utilize your modem line for voice and data without causing confusion. This getty talks to the modem and will automatically determine baudrates et al. It has successfully be utilized on: MacII w/A/UX running with both trailblazers and 2400 baud modems Microport SV/AT "" Unix-PC 7300 running with slow modems Any questions? Send me mail. #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: rb.c # Wrapped by pst@anise.ac on Sat Jul 15 11:34:01 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'rb.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'rb.c'\" else echo shar: Extracting \"'rb.c'\" \(12061 characters\) sed "s/^X//" >'rb.c' <<'END_OF_FILE' X/****************************************************************************** X XRingback.c V1.7 13-Jun-1989 X XThis program implements a ring-back system that allows a phone line Xthat is normally used as a voice line and a dial-out data line to be Xused as a limited dial-in data and voice line. It does not interfere Xwith the use of the line for an answering machine. X XIf the ringback feature is disabled, it will act as an intelligent Xbi-directional getty program with proper locking for the uucp directories. X XIt solves a problem for my situation: X X1) I am normally in my office. The phone line is used for dial-out via X modem and dial-in/dial-out voice traffic. X X2) I sometimes travel, at which time I connect an answering machine to X the line. X X3) I'd like to be able to call in to my system via modem when I am X travelling, without interfering with others use of my answering X machine. X X4) I don't want to pay for another phone line. X XThis implements a ringback dialin system. Just call, let the remote line Xring once, hangup, wait a second, and dial a second time. X XIf the program notices that a user (uucp or kermit) is using the line Xfor an outgoing call, it will back off until that call is completed. X(Note: the first modem response char will be eaten. Uucp dialing scripts Xshould be set up to tolerate this.) X XTwo arguments must be present - tty & speed, one more additional argument Xif present, will be an output file for debug information. X XSample lines from /etc/inittab: X rb:1234:respawn:/etc/ringback tty1 2400 [debug-output-file] X ^^^^ X speed to talk to modem! X XDon't worry about speed being "locked" at 2400 baud, ringback will Xexec the getty with the proper speed (300, 1200, or 2400, or whatever). X XYou will have to make a gettydefs entry for the baud rate if you haven't Xalready. For example, my A/UX system with a Trailblazer and a slower X2400 baud modem has the following entries: X X19200# EXTA # EXTA HUPCL SANE2 TAB3 # MODEM ~DTR ~FLOW #\r\nlogin: #19200 X9600# B9600 # B9600 HUPCL SANE2 TAB3 # MODEM ~DTR ~FLOW #\r\nlogin: #9600 X2400# B2400 # B2400 HUPCL SANE2 TAB3 # MODEM ~DTR ~FLOW #\r\nlogin: #2400 X1200# B1200 # B1200 HUPCL SANE2 TAB3 # MODEM ~DTR ~FLOW #\r\nlogin: #1200 X300# B300 # B300 HUPCL SANE2 TAB3 # MODEM ~DTR ~FLOW #\r\nlogin: #3000 X XTo install: X X1) Edit defines below X2) Compile and install as /etc/ringback X3) Create an initab line like the above one. X X - Paul Traina (pst@anise.acc.com) X adapted from work by: X - Jon Zeeff (umix!b-tech!zeeff) X XThis program is in the public domain. No one is begging for money, however Xwe would appreciate it if you continue to distribute this program with proper Xcredit due to Jon & Paul. If you want to sell the program, fine; make a Xbuck off of our work, but it would be nice if your stuff our names in the Xdocumentation and object code somewhere. If you like the program, great X(I'd like to hear from you). If you don't, sorry, but you get what you Xpay for. If you find any problems (I've done a lot of tuning to get around XSystemV bugs with the process group stuff) let me know. If you find yet Xanother use for it, I'd be glad to hear about that too. X X - Paul Traina X X******************************************************************************/ X X#define NORB /* disable ringback feature */ X#define TELEBIT /* using Telebit Trailblazer modem */ X/* #define HDB_UUCP /* honey danber uucp & locks */ X/* #define BSD43_UUCP /* 4.3bsd uucp lock directory X instead of HDB or USG */ X X/* the id and gid for normal ownership of tty lines (usually uucp) */ X X#define TTYID 5 /* uucp */ X#define TTYGID 11 /* modem */ X X/*****************************************************************************/ X X#include <stdio.h> X#include <sys/types.h> X#include <sys/stat.h> X#include <signal.h> X#include <setjmp.h> X#include <fcntl.h> X#include <termio.h> X#include <varargs.h> X#include <time.h> X#include <utmp.h> X Xchar *strcpy(); Xchar *strcat(); Xunsigned sleep(); Xunsigned alarm(); Xvoid exit(); X X#define TIMEOUT -1 X Xchar dbg_name[255]; Xint tty; Xstruct termio ttymodes; Xstatic jmp_buf sjbuf; X X X/* print debug message on console */ X X/*VARARGS0*/ Xvoid debug(va_alist) Xva_dcl X{ X va_list args; X char *fmt; X struct tm *t; X long clock; X static FILE *fp = NULL; X X if (*dbg_name == '\0') X return; X else { X if (fp == NULL) X if ((fp = fopen(dbg_name, "a")) == NULL) X return; X (void) time(&clock); X t = localtime(&clock); X X (void) fprintf(fp, "[%02d/%02d %02d:%02d] ", t->tm_mon+1, X t->tm_mday, t->tm_hour, t->tm_min); X va_start(args); X fmt = va_arg(args, char *); X (void) vfprintf(fp, fmt, args); X (void) fprintf(fp, "\n"); X fflush(fp); X va_end(args); X } X} X X/* send a string to modem, sleep n seconds after doing so */ X Xvoid sendmodem(string, t) Xchar *string; Xint t; X{ X debug("sent: %s", string); X write(tty, string, strlen(string)); /* send out string */ X if (t) X sleep(t); X} X X/* flush input buffer */ Xvoid eatall() { ioctl(tty, TCFLSH, 0); } X X/* flag timeout as having occured, do longjump into waitfor */ Xvoid expired() { longjmp(sjbuf, 1); } X X X/* waitfor will wait 'timeout' seconds for a character, returning X the character immediately if found, otherwise returning TIMEOUT. */ X Xchar waitfor(timeout) Xint timeout; X{ X char c; X X signal(SIGALRM, expired); X alarm(timeout); X X if (setjmp(sjbuf)) { X signal(SIGALRM, SIG_DFL); X debug("timeout!"); X return TIMEOUT; X } else { X do { X while (read(tty, &c, sizeof(c)) != 1) X ; X c &= 0x7f; X } while (c == '\r' || c == '\n'); /* ignore crlfs */ X alarm(0); X signal(SIGALRM, SIG_DFL); X return (c & 127); X } X} X Xmain(argc, argv) Xint argc; Xchar **argv; X{ X char result; X struct stat buf; X char tty_lock[100]; X char tty_name[100]; X int speed, baud, modemspeed; X char aspeed[10]; X FILE *lock; X X close(0); /* close stdin */ X close(1); /* close stdout */ X close(2); /* close stderr */ X fclose(stdin); X fclose(stdout); X fclose(stderr); X X /* name and location of tty locks - change this as needed */ X#ifndef HDB_UUCP X# ifdef BSD43_UUCP /* berkeley 4.3 uucp */ X strcpy(tty_lock, "/usr/spool/uucp/LCK/LCK.."); X# else /* System 5.2 uucp */ X strcpy(tty_lock, "/usr/spool/uucp/LCK.."); X# endif X#else /* HDB uucp */ X strcpy(tty_lock, "/usr/spool/locks/LCK.."); X#endif X if (argc == 4) X strcpy(dbg_name, argv[3]); X else X *dbg_name = '\0'; X X if (argc < 3 && argc > 4) { X debug("invalid number of parameters, exiting"); X exit(2); X } X X strcat(tty_lock, argv[1]); X strcpy(tty_name, "/dev/"); X strcat(tty_name, argv[1]); X X modemspeed = atoi(argv[2]); /* speed to talk to modem */ X switch (modemspeed) { X case 300: baud = B300; break; X case 1200: baud = B1200; break; X case 2400: baud = B2400; break; X case 4800: baud = B4800; break; X case 9600: baud = B9600; break; X case 19200: baud = EXTA; break; X default: debug("invalid baud rate"); exit(2); X } X X unlink(tty_lock); /* always existed because user was there */ X umask(022); X X signal(SIGHUP, SIG_IGN); X signal(SIGQUIT, SIG_IGN); X X for (;;) { X X /* Set the permissions, owner, and group for dial-out use */ X X chown(tty_name, TTYID, TTYGID); X chmod(tty_name, 0662); X X if ((tty = open(tty_name, O_RDWR, 0662)) == -1) { X debug("error opening %s", tty_name); X exit(2); X } X X ttymodes.c_iflag = 0; X ttymodes.c_oflag = NL1 | CR3; X ttymodes.c_cflag = 0; /* drop dtr */ X ttymodes.c_lflag = 0; X ttymodes.c_line = 0; X ttymodes.c_cc[VMIN] = 1; /* min number of characters */ X ttymodes.c_cc[VTIME] = 0; /* no max time before return */ X ioctl(tty, TCSETA, &ttymodes); /* hang up the line */ X sleep(1); X ttymodes.c_cflag = baud | CS8 | CREAD | HUPCL; X ioctl(tty, TCSETA, &ttymodes); X sleep(1); X X debug("remote line setup"); X X do { X sendmodem("\rAT\r", 1); /* set baudrate */ X sendmodem("ATE0\r", 2); /* turn off echo */ X eatall(); /* flush input buffer */ X X#ifdef TELEBIT X sendmodem("AT&EE0X1V0S2=128S58=0\r", 0); X#else X sendmodem("ATV0Q0S0=0S2=128M3X1S10=25\r", 0); X#endif X X do { X result = waitfor(1); /* wait 1s for result */ X debug("program modem result=<%c> (%d)", result, result); X } while (result != '0' && result != '4' && result != TIMEOUT); X X if (result == '4') X debug("modem program error"); X if (result == TIMEOUT) X debug("modem timed out"); X if (result != '0') X sleep(10); /* wait ten seconds */ X X } while (result != '0'); /* need "OK" from modem */ X X sleep(2); X eatall(); X X /* Wait for incoming call ('2') or other usage (uucp or user) */ X X while (read(tty, &result, sizeof(result)) != 1) X ; X X /* If we receive a '2' and no lock file is present, we can X be sure that it is not someone calling out. */ X X result &= 127; /* strip parity */ X X debug("received a character <%c> (%d)", result, result); X X if (result == '2' && stat(tty_lock, &buf) == -1) { X /* create a hdb style lock file */ X if ((lock = fopen(tty_lock, "w", 0444))) { X#ifdef HDB_UUCP X fprintf(lock, "%10d\n", getpid()); X#else X putw(getpid(), lock); X#endif X fclose(lock); X } X X#ifndef NORB X debug("waiting for second ring..."); X X do { X result = waitfor(8); /* wait 8 seconds */ X } while (result != '2' && result != TIMEOUT); X X if (result == '2') { X debug("second ring detected, waiting for third ring..."); X do { X result = waitfor(8); /* wait 8 seconds */ X } while (result != '2' && result != TIMEOUT); X } X X if (result == '2') { /* got third ring */ X debug("voice call"); X unlink(tty_lock); X sleep(60); /* wait long enough for human or answering X machine to pick up call */ X X } else { /* must be timeout (no second ring) */ X debug("waiting 45 seconds for second call"); X sleep(3); X eatall(); X result = waitfor(42); X speed = 0; X X if (result != '2') { X debug("didn't get ring for second call"); X unlink(tty_lock); X } else { X#endif X debug("answering phone"); X sendmodem("ATA\r", 1); X eatall(); X result = waitfor(60); X switch (result) { X case TIMEOUT: X debug("answer call timeout"); break; X case '3': X case '8': X debug("no carrier"); break; X case '4': X debug("phone answer error"); break; X case '5': X result = waitfor(1); X if (result == '0') { X debug("FAST call"); X speed = 19200; X } else { X debug("1200 baud call"); X speed = 1200; X } X break; X case '1': X result = waitfor(1); X if (result == '0') { X debug("2400 baud call"); X speed = 2400; X } else { X debug("300 baud call"); X speed = 300; X } X break; X default: X debug("unknown character <%c> (%d)", X result, result); X } /* end switch */ X X eatall(); /* clear out initial crap */ X X if (speed == 0) { X debug("invalid answer code from modem"); X unlink(tty_lock); X } else { X debug("execing getty"); X#ifdef TELEBIT /* telebit is programmed to always talk fast */ X sprintf(aspeed, "%d", modemspeed); X#else X sprintf(aspeed, "%d", speed); X#endif X /* to circumvent a system5 process group bug, X * we'll turn off hangup-after-last-close, let X * getty close the channel to the tty & reopen it. X * this (hopefully) will make getty be able to always X * fopen /dev/tty X */ X ttymodes.c_cflag &= ~HUPCL; X ioctl(tty, TCSETA, &ttymodes); X sleep(1); X X execl("/etc/getty", "getty", "-h", "-t", "90", X argv[1], aspeed, (char *)0); X X debug("exec of getty failed"); X } X#ifndef NORB X } /* endif got second call */ X } X#endif X } else { /* result != 2 --> Must be someone using line */ X X debug("giving up line to uucp or user"); X close(tty); /* Release line */ X sleep(60); X X /* Loop until lock file goes away (uucp or user done) */ X X do { X while (stat(tty_lock, &buf) == 0) X sleep(40); X sleep(20); X } while (stat(tty_lock, &buf) == 0); X X } /* endif result != 2 */ X } /* for(;;) */ X} END_OF_FILE if test 12061 -ne `wc -c <'rb.c'`; then echo shar: \"'rb.c'\" unpacked with wrong size! fi # end of 'rb.c' fi echo shar: End of shell archive. exit 0 -- "Calling people sexist because they are into S/M is like calling people capitalist because they like to play Monopoly(TM)." -- `Ask Aunt Sadie' / the Ministry of Truth