[net.sources] uumail/uupath uucp mail router

sob@neuro1.UUCP (Stan Barber) (08/03/85)

Keywords:

Here is my version of a uucp mailer. Thanks to those who contributed
the subroutines on which it is based.

Watch for the signature line!

-------------------------- cut here ---------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	README
#	README.orig
#	makefile
#	uuconf.h
#	gethostnam.c
#	uupath.c
#	getpath.c
#	uumail.c
#	uumail.1
#	uupath.1
# This archive created: Sat Aug  3 01:28:09 1985
export PATH; PATH=/bin:$PATH
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
cat << \SHAR_EOF > 'README'
This is an updated version of uupath and a new program uumail that can 
access a pathalias-generated database to facilitate routine mail.

These program can cope with DBM and standard line-oriented forms of 
pathalias-generated databases.

uumail at present has no concept of what is being piped through it. It is
most suitable to be used as a "mailer" for sendmail to cope with
uucp formatted addresses (so-called "bang" format) that are not adjacent to
the machine attempting to route the mail. If the host is not found in 
the database, uumail returns an error EX_NOHOST which will cause sendmail 
to return the mail with that error.

Here is the mailer segment of a sendmail configuration file that you
can use to define the uumail program as a mailer.
-------------------------------------------------------------------
############################################################
#### This is a special mailer that takes advantage of    ###
#### usemap database for addresses of the form           ###
#### host!user where host is not a uucp neighbor         ###
############################################################

Muumail, P=/usr/lib/uucp/uumail,F=sDFhuUM,S=13,R=23,M=1000000,
	A=uumail $h!$u
--------------------------------------------------------------
Please be sure that the S= and R= rules are correct for your
system. They should match the uucp mailer rules exactly.

A manual page for uumail and uupath are included.

Please forward comments and bug fixes to me at sob@rice.edu or 
ihnp4!shell!neuro1!sob or texsun!drilltech!sob

Stan Barber
Baylor College of Medicine
Houston, Texas
SHAR_EOF
fi # end of overwriting check
if test -f 'README.orig'
then
	echo shar: will not over-write existing file "'README.orig'"
else
cat << \SHAR_EOF > 'README.orig'

The makefile can make two programs.  One is a filter that can be used
to expand network paths.  To install it you rename the program that you
want filtered.  The new file name is simply the old one with a period (.) 
appended to the end.  The filter program (filter) is then renamed to the 
original name of the program to be filtered.
	ie mail druxn!kak gets converted to
	mail. pur-ee!decvax!...!druxn!kak

The second file the makefile makes is uupath.  This will tell you the network
paths of its arguments
name tell you the path to it.

Don't forget to modify the defines for the location of the network map.  The
default location is /etc/usemap

If you have any questions just ask.

			Jeff Donnelly  (217) 333-6106
			University of Illinois
			pur-ee!uiucdcs!donnelly

Jeff may not help much -- his new number is 217-333-7937;
Kolstad can help some also:  214-669-3700
SHAR_EOF
fi # end of overwriting check
if test -f 'makefile'
then
	echo shar: will not over-write existing file "'makefile'"
else
cat << \SHAR_EOF > 'makefile'
####################################################################
# makefile for uumail & uupath
# program to integrate with pathalias created uucpmap databases
# programs originally developed by Jeff Donnelly
# updated to use pathalias database by Stan Barber
# $Header: makefile,v 1.3 85/08/03 00:38:33 UUCP Exp $
#
# the following defines should be configured for you site
# add -DDBM to CCFLAGS if your pathalias database used the
# dbm(3) routines
# if you are a ATT system III or system V site
# or a masscomp add the -DSYSIII flags
# you may want to modify the LIBS line to correspond to 
# libraries that you may need at you site
# see conf.h for other changes that may need be made
# $Log:	makefile,v $
# Revision 1.3  85/08/03  00:38:33  UUCP
# Added support for shar and RCS.
# Changed name of gethostname to gethostnam to allow RCS to work right.
# Stan Barber
# 
# Revision 1.2  85/07/11  19:28:52  sob
# updated with gethostname.c
# 
# Revision 1.1  85/07/11  19:23:22  sob
# Initial revision
# 
###############################################################
.SUFFIXES: .c,v .h,v

