UUCP Changes in A/UX 2.0?

Richard Todd rmtodd at servalan.uucp
Sun Apr 8 06:21:46 AEST 1990


mike at bushido (Michael A. Nowak) writes:
>1.  uucico wouldn't call uuxqt correctly.  I think it was trying to set up
>	the time zone and so forth but it didn't come out right.  I had to
>	rename uuxqt and call it from my uudemon.hr script separately.
  Huh?  I've never seen this problem.  Here's the script I use to poll 
my feed site twice an hour.  
---------------------------
TZ=CST6CDT;export TZ
/usr/lib/uucp/uucico -r1 -suokmax
--------------------------
>2.	mail & rmail do not munge the headers correctly.  All the mail appears
>	like it's coming from uucp instead of the original sender.  This was
>	corrected using another version of rmail and recompiling.
  Personally, I just installed smail and Deliver (smail for handling uucp
routing, Deliver for handling local mail delivery).  Both are available at
your friendly neighborhood source archive site.  And there are so many fun
things you can do with .deliver files...

>problematic.  If you're building a wish list form customers, a
>bidirectional getty would be great too.  :)
  Will you settle for a free getty front-end that does much the same thing? :-)
Here's one I pulled off the net some time back, originally written by Paul
Traina and hacked on slightly by me.  Some of the modem command sequences are
Trailblazer-specific; hack as needed for your modem.  Enjoy.
----------------------------cut here----------------------------------------
/******************************************************************************

Ringback.c V1.7		13-Jun-1989

This program implements a ring-back system that allows a phone line 
that is normally used as a voice line and a dial-out data line to be 
used as a limited dial-in data and voice line.  It does not interfere 
with the use of the line for an answering machine.  

If the ringback feature is disabled,  it will act as an intelligent
bi-directional getty program with proper locking for the uucp directories.

It solves a problem for my situation:

1) I am normally in my office.  The phone line is used for dial-out via
   modem and dial-in/dial-out voice traffic.

2) I sometimes travel, at which time I connect an answering machine to
   the line.  

3) I'd like to be able to call in to my system via modem when I am 
   travelling, without interfering with others use of my answering 
   machine.  

4) I don't want to pay for another phone line.

This implements a ringback dialin system.  Just call, let the remote line
ring once, hangup, wait a second, and dial a second time.

If the program notices that a user (uucp or kermit) is using the line 
for an outgoing call, it will back off until that call is completed.  
(Note: the first modem response char will be eaten.  Uucp dialing scripts 
should be set up to tolerate this.) 

Two arguments must be present - tty & speed, one more additional argument
if present, will be an output file for debug information.

Sample lines from /etc/inittab:
     rb:1234:respawn:/etc/ringback tty1 2400 [debug-output-file]
					^^^^
					speed to talk to modem!

Don't worry about speed being "locked" at 2400 baud, ringback will
exec the getty with the proper speed (300, 1200, or 2400, or whatever).

You will have to make a gettydefs entry for the baud rate if you haven't
already.  For example,  my A/UX system with a Trailblazer and a slower
2400 baud modem has the following entries:

19200# EXTA # EXTA  HUPCL SANE2 TAB3 # MODEM ~DTR ~FLOW #\r\nlogin: #19200
9600# B9600 # B9600 HUPCL SANE2 TAB3 # MODEM ~DTR ~FLOW #\r\nlogin: #9600
2400# B2400 # B2400 HUPCL SANE2 TAB3 # MODEM ~DTR ~FLOW #\r\nlogin: #2400
1200# B1200 # B1200 HUPCL SANE2 TAB3 # MODEM ~DTR ~FLOW #\r\nlogin: #1200
300#  B300  # B300  HUPCL SANE2 TAB3 # MODEM ~DTR ~FLOW #\r\nlogin: #3000

To install:

1) Edit defines below
2) Compile and install as /etc/ringback
3) Create an initab line like the above one.

				- Paul Traina (pst at anise.acc.com)
				adapted from work by:
 				- Jon Zeeff (umix!b-tech!zeeff)

This program is in the public domain.  No one is begging for money, however
we would appreciate it if you continue to distribute this program with proper
credit due to Jon & Paul.  If you want to sell the program,  fine;  make a
buck off of our work,  but it would be nice if your stuff our names in the
documentation and object code somewhere.  If you like the program, great
(I'd like to hear from you).  If you don't, sorry, but you get what you
pay for. If you find any problems (I've done a lot of tuning to get around
SystemV bugs with the process group stuff) let me know.  If you find yet
another use for it,  I'd be glad to hear about that too.

				- Paul Traina

******************************************************************************/

