[comp.os.minix] Mail for MINIX

ast@cs.vu.nl (Andy Tanenbaum) (10/23/89)

------------------------------- Cut Here -------------------------------
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
#		"End of archive"
# Contents:
#	README        	umail.doc     	umail.cf      	umail         
#	Makefile      	uucp.h        	umail.h       	ummain.c      
#	umtime.c      	umheader.c    	umconvert.c   	umroute.c     
#	umsend.c      	umscanner.c   
#
# Wrapped by root@minixug on Thu Oct 19 22:37:16 1989
#
PATH=/bin:/usr/bin:/usr/local/bin:/usr/ucb:/tmp ; export PATH
if test -f 'README' -a "${1}" != "-c"
then
   echo "$0: Will not overwrite existing file: 'README'"
else
   echo "x - README"
sed 's/^X//' <<\END_OF_SHAR >'README'
X	  U-MAIL Remote Mail Transport Agent (MINIX)
X
X		     MicroWalt U-MAIL V2.5
X		     =====================
X
X
XThis archive contains the sources of the UMAIL Network Mailer
Xfor the MINIX operating system. It runs on most UNIXes as well.
X
XThe file 'umail' is the executable program, and 'umail.doc' is
Xthe (preliminary) documentation of the program.
XSee 'umail.cf' for configuration information.
X
XOf course, this program needs the presence of either UUCP or
XRSMTP to run properly...
X
XEnjoy!
X+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+
X| MINIX User Group (Holland)   UUCP: hp4nl!kyber!minixug!waltje	|
X| c/o Fred van Kempen,		 or: minixug!waltje@kyber.UUCP	|
X| Hoefbladhof  27						|
X| 2215 DV  VOORHOUT						|
X| The Netherlands	"A good programmer knows his Sources"	|
X+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+
X
END_OF_SHAR
fi
if test -f 'umail.doc' -a "${1}" != "-c"
then
   echo "$0: Will not overwrite existing file: 'umail.doc'"
else
   echo "x - umail.doc"
