[mod.sources] v09i007: ELM Mail System, Part07/19

sources-request@mirror.TMC.COM (03/09/87)

Submitted by: Dave Taylor <hplabs!taylor>
Mod.sources: Volume 9, Issue 7
Archive-name: elm2/Part07

#! /bin/sh
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
# If this archive is complete, you will see the message:
#		"End of archive 7 (of 19)."
# Contents:  src/aliasdb.c src/domains.c src/initialize.c
#   utils/fastmail.c utils/newmail.c utils/wnewmail.c
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo shar: Extracting \"src/aliasdb.c\" \(7752 characters\)
if test -f src/aliasdb.c ; then 
  echo shar: Will not over-write existing file \"src/aliasdb.c\"
else
sed "s/^X//" >src/aliasdb.c <<'END_OF_src/aliasdb.c'
X/**			aliasdb.c			**/
X
X/** Alias database files...
X
X    (C) Copyright 1986 Dave Taylor
X**/
X
X
X#include "headers.h"
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <errno.h>
X
Xextern int errno;
X
X#ifdef USE_DBM
X# include <dbm.h>
X#endif
X
X#define  absolute(x)		((x) > 0 ? x : -(x))
X
Xchar *shift_lower(), *find_path_to(), *strcat(), *strcpy();
Xunsigned long sleep();
X
Xint  findnode_has_been_initialized = FALSE;
X
Xfindnode(name, display_error)
Xchar *name;
Xint   display_error;
X{
X	/** break 'name' into machine!user or user@machine and then
X	    see if you can find 'machine' in the path database..
X	    If so, return name as the expanded address.  If not,
X	    return what was given to us!   If display_error, then
X	    do so...
X	**/
X
X#ifndef DONT_TOUCH_ADDRESSES
X	
X	char   old_name[SLEN];
X	char   address[SLEN];
X
X	if (strlen(name) == 0)
X	  return;
X	
X	if (! findnode_has_been_initialized) {
X	  if (! mail_only)
X	    error("initializing internal tables...");
X#ifndef USE_DBM
X	  get_connections();
X	  open_domain_file();
X#endif
X	  init_findnode();
X	  clear_error();
X          findnode_has_been_initialized = TRUE;
X	}
X
X	strcpy(old_name, name);		/* save what we were given */
X
X	if (expand_site(name, address) == -1) {
X          if (display_error && name[0] != '!') {
X	    dprint2(2,"Couldn't expand host %s in address. (%s)\n",
X	             name, "findnode");
X	    if (! check_only && warnings) {	/* be silent if just checking */
X	      if (mail_only)
X	        printf("Warning: couldn't expand %s...\n\r", name);
X	      else {
X	        error1("Warning: couldn't expand %s...", name);
X	        sleep(1);
X	      }
X	    }
X	  }
X	  strcpy(name, old_name);	/* and restore... */
X	}
X	else
X	  strcpy(name, address);
X#endif
X	return;
X}
X
Xint
Xexpand_site(cryptic, expanded)
Xchar *cryptic, *expanded;
X{
X
X	/** Given an address of the form 'xyz@site' or 'site!xyz'
X	    return an address of the form <expanded address for site>
X            with 'xyz' embedded according to the path database entry.
X	    Note that 'xyz' can be eiher a simple address (as in "joe")
X	    or a complex address (as in "joe%xerox.parc@Xerox.ARPA")!
X	    0 = found, -1 return means unknown site code 
X	
X	    Modified to strip out parenthetical comments...
X	**/
X
X#ifdef ACSNET
X
X	strcpy(expanded, cryptic);	/* fast and simple */
X	return(0);
X
X#else
X# ifdef USE_DBM
X	datum  key, contents;
X# endif
X
X	char   name[VERY_LONG_STRING], sitename[VERY_LONG_STRING], 
X               temp[VERY_LONG_STRING], old_name[VERY_LONG_STRING],
X	       comment[LONG_STRING];
X	char   *expand_domain(), *addr;
X	register int i = 0, j = 0, domain_name;
X
X	strcpy(old_name, cryptic);	/* remember what we were given */
X
X	/** break down **/
X
X	/** first, rip out the comment, if any **/
X
X	if ((i = chloc(cryptic, '(')) > -1) {
X	  comment[j++] = ' ';			/* leading space */
X	  for ( ;cryptic[i] != ')'; i++)
X  	    comment[j++] = cryptic[i];
X	  comment[j++] = ')';
X	  comment[j] = '\0';
X	  /* and remove this from cryptic string too... */
X	  if (cryptic[(j = chloc(cryptic,'('))-1] == ' ')
X	    cryptic[j-1] = '\0';
X	  else
X	    cryptic[j] = '\0';
X	}
X	else
X	  comment[0] = '\0';
X
X	i = j = 0;	/* reset */
X
X	while (cryptic[i] != AT_SIGN && cryptic[i] != BANG && 
X	       cryptic[i] != '\0' && cryptic[i] != '(')
X	  sitename[j++] = cryptic[i++];
X
X	sitename[j++] = '\0';
X
X	j = 0;
X	
X	if (cryptic[i] == '\0') return(-1);	/* nothing to expand! */
X
X	domain_name = (cryptic[i] == AT_SIGN);
X
X	i++;
X
X	while (cryptic[i] != '\0' && cryptic[i] != '(' && 
X               ! whitespace(cryptic[i]))
X	  name[j++] = cryptic[i++];
X
X	name[j] = '\0';
X
X	if (domain_name) {
X	  strcpy(temp, name);
X	  strcpy(name, sitename);
X	  strcpy(sitename, temp);
X	}
X
X	dprint3(5,"\nBroke address into '%s' @ '%s' '%s'\n\n",
X		name, sitename, comment);
X
X#ifdef USE_DBM
X
X	if (size_of_pathfd == 0)
X	  return(-1);
X
X	key.dptr  = sitename;
X	key.dsize = strlen(sitename) + 1;
X
X	contents = fetch(key);
X
X	if (contents.dptr == 0) 
X	  return(-1);			/* can't find it! */
X
X	sprintf(expanded, contents.dptr, name);
X	strcat(expanded, " ");			/* add a single space... */
X	strcat(expanded, comment);		/*    ...and add comment */
X	return(0);
X#endif
X
X#ifndef LOOK_CLOSE_AFTER_SEARCH
X
X	if (talk_to(sitename)) {
X	  strcpy(expanded, old_name);	/* restore! */
X	  return(0);
X	}
X#endif
X
X	if ((addr = find_path_to(sitename, TRUE)) == NULL) {
X
X#ifdef LOOK_CLOSE_AFTER_SEARCH
X
X	    if (talk_to(sitename)) {
X	      strcpy(expanded, old_name);	/* restore! */
X	      return(0);
X	    }
X	    else
X#endif
X	    if ((addr = expand_domain(cryptic)) != NULL) {
X	       strcpy(expanded, addr);	/* into THIS buffer */
X	       strcat(expanded, comment);	/* patch in comment */
X	       return(0);
X	    }
X	    else  if (size_of_pathfd == 0) {	/* no path database! */
X	      strcpy(expanded, old_name);	/* restore! */
X	      return(0);
X	    }
X	    else {			     /* We just can't get there! */
X	      strcpy(expanded, old_name);	/* restore! */
X	      return(-1);
X	    }
X	}
X	else {			/* search succeeded */
X	   sprintf(expanded, addr, name);
X	   strcat(expanded, comment);		/* add comment */
X	   return(0);
X	}
X#endif
X}
X
Xint
Xbinary_search(name, address)
Xchar *name, *address;
X{
X	/* binary search file for name.  Return 0 if found, -1 if not */
X
X	char machine[40];
X	register long first = 0, last, middle;
X	register int  compare;
X
X	address[0] = '\0';
X
X	last = size_of_pathfd;
X
X	do {
X
X	  middle = (long) ((first+last) / 2);
X
X	  get_entry(machine, address, pathfd, middle);
X
X	  compare = strcmp(name, machine);
X
X	  if (compare < 0) 
X	    last = middle - 1;
X	  else if (compare == 0) 
X	    return(0);
X	  else  /* greater */
X	    first = middle + 1; 
X	} while (absolute(last) - absolute(first) > FIND_DELTA);
X
X	return(-1);
X}
X
Xget_entry(machine, address, fileid, offset)
Xchar *machine, *address;
XFILE *fileid;
Xlong offset;
X{
X	/** get entry...return machine and address immediately
X	    following given offset in fileid.  **/
X
X	fseek(fileid, offset, 0);
X
X	/* read until we hit an end-of-line */
X
X	while (getc(fileid) != '\n')
X	   ;
X
X	fscanf(fileid, "%s\t%s", machine, address);
X}
X
Xinit_findnode()
X{
X	/** Initialize the FILE and 'size_of_file' values for the 
X	    findnode procedure **/
X
X	struct stat buffer;
X
X	if (stat(pathfile, &buffer) == -1) {
X	  dprint2(1, "Warning: No pathalias file [filename %s] found! (%s)\n", 
X		  pathfile, "init_findnode");
X	  size_of_pathfd = 0;
X	  return;
X	}
X
X	size_of_pathfd = (long) buffer.st_size;
X
X#ifdef USE_DBM
X	
X	if (dbminit(pathfile) != 0) {
X	  dprint1(1, "Warning: couldn't initialize DBM database %s\n", 
X		     pathfile);
X	  dprint2(1, "** %s - %s **\n\n", error_name(errno),
X		     error_description(errno));
X	  size_of_pathfd = 0;	/* error flag, in this case */
X	  return;
X	}
X 	
X	return;
X#else
X
X	if ((pathfd = fopen(pathfile,"r")) == NULL) {
X	  dprint2(1, "Warning: Can't read pathalias file [filename %s] (%s)\n", 
X		   pathfile, "init_findnode");
X	  size_of_pathfd = 0;
X	}
X	else
X	  dprint2(2, "\nOpened file '%s' as path alias database.  (%s)\n\n", 
X		  pathfile, "init_findnode");
X#endif
X}
X
Xchar *find_path_to(machine, printf_format)
Xchar *machine;
Xint   printf_format;
X{
X	/** Returns either the path to the specified machine or NULL if
X	    not found.  If "printf_format" is TRUE, then it leaves the
X	    '%s' intact, otherwise it assumes that the address is a uucp
X	    address for the domain expansion program and removes the
X	    last three characters of the expanded name ("!%s") since
X	    they're redundant with the expansion!
X        **/
X
X	static char buffer[LONG_SLEN];	/* space for path */
X
X	if (size_of_pathfd > 0)
X	  if (binary_search(machine, buffer) != -1) {   	/* found it! */
X	    if (! printf_format && strlen(buffer) > 3)
X	      buffer[strlen(buffer)-3] = '\0';
X	    return( (char *) buffer);
X	  }
X
X	return(NULL);			            /* failed if it's here! */
X}
END_OF_src/aliasdb.c
if test 7752 -ne `wc -c <src/aliasdb.c`; then
    echo shar: \"src/aliasdb.c\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: Extracting \"src/domains.c\" \(7773 characters\)