#define NORB				/* disable ringback feature */
#define TELEBIT				/* using Telebit Trailblazer modem */
/* #define HDB_UUCP			/* honey danber uucp & locks */
/* #define BSD43_UUCP			/* 4.3bsd uucp lock directory
					   instead of HDB or USG */

/* the id and gid for normal ownership of tty lines (usually uucp) */

#define TTYID		5		/* uucp */
#define TTYGID		1		/* daemon */

/*****************************************************************************/

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <setjmp.h>
#include <fcntl.h>
#include <termio.h>
#include <varargs.h>
#include <time.h>
#include <utmp.h>

char		*strcpy();
char		*strcat();
unsigned	sleep();
unsigned	alarm();
void		exit();

#define	TIMEOUT	-1

char dbg_name[255];
int tty;
struct termio ttymodes;
static jmp_buf sjbuf;


/* print debug message on console */

/*VARARGS0*/
void debug(va_alist)
va_dcl
{
	va_list		 args;
	char		*fmt;
	struct tm	*t;
	long		 clock;
	static FILE	*fp = NULL;

	if (*dbg_name == '\0')
	    return;
	else {
	    if (fp == NULL)
		if ((fp = fopen(dbg_name, "a")) == NULL)
		    return;
	    (void) time(&clock);
	    t = localtime(&clock);

	    (void) fprintf(fp, "[%02d/%02d %02d:%02d] ", t->tm_mon+1,
				t->tm_mday, t->tm_hour, t->tm_min);
	    va_start(args);
	    fmt = va_arg(args, char *);
	    (void) vfprintf(fp, fmt, args); 
	    (void) fprintf(fp, "\n");
	    fflush(fp);
	    va_end(args);
	}
}

/* send a string to modem, sleep n seconds after doing so */

void sendmodem(string, t)
char *string;
int t;
{
	debug("sent: %s", string);
	write(tty, string, strlen(string));		/* send out string */
	if (t)
		sleep(t);
}

/* flush input buffer */
void eatall() { ioctl(tty, TCFLSH, 0); }

/*	flag timeout as having occured, do longjump into waitfor */
void expired() { longjmp(sjbuf, 1); }


/* waitfor will wait 'timeout' seconds for a character, returning
   the character immediately if found, otherwise returning TIMEOUT.  */

char	waitfor(timeout)
int	timeout;
{
	char	c;

	signal(SIGALRM, expired);
	alarm(timeout);

	if (setjmp(sjbuf)) {
	    signal(SIGALRM, SIG_DFL);
	    debug("timeout!");
	    return TIMEOUT;
	} else {
	    do {
		while (read(tty, &c, sizeof(c)) != 1)
		    ;
		c &= 0x7f;
	    } while (c == '\r' || c == '\n'); /* ignore crlfs */
	    alarm(0);
	    signal(SIGALRM, SIG_DFL);
	    return (c & 127);
	}
}

