home *** CD-ROM | disk | FTP | other *** search
- Subject: v18i087: Elm mail system, release 2.2, Part08/24
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: dsinc!syd@uunet.UU.NET (Syd Weinstein)
- Posting-number: Volume 18, Issue 87
- Archive-name: elm2.2/part08
-
- #!/bin/sh
- # this is part 8 of a multipart archive
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file doc/tmac.n continued
- #
- CurArch=8
- if test ! -r s2_seq_.tmp
- then echo "Please unpack part 1 first!"
- exit 1; fi
- ( read Scheck
- if test "$Scheck" != $CurArch
- then echo "Please unpack part $Scheck next!"
- exit 1;
- else exit 0; fi
- ) < s2_seq_.tmp || exit 1
- echo "x - Continuing file doc/tmac.n"
- sed 's/^X//' << 'SHAR_EOF' >> doc/tmac.n
- X. ef \" short and sweet ...
- X.\}
- X..
- X.de ux \" print "UNIX"
- X.ie \\n(ux \\&\\$2\\s-1UNIX\\s0\\$1
- X.el \{\
- X. nr ux +1 \" mark footnote as dropped
- X\\&\\$2\\s-1UNIX\\s0\\*(rg\\$1
- X. fn \" put out the footnote
- X\\&\\*(rgUNIX is a registered trademark of AT&T.
- X. ef \" short and sweet ...
- X.\}
- X..
- X.de vx \" print "VAX"
- X.ie \\n(vx \\&\\$2\\s-1VAX\\s0\\$1
- X.el \{\
- X. nr vx +1 \" mark footnote as dropped
- X\\&\\$2\\s-1VAX\\s0\\*(rg\\$1
- X. fn \" put out the footnote
- X\\&\\*(rgVAX is a trademark of Digital Equipment Corporation.
- X. ef \" short and sweet ...
- X.\}
- X..
- X.\" **********
- X.\" set up string and number registers
- X. \" set up for the date
- X.if \n(mo=1 .ds mo January
- X.if \n(mo=2 .ds mo February
- X.if \n(mo=3 .ds mo March
- X.if \n(mo=4 .ds mo April
- X.if \n(mo=5 .ds mo May
- X.if \n(mo=6 .ds mo June
- X.if \n(mo=7 .ds mo July
- X.if \n(mo=8 .ds mo August
- X.if \n(mo=9 .ds mo September
- X.if \n(mo=10 .ds mo October
- X.if \n(mo=11 .ds mo November
- X.if \n(mo=12 .ds mo December
- X.ds dy "\*(mo \n(dy, 19\n(yr
- X.if \n(dw=1 .ds dw Sunday
- X.if \n(dw=2 .ds dw Monday
- X.if \n(dw=3 .ds dw Tuesday
- X.if \n(dw=4 .ds dw Wednesday
- X.if \n(dw=5 .ds dw Thursday
- X.if \n(dw=6 .ds dw Friday
- X.if \n(dw=7 .ds dw Saturday
- X. \" NROFF dependencies
- X.if n \{\
- X. \" string registers
- X. ds rg (R)
- X. ds lq ""
- X. ds rq ""
- X. ds f1 "\*(dy
- X. \" number registers
- X. nr hs 1v \" space before section header
- X. nr pd 1v \" inter-paragraph spacing
- X. nr bm 1.0i \" height of bottom margin
- X.\}
- X. \" NROFF dependencies
- X.if t \{\
- X. \" string registers
- X. ds rg \\u\\s-2\\(rg\\s0\\d
- X. ds lq ``
- X. ds rq ''
- X. \" number registers
- X. nr hs 1v \" space before section header
- X. nr pd 0.3v \" inter-paragraph spacing
- X. nr bm 1.0i+1v \" height of bottom margin (wacky laser)
- X.\}
- X. \" these are the same for [NT]ROFF
- X.ds dg \(dg
- X.ds vr "News Version B2.11
- X.ds pv "News macros 1.5
- X.ds h1 - % -
- X.nr bt 0.5i+1v \" bottom of page to footer
- X.nr cm 0 \" no cut marks
- X.nr fc 0 1 \" init footnote count
- X.nr fl 5.5i \" footnote line length
- X.nr fp 0-\n(bmu \" fo macro trap location
- X.nr h0 0 \" init section header level 0
- X.nr h1 0 \" init section header level 1
- X.nr h2 0 \" init section header level 2
- X.nr h3 0 \" init section header level 3
- X.nr id 0 \" 1 in display
- X.nr if 0 \" 1 in keep
- X.nr it 0 \" 1 when beyond title, etc.
- X.nr li 5n \" indent for labelled paragraph
- X.nr ll 6.5i \" line length
- X.nr lm 0 \" left margin
- X.nr l0 0 \" first indent level
- X.nr mt 1.5i+1v \" title goes down this far
- X.nr pi 5n \" regular paragraph indent
- X.nr po 1.0i \" page offset
- X.nr ps 10 \" point size
- X.nr tm 1.0i \" height of top margin
- X.nr tt 0.5i-0.5v \" top of page to header
- X.nr p1 0 \" no PDP-TM message yet
- X.nr ux 0 \" no UNIX-TM message yet
- X.nr vx 0 \" no VAX-TM message yet
- X.nr vs 12 \" vertical spacing
- X.\" set things up
- X.\" DSINC changes for XROFF
- X.nr f1 1
- X.nr f2 1
- X.nr s1 10
- X.nr s2 10
- X.nr v1 12
- X.nr v2 12
- X.ps 10
- X.vs 12
- X.\" DSINC end changes for XROFF
- X.po \n(pou \" set page offset
- X.ps \n(ps \" set previous, current
- X.ps \n(ps \" point sizes
- X.vs \n(vs \" set previous, current
- X.vs \n(vs \" vertical spacings
- X.ll \n(llu \" set line length
- X.lt \n(llu \" set title line length
- X.ev 1 \" *** footnote environment
- X.ps \n(ps-2p \" set previous, current
- X.ps \n(ps-2p \" point sizes
- X.vs \n(vs-2p \" set previous, current
- X.vs \n(vs-2p \" vertical spacings
- X.ll \n(flu \" set line length
- X.lt \n(flu \" set title line length
- X.ev \" *** pop environment
- X.ev 2 \" *** footnote environment
- X.ps \n(ps \" set previous, current
- X.ps \n(ps \" point sizes
- X.vs \n(vs \" set previous, current
- X.vs \n(vs \" vertical spacings
- X.ll \n(llu \" set line length
- X.lt \n(llu \" set title line length
- X.ev \" *** pop environment
- X.\" now set internal registers (for the first header section)
- X.nr f1 \n(.f \" saved font #1
- X.nr f2 \n(.f \" saved font #2
- X.nr s1 \n(.s \" saved point size #1
- X.nr s2 \n(.s \" saved point size #2
- X.nr v1 \n(.v \" saved vertical spacing #1
- X.nr v2 \n(.v \" saved vertical spacing #2
- X.\" install traps
- X.wh 0i hd \" position header trap
- X.wh -\n(bmu fo \" position footer trap
- X.wh \n(.pu+1i fx \" put footnote overflow trap here
- X.ch fx -\n(bmu \" move it over fo
- X.wh -\n(btu pf \" print the bottom margin here
- X.em et \" at end of file, call et
- X.\" couple of miscellaneous requests
- X.bd S 3 3 \" embolden special font chars if B
- X.hy 2 \" don't hyphenate last lines
- SHAR_EOF
- echo "File doc/tmac.n is complete"
- chmod 0444 doc/tmac.n || echo "restore of doc/tmac.n fails"
- echo "x - extracting doc/wnewmail.1 (Text)"
- sed 's/^X//' << 'SHAR_EOF' > doc/wnewmail.1 &&
- X.TH WNEWMAIL 1L "Elm Version 2.2" "USENET Community Trust"
- X.ad b
- X.SH NAME
- Xwnewmail - daemon to asynchronously notify of new mail
- X.SH SYNOPSIS
- X.B wnewmail
- X.br
- X.B wnewmail
- Xfilename
- X.PP
- X.SH DESCRIPTION
- X.I Wnewmail\^
- Xis a daemon designed to run in \fBa window\fR on a windowing
- Xsystem (such as an HP or Sun system) and check every 10 seconds
- Xto see if there is any new mail for the user that
- Xstarted it up.
- X.P
- XIf there is new mail, the program will "beep", and write to
- Xthe window for each of the new messages;
- X.nf
- X
- X Mail from <name> -- <subject>
- X
- X.fi
- Xwhere <name> is either the name of the person sending it,
- Xif available (the ARPA 'From:' line) or machine!login where
- Xmachine is the machine the mail was sent from. If there
- Xis no subject, the message "<no subject>" will appear on
- Xthe screen.
- X.P
- XIf the message is a \fIpriority\fR message (that is, the
- Xheader contains a line "Priority:"), then the line output
- Xwill be "PRIORITY mail from ..." rather than just "Mail from".
- X.P
- XThis program will run forever, and can internally reset
- Xitself if mail is deleted from the incoming mailbox while
- Xtrying to monitor it.
- X.P
- XIf \fBwnewmail\fR is started up with a filename, it will
- Xperform exactly the same, but with the specified file as
- Xthe one to check rather than the default users mailbox.
- X.SH AUTHOR
- XDave Taylor, Hewlett-Packard Laboratories.
- X.SH SEE ALSO
- Xnotify in sh(1) or csh(1), newmail(1L)
- X.SH NOTE
- XThis is almost identical to the program \fBnewmail\fR...
- X.SH BUG REPORTS TO
- XSyd Weinstein elm@dsinc.UUCP (dsinc!elm)
- X.SH COPYRIGHTS
- X.ps 18
- X\fB\(co\fR\s12 Copyright 1986, 1987 by Dave Taylor
- X.br
- X.ps 18
- X\fB\(co\fR\s12 Copyright 1988, 1989 by The USENET Community Trust
- SHAR_EOF
- chmod 0444 doc/wnewmail.1 || echo "restore of doc/wnewmail.1 fails"
- echo "x - extracting filter/Makefile.SH (Text)"
- sed 's/^X//' << 'SHAR_EOF' > filter/Makefile.SH &&
- Xcase $CONFIG in
- X'')
- X if test ! -f config.sh; then
- X ln ../config.sh . || \
- X ln ../../config.sh . || \
- X ln ../../../config.sh . || \
- X (echo "Can't find config.sh."; exit 1)
- X fi
- X . ./config.sh
- X ;;
- Xesac
- Xcase "$0" in
- X*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
- Xesac
- X
- Xecho "Extracting filter/Makefile (with variable substitutions)"
- Xcat >Makefile <<!GROK!THIS!
- X#
- X# @(#)$Id: Makefile.SH,v 2.11 89/03/25 21:45:09 syd Exp $
- X# Makefile for the Elm system filter program
- X#
- X# Copyright (c) 1986, 1987 Dave Taylor
- X# Copyright (c) 1988, 1989 USENET Community Trust
- X#
- X# Bug reports, patches, comments, suggestions should be sent to:
- X#
- X# Syd Weinstein - elm@dsinc.UUCP
- X# dsinc!elm
- X#
- X# $Log: Makefile.SH,v $
- X# Revision 2.11 89/03/25 21:45:09 syd
- X# Initial 2.2 Release checkin
- X#
- X#
- X# Variables
- X# Variables established by Configure
- XCC = $cc
- XCCFLAGS = $ccflags $xencf
- XCHGRP = $chgrp
- XCHMOD = $chmod
- XCP = $cp
- XDEST = $bin
- XECHO = $echo
- XLFLAGS = $ldflags $xenlf
- XLIB = $lib
- XLIB2 = $libs
- XLIBS = $termlib $dbm
- XLINT = $lint
- XMAILGRP = $mailgrp
- XMAILERMODE = $mailermode
- XMAKE = $make
- XMV = $mv
- XOPTIMIZE = $optimize
- XRM = $rm -f
- XTOUCH = $touch
- X
- X!GROK!THIS!
- X
- Xcat >>Makefile <<'!NO!SUBS!'
- X# Variables you may want to manually edit
- X# If you want debug logging then you'll
- X# want to uncomment the following.
- X#DEBUG = -DDEBUG
- X
- X# Other variables
- XBIN = ../bin
- XINCLDIR = ../hdrs
- XCFLAGS = $(CCFLAGS) $(OPTIMIZE) -I$(INCLDIR) $(DEBUG) $(DACSNET)
- XLINTFLAGS = -I$(INCLDIR)
- XSHELL = /bin/sh
- X
- X# Definitions of variables
- XFILTER_SRC = actions.c \
- X buffer.c \
- X filter.c \
- X lock.c \
- X parse.c \
- X rules.c \
- X summarize.c \
- X utils.c \
- X ../src/opt_utils.c
- X
- XFILTER_OBJ = actions.o \
- X buffer.o \
- X filter.o \
- X lock.o \
- X parse.o \
- X rules.o \
- X summarize.o \
- X utils.o \
- X ../src/opt_utils.o
- X
- X# Standard targets
- Xall: $(BIN)/filter
- X
- Xinstall: $(DEST)/filter
- X
- Xuninstall:
- X $(RM) $(DEST)/filter
- X
- X# This is the only target that gets installed even if not out-of-date
- X# with respect the files from which it is installed.
- Xrmt-install: rmt-defined
- X -$(MV) $(DEST)/filter $(DEST)/filter.old
- X -$(RM) $(DEST)/filter.old
- X $(CP) $(REMOTE)$(DEST)/filter $(DEST)/filter
- X $(CHGRP) $(MAILGRP) $(DEST)/filter
- X $(CHMOD) $(MAILERMODE) $(DEST)/filter
- X
- Xrmt-defined:
- X @(if [ "$(REMOTE)" = "" ];\
- X then\
- X $(ECHO) "You need to define 'REMOTE' as the remote file system";\
- X $(ECHO) "for this particular command. The easiest way to do this";\
- X $(ECHO) "to type:";\
- X $(ECHO) " make REMOTE=<remote file system> rmt-install";\
- X exit 1;\
- X fi);
- X
- Xlint:
- X $(LINT) $(LINTFLAGS) $(FILTER_SRC) > LINT.OUT
- X
- Xclean:
- X $(RM) $(FILTER_OBJ) $(BIN)/filter
- X
- X# Dependencies and rules
- X# Dependencies of header files upon other header files they include
- X$(INCLDIR)/defs.h: $(INCLDIR)/../config.h $(INCLDIR)/sysdefs.h
- X $(CHMOD) u+w $@
- X $(TOUCH) $@
- X
- X$(INCLDIR)/elm.h: $(INCLDIR)/curses.h $(INCLDIR)/defs.h
- X $(CHMOD) u+w $@
- X $(TOUCH) $@
- X
- X$(INCLDIR)/headers.h: $(INCLDIR)/curses.h $(INCLDIR)/defs.h
- X $(CHMOD) u+w $@
- X $(TOUCH) $@
- X
- X# Dependencies and rules for C object files
- Xactions.o: $(INCLDIR)/defs.h $(INCLDIR)/filter.h
- Xfilter.o: $(INCLDIR)/defs.h $(INCLDIR)/filter.h
- Xlock.o: $(INCLDIR)/defs.h $(INCLDIR)/filter.h
- Xparse.o: $(INCLDIR)/defs.h $(INCLDIR)/filter.h
- Xrules.o: $(INCLDIR)/defs.h $(INCLDIR)/filter.h
- Xsummarize.o: $(INCLDIR)/defs.h $(INCLDIR)/filter.h
- Xutils.o: $(INCLDIR)/defs.h $(INCLDIR)/filter.h
- X../src/opt_utils.o:
- X cd ../src; $(MAKE) -$(MAKEFLAGS) $(@F)
- X
- X# Dependencies and rules for compiling programs
- X$(BIN)/filter: $& $(FILTER_OBJ)
- X $(CC) $(LFLAGS) -o $@ $(FILTER_OBJ) $(LIB2)
- X
- X# Dependencies and rules for installing programs from bin directory
- X$(DEST)/filter: $(BIN)/filter
- X -$(MV) $(DEST)/filter $(DEST)/filter.old
- X -$(RM) $(DEST)/filter.old
- X $(CP) $? $@
- X $(CHGRP) $(MAILGRP) $@
- X $(CHMOD) $(MAILERMODE) $@
- X!NO!SUBS!
- SHAR_EOF
- chmod 0444 filter/Makefile.SH || echo "restore of filter/Makefile.SH fails"
- echo "x - extracting filter/actions.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > filter/actions.c &&
- X
- Xstatic char rcsid[] ="@(#)$Id: actions.c,v 2.4 89/03/25 21:45:10 syd Exp $";
- X
- X/*******************************************************************************
- X * The Elm Mail System - $Revision: 2.4 $ $State: Exp $
- X *
- X * Copyright (c) 1986, 1987 Dave Taylor
- X * Copyright (c) 1988, 1989 USENET Community Trust
- X *******************************************************************************
- X * Bug reports, patches, comments, suggestions should be sent to:
- X *
- X * Syd Weinstein - elm@dsinc.UUCP
- X * dsinc!elm
- X *
- X *******************************************************************************
- X * $Log: actions.c,v $
- X * Revision 2.4 89/03/25 21:45:10 syd
- X * Initial 2.2 Release checkin
- X *
- X *
- X ******************************************************************************/
- X
- X
- X/** RESULT oriented routines *chuckle*. These routines implement the
- X actions that result from either a specified rule being true or from
- X the default action being taken.
- X**/
- X
- X#include <stdio.h>
- X#include <pwd.h>
- X#include <ctype.h>
- X#include <fcntl.h>
- X
- X#include "defs.h"
- X#include "filter.h"
- X
- XFILE *emergency_local_delivery();
- X
- Xmail_message(address)
- Xchar *address;
- X{
- X /** Called with an address to send mail to. For various reasons
- X that are too disgusting to go into herein, we're going to actually
- X open the users mailbox and by hand add this message. Yech.
- X NOTE, of course, that if we're going to MAIL the message to someone
- X else, that we'll try to do nice things with it on the fly...
- X **/
- X
- X FILE *pipefd, *tempfd, *mailfd;
- X int in_header = TRUE, line_count = 0;
- X char tempfile[SLEN], mailbox[SLEN], lockfile[SLEN],
- X buffer[VERY_LONG_STRING];
- X
- X if (verbose && ! log_actions_only && outfd != NULL)
- X fprintf(outfd, "filter (%s): Mailing message to %s\n",
- X username, address);
- X
- X if (! show_only) {
- X sprintf(tempfile, "%s.%d", filter_temp, getpid());
- X
- X if ((tempfd = fopen(tempfile, "r")) == NULL) {
- X if (outfd != NULL)
- X fprintf(outfd, "filter (%s): Can't open temp file %s!!\n",
- X username, tempfile);
- X if (outfd != NULL) fclose(outfd);
- X exit(1);
- X }
- X
- X if (strcmp(address, username) != 0) { /* mailing to someone else */
- X
- X if (already_been_forwarded) { /* potential looping! */
- X if (contains(from, username)) {
- X if (outfd != NULL)
- X fprintf(outfd,
- X "filter (%s): Filter loop detected! Message left in file %s.%d\n",
- X username, filter_temp, getpid());
- X if (outfd != NULL) fclose(outfd);
- X exit(0);
- X }
- X }
- X
- X sprintf(buffer, "%s %s %s", sendmail, smflags, address);
- X
- X if ((pipefd = popen(buffer, "w")) == NULL) {
- X if (outfd != NULL)
- X fprintf(outfd, "filter (%s): popen %s failed!\n", buffer);
- X sprintf(buffer, "((%s %s %s ; %s %s) & ) < %s &",
- X sendmail , smflags, address, remove_cmd, tempfile, tempfile);
- X system(buffer);
- X return;
- X }
- X
- X fprintf(pipefd, "Subject: \"%s\"\n", subject);
- X fprintf(pipefd, "From: The Filter of %s@%s <%s>\n",
- X username, hostname, username);
- X fprintf(pipefd, "To: %s\n", address);
- X fprintf(pipefd, "X-Filtered-By: filter, version %s\n\n", VERSION);
- X
- X fprintf(pipefd, "-- Begin filtered message --\n\n");
- X
- X while (fgets(buffer, SLEN, tempfd) != NULL)
- X if (already_been_forwarded && in_header)
- X in_header = (strlen(buffer) == 1? 0 : in_header);
- X else
- X fprintf(pipefd," %s", buffer);
- X
- X fprintf(pipefd, "\n-- End of filtered message --\n");
- X fclose(pipefd);
- X fclose(tempfd);
- X
- X return; /* YEAH! Wot a slick program, eh? */
- X
- X }
- X
- X /** OTHERWISE it is to the current user... **/
- X
- X sprintf(mailbox, "%s%s", mailhome, username);
- X
- X if (! lock()) {
- X if (outfd != NULL) {
- X fprintf(outfd, "filter (%s): Couldn't create lockfile %s\n",
- X username, lockfile);
- X fprintf(outfd, "filter (%s): Can't open mailbox %s!\n",
- X username, mailbox);
- X }
- X if ((mailfd = emergency_local_delivery()) == NULL)
- X exit(1);
- X }
- X else if ((mailfd = fopen(mailbox,"a")) == NULL)
- X if ((mailfd = emergency_local_delivery()) == NULL)
- X exit(1);
- X
- X while (fgets(buffer, sizeof(buffer), tempfd) != NULL) {
- X line_count++;
- X if (the_same(buffer, "From ") && line_count > 1)
- X fprintf(mailfd, ">%s", buffer);
- X else
- X fputs(buffer, mailfd);
- X }
- X
- X fputs("\n", mailfd);
- X
- X fclose(mailfd);
- X unlock(); /* blamo or not? Let it decide! */
- X fclose(tempfd);
- X } /* end if show only */
- X}
- X
- Xsave_message(foldername)
- Xchar *foldername;
- X{
- X /** Save the message in a folder. Use full file buffering to
- X make this work without contention problems **/
- X
- X FILE *fd, *tempfd;
- X char filename[SLEN], buffer[SLEN];
- X
- X if (verbose && outfd != NULL)
- X fprintf(outfd, "filter (%s): Message saved in folder %s\n",
- X username, foldername);
- X
- X if (!show_only) {
- X sprintf(filename, "%s.%d", filter_temp, getpid());
- X
- X if ((fd = fopen(foldername, "a")) == NULL) {
- X if (outfd != NULL)
- X fprintf(outfd,
- X "filter (%s): can't save message to requested folder %s!\n",
- X username, foldername);
- X return(1);
- X }
- X
- X if ((tempfd = fopen(filename, "r")) == NULL) {
- X if (outfd != NULL)
- X fprintf(outfd,
- X "filter (%s): can't open temp file for reading!\n",
- X username);
- X return(1);
- X }
- X
- X while (fgets(buffer, sizeof(buffer), tempfd) != NULL)
- X fputs(buffer, fd);
- X
- X fclose(fd);
- X fclose(tempfd);
- X }
- X
- X return(0);
- X}
- X
- Xexecute(command)
- Xchar *command;
- X{
- X /** execute the indicated command, feeding as standard input the
- X message we have.
- X **/
- X
- X char buffer[SLEN];
- X
- X if (verbose && outfd != NULL)
- X fprintf(outfd, "filter (%s): Executing %s\n",
- X username, command);
- X
- X if (! show_only) {
- X sprintf(buffer, "%s %s.%d | %s", cat, filter_temp, getpid(), command);
- X system(buffer);
- X }
- X}
- X
- XFILE *
- Xemergency_local_delivery()
- X{
- X /** This is called when we can't deliver the mail to the usual
- X mailbox in the usual way ...
- X **/
- X
- X FILE *tempfd;
- X char mailbox[SLEN];
- X
- X sprintf(mailbox, "%s/%s", home, EMERGENCY_MAILBOX);
- X
- X if ((tempfd = fopen(mailbox, "a")) == NULL) {
- X if (outfd != NULL)
- X fprintf(outfd, "filter (%s): Can't open %s either!!\n",
- X username, mailbox);
- X
- X sprintf(mailbox,"%s/%s", home, EMERG_MBOX);
- X
- X if ((tempfd = fopen(mailbox, "a")) == NULL) {
- X
- X if (outfd != NULL) {
- X fprintf(outfd,"filter (%s): Can't open %s either!!!!\n",
- X username, mailbox);
- X fprintf(outfd,
- X "filter (%s): I can't open ANY mailboxes! Augh!!\n",
- X username);
- X }
- X
- X fclose(tempfd);
- X leave("Cannot open any mailbox"); /* DIE DIE DIE DIE!! */
- X }
- X else
- X if (outfd != NULL)
- X fprintf(outfd, "filter (%s): Using %s as emergency mailbox\n",
- X username, mailbox);
- X }
- X else
- X if (outfd != NULL)
- X fprintf(outfd, "filter (%s): Using %s as emergency mailbox\n",
- X username, mailbox);
- X
- X return((FILE *) tempfd);
- X}
- SHAR_EOF
- chmod 0444 filter/actions.c || echo "restore of filter/actions.c fails"
- echo "x - extracting filter/buffer.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > filter/buffer.c &&
- X
- Xstatic char rcsid[] ="@(#)$Id: buffer.c,v 2.3 89/03/25 21:45:12 syd Exp $";
- X
- X/*******************************************************************************
- X * The Elm Mail System - $Revision: 2.3 $ $State: Exp $
- X *
- X * Copyright (c) 1986, 1987 Dave Taylor
- X * Copyright (c) 1988, 1989 USENET Community Trust
- X *******************************************************************************
- X * Bug reports, patches, comments, suggestions should be sent to:
- X *
- X * Syd Weinstein - elm@dsinc.UUCP
- X * dsinc!elm
- X *
- X *******************************************************************************
- X * $Log: buffer.c,v $
- X * Revision 2.3 89/03/25 21:45:12 syd
- X * Initial 2.2 Release checkin
- X *
- X *
- X ******************************************************************************/
- X
- X#include <stdio.h>
- X
- Xchar _vbuf[5*BUFSIZ]; /* space for file buffering */
- SHAR_EOF
- chmod 0444 filter/buffer.c || echo "restore of filter/buffer.c fails"
- echo "x - extracting filter/filter.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > filter/filter.c &&
- X
- Xstatic char rcsid[] ="@(#)$Id: filter.c,v 2.6 89/03/25 21:45:13 syd Exp $";
- X
- X/*******************************************************************************
- X * The Elm Mail System - $Revision: 2.6 $ $State: Exp $
- X *
- X * Copyright (c) 1986, 1987 Dave Taylor
- X * Copyright (c) 1988, 1989 USENET Community Trust
- X *******************************************************************************
- X * Bug reports, patches, comments, suggestions should be sent to:
- X *
- X * Syd Weinstein - elm@dsinc.UUCP
- X * dsinc!elm
- X *
- X *******************************************************************************
- X * $Log: filter.c,v $
- X * Revision 2.6 89/03/25 21:45:13 syd
- X * Initial 2.2 Release checkin
- X *
- X *
- X ******************************************************************************/
- X
- X
- X/** This program is used as a filter within the users ``.forward'' file
- X and allows intelligent preprocessing of mail at the point between
- X when it shows up on the machine and when it is actually put in the
- X mailbox.
- X
- X The program allows selection based on who the message is FROM, TO, or
- X what the subject is. Acceptable actions are for the program to DELETE_MSG
- X the message, SAVE the message in a specified folder, FORWARD the message
- X to a specified user, SAVE the message in a folder, but add a copy to the
- X users mailbox anyway, or simply add the message to the incoming mail.
- X
- X Filter also keeps a log of what it does as it goes along, and at the
- X end of each `quantum' mails a summary of actions, if any, to the user.
- X
- X Uses the files: $HOME/.filter for instructions to this program, and
- X $HOME/.filterlog for a list of what has been done since last summary.
- X
- X Rev 2.0: knows about From: and Reply-To:
- X Fix: knows that mail lines are approx. ~5K or greater...
- X enhanced to have the '-o output-file' specifier
- X
- X**/
- X
- X#include <stdio.h>
- X#include <pwd.h>
- X#include <ctype.h>
- X#include <time.h>
- X#include <fcntl.h>
- X
- X#include "defs.h"
- X
- X#define MAIN_ROUTINE /* for the filter.h file, of course! */
- X#include "filter.h"
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X extern char *optarg;
- X FILE *fd; /* for output to temp file! */
- X struct passwd *passwd_entry,
- X *getpwuid(); /* for /etc/passwd */
- X char filename[SLEN], /* name of the temp file */
- X buffer[MAX_LINE_LEN]; /* input buffer space */
- X int in_header = TRUE, /* for header parsing */
- X in_to = FALSE, /* are we on 'n' line To: ? */
- X summary = FALSE, /* a summary is requested? */
- X c; /* var for getopt routine */
- X
- X /* first off, let's get the info from /etc/passwd */
- X
- X if ((passwd_entry = getpwuid(getuid())) == NULL)
- X leave("Cannot get password entry for this uid!");
- X
- X strcpy(home, passwd_entry->pw_dir);
- X strcpy(username, passwd_entry->pw_name);
- X outfname[0] = to[0] = '\0'; /* nothing read in yet, right? */
- X
- X#ifdef HOSTCOMPILED
- X strncpy(hostname, HOSTNAME, sizeof(hostname));
- X#else
- X gethostname(hostname, sizeof(hostname));
- X#endif
- X
- X /* now parse the starting arguments... */
- X
- X while ((c = getopt(argc, argv, "clno:rSsv")) != EOF) {
- X switch (c) {
- X case 'c' : clear_logs = TRUE; break;
- X case 'l' : log_actions_only = TRUE; break;
- X case 'o' : strcpy(outfname, optarg); break;
- X case 'r' : printing_rules = TRUE; break;
- X
- X case 's' : summary = TRUE; break;
- X case 'S' : long_summary = TRUE; break;
- X
- X case 'n' : show_only = TRUE; break;
- X case 'v' : verbose = TRUE; break;
- X case '?' : fprintf(stderr,
- X "Usage: | filter [-nrv]\n or: filter [-c] -[s|S]\n");
- X exit(1);
- X }
- X }
- X
- X if (c < 0) {
- X }
- X
- X /* let's open our outfd logfile as needed... */
- X
- X if (outfname[0] == '\0') /* default is stdout */
- X outfd = stdout;
- X else
- X if ((outfd = fopen(outfname, "a")) == NULL) {
- X if (isatty(fileno(stderr)))
- X fprintf(stderr,"filter (%s): couldn't open log file %s\n",
- X username, outfname);
- X }
- X
- X if (summary || long_summary) {
- X if (get_filter_rules() == -1) {
- X exit(1);
- X if (outfd != NULL) fclose(outfd);
- X }
- X show_summary();
- X if (outfd != NULL) fclose(outfd);
- X exit(0);
- X }
- X
- X if (printing_rules) {
- X if (get_filter_rules() == -1)
- X fprintf(outfd,"filter (%s): Couldn't get rules!\n", username);
- X else
- X print_rules();
- X if (outfd != NULL) fclose(outfd);
- X exit(0);
- X }
- X
- X /* next, create the tempfile and save the incoming message */
- X
- X sprintf(filename, "%s.%d", filter_temp, getpid());
- X
- X if ((fd = fopen(filename,"w")) == NULL)
- X leave("Cannot open temporary file!");
- X
- X while (fgets(buffer, MAX_LINE_LEN, stdin) != NULL) {
- X
- X remove_return(buffer);
- X
- X if (in_header) {
- X
- X if (! whitespace(buffer[0]))
- X in_to = FALSE;
- X
- X if (the_same(buffer, "From "))
- X save_from(buffer);
- X else if (the_same(buffer, "Subject:"))
- X save_subject(buffer);
- X else if (the_same(buffer, "To:") || the_same(buffer, "Cc:")) {
- X in_to++;
- X save_to(buffer);
- X }
- X else if (the_same(buffer, "X-Filtered-By:"))
- X already_been_forwarded++; /* could be a loop here! */
- X#ifdef USE_EMBEDDED_ADDRESSES
- X else if (the_same(buffer, "From:"))
- X save_embedded_address(buffer, "From:");
- X else if (the_same(buffer, "Reply-To:"))
- X save_embedded_address(buffer, "Reply-To:");
- X#endif
- X else if (strlen(buffer) < 2)
- X in_header = 0;
- X else if (whitespace(buffer[0]) && in_to)
- X strcat(to, buffer);
- X }
- X
- X fprintf(fd, "%s\n", buffer); /* and save it regardless! */
- X fflush(fd);
- X lines++;
- X }
- X
- X fclose(fd);
- X
- X /** next let's see if the user HAS a filter file, and if so what's in
- X it (and so on) **/
- X
- X if (get_filter_rules() == -1)
- X mail_message(username);
- X else {
- X switch (action_from_ruleset()) {
- X
- X case DELETE_MSG : if (verbose && outfd != NULL)
- X fprintf(outfd, "filter (%s): Message deleted\n",
- X username);
- X log(DELETE_MSG); break;
- X
- X case SAVE : if (save_message(rules[rule_choosen].argument2)) {
- X mail_message(username);
- X log(FAILED_SAVE);
- X }
- X else
- X log(SAVE); break;
- X
- X case SAVECC : if (save_message(rules[rule_choosen].argument2))
- X log(FAILED_SAVE);
- X else
- X log(SAVECC);
- X mail_message(username); break;
- X
- X case FORWARD: mail_message(rules[rule_choosen].argument2);
- X log(FORWARD); break;
- X
- X case EXEC : execute(rules[rule_choosen].argument2);
- X log(EXEC); break;
- X
- X case LEAVE : mail_message(username);
- X log(LEAVE); break;
- X }
- X }
- X
- X (void) unlink(filename); /* remove the temp file, please! */
- X if (outfd != NULL) fclose(outfd);
- X exit(0);
- X}
- X
- Xsave_from(buffer)
- Xchar *buffer;
- X{
- X /** save the SECOND word of this string as FROM **/
- X
- X register int i, j;
- X
- X for (i=0; buffer[i] != ' '; i++) ; /* get to word */
- X
- X for (i++, j=0; buffer[i] != ' ' && i < strlen(buffer); i++)
- X from[j++] = buffer[i]; /* copy it and */
- X
- X from[j++] = '\0'; /* Null terminate! */
- X}
- X
- Xsave_subject(buffer)
- Xchar *buffer;
- X{
- X /** save all but the word "Subject:" for the subject **/
- X
- X register int skip = 8; /* skip "Subject:" initially */
- X
- X while (buffer[skip] == ' ') skip++;
- X
- X strcpy(subject, (char *) buffer + skip);
- X}
- X
- Xsave_to(buffer)
- Xchar *buffer;
- X{
- X /** save all but the word "To:" or "Cc:" for the to list **/
- X
- X register int skip = 3; /* skip "To:" or "Cc:" initially */
- X
- X while (buffer[skip] == ' ') skip++;
- X
- X strcat(to, (char *) buffer + skip);
- X}
- X
- X#ifdef USE_EMBEDDED_ADDRESSES
- X
- Xsave_embedded_address(buffer, fieldname)
- Xchar *buffer, *fieldname;
- X{
- X /** this will replace the 'from' address with the one given,
- X unless the address is from a 'reply-to' field (which overrides
- X the From: field). The buffer given to this routine can have one
- X of three forms:
- X fieldname: username <address>
- X fieldname: address (username)
- X fieldname: address
- X **/
- X
- X static int processed_a_reply_to = 0;
- X char address[LONG_STRING];
- X register int i, j = 0;
- X
- X /** first let's extract the address from this line.. **/
- X
- X if (buffer[strlen(buffer)-1] == '>') { /* case #1 */
- X for (i=strlen(buffer)-1; buffer[i] != '<' && i > 0; i--)
- X /* nothing - just move backwards .. */ ;
- X i++; /* skip the leading '<' symbol */
- X while (buffer[i] != '>')
- X address[j++] = buffer[i++];
- X address[j] = '\0';
- X }
- X else { /* get past "from:" and copy until white space or paren hit */
- X for (i=strlen(fieldname); whitespace(buffer[i]); i++)
- X /* skip past that... */ ;
- X while (buffer[i] != '(' && ! whitespace(buffer[i]) && buffer[i]!='\0')
- X address[j++] = buffer[i++];
- X address[j] = '\0';
- X }
- X
- X /** now let's see if we should overwrite the existing from address
- X with this one or not.. **/
- X
- X if (processed_a_reply_to)
- X return; /* forget it! */
- X
- X strcpy(from, address); /* replaced!! */
- X
- X if (strcmp(fieldname, "Reply-To:") == 0)
- X processed_a_reply_to++;
- X}
- X#endif
- SHAR_EOF
- chmod 0444 filter/filter.c || echo "restore of filter/filter.c fails"
- echo "x - extracting filter/lock.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > filter/lock.c &&
- X
- Xstatic char rcsid[] ="@(#)$Id: lock.c,v 2.4 89/03/25 21:45:14 syd Exp $";
- X
- X/*******************************************************************************
- X * The Elm Mail System - $Revision: 2.4 $ $State: Exp $
- X *
- X * Copyright (c) 1986, 1987 Dave Taylor
- X * Copyright (c) 1988, 1989 USENET Community Trust
- X *******************************************************************************
- X * Bug reports, patches, comments, suggestions should be sent to:
- X *
- X * Syd Weinstein - elm@dsinc.UUCP
- X * dsinc!elm
- X *
- X *******************************************************************************
- X * $Log: lock.c,v $
- X * Revision 2.4 89/03/25 21:45:14 syd
- X * Initial 2.2 Release checkin
- X *
- X *
- X ******************************************************************************/
- X
- X
- X/** The lock() and unlock() routines herein duplicate exactly the
- X equivalent routines in the Elm Mail System, and should also be
- X compatible with sendmail, rmail, etc etc.
- X
- X
- X**/
- X
- X#include <stdio.h>
- X#include <fcntl.h>
- X#include "defs.h"
- X#include "filter.h"
- X
- Xint we_locked_it = 0;
- Xchar lockfile[SLEN];
- X
- Xint
- Xlock()
- X{
- X /** This routine will return 1 if we could lock the mailfile,
- X zero otherwise.
- X **/
- X
- X int attempts = 0, ret;
- X
- X sprintf(lockfile, "%s%s.lock", mailhome, username);
- X
- X while ((ret = open(lockfile, O_WRONLY | O_CREAT | O_EXCL, 0777)) < 0
- X && attempts++ < 10) {
- X sleep(3); /* wait three seconds each pass, okay?? */
- X }
- X
- X if (ret > 0) {
- X we_locked_it++;
- X close(ret); /* no need to keep it open! */
- X }
- X
- X return( (ret >= 0) );
- X}
- X
- Xunlock()
- X{
- X /** this routine will remove the lock file, but only if we were
- X the people that locked it in the first place... **/
- X
- X if (we_locked_it)
- X unlink(lockfile); /* blamo! */
- X
- X we_locked_it = 0;
- X}
- SHAR_EOF
- chmod 0444 filter/lock.c || echo "restore of filter/lock.c fails"
- echo "x - extracting filter/parse.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > filter/parse.c &&
- X
- Xstatic char rcsid[] ="@(#)$Id: parse.c,v 2.4 89/03/25 21:45:16 syd Exp $";
- X
- X/*******************************************************************************
- X * The Elm Mail System - $Revision: 2.4 $ $State: Exp $
- X *
- X * Copyright (c) 1986, 1987 Dave Taylor
- X * Copyright (c) 1988, 1989 USENET Community Trust
- X *******************************************************************************
- X * Bug reports, patches, comments, suggestions should be sent to:
- X *
- X * Syd Weinstein - elm@dsinc.UUCP
- X * dsinc!elm
- X *
- X *******************************************************************************
- X * $Log: parse.c,v $
- X * Revision 2.4 89/03/25 21:45:16 syd
- X * Initial 2.2 Release checkin
- X *
- X *
- X ******************************************************************************/
- X
- X
- X/** This is the parser for the filter program. It accepts a wide variety of
- X constructs, building the ruleset table as it goes along. Check the
- X data structure in filter.h for more information on how the rules are
- X stored. The parser is a cunning state-table based program.
- X
- X**/
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X
- X#include "defs.h"
- X#include "filter.h"
- X
- X#define NONE 0
- X#define AND 10
- X
- X#define NEXT_CONDITION 0
- X#define GETTING_OP 1
- X#define READING_ARGUMENT 2
- X#define READING_ACTION 3
- X#define ACTION_ARGUMENT 4
- X
- Xchar *strtok(), *whatname(), *actionname();
- X
- Xint
- Xget_filter_rules()
- X{
- X /** Given the users home directory, open and parse their rules table,
- X building the data structure as we go along.
- X returns -1 if we hit an error of any sort...
- X **/
- X
- X FILE *fd; /* the file descriptor */
- X char buffer[SLEN], /* fd reading buffer */
- X *str, /* ptr to read string */
- X *word, /* ptr to 'token' */
- X filename[SLEN], /* the name of the ruleset */
- X action_argument[SLEN], /* action arg, per rule */
- X cond_argument[SLEN]; /* cond arg, per condition */
- X int not_condition = FALSE, /* are we in a "not" ?? */
- X type=NONE, /* what TYPE of condition? */
- X lasttype, /* and the previous TYPE? */
- X state = NEXT_CONDITION, /* the current state */
- X in_single, in_double, /* for handling spaces. */
- X i, /* misc integer for loops */
- X relop = NONE, /* relational operator */
- X action, /* the current action type */
- X line = 0; /* line number we're on */
- X
- X struct condition_rec *cond, *newcond;
- X
- X sprintf(filename,"%s/%s", home, filterfile);
- X
- X if ((fd = fopen(filename,"r")) == NULL) {
- X if (outfd != NULL)
- X fprintf(outfd,"filter (%s): Couldn't read user filter rules file!\n",
- X username);
- X return(-1);
- X }
- X
- X cond_argument[0] = action_argument[0] = '\0';
- X
- X /* Now, for each line... **/
- X
- X if ((cond = (struct condition_rec *)
- X malloc(sizeof(struct condition_rec))) == NULL) {
- X if (outfd != NULL)
- X fprintf(outfd,"filter (%s): couldn't malloc first condition rec!\n",
- X username);
- X return(-1);
- X }
- X
- X rules[total_rules].condition = cond; /* hooked in! */
- X
- X while (fgets(buffer, SLEN, fd) != NULL) {
- X line++;
- X
- X if (buffer[0] == '#' || strlen(buffer) < 2)
- X continue; /* nothing to look at! */
- X
- X in_single = in_double = 0;
- X
- X for (i=0; i < strlen(buffer); i++) {
- X if (buffer[i] == '"')
- X in_double = ! in_double;
- X else if (buffer[i] == '\'')
- X in_single = ! in_single;
- X if ((in_double || in_single) && buffer[i] == ' ')
- X buffer[i] = '_';
- X }
- X
- X lasttype = type;
- X type = NONE;
- X str = (char *) buffer;
- X
- X /** Three pieces to this loop - get the `field', the 'relop' (if
- X there) then, if needed, get the argument to check against (not
- X needed for errors or the AND, of course)
- X **/
- X
- X while ((word = strtok(str, " ()[]:\t\n")) != NULL) {
- X
- X str = (char *) NULL; /* we can start stomping! */
- X
- X lowercase(word);
- X
- X if (strcmp(word, "if") == 0) { /* only ONE 'if' allowed */
- X if ((word = strtok(str, " ()[]:\t\n")) == NULL) /* NEXT! */
- X continue;
- X lowercase(word);
- X }
- X
- X if (state == NEXT_CONDITION) {
- X lasttype = type;
- X type = NONE;
- X
- X if (the_same(word, "not") || the_same(word, "!")) {
- X not_condition = TRUE;
- X if ((word = strtok(str, " ()[]'\"\t\n")) == NULL)
- X continue;
- X }
- X
- X if (the_same(word, "from")) type = FROM;
- X else if (the_same(word, "to")) type = TO;
- X else if (the_same(word, "subject")) type = SUBJECT;
- X else if (the_same(word, "lines")) type = LINES;
- X else if (the_same(word, "contains")) type = CONTAINS;
- X else if (the_same(word, "and") ||
- X the_same(word, "&&")) type = AND;
- X
- X else if (the_same(word,"?") || the_same(word, "then") ||
- X the_same(word, "always")) {
- X
- X /** shove THIS puppy into the structure and let's continue! **/
- X
- X if (lasttype == AND) {
- X if (outfd != NULL)
- X fprintf(outfd,
- X "filter (%s): Error reading line %d of rules - badly placed \"and\"\n",
- X username, line);
- X return(-1);
- X }
- X
- X if (the_same(word, "always"))
- X cond->matchwhat = ALWAYS; /* so it's a hack... */
- X else
- X cond->matchwhat = lasttype;
- X
- X if (relop == NONE) relop = EQ; /* otherwise can't do -relop */
- X cond->relation = (not_condition? - (relop) : relop);
- X
- X for (i=0;i<strlen(cond_argument);i++)
- X if (cond_argument[i] == '_') cond_argument[i] = ' ';
- X
- X strcpy(cond->argument1, cond_argument);
- X if ((newcond = (struct condition_rec *)
- X malloc(sizeof(struct condition_rec))) == NULL) {
- X if (outfd != NULL)
- X fprintf(outfd,
- X "filter (%s): Couldn't malloc new cond rec!!\n",
- X username);
- X return(-1);
- X }
- X cond->next = NULL;
- X
- X relop = EQ; /* default relational condition */
- X
- X state = READING_ACTION;
- X if ((word = strtok(str, " ()[]'\"\t\n")) == NULL)
- X continue;
- X goto get_outta_loop;
- X }
- X
- X if (type == NONE) {
- X if (outfd != NULL)
- X fprintf(outfd,
- X "filter (%s): Error reading line %d of rules - field \"%s\" unknown!\n",
- X username, line, word);
- X return(-1);
- X }
- X
- X if (type == AND) {
- X
- X /** shove THIS puppy into the structure and let's continue! **/
- X
- X cond->matchwhat = lasttype;
- X cond->relation = (not_condition? - (relop) : relop);
- X strcpy(cond->argument1, cond_argument);
- X if ((newcond = (struct condition_rec *)
- X malloc(sizeof(struct condition_rec))) == NULL) {
- X if (outfd != NULL)
- X fprintf(outfd,
- X "filter (%s): Couldn't malloc new cond rec!!\n",
- X username);
- X return(-1);
- X }
- X cond->next = newcond;
- X cond = newcond;
- X cond->next = NULL;
- X
- X not_condition = FALSE;
- X state = NEXT_CONDITION;
- X }
- X else {
- X state = GETTING_OP;
- X }
- X }
- X
- Xget_outta_loop: /* jump out when we change state, if needed */
- X
- X if (state == GETTING_OP) {
- X
- X if ((word = strtok(str, " ()[]'\"\t\n")) == NULL)
- X continue;
- X
- X lowercase(word);
- X
- X relop = NONE;
- X
- X if (the_same(word, "=") || the_same(word, "in") ||
- X the_same(word, "contains")) {
- X state = READING_ARGUMENT;
- X relop = EQ;
- X }
- X else {
- X if (the_same(word, "<=")) relop = LE;
- X else if (the_same(word, ">=")) relop = GE;
- X else if (the_same(word, ">")) relop = GT;
- X else if (the_same(word, "<>")||
- X the_same(word, "!=")) relop = NE;
- X else if (the_same(word, "<")) relop = LT;
- X
- X /* maybe there isn't a relop at all!! */
- X
- X state=READING_ARGUMENT;
- X
- X }
- X }
- X
- X if (state == READING_ARGUMENT) {
- X if (relop != NONE) {
- X if ((word = strtok(str, " ()[]'\"\t\n")) == NULL)
- X continue;
- X }
- X for (i=0;i<strlen(word);i++)
- X if (word[i] == '_') word[i] = ' ';
- X
- X strcpy(cond_argument, word);
- X state = NEXT_CONDITION;
- X }
- X
- X if (state == READING_ACTION) {
- X action = NONE;
- X
- X not_condition = FALSE;
- X
- X if (the_same(word, "delete")) action = DELETE_MSG;
- X else if (the_same(word, "savec")) action = SAVECC;
- X else if (the_same(word, "save")) action = SAVE;
- X else if (the_same(word, "forward")) action = FORWARD;
- X else if (the_same(word, "exec")) action = EXEC;
- X else if (the_same(word, "leave")) action = LEAVE;
- X else {
- X if (outfd != NULL)
- X fprintf(outfd,
- X "filter (%s): Error on line %d of rules - action \"%s\" unknown\n",
- X username, line, word);
- X }
- X
- X if (action == DELETE_MSG || action == LEAVE) {
- X /** add this to the rules section and alloc next... **/
- X
- X rules[total_rules].action = action;
- X rules[total_rules].argument2[0] = '\0'; /* nothing! */
- X total_rules++;
- X
- X if ((cond = (struct condition_rec *)
- X malloc(sizeof(struct condition_rec))) == NULL) {
- X if (outfd != NULL)
- X fprintf(outfd,
- X "filter (%s): couldn't malloc first condition rec!\n",
- X username);
- X return(-1);
- X }
- X
- X rules[total_rules].condition = cond; /* hooked in! */
- X state = NEXT_CONDITION;
- X }
- X else {
- X state = ACTION_ARGUMENT;
- X }
- X
- X if ((word = strtok(str, " ()[]'\"\t\n")) == NULL)
- X continue;
- X
- X }
- X
- X if (state == ACTION_ARGUMENT) {
- X strcpy(action_argument, word);
- X
- X /** add this to the rules section and alloc next... **/
- X
- X rules[total_rules].action = action;
- X expand_macros(action_argument, rules[total_rules].argument2,line,
- X printing_rules);
- X total_rules++;
- X
- X if ((cond = (struct condition_rec *)
- X malloc(sizeof(struct condition_rec))) == NULL) {
- X if (outfd != NULL)
- X fprintf(outfd,
- X "filter (%s): couldn't malloc first condition rec!\n",
- X username);
- X return(-1);
- X }
- X
- X rules[total_rules].condition = cond; /* hooked in! */
- X
- X state = NEXT_CONDITION;
- X if ((word = strtok(str, " ()[]'\"\t\n")) == NULL)
- X continue;
- X }
- X }
- X }
- X
- X return(0);
- X}
- SHAR_EOF
- chmod 0444 filter/parse.c || echo "restore of filter/parse.c fails"
- echo "x - extracting filter/rules.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > filter/rules.c &&
- X
- Xstatic char rcsid[] ="@(#)$Id: rules.c,v 2.4 89/03/25 21:45:17 syd Exp $";
- X
- X/*******************************************************************************
- X * The Elm Mail System - $Revision: 2.4 $ $State: Exp $
- X *
- X * Copyright (c) 1986, 1987 Dave Taylor
- X * Copyright (c) 1988, 1989 USENET Community Trust
- X *******************************************************************************
- X * Bug reports, patches, comments, suggestions should be sent to:
- X *
- X * Syd Weinstein - elm@dsinc.UUCP
- X * dsinc!elm
- X *
- X *******************************************************************************
- X * $Log: rules.c,v $
- X * Revision 2.4 89/03/25 21:45:17 syd
- X * Initial 2.2 Release checkin
- X *
- X *
- X ******************************************************************************/
- X
- X/** This file contains all the rule routines, including those that apply the
- X specified rules and the routine to print the rules out.
- X
- X**/
- X
- X#include <stdio.h>
- X#include <pwd.h>
- X#include <ctype.h>
- X#include <time.h>
- X#include <fcntl.h>
- X
- X#include "defs.h"
- X#include "filter.h"
- X
- Xchar *listrule();
- X
- Xint
- Xaction_from_ruleset()
- X{
- X /** Given the set of rules we've read in and the current to, from,
- X and subject, try to match one. Return the ACTION of the match
- X or LEAVE if none found that apply.
- X **/
- X
- X register int iindex = 0, not, relation, try_next_rule, x;
- X struct condition_rec *cond;
- X
- X while (iindex < total_rules) {
- X cond = rules[iindex].condition;
- X try_next_rule = 0;
- X
- X while (cond != NULL && ! try_next_rule) {
- X
- X not = (cond->relation < 0);
- X relation = abs(cond->relation);
- X
- X switch (cond->matchwhat) {
- X
- X case TO : x = contains(to, cond->argument1); break;
- X case FROM : x = contains(from, cond->argument1); break;
- X case SUBJECT: x = contains(subject, cond->argument1); break;
- X case LINES : x = compare(lines, relation, cond->argument1);break;
- X
- X case CONTAINS: if (outfd != NULL) fprintf(outfd,
- X "filter (%s): Error: rules based on 'contains' are not implemented!\n",
- X username);
- X if (outfd != NULL) fclose(outfd);
- X exit(0);
- X
- X case ALWAYS: not = FALSE; x = TRUE; break;
- X }
- X
- X if ((not && x) || ((! not) && (! x))) /* this test failed (LISP?) */
- X try_next_rule++;
- X else
- X cond = cond->next; /* next condition, if any? */
- X }
- X
- X if (! try_next_rule) {
- X rule_choosen = iindex;
- X return(rules[rule_choosen].action);
- X }
- X iindex++;
- X }
- X
- X rule_choosen = -1;
- X return(LEAVE);
- X}
- X
- X#define get_the_time() if (!gotten_time) { \
- X thetime = time( (long *) 0); \
- X timerec = localtime(&thetime); \
- X gotten_time++; \
- X }
- X
- Xexpand_macros(word, buffer, line, display)
- Xchar *word, *buffer;
- Xint line, display;
- X{
- X /** expand the allowable macros in the word;
- X %d = day of the month
- X %D = day of the week
- X %h = hour (0-23)
- X %m = month of the year
- X %r = return address of sender
- X %s = subject of message
- X %S = "Re: subject of message" (only add Re: if not there)
- X %t = hour:minute
- X %y = year
- X or simply copies word into buffer. If "display" is set then
- X instead it puts "<day-of-month>" etc. etc. in the output.
- X **/
- X
- X struct tm *localtime(), *timerec;
- X long time(), thetime;
- X register int i, j=0, gotten_time = 0, reading_a_percent_sign = 0;
- X
- X for (i = 0; i < strlen(word); i++) {
- X if (reading_a_percent_sign) {
- X reading_a_percent_sign = 0;
- X switch (word[i]) {
- X
- X case 'r' : buffer[j] = '\0';
- X if (display)
- X strcat(buffer, "<return-address>");
- X else
- X strcat(buffer, from);
- X j = strlen(buffer);
- X break;
- X
- X case 's' : buffer[j] = '\0';
- X if (display)
- X strcat(buffer, "<subject>");
- X else {
- X strcat(buffer, "\"");
- X strcat(buffer, subject);
- X strcat(buffer, "\"");
- X }
- X j = strlen(buffer);
- X break;
- X
- X case 'S' : buffer[j] = '\0';
- X if (display)
- X strcat(buffer, "<Re: subject>");
- X else {
- X if (! the_same(subject, "Re:"))
- X strcat(buffer, "\"Re: ");
- X strcat(buffer, subject);
- X strcat(buffer, "\"");
- X }
- X j = strlen(buffer);
- X break;
- X
- X case 'd' : get_the_time(); buffer[j] = '\0';
- X if (display)
- X strcat(buffer, "<day-of-month>");
- X else
- X strcat(buffer, itoa(timerec->tm_mday,FALSE));
- X j = strlen(buffer);
- X break;
- X
- X case 'D' : get_the_time(); buffer[j] = '\0';
- X if (display)
- X strcat(buffer, "<day-of-week>");
- X else
- X strcat(buffer, itoa(timerec->tm_wday,FALSE));
- X j = strlen(buffer);
- X break;
- X
- X case 'm' : get_the_time(); buffer[j] = '\0';
- X if (display)
- X strcat(buffer, "<month>");
- X else
- X strcat(buffer, itoa(timerec->tm_mon+1,FALSE));
- X j = strlen(buffer);
- X break;
- X
- X case 'y' : get_the_time(); buffer[j] = '\0';
- X if (display)
- X strcat(buffer, "<year>");
- X else
- X strcat(buffer, itoa(timerec->tm_year,FALSE));
- X j = strlen(buffer);
- X break;
- X
- X case 'h' : get_the_time(); buffer[j] = '\0';
- X if (display)
- X strcat(buffer, "<hour>");
- X else
- X strcat(buffer, itoa(timerec->tm_hour,FALSE));
- X j = strlen(buffer);
- X break;
- X
- X case 't' : get_the_time(); buffer[j] = '\0';
- X if (display)
- X strcat(buffer, "<time>");
- X else {
- X strcat(buffer, itoa(timerec->tm_hour,FALSE));
- X strcat(buffer, ":");
- X strcat(buffer, itoa(timerec->tm_min,TRUE));
- X }
- X j = strlen(buffer);
- X break;
- X
- X default : if (outfd != NULL) fprintf(outfd,
- X "filter (%s): Error on line %d translating %%%c macro in word \"%s\"!\n",
- X username, line, word[i], word);
- X if (outfd != NULL) fclose(outfd);
- X exit(1);
- X }
- X }
- X else if (word[i] == '%')
- X reading_a_percent_sign++;
- X else
- X buffer[j++] = (word[i] == '_' ? ' ' : word[i]);
- X }
- X buffer[j] = '\0';
- X}
- X
- Xprint_rules()
- X{
- X /** print the rules out. A double check, of course! **/
- X
- X register int i = -1;
- X char *whatname(), *actionname();
- X struct condition_rec *cond;
- X
- X if (outfd == NULL) return; /* why are we here, then? */
- X
- X while (++i < total_rules) {
- X if (rules[i].condition->matchwhat == ALWAYS) {
- X fprintf(outfd, "\nRule %d: ** always ** \n\t%s %s\n", i+1,
- X actionname(rules[i].action), listrule(rules[i].argument2));
- X continue;
- X }
- X
- X fprintf(outfd, "\nRule %d: if (", i+1);
- X
- X cond = rules[i].condition;
- X
- X while (cond != NULL) {
- X if (cond->relation < 0)
- X fprintf(outfd, "not %s %s %s%s%s",
- X whatname(cond->matchwhat),
- X relationname(- (cond->relation)),
- X quoteit(cond->matchwhat),
- X cond->argument1,
- X quoteit(cond->matchwhat));
- X else
- X fprintf(outfd, "%s %s %s%s%s",
- X whatname(cond->matchwhat),
- X relationname(cond->relation),
- X quoteit(cond->matchwhat),
- X cond->argument1,
- X quoteit(cond->matchwhat));
- X
- X cond = cond->next;
- X
- X if (cond != NULL) fprintf(outfd, " and ");
- X }
- X
- X fprintf(outfd, ") then\n\t %s %s\n",
- X actionname(rules[i].action),
- X listrule(rules[i].argument2));
- X }
- X fprintf(outfd, "\n");
- X}
- X
- Xchar *whatname(n)
- Xint n;
- X{
- X static char buffer[10];
- X
- X switch(n) {
- X case FROM : return("from");
- X case TO : return("to");
- X case SUBJECT: return("subject");
- X case LINES : return ("lines");
- X case CONTAINS: return("contains");
- X default : sprintf(buffer, "?%d?", n); return((char *)buffer);
- X }
- X}
- X
- Xchar *actionname(n)
- Xint n;
- X{
- X switch(n) {
- X case DELETE_MSG : return("Delete");
- X case SAVE : return("Save");
- X case SAVECC : return("Copy and Save");
- X case FORWARD : return("Forward");
- SHAR_EOF
- echo "End of part 8"
- echo "File filter/rules.c is continued in part 9"
- echo "9" > s2_seq_.tmp
- exit 0
-
-