if test -f src/domains.c ; then 
  echo shar: Will not over-write existing file \"src/domains.c\"
else
sed "s/^X//" >src/domains.c <<'END_OF_src/domains.c'
X/**			domains.c			**/
X
X/** This file contains all the code dealing with the expansion of 
X    domain based addresses in Elm.  It uses the file "domains" as
X    defined in the sysdefs.h file.
X
X    (C) Copyright 1986 Dave Taylor
X
X    From a file format and idea in "uumail" - designed by Stan Barber.
X**/
X
X#include <stdio.h>
X#include <ctype.h>
X
X#include "headers.h"
X
X#ifdef BSD
X# undef toupper
X# undef tolower
X#endif
X
X/** define the various characters that we can encounter after a "%" sign
X    in the template file...
X**/
X
X#define USERNAME	'U'	/* %U = the name of the remote user */
X#define HOSTNAME	'N'	/* %N = the remote machine name     */
X#define FULLNAME	'D'	/* %D = %N + domain info given      */
X#define NPATH		'R'	/* %R = path to %N from pathalias   */
X#define PPATH		'P'	/* %P = path to 'P' from pathalias  */
X#define OBSOLETE	'S'	/* %S = (used to be suffix string)  */
X
X/** and finally some characters that are allowed in user/machine names **/
X
X#define okay_others(c)	(c == '-' || c == '^' || c == '$' || c == '_')
X
X/** and some allowed ONLY in the username field **/
X
X#define special_chars(c)	(c == '%' || c == ':')
X
Xchar *find_path_to(), *expand_domain(), *match_and_expand_domain();
Xchar *strcpy(), *strcat(), *strtok();
Xunsigned long sleep();
Xvoid rewind();
X	      
Xopen_domain_file()
X{
X	if ((domainfd = fopen(domains, "r")) == NULL) {
X	  dprint1(1, "Can't open file %s as domains file (open_domain_file)\n", 
X		  domains);
X	}
X	else {
X	  dprint1(2,
X            "\nOpened '%s' as the domain database. (open_domain_file)\n\n", 
X		  domains);
X	}
X	
X	/* if it fails it'll instantiate domainfd to NULL which is
X	   exactly what we want to have happen!! */
X}
X
Xchar *expand_domain(buffer)
Xchar *buffer;
X{
X	/** Expand the address 'buffer' based on the domain information, 
X	    if any.  Returns NULL if it can't expand it for any reason.
X	**/
X
X	char name[2*NLEN], address[2*NLEN], domain[2*NLEN];
X	char *match_and_expand_domain();
X
X	if (domainfd == NULL) return(NULL);	/* no file present! */
X
X	if (explode(buffer, name, address, domain)) 
X	  return( match_and_expand_domain(domain, name, address) );
X	else {	/* invalid format - not "user@host.domain" */
X	  dprint1(3, 
X		 "Invalid format for domain expansion: %s (expand_domain)\n", 
X		   buffer);
X	  return(NULL);
X	}
X}	
X
Xint
Xexplode(buffer, name, address, domain)
Xchar *buffer, *name, *address, *domain;
X{
X	/** Break buffer, if in format name@machine.domain, into the
X	    component parts, otherwise return ZERO and don't worry
X	    about the values of the parameters!
X	**/
X	
X	register int i, j = 0;
X
X	/** First get the name... **/
X
X	for (i=0; buffer[i] != '@'; i++) {
X	  if (! isalnum(buffer[i]) && ! okay_others(buffer[i]) && ! 
X		special_chars(buffer[i]))
X	    return(0);			/* invalid character in string! */
X	  name[i] = buffer[i];
X	}
X
X	name[i++] = '\0';
X
X	/** now let's get the machinename **/
X
X	while (buffer[i] != '.') {
X	  if (! isalnum(buffer[i]) && ! okay_others(buffer[i]))
X	     return(0);			/* invalid character in string! */
X	  address[j++] = buffer[i++];
X	}
X	address[j] = '\0';
X
X	j = 0;
X
X	/** finally let's get the domain information (there better be some!) **/
X
X	while (buffer[i] != '\0') {
X	  if (! isalnum(buffer[i]) && ! okay_others(buffer[i]) && 
X	        buffer[i] != '.')
X	    return(0);		      /* an you fail again, bozo! */
X	  domain[j++] = toupper(buffer[i]);
X	  i++;
X	}
X
X	domain[j] = '\0';
X	
X	return(j);		/* if j == 0 there's no domain info! */
X}
X        
Xchar *match_and_expand_domain(domain, name, machine)
Xchar *domain, *name, *machine;
X{
X	/** Given the domain, try to find it in the domain file and
X   	    if found expand the entry and return the result as a 
X	    character string...
X	**/
X
X	static char address[SLEN];
X	char   buffer[SLEN], domainbuff[NLEN];
X	char   field1[2*NLEN], field2[2*NLEN], field3[2*NLEN];
X	char   *path, *template, *expanded, *mydomain, *strtok();
X	int    matched = 0, in_percent = 0;
X	register int i, j = 0;
X
X	address[j] = '\0';
X
X	domainbuff[0] = '\0';
X	mydomain = (char *) domainbuff;		    /* set up buffer etc */
X
X	do { 
X	  rewind(domainfd);		           /* back to ground zero! */
X
X	  if (strlen(mydomain) > 0) {		   /* already in a domain! */
X	    mydomain++;		 		      /* skip leading '.' */
X	    while (*mydomain != '.' && *mydomain != ',') 
X	      mydomain++;	 		      /* next character   */
X	    if (*mydomain == ',')
X	      return (NULL);  			  /* didn't find domain!  */
X	  }
X	  else
X	    sprintf(mydomain, "%s,", domain);		/* match ENTIRELY! */
X
X	/* whip through file looking for the entry, please... */
X
X	while (fgets(buffer, SLEN, domainfd) != NULL) {
X	  if (buffer[0] == '#')				  /* skip comments */
X	    continue;
X	  if (strncmp(buffer, mydomain, strlen(mydomain)) == 0) { /* match? */
X	     matched++;	/* Gotcha!  Remember this momentous event! */
X	     break;
X	  }
X	}
X
X	if (! matched) 
X	   continue;		/* Nothing.  Not a sausage!  Step through! */
X
X	/** We've matched the domain! **/
X
X	no_ret(buffer);
X
X	(void) strtok(buffer, ",");	/* skip the domain info */
X
X	strcpy(field1, strtok(NULL, ","));	/* fun 		*/
X	strcpy(field2, strtok(NULL, ","));	/*    stuff     */
X	strcpy(field3, strtok(NULL, ","));	/*       eh?    */
X	
X	path = (char *) NULL;
X
X	/* now we merely need to figure out what permutation this is! */
X
X	if (field3 == NULL || strlen(field3) == 0)
X	  if (field2 == NULL || strlen(field2) == 0)
X	    template = (char *) field1;
X	  else {
X	    path     = (char *) field1;
X	    template = (char *) field2;
X	  }
X	else {
X	  dprint1(2,"Domain info for %s from file broken into THREE fields!!\n",
X		   domain);
X	  dprint3(2, "-> %s\n-> %s\n-> %s\n", field1, field2, field3);
X	  error1("Warning: domain %s uses a defunct field!!", domain);
X	  sleep(2);
X	  path     = (char *) field1;
X	  template = (char *) field3;
X	}
X
X	if (strlen(path) > 0 && path[0] == '>') 
X	   path++;	/* skip the '>' character, okay? */
X
X	j = 0;		 	/* address is zero, right now, right?? */
X	address[j] = '\0';	      /* make sure string is too! */
X
X	for (i=0; i < strlen(template); i++) {
X	  if (template[i] == '%') {
X	    if (! in_percent)			   /* just hit a NEW percent! */
X	      in_percent = 1;
X	    else {		  /* just another percent sign on the wall... */
X	      address[j++] = '%';
X	      address[j] = '\0';		     /* ALWAYS NULL terminate */
X	      in_percent = 0;
X	    }
X	  }
X	  else if (in_percent) {	       /* Hey! a real command string */
X	    in_percent = 0;
X	    switch (template[i]) {
X	      case USERNAME: strcat(address, name);		break;
X	      case HOSTNAME: strcat(address, machine);		break;
X	      case FULLNAME: strcat(address, machine);
X			     strcat(address, domain);		break;
X	      case NPATH   : 
X
X		 if ((expanded = find_path_to(machine, FALSE)) == NULL) {
X		    dprint2(3,"\nCouldn't expand system path '%s' (%s)\n\n",
X			    machine, "domains");
X	            error1("Couldn't find a path to %s!", machine);
X	            sleep(2);
X	            return(NULL);	/* failed!! */
X	         }
X	         strcat(address, expanded);	/* isn't this fun??? */
X
X	         break;
X
X	      case PPATH   : 
X
X		 if ((expanded = find_path_to(path, FALSE)) == NULL) {
X		    dprint2(3,"\nCouldn't expand system path '%s' (%s)\n\n",
X			    path, "domains");
X	            error1("I Couldn't find a path to %s!", path);
X	            sleep(2);
X	            return(NULL);	/* failed!! */
X	         }
X	         strcat(address, expanded);	/* isn't this fun??? */
X
X	         break;
X
X	      case OBSOLETE:	/* fall through.. */
X	      default      : dprint2(1,
X	     "\nError: Bad sequence in template file for domain '%s': %%%c\n\n",
X			domain, template[i]);
X	    }
X	    j = strlen(address);
X	  }
X	  else {
X	    address[j++] = template[i];
X	    address[j] = '\0';			/* null terminate */
X	  }
X	}	
X
X	address[j] = '\0';
X
X	} while (strlen(address) < 1);
X
X	return( (char *) address);
X}
END_OF_src/domains.c
if test 7773 -ne `wc -c <src/domains.c`; then
    echo shar: \"src/domains.c\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: Extracting \"src/initialize.c\" \(8292 characters\)