CFLAGS= -O -DSYSIII

LIBS= -lBSD 

.c,v.c:
	co -q $*.c

.h,v.h:
	co -q $*.h

uumail: getpath.o uumail.o gethostnam.o 
	cc $(CFLAGS) getpath.o uumail.o gethostnam.o -o uumail $(LIBS)

uupath: getpath.o uupath.o gethostnam.o
	cc $(CFLAGS) getpath.o uupath.o gethostnam.o -o uupath $(LIBS)

getpath.o: getpath.c uuconf.h

uupath.o: uupath.c uuconf.h

uumail.o: uumail.c uuconf.h

gethostnam.o:gethostnam.c

clean: 
	rm -f *.o *.CKP *.BAK *.bak

doc: uumail.1 uupath.1
	nroff -man uumail.1 >uumail.cat; nroff -man uupath.1 >uupath.cat

shar: uumail.c uuconf.h gethostnam.c uupath.c getpath.c README makefile uumail.1 uupath.1 README.orig
	shar README README.orig makefile uuconf.h gethostnam.c uupath.c getpath.c uumail.c uumail.1 uupath.1 > shar.out
SHAR_EOF
fi # end of overwriting check
if test -f 'uuconf.h'
then
	echo shar: will not over-write existing file "'uuconf.h'"
else
cat << \SHAR_EOF > 'uuconf.h'
/* $Header: uuconf.h,v 1.2 85/07/11 19:29:34 sob Exp $
 * Configuration for uumail and uupath utilities
 * Please see the header for makefile for changes you may
 * need to make there.
 * $Log:	uuconf.h,v $
 * Revision 1.2  85/07/11  19:29:34  sob
 * *** empty log message ***
 * 
 * Revision 1.1  85/07/11  19:22:20  sob
 * Initial revision
 * 
 */
#include <stdio.h>
/*
 * sysexits is a file of exit codes that are used in sendmail
 * and other programs ...
 */
#include <sysexits.h>

typedef char bool;

#ifdef DBM
#include <dbm.h>
#endif

#ifdef SYSIII
#define index strchr
#define rindex strrchr
#include <sys/utsname.h>
#endif

#define NAMESIZ 20 /* system name size */
#define PATHSIZ 150 /* path length */

#define TRUE	1
#define FALSE	0

/* Here's where you should put in the the name of the file
 * in which the uucpmap data is kept.
 * For those using DBM, this will be the root filename for the database
 * (eg... file.pag and file.dir with root name file)
 */

#define DATABASE "/usr/lib/uucp/palias"
SHAR_EOF
fi # end of overwriting check
if test -f 'gethostnam.c'
then
	echo shar: will not over-write existing file "'gethostnam.c'"
else
cat << \SHAR_EOF > 'gethostnam.c'
#ifndef lint
static char	sccsid[] = "@(#)gethostnam.c	6.1 (down!honey) 85/01/21";
static char	rcsid[] = "$Header: gethostnam.c,v 6.2 85/08/03 00:25:16 UUCP Exp $";
#endif lint

#ifndef GETHOSTNAME
#include "uuconf.h"

