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> ! MV*, %!34>C$!(/$!E#HD#95B>505E>+?@2)_H \ '0;B@28/6$ ?!"*!)@] M>@!_"(H$F"T@ (@$1NO@B?CIV3I5B>505E>+?@2)_H \ '0;B@28/4$ ?!"* M!)@]6@!_"(H$F"W@_X@$1NO@B?CIJ3I5B>504%97N 0 4.@_+5N)QH,^" M=0:)-@@ ZP^+/@@ @ST = 2+/>OWB37'! _W8$Z#(P6P4" %#H#BU;B40" M_W8$_W0"Z)<P6UOI6#I5B>504%97N H 4.CN+%N)QH,^# =0:)-@P ZP^+ M/@P @ST = 2+/>OWB37'! _W8$Z.$O6P4" %#HO2Q;B40"_W8(Z,\O6P4" M %#HJRQ;B40&_W8*Z+TO6P4" %#HF2Q;B40(_W8$_W0"Z"(P6UO_=@C_= ;H M%S!;6_]V"O]T".@,,%M;BT8&B40$Z<<Y58GE4%!65[@( %#H72Q;B<:#/@X M '4&B38. .L/BSX. (,] '0$BSWK]XDUQP0 /]V!.A0+UL% @!0Z"PL6XE$ M O]V!N@^+UL% @!0Z!HL6XE$!/]V".@L+UL% @!0Z @L6XE$!O]V!/]T NB1 M+UM;_W8&_W0$Z(8O6UO_=@C_= ;H>R];6^D\.56)Y5!05E?_=@3H)OY;N 8 M4.C+*UN)QH,^"@ =0:)-@H ZP^+/@H @ST = 2+/>OWB37'! _W8$Z+XN M6P4" %#HFBM;B40"_W8&Z*PN6P4" %#HB"M;B40$_W8$_W0"Z!$O6UO_=@;_ M= 3H!B];6^G'.%6)Y5!6BS8* GV=!C_=@3_= +H.RY;6PG =07_= 3K!XLT MZ^0QP%!8Z9PX58GE5HMV!%;HA_U;"?9T#K@X %!6Z TN6UL)P'4%,<!0ZR:X M/@!05NCZ+5M;"<!U!K@! %#K$E:X1 !0_S8*#>BC'H/$!C' 4%CI3SA5B>50 M5HLV# )]G06_W8$_W0"Z,(M6UL)P'4#5NL'BS3KYC' 4%CI)3A5B>505HLV M#@ )]G06_W8$_W0"Z)@M6UL)P'4#5NL'BS3KYC' 4%CI^S=5B>504%97BWX( MBW8$_TX&?B%7Z-XG6XE&_H-^_O]T$X-^_@IU!<8$ .L(BT;^B 1&Z]J#?O[_ M=0HY=@1U!3' 4.L#_W8$6.FP-U6)Y?\V$@#_-A _W8$N& 4+@P#E#H0"&# MQ JX, [ID#=5B>505O]V!.A_'UN)Q@GV= 7_= CK!+AJ %!8Z7 W58GE4%:X M> !0Z)S^6XG&"?9U [Z" %;_=@3HE@);4+B$ %"X8 Y0Z.X@@\0(N& .Z3TW M58GE@>P !%:+=@97BWX$5[@ !%"-A@#\4.A[&X/$!@G =0+K'%:-A@#\4.C. M+%M0N $ 4(V& /Q0Z*4;@\0(Z\[I^#95B>56BW8$5N@"&EL)P'0-5N@>(5NX M 0!0Z&,R6[B* %#H#?Y;HQ @SX0 !U%;B2 %#_-@H-Z D=6UNX__]0Z#PR M6[BN %#HYOU;HQ( @SX2 !U%;BV %#_-@H-Z.(<6UNX__]0Z!4R6[C2 %#H MO_U;HQ0 N. 4.BT_5M0Z-O]6Z,6 +CJ %#HI/U;4.C+_5NC& #I8#95B>6X M\@!0_S8*#>B<'%M;Z4XV58GE@^P*5E?'1O@N 8M>!HL?@#]R=0;'!@8 0"X M1@%0_W8&_W8$Z"D;@\0&B<:#_O]T1%;K.HL.*BF)3OCKW<<&! ! .O5N'\ M4/\V*BFX$!M0Z,X@@\0&Z\''!A(< 0#KN>B&_[@! %#H93%;ZZR[&@!8Z9$S MBT8$.0:*"7P+Z&G_N/__4.A(,5NX3P!0Z!HL6_]V^.BZ_ENX3@%0N) ;4.C@ M*UM;N) ;4.CS'5NX7 %0N) ;4.AH)EM;B4;^@W[^ '40N%X!4.BY'UNX 0!0 MZ/XP6XL>B@G1XP->!O\WZ*H*6XE&^H-^^@!U!#'VZPG_=OKHQ0M;B<: /A ; M '0EN&8!4+@0&U#H%B9;6XG'"?]U%K@0&U#H:A];N $ 4.BO,%OK!(L^!@W_ M=OY7Z"H*6UO_=OY7Z-7]6UO_=O[HH"1;.3XF%5^B5)%L)]G41,<!0N! 9 M4.BF$UM;OO__ZQRXD!M0N) .4+C0#E"XT!!0N! 14.@&$X/$"HG&N) ;4.A$ M*UM6Z$<P6^F\-%6)Y8/L"(M>!(L'BT\"B4;\B4[^QP8>' QP8<' QP8: M' $ QP88' QP86' QP84' _W;^_W;\N $ 4+B 45#H4S(%! "#T@"Y M!P"9]_F)%B <N00 H1X<F??Y_W;^_W;\@_H"=0JXX@%0N "%4.L(N.$!4+B M,U"/1OB/1OK_=OK_=OCH.#0)P'P8_P8>'(M&_(M._BM&^!M.^HE&_(E._NNO M@08>'+('_W;^_W;\N $ 4+B 45#HVS&C(AS'!FH!' "Y! "A'AR9]_D)TG4$ M_P9J 8L>'!S1XXN': &9_W;^_W;\4E"X@%&Z 0#H@S)24.C*,PG ?#"+#AP< M_P8<'(G+T>.+AV@!F?]V_O]V_%)0N(!1N@$ Z%@R65LIP1G3B4[\B5[^ZZO_ M=O[_=ORX 0!0N(!14.B%,PG ?!B+1OR+3OXM@%&#V0&)1OR)3O[_!AH<Z]/_ M=O[_=OPQP%"X$ Y0Z%DS"<!\&(M&_(M._BT0#H/9 (E&_(E._O\&&!SKU/]V M_O]V_#' 4+@\ %#H+3,)P'P8BT;\BT[^+3P @]D B4;\B4[^_P86'.O4BT[\ MB0X4'(L.'AR!Z6P'BQX<'-'C_S84'/\V%AS_-A@<4?^W@ &+'B <T>/_-AH< M_[>8 ;CR 5"X)AQ0Z'$<@\02N"8<Z<$R58GE@^PR5HLV% ()]G0M_W0(C4;. M4.C@*%M;C4;.4.B4]UO_=@2-1LY0Z!PH6UL)P'4%_W0*ZP>+-.O/,<!06.E] M,E6)Y8/L,E:+-A0""?9T-O]T"(U&SE#HG2A;6XU&SE#H4?=;_W8$C4;.4.C9 M)UM;"<!U#H-\ @!U",=$ @$ 5NL'BS3KQC' 4%CI,3)5B>6#[ 965[AP E#H M8O];B<8)]G48N) ;4+AV E"X$!E0Z+0;@\0&,<!0Z<< 5KBD'%#H-"A;6[ZD M'( \ '0-@#P@= B / ET T;K[L8$ $:)=OJ)\T:X<@!04^CE&UM;B<<)_W03 MN P 4+B( E!7Z/H<@\0&"<!UV@G_=$:X( !05^C '%M;B<;&1?\ _W;ZN'0< M4.C2)UM;1E:X1!Q0Z,<G6UNXI!Q0N$0<4+B6 E"X$!50Z"$;@\0(BUX$QP<! M .LM_W;ZN'0<4.B<)UM;N)P"4+A$'%#HCR=;6[BD'%"X$!50Z((G6UN+7@3' M!P N $ 4%CI-S%5B>6#[ I65[B> E#H:?Y;B<>XI )0Z%_^6XG&"?9T! G_ M=2R#/A8 70#Z9\ C4;^4.C2_EL)P'0#Z9 N*H"4+@0&5#HU!I;6S' 4.F M %:X=!Q0Z!DG6UM7N$0<4.@/)UM;OD0<@#P = V /"!T"( \"70#1NONQ@0 MN$0<4+@0%5#HZB9;6[@A %"X1!Q0Z+<:6UN)Q@GV=!7'1OX! ,8$ $96N*0< M4.C$)EM;ZQS'1OX %>XI!Q0Z+,F6UNXQ )0N$0<4.BF)EM;_W;^6.EC,%6) MY8/L#%97BWX$QT;XQ@+'1O;. HU&_%#HX"9;C4;\4.C0^%N)1OJ#/A8 74< M_S80 (U&_%#H;?M;4+BD'%"XT@)05^AF%H/$"KBD'%#H@_A;4+BD'%#_-A MN.X"4%?H2A:#Q K_=OK_-@( _S82 /\V$ "X -05^@P%H/$#+BD'%#H3?A; M4+BD'%#H(OA;4+@X U!7Z!,6@\0(@SX4 !T#_\V% "X2@-05^C]%8/$!KA< M U#HZ?Q;B<8)]G0,5KA@ U!7Z.,5@\0&N&@#4.C/_%N)Q@GV= Q6N' #4%?H MR16#Q :X=!Q0N'X#4%?HNA6#Q :XB -05^BO%5M;Z5\O58GE@^P.5E>+?@3' M1OB* \=&]I(#C4;\4.C<)5N-1OQ0Z,SW6XE&^H,^%@ !=4^XE@-0Z*W\6XG& M@#Y$' !U'O\V$ "-1OQ0Z%CZ6U"XI!Q0N)P#4%?H416#Q KK(/\V$ "-1OQ0 MZ#KZ6U"XI!Q0N$0<4+BX U!7Z"\5@\0,N-8#4.A>_%N)Q@GV="^#/A < 747 M_W0*_S80 /]T"+C< U!7Z 45@\0*ZQ'_= K_= BXZ -05^CR%(/$"/]V^O\V M @#_-A( _S80 +CP U!7Z-@4@\0,N"@$4.@'_%N)Q@GV=">#? 0!?@__= K_ M=O97Z+<4@\0&Z]W_= K_= C_=OA7Z*44@\0(Z\NX,@10Z-+[6XG&"?9T)8-\ M! %^#_]T"O]V]E?H@A2#Q ;K$/]T"O]T"/]V^%?H<!2#Q B+-A0""?9T'X-\ M!@!U%<=$ @$ _W0*_W0(_W;X5^A-%(/$"(LTZ]VX.@10Z'C[6XG&"?9T)8-\ M! %^#_]T"O]V]E?H*!2#Q ;K$/]T"O]T"/]V^%?H%A2#Q BX/@10Z$7[6XG& M"?9T)8-\! %^#_]T"O]V]E?H]1.#Q ;K$/]T"O]T"/]V^%?HXQ.#Q BX0@10 MZ!+[6XG&"?9T)8-\! %^#_]T"O]V]E?HPA.#Q ;K$/]T"O]T"/]V^%?HL!.# MQ BX1@10Z-_Z6XG&"?9T)8-\! %^#_]T"O]V]E?HCQ.#Q ;K$/]T"O]T"/]V M^%?H?1.#Q BX3@10Z*SZ6XG&"?9T)8-\! %^#_]T"O]V]E?H7!.#Q ;K$/]T M"O]T"/]V^%?H2A.#Q BX6@10Z'GZ6XG&"?9T)X-\! %^#_]T"O]V]E?H*1.# MQ ;K(_]T"O]T"/]V^%?H%Q.#Q CK$?]V^KA@!%#_=OA7Z 03@\0(N&@$4%?H M^1);6^FI+%6)Y8'LC@165\>&?/L ,>&>OL! /]V!+@ !%"-A@#\4.B+](/$ M!@G =0/IB & O@#\ '4#Z7X!_X9\^XV& /R)AG3[N 4 4+AJ!%"-A@#\4.B2 M%X/$!@G =0/I:P"+GG3[@#\@= F+GG3[@#\)=13_AGK[C8: ^XF&=/N-A@#\ MB<;K4;@Z %#_MG3[Z"X66UN)Q@GV="S&! !&@#P = V /"!T!8 \"74#1NON M_[9T^XV&@/M0Z"HB6UO'AGK[ 0#K$HNV=/OK#,>&=/MP!(V&!?R)QK@, %#H M<1Y;B<>#/A0" '4&B3X4 NLCBPX4 HF.=ON+GG;[@S\ = R+GG;[BP>)AG;[ MZ^N+GG;[B3_'!0 _[9T^^A/(5L% @!0Z"L>6XE%"%;H/R%;!0( 4.@;'EN) M10K_MG3[_W4(Z*,A6UM6_W4*Z)HA6UO'10( (N&>ON)103'108 ,>&?OL M (N>?OO1XXNW%@+_=0B-A@#\4.AL(5M;C88 _%#H'_!;"?9T(8V& /Q05NBD M(%M;"<!U NL0_X9^^XN>?OO1XXNW%@+KVPGV=0/I9_['108! .E?_NGP*E6) MY5!05HMV!E>+?@17Z#;^6U;HH_E;B4;^@W[^ '4'5NAI^EOK!5;H9OM;BT;^ MZ;XJ58GE@>P*!%97_W8$N! 14.CE(%M;Q@:D(0#&!J0B ,:& /P Q@:D( "X M0 !0N! 14.B@%5M;B<8)]G4#Z9T Q@0 1K@0$5"XI"!0Z*H@6UM6C88 _%#H MGR!;6XV& /Q0Z(+O6[@N %"-A@#\4.AB%%M;B<8)]G5"C88 _%#H\/%;B<<) M_W0:C88 _%"XI"%0Z&4@6UO&!J0B +BD(%#IB@"-A@#\4+BD(E#H2R!;6\8& MI"$ N*0@4.MQQ@0 1HV& /Q0N*0A4.@N(%M;5KBD(E#H)"!;6[BD(%#K3[@A M %"X$!%0Z.L36UN)Q@GV="'&! !&N! 14+BD(5#H^A];6U:XI"!0Z/ ?6UNX MI"!0ZQNX$!%0N*0@4.C='UM;Q@:D(0#&!J0B +BD(%!8Z8\I58GE@>P*!%:+ M=@17@+P @!U$8V$ %0C88 _%#HJ1];6^L9C80 E"-A !4+AV!%"-A@#\ M4.C^$H/$"(V& /Q0Z/<#6PG = K&A ! ,:$ ( @+P @!U ^D2 H"\ $ M=!N-A "4(V$ %0N'P$4(V& /Q0Z+T2@\0(ZP^-A "4(V& /Q0Z#P?6UN- MA@#\4(V$ %0Z"T?6UN-A@#\B8;^^S'_BX;^^XF&_/O_MO[[Z+3P6XG'"?]T M$/^V_ON-A "4.C_'EM;ZR"X+@!0_[;\^^C*$EM;B8;^^X.^_OL =0+K!O^& M_OOKN@G_=52#/A@ '49C80 E"X@@10N! 94.@O$H/$!C' 4.D' [B8!%#H M4O!;B<<)_W4FC80 E"XF@10N! 94.@($H/$!KBP!%"X$!E0Z#826ULQP%#I MTP+_=03H]>];B8;X^X.^^/L =1?_=02XS 10N! 94.C2$8/$!C' 4.FJ HN> M^/N#?P0!= /I>@"+70: /T!U-("\ $ =1>-A "4%:XY 10N! 14.B<$8/$ M".F& (V$ %05KCJ!%"X$!%0Z(41@\0(ZW" O ! '49C80 E!6_W4&N/ $ M4+@0$5#H91&#Q KK4(V$ )0C80 5!6_W4&N/H$4+@0$5#H1Q&#Q SK,H"\ M $ =116_W4&N 8%4+@0$5#H+!&#Q CK%U:-A !4/]U!K@,!5"X$!%0Z!,1 M@\0*_W4$C80 5#HEAU;6XN>^/O_=P:XT Y0Z(8=6UN+GOC[_W<(N) .4.AV M'5M;C80 5"XT!!0Z&@=6UO'!A < 0"X 0!0Z:D!@+P 0!U ^DV <:$ ( MC80 5#HNNY;B8;X^X.^^/L = /IB@"#/A@ '49C80 5"X%@50N! 94.B+ M$(/$!C' 4.EC ;@J!5#HKNY;B<<)_W4FC80 5"X+ 50N! 94.AD$(/$!KA M!5"X$!E0Z)(06ULQP%#I+P'_=02-A "4.C4'%M;_W4$Z$3N6XF&^/N#OOC[ M '47_W4$N%P%4+@0&5#H(1"#Q 8QP%#I^0" O " '1%BY[X^X-_! %U%HV$ M %05KAT!5"X$!%0Z/8/@\0(ZQ16C80 5"X>@50N! 14.C@#X/$"(V$ )0 MC80 5#H81Q;6^L*5K@0$5#H51Q;6XV$ %0N- 04.A''%M;BY[X^_]W!KC0 M#E#H-QQ;6XN>^/O_=PBXD Y0Z"<<6UO'!A < 0"X 0!0ZVE6Z-<-6XF&]ON# MOO;[ '445KB !5"X$!E0Z&P/@\0&,<!0ZT7_-A Z&;M6XF&^/M6N! 14.CA M&UM;Q@;0$ "+GOC[_W<&N- .4.C,&UM;BY[X^_]W"+B0#E#HO!M;6\<&$!P M +@! %!8Z7(E58GE4%;_=@3H&>U;B<8)]G4%,<!0ZP2X 0!06.E4)56)Y5!6 MBS8( GV=!G_=@3_= +HQQI;6PG =0:X 0!0ZP>+-.OC,<!06.DG)56)Y8/L M$E97QT;^ "^E 7'1O"L!3' 4%;H2PE;6PG = ^X@ %05NCT%EM;4.C0&EO_ M=O!6Z)P-6UL)P'07N 4 4.C##5O_1OZ#?OX%?N(QP%#IF "XR 505NB@%5M; MB<=7N H 4(U&]%#H% F#Q 97Z$D46_]V\.@J&UN-1O10Z,$36T")1OZXR@50 M5NAM%5M;B<<)_W4%,<!0ZU#_=OZXS 505^C)"H/$!E?H#A1;@WX& '49_W;^ M_W8(_W8$N- %4+BD(U#H!0Z#Q KK&O]V_O]V!O]V"/]V!+C>!5"XI"-0Z.D- M@\0,N*0C4%CI-215B>6![(( 5HMV!%=6Z"$,6XG'"?]U(?\V$ !6N.X%4(V& M?O]0Z+8-@\0(,<!0C89^_U#HM@);6U;_=@:X& 90N @&4(V&?O]0Z)(-@\0* MC89^_U#H9 ];Z=HC58GE@>R( E:+=@175NA8_EL)P'4;5K@>!E"-1H!0Z&(- M@\0&,<!0C4: 4.AC EM;5C' 4+A" %#H>?Z#Q 90C88 _U#HS1E;6U:X3@!0 MN$, 4.A?_H/$!E"-AH#^4.BS&5M;_S80 #' 4+A$ %#H0_Z#Q 90C88 _E#H MEQE;6U:X3@!0N%@ 4.@I_H/$!E"-AH#]4.A]&5M;N#H&4(V& /Y0Z P46UN) MAGK]@[YZ_0!U$K@\!E#H6PU;N $ 4.B@'EOK+;A$!E#_=@CHXQ-;6XF&>/W_ MMGK]_[9X_>B_ZUM;_[9Z_>B)$EO_MGC]Z($26[A&!E"-A@#_4.BT$UM;B89\ M_8.^?/T =1*X2 90Z ,-6[@! %#H2!Y;ZR?_=@:-A@#^4%#_-A N&X&4+A0 M!E#_MGS]Z.T(@\0._[9\_>@O$ENX= 90C8: _E#H8A-;6XG'"?]U$KAV!E#H MM@Q;N $ 4.C['5OK,HV& /]0N+ &4(V&@/U0C88 _U"-A@#^4+BJ!E"-A@#^ M4%"X?@905^B2"(/$%%?HUQ%;N"@ 4%"-A@#_4.A*!H/$!K@H %!0C8: _E#H M.@:#Q :X* !04(V& /Y0Z"H&@\0&N"@ 4%"-AH#]4.@:!H/$!H,^$AP!=2BX MM@90C4: 4.@G&%M;5KCJ!E"XS 90C4: 4.B$"X/$"(U&@%#H5PU;,<#IRR%5 MB>6![ $5HMV#%>+?@2X =0Z*(&6[@0!U#_=@CH-!=;6PG =1Z+7@: /P!U M"597Z&+]6UOK1U97_W8&Z+']@\0&ZSK_=@K_=@BX% =0C88 _%#H'0N#Q A6 MC88 _%"-A@#^4.@,"X/$!E>-A@#^4.@\"UM;C88 _E#HTPQ;Z4DA58GE@>RH M %97N" '4(U&V%#H;Q=;6XU&V%#H@@E;N# '4(U&V%#H]Q%;6XG&N#('4+B0 M&U#HZ!%;6XG'C4;X4.B?%UN-1OA0Z$+L6U"X0 =0N#0'4%;H.P>#Q BX$!4) MP'0/N! 54+A,!U!6Z"4'@\0&N%0'4%;H&@=;6[AN!U!6Z! '6UO_=@2XG =0 M5N@#!X/$!KB@!U!6Z/@&6UM7N( 4(V&6/]0Z*3H@\0&"<!T$HV&6/]0N,8' M4%;HU0:#Q ;KVE;H&!!;5^@3$%N#?@8 =1J-1MA0N-0'4+C.!U"XS =0N! 5 M4.B3_H/$"HU&V%"X[ =0N.@'4+CF!U"XV@=0Z'G^@\0*C4;84.BY%ENXD!M0 MZ+$66[@! %#HL1M;Z28@58GE4%;_-B8IZ!006XG&@_X*=1/_!O('BQ[N!\8' M ,<&[@<F)>L,BQ[N!XGPB ?_!NX'B?#I[Q]5B>6#[ 965XL^\ ?HN?^)1OJ# M?OH*= :#?OK_=>['!O@' 0"X)B50_S;R![C,"%#_-@H-Z (&@\0(OB8E3SGW M=A"XW@A0_S8*#>CL!5M;1NOL_W8$N. (4/\V"@WHV06#Q ;IB!]5B>505K[\ M!X-\ @!T&/]V!/\TZ/P46UL)P'4%_W0"ZPB#Q@3KXC' 4%CI7!]5B>504%:+ M=@17O^8(5NC"_UN)1OZ#/O@' 70#Z=, _W;^Z<8 @S[V!P%T!X,^]@<#=0G' M!O0' 0#IM@!7Z"W_6^FN (,^]@<!= >#/O8' W4)QP;T!P( Z9< 5^@._UOI MCP"#/O8' 70'@S[V!P-U"<<&] <# .EX %?H[_Y;Z7 @S[V!P%T!X,^]@<# M=0C'!O0'! #K6E?HT?Y;ZU/_-O0'ZQC'!O@' 0#'!O8' @#K/[CT"%#HL_Y; MZS6[' A8Z3 <@S[V!P)U#L<&]@<! ,<&] < .L9N H)4.B-_EOK#\<&^ <" M .L'NRH(6.D"'/\V^ ?I;0'_-O0'ZRQ6N*8D4.B.%%M;QP;X!P, Z5L!5NB< MXUO'!O@' 0#I30&X&@E0Z$;^6^E" ;L\"%CIPAM6Z)W^6XE&_H-^_@%U*/\V M] ?K&\<&^ <% .D> <<&^ <& .D5 <<&^ <( .D, ;M*"%CIC!NX,@E0Z/[] M6^GZ %;H7/Y;B4;^@W[^ G5+_S;T!^L^QP;X!P< Z=T _S;Z!^L=QP;X!PD MZ<X QP;X!PH Z<4 N$()4.B^_5OIN@"[6 A8Z3H;N% )4.BL_5OIJ "[8@A8 MZ2@;N%X)4.B:_5OIE@!6N*8D4.A Y%M;QP;X!P$ Z8, 5K@F)%#HHQ-;6\<& M^ <$ .MQ5K@F)%"XIB10Z(SC@\0&QP;X!P$ ZUI6Z*GD6Z,D),<&^ <$ ,<& M^@<( .M$5K@F)%#H9!-;6\<&^ <$ ,<&^@<) .LL5K@F)%#_-B0DN*8D4.BR MXH/$",<&^ <! .L1N&X)4.@*_5OK![ML"%CIAQKIZQQ5B>6![ @"5E>-A@#^ MB<;'AOK] #'AOC] "XB E0_W8$Z)T-6UNC)BF#/B8I '4'N/__4.G' ,<& M[@<F)>B$_(G'5^F< .A[_(G'@_\*=?;IE@"#OOK] '4SBP[N!XD.\ ?H7_R) MQX/_('3V@_\)=/'&! "-A@#^.<9T;8V& /Y0Z O]6XV& /Z)QNM<B?B(!$;H M+_R)Q^M0QX;X_0$ Q@0 @+X _@!T#XV& /Y0Z-[\6XV& /Z)QH/__W0LZ 3\ MB<?K);@! "N&^OV)AOK]Z/+[B<?K$XGXB 1&Z.;[B<?K![N&"%CIOAF#OOC] M '4#Z4___S8F*>B'"ULQP%!8Z>@;58GE5HMV!#' 4%!6_W8(_W8&5N@1&5M0 MN! 4+@! %#H/1B#Q!#IP!M5B>7_=@3_=@:X(0!0N $ 4.A>&(/$".FG&U6) MY5!05E>+=@2+1@8M 0")1@:#?@8 =AC_=@CH@ M;B<>#__]T"HGXB 1&@_\* M==F#__]U"CEV!'4%,<!0ZP;&! #_=@18Z5L;58GE4%!65S'V@WX& '0T.78( M=B^+?@:+7@3_1@2*!YC_=@I0Z,H56UN+7@KV1P00= -6ZP^)^"T! (G'"?]U MUT;KS%98Z1,;58GE_W8$,<!0N P 4+@! %#HLA>#Q CI^QI5B>504%97BWX& MQP8J*0 @SZ."0!T#(L>C@F /P!T ^EQ (,^B@D =03_!HH)BT8$.0:*"7T? MBQZ*"='C ?N+'X _+740BQZ*"='C ?N+'X!_ 0!U![C__U#IXP"+'HH)T>,! M^[B0"5#_-^@5$%M;"<!U"_\&B@FX__]0Z<$ BQZ*"='C ?N+'X/# 8D>C@G_ M!HH)BQZ."?\&C@F*!XA&_YBC*"F84/]V".A@!%M;B<8)]G0&@'[_.G4B@SZ, M"0!T%8I&_YA0_S6XE E0_S8*#>AP (/$"+@_ %#K8T: /#IU6(L>C@F /P!T M$(L.C@F)#BHIQP:."0 ZS^+1@0Y!HH)?12+'HH)T>,!^XL/B0XJ*?\&B@GK M(H,^C D =!6*1O^84/\UN*P)4/\V"@WH$@"#Q BX/P!0ZP6*1O^84%CIM1E5 MB>56BW8$C48(4/]V!E;H@A&#Q ;V1 1 = 56Z&056^F3&56)Y8U&!E#_=@3_ M-@@-Z& 1@\0&BQX(#?9'!$!T"/\V" WH.Q5;Z6L958GE@S[2"0!\$3' 4%!0 M_S;2">AE"X/$".L/,<!0N,8)4.@\#UM;H]()QP8Z*0 H=()Z34958GE@S[2 M"0!\"/\VT@GH_ Y;QP;2"?__QP8Z*0 Z10958GE@S[2"0!]#.B<_PG ?04Q MP%#K;<<&/"E +?\..BE_)[@ !%"X0"E0_S;2">CS#H/$!J,Z*8,^.BD ?P4Q MP%#K0,<&/BE *8L>/BG_!CXI,<"*!U"+'CPI6(@'_P8\*8L>/BF /PIULO\& M/BG_#CHIBQX\*<8' ,<&/"E +;@! %!8Z8T858GEBQX\*8 _.G0&_P8\*>OQ MBQX\*<8' /\&/"GI;1A5B>7H4_\)P'4%,<!0ZU2+#CPIB0XL*>C&_XL./"F) M#BXIZ+O__S8\*>A=!UNC,"GHK?__-CPIZ$\'6Z,R*>B?_XL./"F)#C0IZ)3_ MBPX\*8D.-BGHB?^+#CPIB0XX*;@L*5!8Z08858GE4%;HD_[HCO^)Q@GV= [_ M=@3_-.AU#5M;"<!UZ>BO_@GV= -6ZP,QP%!8Z=4758GE4%;H8_[H7O^)Q@GV M= B+1@0Y1 1U[^B%_@GV= -6ZP,QP%!8Z:L758GE@^P&5E?H,@")QXMV!(GS M1H _ '0"Z_9.3H \6'46N0H B?B9]_F#PC"(%(GXF??YB<?KY(M&!.EM%U6) MY3' 4%!04%!0N!0 4#' 4.C0$X/$$.E4%U6)Y5:+=@97BWX$,<!05E=05NA\ M%%M05^AV%%M0N D 4+@! %#HHA.#Q!#I)!=5B>7I(!=5B>6#[ 965X-^! !U M!C' 4.EW #' 4.AU %N)Q@GV= 4Y=@1S1;@#)%"X#@!0Z%$%6UN)1OK_=@3H M4P!;Z&P ,<!0Z$D 6XG'_W;ZN X 4.@O!5M;.78$<PZ+1@0I^"GP]]A0Z"@ M6U?K(%;H( !;Z#D ,<!0Z!8 6XG'5^@/ %N)\"GX*T8$]]A06.F/%E6)Y3' M4%!04%#_=@2X&P!0,<!0Z/ 2@\00Z70658GE,<!04%!04%"X'0!0,<!0Z-42 M@\00Z5D658GE@^P*5HMV!,=&]O__QT;Z@@")=OR)=OZ-1@A0_W8&C4;V4.@. M#H/$!HU&]E QP%#HN!!;6XGPZ1P658GE4%:+=@17BWX&B7;^@#P = -&Z_B M/0!T"HG[1XH'B 1&Z_'&! "+1O[I[!55B>56BW8$B@284(I&!IA9.<%U U;K M"XGS1H _ '7H,<!06.G'%56)Y5:+=@2#/G V 'P'@SYP-B-\%+@. %"X;@Q0 MN ( 4.CX$8/$!NM85NA7 %M05K@" %#HY1&#Q :X @!0N'X,4+@" %#HTQ&# MQ :+'G VT>/_M]0)Z"L 6XL><#;1XU#_M]0)N ( 4.BP$8/$!K@! %"X@@Q0 MN ( 4.B>$8/$!NE#%56)Y5!65XM^!#'VB?M'@#\ = -&Z_6)\.DG%56)Y5!6 M5XM^!HMV!(-^" !^)8G[1XH'B 1&F G = ?_3@AT NOL@WX( '0+_TX(= ;& M! !&Z_6+1@3IZA15B>505HMV!%<Q_XH$F%"*1@:863G!=0*)]XGS1H _ '7I MB?CIPQ15B>56BW8$5XM^!H-^" !_!3' 4.LOB?-&B@>8B?M'4(H'F%DYP740 M@'S_ '0%_TX(=>,QP%#K#8I$_YA0BD7_F%DIP5%8Z7H458GE@^P*5E?HN *) MQ@GV=2 QP%#_=@2XD Q0N(P,4+B$#%#H<P"#Q JX?P!0Z-$/6PGV?0:X ']0 MZUJX 0!0N ( 4.B8 EM;B4;XN $ 4+@# %#HB );6XE&]HU&_E#H.Q!;B<<Y M_G0'@___= +KZX/__W4%QT;^____=OBX @!0Z%H"6UO_=O:X P!0Z$X"6UO_ M=OY8Z>$358GE_S8 (U&!E#_=@3H1 "#Q ;IS!-5B>505HU&!HG&B?.#Q@*# M/P!T NOT_S2-1@90_W8$Z!P @\0&Z:,358GE_S8 /]V!O]V!.@& (/$!NF. M$U6)Y8'L% A65\>&\O< ,>&\/< (M&!HF&_O>+1@B)AOSWBY[^]X.&_O<" M@S\ = ;_AO+WZ^R+GOSW@X;\]P*#/P!T!O^&\/?K[(N&\/<#AO+WT> %!@"- MG@#X <.)WHN>\O<!\P.>\/>-1@ YPW(-QP9P-@< N/__4.DG 8V& /B)QXN& M\O>)!8/' L>&]/< (N&\O<YAO3W?5:-A@#XB?$IP8F.[/>+ANSWB06#QP*+ M7@:#1@8"BP>)AO;WBY[V]X _ '0ABY[V]_^&]O>*!X@$1HU& #G&<N/'!G V M!P"X__]0Z;P Q@0 1O^&]/?KH,<% "#QP+'AO3W "+AO#W.8;T]WU5C88 M^(GQ*<&)CNSWBX;L]XD%@\<"BUX(@T8( HL'B8;V]XN>]O> /P!T((N>]O?_ MAO;WB@>(!$:-1@ YQG+CQP9P-@< N/__4.M0Q@0 1O^&]/?KH<<% "#QP*- MA@#XB?$IP4&[ @")R)GW^]'@B8;N]S' 4(V& /A0_W8$,<!0_[;N]_]V!.@V M#UM0N#L 4#' 4.AC#H/$$%!8Z>,158GE5HMV!#' 4+A +E!6,<!0N 8 4%;H M" ];4+@[ % QP%#H-0Z#Q!#IN!%5B>4QP%!04%!04+@" % QP%#H&@Z#Q!#I MGA%5B>504%:+=@97BT8$T> M @")PXN_1BZ+3@2)#C(-@_X!= 0)]G4&B38\ M#>L4BT8$T> M @")PXFW1B['!CP-%"JX, !0,<!0Z$\.6UN)1OZ#?OX ?1.+ M1@31X"T" (G#B;]&+O]V_NL;BT8$T> M @")PXFW1BZ#?OX!=0:X 0!0ZP%7 M6.D3$5!345)65U4>!HGCBU\2B=A+ =N+GT8N_S8P#5#_TUB/!C -!Q]=7UY: M65M8CP:4#,]5B>6#[ 96BW8$5S'_QT;Z "*!)BC9BZ#/F8N('0<@SYF+@ET M%8,^9BX-= Z#/F8N"G0'@SYF+@QU T;KU( \+74&1L=&^@$ B?-&B@>8+3 MB4;\@W[\"G,,N H ]^>)QP-^_.OB@W[Z '0'B?CWV%#K 5=8Z6D058GE4%97 MBWX$,?:#_A1]&8GST>,YOP8-=0R)\]'CQX<� ZP-&Z^*#_A1\!KC__U#K M*U?H_PM;_S7H!09;]D4$('0-@WT& '0'_W4&Z+D$6X/^ GX%5^BO!%LQP%!8 MZ08058GE4%:+=@3V1 08= >X__]0Z<0 .38˦BQX(#8-_ @!^"/\V" WH MJ M;]D0$ 74G]D0$ W4'N/__4.F9 %;HD M;QT0" "+1 :)1 B!9 3]_X%, M! $ @WP" ']1]D0$!'05N $ 4(U&_E#_-.BE!8/$!HE$ NL2N $4/]T!O\T MZ)$%@\0&B40"@WP" '\8@WP" '4'@4P$" #K!8%,!! N/__4.LNBT0&B40( MBT0"2(E$ O9$! 1T"8M&_B7_ %#K$HM$"(G#@\,!B5P(B<,QP(H'4%CI*@]5 MB>6#[ A65\=&^ ,?^)^]'C@[\�!T#H/_%'P&,<!0Z?@ 1^OGBUX&B@>8 M4.F5 (%.^ ( N+8!4/]V!.C@ %M;B4;Z@W[Z 'P#Z7\ ,<!0Z<@ @4[X @"X M 0!0_W8$Z+T$6UN)1OJ#?OH ?2*#/G V G45N+8!4/]V!.BA %M;B4;Z@W[Z M 'T&,<!0Z8P N ( 4#' 4%#_=OKHG "#Q CK*H%.^ $ ,<!0_W8$Z&\$6UN) M1OJ#?OH ?1$QP%#K6S' 4.M6NY8,6.D8#+@* %#H^ !;B<8)]G4%,<!0ZSS' M1 ( (M&^HD$BT;XB40$N $4.C5 %N)1 :#? 8 =0>!3 0$ .L%@4P$( "+ M1 :)1 B)^]'CB;<ɖZ0@.58GE_W8$_W8&N @ 4+@! %#HIPJ#Q CI\ U5 MB>505HM.!(D.,@V+3@:+5@B)#C@-B18Z#8M."HD.- VX$P!0N $ 4.C!"EM; MB<8)]G0'B?"94E#K"/\V.@W_-C@-6%KIIPU5B>505HL.:BX#3@2!P?\#@>$ M_(G..39J+G<)5NB7 EL)P'0%,<!0ZQR+'FHNB7?^QT3^ #_-FHNZ H"6XDV M:BZX 0!06.E=#56)Y8/L#%97@WX$ '4%QT8$ @#'1O0 (-^] )R ^FM (M& M!$ E_O\% @")1O:#/FPN '4BN 0 4.AH EN)QHGP0"7^_XG&@\8"B39L+HDV M:B['1/X ,=&_@ BS9H+@GV=%>+1/Z)1OJ+7O8!\XG?.7[Z<P+K/(M&^HU- M CG!<P^+1OJ)1?Z)?/Z+!(D%B3PY-FPN=@4QP%#K-8-^_@!T"8L$BU[^B0?K M!HL,B0YH+E;K'8EV_HLTZZ7_=O;H]?Y;"<!U NL&_T;TZ4K_,<!06.F'#%6) MY8/L#%97BT8&0"7^_P4" (E&]HM>!(M'_HE&^HM&^BM&!(E&],=&_@ BS9H M+@GV=#PY=OIS NLU.7;Z=2F+7@2+1/Z)1_Z#?OX = F+!(M>_HD'ZP:+#(D. M:"Z+7@2+1_Z)1OKK!XEV_HLTZ\"+7O8#7@2)WSE^^G(@BT;ZC4T".<%S$8M& M^HE%_HM>!(E__E?HD0!;_W8$ZR?_=@;HB/Y;B<<)_W4%,<!0ZQ7_=O17_W8$ MZ \ @\0&_W8$Z&8 6U=8Z;\+58GE5HMV!E>+?@2+1@C_3@@)P'0*B?M'B@>( M!$;K[.F="U6)Y5!05E>+1@3W9@:)1@3_=@3H*_Y;B<8)]G4%,<!0ZQB)]XM& M!(G!@^D!B4X$"<!T!L8% $?KZU98Z5\+58GE4%!65S'_BS9H+@GV= TY=@1S M NL&B?>+-.OOBUX$B3<)_W0'BT8$B07K!XM.!(D.:"X)]G08BUX$.7?^=1"+ M7@2+1/Z)1_Z+!(M>!(D'"?]T&(M&!#E%_G40BUX$BT?^B47^BUX$BP>)!>GO M"E6)Y5!6,<!04/]V!%!04+@1 % QP%#H3@>#Q!")Q@GV=0V+#D -B0[F##' M4.L$N/__4%CIN0I5B>504%97BS[F#(M>! ,>Y@R)WH-^! !^!#GW=PJ#?@0 M?0HY]W,&N/__4.L05NB7_UL)P'4#5^L$N/__4%CI=@I5B>56BW8$5XM^!HH$ MF%"*!9A9.<%T#8H$F%"*!9A9*<%1ZPZ / !U!3' 4.L$1D?KV5CI0 I5B>50 M5HMV!%>)]X \ '0#1NOXB? I^.DF"E6)Y3' 4%!04%#_=@2X!@!0N $ 4.B& M!H/$$.D*"E6)Y?]V!/]V!K@% %"X 0!0Z*<&@\0(Z? )58GE4%8QP%!0_W8& M4/]V"/]V!+@# %"X 0!0Z$@&@\00B<:)\.G'"56)Y5!6BW8$5XM^!HEV_H ] M '0*B?M'B@>(!$;K\<8$ (M&_NF?"56)Y3' 4%!04%#_=@2X/ !0N $ 4.C_ M!8/$$.F#"56)Y?]V!#' 4+@* %"X 0!0Z" &@\0(Z6D)58GE@^P&5E>+?@0Q MP%!04%!04+@- %"X 0!0Z,$%@\00B<:#/C - 'P$"?9T%(L., WWV8D.<#:X M__]0N/__4.LCBPXX#8L6.@V)3OJ)5OP)_W0+BT;ZBT[\B06)30+_=OS_=OI8 M6NG]"%6)Y5!05E>+7@2#PPN)WHM&!C'2]W8(B=>#QS"#_SE^ X/'!TZ)^(@$ MBT8&,=+W=@B)1@:#?@8 ==6+7@0I\X/#"XG?B?-&,<"*!U"+7@18B ?_1@1/ M"?]UZHM&!.F="%6)Y5!05E>+7@2#PPN)WHM&"IG_=@C_=@924.A>!XG'@\<P M@_\Y?@.#QP=.B?B(!(M&"IG_=@C_=@924.C+!HE&!HE6"/]V"/]V!C' 4%#H MP@4)P'6YBUX$*?.#PPN)WXGS1C' B@=0BUX$6(@'_T8$3PG_=>J+1@3I(0A5 MB>6#["165XM>!O]&!HH'F(G'"?]U ^D'"(/_)70+_W8$5^B1 EM;Z]Z-1O2) MQHU&](E&\,=&Y BUX&@#\M=0;_1@;_1N3'1N(@ (M>!H _,'4(_T8&QT;B M, #'1NH (M>!O]&!HH'F(G'@_\P? J#_SE_!8/O,.L.@_\J=1>+7@B#1@@" MBS^X"@#W9NJ)1NH!?NKKRL=&Y@ QT;H "#_RYU.8M>!O]&!HH'F(G'@_\P M? J#_SE_!8/O,.L.@_\J=1J+7@B#1@@"BS^X"@#W9NB)1N@!?NC_1N;KQ\=& MX @_]L= 6#_TQU%O]&X(M>!H _ '0+BUX&_T8&B@>8B<=7Z1<!_T;@OQ MZP[_1N"_"@#K!O]&X+\( (-^X !T&8M>"(-&" 17_W<"_S=6Z$[^@\0(B<;I MZ0"+7@B#1@@"5_\W5NC8_8/$!HG&Z=, _T;@@W[@ '0\BUX(@T8(!(L'BT\" MB4;<B4[>@W[> 'T.Q@0M1O=>W/=>WH->W@"X"@!0_W;>_W;<5NCS_8/$"(G& MZ8X BUX(@T8( HL'B4;L@W[L 'T'Q@0M1O=>[+@* %#_=NQ6Z&?]@\0&B<;K M8\=&XB Q@0_1NM8QT;B( "+7@B#1@@"BP>(!$;K1<=&XB BUX(@T8( HL' MB4;P@W[P '4%QT;PW@R#?N@ =07'1NC_?XMV\( \ '06_T[H?!%&Z_.)^(@$ M1NL'NZ8,6.FW XGP*T;PB4;LBT;J*T;LB4;J@W[J 'T%QT;J "#?N0 =0/W M7NJ#?NH ?3.+7O" /RUU&X-^XC!U%8M>\/]&\(H'F/]V!%#H1P!;6_].[/]V M!/]VXN@Y %M;_T;J=?#_3NQ\%(M>\/]&\(H'F/]V!%#H'0!;6^OG@W[J '4# MZ6']_W8$_W;BZ < 6UO_3NKKYU6)Y5!05HMV!E<Q__9$!!AT![C__U#IJP#V M1 0"=0>X__]0Z9X ]D0$!'0;N $ 4(U&!%#_-.B' 8/$!HE&_L=$ @$ 1^M( MQP9N+H4VBT0(B<.#PP$QR8I.!%&)7 B)PUB(!XM$ D")1 *!? ( !'P>]D0$ M@'48_W0"_W0&_S3H/@&#Q :)1OZ+1 :)1 A'"?]T*X-^_@!^"(M&_CE$ G08 M@W[^ 'T'@4P$$ #K!8%,! @ N/__4.L+QT0" QP(I&!%!8Z:($58GE4%8Q M]H/^%'T:B?/1XX._!@T = R)\]'C_[<&#>A. %M&Z^'I>@15B>6#/FXN '0& MBPYN+O_1,<!04%!04/]V!+@! % QP%#HS0"#Q!#I4015B>4QP%!04%!0_W8$ MN $ 4#' 4.BP (/$$.DT!%6)Y5!6BW8$5_9$! 1U!O9$! )U!3' 4.LW@WP" M '\%,<!0ZRS_= +_= ;_-.A8 (/$!HG'.7P"=0['1 ( (M$!HE$"%?K"8%, M!! N/__4%CIW0-5B>505E>+?@0QP%!04%!04+@' % QP%#H.@"#Q!")Q@GV M? H)_W0&BPXR#8D-B?#IJ@-5B>4QP%!0_W8&4/]V"/]V!+@$ %"X 0!0Z 8 M@\00Z8H#58GEBTX(B0XR#8M."HD.- V+3@R)#C8-BTX.B0XX#8M.$(D..@V+ M3A*)#CP-_W8&_W8$Z%$ 6UOI3P-5B>504%97_W8*Z'\ 6XG'B3XR#8M."(D. M- V+3@J)#C8-OC@-@_\.?Q2)^$\)P'0-BUX*_T8*B@>(!$;K[/]V!O]V!.@% M %M;Z0$#58GE4%:+3@:)#C -N"X-4/]V!.A0 %M;B<8)]G0#5NL;@SXP#0!] M$(L., WWV8D.<#:X__]0ZP3_-C -6.G" E6)Y5!6BW8$5S'_B?-&@#\ = -' MZ_6)^$#II0*Y 0#K"KD" .L%N0, ZP!5B>6+1@2+7@;-(%W#6UE:6%:)YH=< M EXYTW</<@8YR'<)= 2X___#,<##N $ PXL7*T<".T<$=PO1X '#BU\&A=MU M#8G3A=MU![@4 %#I>0'_XXL7BT\"@\,$27P4.P=U]HM? H7;=0>X% !0Z5H! M_^.)T^OO5E>)YHM<!HM$")F)USG"=38ATGT$]]MT+C'2BTP*BT0,(<!]"/?8 M]]D9T/?7]_.1]_,A_WT']]GWV(/9 (G*7UY;@\0(_^-2B<<QVR'_?0?WW_=< M!AG?BT0*BU0,(=)]"??:]]@9VO=4_KD0 -'@T=+1TSG?=P=R"3E4!G8$XNWK M""M4!AG[0.+C7^NE5E>)YHM<!HM$" G =1<QTHM,"HM$#/?SD??SB<I?7EN# MQ C_XXG',=N+1 J+5 RY$ #1X-'2T=,YWW<'<@DY5 9V!.+MZ]0K5 89^T#B MX^O*B>-2B<'W9P1:4(G0]V<"6@'"B<B)T?=G @'*6X/$!/_C5E>)YHM<!HM$ M" G =1LQTHM,"HM$#/?SD??S,=N)T(G:7UY;@\0(_^.)QS';BT0*BU0,N1 MT>#1TM'3.=]W!W().50&=@3B[>O2*U0&&?M XN/KR.A9 .C# +@& +IP#>LP MN!( NH<-ZRBX% "ZG@WK(+@! +JU#>L8N ( NLP-ZQ"X$@"ZX@WK"+@1 +KY M#>L ,=N''B8.A=MT!5#_TUC#NQ8 4U*X @!0Z#L Z/?[B<*#^A5S$='BNT8- M =.+'X7;= 2)VNL>NQ<.N08 B<*!X@< Q8P (@72]'ZT?K1^N+MN@D.ZZI5 MB>7'!G0V! "+7@2)'G8VBUX(B1YX-HM>!HD>?#:X<C90N $ 4+@! +MR-KD# M ,T@B>Q=P^B'^U]>B>Q=PUY?Z_A;65I85HGFAUP"7CG3?P]\!CG(=PET!+C_ M_\,QP,.X 0## +@ M /P4$ &, $@5D !L%:0 C!6X -P4R+C4O34E.25@ 1D%,4T4 5%)510 M0F%D('9A;'5E(&]F(&)O;VQE86XZ("(E<R(* "5S0"5S+B5S !U;FMN;W=N 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" | +-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+