if test -f src/initialize.c ; then 
  echo shar: Will not over-write existing file \"src/initialize.c\"
else
sed "s/^X//" >src/initialize.c <<'END_OF_src/initialize.c'
X/**		initialize.c		**/
X
X/***** Initialize - read in all the defaults etc etc 
X       (C) Copyright 1985 Dave Taylor
X*****/
X
X#include "headers.h"
X
X#ifdef BSD
X#  include <sgtty.h>
X#else
X#  include <termio.h>
X#endif
X
X#include <pwd.h>
X
X#ifdef BSD
X#  include <sys/time.h>
X#else
X#  include <time.h>
X#endif
X
X#include <signal.h>
X#include <ctype.h>
X#include <errno.h>
X
X#ifdef BSD
X#undef toupper
X#undef tolower
X#endif
X
Xextern int errno;		/* system error number on failure */
X
Xchar *error_name(), *error_description();
X
Xchar *expand_logname(), *getenv(), *getlogin(), *strcpy(), *strcat();
Xunsigned short getgid(), getuid(); 
Xvoid exit();
X
Xstruct   header_rec *malloc();
X
Xinitialize(initscreen_too)
Xint initscreen_too;
X{
X	/** initialize the whole ball of wax.   If "initscreen_too" then
X	    call init_screen where appropriate..
X	**/
X	struct passwd *pass, *getpwnam();
X
X	register int i, j; 
X	int      quit_signal(), term_signal(), ill_signal(),
X		 fpe_signal(),  bus_signal(),  segv_signal(),
X	         alarm_signal(), pipe_signal();
X	char     buffer[SLEN], *cp;
X	
X
X	userid  = getuid();
X	groupid = getgid();	
X
X	strcpy(home,((cp = getenv("HOME")) == NULL)? "" : cp);
X	strcpy(shell,((cp = getenv("SHELL")) == NULL)? "" : cp);
X	strcpy(pager,((cp = getenv("PAGER")) == NULL)? default_pager : cp);
X
X	if (debug) {		/* setup for dprintf statements! */
X	  char newfname[SLEN], filename[SLEN];
X
X	  sprintf(filename, "%s/%s", home, DEBUG);
X	  if (access(filename, ACCESS_EXISTS) == 0) {	/* already one! */
X	    sprintf(newfname,"%s/%s", home, OLDEBUG);
X	    (void) link(filename, newfname);
X	  }
X
X	  /* Note what we just did up there: we always save the old
X	     version of the debug file as OLDEBUG, so users can mail
X	     copies of bug files without trashing 'em by starting up
X	     the mailer.  Dumb, subtle, but easy enough to do!
X 	  */
X
X	  if ((debugfile = fopen(filename, "w")) == NULL) {
X	    debug = 0;	/* otherwise 'leave' will try to log! */
X	    leave(fprintf(stderr,"Could not open file %s for debug output!\n",
X		  filename));
X	  }
X	  chown(filename, userid, groupid); /* file owned by user */
X
X	  fprintf(debugfile, "Debug output of the ELM program.  Version %s\n\n",
X		  VERSION);
X	}
X
X	if (initscreen_too)	/* don't set up unless we need to! */
X	  InitScreen();
X
X	if (debug < 2) {	/* otherwise let the system trap 'em! */
X	  signal(SIGINT,  SIG_IGN);
X	  signal(SIGQUIT, quit_signal);		/* Quit signal 	            */
X	  signal(SIGTERM, term_signal); 	/* Terminate signal         */
X	  signal(SIGILL,  ill_signal);		/* Illegal instruction      */
X	  signal(SIGFPE,  fpe_signal);		/* Floating point exception */
X	  signal(SIGBUS,  bus_signal);		/* Bus error  		    */
X	  signal(SIGSEGV, segv_signal);		/* Segmentation Violation   */
X	}
X	
X	signal(SIGALRM, alarm_signal);		/* Process Timer Alarm	    */
X	signal(SIGPIPE, pipe_signal);		/* Illegal Pipe Operation   */
X
X	get_term_chars();
X	
X	gethostname(hostname, sizeof(hostname));
X
X#ifdef BSD
X	if ((cp = getenv("USER")) == NULL)
X#else
X	if ((cp = getenv("LOGNAME")) == NULL)
X#endif
X	  if ((cp = getlogin()) == NULL)
X	    cuserid(username);
X	  else
X	    strcpy(username, cp);
X	else
X	  strcpy(username, cp);
X
X	/* now let's get the full username.. */
X
X	if ((pass = getpwnam(username)) == NULL) {
X	  error("Couldn't read password entry??");
X	  strcpy(full_username, username);
X	}
X	else {
X	  /* fix for this section from Don Joslyn of Nova University */
X	  for (i=0,j=0; pass->pw_gecos[i] != '\0' && pass->pw_gecos[i] != ',';
X	       i++)
X	      if (pass->pw_gecos[i] == '&') {
X	        full_username[j] = '\0';
X	        strcat(full_username, expand_logname());
X	        j = strlen(full_username);
X	      }
X	      else
X	        full_username[j++] = pass->pw_gecos[i];
X	  full_username[j] = '\0'; 
X	}
X
X	if ((cp = getenv("EDITOR")) == NULL)
X	  strcpy(editor,default_editor);
X	else
X	  strcpy(editor, cp);
X	strcpy(alternative_editor, editor);	/* this one can't be changed! */
X
X	if (! mail_only) {
X	  mailbox[0] = '\0';
X	  strcpy(prefixchars, "> "); 	/* default message prefix */
X	  sprintf(calendar_file, "%s/%s", home, dflt_calendar_file);
X	}
X
X	local_signature[0] = remote_signature[0] = '\0';	/* NULL! */
X
X	read_rc_file();		/* reading the .elmrc next... */
X
X	/** now try to expand the specified filename... **/
X
X	if (strlen(infile) > 0) {
X	  (void) expand_filename(infile);
X	  if ((errno = can_access(infile, READ_ACCESS))) {
X	    dprint2(1,"Error: given file %s as mailbox - unreadable (%s)!\n", 
X		     infile, error_name(errno));
X	    fprintf(stderr,"Can't open mailbox '%s' for reading!\n", infile);
X	    exit(1);
X	  }
X	}
X
X	/** check to see if the user has defined a LINES or COLUMNS
X	    value different to that in the termcap entry (for
X	    windowing systems, of course!) **/
X
X	ScreenSize(&LINES, &COLUMNS);
X
X	if ((cp = getenv("LINES")) != NULL && isdigit(*cp)) {
X	  sscanf(cp, "%d", &LINES);
X	  LINES -= 1;	/* kludge for HP Window system? ... */
X	}
X
X	if ((cp = getenv("COLUMNS")) != NULL && isdigit(*cp))
X	  sscanf(cp, "%d", &COLUMNS);
X
X	/** fix the shell if needed **/
X
X	if (shell[0] != '/') {
X	   sprintf(buffer, "/bin/%s", shell);
X	   strcpy(shell, buffer);
X	}
X
X	if (! mail_only) {
X	  mailbox_defined = (mailbox[0] != '\0'); 
X
X	  /* get the cursor control keys... */
X
X	  cursor_control = FALSE;
X
X	  if ((cp = return_value_of("ku")) != NULL)
X	   if (strlen(cp) == 2) {
X	    strcpy(up, cp);
X	    if ((cp = return_value_of("kd")) == NULL)
X	      cursor_control = FALSE;
X	    else if (strlen(cp) != 2)
X	      cursor_control = FALSE;
X	    else {
X	      strcpy(down, cp);
X	      cursor_control = TRUE;
X	      transmit_functions(ON);
X	    }
X	  }
X
X	  strcpy(start_highlight, "->");
X	  end_highlight[0] = '\0';
X
X	  if (!arrow_cursor) {	/* try to use inverse bar instead */
X	    if ((cp = return_value_of("so")) != NULL) {
X	      strcpy(start_highlight, cp);
X	      if ((cp = return_value_of("se")) == NULL)
X	        strcpy(start_highlight, "->");
X	      else {
X	        strcpy(end_highlight, cp);
X	        has_highlighting = TRUE;
X	      }
X	    }
X	  }
X	}
X
X	/** allocate the first KLICK headers... **/
X
X	if ((header_table = malloc(KLICK*sizeof(struct header_rec))) == NULL) {
X	   fprintf(stderr,"\n\r\n\rCouldn't allocate initial headers!\n\r\n");
X	   leave();
X	}
X	max_headers = KLICK;		/* we have those preallocated */
X
X	/** now cruise along... **/
X
X	if (! mail_only) {
X	  if (mini_menu)
X	    headers_per_page = LINES - 13;
X	  else
X	    headers_per_page = LINES -  8;	/* 5 more headers! */
X
X	  newmbox(1,FALSE, TRUE);	/* read in the mailbox! */
X	}
X
X	dprint0(2,"\n-- end of initialization phase --\n");
X
X	dprint3(2,"\thostname = %s\n\tusername = %s\n\tfull_username = \"%s\"\n",
X	         hostname, username, full_username);
X
X	dprint3(2,"\thome = %s\n\teditor = %s\n\tmailbox = %s\n",
X		 home, editor, mailbox);
X
X	dprint3(2,"\tinfile = %s\n\tfolder-dir = %s\n\tprintout = \"%s\"\n",
X		 infile, folders, printout);
X	
X	dprint3(2,"\tsavefile = %s\n\tprefix = \"%s\"\n\tshell = %s\n",
X		savefile, prefixchars, shell);
X	
X	if (signature)
X	  dprint2(2,"\tlocal-signature = %s\n\tremote-signature = %s\n",
X	  	  local_signature, remote_signature);
X
X	dprint0(1,"-- beginning execution phase --\n\n");
X}
X
Xget_term_chars()
X{
X	/** This routine sucks out the special terminal characters
X	    ERASE and KILL for use in the input routine.  The meaning 
X            of the characters are (dare I say it?) fairly obvious... **/
X
X#ifdef BSD
X	struct sgttyb term_buffer;
X
X# define TCGETA	TIOCGETP
X
X#else 
X	struct termio term_buffer;
X#endif
X
X	if (ioctl(STANDARD_INPUT, TCGETA, &term_buffer) == -1) {
X	  dprint1(1,"Error: %s encountered on ioctl call (get_term_chars)\n", 
X		   error_name(errno));
X	  /* set to defaults for terminal driver */
X	  backspace = BACKSPACE;
X	  kill_line = ctrl('U');
X	}
X	else {
X#ifdef BSD
X	  backspace = term_buffer.sg_erase;
X	  kill_line = term_buffer.sg_kill;
X#else
X	  backspace = term_buffer.c_cc[VERASE];
X	  kill_line = term_buffer.c_cc[VKILL];
X#endif
X	}
X}
X
Xchar *expand_logname()
X{
X	/** Return logname in a nice format (for expanding "&" in the
X	    /etc/passwd file) **/
X
X	static char buffer[SLEN];
X	register int i;
X
X	if (strlen(username) == 0)
X	  buffer[0] = '\0';
X	else {
X	  buffer[0] = toupper(username[0]);
X
X	  for (i=1; username[i] != '\0'; i++)
X	    buffer[i] = tolower(username[i]);
X
X	  buffer[i] = '\0';
X	}
X
X	return( (char *) buffer);	
X}
END_OF_src/initialize.c
if test 8292 -ne `wc -c <src/initialize.c`; then
    echo shar: \"src/initialize.c\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: Extracting \"utils/fastmail.c\" \(8167 characters\)
