[alt.sources] Anonymous Contact Service software v1.1, Part03/08

csu@alembic.acs.com (Dave Mack) (07/16/90)

This is the second distribution of the Anonymous Contact Service
software. The distribution consists of 8 shar files. This will
(hopefully) be the last full distribution of the system - all
future versions will be distributed as patches. The patchlevel of
this version is 1.

The ACS software provides a mechanism for posting anonymous articles,
for receiving replies to those articles which are also anonymous, and
permits prolonged anonymous conversations in which neither writer knows
the other's actual e-mail address.

This software is currently being used to provide an anonymous personals
service in alt.personals.

Dave Mack
csu@alembic.ACS.COM

#! /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 archive 3 (of 8)."
# Contents:  mailer/aliases.8 mailer/main.c mailer/misc.c mailer/nptx.c
#   mailer/pw.c
# Wrapped by csu@alembic on Sun Jul 15 12:46:45 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'mailer/aliases.8' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mailer/aliases.8'\"
else
echo shar: Extracting \"'mailer/aliases.8'\" \(4447 characters\)
sed "s/^X//" >'mailer/aliases.8' <<'END_OF_FILE'
X.TH ALIASES 8
X.tr ~
X.SH NAME
Xaliases \- alias file for smail
X.SH DESCRIPTION
XThis file is used by
X.I smail
Xonly if
X.I SENDMAIL
Xis
X.I not defined.
XIf
X.I SENDMAIL
Xis defined, then
X.I sendmail
Xdoes all of the aliasing for the host.
X.PP
XThis file contains a list of aliases for
Xlocal users or mailing lists.
XThe format of each alias is
X.sp
X.ce
Xalias_name~recip_name1~recip_name2~...
X.sp
XAn attempt has been made to remain compatible with
X.I sendmail
Xalias file format, though the syntax is much more format free than
X.I sendmail.
XAs distributed,
X.I case differences are ignored
Xwhen comparing names to aliases.
XOnly alias names which resolve to the local host are recognized, and are
Xstored in their local form.
XLines which start with a white~space are continuation lines.
XParenthesised strings are taken as comments (no nesting),
Xas is anything after a '#' (as in
X.IR /bin/sh ).
XHere are some examples:
X.sp
X.nf
X# this whole line is a comment
X#
X# These are equivalent definitions
X
Xalias_name      recip1 recip2 recip3
X
Xalias_name:     recip1, recip2 , recip3
X
Xalias_name      recip1 recip2
X                recip3
X
Xalias_name      recip1  # Recip1's name
X                recip2  # Recip2's name
X                recip3  # Recip3's name
X
Xalias_name      recip1 (Recp1's name) recip2 (Recp2's name)
X                recip3 (Recp3's name)
X
Xalias_name@thishost     recip1 recip2 recip3
X
Xalias_name@thisdomain   recip1 recip2 recip3
X
Xthishost!alias_name     recip1 recip2 recip3
X
Xthisdomain!alias_name   recip1 recip2 recip3
X.fi
X.PP
XMailing lists are easily handled by two forms of file inclusion.
XThe first form is the same as is supported by
X.I sendmail
X.sp
X.ce
Xmylist	:include:/usr/lib/ml/mylist
X.sp
XIn this example, each entry in
X.I /usr/lib/ml/mylist
Xwould be added to the alias for
X.I mylist.
XThe second form is unique to
X.I smail.
XIt allows the
X.I aliases
Xfile to include other
X.I aliases
Xfiles.
X.sp
X.ce
X:include:/usr/lib/ml/more-aliases
X.sp
XThis would include the file
X.I /usr/lib/ml/more-aliases
Xas a regular alias file.
XThis makes it easier to maintain groups of aliases that
Xchange frequently, such as the list of netnews moderators.
X.PP
XAll aliases are recursive, so care
Xmust be taken in their definition.
X.I smail
Xaliasing attempts to prevent infinite loops, and to
Xdo what was intended by the user.  For example, the alias:
X.sp
X.ce
Xmylogin~mypc!mylogin~mylogin
X.sp
XExpands to
X.sp
X.ce
Xmypc!mylogin mylogin
X.sp
Xeven though the second occurrence of
X.I mylogin
Xmatches the alias name.
X.sp
XBoth forms of file inclusion are recursive, too,
Xso watch out for nesting include files.  They
Xmay lead to infinite loops.
X.PP
XWhile the cost of parsing an alias file is usually negligible,
Xit's wise to take savings anywhere savings
Xcan be found.  Therefore, it's worth mentioning
X.IR smail 's
Xparsing strategy.
X.I smail
Xwill try to get by with doing as little work
Xas possible when aliasing.  If on a particular
Xinvocation of
X.I smail,
Xnone of the recipent addresses are local,
X(i.e., not potential aliases)
Xthen the
X.I aliases
Xfile won't even be read.  Similarly,
Xwhen an
X.I aliases
Xfile is read, it does not expand any of the :include: files
Xuntil they are referenced.  Thus, in the alias (above) for
X.I mylist,
Xthe file
X.I :include:/usr/lib/ml/mylist
Xwould not be opened and read (parsed) unless
Xmail was sent to
X.I mylist.
XWise use of :include: files can greatly
Xincrease the efficiency of the alias utility.
XIt's not clear exactly where the
X.I break-even
Xpoint is when deciding to use an  :include: file in an alias,
Xversus having all of the recipents listed on the line;
Xbut if a mailing list is large (whatever that means)
Xit is wise to use the :include: feature to save on
Xparsing costs.  Note that this discussion only applies to the
Xfirst form of file inclusion, since reading an
X.I aliases
Xfile constitutes a reference to :include: files of the second form.
X.PP
XThere is another form of aliasing which works with the alias capability.
XThis is called
X.I per user forwarding.
XFor a given user name, if there is no alias for the user
Xthen, if the file
X.I ~user/.forward
Xexists, then its contents will be treated as an alias for
Xthe user.  The syntax is the same as that of the
Xrecipient lists in the alias file described above.
X.PP
XOne difference between
X.I smail
Xand
X.I sendmail
Xis that
X.I smail
Xdoesn't handle stuff like mail to files
Xor command execution.
X.SH SEE ALSO
Xsmail(8), paths(8), pathproc(8)
X.SH VERSION
X@(#)aliases.8	2.5 (smail) 9/15/87
END_OF_FILE
if test 4447 -ne `wc -c <'mailer/aliases.8'`; then
    echo shar: \"'mailer/aliases.8'\" unpacked with wrong size!
fi
# end of 'mailer/aliases.8'
fi
if test -f 'mailer/main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mailer/main.c'\"
else
echo shar: Extracting \"'mailer/main.c'\" \(5194 characters\)
sed "s/^X//" >'mailer/main.c' <<'END_OF_FILE'
X/*
X**
X**  rmail/smail - UUCP mailer with automatic routing.
X**
X**  Christopher Seiwald		/+\
X**  chris@cbosgd.att.com	+\
X**  January, 1985		\+/
X**
X*/
X
X#ifndef lint
Xstatic char 	*sccsid="@(#)main.c	2.5 (smail) 9/15/87";
X#endif
X
X/*
X**
X**  usage:  	rmail [options] address...
X**		smail [options] address...
X**  options:
X**		-d 		debug - verbose and don't invoke mailers.
X**		-v		verbose - just verbose.
X**		-A		print mapped addresses.  don't invoke mailers.
X**		-h hostname	set hostname 
X**		-H hostdomain	set hostdomain (default hostname.MYDOM)
X**		-p pathfile	path database filename
X**		-r		force routing of host!address
X**		-R		reroute even explicit path!user
X**		-l		user@domain goes to local mailer
X**		-L		all mail goes local
X**		-q number	mail queueing cost threshold
X**		-m number	limit on number of uux_noqueue jobs
X**		-u string	string of flags for uux
X**              -F address      name to substitute in From: line
X**		-a aliasfile	aliases filename (not used with SENDMAIL)
X**		-n namelist	list of full names for simple aliases
X*/
X
X#include	<stdio.h>
X#include	<ctype.h>
X#include	"defs.h"
X
Xint exitstat = 0;		/* exit status, set by resolve, deliver	*/
X
Xenum edebug debug     = NO;	/* set by -d or -v option		*/
Xenum ehandle handle   = HANDLE;	/* which mail we can handle, see defs.h	*/
Xenum erouting routing = ROUTING;/* to route or not to route, see defs.h */
X
Xchar hostname[SMLBUF]   = "";	/* set by -h, defaults in defs.h 	*/
Xchar hostdomain[SMLBUF] = "";	/* set by -H, defaults in defs.h 	*/
Xchar hostuucp[SMLBUF] = "";	/* built with hostname+".UUCP"	 	*/
X
Xchar *pathfile  = PATHS;	/* or set by -p 			*/
Xchar *uuxargs   = NULL;		/* or set by -u				*/
X
Xchar *aliasfile =
X#ifdef ALIAS
X		ALIAS;		/* or set by -a				*/
X#else
X		NULL;
X#endif
X
Xchar *fnlist    =
X#ifdef FULLNAME
X		FULLNAME;	/* or set by -n				*/
X#else
X		NULL;
X#endif
X
Xint  queuecost  = QUEUECOST;	/* or set by -q				*/
Xchar *from_addr = NULL;		/* or set by -F				*/
Xint  maxnoqueue = MAXNOQUEUE;	/* or set by -m                         */
X
Xint  getcost    = 
X#ifdef GETCOST
X		1;	/* get cost of path even if not routing */
X#else
X		0;
X#endif
X
Xchar *spoolfile = NULL;		/* name of the file containing letter   */
XFILE *spoolfp;			/* file pointer to spoolfile		*/
Xint  spoolmaster = 0;		/* indicates 'control' of spoolfile     */
X
Xvoid spool();
X
X
X/*
X**
X**  rmail/smail: mail stdin letter to argv addresses.
X**
X**  After processing command line options and finding our host and domain 
X**  names, we map addresses into <host,user,form,cost> sets.  Then we deliver.
X**
X*/
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	char *hostv[MAXARGS];		/* UUCP neighbor 		*/
X	char *userv[MAXARGS];		/* address given to host 	*/
X	int  costv[MAXARGS];		/* cost of resolved route	*/
X	enum eform formv[MAXARGS];	/* invalid, local, or uucp 	*/
X	char *p;
X	int c;
X	int  printaddr  = 0;		/* or set by -A			*/
X	int nargc;
X	char **nargv, **alias();
X
X	char *optstr = "cdvArRlLH:h:p:u:q:a:n:m:f:F:";
X	extern char *optarg;
X	extern int optind;
X
X/*
X**  see if we aren't invoked as rmail
X*/
X	if((p = rindex(argv[0], '/')) == NULL) {
X		p = argv[0];
X	} else {
X		p++;
X	}
X
X	if(*p != 'r' ) {
X		handle = ALL;
X	}
X
X/*
X**  Process command line arguments
X*/
X	while ((c = getopt(argc, argv, optstr)) != EOF) {
X		switch ( c ) {
X		case 'd': debug      = YES; 		break;
X		case 'v': debug      = VERBOSE; 	break; 
X		case 'A': printaddr  = 1; 		break; 
X		case 'F': from_addr  = optarg;		break;
X		case 'r': routing    = ALWAYS;		break;
X		case 'R': routing    = REROUTE;		break;
X		case 'l': handle     = JUSTUUCP;	break;
X		case 'L': handle     = NONE;		break;
X		case 'f': spoolfile  = optarg;		break;
X		case 'p': pathfile   = optarg; 		break;
X		case 'u': uuxargs    = optarg; 		break;
X		case 'a': aliasfile  = optarg; 		break;
X		case 'n': fnlist     = optarg; 		break;
X		case 'H': (void) strcpy(hostdomain, optarg);	break;
X		case 'h': (void) strcpy(hostname, optarg); 	break;
X		case 'm': if(isdigit(*optarg)) {
X				  maxnoqueue = atoi(optarg);
X			  }
X			  break;
X		case 'c': getcost     = 1;		break;
X		case 'q': if(isdigit(*optarg)) {
X				  queuecost = atoi(optarg);
X			  }
X			  break;
X		default:
X			error( EX_USAGE, "valid flags are %s\n", optstr);
X		}
X	}
X	if ( argc <= optind ) {
X		error( EX_USAGE, "usage: %s [flags] address...\n", argv[0] );
X	}
X
X/*
X**  Get our default hostname and hostdomain.
X*/
X	getmynames();
X
X/*
X**  Spool the letter in a temporary file.
X*/
X	nargc = argc - optind;
X	if(printaddr == 0) {
X		spool(nargc, &argv[optind]);
X	}
X
X/*
X** Do aliasing and fullname resolution
X*/
X	nargv = alias(&nargc, &argv[optind]);
X
X/*
X**  Map argv addresses to <host, user, form, cost>.
X*/
X	map(nargc, nargv, hostv, userv, formv, costv);
X/*
X**  If all we want it mapped addresses, print them and exit.
X*/
X	if(printaddr) {
X		int i;
X		char abuf[SMLBUF];
X		for(i=nargc-1; i >= 0; i--) {
X			if(formv[i] == ERROR) {
X				(void) strcpy(abuf, nargv[i]);
X			} else {
X				build(hostv[i], userv[i], formv[i], abuf);
X			}
X			(void) fputs(abuf, stdout);
X			if(i != 0) (void) putchar(' ');
X		}
X		(void) putchar('\n');
X		exit(0);
X	}
X/*
X**  Deliver.
X*/
X	deliver(nargc, hostv, userv, formv, costv);
X/*
X**  Exitstat was set if any resolve or deliver failed, otherwise 0.
X*/
X	return( exitstat );
X}
END_OF_FILE
if test 5194 -ne `wc -c <'mailer/main.c'`; then
    echo shar: \"'mailer/main.c'\" unpacked with wrong size!
fi
# end of 'mailer/main.c'
fi
if test -f 'mailer/misc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mailer/misc.c'\"
else
echo shar: Extracting \"'mailer/misc.c'\" \(6551 characters\)
sed "s/^X//" >'mailer/misc.c' <<'END_OF_FILE'
X
X/*
X**  Miscellaneous support functions for smail/rmail
X*/
X
X#ifndef lint
Xstatic char 	*sccsid="@(#)misc.c	2.5 (smail) 9/15/87";
X#endif
X
X# include	<stdio.h>
X# include	<sys/types.h>
X# include	<ctype.h>
X# include	"defs.h"
X#ifdef BSD
X# include	<sys/time.h>
X# include	<sys/timeb.h>
X#else
X# include	<time.h>
X# include	<sys/utsname.h>
X#endif
X
Xextern int  exitstat;		/* set if a forked mailer fails */
Xextern enum edebug debug;	/* how verbose we are 		*/ 
Xextern enum ehandle handle;	/* what we handle		*/
Xextern char *uuxargs;		/* arguments given to uux       */
Xextern int  queuecost;		/* threshold for queueing mail  */
Xextern int  maxnoqueue;		/* max number of uucico's       */
Xextern enum erouting routing;	/* when to route addresses	*/
Xextern char hostdomain[];	/* */
Xextern char hostname[];		/* */
Xextern char hostuucp[];		/* */
Xextern char *pathfile;		/* location of path database	*/
Xextern char *spoolfile;		/* file name of spooled message */
Xextern FILE *spoolfp;		/* file ptr  to spooled message */
Xextern int spoolmaster;		/* set if creator of spoolfile  */
X
Xextern struct tm *localtime();
X
Xstruct tm *gmt, *loc;		/* GMT and local time structure	*/
Xtime_t now;			/* current system time		*/
Xchar nows[50];			/* time in ctime format		*/
Xchar arpanows[50];		/* time in arpa format		*/
X
X# ifdef LOG
Xvoid
Xlog(command, from, size)
Xchar *command, *from;
Xlong size;
X{
X	FILE *fd;
X	char *logtime, tbuf[50];
X	int cmask;
X
X	logtime = strcpy(tbuf, nows);
X	logtime[16] = '\0';
X	logtime += 4;
X
X	cmask = umask(0);
X	fd = fopen(LOG, "a");
X	(void) umask(cmask);
X
X	if (fd != NULL) {
X		(void) fprintf(fd, "%s\t%ld\t%s\t%s\n",
X			logtime, size, from, command);
X		(void) fclose(fd);
X	}
X}
X# endif
X
X# ifdef RECORD
XFILE *
Xrecord(command, from, size)
Xchar *command, *from;
Xlong size;
X{
X	FILE *fd;
X	char *logtime, buf[SMLBUF];
X	int cmask;
X
X	logtime = strcpy(buf, nows);
X	logtime[16] = 0;
X	logtime += 4;
X
X	cmask = umask(0);
X	fd = fopen(RECORD, "a");
X	(void) umask(cmask);
X
X	if (fd != NULL) {
X		(void) fprintf(fd, "%s: %s, from %s, %ld bytes\n", 
X			logtime, command, from, size);
X	}
X	while(fgets(buf, sizeof(buf), spoolfp) != NULL) {
X		(void) fputs(buf, fd);
X	}
X	(void) fclose(fd);
X}
X# endif
X
X
Xsetdates()
X{
X	time_t time();
X	struct tm *gmtime();
X	char *ctime(), *arpadate();
X
X	(void) time(&now);
X	(void) strcpy(nows, ctime(&now));
X	gmt = gmtime(&now);
X	loc = localtime(&now);
X	(void) strcpy(arpanows, arpadate(nows));
X}
X
X/*
X**  Note: This routine was taken from sendmail
X**
X**  ARPADATE -- Create date in ARPANET format
X**
X**	Parameters:
X**		ud -- unix style date string.  if NULL, one is created.
X**
X**	Returns:
X**		pointer to an ARPANET date field
X**
X**	Side Effects:
X**		none
X**
X**	WARNING:
X**		date is stored in a local buffer -- subsequent
X**		calls will overwrite.
X**
X**	Bugs:
X**		Timezone is computed from local time, rather than
X**		from whereever (and whenever) the message was sent.
X**		To do better is very hard.
X**
X**		Some sites are now inserting the timezone into the
X**		local date.  This routine should figure out what
X**		the format is and work appropriately.
X*/
X
Xchar *
Xarpadate(ud)
X	register char *ud;
X{
X	register char *p;
X	register char *q;
X	static char b[40];
X	extern char *ctime();
X	register int i;
X#ifndef BSD
X	extern char *tzname[];
X	time_t t, time();
X#else
X	/* V7 and 4BSD */
X	struct timeb t;
X	extern struct timeb *ftime();
X	extern char *timezone();
X#endif
X
X	/*
X	**  Get current time.
X	**	This will be used if a null argument is passed and
X	**	to resolve the timezone.
X	*/
X
X#ifndef BSD
X	(void) time(&t);
X	if (ud == NULL)
X		ud = ctime(&t);
X#else
X	/* V7 or 4BSD */
X	ftime(&t);
X	if (ud == NULL)
X		ud = ctime(&t.time);
X#endif
X
X	/*
X	**  Crack the UNIX date line in a singularly unoriginal way.
X	*/
X
X	q = b;
X
X	p = &ud[8];		/* 16 */
X	if (*p == ' ')
X		p++;
X	else
X		*q++ = *p++;
X	*q++ = *p++;
X	*q++ = ' ';
X
X	p = &ud[4];		/* Sep */
X	*q++ = *p++;
X	*q++ = *p++;
X	*q++ = *p++;
X	*q++ = ' ';
X
X	p = &ud[22];		/* 1979 */
X	*q++ = *p++;
X	*q++ = *p++;
X	*q++ = ' ';
X
X	p = &ud[11];		/* 01:03:52 */
X	for (i = 8; i > 0; i--)
X		*q++ = *p++;
X
X				/* -PST or -PDT */
X#ifndef BSD
X	p = tzname[localtime(&t)->tm_isdst];
X#else
X	p = timezone(t.timezone, localtime(&t.time)->tm_isdst);
X#endif
X	if (p[3] != '\0')
X	{
X		/* hours from GMT */
X		p += 3;
X		*q++ = *p++;
X		if (p[1] == ':')
X			*q++ = '0';
X		else
X			*q++ = *p++;
X		*q++ = *p++;
X		p++;		/* skip ``:'' */
X		*q++ = *p++;
X		*q++ = *p++;
X	}
X	else
X	{
X		*q++ = ' ';
X		*q++ = *p++;
X		*q++ = *p++;
X		*q++ = *p++;
X	}
X
X	p = &ud[0];		/* Mon */
X	*q++ = ' ';
X	*q++ = '(';
X	*q++ = *p++;
X	*q++ = *p++;
X	*q++ = *p++;
X	*q++ = ')';
X
X	*q = '\0';
X	return (b);
X}
X
X/*
X *	The user name "postmaster" must be accepted regardless of what
X *	combination of upper and lower case is used.  This function is
X *	used to convert all case variants of "postmaster" to all lower
X *	case.  If the user name passed in is not "postmaster", it is
X *	returned unchanged.
X */
Xchar *
Xpostmaster(user)
Xchar *user;
X{
X	static char *pm = "postmaster";
X
X	if(strcmpic(user, pm) == 0) {
X		return(pm);
X	} else {
X		return(user);
X	}
X}
X
X/*
X * Return 1 iff the string is "UUCP" (ignore case).
X */
Xisuucp(str)
Xchar *str;
X{
X	if(strcmpic(str, "UUCP") == 0) {
X		return(1);
X	} else {
X		return(0);
X	}
X}
X
X/*
X** sform(form) returns a pointer to a string that tells what 'form' means
X*/
X
Xchar *
Xsform(form)
Xenum eform form;
X{
X	if(form == ERROR)  return("ERROR");
X	if(form == LOCAL)  return("LOCAL");
X	if(form == DOMAIN) return("DOMAIN");
X	if(form == UUCP)   return("UUCP");
X	if(form == ROUTE)  return("ROUTE");
X	return("UNKNOWN");
X}
X
X/*
X**
X**  getmynames(): what is my host name and host domain?
X**
X**  Hostname set by -h, failing that by #define HOSTNAME, failing
X**  that by gethostname() or uname().
X**  
X**  Hostdomain set by -h, failing that by #define HOSTDOMAIN,
X**  failing that as hostname.MYDOM, or as just hostname.
X**
X**  See defs.h for the inside story.
X**
X*/
X
Xgetmynames()
X{
X#ifdef HOSTNAME
X	if (!*hostname)
X		(void) strcpy(hostname, HOSTNAME);
X#endif
X#ifdef GETHOSTNAME
X	if (!*hostname)
X		gethostname(hostname, SMLBUF - 1);
X#endif
X#ifdef UNAME
X	if (!*hostname) {
X		struct utsname site;
X
X		if (uname(&site) < 0)
X			error(EX_SOFTWARE, "uname() call failed", 0);
X		(void) strcpy(hostname, site.nodename);
X	}
X#endif
X	if (!*hostname)
X		error(EX_SOFTWARE, "can't determine hostname.\n", 0);
X#ifdef HOSTDOMAIN
X	if (!*hostdomain)
X		(void) strcpy(hostdomain, HOSTDOMAIN);
X#endif
X#ifdef MYDOM
X	if (!*hostdomain)
X		(void) strcat(strcpy(hostdomain, hostname), MYDOM);
X#endif
X	if (!*hostdomain)
X		(void) strcpy(hostdomain, hostname);
X
X	(void) strcat(strcpy(hostuucp, hostname), ".UUCP");
X}
END_OF_FILE
if test 6551 -ne `wc -c <'mailer/misc.c'`; then
    echo shar: \"'mailer/misc.c'\" unpacked with wrong size!
fi
# end of 'mailer/misc.c'
fi
if test -f 'mailer/nptx.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mailer/nptx.c'\"
else
echo shar: Extracting \"'mailer/nptx.c'\" \(3534 characters\)
sed "s/^X//" >'mailer/nptx.c' <<'END_OF_FILE'
X#ifndef lint
Xstatic char *sccsid = "@(#)nptx.c	2.5 (smail) 9/15/87";
X#endif
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <pwd.h>
X#include "defs.h"
X#include <ctype.h>
X
Xchar *malloc(), *index(), *fullname();
Xvoid nptx(), free(), dotspace();
X
Xenum edebug debug;	/* not used by nptx */
Xchar *fnlist = NULL;	/* not used by nptx */
X
Xmain()
X{
X	int i;
X	char buf[SMLBUF], *p, *name, *last, *nick, *ctmp;
X
X	while(gets(buf) != NULL) {
X		/*  line should be in form
X		**
X		**  login	First Last
X		** or
X		**  login	First Last(Nickname)
X		**
X		*/
X		if((p = index(buf, '\t')) == NULL) {
X			(void) fprintf(stderr, "format error: %s\n", buf);
X			continue;
X		}
X
X		*p++ = '\0';
X		name = fullname(p);
X		dotspace(name);
X
X		if (last = rindex(name, '.')) {
X			last++;
X		} else {
X			last = NULL;
X		}
X
X		if ((nick = index(p, '(')) != NULL) {
X			nick++;
X			if ((ctmp = index(nick, ')')) == NULL) {
X				nick = NULL;
X			} else {
X				*ctmp = '\0';
X			}
X		}
X
X		nptx(buf, name);
X
X		if((last != NULL) && (nick != NULL)) {
X			i=strlen(nick) + strlen(last) + 2;
X			if((name = malloc(i)) != NULL) {
X				(void) strcpy(name, nick);
X				(void) strcat(name, ".");
X				(void) strcat(name, last);
X				dotspace(name);
X				nptx(buf, name);
X				free(name);
X			}
X		}
X	}
X	return(0);
X}
X
Xvoid
Xdotspace(s)
Xchar *s;
X{
X	register char *p, *t;
X
X	/* turn whitespace to '.' */
X	for(p = s; *p != '\0'; p++) {
X		if((*p == ' ') || (*p == '\t')) {
X			*p = '.';
X		}
X	}
X
X	/* elide leading '.'s */
X	for(p = s; *p == '.' ; p++)
X		;
X
X	/* elide mulitple '.'s and all "'"s */
X	for(t = s; *p != '\0'; p++, t++) {
X		*t = *p;
X
X		if(*t == '\'') {
X			t--;
X			continue;
X		}
X
X		if(*p == '.') {
X			while(*(++p) == '.')
X				;
X			p--;
X		}
X	}
X	*t = '\0';
X
X	/* elide trailing '.' */
X	if((t > s) && (*(--t) == '.')) *t = '\0';
X}
X
Xvoid
Xnptx(login, name)
Xchar *login, *name;
X{
X	int i,j,k,N,lim,mask;
X	int ii,ji,ki,Ni,limi,maski;
X	char nl[11][100], il[11][100];
X	char *pi, *p, *rindex();
X	char buf[100];
X	char bufi[100];
X
X	if((name == NULL) || (*name == '\0')) {
X		return;
X	}
X
X	for(i=0; i < 10; i++) {
X		if((p = rindex(name, '.')) == NULL) break;
X		(void) strcpy(nl[i], p+1);
X		*p = NULL;
X	}
X	(void) strcpy(nl[i], name);
X
X	while((strcmpic(nl[i], "Mr"  ) == 0)
X	 ||   (strcmpic(nl[i], "Dr"  ) == 0)
X	 ||   (strcmpic(nl[i], "Mrs" ) == 0)
X	 ||   (strcmpic(nl[i], "Miss") == 0)
X	 ||   (strcmpic(nl[i], "Ms"  ) == 0)) {
X		i--;
X	}
X
X	while((strcmpic(nl[0], "Jr") == 0)
X	 ||   (strcmpic(nl[0], "Sr") == 0)) {
X		for(j=0; j < i; j++) {
X			(void) strcpy(nl[j], nl[j+1]);
X		}
X		i--;
X	}
X
X	N = i;
X	lim = 1 << (N+1);
X	for(mask = 1 << N ; mask < lim ; mask++) {
X		buf[0] = '\0';
X		for(j = 1, k = N; j < lim; j <<=1, k--) {
X			if(j & mask) {
X				(void) strcat(buf, nl[k]);
X				(void) strcat(buf, ".");
X			}
X		}
X		if((p = rindex(buf, '.')) != NULL) {
X			*p = '\0';
X		}
X
X		for(ii=0; ii < 10; ii++) {
X			if((pi = rindex(buf, '.')) == NULL) break;
X			(void) strcpy(il[ii], pi+1);
X			*pi = NULL;
X		}
X		(void) strcpy(il[ii], buf);
X		Ni = ii;
X		limi = 1 << (Ni+1);
X		for(maski = 1 << Ni /* 0 */ ; maski < limi ; maski++) {
X			bufi[0] = '\0';
X			for(ji = 1, ki = Ni; ji < limi; ji <<=1, ki--) {
X				if(ji & maski) {
X					(void) strcat(bufi, il[ki]);
X				} else {
X					char init[3];
X					init[0] = il[ki][0];
X					init[1] = '\0';
X					(void) strcat(bufi, init);
X				}
X				(void) strcat(bufi, ".");
X			}
X			if((pi = rindex(bufi, '.')) != NULL) {
X				*pi = '\0';
X			}
X#ifdef DOT_REQD
X			if(index(bufi, '.') == NULL) {
X				continue;
X			}
X#endif /* DOT_REQD */
X			(void) printf("%s\t%s\n",bufi, login); /* */
X		}
X	}
X}
END_OF_FILE
if test 3534 -ne `wc -c <'mailer/nptx.c'`; then
    echo shar: \"'mailer/nptx.c'\" unpacked with wrong size!
fi
# end of 'mailer/nptx.c'
fi
if test -f 'mailer/pw.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mailer/pw.c'\"
else
echo shar: Extracting \"'mailer/pw.c'\" \(4604 characters\)
sed "s/^X//" >'mailer/pw.c' <<'END_OF_FILE'
X#ifndef lint
Xstatic char *sccsid = "@(#)pw.c	2.5 (smail) 9/15/87";
X#endif
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <pwd.h>
X#include "defs.h"
X#include <ctype.h>
X
Xchar *malloc();
Xvoid free();
X
Xtypedef struct pw_node pwlist;
X
Xstruct pw_node {
X	char *lname;			/* login name */
X	char *fname;			/* full name  */
X	int  uid;			/* user-id    */
X	char *home;			/* login name */
X	pwlist *vlink;			/* link to next item */
X};
X
Xpwlist *pwhead;		/* head of linked list */
Xpwlist *pwparse();	/* head of linked list */
X
X#define PNULL	((pwlist *) 0)
X
Xchar *
Xpwfnam(user)
Xchar *user;
X{
X	pwlist *f;
X
X	/*
X	** check for previously cached user
X	*/
X
X	for(f=pwhead; f != NULL; f=f->vlink) {
X		if(strcmp(user, f->lname) == 0) {
X			return(f->fname);
X		}
X	}
X	/*
X	** not found parse the password file
X	*/
X
X	while((f=pwparse()) != PNULL) {
X		if(strcmp(user, f->lname) == 0) {
X			return(f->fname);
X		}
X	}
X	return(NULL);
X}
X
Xchar *
Xpwuid(uid)
Xint uid;
X{
X	pwlist *f;
X
X	/*
X	** check for previously cached user
X	*/
X
X	for(f=pwhead; f != NULL; f=f->vlink) {
X		if(uid == f->uid) {
X			return(f->lname);
X		}
X	}
X	/*
X	** not found parse the password file
X	*/
X
X	while((f=pwparse()) != PNULL) {
X		if(uid == f->uid) {
X			return(f->lname);
X		}
X	}
X	return(NULL);
X}
X
X#ifndef SENDMAIL
Xchar *
Xtilde(user)
Xchar *user;
X{
X	pwlist *f;
X
X	/*
X	** check for previously cached user
X	*/
X
X	for(f=pwhead; f != NULL; f=f->vlink) {
X		if(strcmp(user, f->lname) == 0) {
X			return(f->home);
X		}
X	}
X	/*
X	** not found parse the password file
X	*/
X
X	while((f=pwparse()) != PNULL) {
X		if(strcmp(user, f->lname) == 0) {
X			return(f->home);
X		}
X	}
X	return(NULL);
X}
X#endif /* not SENDMAIL */
X
Xchar *
Xfullname(gecos)
Xchar *gecos;
X{
X	static char fname[SMLBUF];
X	register char *cend;
X
X	(void) strcpy(fname, gecos);
X	if (cend = index(fname, ','))
X		*cend = '\0';
X	if (cend = index(fname, '('))
X		*cend = '\0';
X	/*
X	** Skip USG-style 0000-Name nonsense if necessary.
X	*/
X	if (isdigit(*(cend = fname))) {
X		if ((cend = index(fname, '-')) != NULL)
X			cend++;
X		else
X			/*
X			** There was no `-' following digits.
X			*/
X			cend = fname;
X	}
X	return (cend);
X}
X
Xpwlist *
Xpwparse()
X{
X	pwlist *f;
X	char *p, *name;
X	struct passwd *pwent, *getpwent();
X	unsigned int i;
X	static int pw_eof = 0;
X
X	if((pw_eof == 1)
X	|| ((pwent = getpwent()) == (struct passwd *) NULL)) {
X		pw_eof = 1;
X		return(PNULL);
X	}
X	/*
X	** Get an entry from the password file.
X	** Parse relevant strings.
X	*/
X	f = (pwlist *) malloc(sizeof(pwlist));
X	if(f == PNULL) return(PNULL);
X
X	f->vlink = pwhead;
X	pwhead   = f;
X	f->uid   = pwent->pw_uid;
X
X	i=strlen(pwent->pw_name)+1;
X	p = malloc(i);
X	if(p == NULL) return(PNULL);
X	f->lname = strcpy(p, pwent->pw_name);
X
X	i=strlen(pwent->pw_dir)+1;
X	p = malloc(i);
X	if(p == NULL) return(PNULL);
X	f->home  = strcpy(p, pwent->pw_dir);
X
X	name = fullname(pwent->pw_gecos);
X	i=strlen(name)+1;
X	p = malloc(i);
X	if(p == NULL) return(PNULL);
X	f->fname = strcpy(p, name);
X	return(f);
X}
X
X#ifdef FULLNAME
X/*
X** Resolve a full name to a login name.
X** Not too much smarts here.
X*/
X
Xchar *
Xres_fname(user)
Xregister char *user;
X{
X	long pos, middle, hi, lo;
X	static long pathlength = 0;
X	register char *s;
X	int c;
X	static FILE *file;
X	int flag;
X	char namebuf[SMLBUF], *path;
X	extern enum edebug debug;
X	extern char *fnlist;
X
X
X
XDEBUG("res_fname: looking for '%s'\n", user);
X
X	if(pathlength == 0) {	/* open file on first use */
X		if((file=fopen(fnlist, "r")) == NULL) {
X			DEBUG( "can't access %s.\n", fnlist);
X			pathlength = -1;
X		} else {
X			(void) fseek(file, 0L, 2); 	/* find length */
X			pathlength = ftell(file);
X		}
X	}
X
X	if(pathlength == -1 ) return(NULL);
X
X	lo = 0;
X	hi = pathlength;
X	path = namebuf;
X
X	(void) strcpy( path, user );
X	(void) strcat( path, "\t" );
X
X	for( ;; ) {
X		pos = middle = ( hi+lo+1 )/2;
X		(void) fseek( file, pos, 0 );	/* find midpoint */
X		if (pos != 0)		/* to beginning of next line */
X			while( ( c=getc( file ) ) != EOF && c != '\n' );
X		for( flag = 0, s = path; flag == 0; s++ ) { /* match??? */
X			if ( *s == '\0' ) {
X				goto solved;
X			}
X			c = getc( file );
X			flag = lower( c ) - lower( *s );
X		} 
X		if (lo >= middle)		/* failure? */
X			return(NULL);
X
X		if(c != EOF && flag < 0)	/* close window */
X			lo = middle;
X		else 
X			hi = middle - 1;
X	}
X/* 
X** Now just copy the result.
X*/
Xsolved:
X	while(((c  = getc(file)) != EOF) && (c != '\t') && (c != '\n')) {
X		*path++ = c;
X	}
X
X	if(path == namebuf) {	/* NULL alias field */
X		return(NULL);
X	}
X
X	*path = '\0';
X	if((path = malloc((unsigned) strlen(namebuf)+1)) == NULL) {
X		return(NULL);	/* sorry, no memory */
X	}
X
X	(void) strcpy(path, namebuf);
X	return(path);
X
X}
X#endif	/* FULLNAME */
END_OF_FILE
if test 4604 -ne `wc -c <'mailer/pw.c'`; then
    echo shar: \"'mailer/pw.c'\" unpacked with wrong size!
fi
# end of 'mailer/pw.c'
fi
echo shar: End of archive 3 \(of 8\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 8 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0