void
gethostname(name, len)
char	*name;
{
	FILE	*whoami, *fopen(), *popen();
	char	*ptr, *index();
#ifdef SYSIII
	struct utsname utsn;
#endif

	*name = '\0';
#ifdef SYSIII
	if (uname(&utsn) != -1)
	{
		strcpy(name,utsn.nodename);
		len = strlen(name);
	  	return;
	}
#endif

	/* try /etc/whoami */
	if ((whoami = fopen("/etc/whoami", "r")) != 0) {
		(void) fgets(name, len, whoami);
		(void) fclose(whoami);
		if ((ptr = index(name, '\n')) != 0)
			*ptr = '\0';
	}
	if (*name)
		return;

	/* try /usr/include/whoami.h */
	if ((whoami = fopen("/usr/include/whoami.h", "r")) != 0) {
		while (!feof(whoami)) {
			char	buf[100];

			if (fgets(buf, 100, whoami) == 0)
				break;
			if (sscanf(buf, "#define sysname \"%[^\"]\"", name))
				break;
		}
		(void) fclose(whoami);
		if (*name)
			return;
	}

	/* ask uucp */
	if ((whoami = popen("uuname -l", "r")) != 0) {
		(void) fgets(name, len, whoami);
		(void) pclose(whoami);
		if ((ptr = index(name, '\n')) != 0)
			*ptr = '\0';
	}
	if (*name)
		return;
	
	/* failure */
	return;
}
#endif GETHOSTNAME
SHAR_EOF
fi # end of overwriting check
if test -f 'uupath.c'
then
	echo shar: will not over-write existing file "'uupath.c'"
else
cat << \SHAR_EOF > 'uupath.c'
/*
 * Name: uupath
 *
 * Calls getpath to lookup the usenet path
 *
 * Author: J. Donnelly  3/82
 * $Log:	uupath.c,v $
 * Revision 1.3  85/08/03  01:26:17  UUCP
 * *** empty log message ***
 * 
 * Revision 1.2  85/07/19  17:47:05  UUCP
 * updated to define Debug for compatability with getpath
 * 
 * Revision 1.1  85/07/11  18:35:59  sob
 * Initial revision
 * 
 *
 */

#include	"uuconf.h"
bool Debug;

static char rcsid[] = "$Header: uupath.c,v 1.3 85/08/03 01:26:17 UUCP Exp $";

main (argc, argv) char *argv[];
{
    char    path[PATHSIZ],work[BUFSIZ];
    int     i,
            retval;					/* value returned from getpath */

    if (argc < 2)
    {
	printf ("Usage: uupath sysname1 sysname2 ...\n");
	exit (EX_USAGE);
    }

    for (i = 1; i < argc; i++)
    {
	retval = getpath (argv[i], &path[0],DATABASE);		/* lookup usenet path */
	if (retval == EX_NOHOST)
	    printf ("Can't find path to %s\n", argv[i]);

	else
	    if (retval == EX_NOINPUT)
	    {
		printf ("Can't open the network map\n");
		exit (EX_TEMPFAIL);
	    }

	    else
		{
		sprintf (&work[0],"Path to %s:  %s\n", argv[i], &path[0]);
    		printf(&work[0],"username");
		}
	}
}
SHAR_EOF
fi # end of overwriting check
if test -f 'getpath.c'
then
	echo shar: will not over-write existing file "'getpath.c'"
else
cat << \SHAR_EOF > 'getpath.c'
/*
 * Name: getpath -- return the full usenet path of the given name
 *
 * Paramaters: sysname (input) -- The system name to be expanded
 *	       pathname (output)  The usenet path of the given system name
 *	       pathfile (input) the file to search for the system name
 *
 * Returns: EX_OK     -- path found
 *	    EX_NOHOST -- path not found
 *	    EX_NOINPUT-- unable to open usemap
 *
 * Author: J. Donnelly   3/82
 *
 */

/* 22-jun-83 Sheppard
 * modified to rewind path file (if open), rather than open again
 *
 * $Log:	getpath.c,v $
 * Revision 1.6  85/08/03  00:48:57  UUCP
 * Cleaned up with lint.
 * Stan Barber
 * 
 * Revision 1.5  85/07/19  17:45:13  UUCP
 * Added \t as a valid seperation character for the database
 * in the non DBM case. This is what pathalias uses.
 * 
 * Revision 1.4  85/07/19  16:44:07  UUCP
 * revised to return proper things in accordance with sysexits
 * Stan
 * 
 * Revision 1.3  85/07/11  19:30:31  sob
 * added "uuconf.h" include file and deleted duplicated information
 * 
 * Revision 1.2  85/07/10  18:30:59  sob
 * updated to add DBM capabilities
 * Stan Barber, Baylor College of Medicine
 * 
 * Revision 1.1  85/07/10  18:03:28  sob
 * Initial revision
 * 
 */