if test -f utils/fastmail.c ; then 
  echo shar: Will not over-write existing file \"utils/fastmail.c\"
else
sed "s/^X//" >utils/fastmail.c <<'END_OF_utils/fastmail.c'
X/**			fastmail.c			**/
X
X/** This program is specifically written for group mailing lists and
X    such batch type mail processing.  It does NOT use aliases at all,
X    it does NOT read the /etc/password file to find the From: name
X    of the user and does NOT expand any addresses.  It is meant 
X    purely as a front-end for either /bin/mail or /usr/lib/sendmail
X    (according to what is available on the current system).
X
X         **** This program should be used with CAUTION *****
X
X    (C) Copyright 1985 Dave Taylor
X**/
X
X/** The calling sequence for this program is:
X
X	fastmail {args}  filename full-email-address 
X
X   where args could be any (or all) of;
X
X	   -b bcc-list		(Blind carbon copies to)
X	   -c cc-list		(carbon copies to)
X	   -d			(debug on)
X	   -f from 		(from name)
X	   -r reply-to-address 	(Reply-To:)
X	   -s subject 		(subject of message)
X**/
X
X#include <stdio.h>
X
X#ifdef BSD
X# ifdef BSD4.1
X#   include <time.h>
X#   include <sys/types.h>
X#   include <sys/timeb.h>
X# else
X#   include <sys/time.h>
X# endif
X#else
X#  include <time.h>
X#endif
X
X#include "defs.h"
X
Xstatic char ident[] = { WHAT_STRING };
X
X#define  binrmail	"/bin/rmail"
X#define  temphome	"/tmp/fastmail."
X
X#define DONE		0
X#define ERROR		-1
X
Xchar *optional_arg;			/* optional argument as we go */
Xint   opt_index;			/* argnum + 1 when we leave   */
X
Xchar *arpa_dayname[] = { "Sun", "Mon", "Tue", "Wed", "Thu",
X		  "Fri", "Sat", "" };
X
Xchar *arpa_monname[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
X		  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ""};
X
Xchar *get_arpa_date();
X
X#ifdef BSD
X  char *timezone();
X#else
X  extern char *tzname[];
X#endif
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X
X	FILE *tempfile;
X	char hostname[NLEN], username[NLEN], from_string[SLEN], subject[SLEN];
X	char filename[SLEN], tempfilename[SLEN], command_buffer[256];
X	char replyto[SLEN], cc_list[SLEN], bcc_list[SLEN], to_list[SLEN];
X	int  c, sendmail_available, debug = 0;
X
X	replyto[0] = '\0';
X	cc_list[0] = '\0';
X	bcc_list[0] = '\0';
X
X	while ((c = get_options(argc, argv, "b:c:df:r:s:")) > 0) {
X	  switch (c) {
X	    case 'b' : strcpy(bcc_list, optional_arg);		break;
X	    case 'c' : strcpy(cc_list, optional_arg);		break;
X	    case 'd' : debug++;					break;	
X	    case 'f' : strcpy(from_string, optional_arg);	break;
X	    case 'r' : strcpy(replyto, optional_arg);		break;
X	    case 's' : strcpy(subject, optional_arg);		break;
X 	  }
X	}	
X
X	if (c == ERROR) {
X	  fprintf(stderr,"Usage: fastmail {args} filename address(es)\n");
X	  fprintf(stderr, "   where {args} can be;\n");
X	  fprintf(stderr,"\t-b bcc-list\n\t-c cc-list\n\t-d\n\t-f from-name\n");
X	  fprintf(stderr, "\t-r reply-to\n\t-s subject\n\n");
X	  exit(1);
X	}
X
X	if (opt_index > argc) {
X	  fprintf(stderr,"Usage: fastmail {args} filename address(es)\n");
X	  fprintf(stderr, "   where {args} can be;\n");
X	  fprintf(stderr,"\t-b bcc-list\n\t-c cc-list\n\t-d\n\t-f from-name\n");
X	  fprintf(stderr, "\t-r reply-to\n\t-s subject\n\n");
X	  exit(1);
X	}
X
X	strcpy(filename, argv[opt_index++]);
X
X	if (opt_index > argc) {
X	  fprintf(stderr,"Usage: fastmail {args} filename address(es)\n");
X	  fprintf(stderr, "   where {args} can be;\n");
X	  fprintf(stderr,"\t-b bcc-list\n\t-c cc-list\n\t-d\n\t-f from-name\n");
X	  fprintf(stderr, "\t-r reply-to\n\t-s subject\n\n");
X	  exit(1);
X	}
X
X	gethostname(hostname, sizeof(hostname));
X	strcpy(username, getlogin());
X	if (strlen(username) == 0)
X	  cuserid(username);
X
X	if (access(filename, READ_ACCESS) == -1)
X	  exit(fprintf(stderr, "Error: can't find file %s!\n", filename));
X
X	sprintf(tempfilename, "%s%d", temphome, getpid());
X
X	if ((tempfile = fopen(tempfilename, "w")) == NULL)
X	  exit(fprintf(stderr, "Couldn't open temp file %s\n", tempfilename));
X
X	if (strlen(from_string) > 0)
X	  fprintf(tempfile, "From: %s!%s (%s)\n", 
X		  hostname, username, from_string);
X	else
X	  fprintf(tempfile, "From: %s!%s\n", hostname, username);
X
X	fprintf(tempfile, "Date: %s\n", get_arpa_date());
X
X	if (strlen(subject) > 0)
X	  fprintf(tempfile, "Subject: %s\n", subject);
X
X	if (strlen(replyto) > 0)
X	  fprintf(tempfile, "Reply-To: %s\n", replyto);
X
X	while (opt_index < argc) 
X          sprintf(to_list, "%s%s%s", to_list, (strlen(to_list) > 0? ", ":""), 
X		  argv[opt_index++]);
X	
X	fprintf(tempfile, "To: %s\n", to_list);
X
X	if (strlen(cc_list) > 0)
X	  fprintf(tempfile, "Cc: %s\n", cc_list);
X
X	if (strlen(bcc_list) > 0)
X	  fprintf(tempfile, "Bcc: %s\n", bcc_list);	/* trust xport */
X
X	fprintf(tempfile, "X-Mailer: fastmail [version %s]\n", VERSION);
X	fprintf(tempfile, "\n");
X
X	fclose(tempfile);
X
X	/** now we'll cat both files to /bin/rmail or sendmail... **/
X
X	sendmail_available = (access(sendmail, EXECUTE_ACCESS) != -1);
X
X	printf("Mailing to %s%s%s%s%s [via %s]\n", to_list,
X		(strlen(cc_list) > 0 ? " ":""), cc_list,
X		(strlen(bcc_list) > 0 ? " ":""), bcc_list,
X		sendmail_available? "sendmail" : "rmail");
X
X	sprintf(command_buffer, "cat %s %s | %s '%s %s %s'", 
X		tempfilename, filename, 
X	        sendmail_available? sendmail : mailer,
X		to_list, cc_list, bcc_list);
X
X	if (debug)
X	  printf("%s\n", command_buffer);
X
X	system(command_buffer);
X
X	unlink(tempfilename);
X}
X
X
Xchar *get_arpa_date()
X{
X	/** returns an ARPA standard date.  The format for the date
X	    according to DARPA document RFC-822 is exemplified by;
X
X	       	      Mon, 12 Aug 85 6:29:08 MST
X
X	**/
X
X	static char buffer[SLEN];	/* static character buffer       */
X	struct tm *the_time,		/* Time structure, see CTIME(3C) */
X		  *localtime();
X	long	   junk;		/* time in seconds....		 */
X#ifdef BSD
X#  ifdef BSD4.1
X	struct timeb loc_time;	/* of course this is different! */
X#  else
X	struct  timeval  time_val;		
X	struct  timezone time_zone;
X#  endif
X#endif
X
X#ifdef BSD
X#  ifdef BSD4.1
X	junk = (long) time((long *) 0);
X	ftime(&loc_time);
X#  else
X	gettimeofday(&time_val, &time_zone);
X	junk = time_val.tv_sec;
X#  endif
X#else
X	junk = time(0);	/* this must be here for it to work! */
X#endif
X	the_time = localtime(&junk);
X
X	sprintf(buffer, "%s, %d %s %d %d:%02d:%02d %s",
X	  arpa_dayname[the_time->tm_wday],
X	  the_time->tm_mday % 32,
X	  arpa_monname[the_time->tm_mon],
X	  the_time->tm_year % 100,
X	  the_time->tm_hour % 24,
X	  the_time->tm_min  % 61,
X	  the_time->tm_sec  % 61,
X#ifdef BSD
X#  ifdef BSD4.1
X	  timezone(loc_time.time_zone, the_time->tz_isdst));
X#  else
X	  timezone(time_zone.tz_minuteswest, time_zone.tz_dsttime));
X#  endif
X#else
X	  tzname[the_time->tm_isdst]);
X#endif
X	
X	return( (char *) buffer);
X}
X
X/** Starting argument parsing routine.   
X
X    Called as "get_options(argc, argv, options)" where options is a string
X    of the form "abc:d" indicating that 'a' 'b' and 'd' are flags and
X    'c' is a flag with a trailing argument.   Optional arguments are
X    returned in the external char * variable "optional_arg", and the
X    external int "opt_index" is set to the first entry in the argv list
X    that wasn't processed (ie after the flags). 
X
X    For example, the C compiler would have something of the form 
X    getopt(argc, argv, "Oo:l:") to allow "cc -O -o output -l lib file.c"
X
X    (C) Copyright 1986, Dave Taylor
X**/
X
Xint  _indx = 1, _argnum = 1;
X
Xint
Xget_options(argc, argv, options)
Xint argc;
Xchar *argv[], *options;
X{
X	/** Returns the character argument next, and optionally instantiates 
X	    "argument" to the argument associated with the particular option 
X	**/
X	
X	char       *word, *strchr();
X
X	if (_indx >= strlen(argv[_argnum])) {
X	  _argnum++;
X	  _indx = 1;		/* zeroeth char is '-' */
X	}
X
X	if (_argnum >= argc) {
X	  opt_index = argc;
X	  return(DONE);
X	}
X	
X	if (argv[_argnum][0] != '-') {
X	  opt_index = _argnum;
X	  return(DONE);
X	}
X
X        word = strchr(options, argv[_argnum][_indx++]);
X
X	if (strlen(word) == 0) 
X	  return(ERROR);
X	
X	if (word[1] == ':') {
X
X	  /** Two possibilities - either tailing end of this argument or the 
X	      next argument in the list **/
X
X	  if (_indx < strlen(argv[_argnum])) { /* first possibility */
X	    optional_arg = (char *) (argv[_argnum] + _indx);
X	    _argnum++;
X	    _indx = 1;
X	  }
X	  else {				/* second choice     */
X	    if (++_argnum >= argc) 
X	      return(ERROR);			/* no argument!!     */
X
X	    optional_arg = (char *) argv[_argnum++];
X	    _indx = 1;
X	  }
X	}
X
X	return((int) word[0]);
X}
END_OF_utils/fastmail.c
if test 8167 -ne `wc -c <utils/fastmail.c`; then
    echo shar: \"utils/fastmail.c\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: Extracting \"utils/newmail.c\" \(7989 characters\)
