home *** CD-ROM | disk | FTP | other *** search
- Subject: v09i014: ELM Mail System, Part14/19
- Newsgroups: mod.sources
- Approved: rs@mirror.TMC.COM
-
- Submitted by: Dave Taylor <hplabs!taylor>
- Mod.sources: Volume 9, Issue 14
- Archive-name: elm2/Part14
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- # If this archive is complete, you will see the message:
- # "End of archive 14 (of 19)."
- # Contents: doc/Filter.guide src/newmbox.c src/reply.c
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo shar: Extracting \"doc/Filter.guide\" \(15096 characters\)
- if test -f doc/Filter.guide ; then
- echo shar: Will not over-write existing file \"doc/Filter.guide\"
- else
- sed "s/^X//" >doc/Filter.guide <<'END_OF_doc/Filter.guide'
- X.PH ""
- X\"
- X\" A guide to the Elm Filter program
- X\" format with 'tbl Filter.guide | troff -mm > Filter.format'
- X\" or something similar.
- X\" (C) Copyright 1986 Dave Taylor
- X\"
- X\" Last modification: January 19th, 1987
- X\"
- X.SA 1
- X.nr Hy 1
- X.nr Pt 1
- X.nr Pi 8
- X.lg
- X.HM 1 1
- X.rs
- X.ds HF 3 3
- X.ds HP 12 12 10 10 10
- X.PF ""
- X.ce 99
- X.sp 9
- X.ps 20
- X\fBElm Filter Guide\fR
- X.sp 7
- X.ps 12
- X\fIWhat the filter program is, what it does,
- Xand how to use it\fR
- X.sp 5
- XDave Taylor
- X.sp
- XHewlett-Packard Laboratories
- X1501 Page Mill Road
- XPalo Alto CA
- X94304
- X.sp
- Xemail: taylor@hplabs.HP.COM or hplabs!taylor
- X.sp 10
- X.ps 18
- X\fB\(co\fR\s12 Copyright 1986, 1987 by Dave Taylor
- X.ps 10
- X.SK
- X.sp 5
- X.ps 14
- X\fBElm Filter Guide\fR
- X.PH "'Filter Guide''version 1.5'
- X.PF "''Page \\\\nP''"
- X.nr P 1
- X.sp
- X.ps 10
- X(version 1.5)
- X.sp 2
- XDave Taylor
- X.sp
- XHewlett-Packard Laboratories
- X1501 Page Mill Road
- XPalo Alto CA
- X94304
- X.sp
- Xemail: taylor@hplabs.HP.COM or hplabs!taylor
- X.sp 2
- X\*(DT
- X.ce 0
- X.sp 3
- X.P
- XOne of the greatest problems with the burgeoning electronic mail
- Xexplosion is that we tend to get mail that we don't care about.
- XAmusingly, perhaps, we have the equivalent of electronic junk mail.
- XNot amusing, however, is the fact that this can rapidly
- Xaccumulate and end up taking over your mailbox!
- X.P
- XAt the same time we often get mail that, while it is interesting
- Xand important, can easily be filed to be read later, without ever
- Xactually cluttering up the mailbox.
- X.sp 2
- XThis, then, is what \fIfilter\fR does for you! The \fIfilter\fR program
- Xallows you to define a set of rules by which all incoming mail should
- Xbe screened, and a subsequent set of actions to perform based on whether
- Xthe rules were met or not. \fIFilter\fR also has the ability to mail
- Xa summary of what actions it performed on the incoming mail as often as
- Xyou'd like.
- X.sp
- X.ps 12
- X\fB
- XWriting the Rules\fR
- X.ps 10
- X.sp
- XThe language for writing \fIfilter\fR rules is pretty simple, actually.
- XThe fundamental structure is;
- X.nf
- X
- X if (\fIcondition\fR) then \fIaction\fR
- X
- X.fi
- XWhere \fIcondition\fR is constructed by an arbitrary number of
- Xindividual conditions of the form ``\fIfield\fR \fIrelation\fR \fIvalue\fR''.
- XThe \fIfield\fR value can be;
- X.nf
- X
- X subject
- X from
- X to
- X lines
- X contains
- X
- X.fi
- Xwhere, if ``lines'' is choosen, the \fIrelation\fR can be any of the
- Xstandard relationships (`>', `<', `>=', `<=', `!=' and `=').
- XIf another action is
- Xchoosen, ``contains'' can be used as the relation, ``='', or, if you'd
- Xlike, you can skip the relationship entirely (e.g. `subject "joe"').
- XThe \fIvalue\fR is any quoted string that is to be matched against
- Xor number if ``lines'' is the field being considered.
- X.sp
- XInvidivual conditions are joined together by using the word ``and'',
- Xand the logic of a condition can be flipped by using ``not'' as the
- Xfirst word (e.g. `not subject "joe"'). We'll see more examples of
- Xthis later.
- X.sp
- XNote that the ``or'' logical conjunction isn't a valid part of the
- X\fIfilter\fR conditional statement.
- X.sp
- XFinally, <\fIaction\fR> can be any of;
- X.nf
- X
- X delete
- X
- X save \fIfoldername\fR
- X
- X savecopy \fIfoldername\fR
- X
- X forward \fIaddress\fR
- X
- X execute \fIcommand\fR
- X
- X leave
- X
- X.fi
- Xwhere they result in the actions; \fBdelete\fR deletes the message;
- X\fBsave\fR saves a copy of the message in the specified foldername;
- X\fBsavecopy\fR does the same as save, but also puts a copy in your mailbox;
- X\fBforward\fR sends the message to the specified address;
- X\fBexecute\fR feeds the message to the specified command (or complex
- Xsequence of commands) as standard input;
- Xand \fBleave\fR leaves the message in your mailbox.
- X.sp
- XFoldernames can contain any of a number of macros, too, as we'll see in
- Xthe example ruleset below. The macros available for the string fields are;
- X.DS CB
- X.TS
- Xl l.
- X Macro Meaning
- X
- X %d day of the month
- X %D day of the week (0-6)
- X %h hour of the day (0-23)
- X %m month of the year (0-11)
- X %r return address of message
- X %s subject of original message
- X %S ``Re: \fIsubject of original message\fR''
- X %t current hour and minute in HH:MM format
- X %y year (last two digits)
- X.TE
- X.DE
- X.sp
- XThe rules file can also contain comments (any line starting with a `#')
- Xand blank lines.
- X.sp
- XThe file itself needs to reside in your home directory and be
- Xcalled \fI.filter-rules\fR. Here's an example;
- X.nf
- X
- X # $HOME/.filter-rules
- X #
- X # Filter rules for the Elm Filter program. Don't change without some
- X # serious thought. (remember - order counts)
- X #
- X # Dave Taylor
- X
- X # rule 1
- X if (from contains "!uucp") then delete
- X
- X # rule 2
- X to "postmaster" ? save "/tmp/postmaster-mail.%d"
- X
- X # rule 3
- X if (to "culture" and lines > 20) ? save "/users/taylor/Mail/culture"
- X
- X # rule 4
- X subject = "filter test" ? forward "hpldat!taylor"
- X
- X # rule 5
- X if [ subject = "elm" ] savecopy "/users/taylor/Mail/elm-incoming"
- X
- X # rule 6
- X subject = "display-to-console" ? execute "cat - > /dev/console"
- X
- X.fi
- X(notice the loose syntax - there are lots of valid ways to specify a
- Xrule in the \fIfilter\fR program!!)
- X.sp
- XTo translate these into English;
- X.sp
- X.AL
- X.LI
- XAll messages from uucp should be summarily deleted.
- X.LI
- XAll mail to postmaster should be saved in a folder (file) called
- X/tmp/posmaster-mail.\fInumeric-day-of-the-week\fR
- X.LI
- XAll mail addressed to `culture' with at least 20 lines
- X should be automatically appended to the folder
- X/users/taylor/Mail/culture.
- X.LI
- XAll messages that contain the subject `filter test' should be forwarded to
- Xme, but via the address `hpldat!taylor' (to force a non-user forward)
- X.LI
- XAll messages with a subject that contains the word `elm' should be saved in
- Xthe folder ``/users/taylor/Mail/elm-incoming'' and also dropped into my
- Xmailbox.
- X.LI
- XAny message with the subject ``display-to-console'' will be immediately
- Xwritten to the console.
- X.LE
- X.sp
- XNotice that the \fIorder\fR of the rules is very important. If we, for
- Xexample, were to get a message from `uucp' that had the subject `filter test',
- Xthe \fIfilter\fR program would match rule 1 and delete the message. It
- Xwould never be forwarded to `hpldat!taylor'. It is for this reason that
- Xgreat care should be taken with the ordering of the rules.
- X.sp
- X.ps 12
- X\fBChecking the rules out\fR
- X.ps 10
- X.sp
- XThe \fIfilter\fR program has a convenient way of check out the rules you
- Xhave written. Simply invoke it with the \fB-r\fR (\fBr\fRules) flag;
- X.nf
- X
- X % \fBfilter -r\fR
- X
- X Rule 1: if (from = "!uucp") then
- X Delete
- X
- X Rule 2: if (to = "postmaster") then
- X Save /tmp/postmaster-mail.2
- X
- X Rule 3: if (to = "culture" and lines > 20) then
- X Save /users/taylor/Mail/culture
- X
- X Rule 4: if (subject = "filter test") then
- X Forward hpldat!taylor
- X
- X Rule 5: if (subject="elm") then
- X Copy and Save /users/taylor/Mail/elm-incoming
- X
- X Rule 6: if (subject="display-to-console") then
- X Execute "cat - > /dev/console"
- X
- X.fi
- XThere are a few things to notice - first off, these are the parsed and
- Xrebuilt rules, so we can see that they are all in a
- Xconsistent format. Also, notice on the filename for rule 2 that the
- Xprogram has correctly expanded the ``%d'' macro to be the day of the
- Xmonth.
- X.sp 2
- XIt is \fBhighly\fR recommended that you always check your ruleset before
- Xactually letting the program use it!
- X.sp
- X.ps 12
- X\fBActually Using the Program\fR
- X.ps 10
- X.sp
- XNow the bad news. If you aren't running \fIsendmail\fR you cannot use
- Xthis program as currently written. Why? Because the \fIfilter\fR
- Xprogram expects to be put in your \fI.forward\fR file and that is something
- Xthat only \fIsendmail\fR looks at!
- X.sp
- XThe format for the entry in the \fI.forward\fR file (located in your
- Xhome directory) is simply;
- X.nf
- X
- X "|filter"
- X
- X.fi
- XAlright, it isn't quite \fIthat\fR simple! Since \fIfilter\fR will be invoked
- Xby processes that don't know where you are logged in, you need to have some
- Xway to trap the error messages. For ease of use, it was decided to have all
- Xthe messages written to \fIstderr\fR which means that you have two main
- Xchoices for the actual entry. Either;
- X.nf
- X
- X "|filter > /dev/console 2>&1"
- X
- X.fi
- Xwhich will log all errors on the system console (each error is prefixed with
- X``filter (\fIusername\fR)'' to distinguish it), or;
- X.nf
- X
- X "|filter >> $HOME/.filter_errors 2>&1"
- X
- X.fi
- XIf you want to have a copy saved to a file. A possible strategy would be
- Xto have the errors written to a file and to then have a few lines in
- Xyour \fI.login\fR script like;
- X.nf
- X
- X if ( -f .filter_errors) then
- X echo "\ \ "
- X echo "Filter program errors;"
- X cat .filter_errors
- X echo "\ \ "
- X endif
- X
- X.fi
- XYou can also use the \fB-v\fR flag in combination with the above to have
- Xthe errors written to a file and a single line indicating messages being
- Xsent off or saved to folders written to the console by having
- Xyour \fI.forward\fR file;
- X.nf
- X
- X "|filter -v > /dev/console 2>> $HOME/.filter_errors"
- X
- X.fi
- XSuffice to say, you can get pretty tricky with all this!! One last point - if
- Xyou're interested in having it beep (for output to the screen, I would
- Xthink) you can use the \fB-a\fR (\fBa\fRudible) flag for any of these
- Xinvocations!
- X.sp
- X.ne 5
- X.ps 12
- X\fBSummarizing the Actions Taken\fR
- X.ps 10
- X.sp
- XThe \fIFilter\fR program keeps a log of all actions performed, including
- Xwhat rules it matched against, in your home directory in a file
- Xcalled \fI.filter_log\fR. You can either directly operate on this file,
- Xor, much more recommended, you can one of the two summarize flags to
- Xthe program and let \fIit\fR do the work for you!
- X.sp
- XThe difference between the two is best demonstrated by example;
- X.nf
- X
- X % \fBfilter -s\fR
- X
- X Summary of filter activity;
- X
- X The default rule of putting mail into your mailbox was used 18 times
- X
- X Rule #3: (save in "/users/taylor/Mail/culture") was applied 2 times.
- X
- Xvs
- X
- X % \fBfilter -S\fR
- X
- X Mail from root about
- X PUT in mailbox: the default action
- X
- X Mail from taylor about Filter Summary
- X PUT in mailbox: the default action
- X
- X Mail from hpcea!hpcesea!hpcesed!scott@hplabs.HP.COM
- X about Comments and questions about elm
- X PUT in mailbox: the default action
- X
- X [etc etc]
- X
- X.fi
- XTo actually use either of the summarizing options, there
- Xare two ways that are recommended;
- X.sp
- XThe preferred way is to have a line in either your \fIcrontab\fR
- X(ask your administrator for help with this) that invokes the \fIfilter\fR
- Xprogram as often as you desire with the \fB-s\fR flag. For example, I
- Xhave a summary mailed to me every morning at 8:00 am;
- X.nf
- X
- X 0 8 * * * "/usr/local/bin/filter -s | elm -s 'Filter Summary' taylor"
- X
- X.fi
- X.sp
- XAn alternative is to have your \fI.login\fR execute the command each time.
- X.sp 2
- XNote that if you want to have your log files cleared out each time the
- Xsummary is generated you'll need to use the '-c' flag too. Also,
- Xif you want to keep a long list of actions performed you can do this
- Xby saving it as you display it. A way to do this would be, if you were to
- Xhave the invocation in your \fI.login\fR script, to use;
- X.nf
- X
- X echo "Filter Log;"
- X filter -c -s | tee -a PERM.filter.log
- X
- X.fi
- Xwhich would append a copy of all the output to the file `PERM.filter.log'
- Xand would avoid you having to read larger and larger summaries of
- Xwhat the program had done.
- X.sp
- X.ne 5
- X.ps 12
- X\fBFurther Testing of the Ruleset\fR
- X.ps 10
- X.sp
- XWith the \fIreadmsg\fR command available, it is quite easy to test the
- Xrules you've written to see if they'll do what you desire.
- X.sp
- XFor example, we can use the \fB-n\fR flag to \fIfilter\fR, which means
- X`don't actually do this, just tell me what rule you matched, if any, and
- Xwhat action you would have performed' (you can see why a single letter
- Xflag is easier to type in!!), and feed it each message in our mailbox
- Xby using a command like;
- X.nf
- X
- X % \fBset message=1\fR
- X % \fBset total_messages=`messages`\fR
- X
- X % \fBwhile (1)\fR
- X > \fBif ($message > $total_messages) exit\fR
- X > \fBecho processing message $message\fR
- X > \fBreadmsg -h $message | filter -n\fR
- X > \fBecho " "\fR
- X > \fB@ messages++\fR
- X > \fBend\fR
- X
- X.fi
- Xwhich will then hand each of the messages in your mailbox to the \fIfilter\fR
- Xprogram and display what action would have been taken with that message and
- Xwhy.
- X.sp
- XFor example, if we do this for a few interesting messages in my mailbox,
- Xwe'd end up with output like;
- X.nf
- X
- X Mail from taylor about filter test
- X FORWARDED to hpldat!taylor by rule;
- X subject="filter test" ? forward "hpldat!taylor"
- X
- X Mail from bradley%hplkab@hplabsc about Re: AI-ED mailing address for HP
- X PUT in mailbox: the default action
- X
- X Mail from taylor about display-to-console
- X EXECUTED "cat - > /dev/console"
- X
- X.fi
- X(sharp users will notice that this is exactly the same format as the longer
- Xsummary listing!!)
- X.sp
- X.ps 12
- X\fBWhat Forwarded Messages Look Like\fR
- X.ps 10
- X.sp
- XWhen a message is forwarded to another user by the \fIaction\fR being specified
- Xas ``forward \fIaddress\fR'', then the program can generate one of two styles
- Xof message. If the message is to you, then it'll simply add it to your mailbox
- Xin such a way as to ensure that the return address is that of the person who
- Xsent the message and so on.
- X.sp
- XIf not, then the message is enclosed in a message of the form;
- X.nf
- X
- X From taylor Thu Oct 2 15:07:04 1986
- X Date: Thu, 2 Oct 86 15:06:58 pdt
- X Subject: "filter test"
- X From: The filter of taylor@hpldat <taylor>
- X To: hpldat!taylor
- X X-Filtered-By: filter, version 1.4
- X
- X -- Begin filtered message --
- X
- X From taylor Thu Oct 2 15:06:41 1986
- X Date: Thu, 2 Oct 86 15:06:33 pdt
- X From: Dave Taylor <taylor>
- X Subject: filter test
- X
- X Just a simple test.
- X
- X -- End of filtered message --
- X
- X.fi
- XThe subject of the actual message is the same as the subject of the
- Xmessage being forwarded, but in quotes. The `From:' field indicates
- Xhow the message was sent, and the `X-Filtered-By:' identifies what
- Xversion of filter is being used.
- X.sp
- X.ps 12
- X\fBAreas to Improve\fR
- X.ps 10
- X.sp
- XWhile the \fIfilter\fR program as presented herein is obviously a
- Xnice addition to the set of tools available for dealing with electronic
- Xmail, there are some key features that are missing and will be added in
- Xthe future based on demand.
- X.sp
- XAs I see it, the main things missing are;
- X.AL
- X.LI
- XThe ability to use regular expressions in the patterns.
- XThis would be a \fIvery\fR nice feature!
- X.LI
- XPerhaps more \fIactions\fR available (but what?)
- X.LI
- XCertainly the ability to filter based on any field or combination of
- Xfields.
- X.LE
- X.sp 2
- X.ps 12
- X\fBWarnings and Things to Look Out For\fR
- X.ps 10
- X.sp
- XSince this is a pretty simple program, there are a few pitfalls, some
- Xof which have already been mentioned;
- X.sp
- X\fBOrder\fR counts in the rules. Beware!
- X.sp
- X\fBMatching\fR is pretty simple - make sure your patterns are sufficiently
- Xexclusive before having any destructive rules.
- X.sp 2
- XFinally, as with the rest of the \fBElm\fR mail system, I welcome feedback
- Xand suggestion on how to improve this program!!
- END_OF_doc/Filter.guide
- if test 15096 -ne `wc -c <doc/Filter.guide`; then
- echo shar: \"doc/Filter.guide\" unpacked with wrong size!?
- fi
- # end of overwriting check
- fi
- echo shar: Extracting \"src/newmbox.c\" \(14549 characters\)
- if test -f src/newmbox.c ; then
- echo shar: Will not over-write existing file \"src/newmbox.c\"
- else
- sed "s/^X//" >src/newmbox.c <<'END_OF_src/newmbox.c'
- X/** newmbox.c **/
- X
- X/** read new mailbox file, (C) Copyright 1986 by Dave Taylor **/
- X
- X#include <ctype.h>
- X
- X#ifdef BSD
- X#undef tolower /* we have our own "tolower" routine instead! */
- X#endif
- X
- X#include "headers.h"
- X
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <errno.h>
- X
- X#ifdef BSD /* Berkeley has library elsewhere... */
- X# ifndef BSD4.1
- X# include <sys/time.h>
- X# else
- X# include <time.h>
- X# endif
- X#else
- X# include <time.h>
- X#endif
- X
- Xextern int errno;
- X
- Xchar *error_name(), *error_description(), *strcpy(), *strncpy();
- Xunsigned long sleep();
- Xvoid rewind();
- Xvoid exit();
- X
- Xstruct header_rec *realloc();
- X
- Xint
- Xnewmbox(stat, resync, main_screen)
- Xint stat, resync, main_screen;
- X{
- X /** Read a new mailbox file or resync on current file.
- X
- X Values of stat and what they mean;
- X
- X stat = 0 - changing mailboxes from within program
- X stat = 1 - read default mailbox or infile for the
- X first time
- X stat = 2 - read existing mailbox, new mail arrived
- X
- X resync is TRUE iff we know the current mailbox has changed. If
- X it's set to true this means that we MUST READ SOMETHING, even
- X if it's the current mailbox again!!
- X
- X main_screen simply tells where the counting line should be.
- X
- X **/
- X
- X int switching_to_default = 0, switching_from_default = 0;
- X int iterations = 0, redraw = 0; /* for dealing with the '?' answer */
- X char buff[SLEN];
- X
- X if (mbox_specified == 0 && stat == 0)
- X switching_from_default++;
- X
- X if (stat > 0) {
- X if (stat == 1 && strlen(infile) == 0) {
- X
- X /* Subtlety - check to see if there's another instantiation
- X of Elm (e.g. if the /tmp file is in use). If so, DIE! */
- X
- X sprintf(infile, "%s%s", temp_mbox, username);
- X if (access(infile, ACCESS_EXISTS) != -1) {
- X error(
- X "Hey! An instantiation of Elm is already reading this mail!\n\r");
- X fprintf(stderr,
- X"\n\r [if this is in error then you'll need to remove '/tmp/mbox.%s']\n\r",
- X username);
- X exit(1);
- X }
- X sprintf(infile, "%s%s", mailhome, username);
- X }
- X if (strlen(infile) == 0) /* no filename yet?? */
- X sprintf(infile,"%s%s",mailhome, username);
- X if ((errno = can_access(infile, READ_ACCESS))) {
- X if (strncmp(infile, mailhome, strlen(mailhome)) == 0) {
- X /* oh wow. incoming mailbox with no messages... */
- X return(1);
- X }
- X error2("Can't open mailbox '%s' for reading [%s]", infile,
- X error_name(errno));
- X exit(1);
- X }
- X }
- X else { /* get name of new mailbox! */
- X MoveCursor(LINES-3, 30);
- X CleartoEOS();
- X PutLine0(LINES-3, 40, "(Use '?' to list your folders)");
- X show_last_error();
- Xask_again:
- X buff[0] = '\0';
- X if (iterations++ == 0) {
- X PutLine0(LINES-2,0,"Name of new mailbox: ");
- X (void) optionally_enter(buff, LINES-2, 21, FALSE);
- X ClearLine(LINES-2);
- X }
- X else {
- X printf("\n\rName of new mailbox: ");
- X (void) optionally_enter(buff, -1, -1, FALSE);
- X }
- X if (strlen(buff) == 0) {
- X if (resync && file_changed)
- X strcpy(buff, infile);
- X else
- X return(redraw);
- X }
- X if (strcmp(buff, "?") == 0) {
- X redraw = 1; /* we'll need to clean the screen */
- X dprint0(1,"*** setting redraw to 1 ***\n");
- X list_folders();
- X goto ask_again;
- X }
- X if (strcmp(buff, "!") == 0 ||
- X strcmp(buff, "%") == 0) /* go to mailbox */
- X sprintf(buff,"%s%s", mailhome, username);
- X else if (! expand_filename(buff)) {
- X error1("can't expand file %s", buff);
- X if (resync && file_changed)
- X strcpy(buff, infile);
- X else
- X return(FALSE);
- X }
- X
- X if (strcmp(buff, infile) == 0 && ! resync) {
- X dprint0(3,"User requested change to current mailbox! (newmbox)\n");
- X error("already reading that mailbox!");
- X return(FALSE);
- X }
- X
- X if ((errno = can_access(buff, READ_ACCESS))) {
- X dprint2(2,"Error: attempt to open %s as mailbox denied (%s)!\n",
- X buff, "newmbox");
- X error1("Permission to open file %s denied", buff);
- X if (resync && file_changed)
- X strcpy(buff, infile);
- X else
- X return(FALSE);
- X }
- X
- X if (first_word(buff, mailhome)) { /* a mail file! */
- X mbox_specified = 0; /* fake program to think that */
- X stat = 1; /* we're the default file */
- X switching_to_default++; /* remember this act! */
- X }
- X
- X if (resync && file_changed && strcmp(buff, infile) == 0)
- X PutLine0(LINES-3,COLUMNS-40,"Resynchronizing file");
- X else
- X PutLine1(LINES-3,COLUMNS-40,"Mailbox: %s", buff);
- X CleartoEOLN();
- X strcpy(infile,buff);
- X if (! switching_to_default) mbox_specified = 1;
- X
- X }
- X
- X if (switching_from_default) { /* we need to remove the tmp file */
- X sprintf(buff, "%s%s", temp_mbox, username);
- X if (unlink(buff) != 0) {
- X error1(
- X "Sorry, but I can't seem to unlink your temp mail file [%s]\n\r",
- X error_name(errno));
- X silently_exit();
- X }
- X }
- X
- X clear_error();
- X clear_central_message();
- X
- X header_page = 0;
- X
- X if (mailfile != NULL)
- X (void) fclose(mailfile); /* close it first, to avoid too many open */
- X
- X if ((mailfile = fopen(infile,"r")) == NULL)
- X message_count = 0;
- X else if (stat < 2) { /* new mail file! */
- X current = 1;
- X message_count = read_headers(FALSE, main_screen);
- X if (! message_count) current = 0;
- X }
- X else /* resync with current mail file */
- X message_count = read_headers(TRUE, main_screen);
- X
- X if (stat < 2)
- X selected = 0; /* we don't preselect new mailboxes, boss! */
- X
- X return(TRUE);
- X}
- X
- Xint
- Xread_headers(rereading, main_screen)
- Xint rereading, main_screen;
- X{
- X /** Reads the headers into the header_table structure and leaves
- X the file rewound for further I/O requests. If the file being
- X read is the default mailbox (ie incoming) then it is copied to
- X a temp file and closed, to allow more mail to arrive during
- X the elm session. If 'rereading' is set, the program will copy
- X the status flags from the previous data structure to the new
- X one if possible. This is (obviously) for re-reading a mailfile!
- X **/
- X
- X FILE *temp;
- X struct header_rec *temp_struct;
- X char buffer[LONG_STRING], temp_filename[SLEN];
- X long bytes = 0L, line_bytes = 0L;
- X register int line = 0, count = 0, subj = 0, copyit = 0, in_header = 1;
- X int count_x, count_y = 17, new_messages = 0, err;
- X int in_to_list = FALSE, forwarding_mail = FALSE;
- X
- X static int first_read = 0;
- X
- X if (! first_read++) {
- X ClearLine(LINES-1);
- X ClearLine(LINES);
- X if (rereading)
- X PutLine2(LINES, 0, "Reading in %s, message: %d", infile,
- X message_count);
- X else
- X PutLine1(LINES, 0, "Reading in %s, message: 0", infile);
- X count_x = LINES;
- X count_y = 22 + strlen(infile);
- X }
- X else {
- X count_x = LINES-2;
- X if (main_screen)
- X PutLine0(LINES-2, 0, "Reading message: 0");
- X else {
- X PutLine0(LINES, 0, "\n");
- X PutLine0(LINES, 0, "Reading message: 0");
- X count_x = LINES;
- X }
- X }
- X
- X if (mbox_specified == 0) {
- X lock(INCOMING); /* ensure no mail arrives while we do this! */
- X sprintf(temp_filename,"%s%s",temp_mbox, username);
- X if (! rereading) {
- X if (access(temp_filename, ACCESS_EXISTS) != -1) {
- X /* Hey! What the hell is this? The temp file already exists? */
- X /* Looks like a potential clash of processes on the same file! */
- X unlock(); /* so remove lock file! */
- X error("What's this? The temp mailbox already exists??");
- X sleep(2);
- X error("Ahhhh.....I give up");
- X silently_exit(); /* leave without tampering with it! */
- X }
- X if ((temp = fopen(temp_filename,"w")) == NULL) {
- X err = errno;
- X unlock(); /* remove lock file! */
- X Raw(OFF);
- X Write_to_screen(
- X "\nCouldn't open file %s for use as temp mailbox;\n", 1,
- X temp_filename);
- X Write_to_screen("** %s - %s **\n", 2,
- X error_name(err), error_description(err));
- X dprint3(1,
- X "Error: Couldn't open file %s as temp mbox. errno %s (%s)\n",
- X temp_filename, error_name(err), "read_headers");
- X leave();
- X }
- X get_mailtime();
- X copyit++;
- X chown(temp_filename, userid, groupid);
- X chmod(temp_filename, 0700); /* shut off file for other people! */
- X }
- X else {
- X if ((temp = fopen(temp_filename,"a")) == NULL) {
- X err = errno;
- X unlock(); /* remove lock file! */
- X Raw(OFF);
- X Write_to_screen(
- X "\nCouldn't reopen file %s for use as temp mailbox;\n", 1,
- X temp_filename);
- X Write_to_screen("** %s - %s **\n", 2,
- X error_name(err), error_description(err));
- X dprint3(1,
- X "Error: Couldn't reopen file %s as temp mbox. errno %s (%s)\n",
- X temp_filename, error_name(err), "read_headers");
- X emergency_exit();
- X }
- X copyit++;
- X }
- X }
- X
- X if (rereading) {
- X if (fseek(mailfile, mailfile_size, 0)) {
- X err = errno;
- X Write_to_screen(
- X "\nCouldn't seek to %ld (end of mailbox) in %s!\n", 2,
- X mailfile_size, infile);
- X Write_to_screen("** %s - %s **\n", 2,
- X error_name(err), error_description(err));
- X dprint4(1,
- X "Error: Couldn't seek to end of mailbox %s: (offset %ld) Errno %s (%s)\n",
- X infile, mailfile_size, error_name(err), "read_headers");
- X emergency_exit();
- X }
- X count = message_count; /* next available */
- X bytes = mailfile_size; /* start correctly */
- X if (message_count > 0)
- X line = header_table[message_count - 1].lines;
- X else
- X line = 0;
- X }
- X
- X while (fgets(buffer, LONG_STRING, mailfile) != NULL) {
- X
- X if (bytes == 0L) { /* first line of file... */
- X if (! mbox_specified) {
- X if (first_word(buffer, "Forward to ")) {
- X set_central_message("Mail being forwarded to %s",
- X (char *) (buffer + 11));
- X forwarding_mail = TRUE;
- X }
- X }
- X if (! first_word(buffer, "From ") && !forwarding_mail) {
- X PutLine0(LINES, 0,
- X "\n\rMail file is corrupt!! I can't read it!!\n\r\n\r");
- X fflush(stderr);
- X dprint0(1, "\n\n**** First mail header is corrupt!! ****\n\n");
- X dprint1(1, "Line is;\n\t%s\n\n", buffer);
- X mail_only++; /* to avoid leave() cursor motion */
- X leave();
- X }
- X }
- X
- X if (copyit) fputs(buffer, temp);
- X line_bytes = (long) strlen(buffer);
- X line++;
- X if (first_word(buffer,"From ")) {
- X
- X /** try to allocate new headers, if needed... **/
- X
- X if (count >= max_headers) {
- X max_headers += KLICK;
- X dprint2(3,
- X "\n\nAbout to allocate headers, count = %d, max_headers=%d\n",
- X count, max_headers);
- X if ((temp_struct = realloc(header_table, max_headers *
- X sizeof(struct header_rec))) == NULL) {
- X error1(
- X "\n\r\n\rCouldn't allocate enough memory! Failed on message #%d\n\r\n\r",
- X count);
- X leave();
- X }
- X header_table = temp_struct;
- X dprint1(7,"\tallocated %d more headers!\n\n", KLICK);
- X }
- X
- X if (real_from(buffer, &header_table[count])) {
- X header_table[count].offset = (long) bytes;
- X header_table[count].index_number = count+1;
- X if (! rereading || count > message_count)
- X header_table[count].status = VISIBLE; /* default status! */
- X strcpy(header_table[count].subject, ""); /* clear subj */
- X header_table[count-1].lines = line;
- X if (new_msg(header_table[count])) {
- X header_table[count].status |= NEW; /* new message! */
- X
- X if (! new_messages++ && point_to_new && ! rereading &&
- X sortby == RECEIVED_DATE) {
- X current = count+1;
- X get_page(current); /* make sure we're ON that page! */
- X }
- X
- X /* Quick comment on that last conditional test...
- X
- X We want to move the current pointer to the first new
- X message IF this is the first of the new messages, the
- X user requested this feature, we're not rereading the
- X mailbox (imagine how THAT could screw the user up!),
- X and we're not in some funky sorting mode (received-date is
- X the default). As always, I'm open to suggestions on
- X other ways to have this work intelligently.
- X */
- X
- X }
- X count++;
- X subj = 0;
- X line = 0;
- X in_header = 1;
- X PutLine1(count_x, count_y, "%d", count);
- X }
- X }
- X else if (in_header) {
- X if (first_word(buffer,">From"))
- X forwarded(buffer, &header_table[count-1]); /* return address */
- X else if (first_word(buffer,"Subject:") ||
- X first_word(buffer,"Subj:") ||
- X first_word(buffer,"Re:")) {
- X if (! subj++) {
- X remove_first_word(buffer);
- X strncpy(header_table[count-1].subject, buffer, STRING);
- X }
- X }
- X else if (first_word(buffer,"From:"))
- X parse_arpa_from(buffer, header_table[count-1].from);
- X
- X /** when it was sent... **/
- X
- X else if (first_word(buffer, "Date:"))
- X parse_arpa_date(buffer, &header_table[count-1]);
- X
- X /** some status things about the message... **/
- X
- X else if (first_word(buffer, "Priority:"))
- X header_table[count-1].status |= PRIORITY;
- X else if (first_word(buffer, "Content-Type: mailform"))
- X header_table[count-1].status |= FORM_LETTER;
- X else if (first_word(buffer, "Action:"))
- X header_table[count-1].status |= ACTION;
- X
- X /** next let's see if it's to us or not... **/
- X
- X else if (first_word(buffer, "To:")) {
- X in_to_list = TRUE;
- X header_table[count-1].to[0] = '\0'; /* nothing yet */
- X figure_out_addressee((char *) buffer +3,
- X header_table[count-1].to);
- X }
- X
- X else if (buffer[0] == LINE_FEED || buffer[0] == '\0') {
- X if (in_header) {
- X in_header = 0; /* in body of message! */
- X fix_date(&header_table[count-1]);
- X }
- X }
- X else if (in_to_list == TRUE) {
- X if (whitespace(buffer[0]))
- X figure_out_addressee(buffer, header_table[count-1].to);
- X else in_to_list = FALSE;
- X }
- X }
- X bytes += (long) line_bytes;
- X }
- X
- X header_table[count > 0? count-1:count].lines = line + 1;
- X
- X if (mbox_specified == 0) {
- X unlock(); /* remove lock file! */
- X fclose(mailfile);
- X fclose(temp);
- X if ((mailfile = fopen(temp_filename,"r")) == NULL) {
- X err = errno;
- X MoveCursor(LINES,0);
- X Raw(OFF);
- X Write_to_screen("\nAugh! Couldn't reopen %s as temp mail file;\n",
- X 1, temp_filename);
- X Write_to_screen("** %s - %s **\n", 2, error_name(err),
- X error_description(err));
- X dprint3(1,
- X "Error: Reopening %s as temp mail file failed! errno %s (%s)\n",
- X temp_filename, error_name(errno), "read_headers");
- X leave();
- X }
- X }
- X else
- X rewind(mailfile);
- X
- X sort_mailbox(count, 1); /* let's sort this baby now! */
- X
- X return(count);
- X}
- END_OF_src/newmbox.c
- if test 14549 -ne `wc -c <src/newmbox.c`; then
- echo shar: \"src/newmbox.c\" unpacked with wrong size!?
- fi
- # end of overwriting check
- fi
- echo shar: Extracting \"src/reply.c\" \(14009 characters\)
- if test -f src/reply.c ; then
- echo shar: Will not over-write existing file \"src/reply.c\"
- else
- sed "s/^X//" >src/reply.c <<'END_OF_src/reply.c'
- X/** reply.c **/
- X
- X/*** routine allows replying to the sender of the current message
- X
- X (C) Copyright 1985, Dave Taylor
- X***/
- X
- X#include "headers.h"
- X#include <errno.h>
- X
- X#ifndef BSD
- X# include <sys/types.h>
- X# include <sys/utsname.h>
- X#endif
- X
- X/** Note that this routine generates automatic header information
- X for the subject and (obviously) to lines, but that these can
- X be altered while in the editor composing the reply message!
- X**/
- X
- Xchar *strip_parens(), *get_token();
- X
- Xextern int errno;
- X
- Xchar *error_name(), *strcat(), *strcpy();
- X
- Xint
- Xreply()
- X{
- X /** Reply to the current message. Returns non-zero iff
- X the screen has to be rewritten. **/
- X
- X char return_address[LONG_SLEN], subject[SLEN];
- X int return_value, form_letter;
- X
- X form_letter = (header_table[current-1].status & FORM_LETTER);
- X
- X get_return(return_address);
- X
- X if (first_word(header_table[current-1].from, "To:")) {
- X strcpy(subject, header_table[current-1].subject);
- X if (form_letter)
- X return_value = mail_filled_in_form(return_address, subject);
- X else
- X return_value = send(return_address, subject, TRUE, NO);
- X }
- X else if (header_table[current-1].subject[0] != '\0') {
- X if ((strncmp("Re:", header_table[current-1].subject, 3) == 0) ||
- X (strncmp("RE:", header_table[current-1].subject, 3) == 0) ||
- X (strncmp("re:", header_table[current-1].subject, 3) == 0))
- X strcpy(subject, header_table[current-1].subject);
- X else {
- X strcpy(subject,"Re: ");
- X strcat(subject,header_table[current-1].subject);
- X }
- X if (form_letter)
- X return_value = mail_filled_in_form(return_address, subject);
- X else
- X return_value = send(return_address, subject, TRUE, NO);
- X }
- X else
- X if (form_letter)
- X return_value = mail_filled_in_form(return_address,
- X "Filled in Form");
- X else
- X return_value = send(return_address, "Re: your mail", TRUE, NO);
- X
- X return(return_value);
- X}
- X
- Xint
- Xreply_to_everyone()
- X{
- X /** Reply to everyone who received the current message.
- X This includes other people in the 'To:' line and people
- X in the 'Cc:' line too. Returns non-zero iff the screen
- X has to be rewritten. **/
- X
- X char return_address[LONG_SLEN], subject[SLEN];
- X char full_address[VERY_LONG_STRING];
- X int return_value;
- X
- X get_return(return_address);
- X
- X strcpy(full_address, return_address); /* sender gets copy */
- X
- X get_and_expand_everyone(return_address, full_address);
- X
- X if (header_table[current-1].subject[0] != '\0') {
- X if ((strncmp("Re:", header_table[current-1].subject, 3) == 0) ||
- X (strncmp("RE:", header_table[current-1].subject, 3) == 0) ||
- X (strncmp("re:", header_table[current-1].subject, 3) == 0))
- X strcpy(subject, header_table[current-1].subject);
- X else {
- X strcpy(subject,"Re: ");
- X strcat(subject,header_table[current-1].subject);
- X }
- X return_value = send(full_address, subject, TRUE, NO);
- X }
- X else
- X return_value = send(full_address, "Re: your mail", TRUE, NO);
- X
- X return(return_value);
- X
- X}
- X
- Xint
- Xforward()
- X{
- X /** Forward the current message. What this actually does is
- X to set auto_copy to true, then call 'send' to get the
- X address and route the mail.
- X **/
- X
- X char subject[SLEN], address[VERY_LONG_STRING];
- X int original_cc, results, edit_msg = FALSE;
- X
- X original_cc = auto_copy;
- X address[0] = '\0';
- X
- X if (header_table[current-1].status & FORM_LETTER)
- X PutLine0(LINES-3,COLUMNS-40,"<no editing allowed>");
- X else {
- X edit_msg = (want_to("Edit outgoing message (y/n) ? ",'y',FALSE)!='n');
- X Write_to_screen("%s", 1, edit_msg? "Yes" : "No");
- X }
- X
- X auto_cc = TRUE; /* we want a copy */
- X
- X if (strlen(header_table[current-1].subject) > 0) {
- X strcpy(subject,header_table[current-1].subject);
- X results = send(address, subject, edit_msg,
- X header_table[current-1].status & FORM_LETTER?
- X PREFORMATTED : allow_forms);
- X }
- X else
- X results = send(address, "Forwarded Mail...", edit_msg,
- X header_table[current-1].status & FORM_LETTER?
- X PREFORMATTED : allow_forms);
- X
- X auto_copy = original_cc;
- X
- X return(results);
- X}
- X
- Xget_and_expand_everyone(return_address, full_address)
- Xchar *return_address, *full_address;
- X{
- X /** Read the current message, extracting addresses from the 'To:'
- X and 'Cc:' lines. As each address is taken, ensure that it
- X isn't to the author of the message NOR to us. If neither,
- X prepend with current return address and append to the
- X 'full_address' string.
- X **/
- X
- X char ret_address[LONG_SLEN], buf[LONG_SLEN], new_address[LONG_SLEN],
- X address[LONG_SLEN], comment[LONG_SLEN];
- X int in_message = 1, first_pass = 0, index;
- X
- X /** First off, get to the first line of the message desired **/
- X
- X if (fseek(mailfile, header_table[current-1].offset, 0) == -1) {
- X dprint3(1,"Error: seek %ld resulted in errno %s (%s)\n",
- X header_table[current-1].offset, error_name(errno),
- X "get_and_expand_everyone");
- X error2("ELM [seek] couldn't read %d bytes into file (%s)",
- X header_table[current-1].offset, error_name(errno));
- X return;
- X }
- X
- X /** okay! Now we're there! **/
- X
- X /** let's fix the ret_address to reflect the return address of this
- X message with '%s' instead of the persons login name... **/
- X
- X translate_return(return_address, ret_address);
- X
- X /** now let's parse the actual message! **/
- X
- X while (in_message) {
- X in_message = (int) (fgets(buf, LONG_SLEN, mailfile) != NULL);
- X if (first_word(buf, "From ") && first_pass++ != 0)
- X in_message = FALSE;
- X else if (first_word(buf, "To:") || first_word(buf, "Cc:") ||
- X first_word(buf, "CC:") || first_word(buf, "cc:")) {
- X do {
- X no_ret(buf);
- X
- X /** we have a buffer with a list of addresses, each of either the
- X form "address (name)" or "name <address>". Our mission, should
- X we decide not to be too lazy, is to break it into the two parts.
- X **/
- X
- X if (!whitespace(buf[0]))
- X index = chloc(buf, ':')+1; /* skip header field */
- X else
- X index = 0; /* skip whitespace */
- X
- X while (break_down_tolist(buf, &index, address, comment)) {
- X
- X if (okay_address(address, return_address)) {
- X sprintf(new_address, ret_address, address);
- X optimize_and_add(new_address, full_address);
- X }
- X }
- X
- X in_message = (int) (fgets(buf, LONG_SLEN, mailfile) != NULL);
- X
- X if (in_message) dprint1(1,"> %s", buf);
- X
- X } while (in_message && whitespace(buf[0]));
- X
- X }
- X else if (strlen(buf) < 2) /* done with header */
- X in_message = FALSE;
- X }
- X}
- X
- Xint
- Xokay_address(address, return_address)
- Xchar *address, *return_address;
- X{
- X /** This routine checks to ensure that the address we just got
- X from the "To:" or "Cc:" line isn't us AND isn't the person
- X who sent the message. Returns true iff neither is the case **/
- X
- X char our_address[SLEN];
- X struct addr_rec *alternatives;
- X
- X if (in_string(address, return_address))
- X return(FALSE);
- X
- X sprintf(our_address, "%s!%s", hostname, username);
- X
- X if (in_string(address, our_address))
- X return(FALSE);
- X
- X sprintf(our_address, "%s@%s", username, hostname);
- X
- X if (in_string(address, our_address))
- X return(FALSE);
- X
- X alternatives = alternative_addresses;
- X
- X while (alternatives != NULL) {
- X if (in_string(address, alternatives->address))
- X return(FALSE);
- X alternatives = alternatives->next;
- X }
- X
- X return(TRUE);
- X}
- X
- Xoptimize_and_add(new_address, full_address)
- Xchar *new_address, *full_address;
- X{
- X /** This routine will add the new address to the list of addresses
- X in the full address buffer IFF it doesn't already occur. It
- X will also try to fix dumb hops if possible, specifically hops
- X of the form ...a!b...!a... and hops of the form a@b@b etc
- X **/
- X
- X register int len, host_count = 0, i;
- X char hosts[MAX_HOPS][SLEN]; /* array of machine names */
- X char *host, *addrptr;
- X
- X if (in_string(full_address, new_address))
- X return(1); /* duplicate address */
- X
- X /** optimize **/
- X /* break down into a list of machine names, checking as we go along */
- X
- X addrptr = (char *) new_address;
- X
- X while ((host = get_token(addrptr, "!", 1)) != NULL) {
- X for (i = 0; i < host_count && ! equal(hosts[i], host); i++)
- X ;
- X
- X if (i == host_count) {
- X strcpy(hosts[host_count++], host);
- X if (host_count == MAX_HOPS) {
- X dprint1(2,
- X "Error: hit max_hops limit trying to build return address (%s)\n",
- X "optimize_and_add");
- X error("Can't build return address - hit MAX_HOPS limit!");
- X return(1);
- X }
- X }
- X else
- X host_count = i + 1;
- X addrptr = NULL;
- X }
- X
- X /** fix the ARPA addresses, if needed **/
- X
- X if (chloc(hosts[host_count-1], '@') > -1)
- X fix_arpa_address(hosts[host_count-1]);
- X
- X /** rebuild the address.. **/
- X
- X new_address[0] = '\0';
- X
- X for (i = 0; i < host_count; i++)
- X sprintf(new_address, "%s%s%s", new_address,
- X new_address[0] == '\0'? "" : "!",
- X hosts[i]);
- X
- X if (full_address[0] == '\0')
- X strcpy(full_address, new_address);
- X else {
- X len = strlen(full_address);
- X full_address[len ] = ',';
- X full_address[len+1] = ' ';
- X full_address[len+2] = '\0';
- X strcat(full_address, new_address);
- X }
- X
- X return(0);
- X}
- X
- Xget_return_name(address, name, shift_lower)
- Xchar *address, *name;
- Xint shift_lower;
- X{
- X /** Given the address (either a single address or a combined list
- X of addresses) extract the login name of the first person on
- X the list and return it as 'name'. Modified to stop at
- X any non-alphanumeric character. **/
- X
- X /** An important note to remember is that it isn't vital that this
- X always returns just the login name, but rather that it always
- X returns the SAME name. If the persons' login happens to be,
- X for example, joe.richards, then it's arguable if the name
- X should be joe, or the full login. It's really immaterial, as
- X indicated before, so long as we ALWAYS return the same name! **/
- X
- X /** Another note: modified to return the argument as all lowercase
- X always, unless shift_lower is FALSE... **/
- X
- X char single_address[LONG_SLEN];
- X register int i, loc, index = 0;
- X
- X dprint2(6,"get_return_name called with (%s, <>, shift=%s)\n",
- X address, onoff(shift_lower));
- X
- X /* First step - copy address up to a comma, space, or EOLN */
- X
- X for (i=0; address[i] != ',' && ! whitespace(address[i]) &&
- X address[i] != '\0'; i++)
- X single_address[i] = address[i];
- X single_address[i] = '\0';
- X
- X /* Now is it an ARPA address?? */
- X
- X if ((loc = chloc(single_address, '@')) != -1) { /* Yes */
- X
- X /* At this point the algorithm is to keep shifting our copy
- X window left until we hit a '!'. The login name is then
- X located between the '!' and the first metacharacter to
- X it's right (ie '%', ':' or '@'). */
- X
- X for (i=loc; single_address[i] != '!' && i > -1; i--)
- X if (single_address[i] == '%' ||
- X single_address[i] == ':' ||
- X single_address[i] == '.' || /* no domains */
- X single_address[i] == '@') loc = i-1;
- X
- X if (i < 0 || single_address[i] == '!') i++;
- X
- X for (index = 0; index < loc - i + 1; index++)
- X if (shift_lower)
- X name[index] = tolower(single_address[index+i]);
- X else
- X name[index] = single_address[index+i];
- X name[index] = '\0';
- X }
- X else { /* easier - standard USENET address */
- X
- X /* This really is easier - we just cruise left from the end of
- X the string until we hit either a '!' or the beginning of X
- X while (buf[*index] != ',' && buf[*index] != '\0')
- X buffer[loc++] = buf[(*index)++];
- X
- X (*index)++;
- X
- X buffer[loc] = '\0';
- X while (whitespace(buffer[loc - 1]))
- X buffer[--loc] = '\0'; /* remove trailing whitespace */
- X
- X buffer[loc] = '\0';
- X
- X if (strlen(buffer) == 0) return(FALSE);
- X
- X dprint1(5, "\n* got \"%s\"\n", buffer);
- X
- X if (buffer[loc-1] == ')') { /* address (name) format */
- X for (loc = 0;buffer[loc] != '(' && loc < strlen(buffer); loc++)
- X /* get to the opening comment character... */ ;
- X
- X loc--; /* back up to just before the paren */
- X while (whitespace(buffer[loc])) loc--; /* back up */
- X
- X /** get the address field... **/
- X
- X for (i=0; i <= loc; i++)
- X address[i] = buffer[i];
- X address[i] = '\0';
- X
- X /** now get the comment field, en toto! **/
- X
- X loc = 0;
- X
- X for (i = chloc(buffer, '('); i < strlen(buffer); i++)
- X comment[loc++] = buffer[i];
- X comment[loc] = '\0';
- X }
- X else if (buffer[loc-1] == '>') { /* name <address> format */
- X dprint0(7, "\tcomment <address>\n");
- X for (loc = 0;buffer[loc] != '<' && loc < strlen(buffer); loc++)
- X /* get to the opening comment character... */ ;
- X while (whitespace(buffer[loc])) loc--; /* back up */
- X
- X /** get the comment field... **/
- X
- X comment[0] = '(';
- X for (i=1; i < loc; i++)
- X comment[i] = buffer[i-1];
- X comment[i++] = ')';
- X comment[i] = '\0';
- X
- X /** now get the address field, en toto! **/
- X
- X loc = 0;
- X
- X for (i = chloc(buffer,'<') + 1; i < strlen(buffer) - 1; i++)
- X address[loc++] = buffer[i];
- X
- X address[loc] = '\0';
- X }
- X else {
- X strcpy(address, buffer);
- X comment[0] = '\0';
- X }
- X
- X dprint2(5,"-- returning '%s' '%s'\n", address, comment);
- X
- X return(TRUE);
- X}
- END_OF_src/reply.c
- if test 14009 -ne `wc -c <src/reply.c`; then
- echo shar: \"src/reply.c\" unpacked with wrong size!?
- fi
- # end of overwriting check
- fi
- echo shar: End of archive 14 \(of 19\).
- cp /dev/null ark14isdone
- DONE=true
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
- if test ! -f ark${I}isdone ; then
- echo shar: You still need to run archive ${I}.
- DONE=false
- fi
- done
- if test "$DONE" = "true" ; then
- echo You have unpacked all 19 archives.
- echo "See the Instructions file"
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- fi
- ## End of shell archive.
- exit 0
-