[comp.sources.unix] v18i089: Elm mail system, release 2.2, Part10/24

rsalz@uunet.uu.net (Rich Salz) (04/12/89)

Submitted-by: dsinc!syd@uunet.UU.NET (Syd Weinstein)
Posting-number: Volume 18, Issue 89
Archive-name: elm2.2/part10

#!/bin/sh
# this is part 10 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file hdrs/shortname.1 continued
#
CurArch=10
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file hdrs/shortname.1"
sed 's/^X//' << 'SHAR_EOF' >> hdrs/shortname.1
XReceived: by convex (4.12/4.7)
X	id AA01616; Tue, 24 Mar 87 16:47:43 cst
XReceived: by ndmce.UUCP (smail2.3)
X	id AA24491; 24 Mar 87 16:41:30 CST (Tue)
XTo: ndmce!hplabs!taylor@hplabs.HP.COM
XDate: Tue, 24 Mar 87 16:08:01 CST
XSubject: shortnames.h mods
XX-Mailer: Elm [version 1.5]
X
XDave,
X
XHello. I have just finished installing Elm on my 68k unix box running
XUnisoft Uniplus+ sysvr1. Unfortunately the C compiler doesn't support
Xlong variable names so I had the dubious honor of updating shortnames.h
Xto include several new variable and function names. I also do not have
Xthe setvbuf() function. I modified filter.h to delete it. I am enclosing
Xmy changes if you are interested...
X
XManlio D. Marquez
Xjlsoft!marquez
X
X
X
Xshortnames.h
X-----------------------
X/**			shortnames.h			**/
X
X/** This file is from Geoff Kuenning, and will help those poor users that
X    are stuck using C compilers that don't have flexnames.   Too bad.
X
X	This file has no explicit copyright.
X
X**/
X
X#define PutLine0		PLine0
X#define PutLine1		PLine1
X#define PutLine2		PLine2
X#define PutLine3		PLine3
X
X#define add_to_table		add_2_table
X#define address1		addrs1
X#define addressII		addrsII
X#define addresses		addr_s
X#define alternate_prompt	alt_prompt
X#define alternative_addresses	alt_addrs
X#define alternatives		alts
X#define always_leave		alw_leave
X
X#define calendar_line		cal_line
X#define cancelled_msg		cncld_msg
X#define central_message_buffer	cntrl_bfr
X#define check_form_file		chk_frmf
X#define compare_dates		cmp_dates
X#define compare_headers		cmp_hdrs
X#define copy_message_across	cpy_msg_across
X#define current_record		cur_rec
X#define current_time		cur_time
X
X#define define_softkeys		def_softkeys
X#define display_central_message	displ_cntrl_msg
X#define display_error		displ_error
X#define display_headers		displ_hdrs
X#define display_helpfile	dspl_helpfile
X#define display_line		dspl_line
X#define display_options		displ_options
X#define display_title		displ_titles
X#define display_to		displ_to
X
X#define encrypted		crypted
X#define encrypted_key		crypt_key
X#define expanded_cc		xp_cc
X#define expanded_to		xp_to
X#define expand_address		xp_addr
X#define expand_domain		xp_domain
X#define expand_env		xp_env
X#define expand_filename		xp_filename
X#define expand_group		xp_group
X#define expand_logname		xp_logname
X#define expand_site		xp_site
X#define expand_system		xp_system
X
X#define filename2		fn2
X#define findnode_has_been_initialized	fndhbi
X#define format_long		frm_lng
X#define form_letter		frm_let
X#define forward			forwrd
X
X#define generate_reply_to	gen_reply_to
X#define get_return_name		g_ret_name
X
X#define header_line		h_line
X#define header_page		h_page
X#define headers_per_page	h_per_page
X#define header_table		h_table
X
X#define install_aliases		ins_aliases
X
X#define last_line_loc		last_ln_loc
X#define long_sum		lng_sum
X
X#define machine_group		mach_group
X#define mailbox_defined		mbox_defined
X#define mailfile_size		mfile_size
X#define message_count		msg_count
X#define message_number		msg_number
X
X#define newaliases		nwaliases
X#define noptimize_return	noret_opt
X#define noptimize_usenet	nousenet_opt
X
X#define one_liner		one_lner
X#define optimize_and_add	opt_and_add
X#define optimize_arpa		opt_arpa
X#define optimize_cmplx_arpa	opt_cmplx_arpa
X#define optimize_return		opt_return
X#define optimize_usenet		opt_usenet
X#define optional_arg		opt_arg
X#define optionally_enter	opt_enter
X#define options_help		opt_hlp
X#define original_cc		orig_cc
X#define original_msg_num	orig_msg_num
X#define original_to		orig_to
X
X#define parse_arguments		pars_arguments
X#define parse_arpa_from		prs_arpa_from
X#define password_entry		pw_entry
X#define pattern_enter		pat_enter
X#define pattern_match		pat_match
X#define prompt_for_entry	prpt_ent
X#define prompt_for_sized_entry	prpt_sntry
X#define prompt_for_multiple_entries	prpt_fme
X
X#define read_alias_files	rd_alias_files
X#define read_headers		rd_headers
X#define read_in_file		rd_n_file
X#define read_in_messages	rd_n_mess
X#define read_rc			rd_rc
X#define read_rc_file		rd_rc_file
X#define received_on_machine	rcvd_on_machine
X#define remove_all		rem_all
X#define remove_first_word	rem_1st_word
X#define remove_domains		rem_domains
X#define remove_header		rem_hdr
X#define remove_user		rem_user
X#define remove_through_ch	rem_thru_ch
X#define reply_to_everyone	repl_to_everyone
X#define resolve_received	rslv_received
X
X#define save_option_string	sv_string
X#define save_option_sort	sv_sort
X#define save_option_number	sv_number
X#define save_option_on_off	sv_on_off
X#define save_option_weedlist	sv_weed
X#define save_option_alternatives	sv_alts
X#define show_message		shw_message
X#define show_msg		showmsg
X#define show_msg_tag		sh_msg_tag
X#define size_of_pathfd		sz_of_pathfd
X#define softkeys_off		soft_off
X#define softkeys_on		soft_on
X#define subjectbuffer		subjbuff
X#define subject_matches		subj_matches
X#define switching_to_default	sw_t_def
X#define system_call		sys_call
X#define system_data		sys_data
X#define system_files		sys_files
X#define system_hash_table	sys_hash_table
X#define system_record		sys_record
X
X#define tail_of_string		tl_of_string
X#define talk_to_sys		tlk_to_sys
X#define tempfile		tmpfile
X#define termcap_label		tcap_label
X#define top_of_screen_left	top_left_of_screen
X#define top_of_screen_right	top_right_of_screen
X#define translate_return	xlate_return
X
X#define update_mailtime		upd_mailtime
X#define update_title		upd_title
X#define unexpanded_cc		unexp_cc
X#define unexpanded_to		unexp_to
X
X#define verify_transmission	vfy_xmsn
X
X#define weeding_out		wding_out
X
X---------------------------------------
X
Xextra change for filter.h (stuck at end of file)
X
X---------------------------------------
X
X#ifndef setvbuf
X# define setvbuf(fd,a,b,c)	/* if don't have it, punt it off */
X#endif
X
X---------------------------------------
X
X
X
SHAR_EOF
echo "File hdrs/shortname.1 is complete"
chmod 0444 hdrs/shortname.1 || echo "restore of hdrs/shortname.1 fails"
echo "x - extracting hdrs/shortname.2 (Text)"
sed 's/^X//' << 'SHAR_EOF' > hdrs/shortname.2 &&
XNOTE: This file is obsolete and is not being kept uptodate.  It is provided
Xfor reference only.
X
XSyd Weinstein
XElm Coordinator
X
XFrom seismo!sundc!eli!geller@hplabs.HP.COM  Wed Mar 25 22:15:48 1987
XReceived: from hplabsc (hplabsc.hpl.hp.com) by hpldat ; Wed, 25 Mar 87 22:15:48 pst
XReturn-Path: <seismo!sundc!eli!geller@hplabs.HP.COM>
XReceived: from hplabs.HP.COM by hplabsc ; Wed, 25 Mar 87 22:15:04 pst
XReceived: from seismo.CSS.GOV by hplabs.HP.COM with TCP ; Wed, 25 Mar 87 22:12:56 pst
XReceived: from sundc.UUCP by seismo.CSS.GOV (5.54/1.14) with UUCP 
X	id AA24355; Thu, 26 Mar 87 01:12:39 EST
XFrom: seismo!sundc!eli!geller@hplabs.HP.COM
XReceived: by sundc.uucp (3.2/SMI-3.2)
X	id AA06338; Thu, 26 Mar 87 01:10:15 EST
XDate: Thu, 26 Mar 87 01:10:15 EST
XMessage-Id: <8703260610.AA06338@sundc.uucp>
XDave: 
XTo: hplabs!taylor@hplabs.HP.COM
X
XHere's the shortnames.h stuff I told you about. Hope its helpful -
Xbut you probably don't need it, being that you use a real
Xcompiler...
X
XAlso - has reply.c been posted to mod.sources? I'm looking
Xforward to receiving it. That's the last link I need before
XElm gets up and running.
X
X
X/*
X * D. Geller, 3/12/87
X */
X
X#define alternate_editor		alt_editor
X#define prompt_for_entry		pf_entry
X#define prompt_for_multiple_entries	pf_mult
X#define prompt_for_sized_entry		pf_size
X#define long_summary			lng_sum
X#define options_help			opts_help
X#define save_option_string		svo_string
X#define save_option_sort		svo_sort
X#define save_option_on_off		svo_onoff
X#define save_option_number		svo_numb
X#define save_option_weedlist		svo_weed
X#define save_option_alternatives	svo_alt
X#define form_letter			form_le
X#define form_letter_section		form_sect
X#define one_liner_for			onel_for
X#define switching_to_default		swi_to
X#define findnode_has_been_initialized	fnodhas
X
X/*
X * end of additions by Geller
X */
X
X
SHAR_EOF
chmod 0444 hdrs/shortname.2 || echo "restore of hdrs/shortname.2 fails"
echo "x - extracting hdrs/shortname.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > hdrs/shortname.h &&
X
X/* @(#)$Id: shortname.h,v 2.3 89/03/25 21:45:34 syd Exp $ */
X
X/*******************************************************************************
X *  The Elm Mail System  -  $Revision: 2.3 $   $State: Exp $
X *
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X *	Syd Weinstein, Elm Coordinator
X *	syd@dsinc.UUCP			dsinc!syd
X *
X *******************************************************************************
X * $Log:	shortname.h,v $
X * Revision 2.3  89/03/25  21:45:34  syd
X * Initial 2.2 Release checkin
X * 
X *
X ******************************************************************************/
X
X/** This file is from Geoff Kuenning, and will help those poor users that
X    are stuck using C compilers that don't have flexnames.   Too bad.
X
XNOTE: This file is obsolete and is not being kept uptodate.  It is provided
Xfor reference only.
X
XSyd Weinstein
XElm Coordinator
X
X**/
X
X#define CleartoEOS		Clear_EOS
X#define CleartoEOLN		Clear_EOLN
X
X#define PutLine0		PLine0
X#define PutLine1		PLine1
X#define PutLine2		PLine2
X#define PutLine3		PLine3
X
X#define add_to_table		add_2_table
X#define address1		addrs1
X#define addressII		addrsII
X#define addresses		addr_s
X#define alternate_prompt	alt_prompt
X#define alternative_addresses	alt_addrs
X#define always_leave		alw_leave
X
X#define calendar_line		cal_line
X#define cancelled_msg		cncld_msg
X#define central_message_buffer	cntrl_bfr
X#define compare_dates		cmp_dates
X#define compare_headers		cmp_hdrs
X#define copy_message_across	cpy_msg_across
X#define current_record		cur_rec
X#define current_time		cur_time
X
X#define define_softkeys		def_softkeys
X#define display_central_message	displ_cntrl_msg
X#define display_error		displ_error
X#define display_headers		displ_hdrs
X#define display_helpfile	dspl_helpfile
X#define display_options		displ_options
X#define display_title		displ_titles
X#define display_to		displ_to
X
X#define encrypted		crypted
X#define encrypted_key		crypt_key
X#define expanded_cc		xp_cc
X#define expanded_to		xp_to
X#define expand_address		xp_addr
X#define expand_domain		xp_domain
X#define expand_env		xp_env
X#define expand_filename		xp_filename
X#define expand_group		xp_group
X#define expand_logname		xp_logname
X#define expand_site		xp_site
X#define expand_system		xp_system
X
X#define filename2		fn2
X#define forward			forwrd
X
X#define generate_reply_to	gen_reply_to
X#define get_return_name		g_ret_name
X
X#define header_line		h_line
X#define header_page		h_page
X#define headers_per_page	h_per_page
X#define headers                 hdrs
X
X#define install_aliases		ins_aliases
X
X#define last_line_loc		last_ln_loc
X
X#define machine_group		mach_group
X#define mailbox_defined		mbox_defined
X#define mailfile_size		mfile_size
X#define message_count		msg_count
X#define message_number		msg_number
X
X#define newaliases		nwaliases
X#define noptimize_return	noret_opt
X#define noptimize_usenet	nousenet_opt
X
X#define optimize_and_add	opt_and_add
X#define optimize_arpa		opt_arpa
X#define optimize_cmplx_arpa	opt_cmplx_arpa
X#define optimize_return		opt_return
X#define optimize_usenet		opt_usenet
X#define optional_arg		opt_arg
X#define optionally_enter	opt_enter
X#define original_cc		orig_cc
X#define original_msg_num	orig_msg_num
X#define original_to		orig_to
X
X#define parse_arguments		pars_arguments
X#define parse_arpa_from		prs_arpa_from
X#define password_entry		pw_entry
X#define pattern_enter		pat_enter
X#define pattern_match		pat_match
X
X#define read_alias_files	rd_alias_files
X#define read_headers		rd_headers
X#define read_rc			rd_rc
X#define read_rc_file		rd_rc_file
X#define received_on_machine	rcvd_on_machine
X#define remove_all		rem_all
X#define remove_first_word	rem_1st_word
X#define remove_domains		rem_domains
X#define remove_header		rem_hdr
X#define remove_user		rem_user
X#define remove_through_ch	rem_thru_ch
X#define reply_to_everyone	repl_to_everyone
X#define resolve_received	rslv_received
X
X#define show_message		shw_message
X#define show_msg		showmsg
X#define show_msg_tag		sh_msg_tag
X#define size_of_pathfd		sz_of_pathfd
X#define softkeys_off		soft_off
X#define softkeys_on		soft_on
X#define subjectbuffer		subjbuff
X#define subject_matches		subj_matches
X#define system_call		sys_call
X#define system_data		sys_data
X#define system_files		sys_files
X#define system_hash_table	sys_hash_table
X#define system_record		sys_record
X
X#define tail_of_string		tl_of_string
X#define talk_to_sys		tlk_to_sys
X#define tempfile		tmpfile
X#define termcap_label		tcap_label
X#define top_of_screen_left	top_left_of_screen
X#define top_of_screen_right	top_right_of_screen
X#define translate_return	xlate_return
X
X#define update_mailtime		upd_mailtime
X#define update_title		upd_title
X#define unexpanded_cc		unexp_cc
X#define unexpanded_to		unexp_to
X
X#define verify_transmission	vfy_xmsn
X
X#define weeding_out		wding_out
SHAR_EOF
chmod 0444 hdrs/shortname.h || echo "restore of hdrs/shortname.h fails"
echo "x - extracting hdrs/sysdefs.SH (Text)"
sed 's/^X//' << 'SHAR_EOF' > hdrs/sysdefs.SH &&
Xcase $CONFIG in
X'')
X    if test ! -f config.sh; then
X	ln ../config.sh . || \
X	ln ../../config.sh . || \
X	ln ../../../config.sh . || \
X	(echo "Can't find config.sh."; exit 1)
X	echo "Using config.sh from above..."
X    fi
X    . ./config.sh
X    ;;
Xesac
Xecho "Extracting hdrs/sysdefs.h (with variable substitutions)"
Xsed <<!GROK!THIS! >sysdefs.h -e 's!^#undef!/\*#undef!'
X/* $Id: sysdefs.SH,v 2.12 89/03/25 21:45:37 syd Exp $ */
X/*******************************************************************************
X *  The Elm Mail System  -  $Revision: 2.12 $   $State: Exp $
X *
X * 			Copyright (c) 1986, 1987 Dave Taylor
X * 			Copyright (c) 1988, 1989 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X *	Syd Weinstein, Elm Coordinator
X *	elm@dsinc.UUCP			dsinc!elm
X *
X *******************************************************************************
X * $Log:	sysdefs.SH,v $
X * Revision 2.12  89/03/25  21:45:37  syd
X * Initial 2.2 Release checkin
X * 
X *
X ******************************************************************************/
X
X/**  System level, configurable, defines for the ELM mail system.  **/
X
X
X#define FIND_DELTA	10		/* byte region where the binary search
X					   on the path alias file is fruitless 
X                                           (can't be within this boundary)    */
X
X#define MAX_IN_WEEDLIST 150	/* max headers to weed out               */
X
X#define MAX_HOPS	35	/* max hops in return addr to E)veryone  */
X
X#define DEFAULT_BATCH_SUBJECT  "$defbatsub"
X
X#define DEFAULT_DOMAIN  "$mydomain"  /* if mydomain file is missing */
X
X/** If you want to implement 'site hiding' in the mail, then you'll need to
X    uncomment the following lines and set them to reasonable values.  See 
X    the configuration guide for more details....(actually these are undoc-
X    umented because they're fairly dangerous to use.  Just ignore 'em and
X    perhaps one day you'll find out what they do, ok?)
X**/
X
X/****************************************************************************
X
X#define   SITE_HIDING
X#define   HIDDEN_SITE_NAME	"fake-machine-name"
X#define   HIDDEN_SITE_USERS	"/usr/mail/lists/hidden_site_users"
X
X****************************************************************************/
X
X#define system_text_file        "$lib/aliases.text"
X#define system_hash_file        "$lib/aliases.hash"
X#define system_data_file        "$lib/aliases.data"
X
X#define ALIAS_TEXT		".elm/aliases.text"
X#define ALIAS_HASH		".elm/aliases.hash"
X#define ALIAS_DATA		".elm/aliases.data"
X
X#define pathfile		"$pathalias"
X#define domains			"$domains"
X#define hostdomfile             "$lib/domain"
X
X#define Lsys			"$lsysfile"
X
X/** where to put the output of the elm -d command... (in home dir) **/
X#define DEBUGFILE	"ELM:debug.info"
X#define OLDEBUG		"ELM:debug.last"
X
X#define	temp_dir   	"$tmpdir/"
X#define temp_file	"$tmpdir/snd."
X#define temp_form_file	"$tmpdir/form."
X#define temp_mbox	"$tmpdir/mbox."
X#define temp_print      "$tmpdir/print."
X#define temp_edit	"$tmpdir/elm-edit"
X#define temp_uuname	"$tmpdir/uuname."
X#define readmsg_file	".elm/readmsg"
X
X#define emacs_editor	"$emacs"
X
X#define default_editor	"$defeditor"
X#define mailhome	"$maildir/"
X
X#define default_shell	"$prefshell"
X#define default_pager	"$pager"
X#define default_printout	"$cat %s | $linepr"
X
X#define sendmail	"$sendmail"
X#define smflags		"-oi -oem"	/* ignore dots and mail back errors */
X#define smflagsv      "-oi -oem -v"   /* Verbose voyuer mode */
X#define mailer		"$mailer"
X
X#define mailx		"$mailx"
X
X#define helphome	"$lib"
X#define helpfile	"elm-help"
X
X#define ELMRC_INFO	"$lib/elmrc-info"
X
X#define elmrcfile	".elm/elmrc"
X#define old_elmrcfile	".elm/elmrc.old"
X#define mailheaders	".elm/elmheaders"
X#define dead_letter	"Cancelled.mail"
X
X#define unedited_mail	"emergency.mbox"
X
X#define newalias	"newalias 1>&2 > /dev/null"
X#define readmsg		"readmsg"
X
X#define remove_cmd	"$rm -f"	/* how to remove a file */
X#define cat		"$cat"		/* how to display files */
X#define sed_cmd		"$sed"		/* how to access sed */
X#define move_cmd	"$mv"		/* how to access sed */
X#define uuname		"$uuname"	/* how to get a uuname  */
X!GROK!THIS!
SHAR_EOF
chmod 0444 hdrs/sysdefs.SH || echo "restore of hdrs/sysdefs.SH fails"
echo "x - extracting src/Makefile.SH (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/Makefile.SH &&
Xcase $CONFIG in
X'')
X    if test ! -f config.sh; then
X	ln ../config.sh . || \
X	ln ../../config.sh . || \
X	ln ../../../config.sh . || \
X	(echo "Can't find config.sh."; exit 1)
X    fi
X    . ./config.sh
X    ;;
Xesac
Xcase "$0" in
X*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
Xesac
X
Xecho "Extracting src/Makefile (with variable substitutions)"
Xcat >Makefile <<!GROK!THIS!
X# $Id: Makefile.SH,v 2.15 89/03/25 21:45:38 syd Exp $
X#
X#  Makefile for the ELM mail program.
X#
X#	Copyright (c) 1986, 1987 Dave Taylor
X#	Copyright (c) 1988, 1989 USENET Community Trust
X#
X# Bug reports, patches, comments, suggestions should be sent to:
X#
X#	Syd Weinstein - elm@dsinc.UUCP
X#			dsinc!elm
X#
X# $Log:	Makefile.SH,v $
X# Revision 2.15  89/03/25  21:45:38  syd
X# Initial 2.2 Release checkin
X# 
X#
X# Variables
X#	Variables established by Configure
XCC		=	$cc
XCCFLAGS		=	$ccflags $xencf
XCHGRP		=	$chgrp
XCHMOD		=	$chmod
XCP		=	$cp
XDEST		=	$bin
XECHO		=	$echo
XLFLAGS		=	$ldflags $xenlf
XLIB		=	$lib
XLIB2		= 	$libs
XLIBS		=	$cryptlib $termlib $dbm
XLINT		=	$lint
XMAILGRP		=	$mailgrp
XMAILERMODE	=	$mailermode
XMV		=	$mv
XOPTIMIZE	=	$optimize
XRM		= 	$rm -f
XTOUCH		=	$touch
X
X!GROK!THIS!
X
Xcat >>Makefile <<'!NO!SUBS!'
X
X#	Variables you may want to manually edit
X#		If you want debug logging then you'll
X#		want to uncomment the following.
X#DEBUG		=	-DDEBUG
X
X#		If you're on an ACSnet system (Australia) then
X#		you'll want to uncomment the following.
X# DACSNET	=	-DACSNET
X
X#	Other general variables
XBIN		=	../bin
XCFLAGS		=	$(CCFLAGS) $(OPTIMIZE) -I$(INCLDIR) $(DEBUG) $(DACSNET) 
XINCLDIR		=	../hdrs
XLINTFLAGS	=	-I$(INCLDIR)
XSHELL		=	/bin/sh
X
X# 	Lists
XELM_SRC		=	addr_util.c	\
X			alias.c		\
X			aliasdb.c	\
X			aliaslib.c	\
X			args.c		\
X			bouncebk.c	\
X			builtin.c	\
X			calendar.c	\
X			conn_to.c	\
X			curses.c	\
X			date.c		\
X			delete.c	\
X			domains.c	\
X			edit.c		\
X			editmsg.c	\
X			elm.c		\
X			encode.c	\
X			errno.c		\
X			expires.c	\
X			file.c		\
X			file_util.c	\
X			fileio.c	\
X			forms.c		\
X			hdrconfg.c	\
X			help.c		\
X			init.c		\
X			in_utils.c	\
X			leavembox.c	\
X			limit.c		\
X			mailmsg1.c	\
X			mailmsg2.c	\
X			mailtime.c	\
X			mkhdrs.c	\
X			newmbox.c	\
X			opt_utils.c	\
X			options.c	\
X			out_utils.c	\
X			pattern.c	\
X			pmalloc.c	\
X			quit.c		\
X			read_rc.c	\
X			remail.c	\
X			reply.c		\
X			returnadd.c	\
X			save_opts.c	\
X			savecopy.c	\
X			screen.c	\
X			showmsg.c	\
X			showmsg_c.c	\
X			signals.c	\
X			softkeys.c	\
X			sort.c		\
X			string2.c	\
X			strings.c	\
X			syscall.c	\
X			utils.c		\
X			validname.c
X
XELM_OBJ		=	addr_util.o	\
X			alias.o		\
X			aliasdb.o	\
X			aliaslib.o	\
X			args.o		\
X			bouncebk.o	\
X			builtin.o	\
X			calendar.o	\
X			conn_to.o	\
X			curses.o	\
X			date.o		\
X			delete.o	\
X			domains.o	\
X			edit.o		\
X			editmsg.o	\
X			elm.o		\
X			encode.o	\
X			errno.o		\
X			expires.o	\
X			file.o		\
X			file_util.o	\
X			fileio.o	\
X			forms.o		\
X			hdrconfg.o	\
X			help.o		\
X			init.o		\
X			in_utils.o	\
X			leavembox.o	\
X			limit.o		\
X			mailmsg1.o	\
X			mailmsg2.o	\
X			mailtime.o	\
X			mkhdrs.o	\
X			newmbox.o	\
X			opt_utils.o	\
X			options.o	\
X			out_utils.o	\
X			pattern.o	\
X			pmalloc.o	\
X			quit.o		\
X			read_rc.o	\
X			remail.o	\
X			reply.o		\
X			returnadd.o	\
X			save_opts.o	\
X			savecopy.o	\
X			screen.o	\
X			showmsg.o	\
X			showmsg_c.o	\
X			signals.o	\
X			softkeys.o	\
X			sort.o		\
X			string2.o	\
X			strings.o	\
X			syscall.o	\
X			utils.o		\
X			validname.o
X
X# Standard targets
Xall:		$(BIN)/elm
X
Xinstall:	$(DEST)/elm
X
Xuninstall:	
X		$(RM) $(DEST)/elm
X
X#	This is the only target that gets installed even if not out-of-date
X#	with respect the files from which it is installed.
Xrmt-install:	rmt-defined
X		-$(MV) $(DEST)/elm $(DEST)/elm.old
X		-$(RM) $(DEST)/elm.old
X		$(CP) $(REMOTE)$(DEST)/elm $(DEST)/elm
X		$(CHGRP) $(MAILGRP) $(DEST)/elm
X		$(CHMOD) $(MAILERMODE) $(DEST)/elm
X
Xrmt-defined:
X	@(if [ "$(REMOTE)" = "" ];\
X	  then\
X	    $(ECHO) "You need to define 'REMOTE' as the remote file system";\
X	    $(ECHO) "for this particular command. The easiest way to do this";\
X	    $(ECHO) "to type:";\
X	    $(ECHO) "        make REMOTE=<remote file system> rmt-install";\
X	    exit 1;\
X	fi);
X
Xlint:		
X		$(LINT) $(LINTFLAGS) $(ELM_SRC) > LINT.OUT
X
Xclean:		
X		$(RM) $(ELM_OBJ) $(BIN)/elm
X
X# Dependencies and rules
X#	Dependencies of header files upon other header files they include
X$(INCLDIR)/defs.h:	$(INCLDIR)/../config.h $(INCLDIR)/sysdefs.h
X			$(CHMOD) u+w $@
X			$(TOUCH) $@
X
X$(INCLDIR)/elm.h:	$(INCLDIR)/curses.h $(INCLDIR)/defs.h
X			$(CHMOD) u+w $@
X			$(TOUCH) $@
X
X$(INCLDIR)/headers.h:	$(INCLDIR)/curses.h $(INCLDIR)/defs.h
X			$(CHMOD) u+w $@
X			$(TOUCH) $@
X
X#	Dependencies of C object files
Xaddr_util.o:	$(INCLDIR)/headers.h
Xalias.o:	$(INCLDIR)/headers.h
Xaliasdb.o:	$(INCLDIR)/headers.h
Xaliaslib.o:	$(INCLDIR)/headers.h
Xargs.o:		$(INCLDIR)/headers.h
Xbouncebk.o:	$(INCLDIR)/headers.h
Xbuiltin.o:	$(INCLDIR)/headers.h
Xcalendar.o:	$(INCLDIR)/headers.h
Xconn_to.o:	$(INCLDIR)/headers.h
Xcurses.o:	$(INCLDIR)/headers.h
Xdate.o:		$(INCLDIR)/headers.h
Xdelete.o:	$(INCLDIR)/headers.h
Xdomains.o:	$(INCLDIR)/headers.h
Xedit.o:		$(INCLDIR)/headers.h
Xeditmsg.o:	$(INCLDIR)/headers.h
Xelm.o:		$(INCLDIR)/elm.h
Xencode.o:	$(INCLDIR)/headers.h
Xerrno.o:	$(INCLDIR)/headers.h
Xexpires.o:	$(INCLDIR)/headers.h
Xfile.o:		$(INCLDIR)/headers.h
Xfile_util.o:	$(INCLDIR)/headers.h
Xfileio.o:	$(INCLDIR)/headers.h
Xforms.o:	$(INCLDIR)/headers.h
Xhdrconfg.o:	$(INCLDIR)/headers.h
Xhelp.o:		$(INCLDIR)/headers.h
Xin_utils.o:	$(INCLDIR)/headers.h
Xinit.o:		$(INCLDIR)/headers.h $(INCLDIR)/patchlevel.h
Xleavembox.o:	$(INCLDIR)/headers.h
Xlimit.o:	$(INCLDIR)/headers.h
Xmailmsg1.o:	$(INCLDIR)/headers.h
Xmailmsg2.o:	$(INCLDIR)/headers.h
Xmailtime.o:	$(INCLDIR)/headers.h
Xmkhdrs.o:	$(INCLDIR)/headers.h
Xnewmbox.o:	$(INCLDIR)/headers.h
Xopt_utils.o:	$(INCLDIR)/headers.h
Xoptions.o:	$(INCLDIR)/headers.h
Xout_utils.o:	$(INCLDIR)/headers.h
Xpattern.o:	$(INCLDIR)/headers.h
Xpmalloc.o:	$(INCLDIR)/defs.h
Xquit.o:		$(INCLDIR)/headers.h
Xread_rc.o:	$(INCLDIR)/headers.h
Xremail.o:	$(INCLDIR)/headers.h
Xreply.o:	$(INCLDIR)/headers.h
Xreturnadd.o:	$(INCLDIR)/headers.h
Xsave_opts.o:	$(INCLDIR)/save_opts.h $(INCLDIR)/headers.h
Xsavecopy.o:	$(INCLDIR)/headers.h
Xscreen.o:	$(INCLDIR)/headers.h
Xshowmsg.o:	$(INCLDIR)/headers.h
Xshowmsg_c.o:	$(INCLDIR)/headers.h
Xsignals.o:	$(INCLDIR)/headers.h
Xsoftkeys.o:	$(INCLDIR)/headers.h
Xsort.o:		$(INCLDIR)/headers.h
Xstrings.o:	$(INCLDIR)/headers.h
Xsyscall.o:	$(INCLDIR)/headers.h
Xutils.o:	$(INCLDIR)/headers.h
Xvalidname.o:	$(INCLDIR)/defs.h
X
X#	Dependencies and rules for compiling C programs
X$(BIN)/elm:	$& $(ELM_OBJ)
X		$(CC) $(LFLAGS) -o $@ $(ELM_OBJ) $(LIBS) $(LIB2)
X
X#	Dependencies and rules for installing C programs
X$(DEST)/elm:	$(BIN)/elm
X		-$(MV) $@ $@.old
X		-$(RM) $@.old
X		$(CP) $(BIN)/elm $@
X		$(CHGRP) $(MAILGRP) $@
X		$(CHMOD) $(MAILERMODE) $@
X
X!NO!SUBS!
SHAR_EOF
chmod 0444 src/Makefile.SH || echo "restore of src/Makefile.SH fails"
echo "x - extracting src/addr_util.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/addr_util.c &&
X
Xstatic char rcsid[] = "@(#)$Id: addr_util.c,v 2.15 89/03/25 21:45:40 syd Exp $";
X
X/*******************************************************************************
X *  The Elm Mail System  -  $Revision: 2.15 $   $State: Exp $
X *
X * 			Copyright (c) 1986, 1987 Dave Taylor
X * 			Copyright (c) 1988, 1989 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X *	Syd Weinstein, Elm Coordinator
X *	elm@dsinc.UUCP			dsinc!elm
X *
X *******************************************************************************
X * $Log:	addr_util.c,v $
X * Revision 2.15  89/03/25  21:45:40  syd
X * Initial 2.2 Release checkin
X * 
X *
X ******************************************************************************/
X
X/** This file contains addressing utilities 
X
X**/
X
X#include "headers.h"
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#ifdef PWDINSYS
X#  include <sys/pwd.h>
X#else
X#  include <pwd.h>
X#endif
X
X#include <ctype.h>
X
X#ifdef BSD 
X#undef tolower
X#undef toupper
X#endif
X
Xchar *shift_lower(), *get_alias_address(), *get_token(), *strtok(),
X     *strchr(), *strcpy(), *strcat(), *strncpy();
X
Xchar *
Xgcos_name(gcos_field, logname)
Xchar *logname, *gcos_field;
X{
X    /** Return the full name found in a passwd file gcos field **/
X
X#ifdef BERKNAMES
X
X    static char fullname[SLEN];
X    register char *fncp, *gcoscp, *lncp, *end;
X
X
X    /* full name is all chars up to first ',' (or whole gcos, if no ',') */
X    /* replace any & with logname in upper case */
X
X    for(fncp = fullname, gcoscp= gcos_field, end = fullname + SLEN - 1;
X        (*gcoscp != ',' && *gcoscp != '\0' && fncp != end);
X	gcoscp++) {
X
X	if(*gcoscp == '&') {
X	    for(lncp = logname; *lncp; fncp++, lncp++)
X		*fncp = toupper(*lncp);
X	} else {
X	    *fncp++ = *gcoscp;
X	}
X    }
X    
X    *fncp = '\0';
X    return(fullname);
X#else
X#ifdef USGNAMES
X
X    char *firstcp, *lastcp;
X
X    /* The last character of the full name is the one preceding the first
X     * '('. If there is no '(', then the full name ends at the end of the
X     * gcos field.
X     */
X    if(lastcp = strchr(gcos_field, '('))
X	*lastcp = '\0';
X
X    /* The first character of the full name is the one following the 
X     * last '-' before that ending character. NOTE: that's why we
X     * establish the ending character first!
X     * If there is no '-' before the ending character, then the fullname
X     * begins at the beginning of the gcos field.
X     */
X    if(firstcp = strrchr(gcos_field, '-'))
X	firstcp++;
X    else
X	firstcp = gcos_field;
X
X    return(firstcp);
X
X#else
X    /* use full gcos field */
X    return(gcos_field);
X#endif
X#endif
X}
X	    
Xchar *
Xget_full_name(logname)
Xchar *logname;
X{
X	/* return a pointer to the full user name for the passed logname
X	 * or NULL if cannot be found
X	 * If PASSNAMES get it from the gcos field, otherwise get it
X	 * from ~/.fullname.
X	 */
X
X	FILE *fp;
X	static char fullname[SLEN];
X	char fullnamefile[SLEN];
X	struct passwd *getpwnam(), *pass;
X
X	if((pass = getpwnam(logname)) == NULL)
X	  return(NULL);
X#ifdef PASSNAMES	/* get full_username from gcos field */
X	strcpy(fullname, gcos_name(pass->pw_gecos, logname));
X#else			/* get full_username from ~/.fullname file */
X	sprintf(fullnamefile, "%s/.fullname", pass->pw_dir);
X
X	if(can_access(fullnamefile, READ_ACCESS) != 0)
X	  return(NULL);		/* fullname file not accessible to user */
X	if((fp = fopen(fullnamefile, "r")) == NULL)
X	  return(NULL);		/* fullname file cannot be opened! */
X	if(fgets(fullname, SLEN, fp) == NULL) {
X	  fclose(fp);
X	  return(NULL);		/* fullname file empty! */
X	}
X	fclose(fp);
X	no_ret(fullname);	/* remove trailing '\n' */
X#endif
X	return(fullname);
X}
X
Xint
Xtalk_to(sitename)
Xchar *sitename;
X{
X	/** If we talk to the specified site, return true, else
X	    we're going to have to expand this baby out, so 
X	    return false! **/
X
X	struct lsys_rec  *sysname;
X
X	sysname = talk_to_sys;
X
X	if (sysname == NULL) {
X	 dprint(2, (debugfile, 
X		"Warning: talk_to_sys is currently set to NULL!\n"));
X	 return(0);
X	}
X
X	while (sysname != NULL) {
X	  if (strcmp(sysname->name, sitename) == 0)
X	    return(1);
X	  else
X	    sysname = sysname->next;
X	}
X
X	return(0);
X}
X
Xadd_site(buffer, site, lastsite)
Xchar *buffer, *site, *lastsite;
X{
X	/** add site to buffer, unless site is 'uucp', current machine, or
X            site is the same as lastsite.   If not, set lastsite to
X            site.
X	**/
X
X	char local_buffer[SLEN];
X	char *strip_parens();
X
X	if (strcmp(site, "uucp") != 0)
X	  if (strcmp(site, lastsite) != 0) 
X	    if (strcmp(site, hostname) != 0) {
X	      if (buffer[0] == '\0')
X	        strcpy(buffer, strip_parens(site));         /* first in list! */
X	      else {
X	        sprintf(local_buffer,"%s!%s", buffer, strip_parens(site));
X	        strcpy(buffer, local_buffer);
X	      }
X	      strcpy(lastsite, strip_parens(site)); /* don't want THIS twice! */
X	    }
X}
X
X#ifdef USE_EMBEDDED_ADDRESSES
X
Xget_address_from(prefix, line, buffer)
Xchar *prefix, *line, *buffer;
X{
X	/** This routine extracts the address from either a 'From:' line
X	    or a 'Reply-To:' line...the algorithm is quite simple, too:
X	    increment 'line' past header, then check last character of 
X	    line.  If it's a '>' then the address is contained within '<>'
X	    and if it's a ')' then the address is in the 'clear'... **/
X
X	register int i, j = 0;
X	
X	no_ret(line);
X
X	line = (char *) (line + strlen(prefix) + 1);
X
X	if (line[strlen(line)-1] == '>') {
X	  for (i=strlen(line)-2; i > -1 && line[i] != '<'; i--)
X	    buffer[j++] = line[i];
X	  buffer[j] = 0;
X	  reverse(buffer);
X	}
X	else {	/* either ')' or address in the clear... */
X	  for (i=0; i < strlen(line) && line[i] != '('; i++)
X	    buffer[j++] = line[i];
X	  if (buffer[j-1] == '(') j--;
X	  buffer[j] = 0;
X	}
X}
X
X#endif
X
Xtranslate_return(addr, ret_addr)
Xchar *addr, *ret_addr;
X{
X	/** Return ret_addr to be the same as addr, but with the login 
X            of the person sending the message replaced by '%s' for 
X            future processing... 
X	    Fixed to make "%xx" "%%xx" (dumb 'C' system!) 
X	**/
X
X	register int loc, loc2, iindex = 0;
X	
X	loc2 = chloc(addr,'@');
X	if ((loc = chloc(addr, '%')) < loc2)
X	  loc2 = loc;
X
X	if (loc2 != -1) {	/* ARPA address. */
X	  /* algorithm is to get to '@' sign and move backwards until
X	     we've hit the beginning of the word or another metachar.
X	  */
X	  for (loc = loc2 - 1; loc > -1 && addr[loc] != '!'; loc--)
X	     ;
X	}
X	else {			/* usenet address */
X	  /* simple algorithm - find last '!' */
X
X	  loc2 = strlen(addr);	/* need it anyway! */
X
X	  for (loc = loc2; loc > -1 && addr[loc] != '!'; loc--)
X	      ;
X	}
X	
X	/** now copy up to 'loc' into destination... **/
X
X	while (iindex <= loc) {
X	  ret_addr[iindex] = addr[iindex];
X	  iindex++;
X	}
X
X	/** now append the '%s'... **/
X
X	ret_addr[iindex++] = '%';
X	ret_addr[iindex++] = 's';
X
X	/** and, finally, if anything left, add that **/
X
X	while (loc2 < strlen(addr)) {
X	  ret_addr[iindex++] = addr[loc2++];
X	  if (addr[loc2-1] == '%')	/* tweak for "printf" */
X	    ret_addr[iindex++] = '%';
X	}
X	
X	ret_addr[iindex] = '\0';
X}
X
Xint
Xbuild_address(to, full_to)
Xchar *to, *full_to;
X{
X	/** loop on all words in 'to' line...append to full_to as
X	    we go along, until done or length > len.  Modified to
X	    know that stuff in parens are comments...Returns non-zero
X	    if it changed the information as it copied it across...
X	**/
X
X	register int i, j, changed = 0, in_parens = 0, expanded_information = 0;
X	char word[SLEN], next_word[SLEN], *ptr, buffer[SLEN];
X	char new_to_list[SLEN];
X	char *strpbrk(), *expand_system(), *strcat(), *gecos;
X
X	new_to_list[0] = '\0';
X
X	i = get_word(to, 0, word);
X
X	full_to[0] = '\0';
X
X	while (i > 0) {
X
X	  j = get_word(to, i, next_word);
X
Xtry_new_word:
X	  if(word[0] == '(')
X	    in_parens++;
X
X	  if (in_parens) {
X	    if(word[strlen(word)-1] == ')')
X	      in_parens--;
X	    strcat(full_to, " ");
X	    strcat(full_to, word);
X	  }
X	  else if (strpbrk(word,"!@:") != NULL) {
X#ifdef DONT_TOUCH_ADDRESSES
X	    sprintf(full_to, "%s%s%s", full_to,
X                    full_to[0] != '\0'? ", " : "", word);
X#else
X	    sprintf(full_to, "%s%s%s", full_to,
X                    full_to[0] != '\0'? ", " : "", expand_system(word, 1));
X#endif
X	  }
X	  else if ((ptr = get_alias_address(word, 1, 0)) != NULL) {
X	    sprintf(full_to, "%s%s%s", full_to, 
X                    full_to[0] != '\0'? ", " : "", ptr);
X	    expanded_information++;
X	  }
X	  else if (strlen(word) > 0) {
X	    if (valid_name(word)) {
X	      if (j > 0 && next_word[0] == '(')	/* already has full name */
X		gecos = NULL;
X	      else				/* needs a full name */
X		gecos=get_full_name(word);
X#ifdef USE_DOMAIN
X	      sprintf(full_to, "%s%s%s@%s%s%s%s%s",
X		      full_to,
X		      (full_to[0] != '\0'? ", " : ""),
X		      word,
X		      hostname,
X		      hostdomain,
X		      (gecos ? " (" : ""),
X		      (gecos ? gecos : ""),
X		      (gecos ? ")" : ""));
X#else
X	      sprintf(full_to, "%s%s%s%s%s%s",
X		      full_to,
X		      (full_to[0] != '\0'? ", " : ""),
X		      word,
X		      (gecos ? " (" : ""),
X		      (gecos ? gecos : ""),
X		      (gecos ? ")" : ""));
X#endif
X	    } else if (check_only) {
X	      printf("(alias \"%s\" is unknown)\n\r", word);
X	      changed++;
X	    }
X	    else if (! isatty(fileno(stdin)) ) {	/* batch mode error! */
X	      fprintf(stderr,"Cannot expand alias '%s'!\n\r", word);
X	      fprintf(stderr,"Use \"checkalias\" to find valid addresses!\n\r");
X	      dprint(1, (debugfile,
X		      "Can't expand alias %s - bailing out of build_address\n", 
X		      word));
X	      leave(0);
X	    }
X	    else {
X	      dprint(2,(debugfile,"Entered unknown address %s\n", word));
X	      sprintf(buffer, "'%s' is an unknown address.  Replace with: ", 
X	              word);
X	      word[0] = '\0';
X	      changed++;
X
X	      PutLine0(LINES, 0, buffer);
X		
X	      (void)optionally_enter(word, LINES, strlen(buffer), FALSE, FALSE);
X	      clear_error();
X	      if (strlen(word) > 0) {
X	        dprint(3,(debugfile, "Replaced with %s in build_address\n", 
X			 word));
X		goto try_new_word;
X	      }
X	      else
X		dprint(3,(debugfile, 
X		    "Address removed from TO list by build_address\n"));
X	      continue;
X	    }
X	  }
X
X	  /* and this word to the new to list */
X	  if(*new_to_list != '\0')
X	    strcat(new_to_list, " ");
X	  strcat(new_to_list, word);
X
X	  if((i = j) > 0)
X	    strcpy(word, next_word);
X	}
X
X	/* if new to list is different from original, update original */
X	if (changed)
X	  strcpy(to, new_to_list);
X
X	return( expanded_information > 0 ? 1 : 0 );
X}
X
Xint
Xreal_from(buffer, entry)
Xchar *buffer;
Xstruct header_rec *entry;
X{
X	/***** Returns true iff 's' has the seven 'from' fields, (or
X	       8 - some machines include the TIME ZONE!!!)
X	       Initialize the date and from entries in the record 
X	       and also the message received date/time if 'entry'
X	       is not NULL.  *****/
X
X	struct header_rec temp_rec, *rec_ptr;
X	char junk[STRING], timebuff[STRING], holding_from[SLEN];
X	int  eight_fields = 0;
X
X	/* set rec_ptr according to whether the data is to be returned
X	 * in the second argument */
X	rec_ptr = (entry == NULL ? &temp_rec : entry);
X
X	rec_ptr->year[0] = '\0';
X	timebuff[0] = '\0';
X	junk[0] = '\0';
X
X	/* From <user> <day> <month> <day> <hr:min:sec> <year> */
X
X	sscanf(buffer, "%*s %*s %*s %*s %*s %s %*s %s", timebuff, junk);
X
X	if (strlen(timebuff) < 3) {
X	  dprint(3,(debugfile, 
X		"Real_from returns FAIL [no time field] on\n-> %s\n", 
X		buffer));
X	  return(FALSE);
X	}
X
X	if (timebuff[1] != ':' && timebuff[2] != ':') { 
X	  dprint(3,(debugfile, 
X		"Real_from returns FAIL [bad time field] on\n-> %s\n", 
X		buffer));
X	  return(FALSE);
X	}
X	if (junk[0] != '\0') {	/* try for 8 field entry */
X	  junk[0] = '\0';
X	  sscanf(buffer, "%*s %*s %*s %*s %*s %s %*s %*s %s", timebuff, junk);
X	  if (junk[0] != '\0') {
X	    dprint(3, (debugfile, 
X		  "Real_from returns FAIL [too many fields] on\n-> %s\n", 
X		  buffer));
X	    return(FALSE);
X	  }
X	  eight_fields++;
X	}
X
X	/** now get the info out of the record! **/
X
X	if (eight_fields) 
X	  sscanf(buffer, "%s %s %s %s %s %s %*s %s",
X	            junk, holding_from, rec_ptr->dayname, rec_ptr->month, 
X                    rec_ptr->day, rec_ptr->time, rec_ptr->year);
X	else
X	  sscanf(buffer, "%s %s %s %s %s %s %s",
X	            junk, holding_from, rec_ptr->dayname, rec_ptr->month, 
X                    rec_ptr->day, rec_ptr->time, rec_ptr->year);
X	
X	strncpy(rec_ptr->from, holding_from, STRING-1);
X	rec_ptr->from[STRING-1] = '\0';
X	resolve_received(rec_ptr);
X	return(rec_ptr->year[0] != '\0');
X}
X
Xforwarded(buffer, entry)
Xchar *buffer;
Xstruct header_rec *entry;
X{
X	/** Change 'from' and date fields to reflect the ORIGINATOR of 
X	    the message by iteratively parsing the >From fields... 
X	    Modified to deal with headers that include the time zone
X	    of the originating machine... **/
X
X	char machine[SLEN], buff[SLEN], holding_from[SLEN];
X
X	machine[0] = holding_from[0] = '\0';
X
X	sscanf(buffer, "%*s %s %s %s %s %s %s %*s %*s %s",
X	            holding_from, entry->dayname, entry->month, 
X                    entry->day, entry->time, entry->year, machine);
X
X	if (isdigit(entry->month[0])) { /* try for veeger address */
X	  sscanf(buffer, "%*s %s %s%*c %s %s %s %s %*s %*s %s",
X	            holding_from, entry->dayname, entry->day, entry->month, 
X                    entry->year, entry->time, machine);
X	}
X	if (isalpha(entry->year[0])) { /* try for address including tz */
X	  sscanf(buffer, "%*s %s %s %s %s %s %*s %s %*s %*s %s",
X	            holding_from, entry->dayname, entry->month, 
X                    entry->day, entry->time, entry->year, machine);
X	}
X
X	/* the following fix is to deal with ">From xyz ... forwarded by xyz"
X	   which occasionally shows up within AT&T.  Thanks to Bill Carpenter
X	   for the fix! */
X
X	if (strcmp(machine, holding_from) == 0)
X	  machine[0] = '\0';
X
X	if (machine[0] == '\0')
X	  strcpy(buff, holding_from[0] ? holding_from : "anonymous");
X	else
X	  sprintf(buff,"%s!%s", machine, holding_from);
X
X	strncpy(entry->from, buff, STRING-1);
X	entry->from[STRING-1] = '\0';
X}
X
Xparse_arpa_who(buffer, newfrom, is_really_a_to)
Xchar *buffer, *newfrom;
Xint is_really_a_to;
X{
X	/** try to parse the 'From:' line given... It can be in one of
X	    two formats:
X		From: Dave Taylor <hplabs!dat>
X	    or  From: hplabs!dat (Dave Taylor)
X
X	    Added: removes quotes if name is quoted (12/12)
X	    Added: only copies STRING characters...
X	    Added: if no comment part, copy address instead! 
X	    Added: if is_really_a_to, this is really a 'to' line
X		   and treat as if we allow embedded addresses
X	**/
X
X	int use_embedded_addresses;
X	char temp_buffer[SLEN], *temp;
X	register int i, j = 0, in_parens;
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	  in_parens = 1;
X	  for (i=strlen(buffer)-2; buffer[i] != '\0' && buffer[i] != '<'; i--) {
X	    switch(buffer[i]) {
X	    case ')':	in_parens++;
X			break;
X	    case '(':	in_parens--;
X			break;
X	    }
X	    if(!in_parens) break;
X	    temp[j++] = buffer[i];
X	  }
X	  temp[j] = '\0';
X	  reverse(temp);
X	}
X
X#ifdef USE_EMBEDDED_ADDRESSES
X	use_embedded_addresses = TRUE;
X#else
X	use_embedded_addresses = FALSE;
X#endif
X
X	if(use_embedded_addresses || is_really_a_to) {
X	  /** if we have a null string at this point, we must just have a 
X	      From: line that contains an address only.  At this point we
X	      can have one of a few possibilities...
X
X		  From: address
X		  From: <address>
X		  From: address ()
X	  **/
X	    
X	  if (strlen(temp) == 0) {
X	    if (lastch(buffer) != '>') {       
X	      for (i=strlen("From:");buffer[i] != '\0' && buffer[i] != '('; i++)
X		temp[j++] = buffer[i];
X	      temp[j] = '\0';
X	    }
X	    else {	/* get outta '<>' pair, please! */
X	      for (i=strlen(buffer)-2;buffer[i] != '<' && buffer[i] != ':';i--)
X		temp[j++] = buffer[i];
X	      temp[j] = '\0';
X	      reverse(temp);
X	    }
X	  }
X	}
X	  
X	if (strlen(temp) > 0) {		/* mess with buffer... */
X
X	  /* remove leading spaces and quotes... */
X
X	  while (whitespace(temp[0]) || quote(temp[0]))
X	    temp = (char *) (temp + 1);		/* increment address! */
X
X	  /* remove trailing spaces and quotes... */
X
X	  i = strlen(temp) - 1;
X
X	  while (whitespace(temp[i]) || quote(temp[i]))
X	   temp[i--] = '\0';
X
X	  /* if anything is left, let's change 'from' value! */
X
X	  if (strlen(temp) > 0) {
X	    strncpy(newfrom, temp, STRING-1);
X	    newfrom[STRING-1] = '\0';
X	  }
X	}
X}
X
Xparse_arpa_date(string, entry)
Xchar *string;
Xstruct header_rec *entry;
X{
X	/** Parse and figure out the given date format... return
X	    the entry fields changed iff it turns out we have a
X	    valid parse of the date!  **/
X
X	char word[15][WLEN], buffer[SLEN], *bufptr;
X	char *aword;
X	int  words = 0;
X
X	strcpy(buffer, string);
X	bufptr = (char *) buffer;
X
X	/** break the line down into words... **/
X
X	while ((aword = strtok(bufptr," \t '\"-/(),.")) != NULL) {
X	  strcpy(word[words++], aword);
X	  bufptr = NULL;
X	}
X
X	if (words < 6) {	/* strange format.  We're outta here! */
X	  dprint(3,(debugfile, 
X		"Parse_arpa_date failed [less than six fields] on\n-> %s\n",
X		string));
X	  return;
X	}
X
X	/* There are now five possible combinations that we could have:
X	 
X	    Date: day_number month_name year_number time timezone
X	    Date: day_name day_number month_name year_number ...
X	    Date: day_name month_name day_number time year_number
X	    Date: day_name month_name day_number year_number time
X	    Date: day_number month_name year_number time timezone day_name
X
X	   Note that they are distinguishable by checking the first
X	   character of the second, third and fourth words... 
X	*/
X
X	if (isdigit(word[1][0])) {			/*** type one! ***/
X	  if (! valid_date(word[1], word[2], word[3])) {
X	    dprint(3,(debugfile, 
X		  "parse_arpa_date failed [bad date: %s/%s/%s] on\n-> %s\n",
X		  word[1], word[2], word[3], string));
X	    return;		/* strange date! */
X	  }
X	  strncpy(entry->day, word[1], 2);
X	  entry->day[2] = '\0';
X	  strncpy(entry->month, word[2], 3);
X	  entry->month[3] = '\0';
X	  strncpy(entry->year,  word[3], 4);
X	  entry->year[4] = '\0';
X	  strncpy(entry->time,  word[4], 10);
X	  entry->time[10] = '\0';
X	}
X	else if (isdigit(word[2][0])) {		        /*** type two! ***/
X	  if (! valid_date(word[2], word[3], word[4])) {
X	    dprint(3,(debugfile,
X		  "parse_arpa_date failed [bad date: %s/%s/%s] on\n-> %s\n",
X		  word[2], word[3], word[4], string));
X	    return;		/* strange date! */
X	  }
X	  strncpy(entry->day, word[2], 2);
X	  entry->day[2] = '\0';
X	  strncpy(entry->month, word[3], 3);
X	  entry->month[3] = '\0';
X	  strncpy(entry->year,  word[4], 4);
X	  entry->year[4] = '\0';
X	  strncpy(entry->time,  word[5], 10);
X	  entry->time[10] = '\0';
X	}
X	else if (isdigit(word[3][0])) {		
X	  if (word[4][1] == ':' || 
X              word[4][2] == ':') {	               /*** type three! ***/
X	    if (! valid_date(word[3], word[2], word[5])) {
X	     dprint(3, (debugfile,
X		"parse_arpa_date failed [bad date: %s/%s/%s] on\n-> %s\n",
X		    word[3], word[2], word[5], string));
X	      return;		/* strange date! */
X	    }
X	    strncpy(entry->year,  word[5], 4);
X	    entry->year[4] = '\0';
X	    strncpy(entry->time,  word[4], 10);
X	    entry->time[10] = '\0';
X	  }
X	  else {				       /*** type four!  ***/ 
X	    if (! valid_date(word[3], word[2], word[4])) {
X	     dprint(3,(debugfile,
X		    "parse_arpa_date failed [bad date: %s/%s/%s] on\n-> %s\n",
X		    word[3], word[2], word[4], string));
X	      return;		/* strange date! */
X	    }
X	    strncpy(entry->year,  word[4], 4);
X	    entry->year[4] = '\0';
X	    strncpy(entry->time, word[5], 10);
X	    entry->time[10] = '\0';
X	  }
X	  strncpy(entry->day, word[3], 2);
X	  entry->day[2] = '\0';
X	  strncpy(entry->month, word[2], 3);
X	  entry->month[3] = '\0';
X	}
X
X	/** finally, let's just normalize the monthname to be a three
X	    letter abbreviation, with the first capitalized and the
X	    second and third in lowercase... **/
X
X	shift_lower(entry->month);
X	entry->month[0] = toupper(entry->month[0]);
X}
X
Xfix_arpa_address(address)
Xchar *address;
X{
X	/** Given a pure ARPA address, try to make it reasonable.
X
X	    This means that if you have something of the form a@b@b make 
X            it a@b.  If you have something like a%b%c%b@x make it a%b@x...
X	**/
X
X	register int host_count = 0, i;
X	char     hosts[MAX_HOPS][NLEN];	/* array of machine names */
X	char     *host, *addrptr;
X
X	/*  break down into a list of machine names, checking as we go along */
X	
X	addrptr = (char *) address;
X
X	while ((host = get_token(addrptr, "%@", 2)) != NULL) {
X	  for (i = 0; i < host_count && ! equal(hosts[i], host); i++)
X	      ;
X
X	  if (i == host_count) {
X	    strcpy(hosts[host_count++], host);
X	    if (host_count == MAX_HOPS) {
X	       dprint(2, (debugfile, 
X           "Can't build return address - hit MAX_HOPS in fix_arpa_address\n"));
X	       error("Can't build return address - hit MAX_HOPS limit!");
X	       return(1);
X	    }
X	  }
X	  else 
X	    host_count = i + 1;
X	  addrptr = NULL;
X	}
X
X	/** rebuild the address.. **/
X
X	address[0] = '\0';
X
X	for (i = 0; i < host_count; i++)
X	  sprintf(address, "%s%s%s", address, 
X	          address[0] == '\0'? "" : 
X	 	    (i == host_count - 1 ? "@" : "%"),
X	          hosts[i]);
X
X	return(0);
X}
X
Xfigure_out_addressee(buffer, mail_to)
Xchar *buffer;
Xchar *mail_to;
X{
X	/** This routine steps through all the addresses in the "To:"
X	    list, initially setting it to the first entry (if mail_to
X	    is NULL) or, if the user is found (eg "alternatives") to
X	    the current "username".
X
X	    Modified to know how to read quoted names...
X	    also modified to look for a comma or eol token and then
X	    try to give the maximal useful information when giving the
X	    default "to" entry (e.g. "Dave Taylor <taylor@hpldat>"
X	    will now give "Dave Taylor" rather than just "Dave")
X	**/
X
X	char *address, *bufptr, mybuf[SLEN];
X	register int iindex = 0, index2 = 0;
X	
X	if (equal(mail_to, username)) return;	/* can't be better! */
X
X	bufptr = (char *) buffer;	       /* use the string directly   */
X
X	if (strchr(buffer,'"') != NULL) {	/* we have a quoted string */
X	  while (buffer[iindex] != '"')
X	    iindex++;
X	  iindex++;	/* skip the leading quote */
X	  while (buffer[iindex] != '"' && iindex < strlen(buffer))
X	    mail_to[index2++] = buffer[iindex++];
X	  mail_to[index2] = '\0';
X	}
X
X	else  {
X
X	  while ((address = strtok(bufptr, ",\t\n\r")) != NULL) {
X
X	    if (! okay_address(address, "don't match me!")) {
X	      strcpy(mail_to, username);	/* it's to YOU! */
X	      return;
X	    }
X	    else if (strlen(mail_to) == 0) {	/* it's SOMEthing! */
X	
X	      /** this next bit is kinda gory, but allows us to use the
X		  existing routines to parse the address - by pretending
X		  it's a From: line and going from there...
X	          Ah well - you get what you pay for, right?
X	      **/
X
X	      if (strlen(address) > (sizeof mybuf) - 7)	/* ensure it ain't */
X		address[(sizeof mybuf)-7] = '\0';	/*  too long mon!  */
X
X	      sprintf(mybuf, "From: %s", address);
X	      parse_arpa_who(mybuf, mail_to, TRUE);
SHAR_EOF
echo "End of part 10"
echo "File src/addr_util.c is continued in part 11"
echo "11" > s2_seq_.tmp
exit 0

-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.