if test -f utils/newmail.c ; then 
  echo shar: Will not over-write existing file \"utils/newmail.c\"
else
sed "s/^X//" >utils/newmail.c <<'END_OF_utils/newmail.c'
X/**			newmail.c			**/
X
X/** Keep track of the mail for the current user...if new mail
X    arrives, output a line of the form;
X
X	   New mail from <name> - <subject>
X
X    where <name> is either the persons full name, or machine!login.
X    If there is no subject, it will say.
X
X    Added: you can specify a file other than the mailbox to keep
X    track of - if an argument is given, the program will try
X    to use it as a filename...
X
X    Also, the program will quit when you log off of the machine.
X
X    (C) Copyright 1986, Dave Taylor
X**/
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
X#include "defs.h"
X
X#ifdef AUTO_BACKGROUND
X#include <signal.h>	/* background jobs ignore some signals... */
X#endif
X
Xstatic char ident[] = { WHAT_STRING };
X
X#define LINEFEED	(char) 10
X#define BEGINNING	0			/* seek fseek(3S) */
X#define SLEEP_TIME	60		
X
X#define NO_SUBJECT	"(No Subject Specified)"
X
XFILE *mailfile;
X
Xlong  bytes();
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	char filename[LONG_SLEN];
X	long size, newsize;
X
X	if (argc > 2) 
X	  fprintf(stderr, "Usage: %s [filename] &\n", argv[0]);
X	else if (argc == 2) {
X	  strcpy(filename, argv[1]);
X	  if (access(filename, ACCESS_EXISTS) == -1) {
X	    fprintf(stderr,"%s: Can't open file %s to keep track of!\n",
X		    argv[0], filename);
X	    exit(1);
X	  }
X	}
X	else
X	  sprintf(filename,"%s%s",mailhome, getlogin());
X
X#ifdef AUTO_BACKGROUND
X	if (fork())	    /* automatically puts this task in background! */
X	  exit(0);
X
X	signal(SIGINT, SIG_IGN);
X	signal(SIGQUIT, SIG_IGN);
X	signal(SIGHUP,  SIG_DFL);	/* so we exit when logged out */
X#endif
X
X	size = bytes(filename);
X
X	mailfile = (FILE *) NULL;
X
X	while (1) {
X	
X#ifndef AUTO_BACKGROUND		/* won't work if we're nested this deep! */
X	  if (getppid() == 1) 	/* we've lost our shell! */
X	    exit();
X#endif
X	if (! isatty(1))	/* we're not sending output to a tty any more */
X	   exit();
X	
X	/** Note the lack of error checking on the fopen() (Philip Peake
X	    did!) - this is okay since if it fails we don't have any 
X	    mail and we can sleep(60) and try again later... 
X	**/
X
X	  if (mailfile == (FILE *) NULL) 
X	    mailfile = fopen(filename,"r");
X
X	  if ((newsize = bytes(filename)) > size) {	/* new mail */
X	    fseek(mailfile, size, BEGINNING); /* skip all current mail */
X	    size = newsize;
X	    printf("\n\r");	/* blank lines surrounding message */
X	    read_headers();
X	    printf("\n\r");
X	  }
X	  else if (newsize != size) {
X	    size = newsize; 		/* mail's been removed... */
X	    (void) fclose(mailfile);	/* close it and ...       */
X	    mailfile = (FILE *) NULL;	/* let's reopen the file  */
X	  }
X
X	  sleep(SLEEP_TIME);
X	}
X}
X
Xint
Xread_headers()
X{
X	/** read the headers, output as found **/
X
X	char buffer[LONG_SLEN], from_whom[SLEN], subject[SLEN];
X	register int subj = 0, in_header = 1, count = 0, priority=0;
X
X	while (fgets(buffer, LONG_SLEN, mailfile) != NULL) {
X	  if (first_word(buffer,"From ")) {
X	    if (real_from(buffer, from_whom)) {
X	      subj = 0;
X	      in_header = 1;
X	    }
X	  }
X	  else if (in_header) {
X	    if (first_word(buffer,">From")) 
X	      forwarded(buffer, from_whom); /* return address */
X	    else if (first_word(buffer,"Subject:") ||
X		     first_word(buffer,"Re:")) {
X	      if (! subj++) {
X	        remove_first_word(buffer);
X		strcpy(subject, buffer);
X	      }
X	    }
X	    else if (first_word(buffer,"Priority:")) 
X	      priority++;
X	    else if (first_word(buffer,"From:")) 
X	      parse_arpa_from(buffer, from_whom);
X	    else if (buffer[0] == LINEFEED) {
X	      in_header = 0;	/* in body of message! */
X	      show_header(priority, from_whom, subject);
X	      from_whom[0] = 0;
X	      subject[0] = 0;
X	      count++;
X	    }
X	  }
X	}
X	return(count);
X}
X
Xint
Xreal_from(buffer, who)
Xchar *buffer, *who;
X{
X	/***** returns true iff 's' has the seven 'from' fields,
X	       initializing the who to the sender *****/
X
X	char junk[80];
X
X	junk[0] = '\0';
X	sscanf(buffer, "%*s %s %*s %*s %*s %*s %s",
X	            who, junk);
X	return(junk[0] != '\0');
X}
X
Xforwarded(buffer, who)
Xchar *buffer, *who;
X{
X	/** change 'from' and date fields to reflect the ORIGINATOR of 
X	    the message by iteratively parsing the >From fields... **/
X
X	char machine[80], buff[80];
X
X	machine[0] = '\0';
X	sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %*s %s",
X	            who, machine);
X
X	if (machine[0] == '\0') /* try for srm address */
X	  sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %s",
X	            who, machine);
X
X	if (machine[0] == '\0')
X	  sprintf(buff,"anonymous");
X	else
X	  sprintf(buff,"%s!%s", machine, who);
X
X	strncpy(who, buff, 80);
X}
X
X
Xremove_first_word(string)
Xchar *string;
X{	/** removes first word of string, ie up to first non-white space
X	    following a white space! **/
X
X	register int loc;
X
X	for (loc = 0; string[loc] != ' ' && string[loc] != '\0'; loc++) 
X	    ;
X
X	while (string[loc] == ' ' || string[loc] == '\t')
X	  loc++;
X	
X	move_left(string, loc);
X}
X
Xmove_left(string, chars)
Xchar string[];
Xint  chars;
X{
X	/** moves string chars characters to the left DESTRUCTIVELY **/
X
X	register int i;
X
X	chars--; /* index starting at zero! */
X
X	for (i=chars; string[i] != '\0' && string[i] != '\n'; i++)
X	  string[i-chars] = string[i];
X
X	string[i-chars] = '\0';
X}
X
Xshow_header(priority, from, subject)
Xint   priority;
Xchar *from, *subject;
X{
X	/** output header in clean format, including abbreviation
X	    of return address if more than one machine name is
X	    contained within it! **/
X	char buffer[SLEN];
X	int  loc, i=0, exc=0;
X
X#ifdef PREFER_UUCP
X
X	if (chloc(from, '!') != -1 && in_string(from, BOGUS_INTERNET))
X	  from[strlen(from) - strlen(BOGUS_INTERNET)] = '\0';
X
X#endif
X
X	loc = strlen(from);
X
X	while (exc < 2 && loc > 0)
X	  if (from[--loc] == '!')
X	    exc++;
X
X	if (exc == 2) { /* lots of machine names!  Get last one */
X	  loc++;
X	  while (loc < strlen(from) && loc < SLEN)
X	    buffer[i++] = from[loc++];
X	  buffer[i] = '\0';
X	  strcpy(from, buffer);
X	}
X
X	if (strlen(subject) < 2)
X	  strcpy(subject, NO_SUBJECT);
X	
X	  printf(">> %s mail from %s - %s\n\r", 
X		priority? "PRIORITY" : "New", from, subject);
X}	
X
Xparse_arpa_from(buffer, newfrom)
Xchar *buffer, *newfrom;
X{
X	/** try to parse the 'From:' line given... It can be in one of
X	    two formats:
X		From: Dave Taylor <hpcnou!dat>
X	    or  From: hpcnou!dat (Dave Taylor)
X	    Change 'newfrom' ONLY if sucessfully parsed this entry and
X	    the resulting name is non-null! 
X	**/
X
X	char temp_buffer[SLEN], *temp;
X	register int i, j = 0;
X
X	temp = (char *) temp_buffer;
X	temp[0] = '\0';
X
X	no_ret(buffer);		/* blow away '\n' char! */
X
X	if (lastch(buffer) == '>') {
X	  for (i=strlen("From: "); buffer[i] != '\0' && buffer[i] != '<' &&
X	       buffer[i] != '('; i++)
X	    temp[j++] = buffer[i];
X	  temp[j] = '\0';
X	}
X	else if (lastch(buffer) == ')') {
X	  for (i=strlen(buffer)-2; buffer[i] != '\0' && buffer[i] != '(' &&
X	       buffer[i] != '<'; i--)
X	    temp[j++] = buffer[i];
X	  temp[j] = '\0';
X	  reverse(temp);
X	}
X	  
X	if (strlen(temp) > 0) {		/* mess with buffer... */
X
X	  /* remove leading spaces... */
X
X	  while (whitespace(temp[0]))
X	    temp = (char *) (temp + 1);		/* increment address! */
X
X	  /* remove trailing spaces... */
X
X	  i = strlen(temp) - 1;
X
X	  while (whitespace(temp[i]))
X	   temp[i--] = '\0';
X
X	  /* if anything is left, let's change 'from' value! */
X
X	  if (strlen(temp) > 0)
X	    strcpy(newfrom, temp);
X	}
X}
X
Xreverse(string)
Xchar *string;
X{
X	/** reverse string... pretty trivial routine, actually! **/
X
X	char buffer[SLEN];
X	register int i, j = 0;
X
X	for (i = strlen(string)-1; i >= 0; i--)
X	  buffer[j++] = string[i];
X
X	buffer[j] = '\0';
X
X	strcpy(string, buffer);
X}
X
Xlong
Xbytes(name)
Xchar *name;
X{
X	/** return the number of bytes in the specified file.  This
X	    is to check to see if new mail has arrived....  **/
X
X	int ok = 1;
X	extern int errno;	/* system error number! */
X	struct stat buffer;
X
X	if (stat(name, &buffer) != 0)
X	  if (errno != 2)
X	   exit(fprintf(stderr,"Error %d attempting fstat on %s", errno, name));
X	  else
X	    ok = 0;
X	
X	return(ok ? buffer.st_size : 0);
X}
END_OF_utils/newmail.c
if test 7989 -ne `wc -c <utils/newmail.c`; then
    echo shar: \"utils/newmail.c\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: Extracting \"utils/wnewmail.c\" \(8080 characters\)