main(argc, argv)
int	argc;
char	**argv;
{
	char	result;
	struct stat buf;
	char	tty_lock[100];
	char	tty_name[100];
	int	speed, baud, modemspeed;
	int     fcntlflags;
	char	aspeed[10];
	FILE    *lock;

	close(0);	/* close stdin */
	close(1);	/* close stdout */
	close(2);	/* close stderr */
	fclose(stdin);
	fclose(stdout);
	fclose(stderr);

	/* name and location of tty locks - change this as needed */
#ifndef	HDB_UUCP
# ifdef BSD43_UUCP				/* berkeley 4.3 uucp */
	strcpy(tty_lock, "/usr/spool/uucp/LCK/LCK..");
# else						/* System 5.2 uucp */
	strcpy(tty_lock, "/usr/spool/uucp/LCK..");
# endif
#else						/* HDB uucp */
	strcpy(tty_lock, "/usr/spool/locks/LCK..");
#endif
	if (argc == 4) 
	    strcpy(dbg_name, argv[3]);
	else
	    *dbg_name = '\0';

	if (argc < 3 && argc > 4) {
		debug("invalid number of parameters, exiting");
		exit(2);
	}

	strcat(tty_lock, argv[1]);
	strcpy(tty_name, "/dev/");
	strcat(tty_name, argv[1]);

	modemspeed = atoi(argv[2]);	/* speed to talk to modem */
	switch (modemspeed) {
		case 300:	baud = B300;   break;
		case 1200:	baud = B1200;  break;
		case 2400:	baud = B2400;  break;
		case 4800:	baud = B4800;  break;
		case 9600:	baud = B9600;  break;
		case 19200:	baud = EXTA;   break;
		default:	debug("invalid baud rate"); exit(2);
	}

	unlink(tty_lock);	/* always existed because user was there */
	umask(022);

	signal(SIGHUP, SIG_IGN);
	signal(SIGQUIT, SIG_IGN);

	for (;;) {

	    /* Set the permissions, owner, and group for dial-out use */

	    chown(tty_name, TTYID, TTYGID);
	    chmod(tty_name, 0662);

	    /*
	    ** tty may have been left in modem mode, so be sure and do
	    ** non-blocking open (and shift to normal mode later!) -- RMT
	    */

	    if ((tty  = open(tty_name, O_RDWR | O_NDELAY, 0662)) == -1) {
		debug("error opening %s", tty_name);
		exit(2);
	    }
	    /*
	     * unset modem mode on tty -- getty will set it again if needed for
	     * a dial-up user.
	     */
	    ioctl(tty, UIOCNOMODEM, 0);

	    /*
	     * for reasons that aren't too clear, it looks like we have to 
	     * close and reopen the tty, instead of just unsetting O_NDELAY.
	     * Don't ask me why...
	     */
	    close(tty);
	    if ((tty  = open(tty_name, O_RDWR, 0662)) == -1) {
		debug("error opening %s 2nd time", tty_name);
		exit(2);
	    }
	    
	    ttymodes.c_iflag = 0;
	    ttymodes.c_oflag = NL1 | CR3;
	    ttymodes.c_cflag = 0;	/* drop dtr */
	    ttymodes.c_lflag = 0;
	    ttymodes.c_line  = 0;
	    ttymodes.c_cc[VMIN]  = 1;	/* min number of characters */
	    ttymodes.c_cc[VTIME] = 0;  	/* no max time before return */
	    ioctl(tty, TCSETA, &ttymodes);  /* hang up the line */
	    sleep(1);
	    ttymodes.c_cflag = baud | CS8 | CREAD | HUPCL;
	    ioctl(tty, TCSETA, &ttymodes);
	    sleep(1);

	    debug("remote line setup");

	    do {
		sendmodem("\rAT\r", 1);		/* set baudrate */
		sendmodem("ATE0\r", 2);		/* turn off echo */
		eatall();			/* flush input buffer */

#ifdef	TELEBIT
		sendmodem("AT&EE0X1V0S2=128S58=0\r", 0);
#else
		sendmodem("ATV0Q0S0=0S2=128M3X1S10=25\r", 0);
#endif

		do {
		    result = waitfor(1); /* wait 1s for result */
		    debug("program modem result=<%c> (%d)", result, result);
		} while (result != '0' && result != '4' && result != TIMEOUT);

		if (result == '4')
		    debug("modem program error");
		if (result == TIMEOUT)
		    debug("modem timed out");
		if (result != '0')
		    sleep(10);	/* wait ten seconds */

	    } while (result != '0');	/* need "OK" from modem */

	    sleep(2);
	    eatall();

	/* Wait for incoming call ('2') or other usage (uucp or user) */

	    while (read(tty,  &result, sizeof(result)) != 1)
		;

	/* If we receive a '2' and no lock file is present, we can
	   be sure that it is not someone calling out. */

	    result &= 127;				/* strip parity */

	    debug("received a character <%c> (%d)", result, result);

	    if (result == '2' && stat(tty_lock, &buf) == -1) {
		/* create a hdb style lock file */
		if ((lock = fopen(tty_lock, "w", 0444))) {
#ifdef HDB_UUCP
		    fprintf(lock, "%10d\n", getpid());
#else
		    putw(getpid(), lock);
#endif
		    fclose(lock);
		}

#ifndef	NORB
		debug("waiting for second ring...");

		do {
		    result = waitfor(8);	/* wait 8 seconds */
		} while (result != '2' && result != TIMEOUT);

		if (result == '2') {
		    debug("second ring detected, waiting for third ring...");
		    do {
			result = waitfor(8);	/* wait 8 seconds */
		    } while (result != '2' && result != TIMEOUT);
		}

		if (result == '2') {		/* got third ring */
		    debug("voice call");
		    unlink(tty_lock);
		    sleep(60);	/* wait long enough for human or answering
				   machine to pick up call */

		} else {	/* must be timeout (no second ring) */
		    debug("waiting 45 seconds for second call");
		    sleep(3);
		    eatall();
		    result = waitfor(42);
		    speed  = 0;

		    if (result != '2') {
			debug("didn't get ring for second call");
			unlink(tty_lock);
		    } else {
#endif
			debug("answering phone");
			sendmodem("ATA\r", 1); 
			eatall();
			result = waitfor(60);
			switch (result) {
			    case TIMEOUT:	
				debug("answer call timeout"); break;
			    case '3':
			    case '8':
				debug("no carrier"); break;
			    case '4':	
				debug("phone answer error"); break;
			    case '5':	
				result = waitfor(1);
				if (result == '0') {
				    debug("FAST call");
				    speed = 19200;
				} else {
				    debug("1200 baud call");
				    speed = 1200;
				}
				break;
			    case '1':	
				result = waitfor(1);
				if (result == '0') {
				    debug("2400 baud call");
				    speed = 2400;
				} else { 
				    debug("300 baud call");
				    speed = 300;
				}
				break;
			    default:	
				debug("unknown character <%c> (%d)",
					result, result);
			} /* end switch */

			eatall();	/* clear out initial crap */

			if (speed == 0) {
			    debug("invalid answer code from modem");
			    unlink(tty_lock);
			} else {
			    debug("execing getty");
#ifdef TELEBIT		/* telebit is programmed to always talk fast */
			    /* (Traina's is, mine isn't. -- RMT) */
			    /* sprintf(aspeed, "%d", modemspeed); */
			    sprintf(aspeed, "%d", speed);
#else
			    sprintf(aspeed, "%d", speed);
#endif
			/* to circumvent a system5 process group bug,
			 * we'll turn off hangup-after-last-close, let
			 * getty close the channel to the tty & reopen it.
			 * this (hopefully) will make getty be able to always
			 * fopen /dev/tty
			 */
			    ttymodes.c_cflag &= ~HUPCL;
			    ioctl(tty, TCSETA, &ttymodes);
			    sleep(1);

			    execl("/etc/getty", "getty", "-h", "-t", "90",
				argv[1], aspeed, (char *)0);

			    debug("exec of getty failed");
			}
#ifndef	NORB
		    }		/* endif got second call */
		}
#endif
            } else { /* result != 2 -->  Must be someone using line */

		debug("giving up line to uucp or user");
		close(tty);		/* Release line */
		sleep(60);

	/* Loop until lock file goes away (uucp or user done) */

		do {
		    while (stat(tty_lock, &buf) == 0)
			sleep(40);
		    sleep(20);
		}  while (stat(tty_lock, &buf) == 0);

	    } /* endif result != 2 */
	} /* for(;;) */
}



More information about the Comp.unix.aux mailing list