#include	"uuconf.h"

static char rcsid[] = "$Header: getpath.c,v 1.6 85/08/03 00:48:57 UUCP Exp $";


extern bool Debug;

FILE * fopen (), *in;

getpath (sysname, pathname,pathfile)
char   *sysname, *pathname,*pathfile;
{
    char    name[NAMESIZ],*p,t;

#ifdef DBM
    datum lhs,rhs;
#endif
if (Debug)
	printf("In getpath: Sysname = %s, Pathfile = %s\n",sysname,pathfile);
#ifdef DBM
    if (dbminit(pathfile) <0) return(EX_NOINPUT);
    	lhs.dptr = sysname;
	lhs.dsize = strlen(sysname)+1;
	rhs = fetch(lhs);
	if (rhs.dptr == NULL) return(EX_NOHOST); /* no name found */
	strcpy(pathname,rhs.dptr);
        return(EX_OK);			/* system name found */

#else
if (in == NULL) {
	if ((in = fopen(pathfile, "r")) == NULL)
	    return(EX_NOINPUT);
    }
    else
	rewind(in);

    for (;;)
    {
	p = &name[0];
	while ((t = getc(in)) != EOF && (*p++ = t) != ' ' && t != '\t'); /* read the system name */
	if( t == EOF) return(EX_NOHOST);
	*--p = '\0';					/* set end of string */
	p = &name[0];
	if (Debug) printf("Found %s\n",p);
	if (strcmp (p,sysname) == 0)
	    break;
	while ((getc (in) != '\n'));			/* skip this path */
    }

    p = pathname;					/* save start loc of pathname */
    while ((*pathname++ = getc (in)) != '\n');
    *--pathname = '\0';
    pathname = p;
    return(EX_OK);			/* system name found */
#endif
}
SHAR_EOF
fi # end of overwriting check
if test -f 'uumail.c'
then
	echo shar: will not over-write existing file "'uumail.c'"
else
cat << \SHAR_EOF > 'uumail.c'
/*
 *  U U M A I L
 *  This program when invoked in the form:
 *  uumail host!user will consult the local usemap for
 *  the proper routing.
 * 
 *  If it finds it, it will invoke the proper uux call
 *  to send the mail.
 *  Otherwise it aborts with an error 68 (host unknown)
 * $Log:	uumail.c,v $
 * Revision 1.7  85/08/03  00:49:14  UUCP
 * Cleaned up with lint.
 * Stan Barber
 * 
 * Revision 1.6  85/07/11  19:30:00  sob
 * changed PATHSIZE to PATHSIZ to conform with uupath
 * 
 * Revision 1.5  85/07/11  18:08:13  sob
 * This one works both as uumail and uupath!
 * Stan
 * 
 * Revision 1.4  85/07/10  18:35:05  sob
 * moved DBM to getpath
 * Stan Barber
 * 
 * Revision 1.3  85/07/09  01:28:14  sob
 * First attempt to integrate uupath
 * Not successful. Changed PATHALIAS define
 * to DBM... will ultimately alter getpath as well
 * added gethostname call to fill in for local host.
 * 
 * Revision 1.2  85/07/08  05:29:16  sob
 * This one works with pathalias database...
 * need to modify to substitue for uupath.
 * Stan
 * 
 * Revision 1.1  85/07/08  03:11:10  sob
 * Initial revision
 * 
 */

#include "uuconf.h"

bool Debug;
bool uupath;

