# To unbundle, run this file
echo Makefile
sed 's/.//' >Makefile <<'//GO.SYSIN DD Makefile'
-#
-# @(#)Makefile 1.49
-#
-BINDIR = $(HOME)/bin/$(cputype)
-SHBINDIR = $(HOME)/bin
-CC = cc
-CFLAGS = -O -g -w4 -DYYDEBUG
-STICKY = 0
-XMODE = $(STICKY)711
-SHXMODE = 755
-XSGID = $(STICKY)2711
-MAIL = mail
-RANLIB = : ranlib
-YFLAGS = #-v
-SHELL = /bin/sh
-
-#
-# Braindamage for broken socket installations
-#
-NETLIBS = -lsocket -lnsl
-
-NEW =
-
-INC = \
- addr.h \
- conf.h \
- flex.h \
- headers.h \
- line.h \
- mace.h \
- message.h \
- pop.h \
- regexp.h \
- regmagic.h \
- tty.h
-
-LIBSRC = \
- addr.y \
- aka.c \
- args.c \
- conf.c \
- dir.c \
- domain.c \
- id.c \
- flex.c \
- headers.c \
- host.c \
- line.c \
- lock.c \
- mail.c \
- macebox.c \
- macedir.c \
- memory.c \
- mesg.c \
- mess.c \
- misc.c \
- name.c \
- pipe.c \
- re.c \
- readdir.c \
- readfile.c \
- readpass.c \
- regexp.c \
- rfc.c \
- run.c \
- string.c \
- sysmess.c \
- tn.c \
- tty.c \
- vec.c \
- writefile.c
-
-SH = \
- bundle \
- mal
-
-SRC = \
- $(INC) \
- $(LIBSRC) \
- $(SH) \
- box.c \
- com.c \
- despool.c \
- mace.c \
- mad.c \
- mal \
- mam.c \
- mda.c \
- mox.c \
- msg.c \
- pop.c \
- reo.c \
- ret.c
-
-DOC = \
- box.1 \
- com.1 \
- mace.1 \
- mal.1 \
- mam.1 \
- mov.1 \
- mox.1 \
- msg.1 \
- pop.1 \
- reo.1 \
- mace-config.4 \
- mace-proto.4
-
-TEXT = \
- Makefile \
- NEW \
- TODO \
- :yyfix \
- setup \
- $(DOC) \
- $(SRC)
-
-LIB = libmace.a
-
-LIBOBJ = \
- addr.o \
- aka.o \
- args.o \
- conf.o \
- dir.o \
- domain.o \
- id.o \
- flex.o \
- headers.o \
- host.o \
- line.o \
- lock.o \
- macebox.o \
- macedir.o \
- mail.o \
- memory.o \
- mesg.o \
- mess.o \
- misc.o \
- name.o \
- pipe.o \
- re.o \
- readdir.o \
- readfile.o \
- readpass.o \
- regexp.o \
- rfc.o \
- run.o \
- string.o \
- sysmess.o \
- tn.o \
- tty.o \
- vec.o \
- writefile.o
-
-BIN = \
- box \
- com \
- mace \
- despool \
- mad \
- mam \
- mda \
- mox \
- msg \
- pop \
- reo \
- ret
-
-MACE = \
- $(BIN) \
- $(SH)
-
-all : $(MACE)
-
-install : all
- cp $(BIN) $(BINDIR)
- cd $(BINDIR) ; chmod $(XMODE) $(BIN)
- cp $(SH) $(SHBINDIR)
- cd $(SHBINDIR) ; chmod $(SHXMODE) $(SH)
- -cd $(BINDIR) ; rm -f rem ; ln msg rem
- -cd $(BINDIR) ; rm -f med ; ln msg med
- -cd $(BINDIR) ; rm -f mov ; ln msg mov
- -cd $(BINDIR) ; rm -f del ; ln msg del
- -cd $(BINDIR) ; rm -f cop ; ln msg cop
- -cd $(BINDIR) ; rm -f lnk ; ln msg lnk
- -cd $(BINDIR) ; rm -f mrk ; ln msg mrk
- -cd $(BINDIR) ; rm -f ./- ; ln msg ./-
- -cd $(BINDIR) ; rm -f + ; ln msg +
- -cd $(BINDIR) ; rm -f rep ; ln com rep
- -cd $(BINDIR) ; rm -f fwd ; ln com fwd
- -cd $(BINDIR) ; rm -f mcp ; ln mad mcp
- -cd $(BINDIR) ; rm -f mln ; ln mad mln
- cd $(BINDIR) ; chgrp $(MAIL) despool
- cd $(BINDIR) ; chmod $(XSGID) despool
-
-print :
- pr -l66 -w132 $(TEXT) | lp
-
-dist : bundle
- sh bundle $(TEXT) > mace.bundle
-
-shar : bundle
- sh bundle $(TEXT) > mace.$@
-
-$(LIB) : $(LIBOBJ)
- @-rm -f $(LIB)
- ar qv $(LIB) $(LIBOBJ)
- $(RANLIB) $(LIB)
-
-test : test.o $(LIB)
- $(CC) -o test test.o $(LIB)
-
-clean :
- rm -f $(LIB) *.o y.output y.tab.c
-
-nuke : clean
- rm -f $(BIN)
-
-tags ::
- ctags $(SRC)
-
-admin : $(NEW)
- @echo 'Comment? ' | tr -d '\012' ; read x ; set -x ; \
- for i in $(NEW) ; \
- do \
- admin -i"$$i" -y"$$x" SCCS/s."$$i" ; \
- done
-
-delta :
- @echo 'Comment? ' | tr -d '\012' ; read x ; set -x ; \
- for i in $(TEXT) ; \
- do \
- delta -y"$$x" SCCS/s."$$i" || : ; \
- done
-
-box : $(LIB) box.o
- $(CC) -o box box.o $(LIB)
-
-com : $(LIB) com.o
- $(CC) -o com com.o $(LIB)
-
-mace : $(LIB) mace.o
- $(CC) -o mace mace.o $(LIB)
-
-despool : $(LIB) despool.o
- $(CC) -o despool despool.o $(LIB)
-
-mad : $(LIB) mad.o
- $(CC) -o mad mad.o $(LIB)
-
-mam : $(LIB) mam.o
- $(CC) -o mam mam.o $(LIB)
-
-mda : $(LIB) mda.o
- $(CC) -o mda mda.o $(LIB)
-
-mox : $(LIB) mox.o
- $(CC) -o mox mox.o $(LIB)
-
-msg : $(LIB) msg.o
- $(CC) -o msg msg.o $(LIB)
-
-pop : $(LIB) pop.o
- $(CC) -o pop pop.o $(LIB) || ( set -x ; $(CC) -o pop pop.o $(LIB) $(NETLIBS) )
-
-reo : $(LIB) reo.o
- $(CC) -o reo reo.o $(LIB)
-
-ret : $(LIB) ret.o
- $(CC) -o ret ret.o $(LIB)
-
-.c.o :
- $(CC) $(CFLAGS) -c $*.c
-
-addr.c : addr.y
- yacc $(YFLAGS) addr.y
- sh :yyfix
-
-box.o : box.c mace.h line.h message.h headers.h conf.h regexp.h
-com.o : com.c mace.h message.h headers.h conf.h regexp.h addr.h
-mace.o : mace.c mace.h conf.h headers.h line.h message.h regexp.h flex.h
-despool.o : despool.c mace.h
-mad.o : mad.c mace.h
-mam.o : mam.c mace.h regexp.h message.h line.h
-mda.o : mad.c conf.h line.h mace.h headers.h message.h regexp.h addr.h
-mox.o : mox.c mace.h regexp.h conf.h line.h message.h
-msg.o : msg.c mace.h line.h flex.h message.h
-pop.o : pop.c mace.h line.h flex.h pop.h
-reo.o : reo.c mace.h line.h message.h
-ret.o : ret.c mace.h line.h message.h
-test.o : test.c mace.h
-
-messid.o : messid.c mace.h
-
-addr.o : addr.c mace.h flex.h headers.h addr.h
-aka.o : aka.c mace.h
-args.o : args.c mace.h line.h
-conf.o : conf.c conf.h flex.h headers.h line.h mace.h message.h regexp.h
-dir.o : dir.c mace.h
-domain.o : domain.c mace.h line.h
-id.o : id.c mace.h
-flex.o : flex.c flex.h mace.h
-host.o : host.c mace.h line.h
-headers.o : headers.c mace.h headers.h
-line.o : line.c flex.h line.h mace.h
-lock.o : lock.c mace.h
-macebox.o : macebox.c mace.h
-macedir.o : macedir.c mace.h
-mail.o : mail.c mace.h line.h headers.h
-memory.o : memory.c mace.h
-mesg.o : mesg.c mace.h
-mess.o : mess.c mace.h message.h headers.h line.h
-misc.o : misc.c mace.h
-name.o : name.c mace.h
-pipe.o : pipe.c mace.h
-re.o : re.c mace.h
-readdir.o : readdir.c mace.h
-readfile.o : readfile.c mace.h
-readpass.o : readpass.c mace.h flex.h tty.h
-regexp.o : regexp.c mace.h regmagic.h regexp.h
-rfc.o : rfc.c mace.h conf.h headers.h line.h message.h regexp.h
-run.o : run.c mace.h
-string.o : string.c mace.h
-sysmess.o : sysmess.c
-tn.o : tn.c mace.h
-tty.o : tty.c tty.h mace.h
-vec.o : vec.c mace.h
-writefile.o : writefile.c mace.h
//GO.SYSIN DD Makefile
echo NEW
sed 's/.//' >NEW <<'//GO.SYSIN DD NEW'
-What's New (1.1):
-
- bundle
-
- A /bin/sh version of Plan 9 bundle; a simple shell archiver.
-
- mal +box ...
-
- A simple alias facility that uses the To: line in a box's .proto.
-
- % mal +bonehead
- Bonehead <bonehead@clueless.com>
-
- mam
-
- Used to add messages to boxes:
-
- mam [ -u ] [ -dps ] [ +[+]box ] [ files ] ...
-
- It's a more or less like 'mace' and handles multiple box/file arguments
- in the same style as 'msg':
-
- mam +foo a b c ++bar d
-
- It can also be invoked as a filter.
-
- It's options are:
-
- d - don't audit
- p - preserve a box's current message
- s - silent (doesn't print the message summary)
- u - unlock audit trail
-
- pop
-
- A POP 3 client which splits a POP mailbox into multiple files:
-
- pop [ -delete ] [ -n number ] [ -r [ seconds ] ] [ -s spooldir ] [ -t ] [ [user@]server ]
-
- It's options are:
-
- -delete
-
- Delete messages off the POP server after they've all been retrieved.
-
- -n number
-
- Message file names start at 'number', instead of 0.
-
- -r [ seconds ]
-
- Run in the background and interrogate the server periodically.
- A timeout value can be specified in seconds. If none is given
- a default of 120 seconds (2 minutes) is used.
-
- In this mode the password is asked for once and from then on it
- lives in a pipe. This eliminates tedious password typing and minimises
- the likelyhood of the password winding up in a core dump.
-
- -s spooldir
-
- Create messages in 'spooldir'. The current directory is the default.
-
- -t
-
- Trace the POP 3 protocol to standard error:
-
- system% pop -s /tmp -t pacific
- pop: <-- +OK QUALCOMM Pop server derived from UCB (version 2.1.4-R3) at PACIFIC starting.
- pop: --> USER boyd
- pop: <-- +OK Password required for boyd.
- pop: --> PASS ...
- pop: <-- +OK boyd has 37 message(s) (106154 octets).
- pop: --> STAT
- pop: <-- +OK 37 106154
- pop: --> RETR 1
- pop: <-- +OK 1397 octets
- ...
-
- [user@]server
-
- Optional user/mailbox name and POP 3 server to contact.
- Otherwise the current user on 'localhost' is used.
-
- reo
-
- A filter to re-order headers in an RFC 822 message. It is not configurable
- and uses the standard mace order of:
-
- From:
- Date:
- To:
- Cc:
- Bcc:
- Subject:
-
- See headers.c for the ordering code.
-
- It was written to fix messages broken by a braindamaged delivery agent in
- conjunction with this script:
-
- #!/bin/sh
-
- # Fix broken mail headers
-
- sed -e '1,5d' -e '/^>From:/s/>//' | reo
-
- setup [ directory ]
-
- A script to setup the directory for Mace and a sample configuration file.
//GO.SYSIN DD NEW
echo TODO
sed 's/.//' >TODO <<'//GO.SYSIN DD TODO'
-Things To Do (1.1):
-
-1. Integrate 'mam' and 'pop -r' in some way. Possibly a script 'mop' is invoked
- by the user to pick up the messages retrieved by 'pop'.
-
-2. Limbo rewrite for Inferno?
//GO.SYSIN DD TODO
echo :yyfix
sed 's/.//' >:yyfix <<'//GO.SYSIN DD :yyfix'
-:
-: "@(#):yyfix 1.17"
-:
-sed '/in:/{s/in:/in state %d:/
- s/yyn/&, yystate/
- }' y.tab.c > addr.c
//GO.SYSIN DD :yyfix
echo setup
sed 's/.//' >setup <<'//GO.SYSIN DD setup'
-#!/bin/sh
-
-#
-# @(#)setup 1.1
-#
-# mace setup
-#
-
-macedir="$HOME/.macedir"
-config=".config"
-
-umask 077
-
-myname="`basename \"$0\"`"
-
-# use argument or prompt for directory
-case $# in
-0)
- dir="$HOME/Mace"
- echo "Directory where your mail will be kept [$dir]? " | tr -d '\012'
-
- if read x
- then
- case "$x" in
- '')
- ;;
-
- *)
- dir="$x"
- ;;
- esac
- else
- exit 1
- fi
- ;;
-
-1)
- dir="$1"
- ;;
-
-*)
- echo "usage: $myname [ directory ]" 1>&2
- exit 1
- ;;
-esac
-
-# full path name
-case "$dir" in
-/*)
- ;;
-
-*)
- dir="`pwd`/$dir"
- ;;
-esac
-
-# create if necessary
-if [ ! -d "$dir" ]
-then
- mkdir "$dir" || exit 1
-fi
-
-# slice off $HOME and put in $macedir
-if echo "$dir" | sed "s;^$HOME/;;" > "$macedir" 2> /dev/null
-then
- # determine login name
- user=your.login.name
-
- case "$USER" in
- '')
- user="$LOGNAME"
- ;;
-
- *)
- user="$USER"
- ;;
- esac
-
- # create prototype configuration in $config
- if cat <<! > "$dir/$config"
-incoming in
-outgoing out
-address your.address.here
-remove "$user"
-#deliver custom delivery agent command
-#exec "regexp" "command"
-!
- then
- echo "Tailor '$dir/$config' to suit your environment."
- echo 'It currently contains:'
- cat "$dir/$config"
- else
- echo "$myname: Could not write '$dir/$config'" 1>&2
- exit 1
- fi
-
-else
- echo "$myname: Could not write '$macedir'" 1>&2
- exit 1
-fi
//GO.SYSIN DD setup
echo box.1
sed 's/.//' >box.1 <<'//GO.SYSIN DD box.1'
-.\"
-.\" @(#)box.1 1.1
-.\"
-.TH BOX 1
-.SH NAME
-box \- manage boxes
-.SH SYNOPSIS
-.B box
-[
-.B -acdilmorst
-]
-[
-[\fB+\fP]\fB+\fP\fIbox\fP
-\&...
-]
-.SH DESCRIPTION
-.B Box
-allows boxes to be created and deleted as well as providing information on
-their status and contents. A particular
-.I box
-can be specified by prefixing its name by the
-.I "box character"
-.BR + .
-.PP
-With no arguments
-.B box
-displays the name of the current
-.I box
-prepended with the
-.I "box character"
-.BR + .
-If one
-.I box
-is specified with no options it is made the
-.IR "current box" .
-A
-.I box
-can also be made the current box by specifying the
-.I "box character"
-.B +
-twice.
-.PP
-Several options, some mutually exclusive, are available:
-.TP
-.B -a
-Apply action to all boxes.
-.TP
-.B -c
-Create the named box(es).
-.TP
-.B -d
-Delete the named box(es).
-.TP
-.B -i
-Show the name of the
-.I incoming
-box.
-.TP
-.B -l
-Gives a one line summary for the
-.IR box .
-The output consists of the
-.I "box character"
-.BR + ,
-prepended to the name of the box, the name of the current message and
-number of messages in the box followed by
-.BR messages ( s ).
-If the
-.I box
-contains no messages the message count is replaced by
-.BR empty .
-.TP
-.B -m
-Gives a one line summary for the current message in the
-.IR box .
-.TP
-.B -o
-Show the name of the
-.I outgoing
-box.
-.TP
-.B -r
-Gives a one line summary for each message in the
-.I box
-in reverse message order.
-.TP
-.B -s
-Gives a one line summary for each message in the
-.IR box .
-The output consists of a
-.B -
-(indicating that the message was received) or a
-.B +
-(indicating that the message is pending delivery), the
-.I "box character"
-.B +
-prepended to the name of the box, an optional
-.B ?
-(indicating links to the message),
-an optional
-.B |
-(indicating delivery by
-.BR del ( 1 ))
-and the text of the message's
-.BR From: ,
-.B Date:
-and
-.B Subject:
-lines.
-.TP
-.B -t
-Gives a one line summary for each message in the
-.I box
-showing the message's
-.B To:
-line instead of the
-.B From:
-line.
-.PP
-Before a
-.I box
-can be deleted all its messages must be removed with
-.BR rem ( 1 ).
-.SH FILES
-$MACEDIR/.config
-.br
-$MACEDIR/.box
-.br
-.RI $MACEDIR/ box /.messid
-.br
-.RI $MACEDIR/ box / id
-.SH "SEE ALSO"
-.BR del ( 1 ),
-.BR msg ( 1 ),
-.BR rem ( 1 ),
-.BR mace-config ( 4 ).
//GO.SYSIN DD box.1
echo com.1
sed 's/.//' >com.1 <<'//GO.SYSIN DD com.1'
-.\"
-.\" %W%
-.\"
-.TH COM 1
-.SH NAME
-com, fwd, rep \- compose, forward or reply to messages
-.SH SYNOPSIS
-.B com
-[
-.B
--eis
-]
-[
-[\fB+\fP]\fB+\fP\fIbox\fP
-]
-.sp
-.B fwd
-[
-.B
--eis
-]
-[
-[\fB+\fP]\fB+\fP\fIbox\fP
-]
-[
-.I id
-]
-.sp
-.B rep
-[
-.B
--eis
-]
-[
-[\fB+\fP]\fB+\fP\fIbox\fP
-]
-[
-.I id
-]
-.SH DESCRIPTION
-All create a new message template and then invoke
-.B $EDITOR
-on it. The new message is located in the one of the following boxes:
-.TP
-.I multiple
-.B Rep
-applies the
-.I refile
-regular expressions to the headers of message being replied to. The
-first match determines the box used.
-.I Copies
-are made for boxes in subsequent matches with
-.BR mln ( 1 ).
-.TP
-.I outgoing
-If the current box is
-.IR incoming .
-.TP
-.I current
-If the current box is not
-.IR incoming .
-.TP
-.I box
-The named
-.I box
-specified by the argument.
-.PP
-The
-.I id
-of the message in the chosen
-.I box
-is the next in the series after the last message in the
-.IR box .
-.PP
-Once the message has been edited it is set to be the
-.I "current message"
-and it is ready to be delivered with
-.BR del ( 1 ).
-The separation of composition and delivery is a deliberate choice.
-.PP
-All support the following options:
-.TP
-.B -e
-An external agent requests only the creation of the template;
-.B $EDITOR
-is not invoked.
-.TP
-.B -i
-Include the current message, after the headers, in the template.
-.TP
-.B -s
-Insert
-.B Sender:
-and
-.B Reply-To:
-headers in the template. The text in the
-.B Sender:
-header is that which would normally appear in the
-.B From:
-header.
-.PP
-The headers are constructed based on a standard template as modified
-by the global and local
-.I "message prototype"
-files. The standard headers are:
-.TP
-From:
-This is followed by your email address. If
-.B $NAME
-is set it consists of
-.B "$NAME <\fIuser\fP@\fIdomain\fP>" otherwise
-it is
-.BR \fIuser\fP@\fIdomain\fP .
-.I User
-is your login name.
-.I Domain
-is the parameter specified with the
-.B address
-configuration option.
-.TP
-Date:
-The current date and time.
-.TP
-To:
-Not initialised.
-.TP
-Cc:
-Not initialised.
-.TP
-Bcc:
-Not initialised.
-.TP
-Subject:
-Not initialised.
-.TP
-Message-ID:
-An RFC 822 message id of the form
-.BR "<\fIyyyymmddhhmm\fP.\fIpid\fP.\fIbox\fP.\fIid\fP@\fIdomain\fP>" .
-.PP
-The global and local prototype files are read in turn and matching headers
-are replaced by those specified in the prototypes. Non-matching headers found
-in the prototypes are concatenated to the existing headers. This provides a
-mechanism for header customisation.
-.PP
-.B Fwd
-forwards a message by constructing a template which has the current
-message or
-.I id
-in the current box appended to it.
-.PP
-.B Rep
-replies to a message with the headers constructed as before
-but with some further initialisation (based on the message being
-replied to):
-.TP
-To:
-Contains the address(es) found in the
-.B From:
-header.
-.TP
-Cc:
-Contains the address(es) found in the
-.B Cc:
-header.
-.TP
-Subject:
-If the message has a
-.B Subject:
-header it contains
-.B Re:
-followed by the subject.
-.TP
-.B In-Reply-To:
-This header is added with the contents of the
-.B Message-ID:
-header, if present.
-.SH FILES
-$MACEDIR/.config
-.br
-$MACEDIR/.proto
-.br
-$MACEDIR/.box
-.br
-.RI $MACEDIR/ box /.proto
-.br
-.RI $MACEDIR/ box /.messid
-.br
-.RI $MACEDIR/ box / id
-.SH "SEE ALSO"
-.BR del ( 1 ),
-.BR mln ( 1 ),
-.BR environ ( 5 ),
-.BR mace-config ( 4 ),
-.BR mace-proto ( 4 ).
//GO.SYSIN DD com.1
echo mace.1
sed 's/.//' >mace.1 <<'//GO.SYSIN DD mace.1'
-.\"
-.\" @(#)mace.1 1.1
-.\"
-.TH MACE 1
-.SH NAME
-mace \- add messages to incoming box
-.SH SYNOPSIS
-.B mace
-[
-.B -adsu
-]
-[
-.B -f
-.I mailfile
-]
-.SH DESCRIPTION
-.B Mace
-reads a user's
-.I mailfile
-and copies the messages into the
-.I incoming
-box. After the messages have been added sucessfully the
-.I mailfile
-is deleted.
-.PP
-As messages are read they are added to the
-.I "audit trail"
-which contains a verbatim copy of the message, as it existed in the
-file. To prevent audit trail corruption a simple locking protocol is
-used.
-.PP
-A one line summary for each message processed is output using
-the same format used by
-.BR box ( 1 ).
-The first message added is set to be the
-.IR "current message" .
-.PP
-The headers of each message are re-ordered, before the message is
-added to the
-.IR box ,
-so that all messages
-have their headers in a standard order. The order is documented in
-.BR reo ( 1 ).
-.PP
-.B Mace
-supports several options:
-.TP
-.B -a
-Use the audit trail.
-.TP
-.B -d
-Don't use the audit trail.
-.TP
-.B -s
-Silently add messages without printing a summary.
-.TP
-.B -u
-Unlock the audit trail and exit.
-.TP
-.BI -f " mailfile"
-Use
-.I mailfile
-as the user's mail file instead of
-.BR $MAIL .
-The
-.I mailfile
-is not deleted in this case.
-.PP
-.BR Pop ( 1 )
-and
-.BR mam ( 1 )
-should be used in preference to
-.B mace
-where mail is managed by a Post Office Protocol (POP) version 3 server.
-.SH FILES
-$MACEDIR/.audit
-.br
-$MACEDIR/.audit.lck
-.br
-$MACEDIR/.box
-.br
-.RI $MACEDIR/ box /.messid
-.br
-.RI $MACEDIR/ box / id
-.SH "SEE ALSO"
-.BR box ( 1 ),
-.BR msg ( 1 ),
-.BR pop ( 1 ),
-.BR mam ( 1 ),
-.BR reo ( 1 ),
-.BR mace-config ( 4 ).
//GO.SYSIN DD mace.1
echo mal.1
sed 's/.//' >mal.1 <<'//GO.SYSIN DD mal.1'
-.\"
-.\" @(#)mal.1 1.1
-.\"
-.TH MAL 1
-.SH NAME
-mal \- per box aliases
-.SH SYNOPSIS
-.B mam
-\fB+\fP\fIbox\fP
-\&...
-.SH DESCRIPTION
-.B Mal
-uses a
-.IR box 's
-.I "message prototype"
-file to provide a simple alias facility. A
-.I box
-is specified by prepending the
-.I "box character"
-.B +
-to its name. For each
-.I box
-specified its
-.I "message prototype"
-file is read and if a
-.B To:
-header is found the corresponding address contained in this header is output.
-.PP
-It is assumed that addresses to not span multiple lines. A comma is
-inserted between pairs of lines to construct a valid RFC 822 address
-list. The output of
-.B mal
-is designed to be used with
-.BR com ( 1 ).
-.SH FILES
-.RI $MACEDIR/ box /.proto
-.SH "SEE ALSO"
-.BR box ( 1 ),
-.BR com ( 1 ),
-.BR mace-proto ( 4 ).
//GO.SYSIN DD mal.1
echo mam.1
sed 's/.//' >mam.1 <<'//GO.SYSIN DD mam.1'
-.\"
-.\" @(#)mam.1 1.1
-.\"
-.TH MAM 1
-.SH NAME
-mam \- add messages to boxes
-.SH SYNOPSIS
-.B mam
-[
-.B -u
-]
-[
-.B -dps
-]
-[
-[\fB+\fP]\fB+\fP\fIbox\fP
-]
-[
-.I files
-]
-\&...
-.SH DESCRIPTION
-.B Mam
-reads standard input or files for RFC 822 messages and adds them
-to boxes. Boxes are specified by the name of the
-.I box
-prefixed by the
-.I "box character"
-.BR + .
-The
-.I "current box"
-can be changed by inserting an extra
-.B +
-character.
-.PP
-Multiple
-.I box
-options can be specified with one or more
-.IR files .
-If no
-.I files
-are specified the standard input is read.
-If no
-.I box
-is specified the current box is used.
-.PP
-As messages are read they are added to the
-.I "audit trail"
-which contains a verbatim copy of the message, as it existed in the
-file. To prevent audit trail corruption a simple locking protocol is
-used.
-.PP
-A one line summary for each message processed is output using
-the same format used by
-.BR box ( 1 ).
-The first message added to a
-.I box
-it is set to be the
-.I "current message"
-for that
-.IR box .
-.PP
-The headers of each message are re-ordered, before the message is
-added to the
-.IR box ,
-so that all messages
-have their headers in a standard order. The order is documented in
-.BR reo ( 1 ).
-.PP
-.B Mam
-supports several options:
-.TP
-.B -d
-Don't use the audit trail.
-.TP
-.B -p
-Preserve a
-.IR box 's
-current message as current.
-.TP
-.B -s
-Silently add messages without printing a summary.
-.TP
-.B -u
-Unlock the audit trail and exit.
-.SH FILES
-$MACEDIR/.audit
-.br
-$MACEDIR/.audit.lck
-.br
-$MACEDIR/.box
-.br
-.RI $MACEDIR/ box /.messid
-.br
-.RI $MACEDIR/ box / id
-.SH "SEE ALSO"
-.BR msg ( 1 ),
-.BR rem ( 1 ).
//GO.SYSIN DD mam.1
echo mov.1
sed 's/.//' >mov.1 <<'//GO.SYSIN DD mov.1'
-.\"
-.\" @(#)mov.1 1.1
-.\"
-.TH MOV 1
-.SH NAME
-mov, lnk, cop \- move, link or copy messages
-.SH SYNOPSIS
-.B mov
-[
-[\fB+\fP]\fB+\fP\fIbox\fP
-]
-[
-.I id
-]
-[
-first|previous|current|next|last
-]
-[
-.RI [ from ]\-[ to ]
-]
-[
-.I regex
-]
-[
-all
-]
-\&...
-.BI + target
-.sp
-.B mln
-[
-[\fB+\fP]\fB+\fP\fIbox\fP
-]
-[
-.I id
-]
-[
-first|previous|current|next|last
-]
-[
-.RI [ from ]\-[ to ]
-]
-[
-.I regex
-]
-[
-all
-]
-\&...
-.BI + target
-.sp
-.B cop
-[
-[\fB+\fP]\fB+\fP\fIbox\fP
-]
-[
-.I id
-]
-[
-first|previous|current|next|last
-]
-[
-.RI [ from ]\-[ to ]
-]
-[
-.I regex
-]
-[
-all
-]
-\&...
-.BI + target
-.SH DESCRIPTION
-.B Mov
-moves messages from one or more boxes into a single
-.I target
-box. Messages are named either by their
-.I id
-or by their
-.I box
-and
-.IR id .
-A full explanation of message naming can be found in
-.BR msg ( 1 ).
-If no message is specified the current message is moved.
-.PP
-Messages created in the
-.I target
-box are relative to that box, starting with the
-.I next
-.I id
-after the
-.I last
-message in that box. The last message created in the
-.I target
-box is set to be the current message for that box.
-.PP
-.B Lnk
-links messages. It is not available on Plan 9.
-.PP
-.B Cop
-copies messages.
-.SH FILES
-$MACEDIR/.config
-.br
-$MACEDIR/.box
-.br
-.RI $MACEDIR/ box /.messid
-.br
-.RI $MACEDIR/ box / id
-.SH "SEE ALSO"
-.BR msg ( 1 ).
//GO.SYSIN DD mov.1
echo mox.1
sed 's/.//' >mox.1 <<'//GO.SYSIN DD mox.1'
-.\"
-.\" @(#)mox.1 1.1
-.\"
-.TH MOX 1
-.SH NAME
-mox \- add messages from a directory to incoming box
-.SH SYNOPSIS
-.B mox
-[
-.B -ds
-]
-[
-.B -delete
-]
-.SH DESCRIPTION
-.B Mox
-acts like
-.BR mace ( 1 )
-but takes messages from a spool directory, one per file, and adds them
-to the
-.I incoming
-box with
-.BR mam ( 1 ).
-The location of the spool directory is determined
-by the
-.I spooldir
-keyword (see
-.BR mace-config ( 1 )).
-.B
-Mox
-was designed to work with mail despoolers such as
-.BR pop ( 1 ).
-.PP
-After a message has been added,
-.B mox
-applies any
-.I refile
-directives, prints a summary of the message and then
-applies any
-.I exec
-directives.
-This order is to ensure that the summary reflects an accurate view of
-reality. An explanation of these directives can be found in
-.BR mace-config ( 4 ).
-.PP
-The default behaviour can be modified by the following options:
-.TP
-.B -d
-Don't use the audit trail.
-.TP
-.B -delete
-Delete messages from
-.I spooldir
-after they have been processed
-successfully.
-.TP
-.B -s
-Silently add messages without printing a summary.
-.SH "SEE ALSO"
-.BR mace ( 1 ),
-.BR mam ( 1 ),
-.BR pop ( 1 ),
-.BR mace-config ( 4 ).
//GO.SYSIN DD mox.1
echo msg.1
sed 's/.//' >msg.1 <<'//GO.SYSIN DD msg.1'
-.\"
-.\" @(#)msg.1 1.1
-.\"
-.TH MSG 1
-.SH NAME
-msg, med, del, rem \- display, edit, deliver or remove messages
-.SH SYNOPSIS
-.B msg
-[
-[\fB+\fP]\fB+\fP\fIbox\fP
-]
-[
-.I id
-]
-[
-first|previous|current|next|last
-]
-[
-.RI [ from ]\-[ to ]
-]
-[
-.I regex
-]
-[
-all
-]
-\&...
-.sp
-.B med
-[
-[\fB+\fP]\fB+\fP\fIbox\fP
-]
-[
-.I id
-]
-[
-first|previous|current|next|last
-]
-[
-.RI [ from ]\-[ to ]
-]
-[
-.I regex
-]
-[
-all
-]
-\&...
-.sp
-.B del
-[
-[\fB+\fP]\fB+\fP\fIbox\fP
-]
-[
-.I id
-]
-[
-first|previous|current|next|last
-]
-[
-.RI [ from ]\-[ to ]
-]
-[
-.I regex
-]
-[
-all
-]
-\&...
-.sp
-.B rem
-[
-[\fB+\fP]\fB+\fP\fIbox\fP
-]
-[
-.I id
-]
-[
-first|previous|current|next|last
-]
-[
-.RI [ from ]\-[ to ]
-]
-[
-.I regex
-]
-[
-all
-]
-\&...
-.SH DESCRIPTION
-.B Msg
-displays messages based on its arguments or the current message if none are
-specified. Messages are named either by their
-.I id
-or by their
-.I box
-and
-.IR id .
-An
-.I id
-consists of 5 characters constructed from alternating consonant
-and vowel
-characters to make a
-.I pronounceable
-identifier. Consonants are taken from the set [bdfgjklmnprstvyz].
-.PP
-Messages can also be referred to by these aliases:
-.TP
-first
-The first message in a box.
-.TP
-previous
-The message before the current message.
-.TP
-current
-The current message. This not normally used but is included for completeness.
-.TP
-next
-The message after the current message.
-.TP
-last
-The last message in a box.
-.PP
-Aliases may be abbreviated to their first four characters.
-.PP
-Ranges of messages can be specified by two
-.IR id 's
-separated by a
-.BR \- .
-These can be either a pronounceable message
-.I id
-or an alias and one or both need not be specified. If one is missing
-then the current message is used to start or terminate the range. If
-both are missing the current message is used.
-.PP
-Groups of messages may be referred to with a
-.I regex
-in the form of
-.BR sh ( 1 )
-style metacharacters
-.B ?
-and
-.BR * ,
-as well as character ranges of the form
-.B [a-z]
-and
-.BR [abc] .
-Care should be taken to quote such arguments to prevent interpretation
-by the shell.
-.PP
-All messages in a box may be specified by
-.BR all .
-.PP
-A message (or messages) in a particular
-.I box
-can be specified by prefixing the name of the
-.I box
-by the
-.B +
-character. Subsequent messages identifiers are then interpreted relative
-to the messages in that
-.IR box .
-Two
-.B +
-characters can be used to make the named
-.I box
-to be the current
-.IR box .
-More than one
-.IR box
-argument with zero or more message identifiers can be specified. If no
-message identifier is specified the current message in that box is used.
-.PP
-.B Msg
-converts the arguments to filenames and uses
-.B $PAGER
-to display them all. It is run once and the current message for each
-box is set to the last message selected from that box if the exit status
-is zero. Regardless of the exit status the current box is set as
-directed by the arguments.
-.PP
-.B Med
-uses
-.B $EDITOR
-instead of
-.BR $PAGER .
-.PP
-.B Del
-delivers messages that have been created with
-.BR com ( 1 ).
-.PP
-.B Rem
-removes the selected messages.
-.SH FILES
-$MACEDIR/.config
-.br
-$MACEDIR/.box
-.br
-.RI $MACEDIR/ box /.messid
-.br
-.RI $MACEDIR/ box / id
-.SH "SEE ALSO"
-.BR mov ( 1 ),
-.BR environ ( 5 ).
//GO.SYSIN DD msg.1
echo pop.1
sed 's/.//' >pop.1 <<'//GO.SYSIN DD pop.1'
-.\"
-.\" @(#)pop.1 1.1
-.\"
-.TH POP 1
-.SH NAME
-pop \- POP 3 client
-.SH SYNOPSIS
-.B pop
-[
-.B -delete
-]
-[
-.B -n
-.I number
-]
-[
-.B -r
-[
-.I seconds
-]
-]
-[
-.B -s
-.I spooldir
-]
-[
-.B -t
-]
-[
-[\fIuser\fP\fB@\fP]\fIserver\fP
-]
-.SH DESCRIPTION
-.B Pop
-is a client that uses version 3 of the Post Office Protocol (POP). It
-is designed to be used in conjunction with
-.BR mam ( 1 )
-to add messages from a maildrop to one or more boxes.
-.PP
-By default it connects to
-.B localhost
-as the current user and prompts for the user's password on the maildrop.
-If the supplied password is correct, it then copies each message into
-files in the current directory. Files are named numerically, starting at 0,
-increasing monotonically.
-An alternative
-.I user
-name and POP
-.I server
-can be specified as an argument.
-.PP
-The default behaviour can be modified by the following options:
-.TP
-.B -delete
-Delete messages on the maildrop after they have been transferred
-successfully. Should an error occur,
-.B pop
-does not request that the messages be deleted.
-.TP
-.BI -n " number"
-Files are named starting with
-.IR number .
-.TP
-\fB-r\fP [ \fIseconds\fP ]
-Re-check the maildrop every
-.IR seconds .
-If no time is given a default of 2 minutes (120 seconds) is used.
-It is not necessary to re-enter the password for the mail-drop each
-time. The password is maintained by
-.B pop
-in a pipe to minimise the risk of is appearing in a
-.BR core ( 4 )
-file.
-.TP
-.BI -s " spooldir
-Files are created in the directory
-.I spooldir
-rather than the current directory.
-.TP
-.B -t
-Communication with the POP server is traced to standard error. Commands
-sent to the server are prefixed with
-.BR --> .
-Responses from the server are prefixed with
-.BR <-- .
-The password is not traced.
-.PP
-Files are created
-.I write-only
-(owner)
-to prevent other processes from reading them while they are being written.
-Once a file has been completely written it is changed to be
-.I read/write
-(owner). This simple mechanism negates the need for a locking protocol.
-.PP
-.B Pop
-was designed to use as few POP commands as necessary. The following
-are used:
-.TP
-USER
-User name.
-.TP
-PASS
-User password.
-.TP
-STAT
-Query maildrop status.
-.TP
-RETR
-Retrieve message.
-.TP
-DELE
-Delete message.
-.TP
-RSET
-Reset protocol.
-.TP
-QUIT
-Quit session.
-.SH "SEE ALSO"
-RFC 1225,
-.BR mam ( 1 ),
-.BR core ( 4 ).
//GO.SYSIN DD pop.1
echo reo.1
sed 's/.//' >reo.1 <<'//GO.SYSIN DD reo.1'
-.\"
-.\" @(#)reo.1 1.1
-.\"
-.TH REO 1
-.SH NAME
-reo \- re-order message headers
-.SH SYNOPSIS
-.B reo
-.SH DESCRIPTION
-.B Reo
-is a filter that reorders the headers of an RFC 822 message. After it has
-output the re-ordered headers it copies the body of the message unchanged.
-The order chosen is:
-.BR From: ,
-.BR Date: ,
-.BR To: ,
-.BR Cc: ,
-.B Bcc
-and
-.BR Subject: .
-The remaining headers are then appended as they appeared in the message.
-.SH "SEE ALSO"
-.BR mam ( 1 ).
//GO.SYSIN DD reo.1
echo mace-config.4
sed 's/.//' >mace-config.4 <<'//GO.SYSIN DD mace-config.4'
-.\"
-.\" @(#)mace-config.4 1.2
-.\"
-.TH MACE-CONFIG 4
-.SH NAME
-mace\-config \- mace configuration
-.SH SYNOPSIS
-$MACEDIR
-.SH DESCRIPTION
-Mail managed by mace is located in the directory
-.B $MACEDIR
-(if set) or by the directory specified in
-.BR $HOME/.macedir .
-If the directory in
-.B $HOME/.macedir
-does not begin with a
-.B /
-the directory is interpreted to be
-relative to
-.BR $HOME .
-.PP
-The directory contains the following:
-.TP
-.B .config
-The configuration file.
-.TP
-.B .audit
-The
-.I "audit trail"
-maintained by
-.BR mace ( 1 )
-and
-.BR mam ( 1 ).
-.TP
-.B .audit.lck
-The
-.I "audit trail"
-lock file.
-.TP
-.B .box
-A file containing the name of the current
-.IR box .
-.TP
-.B .proto
-The global
-.I "message prototype"
-file.
-.TP
-.I box
-A directory for each
-.IR box .
-.PP
-A
-.I box
-is a directory in
-.B $MACEDIR
-which contains:
-.TP
-.B .messid
-The file containing the name of the
-.IR box 's
-.IR "current message" .
-.TP
-.B .proto
-The
-.IR box 's
-.I "message prototype"
-file.
-.TP
-.I id
-Message files are named by their
-.IR id .
-An
-.I id
-consists of 5 characters constructed from alternating consonant
-and vowel
-characters to make a
-.I pronounceable
-identifier. Consonants are taken from the set [bdfgjklmnprstvyz].
-The first message
-.I id
-is
-.BR babab .
-The last is
-.BR zuzuz .
-.PP
-The configuration file consists of a list of keywords and values,
-separated by spaces and tabs. Lines commencing with
-.B #
-are comments and are ignored. An entry can be continued on the next line
-by a
-.B \e
-at the end of the line.
-.PP
-The following keywords are understood:
-.TP
-.BI "address* " domain
-The
-.I domain
-used in creating the user's
-.B From:
-address.
-.TP
-.BI "deliver* " command
-A
-.I command
-to deliver messages.
-.TP
-.BI "despool " command
-The
-.I command
-run by
-.BR mace ( 1 )
-to lock, output, unlock and remove the user's mail
-.IR file .
-.TP
-\fBexec\fP "\fIregex\fP" "\fIcommand\fP"
-A regular expression matched against the headers of a message by
-.BR mace ( 1 )
-and
-.BR mox ( 1 ).
-If a header matches
-.I regex
-then then
-.I command
-is executed. A two character sequence beginning with a
-.B %
-allows substitution of the following parameters:
-.BR b ,
-.I "incoming box"
-preceded by the
-.I "box character"
-.BR + ;
-.BR d ,
-.BR $MACEDIR ;
-.BR m ,
-message
-.IR id ;
-.BR p ,
-message pathname;
-.BR % ,
-%.
-.TP
-.BI "incoming " box
-The name of the
-.I box
-where incoming mail is held.
-.TP
-.BI "outgoing " box
-The name of the
-.I box
-where outgoing mail templates are created by default.
-.TP
-.BI "peruse " command
-The
-.I command
-run by
-.BR mace ( 1 )
-to lock, output and unlock the user's mail file.
-.TP
-\fBrefile\fP "\fIregex\fP" \fIbox\fP
-A regular expression matched against the headers of a message by
-.BR mace ( 1 )
-and
-.BR mox ( 1 ).
-If a header matches
-.I regex
-then the message is linked into
-.IR box .
-.TP
-\fBremove\fP "\fIregex\fP"
-A regular expression that is matched against the recipient list
-when replying to a message. Addresses matching
-.I regex
-are removed from the
-.B To:
-and
-.B Cc:
-headers when the template is created.
-It is used to delete the replier's address.
-.TP
-.BI "spool " file
-The name of the user's mail file.
-.TP
-.BI "spooldir " file
-The name of a directory containing mail messages, one per file.
-This directory can be used by mail despoolers that operate like
-.BR pop ( 1 ).
-Files
-in this directory can be added to
-.I incoming
-by
-.BR mox ( 1 ).
-.PP
-Regular expressions are of the form used by
-.BR egrep ( 1 ).
-Keywords marked with an
-.B *
-are mandatory.
-.SH EXAMPLES
-.IP
-.nf
-address civil.su.oz.au
-incoming in
-outgoing out
-remove "(john@(.+\.)?(civil|vetsci|physiol)\.su\.[Oo][Zz]\.[Aa][Uu])|(mackin@(.+\.)?geology\.su\.oz\.au)|(^john$)"
-exec "^Sender: Viet Nam War Discussion List" "mov %b %m +vwar"
-.fi
-.SH FILES
-$HOME/.macedir
-.br
-$MACEDIR/.audit
-.br
-$MACEDIR/.audit.lck
-.br
-$MACEDIR/.config
-.br
-$MACEDIR/.box
-.br
-$MACEDIR/.proto
-.br
-.RI $MACEDIR/ box /.messid
-.br
-.RI $MACEDIR/ box /.proto
-.br
-.RI $MACEDIR/ box / id
-.SH "SEE ALSO"
-.BR mace-proto ( 4 ),
-.BR environ ( 5 ).
//GO.SYSIN DD mace-config.4
echo mace-proto.4
sed 's/.//' >mace-proto.4 <<'//GO.SYSIN DD mace-proto.4'
-.\"
-.\" @(#)mace-proto.4 1.1
-.\"
-.TH MACE-PROTO 4
-.SH NAME
-mace\-proto \- message prototype files
-.SH SYNOPSIS
-$MACEDIR/.proto
-.sp
-.RI $MACEDIR/ box /.proto
-.SH DESCRIPTION
-.I "Message prototype"
-files are used to customise message prototypes generated by
-.BR com ( 1 ).
-The global prototype is $MACEDIR/.proto and
-boxes also may have a local prototype in
-.RI $MACEDIR/ box /.proto.
-.PP
-These files consist of a series of RFC 822 headers and text following
-the header. They follow the usual conventions of RFC 822 headers.
-.SH EXAMPLES
-To customise your
-.B From:
-address:
-.IP
-From: donald.duck@duckpond.arpa
-.PP
-To add an
-.B X-Face:
-header (used by
-.BR faces ( 1 )):
-.IP
-.nf
-X-Face: #"03$i1:"_[Hbg~GCPw}`+d4_R`}RaDfYixB`n-mCB0E8m#tNd>uyd[d<DIM0G$`0'*Yp+f
- Qw-B0lP>)`nEix7Bys(:o#o2y7$(=,&BTXdH7)Hm5jP}H5:y]}0GT4?uTT(Y0(Cu7tWBXj\|q\@jZ8
- Y_qn8)NV0*$uO][i7p"K2>Kg(
-.fi
-.SH FILES
-$MACEDIR/.proto
-.br
-.RI $MACEDIR/ box /.proto
-.SH "SEE ALSO"
-.BR com ( 1 ).
//GO.SYSIN DD mace-proto.4
echo addr.h
sed 's/.//' >addr.h <<'//GO.SYSIN DD addr.h'
-/*
-** Mail address data structures
-**
-** %W%
-*/
-
-#define NEED_BZERO
-#define NSUBDOM 20 /* # of subdomain names in domain */
-
-typedef unsigned int MALLOCT; /* Parameter to malloc */
-
-/*
-** An address.
-*/
-typedef struct _addr {
- struct _addr *next; /* next address in list */
- struct _dom *route; /* route icl. destination domain */
- struct _dom *destdom; /* destination domain */
- char *localp; /* RFC local part */
- char *name; /* Comment name */
- char *group; /* Group (List) phrase */
- char *comment; /* () comment phrase */
- char *text; /* literal text */
- char *error; /* error text if not NULL */
-} Addr;
-
-
-/*
-** A domain.
-*/
-typedef struct _dom {
- struct _dom *next; /* next domain (f.i. in route) */
- char *sub[NSUBDOM]; /* subdomain strins */
- char **top; /* toplevel domain */
-} Dom;
-
-
-extern Addr *newAddr(); /* Create a new address */
-extern Dom *newDom(); /* Create a new domain */
-extern Addr *adrlist;
-extern Addr *errlist;
-extern char *strcpy();
-extern char *strncpy();
-extern char *strcat();
-
-/* SHUT UP! */
-#define Strcpy (void)strcpy
-#define Strncpy (void)strncpy
-#define Strcat (void)strcat
-#define Sprintf (void)sprintf
//GO.SYSIN DD addr.h
echo conf.h
sed 's/.//' >conf.h <<'//GO.SYSIN DD conf.h'
-/*
- * Configuration stuff.
- *
- * @(#)conf.h 1.36
- */
-
-/*
- * Tokens to be found in the CONFIG file.
- */
-#define CT_ADDRESS "address"
-#define CT_DELIVER "deliver"
-#define CT_DESPOOL "despool"
-#define CT_EXEC "exec"
-#define CT_INBOX "incoming"
-#define CT_OUTBOX "outgoing"
-#define CT_PERUSE "peruse"
-#define CT_REFILE "refile"
-#define CT_REMOVE "remove"
-#define CT_SAVE "save"
-#define CT_SPOOL "spool"
-#define CT_SPOOLDIR "spooldir"
-
-typedef struct match match;
-
-struct match
-{
- char *m_re;
- regexp *m_cre;
- char *m_action;
- match *m_next;
-};
-
-typedef struct
-{
- char *c_address;
- char *c_deliver;
- char *c_despool;
- char *c_inbox;
- char *c_outbox;
- char *c_peruse;
- match *c_exec;
- match *c_refile;
- match *c_remove;
- match *c_save;
- char *c_spool;
- char *c_spooldir;
-}
- conf;
-
-extern conf *read_config();
-
-/*
- * Substitution characters for CT_EXEC.
- */
-#define CE_SPECIAL '%'
-#define CE_BOX 'b'
-#define CE_MACEDIR 'd'
-#define CE_MESSID 'm'
-#define CE_PATH 'p'
-
-extern char *special_expand(char *, char *, char *);
-extern void regex_apply(char *, message *, match *, void (*)(char *, message *, match *));
//GO.SYSIN DD conf.h
echo flex.h
sed 's/.//' >flex.h <<'//GO.SYSIN DD flex.h'
-/*
- * Flexible string definitions.
- *
- * @(#)flex.h 1.31
- */
-
-#define FLEXZ 128
-
-typedef struct
-{
- char *f_str;
- char *f_end;
- char *f_ptr;
-}
- flex;
-
-#define flex_char(f, c) (*((f)->f_ptr == (f)->f_end ? flex_fill(f) : (f)->f_ptr++) = (c))
-
-extern void flex_end();
-extern char *flex_fill();
-extern void flex_init();
-extern void flex_str();
-extern void flex_nstr();
//GO.SYSIN DD flex.h
echo headers.h
sed 's/.//' >headers.h <<'//GO.SYSIN DD headers.h'
-/*
- * Unix mail / RFC 822 headers.
- *
- * %W%
- */
-
-#define UNIX_FROM "From "
-#define UNIX_FWD_CHAR '>'
-
-#define UNIX_DATE_LEN 25
-
-#define UNIX_REGARDING "Re:"
-
-#define RFC_BCC "Bcc:"
-#define RFC_CC "Cc:"
-#define RFC_DATE "Date:"
-#define RFC_FROM "From:"
-#define RFC_IN_REPLY_TO "In-Reply-To:"
-#define RFC_MESSAGE_ID "Message-ID:"
-#define RFC_REPLY_TO "Reply-To:"
-#define RFC_SENDER "Sender:"
-#define RFC_SUBJECT "Subject:"
-#define RFC_TO "To:"
-
-#define RFC_LWSP_1 ' '
-#define RFC_LWSP_2 '\t'
-
-#define RFC_SPEC_AT '@'
-#define RFC_SPEC_DOT '.'
-#define RFC_SPEC_LANGLE '<'
-#define RFC_SPEC_RANGLE '>'
-#define RFC_SPEC_COMMA ','
-#define RFC_SPEC_COLON ':'
-#define RFC_SPEC_PLUS '+'
-#define RFC_SPEC_MINUS '-'
-#define RFC_SPEC_PERCENT '%'
-
-#define RFC_STR_GMT "GMT"
-
-#define RFC_ZONE_HOUR(h) ((h) * 60)
-
-extern char **find_header();
-extern char *header_text();
-extern char *make_address();
-extern char *parse_address();
-extern char *rfc_cvt_date();
-extern char *rfc_date();
-extern char *rfc_message_id();
-
-extern int rfc_header(char *);
-extern int rfc_hdr_cmp(char *, char *);
-extern int rfc_month(char *);
-extern int rfc_weekday(char *);
-extern int rfc_zone(char *);
-extern int strcasecmp(char *, char *);
-
-extern void reorder_headers(vec *);
//GO.SYSIN DD headers.h
echo line.h
sed 's/.//' >line.h <<'//GO.SYSIN DD line.h'
-/*
- * Line i/o definitions.
- *
- * @(#)line.h 1.31
- */
-
-#define LBUFZ 1024
-
-typedef struct
-{
- int l_fd;
- char l_buf[LBUFZ];
- char *l_ptr;
- char *l_end;
- int l_flag;
-}
- lineio;
-
-#define LREAD 0x01 /* open for read */
-#define LWRITE 0x02 /* open for write */
-#define LEOF 0x04 /* eof seen on read */
-#define LCRLF 0x08 /* CR/LF terminated lines */
-#define LLBUF 0x10 /* line buffered output */
-#define LERROR 0x80 /* error on an i/o */
-
-extern lineio *lopen();
-extern int lclose();
-extern char *lread();
-extern char *lwrite();
//GO.SYSIN DD line.h
echo mace.h
sed 's/.//' >mace.h <<'//GO.SYSIN DD mace.h'
-/*
- * Mace global & system dependent definitions.
- *
- * Tune these to suit your system.
- *
- * Boyd Roberts 1989/1990
- *
- * Thanks to:
- *
- * John Mackin (alpha testing and suggestions)
- * Andrew Gollan (BSD mail-file locking code)
- *
- * @(#)mace.h 1.46
- */
-
-/*
- * Compiler options.
- */
-#define CC_VOID 1 /* 1 iff cc groks void */
-#define CC_UCHAR 1 /* 1 iff cc groks unsigned chars */
-#define CC_STATIC 1 /* 1 iff cc groks forward static declarations */
-
- /*
- * Environment variable names.
- */
-#define ENV_EDITOR "EDITOR"
-#define ENV_HOME "HOME"
-#define ENV_NAME "NAME"
-#define ENV_PAGER "PAGER"
-#define ENV_SHELL "SHELL"
-#define ENV_USER "LOGNAME"
-
-#define SPEC_CHAR '.'
-#define BOX_CHAR '+'
-#define SPEC_NAME(s) "."#s
-#define AUDIT SPEC_NAME(audit)
-#define BOX SPEC_NAME(box)
-#define MESSID SPEC_NAME(messid)
-#define CONFIG SPEC_NAME(config)
-#define PROTO SPEC_NAME(proto)
-#define MARK SPEC_NAME(mark)
-#define MACEDIR ".macedir"
-
-/*
- * String to insert before each line of a forwarded message
- */
-#define FWD_LEADER " "
-
-/*
- * Regular expression to match the name of the delivery agent.
- *
- * Used to discard the bogus From line added by "rmail".
- *
- * If your mail delivery doesn't exhibit this behaivour
- * define it to be NULLSTR.
- */
-#define DELIVERY_AGENT "Unknown"
-
-/*
- * The default system mail despooler. NULLSTR if there isn't one.
- */
-#define DESPOOLER "despool -delete"
-
-/*
- * The default system mail printer. Allows mail to be viewed
- * without deletion. NULLSTR if there isn't one.
- */
-#define PERUSER "despool"
-
-/*
- * The default system mail deliverer. NULLSTR if there isn't one.
- *
- * This must be set if RFC_DELIVERER is 1.
- */
-#define DELIVERER "/usr/ucblib/sendmail -t -oi -odb"
-
-#define RFC_DELIVERER 1 /* 1 iff the delivery agent can read the
- recipients from the message body */
-
-/*
- * If RFC_DELIVERER == 1 and you want the headers verified before
- * they are passed to the delivery agent. This is useful is you're
- * using sendmail and don't want anoying messages from `mailer-daemon'
- * about syntactically incorrect addresses.
- */
-#define RFC_VALIDATE 1
-
-#define ID_LEN 5
-
-#define NPIPES 64 /* == NOFILE */
-
-#define FS_BLKZ 8192 /* size of a filesystem block */
-
-#define CREAT_MODE 0666 /* file creation mode */
-#define MKDIR_MODE 0777 /* directory creation mode */
-
-#define LOCK_STR ".lck" /* file lock extension */
-
-#define BSD_STR 0 /* 1 iff str[r]chr == [r]index */
-#define BSD_DIR 0 /* 1 iff 4.2BSD directories */
-#define BSD_MKDIR 1 /* 1 iff 4.2BSD mkdir() call */
-
-#define STR_CSPN 1 /* 1 iff you have strcspn() */
-
-#define DIRECTORY_3 1 /* 1 iff you have the directory(3) routines */
-#define V9_DIRECTORY_3 0 /* 1 iff you have the V9 directory(3) routines */
-#define DEC_DIRECTORY_3 1 /* 1 iff you have old (ULTRIX) directory(3) */
-
-#define USG_MAIL 1 /* 1 iff mail file is locked by USG .lock */
-#define BSD_MAIL 0 /* 1 iff mail file is locked by flock(2) */
-
-#define USG_UNAME 1 /* 1 iff you have uname(2) */
-#define BSD_GETHOSTNAME 0 /* 1 iff you have gethostname(2) */
-
-#define SIG_RET void /* signal(2) returns int/void? */
-
-/*
- * If the previous two are both 0 then specify a command
- * that writes the system's nodename to standard output.
- *
- * Set to NULLSTR otherwise.
- */
-#define HOST_CMD NULLSTR
-
-/*
- * Specify the command that writes the system's domain
- * name to standard output.
- *
- * Set to NULLSTR if you intend to specify it in "config".
- */
-#define DOMAIN_CMD NULLSTR
-
-/*
- * The negation character used by your shell to negate a character
- * class in a metacharacter expansion (ie [!a-z]*). Usually '!',
- * but some shells use '^'.
- */
-#define SH_META_NOT '!'
-
-#define SYSERROR (-1) /* system call error return */
-
-/*
- * Default commands; tailor them to suit.
- */
-#define DEF_PAGER "cat"
-#define DEF_EDITOR "ed"
-#define DEF_SHELL "/bin/sh" /* full pathname required */
-
-#define COM_STR "com" /* compose message */
-#define COP_STR "cop" /* front end to MCP_STR */
-#define DEL_STR "del" /* front end to MDA_STR */
-#define FWD_STR "fwd" /* forward message */
-#define LNK_STR "lnk" /* front end to MLN_STR */
-#define MAM_STR "mam" /* mace add message (from a file) */
-#define MED_STR "med" /* message edit */
-#define MOV_STR "mov" /* front end to MAD_STR */
-#define MSG_STR "msg" /* show message */
-#define REM_STR "rem" /* remove message */
-#define REP_STR "rep" /* reply to a message */
-
-#define MAD_STR "mad" /* Message add (to a box) */
-#define MCP_STR "mcp" /* Message copy (to a box) */
-#define MLN_STR "mln" /* Message link (to a box) */
-#define MDA_STR "mda" /* Message delivery agent */
-#define MKDIR_STR "mkdir" /* Make directory */
-#define RMDIR_STR "rmdir" /* Remove directory */
-
-#define O_RD 0 /* open mode for read */
-#define O_WR 1 /* open mode for write */
-#define O_RW 2 /* open mode for read/write */
-
-#define A_RD 4 /* access mode for read */
-
-#if BSD_STR
-#define strchr index
-#define strrchr rindex
-#endif BSD_STR
-
-#if CC_VOID == 0
-#define void int
-#endif CC_VOID == 0
-
-#if CC_STATIC == 0
-#define STATIC extern
-#endif CC_STATIC == 0
-
-#if CC_UCHAR == 0
-#define CHARBITS 0377
-#endif CC_UCHAR == 0
-
-#if STR_CSPN == 0
-#define STRCSPN 1
-#endif STR_CSPN == 0
-
-#if V9_DIRECTORY_3
-#define DIRECTORY_3 1
-#endif V9_DIRECTORY_3
-
-#define NULLBOX (mbox *)0
-#define NULLSTR (char *)0
-#define NULLMSG ((msg_idx)-1)
-
-typedef long msg_idx;
-
-typedef struct
-{
- char *m_name;
- char *m_path;
- msg_idx m_count;
- msg_idx m_current;
- char *m_messid;
- char **m_list;
-}
- mbox;
-
-typedef struct
-{
- msg_idx v_count;
- msg_idx v_size;
- msg_idx v_incr;
- char **v_list;
-}
- vec;
-
-extern char *my_name;
-extern char *re_error;
-
-extern char *basename();
-extern char *check_box();
-extern char *concat();
-extern char *concat3();
-extern char *create_box();
-extern char *curr_box();
-extern char *curr_in_box();
-extern char *defenv();
-extern char *domain();
-extern char *host();
-extern char *mace_dir();
-extern char *mess_to_path();
-extern char *newstr();
-extern char *nextid();
-extern char *read_file();
-extern char *readpass(char *);
-extern char *salloc();
-extern char *splice();
-extern char *srealloc();
-extern char *strstr();
-extern char *sysmess();
-extern char *user_id();
-extern char *user_name();
-extern char *vec_str();
-extern char *vec_cat();
-
-extern char **mess_range();
-extern char **read_dir();
-
-extern int args_to_messages();
-extern int delete_box();
-extern int lock();
-extern int mail_check();
-extern int mail_locked();
-extern int mail_lock();
-extern int mail_unlock();
-extern int pipe_exec();
-extern int pipe_open();
-extern int pipe_close();
-extern int run();
-extern int set_box();
-extern int set_current();
-extern int unlock();
-extern int valid_id();
-
-extern mbox *read_box();
-
-extern msg_idx mess_alias();
-extern msg_idx mess_index();
-
-extern void bcopy();
-extern void could_not();
-extern void fatal();
-extern void free_dir();
-extern void free_box();
-extern void free_mess();
-extern void name();
-extern void path_to_mess();
-extern void print_summary();
-extern void vec_free();
-extern void vec_init();
-extern void would_not();
//GO.SYSIN DD mace.h
echo message.h
sed 's/.//' >message.h <<'//GO.SYSIN DD message.h'
-/*
- * Internal message format.
- *
- * @(#)message.h 1.33
- */
-
-typedef struct
-{
- char *ms_path;
- char *ms_messid;
- vec ms_headers;
- long ms_size;
- int ms_copies;
- int ms_state;
-}
- message;
-
-#define NULLMESS (message *)0
-
-extern int set_state(char *, int);
-extern int clear_state(char *, int);
-
-extern message *read_mess(mbox *, char *);
-extern message *parse_fd(int, lineio *);
-extern message *parse_file(char *, lineio *);
-
-#define MESG_SENT S_IEXEC
-#define MESG_COMP (S_IEXEC >> 3)
-#define MESG_MARK (S_IEXEC >> 6)
//GO.SYSIN DD message.h
echo pop.h
sed 's/.//' >pop.h <<'//GO.SYSIN DD pop.h'
-/*
- * @(#)pop.h 1.2
- *
- * POP 3 (RFC 1225) definitions.
- */
-
-/*
- * Maximum length of a POP password. Must be less that PIPSIZ.
- */
-#define POP_PASS_LEN 1024
-
-/*
- * POP server
- */
-#define POP_SERVICE "pop3"
-#define POP_PROTOCOL "tcp"
-#define POP_PORT 110
-
-/*
- * Commands
- */
-#define POP_CMD_DELE "DELE"
-#define POP_CMD_LAST "LAST"
-#define POP_CMD_LIST "LIST"
-#define POP_CMD_NOOP "NOOP"
-#define POP_CMD_PASS "PASS"
-#define POP_CMD_QUIT "QUIT"
-#define POP_CMD_RETR "RETR"
-#define POP_CMD_RSET "RSET"
-#define POP_CMD_STAT "STAT"
-#define POP_CMD_USER "USER"
-
-#define POP_REP_OK "+OK"
-#define POP_REP_ERR "-ERR"
-#define POP_REP_TCHAR '.'
//GO.SYSIN DD pop.h
echo regexp.h
sed 's/.//' >regexp.h <<'//GO.SYSIN DD regexp.h'
-/*
- * Definitions etc. for regexp(3) routines.
- *
- * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof],
- * not the System V one.
- *
- * Snarfed to be part of "mace" but not modified save
- * for the odd include & sccsid.
- * -- Boyd Roberts
- * May '89
- *
- * @(#)regexp.h 1.6
- */
-#define NSUBEXP 10
-typedef struct regexp {
- char *startp[NSUBEXP];
- char *endp[NSUBEXP];
- char regstart; /* Internal use only. */
- char reganch; /* Internal use only. */
- char *regmust; /* Internal use only. */
- int regmlen; /* Internal use only. */
- char program[1]; /* Unwarranted chumminess with compiler. */
-} regexp;
-
-extern regexp *regcomp();
-extern int regexec();
-extern void regsub();
-extern void regerror();
//GO.SYSIN DD regexp.h
echo regmagic.h
sed 's/.//' >regmagic.h <<'//GO.SYSIN DD regmagic.h'
-/*
- * The first byte of the regexp internal "program" is actually this magic
- * number; the start node begins in the second byte.
- *
- * Snarfed to be part of "mace" but not modified save
- * for the odd include & sccsid.
- * -- Boyd Roberts
- * May '89
- *
- * @(#)regmagic.h 1.6
- */
-#define MAGIC 0234
//GO.SYSIN DD regmagic.h
echo tty.h
sed 's/.//' >tty.h <<'//GO.SYSIN DD tty.h'
-/*
- * @(#)tty.h 1.1
- *
- * Definitions for horrible system dependent tty routines.
- */
-
-extern int ttyecho(int, int);
-extern int ttyechoing(int);
//GO.SYSIN DD tty.h
echo addr.y
sed 's/.//' >addr.y <<'//GO.SYSIN DD addr.y'
-%{
-/*
- * RFC 822 address parsing routines.
- */
-
-#ifndef lint
-static char sccsid[] = "%W%";
-#endif lint
-
-#include "mace.h"
-#include "headers.h"
-#include "flex.h"
-#include "addr.h"
-#include <sys/types.h>
-#include <time.h>
-
-#define panic(s) abort(s)
-#define nomem() abort("nomem")
-
-static flex f = { NULLSTR, NULLSTR, NULLSTR, };
-
-/* $Log: address.y,v $
- * Revision 1.5 88/12/29 00:44:14 john
- * Moved to MIPS
- *
- * Revision 1.5 88/12/29 00:44:14 john
- * Move eatcomment() into address.y where it belongs, and fix it to
- * handle \-quoting of parens inside comments.
- *
- * Revision 1.4 88/12/28 22:13:40 john
- * Fix \ quoting within quoted-strings and domain-literals (it was
- * missing). Also fix missing cases for ']' as an atom.
- *
- * Revision 1.3 88/12/28 00:14:03 john
- * Fix lexical analysis bug, parentheses were not being correctly
- * recognized as atoms.
- *
- * Revision 1.2 88/10/30 07:46:22 john
- * Improve compliance of grammar to RFC822:
- * - insist on a domain at the end of a source-route
- * Change makeaddress() to do the right thing with a
- * source-routed address (i.e., make it an actual textual
- * representation of the source-routed address).
- * Fix bug in putdom.
- *
- * Revision 1.1 88/10/26 09:54:04 john
- * Initial revision
- *
- */
-
-static char RCSid[] =
- "$Header: address.y,v 1.5 88/12/29 00:44:14 john Exp $";
-
-typedef struct token token;
-
-struct token
-{
- char *name;
- int token;
-};
-
-static char *errstr;
-static char *comstr;
-static char *cp;
-static char *savecp;
-static char *saveline;
-static flex errbuf = { NULLSTR, NULLSTR, NULLSTR };
-static flex combuf = { NULLSTR, NULLSTR, NULLSTR };
-static int iseol;
-
-static char *text;
-Addr *adrlist;
-Addr *errlist;
-%}
-
-%union {
- char yChar;
- char *yString;
- Dom *yDom;
- Addr *yAddr;
- time_t yTime;
- int yInt;
-}
-
-%token EOL ATOM LIT_DOMAIN QUOTED_STRING
-%token DATE FROM TO CC BCC SUBJECT
-%token RECEIVED RFROM BY VIA WITH ID FOR
-
-%type <yString> word domain_ref sub_domain local_part phrase
-%type <yDom> domain route_list route
-%type <yAddr> addr_spec non_local_addr_spec route_addr mailbox mbox_list group address msg_id
-%type <yTime> date_header date_time
-%type <yInt> zone weekday month
-
-%start rfc822
-
-%%
-rfc822 :
- date_header
- |
- addr_header ':' addr_list
- |
- received;
-
-addr_header : FROM | TO | CC | BCC;
-
-date_header : DATE ':' date_time
- {
- $$ = $3;
- };
-
-date_time : weekday date time
- {
- struct tm t;
- };
-
-weekday :
- /* null
- |
- {
- $$ = 0
- } */
- ATOM ','
- {
- $$ = 0;
- };
-
-date : ATOM month ATOM
- {
- };
-
-month : ATOM
- {
- $$ = 0;
- };
-
-time : hour zone
- {
- };
-
-home : ATOM ':' ATOM seconds
-
-seconds : /* null */
- |
- ':' ATOM
- {
- };
-
-zone : ATOM
- {
- $$ = 0;
- }
- |
- '+' ATOM
- {
- $$ = 0;
- }
- |
- '-' ATOM
- {
- $$ = 0;
- };
-
-addr_list: addr_lel
- | addr_list addr_lel
- ;
-
-addr_lel: address EOL {
- $1->comment = comstr;
- $1->error = errstr;
- comstr = NULL;
- errstr = NULL;
- appAddr(&adrlist, $1);
- }
- | address ',' {
- $1->comment = comstr;
- $1->error = errstr;
- comstr = NULL;
- errstr = NULL;
- appAddr(&adrlist, $1);
- }
- | error {
- register Addr *ap;
-
- ap = newAddr();
- if (savecp > saveline) {
- flex_str(&errbuf, " after \"");
- flex_nstr(&errbuf, saveline, savecp - saveline);
- flex_char(&errbuf, '"');
- if (cp && *cp) {
- flex_str(&errbuf, ", before \"");
- flex_str(&errbuf, cp);
- flex_char(&errbuf, '"');
- }
- }
- else if (cp && *cp) {
- flex_str(&errbuf, " before \"");
- flex_str(&errbuf, cp);
- flex_char(&errbuf, '"');
- }
-
- if (errbuf.f_ptr != errbuf.f_str) {
- flex_char(&errbuf, '\0');
- errstr = newstring2(errstr, errbuf.f_str);
- flex_end(&errbuf);
- }
-
- ap->error = errstr;
- errstr = NULL;
- comstr = NULL;
- appAddr(&errlist, ap);
- }
- ;
-
-address: mailbox {
- $$ = $1;
- }
- | group {
- $$ = $1;
- }
- ;
-
-group : phrase ':' mbox_list ';' {
- register Addr *a;
-
- for (a = $3; a; a = a->next)
- a->group = $1;
- $$ = $3;
- }
- ;
-
-mbox_list: mailbox {
- $$ = $1;
- }
- | mbox_list ',' mailbox {
- $3->comment = comstr;
- $3->error = errstr;
- comstr = NULL;
- errstr = NULL;
- appAddr(&($1), $3);
- $$ = $1;
- }
- ;
-
-mailbox: addr_spec {
- $$ = $1;
- }
- | route_addr {
- $$ = $1;
- }
- | phrase route_addr {
- $2->name = $1;
- $$ = $2;
- }
- ;
-
-phrase : word {
- $$ = $1;
- }
- | phrase word {
- $$ = newstring3($1, " ", $2);
- free($1);
- free($2);
- }
- ;
-
-route_addr: '<' addr_spec '>' {
- $$ = $2;
- }
- | '<' route non_local_addr_spec '>' {
- prepDom(&($3->route), $2);
- $$ = $3;
- }
- ;
-
-route : route_list ':' {
- $$ = $1;
- }
- ;
-
-route_list: '@' domain {
- $$ = $2;
- }
- | route_list ',' '@' domain {
- appDom(&($1), $4);
- $$ = $1;
- }
- ;
-
-addr_spec: non_local_addr_spec
- | local_part {
- register Addr *ap;
-
- $$ = ap = newAddr();
- ap->localp = $1;
- ap->destdom = NULL;
- }
- ;
-
-non_local_addr_spec: local_part '@' domain {
- register Addr *ap;
-
- $$ = ap = newAddr();
- ap->localp = $1;
- ap->destdom = $3;
- ap->route = $3;
- }
- ;
-
-local_part: word {
- $$ = $1;
- }
- | local_part '.' word {
- $$ = newstring3($1, ".", $3);
- free($1);
- free($3);
- }
- | local_part '%' word {
- $$ = newstring3($1, "%", $3);
- free($1);
- free($3);
- }
- ;
-
-domain : sub_domain {
- register Dom *dp;
-
- dp = newDom();
- dp->sub[0] = $1;
- dp->top = dp->sub;
- $$ = dp;
- }
- | domain '.' sub_domain {
- ($1->top)++;
- *($1->top) = $3;
- $$ = $1;
- }
- ;
-
-sub_domain: domain_ref {
- $$ = $1;
- }
- | LIT_DOMAIN {
- $$ = yylval.yString;
- }
- ;
-
-domain_ref: ATOM {
- $$ = yyval.yString;
- }
- ;
-
-word : ATOM {
- $$ = yylval.yString;
- }
- | QUOTED_STRING {
- $$ = yylval.yString;
- }
- ;
-
-day :
- |
- ATOM ','
- {
- }
- ;
-
-hour :
- ATOM ':' ATOM
- {
- }
- |
- ATOM ':' ATOM ':' ATOM
- {
- }
- ;
-
-zone :
- ATOM
- {
- }
- |
- ATOM
- {
- }
- |
- '+' ATOM
- {
- }
- |
- '-' ATOM
- {
- }
- ;
-
-msg_id : '<' addr_spec '>'
- {
-printf("msg_id %s\n", make_address($2));
- $$ = $2;
- }
- ;
-
-rfrom : /* null */
- |
- FROM domain
- {
-Addr a;
-a.localp = "";
-a.next = 0;
-a.route = $2;
-printf("from %s\n", make_address(&a));
- }
- ;
-
-by : /* null */
- |
- BY domain
- {
-Addr a;
-a.localp = "";
-a.next = 0;
-a.route = $2;
-printf("by %s\n", make_address(&a));
- }
- ;
-
-via : /* null */
- |
- VIA ATOM
- {
-printf("via '%s'\n", yylval.yString);
- }
- ;
-
-with : /* null */
- |
- WITH ATOM
- {
-printf("with '%s'\n", yylval.yString);
- }
- ;
-
-id : /* null */
- |
- ID '<' msg_id '>'
- {
-Addr *a;
-a = $3;
-printf("id %s\n", make_address(a));
- }
- |
- ID ATOM
- {
-printf("id %s\n", yylval.yString);
- }
- ;
-
-for : /* null */
- |
- FOR addr_spec
- {
-Addr *a;
-a = $2;
-printf("for %s\n", make_address(a));
- }
- |
- FOR '<' addr_spec '>'
- {
-Addr *a;
-a = $3;
-printf("for %s\n", make_address(a));
- }
- ;
-
-
-received: RECEIVED ':' rfrom by via with id for ';' EOL
- {
- }
- ;
-%%
-
-#include <stdio.h>
-#include <ctype.h>
-
-#define ERROR -2
-
-enum
-{
- Header,
- Colon,
- Body,
-};
-
-int where;
-
-static token headers[] =
-{
- { "From", FROM, },
- { "To", TO, },
- { "Cc", CC, },
- { "Bcc", BCC, },
- { "Date", DATE, },
- { "Subject", SUBJECT, },
- { NULLSTR, 0, },};
-
-static token received[] =
-{
- { "from", FROM, },
- { "by", BY, },
- { "via", VIA, },
- { "with", WITH, },
- { "id", ID, },
- { "for", FOR, },
- { NULLSTR, 0, },
-};
-
-int
-tokatom(token *t, char *s)
-{
- while (t->name != 0)
- {
- if (strcasecmp(t->name, s) == 0)
- return t->token;
-
- t++;
- }
-
- return ATOM;
-}
-
-static char *
-newstring3(a, b, c)
- char *a;
- char *b;
- char *c;
-{
- char *p;
- char *q;
- int i;
-
- i = strlen(a) + strlen(b) + strlen(c) + 1;
- if ((p = salloc((MALLOCT)i)) == NULL)
- nomem();
- q = p + strlen(strcpy(p, a));
- q += strlen(strcpy(q, b));
- Strcpy(q, c);
- return(p);
-}
-
-
-static char *
-newstring2(a, b)
- char *a;
- char *b;
-{
- char *p;
- int i;
-
- if (a == (char *)0)
- a = "";
- i = strlen(a) + strlen(b) + 1;
- if ((p = salloc((MALLOCT)i)) == NULL)
- nomem();
- Strcpy(p, a);
- Strcat(p, b);
- return(p);
-}
-
-/*
- * <mess>: [ "<what>" ] unexpected [ <tail> ]
- */
-static void
-unexpected(mess, what, tail)
-char *mess;
-char *what;
-char *tail;
-{
- flex_str(&errbuf, mess);
- flex_str(&errbuf, ": ");
-
- if (what != NULLSTR)
- {
- flex_char(&errbuf, '"');
- flex_str(&errbuf, what);
- flex_str(&errbuf, "\" ");
- }
-
- flex_str(&errbuf, "unexpected");
-
- if (tail != NULLSTR)
- {
- flex_char(&errbuf, ' ');
- flex_str(&errbuf, tail);
- }
-
- flex_char(&errbuf, '\0');
-}
-
-static void
-yyerror(s)
- char *s;
-{
- static char c[2] = { '\0', '\0' };
-
- switch(yychar) {
- default:
- c[0] = yylval.yChar;
- unexpected(s, c, NULLSTR);
- errstr = newstring2(errstr, errbuf.f_str);
- break;
- case LIT_DOMAIN:
- case QUOTED_STRING:
- case ATOM:
- unexpected(s, yylval.yString, NULLSTR);
- errstr = newstring2(errstr, errbuf.f_str);
- break;
- case EOL:
- case 0: /* EOF */
- unexpected(s, NULLSTR, "end-of-header");
- errstr = newstring2(errstr, errbuf.f_str);
- break;
- }
- flex_end(&errbuf);
-}
-
-
-parseit(char *line)
-{
-extern int yydebug;
- saveline = cp = text = line;
- adrlist = NULL;
- errlist = NULL;
- if (combuf.f_str == NULLSTR)
- flex_init(&combuf);
- flex_end(&combuf);
- if (errbuf.f_str == NULLSTR)
- flex_init(&errbuf);
- flex_end(&errbuf);
-
- if (!rfc_header(line))
- {
- Addr *ap;
-
- ap = newAddr();
- errstr = newstring2("not a header field", errbuf.f_str);
- ap->error = errstr;
- comstr = NULL;
- errstr = NULL;
- appAddr(&adrlist, ap);
- return;
- }
-
- where = Header;
-yydebug = 0;
- (void)yyparse();
-}
-
-char *
-eatcomment(s)
-register char *s;
-{
- register int parencount;
-
- parencount = 0;
- for (;;) {
- if (*s == '\\') { /* quoted-pair */
- s++;
- if (*s == '\0')
- return ((char *)0);
- s++;
- if (*s == '\0')
- return ((char *)0);
- continue;
- }
- if (*s == '(')
- parencount++;
- else if (*s == ')')
- parencount--;
-
- if (parencount == 0)
- return (++s);
- else if (parencount < 0)
- panic("eatcomment botch");
-
- if (*++s == '\0')
- return ((char *)0);
- }
-}
-
-
-/*
- * Case independent strcmp().
- */
-static int
-strcasecmp(char *s1, char *s2)
-{
- while (*s1 != '\0')
- {
- int c1;
- int c2;
-
- if (*s1 != *s2 && (c1 = tolower(*s1)) != (c2 = tolower(*s2)))
- return c1 < c2 ? -1 : 1;
-
- s1++;
- s2++;
- }
-
- return 0;
-}
-
-yylex()
-{
- char *p;
-
- savecp = cp;
- while (isascii(*cp) && (isspace(*cp) || (*cp == '('))) {
- if (*cp == '(') {
- p = eatcomment(cp);
- if (p == (char *)0)
- return (EOF);
- flex_nstr(&combuf, cp + 1, (p - 2) - cp);
- flex_char(&combuf, '\0');
- if (comstr == NULL) {
- if ((comstr = salloc((MALLOCT)(strlen(combuf.f_str) + 1))) == NULL)
- nomem();
- Strcpy(comstr, combuf.f_str);
- }
- else
- comstr = newstring3(comstr, ", ", combuf.f_str);
- flex_end(&combuf);
- cp = p;
- }
- else
- cp++;
- }
-
- if (!isascii(*cp))
- return(ERROR);
-
- switch (*cp) {
- case '\0':
- if (iseol) {
- iseol = 0;
- return(EOF);
- }
- iseol = 1;
- return(EOL);
- case ':':
- if (where == Colon)
- where = Body;
- case ',':
- case ';':
- case '.':
- case '@':
- case '%':
- case '<':
- case '>':
- case '(':
- case ')':
- case ']':
- yylval.yChar = *cp;
- return(*cp++);
- case '[': /* LIT_DOMAIN */
- for (p = cp + 1; *p && *p != ']'; ) {
- if (*p == '\\') {
- p++;
- if (*p == '\0')
- return(EOF);
- }
- p++;
- }
- if (*p == '\0')
- return(EOF);
- if ((yylval.yString = salloc((MALLOCT)(p - cp + 2))) == NULL)
- nomem();
- Strncpy(yylval.yString, cp, p - cp + 1);
- yylval.yString[p - cp + 1] = '\0';
- cp = ++p;
- return(LIT_DOMAIN);
- case '"': /* QUOTED_STRING */
- for (p = cp + 1; *p && *p != '"'; ) {
- if (*p == '\\') {
- p++;
- if (*p == '\0')
- return(EOF);
- }
- p++;
- }
- if (*p == '\0')
- return(EOF);
- if ((yylval.yString = salloc((MALLOCT)(p - cp))) == NULL)
- nomem();
- Strncpy(yylval.yString, cp + 1, p - cp);
- yylval.yString[p - cp - 1] = '\0';
- cp = ++p;
- return(QUOTED_STRING);
- }
-
- for (p = cp; ; p++)
- switch (*p) {
- case ',':
- case ':':
- case ';':
- case '.':
- case '@':
- case '%':
- case '<':
- case '>':
- case '(':
- case ')':
- case '[':
- case ']':
- case '"':
- case '\0':
- goto out;
- default:
- if (isspace(*p))
- goto out;
- }
-out:
- if ((yylval.yString = salloc((MALLOCT)(p - cp + 1))) == NULL)
- nomem();
- Strncpy(yylval.yString, cp, p - cp);
- yylval.yString[p - cp] = '\0';
- cp = p;
-
-printf("ATOM '%s'\n", yylval.yString);
- switch (where)
- {
- case Header:
- where = Colon;
- return tokatom(headers, yylval.yString);
-
- case Colon:
- case Body:
- return ATOM;
- break;
-
- default:
- panic("header field state?");
- }
-}
-
-/*
-** Create and initialize a new address.
-*/
-Addr *
-newAddr()
-{
- register Addr *ap;
-
- if ((ap = (Addr *)salloc((MALLOCT)sizeof *ap)) == NULL)
- nomem();
- memset((char *)ap, '\0', sizeof *ap);
- return(ap);
-}
-
-
-/*
-** Append addresslist "addr" to addresslist "head".
-*/
-appAddr(head, addr)
- Addr **head;
- Addr *addr;
-{
- register Addr *ap;
- register char *p;
- register int i;
-
- if (*head) {
- for (ap = *head; ap->next; ap = ap->next)
- ;
- ap->next = addr;
- }
- else
- *head = addr;
-
- if (head == &adrlist)
- {
- while (isspace(*text))
- text++;
-
- if (*(p = cp) != '\0')
- {
- p--;
-
- if (isspace(p[-1]))
- {
- p--;
-
- while (isspace(*p))
- p--;
-
- p++;
- }
- }
-
- if ((addr->text = salloc((MALLOCT)(p - text + 1))) == NULLSTR)
- nomem();
-
- strncpy(addr->text, text, i = p - text);
- addr->text[i] = '\0';
-
- text = cp;
- }
- else
- addr->text = NULLSTR;
-}
-
-
-
-/*
-** Create and initialize a new domain.
-*/
-Dom *
-newDom()
-{
- register Dom *dp;
-
- if ((dp = (Dom *)salloc((MALLOCT)sizeof *dp)) == NULL)
- nomem();
- memset((char *)dp, '\0', sizeof *dp);
- dp->top = dp->sub;
- return(dp);
-}
-
-
-/*
-** Append domainlist "dom" to domainlist "head".
-*/
-appDom(head, dom)
- Dom **head;
- Dom *dom;
-{
- register Dom *dp;
-
- if (*head) {
- for (dp = *head; dp->next; dp = dp->next)
- ;
- dp->next = dom;
- }
- else
- *head = dom;
-}
-
-
-/*
-** Prepend domainlist "dom" before domainlist "head".
-*/
-prepDom(head, dom)
- Dom **head;
- Dom *dom;
-{
- register Dom *dp;
-
- for (dp = dom; dp->next; dp = dp->next)
- ;
- dp->next = *head;
- *head = dom;
-}
-
-static void
-putdom(d)
-register Dom *d;
-{
- register char **p;
-
- for (p = d->sub; p != d->top; p++)
- {
- flex_str(&f, *p);
- flex_char(&f, RFC_SPEC_DOT);
- }
-
- flex_str(&f, *p);
-}
-
-/*
- * Take an Addr struct and return a textual representation that
- * a delivery agent can use to deliver the message.
- */
-char *
-make_address(a)
-register Addr *a;
-{
- register Dom *d;
- register char *p;
-
- if (f.f_str == NULLSTR)
- flex_init(&f);
-
- d = a->route;
-
- while (d != (Dom *)0 && d->next != (Dom *)0)
- {
- /* source route */
-
- flex_char(&f, RFC_SPEC_AT);
- putdom(d);
- flex_char(&f, d->next->next ? RFC_SPEC_COMMA : RFC_SPEC_COLON);
- d = d->next;
- }
-
- flex_str(&f, a->localp);
-
- if (d != (Dom *)0)
- {
- flex_char(&f, RFC_SPEC_AT);
- putdom(d);
- }
-
- flex_char(&f, '\0');
- p = newstr(f.f_str);
- flex_end(&f);
-
- return p;
-}
-
-static char *
-cleanup(Addr **ap)
-{
- Addr *a;
-
- if (errlist != (Addr *)0)
- {
- for (a = errlist; a != (Addr *)0; a = a->next)
- {
- if (a->error != NULLSTR)
- return a->error;
- }
-
- abort("make_address");
- /* NOTREACHED */
- }
-
- for (a = adrlist; a != (Addr *)0; a = a->next)
- {
- if (a->localp == (char *)0 || a->localp[0] == '\0')
- return "null local-part in address";
- }
-
- *ap = adrlist;
-
- return NULLSTR;
-}
-
-/*
- * Parse a textual address list and return it as a list of Addr structs.
- *
- * Returns NULLSTR for ok; otherwise an error string.
- */
-char *
-parse_address(ap, s)
-Addr **ap;
-char *s;
-{
- parseit(s);
-
- return cleanup(ap);
-}
-
-/*
- * Parse a Received: header and return it as a list of Addr structs.
- *
- * Returns NULLSTR for ok; otherwise an error string.
- */
-char *
-parse_received(Addr **ap, char *s)
-{
- parseit(s);
-
- return cleanup(ap);
-}
//GO.SYSIN DD addr.y
echo aka.c
sed 's/.//' >aka.c <<'//GO.SYSIN DD aka.c'
-/*
- * Message aliases & aka's.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)aka.c 1.30";
-#endif lint
-
-#include "mace.h"
-
-#define ABBREV_CHAR '|'
-
-typedef struct
-{
- char *a_str;
- msg_idx (*a_func)();
-}
- abbrev;
-
-static msg_idx first_mess();
-static msg_idx last_mess();
-static msg_idx current_mess();
-static msg_idx next_mess();
-static msg_idx previous_mess();
-
-static abbrev mess_abbrev[] =
-{
- { "firs|t", first_mess },
- { "last", last_mess },
- { "curr|ent", current_mess },
- { "next", next_mess },
- { "prev|ious", previous_mess },
- { NULLSTR, },
-};
-
-static msg_idx
-first_mess(m)
-register mbox *m;
-{
- return m->m_count > 0 ? 0 : NULLMSG;
-}
-
-static msg_idx
-last_mess(m)
-register mbox *m;
-{
- return m->m_count > 0 ? m->m_count - 1 : NULLMSG;
-}
-
-static msg_idx
-current_mess(m)
-register mbox *m;
-{
- return m->m_current;
-}
-
-static msg_idx
-next_mess(m)
-register mbox *m;
-{
- register msg_idx i;
- register char *s;
-
- if ((i = m->m_current) != NULLMSG)
- return ++i == m->m_count ? NULLMSG : i;
-
- if ((s = m->m_messid) == NULLSTR || m->m_count == 0)
- return NULLMSG;
-
- if (strcmp(s, m->m_list[0]) < 0)
- return 0;
-
- if (strcmp(s, m->m_list[m->m_count - 1]) > 0)
- return NULLMSG;
-
- for (i = 0; i < m->m_count; i++)
- {
- if (strcmp(s, m->m_list[i]) > 0)
- continue;
-
- return i;
- }
-
- return NULLMSG;
-}
-
-static msg_idx
-previous_mess(m)
-register mbox *m;
-{
- register msg_idx i;
- register char *s;
-
- if ((i = m->m_current) != NULLMSG)
- return --i < 0 ? NULLMSG : i;
-
- if ((s = m->m_messid) == NULLSTR || m->m_count == 0)
- return NULLMSG;
-
- if (strcmp(s, m->m_list[0]) < 0)
- return NULLMSG;
-
- if (strcmp(s, m->m_list[m->m_count - 1]) > 0)
- return m->m_count - 1;
-
- for (i = m->m_count - 1; i >= 0; i--)
- {
- if (strcmp(s, m->m_list[i]) < 0)
- continue;
-
- return i;
- }
-
- return NULLMSG;
-}
-
-msg_idx
-mess_alias(m, s)
-mbox *m;
-char *s;
-{
- register char *p;
- register abbrev *ap;
-
- for (p = s; *p != '\0'; p++)
- {
- if (*p == ABBREV_CHAR)
- return NULLMSG;
- }
-
- for (ap = mess_abbrev; ap->a_str != NULLSTR; ap++)
- {
- register char *q;
- int seen_bar;
-
- p = s;
- q = ap->a_str;
- seen_bar = 0;
-
- for (;;)
- {
- if (!seen_bar)
- seen_bar = *q == '|';
-
- if (*p == '\0')
- {
- if (seen_bar || *q == '\0')
- return (*ap->a_func)(m);
-
- break;
- }
-
- if (*p == *q)
- {
- p++;
- q++;
- continue;
- }
-
- if (*q++ != '|')
- break;
- }
- }
-
- return NULLMSG;
-}
-
-char **
-mess_range(m, from, to)
-mbox *m;
-msg_idx from;
-msg_idx to;
-{
- register char **n;
- register msg_idx i;
- register char **v;
-
- if ((i = to - from) < 0)
- i = -i;
-
- i++;
-
- v = n = (char **)salloc((int)((i + 1) * sizeof(char *)));
-
- while (i-- > 0)
- {
- /* I could use a ?: here, but the MIPS doesn't like it */
-
- if (from > to)
- *n++ = newstr(m->m_list[from--]);
- else
- *n++ = newstr(m->m_list[from++]);
- }
-
- *n = NULLSTR;
-
- return v;
-}
//GO.SYSIN DD aka.c
echo args.c
sed 's/.//' >args.c <<'//GO.SYSIN DD args.c'
-/*
- * Message argument list processing.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)args.c 1.4";
-#endif lint
-
-#include "mace.h"
-#include "line.h"
-#include <stdio.h>
-
-#define ALL_NAME "all"
-#define ALL_RANGE "first-last"
-
-static char *metas = "?*[]"; /* sh(1) metacharacters */
-
-/*
- * Shell metacharacter matcher.
- */
-static int
-match(str, pat)
-register char *str;
-register char *pat;
-{
- register char c;
-
- switch (c = *pat++)
- {
- case '?':
- return match(++str, pat);
-
- case '*':
- while (*pat == '*')
- pat++;
-
- if (*pat == '\0')
- return 1;
-
- while (*++str != '\0')
- {
- if (match(str, pat))
- return 1;
- }
-
- return 0;
-
- case '[':
- {
- int not;
- int hit;
- int range;
- char pc;
-
- hit = 0;
- not = 0;
- pc = 0;
-
- if (*pat == SH_META_NOT)
- {
- not = 1;
- hit = 1;
- pat++;
- }
-
- while ((c = *pat++) != '\0')
- {
- if (c == ']')
- return hit ? match(++str, pat) : 0;
-
- if (c == '-')
- {
- if ((range = *pat++) == '\0' || range == ']')
- return 0;
-
- if (*str >= pc && *str <= range)
- {
- if (not)
- return 0;
-
- hit = 1;
- }
- }
- else
- {
- pc = c;
-
- if (*str == c)
- {
- if (not)
- return 0;
-
- hit = 1;
- }
- }
- }
-
- return 0;
- }
-
- default:
- if (c == *str)
- {
- if (c == '\0')
- return 1;
-
- return match(++str, pat);
- }
-
- return 0;
- }
-}
-
-/*
- * Turn a shell metacharacter specification into messages id's.
- */
-static void
-metas_to_messages(mb, pattern, vp)
-register mbox *mb;
-char *pattern;
-register vec *vp;
-{
- register msg_idx i;
-
- for (i = 0; i < mb->m_count; i++)
- {
- if (match(mb->m_list[i], pattern))
- vec_str(vp, mess_to_path(mb, mb->m_list[i]));
- }
-}
-
-/*
- * Find a messages' index into a mailbox.
- */
-static msg_idx
-find_msg(m, s)
-register mbox *m;
-register char *s;
-{
- register msg_idx i;
-
- if (*s == '\0')
- {
- if (m->m_current == NULLMSG)
- fprintf(stderr, "%s: No current message in \"%s\".\n", my_name, m->m_name);
-
- return m->m_current;
- }
-
- if ((i = valid_id(s) ? mess_index(m, s) : mess_alias(m, s)) == NULLMSG)
- fprintf(stderr, "%s: No such message qualifier as \"%s\".\n", my_name, s);
-
- return i;
-}
-
-/*
- * Take a command line and interpret it into messages.
- *
- * [ [+]box ] [ messages ] ...
- */
-int
-args_to_messages(argc, argv, vp, bp)
-register int argc;
-register char *argv[];
-register vec *vp;
-char **bp;
-{
- register int i;
- register mbox *mb;
- char *box;
-
- mb = NULLBOX;
- box = NULLSTR;
-
- if (argc == 1)
- {
- /*
- * Current message in the current box.
- */
- if ((box = curr_box()) == NULLSTR)
- {
- fprintf(stderr, "%s: No current box.\n", my_name);
- return 0;
- }
-
- if ((mb = read_box(box)) == NULLBOX)
- {
- fprintf(stderr, "%s: No such box as \"%s\".\n", my_name, box);
- return 0;
- }
-
- if (mb->m_current == NULLMSG)
- {
- fprintf(stderr, "%s: No current message in \"%s\".\n", my_name, box);
- return 0;
- }
-
- vec_str(vp, mess_to_path(mb, mb->m_list[mb->m_current]));
- }
-
- for (i = 1; i < argc; i++)
- {
- register char *id;
- char *p;
- msg_idx x;
- extern char *strchr();
-
- /*
- * New box to pick messages from?
- */
- if (argv[i][0] == BOX_CHAR)
- {
- /*
- * Change current box?
- */
- if (argv[i][1] == BOX_CHAR)
- {
- if (*bp != NULLSTR)
- {
- usage();
- /* NOTREACHED */
- }
-
- *bp = box = newstr(&argv[i][2]);
- }
- else
- box = newstr(&argv[i][1]);
-
- if (*box == '\0')
- {
- usage();
- /* NOTREACHED */
- }
-
- if (mb != NULLBOX)
- free_box(mb);
-
- if ((mb = read_box(box)) == NULLBOX)
- {
- fprintf(stderr, "%s: No such box as \"%s\".\n", my_name, box);
-
- if (*bp != NULLSTR && strcmp(*bp, box) == 0)
- *bp = NULLSTR;
-
- continue;
- }
-
- /*
- * If this is the end of the line or the next
- * argument is a box then get the current message
- * in the specified box. Otherwise continue.
- */
- if (i + 1 < argc && argv[i + 1][0] != BOX_CHAR)
- continue;
-
- if (mb->m_current == NULLMSG)
- {
- fprintf(stderr, "%s: No current message in \"%s\".\n", my_name, box);
- continue;
- }
-
- vec_str(vp, mess_to_path(mb, mb->m_list[mb->m_current]));
- continue;
- }
-
- /*
- * Kludge the qualifier "all" into a "range".
- */
- if (strcmp(argv[i], ALL_NAME) == 0)
- id = ALL_RANGE;
- else
- id = argv[i];
-
- /*
- * No specified box, so use current one.
- */
- if (mb == NULLBOX)
- {
- if (box != NULLSTR)
- continue;
-
- if ((box = curr_box()) == NULLSTR)
- {
- fprintf(stderr, "%s: No current box.\n", my_name);
-
- while (++i < argc && argv[i][0] != BOX_CHAR)
- ;
-
- i--;
- continue;
- }
-
- if ((mb = read_box(box)) == NULLBOX)
- {
- fprintf(stderr, "%s: No such box as \"%s\".\n", my_name, box);
- continue;
- }
- }
-
- /*
- * Literal message id.
- */
- if (valid_id(id))
- {
- if (mess_index(mb, id) != NULLMSG)
- vec_str(vp, mess_to_path(mb, id));
- else
- fprintf(stderr, "%s: No message \"%s\" in \"%s\".\n", my_name, id, box);
-
- continue;
- }
-
- /*
- * Shell metacharacter message specifier.
- */
- if (strstr(id, metas) != NULLSTR)
- {
- metas_to_messages(mb, id, vp);
- continue;
- }
-
- /*
- * Range of messages.
- */
- if ((p = strchr(id, '-')) != NULLSTR)
- {
- char **v;
- char **n;
- msg_idx start;
- msg_idx finish;
-
- *p++ = '\0';
-
- if
- (
- (start = find_msg(mb, id)) == NULLMSG
- ||
- (finish = find_msg(mb, p)) == NULLMSG
- )
- continue;
-
- if ((v = n = mess_range(mb, start, finish)) == (char **)0)
- continue;
-
- while (*n != NULLSTR)
- vec_str(vp, mess_to_path(mb, *n++));
-
- *--p = '-';
- (void)free((char *)v);
-
- continue;
- }
-
- /*
- * An alias (first, current, last, etc ...)
- */
- if ((x = mess_alias(mb, id)) != NULLMSG)
- {
- vec_str(vp, mess_to_path(mb, mb->m_list[x]));
- continue;
- }
-
- fprintf(stderr, "%s: Message \"%s\" not in \"%s\".\n", my_name, id, box);
- }
-
- if (mb != NULLBOX)
- free_box(mb);
-
- return vp->v_count;
-}
//GO.SYSIN DD args.c
echo conf.c
sed 's/.//' >conf.c <<'//GO.SYSIN DD conf.c'
-/*
- * Configuration stuff.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)conf.c 1.39";
-#endif lint
-
-#include <stdio.h>
-#include "mace.h"
-#include "regexp.h"
-#include "line.h"
-#include "message.h"
-#include "conf.h"
-#include "flex.h"
-#include "headers.h"
-
-typedef struct
-{
- char *p_token;
- char **p_strp;
- match **p_matp;
- int (*p_func)();
- int p_required;
-}
- parse;
-
-static conf cf =
-{
- NULLSTR,
- NULLSTR,
- NULLSTR,
- NULLSTR,
- NULLSTR,
- NULLSTR,
- (match *)0,
- (match *)0,
- (match *)0,
-};
-
-static int lineno;
-static char *file;
-
-static void
-white(pp)
-register char **pp;
-{
- register char *s;
- register char c;
-
- s = *pp;
-
- for (;;)
- {
- switch (c = *s++)
- {
- case ' ':
- case '\t':
- continue;
-
- case '\\':
- if (*s == '\n')
- {
- s++;
- lineno++;
- continue;
- }
- /* fall through */
-
- default:
- s--;
- break;
- }
-
- break;
- }
-
- *pp = s;
-}
-
-static char *
-copy(p, q)
-register char *p;
-register char *q;
-{
- register char c;
-
-
- if (q[-1] == '\n')
- q--;
-
- c = *q;
- *q = '\0';
- p = newstr(p);
- *q = c;
-
- return p;
-}
-
-static char *
-string(pp)
-register char **pp;
-{
- register char *s;
- register char c;
- char *p;
-
- white(pp);
-
- s = p = *pp;
-
- while ((c = *s) != '\0' && c != '\n')
- s++;
-
- *pp = s;
-
- if (s == p)
- return NULLSTR;
-
- return copy(p, s);
-}
-
-static char *
-quoted_string(pp)
-register char **pp;
-{
- register char *p;
- register char c;
- static flex f = { NULLSTR, NULLSTR, NULLSTR, };
-
- white(pp);
-
- if (*(p = *pp) != '"')
- return NULLSTR;
-
- if (f.f_str == NULLSTR)
- flex_init(&f);
-
- for (;;)
- {
- switch (c = *++p)
- {
- case '\0':
- case '\n':
- *pp = p;
- flex_end(&f);
- return NULLSTR;
-
- case '\\':
- if (p[1] == '"')
- flex_char(&f, *++p);
- else if (p[1] == '\n')
- {
- p++;
- lineno++;
- }
- else
- flex_char(&f, c);
-
- continue;
-
- case '"':
- flex_char(&f, '\0');
- p++;
- break;
-
- default:
- flex_char(&f, c);
- continue;
- }
-
- break;
- }
-
- *pp = p;
- p = newstr(f.f_str);
- flex_end(&f);
-
- return p;
-}
-
-static char *
-token(pp)
-register char **pp;
-{
- register char *s;
- register char c;
- register char *p;
-
- white(pp);
-
- p = s = *pp;
-
- for (;;)
- {
- if
- (
- ((c = *s) >= 'a' && c <= 'z')
- ||
- ((c = *s) >= 'A' && c <= 'Z')
- ||
- *s == '-'
- )
- {
- s++;
- continue;
- }
-
- break;
- }
-
- *pp = s;
-
- if (s == p)
- return NULLSTR;
-
- return copy(p, s);
-}
-
-static int
-newline(pp)
-register char **pp;
-{
- register char *s;
- register char c;
-
- s = *pp;
-
- while ((c = *s++) != '\n')
- {
- if (c == '\0')
- {
- *pp = --s;
- return 1;
- }
-
- if (c == '\\' && *s == '\n')
- {
- s++;
- lineno++;
- }
- }
-
- lineno++;
-
- *pp = s;
-
- return 0;
-}
-
-static int
-string_value(pi, pp)
-register parse *pi;
-register char **pp;
-{
- if (*pi->p_strp != NULLSTR)
- {
- fprintf(stderr, "%s: \"%s\": \"%s\" multiply declared on line %d.\n", my_name, file, pi->p_token, lineno);
- return 1;
- }
-
- if ((*pi->p_strp = string(pp)) == NULLSTR)
- {
- fprintf(stderr, "%s: \"%s\": String expected after \"%s\" on line %d.\n", my_name, file, pi->p_token, lineno);
- return 1;
- }
-
- pi->p_required = 0;
-
- return 0;
-}
-
-static int
-re_value(pi, pp)
-register parse *pi;
-register char **pp;
-{
- register match *mp;
- regexp *cre;
- char *re;
-
- if (*pi->p_matp != (match *)0)
- {
- fprintf(stderr, "%s: \"%s\": Multiple definition of \"%s\" on line %d.\n", my_name, file, pi->p_token, lineno);
- return 1;
- }
-
- if ((re = quoted_string(pp)) == NULLSTR)
- {
- fprintf(stderr, "%s: \"%s\": Quoted string expected after \"%s\" on line %d.\n", my_name, file, pi->p_token, lineno);
- return 1;
- }
-
- if ((cre = regcomp(re)) == (regexp *)0)
- {
- fprintf(stderr, "%s: \"%s\": Regular expression \"%s\" on line %d %s\n", my_name, file, re, lineno, re_error);
- return 1;
- }
-
- mp = (match *)salloc(sizeof *mp);
- mp->m_re = re;
- mp->m_cre = cre;
- mp->m_action = NULLSTR;
- mp->m_next = (match *)0;
-
- *pi->p_matp = mp;
- pi->p_required = 0;
-
- return 0;
-}
-
-static int
-regex_string(pi, pp, quoted)
-register parse *pi;
-register char **pp;
-{
- register match **n;
- register match *mp;
- regexp *cre;
- char *re;
- char *action;
-
- if ((re = quoted_string(pp)) == NULLSTR)
- {
- fprintf(stderr, "%s: \"%s\": Quoted string expected after \"%s\" on line %d.\n", my_name, file, pi->p_token, lineno);
- return 1;
- }
-
- if (quoted)
- {
- if ((action = quoted_string(pp)) == NULLSTR)
- {
- fprintf(stderr, "%s: \"%s\": Quoted string expected after regular expression \"%s\" on line %d.\n", my_name, file, re, lineno);
- return 1;
- }
- }
- else
- {
- if ((action = string(pp)) == NULLSTR)
- {
- fprintf(stderr, "%s: \"%s\": String expected after regular expression \"%s\" on line %d.\n", my_name, file, re, lineno);
- return 1;
- }
- }
-
- if ((cre = regcomp(re)) == (regexp *)0)
- {
- fprintf(stderr, "%s: \"%s\": Regular expression \"%s\" on line %d %s\n", my_name, file, re, lineno, re_error);
- return 1;
- }
-
- mp = (match *)salloc(sizeof *mp);
- mp->m_re = re;
- mp->m_cre = cre;
- mp->m_action = action;
- mp->m_next = (match *)0;
-
- for (n = pi->p_matp; *n != (match *)0; n = &(*n)->m_next)
- ;
-
- *n = mp;
- pi->p_required = 0;
-
- return 0;
-}
-
-static int
-re_string(pi, pp)
-register parse *pi;
-register char **pp;
-{
- return regex_string(pi, pp, 0);
-}
-
-static int
-re_qstring(pi, pp)
-register parse *pi;
-register char **pp;
-{
- return regex_string(pi, pp, 1);
-}
-
-conf *
-read_config()
-{
- register char *p;
- register parse *pi;
- static char *despool = DESPOOLER;
- static char *deliver = DELIVERER;
- static char *peruse = PERUSER;
- char *s;
- int ok;
- static int done = 0;
- static parse look_for[] =
- {
- { CT_ADDRESS, &cf.c_address, (match **)0, string_value, 0, },
- { CT_DELIVER, &cf.c_deliver, (match **)0, string_value, 0, },
- { CT_DESPOOL, &cf.c_despool, (match **)0, string_value, 0, },
- { CT_EXEC, (char **)0, &cf.c_exec, re_qstring, 0, },
- { CT_INBOX, &cf.c_inbox, (match **)0, string_value, 1, },
- { CT_OUTBOX, &cf.c_outbox, (match **)0, string_value, 1, },
- { CT_PERUSE, &cf.c_peruse, (match **)0, string_value, 0, },
- { CT_REFILE, (char **)0, &cf.c_refile, re_string, 0, },
- { CT_REMOVE, (char **)0, &cf.c_remove, re_value, 0, },
- { CT_SAVE, (char **)0, &cf.c_save, re_string, 0, },
- { CT_SPOOL, &cf.c_spool, (match **)0, string_value, 0, },
- { CT_SPOOLDIR, &cf.c_spooldir, (match **)0, string_value, 0, },
- { NULLSTR, (char **)0, (match **)0, (int (*)())0, 0, },
- };
-
- if (done)
- return &cf;
-
- file = concat3(mace_dir(), "/", CONFIG);
-
- if ((s = p = read_file(file)) == NULLSTR)
- {
- could_not("read", file);
- /* NOTREACHED*/
- }
-
- ok = 0;
- lineno = 1;
-
- do
- {
- register char *t;
-
- if (*s == '#')
- {
- newline(&s);
- continue;
- }
-
- if ((t = token(&s)) != NULLSTR)
- {
- for (pi = look_for; pi->p_token != NULLSTR; pi++)
- {
- if (strcmp(pi->p_token, t) == 0)
- {
- ok |= (*pi->p_func)(pi, &s);
- break;
- }
- }
-
- if (pi->p_token == NULLSTR)
- fprintf(stderr, "%s: \"%s\": Unrecognised token \"%s\" on line %d.\n", my_name, file, t, lineno);
-
- (void)free(t);
- }
- else
- fprintf(stderr, "%s: \"%s\": Token expected on line %d.\n", my_name, file, lineno);
-
- newline(&s);
- }
- while (*s != '\0');
-
- for (pi = look_for; pi->p_token != NULLSTR; pi++)
- {
- if (pi->p_required)
- {
- fprintf(stderr, "%s: \"%s\": Specification of \"%s\" required.\n", my_name, file, pi->p_token);
- ok = 1;
- }
- }
-
- if (ok)
- {
- exit(1);
- /* NOTREACHED */
- }
-
- if (cf.c_despool == NULLSTR)
- {
- if (despool == NULLSTR)
- {
- fprintf(stderr, "%s: \"%s\": Specification of \"%s\" required.\n", my_name, file, CT_DESPOOL);
- exit(1);
- /* NOTREACHED */
- }
-
- cf.c_despool = newstr(despool);
- }
-
- if (cf.c_deliver == NULLSTR)
- {
- if (deliver == NULLSTR)
- {
- fprintf(stderr, "%s: \"%s\": Specification of \"%s\" required.\n", my_name, file, CT_DELIVER);
- exit(1);
- /* NOTREACHED */
- }
-
- cf.c_deliver = newstr(deliver);
- }
-
- if (cf.c_address == NULLSTR)
- {
- static char dot[2] = { RFC_SPEC_DOT, '\0' };
-
- if (DOMAIN_CMD == NULLSTR)
- {
- fprintf(stderr, "%s: Don't know your domain. Specify it with \"%s\" in \"%s\".\n", my_name, CT_ADDRESS, file);
- exit(1);
- }
-
- cf.c_address = concat3(host(), dot, domain());
- }
-
- if (cf.c_peruse == NULLSTR)
- {
- if (peruse == NULLSTR)
- {
- fprintf(stderr, "%s: \"%s\": Specification of \"%s\" required.\n", my_name, file, CT_PERUSE);
- exit(1);
- /* NOTREACHED */
- }
-
- cf.c_peruse = newstr(peruse);
- }
-
- (void)free(file);
- (void)free(p);
- done = 1;
-
- return &cf;
-}
-
-/*
- * Expand a string containing `exec' CE_SPECIAL substitutions.
- */
-char *
-special_expand(char *s, char *box, char *id)
-{
- char c;
- static flex f = { NULLSTR, NULLSTR, NULLSTR };
-
- if (f.f_str == NULLSTR)
- flex_init(&f);
-
- while ((c = *s++) != '\0')
- {
- if (c == CE_SPECIAL)
- {
- switch (*s++)
- {
- case CE_BOX:
- flex_char(&f, BOX_CHAR);
- flex_str(&f, box);
- break;
-
- case CE_MESSID:
- flex_str(&f, id);
- break;
-
- case CE_MACEDIR:
- flex_str(&f, mace_dir());
- break;
-
- case CE_PATH:
- /* this is wrong and should be changed */
- flex_str(&f, mace_dir());
- flex_char(&f, '/');
- flex_str(&f, box);
- flex_char(&f, '/');
- flex_str(&f, id);
- break;
-
- case CE_SPECIAL:
- flex_char(&f, CE_SPECIAL);
- break;
-
- default:
- flex_char(&f, CE_SPECIAL);
- s--;
- break;
- }
-
- continue;
- }
-
- flex_char(&f, c);
- }
-
- flex_char(&f, '\0');
- flex_end(&f);
-
- return f.f_str;
-}
-
-/*
- * Call f() for each time a regex matches a message's headers.
- */
-void
-regex_apply(char *inbox, message *m, match *re, void (*f)(char *, message *, match *))
-{
- char **n;
-
- while (re != (match *)0)
- {
- for (n = m->ms_headers.v_list; *n != NULLSTR && **n != '\0'; n++)
- {
- re_error = NULLSTR;
-
- if (regexec(re->m_cre, *n) == 0)
- {
- if (re_error != NULLSTR)
- {
- fprintf(stderr, "%s: Regular expression \"%s\" %s\n", my_name, re->m_re, re_error);
- break;
- }
-
- continue;
- }
-
- (*f)(inbox, m, re);
- }
-
- re = re->m_next;
- }
-}
//GO.SYSIN DD conf.c
echo dir.c
sed 's/.//' >dir.c <<'//GO.SYSIN DD dir.c'
-/*
- * mkdir/rmdir [in]compatibility.
- */
-
-#include "mace.h"
-
-#if !BSD_MKDIR
-
-#ifndef lint
-static char sccsid[] = "@(#)dir.c 1.30";
-#endif lint
-
-static int
-dir_op(op, s)
-register char *op;
-register char *s;
-{
- char *v[3];
-
- v[0] = op;
- v[1] = s;
- v[2] = NULLSTR;
-
- return run(v) != 0 ? SYSERROR : 0;
-}
-
-int
-mkdir(s, mode)
-register char *s;
-register int mode;
-{
- return dir_op(MKDIR_STR, s);
-}
-
-int
-rmdir(s)
-register char *s;
-{
- return dir_op(RMDIR_STR, s);
-}
-
-#endif !BSD_MKDIR
//GO.SYSIN DD dir.c
echo domain.c
sed 's/.//' >domain.c <<'//GO.SYSIN DD domain.c'
-/*
- * Discover this host's domain.
- *
- * Returns static data.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)domain.c 1.25";
-#endif lint
-
-#include "mace.h"
-#include "line.h"
-
-static char *domainname = NULLSTR;
-
-char *
-domain()
-{
- register int fd;
- register char *p;
- lineio l;
- char *cmd = DOMAIN_CMD;
-
- if (domainname != NULLSTR)
- return domainname;
-
- if (cmd == NULLSTR)
- {
- fatal("domain");
- /* NOTREACHED */
- }
-
- if ((fd = pipe_open(cmd, 'r')) == -1)
- {
- could_not("pipe to", cmd);
- /* NOTREACHED */
- }
-
- (void)lopen(&l, fd, LREAD);
-
- if ((p = lread(&l)) == NULLSTR)
- {
- could_not("read", cmd);
- /* NOTREACHED */
- }
-
- if (lclose(&l))
- {
- (void)pipe_close(fd);
- could_not("close", cmd);
- /* NOTREACHED */
- }
-
- if (pipe_close(fd))
- {
- could_not("close", cmd);
- /* NOTREACHED */
- }
-
- return domainname = p;
-}
//GO.SYSIN DD domain.c
echo id.c
sed 's/.//' >id.c <<'//GO.SYSIN DD id.c'
-/*
- * Generate message id's
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)id.c 1.31";
-#endif lint
-
-#include "mace.h"
-
-static char *vowels = "aeiou";
-static char *cons = "bdfgjklmnprstvyz";
-
-char *
-nextid(s)
-char *s;
-{
- register char *p;
- register char *q;
- char *set;
- char *id;
- int carry;
- extern char *strchr();
-
- if (s == NULLSTR)
- {
- for (p = id = salloc(ID_LEN + 1); p < &id[ID_LEN]; p++)
- *p = ((p - id) & 1 ? vowels : cons)[0];
-
- *p = '\0';
-
- return id;
- }
-
- id = newstr(s);
-
- if (!valid_id(id))
- {
- fatal("nextid");
- /* NOTREACHED */
- }
-
- carry = 1;
-
- p = &id[ID_LEN];
-
- while (--p >= id)
- {
- set = (p - id) & 1 ? vowels : cons;
-
- q = strchr(set, *p);
-
- if (carry)
- {
- if (*++q == '\0')
- q = set;
- else
- carry = 0;
-
- *p = *q;
- }
- }
-
- return id;
-}
-
-int
-valid_id(id)
-register char *id;
-{
- register char *p;
-
- for (p = id; *p != '\0'; p++)
- ;
-
- if (p - id != ID_LEN)
- return 0;
-
- for (p = id; *p != '\0'; p++)
- {
- if (strchr((p - id) & 1 ? vowels : cons, *p) == NULLSTR)
- return 0;
- }
-
- return 1;
-}
//GO.SYSIN DD id.c
echo flex.c
sed 's/.//' >flex.c <<'//GO.SYSIN DD flex.c'
-/*
- * Flexible string handling.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)flex.c 1.31";
-#endif lint
-
-#include "mace.h"
-#include "flex.h"
-
-void
-flex_init(f)
-register flex *f;
-{
- f->f_str = f->f_ptr = salloc(FLEXZ);
- f->f_end = f->f_ptr + FLEXZ;
-}
-
-char *
-flex_fill(f)
-register flex *f;
-{
- register int s;
-
- s = f->f_end - f->f_str + FLEXZ;
-
- f->f_str = srealloc(f->f_str, s);
- f->f_end = f->f_str + s;
- f->f_ptr = f->f_end - FLEXZ;
-
- return f->f_ptr++;
-}
-
-void
-flex_end(f)
-register flex *f;
-{
- f->f_ptr = f->f_str;
-}
-
-void
-flex_str(f, s)
-register flex *f;
-register char *s;
-{
- while (*s != '\0')
- flex_char(f, *s++);
-}
-
-void
-flex_nstr(f, s, n)
-register flex *f;
-register char *s;
-register int n;
-{
- while (n-- > 0 && *s != '\0')
- flex_char(f, *s++);
-}
//GO.SYSIN DD flex.c
echo headers.c
sed 's/.//' >headers.c <<'//GO.SYSIN DD headers.c'
-/*
- * RFC 822 header routines.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)headers.c 1.33";
-#endif lint
-
-#include "mace.h"
-#include "headers.h"
-
-char **
-find_header(v, h)
-register char **v;
-register char *h;
-{
- register char *p;
-
- while ((p = *v) != NULLSTR)
- {
- if (rfc_hdr_cmp(p, h))
- return v;
-
- v++;
- }
-
- return (char **)NULLSTR;
-}
-
-char *
-header_text(h)
-register char *h;
-{
- while (*h++ != RFC_SPEC_COLON)
- ;
-
- while ((*h == RFC_LWSP_1 || *h == RFC_LWSP_2) && *h != '\0')
- h++;
-
- return *h == '\0' ? NULLSTR : h;
-}
-
-/*
- * Re-order the headers in a message so they are in this order:
- *
- * From:
- * Date:
- * To:
- * Cc:
- * Bcc:
- * Subject:
- */
-static char *header_order[] =
-{
- RFC_FROM,
- RFC_DATE,
- RFC_TO,
- RFC_CC,
- RFC_BCC,
- RFC_SUBJECT,
- NULLSTR,
-};
-
-void
-reorder_headers(vec *h)
-{
- register char **hp;
- register int i;
- static vec new;
- static char stolen[] = "";
-
- if (new.v_size == 0)
- vec_init(&new, 64);
-
- /*
- * Steal the headers that we want.
- */
- for (hp = header_order; *hp != NULLSTR; hp++)
- {
- register char **n;
-
- /*
- * Search all the headers because multiple To:/Cc:/Bcc:
- * headers can occur.
- */
- for (n = h->v_list; *n != NULLSTR; n++)
- {
- if (rfc_hdr_cmp(*n, *hp))
- {
- vec_str(&new, *n);
- *n = stolen;
- }
- }
- }
-
- /*
- * Append the others.
- */
- for (hp = h->v_list; *hp != NULLSTR; hp++)
- {
- if (*hp != stolen)
- vec_str(&new, *hp);
- }
-
- vec_str(&new, NULLSTR);
-
- /*
- * Return the re-ordered headers.
- */
- if (new.v_count != h->v_count)
- {
- fatal("reorder_headers");
- /* NOTREACHED */
- }
-
- for (i = 0; i < new.v_count; i++)
- h->v_list[i] = new.v_list[i];
-
- new.v_count = 0;
-}
//GO.SYSIN DD headers.c
echo host.c
sed 's/.//' >host.c <<'//GO.SYSIN DD host.c'
-/*
- * Discover this host's name.
- *
- * Returns static data.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)host.c 1.25";
-#endif lint
-
-#include "mace.h"
-
-static char *hostname = NULLSTR;
-
-#if USG_UNAME && BSD_GETHOSTNAME
-
-$$ "You're either on a USG or BSD system" $$
-
-#endif USG_UNAME && BSD_GETHOSTNAME
-
-#if USG_UNAME
-
-#include <sys/utsname.h>
-
-char *
-host()
-{
- static struct utsname n;
-
- if (hostname != NULLSTR)
- return hostname;
-
- if (uname(&n) == -1)
- {
- could_not("uname", "host");
- /* NOTREACHED */
- }
-
- return hostname = n.nodename;
-}
-
-#endif USG_UNAME
-
-#if BSD_GETHOSTNAME
-
-char *
-host()
-{
- static char n[64];
-
- if (hostname != NULLSTR)
- return hostname;
-
- if (gethostname(n, sizeof n) == -1)
- {
- could_not("gethostname", "host");
- /* NOTREACHED */
- }
-
- return hostname = n;
-}
-
-#endif BSD_GETHOSTNAME
-
-#if !USG_UNAME && !BSD_GETHOSTNAME
-
-#include "line.h"
-
-char *
-host()
-{
- register int fd;
- register char *p;
- lineio l;
- char *cmd = HOST_CMD;
-
- if (hostname != NULLSTR)
- return hostname;
-
- if (cmd == NULLSTR)
- {
- fatal("host");
- /* NOTREACHED */
- }
-
- if ((fd = pipe_open(cmd, 'r')) == -1)
- {
- could_not("pipe to", cmd);
- /* NOTREACHED */
- }
-
- (void)lopen(&l, fd, LREAD);
-
- if ((p = lread(&l)) == NULLSTR)
- {
- could_not("read", cmd);
- /* NOTREACHED */
- }
-
- if (lclose(&l))
- {
- (void)pipe_close(fd);
- could_not("close", cmd);
- /* NOTREACHED */
- }
-
- if (pipe_close(fd))
- {
- could_not("close", cmd);
- /* NOTREACHED */
- }
-
- return hostname = p;
-}
-
-#endif !USG_UNAME && !BSD_GETHOSTNAME
//GO.SYSIN DD host.c
echo line.c
sed 's/.//' >line.c <<'//GO.SYSIN DD line.c'
-/*
- * Line i/o routines.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)line.c 1.31";
-#endif lint
-
-#include "mace.h"
-#include "line.h"
-#include "flex.h"
-
-lineio *
-lopen(lp, fd, flag)
-register lineio *lp;
-register int fd;
-register int flag;
-{
- lp->l_fd = fd;
- lp->l_ptr = lp->l_end = lp->l_buf;
- lp->l_flag = flag;
-
- return lp;
-}
-
-int
-lclose(lp)
-register lineio *lp;
-{
- register int n;
-
- if ((lp->l_flag & (LWRITE|LERROR)) == LWRITE && (n = lp->l_ptr - lp->l_buf) > 0)
- {
- if (write(lp->l_fd, lp->l_buf, n) != n)
- lp->l_flag |= LERROR;
- }
-
- n = (lp->l_flag & LERROR) != 0;
-
- lp->l_flag = 0;
-
- return n;
-}
-
-char *
-lread(lp)
-register lineio *lp;
-{
- register char *p;
- static flex f = { NULLSTR, NULLSTR, NULLSTR, };
-
- switch (lp->l_flag & ~LCRLF)
- {
- case LREAD:
- break;
-
- case LREAD|LEOF:
- return NULLSTR;
-
- default:
- fatal("lread");
- /* NOTREACHED */
- }
-
- if (f.f_str == NULLSTR)
- flex_init(&f);
-
- for (;;)
- {
- register char c;
-
- if (lp->l_ptr == lp->l_end)
- {
- register int n;
-
- switch (n = read(lp->l_fd, lp->l_buf, LBUFZ))
- {
- case SYSERROR:
- lp->l_flag |= LERROR;
- flex_end(&f);
- return NULLSTR;
-
- case 0:
- lp->l_flag |= LEOF;
- break;
-
- default:
- lp->l_ptr = lp->l_buf;
- lp->l_end = lp->l_ptr + n;
- }
- }
-
- if ((lp->l_flag & LEOF) != 0)
- {
- if (f.f_ptr == f.f_str)
- return NULLSTR;
-
- break;
- }
-
- if ((c = *lp->l_ptr++) == '\n')
- {
- if ((lp->l_flag & LCRLF) == 0)
- break;
-
- if (f.f_ptr != f.f_str && f.f_ptr[-1] == '\r')
- {
- f.f_ptr--;
- break;
- }
- }
-
- flex_char(&f, c);
- }
-
- flex_char(&f, '\0');
- p = newstr(f.f_str);
- flex_end(&f);
- return p;
-}
-
-static void
-lflush(lp)
-register lineio *lp;
-{
- register int n;
-
- switch (lp->l_flag & ~(LCRLF|LLBUF))
- {
- case LWRITE:
- break;
-
- default:
- fatal("lflush");
- /* NOTREACHED */
- }
-
- n = lp->l_ptr - lp->l_buf;
-
- if (write(lp->l_fd, lp->l_buf, n) != n)
- {
- lp->l_flag |= LERROR;
- return;
- }
-
- lp->l_ptr = lp->l_buf;
-}
-
-#define lputchar(lp, c) do \
- { \
- if (((lp)->l_flag & LERROR) != 0) \
- break; \
- if ((lp)->l_ptr == &(lp)->l_buf[LBUFZ]) \
- lflush(lp); \
- if ((*(lp)->l_ptr++ = (c)) == '\n' && ((lp)->l_flag & LLBUF) != 0) \
- lflush(lp); \
- } while(0)
-
-
-char *
-lwrite(lp, s)
-register lineio *lp;
-register char *s;
-{
- register char *p;
-
- switch (lp->l_flag & ~(LCRLF|LLBUF))
- {
- case LWRITE:
- break;
-
- default:
- fatal("lwrite");
- /* NOTREACHED */
- }
-
- p = s;
-
- for (;;)
- {
- register char c;
-
- if ((c = *p++) == '\0')
- {
- if ((lp->l_flag & LCRLF) != 0)
- lputchar(lp, '\r');
-
- lputchar(lp, '\n');
-
- return (lp->l_flag & LERROR) == 0 ? s : NULLSTR;
- }
-
- lputchar(lp, c);
- }
-}
//GO.SYSIN DD line.c
echo lock.c
sed 's/.//' >lock.c <<'//GO.SYSIN DD lock.c'
-/*
- * File locking.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)lock.c 1.30";
-#endif lint
-
-#include "mace.h"
-#include <errno.h>
-
-int
-lock(f)
-register char *f;
-{
- register char *p;
- register int tries;
- extern int errno;
-
- tries = 0;
-
- p = concat(f, LOCK_STR);
-
- while (tries++ < 5)
- {
- errno = 0;
-
- link(f, p);
-
- if (errno != EEXIST)
- break;
-
- sleep(2);
- }
-
- (void)free(p);
-
- return errno;
-}
-
-int
-unlock(f)
-register char *f;
-{
- register char *p;
- extern int errno;
-
- errno = 0;
-
- (void)unlink(p = concat(f, LOCK_STR));
-
- (void)free(p);
-
- return errno;
-}
//GO.SYSIN DD lock.c
echo mail.c
sed 's/.//' >mail.c <<'//GO.SYSIN DD mail.c'
-/*
- * System independent mail box locking.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)mail.c 1.33";
-#endif lint
-
-#include "mace.h"
-#include "line.h"
-#include "headers.h"
-#include <stdio.h>
-#include <errno.h>
-
-#define MAIL_FORWARD "Forward to "
-#define MAIL_PIPE "Pipe to "
-
-static char *mail_file = NULLSTR;
-static int locked = 0;
-
-/*
- * Returns a pointer to static data, unlike the rest.
- */
-static char *
-mail_name()
-{
- register char *p;
- extern char *getenv();
-
- if (mail_file == NULLSTR)
- {
- if ((p = getenv("MAIL")) == NULLSTR)
- {
- would_not("getenv", "MAIL");
- return NULLSTR;
- }
-
- mail_file = p;
- }
-
- return mail_file;
-}
-
-int
-mail_check(mf)
-char *mf;
-{
- register char *p;
- register char *l;
- int fd;
- lineio mld;
- extern int errno;
-
- if ((p = mf) == NULLSTR && (p = mail_name()) == NULLSTR)
- return 0;
-
- if (access(p, 4) == SYSERROR && errno == EACCES)
- {
- fprintf(stderr, "%s: Mail in \"%s\" is not accessable by you.\n", my_name, p);
- return 0;
- }
-
- if ((fd = open(p, O_RD)) == SYSERROR)
- {
- fprintf(stderr, "%s: No mail in \"%s\".\n", my_name, p);
- return 0;
- }
-
- lopen(&mld, fd, LREAD);
-
- if ((l = lread(&mld)) == NULLSTR)
- {
- fprintf(stderr, "%s: No mail in \"%s\".\n", my_name, p);
- (void)lclose(&mld);
- (void)close(fd);
-
- return 0;
- }
-
- (void)lclose(&mld);
- (void)close(fd);
-
- if (strncmp(l, UNIX_FROM, (sizeof UNIX_FROM) - 1) == 0)
- {
- free(l);
- return 1;
- }
-
- if (strncmp(l, MAIL_FORWARD, (sizeof MAIL_FORWARD) - 1) == 0)
- {
- fprintf(stderr, "%s: Mail in \"%s\" is being forwarded to \"%s\".\n", my_name, p, l + (sizeof MAIL_FORWARD) - 1);
-
- free(l);
- return 0;
- }
-
- if (strncmp(l, MAIL_PIPE, (sizeof MAIL_PIPE) - 1) == 0)
- {
- fprintf(stderr, "%s: Mail in \"%s\" is being piped to \"%s\".\n", my_name, p, l + (sizeof MAIL_PIPE) - 1);
-
- free(l);
- return 0;
- }
-
- free(l);
-
- fprintf(stderr, "%s: Mail in \"%s\" is not in a UNIX format.\n", my_name, p);
- return 0;
-}
-
-#if USG_MAIL && BSD_MAIL
-#include "You cannot have both USG_MAIL and BSD_MAIL defined!"
-#endif
-
-#if USG_MAIL
-
-#define USG_LOCK ".lock"
-
-static char *lock_file = NULLSTR;
-
-#endif USG_MAIL
-
-#if BSD_MAIL
-
-#include <sys/types.h>
-#include <sys/file.h>
-
-static int lock_fd;
-
-#endif BSD_MAIL
-
-int
-mail_lock(m)
-register char **m;
-{
- register char *p;
- register int fd;
- register int tries;
-
- if (locked)
- {
- fprintf(stderr, "%s: \"%s\" locked.\n", my_name, mail_file);
- return SYSERROR;
- }
-
- if ((p = *m) != NULLSTR)
- mail_file = newstr(*m);
- else if ((p = mail_name()) == NULLSTR)
- return SYSERROR;
-
- if (!mail_check(p))
- return SYSERROR;
-
-#if USG_MAIL
-
- if (lock_file == NULLSTR)
- lock_file = concat(p, USG_LOCK);
-
- tries = 0;
-
- while ((fd = creat(lock_file, 0)) == SYSERROR)
- {
- if (errno != EPERM || tries++ > 5)
- {
- would_not("creat", lock_file);
- return SYSERROR;
- }
-
- sleep(2);
- }
-
- if (close(fd) == SYSERROR)
- {
- would_not("close", lock_file);
- return SYSERROR;
- }
-
-#endif USG_MAIL
-
- if ((fd = open(mail_file, O_RD)) == SYSERROR)
- {
- would_not("open", mail_file);
- return SYSERROR;
- }
-
-#if BSD_MAIL
-
- while (flock(lock_fd = fd, LOCK_EX) == SYSERROR)
- {
- if (tries++ > 5)
- {
- would_not("lock", mail_file);
- close(fd);
- return SYSERROR;
- }
-
- sleep(2);
- }
-
-#endif BSD_MAIL
-
- if (*m == NULLSTR)
- *m = mail_file;
- locked = 1;
-
- return fd;
-}
-
-int
-mail_unlock(delete)
-register int delete;
-{
- register int ret;
-
- if
- (
- mail_file == NULLSTR
-#if USG_MAIL
- ||
- lock_file == NULLSTR
-#endif USG_MAIL
- )
- {
- fatal("mail_unlock");
- /* NOTREACHED */
- }
-
- if (delete && (ret = unlink(mail_file)) == SYSERROR)
- would_not("unlink", mail_file);
- else
- ret = 0;
-
-#if USG_MAIL
-
- if (unlink(lock_file) == SYSERROR)
- {
- ret = SYSERROR;
- would_not("unlink", mail_file);
- }
-
-#endif USG_MAIL
-
-#if BSD_MAIL
-
- (void)flock(lock_fd, LOCK_UN);
- (void)close(lock_fd);
-
-#endif BSD_MAIL
-
- locked = 0;
-
- return ret;
-}
-
-int
-mail_locked()
-{
- return locked;
-}
//GO.SYSIN DD mail.c
echo macebox.c
sed 's/.//' >macebox.c <<'//GO.SYSIN DD macebox.c'
-/*
- * Box handling stuff.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)macebox.c 1.32";
-#endif lint
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdio.h>
-#include "mace.h"
-
-/*
- * Return the name of the current box.
- */
-char *
-curr_box()
-{
- register char *box;
- register char *p;
-
- if ((box = read_file(p = concat3(mace_dir(), "/", BOX))) == NULLSTR)
- {
- (void)free(p);
- return NULLSTR;
- }
-
- (void)free(p);
-
- if ((p = check_box(box)) == NULLSTR)
- {
- (void)free(box);
- return NULLSTR;
- }
-
- (void)free(p);
-
- return box;
-}
-
-char *
-check_box(s)
-char *s;
-{
- register char *box;
- struct stat statb;
-
- if (*s == SPEC_CHAR)
- return NULLSTR;
-
- box = concat3(mace_dir(), "/", s);
-
- if (stat(box, &statb) == SYSERROR || (statb.st_mode & S_IFMT) != S_IFDIR)
- {
- (void)free(box);
- return NULLSTR;
- }
-
- return box;
-}
-
-char *
-create_box(s)
-char *s;
-{
- register char *dir;
- register char *messid;
- register char *id;
-
- if (*s == SPEC_CHAR)
- return NULLSTR;
-
- dir = concat3(mace_dir(), "/", s);
-
- if (mkdir(dir, MKDIR_MODE) == SYSERROR)
- {
- (void)free(dir);
- return NULLSTR;
- }
-
- messid = concat3(dir, "/", MESSID);
-
- if (write_file(messid, id = nextid(NULLSTR)))
- {
- (void)free(id);
- (void)free(dir);
- (void)free(messid);
- return NULLSTR;
- }
-
- (void)free(id);
- (void)free(messid);
-
- return dir;
-}
-
-int
-delete_box(s)
-char *s;
-{
- register char *b;
- register char *m;
- register int ok;
-
- if ((b = check_box(s)) == NULLSTR)
- {
- fprintf(stderr, "%s: No such box as \"%s\".\n", my_name, s);
- return 1;
- }
-
- m = concat3(b, "/", MESSID);
- (void)unlink(m);
- (void)free(m);
-
- m = concat3(b, "/", PROTO);
- (void)unlink(m);
-
- if ((ok = rmdir(b)) != 0)
- would_not("rmdir", b);
-
- (void)free(b);
- (void)free(m);
-
- return ok != 0;
-}
-
-static int
-mess_cmp(m1, m2)
-register char **m1;
-register char **m2;
-{
- return strcmp(*m1, *m2);
-}
-
-mbox *
-read_box(s)
-char *s;
-{
- register char *box;
- register char **list;
- register int i;
- register mbox *info;
- register char **n;
- register char *current;
-
- if ((box = check_box(s)) == NULLSTR)
- return NULLBOX;
-
- list = read_dir(box);
-
- /*
- * Ensure there are no invalid message id's in the box.
- */
- for (i = 0; list[i] != NULLSTR; i++)
- {
- register int j;
-
- if (valid_id(list[i]))
- continue;
-
- fprintf(stderr, "%s: warning - Invalid message id \"%s\" in \"%c%s\".\n", my_name, list[i], BOX_CHAR, s);
-
- /* shuffle down by one */
- (void)free(list[i]);
-
- for (j = i; list[j] != NULLSTR; j++)
- list[j] = list[j + 1];
-
- i--;
- }
-
- qsort((char *)list, i, sizeof(*list), mess_cmp);
-
- if ((current = curr_in_box(s)) != NULLSTR)
- {
- for (n = list; *n != NULLSTR; n++)
- {
- if (strcmp(*n, current) == 0)
- break;
- }
- }
- else
- n = &list[i];
-
- info = (mbox *)salloc(sizeof(mbox));
- info->m_name = newstr(s);
- info->m_path = box;
- info->m_count = i;
- info->m_messid = current;
- info->m_list = list;
- info->m_current = *n == NULLSTR ? NULLMSG : n - list;
-
- return info;
-}
-
-void
-free_box(mp)
-register mbox *mp;
-{
- free_dir(mp->m_list);
- (void)free(mp->m_name);
- (void)free(mp->m_path);
- if (mp->m_messid != NULLSTR)
- (void)free(mp->m_messid);
- (void)free((char *)mp);
-}
-
-int
-set_box(s)
-register char *s;
-{
- register char *f;
-
- if ((f = check_box(s)) == NULLSTR)
- {
- fprintf(stderr, "%s: No such box as \"%s\".\n", my_name, s);
- return 1;
- }
-
- (void)free(f);
-
- f = concat3(mace_dir(), "/", BOX);
-
- if (write_file(f, s))
- {
- would_not("write", f);
- (void)free(f);
- return 1;
- }
-
- (void)free(f);
- return 0;
-}
-
//GO.SYSIN DD macebox.c
echo macedir.c
sed 's/.//' >macedir.c <<'//GO.SYSIN DD macedir.c'
-/*
- * Spool directory finder.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)macedir.c 1.32";
-#endif lint
-
-#include <stdio.h>
-#include "mace.h"
-
-/*
- * Unlike the others we return a pointer to static data.
- * It doesn't need to be free()'d.
- *
- * If the first character of the pathname contained in MAIL_DIR
- * is a '/' assume that it's a full pathname and return it.
- */
-char *
-mace_dir()
-{
- char *s;
- char *t;
- static char *home = NULLSTR;
- static char *dir = NULLSTR;
- extern char *getenv();
-
- if (dir != NULLSTR)
- return dir;
-
- if (home == NULLSTR && (home = getenv(ENV_HOME)) == NULLSTR)
- {
- fprintf(stderr, "%s: You have no $%s in your environment.\n", my_name, ENV_HOME);
- exit(1);
- /* NOTREACHED */
- }
-
- s = concat3(home, "/", MACEDIR);
-
- if ((t = read_file(s)) == NULLSTR)
- {
- could_not("read", s);
- /* NOTREACHED */
- }
-
- if (*t != '/')
- {
- dir = concat3(home, "/", t);
- (void)free(t);
- }
- else
- dir = t;
-
- (void)free(s);
-
- return dir;
-}
//GO.SYSIN DD macedir.c
echo memory.c
sed 's/.//' >memory.c <<'//GO.SYSIN DD memory.c'
-/*
- * Memory allocation.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)memory.c 1.30";
-#endif lint
-
-#include <stdio.h>
-#include "mace.h"
-
-char *
-salloc(n)
-int n;
-{
- register char *s;
- extern char *malloc();
-
- if ((s = malloc((unsigned)n)) == NULLSTR)
- {
- fprintf(stderr, "%s: Ran out of memory.\n", my_name);
- exit(1);
- /* NOTREACHED */
- }
-
- return s;
-}
-
-char *
-srealloc(p, n)
-char *p;
-int n;
-{
- register char *s;
- extern char *realloc();
-
- if ((s = realloc(p, (unsigned)n)) == NULLSTR)
- {
- fprintf(stderr, "%s: Ran out of memory.\n", my_name);
- exit(1);
- /* NOTREACHED */
- }
-
- return s;
-}
-
-void
-bcopy(from, to, len)
-register char *from;
-register char *to;
-register int len;
-{
- while (len-- > 0)
- *to++ = *from++;
-}
//GO.SYSIN DD memory.c
echo mesg.c
sed 's/.//' >mesg.c <<'//GO.SYSIN DD mesg.c'
-/*
- * Messages.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)mesg.c 1.30";
-#endif lint
-
-#include <stdio.h>
-#include "mace.h"
-
-void
-could_not(what, with)
-char *what;
-char *with;
-{
- fprintf(stderr, "%s: Could not %s \"%s\". %s\n", my_name, what, with, sysmess());
- exit(1);
- /* NOTREACHED */
-}
-
-void
-would_not(what, with)
-char *what;
-char *with;
-{
- fprintf(stderr, "%s: Could not %s \"%s\". %s\n", my_name, what, with, sysmess());
-}
-
-void
-fatal(what)
-char *what;
-{
- fprintf(stderr, "%s: Internal error: \"%s\".\n", my_name, what);
- exit(1);
- /* NOTREACHED */
-}
//GO.SYSIN DD mesg.c
echo mess.c
sed 's/.//' >mess.c <<'//GO.SYSIN DD mess.c'
-/*
- * Message naming & reading.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)mess.c 1.40";
-#endif lint
-
-#include "mace.h"
-#include "line.h"
-#include "message.h"
-#include "headers.h"
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-
-char *
-curr_in_box(box)
-register char *box;
-{
- register char *messid;
- register char *m;
-
- if ((m = check_box(box)) == NULLSTR)
- return NULLSTR;
-
- messid = concat3(m, "/", MESSID);
- (void)free(m);
-
- if ((m = read_file(messid)) == NULLSTR)
- {
- (void)free(messid);
- return NULLSTR;
- }
-
- (void)free(messid);
-
- if (!valid_id(m))
- {
- (void)free(m);
- m = NULLSTR;
- }
-
- return m;
-}
-
-void
-free_mess(mp)
-register message *mp;
-{
- (void)free(mp->ms_path);
- (void)free(mp->ms_messid);
- vec_free(&mp->ms_headers);
- (void)free((char *)mp);
-}
-
-/*
- * Allocate a new message. Returns NULLMESS on failure.
- */
-static message *
-new(char *f, char *id, int fd)
-{
- message *mp;
- struct stat statb;
- extern int errno;
-
- mp = (message *)salloc(sizeof(*mp));
- mp->ms_path = newstr(f);
- mp->ms_messid = newstr(id);
- vec_init(&mp->ms_headers, 128);
-
- if (fstat(fd, &statb) == SYSERROR)
- goto broken;
-
- switch (statb.st_mode & S_IFMT)
- {
- case S_IFDIR:
- errno = EISDIR;
- goto broken;
-
- case S_IFREG:
- mp->ms_size = statb.st_size;
- mp->ms_copies = statb.st_nlink;
- mp->ms_state = statb.st_mode;
- break;
-
- default:
- /*
- * Fake it for a pipe/socket/device.
- */
- mp->ms_size = statb.st_size;
- mp->ms_copies = 1;
- mp->ms_state = 0;
- break;
- }
-
- return mp;
-
-broken:
- free_mess(mp);
- return NULLMESS;
-}
-
-/*
- * Parse a message using lread(), optionally closing the lineio.
- * Returns 0 on success, 1 on failure.
- */
-static int
-parse(message *mp, lineio *l, int clunk)
-{
- char *p;
- int line;
-
- line = 0;
-
- while ((p = lread(l)) != NULLSTR)
- {
- line++;
-
- switch (*p)
- {
- case '\0':
- (void)free(p);
- break;
-
- case RFC_LWSP_1:
- case RFC_LWSP_2:
- if (line > 1)
- {
- vec_cat(&mp->ms_headers, concat("\n", p));
- (void)free(p);
- continue;
- }
- /* fall through */
-
- default:
- if (!rfc_header(p))
- {
- fprintf(stderr, "%s: \"%s\" line %d: warning: \"%s\" is not an RFC 822 header.\n", my_name, mp->ms_path, line, p);
- (void)free(p);
- break;
- }
-
- vec_str(&mp->ms_headers, p);
- continue;
- }
-
- break;
- }
-
- vec_str(&mp->ms_headers, NULLSTR);
-
- /*
- * Fake size, based on what was read.
- */
- if (mp->ms_size == 0)
- {
- char **h;
- char *s;
-
- for (h = mp->ms_headers.v_list; (s = *h) != NULLSTR; h++)
- mp->ms_size += strlen(s);
-
- if (p != NULLSTR)
- mp->ms_size++;
- }
-
- /*
- * Finished with lineio?
- */
- if (clunk == 0)
- return 0;
-
- if (lclose(l) == 0)
- {
- if (close(l->l_fd) != SYSERROR)
- return 0;
- }
- else
- (void)close(l->l_fd);
-
- return 1;
-
-}
-
-/*
- * Parse an RFC 822 message from a file descriptor, optionally returning
- * a lineio positioned to read the message body.
- */
-message *
-parse_fd(int fd, lineio *l)
-{
- message *mp;
- lineio mld;
- lineio *ml;
-
- ml = l ? l : &mld;
-
- if ((mp = new("", "", fd)) == NULLMESS)
- return mp;
-
- (void)lopen(ml, fd, LREAD);
-
- if (parse(mp, ml, l == 0))
- {
- free_mess(mp);
- mp = NULLMESS;
- }
-
- return mp;
-}
-
-/*
- * Parse an RFC 822 message from a file, optionally returning
- * a lineio positioned to read the message body.
- */
-message *
-parse_file(char *s, lineio *l)
-{
- message *mp;
- int fd;
- lineio mld;
- lineio *ml;
-
- if ((fd = open(s, O_RD)) == SYSERROR)
- return NULLMESS;
-
- ml = l ? l : &mld;
-
- if ((mp = new(s, "", fd)) == NULLMESS)
- return mp;
-
- (void)lopen(ml, fd, LREAD);
-
- if (parse(mp, ml, l == 0))
- {
- free_mess(mp);
- mp = NULLMESS;
- }
-
- return mp;
-}
-
-
-/*
- * Parse an RFC 822 message from a box.
- */
-message *
-read_mess(mbox *mb, char *id)
-{
- message *mp;
- int fd;
- lineio mld;
- lineio *ml;
- char *p;
-
- ml = &mld;
-
- p = concat3(mb->m_path, "/", id);
-
- if ((fd = open(p, O_RD)) == SYSERROR)
- return NULLMESS;
-
- (void)lopen(ml, fd, LREAD);
-
- if ((mp = new(p, id, fd)) == NULLMESS)
- return mp;
-
- if (parse(mp, ml, 1))
- {
- free_mess(mp);
- mp = NULLMESS;
- }
-
- return mp;
-}
-
-int
-set_current(b, m)
-register char *b;
-register char *m;
-{
- register char *f;
-
- if (!valid_id(m))
- {
- fprintf(stderr, "%s: \"%s\" is not a valid message id.\n", my_name, m);
- return 1;
- }
-
- if ((b = check_box(b)) == NULLSTR)
- {
- fprintf(stderr, "%s: No such box as \"%s\".\n", my_name, b);
- return 1;
- }
-
- f = concat3(b, "/", MESSID);
-
- (void)free(b);
-
- if (write_file(f, m))
- {
- would_not("write", f);
- (void)free(f);
- return 1;
- }
-
- (void)free(f);
- return 0;
-}
-
-/*
- * Print an `n' character field turning new-lines into `~' and
- * mashing tabs into spaces (a necessary evil).
- */
-static void
-lprintn(p, n)
-register char *p;
-register int n;
-{
- while (n-- > 0)
- {
- register char c;
-
- switch ((c = *p))
- {
- case '\0':
- putchar(' ');
- continue;
-
- case '\n':
- putchar('~');
- break;
-
- case '\t':
- putchar(' ');
- break;
-
- default:
- putchar(c);
- break;
- }
-
- p++;
- }
-}
-
-/*
- * Print a one line message summary.
- */
-void
-print_summary(box, id, h, current, copies, to, state)
-char *box;
-char *id;
-register char **h;
-int current;
-int copies;
-int to;
-int state;
-{
- register char *p;
- register char **n;
- char cc;
-
- if (current)
- cc = (state & MESG_MARK) != 0 ? '=' : '-';
- else if ((state & MESG_MARK) != 0)
- cc = '\'';
- else
- cc = ' ';
-
- printf
- (
- "%c %c%s %s %c%c%c ",
- (state & (MESG_SENT|MESG_COMP)) == MESG_COMP ? '+' : '-',
- BOX_CHAR,
- box,
- id,
- cc,
- copies > 1 ? '?' : ' ',
- (state & MESG_SENT) != 0 ? '|' : ' '
- );
-
- if ((n = find_header(h, to ? RFC_TO : RFC_FROM)) == (char **)0 || (p = header_text(*n)) == NULLSTR)
- p = "";
-
- lprintn(p, 16);
- putchar(' ');
-
- if ((n = find_header(h, RFC_DATE)) == (char **)0 || (p = header_text(*n)) == NULLSTR)
- p = "";
-
- lprintn(p, 16);
- putchar(' ');
-
- if ((n = find_header(h, RFC_SUBJECT)) != (char **)0 && (p = header_text(*n)) != NULLSTR)
- {
- putchar('"');
- lprintn(p, strlen(p));
- putchar('"');
- }
-
- printf("\n");
-}
-
-int
-set_state(m, s)
-register char *m;
-register int s;
-{
- struct stat statb;
-
- if (stat(m, &statb) == SYSERROR)
- {
- would_not("stat", m);
- return 1;
- }
-
- if (chmod(m, statb.st_mode | s) == SYSERROR)
- {
- would_not("chmod", m);
- return 1;
- }
-
- return 0;
-}
-
-int
-clear_state(m, s)
-register char *m;
-register int s;
-{
- struct stat statb;
-
- if (stat(m, &statb) == SYSERROR)
- {
- would_not("stat", m);
- return 1;
- }
-
- if (chmod(m, statb.st_mode & ~s) == SYSERROR)
- {
- would_not("chmod", m);
- return 1;
- }
-
- return 0;
-}
-
-/*
- * Convert a mailbox/message pair into a pathname.
- */
-char *
-mess_to_path(mb, m)
-register mbox *mb;
-register char *m;
-{
- return concat3(mb->m_path, "/", m);
-}
-
-/*
- * Convert a pathname into a mailbox/message name pair.
- */
-void
-path_to_mess(p, b, m)
-register char *p;
-register char **b;
-register char **m;
-{
- static int l = 0;
-
- if (l == 0)
- l = strlen(mace_dir());
-
- *b = newstr(&p[l + 1]);
-
- for (p = *b; *p != '/'; p++)
- ;
-
- *p++ = '\0';
- *m = p;
-}
//GO.SYSIN DD mess.c
echo misc.c
sed 's/.//' >misc.c <<'//GO.SYSIN DD misc.c'
-/*
- * Miscellaneous stuff.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)misc.c 1.28";
-#endif lint
-
-#include "mace.h"
-#include <stdio.h>
-
-/*
- * Returns the login name of the current user.
- *
- * This is nasty and can allow forgery, but who cares?
- *
- * Returns static data.
- */
-char *
-user_id()
-{
- register char *p;
- extern char *getenv();
-
- if ((p = getenv(ENV_USER)) == NULLSTR)
- {
- fprintf(stderr, "%s: Who are you? \"$%s\" not set.\n", my_name, ENV_USER);
- exit(1);
- /* NOTREACHED */
- }
-
- return p;
-}
-
-/*
- * Returns the name of the current user.
- *
- * This is nasty and can allow forgery, but who cares?
- *
- * Returns static data.
- */
-char *
-user_name()
-{
- extern char *getenv();
-
- return getenv(ENV_NAME);
-}
-
-/*
- * Return an environment variable or its default.
- */
-char *
-defenv(s, d)
-register char *s;
-register char *d;
-{
- register char *e;
- extern char *getenv();
-
- return (e = getenv(s)) != NULLSTR ? e : d;
-}
//GO.SYSIN DD misc.c
echo name.c
sed 's/.//' >name.c <<'//GO.SYSIN DD name.c'
-/*
- * Initialise my_name.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)name.c 1.30";
-#endif lint
-
-#include <stdio.h>
-#include "mace.h"
-
-char *my_name;
-
-void
-name(s)
-register char *s;
-{
- my_name = basename(s);
-}
//GO.SYSIN DD name.c
echo pipe.c
sed 's/.//' >pipe.c <<'//GO.SYSIN DD pipe.c'
-/*
- * Pipe to/from a process.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)pipe.c 1.31";
-#endif lint
-
-#include "mace.h"
-#include <signal.h>
-
-typedef struct
-{
- int p_pid;
- int p_stat;
- int p_xstat;
-}
- pstat;
-
-#define SRUN 1
-#define SZOMB 2
-
-static pstat pipes[NPIPES];
-
-/*
- * Set up a pipe.
- */
-static int
-pipe_action(s, v, rw)
-register char *s;
-register char *v[];
-register char rw;
-{
- register pstat *p;
- register int read;
- register char *x;
- int fds[2];
-
- if (s != NULLSTR && v != (char **)0)
- {
- fatal("pipe_action");
- /* NOTREACHED */
- }
-
- if (pipe(fds) == SYSERROR)
- return SYSERROR;
-
- if (fds[0] >= NPIPES || fds[1] >= NPIPES)
- {
- fatal("pipe_open");
- /* NOTREACHED */
- }
-
- read = rw == 'r';
- p = &pipes[fds[!read]];
- p->p_stat = SRUN;
-
- switch (p->p_pid = fork())
- {
- case SYSERROR:
- return SYSERROR;
-
- case 0:
- if
- (
- close(read) == SYSERROR
- ||
- dup(fds[read]) != read
- ||
- close(fds[0]) == SYSERROR
- ||
- close(fds[1]) == SYSERROR
- )
- {
- could_not("pipe", s);
- /* NOTREACHED */
- }
-
- if (s != NULLSTR)
- {
- x = defenv(ENV_SHELL, DEF_SHELL);
-
- execl(x, basename(x), "-c", s, NULLSTR);
- could_not("exec", s);
- }
- else
- {
- execv(v[0], v);
- could_not("exec", v[0]);
- }
-
- /* NOTREACHED */
-
- default:
- if (close(fds[read]) == SYSERROR)
- {
- (void)close(fds[!read]);
- p->p_stat = 0;
- return SYSERROR;
- }
-
- (void)signal(SIGPIPE, SIG_IGN);
-
- return fds[!read];
- }
-}
-
-/*
- * Pipe to a shell command.
- */
-int
-pipe_open(s, rw)
-register char *s;
-register char rw;
-{
- return pipe_action(s, (char **)0, rw);
-}
-
-/*
- * Pipe to an argument vector.
- */
-int
-pipe_execv(v, rw)
-register char *v[];
-register char rw;
-{
- return pipe_action(NULLSTR, v, rw);
-}
-
-int
-pipe_close(fd)
-register int fd;
-{
- register pstat *p;
- register int i;
- int xstat;
-
- if (fd < 0 || fd >= NPIPES)
- return SYSERROR;
-
- p = &pipes[fd];
- (void)close(fd);
-
- switch (p->p_stat)
- {
- case SRUN:
- wait_some_more:
- while ((i = wait(&xstat)) != p->p_pid)
- {
- register pstat *pp;
-
- if (i == SYSERROR)
- {
- fatal("pipe_wait");
- /* NOTREACHED */
- }
-
- for (pp = pipes; pp < &pipes[NPIPES]; pp++)
- {
- if (pp->p_stat == SRUN && pp->p_pid == i)
- {
- pp->p_stat = SZOMB;
- pp->p_xstat = xstat;
- goto wait_some_more;
- }
- }
-
- fatal("pipe_zombie");
- /* NOTREACHED */
- }
-
- p->p_stat = SZOMB;
- p->p_xstat = xstat;
- /* fall thru... */
-
- case SZOMB:
- p->p_stat = 0;
- return p->p_xstat;
-
- default:
- return SYSERROR;
- }
-}
//GO.SYSIN DD pipe.c
echo re.c
sed 's/.//' >re.c <<'//GO.SYSIN DD re.c'
-/*
- * Regular expression hooks.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)re.c 1.6";
-#endif lint
-
-#include "mace.h"
-
-char *re_error; /* regexp error string */
-
-/*
- * Save a regexp error message.
- */
-void
-regerror(msg)
-char *msg;
-{
- re_error = msg;
-}
//GO.SYSIN DD re.c
echo readdir.c
sed 's/.//' >readdir.c <<'//GO.SYSIN DD readdir.c'
-/*
- * Read a directory & return its files as a vector of strings.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)readdir.c 1.33";
-#endif lint
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include "mace.h"
-#if DIRECTORY_3
-#if V9_DIRECTORY_3
-#include <ndir.h>
-#else V9_DIRECTORY_3
-#if DEC_DIRECTORY_3
-#include <dirent.h>
-#else DEC_DIRECTORY_3
-#include <sys/dir.h>
-#endif DEC_DIRECTORY_3
-#endif V9_DIRECTORY_3
-#else DIRECTORY_3
-#include <sys/dir.h>
-#endif DIRECTORY_3
-
-#if DIRECTORY_3
-
-/*
- * Read the directory using directory(3).
- */
-static char **
-directory_3(f)
-register char *f;
-{
- register DIR *dirp;
-#if DEC_DIRECTORY_3
- register struct dirent *dp;
-#else DEC_DIRECTORY_3
- register struct direct *dp;
-#endif DEC_DIRECTORY_3
- register int i;
- register char **v;
- vec slots;
-
- if ((dirp = opendir(f)) == (DIR *)0)
- {
- could_not("open", f);
- /* NOTREACHED */
- }
-
- vec_init(&slots, 64);
-
-#if DEC_DIRECTORY_3
- while ((dp = readdir(dirp)) != (struct dirent *)0)
-#else DEC_DIRECTORY_3
- while ((dp = readdir(dirp)) != (struct direct *)0)
-#endif DEC_DIRECTORY_3
- {
- if (dp->d_name[0] == SPEC_CHAR || dp->d_name[0] == '.')
- continue;
-
- vec_str(&slots, newstr(&dp->d_name[0]));
- }
-
- closedir(dirp);
-
- v = (char **)salloc((slots.v_count + 1) * sizeof(char *));
-
- for (i = 0; i < slots.v_count; i++)
- v[i] = newstr(slots.v_list[i]);
-
- v[i++] = NULLSTR;
-
- vec_free(&slots);
-
- return v;
-}
-
-#endif DIRECTORY_3
-
-char **
-read_dir(f)
-char *f;
-{
-#if !DIRECTORY_3
- register int fd;
- register int slot;
- register struct direct *dp;
- char *s;
-#endif !DIRECTORY_3
- register char **v;
- struct stat statb;
-
-#if DIRECTORY_3
-
- if (stat(f, &statb) == SYSERROR)
- {
- could_not("stat", f);
- /* NOTREACHED */
- }
-
-#else DIRECTORY_3
-
- if ((fd = open(f, O_RDONLY)) == SYSERROR)
- {
- could_not("open", f);
- /* NOTREACHED */
- }
-
- if (fstat(fd, &statb) == SYSERROR)
- {
- could_not("stat", f);
- /* NOTREACHED */
- }
-
-#endif DIRECTORY_3
-
- if ((statb.st_mode & S_IFMT) != S_IFDIR)
- {
- fprintf(stderr, "%s: \"%s\" is not a directory.\n", my_name, f);
- exit(1);
- /* NOTREACHED */
- }
-
-#if DIRECTORY_3
-
- v = directory_3(f);
-
-#else DIRECTORY_3
-
- s = salloc((int)statb.st_size);
-
-#if BSD_DIR
- v = (char **)salloc((int)((statb.st_size / (sizeof(struct direct) - (MAXNAMLEN + 1))) + 1) * sizeof(char *));
-#else BSD_DIR
- v = (char **)salloc((int)((statb.st_size / sizeof(struct direct)) + 1) * sizeof(char *));
-#endif BSD_DIR
-
- if (read(fd, s, (int)statb.st_size) != (int)statb.st_size)
- {
- could_not("read", f);
- /* NOTREACHED */
- }
-
- for
- (
- slot = 0, dp = (struct direct *)s;
- dp < (struct direct *)&s[statb.st_size];
-#if BSD_DIR
- dp = (struct direct *)((char *)dp + dp->d_reclen)
-#else BSD_DIR
- dp++
-#endif BSD_DIR
- )
- {
- if (dp->d_ino == 0 || dp->d_name[0] == SPEC_CHAR || dp->d_name[0] == '.')
- continue;
-
-#if BSD_DIR
- v[slot++] = newstr(&dp->d_name[0]);
-#else BSD_DIR
- v[slot] = salloc(DIRSIZ + 1);
- bcopy(&dp->d_name[0], v[slot], DIRSIZ);
- v[slot++][DIRSIZ] = '\0';
-#endif BSD_DIR
- }
-
- v[slot] = NULLSTR;
-
- if (close(fd) == SYSERROR)
- {
- could_not("close", f);
- /* NOTREACHED */
- }
-
- (void)free(s);
-
-#endif DIRECTORY_3
-
- return v;
-}
-
-void
-free_dir(v)
-register char **v;
-{
- register char **n;
-
- for (n = v; *n != NULLSTR; n++)
- (void)free(*n);
-
- (void)free((char *)v);
-}
//GO.SYSIN DD readdir.c
echo readfile.c
sed 's/.//' >readfile.c <<'//GO.SYSIN DD readfile.c'
-/*
- * Read a named file & return it's contents.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)readfile.c 1.31";
-#endif lint
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include "mace.h"
-
-char *
-read_file(f)
-char *f;
-{
- register int fd;
- char *s;
- struct stat statb;
-
- if ((fd = open(f, O_RDONLY)) == SYSERROR)
- return NULLSTR;
-
- if (fstat(fd, &statb) == SYSERROR)
- {
- could_not("stat", f);
- /* NOTREACHED */
- }
-
- if ((statb.st_mode & S_IFMT) != S_IFREG)
- {
- fprintf(stderr, "%s: \"%s\" is not a regular file.\n", my_name, f);
- exit(1);
- /* NOTREACHED */
- }
-
- s = salloc((int)statb.st_size + 1);
-
- if (statb.st_size != 0)
- {
- if (read(fd, s, (int)statb.st_size) != (int)statb.st_size)
- {
- could_not("read", f);
- /* NOTREACHED */
- }
-
- if (s[statb.st_size - 1] == '\n')
- s[statb.st_size - 1] = '\0';
- else
- s[statb.st_size] = '\0';
- }
- else
- s[0] = '\0';
-
- if (close(fd) == SYSERROR)
- {
- could_not("close", f);
- /* NOTREACHED */
- }
-
- return s;
-}
//GO.SYSIN DD readfile.c
echo readpass.c
sed 's/.//' >readpass.c <<'//GO.SYSIN DD readpass.c'
-/*
- * @(#)readpass.c 1.1
- *
- * Read a password from /dev/tty. Looks like getpass(3) but
- * accepts an arbitarily long password.
- */
-
-#include "mace.h"
-#include "flex.h"
-#include "tty.h"
-#include <signal.h>
-
-#define DEV_TTY "/dev/tty"
-
-/*
- * Catch a signal and do nothing.
- */
-static SIG_RET
-catch(int s)
-{
-}
-
-/*
- * Prompt for an arbitary length password and read it.
- */
-char *
-readpass(char *prompt)
-{
- int fd;
- int l;
- static flex f = { NULLSTR, NULLSTR, NULLSTR, };
- int echo;
- char c;
- SIG_RET (*int_sig)();
- SIG_RET (*quit_sig)();
-
- echo = 0;
-
- if (f.f_str == NULLSTR)
- flex_init(&f);
-
- if ((fd = open(DEV_TTY, O_RW)) == SYSERROR)
- return NULLSTR;
-
- /*
- * Catch signals so read will return with errno == EINTR.
- */
- if ((int_sig = signal(SIGINT, catch)) != SIG_DFL)
- signal(SIGINT, int_sig);
-
- if ((quit_sig = signal(SIGQUIT, catch)) != SIG_DFL)
- quit_sig = signal(SIGQUIT, catch);
-
- /*
- * Turn off echo.
- */
- if
- (
- (echo = ttyechoing(fd)) == SYSERROR
- ||
- (echo && ttyecho(fd, 0) == SYSERROR)
- )
- goto end;
-
- /*
- * Write prompt.
- */
- l = strlen(prompt);
-
- while (l > 0)
- {
- int n;
-
- if ((n = write(fd, prompt, l)) == SYSERROR)
- goto end;
-
- prompt += n;
- l -= n;
- }
-
- /*
- * Read password.
- */
- for (;;)
- {
- int n;
-
- /*
- * Do read(..., ..., 1) to avoid canon state.
- */
- switch (n = read(fd, &c, 1))
- {
- case 0:
- flex_char(&f, '\0');
- break;
-
- case 1:
- if (c == '\n')
- {
- flex_char(&f, '\0');
-
- if (echo)
- write(fd, &c, 1);
-
- break;
- }
-
- flex_char(&f, c);
- continue;
-
- case SYSERROR:
- default:
- f.f_ptr = f.f_str;
- break;
- }
-
- break;
- }
-
-end:
- /*
- * Restore echo to previous state.
- */
- if (echo)
- ttyecho(fd, 1);
-
- close(fd);
-
- /*
- * Restore signals.
- */
- if (int_sig != SIG_DFL)
- signal(SIGINT, int_sig);
-
- if (quit_sig != SIG_DFL)
- signal(SIGQUIT, quit_sig);
-
- /*
- * Errored?
- */
- if (f.f_ptr == f.f_str)
- return NULLSTR;
-
- flex_end(&f);
- return f.f_str;
-}
//GO.SYSIN DD readpass.c
echo regexp.c
sed 's/.//' >regexp.c <<'//GO.SYSIN DD regexp.c'
-/*
- * regcomp and regexec -- regsub and regerror are elsewhere
- *
- * Copyright (c) 1986 by University of Toronto.
- * Written by Henry Spencer. Not derived from licensed software.
- *
- * Permission is granted to anyone to use this software for any
- * purpose on any computer system, and to redistribute it freely,
- * subject to the following restrictions:
- *
- * 1. The author is not responsible for the consequences of use of
- * this software, no matter how awful, even if they arise
- * from defects in it.
- *
- * 2. The origin of this software must not be misrepresented, either
- * by explicit claim or by omission.
- *
- * 3. Altered versions must be plainly marked as such, and must not
- * be misrepresented as being the original software.
- *
- * Beware that some of this code is subtly aware of the way operator
- * precedence is structured in regular expressions. Serious changes in
- * regular-expression syntax might require a total rethink.
- *
- * Snarfed to be part of "mace" but not modified save
- * for the odd include & sccsid.
- * -- Boyd Roberts
- * May '89
- */
-#ifndef lint
-static char sccsid[] = "@(#)regexp.c 1.6";
-#endif lint
-
-#include "mace.h"
-#include <stdio.h>
-#include "regexp.h"
-#include "regmagic.h"
-
-/*
- * The "internal use only" fields in regexp.h are present to pass info from
- * compile to execute that permits the execute phase to run lots faster on
- * simple cases. They are:
- *
- * regstart char that must begin a match; '\0' if none obvious
- * reganch is the match anchored (at beginning-of-line only)?
- * regmust string (pointer into program) that match must include, or NULL
- * regmlen length of regmust string
- *
- * Regstart and reganch permit very fast decisions on suitable starting points
- * for a match, cutting down the work a lot. Regmust permits fast rejection
- * of lines that cannot possibly match. The regmust tests are costly enough
- * that regcomp() supplies a regmust only if the r.e. contains something
- * potentially expensive (at present, the only such thing detected is * or +
- * at the start of the r.e., which can involve a lot of backup). Regmlen is
- * supplied because the test in regexec() needs it and regcomp() is computing
- * it anyway.
- */
-
-/*
- * Structure for regexp "program". This is essentially a linear encoding
- * of a nondeterministic finite-state machine (aka syntax charts or
- * "railroad normal form" in parsing technology). Each node is an opcode
- * plus a "next" pointer, possibly plus an operand. "Next" pointers of
- * all nodes except BRANCH implement concatenation; a "next" pointer with
- * a BRANCH on both ends of it is connecting two alternatives. (Here we
- * have one of the subtle syntax dependencies: an individual BRANCH (as
- * opposed to a collection of them) is never concatenated with anything
- * because of operator precedence.) The operand of some types of node is
- * a literal string; for others, it is a node leading into a sub-FSM. In
- * particular, the operand of a BRANCH node is the first node of the branch.
- * (NB this is *not* a tree structure: the tail of the branch connects
- * to the thing following the set of BRANCHes.) The opcodes are:
- */
-
-/* definition number opnd? meaning */
-#define END 0 /* no End of program. */
-#define BOL 1 /* no Match "" at beginning of line. */
-#define EOL 2 /* no Match "" at end of line. */
-#define ANY 3 /* no Match any one character. */
-#define ANYOF 4 /* str Match any character in this string. */
-#define ANYBUT 5 /* str Match any character not in this string. */
-#define BRANCH 6 /* node Match this alternative, or the next... */
-#define BACK 7 /* no Match "", "next" ptr points backward. */
-#define EXACTLY 8 /* str Match this string. */
-#define NOTHING 9 /* no Match empty string. */
-#define STAR 10 /* node Match this (simple) thing 0 or more times. */
-#define PLUS 11 /* node Match this (simple) thing 1 or more times. */
-#define OPEN 20 /* no Mark this point in input as start of #n. */
- /* OPEN+1 is number 1, etc. */
-#define CLOSE 30 /* no Analogous to OPEN. */
-
-/*
- * Opcode notes:
- *
- * BRANCH The set of branches constituting a single choice are hooked
- * together with their "next" pointers, since precedence prevents
- * anything being concatenated to any individual branch. The
- * "next" pointer of the last BRANCH in a choice points to the
- * thing following the whole choice. This is also where the
- * final "next" pointer of each individual branch points; each
- * branch starts with the operand node of a BRANCH node.
- *
- * BACK Normal "next" pointers all implicitly point forward; BACK
- * exists to make loop structures possible.
- *
- * STAR,PLUS '?', and complex '*' and '+', are implemented as circular
- * BRANCH structures using BACK. Simple cases (one character
- * per match) are implemented with STAR and PLUS for speed
- * and to minimize recursive plunges.
- *
- * OPEN,CLOSE ...are numbered at compile time.
- */
-
-/*
- * A node is one char of opcode followed by two chars of "next" pointer.
- * "Next" pointers are stored as two 8-bit pieces, high order first. The
- * value is a positive offset from the opcode of the node containing it.
- * An operand, if any, simply follows the node. (Note that much of the
- * code generation knows about this implicit relationship.)
- *
- * Using two bytes for the "next" pointer is vast overkill for most things,
- * but allows patterns to get big without disasters.
- */
-#define OP(p) (*(p))
-#define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
-#define OPERAND(p) ((p) + 3)
-
-/*
- * See regmagic.h for one further detail of program structure.
- */
-
-
-/*
- * Utility definitions.
- */
-#ifndef CHARBITS
-#define UCHARAT(p) ((int)*(unsigned char *)(p))
-#else
-#define UCHARAT(p) ((int)*(p)&CHARBITS)
-#endif
-
-#define FAIL(m) { regerror(m); return(NULL); }
-#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?')
-#define META "^$.[()|?+*\\"
-
-/*
- * Flags to be passed up and down.
- */
-#define HASWIDTH 01 /* Known never to match null string. */
-#define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */
-#define SPSTART 04 /* Starts with * or +. */
-#define WORST 0 /* Worst case. */
-
-/*
- * Global work variables for regcomp().
- */
-static char *regparse; /* Input-scan pointer. */
-static int regnpar; /* () count. */
-static char regdummy;
-static char *regcode; /* Code-emit pointer; ®dummy = don't. */
-static long regsize; /* Code size. */
-
-/*
- * Forward declarations for regcomp()'s friends.
- */
-#ifndef STATIC
-#define STATIC static
-#endif
-STATIC char *reg();
-STATIC char *regbranch();
-STATIC char *regpiece();
-STATIC char *regatom();
-STATIC char *regnode();
-STATIC char *regnext();
-STATIC void regc();
-STATIC void reginsert();
-STATIC void regtail();
-STATIC void regoptail();
-#ifdef STRCSPN
-STATIC int strcspn();
-#endif
-
-/*
- - regcomp - compile a regular expression into internal code
- *
- * We can't allocate space until we know how big the compiled form will be,
- * but we can't compile it (and thus know how big it is) until we've got a
- * place to put the code. So we cheat: we compile it twice, once with code
- * generation turned off and size counting turned on, and once "for real".
- * This also means that we don't allocate space until we are sure that the
- * thing really will compile successfully, and we never have to move the
- * code and thus invalidate pointers into it. (Note that it has to be in
- * one piece because free() must be able to free it all.)
- *
- * Beware that the optimization-preparation code in here knows about some
- * of the structure of the compiled regexp.
- */
-regexp *
-regcomp(exp)
-char *exp;
-{
- register regexp *r;
- register char *scan;
- register char *longest;
- register int len;
- int flags;
- extern char *malloc();
-
- if (exp == NULL)
- FAIL("NULL argument");
-
- /* First pass: determine size, legality. */
- regparse = exp;
- regnpar = 1;
- regsize = 0L;
- regcode = ®dummy;
- regc(MAGIC);
- if (reg(0, &flags) == NULL)
- return(NULL);
-
- /* Small enough for pointer-storage convention? */
- if (regsize >= 32767L) /* Probably could be 65535L. */
- FAIL("regexp too big");
-
- /* Allocate space. */
- r = (regexp *)malloc(sizeof(regexp) + (unsigned)regsize);
- if (r == NULL)
- FAIL("out of space");
-
- /* Second pass: emit code. */
- regparse = exp;
- regnpar = 1;
- regcode = r->program;
- regc(MAGIC);
- if (reg(0, &flags) == NULL)
- return(NULL);
-
- /* Dig out information for optimizations. */
- r->regstart = '\0'; /* Worst-case defaults. */
- r->reganch = 0;
- r->regmust = NULL;
- r->regmlen = 0;
- scan = r->program+1; /* First BRANCH. */
- if (OP(regnext(scan)) == END) { /* Only one top-level choice. */
- scan = OPERAND(scan);
-
- /* Starting-point info. */
- if (OP(scan) == EXACTLY)
- r->regstart = *OPERAND(scan);
- else if (OP(scan) == BOL)
- r->reganch++;
-
- /*
- * If there's something expensive in the r.e., find the
- * longest literal string that must appear and make it the
- * regmust. Resolve ties in favor of later strings, since
- * the regstart check works with the beginning of the r.e.
- * and avoiding duplication strengthens checking. Not a
- * strong reason, but sufficient in the absence of others.
- */
- if (flags&SPSTART) {
- longest = NULL;
- len = 0;
- for (; scan != NULL; scan = regnext(scan))
- if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
- longest = OPERAND(scan);
- len = strlen(OPERAND(scan));
- }
- r->regmust = longest;
- r->regmlen = len;
- }
- }
-
- return(r);
-}
-
-/*
- - reg - regular expression, i.e. main body or parenthesized thing
- *
- * Caller must absorb opening parenthesis.
- *
- * Combining parenthesis handling with the base level of regular expression
- * is a trifle forced, but the need to tie the tails of the branches to what
- * follows makes it hard to avoid.
- */
-static char *
-reg(paren, flagp)
-int paren; /* Parenthesized? */
-int *flagp;
-{
- register char *ret;
- register char *br;
- register char *ender;
- register int parno;
- int flags;
-
- *flagp = HASWIDTH; /* Tentatively. */
-
- /* Make an OPEN node, if parenthesized. */
- if (paren) {
- if (regnpar >= NSUBEXP)
- FAIL("too many ()");
- parno = regnpar;
- regnpar++;
- ret = regnode(OPEN+parno);
- } else
- ret = NULL;
-
- /* Pick up the branches, linking them together. */
- br = regbranch(&flags);
- if (br == NULL)
- return(NULL);
- if (ret != NULL)
- regtail(ret, br); /* OPEN -> first. */
- else
- ret = br;
- if (!(flags&HASWIDTH))
- *flagp &= ~HASWIDTH;
- *flagp |= flags&SPSTART;
- while (*regparse == '|') {
- regparse++;
- br = regbranch(&flags);
- if (br == NULL)
- return(NULL);
- regtail(ret, br); /* BRANCH -> BRANCH. */
- if (!(flags&HASWIDTH))
- *flagp &= ~HASWIDTH;
- *flagp |= flags&SPSTART;
- }
-
- /* Make a closing node, and hook it on the end. */
- ender = regnode((paren) ? CLOSE+parno : END);
- regtail(ret, ender);
-
- /* Hook the tails of the branches to the closing node. */
- for (br = ret; br != NULL; br = regnext(br))
- regoptail(br, ender);
-
- /* Check for proper termination. */
- if (paren && *regparse++ != ')') {
- FAIL("unmatched ()");
- } else if (!paren && *regparse != '\0') {
- if (*regparse == ')') {
- FAIL("unmatched ()");
- } else
- FAIL("junk on end"); /* "Can't happen". */
- /* NOTREACHED */
- }
-
- return(ret);
-}
-
-/*
- - regbranch - one alternative of an | operator
- *
- * Implements the concatenation operator.
- */
-static char *
-regbranch(flagp)
-int *flagp;
-{
- register char *ret;
- register char *chain;
- register char *latest;
- int flags;
-
- *flagp = WORST; /* Tentatively. */
-
- ret = regnode(BRANCH);
- chain = NULL;
- while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
- latest = regpiece(&flags);
- if (latest == NULL)
- return(NULL);
- *flagp |= flags&HASWIDTH;
- if (chain == NULL) /* First piece. */
- *flagp |= flags&SPSTART;
- else
- regtail(chain, latest);
- chain = latest;
- }
- if (chain == NULL) /* Loop ran zero times. */
- (void) regnode(NOTHING);
-
- return(ret);
-}
-
-/*
- - regpiece - something followed by possible [*+?]
- *
- * Note that the branching code sequences used for ? and the general cases
- * of * and + are somewhat optimized: they use the same NOTHING node as
- * both the endmarker for their branch list and the body of the last branch.
- * It might seem that this node could be dispensed with entirely, but the
- * endmarker role is not redundant.
- */
-static char *
-regpiece(flagp)
-int *flagp;
-{
- register char *ret;
- register char op;
- register char *next;
- int flags;
-
- ret = regatom(&flags);
- if (ret == NULL)
- return(NULL);
-
- op = *regparse;
- if (!ISMULT(op)) {
- *flagp = flags;
- return(ret);
- }
-
- if (!(flags&HASWIDTH) && op != '?')
- FAIL("*+ operand could be empty");
- *flagp = (op != '+') ? (WORST|SPSTART) : (WORST|HASWIDTH);
-
- if (op == '*' && (flags&SIMPLE))
- reginsert(STAR, ret);
- else if (op == '*') {
- /* Emit x* as (x&|), where & means "self". */
- reginsert(BRANCH, ret); /* Either x */
- regoptail(ret, regnode(BACK)); /* and loop */
- regoptail(ret, ret); /* back */
- regtail(ret, regnode(BRANCH)); /* or */
- regtail(ret, regnode(NOTHING)); /* null. */
- } else if (op == '+' && (flags&SIMPLE))
- reginsert(PLUS, ret);
- else if (op == '+') {
- /* Emit x+ as x(&|), where & means "self". */
- next = regnode(BRANCH); /* Either */
- regtail(ret, next);
- regtail(regnode(BACK), ret); /* loop back */
- regtail(next, regnode(BRANCH)); /* or */
- regtail(ret, regnode(NOTHING)); /* null. */
- } else if (op == '?') {
- /* Emit x? as (x|) */
- reginsert(BRANCH, ret); /* Either x */
- regtail(ret, regnode(BRANCH)); /* or */
- next = regnode(NOTHING); /* null. */
- regtail(ret, next);
- regoptail(ret, next);
- }
- regparse++;
- if (ISMULT(*regparse))
- FAIL("nested *?+");
-
- return(ret);
-}
-
-/*
- - regatom - the lowest level
- *
- * Optimization: gobbles an entire sequence of ordinary characters so that
- * it can turn them into a single node, which is smaller to store and
- * faster to run. Backslashed characters are exceptions, each becoming a
- * separate node; the code is simpler that way and it's not worth fixing.
- */
-static char *
-regatom(flagp)
-int *flagp;
-{
- register char *ret;
- int flags;
-
- *flagp = WORST; /* Tentatively. */
-
- switch (*regparse++) {
- case '^':
- ret = regnode(BOL);
- break;
- case '$':
- ret = regnode(EOL);
- break;
- case '.':
- ret = regnode(ANY);
- *flagp |= HASWIDTH|SIMPLE;
- break;
- case '[': {
- register int class;
- register int classend;
-
- if (*regparse == '^') { /* Complement of range. */
- ret = regnode(ANYBUT);
- regparse++;
- } else
- ret = regnode(ANYOF);
- if (*regparse == ']' || *regparse == '-')
- regc(*regparse++);
- while (*regparse != '\0' && *regparse != ']') {
- if (*regparse == '-') {
- regparse++;
- if (*regparse == ']' || *regparse == '\0')
- regc('-');
- else {
- class = UCHARAT(regparse-2)+1;
- classend = UCHARAT(regparse);
- if (class > classend+1)
- FAIL("invalid [] range");
- for (; class <= classend; class++)
- regc(class);
- regparse++;
- }
- } else
- regc(*regparse++);
- }
- regc('\0');
- if (*regparse != ']')
- FAIL("unmatched []");
- regparse++;
- *flagp |= HASWIDTH|SIMPLE;
- }
- break;
- case '(':
- ret = reg(1, &flags);
- if (ret == NULL)
- return(NULL);
- *flagp |= flags&(HASWIDTH|SPSTART);
- break;
- case '\0':
- case '|':
- case ')':
- FAIL("internal urp"); /* Supposed to be caught earlier. */
- break;
- case '?':
- case '+':
- case '*':
- FAIL("?+* follows nothing");
- break;
- case '\\':
- if (*regparse == '\0')
- FAIL("trailing \\");
- ret = regnode(EXACTLY);
- regc(*regparse++);
- regc('\0');
- *flagp |= HASWIDTH|SIMPLE;
- break;
- default: {
- register int len;
- register char ender;
-
- regparse--;
- len = strcspn(regparse, META);
- if (len <= 0)
- FAIL("internal disaster");
- ender = *(regparse+len);
- if (len > 1 && ISMULT(ender))
- len--; /* Back off clear of ?+* operand. */
- *flagp |= HASWIDTH;
- if (len == 1)
- *flagp |= SIMPLE;
- ret = regnode(EXACTLY);
- while (len > 0) {
- regc(*regparse++);
- len--;
- }
- regc('\0');
- }
- break;
- }
-
- return(ret);
-}
-
-/*
- - regnode - emit a node
- */
-static char * /* Location. */
-regnode(op)
-char op;
-{
- register char *ret;
- register char *ptr;
-
- ret = regcode;
- if (ret == ®dummy) {
- regsize += 3;
- return(ret);
- }
-
- ptr = ret;
- *ptr++ = op;
- *ptr++ = '\0'; /* Null "next" pointer. */
- *ptr++ = '\0';
- regcode = ptr;
-
- return(ret);
-}
-
-/*
- - regc - emit (if appropriate) a byte of code
- */
-static void
-regc(b)
-char b;
-{
- if (regcode != ®dummy)
- *regcode++ = b;
- else
- regsize++;
-}
-
-/*
- - reginsert - insert an operator in front of already-emitted operand
- *
- * Means relocating the operand.
- */
-static void
-reginsert(op, opnd)
-char op;
-char *opnd;
-{
- register char *src;
- register char *dst;
- register char *place;
-
- if (regcode == ®dummy) {
- regsize += 3;
- return;
- }
-
- src = regcode;
- regcode += 3;
- dst = regcode;
- while (src > opnd)
- *--dst = *--src;
-
- place = opnd; /* Op node, where operand used to be. */
- *place++ = op;
- *place++ = '\0';
- *place++ = '\0';
-}
-
-/*
- - regtail - set the next-pointer at the end of a node chain
- */
-static void
-regtail(p, val)
-char *p;
-char *val;
-{
- register char *scan;
- register char *temp;
- register int offset;
-
- if (p == ®dummy)
- return;
-
- /* Find last node. */
- scan = p;
- for (;;) {
- temp = regnext(scan);
- if (temp == NULL)
- break;
- scan = temp;
- }
-
- if (OP(scan) == BACK)
- offset = scan - val;
- else
- offset = val - scan;
- *(scan+1) = (offset>>8)&0377;
- *(scan+2) = offset&0377;
-}
-
-/*
- - regoptail - regtail on operand of first argument; nop if operandless
- */
-static void
-regoptail(p, val)
-char *p;
-char *val;
-{
- /* "Operandless" and "op != BRANCH" are synonymous in practice. */
- if (p == NULL || p == ®dummy || OP(p) != BRANCH)
- return;
- regtail(OPERAND(p), val);
-}
-
-/*
- * regexec and friends
- */
-
-/*
- * Global work variables for regexec().
- */
-static char *reginput; /* String-input pointer. */
-static char *regbol; /* Beginning of input, for ^ check. */
-static char **regstartp; /* Pointer to startp array. */
-static char **regendp; /* Ditto for endp. */
-
-/*
- * Forwards.
- */
-STATIC int regtry();
-STATIC int regmatch();
-STATIC int regrepeat();
-
-#ifdef DEBUG
-int regnarrate = 0;
-void regdump();
-STATIC char *regprop();
-#endif
-
-/*
- - regexec - match a regexp against a string
- */
-int
-regexec(prog, string)
-register regexp *prog;
-register char *string;
-{
- register char *s;
- extern char *strchr();
-
- /* Be paranoid... */
- if (prog == NULL || string == NULL) {
- regerror("NULL parameter");
- return(0);
- }
-
- /* Check validity of program. */
- if (UCHARAT(prog->program) != MAGIC) {
- regerror("corrupted program");
- return(0);
- }
-
- /* If there is a "must appear" string, look for it. */
- if (prog->regmust != NULL) {
- s = string;
- while ((s = strchr(s, prog->regmust[0])) != NULL) {
- if (strncmp(s, prog->regmust, prog->regmlen) == 0)
- break; /* Found it. */
- s++;
- }
- if (s == NULL) /* Not present. */
- return(0);
- }
-
- /* Mark beginning of line for ^ . */
- regbol = string;
-
- /* Simplest case: anchored match need be tried only once. */
- if (prog->reganch)
- return(regtry(prog, string));
-
- /* Messy cases: unanchored match. */
- s = string;
- if (prog->regstart != '\0')
- /* We know what char it must start with. */
- while ((s = strchr(s, prog->regstart)) != NULL) {
- if (regtry(prog, s))
- return(1);
- s++;
- }
- else
- /* We don't -- general case. */
- do {
- if (regtry(prog, s))
- return(1);
- } while (*s++ != '\0');
-
- /* Failure. */
- return(0);
-}
-
-/*
- - regtry - try match at specific point
- */
-static int /* 0 failure, 1 success */
-regtry(prog, string)
-regexp *prog;
-char *string;
-{
- register int i;
- register char **sp;
- register char **ep;
-
- reginput = string;
- regstartp = prog->startp;
- regendp = prog->endp;
-
- sp = prog->startp;
- ep = prog->endp;
- for (i = NSUBEXP; i > 0; i--) {
- *sp++ = NULL;
- *ep++ = NULL;
- }
- if (regmatch(prog->program + 1)) {
- prog->startp[0] = string;
- prog->endp[0] = reginput;
- return(1);
- } else
- return(0);
-}
-
-/*
- - regmatch - main matching routine
- *
- * Conceptually the strategy is simple: check to see whether the current
- * node matches, call self recursively to see whether the rest matches,
- * and then act accordingly. In practice we make some effort to avoid
- * recursion, in particular by going through "ordinary" nodes (that don't
- * need to know whether the rest of the match failed) by a loop instead of
- * by recursion.
- */
-static int /* 0 failure, 1 success */
-regmatch(prog)
-char *prog;
-{
- register char *scan; /* Current node. */
- char *next; /* Next node. */
- extern char *strchr();
-
- scan = prog;
-#ifdef DEBUG
- if (scan != NULL && regnarrate)
- fprintf(stderr, "%s(\n", regprop(scan));
-#endif
- while (scan != NULL) {
-#ifdef DEBUG
- if (regnarrate)
- fprintf(stderr, "%s...\n", regprop(scan));
-#endif
- next = regnext(scan);
-
- switch (OP(scan)) {
- case BOL:
- if (reginput != regbol)
- return(0);
- break;
- case EOL:
- if (*reginput != '\0')
- return(0);
- break;
- case ANY:
- if (*reginput == '\0')
- return(0);
- reginput++;
- break;
- case EXACTLY: {
- register int len;
- register char *opnd;
-
- opnd = OPERAND(scan);
- /* Inline the first character, for speed. */
- if (*opnd != *reginput)
- return(0);
- len = strlen(opnd);
- if (len > 1 && strncmp(opnd, reginput, len) != 0)
- return(0);
- reginput += len;
- }
- break;
- case ANYOF:
- if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == NULL)
- return(0);
- reginput++;
- break;
- case ANYBUT:
- if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != NULL)
- return(0);
- reginput++;
- break;
- case NOTHING:
- break;
- case BACK:
- break;
- case OPEN+1:
- case OPEN+2:
- case OPEN+3:
- case OPEN+4:
- case OPEN+5:
- case OPEN+6:
- case OPEN+7:
- case OPEN+8:
- case OPEN+9: {
- register int no;
- register char *save;
-
- no = OP(scan) - OPEN;
- save = reginput;
-
- if (regmatch(next)) {
- /*
- * Don't set startp if some later
- * invocation of the same parentheses
- * already has.
- */
- if (regstartp[no] == NULL)
- regstartp[no] = save;
- return(1);
- } else
- return(0);
- }
- break;
- case CLOSE+1:
- case CLOSE+2:
- case CLOSE+3:
- case CLOSE+4:
- case CLOSE+5:
- case CLOSE+6:
- case CLOSE+7:
- case CLOSE+8:
- case CLOSE+9: {
- register int no;
- register char *save;
-
- no = OP(scan) - CLOSE;
- save = reginput;
-
- if (regmatch(next)) {
- /*
- * Don't set endp if some later
- * invocation of the same parentheses
- * already has.
- */
- if (regendp[no] == NULL)
- regendp[no] = save;
- return(1);
- } else
- return(0);
- }
- break;
- case BRANCH: {
- register char *save;
-
- if (OP(next) != BRANCH) /* No choice. */
- next = OPERAND(scan); /* Avoid recursion. */
- else {
- do {
- save = reginput;
- if (regmatch(OPERAND(scan)))
- return(1);
- reginput = save;
- scan = regnext(scan);
- } while (scan != NULL && OP(scan) == BRANCH);
- return(0);
- /* NOTREACHED */
- }
- }
- break;
- case STAR:
- case PLUS: {
- register char nextch;
- register int no;
- register char *save;
- register int min;
-
- /*
- * Lookahead to avoid useless match attempts
- * when we know what character comes next.
- */
- nextch = '\0';
- if (OP(next) == EXACTLY)
- nextch = *OPERAND(next);
- min = (OP(scan) == STAR) ? 0 : 1;
- save = reginput;
- no = regrepeat(OPERAND(scan));
- while (no >= min) {
- /* If it could work, try it. */
- if (nextch == '\0' || *reginput == nextch)
- if (regmatch(next))
- return(1);
- /* Couldn't or didn't -- back up. */
- no--;
- reginput = save + no;
- }
- return(0);
- }
- break;
- case END:
- return(1); /* Success! */
- break;
- default:
- regerror("memory corruption");
- return(0);
- break;
- }
-
- scan = next;
- }
-
- /*
- * We get here only if there's trouble -- normally "case END" is
- * the terminating point.
- */
- regerror("corrupted pointers");
- return(0);
-}
-
-/*
- - regrepeat - repeatedly match something simple, report how many
- */
-static int
-regrepeat(p)
-char *p;
-{
- register int count = 0;
- register char *scan;
- register char *opnd;
-
- scan = reginput;
- opnd = OPERAND(p);
- switch (OP(p)) {
- case ANY:
- count = strlen(scan);
- scan += count;
- break;
- case EXACTLY:
- while (*opnd == *scan) {
- count++;
- scan++;
- }
- break;
- case ANYOF:
- while (*scan != '\0' && strchr(opnd, *scan) != NULL) {
- count++;
- scan++;
- }
- break;
- case ANYBUT:
- while (*scan != '\0' && strchr(opnd, *scan) == NULL) {
- count++;
- scan++;
- }
- break;
- default: /* Oh dear. Called inappropriately. */
- regerror("internal foulup");
- count = 0; /* Best compromise. */
- break;
- }
- reginput = scan;
-
- return(count);
-}
-
-/*
- - regnext - dig the "next" pointer out of a node
- */
-static char *
-regnext(p)
-register char *p;
-{
- register int offset;
-
- if (p == ®dummy)
- return(NULL);
-
- offset = NEXT(p);
- if (offset == 0)
- return(NULL);
-
- if (OP(p) == BACK)
- return(p-offset);
- else
- return(p+offset);
-}
-
-#ifdef DEBUG
-
-STATIC char *regprop();
-
-/*
- - regdump - dump a regexp onto stdout in vaguely comprehensible form
- */
-void
-regdump(r)
-regexp *r;
-{
- register char *s;
- register char op = EXACTLY; /* Arbitrary non-END op. */
- register char *next;
- extern char *strchr();
-
-
- s = r->program + 1;
- while (op != END) { /* While that wasn't END last time... */
- op = OP(s);
- printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */
- next = regnext(s);
- if (next == NULL) /* Next ptr. */
- printf("(0)");
- else
- printf("(%d)", (s-r->program)+(next-s));
- s += 3;
- if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
- /* Literal string, where present. */
- while (*s != '\0') {
- putchar(*s);
- s++;
- }
- s++;
- }
- putchar('\n');
- }
-
- /* Header fields of interest. */
- if (r->regstart != '\0')
- printf("start `%c' ", r->regstart);
- if (r->reganch)
- printf("anchored ");
- if (r->regmust != NULL)
- printf("must have \"%s\"", r->regmust);
- printf("\n");
-}
-
-/*
- - regprop - printable representation of opcode
- */
-static char *
-regprop(op)
-char *op;
-{
- register char *p;
- static char buf[50];
-
- (void) strcpy(buf, ":");
-
- switch (OP(op)) {
- case BOL:
- p = "BOL";
- break;
- case EOL:
- p = "EOL";
- break;
- case ANY:
- p = "ANY";
- break;
- case ANYOF:
- p = "ANYOF";
- break;
- case ANYBUT:
- p = "ANYBUT";
- break;
- case BRANCH:
- p = "BRANCH";
- break;
- case EXACTLY:
- p = "EXACTLY";
- break;
- case NOTHING:
- p = "NOTHING";
- break;
- case BACK:
- p = "BACK";
- break;
- case END:
- p = "END";
- break;
- case OPEN+1:
- case OPEN+2:
- case OPEN+3:
- case OPEN+4:
- case OPEN+5:
- case OPEN+6:
- case OPEN+7:
- case OPEN+8:
- case OPEN+9:
- sprintf(buf+strlen(buf), "OPEN%d", OP(op)-OPEN);
- p = NULL;
- break;
- case CLOSE+1:
- case CLOSE+2:
- case CLOSE+3:
- case CLOSE+4:
- case CLOSE+5:
- case CLOSE+6:
- case CLOSE+7:
- case CLOSE+8:
- case CLOSE+9:
- sprintf(buf+strlen(buf), "CLOSE%d", OP(op)-CLOSE);
- p = NULL;
- break;
- case STAR:
- p = "STAR";
- break;
- case PLUS:
- p = "PLUS";
- break;
- default:
- regerror("corrupted opcode");
- break;
- }
- if (p != NULL)
- (void) strcat(buf, p);
- return(buf);
-}
-#endif
-
-/*
- * The following is provided for those people who do not have strcspn() in
- * their C libraries. They should get off their butts and do something
- * about it; at least one public-domain implementation of those (highly
- * useful) string routines has been published on Usenet.
- */
-#ifdef STRCSPN
-/*
- * strcspn - find length of initial segment of s1 consisting entirely
- * of characters not from s2
- */
-
-static int
-strcspn(s1, s2)
-char *s1;
-char *s2;
-{
- register char *scan1;
- register char *scan2;
- register int count;
-
- count = 0;
- for (scan1 = s1; *scan1 != '\0'; scan1++) {
- for (scan2 = s2; *scan2 != '\0';) /* ++ moved down. */
- if (*scan1 == *scan2++)
- return(count);
- count++;
- }
- return(count);
-}
-#endif
//GO.SYSIN DD regexp.c
echo rfc.c
sed 's/.//' >rfc.c <<'//GO.SYSIN DD rfc.c'
-/*
- * Various RFC 822 compatibility routines.
- */
-
-#ifndef lint
-static char sccsid[] = "%W%";
-#endif lint
-
-#include "mace.h"
-#include "headers.h"
-#include "regexp.h"
-#include "line.h"
-#include "message.h"
-#include "conf.h"
-#include <time.h>
-
-#define ZONE_HOUR(h) ((h) * 60)
-#define YEAR_OFFSET 1900
-
-static char *days[] =
-{
- "Sun",
- "Mon",
- "Tue",
- "Wed",
- "Thu",
- "Fri",
- "Sat",
- NULLSTR,
-};
-
-static char *months[] =
-{
- "Jan",
- "Feb",
- "Mar",
- "Apr",
- "May",
- "Jun",
- "Jul",
- "Aug",
- "Sep",
- "Oct",
- "Nov",
- "Dec",
- NULLSTR,
-};
-
-typedef struct zone zone;
-
-struct zone
-{
- char *name;
- int offset;
-};
-
-static zone zones[] =
-{
- { "UT", ZONE_HOUR(0) }, /* UTC */
- { "GMT", ZONE_HOUR(0) }, /* GMT */
- /* North American */
- { "EST", ZONE_HOUR(-5) },
- { "EDT", ZONE_HOUR(-4) },
- { "CST", ZONE_HOUR(-6) },
- { "CDT", ZONE_HOUR(-5) },
- { "MST", ZONE_HOUR(-7) },
- { "MDT", ZONE_HOUR(-6) },
- { "PST", ZONE_HOUR(-8) },
- { "PDT", ZONE_HOUR(-7) },
- /* Military */
- { "A", ZONE_HOUR(-1) },
- { "B", ZONE_HOUR(-2) },
- { "C", ZONE_HOUR(-3) },
- { "D", ZONE_HOUR(-4) },
- { "E", ZONE_HOUR(-5) },
- { "F", ZONE_HOUR(-6) },
- { "G", ZONE_HOUR(-7) },
- { "H", ZONE_HOUR(-8) },
- { "I", ZONE_HOUR(-9) },
- { "K", ZONE_HOUR(-10) },
- { "L", ZONE_HOUR(-11) },
- { "M", ZONE_HOUR(-12) },
- { "N", ZONE_HOUR(1) },
- { "O", ZONE_HOUR(2) },
- { "P", ZONE_HOUR(3) },
- { "Q", ZONE_HOUR(4) },
- { "R", ZONE_HOUR(5) },
- { "S", ZONE_HOUR(6) },
- { "T", ZONE_HOUR(7) },
- { "U", ZONE_HOUR(8) },
- { "V", ZONE_HOUR(9) },
- { "X", ZONE_HOUR(10) },
- { "Y", ZONE_HOUR(11) },
- { "Z", ZONE_HOUR(0) },
- { NULLSTR, ZONE_HOUR(24) },
-};
-
-/*
- * Case independent strcmp().
- */
-int
-strcasecmp(char *s1, char *s2)
-{
- while (*s1 != '\0')
- {
- int c1;
- int c2;
-
- if (*s1 != *s2 && (c1 = tolower(*s1)) != (c2 = tolower(*s2)))
- return c1 < c2 ? -1 : 1;
-
- s1++;
- s2++;
- }
-
- return 0;
-}
-
-/*
- * Return the offset in minutes from GMT.
- */
-static int
-gmt_offset(t)
-long t;
-{
- register int minutes;
- register struct tm *gmtp;
- register struct tm *localp;
- register int day;
- struct tm gmt;
-
- bcopy((char *)gmtime(&t), (char *)&gmt, sizeof gmt);
- localp = localtime(&t);
-
- gmtp = &gmt;
-
- if (gmtp->tm_year == localp->tm_year)
- {
- if (gmtp->tm_yday == localp->tm_yday)
- day = 0;
- else if (gmtp->tm_yday < localp->tm_yday)
- day = 1;
- else
- day = -1;
- }
- else if (gmtp->tm_year < localp->tm_year)
- day = 1;
- else
- day = -1;
-
- return (localp->tm_hour + day * 24) * 60 + localp->tm_min - gmtp->tm_hour * 60 - gmtp->tm_min;
-}
-
-/*
- * Returns the date in the correct format.
- */
-static char *
-date_str(t, tp)
-long t;
-register struct tm *tp;
-{
- register int hours;
- register int minutes;
- int east;
- static char date[64];
- static char zone_name[9];
- extern char *strcpy();
-
- if ((minutes = gmt_offset(t)) < 0)
- {
- minutes = -minutes;
- east = 0;
- }
- else
- east = 1;
-
- hours = minutes / 60;
- minutes %= 60;
-
- if (hours != 0 || minutes != 0)
- sprintf(zone_name, "%c%02d%02d", east ? RFC_SPEC_PLUS : RFC_SPEC_MINUS, hours, minutes);
- else
- (void)strcpy(zone_name, RFC_STR_GMT);
-
- if (tp == (struct tm *)0)
- tp = localtime(&t);
-
- sprintf
- (
- date,
- "%s%c%c%2d%c%s%c%d%c%02d%c%02d%c%02d%c%s",
- days[tp->tm_wday],
- RFC_SPEC_COMMA,
- RFC_LWSP_1,
- tp->tm_mday,
- RFC_LWSP_1,
- months[tp->tm_mon],
- RFC_LWSP_1,
- tp->tm_year + YEAR_OFFSET,
- RFC_LWSP_1,
- tp->tm_hour,
- RFC_SPEC_COLON,
- tp->tm_min,
- RFC_SPEC_COLON,
- tp->tm_sec,
- RFC_LWSP_1,
- zone_name
- );
-
- return newstr(date);
-}
-
-/*
- * Returns the date in the correct format.
- */
-char *
-rfc_date(t)
-long t;
-{
- return date_str(t, (struct tm *)0);
-}
-
-/*
- * Is this char a digit?
- */
-int
-digit(c)
-register char c;
-{
- return c >= '0' && c <= '9';
-}
-
-/*
- * Return the numeric value of a two digit ASCII sequence.
- */
-static char *
-two_digits(c, s, ip)
-char c;
-register char *s;
-register int *ip;
-{
- register int i;
-
- if (*s++ != c || !digit(*s))
- return NULLSTR;
-
- i = *s++ - '0';
- i *= 10;
-
- if (!digit(*s))
- return NULLSTR;
-
- i += *s++ - '0';
-
- *ip = i;
- return s;
-}
-
-/*
- * Take a UNIX date and return it's RFC 822 representation.
- */
-char *
-rfc_cvt_date(s)
-register char *s;
-{
- register struct tm *tp;
- register char **n;
- struct tm now;
- extern long time();
- int year;
-
- tp = &now;
-
- n = days;
-
- for (;;)
- {
- if (*n == NULLSTR)
- goto disaster;
-
- if (strncmp(s, *n, 3) == 0)
- {
- tp->tm_wday = n - days;
- break;
- }
-
- n++;
- }
-
- s += 3;
-
- if (*s++ != ' ')
- goto disaster;
-
- n = months;
-
- for (;;)
- {
- if (*n == NULLSTR)
- goto disaster;
-
- if (strncmp(s, *n, 3) == 0)
- {
- tp->tm_mon = n - months;
- break;
- }
-
- n++;
- }
-
- s += 3;
-
- if (*s != ' ')
- goto disaster;
-
- if (digit(*++s))
- {
- if ((s = two_digits(' ', --s, &tp->tm_mday)) == NULLSTR)
- goto disaster;
- }
- else if (*s++ == ' ')
- tp->tm_mday = *s++ - '0';
- else
- goto disaster;
-
- if ((s = two_digits(' ', s, &tp->tm_hour)) == NULLSTR)
- goto disaster;
-
- if ((s = two_digits(':', s, &tp->tm_min)) == NULLSTR)
- goto disaster;
-
- if (*s == ':')
- {
- if ((s = two_digits(':', s, &tp->tm_sec)) == NULLSTR)
- goto disaster;
- }
- else if (*s == ' ')
- tp->tm_sec = 0;
- else
- goto disaster;
-
- while (*s != '\0')
- s++;
-
- if (!digit(*--s) || !digit(*--s) || !digit(*--s) || !digit(*--s))
- goto disaster;
-
- year = 0;
-
- while (*s != '\0')
- year = year * 10 + *s++ - '0';
-
- tp->tm_year = year - YEAR_OFFSET;
-
- return date_str(time((long *)0), tp);
-
-disaster:
- return rfc_date(time((long *)0));
-}
-
-/*
- * Make up a message id from the:
- *
- * date
- * pid
- * box
- * id
- * host
- * domain
- */
-char *
-rfc_message_id(t, cf, box, id)
-long t;
-register conf *cf;
-char *box;
-char *id;
-{
- register struct tm *tp;
- char *mid;
-
- tp = localtime(&t);
-
- mid = salloc
- (
- 1 + /* Left angle bracket */
- 10 + 1 + /* Date */
- 10 + 1 + /* Worst case 32 bit pids */
- strlen(box) + 1 + /* box */
- strlen(id) + 1 + /* message id */
- strlen(cf->c_address) + 1 + /* address */
- 1 + /* Right angle bracket */
- 1 /* nul */
- );
-
- sprintf
- (
- mid,
- "%c%d%02d%02d%02d%02d%c%d%c%s%c%s%c%s%c",
- RFC_SPEC_LANGLE,
- tp->tm_year + YEAR_OFFSET,
- tp->tm_mon + 1,
- tp->tm_mday,
- tp->tm_hour,
- tp->tm_min,
- RFC_SPEC_DOT,
- getpid(),
- RFC_SPEC_DOT,
- box,
- RFC_SPEC_DOT,
- id,
- RFC_SPEC_AT,
- cf->c_address,
- RFC_SPEC_RANGLE
- );
-
- return mid;
-}
-
-/*
- * Case independant header comparison allowing LWSP
- * between header and ':'.
- */
-int
-rfc_hdr_cmp(s, h)
-register char *s;
-register char *h;
-{
- register char c;
- register char d;
-
- for (;;)
- {
- if (*s == '\0')
- return 0;
-
- if (*h == RFC_SPEC_COLON)
- {
- while (*s == RFC_LWSP_1 || *s == RFC_LWSP_2)
- s++;
-
- return *s == RFC_SPEC_COLON;
- }
-
- if (*s != *h)
- {
- if ((c = *s) >= 'A' && c <= 'Z')
- c = c - 'A' + 'a';
-
- if ((d = *h) >= 'A' && d <= 'Z')
- d = d - 'A' + 'a';
-
- if (c != d)
- return 0;
- }
-
- s++;
- h++;
- }
-}
-
-/*
- * Determine whether a string starts with an RFC 822 header.
- */
-int
-rfc_header(s)
-char *s;
-{
- register char *p;
-
- /*
- * 1*<any CHAR, excluding CTLs, space and ":">
- */
- p = s;
-
- do
- {
- if (*p <= RFC_LWSP_1 || *p == '\177')
- {
- if
- (
- (*p != RFC_LWSP_1 && *p != RFC_LWSP_2)
- ||
- p == s
- )
- return 0;
-
- break;
- }
-
- if (*p == RFC_SPEC_COLON)
- {
- if (p == s)
- return 0;
-
- break;
- }
- }
- while (*p++ != '\0');
-
- /*
- * 1*<LWSP> ":"
- */
- do
- {
- if (*p == RFC_SPEC_COLON)
- return 1;
- }
- while ((*p == RFC_LWSP_1 || *p == RFC_LWSP_2) && *p++ != '\0');
-
-
- return 0;
-}
-
-/*
- * Determine whether a string is an RFC 822 weekday.
- */
-int
-rfc_weekday(char *s)
-{
- char **d;
-
- for (d = days; *d != NULLSTR; d++)
- {
- if (strcasecmp(*d, s) == 0)
- return d - days;
- }
-
- return -1;
-}
-
-/*
- * Determine whether a string is an RFC 822 month.
- */
-int
-rfc_month(char *s)
-{
- char **m;
-
- for (m = months; *m != NULLSTR; m++)
- {
- if (strcasecmp(*m, s) == 0)
- return m - months;
- }
-
- return -1;
-}
-
-/*
- * Return a 4DIGIT local differential in minutes for an RFC 822 zone.
- */
-static int
-diff(char *s, int west)
-{
- int m;
- int n;
-
- m = 0;
- n = 0;
-
- for (;;)
- {
- if (*s == '\0')
- {
- if (n != 4)
- break;
-
- return west ? m : -m;
- }
-
- if (!isdigit(*s) || n >= 4)
- break;
-
- m = m * 10 + *s - '0';
- n++;
- }
-
- return ZONE_HOUR(24);
-}
-
-/*
- * Return an offset in minutes for an RFC 822 zone.
- */
-int
-rfc_zone(char *s)
-{
- zone *z;
- int west;
-
- west = 1;
-
- /* optional +/- ? */
- switch (*s)
- {
- case RFC_SPEC_MINUS:
- west = 0;
- case RFC_SPEC_PLUS:
- return diff(&s[1], west);
- }
-
- for (z = zones; z->name != NULLSTR; z++)
- {
- if (strcasecmp(z->name, s) == 0)
- break;
- }
-
- return z->offset;
-}
//GO.SYSIN DD rfc.c
echo run.c
sed 's/.//' >run.c <<'//GO.SYSIN DD run.c'
-/*
- * Fork/exec an argument vector using sh(1).
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)run.c 1.30";
-#endif lint
-
-#include <signal.h>
-#include "mace.h"
-
-int
-run(argv)
-register char *argv[];
-{
- register int i;
- register int pid;
- register char *x;
- int status;
- SIG_RET (*int_sig)();
- SIG_RET (*quit_sig)();
-
- switch (pid = fork())
- {
- case SYSERROR:
- could_not("fork", argv[0]);
- /* NOTREACHED */
-
- case 0:
- x = defenv(ENV_SHELL, DEF_SHELL);
-
- execl(x, basename(x), "-c", splice(argv, " "), NULLSTR);
- could_not("exec", argv[0]);
- /* NOTREACHED */
-
- default:
- break;
- }
-
- int_sig = signal(SIGINT, SIG_IGN);
- quit_sig = signal(SIGQUIT, SIG_IGN);
-
- while ((i = wait(&status)) != pid)
- {
- if (i == SYSERROR)
- {
- status = SYSERROR;
- break;
- }
- }
-
- signal(SIGINT, int_sig);
- signal(SIGQUIT, quit_sig);
-
- return status;
-}
//GO.SYSIN DD run.c
echo string.c
sed 's/.//' >string.c <<'//GO.SYSIN DD string.c'
-/*
- * String routines.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)string.c 1.32";
-#endif lint
-
-#include "mace.h"
-
-char *
-concat(s1, s2)
-char *s1;
-char *s2;
-{
- register int l;
- register char *s;
- extern char *strcpy();
- extern char *strcat();
-
- l = strlen(s1) + strlen(s2) + 1;
-
- s = salloc(l);
-
- (void)strcat(strcpy(s, s1), s2);
-
- return s;
-}
-
-char *
-concat3(s1, s2, s3)
-char *s1;
-char *s2;
-char *s3;
-{
- register int l;
- register char *s;
- extern char *strcpy();
- extern char *strcat();
-
- l = strlen(s1) + strlen(s2) + strlen(s3) + 1;
-
- s = salloc(l);
-
- (void)strcat(strcat(strcpy(s, s1), s2), s3);
-
- return s;
-}
-
-char *
-newstr(s)
-register char *s;
-{
- extern char *strcpy();
-
- return strcpy(salloc(strlen(s) + 1), s);
-}
-
-char *
-basename(s)
-register char *s;
-{
- register char *p;
- extern char *strrchr();
-
- if ((p = strrchr(s, '/')) == NULLSTR || *++p == '\0')
- p = s;
-
- return p;
-}
-
-char *
-splice(v, s)
-register char *v[];
-register char *s;
-{
- register char *p;
- register char *q;
- register int i;
- register int len;
- char *r;
-
- len = 0;
-
- for (i = 0; v[i] != NULLSTR; i++)
- len += strlen(v[i]);
-
- len += strlen(s) * (i - 1) + 1;
-
- p = r = salloc(len + 1);
-
- for (i = 0; (q = v[i]) != NULLSTR; i++)
- {
- while ((*p++ = *q++) != '\0')
- ;
-
- p--;
-
- if (v[i + 1] != NULLSTR)
- {
- for (q = s; (*p++ = *q) != '\0'; q++)
- ;
-
- p--;
- }
- }
-
- *p = '\0';
-
- return r;
-}
-
-char *
-strstr(s, t)
-register char *s;
-register char *t;
-{
- register char *p;
- extern char *strchr();
-
- while (*t != '\0')
- {
- if ((p = strchr(s, *t++)) != NULLSTR)
- return p;
- }
-
- return NULLSTR;
-}
//GO.SYSIN DD string.c
echo sysmess.c
sed 's/.//' >sysmess.c <<'//GO.SYSIN DD sysmess.c'
-/*
- * System error messages.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)sysmess.c 1.30";
-#endif lint
-
-char *
-sysmess()
-{
- extern int errno;
- extern int sys_nerr;
- extern char *sys_errlist[];
-
- return errno <= 0 || errno > sys_nerr ? "Unknown error" : sys_errlist[errno];
-}
//GO.SYSIN DD sysmess.c
echo tn.c
sed 's/.//' >tn.c <<'//GO.SYSIN DD tn.c'
-/*
- * Message true names (ie. indexes).
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)tn.c 1.30";
-#endif lint
-
-#include "mace.h"
-
-msg_idx
-mess_index(m, s)
-register mbox *m;
-register char *s;
-{
- register msg_idx i;
- register msg_idx j;
- register msg_idx k;
-
- i = 0;
- k = m->m_count - 1;
-
- while (k >= i)
- {
- register int c;
-
- j = i + (k - i) / 2;
-
- if ((c = strcmp(s, m->m_list[j])) == 0)
- return j;
-
- if (c > 0)
- i = j + 1;
- else
- k = j - 1;
- }
-
- return NULLMSG;
-}
//GO.SYSIN DD tn.c
echo tty.c
sed 's/.//' >tty.c <<'//GO.SYSIN DD tty.c'
-/*
- * @(#)tty.c 1.1
- *
- * Horrible system dependent tty routines.
- */
-
-#include "mace.h"
-#include <termios.h>
-
-/*
- * Is echo on?
- */
-int
-ttyechoing(int fd)
-{
- struct termios t;
-
- if (tcgetattr(fd, &t) == SYSERROR)
- return SYSERROR;
-
- return (t.c_lflag & ECHO) != 0;
-}
-
-/*
- * Turn echo off/on?
- */
-int
-ttyecho(int fd, int on)
-{
- struct termios t;
-
- if (tcgetattr(fd, &t) == SYSERROR)
- return SYSERROR;
-
- if (on)
- t.c_lflag |= ECHO;
- else
- t.c_lflag &= ~ECHO;
-
- return tcsetattr(fd, TCSADRAIN, &t);
-}
//GO.SYSIN DD tty.c
echo vec.c
sed 's/.//' >vec.c <<'//GO.SYSIN DD vec.c'
-/*
- * Dynamic vector of strings.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)vec.c 1.31";
-#endif lint
-
-#include "mace.h"
-
-void
-vec_init(v, n)
-register vec *v;
-register int n;
-{
- v->v_count = 0;
- v->v_size = v->v_incr = n;
- v->v_list = (char **)salloc(n * sizeof(char *));
-}
-
-char *
-vec_str(v, s)
-register vec *v;
-register char *s;
-{
- if (v->v_count == v->v_size)
- v->v_list = (char **)srealloc((char *)v->v_list, (int)(v->v_size += v->v_incr) * sizeof(char *));
-
- v->v_list[v->v_count++] = s;
-
- return s;
-}
-
-char *
-vec_cat(v, s)
-register vec *v;
-register char *s;
-{
- if (v->v_count != 0)
- {
- register char *p;
-
- if (v->v_list[v->v_count - 1] != NULLSTR)
- {
- p = concat(v->v_list[v->v_count - 1], s);
-
- (void)free(v->v_list[v->v_count - 1]);
- (void)free(s);
- }
- else
- p = s;
-
- return v->v_list[v->v_count - 1] = p;
- }
- else
- return vec_str(v, s);
-}
-
-void
-vec_free(v)
-register vec *v;
-{
- register int i;
-
- for (i = 0; i < v->v_count; i++)
- {
- if (v->v_list[i] != NULLSTR)
- (void)free(v->v_list[i]);
- }
-
- v->v_count = 0;
- v->v_size = 0;
- v->v_incr = 0;
- (void)free((char *)v->v_list);
-}
//GO.SYSIN DD vec.c
echo writefile.c
sed 's/.//' >writefile.c <<'//GO.SYSIN DD writefile.c'
-/*
- * Write a string to a file (adding a newline).
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)writefile.c 1.30";
-#endif lint
-
-#include "mace.h"
-
-int
-write_file(f, s)
-register char *f;
-register char *s;
-{
- register int fd;
- register int l;
- int ok;
-
- if ((fd = creat(f, CREAT_MODE)) == SYSERROR)
- return 1;
-
- l = strlen(s);
- s[l] = '\n';
-
- ok = 0;
-
- if (write(fd, s, l + 1) != l + 1)
- ok = 1;
-
- if (close(fd) == SYSERROR)
- ok = 1;
-
- s[l] = '\0';
-
- return ok;
-}
//GO.SYSIN DD writefile.c
echo bundle
sed 's/.//' >bundle <<'//GO.SYSIN DD bundle'
-#!/bin/sh
-#
-# @(#)bundle 1.1
-#
-# bundle file ...
-#
-# Plan 9 bundle; a simple shell archiver.
-#
-
-echo '# To unbundle, run this file'
-
-for i
-do
- echo echo "$i"
- echo "sed 's/.//' >$i <<'//GO.SYSIN DD $i'"
- sed 's/^/-/' "$i"
- echo "//GO.SYSIN DD $i"
-done
//GO.SYSIN DD bundle
echo mal
sed 's/.//' >mal <<'//GO.SYSIN DD mal'
-#!/bin/sh
-#
-# @(#)mal 1.2
-#
-# mal +box ...
-#
-# Mail aliasing based on a box's .proto
-#
-
-dir="$HOME/.macedir"
-bchar=+
-proto=.proto
-
-myname="`basename \"$0\"`"
-
-case $# in
-0)
- echo "usage: $myname ${bchar}box ..." 1>&2
- exit 1
- ;;
-esac
-
-# find mail directory
-if [ ! -r "$dir" ]
-then
- echo "$myname: Could not read '$dir'." 1>&2
- exit 1
-fi
-
-mdir="`cat \"$dir\"`"
-
-case "$mdir" in
-"")
- echo "$myname: '$dir' empty." 1>&2
- exit 1
- ;;
-
-/*)
- # absolute pathname, ok
- ;;
-
-*)
- # relative pathname, so prepend $HOME
- mdir="$HOME/$mdir"
- ;;
-esac
-
-for b
-do
- # use box to verify box name, but the usage message is a bit weird
- if box -l "$b" > /dev/null
- then
- case "$b" in
- ${bchar}*)
- # slice off leading ${bchar}
- b="`expr \"$b\" : \"^${bchar}\(.*\)$\"`"
- ;;
- esac
-
- # snarf To:/Cc:/Bcc:
- sed -n \
- -e '/^[Tt][Oo][ ]*:[ ]*/s///p' \
- -e '/^[Cc][Cc][ ]*:[ ]*/s///p' \
- -e '/^[Bb][Cc][Cc][ ]*:[ ]*/s///p' \
- "$mdir/$b/$proto" 2> /dev/null
- fi
-done | sed -e '$n' -e 's/$/,/' # insert , between addresses
//GO.SYSIN DD mal
echo box.c
sed 's/.//' >box.c <<'//GO.SYSIN DD box.c'
-/*
- * box [ -acdilmorst ] [ +box... ]
- *
- * Box specific stuff
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)box.c 1.37";
-#endif lint
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include "mace.h"
-#include "line.h"
-#include "message.h"
-#include "headers.h"
-#include "regexp.h"
-#include "conf.h"
-
-int rev = 0; /* reverse scan */
-int show_to = 0; /* show the "To:" field */
-int current = 0; /* just show the current message */
-int inbox = 0; /* show the `incoming' box */
-int outbox = 0; /* show the `outgoing' box */
-
-int
-box_cmp(m1, m2)
-register char **m1;
-register char **m2;
-{
- return strcmp(*m1, *m2);
-}
-
-int
-show(v)
-register char **v;
-{
- while (*v != NULLSTR)
- printf("%c%s\n", BOX_CHAR, *v++);
-
- return 0;
-}
-
-int
-create(v)
-register char **v;
-{
- int ok;
-
- ok = 0;
-
- while (*v != NULLSTR)
- {
- register char *p;
-
- if ((p = create_box(*v)) == NULLSTR)
- {
- would_not("create", *v);
- ok = 1;
- }
- else
- (void)free(p);
-
- v++;
- }
-
- return ok;
-}
-
-int
-delete(v)
-register char **v;
-{
- int ok;
-
- ok = 0;
-
- while (*v != NULLSTR)
- {
- if (delete_box(*v))
- ok = 1;
-
- v++;
- }
-
- return ok;
-}
-
-int
-list(v)
-register char **v;
-{
- int ok;
-
- ok = 0;
-
- while (*v != NULLSTR)
- {
- register mbox *m;
- register int i;
-
- if ((m = read_box(*v)) == NULLBOX)
- {
- would_not("read", *v);
- ok = 1;
- v++;
- continue;
- }
-
- printf("%c%-20s", BOX_CHAR, m->m_name);
-
- if (m->m_messid == NULLSTR)
- {
- for (i = 0; i < ID_LEN; i++)
- putchar('?');
- }
- else
- printf("%s", m->m_messid);
-
- if (m->m_count != 0)
- printf(" %4d %s", m->m_count, m->m_count == 1 ? "message" : "messages");
- else
- printf(" empty");
-
- putchar('\n');
- v++;
-
- (void)free_box(m);
- }
-
- return ok;
-}
-
-int
-set(v)
-register char **v;
-{
- return set_box(v[0]);
-}
-
-int
-analyse(mb)
-register mbox *mb;
-{
- register message *mp;
- register int i;
- register int j;
- register int id;
- int errs;
-
- errs = 0;
-
- if (current)
- {
- if (mb->m_current == NULLMSG)
- {
- fprintf(stderr, "%s: No current message in \"%s\".\n", my_name, mb->m_name);
- return 1;
- }
-
- i = mb->m_current;
- j = i + 1;
- rev = 0;
- }
- else
- {
- i = 0;
- j = mb->m_count;
- }
-
- while (i < j)
- {
- if ((mp = read_mess(mb, mb->m_list[id = rev ? mb->m_count - (i + 1): i])) != NULLMESS)
- {
- print_summary(mb->m_name, mp->ms_messid, &mp->ms_headers.v_list[0], id == mb->m_current, mp->ms_copies, show_to || (mp->ms_state & MESG_SENT) != 0, mp->ms_state);
-
- free_mess(mp);
- }
- else
- {
- would_not("read message", mb->m_list[id]);
- errs = 1;
- }
-
- i++;
- }
-
- return errs;
-}
-
-int
-scan(v)
-register char **v;
-{
- register char **n;
- register mbox *mb;
- register int errs;
-
- errs = 0;
-
- for (n = v; *n != NULLSTR; n++)
- {
- register char *p;
-
- if ((mb = read_box(p = *n)) == NULLBOX)
- {
- would_not("read", p);
- errs = 1;
- }
- else if (analyse(mb))
- errs = 1;
-
- free_box(mb);
- }
-
- return errs;
-}
-
-void
-validate(v, tp)
-register char **v;
-register char **tp;
-{
- register char **n;
-
- for (n = v; *n != NULLSTR; n++)
- {
- register char *p;
-
- if ((p = check_box(*n)) != NULLSTR)
- {
- *v++ = *n;
- (void)free(p);
- }
- else
- {
- fprintf(stderr, "%s: \"%s\" is not a box.\n", my_name, *n);
-
- if (*tp != NULLSTR && strcmp(*tp, *n) == 0)
- *tp = NULLSTR;
- }
- }
-
- *v = NULLSTR;
-}
-
-void
-usage()
-{
- fprintf(stderr, "usage: %s [ -acdilmorst ] [ [%c]%cbox... ]\n", my_name, BOX_CHAR, BOX_CHAR);
- exit(1);
-}
-
-/*
- * Choose the current box, `incoming', or `outgoing'.
- */
-char *
-select_box()
-{
- register char *p;
-
- if (inbox && outbox)
- {
- usage();
- /* NOTREACHED */
- }
-
- if (inbox || outbox)
- {
- register conf *cp;
-
- cp = read_config();
-
- return newstr(inbox ? cp->c_inbox : cp->c_outbox);
- }
-
- if ((p = curr_box()) == NULLSTR)
- {
- fprintf(stderr, "%s: No current box.\n", my_name);
- exit(1);
- /* NOTREACHED */
- }
-
- return newstr(p);
-}
-
-int
-main(argc, argv)
-register char argc;
-register char *argv[];
-{
- register int i;
- register int j;
- int all;
- vec bvec;
- char *target;
- int (*action)();
-
- name(argv[0]);
-
- action = show;
- all = 0;
- target = NULLSTR;
- vec_init(&bvec, argc);
-
- for (i = 1; i < argc; i++)
- {
- j = 0;
-
- if (argv[i][j] == BOX_CHAR)
- {
- register char *p;
-
- p = &argv[i][1];
-
- if (*p == BOX_CHAR)
- {
- if (target != NULLSTR)
- {
- usage();
- /* NOTREACHED */
- }
-
- target = ++p;
- }
-
- if (*p == '\0')
- {
- usage();
- /* NOTREACHED */
- }
-
- vec_str(&bvec, newstr(p));
- continue;
- }
-
- if (argv[i][j++] != '-')
- {
- usage();
- /* NOTREACHED */
- }
-
- while (argv[i][j] != '\0')
- {
- switch (argv[i][j++])
- {
- case 'a':
- all = 1;
- continue;
-
- case 'c':
- if (action != show)
- {
- usage();
- /* NOTREACHED */
- }
-
- action = create;
- continue;
-
- case 'd':
- if (action != show)
- {
- usage();
- /* NOTREACHED */
- }
-
- action = delete;
- continue;
-
- case 'i':
- inbox = 1;
- continue;
-
- case 'l':
- if (action != show)
- {
- usage();
- /* NOTREACHED */
- }
-
- action = list;
- continue;
-
- case 'm':
- current = 1;
- goto set_scan;
-
- case 'o':
- outbox = 1;
- continue;
-
- case 'r':
- rev = 1;
- goto set_scan;
-
- case 't':
- show_to = 1;
- goto set_scan;
-
- case 's':
- set_scan:
- if (action != show && action != scan)
- {
- usage();
- /* NOTREACHED */
- }
-
- action = scan;
- continue;
-
- default:
- usage();
- /* NOTREACHED */
- }
-
- break;
- }
- }
-
- if (all && action == create)
- {
- usage();
- /* NOTREACHED */
- }
-
- if (rev && action != scan)
- {
- usage();
- /* NOTREACHED */
- }
-
- if (action == show)
- {
- if (bvec.v_count > 1)
- {
- usage();
- /* NOTREACHED */
- }
-
- if (bvec.v_count == 1)
- action = set;
- }
-
- if (all)
- {
- register char **v;
-
- if (bvec.v_count != 0)
- {
- usage();
- /* NOTREACHED */
- }
-
- v = read_dir(mace_dir());
-
- if (*v == NULLSTR)
- {
- fprintf(stderr, "%s: You have no boxes.\n", my_name);
- exit(1);
- /* NOTREACHED */
- }
-
- for (i = 0; v[i] != NULLSTR; i++)
- ;
-
- qsort((char *)v, i, sizeof(*v), box_cmp);
-
- while (*v != NULLSTR)
- vec_str(&bvec, *v++);
- }
- else if (bvec.v_count == 0)
- vec_str(&bvec, select_box());
-
- vec_str(&bvec, NULLSTR);
-
- if (action != create)
- {
- validate(bvec.v_list, &target);
-
- if (bvec.v_list[0] == NULLSTR)
- exit(1);
- }
- else
- (*action)(bvec.v_list);
-
- if
- (
- (target != NULLSTR && set_box(target))
- ||
- (action != create && (*action)(bvec.v_list))
- )
- {
- exit(1);
- /* NOTREACHED */
- }
-
- exit(0);
- /* NOTREACHED */
-}
//GO.SYSIN DD box.c
echo com.c
sed 's/.//' >com.c <<'//GO.SYSIN DD com.c'
-/*
- * com | rep | fwd [ -si ] [ +box ] [ message ]
- *
- * Message composition, reply and forwarding.
- */
-
-#ifndef lint
-static char sccsid[] = "%W%";
-#endif lint
-
-#include "mace.h"
-#include "line.h"
-#include "message.h"
-#include "headers.h"
-#include "regexp.h"
-#include "conf.h"
-#include "addr.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdio.h>
-
-vec to;
-vec cc;
-char *subject = NULLSTR;
-char *message_id = NULLSTR;
-char *my_address = NULLSTR;
-match *removeit = (match *)0;
-
-int external = 0;
-int sender = 0;
-int include_current = 0;
-int replying = 0;
-
-char *current;
-vec refiled;
-
-msg_idx
-find_msg(m, s)
-mbox *m;
-char *s;
-{
- msg_idx i;
-
- if (*s == '\0')
- {
- if (m->m_current == NULLMSG)
- fprintf(stderr, "%s: No current message in \"%s\".\n", my_name, m->m_name);
-
- return m->m_current;
- }
-
- if ((i = valid_id(s) ? mess_index(m, s) : mess_alias(m, s)) == NULLMSG)
- fprintf(stderr, "%s: No such message qualifier as \"%s\".\n", my_name, s);
-
- return i;
-}
-
-mbox *
-current_box(id)
-char *id;
-{
- static mbox *mb = NULLBOX;
- msg_idx idx;
- char *box;
-
- if (mb != NULLBOX)
- return mb;
-
- if ((box = curr_box()) == NULLSTR)
- {
- fprintf(stderr, "%s: No current box.\n", my_name);
- exit(1);
- /* NOTREACHED */
- }
-
- if ((mb = read_box(box)) == NULLBOX)
- {
- fprintf(stderr, "%s: Box \"%s\" does not exist.\n", my_name, box);
- exit(1);
- /* NOTREACHED */
- }
-
- (void)free(box);
-
- if (id != NULLSTR)
- {
- if ((idx = find_msg(mb, id)) == NULLMSG)
- {
- exit(1);
- /* NOTREACHED */
- }
-
- mb->m_current = idx;
- mb->m_messid = mb->m_list[idx];
-
- (void)set_current(mb->m_name, mb->m_messid);
- }
-
- if (mb->m_current == NULLMSG)
- {
- fprintf(stderr, "%s: No current message in \"%s\".\n", my_name, mb->m_name);
- exit(1);
- /* NOTREACHED */
- }
-
- return mb;
-}
-
-int
-open_msg(id)
-char *id;
-{
- mbox *mb;
- char *msg;
- int fd;
-
- mb = current_box(id);
-
- msg = concat3(mb->m_path, "/", mb->m_messid);
-
- if ((fd = open(msg, O_RD)) == SYSERROR)
- {
- could_not("open", msg);
- /* NOTREACHED */
- }
-
- current = msg;
-
- return fd;
-}
-
-/*
- * Compare two addresses.
- */
-int
-same_address(a, b)
-char *a;
-char *b;
-{
- for (;;)
- {
- char c;
- char d;
-
- if (*a != *b)
- {
- if (*a == '\0')
- return (c = *b) == RFC_SPEC_PERCENT || c == RFC_SPEC_AT || c == RFC_SPEC_DOT;
-
- if (*b == '\0')
- return (c = *a) == RFC_SPEC_PERCENT || c == RFC_SPEC_AT || c == RFC_SPEC_DOT;
-
- if ((c = *a) >= 'A' && c <= 'Z')
- c = c - 'A' + 'a';
-
- if ((d = *b) >= 'A' && d <= 'Z')
- d = d - 'A' + 'a';
-
- if (c != d)
- return 0;
- }
- else if (*a == '\0')
- return 1;
-
- a++;
- b++;
- }
-}
-
-/*
- * Add to a list of recipients after removing self.
- */
-void
-add_recipient(vp, s)
-vec *vp;
-char *s;
-{
- char *p;
- Addr *ap;
- Addr *addrs;
-
- if ((p = parse_address(&addrs, s)) != NULLSTR)
- {
- /*
- * If the address has a syntax error add the raw text.
- */
- vec_str(vp, newstr(s));
- fprintf(stderr, "%s: warning: \"%s\" %s.\n", my_name, s, p);
- return;
- }
-
- for (ap = addrs; ap != (Addr *)0; ap = ap->next)
- {
- /*
- * This is hideous, but necessary until I fix the `group bug'.
- */
- if (ap->group != NULLSTR)
- {
- if (ap->text != NULLSTR)
- vec_str(vp, newstr(ap->text));
-
- continue;
- }
-
- if (removeit != (match *)0)
- {
- if (regexec(removeit->m_cre, ap->text) == 0)
- {
- if (re_error != NULLSTR)
- fprintf(stderr, "%s: Regular expression \"%s\" %s\n", my_name, removeit->m_re, re_error);
- else
- vec_str(vp, newstr(ap->text));
- }
- }
- else
- {
- if (!same_address(my_address, p = make_address(ap)))
- vec_str(vp, newstr(ap->text));
-
- (void)free(p);
- }
- }
-}
-
-/*
- * Add multiple To: and Cc: lines to a list of recipients (removing self).
- */
-void
-add_multiple(mbox *mb, vec *list, char **h, char *type)
-{
- while (*h != NULLSTR)
- {
- if (rfc_hdr_cmp(*h, type))
- {
- char *ht;
-
- if ((ht = header_text(*h)) == NULLSTR)
- {
- fprintf(stderr, "%s: Malformed \"%s\" line in \"%s\".\n", my_name, type, mb->m_messid);
- exit(1);
- /* NOTREACHED */
- }
-
- add_recipient(list, ht);
- }
-
- h++;
- }
-}
-
-/*
- * Add links to the message based on the boxes it it refiled in.
- */
-static void
-addlinks(char *box, char *id)
-{
- int i;
-
- for (i = 1; i < refiled.v_count; i++)
- {
- char *a[6];
- int n;
- int s;
- int t;
-
- /*
- * Use 'lnk' to avoid code duplication.
- */
- n = 0;
- a[n++] = LNK_STR;
- a[s = n++] = concat(" ", box);
- a[s][0] = BOX_CHAR;
- a[n++] = id;
- a[t = n++] = concat(" ", refiled.v_list[i]);
- a[t][0] = BOX_CHAR;
- a[n++] = NULLSTR;
- run(a);
-
- free(a[s]);
- free(a[t]);
- }
-}
-
-/*
- * Create a list of boxes in which the message is refiled.
- */
-void
-refile(char *inbox, message *m, match *re)
-{
- vec_str(&refiled, newstr(re->m_action));
-}
-
-void
-set_recipients(conf *cf, char * id)
-{
- message *mp;
- mbox *mb;
- char **h;
- char *p;
- char *ht;
- static char lwsp_1[2] = { RFC_LWSP_1, '\0' };
-
- mb = current_box(id);
-
- vec_init(&to, 64);
- vec_init(&cc, 64);
-
- if (mb->m_current == NULLMSG)
- {
- fprintf(stderr, "%s: No current message in \"%s\".\n", my_name, mb->m_name);
- exit(1);
- /* NOTREACHED */
- }
-
- if ((mp = read_mess(mb, mb->m_messid)) == NULLMESS)
- {
- could_not("read", mb->m_name);
- /* NOTREACHED */
- }
-
- if
- (
- (h = find_header(&mp->ms_headers.v_list[0], p = RFC_REPLY_TO)) == (char **)NULLSTR
- &&
- (h = find_header(&mp->ms_headers.v_list[0], p = RFC_FROM)) == (char **)NULLSTR
- )
- {
- fprintf(stderr, "%s: Missing \"%s\" or \"%s\" line in \"%s\".\n", my_name, RFC_REPLY_TO, RFC_FROM, mb->m_messid);
- exit(1);
- /* NOTREACHED */
- }
-
- if ((ht = header_text(*h)) == NULLSTR)
- {
- fprintf(stderr, "%s: Malformed \"%s\" line in \"%s\".\n", my_name, p, mb->m_messid);
- exit(1);
- /* NOTREACHED */
- }
-
- add_recipient(&to, ht);
-
- add_multiple(mb, &to, &mp->ms_headers.v_list[0], RFC_TO);
- add_multiple(mb, &cc, &mp->ms_headers.v_list[0], RFC_CC);
-
- if
- (
- (h = find_header(&mp->ms_headers.v_list[0], RFC_SUBJECT)) != (char **)NULLSTR
- &&
- (subject = header_text(*h)) != NULLSTR
- &&
- rfc_hdr_cmp(subject, UNIX_REGARDING) == 0
- )
- subject = concat3(UNIX_REGARDING, lwsp_1, subject);
-
- if ((h = find_header(&mp->ms_headers.v_list[0], RFC_MESSAGE_ID)) != (char **)NULLSTR)
- message_id = header_text(*h);
-
- if (subject != NULLSTR)
- subject = newstr(subject);
-
- if (message_id != NULLSTR)
- message_id = newstr(message_id);
-
- /*
- * Build a list of where there are refiled copies of the message.
- */
- vec_init(&refiled, 64);
- regex_apply(cf->c_inbox, mp, cf->c_refile, refile);
-
- (void)free_mess(mp);
-}
-
-void
-tack_address(vp, ap)
-vec *vp;
-vec *ap;
-{
- int i;
- static char sep[7] =
- {
- RFC_SPEC_COMMA,
- '\n',
- RFC_LWSP_1,
- RFC_LWSP_1,
- RFC_LWSP_1,
- RFC_LWSP_1,
- '\0'
- };
-
- for (i = 1; i < ap->v_count; i++)
- vec_cat(vp, concat(sep, ap->v_list[i]));
-}
-
-void
-merge_headers(vp, h)
-vec *vp;
-char **h;
-{
- while (*h != NULLSTR)
- {
- char **x;
-
- if ((x = find_header(vp->v_list, *h)) != (char **)NULLSTR)
- {
- if (header_text(*h) != NULLSTR)
- {
- (void)free(*x);
- *x = newstr(*h);
- }
- else
- {
- char *p;
- extern char *strchr();
-
- p = *x;
- *x = concat(*h, strchr(p, RFC_SPEC_COLON) + 1);
- (void)free(p);
- }
- }
- else
- {
- vec_cat(vp, newstr(*h));
- vec_str(vp, NULLSTR);
- }
-
- h++;
- }
-}
-
-void
-msg_proto(vp, cf, mb, id)
-vec *vp;
-conf *cf;
-mbox *mb;
-char *id;
-{
- char *p;
- message *pp;
- static char lwsp_1[2] = { RFC_LWSP_1, '\0' };
- static char lwsp_2[2] = { RFC_LWSP_2, '\0' };
- static char at[2] = { RFC_SPEC_AT, '\0' };
- static char dot[2] = { RFC_SPEC_DOT, '\0' };
- static char langle[2] = { RFC_SPEC_LANGLE, '\0' };
- static char rangle[2] = { RFC_SPEC_RANGLE, '\0' };
- static char comma[2] = { RFC_SPEC_COMMA, '\0' };
- long t;
-
- vec_init(vp, 64);
- time(&t);
-
- vec_str(vp, concat(RFC_FROM, lwsp_1));
-
- if (sender)
- vec_str(vp, concat(RFC_SENDER, lwsp_1));
-
- if ((p = user_name()) != NULLSTR)
- {
- vec_cat(vp, concat(p, lwsp_1));
- vec_cat(vp, concat3(langle, my_address, rangle));
- }
- else
- vec_cat(vp, my_address);
-
- if (sender)
- vec_str(vp, concat(RFC_REPLY_TO, lwsp_1));
-
- vec_str(vp, concat(RFC_DATE, lwsp_1));
- vec_cat(vp, rfc_date(t));
-
- if (to.v_count > 0)
- {
- vec_str(vp, concat3(RFC_TO, lwsp_1, to.v_list[0]));
- tack_address(vp, &to);
- }
- else
- vec_str(vp, concat(RFC_TO, lwsp_1));
-
- if (cc.v_count > 0)
- {
- vec_str(vp, concat3(RFC_CC, lwsp_1, cc.v_list[0]));
- tack_address(vp, &cc);
- }
- else
- vec_str(vp, concat(RFC_CC, lwsp_1));
-
- vec_str(vp, concat(RFC_BCC, lwsp_1));
-
- if (subject == NULLSTR)
- vec_str(vp, concat(RFC_SUBJECT, lwsp_1));
- else
- vec_str(vp, concat3(RFC_SUBJECT, lwsp_1, subject));
-
- if (message_id != NULLSTR)
- vec_str(vp, concat3(RFC_IN_REPLY_TO, lwsp_1, message_id));
-
- vec_str(vp, concat(RFC_MESSAGE_ID, lwsp_1));
- vec_cat(vp, rfc_message_id(t, cf, mb->m_name, id));
-
- vec_str(vp, NULLSTR);
-
- /* global prototyping */
-
- p = concat3(mace_dir(), "/", PROTO);
-
- if ((pp = parse_file(p, 0)) != NULLMESS)
- {
- merge_headers(vp, pp->ms_headers.v_list);
- free_mess(pp);
- }
-
- (void)free(p);
-
- /* per box prototyping for composition */
-
- if (!replying && (pp = read_mess(mb, PROTO)) != NULLMESS)
- {
- merge_headers(vp, pp->ms_headers.v_list);
- free_mess(pp);
- }
-
- vec_cat(vp, newstr(""));
- vec_str(vp, NULLSTR);
-}
-
-void
-interpolate(msg, fd, fp)
-char *msg;
-int fd;
-FILE *fp;
-{
- char *p;
- lineio ld;
-
- (void)lopen(&ld, fd, LREAD);
-
- if (fseek(fp, 0, 2) == 0)
- {
- while ((p = lread(&ld)) != NULLSTR && !ferror(fp))
- {
- fprintf(fp, "%s%s\n", *p == '\0' ? "" : FWD_LEADER, p);
- (void)free(p);
- }
-
- if (!ferror(fp))
- fprintf(fp, "\n");
- }
- else
- would_not("seek on", msg);
-
- if (lclose(&ld))
- {
- (void)close(fd);
- (void)fclose(fp);
- (void)unlink(msg);
- could_not("read", current);
- /* NOTREACHED */
- }
-
- if (close(fd) == SYSERROR)
- {
- (void)fclose(fp);
- (void)unlink(msg);
- could_not("close", current);
- /* NOTREACHED */
- }
-
- if (ferror(fp))
- {
- (void)fclose(fp);
- (void)unlink(msg);
- could_not("write", msg);
- /* NOTREACHED */
- }
-
- if (fclose(fp) != 0)
- {
- (void)unlink(msg);
- could_not("close", msg);
- /* NOTREACHED */
- }
-}
-
-void
-address(cf)
-conf *cf;
-{
- static char at[2] = { RFC_SPEC_AT, '\0' };
- static char dot[2] = { RFC_SPEC_DOT, '\0' };
-
- my_address = concat3(user_id(), at, cf->c_address);
-}
-
-void
-usage()
-{
- fprintf(stderr, "usage: %s [ -is ] [ %cbox ] [ message ]\n", my_name, BOX_CHAR);
- exit(1);
- /* NOTREACHED */
-}
-
-int
-main(argc, argv)
-int argc;
-char *argv[];
-{
- char *s;
- char *box;
- conf *cf;
- mbox *mb;
- int i;
- int mfd;
- FILE *mfp;
- char *id;
- char *msg;
- vec args;
- vec proto;
- int ok;
-
- name(argv[0]);
-
- box = NULLSTR;
- id = NULLSTR;
-
- for (i = 1; i < argc; i++)
- {
- int j;
-
- if (argv[i][j = 0] == BOX_CHAR)
- {
- if (box != NULLSTR)
- {
- usage();
- /* NOTREACHED */
- }
-
- if (argv[i][1] == BOX_CHAR)
- box = newstr(&argv[i][2]);
- else
- box = newstr(&argv[i][1]);
-
- if (*box == '\0')
- {
- usage();
- /* NOTREACHED */
- }
-
- continue;
- }
-
- if (argv[i][j++] != '-')
- {
- if (id != NULLSTR)
- {
- usage();
- /* NOTREACHED */
- }
-
- id = newstr(argv[i]);
- continue;
- }
-
- while (argv[i][j] != '\0')
- {
- switch (argv[i][j++])
- {
- case 'i':
- include_current = 1;
- continue;
-
- case 'e':
- external = 1;
- continue;
-
- case 's':
- sender = 1;
- continue;
-
- default:
- usage();
- /* NOTREACHED */
- }
-
- break;
- }
- }
-
- mfd = SYSERROR;
-
- if (strcmp(my_name, "com") == 0 && id != NULLSTR)
- fprintf(stderr, "%s: Message id \"%s\" ignored.\n", my_name, id);
-
- /*
- * Construct the users' address.
- */
- cf = read_config();
-
- address(cf);
-
- removeit = cf->c_remove;
-
- if (strcmp(my_name, REP_STR) == 0)
- {
- replying = 1;
- set_recipients(cf, id);
- }
-
- if (strcmp(my_name, FWD_STR) == 0 || include_current)
- mfd = open_msg(id);
-
- /*
- * If the box isn't specified choose one.
- */
- if (box == NULLSTR)
- {
- /*
- * If this is a reply choose the box from the first
- * of the boxes where the message is refiled.
- */
- if (replying && refiled.v_count > 0)
- box = refiled.v_list[0];
- else
- {
- /*
- * If the current box is "inbox" choose "outbox",
- * otherwise use the current box.
- */
- if ((box = curr_box()) == NULLSTR)
- {
- fprintf(stderr, "%s: No current box.\n", my_name);
- exit(1);
- }
-
- if (strcmp(box, cf->c_inbox) == 0)
- box = cf->c_outbox;
- }
- }
-
- if ((mb = read_box(box)) == NULLBOX)
- {
- fprintf(stderr, "%s: Box \"%s\" does not exist.\n", my_name, box);
- exit(1);
- /* NOTREACHED */
- }
-
- if (mb->m_count == 0)
- s = nextid(NULLSTR);
- else
- s = nextid(mb->m_list[mb->m_count - 1]);
-
- msg_proto(&proto, cf, mb, s);
-
- msg = concat3(mb->m_path, "/", s);
-
- id = s;
-
- if (mfd != SYSERROR && (mfp = fopen(msg, "w")) == NULL)
- {
- could_not("open", msg);
- /* NOTREACHED */
- }
-
- if (write_file(msg, s = splice(proto.v_list, "\n")))
- {
- (void)unlink(msg);
- could_not("write", msg);
- /* NOTREACHED */
- }
-
- (void)free(s);
- vec_free(&proto);
-
- if (mfd != SYSERROR)
- interpolate(msg, mfd, mfp);
-
- /*
- * Add refiled links to this message.
- */
- if (replying && refiled.v_count > 0)
- {
- addlinks(mb->m_name, id);
- vec_free(&refiled);
- }
-
- /*
- * Invoke $EDITOR
- */
- if (!external)
- {
- vec_init(&args, 4);
- vec_str(&args, newstr(defenv(ENV_EDITOR, DEF_EDITOR)));
- vec_str(&args, msg);
- vec_str(&args, NULLSTR);
-
- ok = run(args.v_list);
- }
- else
- ok = 0;
-
- if (set_state(msg, MESG_COMP))
- ok = 1;
-
- if (set_box(mb->m_name) || set_current(mb->m_name, id))
- ok = 1;
-
- exit(ok != 0);
- /* NOTREACHED */
- return ok != 0; /* shut up! */
-}
//GO.SYSIN DD com.c
echo despool.c
sed 's/.//' >despool.c <<'//GO.SYSIN DD despool.c'
-/*
- * despool [ -delete ] [ -f mailfile ]
- *
- * Mail despooler.
- *
- * Prints mail on standard output and optionally removes it.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)despool.c 1.31";
-#endif lint
-
-#include "mace.h"
-#include <stdio.h>
-#include <signal.h>
-
-#define DELETE_STR "-delete"
-
-int
-terminate(sig)
-int sig;
-{
- signal(sig, SIG_IGN);
-
- if (mail_locked())
- mail_unlock(0);
-
- exit(1);
-
- /* NOTREACHED */
-}
-
-void
-usage()
-{
- fprintf(stderr, "usage: %s [ %s ] [ -f mailfile ]\n", my_name, DELETE_STR);
- exit(1);
- /* NOTREACHED */
-}
-
-int
-main(argc, argv)
-int argc;
-char *argv[];
-{
- register int i;
- register int j;
- register int fd;
- int delete;
- char *mail;
- char buf[FS_BLKZ];
-
- name(argv[0]);
-
- mail = NULLSTR;
- delete = 0;
-
- for (i = 1; i < argc; i++)
- {
- if (argv[i][0] != '-')
- {
- usage();
- /* NOTREACHED */
- }
-
- j = 1;
-
- while (argv[i][j] != '\0')
- {
- switch (argv[i][j++])
- {
- case 'd':
- if (strcmp(argv[i], DELETE_STR) != 0)
- {
- usage();
- /* NOTREACHED */
- }
-
- delete = 1;
- break;
-
- case 'f':
- if (mail != NULLSTR)
- {
- usage();
- /* NOTREACHED */
- }
-
- if (argv[i][j] != '\0')
- mail = &argv[i][j];
- else if (++i < argc)
- mail = argv[i];
- else
- {
- usage();
- /* NOTREACHED */
- }
-
- break;
-
- default:
- usage();
- /* NOTREACHED */
- }
-
- break;
- }
- }
-
- (void)signal(SIGHUP, terminate);
- (void)signal(SIGINT, terminate);
- (void)signal(SIGQUIT, terminate);
- (void)signal(SIGPIPE, terminate);
- (void)signal(SIGTERM, terminate);
-
- if ((fd = mail_lock(&mail)) == SYSERROR)
- exit(1);
-
- for (;;)
- {
- register int n;
-
- switch (n = read(fd, buf, sizeof buf))
- {
- case SYSERROR:
- would_not("read", mail);
- exit(mail_unlock(0) != 0);
- /* NOTREACHED */
-
- case 0:
- if (close(fd) == SYSERROR)
- {
- would_not("close", mail);
- exit(mail_unlock(0) != 0);
- /* NOTREACHED */
- }
- break;
-
- default:
- if (write(fileno(stdout), buf, n) != n)
- {
- would_not("write", "<stdout>");
- exit(mail_unlock(0) != 0);
- /* NOTREACHED */
- }
-
- continue;
- }
-
- break;
- }
-
- exit(mail_unlock(delete) != 0);
-
- /* NOTREACHED */
-}
//GO.SYSIN DD despool.c
echo mace.c
sed 's/.//' >mace.c <<'//GO.SYSIN DD mace.c'
-/*
- * mace [ -dsu ] [ -f mailfile ]
- *
- * Mace your mail-file & extract the mail.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)mace.c 1.3";
-#endif lint
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <signal.h>
-#include "mace.h"
-#include "regexp.h"
-#include "line.h"
-#include "message.h"
-#include "conf.h"
-#include "headers.h"
-#include "flex.h"
-
-typedef struct boxes boxes;
-typedef struct matches matches;
-
-struct boxes
-{
- mbox *b_mbox;
- char *b_messid;
- boxes *b_next;
-};
-
-struct matches
-{
- char *me_box;
- char *me_messid;
- char *me_private;
- matches *me_next;
-};
-
-int just_unlock = 0; /* unlock the AUDIT trail */
-int do_audit = 1; /* create an AUDIT trail */
-int silent = 0; /* don't print the header lines */
-int fail = 0;
-
-matches *cmds = (matches *)0;
-
-void
-mess_close(lp, id)
-register lineio *lp;
-register char *id;
-{
- if (lp->l_fd != SYSERROR)
- {
- if (lclose(lp))
- {
- fprintf(stderr, "%s: Warning - \"%s\" may be incomplete. %s\n", my_name, id, sysmess());
- fail = 1;
- }
-
- if (close(lp->l_fd) == SYSERROR)
- {
- would_not("close", id);
- fail = 1;
- }
- }
-}
-
-char *
-new_mess(lp, mb)
-register lineio *lp;
-register mbox *mb;
-{
- register char *id;
- register char *p;
- register int fd;
- static int first = 1;
-
- if (first)
- {
- if (mb->m_count == 0)
- id = nextid(NULLSTR);
- else
- id = nextid(mb->m_list[mb->m_count - 1]);
-
- (void)set_current(mb->m_name, id);
- first = 0;
- }
- else
- {
- id = nextid(mb->m_messid);
- (void)free(mb->m_messid);
- }
-
- p = concat3(mb->m_path, "/", id);
-
- if ((fd = creat(p, CREAT_MODE)) == SYSERROR)
- {
- lp->l_fd = SYSERROR;
- lp->l_flag = LWRITE|LERROR;
- fail = 1;
- would_not("create", p);
- }
- else
- (void)lopen(lp, fd, LWRITE);
-
- (void)free(p);
-
- return mb->m_messid = id;
-}
-
-/*
- * Maintain a cache (linked list) of boxes.
- */
-boxes *
-get_box(s)
-register char *s;
-{
- register boxes *bp;
- register mbox *mb;
- static boxes *all = (boxes *)0;
- static boxes **n = &all;
-
- for (bp = all; bp != (boxes *)0; bp = bp->b_next)
- {
- if (strcmp(bp->b_mbox->m_name, s) == 0)
- return bp;
- }
-
- if ((mb = read_box(s)) == NULLBOX)
- return (boxes *)0;
-
- bp = (boxes *)salloc(sizeof *bp);
- bp->b_mbox = mb;
- bp->b_messid = mb->m_count ? newstr(mb->m_list[mb->m_count - 1]) : NULLSTR;
- bp->b_next = (boxes *)0;
-
- *n = bp;
- n = &bp->b_next;
-
- return bp;
-}
-
-/*
- * Link two messages together.
- */
-int
-tag(box, id, target)
-char *box;
-char *id;
-char *target;
-{
- register char *curr;
- register char *msg;
- register boxes *bp;
- register char *p;
- int ok;
-
- ok = 0;
-
- if ((bp = get_box(target)) != (boxes *)0)
- {
- curr = concat3(mace_dir(), "/", p = concat3(box, "/", id));
- (void)free(p);
-
- msg = concat3(bp->b_mbox->m_path, "/", p = nextid(bp->b_messid));
-
- if (bp->b_messid != NULLSTR)
- (void)free(bp->b_messid);
-
- bp->b_messid = p;
-
- if (link(curr, msg) == -1)
- would_not("link to", msg);
- else
- ok = 1;
-
- (void)free(msg);
- (void)free(curr);
- }
- else
- fprintf(stderr, "%s: Could not save \"%s\" in \"%s\". %s.\n", my_name, id, target, sysmess());
-
- return ok;
-}
-
-/*
- * Match the regular expressions against the headers.
- *
- * This should be replaced by the more general regex_match().
- */
-int
-save(cf, box, id, hdrs)
-conf *cf;
-char *box;
-char *id;
-char **hdrs;
-{
- register char **n;
- register match *mp;
- int hit;
-
- hit = 0;
-
- for (mp = cf->c_save; mp != (match *)0; mp = mp->m_next)
- {
- for (n = hdrs; *n != NULLSTR && **n != '\0'; n++)
- {
- re_error = NULLSTR;
-
- if (regexec(mp->m_cre, *n) == 0)
- {
- if (re_error != NULLSTR)
- {
- fprintf(stderr, "%s: Regular expression \"%s\" %s\n", my_name, mp->m_re, re_error);
- break;
- }
-
- continue;
- }
-
- if (tag(box, id, mp->m_action))
- hit = 1;
- }
- }
-
- return hit;
-}
-
-/*
- * Snarf away a regex match's private data.
- */
-void
-add_match(mp, box, id, private)
-matches **mp;
-char *box;
-char *id;
-char *private;
-{
- matches *p;
-
- while (*mp != (matches *)0)
- mp = &(*mp)->me_next;
-
- *mp = p = (matches *)salloc(sizeof (matches));
- p->me_box = newstr(box);
- p->me_messid = newstr(id);
- p->me_private = private;
- p->me_next = (matches *)0;
-}
-
-/*
- * Match a list of regular expressions against a message's headers.
- */
-void
-regex_match(mp, box, id, hdrs, mlp)
-match *mp;
-char *box;
-char *id;
-char **hdrs;
-matches **mlp;
-{
- register char **n;
-
- while (mp != (match *)0)
- {
- for (n = hdrs; *n != NULLSTR && **n != '\0'; n++)
- {
- re_error = NULLSTR;
-
- if (regexec(mp->m_cre, *n) == 0)
- {
- if (re_error != NULLSTR)
- {
- fprintf(stderr, "%s: Regular expression \"%s\" %s\n", my_name, mp->m_re, re_error);
- break;
- }
-
- continue;
- }
-
- add_match(mlp, box, id, mp->m_action);
- }
-
- mp = mp->m_next;
- }
-}
-
-/*
- * Take a list of matches and run the corresponding commands.
- */
-void
-run_matches(mp)
-matches **mp;
-{
- matches *p;
- int fd;
- lineio l;
- char *av[2];
-
- av[0] = defenv(ENV_SHELL, DEF_SHELL);
- av[1] = NULLSTR;
-
- if ((fd = pipe_execv(av, 'w')) == SYSERROR)
- {
- would_not("pipe to", av[0]);
- return;
- }
-
- (void)lopen(&l, fd, LWRITE);
-
- while ((p = *mp) != (matches *)0 && (l.l_flag & LERROR) == 0)
- {
- (void)lwrite(&l, special_expand(p->me_private, p->me_box, p->me_messid));
-
- (void)free(p->me_box);
- (void)free(p->me_messid);
- *mp = p->me_next;
- (void)free((char *)p);
- }
-
- if (lclose(&l))
- would_not("write pipe to", av[0]);
-
- if (pipe_close(fd) == SYSERROR)
- would_not("close pipe to", av[0]);
-}
-
-/*
- * Simple RFC 822 canonical processing.
- */
-int
-rfc_peruse(cf, box, id, ps)
-conf *cf;
-char *box;
-char *id;
-char **ps;
-{
- register char *p;
- register char *q;
- register char *s;
- static char *agent = DELIVERY_AGENT;
- static regexp *re = (regexp *)0;
- static int bogus_from = 0;
- static int prev_was_header = 0;
- static char *from = NULLSTR;
- static char *date = NULLSTR;
- static vec hdr;
- static char lwsp[2] = { RFC_LWSP_1, '\0'};
- extern char *strchr();
-
- s = *ps;
-
- if (hdr.v_size == 0)
- vec_init(&hdr, 64);
-
- if (agent != NULLSTR && re == (regexp *)0)
- {
- if ((re = regcomp(agent)) == (regexp *)0)
- {
- fprintf(stderr, "%s: Regular expression \"%s\" %s\n", my_name, agent, re_error);
- agent = NULLSTR;
- }
- }
-
- if (*s == UNIX_FWD_CHAR)
- {
- /*
- * Trash or keep misquoted headers gernerated by broken
- * mailers in the middle of the message headers.
- *
- * Eg:
- * From: foo
- * >From foo ... # trash
- * >From: foo # keep
- * Date: ...
- */
- if (prev_was_header)
- {
- if (!rfc_header(s + 1))
- free(s);
- else
- vec_str(&hdr, s);
-
- return 0;
- }
-
- if (!bogus_from)
- goto body;
-
- if (strncmp(s + 1, UNIX_FROM, (sizeof UNIX_FROM) - 1) != 0)
- goto body;
-
- p = newstr(s + 1);
- (void)free(s);
- s = p;
- }
-
- if (strncmp(s, UNIX_FROM, (sizeof UNIX_FROM) - 1) == 0)
- {
- if ((p = strchr(s, ' ')) == NULLSTR)
- {
- fprintf(stderr, "%s: Malformed \"%s\" line in mailbox.\n", my_name, UNIX_FROM);
- (void)free(s);
- return 0;
- }
-
- q = ++p;
-
- while (*q != ' ' && *q != '\0')
- q++;
-
- if (*q == ' ')
- *q++ = '\0';
-
- re_error = NULLSTR;
-
- if (re == (regexp *)0 || regexec(re, p) == 0)
- {
- if (re_error != NULLSTR)
- {
- fprintf(stderr, "%s: Regular expression \"%s\" %s\n", my_name, agent, re_error);
- re = (regexp *)0;
- }
-
- from = concat3(RFC_FROM, lwsp, p);
-
- /*
- * Ensure removal of "remote from ...".
- */
- for (p = q; *p != '\0'; p++)
- {
- if (p - q == UNIX_DATE_LEN)
- {
- *p = '\0';
- break;
- }
- }
-
- date = concat3(RFC_DATE, lwsp, p = rfc_cvt_date(q));
- (void)free(p);
- bogus_from = 0;
- }
- else
- bogus_from = 1;
-
- (void)free(s);
-
- return 0;
- }
-
- /*
- * This should be simpler but we can't guarantee
- * RFC 822 compatibility in respect of the message
- * body being preceeded by a blank line. After all,
- * there are some V7 style mailers out there.
- */
-
- if (rfc_header(s))
- {
- vec_str(&hdr, s);
- prev_was_header = 1;
-
- return 0;
- }
-
- /*
- * Previous line was a header -- concatenate this header text.
- */
- if (prev_was_header && (*s == RFC_LWSP_1 || *s == RFC_LWSP_2))
- {
- vec_cat(&hdr, concat("\n", s));
- (void)free(s);
-
- return 0;
- }
-
- /*
- * End of headers and start of message body.
- */
-body:
- {
- int hit;
- extern long time();
-
- vec_str(&hdr, NULLSTR);
-
- /*
- * Fix the From: and Date: fields.
- */
- if (find_header(hdr.v_list, RFC_FROM) == (char **)0)
- {
- if (from == NULLSTR)
- from = concat3(RFC_FROM, lwsp, "Address Unknown <unknown@nowhere>");
- vec_cat(&hdr, from);
- vec_str(&hdr, NULLSTR);
- }
-
- if (find_header(hdr.v_list, RFC_DATE) == (char **)0)
- {
- if (date == NULLSTR)
- {
- date = concat3(RFC_DATE, lwsp, p = rfc_date(time((long *)0)));
- (void)free(p);
- }
-
- vec_cat(&hdr, date);
- vec_str(&hdr, NULLSTR);
- }
-
- if (*s != '\0')
- {
- vec_cat(&hdr, newstr(""));
- vec_str(&hdr, s);
- }
- else
- vec_cat(&hdr, s);
-
- vec_str(&hdr, NULLSTR);
-
- reorder_headers(&hdr);
-
- hit = save(cf, box, id, &hdr.v_list[0]);
-
- regex_match(cf->c_exec, box, id, &hdr.v_list[0], &cmds);
-
- if (!silent)
- {
- static int first = 1;
-
- print_summary(box, id, hdr.v_list, first, hit ? 2 : 1, 0, 0);
-
- first = 0;
- }
-
- *ps = splice(&hdr.v_list[0], "\n");
-
- (void)free(s);
-
- bogus_from = 0;
- prev_was_header = 0;
- from = NULLSTR;
- date = NULLSTR;
- vec_free(&hdr);
-
- return 1;
- }
-}
-
-/*
- * This message has no body, so we fake it.
- */
-int
-botched_message(cf, mlp, box, id)
-conf *cf;
-register char *box;
-register lineio *mlp;
-register char *id;
-{
- char *s;
-
- s = newstr("");
-
- (void)rfc_peruse(cf, box, id, &s);
-
- if ((mlp->l_flag & LERROR) == 0 && lwrite(mlp, s) == NULLSTR)
- fprintf(stderr, "%s: Warning - \"%s\" may be incomplete. %s\n", my_name, id, sysmess());
-
- (void)free(s);
-
- return (mlp->l_flag & LERROR) != 0;
-}
-
-int
-mace(cf, mf, delete)
-conf *cf;
-char *mf;
-int delete;
-{
- register int fd;
- register char *audit;
- char *s;
- register int text;
- register mbox *mb;
- lineio pld;
- lineio ald;
- lineio mld;
- char *id;
- char *despool;
- extern long lseek();
-
- if ((mb = read_box(cf->c_inbox)) == NULLBOX)
- {
- fprintf(stderr, "%s: Incoming box \"%s\" does not exist.\n", my_name, cf->c_inbox);
- return 1;
- }
-
- audit = concat3(mace_dir(), "/", AUDIT);
-
- if (just_unlock)
- goto fix_locks;
-
- if (!mail_check(mf))
- return 1;
-
- if (set_box(cf->c_inbox))
- return 1;
-
- if (do_audit)
- {
- for (;;)
- {
- switch (lock(audit))
- {
- case 0:
- fd = open(audit, O_WRONLY);
-
- if (lseek(fd, 0L, 2) == SYSERROR)
- {
- (void)close(fd);
- fd = SYSERROR;
- unlock(audit);
- }
- break;
-
- case ENOENT:
- if ((fd = creat(audit, 0666)) == SYSERROR)
- break;
-
- continue;
-
- case EEXIST:
- default:
- fprintf(stderr, "%s: \"%s\" locked. %s\n", my_name, audit, sysmess());
- return 1;
- }
-
- break;
- }
-
- if (fd == SYSERROR)
- {
- would_not("create", audit);
- return 1;
- }
-
- (void)lopen(&ald, fd, LWRITE);
- }
-
- despool = newstr(delete ? cf->c_despool : cf->c_peruse);
-
- if (mf != NULLSTR)
- {
- char *p;
-
- p = despool;
- despool = concat3(p, " -f ", mf);
- (void)free(p);
- }
-
- if ((fd = pipe_open(despool, 'r')) == SYSERROR)
- {
- fail = 1;
- would_not("pipe to", cf->c_despool);
- goto fix_locks;
- }
-
- (void)lopen(&pld, fd, LREAD);
-
- id = NULLSTR;
- mld.l_fd = SYSERROR;
- text = 0;
-
- while ((s = lread(&pld)) != NULLSTR)
- {
- if (strncmp(s, UNIX_FROM, (sizeof UNIX_FROM) - 1) == 0)
- {
- if (id != NULLSTR && text == 0 && botched_message(cf, &mld, mb->m_name, id))
- fail = 1;
-
- text = 0;
-
- mess_close(&mld, id);
-
- id = new_mess(&mld, mb);
- }
-
- if
- (
- do_audit
- &&
- (ald.l_flag & LERROR) == 0
- &&
- lwrite(&ald, s) == NULLSTR
- )
- {
- would_not("write", audit);
- fail = 1;
- }
-
- if (!text && rfc_peruse(cf, mb->m_name, id, &s))
- text = 1;
-
- if (text)
- {
- if ((mld.l_flag & LERROR) == 0 && lwrite(&mld, s) == NULLSTR)
- {
- fprintf(stderr, "%s: Warning - \"%s\" may be incomplete. %s\n", my_name, id, sysmess());
- fail = 1;
- }
-
- (void)free(s);
- }
-
- if
- (
- (
- (ald.l_flag & LERROR) != 0
- ||
- do_audit == 0
- )
- &&
- (mld.l_flag & LERROR) != 0
- )
- break;
- }
-
- if (id != NULLSTR && text == 0 && botched_message(cf, &mld, mb->m_name, id))
- fail = 1;
-
- mess_close(&mld, id);
-
- if (do_audit)
- {
- if (lclose(&ald))
- {
- fprintf(stderr, "%s: Warning - audit \"%s\" may be incomplete. %s\n", my_name, audit, sysmess());
- fail = 1;
- }
-
- if (close(ald.l_fd) == SYSERROR)
- {
- would_not("close", audit);
- fail = 1;
- }
- }
-
- if (lclose(&pld) != 0)
- {
- fprintf(stderr, "%s: \"%s\" line close error.\n", my_name, cf->c_despool, sysmess());
- fail = 1;
- }
-
- if (pipe_close(fd) != 0)
- {
- fprintf(stderr, "%s: \"%s\" despooling error.\n", my_name, cf->c_despool, sysmess());
- fail = 1;
- }
-
-fix_locks:
- if (do_audit && unlock(audit) != 0)
- would_not("unlock", audit);
-
- (void)free(audit);
-
- run_matches(&cmds);
-
- return fail;
-}
-
-void
-usage()
-{
- fprintf(stderr, "usage: %s [ -dsu ] [ -f mailfile ]\n", my_name);
- exit(1);
- /* NOTREACHED */
-}
-
-int
-main(argc, argv)
-int argc;
-char *argv[];
-{
- register int i;
- register int j;
- char *mail_file;
- int delete;
-
- name(argv[0]);
- mail_file = NULLSTR;
- delete = 1;
-
- for (i = 1; i < argc; i++)
- {
- if (argv[i][0] != '-')
- {
- usage();
- /* NOTREACHED */
- }
-
- j = 1;
-
- while (argv[i][j] != '\0')
- {
- switch (argv[i][j++])
- {
- case 'd':
- do_audit = 0;
- continue;
-
- case 's':
- silent = 1;
- continue;
-
- case 'u':
- just_unlock = 1;
- continue;
-
- case 'f':
- if (mail_file != NULLSTR)
- {
- usage();
- /* NOTREACHED */
- }
-
- if (argv[i][j] != '\0')
- mail_file = &argv[i][j];
- else if (++i < argc)
- mail_file = argv[i];
- else
- {
- usage();
- /* NOTREACHED */
- }
-
- delete = 0;
- break;
-
- default:
- usage();
- /* NOTREACHED */
- }
-
- break;
- }
- }
-
- if (just_unlock && !do_audit)
- {
- usage();
- /* NOTREACHED */
- }
-
- /*
- * Here's hoping...
- */
- (void)signal(SIGHUP, SIG_IGN);
- (void)signal(SIGINT, SIG_IGN);
- (void)signal(SIGQUIT, SIG_IGN);
- (void)signal(SIGTERM, SIG_IGN);
-
- exit(mace(read_config(), mail_file, delete));
-
- /* NOTREACHED */
-}
//GO.SYSIN DD mace.c
echo mad.c
sed 's/.//' >mad.c <<'//GO.SYSIN DD mad.c'
-/*
- * mad|mcp|mln +box messages...
- *
- * mad - add messages to a box
- *
- * mcp - copy messages to a box
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)mad.c 1.29";
-#endif lint
-
-#include "mace.h"
-#include <stdio.h>
-#include <signal.h>
-
-int
-mad(s, t)
-register char *s;
-register char *t;
-{
- if
- (
- link(s, t) == SYSERROR
- ||
- unlink(s) == SYSERROR
- )
- {
- would_not("move", s);
- (void)unlink(t);
- return 1;
- }
-
- return 0;
-}
-
-int
-mln(s, t)
-register char *s;
-register char *t;
-{
- if (link(s, t) == SYSERROR)
- {
- would_not("link", s);
- return 1;
- }
-
- return 0;
-}
-
-int
-mcp(s, t)
-register char *s;
-register char *t;
-{
- register int rfd;
- register int wfd;
- register int n;
- char buf[FS_BLKZ];
-
- if ((rfd = open(s, O_RD)) == SYSERROR)
- {
- would_not("open", s);
- return 1;
- }
-
- if ((wfd = creat(t, CREAT_MODE)) == SYSERROR)
- {
- (void)close(rfd);
- would_not("create", t);
- return 1;
- }
-
- for (;;)
- {
- switch (n = read(rfd, buf, sizeof buf))
- {
- case SYSERROR:
- would_not("read", s);
- goto disaster;
-
- case 0:
- break;
-
- default:
- if (write(wfd, buf, n) != n)
- {
- would_not("write", t);
- goto disaster;
- }
-
- continue;
- }
-
- break;
- }
-
- if (close(rfd) == SYSERROR)
- {
- (void)close(wfd);
- (void)unlink(t);
- return 1;
- }
-
- if (close(wfd) == SYSERROR)
- {
- (void)unlink(t);
- return 1;
- }
-
- return 0;
-
-disaster:
- (void)close(rfd);
- (void)close(wfd);
- (void)unlink(t);
-
- return 1;
-}
-
-void
-usage()
-{
- fprintf(stderr, "usage: %s %cbox messages...\n", my_name, BOX_CHAR);
- exit(1);
- /* NOTREACHED */
-}
-
-int
-main(argc, argv)
-register int argc;
-register char *argv[];
-{
- register mbox *mb;
- register int i;
- register char *id;
- int (*action)();
- char *box;
- int ok;
-
- name(argv[0]);
-
- if (strcmp(my_name, "mad") == 0)
- action = mad;
- else if (strcmp(my_name, "mcp") == 0)
- action = mcp;
- else if (strcmp(my_name, "mln") == 0)
- action = mln;
- else
- {
- fprintf(stderr, "%s: Invocation error.\n", my_name);
- exit(1);
- /* NOTREACHED */
- }
-
- if (argc < 3 || argv[1][0] != BOX_CHAR || argv[1][1] == '\0')
- {
- usage();
- /* NOTREACHED */
- }
-
- box = &argv[1][1];
-
- if ((mb = read_box(box)) == NULLBOX)
- {
- fprintf(stderr, "%s: No such box as \"%s\".\n", my_name, box);
- exit(1);
- /* NOTREACHED */
- }
-
- if (mb->m_count == 0)
- id = nextid(NULLSTR);
- else
- id = nextid(mb->m_list[mb->m_count - 1]);
-
- ok = 0;
-
- for (i = 2; i < argc; i++)
- {
- register char *p;
-
- p = concat3(mb->m_path, "/", id);
-
- signal(SIGHUP, SIG_IGN);
- signal(SIGINT, SIG_IGN);
- signal(SIGQUIT, SIG_IGN);
- signal(SIGTERM, SIG_IGN);
-
- if ((*action)(argv[i], p))
- ok = 1;
- else if (set_current(mb->m_name, id))
- ok = 1;
-
- signal(SIGHUP, SIG_DFL);
- signal(SIGINT, SIG_DFL);
- signal(SIGQUIT, SIG_DFL);
- signal(SIGTERM, SIG_DFL);
-
- free(p);
- p = id;
- id = nextid(id);
- free(p);
- }
-
- return ok;
-}
//GO.SYSIN DD mad.c
echo mal
sed 's/.//' >mal <<'//GO.SYSIN DD mal'
-#!/bin/sh
-#
-# @(#)mal 1.2
-#
-# mal +box ...
-#
-# Mail aliasing based on a box's .proto
-#
-
-dir="$HOME/.macedir"
-bchar=+
-proto=.proto
-
-myname="`basename \"$0\"`"
-
-case $# in
-0)
- echo "usage: $myname ${bchar}box ..." 1>&2
- exit 1
- ;;
-esac
-
-# find mail directory
-if [ ! -r "$dir" ]
-then
- echo "$myname: Could not read '$dir'." 1>&2
- exit 1
-fi
-
-mdir="`cat \"$dir\"`"
-
-case "$mdir" in
-"")
- echo "$myname: '$dir' empty." 1>&2
- exit 1
- ;;
-
-/*)
- # absolute pathname, ok
- ;;
-
-*)
- # relative pathname, so prepend $HOME
- mdir="$HOME/$mdir"
- ;;
-esac
-
-for b
-do
- # use box to verify box name, but the usage message is a bit weird
- if box -l "$b" > /dev/null
- then
- case "$b" in
- ${bchar}*)
- # slice off leading ${bchar}
- b="`expr \"$b\" : \"^${bchar}\(.*\)$\"`"
- ;;
- esac
-
- # snarf To:/Cc:/Bcc:
- sed -n \
- -e '/^[Tt][Oo][ ]*:[ ]*/s///p' \
- -e '/^[Cc][Cc][ ]*:[ ]*/s///p' \
- -e '/^[Bb][Cc][Cc][ ]*:[ ]*/s///p' \
- "$mdir/$b/$proto" 2> /dev/null
- fi
-done | sed -e '$n' -e 's/$/,/' # insert , between addresses
//GO.SYSIN DD mal
echo mam.c
sed 's/.//' >mam.c <<'//GO.SYSIN DD mam.c'
-/*
- * mam [ -u ] [ -dps ] [ +[+]box ] [ files ] ...
- *
- * Read an RFC 822 message and add it to a box.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)mam.c 1.5";
-#endif lint
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <signal.h>
-#include "mace.h"
-#include "regexp.h"
-#include "line.h"
-#include "message.h"
-
-typedef struct boxes boxes;
-typedef struct matches matches;
-
-struct boxes
-{
- mbox *mbox;
- char *messid;
- int first;
- boxes *next;
-};
-
-int just_unlock = 0; /* unlock the AUDIT trail */
-int do_audit = 1; /* create an AUDIT trail */
-int preserve = 0; /* preserve the current message */
-int silent = 0; /* don't print the header lines */
-int quit = 0; /* exit when ready */
-int errors = 0; /* error occured */
-
-enum
-{
- Lock = 0, /* lock audit file */
- Write, /* write to audit file */
- Unlock, /* unlock audit file */
-};
-
-/*
- * Maintain a cache (linked list) of boxes.
- */
-boxes *
-get_box(s)
-register char *s;
-{
- register boxes *bp;
- register mbox *mb;
- static boxes *all = (boxes *)0;
- static boxes **n = &all;
-
- for (bp = all; bp != (boxes *)0; bp = bp->next)
- {
- if (strcmp(bp->mbox->m_name, s) == 0)
- return bp;
- }
-
- if ((mb = read_box(s)) == NULLBOX)
- return (boxes *)0;
-
- bp = (boxes *)salloc(sizeof *bp);
- bp->mbox = mb;
- bp->messid = mb->m_count ? newstr(mb->m_list[mb->m_count - 1]) : NULLSTR;
- bp->first = 1;
- bp->next = (boxes *)0;
-
- *n = bp;
- n = &bp->next;
-
- return bp;
-}
-
-/*
- * Manage the audit trail.
- */
-void
-audit(int type, char *s)
-{
- static char *file = NULLSTR;
- static lineio l = { SYSERROR, };
-
- if (file == NULLSTR)
- file = concat3(mace_dir(), "/", AUDIT);
-
- switch (type)
- {
- case Lock:
- for (;;)
- {
- int fd;
-
- switch (lock(file))
- {
- case 0:
- fd = open(file, O_WRONLY);
-
- if (lseek(fd, 0L, 2) == SYSERROR)
- {
- (void)close(fd);
- fd = SYSERROR;
- unlock(file);
- }
-
- lopen(&l, fd, LWRITE);
- break;
-
- case ENOENT:
- if ((fd = creat(file, CREAT_MODE)) == SYSERROR)
- {
- could_not("creat", file);
- /* NOTREACHED */
- }
-
- continue;
-
- case EEXIST:
- default:
- fprintf(stderr, "%s: \"%s\" locked. %s\n", my_name, file, sysmess());
- exit(1);
- /* NOTREACHED */
- }
-
- return;
- }
-
- case Write:
- if (l.l_fd == SYSERROR)
- {
- fatal("audit: not locked");
- /* NOTREACHED */
- }
-
- if ((l.l_flag & LERROR) != 0)
- return;
-
- if (lwrite(&l, s) == NULLSTR)
- {
- would_not("write", file);
- quit = 1;
- }
- break;
-
- case Unlock:
- if (l.l_fd != SYSERROR && (l.l_flag & LERROR) == 0)
- {
- if (lclose(&l))
- {
- fprintf(stderr, "%s: warning: '%s' incomplete. %s\n", my_name, file, sysmess());
- quit = 1;
- }
-
- if (close(l.l_fd) == SYSERROR)
- {
- would_not("close", file);
- quit = 1;
- }
- }
-
- if (unlock(file) != 0)
- {
- could_not("unlock", file);
- /* NOTREACHED */
- }
-
- return;
-
- default:
- fatal("audit: unknown type");
- /* NOTREACHED */
- }
-}
-
-/*
- * Catch a signal and force exit.
- */
-void
-signalled(int s)
-{
- signal(s, SIG_IGN);
- quit = 1;
-}
-
-/*
- * Arrange for signals to be caught.
- */
-void
-catch()
-{
- int i;
- static int sigs[] =
- {
- SIGHUP,
- SIGINT,
- SIGQUIT,
- SIGTERM,
- };
- static char *names[] =
- {
- "SIGHUP",
- "SIGINT",
- "SIGQUIT",
- "SIGTERM",
- };
-
- for (i = 0; i < sizeof sigs / sizeof sigs[0]; i++)
- {
- SIG_RET (*f)();
-
- if ((f = signal(sigs[i], signalled)) == (SIG_RET (*)())SYSERROR)
- {
- could_not("set signal", names[i]);
- /* NOTREACHED */
- }
-
- if (f == SIG_DFL || f == SIG_IGN)
- continue;
-
- if (signal(sigs[i], f) == (SIG_RET (*)())SYSERROR)
- {
- could_not("reset signal", names[i]);
- /* NOTREACHED */
- }
- }
-}
-
-/*
- * Close a line and it's file descriptor, handling errors.
- */
-void
-clunk(lineio *l, char *f, char *box, char *id)
-{
- int fd;
- int rw;
-
- if (l->l_flag == 0)
- return;
-
- fd = l->l_fd;
- rw = (l->l_flag & LWRITE) != 0;
-
- if (lclose(l))
- {
- if (rw)
- would_not("lclose", f);
- else
- fprintf(stderr, "%s: warning: %c%s %s may be incomplete. %s\n", my_name, BOX_CHAR, box, id, sysmess());
-
- close(fd);
- errors = 1;
- return;
- }
-
- if (close(fd) == SYSERROR)
- {
- would_not("close", f);
- errors = 1;
- }
-}
-
-/*
- * Write an audited line to a message file.
- */
-void
-awrite(lineio *l, char *s)
-{
- if (do_audit)
- audit(Write, s);
-
- if ((l->l_flag & LERROR) == 0)
- lwrite(l, s);
-}
-
-/*
- * Read a file containing an RFC 822 message and add it to a box.
- */
-void
-mam(char *box, char *f)
-{
- boxes *b;
- char *id;
- message *m;
- int fd;
- char *s;
- char *new;
- lineio in;
- lineio out;
- int first;
- char **h;
-
- if ((b = get_box(box)) == 0)
- {
- fprintf(stderr, "%s: No such box as %c%s\n", my_name, BOX_CHAR, box);
- errors = quit = 1;
- return;
- }
-
- first = 0;
- id = b->messid = nextid(b->messid);
-
- /*
- * Set first message to be current.
- */
- if (preserve == 0 && b->first)
- {
- if (set_current(box, id) == 0)
- {
- first = 1;
- b->first = 0;
- }
- else
- errors = 1;
- }
-
- /*
- * Validate headers.
- */
- if ((m = f != NULLSTR ? parse_file(f, &in) : parse_fd(fileno(stdin), &in)) == NULLMESS)
-
- {
- would_not("parse", f != NULLSTR ? f : "<stdin>");
- errors = 1;
- return;
- }
-
- if (!silent)
- print_summary(box, id, m->ms_headers.v_list, first, 1, 0, 0);
-
- /*
- * Copy the file into the new message with auditing.
- */
- out.l_flag = 0;
-
- new = concat3(b->mbox->m_path, "/", id);
-
- if ((fd = creat(new, CREAT_MODE)) == SYSERROR)
- {
- would_not("create", new);
- errors = 1;
- goto finish;
- }
-
- lopen(&out, fd, LWRITE);
-
- /*
- * Write out headers.
- */
- reorder_headers(&m->ms_headers);
-
- for (h = m->ms_headers.v_list; (s = *h) != NULLSTR; h++)
- awrite(&out, s);
-
- free_mess(m);
-
- /*
- * Write separator between headers and body.
- */
- awrite(&out, "");
-
- /*
- * Write out message body.
- */
- while ((s = lread(&in)) != NULLSTR && !quit)
- {
- awrite(&out, s);
- free(s);
- }
-
-finish:
- clunk(&in, f, box, id);
- clunk(&out, new, box, id);
-}
-
-void
-usage()
-{
- fprintf(stderr, "usage: %s [ -u ] [ -dps ] [ +[+]box ] [ files ] ... \n", my_name);
- exit(1);
- /* NOTREACHED */
-}
-
-int
-main(int argc, char *argv[])
-{
- int i;
- int j;
- char *box;
- int filter;
-
- name(argv[0]);
-
- for (i = 1; i < argc; i++)
- {
- if (argv[i][0] != '-')
- break;
-
- j = 1;
-
- while (argv[i][j] != '\0')
- {
- switch (argv[i][j++])
- {
- case 'd':
- do_audit = 0;
- continue;
-
- case 'p':
- preserve = 1;
- continue;
-
- case 's':
- silent = 1;
- continue;
-
- case 'u':
- just_unlock = 1;
- continue;
-
- default:
- usage();
- /* NOTREACHED */
- }
-
- break;
- }
- }
-
- if (just_unlock)
- {
- if (argc > 2)
- {
- usage();
- /* NOTREACHED */
- }
-
- audit(Unlock, NULLSTR);
- exit(0);
- /* NOTREACHED */
- }
-
- if ((box = curr_box()) == NULLSTR)
- {
- fprintf(stderr, "%s: No current box.\n", my_name);
- exit(1);
- /* NOTREACHED */
- }
-
- catch();
-
- if (do_audit)
- audit(Lock, NULLSTR);
-
- filter = 1;
-
- while (i < argc && !quit)
- {
- /*
- * New box to pick messages from?
- */
- if (argv[i][0] == BOX_CHAR)
- {
- /*
- * Change current box?
- */
- if (argv[i][1] == BOX_CHAR)
- {
- box = newstr(&argv[i][2]);
-
- if (set_box(box))
- {
- quit = errors = 1;
- filter = 0;
- break;
- }
- }
- else
- box = &argv[i][1];
- }
- else
- {
- mam(box, argv[i]);
- filter = 0;
- }
-
- i++;
- }
-
- if (filter)
- mam(box, NULLSTR);
-
- if (do_audit)
- audit(Unlock, NULLSTR);
-
- exit(errors);
- return errors;
-}
//GO.SYSIN DD mam.c
echo mda.c
sed 's/.//' >mda.c <<'//GO.SYSIN DD mda.c'
-/*
- * mda messages...
- *
- * Message delivery agent.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)mda.c 1.31";
-#endif lint
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include "mace.h"
-#include "regexp.h"
-#include "line.h"
-#include "message.h"
-#include "conf.h"
-#include "headers.h"
-#include "addr.h"
-
-/*
- * Turn an RFC 822 address into a network address argument.
- */
-char *
-net_address(vp, s)
-register vec *vp;
-register char *s;
-{
- register char *p;
- register Addr *ap;
- Addr *addrs;
-
- if ((p = parse_address(&addrs, s)) != NULLSTR)
- return p;
-
- for (ap = addrs; ap != (Addr *)0; ap = ap->next)
- vec_str(vp, make_address(ap));
-
- return NULLSTR;
-}
-
-/*
- * Add multiple To:/Cc:/Bcc lines to a list of recipients.
- *
- * Returns 0 on success, 1 on failure.
- */
-int
-add_multiple(char *m, vec *list, char **h, char *type)
-{
- int n;
-
- n = 0;
-
- while (*h != NULLSTR)
- {
- if (rfc_hdr_cmp(*h, type))
- {
- char *p;
-
- if ((p = header_text(*h)) == NULLSTR)
- {
- /* Empty Bcc: is ok */
- if (strcmp(type, RFC_BCC) != 0)
- {
- fprintf(stderr, "%s: \"%s\": Malformed \"%s\" field.\n", my_name, m, type);
- return 1;
- }
- }
- else if ((p = net_address(list, p)) != NULLSTR)
- {
- fprintf(stderr, "%s: \"%s\": \"%s\" address error; %s\n", my_name, m, type, p);
- return 1;
- }
-
- n++;
- }
-
- h++;
- }
-
- /* Only one From: allowed */
- if (strcmp(type, RFC_FROM) == 0 && n > 1)
- {
- fprintf(stderr, "%s: \"%s\": Multiple \"%s\" fields.\n", my_name, m, RFC_FROM);
- return 1;
- }
-
- return 0;
-}
-
-/*
- * Check From: field(s).
- *
- * Returns 0 on success, 1 on failure.
- */
-int
-from(char *m, char **h)
-{
- vec v;
- int n;
- int fail;
-
- fail = 0;
-
- vec_init(&v, 32);
-
- if (add_multiple(m, &v, h, RFC_FROM))
- fail = 1;
-
- n = v.v_count;
- vec_free(&v);
-
- if (fail)
- return fail;
-
- /*
- * Check there is a Sender: field if more than one address in
- * the From: field has been specified.
- */
- if (n <= 1)
- return 0;
-
- if
- (
- (h = find_header(h, RFC_SENDER)) != (char **)NULLSTR
- &&
- header_text(*h) != NULLSTR
- )
- return 0;
-
- fprintf(stderr, "%s: \"%s\": Multiple \"%s\" addresses require a \"%s\" field.\n", my_name, m, RFC_FROM, RFC_SENDER);
- return 1;
-}
-
-#if RFC_DELIVERER == 0
-
-/*
- * Pipe the message into the delivery agent after some validation.
- */
-int
-deliver(d, m)
-char *d;
-char *m;
-{
- char *p;
- message *mp;
- char **h;
- lineio mld;
- lineio pld;
- vec args;
- int mfd;
- int pfd;
- int headers;
- static char *dests[] = { RFC_TO, RFC_CC, RFC_BCC, NULLSTR };
-
- /*
- * Read its headers.
- */
- if ((mp = parse_file(m, 0)) == NULLMESS)
- {
- would_not("open", m);
- return 1;
- }
-
- vec_init(&args, 32);
-
- /*
- * Date: field?
- */
- if
- (
- (h = find_header(&mp->ms_headers.v_list[0], RFC_DATE)) == (char **)NULLSTR
- ||
- header_text(*h) == NULLSTR
- )
- {
- fprintf(stderr, "%s: \"%s\": Missing \"%s\" field.\n", my_name, m, RFC_DATE);
- goto disaster;
- }
-
- /*
- * From: field(s)?
- */
- if (from(m, mp->ms_headers.v_list))
- goto disaster;
-
- vec_str(&args, d);
-
- /*
- * Add destination(s).
- */
- for (h = dests; *h != NULLSTR; h++)
- {
- if (add_multiple(m, &args, mp->ms_headers.v_list, *h))
- goto disaster;
- }
-
- if (args.v_count == 1)
- {
- fprintf(stderr, "%s: \"%s\": No destination.\n", my_name, m);
- goto disaster;
- }
-
- vec_str(&args, NULLSTR);
-
- /*
- * Pipe it into the delivery agent.
- */
- if ((mfd = open(m, O_RD)) == SYSERROR)
- {
- would_not("open", m);
- goto disaster;
- }
-
- (void)lopen(&mld, mfd, LREAD);
-
- if ((pfd = pipe_execv(args.v_list, 'w')) == -1)
- {
- would_not("pipe to", args.v_list[0]);
- (void)lclose(&mld);
- (void)close(mfd);
- goto disaster;
- }
-
- (void)lopen(&pld, pfd, LWRITE);
-
- for (h = mp->ms_headers.v_list; *h != NULLSTR; h++)
- {
- if (header_text(*h) == NULLSTR || rfc_hdr_cmp(*h, RFC_BCC))
- continue;
-
- if (lwrite(&pld, *h) == NULLSTR)
- goto failure;
- }
-
- headers = 1;
-
- while ((p = lread(&mld)) != NULLSTR)
- {
- if (headers)
- {
- if (*p != '\0')
- {
- (void)free(p);
- continue;
- }
-
- headers = 0;
- }
-
- if (lwrite(&pld, p) == NULLSTR)
- {
- (void)free(p);
- break;
- }
-
- (void)free(p);
- }
-
-failure:
- if (lclose(&mld))
- {
- would_not("read", m);
-
- (void)close(mfd);
- (void)lclose(&pld);
- (void)pipe_close(pfd);
- goto disaster;
- }
-
- (void)close(mfd);
-
- if (lclose(&pld))
- {
- would_not("deliver", m);
- (void)pipe_close(pfd);
- goto disaster;
- }
-
- if (pipe_close(pfd))
- {
- would_not("deliver", m);
- goto disaster;
- }
-
- free_mess(mp);
- vec_free(&args);
- return 0;
-
-disaster:
- free_mess(mp);
- vec_free(&args);
- return 1;
-}
-
-#else RFC_DELIVERER == 0
-
-#if RFC_VALIDATE != 0
-
-/*
- * Check that the supplied headers in the message are ok. If evils
- * like `sendmail' were half way sane this wouldn't be necessary,
- * but I'm sick of getting mail from `mailer-daemon' about garbled
- * headers, that should have been barfed on at invocation.
- */
-int
-headers_ok(m)
-char *m;
-{
- char **cp;
- message *mp;
- int fail;
- vec v;
- static char *check[] = { RFC_TO, RFC_CC, RFC_BCC, NULLSTR, };
-
- fail = 0;
-
- /*
- * Read its headers.
- */
- if ((mp = parse_file(m, 0)) == NULLMESS)
- {
- would_not("open", m);
- return 1;
- }
-
- /*
- * From: field(s)?
- */
- if (from(m, mp->ms_headers.v_list))
- fail = 1;
-
- vec_init(&v, 32);
-
- /*
- * Check the specified headers.
- */
- for (cp = check; *cp != NULLSTR; cp++)
- {
- if (add_multiple(m, &v, mp->ms_headers.v_list, *cp))
- fail = 1;
- }
-
- if (v.v_count == 0)
- {
- fprintf(stderr, "%s: \"%s\": No destination.\n", my_name, m);
- fail = 1;
- }
-
- (void)free_mess(mp);
- vec_free(&v);
- return fail;
-}
-
-#endif RFC_VALIDATE != 0
-
-/*
- * The delivery agent understands about the recipients
- * being embedded in the message itself.
- */
-int
-deliver(d, m)
-char *d;
-char *m;
-{
- register int fd;
- register int ok;
- register char *agent = DELIVERER;
- char *argv[2];
-
- if (agent == NULLSTR)
- {
- fatal("deliver");
- /* NOTREACHED */
- }
-
- (void)close(0);
-
- if ((fd = open(m, O_RD)) != 0)
- {
- would_not("open", m);
- (void)close(fd);
- return 1;
- }
-
-#if RFC_VALIDATE != 0
-
- if (headers_ok(m))
- {
- (void)close(fd);
- return 1;
- }
-
-#endif RFC_VALIDATE != 0
-
- argv[0] = d;
- argv[1] = NULLSTR;
-
- ok = run(argv);
-
- if (close(0) == SYSERROR)
- {
- would_not("close", m);
- ok = 1;
- }
-
- return ok;
-}
-
-#endif RFC_DELIVERER == 0
-
-void
-usage()
-{
- fprintf(stderr, "usage: %s messages...\n", my_name);
- exit(1);
- /* NOTREACHED */
-}
-
-int
-main(argc, argv)
-int argc;
-char *argv[];
-{
- register int i;
- register conf *cf;
- register int ok;
-
- name(argv[0]);
-
- if (argc < 2)
- {
- usage();
- /* NOTREACHED */
- }
-
- cf = read_config();
-
- ok = 0;
-
- for (i = 1; i < argc; i++)
- {
- if (deliver(cf->c_deliver, argv[i]) || set_state(argv[i], MESG_SENT))
- ok = 1;
- }
-
- exit(ok);
- /* NOTREACHED */
-}
//GO.SYSIN DD mda.c
echo mox.c
sed 's/.//' >mox.c <<'//GO.SYSIN DD mox.c'
-/*
- * mox [ -ds ] [ -delete ]
- *
- * Add messages, one per file, from a directory with mam.
- * Sort of like mace, but not quite.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)mox.c 1.2";
-#endif lint
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <signal.h>
-#include "mace.h"
-#include "regexp.h"
-#include "line.h"
-#include "message.h"
-#include "conf.h"
-
-int delete = 0; /* delete files from spool directory */
-char *_delete = "-delete";
-int do_audit = 1; /* create an AUDIT trail */
-int silent = 0; /* don't print message summary */
-
-/*
- * Link a message into another box by calling 'lnk'.
- */
-void
-refile(char *inbox, message *m, match *re)
-{
- char *args[6];
- int i;
- int bi;
- int bo;
-
- args[i = 0] = LNK_STR;
- args[bi = ++i] = concat(" ", inbox);
- args[bi][0] = BOX_CHAR;
- args[++i] = m->ms_messid;
- args[bo = ++i] = concat(" ", re->m_action);
- args[bo][0] = BOX_CHAR;
- args[++i] = NULLSTR;
-
- if (run(args) == 0)
- m->ms_copies++;
-
- free(args[bi]);
- free(args[bo]);
-}
-
-/*
- * Run a command with a message.
- */
-void
-command(char *inbox, message *m, match *re)
-{
- char *args[2];
- int i;
-
- /* we know that run calls sh -c */
- args[i = 0] = special_expand(re->m_action, inbox, m->ms_messid);
- args[++i] = NULLSTR;
-
- run(args);
-}
-
-/*
- * Invoke 'mam' to add a message to a box returning the newly created message.
- *
- * Returns NULLMESS on failure.
- */
-message *
-mam(char *inbox, char *file, int first)
-{
- message *m;
- char *args[7];
- mbox *b;
- int i;
- int bi;
-
- /*
- * Invoke mam, silently, preserving the first message added to the box.
- */
- args[i = 0] = MAM_STR;
- args[++i] = "-s";
- if (!first)
- args[++i] = "-p";
- if (!do_audit)
- args[++i] = "-d";
- args[bi = ++i] = concat(" ", inbox);
- args[bi][0] = BOX_CHAR;
- args[++i] = file;
- args[++i] = NULLSTR;
-
- if (run(args) || (b = read_box(inbox)) == NULLBOX)
- {
- free(args[bi]);
- return NULLMESS;
- }
-
- free(args[bi]);
-
- /*
- * Newly added message will be the last in the box.
- */
- if (b->m_count == 0 || (m = read_mess(b, b->m_list[b->m_count - 1])) == NULLMESS)
- {
- free_box(b);
- return NULLMESS;
- }
-
- free_box(b);
- return m;
-}
-
-/*
- * Treat each file in a directory as a mail message passing
- * it to 'mam' and matching it against regular expressions.
- */
-int
-mox()
-{
- conf *cf;
- char **dir;
- char **d;
- int first;
- int fail;
-
- first = 1;
- fail = 0;
-
- cf = read_config();
-
- if (cf->c_spooldir == NULLSTR)
- {
- fprintf(stderr, "%s: Specification of \"%s\" missing from \"%s/%s\".\n", my_name, CT_SPOOLDIR, mace_dir(), CONFIG);
- return 1;
- }
-
- dir = read_dir(cf->c_spooldir);
-
- for (d = dir; *d != NULLSTR; d++)
- {
- char *f;
- message *m;
-
- f = concat3(cf->c_spooldir, "/", *d);
-
- if ((m = mam(cf->c_inbox, f, first)) == NULLMESS)
- {
- free(f);
- fail = 1;
- continue;
- }
-
- if (first && set_box(cf->c_inbox))
- fail = 1;
-
- /*
- * Summarise after the refile's but before the exec's.
- * This way the output is more meaningful.
- */
- regex_apply(cf->c_inbox, m, cf->c_refile, refile);
-
- if (!silent)
- print_summary(cf->c_inbox, m->ms_messid, m->ms_headers.v_list, first, m->ms_copies, 0, m->ms_state);
-
- regex_apply(cf->c_inbox, m, cf->c_exec, command);
-
- free_mess(m);
- first = 0;
-
- if (delete && unlink(f) == SYSERROR)
- {
- would_not("unlink", f);
- fail = 1;
- }
-
- free(f);
- }
-
- free_dir(dir);
- return fail;
-}
-
-void
-usage()
-{
- fprintf(stderr, "usage: %s [ -ds ] [ %s ]\n", my_name, _delete);
- exit(1);
- /* NOTREACHED */
-}
-
-int
-main(int argc, char *argv[])
-{
- int i;
- int j;
-
- name(argv[0]);
-
- for (i = 1; i < argc; i++)
- {
- if (argv[i][0] != '-')
- {
- usage();
- /* NOTREACHED */
- }
-
- j = 1;
-
- while (argv[i][j] != '\0')
- {
- switch (argv[i][j++])
- {
- case 's':
- silent = 1;
- continue;
-
- case 'd':
- /* this is not good */
- if (strcmp(argv[i], _delete) != 0)
- {
- do_audit = 0;
- continue;
- }
-
- delete = 1;
- break;
-
- default:
- usage();
- /* NOTREACHED */
- }
-
- break;
- }
- }
-
- exit(mox());
- return 0; /* shut up! */
- /* NOTREACHED */
-}
//GO.SYSIN DD mox.c
echo msg.c
sed 's/.//' >msg.c <<'//GO.SYSIN DD msg.c'
-/*
- * msg - show messages
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)msg.c 1.39";
-#endif lint
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include "mace.h"
-#include "flex.h"
-#include "line.h"
-#include "message.h"
-
-char *target = NULLSTR; /* target box for mov|cop|lnk */
-char *new_box = NULLSTR; /* new current box */
-
-int
-apply(it, v)
-register char *it;
-register vec *v;
-{
- register int i;
- register char **n;
- register char **argv;
- int s;
-
- argv = n = (char **)salloc((int)((v->v_count + 2) * sizeof(char *)));
-
- *n++ = it;
-
- for (i = 0; i < v->v_count; i++)
- *n++ = v->v_list[i];
-
- *n = NULLSTR;
-
- s = run(argv);
-
- (void)free((char *)argv);
-
- return s != 0;
-}
-
-int
-msg(v)
-register vec *v;
-{
- return apply(defenv(ENV_PAGER, DEF_PAGER), v);
-}
-
-int
-med(v)
-register vec *v;
-{
- return apply(defenv(ENV_EDITOR, DEF_EDITOR), v);
-}
-
-int
-rem(v)
-register vec *v;
-{
- register int i;
- int ok;
-
- ok = 0;
-
- for (i = 0; i < v->v_count; i++)
- {
- if (unlink(v->v_list[i]) == SYSERROR)
- {
- would_not("unlink", v->v_list[i]);
- ok = 1;
- }
- }
-
- return ok;
-}
-
-int
-invoke_alias(s, v)
-register char *s;
-register vec *v;
-{
- register char *what;
- register char *q;
- int ok;
- char p[2];
-
- p[0] = BOX_CHAR;
- p[1] = '\0';
-
- q = concat(p, target);
- what = concat3(s, " ", q);
- free(q);
-
- ok = apply(what, v);
-
- free(what);
-
- return ok;
-}
-
-int
-mov(v)
-register vec *v;
-{
- return invoke_alias(MAD_STR, v);
-}
-
-int
-cop(v)
-register vec *v;
-{
- return invoke_alias(MCP_STR, v);
-}
-
-int
-lnk(v)
-register vec *v;
-{
- return invoke_alias(MLN_STR, v);
-}
-
-int
-del(v)
-register vec *v;
-{
- return apply(MDA_STR, v);
-}
-
-int
-mrk(v)
-register vec *v;
-{
- register char *p;
- register int i;
- char *ids;
- flex f;
- int ok;
-
- flex_init(&f);
- ok = 0;
-
- for (i = 0; i < v->v_count; i++)
- {
- char *b;
- char *m;
-
- path_to_mess(v->v_list[i], &b, &m);
-
- (void)set_state(v->v_list[i], MESG_MARK);
-
- flex_char(&f, BOX_CHAR);
- flex_str(&f, b);
- flex_char(&f, ' ');
- flex_str(&f, m);
- flex_char(&f, '\n');
-
- (void)free(b);
- }
-
- if ((ids = read_file(p = concat3(mace_dir(), "/", MARK))) != NULLSTR)
- flex_str(&f, ids);
- else
- f.f_ptr--; /* yuk */
-
- flex_char(&f, '\0');
-
- if (write_file(p, f.f_str))
- {
- would_not("write", p);
- ok = 1;
- }
-
- (void)free(p);
- flex_end(&f);
-
- return ok;
-}
-
-void
-usage()
-{
- fprintf(stderr, "usage: %s [ [%c]%cbox ] [ first|previous|current|next|last|id|all ] ...\n", my_name, BOX_CHAR, BOX_CHAR);
- exit(1);
- /* NOTREACHED */
-}
-
-void
-busage()
-{
- fprintf(stderr, "usage: %s [ [%c]%cbox ] [ first|previous|current|next|last|id|all ] ... [%c]%cbox\n", my_name, BOX_CHAR, BOX_CHAR, BOX_CHAR, BOX_CHAR);
- exit(1);
- /* NOTREACHED */
-}
-
-int
-main(argc, argv)
-int argc;
-char *argv[];
-{
- register int i;
- int (*action)();
- vec mvec;
-
- name(argv[0]);
-
- if (strcmp(my_name, MSG_STR) == 0 || strcmp(my_name, "-") == 0)
- action = msg;
- else if (strcmp(my_name, REM_STR) == 0)
- action = rem;
- else if (strcmp(my_name, MED_STR) == 0)
- action = med;
- else if (strcmp(my_name, MOV_STR) == 0)
- action = mov;
- else if (strcmp(my_name, DEL_STR) == 0 || strcmp(my_name, "+") == 0)
- action = del;
- else if (strcmp(my_name, COP_STR) == 0)
- action = cop;
- else if (strcmp(my_name, LNK_STR) == 0)
- action = lnk;
- else if (strcmp(my_name, "mrk") == 0)
- action = mrk;
- else
- {
- fprintf(stderr, "%s: Invocation error.\n", my_name);
- exit(1);
- /* NOTREACHED */
- }
-
- vec_init(&mvec, 64);
-
- if (action == mov || action == cop || action == lnk)
- {
- char *p;
-
- if (argv[--argc][0] != BOX_CHAR)
- {
- busage();
- /* NOTREACHED */
- }
-
- if (*(target = &argv[argc][1]) == BOX_CHAR)
- new_box = ++target;
-
- if (*target == '\0')
- {
- busage();
- /* NOTREACHED */
- }
-
- if ((p = check_box(target)) == NULLSTR)
- {
- fprintf(stderr, "%s: No such box as \"%s\".\n", my_name, target);
- exit(1);
- }
-
- (void)free(p);
- }
-
- args_to_messages(argc, argv, &mvec, &new_box);
-
- if
- (
- (new_box != NULLSTR && set_box(new_box))
- ||
- mvec.v_count == 0
- ||
- (*action)(&mvec)
- )
- {
- exit(1);
- /* NOTREACHED */
- }
-
- if (action == cop || action == mov || action == lnk)
- {
- exit(0);
- /* NOTREACHED */
- }
-
- /* set current messages */
- {
- char *b;
- char *m;
- char *pm;
- char *pb;
- int ok;
-
- ok = 0;
-
- path_to_mess(mvec.v_list[i = 0], &pb, &pm);
-
- while (++i < mvec.v_count)
- {
- path_to_mess(mvec.v_list[i], &b, &m);
-
- if (strcmp(b, pb) != 0 && set_current(pb, pm))
- ok = 1;
-
- (void)free(pb);
- pb = b;
- pm = m;
- }
-
- if (set_current(pb, pm))
- ok = 1;
-
- exit(ok);
- /* NOTREACHED */
- }
-}
//GO.SYSIN DD msg.c
echo pop.c
sed 's/.//' >pop.c <<'//GO.SYSIN DD pop.c'
-/*
- * @(#)pop.c 1.4
- *
- * pop [ -delete ] [ -n number ] [ -r [ seconds ] ] [ -s spooldir ] [ -t ] [ [user@]server ]
- *
- * POP 3 (RFC 1225) client.
- */
-
-#include "mace.h"
-#include "line.h"
-#include "flex.h"
-#include "pop.h"
-#include <netdb.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <signal.h>
-#include <errno.h>
-#include <stdio.h>
-
-/*
- * POP3 states
- */
-enum
-{
- Idle,
- Authorization,
- Transaction,
- Retrieving,
- Delete,
- Done,
-};
-
-/*
- * POP3 responses
- */
-enum
-{
- Ok,
- Error,
- End,
- Data,
- IoError,
- Broken,
-};
-
-/*
- * POP3 session termination states.
- */
-enum
-{
- Complete = 0,
- NoMail,
- PopError,
- AuthError,
-};
-
-enum
-{
- Timeout = 120
-};
-
-typedef struct sig sig;
-
-struct sig
-{
- int s;
- char *name;
- SIG_RET (*f)(int);
-};
-
-char *_delete = "-delete";
-char *localhost = "localhost";
-
-char *user = NULLSTR;
-char *server = NULLSTR;
-char *spooldir = NULLSTR;
-ulong number = 0L;
-ulong retry = 0L;
-
-int delete = 0;
-int trace = 0;
-int state = Idle;
-int signaled = 0;
-
-lineio tx;
-lineio rx;
-
-SIG_RET catch(int);
-
-/*
- * Signal dispositions when run in the foreground.
- */
-sig foreground[] =
-{
- { SIGHUP, "SIGHUP", catch, },
- { SIGINT, "SIGINT", catch, },
- { SIGQUIT, "SIGQUIT", catch, },
- { SIGTERM, "SIGTERM", catch, },
- { 0, NULLSTR, 0, },
-};
-
-/*
- * Signal dispositions when run in the background.
- */
-sig background[] =
-{
- { SIGHUP, "SIGHUP", catch, },
- { SIGINT, "SIGINT", SIG_IGN, },
- { SIGQUIT, "SIGQUIT", SIG_IGN, },
- { SIGTERM, "SIGTERM", SIG_IGN, },
- { 0, NULLSTR, 0, },
-};
-
-/*
- * Finish communicating with the POP server, handling errors.
- */
-void
-finish()
-{
- char *r;
-
- switch (state)
- {
- case Idle:
- case Done:
- break;
-
- case Delete:
- state = Transaction;
- request(POP_CMD_RSET, NULLSTR, &r);
- if (state == Done)
- break;
-
- /* fall though */
-
- case Authorization:
- case Transaction:
- state = Done;
- request(POP_CMD_QUIT, NULLSTR, &r);
- break;
-
- case Retrieving:
- state = Done;
- break;
-
- default:
- fatal("unknown POP3 state");
- /* NOTREACHED */
- }
-
- if (state == Done)
- {
- int s;
-
- s = rx.l_fd;
- lclose(&rx);
- lclose(&tx);
- close(s);
-
- state = Idle;
- }
-}
-
-/*
- * Read a reply from the server, returning the text and the reply type.
- */
-int
-reply(char **r)
-{
- static char *rcvd = NULLSTR;
-
- if (rcvd != NULLSTR)
- free(rcvd);
-
- if ((rcvd = lread(&rx)) == NULLSTR)
- {
- fprintf(stderr, "%s: Server '%s' closed connection.\n", my_name, server);
- state = Done;
- finish();
- return IoError;
- }
-
- *r = rcvd;
-
- if (trace)
- fprintf(stderr, "%s: <-- %s\n", my_name, *r);
-
- if (state != Retrieving)
- {
- if (*rcvd == '\0')
- {
- finish();
- return Broken;
- }
-
- if (strncmp(rcvd, POP_REP_OK, sizeof POP_REP_OK - 1) == 0)
- {
- *r += sizeof POP_REP_OK - 1;
- return Ok;
- }
-
- if (strncmp(rcvd, POP_REP_ERR, sizeof POP_REP_ERR - 1) == 0)
- {
- *r += sizeof POP_REP_ERR - 1;
- fprintf(stderr, "%s: [%s] %s\n", my_name, server, *r);
- finish();
- return Error;
- }
- }
-
- if (rcvd[0] == POP_REP_TCHAR && rcvd[1] == '\0')
- return End;
-
- return Data;
-}
-
-/*
- * Signal catcher
- */
-SIG_RET
-catch(int s)
-{
- signal(s, SIG_IGN);
- signaled = 1;
-}
-
-/*
- * Set up signal defaults.
- */
-void
-signals(sig *s)
-{
- while (s->s != 0)
- {
- if (signal(s->s, s->f) == (SIG_RET (*)())SYSERROR)
- could_not("signal", s->name);
-
- s++;
- }
-}
-
-/*
- * Send a request to the server and return the reply.
- */
-int
-request(char *cmd, char *arg, char **r)
-{
- static flex f = { NULLSTR, NULLSTR, NULLSTR, };
-
- if (f.f_str == NULLSTR)
- flex_init(&f);
-
- if (trace)
- fprintf(stderr, arg == NULLSTR ? "%s: --> %s\n" : "%s: --> %s %s\n", my_name, cmd, strcmp(cmd, POP_CMD_PASS) == 0 ? "..." : arg);
-
- flex_str(&f, cmd);
-
- if (arg != NULLSTR)
- {
- flex_char(&f, ' ');
- flex_str(&f, arg);
- }
-
- flex_char(&f, '\0');
- flex_end(&f);
-
- if (lwrite(&tx, f.f_str) == NULLSTR)
- {
- state = Done;
- finish();
- return IoError;
- }
-
- return reply(r);
-}
-
-/*
- * Manage the user typed password in a pipe.
- */
-char *
-password()
-{
- char *p;
- static int fds[2] = { SYSERROR, SYSERROR };
- static char buf[POP_PASS_LEN + 1];
- static int l;
-
- /*
- * Return user typed password.
- */
- if (fds[0] != SYSERROR)
- {
- if (read(fds[0], buf, l) != l)
- {
- could_not("read password for", user);
- /* NOTREACHED */
- }
-
- if (write(fds[1], buf, l) != l)
- {
- could_not("write password for", user);
- /* NOTREACHED */
- }
-
- buf[l] = '\0';
- return buf;
- }
-
- /*
- * Read password and write it into the pipe.
- */
- if (pipe(fds) == SYSERROR)
- {
- could_not("create pipe for", server);
- /* NOTREACHED */
- }
-
- if ((p = readpass("password: ")) == NULLSTR)
- p = "";
-
- if ((l = strlen(p)) > POP_PASS_LEN)
- fprintf(stderr, "%s: Password too long, truncated to %d charecters.\n", my_name, server, POP_PASS_LEN);
-
- strncpy(buf, p, POP_PASS_LEN);
- memset(p, '\0', l);
- buf[POP_PASS_LEN] = '\0';
- l = strlen(buf);
-
- if (write(fds[1], buf, l) != l)
- {
- could_not("write password for", user);
- /* NOTREACHED */
- }
-
- return buf;
-}
-
-/*
- * Create a new file for a message. Returns 0 on success, 1 on failure.
- */
-int
-newfile(flex *file, lineio *out, char *n)
-{
- int fd;
-
- if (file->f_str == NULLSTR)
- return 1;
-
- if (spooldir != NULLSTR)
- {
- flex_str(file, spooldir);
- flex_char(file, '/');
- }
-
- flex_str(file, n);
- flex_char(file, '\0');
- flex_end(file);
-
- if ((fd = creat(file->f_str, 0200)) == SYSERROR)
- {
- would_not("creat", file->f_str);
- return 1;
- }
-
- lopen(out, fd, LWRITE);
- return 0;
-}
-
-/*
- * Close a message's file for a message. Returns 0 on success, 1 on failure.
- */
-int
-closefile(flex *file, lineio *out)
-{
- int fail;
-
- if (file->f_str == NULLSTR || (out->l_flag & LWRITE) == 0)
- return 1;
-
- fail = 0;
-
- if ((out->l_flag & LERROR) == 0)
- {
- if (lclose(out))
- {
- would_not("lclose", file->f_str);
- fail = 1;
- }
- }
- else
- fail = 1;
-
- if (close(out->l_fd) == SYSERROR)
- {
- would_not("close", file->f_str);
- fail = 1;
- }
-
- if (!fail && chmod(file->f_str, 0600) == SYSERROR)
- {
- would_not("chmod", file->f_str);
- fail = 1;
- }
-
- if (fail && unlink(file->f_str) == SYSERROR)
- would_not("unlink", file->f_str);
-
- return fail;
-}
-
-/*
- * Receive mail with POP3 on a socket.
- */
-int
-pop3(int s)
-{
- char *r;
- lineio out;
- char *pass;
- ulong messages;
- ulong size;
- ulong i;
- int rs;
- int spoolfull;
- flex file;
-
- flex_init(&file);
- lopen(&rx, s, LREAD|LCRLF);
- lopen(&tx, s, LWRITE|LCRLF|LLBUF);
- out.l_flag = 0;
-
- /*
- * Server up?
- */
- state = Idle;
-
- if (reply(&r) != Ok)
- return PopError;
-
- /*
- * Send user name and password.
- */
- state = Authorization;
-
- switch (request(POP_CMD_USER, user, &r))
- {
- case Ok:
- break;
-
- case Error:
- return AuthError;
-
- default:
- return PopError;
- }
-
- rs = request(POP_CMD_PASS, pass = password(), &r);
- memset(pass, '\0', strlen(pass));
-
- switch (rs)
- {
- case Ok:
- break;
-
- case Error:
- return AuthError;
-
- default:
- return PopError;
- }
-
- /*
- * Inquire maildrop state.
- */
- state = Transaction;
-
- if (request(POP_CMD_STAT, NULLSTR, &r) != Ok)
- return PopError;
-
- switch (sscanf(r, "%lu %lu", &messages, &size))
- {
- case 1:
- fprintf(stderr, "%s: %d message%s for '%s@%s', maildrop size unknown.\n", my_name, messages, messages == 1 ? "" : "s", user, server);
- size = 0;
- break;
-
- case 2:
- if (messages == 0 && retry == 0)
- {
- fprintf(stderr, "%s: No messages for '%s@%s'.\n", my_name, user, server);
- return NoMail;
- }
-
- break;
-
- default:
- fprintf(stderr, "%s: Unknown number of messages for '%s@%s'.\n", my_name, user, server);
- return PopError;
- }
-
- /*
- * Retrieve each message.
- */
- i = 1;
-
- while (i <= messages && !signaled)
- {
- char n[16];
-
- sprintf(n, "%lu", i);
-
- if (request(POP_CMD_RETR, n, &r) != Ok)
- return PopError;
-
- state = Retrieving;
-
- sprintf(n, "%ld", number);
-
- if (newfile(&file, &out, n))
- out.l_flag |= LERROR;
-
- for (;;)
- {
- switch (reply(&r))
- {
- case End:
- /*
- * Quit when we've received a message after
- * an I/O error on the message spool.
- */
- if (closefile(&file, &out))
- {
- i--;
- goto break2;
- }
-
- i++;
- number++;
- break;
-
- case Data:
- if ((out.l_flag & LERROR) == 0 && lwrite(&out, &r[*r == POP_REP_TCHAR]) == NULLSTR)
- would_not("write", file.f_str);
-
- continue;
-
- case IoError:
- case Broken:
- closefile(&file, &out);
- return PopError;
-
- case Ok:
- fatal("bogus POP3 OK reply");
- /* NOTREACHED */
-
- default:
- fatal("unknown POP3 reply");
- /* NOTREACHED */
- }
-
- break;
- }
-
- state = Transaction;
- }
-
-break2:
- if (!(spoolfull = i <= messages))
- i = messages;
-
- /*
- * Delete retrieved messages.
- */
- if (delete && !signaled)
- {
- state = Delete;
-
- /*
- * Delete backwards to preserve unreceived messages.
- */
- while (i >= 1)
- {
- char n[16];
-
- sprintf(n, "%lu", i);
-
- if (request(POP_CMD_DELE, n, &r) != Ok)
- return PopError;
-
- i--;
- }
- }
-
- /*
- * Finished with server.
- */
- state = Transaction;
-
- if (request(POP_CMD_QUIT, NULLSTR, &r) != Ok)
- return PopError;
-
- state = Done;
- finish();
- return spoolfull ? PopError : Complete;
-}
-
-/*
- * Convert an unsigned decimal integer to an unsigned long.
- */
-ulong
-num(char *s)
-{
- char *p;
- ulong n;
-
- n = 0;
-
- for (p = s; *p != '\0'; p++)
- {
- char c;
-
- if ((c = *p) < '0' || c > '9')
- {
- fprintf(stderr, "%s: '%s' is not numeric.\n", my_name, s);
- exit(1);
- /* NOTREACHED */
- }
-
- n = n * 10 + c - '0';
- }
-
- return n;
-}
-
-void
-usage()
-{
- fprintf(stderr, "usage: %s [ %s ] [ -n number ] [ -s spooldir ] [ -r [ seconds ] ] [ -t ] [ [user@]server ]\n", my_name, _delete);
- exit(1);
- /* NOTREACHED */
-}
-
-int
-main(int argc, char *argv[])
-{
- struct sockaddr_in sin;
- struct hostent *hp;
- struct servent *se;
- int i;
- int j;
- char *p;
- extern char *strchr();
-
- name(argv[0]);
-
- for (i = 1; i < argc; i++)
- {
- if (argv[i][0] != '-')
- break;
-
- j = 1;
-
- while (argv[i][j] != '\0')
- {
- switch (argv[i][j++])
- {
- case 'd':
- if (strcmp(argv[i], _delete) != 0)
- {
- usage();
- /* NOTREACHED */
- }
-
- delete = 1;
- break;
-
- case 'n':
- if (number > 0)
- {
- usage();
- /* NOTREACHED */
- }
-
- if (argv[i][j] != '\0')
- number = num(&argv[i][j]);
- else if (++i < argc)
- number = num(argv[i]);
- else
- {
- usage();
- /* NOTREACHED */
- }
- break;
-
- case 'r':
- if (retry > 0)
- {
- usage();
- /* NOTREACHED */
- }
-
- if (argv[i][j] != '\0')
- retry = num(&argv[i][j]);
- else if (i + 1 < argc && argv[i + 1][0] != '-')
- retry = num(argv[++i]);
- else
- retry = Timeout;
-
- break;
-
- case 's':
- if (spooldir != NULLSTR)
- {
- usage();
- /* NOTREACHED */
- }
-
- if (argv[i][j] != '\0')
- spooldir = &argv[i][j];
- else if (++i < argc)
- spooldir = argv[i];
- else
- {
- usage();
- /* NOTREACHED */
- }
- break;
-
- case 't':
- trace = 1;
- break;
-
- default:
- usage();
- /* NOTREACHED */
- }
-
- break;
- }
- }
-
- /*
- * Set user name and POP server.
- */
- switch (argc - i)
- {
- case 0:
- user = user_id();
- server = localhost;
- break;
-
- case 1:
- server = newstr(argv[i]);
-
- if ((p = strchr(server, '@')) != NULL)
- {
- user = server;
- *p++ = '\0';
- server = p;
- }
- else
- user = user_id();
-
- break;
-
- default:
- usage();
- /* NOTREACHED */
- }
-
- if (number < 0)
- number = 0;
-
- if ((hp = gethostbyname(server)) == NULL)
- {
- could_not("gethostbyname", server);
- /* NOTREACHED */
- }
-
- sin.sin_family = AF_INET;
-
- if ((se = getservbyname(POP_SERVICE, POP_PROTOCOL)) != NULL)
- sin.sin_port = se->s_port;
- else
- sin.sin_port = htons(POP_PORT);
-
- signals(foreground);
-
- while (!signaled)
- {
- int s;
- static int forked = 0;
-
- if ((s = socket(PF_INET, SOCK_STREAM, 0)) == SYSERROR)
- {
- could_not("get socket for", server);
- /* NOTREACHED */
- }
-
- for (i = 0; hp->h_addr_list[i] != NULL; i++)
- {
- int e;
-
- sin.sin_addr = *(struct in_addr *)hp->h_addr_list[i];
-
- if (connect(s, (struct sockaddr *)&sin, sizeof sin) == SYSERROR)
- continue;
-
- e = pop3(s);
-
- if (retry == 0 || e == AuthError)
- {
- exit(e != 0);
- /* NOTREACHED */
- }
-
- errno = 0;
- break;
- }
-
- if (errno != 0)
- {
- would_not("connect to", server);
-
- if (retry == 0)
- {
- exit(1);
- /* NOTREACHED */
- }
- }
-
- if (!forked)
- {
- switch (fork())
- {
- case SYSERROR:
- could_not("fork", my_name);
- /* NOTREACHED */
-
- case 0:
- forked = 1;
- signals(background);
- break;
-
- default:
- exit(0);
- /* NOTREACHED */
- }
- }
-
- sleep(retry);
- }
-
- finish();
- exit(0);
- return 0; /* shut up! */
-}
//GO.SYSIN DD pop.c
echo reo.c
sed 's/.//' >reo.c <<'//GO.SYSIN DD reo.c'
-/*
- * reo
- *
- * Read an RFC 822 message and reorder its headers.
- *
- * This could be a script, but it's trivial as a program.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)reo.c 1.1";
-#endif lint
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <signal.h>
-#include "mace.h"
-#include "line.h"
-#include "message.h"
-
-/*
- * Write a line checking for errors.
- */
-void
-ewrite(lineio *l, char *s)
-{
- if (lwrite(l, s) == NULLSTR)
- {
- fprintf(stderr, "%s Could not write standard output.\n", my_name);
- exit(1);
- /* NOTREACHED */
- }
-}
-
-void
-usage()
-{
- fprintf(stderr, "usage: %s\n", my_name);
- exit(1);
- /* NOTREACHED */
-}
-
-int
-main(int argc, char *argv[])
-{
- lineio in;
- lineio out;
- message *m;
- char *s;
- char **h;
-
- name(argv[0]);
-
- if (argc != 1)
- {
- usage();
- /* NOTREACHED */
- }
-
- /*
- * Validate headers.
- */
- if ((m = parse_fd(0, &in)) == NULLMESS)
- {
- could_not("parse", "<stdin>");
- /* NOTREACHED */
- }
-
- lopen(&out, fileno(stdout), LWRITE);
-
- /*
- * Write out headers.
- */
- reorder_headers(&m->ms_headers);
-
- for (h = m->ms_headers.v_list; (s = *h) != NULLSTR; h++)
- ewrite(&out, s);
-
- free_mess(m);
-
- /*
- * Write separator between headers and body.
- */
- ewrite(&out, "");
-
- /*
- * Write out message body.
- */
- while ((s = lread(&in)) != NULLSTR)
- {
- ewrite(&out, s);
- free(s);
- }
-
- if (lclose(&out))
- {
- fprintf(stderr, "%s: Message truncated.\n", my_name);
- exit(1);
- /* NOTREACHED */
- }
-
- exit(0);
- return 0;
- /* NOTREACHED */
-}
//GO.SYSIN DD reo.c
echo ret.c
sed 's/.//' >ret.c <<'//GO.SYSIN DD ret.c'
-/*
- * ret - return to a mark
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)ret.c 1.3";
-#endif lint
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include "mace.h"
-#include "line.h"
-#include "message.h"
-
-void
-usage()
-{
- fprintf(stderr, "usage: %s\n", my_name);
- exit(1);
- /* NOTREACHED */
-}
-
-int
-set(box, mess)
-char *box;
-char *mess;
-{
- register mbox *mb;
- int ok;
-
- ok = 0;
-
- if ((mb = read_box(box)) != NULLBOX)
- {
- if (!set_box(box) && !set_current(box, mess))
- {
- char *f;
-
- if (!clear_state(f = concat3(mb->m_path, "/", mess), MESG_MARK))
- printf("%c%s %s\n", BOX_CHAR, box, mess);
- else
- ok = 1;
-
- (void)free(f);
- }
- else
- ok = 1;
-
- free_box(mb);
- }
- else
- {
- fprintf(stderr, "%s: Box \"%s\" does not exist.\n", my_name, box);
- ok = 1;
- }
-
- return ok;
-}
-
-main(argc, argv)
-int argc;
-char *argv[];
-{
- register char *m;
- char *p;
- int ok;
-
- name(argv[0]);
-
- if (argc > 1)
- {
- usage();
- /* NOTREACHED */
- }
-
- ok = 0;
-
- if ((m = read_file(p = concat3(mace_dir(), "/", MARK))) == NULLSTR)
- {
- exit(1);
- /* NOTREACHED */
- }
-
- if (*m++ == BOX_CHAR)
- {
- register char c;
- char *bp;
- char *mp;
-
- bp = m;
- mp = NULLSTR;
-
- while ((c = *m) != '\0')
- {
- if (c == ' ')
- {
- *m++ = '\0';
- mp = m;
-
- while ((c = *m) != '\0')
- {
- if (c == '\n')
- {
- *m++ = '\0';
- break;
- }
-
- m++;
- }
-
- ok = set(bp, mp);
- break;
- }
-
- if (c == '\n')
- {
- fprintf(stderr, "%s: \"%s\": missing message-id.\n", my_name, p, BOX_CHAR);
- ok = 1;
- m++;
- break;
- }
-
- m++;
- }
- }
- else
- {
- fprintf(stderr, "%s: \"%s\": Leading '%c' missing.\n", my_name, p, BOX_CHAR);
-
- while (*m != '\0' && *m++ != '\n')
- ;
-
- ok = 1;
- }
-
- if (*m != '\0')
- {
- if (write_file(p, m))
- {
- would_not("write", p);
- ok = 1;
- }
- }
- else if (unlink(p) == SYSERROR)
- {
- would_not("unlink", p);
- ok = 1;
- }
-
- return ok;
-}
//GO.SYSIN DD ret.c
|