if test -f utils/wnewmail.c ; then 
  echo shar: Will not over-write existing file \"utils/wnewmail.c\"
else
sed "s/^X//" >utils/wnewmail.c <<'END_OF_utils/wnewmail.c'
X/**			wnewmail.c			**/
X
X/** Same as newmail.c but for a windowing system...
X    
X    (C) Copyright 1986, Dave Taylor
X**/
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
X#include "defs.h"
X
X#ifdef AUTO_BACKGROUND
X#include <signal.h>	/* background jobs ignore some signals... */
X#endif
X
Xstatic char ident[] = { WHAT_STRING };
X
X#define LINEFEED	(char) 10
X#define BEGINNING	0			/* seek fseek(3S) */
X#define SLEEP_TIME	10		
X
X#define NO_SUBJECT	"(No Subject Specified)"
X
XFILE *mailfile;
X
Xlong  bytes();
Xchar  *getusername();
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	char filename[LONG_SLEN];
X	long size, newsize;
X
X	if (argc > 2) 
X	  fprintf(stderr, "Usage: %s [filename] &\n", argv[0]);
X	else if (argc == 2) {
X	  strcpy(filename, argv[1]);
X	  if (access(filename, ACCESS_EXISTS) == -1) {
X	    fprintf(stderr,
X	       "%s: Can't open file %s to keep track of incoming mail.\n",
X		    argv[0], filename);
X	    exit(1);
X	  }
X	}
X	else
X	  sprintf(filename,"%s%s",mailhome, getusername());
X
X#ifdef AUTO_BACKGROUND
X	if (fork())	    /* automatically puts this task in background! */
X	  exit(0);
X
X	signal(SIGINT, SIG_IGN);
X	signal(SIGQUIT, SIG_IGN);
X	signal(SIGHUP,  SIG_DFL);	/* so we exit when logged out */
X#endif
X
X	size = bytes(filename);
X
X	mailfile = (FILE *) NULL;
X
X	printf("Incoming Mail;\n");
X
X	while (1) {
X	
X#ifndef AUTO_BACKGROUND		/* won't work if we're nested this deep! */
X	  if (getppid() == 1) 	/* we've lost our shell! */
X	    exit();
X#endif
X	if (! isatty(1))     /* we're not talking to the screen any more */
X	   exit();
X	
X	/** Note the lack of error checking on the fopen() (Philip Peake
X	    did!) - this is okay since if it fails we don't have any 
X	    mail and we can sleep(60) and try again later... 
X	**/
X
X	  if (mailfile == (FILE *) NULL) 
X	    mailfile = fopen(filename,"r");
X
X	  if ((newsize = bytes(filename)) > size) {	/* new mail */
X	    fseek(mailfile, size, BEGINNING); /* skip all current mail */
X	    size = newsize;
X	    printf("%c", 007);	/* beep for new mail! */
X	    read_headers();
X	  }
X	  else if (newsize != size) {
X	    size = newsize; 		/* mail's been removed... */
X	    (void) fclose(mailfile);	/* close it and ...       */
X	    mailfile = (FILE *) NULL;	/* let's reopen the file  */
X	  }
X
X	  sleep(SLEEP_TIME);
X	}
X}
X
Xint
Xread_headers()
X{
X	/** read the headers, output as found **/
X
X	char buffer[LONG_SLEN], from_whom[SLEN], subject[SLEN];
X	register int subj = 0, in_header = 1, count = 0, priority = 0;
X
X	while (fgets(buffer, LONG_SLEN, mailfile) != NULL) {
X	  if (first_word(buffer,"From ")) {
X	    if (real_from(buffer, from_whom)) {
X	      subj = 0;
X	      priority = 0;
X	      in_header = 1;
X	    }
X	  }
X	  else if (in_header) {
X	    if (first_word(buffer,">From")) 
X	      forwarded(buffer, from_whom); /* return address */
X	    else if (first_word(buffer,"Subject:") ||
X		     first_word(buffer,"Re:")) {
X	      if (! subj++) {
X	        remove_first_word(buffer);
X		strcpy(subject, buffer);
X	      }
X	    }
X	    else if (first_word(buffer,"From:")) 
X	      parse_arpa_from(buffer, from_whom);
X	    else if (first_word(buffer, "Priority:"))
X	      priority++;
X	    else if (buffer[0] == LINEFEED) {
X	      in_header = 0;	/* in body of message! */
X	      show_header(priority, from_whom, subject);
X	      from_whom[0] = 0;
X	      subject[0] = 0;
X	      count++;
X	    }
X	  }
X	}
X	return(count);
X}
X
Xint
Xreal_from(buffer, who)
Xchar *buffer, *who;
X{
X	/***** returns true iff 's' has the seven 'from' fields,
X	       initializing the who to the sender *****/
X
X	char junk[80];
X
X	junk[0] = '\0';
X	sscanf(buffer, "%*s %s %*s %*s %*s %*s %s",
X	            who, junk);
X	return(junk[0] != '\0');
X}
X
Xforwarded(buffer, who)
Xchar *buffer, *who;
X{
X	/** change 'from' and date fields to reflect the ORIGINATOR of 
X	    the message by iteratively parsing the >From fields... **/
X
X	char machine[80], buff[80];
X
X	machine[0] = '\0';
X	sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %*s %s",
X	            who, machine);
X
X	if (machine[0] == '\0') /* try for srm address */
X	  sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %s",
X	            who, machine);
X
X	if (machine[0] == '\0')
X	  sprintf(buff,"anonymous");
X	else
X	  sprintf(buff,"%s!%s", machine, who);
X
X	strncpy(who, buff, 80);
X}
X
X
Xremove_first_word(string)
Xchar *string;
X{	/** removes first word of string, ie up to first non-white space
X	    following a white space! **/
X
X	register int loc;
X
X	for (loc = 0; string[loc] != ' ' && string[loc] != '\0'; loc++) 
X	    ;
X
X	while (string[loc] == ' ' || string[loc] == '\t')
X	  loc++;
X	
X	move_left(string, loc);
X}
X
Xmove_left(string, chars)
Xchar string[];
Xint  chars;
X{
X	/** moves string chars characters to the left DESTRUCTIVELY **/
X
X	register int i;
X
X	chars--; /* index starting at zero! */
X
X	for (i=chars; string[i] != '\0' && string[i] != '\n'; i++)
X	  string[i-chars] = string[i];
X
X	string[i-chars] = '\0';
X}
X
Xshow_header(priority, from, subject)
Xint   priority;
Xchar *from, *subject;
X{
X	/** Output header in clean format, including abbreviation
X	    of return address if more than one machine name is
X	    contained within it! **/
X
X	char buffer[SLEN];
X	int  loc, i=0, exc=0;
X
X#ifdef PREFER_UUCP
X	
X	if (chloc(from,'!') != -1 && in_string(from, BOGUS_INTERNET))
X	  from[strlen(from) - strlen(BOGUS_INTERNET)] = '\0';
X
X#endif
X
X	loc = strlen(from);
X
X	while (exc < 2 && loc > 0)
X	  if (from[--loc] == '!')
X	    exc++;
X
X	if (exc == 2) { /* lots of machine names!  Get last one */
X	  loc++;
X	  while (loc < strlen(from) && loc < SLEN)
X	    buffer[i++] = from[loc++];
X	  buffer[i] = '\0';
X	  strcpy(from, buffer);
X	}
X
X	if (strlen(subject) < 2)
X	  strcpy(subject, NO_SUBJECT);
X	
X	  if (strlen(from) > 0)	/* last final check... */
X	    printf("%sMail from %s -- %s\n", 
X		   priority? "PRIORITY ": "", from, subject);
X}	
X
Xparse_arpa_from(buffer, newfrom)
Xchar *buffer, *newfrom;
X{
X	/** Try to parse the 'From:' line given... It can be in one of
X	    two formats:
X		From: Dave Taylor <hpcnou!dat>
X	    or  From: hpcnou!dat (Dave Taylor)
X	    Change 'newfrom' ONLY if sucessfully parsed this entry and
X	    the resulting name is non-null! 
X	**/
X
X	char temp_buffer[SLEN], *temp;
X	register int i, j = 0;
X
X	temp = (char *) temp_buffer;
X	temp[0] = '\0';
X
X	no_ret(buffer);		/* blow away '\n' char! */
X
X	if (lastch(buffer) == '>') {
X	  for (i=strlen("From: "); buffer[i] != '\0' && buffer[i] != '<' &&
X	       buffer[i] != '('; i++)
X	    temp[j++] = buffer[i];
X	  temp[j] = '\0';
X	}
X	else if (lastch(buffer) == ')') {
X	  for (i=strlen(buffer)-2; buffer[i] != '\0' && buffer[i] != '(' &&
X	       buffer[i] != '<'; i--)
X	    temp[j++] = buffer[i];
X	  temp[j] = '\0';
X	  reverse(temp);
X	}
X	  
X	if (strlen(temp) > 0) {		/* mess with buffer... */
X
X	  /* remove leading spaces... */
X
X	  while (whitespace(temp[0]))
X	    temp = (char *) (temp + 1);		/* increment address! */
X
X	  /* remove trailing spaces... */
X
X	  i = strlen(temp) - 1;
X
X	  while (whitespace(temp[i]))
X	   temp[i--] = '\0';
X
X	  /* if anything is left, let's change 'from' value! */
X
X	  if (strlen(temp) > 0)
X	    strcpy(newfrom, temp);
X	}
X}
X
Xreverse(string)
Xchar *string;
X{
X	/** reverse string... pretty trivial routine, actually! **/
X
X	char buffer[SLEN];
X	register int i, j = 0;
X
X	for (i = strlen(string)-1; i >= 0; i--)
X	  buffer[j++] = string[i];
X
X	buffer[j] = '\0';
X
X	strcpy(string, buffer);
X}
X
Xlong
Xbytes(name)
Xchar *name;
X{
X	/** return the number of bytes in the specified file.  This
X	    is to check to see if new mail has arrived....  **/
X
X	int ok = 1;
X	extern int errno;	/* system error number! */
X	struct stat buffer;
X
X	if (stat(name, &buffer) != 0)
X	  if (errno != 2)
X	   exit(fprintf(stderr,"Error %d attempting fstat on %s", errno, name));
X	  else
X	    ok = 0;
X	
X	return(ok ? (long) buffer.st_size : 0L);
X}
X
Xchar  *getusername()
X{
X	/** Getting the username on some systems is a real pain, so...
X	   This routine is guaranteed to return a usable username **/
X
X	char *return_value, *cuserid(), *getlogin();
X
X	if ((return_value = cuserid(NULL)) == NULL)
X	  if ((return_value = getlogin()) == NULL)
X	    exit(printf("Newmail: I can't get username!\n"));
X
X	return( (char *) return_value);
X}
END_OF_utils/wnewmail.c
if test 8080 -ne `wc -c <utils/wnewmail.c`; then
    echo shar: \"utils/wnewmail.c\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: End of archive 7 \(of 19\).
cp /dev/null ark7isdone
DONE=true
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
    if test ! -f ark${I}isdone ; then
	echo shar: You still need to run archive ${I}.
	DONE=false
    fi
done
if test "$DONE" = "true" ; then
	echo You have unpacked all 19 archives.
	echo "See the Instructions file"
	rm -f ark[1-9]isdone ark[1-9][0-9]isdone
fi
##  End of shell archive.
exit 0