extern FILE	*popen();
extern char	*index();
extern char	*rindex();
extern char	*malloc();


static char rcsid[] ="$Header: uumail.c,v 1.7 85/08/03 00:49:14 UUCP Exp $$";

main(argc, argv)
	char *argv[];
{
	FILE *out;	/* output to uux */
	char lbuf[512]; /* for pipe to uux */
	char from[512];	/* accumulated path of sender */
	char sys[64];	/* a system in path */
	char cmd[2000];
	int i,
            error = 0,
            bangcnt,
	    local = 0;

    char    c,
            name[20], 			/* The system name (if any) */
           *fname,
	   *path,			/* uupath to the system */
           *sysname,			/* points to the system name */
           *p,				/* tmp pointer to argv's */
	   *rsys,
	   *paths =DATABASE;

	if(strcmp(argv[0],"uupath") == 0)
		uupath = TRUE;
	else
	{
		if (argc != 2)
		while(argc > 1 && argv[1][0] == '-')
		{
			argv++;
			argc--;
			switch(argv[0][1])
			{
			case 'd':	
				/* Just type some debugging information */
				Debug = TRUE;
				break;
			case 'w':	/* just print the path */
				uupath = TRUE;
				break;
			case 'p':	/* An alternative path database requested */
				argv++;
				argc--;
				if (argc > 1)
				{
					paths = argv[0];
					if (Debug) printf ("Database = %s\n",paths);
				}
				else
				{
					fprintf(stderr,"Alternate database expected\n");
					exit(1);
				}
				break;
			default:
				fprintf (stderr, "Unknown option: %s\n", *argv);
			}
		}

	}
    
    (void) strcpy(from, "");

    path = malloc(PATHSIZ);

    bangcnt = 0;

    p = argv[1];

    sysname = &name[0];

    if (uupath) 

	(void) strcpy(sysname ,p);

    else 
	{
	do						/* count bangs */
		{
		    while (((c = *p++) != '!') && (c != '\0'));
			    if (c == '!') bangcnt++;
		}
	while (c != '\0' && bangcnt == 1);
		;
	if (bangcnt >= 1)				/* expand path */
		{
		    while ((*sysname++ = *argv[1]++) != '!');
			    *--sysname = '\0';

			}
	
	if (bangcnt == 0) {
			gethostname(p,32);
			strcpy(sysname,p);
			local = 1;
			}
	}
	if (Debug) printf("sysname = %s\n",&name[0]);

	
	if ((error = getpath (&name[0], path,paths)) != EX_OK)
	    {
		if (error == EX_NOHOST) fprintf (stderr, "System %s not found in network map\n", &name[0]);
		if (error == EX_NOINPUT) fprintf(stderr,"Database %s could not be opened\n",paths);
		exit(EX_NOHOST);
	    }

       if (path == "%s") path = sysname;

       if(Debug) printf("Path = %s\n",path);

	p = argv[1];					/* save name */
	for (i = 0; i < 1 && *p != '\0'; p++)
	    if (*p == '/')
		i++;
	fname = &from[0];

        if (uupath)
		sprintf(fname,path,"username");
	else
		sprintf(fname,path,argv[1]);

	p = &from[0];
	rsys = &sys[0];

	if (!local)
		{
		while((*rsys++ = *p++) != '!');
		*--rsys = '\0';
		}
		else
			strcpy(rsys,argv[1]);

		
	if ((!local && *fname =='\0') || (local && &sys[0]=='\0')) {
		fprintf(stdout, "null name\n");
		exit(EX_DATAERR);
	}
	if (Debug)
		printf("p = %s sys = %s fname = %s\n",p, &sys[0],fname);

	if (uupath)
		{
		printf ("Path to %s:  %s\n", argv[1], fname);
		exit(0);
		}
	else
	{
		if (local)
			sprintf(cmd, "rmail %s", &sys[0]);
		else {
		if (index(p, '!'))
			sprintf(cmd, "uux - %s!rmail \\(%s\\)", &sys[0], p);
		else
		sprintf(cmd, "uux - %s!rmail %s", &sys[0], p);

		}
	if (Debug) {
			fprintf(stderr,"Command is %s\n",cmd);
			exit(EX_OK);
		}
	out = popen(cmd, "w");
	fputs(lbuf, out);
	while (fgets(lbuf, sizeof lbuf, stdin))
		fputs(lbuf, out);
	i = pclose(out);
	if ((i & 0377) != 0)
		{
			fprintf(stderr, "pclose: status 0%o\n", i);
			exit(EX_OSERR);
		}
	   }
 exit((i >> 8) & 0377);
}
SHAR_EOF
fi # end of overwriting check
if test -f 'uumail.1'
then
	echo shar: will not over-write existing file "'uumail.1'"