sed 's/^X//' <<\END_OF_SHAR >'umail.doc'
XUMAIL(1)             MINIX User's Manual               UMAIL(1)
X
X
XNAME     
X     umail - electronic mail delivery agent.
X
XSYNOPSIS     
X     umail [-c <config> [-d] [-i <inputfile> [-n] <user>
X
XDESCRIPTION     
X     Umail is a  semi-intelligent  mail transporting  program
X     which  knows something  about Internet adresses and mail
X     adress routing to other systems.
X     It  is  used as  a back-end to  the Mailx program; which
X     is used  to  read or create  messages. Umail  only takes
X     care  of the transportation  of  the  message  to  other
X     MINIX (or UNIX) systems  through  the  available network
X     software like UUCP and RSMTP.
X
X     In  restricted mode ('rmail') it  functions as a message
X     delivery program for incoming network mail.
X     Networking programs like uucico(1)  and rsmtp(8) execute
X     the rmail(1)  command to  deliver a  received message to
X     the adressed user, or to forward  the message to another
X     system.
X
X     The  program  has  some  command-line options, which are
X     used  to alter  the "standard" behaviour of the program.
X     The options are:
X
X	-c <config>	Debug; use 'config' as the configura-
X			tion file  instead  of  the  standard
X			one. This is  sometimes  useful  when
X			debugging the package.
X
X	-d		Debug; generate  some  useful  output
X			while working.
X
X	-i <infile>	Input; use file 'infile' as  the mes-
X			sage file instead of  standard input.
X
X	-n		Now;  call  the  networking  delivery
X			software immediately  after  queueing
X			the message. Not recommended!
X
X     The 'user' string  identifies the  network-adress of the
X     user who is  to receive the message. It can be any legal
X     UUCP or Internet mail-adress.
X
XDELIVERY     
X     The Mailx program can serve as  both a  user agent and a
X     local  delivery  agent. If Mailx sees that the  adressed
X     user is  on the  local system, it  will do  the delivery
X     itself. No  header (except  for From, To and Subject) is
X     added, and  delivery  errors  will  cause the message to
X     be returned to the user as a file 'dead.letter'.
X
X     Otherwise,  if  the  specified  adress is not local, the
X     message  is sent  to  the  Remote Mailer  on the system.
X
X
X
X				-- 1 --
X
X
X
XUMAIL(1)             MINIX User's Manual               UMAIL(1)
X
X
X
X     Usually,  this is  the rmail(1)  command; programs  like
X     sendmail(8)  or  smail(1) (or links to them) are used as
X     well. On  MINIX systems, rmail(1) is a separate program.
X
X     This small remote mailer knows something about UUCP, and
X     how to interpret old-style UUCP (host!user) adresses.
X     This works fine for most users, but it is sometimes nice
X     to have a somewhat more intelligent mailer.
X     Therefore, one could install Umail as a link to rmail(1)
X     so that the mail(1) or Mailx(1) programs will never  see
X     the difference.
X
X     These (more or less)  intelligent mailers add a standard
X     (RFC-822) header to the message, and then send it to the
X     networking software. On MINIX  systems, messages will be
X     transported  using  either  the UUCP networking software
X     (serial lines) or the Amoeba RSMTP (Ethernet) software.
X
X     Because  it would  be too difficult to program all sorts
X     of  networks, system names  and  the lot  in  the mailer
X     software, a file exists which contains the Configuration
X     parameters  of  Umail: the  Config File. This is a plain
X     ASCII text file, containing a mixture  of comments, data
X     and instructions.
X
XAUTHOR     
X     Steve R. Sampson (first draft of rmail program)
X     Fred van Kempen, waltje@kyber.UUCP
X
XFILES     
X     /usr/spool/mail/user   	maildrop file
X     /usr/spool/mail/user.lock  lock for maildrop files
X     /tmp/um*      		temporary file
X     /usr/spool/uucp/*		UUCP networking files
X     /usr/spool/rsmtp/*         SMTP networking files
X     /usr/lib/uucp/umail.cf     configuration file
X
XSEE ALSO    
X     wmail.doc
X
XBUGS     
X     The routing algorithm could be improved a lot.
X     Also, the Config scanner should be more robust.
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X				-- 2 --
X
X
END_OF_SHAR
fi
if test -f 'umail.cf' -a "${1}" != "-c"
then
   echo "$0: Will not overwrite existing file: 'umail.cf'"
else
   echo "x - umail.cf"
sed 's/^X//' <<\END_OF_SHAR >'umail.cf'
X#
X#   MicroWalt Corporation   --  UMAIL Configuration File
X#
X#   System: MINIX User Group Holland, minixug.nluug.nl
X#   OS:     MicroWalt Advanced MINIX 1.4B
X#
X#   Author: F. van Kempen, MicroWalt Corporation
X#
X
X# These are some configuration variables for the
X# mailer. They define the working environment.
XBEGIN
X    Organization    := "MINIX User Group Holland, Netherlands"
X    System          := "minixug"
X    Domain          := "nluug.nl"
X    TimeZone        := "MET +0100"
X    OldMailer       := TRUE	# We want V6 "From <user> <date>" lines
X    Escape          := TRUE	# We can send all undeliverable mail
X				# to another host.
XEND
X
X# The next table defines all the names under which
X# our system could possibly be adressed. It is used
X# to map domain adresses back to local adresses.
XNAMES BEGIN
X    minixug.nluug.nl				# Our official name
X    minixug.nl					# other possible names
X    minixug.uucp                                # old-style UUCP name
X    minixug					# local name
XEND
X
X# This table defines the systems that we know of, and
X# what networking software to use to get to it.
X# 'TRUE' means, that the specified host understands
X# route-adressing (and can thus do things itself).
X# FALSE means that we have to give that host a ready-
X# to-run UUCP adress in bang-style.
XHOSTS BEGIN
X    minixug := TRUE , $$ , "@"                    # Just local mail !
X    kyber   := FALSE , $$ , "@"                   # My UUCP host site
X    archvax := FALSE , "rsmtp" , "<%s archvax!"   # SMTP via Ethernet
XEND
X
X# This is the actual routing table.
X# It defines where mail for the various domains
X# should be sent to. Note, that domain "." is
X# the "default domain", which is used if no
X# matching domain can be found.
X# Format:
X#
X#   DOMAIN	:=  HOST  , ROUTE
X#
XDOMAINS BEGIN
X    aha.nl      :=  kyber , htsa	# Algemene Hogeschool Amsterdam
X    edu         :=  kyber , hp4nl	# Educational Institutes Network
X    nl          :=  kyber , hp4nl	# UUCP-Netherlands
X    nluug       :=  kyber , hp4nl	# Dutch UNIX User Group Network
X    nluug.nl    :=  kyber , hp4nl
X    uu.net      :=  kyber , hp4nl	# USA UUCP Network
X    uucp        :=  kyber , hp4nl	# Old-style UUCP Network
X    uunet       :=  kyber , hp4nl	# USA UUCP Network
X    .           :=  kyber , hp4nl	# Default host
XEND
END_OF_SHAR
fi
if test -f 'umail' -a "${1}" != "-c"
then
   echo "$0: Will not overwrite existing file: 'umail'"
else
if uudecode <<\END_OF_UUTEST 1>/dev/null 2>/dev/null
begin 777 /tmp/unpacker
 
end
END_OF_UUTEST
then
   rm -f /tmp/unpacker
else
   echo "x - uudecode (for non-ascii files)"
   cat <<END_OF_UUDECODE >/tmp/uudecode.c
#include <stdio.h>
#define DEC(c) (((c) - ' ') & 077)
main()
{
   int n, fmode;
   char fname[512], a, b, c, d;

   scanf("begin %o %s", &fmode, fname); getchar();
   if (freopen(fname, "w", stdout) == NULL) {
      perror(fname);
      exit(1);
   }
   while ((n = getchar()) != EOF && (n = DEC(n)) != 0) {
      while (n > 0) {
         a = DEC(getchar());
         b = DEC(getchar());
         c = DEC(getchar());
         d = DEC(getchar());
         if (n-- > 0) putchar (a << 2 | b >> 4);
         if (n-- > 0) putchar (b << 4 | c >> 2);
         if (n-- > 0) putchar (c << 6 | d);
      }
      n = getchar();
   }
   chmod(fname, fmode);
   exit(0);
}
END_OF_UUDECODE
   if cc -o /tmp/uudecode /tmp/uudecode.c 1>/dev/null 2>/dev/null
   then
      rm -f /tmp/uudecode.c
   else
      echo "$0: can't compile uudecode!"
      exit 1
   fi
fi
   echo "x - umail (non-ascii)"
uudecode <<\END_OF_UUENCODED
begin 755 umail
M 0,@!"    !@.P  * X  &(H        "G4       ")XXL/@\,"B<A T> !
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
M(&9L86<  %1)345:3TY%     "5S("5S %-94U1%30  36ES<VEN9R!365-4
M14T@9&5F:6YI=&EO;@H  $1/34%)3@  36ES<VEN9R!$3TU!24X@9&5F:6YI
M=&EO;@H  $]21T%.25I!5$E/3@  3TQ$34%)3$52 $530T%010  57-A9V4Z
M('5M86EL(%LM8R \8V]N9FEG/ET@6RUD72!;+6D@/&EN9FEL93Y=(%LM;ET@
M/'5S97)S/@H +W5S<B]L:6(O=75C<"]U;6%I;"YC9@  8SID:3IN   O=&UP
M+W5M6%A86%A8 '< <FUA:6P@,0!R !\ '  ? !X 'P > !\ 'P > !\ '@ ?
M *8!J@&N ;(!M@&Z ;X!P@'& <H!S@'2 =8!V@'> >(!Y@'J >X!2F%N $9E
M8@!-87( 07!R $UA>0!*=6X 2G5L $%U9P!397  3V-T $YO=@!$96, 4W5N
M $UO;@!4=64 5V5D %1H=0!&<FD 4V%T "5S+" E,BXR9" E<R E,BXR9" E
M,#)D.B4P,F0Z)3 R9    "P",@(X D("2@). E("5@)> FH"  !&4D]-( !&
M4D]-  !214-%259%1   4T5.1$52  !43P  0T,  $)#0P!354)*14-4 $U%
M4U-!1T4M240  $1!5$4  $923TT@ "5S.B!N;R!&<F]M(&QI;F4  ')E;6]T
M92!F<F]M(   )7,A)7,   !&4D]-  !$051%   *"D)A9"!A9')E<W,@;W(@
M:&5A9&5R(0H     )7,Z)7,*   E<PH 1G)O;2 E<R E<R!R96UO=&4@9G)O
M;2 E<PH  $9R;VTZ("5S(25S("@E<RD* %)E8V5I=F5D.B!B>2 E<RXE<R H
M54U!24P@)7,I('=I=&@@555#4#L*(" @(" @(" @("5S"@  4V5N9&5R.B E
M<R H)7,I"@  3W)G86YI>F%T:6]N.B E<PH 5$\  %1O.B E<PH 4U5"2D5#
M5 !3=6)J96-T.B E<PH  $1A=&4Z("5S"@ * "5S.B E<PH )7,* $923TT@
M $9R;VT@)7,@)7,@<F5M;W1E(&9R;VT@)7,*  !&<F]M("5S(25S("5S(')E
M;6]T92!F<F]M("5S"@!&4D]-   E<SH@)7,A)7,*   E<SH@)7,* %)E8V5I
M=F5D.B!B>2 E<RXE<R H54U!24P@)7,I('=I=&@@555#4#L*(" @(" @(" @
M("5S"@  4D5#14E6140  %-%3D1%4@  5$\  $-#  !"0T, 4U5"2D5#5 !-
M15-304=%+4E$  !$051%  !$871E.B    H 1G)O;2  1G)O;2  )7,N)7, 
M)7,N)7, )7,@+BXN(&1O;6%I;B!U;FMN;W=N "X )7,@+BXN(&1O;6%I;B!U
M;FMN;W=N  H*15-#05!%(&1O;6%I;B!N;W0@9F]U;F0N   E<R N+BX@:&]S
M="!U;G)E86-H96)L90 E<T E<P E<T E<P E<R$E<T E<P  )7,A)7- )7,N
M)7, )7,A)7, )7,A)7,A)7,  "5S("XN+B!H;W-T('5N:VYO=VX +@ E<R N
M+BX@:&]S="!U;FMN;W=N  H*15-#05!%(&1O;6%I;B!N;W0@9F]U;F0N   E
M<R N+BX@:&]S="!U;G)E86-H96)L90 E<T E<P E<R$E<P E<R N+BX@=7-E
M<B!U;FMN;W=N "]U<W(O;&EB+W5U8W O4U!/3TQ315$  "]U<W(O;&EB+W5U
M8W O4U!/3TQ315$N3$-+  !R '< )60* "5C+B4N-W,E,#0N-'@ )6,N)2XW
M<R5C)3 T+C1X "5S("XN+B!U;FMN;W=N('5S97(@870@)7, 97AE8R E<R M
M:25S("5S &QM86EL "5S("XN+B!U;FMN;W=N(&AO<W0@;6%C:&EN90!W ')M
M86EL(#0 <@!W ')M86EL(#0 52 E<R E<PI&("5S"DD@)7,*0R!R;6%I;" E
M<PH =75C<   =P!R;6%I;" U %,@)7,@)7,@)7,@+2 E<R P-C8V"E,@)7,@
M)7,@)7,@+2 E<R P-C8V"@  =75C<   =75C<   +W5S<B]L:6(O=75C<"]U
M=6-I8V\  &5X96,@)7,@+7,E<R M>#$@/B]D978O;G5L;" F "]U<W(O;&EB
M+W5U8W O=75C:6-O   O=7-R+W-P;V]L+W5U8W  )"0  &5X96,@)7,@)7,@
M "]T;7 O=6UE6%A86%A8  !W '( 1G)O;2 E<R E<PH <&]S=&UA<W1E<@  
M5&\Z("5S"@!3=6)J96-T.B!2971U<FYE9"!M86EL"@H  " @("TM+2T@5')A
M;G-C<FEP="!O9B!S97-S:6]N(&9O;&QO=W,@+2TM+0H*   E<PH "B @("TM
M+2T@56YS96YT(&UE<W-A9V4@9F]L;&]W<R M+2TM"@ ^("5S"@   ')M86EL
M " \)7,  '!O<W1M87-T97(     )"0           $  0 !  $  0"B" $ 
MI@@" *@( P"N" 0 L@@% +@(!@"^" < Q@@( '\< 0 # '$<<1QQ''$<KQP#
M  4 :QR0'/$;$!PO'$X<[!P!  , RQS>',L<RQPY'@$  P 2'3D>&QTD'70=
M"  ! &(=:QV&'0,  0!3'5P=*!X!  D .1[%'/X</QVC';8=R!W?'?4=#1X3
M'P8 ___6'@D D!X* -P>( "0'B(  1\C (,>.CT  "P 0D5'24X 14Y$ $1!
M5$$  $Y!3453 $1/34%)3E, 2$]35%, )3 U+C5D("5S"B @(" @(   ( !>
M("5S"@!E>'!E8W1E9"!%3D0  &5X<&5C=&5D(&-L87-S('!R969I> !E>'!E
M8W1E9"!"14=)3@  97AP96-T960@0D5'24X@;W(@0TQ!4U, 97AP96-T960@
M05-324=. &YO(&-O;6UA(&AE<F4 ;F\@8V]M;6$@:&5R90!E>'!E8W1E9"!#
M3TU-00  2'5H/R!9;W4@;75S="!B92!J;VMI;F<A  !R     0   "TM   E
M<SH@=6YK;F]W;B!O<'1I;VX@+25C"@ E<SH@+25C(&%R9W5M96YT(&UI<W-I
M;F<* "]E=&,O<&%S<W=D /__' HD"BX*2 I8"G *>@J4"J8*N K("M0*Y@KV
M"@@+% LJ"SP+2 M:"VH+>@N*"YP+L O$"]8+Y@OV"PX,' PR#$(,3@Q<#", 
M17)R;W(@, !.;W0@;W=N97( 3F\@<W5C:"!F:6QE(&]R(&1I<F5C=&]R>0!.
M;R!S=6-H('!R;V-E<W, 26YT97)R=7!T960@<WES=&5M(&-A;&P 22]/(&5R
M<F]R $YO('-U8V@@9&5V:6-E(&]R(&%D9')E<W, 07)G(&QI<W0@=&]O(&QO
M;F< 17AE8R!F;W)M870@97)R;W( 0F%D(&9I;&4@;G5M8F5R $YO(&-H:6QD
M<F5N $YO(&UO<F4@<')O8V5S<V5S $YO="!E;F]U9V@@8V]R90!097)M:7-S
M:6]N(&1E;FEE9 !"860@861D<F5S<P!";&]C:R!D979I8V4@<F5Q=6ER960 
M36]U;G0@9&5V:6-E(&)U<WD 1FEL92!E>&ES=', 0W)O<W,M9&5V:6-E(&QI
M;FL 3F\@<W5C:"!D979I8V4  $YO="!A(&1I<F5C=&]R>0!)<R!A(&1I<F5C
M=&]R>0  26YV86QI9"!A<F=U;65N=   1FEL92!T86)L92!O=F5R9FQO=P!4
M;V\@;6%N>2!O<&5N(&9I;&5S $YO="!A('1Y<&5W<FET97(  %1E>'0@9FEL
M92!B=7-Y  !&:6QE('1O;R!L87)G90  3F\@<W!A8V4@;&5F="!O;B!D979I
M8V4 26QL96=A;"!S965K  !296%D+6]N;'D@9FEL92!S>7-T96T 5&]O(&UA
M;GD@;&EN:W,  $)R;VME;B!P:7!E $UA=&@@87)G=6UE;G0 4F5S=6QT('1O
M;R!L87)G90  26YV86QI9"!E<G)N;PH  #H@   * "]B:6XO<V@ <V@  "UC
M     , L P!A %,L<@"B+'< ,"P?-0T 1 !:-$\ 'S15 !<T6  /-&, U31D
M %TT90#*-&8 RC1G ,HT;P B-', Z#1U !HT>  2-"AN=6QL*0  BC8     
M 0!P,G R 0   $( <"YP+@(    &      #H#/(,_ P                 
M                                                            
M  "U#<P-        < T                          /D-APV'#9X-17)R
M;W(Z($1I=FES:6]N(&)Y(# @"@!);&QE9V%L($5-(&EN<W1R=6-T)VX* $5R
M<B!I;B!%32!C87-E(&EN<W1R( H 5F%R:6%B;&4@;W5T(&]F(')A;F=E"@!%
M<G(@:6X@14T@<V5T(&EN<W1R( H 1FQO871I;F<@<'0@;F]T(&EM<&PN"@!(
M96%P(&]V97)F;&]W( H 14T@=')A<" P,# P,# P(&]C=&%L"@"*-HHV    
! &%P
 
end
END_OF_UUENCODED
fi
if test -f 'Makefile' -a "${1}" != "-c"
then
   echo "$0: Will not overwrite existing file: 'Makefile'"
else
   echo "x - Makefile"
sed 's/^X//' <<\END_OF_SHAR >'Makefile'
X#
X#       Makefile for UMAIL Mail Router (MINIX)
X#
X# Author:   Fred van Kempen, MicroWalt Corporation
X#
X# Define WMAILER if the local mailer is W-MAIL.
X# This mailer understands the "-i filename" option,
X# and this works much faster than stdIO redirecting.
X#
XCFLAGS  =	-DMINIX -DWMAILER
X
XBIN	=	/usr/bin
X
XOBJS    =	ummain.s umtime.s umheader.s umconvert.s \
X		umroute.s umsend.s umscanner.s
XSRCS    =	ummain.c umtime.c umheader.c umconvert.c \
X		umroute.c umsend.c umscanner.c
XOTHERS	=	README umail.doc umail.cf umail Makefile uucp.h umail.h
X
Xumail:	   	Makefile $(OBJS)
X	   	cc -i -o umail $(OBJS)
X		@chmem =16000 umail >/dev/null
X
Xinstall:	umail
X		@rm -f $(BIN)/umail $(BIN)/rmail
X		@echo 'Copying files...'
X		@cp umail $(BIN)/umail
X		@echo 'Setting up links...'
X		@ln $(BIN)/umail $(BIN)/rmail
X		@echo 'Setting up permissions:'
X		chown root.root $(BIN)/umail
X		chmod 6555 $(BIN)/umail
X
Xshar:
X		@shar -v -o umail.shar $(OTHERS) $(SRCS)
X
Xtar:
X		@tar c umail.tar $(OTHERS) $(SRCS)
X
Xummain.s:  	umail.h ummain.c
X	   	cc $(CFLAGS) -S ummain.c
X
Xumtime.s:  	umail.h umtime.c
X	   	cc $(CFLAGS) -S umtime.c
X
Xumheader.s:  	umail.h umheader.c
X		cc $(CFLAGS) -S umheader.c
X
Xumconvert.s:    umail.h umconvert.c
X	   	cc $(CFLAGS) -S umconvert.c
X
Xumroute.s:      umail.h umroute.c
X	   	cc $(CFLAGS) -S umroute.c
X
Xumsend.s:    	umail.h uucp.h umsend.c
X	   	cc $(CFLAGS) -S umsend.c
X
Xumscanner.s: 	umscanner.c
X	   	cc $(CFLAGS) -S umscanner.c
X
END_OF_SHAR
fi
if test -f 'uucp.h' -a "${1}" != "-c"
then
   echo "$0: Will not overwrite existing file: 'uucp.h'"
else
   echo "x - uucp.h"
sed 's/^X//' <<\END_OF_SHAR >'uucp.h'
X/*
X * UUCP.H-	DCP: A UUCP clone.
X * 		Definitions for the UUCP package
X *
X * Copyright Richard H. Lamb 1985,1986,1987
X * Copyright S. R. Sampson, August 1989
X * Copyright F. N. G. van Kempen Jul-Oct '89
X */
X
X#ifndef TRUE
X#	define FALSE	0
X#	define TRUE	1
X#endif
X
X#define LSYS		         "/usr/lib/uucp/L.sys"
X#define LDEVICE		     "/usr/lib/uucp/L-devices"
X#define UUCICO			"/usr/lib/uucp/uucico"
X#define UUXQT			 "/usr/lib/uucp/uuxqt"
X#define RMAIL			      	       "rmail"	/* Remote Mailer */
X#define SMAIL			               "smail"	/* Internet Mailer */
X#define LMAIL			               "lmail"	/* Local Mailer */
X#define SYSLOG          "/usr/lib/uucp/Log/uucico.log"
X#define XQTLOG           "/usr/lib/uucp/Log/uuxqt.log" 
X#define PUBDIR		       "/usr/spool/uucppublic"
X#define SPOOLDIR	             "/usr/spool/uucp"
X#define SPOOLSEQ	      "/usr/lib/uucp/SPOOLSEQ"
X#define LSPOOLSEQ	  "/usr/lib/uucp/SPOOLSEQ.LCK"
X#define LOCKFILE            "/usr/spool/locks/LCK..%s"	/* terminal LOCKfile */ 
X#define GLOCKFILE         "/usr/spool/locks/GLOCK..%s"	/* terminal LOCKfile */ 
X#define NODENAME		       "/etc/uucpname"
X#define CALLFILE				"C.%s"
X#define XQTFILE					"X.%s"
X#define MAILFILE				"B.%s"
X
X#define UUCPUSER			  	"uucp"
X#define ERRUSER				  "postmaster"
X
X#define UUCPUID					    40	/* RMAIL needs these */
X#define UUCPGID					    40
X#define POSTUID					    41	/* RMAIL needs these */
X#define POSTGID					    40
X
X#define SITENAMELEN	 32
X#define PATHLEN		256
X
X#define MSGTIME          20
X#define MAXPACK         256
X
X/* L.sys field defines */
X#define	FLD_REMOTE	  0	/* remote system name */
X#define	FLD_CCTIME	  1	/* legal call times */
X#define	FLD_DEVICE	  2	/* device, or ACU for modem */
X#define	FLD_SPEED	  3	/* bit rate */
X#define FLD_PHONE	  4	/* phone number */
X#define	FLD_EXPECT	  5	/* first login "expect" field */
X#define FLD_SEND	  6	/* first login "send" field */
X
END_OF_SHAR
fi
if test -f 'umail.h' -a "${1}" != "-c"
then
   echo "$0: Will not overwrite existing file: 'umail.h'"
else
   echo "x - umail.h"
sed 's/^X//' <<\END_OF_SHAR >'umail.h'
X/*
X * UMAIL -	MINIX Remote Domain-adressing Mail Router
X *
X *		This version of RMAIL handles message-headers in a much
X *		more "standard" way. It can handle bang-adresses, plus
X *		the new-style Internet adressing (user@host.domain).
X *		It is called by programs as "Mail" and "Uuxqt".
X *
X * 		D E F I N I T I O N S
X *
X * Author:	F. van Kempen, Jul-Oct '89 (waltje@minixug.nluug.nl)
X */
X
X#ifdef MINIX
X#	define VERSION         	  "2.5/MINIX"	/* 10/19/89 */
X#	define CONFIG		"/usr/lib/uucp/umail.cf"
X#endif
X
X#ifdef UNIX
X#	define VERSION             "2.5/UNIX"	/* 10/19/89 */
X#	define CONFIG		"/usr/lib/uucp/umail.cf"
X#endif
X
X#ifndef TRUE
X#	define FALSE	0
X#	define TRUE	1
X#endif
X
Xtypedef struct __name {
X    struct __name *next;
X    char *name;
X} NAME;
X
Xtypedef struct __var {
X    struct __var *next;
X    char *name;
X    char *value;
X} VAR;
X
Xtypedef struct __host {
X    struct __host *next;
X    char *name;
X    int smart;
X    char *command;
X    char *opts;
X} HOST;
X
Xtypedef struct __routemap {
X    struct __routemap *next;
X    char *domain;
X    char *host;
X    char *route;
X} ROUTE;
X
Xtypedef struct {
X    char user[256];			/* user name of adress */
X    char host[256];			/* host name of adress */
X    char domain[256];			/* domain name of adress */
X} BOX;
X
X#define NILNAME      ((NAME *)NULL)
X#define NILVAR        ((VAR *)NULL)
X#define NILHOST      ((HOST *)NULL)
X#define NILROUTE    ((ROUTE *)NULL)
X#define NILBOX	      ((BOX *)NULL)
X
X
X/* globals in ummain.c */
Xextern char *Version;			/* UMAIL version ID */
Xextern int immediate, debug;		/* commandline option flags */
Xextern int restrict;			/* restricted (UUCP) use only */
Xextern int aremote;			/* is adressee REMOTE or LOCAL ? */
Xextern char dfile[], infile[];		/* names of message temp-files */
Xextern char errmsg[];			/* global error message */
Xextern char mailsender[];		/* who sent the message? */
Xextern char mailaddr[];			/* final routed adress to use. */
Xextern char mailhost[];			/* which host to send to */
Xextern char mailcmd[];			/* command to use to send the mail */
Xextern char mailopts[];			/* which options the mailer uses */
Xextern NAME *namelist;			/* list of my network names */
Xextern VAR *varlist;			/* list of configuration variables */
Xextern HOST *hostlist;			/* list of reacheable host names */
Xextern ROUTE *routemap;			/* list of domain routes */
X
X/* configuration settings */
Xextern char *myname;			/* my UUCP site name */
Xextern char *mydomain;			/* my UUCP domain name */
Xextern char *myorg;			/* Name of my organization */
Xextern int oldmailer;			/* mailer uses old From-lines? */
Xextern int escape;			/* routing ESCAPE enable */
X
X/* external routines */
Xextern char *xtime(/* time_t *salt */);
Xextern BOX *convert(/* char *adr */);
Xextern int route(/* BOX *box */);
Xextern int header(/* FILE *infp, FILE *outfp */);
Xextern char *strupr(/* char *s */);
Xextern char *strlwr(/* char *s */);
Xextern void add_name(/* char *name */);
Xextern void add_host(/* char *name, int smart, char *cmd, char *opts */);
Xextern void add_route(/* char *domain, char *host, char *route */);
Xextern void add_var(/* char *name, char *val */);
Xextern char *lookup(/* char *what */);
Xextern int boolean(/* char *ascii */);
Xextern HOST *gethost(/* char *host */);
Xextern ROUTE *getdomain(/* char *domain */);
Xextern char *mfgets(/* char *s, int n, FILE *iop */);
Xextern char *whoami(/* void */);
Xextern char *full_id(/* char *user */);
Xextern char *realname(/* char *who */);
Xextern char *maketime(/* long *salt */);
Xextern void fcopy(/* FILE *inf, FILE *outf */);
Xextern int scanner(/* char *fname */);
Xextern int KnowHost(/* char *name */);
Xextern int islocal(/* char *name */);
Xextern char *genname(/* int prefix, int grade, char *sysname */);
Xextern int send_local(/* char *user, char *data */);
Xextern int send_remote(/* char *rmtname, char *rmtuser, char *data */);
Xextern void errmail(/* char *str, int mgronly */);
Xextern int sendit(/* char *who, char *host, char *cmd, char *opts, char *data */);
END_OF_SHAR
fi
if test -f 'ummain.c' -a "${1}" != "-c"
then
   echo "$0: Will not overwrite existing file: 'ummain.c'"
else
   echo "x - ummain.c"
sed 's/^X//' <<\END_OF_SHAR >'ummain.c'
X/*
X * UMAIL -	MINIX Remote Domain-adressing Mail Router
X *
X *		This version of RMAIL handles message-headers in a much
X *		more "standard" way. It can handle bang-adresses, plus
X *		the new-style Internet adressing (user@host.domain).
X *		It is called by programs as "Mail" and "Uuxqt".
X *
X * Usage:	umail [-c <config>] [-d] [-i <infile>] [-n] <user> ...
X *
X * Author:	F. van Kempen, Jul-Oct '89 (waltje@minixug.nluug.nl)
X */
X#include <stdio.h>
X#include <string.h>
X#include <alloc.h>
X#include <ctype.h>
X#include <time.h>
X#include <pwd.h>
X#include "umail.h"
X
X
Xchar *Version = VERSION;	/* UMAIL version ID */
Xint immediate, debug = FALSE;	/* commandline option flags */
Xint restrict = FALSE;		/* restricted (UUCP) use only */
Xint aremote;			/* is the adressee REMOTE or LOCAL ? */
Xchar dfile[128], infile[128];	/* names of message temp-files */
Xchar errmsg[512];		/* global error message */
Xchar mailsender[1024];		/* who sent the message? */
Xchar mailaddr[1024];		/* final routed adress to use. */
Xchar mailhost[64];		/* which host to send to */
Xchar mailcmd[512];		/* command to use to send the mail */
Xchar mailopts[64];		/* which options the mailer uses */
XNAME *namelist = NILNAME;	/* list of my network names */
XVAR *varlist = NILVAR;		/* list of configuration variables */
XHOST *hostlist = NILHOST;	/* list of reacheable host names */
XROUTE *routemap = NILROUTE;	/* list of domain routes */
X
X/* configuration settings */
Xchar *myname = NULL;		/* my UUCP site name */
Xchar *mydomain = NULL;		/* my UUCP domain name */
Xchar *myorg = NULL;		/* Name of my organization */
Xint oldmailer = FALSE;		/* does our mailer use old From-lines? */
Xint escape = FALSE;		/* can we offer a routing-escape? */
X
X
Xextern int getopt(), optind;	/* from standard library */
Xextern char *optarg, *fgets();
Xextern long ftell();
X
X
X/* 
X * Convert strings S to upper case. 
X */
Xchar *strupr(s)
Xchar *s;
X{
X  register char *sp;
X
X  sp = s;
X  while (*sp) {
X	if (*sp>='a' && *sp<='z') *sp = _toupper(*sp);
X  	sp++;
X  }
X  return(s);
X}
X
X
X/* 
X * Convert strings S to lower case. 
X */
Xchar *strlwr(s)
Xchar *s;
X{
X  register char *sp;
X
X  sp = s;
X  while (*sp) {
X	if (*sp>='A' && *sp<='Z') *sp = _tolower(*sp);
X  	sp++;
X  }
X  return(s);
X}
X
X
X/*
X * Add 'NAME' to the list of our names.
X */
Xvoid add_name(name)
Xchar *name;
X{
X  register NAME *np, *xp;
X
X  np = (NAME *) malloc(sizeof(NAME));       /* allocate new variable */
X  if (namelist == NILNAME) {                /* first variable */
X    	namelist = np;
X  } else {
X          xp = namelist;
X          while (xp->next != NILNAME) xp = xp->next;
X          xp->next = np;
X    }
X
X  np->next = NILNAME;
X  np->name = (char *) malloc(strlen(name) + 2);
X
X  strcpy(np->name, name);
X}
X
X
X/*
X * Add host 'NAME' to the list of hosts.
X */
Xvoid add_host(name, smart, cmd, opts)
Xchar *name;
Xint smart;
Xchar *cmd;
Xchar *opts;
X{
X  register HOST *hp, *xp;
X
X  hp = (HOST *) malloc(sizeof(HOST));       /* allocate new variable */
X  if (hostlist == NILHOST) {                /* first variable */
X    	hostlist = hp;
X  } else {
X          xp = hostlist;
X          while (xp->next != NILHOST) xp = xp->next;
X          xp->next = hp;
X    }
X
X  hp->next = NILHOST;
X  hp->name = (char *) malloc(strlen(name) + 2);
X  hp->command = (char *) malloc(strlen(cmd) + 2);
X  hp->opts = (char *) malloc(strlen(opts) + 2);
X
X  strcpy(hp->name, name);
X  strcpy(hp->command, cmd);
X  strcpy(hp->opts, opts);
X  hp->smart = smart;
X}
X
X
X/*
X * Add route 'DOMAIN' to the routing table.
X */
Xvoid add_route(domain, host, route)
Xchar *domain;
Xchar *host;
Xchar *route;
X{
X  register ROUTE *rp, *xp;
X
X  rp = (ROUTE *) malloc(sizeof(ROUTE));     /* allocate new route */
X  if (routemap == NILROUTE) {               /* first route */
X	routemap = rp;
X  } else {
X          xp = routemap;
X          while (xp->next != NILROUTE) xp = xp->next;
X          xp->next = rp;
X    }
X
X  rp->next = NILROUTE;
X  rp->domain = (char *) malloc(strlen(domain) + 2);
X  rp->host = (char *) malloc(strlen(host) + 2);
X  rp->route = (char *) malloc(strlen(route) + 2);
X
X  strcpy(rp->domain, domain);
X  strcpy(rp->host, host);
X  strcpy(rp->route, route);
X}
X
X
X/*
X * Add variable 'NAME' to the variable list.
X */
Xvoid add_var(name, val)
Xchar *name;
Xchar *val;
X{
X  register VAR *vp, *xp;
X
X  strupr(name);
X
X  vp = (VAR *) malloc(sizeof(VAR));         /* allocate new variable */
X  if (varlist == NILVAR) {                  /* first variable */
X    	varlist = vp;
X  } else {
X          xp = varlist;
X          while (xp->next != NILVAR) xp = xp->next;
X          xp->next = vp;
X    }
X
X  vp->next = NILVAR;
X  vp->name = (char *) malloc(strlen(name) + 2);
X  vp->value = (char *) malloc(strlen(val) + 2);
X
X  strcpy(vp->name, name);
X  strcpy(vp->value, val);
X}
X
X
X/*
X * Get a variable from the variable list.
X * Return NULL if not defined.
X */
Xchar *lookup(what)
Xchar *what;
X{
X  register VAR *vp;
X
X  vp = varlist;
X  while (vp != NILVAR) {
X    	if (!strcmp(vp->name, what)) return(vp->value);
X    	vp = vp->next;
X  }
X  return(NULL);
X}
X
X
X/*
X * Return TRUE or FALSE value, depending on
X * the value of the given variable.
X */
Xint boolean(ascii)
Xchar *ascii;
X{
X  strupr(ascii);
X  if (ascii==NULL || !strcmp(ascii, "FALSE")) return(FALSE);
X    else if (!strcmp(ascii, "TRUE")) return(TRUE);
X           else fprintf(stderr, "Bad value of boolean: \"%s\"\n", ascii);
X  return(FALSE);
X}
X
X
X/*
X * Lookup a host in our hosts-table.
X */
XHOST *gethost(host)
Xchar *host;
X{
X  register HOST *hp;
X
X  hp = hostlist;
X  while (hp != NILHOST) {
X	if (!strcmp(hp->name, host)) return(hp);
X	hp = hp->next;
X  }
X  return(NILHOST);
X}
X
X
X/*
X * Lookup a domain in our domain-table.
X */
XROUTE *getdomain(domain)
Xchar *domain;
X{
X  register ROUTE *rp;
X
X  rp = routemap;
X  while (rp != NILROUTE) {
X	if (!strcmp(rp->domain, domain)) return(rp);
X	rp = rp->next;
X  }
X  return(NILROUTE);
X}
X
X
X/*
X * mfgets (modified fgets)
X * Same as fgets() only this version deletes '\n'
X */
Xchar *mfgets(s, n, iop)
Xchar *s;
Xregister int n;
Xregister FILE *iop;
X{
X  register int c;
X  register char *cs;
X
X  cs = s;
X  while (--n > 0 && (c = getc(iop)) != EOF) {
X	if (c == '\n') {
X		*cs = '\0';
X		break;
X        } else *cs++ = c;
X  }
X  return((c == EOF && cs == s) ? (char *)NULL : s);
X}
X
X
X/*
X * Return the full UUCP ID of the calling user
X */
Xchar *full_id(user)
Xchar *user;
X{
X  static char fullbuf[48];
X
X  sprintf(fullbuf, "%s@%s.%s", user, myname, mydomain);
X  return(fullbuf);
X}
X
X
X/*
X * Return the Real Name of the calling user
X */
Xchar *realname(who)
Xchar *who;
X{
X  struct passwd *pw;
X
X  if ((pw = getpwnam(who)) != NULL) return(pw->pw_gecos);
X    else return("unknown flag");
X}
X
X
X/*
X * Make a decent DATE/TIME string.
X * Note, that there are TWO possible date formats:
X *
X *	Sat, 12 Oct 89 20:29:00\0
X * and
X *	Sat 12 Oct 20:29:00 1989\0
X *
X * Most Internet mailers use this first form, so we try
X * to this also. We use the function xtime() for the work...
X */
Xchar *maketime(salt)
Xlong *salt;
X{
X  static char datetime[48];		/* date and time in MET format */
X  char *sp;
X
X  sp = lookup("TIMEZONE");		/* get Time Zone from config file */
X  if (sp == NULL) sp = "";		/* must have SOME pointer! */
X
X  sprintf(datetime, "%s %s", xtime(salt), sp);
X
X  return(datetime);
X}
X
X
X/*
X * Copy a file from 'inf' to 'outf'.
X */
Xvoid fcopy(inf, outf)
Xregister FILE *inf, *outf;
X{
X  char cpbuff[1024];
X
X  while (TRUE) {
X	if (fgets(cpbuff, sizeof(cpbuff), inf) == (char *)NULL) break;
X	fwrite(cpbuff, sizeof(char), strlen(cpbuff), outf);
X  }
X}
X
X
X/*
X * Load the configuration parameters into their variables.
X */
Xstatic void setup(cfg)
Xchar *cfg;
X{
X  if (scanner(cfg) != 0) {		/* read the configuration file */
X          perror(cfg);
X          exit(1);
X  }
X
X  myname = lookup("SYSTEM");
X  if (myname == NULL) {
X	fprintf(stderr, "Missing SYSTEM definition\n");
X	exit(-1);
X  }
X  mydomain = lookup("DOMAIN");
X  if (mydomain == NULL) {
X	fprintf(stderr, "Missing DOMAIN definition\n");
X	exit(-1);
X  }
X  myorg = lookup("ORGANIZATION");
X  oldmailer = boolean(lookup("OLDMAILER"));
X  escape = boolean(lookup("ESCAPE"));
X}
X
X
X/*
X * Something went wrong.
X * Tell the caller how we should be called!
X */
Xstatic void usage()
X{
X  fprintf(stderr,
X	"Usage: umail [-c <config>] [-d] [-i <infile>] [-n] <users>\n");
X}
X
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X  FILE *fdfile, *infp;			/* message file pointers */
X  BOX *box;				/* conversion/routing adresses */
X  char *cfgfile = CONFIG;		/* config file; to save space */
X  register int st;			/* error status, to exit() */
X  
X  if (argv[0][0] == 'r') {		/* 'rmail' link? */
X 	restrict = TRUE;		/* yes, restrict usage */
X  }
X
X  while ((st = getopt(argc, argv, "c:di:n")) != EOF) switch(st) {
X	case 'c':			/* use non-standard CONFIGH file */
X		cfgfile = optarg;
X		break;
X
X	case 'd':			/* turn on DEBUG mode */
X		debug = TRUE;
X		break;
X	case 'i':			/* use non-stdin input file */
X		strncpy(infile, optarg, 128 - 1);
X		break;
X	case 'n':			/* call UUCICO after processing */
X		immediate = TRUE;
X		break;
X	default:
X		usage();
X		exit(1);
X  }
X
X  if (optind >= argc) {			/* we need another parameter! */
X    	usage();			/* (the adressee ) */
X	exit(-1);
X  }
X
X  umask(0117);				/* change umask to -rw-rw---- */
X
X  setup(cfgfile);			/* read CONFIG and setup */
X
X  strcpy(dfile, "/tmp/umXXXXXX");	/* create temp. message file */
X  mktemp(dfile);
X  if ((fdfile = fopen(dfile, "w")) == (FILE *)NULL) {
X	perror("rmail 1");
X	exit(1);
X  }
X
X  box = convert(argv[optind]);		/* convert Internet adress to UUCP */
X  if (box == NILBOX) st = FALSE;
X    else st = route(box);		/* run it through routing tables */
X
X  if (infile[0] != '\0') {		/* open input file if -i option */
X	infp = fopen(infile, "r");
X	if (infp == (FILE *)NULL) {
X		perror(infile);
X		exit(1);
X	}
X  } else infp = stdin;			/* otherwise use stdin! */
X
X  header(infp, fdfile);			/* analyze message header */
X
X  fcopy(infp, fdfile);			/* copy message to the temp. file */
X
X  fclose(fdfile);
X  if (infp != stdin) fclose(infp);
X
X  if (st == FALSE) {			/* conversion/routing went wrong? */ 
X	errmail(errmsg, FALSE);		/* yes; return the message! */
X	st = -1;
X  } else st = sendit(mailaddr, mailhost, mailcmd, mailopts, dfile);
X
X  unlink(dfile);			/* remote data file */
X  exit(st);				/* and exit! */
X}
END_OF_SHAR
fi
if test -f 'umtime.c' -a "${1}" != "-c"
then
   echo "$0: Will not overwrite existing file: 'umtime.c'"
else
   echo "x - umtime.c"
sed 's/^X//' <<\END_OF_SHAR >'umtime.c'
X/*
X * XTIME	-	Create ASCII string of the given time.
X *			This file contains a modified version
X *			of the ctime(3) function from the MINIX
X *			C library. The format of the string is:
X *
X *				Sat, Oct 14 89 20:26:00\0
X *
X */
X#include <time.h>
X
X
Xstatic int days_per_month[] = {
X	31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
X};
Xstatic char *months[] = { 
X	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
X	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
X};
Xstatic char *days[] = {
X	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
X};
X
X#define	MIN	60L		/* # seconds in a minute */
X#define	HOUR	(60 * MIN)	/* # seconds in an hour */
X#define	DAY	(24 * HOUR)	/* # seconds in a day */
X#define	YEAR	(365 * DAY)	/* # seconds in a year */
X
X
Xchar *xtime(pt)
Xlong *pt;
X{
X  static struct tm tm;
X  static char xtmbuf[30];
X
X  register long t = *pt;
X  long year;
X
X  tm.tm_year = 0;
X  tm.tm_mon = 0;
X  tm.tm_mday = 1;
X  tm.tm_hour = 0;
X  tm.tm_min = 0;
X  tm.tm_sec = 0;
X
X  /* t is elapsed time in seconds since Jan 1, 1970. */
X  tm.tm_wday = (int) (t/DAY + 4L) % 7;	/* Jan 1, 1970 is 4th wday */
X  while (t >= (year=((tm.tm_year%4)==2) ? YEAR+DAY : YEAR)) {
X	tm.tm_year += 1;
X	t -= year;
X  }
X  tm.tm_year += 1970;
X
X  /* t is now the offset into the current year, in seconds. */
X  tm.tm_yday = (t/DAY);		/* day # of the year, Jan 1 = 0 */
X
X  days_per_month[1] = 28;
X  if ((tm.tm_year % 4) == 0)	/* check for leap year */
X		days_per_month[1]++;
X
X  /* Compute month. */
X  while (t >= (days_per_month[tm.tm_mon] * DAY))
X		t -= days_per_month[tm.tm_mon++] * DAY;
X
X  /* Month established, now compute day of the month */
X  while (t >= DAY) {
X	t -= DAY;
X	tm.tm_mday++;
X  }
X
X  /* Day established, now do hour. */
X  while (t >= HOUR) {
X	t -= HOUR;
X	tm.tm_hour++;
X  }
X
X  /* Hour established, now do minute. */
X  while (t >= MIN) {
X	t -= MIN;
X	tm.tm_min++;
X  }
X
X  /* Residual time is # seconds. */
X  tm.tm_sec = (int) t;
X
X  /* Generate output in ASCII in _buf_. */
X  sprintf(xtmbuf, "%s, %2.2d %s %2.2d %02d:%02d:%02d",
X	days[tm.tm_wday], tm.tm_mday, months[tm.tm_mon], 
X	    tm.tm_year - 1900, tm.tm_hour, tm.tm_min, tm.tm_sec); 
X  return(xtmbuf);
X}
END_OF_SHAR
fi
if test -f 'umheader.c' -a "${1}" != "-c"
then
   echo "$0: Will not overwrite existing file: 'umheader.c'"
else
   echo "x - umheader.c"
sed 's/^X//' <<\END_OF_SHAR >'umheader.c'
X/*
X * UMAIL -	MINIX Remote Domain-adressing Mail Router
X *
X *		This version of RMAIL handles message-headers in a much
X *		more "standard" way. It can handle bang-adresses, plus
X *		the new-style Internet adressing (user@host.domain).
X *		It is called by programs as "Mail" and "Uuxqt".
X *
X *	    	M A I L   H E A D E R   C O N V E R S I O N   M O D U L E
X *
X * Headers:	This module reads the header part of a message into
X *		memory, and then rearranges it into RFC-822 order.
X *		The preferred order of fields is:
X *
X *		1.  From (old-style V6/V7)
X *		2.  From:
X *		3.  Received:	(top to bottom)
X *		4.  Sender:
X *
X *		5.  Unknown fields (user-defined)
X *
X *		6.  To:
X *		7.  Cc:
X *		8.  Bcc:
X *		9.  Subject:
X *		10. Message-ID:
X *		11. Date:
X *
X *		This order may be changed and/or expanded in the future,
X *		especially the "Resent-" fields should be added.
X *
X * Author:	F. van Kempen, Jul-Oct '89 (waltje@minixug.nluug.nl)
X */
X#include <stdio.h>
X#include <alloc.h>
X#include <string.h>
X#include <time.h>
X#include "umail.h"
X
X
Xtypedef struct __hdr {
X	struct __hdr *next;
X	int done;		/* 1==READ, 0==UNREAD */
X	int count;		/* 1==FIRST, 2.. == NEXT PART */
X	int std;		/* 1==RFC, 0==USER_DEFINED */
X	char *name;		/* field name */
X	char *value;		/* field value */
X} HEADER;
X#define NILHEAD ((HEADER *)NULL)
X
X
Xstatic HEADER *hlist = NILHEAD;		/* old message header */
Xstatic char *rfcfields[] = {		/* list of RFC-822 fields */
X	"FROM ",	"FROM",		"RECEIVED",	"SENDER",
X	"TO",		"CC",		"BCC",		"SUBJECT",
X	"MESSAGE-ID",	"DATE",		NULL
X};
Xstatic char olduser[1024];		/* old user */
Xstatic char olddate[48];		/* old date */
Xstatic char oldhost[48];		/* old host machine */
X
X
X/*
X * Look for a field in the header table in memory.
X * If found, return its value, otherwise return NULL.
X */
Xstatic char *hfind(name)
Xchar *name;
X{
X  register HEADER *hp;
X  char tmp[48];
X
X  hp = hlist;
X  while (hp != NILHEAD) {
X	strcpy(tmp, hp->name);
X	strupr(tmp);
X	if (!strcmp(tmp, name)) return(hp->value);
X	hp = hp->next;
X  }
X  return(NULL);
X}
X
X
X/*
X * Look for a field in the header table in memory.
X * If found, mark the field as READ, and return its adress.
X * Otherwise, return NILHEAD.
X */
Xstatic HEADER *hsearch(name)
Xchar *name;
X{
X  register HEADER *hp;
X  char tmp[48];
X
X  hp = hlist;
X  while (hp != NILHEAD) {
X	strcpy(tmp, hp->name);
X	strupr(tmp);
X	if (!strcmp(tmp, name)) {
X		if (hp->done == 0) {
X			hp->done = 1;
X			return(hp);
X		}
X	}
X	hp = hp->next;
X  }
X  return(NILHEAD);
X}
X
X
X/*
X * Decode an old-style (V6/V7) mail header.
X * This has a syntax like:
X *
X *	From <user> <date> [remote from <host>]
X *	To: <user>
X *	Subject: <text>
X *
X * We want to find out the <user>, <date> and possible <date> fields.
X * Return TRUE for OK, or FALSE if error.
X */
Xstatic int get_oldhdr(rmt)
Xint *rmt;		/* REMOTE or LOCAL mail? */
X{
X  register char *bp, *sp, *cp;
X
X  sp = hfind("FROM ");
X  if (sp == NULL) {	/* No From-line??? */
X	sprintf(errmsg, "%s: no From line", dfile);
X       	return(FALSE);
X  }
X  
X  strcpy(olduser, sp);		/* stuff field into 'user' */
X  sp = olduser;			/* skip until <date> field */
X  while (*sp && *sp!=' ' && *sp!='\t') sp++;
X  *sp++ = '\0';			/* mark 'end-of-user' */
X
X  /*
X   * SP now contains <date> and (possible) <remote> fields.
X   * Parse line to seek out "remote from".
X   */
X  cp = sp;		/* save the Date-pointer */
X  while (TRUE) {
X	bp = strchr(sp++, 'r');
X	if (bp != NULL) {	 /* we found an 'r' */
X		if (!strncmp(bp, "remote from ", 12)) break;
X        } else break;
X  }
X
X  if (bp != NULL) {		/* remote host found --> remote mail */
X	sp = strrchr(bp, ' ');	/* seek to start of "remote from" text */
X	*(bp - 1) = '\0';	/* mark end-of-date */
X       	strcpy(olddate, cp);	/* set old date */
X	strcpy(oldhost, ++sp);	/* set host name */
X	sprintf(mailsender, "%s!%s", oldhost, olduser);
X	*rmt = TRUE;
X  } else {
X	  strcpy(olddate, cp);	/* set old date */
X	  strcpy(oldhost, "");	/* no remote host */
X	  strcpy(mailsender, olduser);
X	  *rmt = FALSE;	
X    }
X  return(TRUE);
X}
X
X
X/*
X * Analyze the current header.
X *
X * See if this mail was generated locally or came from somewhere else.
X * Note, that old-style mailers use "postmarks" (i.e. header lines
X * looking like "From <user> <date>" with a possible suffix of
X * "remote from <host>". New-style mailers (should) only use the
X * "From: <path>" and "Date: <date>" lines in their headers.
X * UMAIL knows both types. By default it uses new-style headers,
X * but it can use (and generate) old headers by defining OLDMAILER.
X *
X * Return TRUE if we think this mail has been generated remotely,
X * or FALSE if this message was generated by local mail.
X */
Xstatic int chk_hdr(void)
X{
X  int remmail;				/* remote mail? */
X  long now;
X  register char *sp, *bp;		/* fast scanning pointers */
X
X  bp = hfind("FROM");			/* get RFC-From: field */
X  sp = hfind("DATE");			/* get RFC-Date: field */
X
X  if (sp==NULL || bp==NULL) {		/* should have both or none! */
X	if (oldmailer == TRUE) {	/* try old-style header */
X		if (get_oldhdr(&remmail) == FALSE) {
X			strcat(errmsg, "\n\nBad adress or header!\n");
X			return(FALSE);
X		}
X	}
X  } else {	/* only use new-style From:=lines */
X	  strcpy(olddate, sp);	/* Save the DATE field */
X	  strcpy(oldhost, bp);
X	  sp = oldhost;		/* skip comments */
X	  while (*sp && *sp!=' ' && *sp!='\t') sp++;
X	  *sp = '\0';
X	  strcpy(mailsender, oldhost);
X
X	  sp = strchr(oldhost, '!');	/* check for pathname! */
X	  if (sp != NULL) {	/* found one; this was remote! */
X		remmail = TRUE;
X		*sp++ = '\0';
X		strcpy(olduser, sp);
X	  } else {
X		  remmail = FALSE;
X		  strcpy(olduser, bp);
X		  strcpy(oldhost, "");
X	    }
X    }
X  return(remmail);
X}
X
X
X/*
X * Create a new RFC-822 message header.
X * This is necessary because we are processing
X * a locally-generated message.
X * The header should become:
X *
X *      From <host!user> <date> remote from <here>
X *      From: <host>!<user>
X *	Received: by <here> with <proto>;
X *                <receive-date>
X *	Sender: <user>@<host>.<domain> (Real Name)
X *	To: <user>
X *	Subject: <text>
X */
Xstatic void new_hdr(outfp)
XFILE *outfp;
X{
X  long rcvtm;				/* current time */
X  char *date;				/* current date in MET */
X  char *fmt1 = "%s:%s\n";
X  char *fmt2 = "%s\n";
X  register char *sp;
X
X  /* get the current date and time */
X  time(&rcvtm); date = maketime(&rcvtm);
X
X  if (oldmailer == TRUE) {
X	fprintf(outfp, "From %s %s remote from %s\n",
X				olduser, xtime(&rcvtm), myname);
X  }
X  fprintf(outfp, "From: %s!%s (%s)\n", myname, olduser, realname(olduser));
X  fprintf(outfp, "Received: by %s.%s (UMAIL %s) with UUCP;\n          %s\n",
X				myname, mydomain, Version, date);
X  fprintf(outfp, "Sender: %s (%s)\n", full_id(olduser), realname(olduser));
X  if (myorg != NULL) fprintf(outfp, "Organization: %s\n", myorg);
X  if ((sp = hfind("TO")) != NULL) fprintf(outfp, "To: %s\n", sp);
X  if ((sp = hfind("SUBJECT")) != NULL) fprintf(outfp, "Subject: %s\n", sp);
X  fprintf(outfp, "Date: %s\n", olddate);
X  fprintf(outfp, "\n");
X}
X
X
X/*
X * Update the current header.
X * This is necessary because the message comes from
X * a remote system without RFC-conforming mailer...
X * We should include ALL RFC-822 fields in this routine!
X */
Xstatic void upd_hdr(outfp)
XFILE *outfp;
X{
X  long rcvtm;				/* current time */
X  char *date;				/* current date in MET */
X  char *fmt1 = "%s: %s\n";
X  char *fmt2 = "%s\n";
X  register char *sp;
X  register HEADER *hp;
X
X  /* get the current date and time */
X  time(&rcvtm); date = maketime(&rcvtm);
X
X  /* First of all, get the Old V6/V7 From-line */
X  if (oldmailer == TRUE) {
X	hp = hsearch("FROM ");		/* to make it DONE */
X	if (oldhost[0] == '\0')
X		fprintf(outfp, "From %s %s remote from %s\n",
X					olduser, xtime(&rcvtm), myname);
X    	  else fprintf(outfp, "From %s!%s %s remote from %s\n",
X				oldhost, olduser, xtime(&rcvtm), myname);
X  }
X
X  /*
X   * Write the modified From:-line
X   * Note, that we must only add our name if the mail is to be forwarded
X   * to another system. If it will be delivered locally, leave it.
X   */
X  hp = hsearch("FROM");
X  if (hp != NILHEAD) {
X	if (aremote == TRUE) {	/* adressee is REMOTE. add our name! */
X		fprintf(outfp, "%s: %s!%s\n", hp->name, myname, hp->value);
X	} else {		/* adressee is LOCAL */	
X		fprintf(outfp, "%s: %s\n", hp->name, hp->value);
X	  }
X  }
X
X  /* Our own Receive:-line */
X  fprintf(outfp, "Received: by %s.%s (UMAIL %s) with UUCP;\n          %s\n",
X				myname, mydomain, Version, date);
X
X  /* Next, all other Received:-lines */
X  while ((hp = hsearch("RECEIVED")) != NILHEAD) {
X	if (hp->count > 1) fprintf(outfp, fmt2, hp->value);
X	  else fprintf(outfp, fmt1, hp->name, hp->value);
X  }
X
X  /* The old Sender:-line */
X  hp = hsearch("SENDER");
X  if (hp != NILHEAD) {
X	if (hp->count > 1) fprintf(outfp, fmt2, hp->value);
X	  else fprintf(outfp, fmt1, hp->name, hp->value);
X  }
X
X  /* insert all unknown fields here */
X  hp = hlist;
X  while (hp != NILHEAD) {
X	if (hp->std == 0) {
X		hp->done = 1;
X		fprintf(outfp, fmt1, hp->name, hp->value);
X	}
X	hp = hp->next;
X  }
X
X  /* Write the To:-line too */
X  hp = hsearch("TO");
X  if (hp != NILHEAD) {
X	if (hp->count > 1) fprintf(outfp, fmt2, hp->value);
X	  else fprintf(outfp, fmt1, hp->name, hp->value);
X  }
X
X  /* The CarbonCopy Cc:-line */
X  hp = hsearch("CC");
X  if (hp != NILHEAD) {
X	if (hp->count > 1) fprintf(outfp, fmt2, hp->value);
X	  else fprintf(outfp, fmt1, hp->name, hp->value);
X  }
X
X  /* And the BlindCarbonCopy as well */
X  hp = hsearch("BCC");
X  if (hp != NILHEAD) {
X	if (hp->count > 1) fprintf(outfp, fmt2, hp->value);
X	  else fprintf(outfp, fmt1, hp->name, hp->value);
X  }
X
X  /* Finally, the old Subject:-line */
X  hp = hsearch("SUBJECT");
X  if (hp != NILHEAD) {
X	if (hp->count > 1) fprintf(outfp, fmt2, hp->value);
X	  else fprintf(outfp, fmt1, hp->name, hp->value);
X  }
X
X  /* A message ID */
X  hp = hsearch("MESSAGE-ID");
X  if (hp != NILHEAD) {
X	if (hp->count > 1) fprintf(outfp, fmt2, hp->value);
X	  else fprintf(outfp, fmt1, hp->name, hp->value);
X  }
X
X  /* And the old date of sending */
X  hp = hsearch("DATE");
X  if (hp != NILHEAD) {
X	if (hp->count > 1) fprintf(outfp, fmt2, hp->value);
X	  else fprintf(outfp, fmt1, hp->name, hp->value);
X  } else fprintf(outfp, fmt1, "Date: ", date);
X
X  /* an empty line marks the end of the header! */
X  fprintf(outfp, "\n");
X}
X
X
X/*
X * Read the message-header into memory.
X */
Xstatic int read_hdr(infp)
Xregister FILE *infp;
X{
X  char hdrbuf[1024];
X  char lastf[128];
X  int i, numfields = 0;
X  int lastc = 1;
X  register HEADER *hp, *xp;
X  register char *bp, *sp;
X
X  while (TRUE) {
X	if (mfgets(hdrbuf, 1024, infp) == NULL) break;	/* end of file */
X	if (hdrbuf[0] == '\0') break;	/* end of header */
X
X	numfields++;
X	bp = hdrbuf;
X
X	/* first check if this is the V6/V7 From-line */
X	if (strncmp(hdrbuf, "From ", 5)) {
X		/* No From-line. */
X		if (*bp==' ' || *bp=='\t') {
X			lastc++;	/* next part of previous field */	
X			bp = lastf;	/* previous field */
X			sp = hdrbuf;	/* value */
X		} else {
X			sp = strchr(bp, ':');	/* plain field, get sepa */
X			if (sp != NULL) {	/* do we have one? */
X				*sp++ = '\0';		/* end it */
X				while (*sp && (*sp==' ' || *sp=='\t')) sp++;
X				strcpy(lastf, bp);    /* set as prev field */
X				lastc = 1;	
X			} else sp = bp;	      /* no sepa, use entire field */
X	  	  }
X	} else {
X		bp = "From ";
X		sp = &hdrbuf[5];
X	  }
X
X	/* Add a new header field to the message header in memory */
X	hp = (HEADER *) malloc(sizeof(HEADER)); 	/* allocate new variable */
X	if (hlist == NILHEAD) {			/* first variable */
X    		hlist = hp;
X  	} else {
X          	xp = hlist;
X          	while (xp->next != NILHEAD) xp = xp->next;
X          	xp->next = hp;
X    	  }
X
X  	hp->next = NILHEAD;
X  	hp->name = (char *) malloc(strlen(bp) + 2);
X  	hp->value = (char *) malloc(strlen(sp) + 2);
X
X  	strcpy(hp->name, bp);
X  	strcpy(hp->value, sp);
X  	hp->done = 0;		/* not yet read */
X  	hp->count = lastc;	/* folding level */
X  	hp->std = 0;		/* standard field? */
X
X	/* now see if this field is an RFC-822 field */
X	i = 0;
X  	sp = rfcfields[i];
X	strcpy(hdrbuf, hp->name);	/* convert field name to uppercase */
X	strupr(hdrbuf);
X  	while (sp != NULL) {
X		if (!strcmp(sp, hdrbuf)) break;
X 		sp = rfcfields[++i];
X  	}
X  	if (sp != NULL) hp->std = 1;
X  }
X}
X
X
X/*
X * Read the header from the input file 'infd', and adapt some
X * fields to the new values.
X * Then, sort the entries and generate a new header.
X * Put that new header into file 'outfp'.
X * Return TRUE if REMOTE, FALSE if LOCAL mail.
X */
Xint header(infp, outfp)
Xregister FILE *infp;
Xregister FILE *outfp;
X{
X  int remote;
X  char *sp;
X
X  (void) read_hdr(infp);		/* read in the current header */
X	
X  remote = chk_hdr(outfp);		/* analyze old header */
X
X  if (remote == FALSE) new_hdr(outfp);	/* locally-generated mail */
X    else upd_hdr(outfp);
X
X  return(remote);
X}
END_OF_SHAR
fi
if test -f 'umconvert.c' -a "${1}" != "-c"
then
   echo "$0: Will not overwrite existing file: 'umconvert.c'"
else
   echo "x - umconvert.c"
sed 's/^X//' <<\END_OF_SHAR >'umconvert.c'
X/*
X * UMAIL -	MINIX Remote Domain-adressing Mail Router
X *
X *		This version of RMAIL handles message-headers in a much
X *		more "standard" way. It can handle bang-adresses, plus
X *		the new-style Internet adressing (user@host.domain).
X *		It is called by programs as "Mail" and "Uuxqt".
X *
X *	    	A D R E S S   C O N V E R S I O N   M O D U L E
X *
X * 		Convert adresses into manageable chunks.
X *
X * 		We understand the following notations:
X *
X *		1. user@host.domain	--> waltje@minixug.UUCP
X *	
X *		2. host!user		--> minixug!waltje
X *	
X *		3. user			--> waltje
X *
X * Return TRUE (1) if OK, or FALSE (0) if an error was encountered.
X *
X * Author:	F. van Kempen, Jul-Oct '89 (waltje@minixug.nluug.nl)
X */
X#include <stdio.h>
X#include <alloc.h>
X#include <string.h>
X#include "umail.h"
X
X
X/*
X * Convert adress 'adr' into more manageable chunks.
X * Stuff the output into 'mailaddr' (the final user)
X * and 'mailcmd' (the mailer command to use).
X * Return NILBOX if an error ocurred.
X */
XBOX *convert(adr)
Xchar *adr;
X{
X  static BOX box;
X  char temp[1024];
X  register char *bp, *sp, *cp;
X  register ROUTE *rp;
X  register HOST *hp;
X
X  strcpy(mailaddr, adr);
X  box.domain[0] = box.host[0] = '\0';
X  box.user[0] = temp[0] = '\0';
X
X  /*
X   * Rule 1: Check for user@host.domain
X   */
X  sp = strrchr(mailaddr, '@');
X  if (sp != NULL) {
X	*sp++ = '\0';
X	strcpy(box.user, mailaddr);
X	strcpy(temp, sp);	
X	strlwr(temp);		/* convert domain to lower case: RFC822 */
X
X	/*
X	 * Rule 1A: Now check for "." in the domain part.
X	 * 	    This indicates that a host name was given.
X	 */
X	sp = strchr(temp, '.');		/* syntax host.domain ?? */
X	if (sp == NULL) {		/* no, onlky 'host' part */
X		hp = gethost(temp);	/* is this a local host? */
X		if (hp != NILHOST) {	/* yes! */
X			strcpy(box.host, temp);
X			box.domain[0] = '\0';
X			return(&box);
X		} else {		/* no, must be a domain.... */
X			strcpy(box.domain, temp);
X			box.host[0] = '\0';
X			return(&box);
X	  	  }
X	} else {			/* domain and host given! */
X		*sp++ = '\0';
X		strcpy(box.host, temp);
X		strcpy(box.domain, sp);
X		return(&box);
X	  }
X  }
X
X  /*
X   * Rule 2: Check for host!user
X   */
X  sp = strchr(mailaddr, '!');
X  if (sp != NULL) {
X	*sp++ = '\0';
X	strcpy(box.host, mailaddr);
X	strcpy(box.user, sp);
X	return(&box);
X  }
X
X  /*
X   * Rule 3: Must be local user.
X   */
X  strcpy(box.user, mailaddr);
X  box.host[0] = '\0';
X  box.domain[0] = '\0';
X  return(&box);
X}
X
END_OF_SHAR
fi
if test -f 'umroute.c' -a "${1}" != "-c"
then
   echo "$0: Will not overwrite existing file: 'umroute.c'"
else
   echo "x - umroute.c"
sed 's/^X//' <<\END_OF_SHAR >'umroute.c'
X/*
X * UMAIL -	MINIX Remote Domain-adressing Mail Router
X *
X *		This version of RMAIL handles message-headers in a much
X *		more "standard" way. It can handle bang-adresses, plus
X *		the new-style Internet adressing (user@host.domain).
X *		It is called by programs as "Mail" and "Uuxqt".
X *
X *	    	M A I L   R O U T E R   M O D U L E
X *
X * 		Some rules exist for routing to other machines.
X *
X *		1. Check for local system names.
X *
X *		2. If we have a domain, check it for validity.
X *
X *		3. If we have a hostname, check it for validity.
X *
X *		4. Local user: check existence.
X *
X * 		Examples are:
X *
X *			user@host.domain@newdomain -
X *				-> ast@cs.vu@nluug.nl
X *			host!user@domain
X *				--> cs.vu!ast@nluug.nl
X *
X *		If we cannot find a matching domain or system name,
X *		then we get stuck. Fortunately, we can define the
X *		ESCAPE parameter, which allows us to send all mail
X *		for unknown hosts or domains to a "default" domain.
X *		This is the domain called "." in the tables.
X *		If the ESCAPE parameter is FALSE, we cannot deliver
X *		the message, so return it to the sender!
X *
X * Return TRUE (1) if OK, or FALSE (0) if an error was encountered.
X *
X * Author:	F. van Kempen, Jul-Oct '89 (waltje@minixug.nluug.nl)
X */
X#include <stdio.h>
X#include <alloc.h>
X#include <pwd.h>
X#include <string.h>
X#include "umail.h"
X
X
X/*
X * Route the adress in BOX into a ready-to-run
X * UUCP adress.
X */
Xint route(b)
XBOX *b;
X{
X  char temp[1024];
X  register char *bp, *sp;
X  register ROUTE *rp;
X  register HOST *hp;
X  struct passwd *pw;
X
X  /* 
X   * Rule 1: check for local system names.
X   *	     convert to LOCAL if possible.
X   */
X  if (b->domain[0] == '\0') strcpy(temp, b->host);
X    else sprintf(temp, "%s.%s", b->host, b->domain);
X  if (islocal(temp)) {
X	b->host[0] = '\0';
X	b->domain[0] = '\0';
X  }
X
X  /*
X   * Rule 2: Do we have a domain?
X   */
X  if (b->domain[0] != '\0') {			/* domain given? */
X	if (b->host[0]) sprintf(temp, "%s.%s", b->host, b->domain);
X	  else strcpy(temp, b->domain);
X	strcpy(b->host, temp);
X	bp = temp;
X	rp = NILROUTE;
X	while (TRUE) {			/* iterate on domain fragments */
X		sp = bp;
X		rp = getdomain(bp);
X		if (rp != NILROUTE) {		/* a matching domain! */
X			strcpy(b->domain, bp);
X			break;
X		}
X		bp = strchr(sp, '.');				
X		if (bp == NULL) break;
X		  else bp++;
X	}
X
X	/*
X 	 * We now have checked the DOMAIN table for a matching domain.
X	 * If we failed to find a match, there is a problem.
X	 * If the mailer was defined with the ESCAPE parameter, we can
X	 * try to route it to the default (".") domain.
X	 * Otherwise, we cannot deliver the message...
X	 */
X
X	/* check if we found a matching domain */
X	if (rp == NILROUTE) {	/* we did not. try to re-route it */
X		if (escape == FALSE) {
X			sprintf(errmsg, "%s ... domain unknown", b->domain);
X			return(FALSE);
X		}
X		rp = getdomain(".");	/* get default domain! */
X		if (rp == NILROUTE) {
X			sprintf(errmsg, "%s ... domain unknown", b->domain);
X			strcat(errmsg, "\n\nESCAPE domain not found.");
X			return(FALSE);
X		}
X	}
X
X	/*
X	 * At this point we have all the information we
X 	 * need to build an UUCP-adress.
X	 * We have a HOST as well.
X	 * Check if we can indeed reach that host.
X	 */
X	hp = gethost(rp->host);
X	if (hp == NILHOST) {
X		sprintf(errmsg, "%s ... host unreacheble", rp->host);
X		return(FALSE);
X	}
X
X	/* is the host smart enough to get "@"-adresses?? */
X	if (hp->smart == TRUE) {	/* yes, it is! */
X		if (*(rp->route) == '@') {
X			if (b->host[0] == '\0') sprintf(mailaddr,"%s@%s",
X				    	    		b->user, b->domain);
X  	  		  else sprintf(mailaddr, "%s@%s", b->user, b->host);
X		} else {
X			if (b->host[0] == '\0') sprintf(mailaddr,"%s!%s@%s",
X					rp->route, b->user, b->domain);
X  	  		  else sprintf(mailaddr, "%s!%s@%s.%s",
X				rp->route, b->user, b->host, b->domain);
X		  }
X	} else {
X		if (b->host[0] == '\0') sprintf(mailaddr,"%s!%s",
X							rp->route, b->user);
X		  else sprintf(mailaddr, "%s!%s!%s",
X				rp->route, b->host, b->user);
X	  }
X	strcpy(b->host, rp->host);
X
X	/*
X	 * We now have a HOST and an ADRESS.
X	 */
X	strcpy(mailcmd, hp->command);
X	strcpy(mailopts, hp->opts);
X	strcpy(mailhost, b->host);
X	aremote = TRUE;
X	return(TRUE);
X  }
X
X  /*
X   * Rule 3: Do we have a host name ?
X   */
X  if (b->host[0] != '\0') {			/* host name given? */
X	b->domain[0] = '\0';			/* signal 'no routing' */
X	hp = gethost(b->host);
X	if (hp == NILHOST) {
X		if (escape == FALSE) {
X			sprintf(errmsg, "%s ... host unknown", b->host);
X			return(FALSE);
X		}
X		rp = getdomain(".");	/* get default domain! */
X		if (rp == NILROUTE) {
X			sprintf(errmsg, "%s ... host unknown", b->host);
X			strcat(errmsg, "\n\nESCAPE domain not found.");
X			return(FALSE);
X		}
X
X		/*
X		 * We now have a HOST as well.
X		 * Check if we can indeed reach that host.
X		 */
X		strcpy(b->domain, rp->host);
X		hp = gethost(rp->host);
X		if (hp == NILHOST) {
X			sprintf(errmsg, "%s ... host unreacheble", rp->host);
X			return(FALSE);
X		}
X	}
X
X	/*
X	 * USER	contains the user-part
X	 * HOST contains the (old) host-part
X	 * DOMAIN now contains the new hostname
X	 */
X
X	/* is the host smart enough to get "@"-adresses?? */
X	if (b->domain[0] != '\0') {	/* are we routing? */
X		if (hp->smart == TRUE) sprintf(mailaddr, "%s@%s",
X							b->user, b->host);
X		  else sprintf(mailaddr, "%s!%s", b->host, b->user);
X		strcpy(b->host, b->domain);
X	} else {	/* no, ordinary case */
X		strcpy(mailaddr, b->user);
X	  }
X
X	strcpy(mailhost, b->host);
X	strcpy(mailcmd, hp->command);
X	strcpy(mailopts, hp->opts);
X	aremote = TRUE;
X	return(TRUE);
X  }
X
X  /*
X   * Rule 4: Check for local user.
X   */
X  if ((pw = getpwnam(b->user)) == (struct passwd *)NULL) {
X	sprintf(errmsg, "%s ... user unknown", b->user);
X	return(FALSE);
X  }
X  hp = gethost(myname);
X  strcpy(mailaddr, b->user);
X  mailhost[0] = '\0';
X  strcpy(mailcmd, hp->command);
X  strcpy(mailopts, hp->opts);
X  aremote = FALSE;
X  return(TRUE);
X}
END_OF_SHAR
fi
if test -f 'umsend.c' -a "${1}" != "-c"
then
   echo "$0: Will not overwrite existing file: 'umsend.c'"
else
   echo "x - umsend.c"
sed 's/^X//' <<\END_OF_SHAR >'umsend.c'
X/*
X * UMAIL -	MINIX Remote Domain-adressing Mail Router
X *
X *		This version of RMAIL handles message-headers in a much
X *		more "standard" way. It can handle bang-adresses, plus
X *		the new-style Internet adressing (user@host.domain).
X *		It is called by programs as "Mail" and "Uuxqt".
X *
X * 		M A I L   T R A N S P O R T   M O D U L E
X *
X * Author:	F. van Kempen, Jul-Oct '89 (waltje@minixug.nluug.nl)
X */
X#include <stdio.h>
X#include <sys/types.h>
X#include <dirent.h>
X#include <errno.h>
X#include <string.h>
X#include <time.h>
X#include <uucp.h>
X#include "umail.h"
X
X
X/*
X * Check the host machine name.
X *
X * returns FALSE if not found, else TRUE
X */
Xint KnowHost(name)
Xchar *name;
X{
X  register HOST *hp;
X
X  hp = gethost(name);
X  return((hp==NILHOST) ? FALSE : TRUE);
X}		
X
X
X/*
X * Check if this is one of our local names.
X * Return 1 if TRUE, or 0 if FALSE.
X */
Xint islocal(name)
Xchar *name;
X{
X  register NAME *np;
X
X  np = namelist;
X  while (np != NILNAME) {
X	if (!strcmp(np->name, name)) return(TRUE);
X	np = np->next;
X  }
X  return(FALSE);
X}
X
X
X/*
X * Creates a unique UUCP file name, and returns a pointer
X * to it. The filename is a combination of prefix, grade, system name
X * and a sequential number taken from SPOOLSEQ.
X */
Xchar *genname(prefix, grade, sysname)
Xint prefix, grade;
Xchar *sysname;
X{
X  static char _gen_buf[128];
X  int i = 0;
X  char seqline[10];
X  char *seqname = SPOOLSEQ;		/* to save some string space */
X  char *lseqname = LSPOOLSEQ;		/* to save some string space */
X  FILE *spoolseq;
X
X  if (access(seqname, 0) != 0) close(creat(seqname, 0600));
X
X  while(link(seqname, lseqname) != 0) {
X  	sleep(5);
X  	if (++i > 5) return(NULL);
X  }
X
X  spoolseq = fopen(seqname, "r");
X  fgets(seqline, sizeof(seqline), spoolseq);
X  fclose(spoolseq);
X  unlink(lseqname);
X
X  i = (atoi(seqline) + 1);
X
X  if ((spoolseq = fopen(seqname, "w")) == (FILE *)NULL) return(NULL);
X  fprintf(spoolseq, "%d\n", i);
X  fclose(spoolseq);
X
X  if (grade == 0) sprintf(_gen_buf, "%c.%.7s%04.4x", prefix, sysname, i);
X    else sprintf(_gen_buf, "%c.%.7s%c%04.4x", prefix, sysname, grade, i);
X
X  return(_gen_buf);
X}
X
X
X/*
X * Deliver this message to a local user.
X * We do this by calling "LMAIL" (which is actually
X * a link to "Mail"; the Local Mail Agent.
X */
Xint send_local(user, data)
Xchar *user;
Xchar *data;
X{
X  struct passwd *pw;
X  char tmpbuf[128];
X
X  /* See if destination user name exists on this machine */
X  pw = (struct passwd *) getpwnam(user);
X  if (pw == (struct passwd *)NULL) {
X	sprintf(tmpbuf, "%s ... unknown user at %s", user, myname);
X	errmail(tmpbuf, FALSE);
X  }
X
X#ifdef WMAILER	/* faster than redirecting! */
X  sprintf(tmpbuf, "exec %s -i%s %s", LMAIL, data, user);
X#else
X  sprintf(tmpbuf, "exec %s <%s %s", LMAIL, data, user);
X#endif WMAILER
X
X  return(system(tmpbuf));
X}
X
X
X/*
X * Deliver this message to a remote user.
X * We do this by creating the spoolfiles needed by UUCICO.
X * Then we call that program daemon to do the real work.
X */
Xint send_remote(rmtname, rmtuser, data)
Xchar *rmtname;
Xchar *rmtuser;
Xchar *data;
X{
X  char tmpbuf[128];
X  char Bfile[128], Cfile[128], Dfile[128], Xfile[128];
X  FILE *fcfile, *fbfile, *fdfile, *fp;
X
X  if (KnowHost(rmtname) == FALSE) {
X	sprintf(tmpbuf, "%s ... unknown host machine", rmtname);
X	errmail(tmpbuf, FALSE);
X  }
X
X  /* make the spool files for uucico */
X  strcpy(Bfile, genname('B', 0, rmtname));
X  strcpy(Cfile, genname('C', 'N', rmtname));
X  strcpy(Dfile, genname('D', 0, myname));
X  strcpy(Xfile, genname('X', 'N', rmtname));
X
X  /* Copy the temp-file to the UUCP data file (D.???) */
X  if ((fdfile = fopen(Dfile, "w")) == (FILE *)NULL) {
X	perror("rmail 4");
X      	exit(1);
X  } else {
X	  fp = fopen(data, "r");	/* open temp-file */
X	  fcopy(fp, fdfile);
X	  fclose(fdfile);
X	  fclose(fp);
X    }
X    
X  if ((fbfile = fopen(Bfile, "w")) == (FILE *)NULL) {
X	perror("rmail 4");
X	exit(1);
X  } else {
X	  fprintf(fbfile, "U %s %s\nF %s\nI %s\nC rmail %s\n",
X    				UUCPUSER, myname, Dfile, Dfile, rmtuser);
X    	  fclose(fbfile);
X    }
X
X  if ((fcfile = fopen(Cfile, "w")) == (FILE *)NULL) {
X	perror("rmail 5");
X	exit(1);
X  } else {
X	  fprintf(fcfile,"S %s %s %s - %s 0666\nS %s %s %s - %s 0666\n",
X		Dfile, Dfile, UUCPUSER, Dfile, Bfile, Xfile, UUCPUSER, Bfile);
X          fclose(fcfile);
X    }
X
X  /* RMAIL is setUID root... UUCP cannot read these files! */
X  chown(Bfile, UUCPUID, UUCPGID);
X  chown(Cfile, UUCPUID, UUCPGID);
X  chown(Dfile, UUCPUID, UUCPGID);
X  chown(Xfile, UUCPUID, UUCPGID);
X
X  if (immediate == TRUE) {	/* call uucico now! */
X	strcpy(tmpbuf, UUCICO);
X	sprintf(tmpbuf, "exec %s -s%s -x1 >/dev/null &", UUCICO, rmtname);
X	system(tmpbuf);
X  }
X
X  return(FALSE);
X}
X
X
X/*
X * Perform the mail-transport.
X * We do this by calling the appropriate mailer.
X * If the name of the mailer is "$$" then we can use
X * this program to deliver. This saves a lot of memory.
X */
Xint sendit(who, host, cmd, opts, data)
Xchar *who;			/* who is the adressee? */
Xchar *host;			/* on which machine? */
Xchar *cmd;			/* what command should we use? */
Xchar *opts;			/* which options? */
Xchar *data;			/* name of data (message) file */
X{
X  char cmdline[512];
X  char tmpbuff[512];
X
X  chdir(SPOOLDIR); 			/* Change to UUCP directory */
X
X  if (!strcmp(cmd, "$$")) {		/* run our own mail routines */
X	if (*host == '\0') send_local(who, data);
X          else send_remote(host, who, data);
X  } else {
X	  sprintf(tmpbuff, "exec %s %s ", cmd, opts);
X	  sprintf(cmdline, tmpbuff, data);	/* create commandline */
X	  strcat(cmdline, who);			/* add user adress */
X	  system(cmdline);			/* execute command (mailer) */
X    }
X}
X
X
X/*
X * Send mail to system manager upon errors
X *
X * Mail is contained in a file referenced
X * by Global variable 'dfile'
X */
Xvoid errmail(str, mgronly)
Xchar *str;
Xint mgronly;
X{
X  FILE *fp, *tp;
X  long now;
X  char fname[32];
X  char tmp[128];
X
X  strcpy(fname, "/tmp/umeXXXXXX");
X  mktemp(fname);
X
X  tp = fopen(fname, "w");
X  fp = fopen(dfile, "r");
X
X  time(&now);
X
X  /* create header of the report-message */
X  fprintf(tp, "From %s %s\n", ERRUSER, xtime(&now));	
X  if (mailsender != NULL) fprintf(tp, "To: %s\n", mailsender);
X  fprintf(tp, "Subject: Returned mail\n\n");
X
X  /* create an error transcript */
X  fprintf(tp, "   ---- Transcript of session follows ----\n\n");
X  fprintf(tp, "%s\n", str);
X  fprintf(tp, "\n   ---- Unsent message follows ----\n");
X
X  /* copy the message */
X  while (mfgets(tmp, sizeof(tmp), fp) != (char *)NULL)
X				fprintf(tp, "> %s\n", tmp);
X
X  fclose(tp);	/* flush and close message file */
X  fclose(fp);	/* flush and close orig. file */
X
X  /* Return mail to system manager (and sender if mgronly == FALSE) */
X  if (mgronly == FALSE) sendit(mailsender, "", RMAIL, " <%s", fname);
X
X  /* send mail to UUCP administrator */
X  sendit(ERRUSER, "", "$$", "", fname);
X
X  unlink(fname);	/* remove data files */
X  unlink(dfile);
X
X  exit(1);		/* and exit! */
X}
END_OF_SHAR
fi
if test -f 'umscanner.c' -a "${1}" != "-c"
then
   echo "$0: Will not overwrite existing file: 'umscanner.c'"
else
   echo "x - umscanner.c"
sed 's/^X//' <<\END_OF_SHAR >'umscanner.c'
X/*
X * UMAIL -	MINIX Remote Domain-adressing Mail Router
X *
X *		This version of RMAIL handles message-headers in a much
X *		more "standard" way. It can handle bang-adresses, plus
X *		the new-style Internet adressing (user@host.domain).
X *		It is called by programs as "Mail" and "Uuxqt".
X *
X *          	C O N F I G U R A T I O N   F I L E   S C A N N E R
X *
X * Author:	F. van Kempen, Jul-Oct '89 (waltje@minixug.nluug.nl)
X */
X#include <stdio.h>
X
X
Xtypedef struct {
X    char *name;
X    int opcode;
X} WORD;
X
X
X/* operator opcodes */
X#define O_ASSIGN        1       /* ":="             */
X#define O_COMMA         2       /* ","              */
X#define O_BEGIN         3       /* "BEGIN"          */
X#define O_END           4       /* "END"            */
X#define O_DATA          5       /* "DATA"           */
X#define O_NAMES         6       /* "NAMES"          */
X#define O_DOMAIN        7       /* "DOMAINS"        */
X#define O_HOST          8       /* "HOST"           */
X
X
X/* main scanner states */
X#define S_LOOK          1       /* looking for a keyword */
X#define S_BEGIN         2       /* got O_BEGIN */
X#define S_END           3       /* got O_END */
X
X/* block classes */
X#define SC_DATA         1       /* DATA (variable) class */
X#define SC_NAMES        2       /* NAMES (my domains) class */
X#define SC_DOMAIN       3       /* DOMAIN TABLE class */
X#define SC_HOST         4       /* HOSTS class */
X
X#define SS_LOOK         1       /* looking for keyword or variable name */
X#define SS_IDENT        2       /* looking for identifier */
X#define SS_ASSIGN       3       /* got varname, looking for O_COMMA */
X#define SS_COMMA        4       /* got varname, looking for O_ASSIGN */
X#define SS_VALUE        5       /* got O_ASSIGN, looking for value */
X#define SS_DOMAIN1      6       /* got domain, looking for hostname */
X#define SS_DOMAIN2      7       /* got boolean, looking for domain descr. */
X#define SS_HOST1        8       /* got host, looking for boolean */
X#define SS_HOST2        9       /* got host, looking for host mailer name */
X#define SS_HOST3       10       /* got host, looking for host mailer opts */
X
X
Xstatic FILE *infp;                      /* input file pointer */
Xstatic char scbuf[1024];                /* input line buffer */
Xstatic char *scptr = NULL;              /* input line pointer */
Xstatic char *errptr = NULL;		/* error pointer */
Xstatic char sctemp1[128];               /* current identifier */
Xstatic char sctemp2[128];               /* current identifier */
Xstatic int scbool;			/* temp. boolean value */
Xstatic int lineno = 1;                  /* current line number */
Xstatic int sclass = SC_DATA;            /* temporary state */
Xstatic int state = S_LOOK;              /* state of scanner */
Xstatic int sstate = SS_LOOK;            /* secondairy state */
Xstatic int tstate = SS_LOOK;		/* triple state */
Xstatic WORD table[] = {                 /* language table */
X  { ":="    	,   O_ASSIGN    },
X  { ","     	,   O_COMMA     },
X  { "BEGIN" 	,   O_BEGIN     },
X  { "END"   	,   O_END       },
X  { "DATA"  	,   O_DATA      },
X  { "NAMES" 	,   O_NAMES     },
X  { "DOMAINS" 	,   O_DOMAIN    },
X  { "HOSTS" 	,   O_HOST      },
X};
X
X
Xextern int debug;
X
X
X/*
X * Return next character of input file;
X * also do some bookkeeping for error-recovery.
X */
Xstatic int nextch(void)
X{
X  register int ch;
X
X  ch = fgetc(infp);
X  if (ch == '\n') {
X	lineno++;
X	*scptr = '\0';
X	scptr = scbuf;
X  } else *scptr++ = ch;
X  return(ch);
X}
X
X
X/*
X * Handle a syntax error.
X * Also, perform some error recovery.
X */
Xstatic void syntax(s)
Xchar *s;
X{
X  register char *bp, *ep;
X  register int ch;
X
X  ep = errptr;
X  do {
X      ch = nextch();			/* read up to end of line */
X  } while (ch!='\n' && ch!=EOF);	/* and start over on next line */
X
X  sstate = SS_LOOK;     		/* reset state machine #2 */
X
X  fprintf(stderr, "%05.5d %s\n      ", lineno, scbuf);
X  bp = scbuf;
X  ep--;
X  while (bp < ep) {
X	fprintf(stderr, " ");
X	bp++;
X  }
X  fprintf(stderr, "^ %s\n", s);
X}
X
X
X/*
X * Check the text of a keyword.
X */
Xstatic int crunch(text)
Xchar *text;
X{
X  register WORD *wp;
X
X  wp = &table[0];
X  while (wp->opcode != 0) {
X	if (!strcmp(wp->name, text)) return(wp->opcode);
X	wp++;
X  }
X  return(0);
X}
X
X
X/*
X * Decode a word, and perform some action if necessary.
X * This routine holds all the syntax grammar.
X * It is far from perfect, but it works...
X */
Xstatic void do_word(name)
Xchar *name;
X{
X  int op;               /* decoded keyword code */
X  char *s = "expected END";
X
X  op = crunch(name);
X  if (sstate == SS_LOOK) switch(op) {
X	case O_DATA:
X        	if (state==S_LOOK || state==S_END) sclass = SC_DATA;
X		  else syntax(s);
X		break;
X        case O_NAMES:
X		if (state==S_LOOK || state==S_END) sclass = SC_NAMES;
X		  else syntax(s);
X		break;
X        case O_DOMAIN:
X		if (state==S_LOOK || state==S_END) sclass = SC_DOMAIN;
X		  else syntax(s);
X		break;
X        case O_HOST:
X            	if (state==S_LOOK || state==S_END) sclass = SC_HOST;
X              	  else syntax(s);
X		break;
X        case O_BEGIN:
X            	switch(sclass) {
X                	case SC_DATA:
X                	case SC_DOMAIN:
X                	case SC_HOST:
X			case SC_NAMES:
X                		sstate = SS_LOOK;
X                		state = S_BEGIN;
X                		break;
X                	default:
X                    		syntax("expected class prefix");
X                    		break;
X            	}
X            	break;
X        case O_END:
X            	if (state == S_BEGIN) {
X			state = S_LOOK;
X			sclass = 0;
X	    	} else syntax("expected BEGIN");
X            	break;
X        default:
X            	sstate = SS_IDENT;
X            	break;
X  }
X  switch(sstate) {
X    	case SS_LOOK:		/* propagated from the above switch() */
X        	break;
X	case SS_IDENT:      	/* looking for identifier */
X		switch(sclass) {
X			case SC_DATA:
X			case SC_HOST:
X			case SC_DOMAIN:
X    				strcpy(sctemp1, name);
X				sstate = SS_ASSIGN;
X		        	break;
X			case SC_NAMES:
X				add_name(name);
X				sstate = SS_LOOK;
X				break;
X			default:
X				syntax("expected BEGIN or CLASS");
X		}
X		break;
X    	case SS_ASSIGN:     	/* looking for O_ASSIGN */
X		op = crunch(name);
X        	if (op == O_ASSIGN) switch(sclass) {     /* found O_ASSIGN */
X            		case SC_DATA:
X                		sstate = SS_VALUE;
X                		break;
X            		case SC_DOMAIN:
X                		sstate = SS_DOMAIN1;
X                		break;
X            		case SC_HOST:
X                		sstate = SS_HOST1;
X                		break;
X            		default:
X                		break;
X       		 } else syntax("expected ASSIGN");
X        	break;
X	case SS_COMMA:		/* field separator */
X		op = crunch(name);
X		if (op == O_COMMA) switch(sclass) {
X			case SC_DOMAIN:
X				sstate = SS_DOMAIN2;
X				break;
X			case SC_HOST:
X				switch(tstate) {
X					case SS_HOST1:
X						sstate = SS_HOST2;
X						break;
X					case SS_HOST2:
X						sstate = SS_HOST3;
X						break;
X					default:
X						syntax("no comma here");
X						break;
X				}
X				break;
X			default:
X				syntax("no comma here");
X				break;
X		} else syntax("expected COMMA");
X		break;
X    	case SS_VALUE:      	/* looking for value */
X        	add_var(sctemp1, name);
X        	sstate = SS_LOOK;
X        	break;
X	case SS_DOMAIN1:		/* looking for route hostname */
X		strcpy(sctemp2, name);
X		sstate = SS_COMMA;
X		break;
X   	case SS_DOMAIN2:		/* looking for host route */
X        	add_route(sctemp1, sctemp2, name);
X        	sstate = SS_LOOK;
X        	break;
X    	case SS_HOST1:		/* looking for host 'smart' boolean */
X        	scbool = boolean(name);
X		sstate = SS_COMMA;
X		tstate = SS_HOST1;
X        	break;
X    	case SS_HOST2:		/* looking for host mailer name */
X		strcpy(sctemp2, name);	/* mailer name */
X        	sstate = SS_COMMA;	/* look for mailer opts */
X		tstate = SS_HOST2;
X        	break;
X    	case SS_HOST3:		/* looking for host mailer opts */
X		add_host(sctemp1, scbool, sctemp2, name);
X		sstate = SS_LOOK;
X        	break;
X    	default:		/* this can't be for real! */
X        	syntax("Huh? You must be joking!");
X        	break;
X  }
X}
X
X
X/*
X * This is the Configuration File Scanner.
X * It has *some* level of intelligence, but is must
X * be improved a lot.
X */
Xint scanner(fname)
Xchar *fname;
X{
X  char wordbuf[512];
X  register char *bp = wordbuf;
X  register int ch;
X  register int quote = 0;
X  register int stopped = 0;
X
X  infp = fopen(fname, "r");
X  if (infp == (FILE *)NULL) return(-1);
X
X  scptr = scbuf;
X  ch = nextch();
X  do {
X      switch(ch) {
X 	case '#':   /* comment, skip rest of line */
X        	do {
X                    ch = nextch();
X            	   } while (ch != '\n');
X            	break;
X        case ' ':   /* SPACE */
X        case '\t':
X            	if (quote == 0) {
X			errptr = scptr;
X                	do {    /* skip rest of leading space */
X                    	    ch = nextch();
X                	   } while (ch==' ' || ch=='\t');
X                	*bp = '\0';
X                	if (bp != wordbuf) {
X                    		do_word(wordbuf);
X                    		bp = wordbuf;
X                	}
X            	} else {
X                    	*bp++ = ch;
X                    	ch = nextch();
X              	  }
X            	break;
X        case EOF:   /* EOF, done! */
X            	stopped = 1;
X        case '\n':  /* end-of-word marker, handle word */
X            	*bp = '\0';
X            	if (wordbuf[0]) {
X                	do_word(wordbuf);
X                	bp = wordbuf;
X            	}
X            	if (ch != EOF) ch = nextch();
X            	break;
X        case '"':   /* quote, set/reset quoting flag */
X            	quote = 1 - quote;
X            	ch = nextch();
X            	break;
X        default:    /* anything else: text */
X            	*bp++ = ch;
X            	ch = nextch();
X            	break;
X      }
X  } while (!stopped);
X
X  fclose(infp);
X
X  return(0);
X}
END_OF_SHAR
fi
echo "		End of archive"
rm -f /tmp/uudecode
exit 0
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+
| MINIX User Group (Holland)   UUCP: hp4nl!kyber!minixug!waltje	|
| c/o Fred van Kempen,		 or: minixug!waltje@kyber.UUCP	|
| Hoefbladhof  27						|
| 2215 DV  VOORHOUT						|
| The Netherlands	"A good programmer knows his Sources"	|
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+