home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume33 / mailagnt / part11 < prev    next >
Encoding:
Text File  |  1992-11-20  |  54.7 KB  |  1,665 lines

  1. Newsgroups: comp.sources.misc
  2. From: ram@eiffel.com (Raphael Manfredi)
  3. Subject:  v33i103:  mailagent - Rule Based Mail Filtering, Part11/17
  4. Message-ID: <1992Nov20.230639.26768@sparky.imd.sterling.com>
  5. X-Md4-Signature: 744e1c0236b797ca913d70c4db8080bf
  6. Date: Fri, 20 Nov 1992 23:06:39 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: ram@eiffel.com (Raphael Manfredi)
  10. Posting-number: Volume 33, Issue 103
  11. Archive-name: mailagent/part11
  12. Environment: Perl, Sendmail, UNIX
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then feed it
  16. # into a shell via "sh file" or similar.  To overwrite existing files,
  17. # type "sh file -c".
  18. # Contents:  agent/examples/rules agent/files/filter.sh
  19. #   agent/filter/Makefile.SH agent/maillist.SH agent/pl/hook.pl
  20. #   agent/pl/rules.pl config.h.SH
  21. # Wrapped by kent@sparky on Wed Nov 18 22:42:25 1992
  22. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  23. echo If this archive is complete, you will see the following message:
  24. echo '          "shar: End of archive 11 (of 17)."'
  25. if test -f 'agent/examples/rules' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'agent/examples/rules'\"
  27. else
  28.   echo shar: Extracting \"'agent/examples/rules'\" \(7239 characters\)
  29.   sed "s/^X//" >'agent/examples/rules' <<'END_OF_FILE'
  30. X#
  31. X# Rule file for mailagent
  32. X#
  33. X
  34. X# The 'maildir' variable tells the mailagent where the folders are located.
  35. X# By default, it is set to ~/Mail (because it is a convention used by other
  36. X# mail-related programs), but the author prefers to use ~/mail.
  37. X
  38. Xmaildir = ~/mail;
  39. X
  40. X# The 'mailfilter' variable points to the place where all the loaded files
  41. X# are stored (e.g. loaded patterns or addresses) and is used only when a
  42. X# relative path is specified.
  43. X
  44. Xmailfilter = ~/mail;
  45. X
  46. X# This set of rules catches command mails early in the process.
  47. X# Currently, only the author, whose login name is 'ram', is allowed to use
  48. X# this feature. All others get a message explaining why their command was
  49. X# rejected (political reasons), and then the message is processed normally
  50. X# by the other set of rules. Note how the BEGIN and REJECT commands
  51. X# inefficiently replace the missing if/else structure.
  52. X
  53. XAll: /^Subject:\s*[Cc]ommand/    { BEGIN CMD; REJECT };
  54. X<CMD> From: ram            { STRIP Received; SAVE cmds; PROCESS };
  55. X<CMD> *                    { BEGIN INITIAL; MESSAGE ~/tmp/nocmds; REJECT };
  56. X
  57. X# Here, I am turning a mailing list into a newsgroup by locally posting the
  58. X# messages I get, so that others can read them too. I have configured inews to
  59. X# mail me any follow-up made into this group, and those are caught with the
  60. X# next rule and bounced directly to the mailing list... which will of course
  61. X# resend the message to me. But the BOUNCE operation left an ``X-Filter'' field
  62. X# in the message and the mailagent enters in the special seen mode, recognizing
  63. X# an already filtered message. The third rule then simply deletes those
  64. X# duplicates.
  65. X
  66. XTo Cc: gue@eiffel.fr            { POST -l mail.gue };
  67. XApparently-To: ram,
  68. XNewsgroups: mail.gue            { STRIP Apparently-To; BOUNCE gue@eiffel.fr };
  69. X<_SEEN_> Newsgroups: mail.gue    { DELETE };
  70. X
  71. X# The MH users mailing list. I am the sole reader of this list. In the past,
  72. X# I used to get some duplicate messages, but since I've added the UNIQUE
  73. X# command, I havn't seen any... weird! :-)
  74. X
  75. XTo Cc: /^mh-users@ics.uci.edu$/i
  76. X    { STRIP Received; UNIQUE -a; SAVE comp.mail.mh };
  77. X
  78. X# This mailing list is a digest version of the comp.unix.wizards newsgroups.
  79. X# It is not perfectly RFC-934, but close, so I simply discard the original
  80. X# message and delete the header which is only the table of contents... Well,
  81. X# I'm not sure there hasn't been any changes...
  82. X
  83. XTo Cc: /^unix-wizards@.*brl.mil$/i
  84. X    { STRIP Received; SPLIT -id unix-wiz };
  85. X
  86. X# Those are news from the French embassy, which are forwarded to us "froggies".
  87. X# I am forwarding this list to all the French people who are working in this
  88. X# company (they are all listed in the file ~/mail/frog-list) and I keep a
  89. X# copy for myself, of course.
  90. X
  91. XTo Cc: /^.*frog:;@guvax.georgetown.edu$/i
  92. X    { FORWARD "frog-list"; STRIP Received; SAVE frog };
  93. X
  94. X# This mailing list is not at all RFC-934, but it usually has no headers. The
  95. X# moderator prefers to add some comments at the end of the digest, hence the
  96. X# -w flag, mainly to keep the trailing garbage.
  97. X
  98. XTo Cc: /^magic@crdgw1.ge.com$/i
  99. X    { STRIP Received; SPLIT -eiw magic };
  100. X
  101. X# The following mailing list used to forward messages from many newsgroups,
  102. X# but not all of them are valid now, and Paul Vixie is talking about moving
  103. X# the src list to pa.dec.com. Anyway, I am filtering the messages according
  104. X# to the ``Newsgroups'' field.
  105. X
  106. XTo Cc: /^unix-sources.*@.*brl.mil$/i
  107. X    { STRIP Received; BEGIN SRC; REJECT };
  108. X
  109. X<SRC> Newsgroups:
  110. X        comp.sources.unix,
  111. X        comp.sources.misc        { SAVE unix-src/src }
  112. X        comp.sources.games        { SAVE unix-src/games }
  113. X        comp.sources.x            { SAVE unix-src/x }
  114. X        comp.sources.bugs        { SAVE unix-src/bugs }
  115. X        comp.sources.wanted        { SAVE unix-src/wanted };
  116. X<SRC> *                            { SAVE unix-src/other };
  117. X
  118. X# Other mailing list, with nothing particular. Ftpmail is not really a mailing
  119. X# list, nor is it a valid user name, hence the regular not anchored regular
  120. X# expression.
  121. X
  122. XTo Cc: rdb-interest        { STRIP Received; SAVE rdb };
  123. XFrom: /ftpmail/i        { STRIP Received; SAVE ftp.mail };
  124. X
  125. X# I am working with Harlan Stenn on the dist 3.0 release, and I automatically
  126. X# forward to him every mail with the word ``metaconfig'' in the subject.
  127. X# I avoid mailing him back his own mails though.
  128. X
  129. XFrom: harlan, To Cc: ram    { SAVE dist };
  130. XSubject: /metaconfig/i        { BEGIN DIST; REJECT };
  131. X<DIST> From: harlan            { SAVE dist };
  132. X<DIST>                        { SAVE dist; FORWARD harlan@mumps.pfcs.com };
  133. X
  134. X# This is administrative stuff. I am a system administrator here, among other
  135. X# things, and we have several MIPS machine with a verbose cron daemon. I have
  136. X# set up a /.forward on all those machines (which redirect all the root mail
  137. X# to me) and I filter the output according to the machine name.
  138. X
  139. XFrom: root, To: root            { BEGIN ROOT; REJECT };
  140. X<ROOT> Subject: /host (\w+)/    { ASSIGN host %1; REJECT };
  141. X<ROOT> /^Daily run output/        { WRITE ~/var/log/%#host/daily.%D };
  142. X<ROOT> /^Weekly run output/        { WRITE ~/var/log/%#host/weekly };
  143. X<ROOT> /^Monthly run output/    { WRITE ~/var/log/%#host/monthly };
  144. X
  145. X# I have a cron job every day a 5:00 a.m. which cleans up my mail folders. I
  146. X# am using the cron program from Paul Vixie, hence the rule testing against
  147. X# the ``X-Cron-Cmd'' header. This is a nice feature from Paul's cron.
  148. X
  149. XTo: ram, X-Cron-Cmd: /mhclean/    { WRITE ~/var/log/mh/mh.%D };
  150. X
  151. X# I belong to multiple internal mailing lists at ISE, and when I send a mail
  152. X# to this list, I do not wish to get a copy of it, as I already saved mine
  153. X# via the ``Fcc' field provided by MH. Therefore, I delete everything which
  154. X# comes from me and is not explicitely directed to me, with the exception of
  155. X# the mailgent error messages which I receive as ``Bcc''.
  156. X
  157. XFrom: ram        { BEGIN RAM; REJECT };
  158. X<RAM> To: ram    { LEAVE };
  159. X<RAM> X-Mailer: /mailagent/i    { LEAVE };
  160. X<RAM>            { DELETE };
  161. X
  162. X# Every system-related mail is saved in a special folder. Note that the pattern
  163. X# matching is done in a case insensitive manner because all these patterns are
  164. X# implicit matches on the ``login name'' of the sender.
  165. X
  166. XTo Cc:
  167. X    postmaster,
  168. X    newsmaster,
  169. X    usenet, news,
  170. X    mailer-daemon,
  171. X    uucp, daemon,
  172. X    system,
  173. X    unknown-user    { SAVE admin };
  174. X
  175. X# Here, I am detecting mails sent by someone at ISE, i.e. mails with the
  176. X# domain name ``eiffel.com'' appended or simply mails with no domain name.
  177. X# I also turn off vacation messages, for when I am away, people at ISE usually
  178. X# know about it :-).
  179. X
  180. XFrom:
  181. X    /^\w+@.*eiffel\.com$/i
  182. X    /^\w+@\w+$/i
  183. X        { BEGIN ISE; STRIP Received; VACATION off; REJECT };
  184. X
  185. X# A mail explicitely sent to me, leave it in the mailbox.
  186. X
  187. X<ISE> To: ram            { LEAVE };
  188. X
  189. X# Various internal mailing list. Note the ``*eiffel*'' pattern which takes care
  190. X# of various aliases including the word ``eiffel'', as in eiffel, eiffelgroup,
  191. X# ueiffel, etc...
  192. X
  193. X<ISE> To Cc:
  194. X    compiler    { SAVE ise/compiler }
  195. X    *eiffel*    { SAVE ise/eiffel }
  196. X    local        { SAVE ise/local };
  197. X
  198. X# Take care of all the "junk" mails. Usually, I check this mailbox once a week.
  199. X# There is never anything interesting in there, trust me...
  200. X
  201. X<ISE>            { SAVE ise/other };
  202. X
  203. X# Finally, mails coming from the outside world are also filtered into specific
  204. X# folders. This ends the rule file. Anything not matched past this point will
  205. X# simply be left in the mailbox.
  206. X
  207. XTo Cc:
  208. X    *eiffel*,
  209. X    users        { SAVE ise/extern }
  210. X    everyone    { SAVE ise/local };
  211. X
  212. X#
  213. X# End of mailagent rules
  214. X#
  215. END_OF_FILE
  216.   if test 7239 -ne `wc -c <'agent/examples/rules'`; then
  217.     echo shar: \"'agent/examples/rules'\" unpacked with wrong size!
  218.   fi
  219.   # end of 'agent/examples/rules'
  220. fi
  221. if test -f 'agent/files/filter.sh' -a "${1}" != "-c" ; then 
  222.   echo shar: Will not clobber existing file \"'agent/files/filter.sh'\"
  223. else
  224.   echo shar: Extracting \"'agent/files/filter.sh'\" \(7453 characters\)
  225.   sed "s/^X//" >'agent/files/filter.sh' <<'END_OF_FILE'
  226. X#!/bin/sh
  227. X
  228. X# $Id: filter.sh,v 2.9 92/07/14 16:47:49 ram Exp $
  229. X#
  230. X#  Copyright (c) 1991, 1992, Raphael Manfredi
  231. X#
  232. X#  You may redistribute only under the terms of the GNU General Public
  233. X#  Licence as specified in the README file that comes with dist.
  234. X#
  235. X# $Log:    filter.sh,v $
  236. X# Revision 2.9  92/07/14  16:47:49  ram
  237. X# 3.0 beta baseline.
  238. X# 
  239. X
  240. X# You'll have to delete comments by yourself if your shell doesn't grok them
  241. X
  242. X# You should install a .forward in your home directory to activate the
  243. X# process (sendmail must be used as a MTA). Mine looks like this:
  244. X#    "|exec /users/ram/mail/filter >>/users/ram/.bak 2>&1"
  245. X
  246. X# Variable HOME *must* correctly be set to your home directory
  247. XHOME=/york/ram
  248. Xexport HOME
  249. X
  250. X# The PATH variable must also correctly be set. This variable will be
  251. X# used by all the mailagent-related programs. If you have chosen to put
  252. X# the mailagent scripts in a dedicated directory (e.g. $HOME/mailagent),
  253. X# be sure to put that directory in the PATH variable.
  254. X# The mailagent scripts could also have been stored in a directory like
  255. X# /usr/local/scripts by your system administrator, because each user does
  256. X# not need to have a private copy of theese scrips.
  257. XPATH="/bin:/usr/bin:/usr/ucb:$HOME/bin/mailagent:$HOME/bin"
  258. X
  259. X# The following will set the right path for some architecture-specific
  260. X# directories. For instance, if you have your home directory viewed on
  261. X# some different machines (e.g. it is NFS-mounted), then you must be
  262. X# sure the mailagent will be invoked with the right executables.
  263. XHOST=`(uname -n || hostname) 2>/dev/null`
  264. Xcase "$HOST" in
  265. Xyork) PATH="$HOME/bin/rs2030:$PATH" ;;
  266. Xeiffel) PATH="/base/common/sun4/bin:$PATH" ;;
  267. X*) ;;
  268. Xesac
  269. Xexport PATH
  270. X
  271. X# The TZ may not correctly be set when sendmail is invoking the filter, hence
  272. X# funny date could appear in the log message (from GMT zone usually).
  273. XTZ='PST8PDT'
  274. Xexport TZ
  275. X
  276. X# You should not have to edit below this line
  277. X
  278. X# This variable, when eval'ed, adds a log message at the end of the log file
  279. X# if any. Assumes the ~/.mailagent file was successfully parsed.
  280. Xaddlog='umask 077; if test -f $logdir/$log;
  281. Xthen /bin/echo "`date \"+%y/%m/%d %H:%M:%S\"` filter[$$]: $1" >> $logdir/$log;
  282. Xelse echo "`date \"+%y/%m/%d %H:%M:%S\"` filter[$$]: $1";
  283. Xfi; umask 277
  284. X'
  285. X
  286. X# This variable, when eval'ed, dumps the message on stdout. For this
  287. X# reason, error messages should be redirected into a file.
  288. Xemergency='echo "*** Could not process the following ($1) ***";
  289. Xcat $temp;
  290. Xecho "----------- `date` -----------";
  291. Xset "FATAL $1";
  292. Xeval $addlog;
  293. Xrm -f $spool/filter.lock $torm
  294. X'
  295. X
  296. X# This is for safety reasons (mailagent may abort suddenly). Save the
  297. X# whole mail in a temporary file, which has very restrictive permissions
  298. X# (prevents unwanted removal). This will be eventually moved to the
  299. X# mailagent's queue if we can locate it.
  300. Xumask 277
  301. Xtemp=/tmp/Fml$$
  302. Xtorm="$temp"
  303. X
  304. X# The magic number '74' is EX_IOERR as understood by sendmail and means that
  305. X# an I/O error occurred. The mail is left in sendmail's queue. I expect "cat"
  306. X# to give a meaningful exit code.
  307. Xcat > $temp || exit 74
  308. X
  309. X# The following is done in a subshell put in background, so that this
  310. X# process can exit with a zero status immediately, which will make
  311. X# sendmail think that the delivery was successful. Hopefully we can
  312. X# do our own error recovery now.
  313. X
  314. X(
  315. X# Script used to save the processed mail in an emergency situation
  316. Xsaver='umask 077; if (cat $temp; echo ""; echo "") >> $HOME/mbox.filter; then
  317. X    set "DUMPED in ~/mbox.filter"; eval $addlog; rm -f $torm; else
  318. X    set "unable to dump in ~/mbox.filter"; eval $emergency;
  319. Xfi'
  320. X
  321. X# Set a trap in case of interruption. Mail will be dumped in ~/mbox.filter
  322. Xtrap 'eval $saver; exit 0' 1 2 3 15
  323. X
  324. X# Look for the ~/.mailagent file, exit if none found
  325. Xif test ! -f $HOME/.mailagent; then
  326. X    set 'FATAL no ~/.mailagent'
  327. X    eval $addlog
  328. X    eval $saver
  329. X    exit 0
  330. Xfi
  331. X
  332. X# Parse ~/.mailagent to get the queue location
  333. Xset X `<$HOME/.mailagent sed -n \
  334. X    -e '/^[     ]*#/d' \
  335. X    -e 's/^[     ]*\([^     :\/]*\)[     ]*:[     ]*\([^#]*\).*/\1="\2";/p'`
  336. Xshift
  337. X
  338. X# Deal with possible white spaces in variables
  339. Xcmd=''
  340. Xfor line in $*; do
  341. X    cmd="$cmd$line"
  342. Xdone
  343. Xcmd=`echo $cmd | sed -e "s|~|$HOME|g"`
  344. Xeval $cmd
  345. X
  346. X# It would be too hazardous to continue without a valid queue directory
  347. Xif test ! -d "$queue"; then
  348. X    set 'FATAL no valid queue directory'
  349. X    eval $addlog
  350. X    eval $saver
  351. X    exit 0
  352. Xfi
  353. X
  354. X# If there is already a filter.lock file, then we set busy to true. Otherwise,
  355. X# we create the lock file. Note that this scheme is a little lousy (race
  356. X# conditions may occur), but that's not really important because the mailagent
  357. X# will do its own tests with the perl.lock file.The motivation here is to avoid
  358. X# a myriad of filter+perl processes spawned when a lot of mail is delivered
  359. X# via SMTP (for instance after a uucp connection).
  360. Xbusy=''
  361. Xif test -f $spool/filter.lock; then
  362. X    busy='true'
  363. Xelse
  364. X    # Race condition may (and will) occur, but the permissions are kept by 'cp',
  365. X    # so the following will not raise any error message.
  366. X    cp /dev/null $spool/filter.lock >/dev/null 2>&1 || busy='true'
  367. Xfi
  368. X
  369. X# Copy tmp file to the queue directory and call the mailagent. If the file
  370. X# already exists (very unlikely, but...), we append a 'b' for bis.
  371. Xqtemp=$queue/qm$$
  372. Xtqtemp=$queue/Tqm$$
  373. Xif test -f $qtemp; then
  374. X    qtemp=$queue/qmb$$
  375. X    tqtemp=$queue/Tqmb$$
  376. Xfi
  377. X
  378. X# Do not write in a 'qm' file directly, or the mailagent might start
  379. X# its processing on an incomplete file.
  380. Xif cp $temp $tqtemp; then
  381. X    mv $tqtemp $qtemp
  382. X    if test x = "x$busy"; then
  383. X        sleep 60
  384. X        if perl -S mailagent $qtemp; then
  385. X            rm -f $temp $qtemp $spool/filter.lock
  386. X            exit 0
  387. X        fi
  388. X    fi
  389. Xelse
  390. X    set 'ERROR unable to queue mail before processing'
  391. X    eval $addlog
  392. X    if test x = "x$busy"; then
  393. X        sleep 60
  394. X        if perl -S mailagent $temp; then
  395. X            rm -f $temp $spool/filter.lock
  396. X            exit 0
  397. X        fi
  398. X    fi
  399. Xfi
  400. X
  401. X# We come here only if the mailagent failed its processing. The unprocessed
  402. X# mail either left in the queue or is given a meaningful name.
  403. Xif cmp $temp $qtemp >/dev/null 2>&1; then
  404. X    base=`echo $qtemp | sed -e 's/.*\/\(.*\)/\1/'`
  405. X    if test x = "x$busy"; then
  406. X        set "ERROR mailagent failed, [$base] left in queue"
  407. X        rm -f $spool/filter.lock
  408. X    else
  409. X        # Make file a fm* one, so that it will get processed immediately by
  410. X        # the main mailagent when it is ready to deal with the queue.
  411. X        fmbase=`echo $base | sed -e 's/qm/fmx/'`
  412. X        if mv $queue/$base $queue/$fmbase; then
  413. X            set "NOTICE filter busy, [$fmbase] left in queue"
  414. X        else
  415. X            set "NOTICE filter busy, [$base] left in queue"
  416. X        fi
  417. X    fi
  418. X    eval $addlog
  419. X    rm -f $temp
  420. X    exit 0
  421. Xfi
  422. X
  423. X# Change the name of the temporary file.
  424. Xuser=`(logname || whoami) 2>/dev/null`
  425. Xtmpdir=`echo $temp | sed -e 's/\(.*\)\/.*/\1/'`
  426. Xmv $temp $tmpdir/$user.$$
  427. Xtemp="$tmpdir/$user.$$"
  428. Xif test x = "x$busy"; then
  429. X    set "ERROR mailagent failed, mail left in $temp"
  430. X    rm -f $spool/filter.lock
  431. Xelse
  432. X    set "WARNING filter busy, mail left in $temp"
  433. Xfi
  434. Xeval $addlog
  435. X
  436. X# Give the mailagent a clue as to where the mail has been stored. As this
  437. X# should be very very unlikely, no test is done to see whether a mailagent
  438. X# is already updating the agent.wait file. The worse that could result from
  439. X# this shallowness would be having an unprocessed mail.
  440. Xumask 077
  441. Xset 'WARNING mailagent ignores where mail was left'
  442. Xif /bin/echo "$temp" >> $queue/agent.wait; then
  443. X    if grep "$temp" $queue/agent.wait >/dev/null 2>&1; then
  444. X        set "NOTICE $temp memorized into agent.wait"
  445. X    fi
  446. Xfi
  447. Xeval $addlog
  448. Xrm -f $qtemp
  449. X
  450. X# Attempt an emergency saving
  451. Xeval $saver
  452. Xexit 0
  453. X) &
  454. X
  455. X# Delivery was ok -- for sendmail
  456. Xexit 0
  457. END_OF_FILE
  458.   if test 7453 -ne `wc -c <'agent/files/filter.sh'`; then
  459.     echo shar: \"'agent/files/filter.sh'\" unpacked with wrong size!
  460.   fi
  461.   chmod +x 'agent/files/filter.sh'
  462.   # end of 'agent/files/filter.sh'
  463. fi
  464. if test -f 'agent/filter/Makefile.SH' -a "${1}" != "-c" ; then 
  465.   echo shar: Will not clobber existing file \"'agent/filter/Makefile.SH'\"
  466. else
  467.   echo shar: Extracting \"'agent/filter/Makefile.SH'\" \(4807 characters\)
  468.   sed "s/^X//" >'agent/filter/Makefile.SH' <<'END_OF_FILE'
  469. X: Makefile.SH generated from Jmake.tmpl and Jmakefile [jmake 2.8 PL13]
  470. X: $X-Id: Jmake.tmpl,v 2.8.1.2 91/11/18 13:22:54 ram Exp $
  471. X
  472. Xcase $CONFIG in
  473. X'')
  474. X    if test ! -f config.sh; then
  475. X        ln ../config.sh . || \
  476. X        ln ../../config.sh . || \
  477. X        ln ../../../config.sh . || \
  478. X        (echo "Can't find config.sh."; exit 1)
  479. X    fi 2>/dev/null
  480. X    . ./config.sh
  481. X    ;;
  482. Xesac
  483. Xcase "$0" in
  484. X*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
  485. Xesac
  486. XCURRENT=agent/filter
  487. XDIR=`echo $CURRENT/ | sed -e 's/\.\///g'`
  488. Xecho "Extracting ${DIR}Makefile (with variable substitutions)"
  489. XDATE=`date`
  490. X$spitshell >Makefile <<!GROK!THIS!
  491. X########################################################################
  492. X# Makefile generated from Makefile.SH on $DATE
  493. X
  494. XSHELL = /bin/sh
  495. XJMAKE = jmake
  496. XTOP = ../..
  497. XCURRENT = $CURRENT
  498. XDIR = $DIR
  499. XINSTALL = ../../install
  500. X
  501. X########################################################################
  502. X# Parameters set by Configure -- edit config.sh if changes are needed
  503. X
  504. XCC = $cc
  505. XCTAGS = ctags
  506. XJCFLAGS = $(CFLAGS) $optimize $ccflags $large
  507. XJLDFLAGS = $(LDFLAGS) $optimize $ldflags
  508. XLIBS = $libs
  509. XMAKE = make
  510. XMKDEP = $mkdep $(DPFLAGS) --
  511. XMV = $mv
  512. XPRIVLIB = $privlib
  513. XRM = $rm -f
  514. XSED = $sed
  515. X
  516. X########################################################################
  517. X# Automatically generated parameters -- do not edit
  518. X
  519. XSOURCES =  \$(SRC)
  520. XOBJECTS =  \$(OBJ)
  521. X
  522. X########################################################################
  523. X# New suffixes and associated building rules -- edit with care
  524. X
  525. X.c.o:
  526. X    \$(CC) -c \$(JCFLAGS) \$<
  527. X
  528. X!GROK!THIS!
  529. X$spitshell >>Makefile <<'!NO!SUBS!'
  530. X
  531. X########################################################################
  532. X# Jmake rules for building libraries, programs, scripts, and data files
  533. X# $X-Id: Jmake.rules,v 2.8.1.4 91/11/18 13:19:07 ram Exp $
  534. X
  535. X########################################################################
  536. X# Force 'make depend' to be performed first -- do not edit
  537. X
  538. X.FORCE_DEPEND::
  539. X
  540. Xall:: .FORCE_DEPEND
  541. X
  542. X########################################################################
  543. X# Start of Jmakefile
  544. X
  545. X# $X-Id: Jmakefile,v 2.9 92/07/14 18:41:10 ram Exp $
  546. X#
  547. X#  Copyright (c) 1991, Raphael Manfredi
  548. X#
  549. X#  You may redistribute only under the terms of the GNU General Public
  550. X#  Licence as specified in the README file that comes with dist.
  551. X#
  552. X# $X-Log:    Jmakefile,v $
  553. X# Revision 2.9  92/07/14  18:41:10  ram
  554. X# 3.0 beta baseline.
  555. X#
  556. X
  557. X# Files used to build the application
  558. XSRC = environ.c hash.c io.c lock.c logfile.c main.c misc.c msg.c parser.c \
  559. X    user.c
  560. X
  561. X# Derived object file names
  562. XOBJ = \
  563. X    environ.o \
  564. X    hash.o \
  565. X    io.o \
  566. X    lock.o \
  567. X    logfile.o \
  568. X    main.o \
  569. X    misc.o \
  570. X    msg.o \
  571. X    parser.o \
  572. X    user.o 
  573. X
  574. X# File config.h is in the top-level directory
  575. XCFLAGS = -I$(TOP)
  576. XDPFLAGS = -I$(TOP)
  577. X
  578. Xdepend:: ../../mkdep
  579. X
  580. X../../mkdep:
  581. X    @echo "You have to run Configure in $(TOP) first."; exit 1
  582. X
  583. Xdepend::
  584. X    ($(SED) '/^# DO NOT DELETE/q' Makefile && \
  585. X    $(MKDEP) $(SOURCES) | \
  586. X    $(SED) 's/: \.\//: /; /\/usr\/include/d' \
  587. X    ) > Makefile.new
  588. X    cp Makefile Makefile.bak
  589. X    cp Makefile.new Makefile
  590. X    $(RM) Makefile.new
  591. X
  592. Xall:: filter
  593. X
  594. Xlocal_realclean::
  595. X    $(RM) filter
  596. X
  597. Xfilter: $(OBJ)
  598. X    $(RM) $@
  599. X    if test -f $@; then $(MV) $@ $@~; else exit 0; fi
  600. X    $(CC) -o $@ $(OBJ) $(JLDFLAGS) $(LIBS)
  601. X
  602. Xinstall:: filter
  603. X    $(INSTALL) -c -s -m 555  filter  $(PRIVLIB)
  604. X
  605. Xdeinstall::
  606. X    $(RM)  $(PRIVLIB)/filter
  607. X
  608. X########################################################################
  609. X# Common rules for all Makefiles -- do not edit
  610. X
  611. Xemptyrule::
  612. X
  613. Xclean: local_clean
  614. Xrealclean: local_realclean
  615. Xclobber: local_clobber
  616. X
  617. Xlocal_clean::
  618. X    $(RM) core *~ *.o
  619. X
  620. Xlocal_realclean:: local_clean
  621. X
  622. Xlocal_clobber:: local_realclean
  623. X    $(RM) Makefile config.sh
  624. X
  625. XMakefile.SH: Jmakefile
  626. X    -@if test -f $(TOP)/.package; then \
  627. X        if test -f Makefile.SH; then \
  628. X            echo "    $(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~"; \
  629. X            $(RM) Makefile.SH~; $(MV) Makefile.SH Makefile.SH~; \
  630. X        fi; \
  631. X        echo "    $(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT)" ; \
  632. X        $(JMAKE) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT) ; \
  633. X    else touch $@; exit 0; fi
  634. X
  635. XMakefile: Makefile.SH
  636. X    /bin/sh Makefile.SH
  637. X
  638. Xtags::
  639. X    $(CTAGS) -w *.[ch]
  640. X    $(CTAGS) -xw *.[ch] > tags
  641. X
  642. Xlocal_clobber::
  643. X    $(RM) tags
  644. X
  645. X########################################################################
  646. X# Empty rules for directories with no sub-directories -- do not edit
  647. X
  648. Xinstall::
  649. X    @echo "install in $(CURRENT) done."
  650. X
  651. Xdeinstall::
  652. X    @echo "deinstall in $(CURRENT) done."
  653. X
  654. Xinstall.man::
  655. X    @echo "install.man in $(CURRENT) done."
  656. X
  657. Xdeinstall.man::
  658. X    @echo "deinstall.man in $(CURRENT) done."
  659. X
  660. XMakefiles::
  661. X
  662. XMakefiles.SH::
  663. X
  664. X########################################################################
  665. X# Dependencies generated by make depend
  666. X# DO NOT DELETE THIS LINE -- make depend relies on it
  667. X
  668. X# Put nothing here or make depend will gobble it up
  669. X.FORCE_DEPEND::
  670. X    @echo "You must run 'make depend' in $(TOP) first."; exit 1
  671. X!NO!SUBS!
  672. Xchmod 644 Makefile
  673. X$eunicefix Makefile
  674. X
  675. END_OF_FILE
  676.   if test 4807 -ne `wc -c <'agent/filter/Makefile.SH'`; then
  677.     echo shar: \"'agent/filter/Makefile.SH'\" unpacked with wrong size!
  678.   fi
  679.   # end of 'agent/filter/Makefile.SH'
  680. fi
  681. if test -f 'agent/maillist.SH' -a "${1}" != "-c" ; then 
  682.   echo shar: Will not clobber existing file \"'agent/maillist.SH'\"
  683. else
  684.   echo shar: Extracting \"'agent/maillist.SH'\" \(7606 characters\)
  685.   sed "s/^X//" >'agent/maillist.SH' <<'END_OF_FILE'
  686. Xcase $CONFIG in
  687. X'')
  688. X    if test ! -f config.sh; then
  689. X        ln ../config.sh . || \
  690. X        ln ../../config.sh . || \
  691. X        ln ../../../config.sh . || \
  692. X        (echo "Can't find config.sh."; exit 1)
  693. X    fi 2>/dev/null
  694. X    . config.sh
  695. X    ;;
  696. Xesac
  697. Xcase "$0" in
  698. X*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
  699. Xesac
  700. Xecho "Extracting agent/maillist (with variable substitutions)"
  701. X$spitshell >maillist <<!GROK!THIS!
  702. X# feed this into perl
  703. X    eval "exec perl -S \$0 \$*"
  704. X        if \$running_under_some_shell;
  705. X
  706. X# $Id: maillist.SH,v 2.9 92/07/14 16:48:57 ram Exp $
  707. X#
  708. X#  Copyright (c) 1991, 1992, Raphael Manfredi
  709. X#
  710. X#  You may redistribute only under the terms of the GNU General Public
  711. X#  Licence as specified in the README file that comes with dist.
  712. X#
  713. X# $Log:    maillist.SH,v $
  714. X# Revision 2.9  92/07/14  16:48:57  ram
  715. X# 3.0 beta baseline.
  716. X# 
  717. X
  718. X\$mversion = '$VERSION';
  719. X\$patchlevel = '$PATCHLEVEL';
  720. X!GROK!THIS!
  721. X
  722. X$spitshell >>maillist <<'!NO!SUBS!'
  723. X
  724. X$prog_name = $0;                # Who I am
  725. X$prog_name =~ s|^.*/(.*)|$1|;    # Keep only base name
  726. X
  727. Xdo read_config();    # First, read configuration file (in ~/.mailagent)
  728. X
  729. X# take job number and command from environment
  730. X# (passed by mailagent)
  731. X$jobnum = $ENV{'jobnum'};
  732. X$fullcmd = $ENV{'fullcmd'};
  733. X
  734. X$dest=shift;                            # Who should the list to be sent to
  735. X$dest = $ENV{'path'} if $dest eq '';    # If dest was ommitted
  736. X
  737. X# A single '-' as first argument stands for return path
  738. X$dest = $ENV{'path'} if $dest eq '-';
  739. X
  740. Xdo read_dist();        # Read distributions and descriptions
  741. X
  742. Xopen(INFO, "$cf'proglist") ||
  743. X    do fatal("cannot open description file");
  744. X@sysinfo = <INFO>;
  745. Xclose INFO;
  746. X
  747. Xdo read_plsave();    # Read patchlevel description file
  748. X        
  749. X$tmp_mail = "$cf'tmpdir/xml$$";
  750. X
  751. Xopen(XHEAD, ">$tmp_mail") || do fatal("cannot create $tmp_mail");
  752. Xprint XHEAD
  753. X"To: $dest
  754. XSubject: List of available distributions
  755. XX-Mailer: mailagent [version $mversion PL$patchlevel]
  756. X
  757. XHere are the different packages available. If you want the whole
  758. Xdistribution, send me the following:
  759. X
  760. X    @SH maildist $dest system version
  761. X
  762. XIf you want patches, use:
  763. X
  764. X    @SH mailpatch $dest system version LIST
  765. X
  766. Xwhere LIST is a list of patches number, separated by spaces, commas,
  767. Xand/or hyphens. Saying 23- means everything from 23 to the end.
  768. X
  769. XDetailed instructions can be obtained by:
  770. X
  771. X    @SH mailhelp $dest
  772. X
  773. X
  774. X";
  775. X
  776. Xforeach $pname (keys %Program) {
  777. X    ($system, $version) = $pname =~ /^(\w+)\|([\w\.]+)*$/;
  778. X    $version = '---' if $version eq '0';
  779. X    $location = $Location{$pname};
  780. X    do add_log("dealing with $system $version") if ($loglvl > 19);
  781. X
  782. X    # Look for highest patchlevel (even if not maintained)
  783. X    $tmp = "";            # Temporary directory created
  784. X
  785. X    if ($Archived{$pname}) {
  786. X        unless ($PSystem{$pname}) {
  787. X            # Archive not already listed in 'plsave'. Create a new
  788. X            # entry with a modification time of zero.
  789. X            $PSystem{$pname} = 1;
  790. X            $Patch_level{$pname} = -1;    # Not a valid patch level
  791. X            $Mtime{$pname} = 0;            # Force unpacking of archive
  792. X        }
  793. X
  794. X        # We need to unarchive the directory only if archive
  795. X        # modification time is newer than the one in patchlist
  796. X        local($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime, $mtime,
  797. X            $ctime,$blksize,$blocks) = stat(do expand($location));
  798. X
  799. X        if ($mtime != $Mtime{$pname}) {     # Archive was updated
  800. X            $Mtime{$pname} = $mtime;     # Update mod time in 'plsave'
  801. X            # Create a temporary directory
  802. X            $tmp = "$cf'tmpdir/dml$$";
  803. X            mkdir($tmp, 0700) ||
  804. X                do fatal("cannot create $tmp");
  805. X            # Need to unarchive the distribution
  806. X            $location = do unpack($location, $tmp, $Compressed{$pname});
  807. X            $Patch_level{$pname} = -1;    # Force updating
  808. X        } else {
  809. X            do add_log("no changes in $system $version archive")
  810. X                if ($loglvl > 15);
  811. X        }
  812. X
  813. X    } else {
  814. X        # System is not archived
  815. X        $Patch_level{$pname} = -1;        # Force computation
  816. X    }
  817. X
  818. X    if ($Patch_level{$pname} == -1) {
  819. X        # We still don't know wether there is a patchlevel or not...
  820. X        # Go to system directory, and look there.
  821. X        if (!chdir("$location")) {
  822. X            do add_log("ERROR cannot go to $location") if $loglvl > 0;
  823. X            next;
  824. X        }
  825. X        if ($Patch_only{$pname}) {        # Only patches available
  826. X            if ($version eq '') {
  827. X                do add_log("ERROR old system $system has no version number")
  828. X                    if ($loglvl > 0);
  829. X                next;
  830. X            }
  831. X            if (!chdir("bugs-$version")) {
  832. X                do add_log("ERROR no bugs-$version dir for $system")
  833. X                    if ($loglvl > 0);
  834. X                next;
  835. X            }
  836. X            local($maxnum);
  837. X            # There is no patchlevel to look at -- compute by hand.
  838. X            for ($maxnum = 1; ; $maxnum++) {
  839. X                last unless -f "patch$maxnum" || -f "patch$maxnum.Z";
  840. X            }
  841. X            $maxnum--;        # We've gone too far
  842. X            $Patch_level{$pname} = $maxnum;
  843. X        } elsif (! -f 'patchlevel.h') {
  844. X            do add_log("no patchlevel.h for $system $version")
  845. X                if ($loglvl > 17);
  846. X        } elsif (!open(PATCHLEVEL, "patchlevel.h")) {
  847. X            do add_log("cannot open patchlevel.h for $system $version")
  848. X                if ($loglvl > 5);
  849. X        } else {
  850. X            while (<PATCHLEVEL>) {
  851. X                if (/.*PATCHLEVEL[ \t]*(\w+)/) {    # May have letters
  852. X                    $Patch_level{$pname} = $1;
  853. X                    last;
  854. X                }
  855. X            }
  856. X            close PATCHLEVEL;
  857. X            if ($Patch_level{$pname} == -1) {
  858. X                do add_log(
  859. X                    "malformed patchlevel.h for $system $version"
  860. X                ) if ($loglvl > 5);
  861. X            }
  862. X        }
  863. X    }
  864. X
  865. X    if ($Patch_level{$pname} >= 0) {
  866. X        do add_log(
  867. X            "patchlevel is #$Patch_level{$pname} for $system $version"
  868. X        ) if ($loglvl > 18);
  869. X    } else {
  870. X        $Patch_level{$pname} = -2;        # Signals: no patchlevel
  871. X        do add_log("no patchlevel for $system $version")
  872. X            if ($loglvl > 18);
  873. X    }
  874. X    
  875. X    do clean_dir();         # Remove tmp directory, if necessary
  876. X
  877. X    # Now look for a description of the package...
  878. X    $describe = "";
  879. X    $found = 0;
  880. X    foreach (@sysinfo) {
  881. X        next if /^\s*#/;    # Skip comments
  882. X        next if /^\s*$/;    # Skip blank lines
  883. X        next if /^\*\s+$system/ && ($found = 1);
  884. X        last if $found && /^---|^\*/;        # Reached end of description
  885. X        $describe .= "X" . $_ if $found;
  886. X    }
  887. X    $* = 1;
  888. X    $describe =~ s/^X/\t/g;        # Indent description
  889. X    $* = 0;
  890. X
  891. X    print XHEAD "System: $system";
  892. X    print XHEAD " version $version" if $version !~ /---/;
  893. X    print XHEAD "\nStatus: ";
  894. X    print XHEAD $Maintained{$pname} ? "maintained" : "not maintained";
  895. X    print XHEAD " (patches only)" if $Patch_only{$pname};
  896. X    print XHEAD " (official patches available)" if $Patches{$pname};
  897. X    print XHEAD "\n";
  898. X    if ($Maintained{$pname}) {
  899. X        if ($Patch_level{$pname} > 0) {
  900. X            print XHEAD "Highest patch: #$Patch_level{$pname}\n";
  901. X        } else {
  902. X            print XHEAD "No patches yet\n";
  903. X        }
  904. X    } else {
  905. X        print XHEAD "Patch level: #$Patch_level{$pname}\n"
  906. X            if $Patch_level{$pname} > 0;
  907. X    }
  908. X    print XHEAD "\n";
  909. X    print XHEAD "$describe\n" if $describe ne '';
  910. X    print XHEAD "\n";
  911. X}
  912. Xprint XHEAD "-- $prog_name speaking for $cf'user\n";
  913. Xclose XHEAD;
  914. X
  915. Xopen(XHEAD, "$tmp_mail") || do fatal("cannot open mail file");
  916. Xopen(MAILER, "|/usr/lib/sendmail -odq -t");
  917. Xwhile (<XHEAD>) {
  918. X    print MAILER;
  919. X}
  920. Xclose MAILER;
  921. Xif ($?) {
  922. X    do add_log("ERROR couldn't send list to $dest") if $loglvl > 0;
  923. X} else {
  924. X    do add_log("SENT list to $dest") if $loglvl > 2;
  925. X}
  926. Xclose XHEAD;
  927. X
  928. Xdo write_plsave();        # Write new patchlist file
  929. Xdo clean_tmp();            # Remove temporary dirs/files
  930. Xexit 0;                    # All OK
  931. X
  932. Xsub clean_dir {
  933. X    chdir $cf'home;        # Leave [to be removed directory] first
  934. X    if ($tmp ne '') {
  935. X        system '/bin/rm', '-rf', $tmp if -d "$tmp";
  936. X        do add_log("directory $tmp removed") if ($loglvl > 19);
  937. X        $tmp = "";
  938. X    }
  939. X}
  940. X
  941. Xsub clean_tmp {
  942. X    do clean_dir();
  943. X    unlink "$tmp_mail" if -f "$tmp_mail";
  944. X}
  945. X
  946. X!NO!SUBS!
  947. X$grep -v '^;#' pl/fatal.pl >>maillist
  948. X$grep -v '^;#' pl/acs_rqst.pl >>maillist
  949. X$grep -v '^;#' pl/free_file.pl >>maillist
  950. X$grep -v '^;#' pl/add_log.pl >>maillist
  951. X$grep -v '^;#' pl/read_conf.pl >>maillist
  952. X$grep -v '^;#' pl/unpack.pl >>maillist
  953. X$grep -v '^;#' pl/distribs.pl >>maillist
  954. X$grep -v '^;#' pl/checklock.pl >>maillist
  955. X$grep -v '^;#' pl/plsave.pl >>maillist
  956. Xchmod 755 maillist
  957. X$eunicefix maillist
  958. END_OF_FILE
  959.   if test 7606 -ne `wc -c <'agent/maillist.SH'`; then
  960.     echo shar: \"'agent/maillist.SH'\" unpacked with wrong size!
  961.   fi
  962.   chmod +x 'agent/maillist.SH'
  963.   # end of 'agent/maillist.SH'
  964. fi
  965. if test -f 'agent/pl/hook.pl' -a "${1}" != "-c" ; then 
  966.   echo shar: Will not clobber existing file \"'agent/pl/hook.pl'\"
  967. else
  968.   echo shar: Extracting \"'agent/pl/hook.pl'\" \(7089 characters\)
  969.   sed "s/^X//" >'agent/pl/hook.pl' <<'END_OF_FILE'
  970. X;# $Id: hook.pl,v 2.9.1.1 92/08/26 13:14:05 ram Exp $
  971. X;#
  972. X;#  Copyright (c) 1992, Raphael Manfredi
  973. X;#
  974. X;#  You may redistribute only under the terms of the GNU General Public
  975. X;#  Licence as specified in the README file that comes with dist.
  976. X;#
  977. X;# $Log:    hook.pl,v $
  978. X;# Revision 2.9.1.1  92/08/26  13:14:05  ram
  979. X;# patch8: created
  980. X;# 
  981. X;# 
  982. X;# A mail hook (in the mailagent terminology) is an external file which
  983. X;# transparently influences some of the mailagent actions by injecting user-
  984. X;# defined actions at some well-defined places. Currently, the only hooks
  985. X;# available are executable folders, activated via the SAVE, STORE, and LEAVE
  986. X;# commands.
  987. X;#
  988. X;# The hook_type function parses the top of the hook file, looking for magic
  989. X;# token which will give hints regarding the type of the hook. Then the
  990. X;# corresponding hook function will be called with the file name where the mail
  991. X;# is stored given as first argument (an empty string meaning the mail is to be
  992. X;# fetched from stdin), the second argument being the hook file name.
  993. X;#
  994. X;# Five types of hooks are currently supported:
  995. X;#   - Simple program: the mail is simply fed to the standard input of the
  996. X;#     program. The exit status is propagated to the mailagent.
  997. X;#   - Rule file: the mail is to be re-analyzed according to the new rules
  998. X;#     held in the hook file. A new mailagent is called with the -r option.
  999. X;#   - Audit script: This is a perl script. Following the spirit of Martin
  1000. X;#     Streicher's audit.pl package, some special variables are magically set
  1001. X;#     prior to the invocation of script within the special mailhook package,
  1002. X;#     in which the script is compiled.
  1003. X;#   - Deliver script: Same as an audit script, excepted that the output of the
  1004. X;#     script is monitored and taken as mailagent commands, which will then
  1005. X;#     be executed on the original message upon completion of the script.
  1006. X;#   - Perl script: This is an audit script with full access to the mailagent
  1007. X;#     primitives for filtering (same as the ones provided with a PERL command).
  1008. X;#
  1009. X#
  1010. X# Mailhook handling
  1011. X#
  1012. X
  1013. Xpackage hook;
  1014. X
  1015. X# Hooks constants definitions
  1016. Xsub main'init_hooks {
  1017. X    $HOOK_UNKNOWN = "hook'unknown";        # Hook type was not recognized
  1018. X    $HOOK_PROGRAM = "hook'program";        # Hook is a filter program
  1019. X    $HOOK_AUDIT = "hook'audit";            # Hook is an audit-like script
  1020. X    $HOOK_DELIVER = "hook'deliver";        # Hook is a deliver-like script
  1021. X    $HOOK_RULES = "hook'rules";            # Hook is a rule file
  1022. X    $HOOK_PERL = "hook'perl";            # Hook is a perl script
  1023. X}
  1024. X
  1025. X# Determine the nature of the hook. The top 128 bytes are scanned for a magic
  1026. X# number starting with #: and followed by some words. The type of the hook
  1027. X# is determined by the first word (case insensitively).
  1028. Xsub main'hook_type {
  1029. X    local($file) = @_;            # Name of hook file
  1030. X    -f "$file" || return $HOOK_UNKNOWN;        
  1031. X    -x _ || return $HOOK_UNKNOWN;
  1032. X    open(HOOK, $file) || return $HOOK_PROGRAM;
  1033. X    local($hook) = ' ' x 128;    # Consider only top 128 bytes
  1034. X    sysread(HOOK, $hook, 128);
  1035. X    close(HOOK);
  1036. X    local($name) = $hook =~ /^#:\s*(\w+)/;
  1037. X    $name =~ tr/A-Z/a-z/;
  1038. X    return $HOOK_AUDIT if $name eq 'audit';
  1039. X    return $HOOK_DELIVER if $name eq 'deliver';
  1040. X    return $HOOK_RULES if $name eq 'rules';
  1041. X    return $HOOK_PERL if $name eq 'perl';
  1042. X    $HOOK_PROGRAM;                # No magic token found
  1043. X}
  1044. X
  1045. X#
  1046. X# Hook functions
  1047. X#
  1048. X
  1049. X# The hook file is not valid
  1050. Xsub unknown {
  1051. X    local($mail, $hook) = @_;
  1052. X    &'fatal("$hook is not a hook file");
  1053. X}
  1054. X
  1055. X# Mail is to be piped to the hook program (on stdin)
  1056. Xsub program {
  1057. X    local($mail, $hook) = @_;
  1058. X    &'add_log("hook is a plain program") if $'loglvl > 17;
  1059. X    if ($mail ne '') {
  1060. X        unless (open(MAIL, $mail)) {
  1061. X            &'add_log("ERROR cannot open $mail: $!") if $'loglvl;
  1062. X            &'fatal("cannot feed $hook");
  1063. X        }
  1064. X        # Child gets its mail from stdin anyway, so dup MAIL on STDIN
  1065. X        unless (open(STDIN, '<&MAIL')) {
  1066. X            &'add_log("ERROR cannot dup mail on stdin: $!") if $'loglvl;
  1067. X            &'fatal("cannot feed $hook");
  1068. X        }
  1069. X    }
  1070. X    exec $hook;        # Propagate exit status to parent (mailagent)
  1071. X    # Exec system call failed
  1072. X    &'add_log("ERROR cannot exec $hook: $!") if $'loglvl;
  1073. X    &'fatal("cannot run $hook");
  1074. X}
  1075. X
  1076. X# Mail is to be filetered with rules from hook file
  1077. Xsub rules {
  1078. X    local($mail, $hook) = @_;
  1079. X    &'add_log("hook contains mailagent rules") if $'loglvl > 17;
  1080. X    exec "perl -S mailagent -r $hook $mail";
  1081. X    # Exec system call failed
  1082. X    &'add_log("ERROR exec failed: $!") if $'loglvl;
  1083. X    &'fatal("cannot run mailagent");
  1084. X}
  1085. X
  1086. X# Mail is to be filtered through a perl script
  1087. Xsub perl {
  1088. X    local($mail, $hook) = @_;
  1089. X    &'add_log("hook is a perl script") if $'loglvl > 17;
  1090. X    exec "perl -S mailagent -e 'PERL $hook' $mail";
  1091. X    # Exec system call failed
  1092. X    &'add_log("ERROR exec failed: $!") if $'loglvl;
  1093. X    &'fatal("cannot run mailagent");
  1094. X}
  1095. X
  1096. X# Hook is an audit script. Set up a suitable environment and execute the
  1097. X# script without forking any new process. To avoid name clashes, the script
  1098. X# is compiled in a dedicated 'mailhook' package and executed.
  1099. Xsub audit {
  1100. X    local($mail, $hook) = @_;
  1101. X    &'add_log("hook is an audit script") if $'loglvl > 17;
  1102. X    &'parse_mail($mail);        # Fill in %Header
  1103. X    &initialize;                # Initialize special variables
  1104. X    &run($hook);                # Load hook and run it
  1105. X}
  1106. X
  1107. X# A delivery script is about the same as an audit script, except that the
  1108. X# output on stdout is monitored and understood as mailagent commands to be
  1109. X# executed via a '-e' switch upon successful return.
  1110. Xsub deliver {
  1111. X    local($mail, $hook) = @_;
  1112. X    local($pid);
  1113. X    &'add_log("hook is a deliver script") if $'loglvl > 17;
  1114. X    # Fork and let the child do all the work. The parent simply captures the
  1115. X    # output from child's stdout.
  1116. X    &'parse_mail($mail);        # Fill in %Header
  1117. X    $pid = open(HOOK, "-|");    # Implicit fork
  1118. X    unless (defined $pid) {
  1119. X        &'add_log("ERROR cannot fork: $!") if $'loglvl;
  1120. X        &'fatal("cannot deliver to hook");
  1121. X    }
  1122. X    if (0 == $pid) {            # Child process
  1123. X        &initialize;            # Initialize special variables
  1124. X        &run($hook);            # Load hook and run it
  1125. X        exit 0;                    # Everything went well
  1126. X    }
  1127. X    local($/) = undef;            # We wish to slurp the whole output
  1128. X    local($output) = <HOOK>;
  1129. X    close HOOK;                    # An implicit wait -- status put in $?
  1130. X    unless (0 == $?) {
  1131. X        &'add_log("ERROR hook script failed") if $'loglvl;
  1132. X        &'fatal("non-zero exit status") unless $output;
  1133. X        &'fatal("commands ignored");
  1134. X    }
  1135. X    if ($output eq '') {
  1136. X        &'add_log("WARNING no commands from delivery hook") if $'loglvl > 5;
  1137. X    } else {
  1138. X        local($*) = 1;
  1139. X        $output =~ s/\\/\\\\/g;                # Protect backslashes
  1140. X        $output =~ s/([ "'`;<>&|])/\\$1/g;    # Protect spaces, separators, etc...
  1141. X        $pid = open(MAILAGENT, "|perl -S mailagent -e $output");
  1142. X        unless (defined $pid) {
  1143. X            &'add_log("ERROR cannot fork: $!") if $'loglvl;
  1144. X            &'fatal("cannot run mailagent");
  1145. X        }
  1146. X        print MAILAGENT $'Header{'All'};    # Pipe mail to mailagent
  1147. X        close MAILAGENT;                    # Implicit wait
  1148. X        &'fatal("mailagent failed") if $?;
  1149. X    }
  1150. X}
  1151. X
  1152. X# Log hook operation before it happens, as we may well exec() another program.
  1153. Xsub main'hooking {
  1154. X    local($file, $hook, $type) = @_;
  1155. X    $file =~ s|.*/(.*)|$1|;            # Keep only base name
  1156. X    $file = '<stdin>' if $file eq '';
  1157. X    $type =~ s/^hook'//;
  1158. X    $hook =~ s/^$cf'home/~/;
  1159. X    &'add_log("HOOKING [$file] to $hook ($type)") if $'loglvl > 4;
  1160. X}
  1161. X
  1162. Xpackage main;
  1163. X
  1164. END_OF_FILE
  1165.   if test 7089 -ne `wc -c <'agent/pl/hook.pl'`; then
  1166.     echo shar: \"'agent/pl/hook.pl'\" unpacked with wrong size!
  1167.   fi
  1168.   # end of 'agent/pl/hook.pl'
  1169. fi
  1170. if test -f 'agent/pl/rules.pl' -a "${1}" != "-c" ; then 
  1171.   echo shar: Will not clobber existing file \"'agent/pl/rules.pl'\"
  1172. else
  1173.   echo shar: Extracting \"'agent/pl/rules.pl'\" \(8559 characters\)
  1174.   sed "s/^X//" >'agent/pl/rules.pl' <<'END_OF_FILE'
  1175. X;# $Id: rules.pl,v 2.9.1.2 92/11/01 15:52:24 ram Exp $
  1176. X;#
  1177. X;#  Copyright (c) 1992, Raphael Manfredi
  1178. X;#
  1179. X;#  You may redistribute only under the terms of the GNU General Public
  1180. X;#  Licence as specified in the README file that comes with dist.
  1181. X;#
  1182. X;# $Log:    rules.pl,v $
  1183. X;# Revision 2.9.1.2  92/11/01  15:52:24  ram
  1184. X;# patch11: fixed English typo
  1185. X;# patch11: makes sure default rules apply if no valid rules are present
  1186. X;# 
  1187. X;# Revision 2.9.1.1  92/08/02  16:12:42  ram
  1188. X;# patch2: forgot to update last seen selector within rule
  1189. X;# 
  1190. X;# Revision 2.9  92/07/14  16:50:44  ram
  1191. X;# 3.0 beta baseline.
  1192. X;# 
  1193. X;# 
  1194. X# Here are the data structures we use to store the compiled form of the rules:
  1195. X#  @Rules has entries looking like "<$mode> {$action} $rulekeys..."
  1196. X#  %Rule has entries looking like "$selector: $pattern"
  1197. X# Each rule was saved in @Rules. The ruleskeys have the form H<num> where <num>
  1198. X# is an increasing integer. They index the rules in %Rule.
  1199. X
  1200. X# Compile the rules held in file $cf'rules (usually ~/.rules) or in memory
  1201. Xsub compile_rules {
  1202. X    local($mode);            # mode (optional)
  1203. X    local($first_selector);    # selector (mandatory first time)
  1204. X    local($selector);        # selector (optional)
  1205. X    local($pattern);        # pattern to be matched
  1206. X    local($action);            # associated action
  1207. X    local($rulekeys);        # keys to rules in hash table
  1208. X    local($rulenum) = 0;    # to compute unique keys for the hash table
  1209. X    local($line);            # buffer for next rule
  1210. X    local($env);            # environment variable recognized
  1211. X
  1212. X    # This function is called whenever a new line rule has to be read. By
  1213. X    # default, rules are read from a file, but if @Linerules is set, they
  1214. X    # are read from there.
  1215. X    local(*read_rule) = *read_filerule if @Linerules == 0;
  1216. X    local(*read_rule) = *read_linerule if @Linerules > 0;
  1217. X
  1218. X    unless ($edited_rules) {        # If no rules from command line
  1219. X        unless (-s "$cf'rules") {    # No rule file or empty
  1220. X            &default_rules;            # Build default rules
  1221. X            return;
  1222. X        }
  1223. X        unless (open(RULES, "$cf'rules")) {
  1224. X            &add_log("ERROR cannot open $cf'rules: $!") if $loglvl;
  1225. X            &default_rules;            # Default rules will apply then
  1226. X            return;
  1227. X        }
  1228. X    } else {                        # Rules in @Linerules array
  1229. X        &rule_cleanup if @Linerules == 1;
  1230. X    }
  1231. X
  1232. X    while ($line = do get_line()) {
  1233. X        # Detect environment settings as soon as possible
  1234. X        if ($line =~ s/^\s*(\w+)\s*=\s*//) {
  1235. X            # All the variables referenced in the line have to be environment
  1236. X            # variables. So replace them with the values we already computed as
  1237. X            # perl variables. This enables us to do variable substitution in
  1238. X            # perl with minimum trouble.
  1239. X            $env = $1;                                # Variable being changed
  1240. X            $line =~ s/\$(\w+)/\$XENV{'$1'}/g;        # $VAR -> $XENV{'VAR'}
  1241. X            $line =~ s/;$//;                        # Remove trailing ;
  1242. X            eval "\$XENV{'$env'} = \"$line\"";        # Perl does the evaluations
  1243. X            &eval_error;                            # Report any eval error
  1244. X            next;
  1245. X        }
  1246. X        $rulekeys = '';                        # Reset keys for each line
  1247. X        $mode = do get_mode(*line);            # Get operational mode
  1248. X        do add_log("mode: <$mode>") if $loglvl > 19;
  1249. X        $first_selector = do get_selector(*line);        # Fetch a selector
  1250. X        $first_selector = "Subject:" unless $first_selector;
  1251. X        $selector = $first_selector;
  1252. X        for (;;) {
  1253. X            if ($line =~ /^\s*;/) {            # Selector alone on the line
  1254. X                &add_log("ERROR no pattern nor action, line $.") if $loglvl > 1;
  1255. X                last;                        # Ignore the whole line
  1256. X            }
  1257. X            do add_log("selector: $selector") if $loglvl > 19;
  1258. X            # Get a pattern. If none is found, it is assumed to be '*', which
  1259. X            # will match anything.
  1260. X            $pattern = do get_pattern(*line);
  1261. X            $pattern = '*' if $pattern =~ /^\s*$/;
  1262. X            do add_log("pattern: $pattern") if $loglvl > 19;
  1263. X            # Record entry in H table and update the set of used keys
  1264. X            $Rule{"H$rulenum"} = "$selector $pattern";
  1265. X            $rulekeys .= "H$rulenum ";
  1266. X            $rulenum++;
  1267. X            # Now look for an action. No action at the end means LEAVE.
  1268. X            $action = do get_action(*line);
  1269. X            $action = "LEAVE" if $action =~ /^\s*$/ && $line =~/^\s*;/;
  1270. X            if ($action !~ /^\s*$/) {
  1271. X                do add_log("action: $action") if $loglvl > 19;
  1272. X                push(@Rules, "$mode {$action} $rulekeys");
  1273. X                $rulekeys = '';        # Reset rule keys once used
  1274. X            }
  1275. X            last if $line =~ /^\s*;/;    # Finished if end of line reached
  1276. X            last if $line =~ /^\s*$/;    # Also finished if end of file
  1277. X            # Get a new selector, defaults to last one seen if none is found
  1278. X            $selector = do get_selector(*line);
  1279. X            $selector = $first_selector if $selector eq '';
  1280. X            $first_selector = $selector;
  1281. X        }
  1282. X    }
  1283. X    close RULES;        # This may not have been opened
  1284. X
  1285. X    &default_rules unless @Rules;    # Use defaults if no valid rules
  1286. X}
  1287. X
  1288. X# Build default rules:
  1289. X#  -  Anything with 'Subject: Command' in it is processed.
  1290. X#  -  All the mails are left in the mailbox.
  1291. Xsub default_rules {
  1292. X    do add_log("building default rules") if $loglvl > 18;
  1293. X    @Rules = ("ALL {LEAVE; PROCESS} H0");
  1294. X    $Rule{'H0'} = "All: /^Subject: [Cc]ommand/";
  1295. X}
  1296. X
  1297. X# Rule cleanup: If there is only one rule specified within the @Linerules
  1298. X# array, it might not have {} braces.
  1299. Xsub rule_cleanup {
  1300. X    return if $Linerules[0] =~ /[{}]/;        # Braces found
  1301. X    $Linerules[0] = '{' . $Linerules[0] . '}';
  1302. X}
  1303. X
  1304. X# Hook functions for dumping rules
  1305. Xsub print_rule_number {
  1306. X    local($rulenum) = @_;
  1307. X    print "# Rule $rulenum\n";            # For easier reference
  1308. X    1;                                    # Continue
  1309. X}
  1310. X
  1311. X# Void function
  1312. Xsub void_func {
  1313. X    print "\n";
  1314. X}
  1315. X
  1316. X# Print only rule whose number is held in variable $number
  1317. Xsub exact_rule {
  1318. X    $_[0] eq $number;
  1319. X}
  1320. X
  1321. Xsub nothing { }             # Do nothing, really nothing
  1322. X
  1323. X# Dump the rules we've compiled -- for debug purposes
  1324. Xsub dump_rules {
  1325. X    # The 'before' hook is called before each rule is called. It returns a
  1326. X    # boolean stating wether we should continue or skip the rule. The 'after'
  1327. X    # hook is called after the rule has been printed. Both hooks are given the
  1328. X    # rule number as argument.
  1329. X    local(*before, *after) = @_;    # Hook functions to be called
  1330. X    local($mode);            # mode (optional)
  1331. X    local($selector);        # selector (mandatory)
  1332. X    local($rulentry);        # entry in rule H table
  1333. X    local($pattern);        # pattern for selection
  1334. X    local($action);            # related action
  1335. X    local($last_selector);    # last used selector
  1336. X    local($rules);            # a copy of the rules
  1337. X    local($rulenum) = 0;    # each rule is numbered
  1338. X    local($lines);            # number of pattern lines printed
  1339. X    local($selnum);            # number of selector printed
  1340. X    local(@action);            # split actions (split on ;)
  1341. X    # Print the environement variable which differ from the original
  1342. X    # environment, i.e. those variable which were set by the user.
  1343. X    $lines = 0;
  1344. X    foreach (keys(%XENV)) {
  1345. X        unless ("$XENV{$_}" eq "$ENV{$_}") {
  1346. X            print "$_ = ", $XENV{$_}, ";\n";
  1347. X            $lines++;
  1348. X        }
  1349. X    }
  1350. X    print "\n" if $lines;
  1351. X    # Order wrt the one in the rule file is guaranteed
  1352. X    foreach (@Rules) {
  1353. X        $rulenum++;
  1354. X        next unless &before($rulenum);                # Call 'before' hook
  1355. X        $selnum = 0;
  1356. X        $rules = $_;        # Work on a copy
  1357. X        $rules =~ s/^(.*){// && ($mode = $1);        # First "word" is the mode
  1358. X        $rules =~ s/\s*(.*)}// && ($action = $1);    # Then action within {}
  1359. X        $mode =~ s/\s*$//;                            # Remove trailing spaces
  1360. X        print "<$mode> ";                            # Mode in which it applies
  1361. X        $rules =~ s/^\s+//;                            # The rule keys remain
  1362. X        $last_selector = "";                        # Last selector in use
  1363. X        $lines = 0;
  1364. X        foreach $key (split(/ /, $rules)) {            # Loop over the keys
  1365. X            $rulentry = $Rule{$key};
  1366. X            $rulentry =~ s/^\s*([^\/]*:)// && ($selector = $1);
  1367. X            $rulentry =~ s/^\s*//;
  1368. X            $pattern = $rulentry;
  1369. X            if ($last_selector eq $selector) {        # Remain on same line
  1370. X                if ($selnum++ < 2) {                # Unless already 3 printed
  1371. X                    print ", ";
  1372. X                } else {
  1373. X                    print ",\n", ' ' x (length($mode) + length($selector) + 4);
  1374. X                    $selnum = 0;
  1375. X                }
  1376. X            } else {                                # Selector has changed
  1377. X                print ",\n", ' ' x (length($mode) + 3) if $lines++;
  1378. X            }
  1379. X            if ($last_selector ne $selector) {        # Update last selector
  1380. X                $last_selector = $selector;
  1381. X                print "$selector " if $selector ne 'script:';
  1382. X            }
  1383. X            if ($selector ne 'script:') {
  1384. X                print "$pattern";                    # Normal pattern
  1385. X            } else {
  1386. X                print "[[ $pattern ]] ";            # An interpreted script
  1387. X            }
  1388. X        }
  1389. X        print "  " if $lines == 1;
  1390. X        @action = split(/;/, $action);
  1391. X        # If action is large enough, format differently (one action/line)
  1392. X        if (length($action) > 60 && @action > 1) {
  1393. X            print "\n\t{\n";
  1394. X            foreach $act (@action) {
  1395. X                $act =~ s/^\s+//;
  1396. X                print "\t\t$act;\n";
  1397. X            }
  1398. X            print "\t};\n";
  1399. X        } else {
  1400. X            print "\n", ' ' x (length($mode) + 3), ' ' x 4 if $lines > 1;
  1401. X            print "{ $action };\n";
  1402. X        }
  1403. X        # Call the hook function after having printed the rule
  1404. X        &after($rulenum);
  1405. X    }
  1406. X}
  1407. X
  1408. X# Print only a specific rule on stdout
  1409. Xsub print_rule {
  1410. X    local($number) = @_;
  1411. X    local(%XENV);            # Suppress printing of leading variables
  1412. X    &dump_rules(*exact_rule, *nothing);
  1413. X}
  1414. X
  1415. END_OF_FILE
  1416.   if test 8559 -ne `wc -c <'agent/pl/rules.pl'`; then
  1417.     echo shar: \"'agent/pl/rules.pl'\" unpacked with wrong size!
  1418.   fi
  1419.   # end of 'agent/pl/rules.pl'
  1420. fi
  1421. if test -f 'config.h.SH' -a "${1}" != "-c" ; then 
  1422.   echo shar: Will not clobber existing file \"'config.h.SH'\"
  1423. else
  1424.   echo shar: Extracting \"'config.h.SH'\" \(7132 characters\)
  1425.   sed "s/^X//" >'config.h.SH' <<'END_OF_FILE'
  1426. Xcase $CONFIG in
  1427. X'')
  1428. X    if test ! -f config.sh; then
  1429. X        ln ../config.sh . || \
  1430. X        ln ../../config.sh . || \
  1431. X        ln ../../../config.sh . || \
  1432. X        (echo "Can't find config.sh."; exit 1)
  1433. X    fi 2>/dev/null
  1434. X    . ./config.sh
  1435. X    ;;
  1436. Xesac
  1437. Xecho "Extracting config.h (with variable substitutions)"
  1438. Xsed <<!GROK!THIS! >config.h -e 's!^#undef!/\*#define!'
  1439. X/*
  1440. X * This file was produced by running the config.h.SH script, which
  1441. X * gets its values from config.sh, which is generally produced by
  1442. X * running Configure.
  1443. X *
  1444. X * Feel free to modify any of this as the need arises.  Note, however,
  1445. X * that running config.h.SH again will wipe out any changes you've made.
  1446. X * For a more permanent change edit config.sh and rerun config.h.SH.
  1447. X *
  1448. X * \$Id: config.h.SH,v 2.9 92/07/14 16:53:43 ram Exp $
  1449. X */
  1450. X
  1451. X#ifndef _config_h_
  1452. X#define _config_h_
  1453. X
  1454. X/* bcopy:
  1455. X *    This symbol is maped to memcpy if the  bcopy() routine is not
  1456. X *    available to copy strings.
  1457. X */
  1458. X#$d_bcopy bcopy(s,d,l) memcpy((d),(s),(l))        /* mapped to memcpy */
  1459. X
  1460. X/* GETHOSTNAME:
  1461. X *    This symbol, if defined, indicates that the C program may use the
  1462. X *    gethostname() routine to derive the host name.  See also UNAME
  1463. X *    and PHOSTNAME.
  1464. X */
  1465. X/* UNAME:
  1466. X *    This symbol, if defined, indicates that the C program may use the
  1467. X *    uname() routine to derive the host name.  See also GETHOSTNAME and
  1468. X *    PHOSTNAME.
  1469. X */
  1470. X/* PHOSTNAME:
  1471. X *    This symbol, if defined, indicates that the C program may use the
  1472. X *    contents of PHOSTNAME as a command to feed to the popen() routine
  1473. X *    to derive the host name.  See also GETHOSTNAME and UNAME. Note that the
  1474. X *    command uses a fully qualified path, so that it is safe even if used by
  1475. X *    a process with super-user privileges.
  1476. X */
  1477. X#$d_gethname GETHOSTNAME    /**/
  1478. X#$d_uname UNAME        /**/
  1479. X#$d_phostname PHOSTNAME "$aphostname"    /* How to get the host name */
  1480. X
  1481. X/* index:
  1482. X *    This preprocessor symbol is defined, along with rindex, if the system
  1483. X *    uses the strchr and strrchr routines instead.
  1484. X */
  1485. X/* rindex:
  1486. X *    This preprocessor symbol is defined, along with index, if the system
  1487. X *    uses the strchr and strrchr routines instead.
  1488. X */
  1489. X#$d_index    index strchr    /**/
  1490. X#$d_index    rindex strrchr    /**/
  1491. X
  1492. X/* RENAME:
  1493. X *    This symbol, if defined, indicates that the rename routine is available
  1494. X *    to rename files.  Otherwise you should do the unlink(), link(), unlink()
  1495. X *    trick.
  1496. X */
  1497. X#$d_rename    RENAME        /**/
  1498. X
  1499. X/* STRERROR:
  1500. X *    This symbol, if defined, indicates that the strerror routine is
  1501. X *    available to translate error numbers to strings.
  1502. X */
  1503. X/* SYSERRLIST:
  1504. X *    This symbol, if defined, indicates that the sys_errlist array is
  1505. X *    available to translate error numbers to strings. The extern int
  1506. X *    sys_nerr gives the size of that table.
  1507. X */
  1508. X/* SYSERRNOLIST:
  1509. X *    This symbol, if defined, indicates that the sys_errnolist array is
  1510. X *    available to translate an errno code into its symbolic name (e.g.
  1511. X * ENOENT). The extern int sys_nerrno gives the size of that table.
  1512. X */
  1513. X/* strerror:
  1514. X *    This preprocessor symbol is defined as a macro if strerror() is
  1515. X *    not available to translate error numbers to strings but sys_errlist[]
  1516. X *    array is there.
  1517. X */
  1518. X#$d_strerror STRERROR        /**/
  1519. X#$d_syserrlst SYSERRLIST        /**/
  1520. X#$d_sysernlst SYSERRNOLIST    /**/
  1521. X#$d_strerrm strerror(e) ((e)<0||(e)>=sys_nerr?"(unknown)":sys_errlist[e]) /**/
  1522. X
  1523. X/* Time_t:
  1524. X *    This symbol holds the time type, which can be long or time_t on BSD
  1525. X *    sites (in which case <sys/types.h> should be included).
  1526. X */
  1527. X#define Time_t $timetype            /* Time type */
  1528. X
  1529. X/* UNION_WAIT:
  1530. X *    This symbol if defined indicates to the C program that the argument
  1531. X *    for the wait() system call should be declared as 'union wait status'
  1532. X *    instead of 'int status'. You probably need to include <sys/wait.h>
  1533. X *    in the former case (see I_SYSWAIT).
  1534. X */
  1535. X#$d_uwait UNION_WAIT        /**/
  1536. X
  1537. X/* vfork:
  1538. X *    This symbol, if defined, remaps the vfork routine to fork if the
  1539. X *    vfork() routine isn't supported here.
  1540. X */
  1541. X#$d_vfork    vfork fork    /**/
  1542. X
  1543. X/* Signal_t:
  1544. X *    This symbol's value is either "void" or "int", corresponding to the
  1545. X *    appropriate return type of a signal handler.  Thus, you can declare
  1546. X *    a signal handler using "Signal_t (*handler())()", and define the
  1547. X *    handler using "Signal_t handler(sig)".
  1548. X */
  1549. X#define Signal_t $signal_t    /* Signal handler's return type */
  1550. X
  1551. X/* HOSTNAME:
  1552. X *    This symbol contains name of the host the program is going to run on.
  1553. X *    The domain is not kept with hostname, but must be gotten from MYDOMAIN.
  1554. X *    The dot comes with MYDOMAIN, and need not be supplied by the program.
  1555. X *    If gethostname() or uname() exist, HOSTNAME may be ignored. If MYDOMAIN
  1556. X *    is not used, HOSTNAME will hold the name derived from PHOSTNAME.
  1557. X */
  1558. X#define HOSTNAME "$hostname"        /**/
  1559. X
  1560. X/* I_FCNTL:
  1561. X *    This symbol, if defined, indicates to the C program that it should
  1562. X *    include <fcntl.h>.
  1563. X */
  1564. X#$i_fcntl    I_FCNTL        /**/
  1565. X
  1566. X/* I_STRING:
  1567. X *    This symbol, if defined, indicates to the C program that it should
  1568. X *    include <string.h> (USG systems) instead of <strings.h> (BSD systems).
  1569. X */
  1570. X#$i_string I_STRING        /**/
  1571. X
  1572. X/* I_SYSFILE:
  1573. X *    This symbol, if defined, indicates to the C program that it should
  1574. X *    include <sys/file.h> to get definition of R_OK and friends.
  1575. X */
  1576. X#$i_sysfile    I_SYSFILE        /**/
  1577. X
  1578. X/* I_SYSWAIT:
  1579. X *    This symbol, if defined, indicates to the C program that it should
  1580. X *    include <sys/wait.h>.
  1581. X */
  1582. X#$i_syswait I_SYSWAIT    /**/
  1583. X
  1584. X/* I_TIME:
  1585. X *    This symbol, if defined, indicates to the C program that it should
  1586. X *    include <time.h>.
  1587. X */
  1588. X/* I_SYSTIME:
  1589. X *    This symbol, if defined, indicates to the C program that it should
  1590. X *    include <sys/time.h>.
  1591. X */
  1592. X/* I_SYSTIMEKERNEL:
  1593. X *    This symbol, if defined, indicates to the C program that it should
  1594. X *    include <sys/time.h> with KERNEL defined.
  1595. X */
  1596. X#$i_time I_TIME        /**/
  1597. X#$i_systime I_SYSTIME        /**/
  1598. X#$i_systimek I_SYSTIMEKERNEL        /**/
  1599. X
  1600. X/* INTSIZE:
  1601. X *    This symbol contains the size of an int, so that the C preprocessor
  1602. X *    can make decisions based on it.
  1603. X */
  1604. X#define INTSIZE $intsize        /**/
  1605. X
  1606. X/* PERLPATH:
  1607. X *    This symbol contains the absolute location of the perl interpeter.
  1608. X */
  1609. X#define PERLPATH "$perlpath"        /**/
  1610. X
  1611. X/* Pid_t:
  1612. X *    This symbol holds the type used to declare process ids in the kernel.
  1613. X *    It can be int, uint, pid_t, etc... It may be necessary to include
  1614. X *    <sys/types.h> to get any typedef'ed information.
  1615. X */
  1616. X#define Pid_t $pidtype        /* PID type */
  1617. X
  1618. X/* register1:
  1619. X *    This symbol, along with register2, register3, etc. is either the word
  1620. X *    "register" or null, depending on whether the C compiler pays attention
  1621. X *    to this many register declarations.  The intent is that you don't have
  1622. X *    to order your register declarations in the order of importance, so you
  1623. X *    can freely declare register variables in sub-blocks of code and as
  1624. X *    function parameters.  Do not use register<n> more than once per routine.
  1625. X */
  1626. X#define register1 $reg1        /**/
  1627. X#define register2 $reg2        /**/
  1628. X#define register3 $reg3        /**/
  1629. X#define register4 $reg4        /**/
  1630. X#define register5 $reg5        /**/
  1631. X#define register6 $reg6        /**/
  1632. X
  1633. X/* Uid_t:
  1634. X *    This symbol holds the type used to declare user ids in the kernel.
  1635. X *    It can be int, ushort, uid_t, etc... It may be necessary to include
  1636. X *    <sys/types.h> to get any typedef'ed information.
  1637. X */
  1638. X#define Uid_t $uidtype        /* UID type */
  1639. X
  1640. X#endif
  1641. X!GROK!THIS!
  1642. END_OF_FILE
  1643.   if test 7132 -ne `wc -c <'config.h.SH'`; then
  1644.     echo shar: \"'config.h.SH'\" unpacked with wrong size!
  1645.   fi
  1646.   # end of 'config.h.SH'
  1647. fi
  1648. echo shar: End of archive 11 \(of 17\).
  1649. cp /dev/null ark11isdone
  1650. MISSING=""
  1651. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ; do
  1652.     if test ! -f ark${I}isdone ; then
  1653.     MISSING="${MISSING} ${I}"
  1654.     fi
  1655. done
  1656. if test "${MISSING}" = "" ; then
  1657.     echo You have unpacked all 17 archives.
  1658.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1659. else
  1660.     echo You still must unpack the following archives:
  1661.     echo "        " ${MISSING}
  1662. fi
  1663. exit 0
  1664. exit 0 # Just in case...
  1665.