else
cat << \SHAR_EOF > 'uumail.1'
.TH "UUMAIL" "8" "Baylor College of Medicine"
.fi
.ad b
.SH NAME
uumail \- route mail using uucpmap database
.SH SYNOPSIS
.B uumail [ -d ] [ -p \fIaltpathdb\fR ] \fIhost!user\fR
.B uumail [ -d ] [ -p \fIaltpathdb\fR ] -w  \fIhost\fR
.SH DESCRIPTION
.B Uumail
is designed to be used as a mail delivery program to correctly
route mail over uucp connections.
.SS Options
.IP "-d" 16
The -d option turns on the limited debugging facility built into the
mailer.  In debug mode, the mailer does not actually mail anything, but
tells you what it would do if it did do it.
.IP "-w" 16
The -w option causes 
.B uumail
to behave like its companion program
.B uupath
and generate a pathname to the 
.I host
name given. No other action is taken.
.IP "-p \fIaltpathdb\fR" 16
The -p option allows the specification of an alternate path file.  The
default path file is "/usr/lib/uucp/palias".  The path file is the output
of program pathalias (produced by Peter Honeyman), and contains one
entry for each known node on the network.
.SS Arguments
.IP \fIhost!user\fR 16
where host is a system node name on the network and user is the login
name of the addressee. Only one addressee is allowed per invocation of
.B uumail.

.SH FILES
.IP "/usr/lib/uucp/palias" 20
Path file produced by pathalias.
.SH "SEE ALSO"
pathalias(1), Pnews(1), Rnmail(1), rn(1), postnews(1), readnews(1),
uupath(1), sendmail(8)

.SH AUTHORS
.br
Stan Barber, Baylor College of Medicine
.br
Getpath routine by John Donnelly, University of Illinois
.br
Gethostname routine by Peter Honeyman, Princeton

SHAR_EOF
fi # end of overwriting check
if test -f 'uupath.1'
then
	echo shar: will not over-write existing file "'uupath.1'"
else
cat << \SHAR_EOF > 'uupath.1'
.TH "UUPATH" "1" "Baylor College of Medicine"
.fi
.ad b
.SH NAME
uupath \- print mail routing information using uucpmap database
.SH SYNOPSIS
.B uupath  \fIhost1 host2 host3 ...\fR
.SH DESCRIPTION
.B Uupath
is designed to be used to query the uucpmap database for mail routing
paths used by
.I uumail.
.SS Arguments
.IP "host1 host2 host3 ..."
where host1, host2, host3 and so on are system node names on the network.
Many hostnames may be entered as arguements to
.I uupath.

.SH FILES
.IP "/usr/lib/uucp/palias" 
Path file produced by pathalias.
.SH "SEE ALSO"
pathalias(1), Pnews(1), Rnmail(1), rn(1), postnews(1), readnews(1), uumail(8)

.SH AUTHORS
.br
Jeff Donnelly, University of Illinois
.br
Stan Barber, Baylor College of Medicine & Rice University

SHAR_EOF
fi # end of overwriting check
#	End of shell archive
exit 0