From: Ken Hornstein Date: Fri, 18 Apr 2014 14:44:19 +0000 (-0400) Subject: Remove msh(1). X-Git-Url: https://diplodocus.org/git/nmh/commitdiff_plain/e6917522a770cf2dba9997ca047977bc55fac061 Remove msh(1). --- diff --git a/.gitignore b/.gitignore index e432a0e2..217effcf 100644 --- a/.gitignore +++ b/.gitignore @@ -79,7 +79,6 @@ a.out.dSYM/ /uip/mhstore /uip/mkstemp /uip/msgchk -/uip/msh /uip/new /uip/packf /uip/pick diff --git a/Makefile.am b/Makefile.am index e6db2075..48f2cf27 100644 --- a/Makefile.am +++ b/Makefile.am @@ -143,7 +143,7 @@ bin_PROGRAMS = uip/ali uip/anno uip/burst uip/comp uip/dist uip/flist \ uip/fmttest uip/folder uip/forw uip/inc uip/install-mh \ uip/mark uip/mhbuild uip/mhfixmsg uip/mhlist uip/mhn \ uip/mhparam uip/mhpath uip/mhshow uip/mhstore uip/msgchk \ - uip/msh uip/new uip/packf uip/pick uip/prompter uip/refile \ + uip/new uip/packf uip/pick uip/prompter uip/refile \ uip/repl uip/rmf uip/rmm uip/scan uip/send uip/show uip/sortm \ uip/whatnow uip/whom @@ -177,10 +177,10 @@ noinst_LIBRARIES = sbr/libmh.a mts/libmts.a ## noinst_HEADERS = h/addrsbr.h h/aliasbr.h h/crawl_folders.h h/dropsbr.h \ h/fmt_compile.h h/fmt_scan.h h/md5.h h/mf.h \ - h/mh.h h/mhcachesbr.h h/mhparse.h h/mime.h h/msh.h \ + h/mh.h h/mhcachesbr.h h/mhparse.h h/mime.h \ h/mts.h h/nmh.h h/picksbr.h h/popsbr.h h/prototypes.h \ h/rcvmail.h h/scansbr.h h/signals.h h/tws.h h/utils.h \ - h/vmhsbr.h mts/smtp/smtp.h sbr/ctype-checked.h + mts/smtp/smtp.h sbr/ctype-checked.h ## ## Extra files we need to install in various places @@ -232,7 +232,7 @@ man_MANS = man/ali.1 man/anno.1 man/ap.8 man/burst.1 man/comp.1 \ man/mh_profile.5 man/mh-sequence.5 man/mh-tailor.5 man/mhbuild.1 \ man/mhfixmsg.1 man/mhl.1 man/mhlist.1 man/mhmail.1 man/mhn.1 \ man/mhparam.1 man/mhpath.1 man/mhshow.1 man/mhstore.1 \ - man/mh-mkstemp.1 man/msgchk.1 man/msh.1 man/mts.conf.5 man/new.1 \ + man/mh-mkstemp.1 man/msgchk.1 man/mts.conf.5 man/new.1 \ man/next.1 man/nmh.7 man/packf.1 man/pick.1 man/post.8 man/prev.1 \ man/prompter.1 man/rcvdist.1 man/rcvpack.1 man/rcvstore.1 \ man/rcvtty.1 man/refile.1 man/repl.1 man/rmf.1 man/rmm.1 \ @@ -253,7 +253,7 @@ man_SRCS = man/ali.man man/anno.man man/ap.man man/burst.man man/comp.man \ man/mh-tailor.man man/mhbuild.man man/mhfixmsg.man man/mhl.man \ man/mhlist.man man/mhmail.man man/mhn.man man/mhparam.man \ man/mhpath.man man/mhshow.man man/mhstore.man man/mh-mkstemp.man \ - man/msgchk.man man/msh.man man/mts.conf.man man/new.man \ + man/msgchk.man man/mts.conf.man man/new.man \ man/next.man man/nmh.man man/packf.man man/pick.man man/post.man \ man/prev.man man/prompter.man man/rcvdist.man man/rcvpack.man \ man/rcvstore.man man/rcvtty.man man/refile.man man/repl.man \ @@ -359,10 +359,6 @@ uip_mhstore_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_msgchk_SOURCES = uip/msgchk.c uip/popsbr.c uip_msgchk_LDADD = $(LDADD) $(SASLLIB) $(POSTLINK) -uip_msh_SOURCES = uip/msh.c uip/mshcmds.c uip/vmhsbr.c uip/picksbr.c \ - uip/scansbr.c uip/dropsbr.c uip/mhlsbr.c -uip_msh_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) - uip_new_SOURCES = uip/new.c uip_new_LDADD = $(LDADD) $(POSTLINK) diff --git a/docs/pending-release-notes b/docs/pending-release-notes index 62168a74..f4f47358 100644 --- a/docs/pending-release-notes +++ b/docs/pending-release-notes @@ -11,6 +11,7 @@ OBSOLETE FEATURES removed in this release. - conflict(8) was deprecated in nmh 1.6, and was removed in this release. - mhtest(8) was deprecated in nmh 1.6, and was removed in this release. +- msh(1) was deprecated in nmh 1.6, and was removed in this release. ------------------- DEPRECATED FEATURES diff --git a/h/mh.h b/h/mh.h index 4e8be7bc..5e75c0ba 100644 --- a/h/mh.h +++ b/h/mh.h @@ -437,7 +437,6 @@ extern char *mhlproc; extern char *mhlreply; extern char *moreproc; extern char *msgprot; -extern char *mshproc; extern char *nmhaccessftp; extern char *nmhaccessurl; extern char *nmhstorage; @@ -459,7 +458,6 @@ extern char *showproc; extern char *usequence; extern char *version_num; extern char *version_str; -extern char *vmhproc; extern char *whatnowproc; extern char *whomproc; diff --git a/h/vmhsbr.h b/h/vmhsbr.h deleted file mode 100644 index 0b5a9a3e..00000000 --- a/h/vmhsbr.h +++ /dev/null @@ -1,49 +0,0 @@ - -/* - * vmhsbr.h -- definitions for the vmh protocol - */ - -#define RC_VRSN 1 - -/* flags for rh_type */ -#define RC_INI 0x01 /* must be greater than OK */ -#define RC_ACK 0x02 -#define RC_ERR 0x03 -#define RC_CMD 0x04 -#define RC_QRY 0x05 -#define RC_TTY 0x06 -#define RC_WIN 0x07 -#define RC_DATA 0x08 -#define RC_EOF 0x09 -#define RC_FIN 0x0a -#define RC_XXX 0x0b - -struct record { - struct rcheader { - char rh_type; /* type of record */ - int rh_len; /* length of data */ - } rc_header; - char *rc_data; /* extensible array */ -}; - -#define rc_head(rc) (&rc->rc_header) -#define RHSIZE(rc) (sizeof rc->rc_header) -#define rc_type rc_header.rh_type -#define rc_len rc_header.rh_len - -#define initrc(rc) rc->rc_data = NULL - -/* - * prototypes - */ -int rcinit (int, int); -int rcdone (void); -int rc2rc (char, int, char *, struct record *); -int str2rc (char, char *, struct record *); -int peer2rc (struct record *); -int rc2peer (char, int, char *); -int str2peer (char, char *); -int fmt2peer (char, char *, ...); -int err2peer (char, char *, char *, ...); -int verr2peer (char, char *, char *, va_list); - diff --git a/man/burst.man b/man/burst.man index 225bb268..e38a4aee 100644 --- a/man/burst.man +++ b/man/burst.man @@ -1,4 +1,4 @@ -.TH BURST %manext1% "January 1, 2001" "%nmhversion%" +.TH BURST %manext1% "April 18, 2014" "%nmhversion%" .\" .\" %nmhwarning% .\" @@ -92,7 +92,6 @@ To set mode when creating a new message. .PD .SH "SEE ALSO" .IR inc (1), -.IR msh (1), .IR pack (1) .PP .I diff --git a/man/forw.man b/man/forw.man index 4ac85727..362fadea 100644 --- a/man/forw.man +++ b/man/forw.man @@ -1,4 +1,4 @@ -.TH FORW %manext1% "March 21, 2013" "%nmhversion%" +.TH FORW %manext1% "April 18, 2014" "%nmhversion%" .\" .\" %nmhwarning% .\" @@ -336,11 +336,7 @@ The switch specifies the message to be forwarded as an exact filename rather than as an .B nmh -folder and message number. It is -intended to be used by the -.B msh -interface to -.BR nmh . +folder and message number. This switch implies .BR \-noannotate . The forwarded message is simply diff --git a/man/inc.man b/man/inc.man index 8266ae9e..9b7068c9 100644 --- a/man/inc.man +++ b/man/inc.man @@ -1,4 +1,4 @@ -.TH INC %manext1% "April 14, 2013" "%nmhversion%" +.TH INC %manext1% "April 18, 2014" "%nmhversion%" .\" .\" %nmhwarning% .\" @@ -237,10 +237,7 @@ switch is considered. If given, then .B inc simply uses the POP to .B packf -the user's maildrop from the POP service host to the named file. This switch -is provided for those users who prefer to use -.B msh -to read their maildrops. +the user's maildrop from the POP service host to the named file. .PP For debugging purposes, you may give the switch .BR \-snoop , diff --git a/man/mh-profile.man b/man/mh-profile.man index 61cf70bf..cb85747f 100644 --- a/man/mh-profile.man +++ b/man/mh-profile.man @@ -590,12 +590,6 @@ to display message bodies (or message parts) of type text/plain. supersedes the default built-in pager command.) .RE .PP -.BR mshproc : -%bindir%/msh -.RS 5 -Currently not used. -.RE -.PP .BR packproc : %bindir%/packf .RS 5 diff --git a/man/mh-tailor.man b/man/mh-tailor.man index c446b2e2..2a69c58a 100644 --- a/man/mh-tailor.man +++ b/man/mh-tailor.man @@ -14,7 +14,6 @@ At present, these (user) programs are: .BR ap , .BR inc , .BR msgchk , -.BR msh , .BR post , .BR rcvdist , and diff --git a/man/msh.man b/man/msh.man deleted file mode 100644 index 66e29fbe..00000000 --- a/man/msh.man +++ /dev/null @@ -1,265 +0,0 @@ -.TH MSH %manext1% "January 26, 2013" "%nmhversion%" -.\" -.\" %nmhwarning% -.\" -.SH NAME -msh \- nmh shell (and BBoard reader) -.SH SYNOPSIS -.HP 5 -.na -.B msh -.RB [ \-prompt -.IR string ] -.RB [ \-scan " | " \-noscan ] -.RB [ \-topcur " | " \-notopcur ] -.RI [ file ] -.RB [ \-version ] -.RB [ \-help ] -.ad -.SH STATUS -.B msh is deprecated and will be removed from the next nmh release. -.SH DESCRIPTION -.B msh -is an interactive program that implements a subset of the normal -.B nmh -commands operating on a single file in -.BR mmdf -format. -That is, -.B msh -is used to read a file that contains a number -of messages, as opposed to the standard -.B nmh -style of reading -a number of files, each file being a separate message in a folder. -.BR msh 's -chief advantage is that the normal -.B nmh -style does not -allow a file to have more than one message in it. Hence, -.B msh -is -ideal for reading BBoards, as these files are delivered by the -transport system in this format. In addition, -.B msh -can be used on -other files, such as message archives which have been -.BR pack ed -(see -.IR packf (1)). -Finally, -.B msh -is an excellent -.B nmh -tutor. -As the only commands available to the user are -.B nmh -commands, this -allows -.B nmh -beginners to concentrate on how commands to -.B nmh -are formed and (more or less) what they mean. -.PP -When invoked, -.B msh -reads the named file, and enters a command loop. -The user may type most of the normal -.B nmh -commands. The syntax and -semantics of these commands typed to -.B msh -are identical to their -.B nmh -counterparts. In cases where the nature of -.B msh -would be -inconsistent (e.g., specifying a -.I +folder -with some commands), -.B msh -will duly inform the user. The commands that -.B msh -currently supports -(in some slightly modified or restricted forms) are: -.PP -.RS 5 -.nf -ali -burst -comp -dist -folder -forw -inc -mark -mhmail -mhn -msgchk -next -packf -pick -prev -refile -repl -rmm -scan -send -show -sortm -whatnow -whom -.fi -.RE -.PP -In addition, -.B msh -has a -.B help -command which gives a -brief overview. To terminate -.BR msh , -type CTRL\-D, or use the -.B quit -command. -.PP -If the file is writable and has been modified, then using -.B quit -will query the user if the file should be updated. -.PP -The -.B \-prompt -.I string -switch sets the prompting string for -.BR msh . -.PP -You may wish to use an alternate -.B nmh -profile for the commands that -.B msh -executes; see -.IR mh-profile (5) -for details about the -.B $MH -environment variable. -.PP -The -.B exit -command is identical to the -.B quit -command in -.BR msh . -.PP -.B msh -supports an output redirection facility. Commands may be -followed by one of -.PP -.RS 5 -.nf -.ta \w'| \fIcommand\fR 'u -^> \fIfile\fR~^write output to \fIfile\fR -^>> \fIfile\fR~^append output to \fIfile\fR -^| \fIcommand\fR~^pipe output to UNIX \fIcommand\fR -.fi -.RE -.PP -If -.I file -starts with a \*(lq\~\*(rq (tilde), then a -.BR csh \-like -expansion -takes place. Note that -.I command -is interpreted by -.BR sh . -Also note that -.B msh -does NOT support history substitutions, variable -substitutions, or alias substitutions. -.PP -When parsing commands to the left of any redirection symbol, -.B msh -will honor `\\' (backslash) as the quote next\-character symbol, and -`\*(lq' (double\-quote) as quote\-word delimiters. All other input tokens -are separated by whitespace (spaces and tabs). -.SH FILES -.fc ^ ~ -.nf -.ta \w'%etcdir%/ExtraBigFileName 'u -^$HOME/\&.mh\(ruprofile~^The user profile -^%etcdir%/mts.conf~^nmh mts configuration file -.fi -.SH "PROFILE COMPONENTS" -.fc ^ ~ -.nf -.ta 2.4i -.ta \w'ExtraBigProfileName 'u -^Path:~^To determine the user's nmh directory -^Msg\-Protect:~^To set mode when creating a new `file' -^fileproc:~^Program to file messages -^showproc:~^Program to show messages -.fi -.SH "SEE ALSO" -.IR packf (1) -.SH DEFAULTS -.nf -.RB ` file "' defaults to \*(lq./msgbox\*(rq" -.RB ` "\-prompt\ (msh)\ "' -.RB ` \-noscan ' -.RB ` \-notopcur ' -.fi -.SH CONTEXT -None -.SH BUGS -.PP -There is a strict limit of messages per file in -.BR packf 'd -format which -.B msh -can handle. Usually, this limit is 1000 messages. -.PP -Please remember that -.B msh -is not the C\-Shell, and that a lot of -the nice facilities provided by the latter are not present in the former. -.PP -In particular, -.B msh -does not understand backquoting, so the only -effective way to use -.B pick -inside -.B msh -is to always use the -.B \-seq -.I select -switch. Clever users of -.B nmh -will put the line -.P -.RS 5 -pick:\0\-seq\0select\0\-list -.RE -.PP -in their -.I \&.mh\(ruprofile -file so that -.B pick -works equally well from both the shell and -.BR msh . -.PP -.B sortm -always uses -.B \-noverbose -and if -.B \-textfield -.I field -is used, -.B \-limit -.IR 0 . -.PP -The -.B msh -program inherits most (if not all) of the bugs from the -.B nmh -commands it implements. diff --git a/man/nmh.man b/man/nmh.man index 18dd7008..0e77814e 100644 --- a/man/nmh.man +++ b/man/nmh.man @@ -442,9 +442,6 @@ Convenience Wrappers .PD 0 .IR mhmail (1) send or read mail -.TP -.IR msh (1) -nmh shell .PD .ne 4 .SS diff --git a/man/packf.man b/man/packf.man index 3e3dc41b..898f0b0d 100644 --- a/man/packf.man +++ b/man/packf.man @@ -1,4 +1,4 @@ -.TH PACKF %manext1% "January 8, 2012" "%nmhversion%" +.TH PACKF %manext1% "April 18, 2014" "%nmhversion%" .\" .\" %nmhwarning% .\" @@ -75,7 +75,6 @@ can be unpacked using .fi .SH "SEE ALSO" .IR inc (1), -.IR msh (1) .SH DEFAULTS .nf .RB ` +folder "' defaults to the current folder" diff --git a/man/repl.man b/man/repl.man index 245d45ae..fe87c856 100644 --- a/man/repl.man +++ b/man/repl.man @@ -1,4 +1,4 @@ -.TH REPL %manext1% "April 9, 2013" "%nmhversion%" +.TH REPL %manext1% "April 18, 2014" "%nmhversion%" .\" .\" %nmhwarning% .\" @@ -466,11 +466,7 @@ The switch specifies the message to be replied to as an exact filename rather than as an .B nmh -folder and message number. It is -intended to be used by the -.B msh -interface to -.BR nmh . +folder and message number. The same caveats apply to this option as to the .B \-build switch. diff --git a/sbr/readconfig.c b/sbr/readconfig.c index 06a9470b..30b844a2 100644 --- a/sbr/readconfig.c +++ b/sbr/readconfig.c @@ -27,14 +27,12 @@ static struct procstr procs[] = { { "mailproc", &mailproc }, { "mhlproc", &mhlproc }, { "moreproc", &moreproc }, - { "mshproc", &mshproc }, { "packproc", &packproc }, { "postproc", &postproc }, { "rmmproc", &rmmproc }, { "sendproc", &sendproc }, { "showmimeproc", &showmimeproc }, { "showproc", &showproc }, - { "vmhproc", &vmhproc }, { "whatnowproc", &whatnowproc }, { "whomproc", &whomproc }, { NULL, NULL } diff --git a/test/mhparam/test-mhparam b/test/mhparam/test-mhparam index 89bcb5d2..3a9ad02a 100755 --- a/test/mhparam/test-mhparam +++ b/test/mhparam/test-mhparam @@ -88,14 +88,12 @@ $bindir/mhmail $MH_INST_DIR$auxexecdir/mhl cat 600 -$bindir/msh $bindir/packf $MH_INST_DIR$auxexecdir/post $bindir/send $bindir/mhshow $MH_INST_DIR$auxexecdir/mhl nmh-`cat ${srcdir}/VERSION` -$bindir/msh $bindir/whatnow $bindir/whom $sysconfdir @@ -116,14 +114,12 @@ mailproc \ mhlproc \ moreproc \ msgprot \ -mshproc \ packproc \ postproc \ sendproc \ showmimeproc \ showproc \ version \ -vmhproc \ whatnowproc \ whomproc \ etcdir \ diff --git a/uip/mhparam.c b/uip/mhparam.c index bf59b60e..bb2f7d2f 100644 --- a/uip/mhparam.c +++ b/uip/mhparam.c @@ -95,7 +95,6 @@ static struct proc procs [] = { { "mimeencodingproc", &mimeencodingproc }, { "moreproc", &moreproc }, { "msgprot", &msgprot }, - { "mshproc", &mshproc }, { "packproc", &packproc }, { "postproc", &postproc }, { "rmmproc", &rmmproc }, @@ -103,7 +102,6 @@ static struct proc procs [] = { { "showmimeproc", &showmimeproc }, { "showproc", &showproc }, { "version", &version_num }, - { "vmhproc", &vmhproc }, { "whatnowproc", &whatnowproc }, { "whomproc", &whomproc }, { "etcdir", &mhetcdir }, diff --git a/uip/msh.c b/uip/msh.c deleted file mode 100644 index 86855a4f..00000000 --- a/uip/msh.c +++ /dev/null @@ -1,2291 +0,0 @@ - -/* - * msh.c -- The nmh shell - * - * This code is Copyright (c) 2002, by the authors of nmh. See the - * COPYRIGHT file in the root directory of the nmh distribution for - * complete copyright information. - */ - -/* - * TODO: - * Keep more status information in maildrop map - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#define QUOTE '\\' /* sigh */ - -#define MSH_SWITCHES \ - X("idstart number", -7, IDSW) /* interface from bbc */ \ - X("idstop number", -6, FDSW) /* .. */ \ - X("idquit number", -6, QDSW) /* .. */ \ - X("idname BBoard", -6, NMSW) /* .. */ \ - X("prompt string", 0, PRMPTSW) \ - X("scan", 0, SCANSW) \ - X("noscan", 0, NSCANSW) \ - X("vmhread fd", -7, READSW) \ - X("vmhwrite fd", -8, WRITESW) \ - X("popread fd", -7, PREADSW) \ - X("popwrite fd", -8, PWRITSW) \ - X("topcur", 0, TCURSW) \ - X("notopcur", 0, NTCURSW) \ - X("version", 0, VERSIONSW) \ - X("help", 0, HELPSW) \ - -#define X(sw, minchars, id) id, -DEFINE_SWITCH_ENUM(MSH); -#undef X - -#define X(sw, minchars, id) { sw, minchars, id }, -DEFINE_SWITCH_ARRAY(MSH, switches); -#undef X - -static int mbx_style = MMDF_FORMAT; - -/* - * FOLDER - */ -char*fmsh = NULL; /* folder instead of file */ -int modified; /* command modified folder */ -struct msgs *mp; /* used a lot */ -static int nMsgs = 0; -struct Msg *Msgs = NULL; /* Msgs[0] not used */ -static FILE *fp; /* input file */ -static FILE *yp = NULL; /* temporary file */ -static int mode; /* mode of file */ -static int numfds = 0; /* number of files cached */ -static int maxfds = 0; /* number of files cached to be cached */ -static time_t mtime = (time_t) 0; /* mtime of file */ - -/* - * VMH - */ -#define ALARM ((unsigned int) 10) -#define ttyN(c) ttyNaux ((c), NULL) - -static int vmh = 0; - -static int vmhpid = OK; -static int vmhfd0; -static int vmhfd1; -static int vmhfd2; - -static int vmhtty = NOTOK; - -#define SCAN 1 -#define STATUS 2 -#define DISPLAY 3 -#define NWIN DISPLAY - -static int topcur = 0; - -static int numwins = 0; -static int windows[NWIN + 1]; - -static jmp_buf peerenv; - -/* - * PARENT - */ -static int pfd = NOTOK; /* fd parent is reading from */ -static int ppid = 0; /* pid of parent */ - -/* - * COMMAND - */ -int interactive; /* running from a /dev/tty */ -int redirected; /* re-directing output */ -FILE *sp = NULL; /* original stdout */ - -char *cmd_name; /* command being run */ -char myfilter[BUFSIZ]; /* path to mhl.forward */ - -static char *myprompt = "(%s) ";/* prompting string */ - -/* - * BBOARDS - */ -static int gap; /* gap in BBoard-ID:s */ -static char *myname = NULL; /* BBoard name */ -char *BBoard_ID = "BBoard-ID"; /* BBoard-ID constant */ - -/* - * SIGNALS - */ -SIGNAL_HANDLER istat; /* original SIGINT */ -static SIGNAL_HANDLER pstat; /* current SIGPIPE */ -SIGNAL_HANDLER qstat; /* original SIGQUIT */ - -#ifdef SIGTSTP -SIGNAL_HANDLER tstat; /* original SIGTSTP */ -#endif - -int interrupted; /* SIGINT detected */ -int broken_pipe; /* SIGPIPE detected */ -int told_to_quit; /* SIGQUIT detected */ - -/* - * prototypes - */ -void fsetup (char *); -void setup (char *); -void readids (int); -int readid (int); -void display_info (int); -int expand (char *); -void m_reset (void); -void seq_setcur (struct msgs *, int); -void padios (char *, char *, ...); -void padvise (char *, char *, ...); - -extern m_getfld_state_t gstate; /* use the gstate in scansbr.c */ - - -/* - * static prototypes - */ -static void msh (int); -static int read_map (char *, long); -static int read_file (long, int); - -static void m_gMsgs (int); -static int check_folder (int); -static void scanrange (int, int); -static void scanstring (char *); -static void write_ids (void); -static void quit (void); -static int getargs (char *, struct swit *, struct Cmd *); -static int getcmds (struct swit *, struct Cmd *, int); -static int parse (char *, struct Cmd *); -static int init_io (struct Cmd *, int); -static int initaux_io (struct Cmd *); -static void fin_io (struct Cmd *, int); -static void finaux_io (struct Cmd *); -static void m_init (void); -static void intrser (int); -static void pipeser (int); -static void quitser (int); -static void alrmser (int); -static int pINI (void); -static int pQRY (char *, int); -static int pQRY1 (int); -static int pQRY2 (void); -static int pCMD (char *, struct swit *, struct Cmd *); -static int pFIN (void); -static int peerwait (void); -static int ttyNaux (struct Cmd *, char *); -static int ttyR (struct Cmd *); -static int winN (struct Cmd *, int, int); -static int winR (struct Cmd *); -static int winX (int); - - -int -main (int argc, char **argv) -{ - int id = 0, scansw = 0, vmh1 = 0, vmh2 = 0; - char *cp, *file = NULL, *folder = NULL; - char **argp, **arguments, buf[BUFSIZ]; - - if (nmh_init(argv[0], 1)) { return 1; } - - mts_init (invo_name); - arguments = getarguments (invo_name, argc,argv, 1); - argp = arguments; - - while ((cp = *argp++)) { - if (*cp == '-') - switch (smatch (++cp, switches)) { - case AMBIGSW: - ambigsw (cp, switches); - done (1); - case UNKWNSW: - adios (NULL, "-%s unknown", cp); - - case HELPSW: - snprintf (buf, sizeof(buf), "%s [switches] file", invo_name); - print_help (buf, switches, 1); - done (0); - case VERSIONSW: - print_version(invo_name); - done (0); - - case IDSW: - if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); - if ((id = atoi (cp)) < 1) - adios (NULL, "bad argument %s %s", argp[-2], cp); - continue; - case FDSW: - if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); - if ((pfd = atoi (cp)) <= 1) - adios (NULL, "bad argument %s %s", argp[-2], cp); - continue; - case QDSW: - if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); - if ((ppid = atoi (cp)) <= 1) - adios (NULL, "bad argument %s %s", argp[-2], cp); - continue; - case NMSW: - if (!(myname = *argp++) || *myname == '-') - adios (NULL, "missing argument to %s", argp[-2]); - continue; - - case SCANSW: - scansw++; - continue; - case NSCANSW: - scansw = 0; - continue; - - case PRMPTSW: - if (!(myprompt = *argp++) || *myprompt == '-') - adios (NULL, "missing argument to %s", argp[-2]); - continue; - - case READSW: - if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); - if ((vmh1 = atoi (cp)) < 1) - adios (NULL, "bad argument %s %s", argp[-2], cp); - continue; - case WRITESW: - if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); - if ((vmh2 = atoi (cp)) < 1) - adios (NULL, "bad argument %s %s", argp[-2], cp); - continue; - - case PREADSW: - if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); - continue; - case PWRITSW: - if (!(cp = *argp++) || *cp == '-') - adios (NULL, "missing argument to %s", argp[-2]); - continue; - - case TCURSW: - topcur++; - continue; - case NTCURSW: - topcur = 0; - continue; - } - if (*cp == '+' || *cp == '@') { - if (folder) - adios (NULL, "only one folder at a time!"); - else - folder = pluspath (cp); - } - else - if (file) - adios (NULL, "only one file at a time!"); - else - file = cp; - } - - if (!file && !folder) - file = "./msgbox"; - if (file && folder) - adios (NULL, "use a file or a folder, not both"); - strncpy (myfilter, etcpath (mhlforward), sizeof(myfilter)); -#ifdef FIOCLEX - if (pfd > 1) - ioctl (pfd, FIOCLEX, NULL); -#endif /* FIOCLEX */ - - istat = SIGNAL2 (SIGINT, intrser); - qstat = SIGNAL2 (SIGQUIT, quitser); - - sc_width (); /* MAGIC... */ - - if ((vmh = vmh1 && vmh2)) { - rcinit (vmh1, vmh2); - pINI (); - SIGNAL (SIGINT, SIG_IGN); - SIGNAL (SIGQUIT, SIG_IGN); -#ifdef SIGTSTP - tstat = SIGNAL (SIGTSTP, SIG_IGN); -#endif /* SIGTSTP */ - } - - if (folder) - fsetup (folder); - else - setup (file); - readids (id); - display_info (id > 0 ? scansw : 0); - - msh (id > 0 ? scansw : 0); - scan_finished (); - - m_reset (); - - done (0); - return 1; -} - - -#define MSHCMDS_SWITCHES \ - X("advance", -7, ADVCMD) \ - X("ali", 0, ALICMD) \ - X("burst", 0, EXPLCMD) \ - X("comp", 0, COMPCMD) \ - X("dist", 0, DISTCMD) \ - X("exit", 0, EXITCMD) \ - X("folder", 0, FOLDCMD) \ - X("forw", 0, FORWCMD) \ - X("help", 0, HELPCMD) \ - X("inc", 0, INCMD) \ - X("mark", 0, MARKCMD) \ - X("mhmail", 0, MAILCMD) \ - X("mhn", 0, MHNCMD) \ - X("msgchk", 0, MSGKCMD) \ - X("next", 0, NEXTCMD) \ - X("packf", 0, PACKCMD) \ - X("pick", 0, PICKCMD) \ - X("prev", 0, PREVCMD) \ - X("quit", 0, QUITCMD) \ - X("refile", 0, FILECMD) \ - X("repl", 0, REPLCMD) \ - X("rmm", 0, RMMCMD) \ - X("scan", 0, SCANCMD) \ - X("send", 0, SENDCMD) \ - X("show", 0, SHOWCMD) \ - X("sortm", 0, SORTCMD) \ - X("whatnow", 0, WHATCMD) \ - X("whom", 0, WHOMCMD) \ - -#define X(sw, minchars, id) id, -DEFINE_SWITCH_ENUM(MSHCMDS); -#undef X - -#define X(sw, minchars, id) { sw, minchars, id }, -DEFINE_SWITCH_ARRAY(MSHCMDS, mshcmds); -#undef X - - -static void -msh (int scansw) -{ - int i; - register char *cp, **ap; - char prompt[BUFSIZ], *vec[MAXARGS]; - struct Cmd typein; - register struct Cmd *cmdp; - static int once_only = ADVCMD; - - snprintf (prompt, sizeof(prompt), myprompt, invo_name); - cmdp = &typein; - - for (;;) { - if (yp) { - fclose (yp); - yp = NULL; - } - if (vmh) { - if ((i = getcmds (mshcmds, cmdp, scansw)) == EOF) { - rcdone (); - return; - } - } else { - check_folder (scansw); - if ((i = getargs (prompt, mshcmds, cmdp)) == EOF) { - putchar ('\n'); - return; - } - } - cmd_name = mshcmds[i].sw; - - switch (i) { - case QUITCMD: - quit (); - return; - - case ADVCMD: - if (once_only == ADVCMD) - once_only = i = SHOWCMD; - else - i = mp->curmsg != mp->hghmsg ? NEXTCMD : EXITCMD; - cmd_name = mshcmds[i].sw; - /* and fall... */ - - case EXITCMD: - case EXPLCMD: - case FOLDCMD: - case FORWCMD: /* sigh */ - case MARKCMD: - case NEXTCMD: - case PACKCMD: - case PICKCMD: - case PREVCMD: - case RMMCMD: - case SHOWCMD: - case SCANCMD: - case SORTCMD: - if ((cp = context_find (cmd_name))) { - cp = getcpy (cp); - ap = brkstring (cp, " ", "\n"); - ap = copyip (ap, vec, MAXARGS); - } else { - ap = vec; - } - break; - - default: - cp = NULL; - ap = vec; - break; - } - copyip (cmdp->args + 1, ap, MAXARGS); - - m_init (); - - if (!vmh && init_io (cmdp, vmh) == NOTOK) { - if (cp != NULL) - free (cp); - continue; - } - modified = 0; - redirected = vmh || cmdp->direction != STDIO; - - switch (i) { - case ALICMD: - case COMPCMD: - case INCMD: - case MAILCMD: - case MSGKCMD: - case SENDCMD: - case WHATCMD: - case WHOMCMD: - if (!vmh || ttyN (cmdp) != NOTOK) - forkcmd (vec, cmd_name); - break; - - case DISTCMD: - if (!vmh || ttyN (cmdp) != NOTOK) - distcmd (vec); - break; - - case EXPLCMD: - if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK) - explcmd (vec); - break; - - case FILECMD: - if (!vmh - || (filehak (vec) == OK ? ttyN (cmdp) - : winN (cmdp, DISPLAY, 1)) != NOTOK) - filecmd (vec); - break; - - case FOLDCMD: - if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK) - foldcmd (vec); - break; - - case FORWCMD: - if (!vmh || ttyN (cmdp) != NOTOK) - forwcmd (vec); - break; - - case HELPCMD: - if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK) - helpcmd (vec); - break; - - case EXITCMD: - case MARKCMD: - if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK) - markcmd (vec); - break; - - case MHNCMD: - if (!vmh || ttyN (cmdp) != NOTOK) - mhncmd (vec); - break; - - case NEXTCMD: - case PREVCMD: - case SHOWCMD: - if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK) - showcmd (vec); - break; - - case PACKCMD: - if (!vmh - || (packhak (vec) == OK ? ttyN (cmdp) - : winN (cmdp, DISPLAY, 1)) != NOTOK) - packcmd (vec); - break; - - case PICKCMD: - if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK) - pickcmd (vec); - break; - - case REPLCMD: - if (!vmh || ttyN (cmdp) != NOTOK) - replcmd (vec); - break; - - case RMMCMD: - if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK) - rmmcmd (vec); - break; - - case SCANCMD: - if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK) - scancmd (vec); - break; - - case SORTCMD: - if (!vmh || winN (cmdp, DISPLAY, 1) != NOTOK) - sortcmd (vec); - break; - - default: - padios (NULL, "no dispatch for %s", cmd_name); - } - - if (vmh) { - if (vmhtty != NOTOK) - ttyR (cmdp); - if (vmhpid > OK) - winR (cmdp); - } - else - fin_io (cmdp, vmh); - if (cp != NULL) - free (cp); - if (i == EXITCMD) { - quit (); - return; - } - } -} - - -void -fsetup (char *folder) -{ - register int msgnum; - char *maildir; - struct stat st; - - maildir = m_maildir (folder); - if (chdir (maildir) == NOTOK) - padios (maildir, "unable to change directory to"); - - /* read folder and create message structure */ - if (!(mp = folder_read (folder, 0))) - padios (NULL, "unable to read folder %s", folder); - - /* check for empty folder */ - if (mp->nummsg == 0) - padios (NULL, "no messages in %s", folder); - - mode = m_gmprot (); - mtime = stat (mp->foldpath, &st) != NOTOK ? st.st_mtime : 0; - - m_gMsgs (mp->hghmsg); - - for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg; msgnum++) { - Msgs[msgnum].m_bboard_id = 0; - Msgs[msgnum].m_top = NOTOK; - Msgs[msgnum].m_start = Msgs[msgnum].m_stop = 0L; - Msgs[msgnum].m_scanl = NULL; - } - - m_init (); - - fmsh = getcpy (folder); - - maxfds = OPEN_MAX / 2; - - if ((maxfds -= 2) < 1) - maxfds = 1; -} - - -void -setup (char *file) -{ - int i, msgp; - struct stat st; - if ((fp = fopen (file, "r")) == NULL) - padios (file, "unable to read"); -#ifdef FIOCLEX - ioctl (fileno (fp), FIOCLEX, NULL); -#endif /* FIOCLEX */ - if (fstat (fileno (fp), &st) != NOTOK) { - mode = (int) (st.st_mode & 0777), mtime = st.st_mtime; - msgp = read_map (file, (long) st.st_size); - } - else { - mode = m_gmprot (), mtime = 0; - msgp = 0; - } - - if ((msgp = read_file (msgp ? Msgs[msgp].m_stop : 0L, msgp + 1)) < 1) - padios (NULL, "no messages in %s", myname ? myname : file); - - if (!(mp = (struct msgs *) calloc ((size_t) 1, sizeof(*mp)))) - padios (NULL, "unable to allocate folder storage"); - - if (!(mp->msgstats = calloc ((size_t) msgp + 3, sizeof(*(mp->msgstats))))) - padios (NULL, "unable to allocate message status storage"); - - mp->hghmsg = msgp; - mp->nummsg = msgp; - mp->lowmsg = 1; - mp->curmsg = 0; - mp->foldpath = getcpy (myname ? myname : file); - clear_folder_flags (mp); - - stat (file, &st); - if (st.st_uid != getuid () || access (file, W_OK) == NOTOK) - set_readonly (mp); - - mp->lowoff = 1; - mp->hghoff = mp->hghmsg + 1; - - for (i = mp->lowmsg; i <= mp->hghmsg; i++) { - clear_msg_flags (mp, i); - set_exists (mp, i); - } - m_init (); - - svector_push_back (mp->msgattrs, getcpy ("unseen")); - - scan_detect_mbox_style (fp); /* the MAGIC invocation */ - if (fmsh) { - free (fmsh); - fmsh = NULL; - } -} - - -static int -read_map (char *file, long size) -{ - register int i, msgp; - register struct drop *dp, *mp; - struct drop *rp; - - if ((i = map_read (file, size, &rp, 1)) == 0) - return 0; - - m_gMsgs (i); - - msgp = 1; - for (dp = rp + 1; i-- > 0; msgp++, dp++) { - mp = &Msgs[msgp].m_drop; - mp->d_id = dp->d_id; - mp->d_size = dp->d_size; - mp->d_start = dp->d_start; - mp->d_stop = dp->d_stop; - Msgs[msgp].m_scanl = NULL; - } - free ((char *) rp); - - return (msgp - 1); -} - - -static int -read_file (long pos, int msgp) -{ - register int i; - register struct drop *dp, *mp; - struct drop *rp; - - if ((i = mbx_read (fp, pos, &rp, 1)) <= 0) - return (msgp - 1); - - m_gMsgs ((msgp - 1) + i); - - for (dp = rp; i-- > 0; msgp++, dp++) { - mp = &Msgs[msgp].m_drop; - mp->d_id = 0; - mp->d_size = dp->d_size; - mp->d_start = dp->d_start; - mp->d_stop = dp->d_stop; - Msgs[msgp].m_scanl = NULL; - } - free ((char *) rp); - - return (msgp - 1); -} - - -static void -m_gMsgs (int n) -{ - int nmsgs; - - if (Msgs == NULL) { - nMsgs = n + MAXFOLDER / 2; - Msgs = (struct Msg *) calloc ((size_t) (nMsgs + 2), sizeof *Msgs); - if (Msgs == NULL) - padios (NULL, "unable to allocate Msgs structure"); - return; - } - - if (nMsgs >= n) - return; - - nmsgs = nMsgs + n + MAXFOLDER / 2; - Msgs = (struct Msg *) mh_xrealloc ((char *) Msgs, (size_t) (nmsgs + 2) * sizeof *Msgs); - memset((char *) (Msgs + nMsgs + 2), 0, (size_t) ((nmsgs - nMsgs) * sizeof *Msgs)); - - nMsgs = nmsgs; -} - - -FILE * -msh_ready (int msgnum, int full) -{ - register int msgp; - int fd; - char *cp; - NMH_UNUSED (full); - - if (yp) { - fclose (yp); - yp = NULL; - } - - if (fmsh) { - if ((fd = Msgs[msgnum].m_top) == NOTOK) { - if (numfds >= maxfds) - for (msgp = mp->lowmsg; msgp <= mp->hghmsg; msgp++) - if (Msgs[msgp].m_top != NOTOK) { - close (Msgs[msgp].m_top); - Msgs[msgp].m_top = NOTOK; - numfds--; - break; - } - - if ((fd = open (cp = m_name (msgnum), O_RDONLY)) == NOTOK) - padios (cp, "unable to open message"); - Msgs[msgnum].m_top = fd; - numfds++; - } - - if ((fd = dup (fd)) == NOTOK) - padios ("cached message", "unable to dup"); - if ((yp = fdopen (fd, "r")) == NULL) - padios (NULL, "unable to fdopen cached message"); - fseek (yp, 0L, SEEK_SET); - return yp; - } - - scan_reset_m_getfld_state (); - scan_eom_action ((int (*)()) 0); /* XXX */ - fseek (fp, Msgs[msgnum].m_start, SEEK_SET); - return fp; -} - - -static int -check_folder (int scansw) -{ - int seqnum, i, low, hgh, msgp; - struct stat st; - - if (fmsh) { - if (stat (mp->foldpath, &st) == NOTOK) - padios (mp->foldpath, "unable to stat"); - if (mtime == st.st_mtime) - return 0; - mtime = st.st_mtime; - - low = mp->hghmsg + 1; - folder_free (mp); /* free folder/message structure */ - - if (!(mp = folder_read (fmsh, 0))) - padios (NULL, "unable to re-read folder %s", fmsh); - - hgh = mp->hghmsg; - - for (msgp = mp->lowmsg; msgp <= mp->hghmsg; msgp++) { - if (Msgs[msgp].m_top != NOTOK) { - close (Msgs[msgp].m_top); - Msgs[msgp].m_top = NOTOK; - numfds--; - } - if (Msgs[msgp].m_scanl) { - free (Msgs[msgp].m_scanl); - Msgs[msgp].m_scanl = NULL; - } - } - - m_init (); - - if (modified || low > hgh) - return 1; - goto check_vmh; - } - if (fstat (fileno (fp), &st) == NOTOK) - padios (mp->foldpath, "unable to fstat"); - if (mtime == st.st_mtime) - return 0; - mode = (int) (st.st_mode & 0777); - mtime = st.st_mtime; - - if ((msgp = read_file (Msgs[mp->hghmsg].m_stop, mp->hghmsg + 1)) < 1) - padios (NULL, "no messages in %s", mp->foldpath); /* XXX */ - if (msgp >= MAXFOLDER) - padios (NULL, "more than %d messages in %s", MAXFOLDER, - mp->foldpath); - if (msgp <= mp->hghmsg) - return 0; /* XXX */ - - if (!(mp = folder_realloc (mp, mp->lowoff, msgp))) - padios (NULL, "unable to allocate folder storage"); - - low = mp->hghmsg + 1, hgh = msgp; - seqnum = scansw ? seq_getnum (mp, "unseen") : -1; - for (i = mp->hghmsg + 1; i <= msgp; i++) { - set_exists(mp, i); - if (seqnum != -1) - add_sequence(mp, seqnum, i); - mp->nummsg++; - } - mp->hghmsg = msgp; - m_init (); - -check_vmh: ; - if (vmh) - return 1; - - advise (NULL, "new messages have arrived!\007"); - if (scansw) - scanrange (low, hgh); - - return 1; -} - - -static void -scanrange (int low, int hgh) -{ - char buffer[BUFSIZ]; - - snprintf (buffer, sizeof(buffer), "%d-%d", low, hgh); - scanstring (buffer); -} - - -static void -scanstring (char *arg) -{ - char *cp, **ap, *vec[MAXARGS]; - - /* - * This should be replace with a call to getarguments() - */ - if ((cp = context_find (cmd_name = "scan"))) { - cp = getcpy (cp); - ap = brkstring (cp, " ", "\n"); - ap = copyip (ap, vec, MAXARGS); - } else { - ap = vec; - } - *ap++ = arg; - *ap = NULL; - m_init (); - scancmd (vec); - if (cp != NULL) - free (cp); -} - - -void -readids (int id) -{ - register int cur, seqnum, i=0, msgnum; - - if (mp->curmsg == 0) - seq_setcur (mp, mp->lowmsg); - if (id <= 0 || (seqnum = seq_getnum (mp, "unseen")) == -1) - return; - - for (msgnum = mp->hghmsg; msgnum >= mp->lowmsg; msgnum--) - add_sequence(mp, seqnum, msgnum); - - if (id != 1) { - cur = mp->curmsg; - - for (msgnum = mp->hghmsg; msgnum >= mp->lowmsg; msgnum--) - if (does_exist(mp, msgnum)) /* FIX */ - if ((i = readid (msgnum)) > 0 && i < id) { - cur = msgnum + 1; - clear_sequence(mp, seqnum, msgnum); - break; - } - for (i = mp->lowmsg; i < msgnum; i++) - clear_sequence(mp, seqnum, i); - - if (cur > mp->hghmsg) - cur = mp->hghmsg; - - seq_setcur (mp, cur); - } - - if ((gap = 1 < id && id < (i = readid (mp->lowmsg)) ? id : 0) && !vmh) - advise (NULL, "gap in ID:s, last seen %d, lowest present %d\n", - id - 1, i); -} - - -int -readid (int msgnum) -{ - int i, state; - char *bp, buf[BUFSIZ], name[NAMESZ]; - register FILE *zp; - - if (Msgs[msgnum].m_bboard_id) - return Msgs[msgnum].m_bboard_id; - - zp = msh_ready (msgnum, 0); - for (;;) { - int bufsz = sizeof buf; - switch (state = m_getfld (&gstate, name, buf, &bufsz, zp)) { - case FLD: - case FLDPLUS: - if (!strcasecmp (name, BBoard_ID)) { - bp = getcpy (buf); - while (state == FLDPLUS) { - bufsz = sizeof buf; - state = m_getfld (&gstate, name, buf, &bufsz, zp); - bp = add (buf, bp); - } - i = atoi (bp); - free (bp); - if (i > 0) - return (Msgs[msgnum].m_bboard_id = i); - else - continue; - } - while (state == FLDPLUS) { - bufsz = sizeof buf; - state = m_getfld (&gstate, name, buf, &bufsz, zp); - } - continue; - - default: - return 0; - } - } -} - - -void -display_info (int scansw) -{ - int seqnum, sd; - - interactive = isatty (fileno (stdout)); - if (sp == NULL) { - if ((sd = dup (fileno (stdout))) == NOTOK) - padios ("standard output", "unable to dup"); -#ifdef FIOCLEX - ioctl (sd, FIOCLEX, NULL); -#endif /* FIOCLEX */ - if ((sp = fdopen (sd, "w")) == NULL) - padios ("standard output", "unable to fdopen"); - } - - m_putenv ("mhfolder", mp->foldpath); - if (vmh) - return; - - if (myname) { - printf ("Reading "); - if (SOprintf ("%s", myname)) - printf ("%s", myname); - printf (", currently at message %d of %d\n", - mp->curmsg, mp->hghmsg); - } - else { - printf ("Reading "); - if (fmsh) - printf ("+%s", fmsh); - else - printf ("%s", mp->foldpath); - printf (", currently at message %d of %d\n", - mp->curmsg, mp->hghmsg); - } - - if (((seqnum = seq_getnum (mp, "unseen")) != -1) - && scansw - && in_sequence(mp, seqnum, mp->hghmsg)) - scanstring ("unseen"); -} - - -static void -write_ids (void) -{ - int i = 0, seqnum, msgnum; - char buffer[80]; - - if (pfd <= 1) - return; - - if ((seqnum = seq_getnum (mp, "unseen")) != -1) - for (msgnum = mp->hghmsg; msgnum >= mp->lowmsg; msgnum--) - if (!in_sequence(mp, seqnum, msgnum)) { - if (Msgs[msgnum].m_bboard_id == 0) - readid (msgnum); - if ((i = Msgs[msgnum].m_bboard_id) > 0) - break; - } - - snprintf (buffer, sizeof(buffer), "%d %d\n", i, Msgs[mp->hghmsg].m_bboard_id); - write (pfd, buffer, sizeof(buffer)); - close (pfd); - pfd = NOTOK; -} - - -static void -quit (void) -{ - int i, md, msgnum; - char *cp, tmpfil[BUFSIZ]; - char map1[BUFSIZ], map2[BUFSIZ]; - struct stat st; - FILE *dp; - int failed_to_lock = 0; - - if (!(mp->msgflags & MODIFIED) || is_readonly(mp) || fmsh) { - if (vmh) - rc2peer (RC_FIN, 0, NULL); - return; - } - - if (vmh) - ttyNaux (NULLCMD, "FAST"); - cp = NULL; - if ((dp = lkfopendata (mp->foldpath, "r", &failed_to_lock)) == NULL) { - advise (mp->foldpath, "unable to lock"); - if (vmh) { - ttyR (NULLCMD); - pFIN (); - } - return; - } - if (fstat (fileno (dp), &st) == NOTOK) { - advise (mp->foldpath, "unable to stat"); - goto release; - } - if (mtime != st.st_mtime) { - advise (NULL, "new messages have arrived, no update"); - goto release; - } - mode = (int) (st.st_mode & 0777); - - if (mp->nummsg == 0) { - cp = concat ("Zero file \"", mp->foldpath, "\"? ", NULL); - if (getanswer (cp)) { - if ((i = creat (mp->foldpath, mode)) != NOTOK) - close (i); - else - advise (mp->foldpath, "error zero'ing"); - (void) m_unlink (map_name (mp->foldpath));/* XXX */ - } - goto release; - } - - cp = concat ("Update file \"", mp->foldpath, "\"? ", NULL); - if (!getanswer (cp)) - goto release; - strncpy (tmpfil, m_backup (mp->foldpath), sizeof(tmpfil)); - if ((md = mbx_open (tmpfil, mbx_style, st.st_uid, st.st_gid, mode)) == NOTOK) { - advise (tmpfil, "unable to open"); - goto release; - } - - for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg; msgnum++) - if (does_exist(mp, msgnum) && pack (tmpfil, md, msgnum) == NOTOK) { - mbx_close (tmpfil, md); - (void) m_unlink (tmpfil); - (void) m_unlink (map_name (tmpfil)); - goto release; - } - mbx_close (tmpfil, md); - - if (rename (tmpfil, mp->foldpath) == NOTOK) - admonish (mp->foldpath, "unable to rename %s to", tmpfil); - else { - strncpy (map1, map_name (tmpfil), sizeof(map1)); - strncpy (map2, map_name (mp->foldpath), sizeof(map2)); - - if (rename (map1, map2) == NOTOK) { - admonish (map2, "unable to rename %s to", map1); - (void) m_unlink (map1); - (void) m_unlink (map2); - } - } - -release: ; - if (cp) - free (cp); - lkfclosedata (dp, mp->foldpath); - if (vmh) { - ttyR (NULLCMD); - pFIN (); - } -} - - -static int -getargs (char *prompt, struct swit *sw, struct Cmd *cmdp) -{ - int i; - char *cp; - static char buffer[BUFSIZ]; - - told_to_quit = 0; - for (;;) { - interrupted = 0; - if (interactive) { - printf ("%s", prompt); - fflush (stdout); - } - for (cp = buffer; (i = getchar ()) != '\n';) { - if (interrupted && !told_to_quit) { - buffer[0] = '\0'; - putchar ('\n'); - break; - } - if (told_to_quit || i == EOF) { - if (ppid > 0) -#ifdef SIGEMT - kill (ppid, SIGEMT); -#else - kill (ppid, SIGTERM); -#endif - return EOF; - } - if (cp < &buffer[sizeof buffer - 2]) - *cp++ = i; - } - *cp = 0; - - if (buffer[0] == 0) - continue; - if (buffer[0] == '?') { - printf ("commands:\n"); - print_sw (ALL, sw, "", stdout); - printf ("type CTRL-D or use ``quit'' to leave %s\n", - invo_name); - continue; - } - - if (parse (buffer, cmdp) == NOTOK) - continue; - - switch (i = smatch (cmdp->args[0], sw)) { - case AMBIGSW: - ambigsw (cmdp->args[0], sw); - continue; - case UNKWNSW: - printf ("say what: ``%s'' -- type ? (or help) for help\n", - cmdp->args[0]); - continue; - default: - return i; - } - } -} - - -static int -getcmds (struct swit *sw, struct Cmd *cmdp, int scansw) -{ - int i; - struct record rcs, *rc; - - rc = &rcs; - initrc (rc); - - for (;;) - switch (peer2rc (rc)) { - case RC_QRY: - pQRY (rc->rc_data, scansw); - break; - - case RC_CMD: - if ((i = pCMD (rc->rc_data, sw, cmdp)) != NOTOK) - return i; - break; - - case RC_FIN: - if (ppid > 0) -#ifdef SIGEMT - kill (ppid, SIGEMT); -#else - kill (ppid, SIGTERM); -#endif - return EOF; - - case RC_XXX: - padios (NULL, "%s", rc->rc_data); - - default: - fmt2peer (RC_ERR, "pLOOP protocol screw-up"); - done (1); - } -} - - -static int -parse (char *buffer, struct Cmd *cmdp) -{ - int argp = 0; - char c, *cp, *pp; - - cmdp->line[0] = 0; - pp = cmdp->args[argp++] = cmdp->line; - cmdp->redirect = NULL; - cmdp->direction = STDIO; - cmdp->stream = NULL; - - for (cp = buffer; (c = *cp); cp++) { - if (!isspace ((unsigned char) c)) - break; - } - if (c == '\0') { - if (vmh) - fmt2peer (RC_EOF, "null command"); - return NOTOK; - } - - while ((c = *cp++)) { - if (isspace ((unsigned char) c)) { - while (isspace ((unsigned char) c)) - c = *cp++; - if (c == 0) - break; - *pp++ = 0; - cmdp->args[argp++] = pp; - *pp = 0; - } - - switch (c) { - case '"': - for (;;) { - switch (c = *cp++) { - case 0: - padvise (NULL, "unmatched \""); - return NOTOK; - case '"': - break; - case QUOTE: - if ((c = *cp++) == 0) - goto no_quoting; - default: - *pp++ = c; - continue; - } - break; - } - continue; - - case QUOTE: - if ((c = *cp++) == 0) { - no_quoting: ; - padvise (NULL, "the newline character can not be quoted"); - return NOTOK; - } - - default: ; - *pp++ = c; - continue; - - case '>': - case '|': - if (pp == cmdp->line) { - padvise (NULL, "invalid null command"); - return NOTOK; - } - if (*cmdp->args[argp - 1] == 0) - argp--; - cmdp->direction = c == '>' ? CRTIO : PIPIO; - if (cmdp->direction == CRTIO && (c = *cp) == '>') { - cmdp->direction = APPIO; - cp++; - } - cmdp->redirect = pp + 1;/* sigh */ - for (; (c = *cp); cp++) - if (!isspace ((unsigned char) c)) - break; - if (c == 0) { - padvise (NULL, cmdp->direction != PIPIO - ? "missing name for redirect" - : "invalid null command"); - return NOTOK; - } - strcpy (cmdp->redirect, cp); - if (cmdp->direction != PIPIO) { - for (; *cp; cp++) - if (isspace ((unsigned char) *cp)) { - padvise (NULL, "bad name for redirect"); - return NOTOK; - } - if (expand (cmdp->redirect) == NOTOK) - return NOTOK; - } - break; - } - break; - } - - *pp++ = 0; - cmdp->args[argp] = NULL; - - return OK; -} - - -int -expand (char *redirect) -{ - char *cp, *pp; - char path[BUFSIZ]; - struct passwd *pw; - - if (*redirect != '~') - return OK; - - if ((cp = strchr(pp = redirect + 1, '/'))) - *cp++ = 0; - if (*pp == 0) - pp = mypath; - else - if ((pw = getpwnam (pp))) - pp = pw->pw_dir; - else { - padvise (NULL, "unknown user: %s", pp); - return NOTOK; - } - - snprintf (path, sizeof(path), "%s/%s", pp, cp ? cp : ""); - strcpy (redirect, path); - return OK; -} - - -static int -init_io (struct Cmd *cmdp, int vio) -{ - int io, result; - - io = vmh; - - vmh = vio; - result = initaux_io (cmdp); - vmh = io; - - return result; -} - - -static int -initaux_io (struct Cmd *cmdp) -{ - char *mode; - - switch (cmdp->direction) { - case STDIO: - return OK; - - case CRTIO: - case APPIO: - mode = cmdp->direction == CRTIO ? "write" : "append"; - if ((cmdp->stream = fopen (cmdp->redirect, mode)) == NULL) { - padvise (cmdp->redirect, "unable to %s ", mode); - cmdp->direction = STDIO; - return NOTOK; - } - break; - - case PIPIO: - if ((cmdp->stream = popen (cmdp->redirect, "w")) == NULL) { - padvise (cmdp->redirect, "unable to pipe"); - cmdp->direction = STDIO; - return NOTOK; - } - SIGNAL (SIGPIPE, pipeser); - broken_pipe = 0; - break; - - default: - padios (NULL, "unknown redirection for command"); - } - - fflush (stdout); - if (dup2 (fileno (cmdp->stream), fileno (stdout)) == NOTOK) - padios ("standard output", "unable to dup2"); - clearerr (stdout); - - return OK; -} - - -static void -fin_io (struct Cmd *cmdp, int vio) -{ - int io; - - io = vmh; - vmh = vio; - finaux_io (cmdp); - vmh = io; -} - - -static void -finaux_io (struct Cmd *cmdp) -{ - switch (cmdp->direction) { - case STDIO: - return; - - case CRTIO: - case APPIO: - fflush (stdout); - close (fileno (stdout)); - if (ferror (stdout)) - padvise (NULL, "problems writing %s", cmdp->redirect); - fclose (cmdp->stream); - break; - - case PIPIO: - fflush (stdout); - close (fileno (stdout)); - pclose (cmdp->stream); - SIGNAL (SIGPIPE, SIG_DFL); - break; - - default: - padios (NULL, "unknown redirection for command"); - } - - if (dup2 (fileno (sp), fileno (stdout)) == NOTOK) - padios ("standard output", "unable to dup2"); - clearerr (stdout); - - cmdp->direction = STDIO; -} - - -static void -m_init (void) -{ - int msgnum; - - for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg; msgnum++) - unset_selected (mp, msgnum); - mp->lowsel = mp->hghsel = mp->numsel = 0; -} - - -void -m_reset (void) -{ - write_ids (); - folder_free (mp); /* free folder/message structure */ - myname = NULL; -} - - -void -seq_setcur (struct msgs *mp, int msgnum) -{ - if (mp->curmsg == msgnum) - return; - - if (mp->curmsg && Msgs[mp->curmsg].m_scanl) { - free (Msgs[mp->curmsg].m_scanl); - Msgs[mp->curmsg].m_scanl = NULL; - } - if (Msgs[msgnum].m_scanl) { - free (Msgs[msgnum].m_scanl); - Msgs[msgnum].m_scanl = NULL; - } - - mp->curmsg = msgnum; -} - - - -static void -intrser (int i) -{ - NMH_UNUSED (i); - discard (stdout); - interrupted++; -} - - -static void -pipeser (int i) -{ - NMH_UNUSED (i); - if (broken_pipe++ == 0) - fprintf (stderr, "broken pipe\n"); - told_to_quit++; - interrupted++; -} - - -static void -quitser (int i) -{ - NMH_UNUSED (i); - told_to_quit++; - interrupted++; -} - - -static void -alrmser (int i) -{ - NMH_UNUSED (i); - longjmp (peerenv, DONE); -} - - -static int -pINI (void) -{ - int i, vrsn; - char *bp; - struct record rcs, *rc; - - rc = &rcs; - initrc (rc); - - switch (peer2rc (rc)) { - case RC_INI: - bp = rc->rc_data; - while (isspace ((unsigned char) *bp)) - bp++; - if (sscanf (bp, "%d", &vrsn) != 1) { - bad_init: ; - fmt2peer (RC_ERR, "bad init \"%s\"", rc->rc_data); - done (1); - } - if (vrsn != RC_VRSN) { - fmt2peer (RC_ERR, "version %d unsupported", vrsn); - done (1); - } - - while (*bp && !isspace ((unsigned char) *bp)) - bp++; - while (isspace ((unsigned char) *bp)) - bp++; - if (sscanf (bp, "%d", &numwins) != 1 || numwins <= 0) - goto bad_init; - if (numwins > NWIN) - numwins = NWIN; - - for (i = 1; i <= numwins; i++) { - while (*bp && !isspace ((unsigned char) *bp)) - bp++; - while (isspace ((unsigned char) *bp)) - bp++; - if (sscanf (bp, "%d", &windows[i]) != 1 || windows[i] <= 0) - goto bad_init; - } - rc2peer (RC_ACK, 0, NULL); - return OK; - - case RC_XXX: - padios (NULL, "%s", rc->rc_data); - - default: - fmt2peer (RC_ERR, "pINI protocol screw-up"); - done (1); /* NOTREACHED */ - } - - return 1; /* dead code to satisfy the compiler */ -} - - -static int -pQRY (char *str, int scansw) -{ - NMH_UNUSED (str); - if (pQRY1 (scansw) == NOTOK || pQRY2 () == NOTOK) - return NOTOK; - - rc2peer (RC_EOF, 0, NULL); - return OK; -} - - -static int -pQRY1 (int scansw) -{ - int oldhgh; - static int lastlow = 0, - lastcur = 0, - lasthgh = 0, - lastnum = 0; - - oldhgh = mp->hghmsg; - if (check_folder (scansw) && oldhgh < mp->hghmsg) { - switch (winX (STATUS)) { - case NOTOK: - return NOTOK; - - case OK: - printf ("new messages have arrived!"); - fflush (stdout); - fflush (stderr); - _exit (0); /* NOTREACHED */ - - default: - lastlow = lastcur = lasthgh = lastnum = 0; - break; - } - - switch (winX (DISPLAY)) { - case NOTOK: - return NOTOK; - - case OK: - scanrange (oldhgh + 1, mp->hghmsg); - fflush (stdout); - fflush (stderr); - _exit (0); /* NOTREACHED */ - - default: - break; - } - return OK; - } - - if (gap) - switch (winX (STATUS)) { - case NOTOK: - return NOTOK; - - case OK: - printf ("%s: gap in ID:s, last seen %d, lowest present %d\n", - myname ? myname : fmsh ? fmsh : mp->foldpath, gap - 1, - readid (mp->lowmsg)); - fflush (stdout); - fflush (stderr); - _exit (0); /* NOTREACHED */ - - default: - gap = 0; - return OK; - } - - if (mp->lowmsg != lastlow - || mp->curmsg != lastcur - || mp->hghmsg != lasthgh - || mp->nummsg != lastnum) - switch (winX (STATUS)) { - case NOTOK: - return NOTOK; - - case OK: - foldcmd (NULL); - fflush (stdout); - fflush (stderr); - _exit (0); /* NOTREACHED */ - - default: - lastlow = mp->lowmsg; - lastcur = mp->curmsg; - lasthgh = mp->hghmsg; - lastnum = mp->nummsg; - return OK; - } - - return OK; -} - - -static int -pQRY2 (void) -{ - int i, j, k, msgnum, n; - static int cur = 0, - num = 0, - lo = 0, - hi = 0; - - if (mp->nummsg == 0 && mp->nummsg != num) - switch (winX (SCAN)) { - case NOTOK: - return NOTOK; - - case OK: - printf ("empty!"); - fflush (stdout); - fflush (stderr); - _exit (0); /* NOTREACHED */ - - default: - num = mp->nummsg; - return OK; - } - num = mp->nummsg; - - i = 0; - j = (k = windows[SCAN]) / 2; - for (msgnum = mp->curmsg; msgnum <= mp->hghmsg; msgnum++) - if (does_exist (mp, msgnum)) - i++; - if (i-- > 0) { - if (topcur) - k = i >= k ? 1 : k - i; - else - k -= i > j ? j : i; - } - - i = j = 0; - n = 1; - for (msgnum = mp->curmsg; msgnum >= mp->lowmsg; msgnum--) - if (does_exist (mp, msgnum)) { - i = msgnum; - if (j == 0) - j = msgnum; - if (n++ >= k) - break; - } - for (msgnum = mp->curmsg + 1; msgnum <= mp->hghmsg; msgnum++) - if (does_exist (mp, msgnum)) { - if (i == 0) - i = msgnum; - j = msgnum; - if (n++ >= windows[SCAN]) - break; - } - if (!topcur - && lo > 0 - && hi > 0 - && does_exist (mp, lo) - && does_exist (mp, hi) - && (lo < mp->curmsg - || (lo == mp->curmsg && lo == mp->lowmsg)) - && (mp->curmsg < hi - || (hi == mp->curmsg && hi == mp->hghmsg)) - && hi - lo == j - i) - i = lo, j = hi; - - if (mp->curmsg != cur || modified) - switch (winN (NULLCMD, SCAN, 0)) { - case NOTOK: - return NOTOK; - - case OK: - return OK; - - default: - scanrange (lo = i, hi = j); - cur = mp->curmsg; - winR (NULLCMD); - return OK; - } - - return OK; -} - - -static int -pCMD (char *str, struct swit *sw, struct Cmd *cmdp) -{ - int i; - - if (*str == '?') - switch (winX (DISPLAY)) { - case NOTOK: - return NOTOK; - - case OK: - printf ("commands:\n"); - print_sw (ALL, sw, "", stdout); - printf ("type ``quit'' to leave %s\n", invo_name); - fflush (stdout); - fflush (stderr); - _exit (0); /* NOTREACHED */ - - default: - rc2peer (RC_EOF, 0, NULL); - return NOTOK; - } - - if (parse (str, cmdp) == NOTOK) - return NOTOK; - - switch (i = smatch (cmdp->args[0], sw)) { - case AMBIGSW: - switch (winX (DISPLAY)) { - case NOTOK: - return NOTOK; - - case OK: - ambigsw (cmdp->args[0], sw); - fflush (stdout); - fflush (stderr); - _exit (0); /* NOTREACHED */ - - default: - rc2peer (RC_EOF, 0, NULL); - return NOTOK; - } - - case UNKWNSW: - fmt2peer (RC_ERR, - "say what: ``%s'' -- type ? (or help) for help", - cmdp->args[0]); - return NOTOK; - - default: - return i; - } -} - - -static int -pFIN (void) -{ - int status; - - switch (setjmp (peerenv)) { - case OK: - SIGNAL (SIGALRM, alrmser); - alarm (ALARM); - - status = peerwait (); - - alarm (0); - return status; - - default: - return NOTOK; - } -} - - -static int -peerwait (void) -{ - struct record rcs, *rc; - - rc = &rcs; - initrc (rc); - - switch (peer2rc (rc)) { - case RC_QRY: - case RC_CMD: - rc2peer (RC_FIN, 0, NULL); - return OK; - - case RC_XXX: - advise (NULL, "%s", rc->rc_data); - return NOTOK; - - default: - fmt2peer (RC_FIN, "pLOOP protocol screw-up"); - return NOTOK; - } -} - - -static int -ttyNaux (struct Cmd *cmdp, char *s) -{ - struct record rcs, *rc; - - rc = &rcs; - initrc (rc); - - if (cmdp && init_io (cmdp, vmh) == NOTOK) - return NOTOK; - - /* XXX: fseek() too tricky for our own good */ - if (!fmsh) - fseek (fp, 0L, SEEK_SET); - - vmhtty = NOTOK; - switch (rc2rc (RC_TTY, s ? strlen (s) : 0, s, rc)) { - case RC_ACK: - vmhtty = OK; /* fall */ - case RC_ERR: - break; - - case RC_XXX: - padios (NULL, "%s", rc->rc_data);/* NOTREACHED */ - - default: - fmt2peer (RC_ERR, "pTTY protocol screw-up"); - done (1); /* NOTREACHED */ - } - -#ifdef SIGTSTP - SIGNAL (SIGTSTP, tstat); -#endif - return vmhtty; -} - - -static int -ttyR (struct Cmd *cmdp) -{ - struct record rcs, *rc; - - rc = &rcs; - -#ifdef SIGTSTP - SIGNAL (SIGTSTP, SIG_IGN); -#endif - - if (vmhtty != OK) - return NOTOK; - - initrc (rc); - - if (cmdp) - fin_io (cmdp, 0); - - vmhtty = NOTOK; - switch (rc2rc (RC_EOF, 0, NULL, rc)) { - case RC_ACK: - rc2peer (RC_EOF, 0, NULL); - return OK; - - case RC_XXX: - padios (NULL, "%s", rc->rc_data);/* NOTREACHED */ - - default: - fmt2peer (RC_ERR, "pTTY protocol screw-up"); - done (1); /* NOTREACHED */ - } - - return 1; /* dead code to satisfy compiler */ -} - - -static int -winN (struct Cmd *cmdp, int n, int eof) -{ - int i, pd[2]; - char buffer[BUFSIZ]; - struct record rcs, *rc; - - rc = &rcs; - if (vmhpid == NOTOK) - return OK; - - initrc (rc); - - /* XXX: fseek() too tricky for our own good */ - if (!fmsh) - fseek (fp, 0L, SEEK_SET); - - vmhpid = OK; - - snprintf (buffer, sizeof(buffer), "%d", n); - switch (str2rc (RC_WIN, buffer, rc)) { - case RC_ACK: - break; - - case RC_ERR: - return NOTOK; - - case RC_XXX: - padios (NULL, "%s", rc->rc_data); - - default: - fmt2peer (RC_ERR, "pWIN protocol screw-up"); - done (1); - } - - if (pipe (pd) == NOTOK) { - err2peer (RC_ERR, "pipe", "unable to"); - return NOTOK; - } - - switch (vmhpid = fork()) { - case NOTOK: - err2peer (RC_ERR, "fork", "unable to"); - close (pd[0]); - close (pd[1]); - return NOTOK; - - case OK: - close (pd[1]); - SIGNAL (SIGPIPE, SIG_IGN); - while ((i = read (pd[0], buffer, sizeof buffer)) > 0) - switch (rc2rc (RC_DATA, i, buffer, rc)) { - case RC_ACK: - break; - - case RC_ERR: - _exit (1); - - case RC_XXX: - advise (NULL, "%s", rc->rc_data); - _exit (2); - - default: - fmt2peer (RC_ERR, "pWIN protocol screw-up"); - _exit (2); - } - if (i == OK) - switch (rc2rc (RC_EOF, 0, NULL, rc)) { - case RC_ACK: - if (eof) - rc2peer (RC_EOF, 0, NULL); - i = 0; - break; - - case RC_XXX: - advise (NULL, "%s", rc->rc_data); - i = 2; - break; - - default: - fmt2peer (RC_ERR, "pWIN protocol screw-up"); - i = 2; - break; - } - if (i == NOTOK) - err2peer (RC_ERR, "pipe", "error reading from"); - close (pd[0]); - _exit (i != NOTOK ? i : 1); - - default: - if ((vmhfd0 = dup (fileno (stdin))) == NOTOK) - padios ("standard input", "unable to dup"); - if ((vmhfd1 = dup (fileno (stdout))) == NOTOK) - padios ("standard output", "unable to dup"); - if ((vmhfd2 = dup (fileno (stderr))) == NOTOK) - padios ("diagnostic output", "unable to dup"); - - close (0); - if ((i = open ("/dev/null", O_RDONLY)) != NOTOK && i != fileno (stdin)) { - dup2 (i, fileno (stdin)); - close (i); - } - - fflush (stdout); - if (dup2 (pd[1], fileno (stdout)) == NOTOK) - padios ("standard output", "unable to dup2"); - clearerr (stdout); - - fflush (stderr); - if (dup2 (pd[1], fileno (stderr)) == NOTOK) - padios ("diagnostic output", "unable to dup2"); - clearerr (stderr); - - if (cmdp && init_io (cmdp, 0) == NOTOK) - return NOTOK; - pstat = SIGNAL (SIGPIPE, pipeser); - broken_pipe = 1; - - close (pd[0]); - close (pd[1]); - - return vmhpid; - } -} - - -static int -winR (struct Cmd *cmdp) -{ - int status; - - if (vmhpid <= OK) - return NOTOK; - - if (cmdp) - fin_io (cmdp, 0); - - if (dup2 (vmhfd0, fileno (stdin)) == NOTOK) - padios ("standard input", "unable to dup2"); - clearerr (stdin); - close (vmhfd0); - - fflush (stdout); - if (dup2 (vmhfd1, fileno (stdout)) == NOTOK) - padios ("standard output", "unable to dup2"); - clearerr (stdout); - close (vmhfd1); - - fflush (stderr); - if (dup2 (vmhfd2, fileno (stderr)) == NOTOK) - padios ("diagnostic output", "unable to dup2"); - clearerr (stderr); - close (vmhfd2); - - SIGNAL (SIGPIPE, pstat); - - if ((status = pidwait (vmhpid, OK)) == 2) - done (1); - - vmhpid = OK; - return (status == 0 ? OK : NOTOK); -} - - -static int -winX (int n) -{ - int i, pid, pd[2]; - char buffer[BUFSIZ]; - struct record rcs, *rc; - - rc = &rcs; - initrc (rc); - - /* XXX: fseek() too tricky for our own good */ - if (!fmsh) - fseek (fp, 0L, SEEK_SET); - - snprintf (buffer, sizeof(buffer), "%d", n); - switch (str2rc (RC_WIN, buffer, rc)) { - case RC_ACK: - break; - - case RC_ERR: - return NOTOK; - - case RC_XXX: - padios (NULL, "%s", rc->rc_data); - - default: - fmt2peer (RC_ERR, "pWIN protocol screw-up"); - done (1); - } - - if (pipe (pd) == NOTOK) { - err2peer (RC_ERR, "pipe", "unable to"); - return NOTOK; - } - - switch (pid = fork ()) { - case NOTOK: - err2peer (RC_ERR, "fork", "unable to"); - close (pd[0]); - close (pd[1]); - return NOTOK; - - case OK: - close (fileno (stdin)); - if ((i = open ("/dev/null", O_RDONLY)) != NOTOK && i != fileno (stdin)) { - dup2 (i, fileno (stdin)); - close (i); - } - dup2 (pd[1], fileno (stdout)); - dup2 (pd[1], fileno (stderr)); - close (pd[0]); - close (pd[1]); - vmhpid = NOTOK; - return OK; - - default: - close (pd[1]); - while ((i = read (pd[0], buffer, sizeof buffer)) > 0) - switch (rc2rc (RC_DATA, i, buffer, rc)) { - case RC_ACK: - break; - - case RC_ERR: - close (pd[0]); - pidwait (pid, OK); - return NOTOK; - - case RC_XXX: - padios (NULL, "%s", rc->rc_data); - - default: - fmt2peer (RC_ERR, "pWIN protocol screw-up"); - done (1); - } - if (i == OK) - switch (rc2rc (RC_EOF, 0, NULL, rc)) { - case RC_ACK: - break; - - case RC_XXX: - padios (NULL, "%s", rc->rc_data); - - default: - fmt2peer (RC_ERR, "pWIN protocol screw-up"); - done (1); - } - if (i == NOTOK) - err2peer (RC_ERR, "pipe", "error reading from"); - - close (pd[0]); - pidwait (pid, OK); - return (i != NOTOK ? pid : NOTOK); - } -} - - -void -padios (char *what, char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - if (vmh) { - verr2peer (RC_FIN, what, fmt, ap); - rcdone (); - } else { - advertise (what, NULL, fmt, ap); - } - va_end(ap); - - done (1); -} - - -void -padvise (char *what, char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - if (vmh) { - verr2peer (RC_ERR, what, fmt, ap); - } else { - advertise (what, NULL, fmt, ap); - } - va_end(ap); -} diff --git a/uip/mshcmds.c b/uip/mshcmds.c deleted file mode 100644 index 6627c6ab..00000000 --- a/uip/mshcmds.c +++ /dev/null @@ -1,2901 +0,0 @@ - -/* - * mshcmds.c -- command handlers in msh - * - * This code is Copyright (c) 2002, by the authors of nmh. See the - * COPYRIGHT file in the root directory of the nmh distribution for - * complete copyright information. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -static char delim3[] = "-------"; /* from burst.c */ - -static int mhlnum; -static FILE *mhlfp; - -/* - * Type for a compare function for qsort. This keeps - * the compiler happy. - */ -typedef int (*qsort_comp) (const void *, const void *); - -/* - * static prototypes - */ -static int burst (struct Msg *, int, int, int, int); -static void forw (char *, char *, int, char **); -static void rmm (void); -static void show (int); -static int eom_action (int); -static FILE *mhl_action (char *); -static int ask (int); -static int is_nontext (int); -static int get_fields (char *, char *, int, struct Msg *); -static int msgsort (struct Msg *, struct Msg *); -static int subsort (struct Msg *, struct Msg *); -static char *sosmash (char *, char *); -static int process (int, char *, int, char **); -static void copy_message (int, FILE *); -static void copy_digest (int, FILE *); - -extern m_getfld_state_t gstate; /* use the gstate in scansbr.c */ - -void -forkcmd (char **args, char *pgm) -{ - int child_id; - char *vec[MAXARGS]; - - vec[0] = r1bindex (pgm, '/'); - copyip (args, vec + 1, MAXARGS - 1); - - if (fmsh) { - context_del (pfolder); - context_replace (pfolder, fmsh);/* update current folder */ - seq_save (mp); - context_save (); /* save the context file */ - } - fflush (stdout); - switch (child_id = fork ()) { - case NOTOK: - advise ("fork", "unable to"); - return; - - case OK: - closefds (3); - SIGNAL (SIGINT, istat); - SIGNAL (SIGQUIT, qstat); - - execvp (pgm, vec); - fprintf (stderr, "unable to exec "); - perror (cmd_name); - _exit (1); - - default: - pidXwait (child_id, NULL); - break; - } - if (fmsh) { /* assume the worst case */ - mp->msgflags |= MODIFIED; - modified++; - } -} - - -#define DIST_SWITCHES \ - X("annotate", 0, DIANSW) \ - X("noannotate", 0, DINANSW) \ - X("draftfolder +folder", 0, DIDFSW) \ - X("draftmessage msg", 0, DIDMSW) \ - X("nodraftfolder", 0, DINDFSW) \ - X("editor editor", 0, DIEDTSW) \ - X("noedit", 0, DINEDSW) \ - X("form formfile", 0, DIFRMSW) \ - X("inplace", 0, DIINSW) \ - X("noinplace", 0, DININSW) \ - X("whatnowproc program", 0, DIWHTSW) \ - X("nowhatnowproc", 0, DINWTSW) \ - X("help", 0, DIHELP) \ - -#define X(sw, minchars, id) id, -DEFINE_SWITCH_ENUM(DIST); -#undef X - -#define X(sw, minchars, id) { sw, minchars, id }, -DEFINE_SWITCH_ARRAY(DIST, distswit); -#undef X - - -void -distcmd (char **args) -{ - int vecp = 1; - char *cp, *msg = NULL; - char buf[BUFSIZ], *vec[MAXARGS]; - - if (fmsh) { - forkcmd (args, cmd_name); - return; - } - - while ((cp = *args++)) { - if (*cp == '-') - switch (smatch (++cp, distswit)) { - case AMBIGSW: - ambigsw (cp, distswit); - return; - case UNKWNSW: - fprintf (stderr, "-%s unknown\n", cp); - return; - case DIHELP: - snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name); - print_help (buf, distswit, 1); - return; - - case DIANSW: /* not implemented */ - case DINANSW: - case DIINSW: - case DININSW: - continue; - - case DINDFSW: - case DINEDSW: - case DINWTSW: - vec[vecp++] = --cp; - continue; - - case DIEDTSW: - case DIFRMSW: - case DIDFSW: - case DIDMSW: - case DIWHTSW: - vec[vecp++] = --cp; - if (!(cp = *args++) || *cp == '-') { - advise (NULL, "missing argument to %s", args[-2]); - return; - } - vec[vecp++] = cp; - continue; - } - if (*cp == '+' || *cp == '@') { - advise (NULL, "sorry, no folders allowed!"); - return; - } - else - if (msg) { - advise (NULL, "only one message at a time!"); - return; - } - else - msg = cp; - } - - vec[0] = cmd_name; - vec[vecp++] = "-file"; - vec[vecp] = NULL; - if (!msg) - msg = "cur"; - if (!m_convert (mp, msg)) - return; - seq_setprev (mp); - - if (mp->numsel > 1) { - advise (NULL, "only one message at a time!"); - return; - } - process (mp->hghsel, cmd_name, vecp, vec); - seq_setcur (mp, mp->hghsel); -} - - -#define EXPLODE_SWITCHES \ - X("inplace", 0, EXINSW) \ - X("noinplace", 0, EXNINSW) \ - X("quiet", 0, EXQISW) \ - X("noquiet", 0, EXNQISW) \ - X("verbose", 0, EXVBSW) \ - X("noverbose", 0, EXNVBSW) \ - X("help", 0, EXHELP) \ - -#define X(sw, minchars, id) id, -DEFINE_SWITCH_ENUM(EXPLODE); -#undef X - -#define X(sw, minchars, id) { sw, minchars, id }, -DEFINE_SWITCH_ARRAY(EXPLODE, explswit); -#undef X - - -void -explcmd (char **args) -{ - int inplace = 0, quietsw = 0, verbosw = 0; - int msgp = 0, hi, msgnum; - char *cp, buf[BUFSIZ], *msgs[MAXARGS]; - struct Msg *smsgs; - - if (fmsh) { - forkcmd (args, cmd_name); - return; - } - - while ((cp = *args++)) { - if (*cp == '-') - switch (smatch (++cp, explswit)) { - case AMBIGSW: - ambigsw (cp, explswit); - return; - case UNKWNSW: - fprintf (stderr, "-%s unknown\n", cp); - return; - case EXHELP: - snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name); - print_help (buf, explswit, 1); - return; - - case EXINSW: - inplace++; - continue; - case EXNINSW: - inplace = 0; - continue; - case EXQISW: - quietsw++; - continue; - case EXNQISW: - quietsw = 0; - continue; - case EXVBSW: - verbosw++; - continue; - case EXNVBSW: - verbosw = 0; - continue; - } - if (*cp == '+' || *cp == '@') { - advise (NULL, "sorry, no folders allowed!"); - return; - } - else - msgs[msgp++] = cp; - } - - if (!msgp) - msgs[msgp++] = "cur"; - for (msgnum = 0; msgnum < msgp; msgnum++) - if (!m_convert (mp, msgs[msgnum])) - return; - seq_setprev (mp); - - smsgs = (struct Msg *) - calloc ((size_t) (MAXFOLDER + 2), sizeof *smsgs); - if (smsgs == NULL) - adios (NULL, "unable to allocate folder storage"); - - hi = mp->hghmsg + 1; - interrupted = 0; - for (msgnum = mp->lowsel; - msgnum <= mp->hghsel && !interrupted; - msgnum++) - if (is_selected (mp, msgnum)) - if (burst (smsgs, msgnum, inplace, quietsw, verbosw) != OK) - break; - - free ((char *) smsgs); - - if (inplace) - seq_setcur (mp, mp->lowsel); - else - if (hi <= mp->hghmsg) - seq_setcur (mp, hi); - - mp->msgflags |= MODIFIED; - modified++; -} - - -static int -burst (struct Msg *smsgs, int msgnum, int inplace, int quietsw, int verbosw) -{ - int i, j, ld3, wasdlm, msgp; - long pos; - char c, buffer[BUFSIZ]; - register FILE *zp; - - ld3 = strlen (delim3); - - if (Msgs[msgnum].m_scanl) { - free (Msgs[msgnum].m_scanl); - Msgs[msgnum].m_scanl = NULL; - } - - pos = ftell (zp = msh_ready (msgnum, 1)); - for (msgp = 0; msgp <= MAXFOLDER;) { - while (fgets (buffer, sizeof buffer, zp) != NULL - && buffer[0] == '\n' - && pos < Msgs[msgnum].m_stop) - pos += (long) strlen (buffer); - if (feof (zp) || pos >= Msgs[msgnum].m_stop) - break; - fseek (zp, pos, SEEK_SET); - smsgs[msgp].m_start = pos; - - for (c = 0; - pos < Msgs[msgnum].m_stop - && fgets (buffer, sizeof buffer, zp) != NULL; - c = buffer[0]) - if (strncmp (buffer, delim3, ld3) == 0 - && (msgp == 1 || c == '\n') - && peekc (zp) == '\n') - break; - else - pos += (long) strlen (buffer); - - wasdlm = strncmp (buffer, delim3, ld3) == 0; - if (smsgs[msgp].m_start != pos) - smsgs[msgp++].m_stop = (c == '\n' && wasdlm) ? pos - 1 : pos; - if (feof (zp) || pos >= Msgs[msgnum].m_stop) { - if (wasdlm) - smsgs[msgp - 1].m_stop -= ((long) strlen (buffer) + 1); - break; - } - pos += (long) strlen (buffer); - } - - switch (msgp--) { /* toss "End of XXX Digest" */ - case 0: - adios (NULL, "burst() botch -- you lose big"); - - case 1: - if (!quietsw) - printf ("message %d not in digest format\n", msgnum); - return OK; - - default: - if (verbosw) - printf ("%d message%s exploded from digest %d\n", - msgp, msgp != 1 ? "s" : "", msgnum); - break; - } - - if ((i = msgp + mp->hghmsg) > MAXFOLDER) { - advise (NULL, "more than %d messages", MAXFOLDER); - return NOTOK; - } - if (!(mp = folder_realloc (mp, mp->lowoff, i))) - adios (NULL, "unable to allocate folder storage"); - - j = mp->hghmsg; - mp->hghmsg += msgp; - mp->nummsg += msgp; - if (mp->hghsel > msgnum) - mp->hghsel += msgp; - - if (inplace) - for (i = mp->hghmsg; j > msgnum; i--, j--) { - if (verbosw) - printf ("message %d becomes message %d\n", j, i); - - Msgs[i].m_bboard_id = Msgs[j].m_bboard_id; - Msgs[i].m_top = Msgs[j].m_top; - Msgs[i].m_start = Msgs[j].m_start; - Msgs[i].m_stop = Msgs[j].m_stop; - Msgs[i].m_scanl = NULL; - if (Msgs[j].m_scanl) { - free (Msgs[j].m_scanl); - Msgs[j].m_scanl = NULL; - } - copy_msg_flags (mp, i, j); - } - - if (Msgs[msgnum].m_bboard_id == 0) - readid (msgnum); - - unset_selected (mp, msgnum); - i = inplace ? msgnum + msgp : mp->hghmsg; - for (j = msgp; j >= (inplace ? 0 : 1); i--, j--) { - if (verbosw && i != msgnum) - printf ("message %d of digest %d becomes message %d\n", - j, msgnum, i); - - Msgs[i].m_bboard_id = Msgs[msgnum].m_bboard_id; - Msgs[i].m_top = Msgs[j].m_top; - Msgs[i].m_start = smsgs[j].m_start; - Msgs[i].m_stop = smsgs[j].m_stop; - Msgs[i].m_scanl = NULL; - copy_msg_flags (mp, i, msgnum); - } - - return OK; -} - - -#define FILE_SWITCHES \ - X("draft", 0, FIDRFT) \ - X("link", 0, FILINK) \ - X("nolink", 0, FINLINK) \ - X("preserve", 0, FIPRES) \ - X("nopreserve", 0, FINPRES) \ - X("src +folder", 0, FISRC) \ - X("file file", 0, FIFILE) \ - X("rmmproc program", 0, FIPROC) \ - X("normmproc", 0, FINPRC) \ - X("help", 0, FIHELP) \ - -#define X(sw, minchars, id) id, -DEFINE_SWITCH_ENUM(FILE); -#undef X - -#define X(sw, minchars, id) { sw, minchars, id }, -DEFINE_SWITCH_ARRAY(FILE, fileswit); -#undef X - - -void -filecmd (char **args) -{ - int linksw = 0, msgp = 0; - int vecp = 1, i, msgnum; - char *cp, buf[BUFSIZ]; - char *msgs[MAXARGS], *vec[MAXARGS]; - - if (fmsh) { - forkcmd (args, cmd_name); - return; - } - - while ((cp = *args++)) { - if (*cp == '-') - switch (i = smatch (++cp, fileswit)) { - case AMBIGSW: - ambigsw (cp, fileswit); - return; - case UNKWNSW: - fprintf (stderr, "-%s unknown\n", cp); - return; - case FIHELP: - snprintf (buf, sizeof(buf), "%s +folder... [msgs] [switches]", cmd_name); - print_help (buf, fileswit, 1); - return; - - case FILINK: - linksw++; - continue; - case FINLINK: - linksw = 0; - continue; - - case FIPRES: - case FINPRES: - continue; - - case FISRC: - case FIDRFT: - case FIFILE: - case FIPROC: - case FINPRC: - advise (NULL, "sorry, -%s not allowed!", fileswit[i].sw); - return; - } - if (*cp == '+' || *cp == '@') - vec[vecp++] = cp; - else - msgs[msgp++] = cp; - } - - vec[0] = cmd_name; - vec[vecp++] = "-file"; - vec[vecp] = NULL; - if (!msgp) - msgs[msgp++] = "cur"; - for (msgnum = 0; msgnum < msgp; msgnum++) - if (!m_convert (mp, msgs[msgnum])) - return; - seq_setprev (mp); - - interrupted = 0; - for (msgnum = mp->lowsel; - msgnum <= mp->hghsel && !interrupted; - msgnum++) - if (is_selected (mp, msgnum)) - if (process (msgnum, fileproc, vecp, vec)) { - unset_selected (mp, msgnum); - mp->numsel--; - } - - if (mp->numsel != mp->nummsg || linksw) - seq_setcur (mp, mp->hghsel); - if (!linksw) - rmm (); -} - - -int -filehak (char **args) -{ - int result, vecp = 0; - char *cp, *cwd, *vec[MAXARGS]; - - while ((cp = *args++)) { - if (*cp == '-') - switch (smatch (++cp, fileswit)) { - case AMBIGSW: - case UNKWNSW: - case FIHELP: - return NOTOK; - - case FILINK: - case FINLINK: - case FIPRES: - case FINPRES: - continue; - - case FISRC: - case FIDRFT: - case FIFILE: - return NOTOK; - } - if (*cp == '+' || *cp == '@') - vec[vecp++] = cp; - } - vec[vecp] = NULL; - - result = NOTOK; - cwd = NULL; - for (vecp = 0; (cp = vec[vecp]) && result == NOTOK; vecp++) { - if (cwd == NULL) - cwd = getcpy (pwd ()); - chdir (m_maildir ("")); - cp = pluspath (cp); - if (access (m_maildir (cp), F_OK) == NOTOK) - result = OK; - free (cp); - } - if (cwd) - chdir (cwd); - - return result; -} - - -#define FOLDER_SWITCHES \ - X("all", 0, FLALSW) \ - X("fast", 0, FLFASW) \ - X("nofast", 0, FLNFASW) \ - X("header", 0, FLHDSW) \ - X("noheader", 0, FLNHDSW) \ - X("pack", 0, FLPKSW) \ - X("nopack", 0, FLNPKSW) \ - X("recurse", 0, FLRCSW) \ - X("norecurse", 0, FLNRCSW) \ - X("total", 0, FLTLSW) \ - X("nototal", 0, FLNTLSW) \ - X("print", 0, FLPRSW) \ - X("push", 0, FLPUSW) \ - X("pop", 0, FLPOSW) \ - X("list", 0, FLLISW) \ - X("help", 0, FLHELP) \ - -#define X(sw, minchars, id) id, -DEFINE_SWITCH_ENUM(FOLDER); -#undef X - -#define X(sw, minchars, id) { sw, minchars, id }, -DEFINE_SWITCH_ARRAY(FOLDER, foldswit); -#undef X - - -void -foldcmd (char **args) -{ - int fastsw = 0, headersw = 0, packsw = 0; - int hole, msgnum; - char *cp, *folder = NULL, *msg = NULL; - char buf[BUFSIZ], **vec = args; - - if (args == NULL) - goto fast; - - while ((cp = *args++)) { - if (*cp == '-') - switch (smatch (++cp, foldswit)) { - case AMBIGSW: - ambigsw (cp, foldswit); - return; - case UNKWNSW: - fprintf (stderr, "-%s unknown\n", cp); - return; - case FLHELP: - snprintf (buf, sizeof(buf), "%s [+folder] [msg] [switches]", cmd_name); - print_help (buf, foldswit, 1); - return; - - case FLALSW: /* not implemented */ - case FLRCSW: - case FLNRCSW: - case FLTLSW: - case FLNTLSW: - case FLPRSW: - case FLPUSW: - case FLPOSW: - case FLLISW: - continue; - - case FLFASW: - fastsw++; - continue; - case FLNFASW: - fastsw = 0; - continue; - case FLHDSW: - headersw++; - continue; - case FLNHDSW: - headersw = 0; - continue; - case FLPKSW: - packsw++; - continue; - case FLNPKSW: - packsw = 0; - continue; - } - if (*cp == '+' || *cp == '@') { - if (folder) { - advise (NULL, "only one folder at a time!\n"); - return; - } - else - folder = fmsh ? pluspath (cp) - : cp + 1; - } - else - if (msg) { - advise (NULL, "only one message at a time!\n"); - return; - } - else - msg = cp; - } - - if (folder) { - if (*folder == 0) { - advise (NULL, "null folder names are not permitted"); - return; - } - if (fmsh) { - if (access (m_maildir (folder), R_OK) == NOTOK) { - advise (folder, "unable to read"); - return; - } - } - else { - strncpy (buf, folder, sizeof(buf)); - if (expand (buf) == NOTOK) - return; - folder = buf; - if (access (folder, R_OK) == NOTOK) { - advise (folder, "unable to read"); - return; - } - } - m_reset (); - - if (fmsh) - fsetup (folder); - else - setup (folder); - readids (0); - display_info (0); - } - - if (msg) { - if (!m_convert (mp, msg)) - return; - seq_setprev (mp); - - if (mp->numsel > 1) { - advise (NULL, "only one message at a time!"); - return; - } - seq_setcur (mp, mp->hghsel); - } - - if (packsw) { - if (fmsh) { - forkcmd (vec, cmd_name); - return; - } - - if (mp->lowoff > 1 && !(mp = folder_realloc (mp, 1, mp->hghmsg))) - adios (NULL, "unable to allocate folder storage"); - - for (msgnum = mp->lowmsg, hole = 1; msgnum <= mp->hghmsg; msgnum++) - if (does_exist (mp, msgnum)) { - if (msgnum != hole) { - Msgs[hole].m_bboard_id = Msgs[msgnum].m_bboard_id; - Msgs[hole].m_top = Msgs[msgnum].m_top; - Msgs[hole].m_start = Msgs[msgnum].m_start; - Msgs[hole].m_stop = Msgs[msgnum].m_stop; - Msgs[hole].m_scanl = NULL; - if (Msgs[msgnum].m_scanl) { - free (Msgs[msgnum].m_scanl); - Msgs[msgnum].m_scanl = NULL; - } - copy_msg_flags (mp, hole, msgnum); - if (mp->curmsg == msgnum) - seq_setcur (mp, hole); - } - hole++; - } - if (mp->nummsg > 0) { - mp->lowmsg = 1; - mp->hghmsg = hole - 1; - } - mp->msgflags |= MODIFIED; - modified++; - } - -fast: ; - if (fastsw) - printf ("%s\n", fmsh ? fmsh : mp->foldpath); - else { - if (headersw) - printf ("\t\tFolder %*s# of messages (%*srange%*s); cur%*smsg\n", - DMAXFOLDER, "", DMAXFOLDER - 2, "", DMAXFOLDER - 2, "", - DMAXFOLDER - 2, ""); - printf (args ? "%22s " : "%s ", fmsh ? fmsh : mp->foldpath); - - /* check for empty folder */ - if (mp->nummsg == 0) { - printf ("has no messages%*s", - mp->msgflags & OTHERS ? DMAXFOLDER * 2 + 4 : 0, ""); - } else { - printf ("has %*d message%s (%*d-%*d)", - DMAXFOLDER, mp->nummsg, mp->nummsg != 1 ? "s" : "", - DMAXFOLDER, mp->lowmsg, DMAXFOLDER, mp->hghmsg); - if (mp->curmsg >= mp->lowmsg - && mp->curmsg <= mp->hghmsg) - printf ("; cur=%*d", DMAXFOLDER, mp->curmsg); - } - printf (".\n"); - } -} - - -#define FORW_SWITCHES \ - X("annotate", 0, FOANSW) \ - X("noannotate", 0, FONANSW) \ - X("draftfolder +folder", 0, FODFSW) \ - X("draftmessage msg", 0, FODMSW) \ - X("nodraftfolder", 0, FONDFSW) \ - X("editor editor", 0, FOEDTSW) \ - X("noedit", 0, FONEDSW) \ - X("filter filterfile", 0, FOFTRSW) \ - X("form formfile", 0, FOFRMSW) \ - X("format", 5, FOFTSW) \ - X("noformat", 7, FONFTSW) \ - X("inplace", 0, FOINSW) \ - X("noinplace", 0, FONINSW) \ - X("mime", 0, FOMISW) \ - X("nomime", 0, FONMISW) \ - X("whatnowproc program", 0, FOWHTSW) \ - X("nowhatnow", 0, FONWTSW) \ - X("help", 0, FOHELP) \ - -#define X(sw, minchars, id) id, -DEFINE_SWITCH_ENUM(FORW); -#undef X - -#define X(sw, minchars, id) { sw, minchars, id }, -DEFINE_SWITCH_ARRAY(FORW, forwswit); -#undef X - - -void -forwcmd (char **args) -{ - int msgp = 0, vecp = 1, msgnum; - char *cp, *filter = NULL, buf[BUFSIZ]; - char *msgs[MAXARGS], *vec[MAXARGS]; - char *tfile = NULL; - char tmpfil[BUFSIZ]; - - if (fmsh) { - forkcmd (args, cmd_name); - return; - } - - while ((cp = *args++)) { - if (*cp == '-') - switch (smatch (++cp, forwswit)) { - case AMBIGSW: - ambigsw (cp, forwswit); - return; - case UNKWNSW: - fprintf (stderr, "-%s unknown\n", cp); - return; - case FOHELP: - snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name); - print_help (buf, forwswit, 1); - return; - - case FOANSW: /* not implemented */ - case FONANSW: - case FOINSW: - case FONINSW: - case FOMISW: - case FONMISW: - continue; - - case FONDFSW: - case FONEDSW: - case FONWTSW: - vec[vecp++] = --cp; - continue; - - case FOEDTSW: - case FOFRMSW: - case FODFSW: - case FODMSW: - case FOWHTSW: - vec[vecp++] = --cp; - if (!(cp = *args++) || *cp == '-') { - advise (NULL, "missing argument to %s", args[-2]); - return; - } - vec[vecp++] = cp; - continue; - case FOFTRSW: - if (!(filter = *args++) || *filter == '-') { - advise (NULL, "missing argument to %s", args[-2]); - return; - } - continue; - case FOFTSW: - if (access (filter = myfilter, R_OK) == NOTOK) { - advise (filter, "unable to read default filter file"); - return; - } - continue; - case FONFTSW: - filter = NULL; - continue; - } - if (*cp == '+' || *cp == '@') { - advise (NULL, "sorry, no folders allowed!"); - return; - } - else - msgs[msgp++] = cp; - } - - /* foil search of .mh_profile */ - snprintf (buf, sizeof(buf), "%sXXXXXX", invo_name); - - tfile = m_mktemp(buf, NULL, NULL); - if (tfile == NULL) adios("forwcmd", "unable to create temporary file"); - strncpy (tmpfil, tfile, sizeof(tmpfil)); - vec[0] = tmpfil; - - vec[vecp++] = "-file"; - vec[vecp] = NULL; - if (!msgp) - msgs[msgp++] = "cur"; - for (msgnum = 0; msgnum < msgp; msgnum++) - if (!m_convert (mp, msgs[msgnum])) - return; - seq_setprev (mp); - - if (filter) { - strncpy (buf, filter, sizeof(buf)); - if (expand (buf) == NOTOK) - return; - if (access (filter = getcpy (etcpath (buf)), R_OK) == NOTOK) { - advise (filter, "unable to read"); - free (filter); - return; - } - } - forw (cmd_name, filter, vecp, vec); - seq_setcur (mp, mp->hghsel); - if (filter) - free (filter); -} - - -static void -forw (char *proc, char *filter, int vecp, char **vec) -{ - int i, child_id, msgnum, msgcnt; - char tmpfil[BUFSIZ], *args[MAXARGS]; - FILE *out; - char *tfile = NULL; - - tfile = m_mktemp2(NULL, invo_name, NULL, NULL); - if (tfile == NULL) adios("forw", "unable to create temporary file"); - strncpy (tmpfil, tfile, sizeof(tmpfil)); - - interrupted = 0; - if (filter) - switch (child_id = fork ()) { - case NOTOK: - advise ("fork", "unable to"); - return; - - case OK: /* "trust me" */ - if (freopen (tmpfil, "w", stdout) == NULL) { - fprintf (stderr, "unable to create "); - perror (tmpfil); - _exit (1); - } - args[0] = r1bindex (mhlproc, '/'); - i = 1; - args[i++] = "-forwall"; - args[i++] = "-form"; - args[i++] = filter; - for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) - if (is_selected (mp, msgnum)) - args[i++] = getcpy (m_name (msgnum)); - args[i] = NULL; - mhlsbr (i, args, mhl_action); - scan_eom_action ((int (*) ()) 0); - fclose (stdout); - _exit (0); - - default: - if (pidXwait (child_id, NULL)) - interrupted++; - break; - } - else { - if ((out = fopen (tmpfil, "w")) == NULL) { - advise (tmpfil, "unable to create temporary file"); - return; - } - - msgcnt = 1; - for (msgnum = mp->lowsel; - msgnum <= mp->hghsel && !interrupted; - msgnum++) - if (is_selected (mp, msgnum)) { - fprintf (out, "\n\n-------"); - if (msgnum == mp->lowsel) - fprintf (out, " Forwarded Message%s", - mp->numsel > 1 ? "s" : ""); - else - fprintf (out, " Message %d", msgcnt); - fprintf (out, "\n\n"); - copy_digest (msgnum, out); - msgcnt++; - } - - fprintf (out, "\n\n------- End of Forwarded Message%s\n", - mp->numsel > 1 ? "s" : ""); - fclose (out); - } - - fflush (stdout); - if (!interrupted) - switch (child_id = fork ()) { - case NOTOK: - advise ("fork", "unable to"); - break; - - case OK: - closefds (3); - SIGNAL (SIGINT, istat); - SIGNAL (SIGQUIT, qstat); - - vec[vecp++] = tmpfil; - vec[vecp] = NULL; - - execvp (proc, vec); - fprintf (stderr, "unable to exec "); - perror (proc); - _exit (1); - - default: - pidXwait (child_id, NULL); - break; - } - - (void) m_unlink (tmpfil); -} - - -static char *hlpmsg[] = { - "The %s program emulates many of the commands found in the nmh", - "system. Instead of operating on nmh folders, commands to %s concern", - "a single file.", - "", - "To see the list of commands available, just type a ``?'' followed by", - "the RETURN key. To find out what switches each command takes, type", - "the name of the command followed by ``-help''. To leave %s, use the", - "``quit'' command.", - "", - "Although a lot of nmh commands are found in %s, not all are fully", - "implemented. %s will always recognize all legal switches for a", - "given command though, and will let you know when you ask for an", - "option that it is unable to perform.", - "", - "Running %s is fun, but using nmh from your shell is far superior.", - "After you have familiarized yourself with the nmh style by using %s,", - "you should try using nmh from the shell. You can still use %s for", - "message files that aren't in nmh format, such as BBoard files.", - NULL -}; - - -void -helpcmd (char **args) -{ - int i; - NMH_UNUSED (args); - - for (i = 0; hlpmsg[i]; i++) { - printf (hlpmsg[i], invo_name); - putchar ('\n'); - } -} - - -#define MARK_SWITCHES \ - X("add", 0, MADDSW) \ - X("delete", 0, MDELSW) \ - X("list", 0, MLSTSW) \ - X("sequence name", 0, MSEQSW) \ - X("public", 0, MPUBSW) \ - X("nopublic", 0, MNPUBSW) \ - X("zero", 0, MZERSW) \ - X("nozero", 0, MNZERSW) \ - X("help", 0, MHELP) \ - X("debug", -5, MDBUGSW) \ - -#define X(sw, minchars, id) id, -DEFINE_SWITCH_ENUM(MARK); -#undef X - -#define X(sw, minchars, id) { sw, minchars, id }, -DEFINE_SWITCH_ARRAY(MARK, markswit); -#undef X - - -void -markcmd (char **args) -{ - int addsw = 0, deletesw = 0, debugsw = 0; - int listsw = 0, zerosw = 0; - size_t seqp = 0; - int msgp = 0, msgnum; - char *cp, buf[BUFSIZ]; - char *seqs[NUMATTRS + 1], *msgs[MAXARGS]; - - while ((cp = *args++)) { - if (*cp == '-') { - switch (smatch (++cp, markswit)) { - case AMBIGSW: - ambigsw (cp, markswit); - return; - case UNKWNSW: - fprintf (stderr, "-%s unknown\n", cp); - return; - case MHELP: - snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name); - print_help (buf, markswit, 1); - return; - - case MADDSW: - addsw++; - deletesw = listsw = 0; - continue; - case MDELSW: - deletesw++; - addsw = listsw = 0; - continue; - case MLSTSW: - listsw++; - addsw = deletesw = 0; - continue; - - case MSEQSW: - if (!(cp = *args++) || *cp == '-') { - advise (NULL, "missing argument to %s", args[-2]); - return; - } - if (seqp < NUMATTRS) - seqs[seqp++] = cp; - else { - advise (NULL, "only %d sequences allowed!", NUMATTRS); - return; - } - continue; - - case MPUBSW: /* not implemented */ - case MNPUBSW: - continue; - - case MDBUGSW: - debugsw++; - continue; - - case MZERSW: - zerosw++; - continue; - case MNZERSW: - zerosw = 0; - continue; - } - } - if (*cp == '+' || *cp == '@') { - advise (NULL, "sorry, no folders allowed!"); - return; - } else { - msgs[msgp++] = cp; - } - } - - if (!addsw && !deletesw && !listsw) { - if (seqp) - addsw++; - else - if (debugsw) - listsw++; - else { - seqs[seqp++] = "unseen"; - deletesw++; - zerosw = 0; - if (!msgp) - msgs[msgp++] = "all"; - } - } - - if (!msgp) - msgs[msgp++] = listsw ? "all" :"cur"; - for (msgnum = 0; msgnum < msgp; msgnum++) - if (!m_convert (mp, msgs[msgnum])) - return; - - if (debugsw) { - printf ("invo_name=%s mypath=%s defpath=%s\n", - invo_name, mypath, defpath); - printf ("ctxpath=%s context flags=%s\n", - ctxpath, snprintb (buf, sizeof(buf), (unsigned) ctxflags, DBITS)); - printf ("foldpath=%s flags=%s\n", - mp->foldpath, - snprintb (buf, sizeof(buf), (unsigned) mp->msgflags, FBITS)); - printf ("hghmsg=%d lowmsg=%d nummsg=%d curmsg=%d\n", - mp->hghmsg, mp->lowmsg, mp->nummsg, mp->curmsg); - printf ("lowsel=%d hghsel=%d numsel=%d\n", - mp->lowsel, mp->hghsel, mp->numsel); - printf ("lowoff=%d hghoff=%d\n", mp->lowoff, mp->hghoff); - } - - if (seqp == 0 && (addsw || deletesw)) { - advise (NULL, "-%s requires at least one -sequence argument", - addsw ? "add" : "delete"); - return; - } - seqs[seqp] = NULL; - - if (addsw) { - for (seqp = 0; seqs[seqp]; seqp++) - if (!seq_addsel (mp, seqs[seqp], 0, zerosw)) - return; - } - - if (deletesw) { - for (seqp = 0; seqs[seqp]; seqp++) - if (!seq_delsel (mp, seqs[seqp], 0, zerosw)) - return; - } - - /* Listing messages in sequences */ - if (listsw) { - if (seqp) { - /* list the given sequences */ - for (seqp = 0; seqs[seqp]; seqp++) - seq_print (mp, seqs[seqp]); - } else { - /* else list them all */ - seq_printall (mp); - } - - interrupted = 0; - if (debugsw) - for (msgnum = mp->lowsel; - msgnum <= mp->hghsel && !interrupted; - msgnum++) - if (is_selected (mp, msgnum)) { - printf ("%*d: id=%d top=%d start=%ld stop=%ld %s\n", - DMAXFOLDER, - msgnum, - Msgs[msgnum].m_bboard_id, - Msgs[msgnum].m_top, - (long) Msgs[msgnum].m_start, - (long) Msgs[msgnum].m_stop, - snprintb (buf, sizeof(buf), - (unsigned) *bvector_bits (msgstat (mp, - msgnum)), - seq_bits (mp))); - if (Msgs[msgnum].m_scanl) - printf ("%s", Msgs[msgnum].m_scanl); - } - } -} - - -#define MHN_SWITCHES \ - X("auto", 0, MHNAUTOSW) \ - X("noauto", 0, MHNNAUTOSW) \ - X("debug", -5, MHNDEBUGSW) \ - X("form formfile", 4, MHNFORMSW) \ - X("headers", 0, MHNHEADSW) \ - X("noheaders", 0, MHNNHEADSW) \ - X("list", 0, MHNLISTSW) \ - X("nolist", 0, MHNNLISTSW) \ - X("part number", 0, MHNPARTSW) \ - X("realsize", 0, MHNSIZESW) \ - X("norealsize", 0, MHNNSIZESW) \ - X("rfc934mode", 0, MHNRFC934SW) \ - X("norfc934mode", 0, MHNNRFC934SW) \ - X("serialonly", 0, MHNSERIALSW) \ - X("noserialonly", 0, MHNNSERIALSW) \ - X("show", 0, MHNSHOWSW) \ - X("noshow", 0, MHNNSHOWSW) \ - X("store", 0, MHNSTORESW) \ - X("nostore", 0, MHNNSTORESW) \ - X("type content", 0, MHNTYPESW) \ - X("verbose", 0, MHNVERBSW) \ - X("noverbose", 0, MHNNVERBSW) \ - X("help", 0, MHNHELPSW) \ - X("moreproc program", -4, MHNPROGSW) \ - X("nomoreproc", -3, MHNNPROGSW) \ - X("length lines", -4, MHNLENSW) \ - X("width columns", -4, MHNWIDSW) \ - -#define X(sw, minchars, id) id, -DEFINE_SWITCH_ENUM(MHN); -#undef X - -#define X(sw, minchars, id) { sw, minchars, id }, -DEFINE_SWITCH_ARRAY(MHN, mhnswit); -#undef X - - -void -mhncmd (char **args) -{ - int msgp = 0, vecp = 1; - int msgnum; - char *cp, buf[BUFSIZ]; - char *msgs[MAXARGS], *vec[MAXARGS]; - - if (fmsh) { - forkcmd (args, cmd_name); - return; - } - while ((cp = *args++)) { - if (*cp == '-') { - switch (smatch (++cp, mhnswit)) { - case AMBIGSW: - ambigsw (cp, mhnswit); - return; - case UNKWNSW: - fprintf (stderr, "-%s unknown\n", cp); - return; - case MHNHELPSW: - snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name); - print_help (buf, mhnswit, 1); - return; - - case MHNAUTOSW: - case MHNNAUTOSW: - case MHNDEBUGSW: - case MHNHEADSW: - case MHNNHEADSW: - case MHNLISTSW: - case MHNNLISTSW: - case MHNSIZESW: - case MHNNSIZESW: - case MHNRFC934SW: - case MHNNRFC934SW: - case MHNSERIALSW: - case MHNNSERIALSW: - case MHNSHOWSW: - case MHNNSHOWSW: - case MHNSTORESW: - case MHNNSTORESW: - case MHNVERBSW: - case MHNNVERBSW: - case MHNNPROGSW: - vec[vecp++] = --cp; - continue; - - case MHNFORMSW: - case MHNPARTSW: - case MHNTYPESW: - case MHNPROGSW: - case MHNLENSW: - case MHNWIDSW: - vec[vecp++] = --cp; - if (!(cp = *args++) || *cp == '-') { - advise (NULL, "missing argument to %s", args[-2]); - return; - } - vec[vecp++] = cp; - continue; - } - } - if (*cp == '+' || *cp == '@') { - advise (NULL, "sorry, no folders allowed!"); - return; - } else { - msgs[msgp++] = cp; - } - } - - vec[0] = cmd_name; - vec[vecp++] = "-file"; - vec[vecp] = NULL; - if (!msgp) - msgs[msgp++] = "cur"; - for (msgnum = 0; msgnum < msgp; msgnum++) - if (!m_convert (mp, msgs[msgnum])) - return; - seq_setprev (mp); - - interrupted = 0; - for (msgnum = mp->lowsel; - msgnum <= mp->hghsel && !interrupted; - msgnum++) - if (is_selected (mp, msgnum)) - if (process (msgnum, cmd_name, vecp, vec)) { - unset_selected (mp, msgnum); - mp->numsel--; - } - - seq_setcur (mp, mp->hghsel); -} - - -#define PACK_SWITCHES \ - X("file name", 0, PAFISW) \ - X("help", 0, PAHELP) \ - -#define X(sw, minchars, id) id, -DEFINE_SWITCH_ENUM(PACK); -#undef X - -#define X(sw, minchars, id) { sw, minchars, id }, -DEFINE_SWITCH_ARRAY(PACK, packswit); -#undef X - -static int mbx_style = MMDF_FORMAT; - -void -packcmd (char **args) -{ - int msgp = 0, md, msgnum; - char *cp, *file = NULL; - char buf[BUFSIZ], *msgs[MAXARGS]; - struct stat st; - - if (fmsh) { - forkcmd (args, cmd_name); - return; - } - - while ((cp = *args++)) { - if (*cp == '-') - switch (smatch (++cp, packswit)) { - case AMBIGSW: - ambigsw (cp, packswit); - return; - case UNKWNSW: - fprintf (stderr, "-%s unknown\n", cp); - return; - case PAHELP: - snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name); - print_help (buf, packswit, 1); - return; - - case PAFISW: - if (!(file = *args++) || *file == '-') { - advise (NULL, "missing argument to %s", args[-2]); - return; - } - continue; - } - if (*cp == '+' || *cp == '@') { - advise (NULL, "sorry, no folders allowed!"); - return; - } - else - msgs[msgp++] = cp; - } - - if (!file) - file = "./msgbox"; - file = path (file, TFILE); - if (stat (file, &st) == NOTOK) { - if (errno != ENOENT) { - advise (file, "error on file"); - goto done_pack; - } - md = getanswer (cp = concat ("Create file \"", file, "\"? ", NULL)); - free (cp); - if (!md) - goto done_pack; - } - - if (!msgp) - msgs[msgp++] = "all"; - for (msgnum = 0; msgnum < msgp; msgnum++) - if (!m_convert (mp, msgs[msgnum])) - goto done_pack; - seq_setprev (mp); - - if ((md = mbx_open (file, mbx_style, getuid (), getgid (), m_gmprot ())) == NOTOK) { - advise (file, "unable to open"); - goto done_pack; - } - for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) - if (is_selected (mp, msgnum)) - if (pack (file, md, msgnum) == NOTOK) - break; - mbx_close (file, md); - - if (mp->hghsel != mp->curmsg) - seq_setcur (mp, mp->lowsel); - -done_pack: ; - free (file); -} - - -int -pack (char *mailbox, int md, int msgnum) -{ - register FILE *zp; - - if (Msgs[msgnum].m_bboard_id == 0) - readid (msgnum); - - zp = msh_ready (msgnum, 1); - return mbx_write (mailbox, md, zp, Msgs[msgnum].m_bboard_id, - 0L, ftell (zp), Msgs[msgnum].m_stop, 1, 1); -} - - -int -packhak (char **args) -{ - int result; - char *cp, *file = NULL; - - while ((cp = *args++)) { - if (*cp == '-') - switch (smatch (++cp, packswit)) { - case AMBIGSW: - case UNKWNSW: - case PAHELP: - return NOTOK; - - case PAFISW: - if (!(file = *args++) || *file == '-') - return NOTOK; - continue; - } - if (*cp == '+' || *cp == '@') - return NOTOK; - } - - file = path (file ? file : "./msgbox", TFILE); - result = access (file, F_OK) == NOTOK ? OK : NOTOK; - free (file); - - return result; -} - - -#define PICK_SWITCHES \ - X("and", 0, PIANSW) \ - X("or", 0, PIORSW) \ - X("not", 0, PINTSW) \ - X("lbrace", 0, PILBSW) \ - X("rbrace", 0, PIRBSW) \ - X("cc pattern", 0, PICCSW) \ - X("date pattern", 0, PIDASW) \ - X("from pattern", 0, PIFRSW) \ - X("search pattern", 0, PISESW) \ - X("subject pattern", 0, PISUSW) \ - X("to pattern", 0, PITOSW) \ - X("-othercomponent pattern", 15, PIOTSW) \ - X("after date", 0, PIAFSW) \ - X("before date", 0, PIBFSW) \ - X("datefield field", 5, PIDFSW) \ - X("sequence name", 0, PISQSW) \ - X("public", 0, PIPUSW) \ - X("nopublic", 0, PINPUSW) \ - X("zero", 0, PIZRSW) \ - X("nozero", 0, PINZRSW) \ - X("list", 0, PILISW) \ - X("nolist", 0, PINLISW) \ - X("help", 0, PIHELP) \ - -#define X(sw, minchars, id) id, -DEFINE_SWITCH_ENUM(PICK); -#undef X - -#define X(sw, minchars, id) { sw, minchars, id }, -DEFINE_SWITCH_ARRAY(PICK, pickswit); -#undef X - - -void -pickcmd (char **args) -{ - int zerosw = 1, msgp = 0; - size_t seqp = 0; - int vecp = 0, hi, lo, msgnum; - char *cp, buf[BUFSIZ], *msgs[MAXARGS]; - char *seqs[NUMATTRS], *vec[MAXARGS]; - register FILE *zp; - - while ((cp = *args++)) { - if (*cp == '-') { - if (*++cp == '-') { - vec[vecp++] = --cp; - goto pattern; - } - switch (smatch (cp, pickswit)) { - case AMBIGSW: - ambigsw (cp, pickswit); - return; - case UNKWNSW: - fprintf (stderr, "-%s unknown\n", cp); - return; - case PIHELP: - snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name); - print_help (buf, pickswit, 1); - return; - - case PICCSW: - case PIDASW: - case PIFRSW: - case PISUSW: - case PITOSW: - case PIDFSW: - case PIAFSW: - case PIBFSW: - case PISESW: - vec[vecp++] = --cp; -pattern: ; - if (!(cp = *args++)) {/* allow -xyz arguments */ - advise (NULL, "missing argument to %s", args[-2]); - return; - } - vec[vecp++] = cp; - continue; - case PIOTSW: - advise (NULL, "internal error!"); - return; - case PIANSW: - case PIORSW: - case PINTSW: - case PILBSW: - case PIRBSW: - vec[vecp++] = --cp; - continue; - - case PISQSW: - if (!(cp = *args++) || *cp == '-') { - advise (NULL, "missing argument to %s", args[-2]); - return; - } - if (seqp < NUMATTRS) - seqs[seqp++] = cp; - else { - advise (NULL, "only %d sequences allowed!", NUMATTRS); - return; - } - continue; - case PIZRSW: - zerosw++; - continue; - case PINZRSW: - zerosw = 0; - continue; - - case PIPUSW: /* not implemented */ - case PINPUSW: - case PILISW: - case PINLISW: - continue; - } - } - if (*cp == '+' || *cp == '@') { - advise (NULL, "sorry, no folders allowed!"); - return; - } - else - msgs[msgp++] = cp; - } - vec[vecp] = NULL; - - if (!msgp) - msgs[msgp++] = "all"; - for (msgnum = 0; msgnum < msgp; msgnum++) - if (!m_convert (mp, msgs[msgnum])) - return; - seq_setprev (mp); - - interrupted = 0; - if (!pcompile (vec, NULL)) - return; - - lo = mp->lowsel; - hi = mp->hghsel; - - for (msgnum = mp->lowsel; - msgnum <= mp->hghsel && !interrupted; - msgnum++) - if (is_selected (mp, msgnum)) { - zp = msh_ready (msgnum, 1); - if (pmatches (zp, msgnum, fmsh ? 0L : Msgs[msgnum].m_start, - fmsh ? 0L : Msgs[msgnum].m_stop)) { - if (msgnum < lo) - lo = msgnum; - if (msgnum > hi) - hi = msgnum; - } - else { - unset_selected (mp, msgnum); - mp->numsel--; - } - } - - if (interrupted) - return; - - mp->lowsel = lo; - mp->hghsel = hi; - - if (mp->numsel <= 0) { - advise (NULL, "no messages match specification"); - return; - } - - seqs[seqp] = NULL; - for (seqp = 0; seqs[seqp]; seqp++) - if (!seq_addsel (mp, seqs[seqp], 0, zerosw)) - return; - - printf ("%d hit%s\n", mp->numsel, mp->numsel == 1 ? "" : "s"); -} - - -#define REPL_SWITCHES \ - X("annotate", 0, REANSW) \ - X("noannotate", 0, RENANSW) \ - X("cc type", 0, RECCSW) \ - X("nocc type", 0, RENCCSW) \ - X("draftfolder +folder", 0, REDFSW) \ - X("draftmessage msg", 0, REDMSW) \ - X("nodraftfolder", 0, RENDFSW) \ - X("editor editor", 0, REEDTSW) \ - X("noedit", 0, RENEDSW) \ - X("fcc +folder", 0, REFCCSW) \ - X("filter filterfile", 0, REFLTSW) \ - X("form formfile", 0, REFRMSW) \ - X("inplace", 0, REINSW) \ - X("noinplace", 0, RENINSW) \ - X("query", 0, REQUSW) \ - X("noquery", 0, RENQUSW) \ - X("whatnowproc program", 0, REWHTSW) \ - X("nowhatnow", 0, RENWTSW) \ - X("width columns", 0, REWIDSW) \ - X("help", 0, REHELP) \ - -#define X(sw, minchars, id) id, -DEFINE_SWITCH_ENUM(REPL); -#undef X - -#define X(sw, minchars, id) { sw, minchars, id }, -DEFINE_SWITCH_ARRAY(REPL, replswit); -#undef X - - -void -replcmd (char **args) -{ - int vecp = 1; - char *cp, *msg = NULL; - char buf[BUFSIZ], *vec[MAXARGS]; - - if (fmsh) { - forkcmd (args, cmd_name); - return; - } - - while ((cp = *args++)) { - if (*cp == '-') - switch (smatch (++cp, replswit)) { - case AMBIGSW: - ambigsw (cp, replswit); - return; - case UNKWNSW: - fprintf (stderr, "-%s unknown\n", cp); - return; - case REHELP: - snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name); - print_help (buf, replswit, 1); - return; - - case REANSW: /* not implemented */ - case RENANSW: - case REINSW: - case RENINSW: - continue; - - case REQUSW: - case RENQUSW: - case RENDFSW: - case RENEDSW: - case RENWTSW: - vec[vecp++] = --cp; - continue; - - case RECCSW: - case RENCCSW: - case REEDTSW: - case REFCCSW: - case REFLTSW: - case REFRMSW: - case REWIDSW: - case REDFSW: - case REDMSW: - case REWHTSW: - vec[vecp++] = --cp; - if (!(cp = *args++) || *cp == '-') { - advise (NULL, "missing argument to %s", args[-2]); - return; - } - vec[vecp++] = cp; - continue; - } - if (*cp == '+' || *cp == '@') { - advise (NULL, "sorry, no folders allowed!"); - return; - } - else - if (msg) { - advise (NULL, "only one message at a time!"); - return; - } - else - msg = cp; - } - - vec[0] = cmd_name; - vec[vecp++] = "-file"; - vec[vecp] = NULL; - if (!msg) - msg = "cur"; - if (!m_convert (mp, msg)) - return; - seq_setprev (mp); - - if (mp->numsel > 1) { - advise (NULL, "only one message at a time!"); - return; - } - process (mp->hghsel, cmd_name, vecp, vec); - seq_setcur (mp, mp->hghsel); -} - - -#define RMM_SWITCHES \ - X("help", 0, RMHELP) \ - -#define X(sw, minchars, id) id, -DEFINE_SWITCH_ENUM(RMM); -#undef X - -#define X(sw, minchars, id) { sw, minchars, id }, -DEFINE_SWITCH_ARRAY(RMM, rmmswit); -#undef X - - -void -rmmcmd (char **args) -{ - int msgp = 0, msgnum; - char *cp, buf[BUFSIZ], *msgs[MAXARGS]; - - while ((cp = *args++)) { - if (*cp == '-') - switch (smatch (++cp, rmmswit)) { - case AMBIGSW: - ambigsw (cp, rmmswit); - return; - case UNKWNSW: - fprintf (stderr, "-%s unknown\n", cp); - return; - case RMHELP: - snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name); - print_help (buf, rmmswit, 1); - return; - } - if (*cp == '+' || *cp == '@') { - advise (NULL, "sorry, no folders allowed!"); - return; - } - else - msgs[msgp++] = cp; - } - - if (!msgp) - msgs[msgp++] = "cur"; - for (msgnum = 0; msgnum < msgp; msgnum++) - if (!m_convert (mp, msgs[msgnum])) - return; - seq_setprev (mp); - - rmm (); -} - - -static void -rmm (void) -{ - register int msgnum, vecp; - register char *cp; - char buffer[BUFSIZ], *vec[MAXARGS]; - - if (fmsh) { - if (rmmproc) { - if (mp->numsel > MAXARGS - 1) { - advise (NULL, "more than %d messages for %s exec", - MAXARGS - 1, rmmproc); - return; - } - vecp = 0; - for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) - if (is_selected (mp, msgnum)) - vec[vecp++] = getcpy (m_name (msgnum)); - vec[vecp] = NULL; - forkcmd (vec, rmmproc); - for (vecp = 0; vec[vecp]; vecp++) - free (vec[vecp]); - } - else - for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) - if (is_selected (mp, msgnum)) { - strncpy (buffer, m_backup (cp = m_name (msgnum)), sizeof(buffer)); - if (rename (cp, buffer) == NOTOK) - admonish (buffer, "unable to rename %s to", cp); - } - } - - for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) - if (is_selected (mp, msgnum)) { - set_deleted (mp, msgnum); - unset_exists (mp, msgnum); - } - - if ((mp->nummsg -= mp->numsel) <= 0) { - if (fmsh) - admonish (NULL, "no messages remaining in +%s", fmsh); - else - admonish (NULL, "no messages remaining in %s", mp->foldpath); - mp->lowmsg = mp->hghmsg = mp->nummsg = 0; - } - if (mp->lowsel == mp->lowmsg) { - for (msgnum = mp->lowmsg + 1; msgnum <= mp->hghmsg; msgnum++) - if (does_exist (mp, msgnum)) - break; - mp->lowmsg = msgnum; - } - if (mp->hghsel == mp->hghmsg) { - for (msgnum = mp->hghmsg - 1; msgnum >= mp->lowmsg; msgnum--) - if (does_exist (mp, msgnum)) - break; - mp->hghmsg = msgnum; - } - - mp->msgflags |= MODIFIED; - modified++; -} - - -#define SCAN_SWITCHES \ - X("clear", 0, SCCLR) \ - X("noclear", 0, SCNCLR) \ - X("form formatfile", 0, SCFORM) \ - X("format string", 5, SCFMT) \ - X("header", 0, SCHEAD) \ - X("noheader", 0, SCNHEAD) \ - X("width columns", 0, SCWID) \ - X("help", 0, SCHELP) \ - -#define X(sw, minchars, id) id, -DEFINE_SWITCH_ENUM(SCAN); -#undef X - -#define X(sw, minchars, id) { sw, minchars, id }, -DEFINE_SWITCH_ARRAY(SCAN, scanswit); -#undef X - - -void -scancmd (char **args) -{ -#define equiv(a,b) (a ? b && !strcmp (a, b) : !b) - - int clearsw = 0, headersw = 0, width = 0, msgp = 0; - int msgnum, optim, state; - char *cp, *form = NULL, *format = NULL; - char buf[BUFSIZ], *nfs, *msgs[MAXARGS]; - register FILE *zp; - static int s_optim = 0; - static char *s_form = NULL, *s_format = NULL; - - while ((cp = *args++)) { - if (*cp == '-') - switch (smatch (++cp, scanswit)) { - case AMBIGSW: - ambigsw (cp, scanswit); - return; - case UNKWNSW: - fprintf (stderr, "-%s unknown\n", cp); - return; - case SCHELP: - snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name); - print_help (buf, scanswit, 1); - return; - - case SCCLR: - clearsw++; - continue; - case SCNCLR: - clearsw = 0; - continue; - case SCHEAD: - headersw++; - continue; - case SCNHEAD: - headersw = 0; - continue; - case SCFORM: - if (!(form = *args++) || *form == '-') { - advise (NULL, "missing argument to %s", args[-2]); - return; - } - format = NULL; - continue; - case SCFMT: - if (!(format = *args++) || *format == '-') { - advise (NULL, "missing argument to %s", args[-2]); - return; - } - form = NULL; - continue; - case SCWID: - if (!(cp = *args++) || *cp == '-') { - advise (NULL, "missing argument to %s", args[-2]); - return; - } - width = atoi (cp); - continue; - } - if (*cp == '+' || *cp == '@') { - advise (NULL, "sorry, no folders allowed!"); - return; - } - else - msgs[msgp++] = cp; - } - - if (!msgp) - msgs[msgp++] = "all"; - for (msgnum = 0; msgnum < msgp; msgnum++) - if (!m_convert (mp, msgs[msgnum])) - return; - seq_setprev (mp); - - /* Get new format string */ - nfs = new_fs (form, format, FORMAT); - - /* force scansbr to (re)compile format */ - if (scanl) { - free (scanl); - scanl = NULL; - } - - if (s_optim == 0) { - s_optim = optim = 1; - s_form = form ? getcpy (form) : NULL; - s_format = format ? getcpy (format) : NULL; - - } - else - optim = equiv (s_form, form) && equiv (s_format, format); - - interrupted = 0; - for (msgnum = mp->lowsel; - msgnum <= mp->hghsel && !interrupted; - msgnum++) - if (is_selected (mp, msgnum)) { - if (optim && Msgs[msgnum].m_scanl) - printf ("%s", Msgs[msgnum].m_scanl); - else { - - zp = msh_ready (msgnum, 0); - switch (state = scan (zp, msgnum, 0, nfs, width, - msgnum == mp->curmsg, - is_unseen (mp, msgnum), - headersw ? (fmsh ? fmsh : mp->foldpath) : NULL, - fmsh ? 0L : (long) (Msgs[msgnum].m_stop - Msgs[msgnum].m_start), - 1)) { - case SCNMSG: - case SCNENC: - case SCNERR: - if (optim) - Msgs[msgnum].m_scanl = getcpy (scanl); - break; - - default: - advise (NULL, "scan() botch (%d)", state); - return; - - case SCNEOF: - printf ("%*d empty\n", DMAXFOLDER, msgnum); - break; - } - } - headersw = 0; - } - - if (clearsw) - nmh_clear_screen (); -} - - -#define SHOW_SWITCHES \ - X("draft", 5, SHDRAFT) \ - X("form formfile", 4, SHFORM) \ - X("moreproc program", 4, SHPROG) \ - X("nomoreproc", 3, SHNPROG) \ - X("length lines", 4, SHLEN) \ - X("width columns", 4, SHWID) \ - X("showproc program", 4, SHSHOW) \ - X("noshowproc", 3, SHNSHOW) \ - X("header", 4, SHHEAD) \ - X("noheader", 3, SHNHEAD) \ - X("help", 0, SHHELP) \ - -#define X(sw, minchars, id) id, -DEFINE_SWITCH_ENUM(SHOW); -#undef X - -#define X(sw, minchars, id) { sw, minchars, id }, -DEFINE_SWITCH_ARRAY(SHOW, showswit); -#undef X - - -void -showcmd (char **args) -{ - int headersw = 1, nshow = 0, msgp = 0, vecp = 1; - int mhl = 0, seqnum = -1, mode = 0, i, msgnum; - char *cp, *proc = showproc, buf[BUFSIZ]; - char *msgs[MAXARGS], *vec[MAXARGS]; - - if (!strcasecmp (cmd_name, "next")) - mode = 1; - else - if (!strcasecmp (cmd_name, "prev")) - mode = -1; - while ((cp = *args++)) { - if (*cp == '-') - switch (i = smatch (++cp, showswit)) { - case AMBIGSW: - ambigsw (cp, showswit); - return; - case UNKWNSW: - case SHNPROG: - vec[vecp++] = --cp; - continue; - case SHHELP: - snprintf (buf, sizeof(buf), "%s %s[switches] [switches for showproc]", - cmd_name, mode ? NULL : "[msgs] "); - print_help (buf, showswit, 1); - return; - - case SHFORM: - case SHPROG: - case SHLEN: - case SHWID: - vec[vecp++] = --cp; - if (!(cp = *args++) || *cp == '-') { - advise (NULL, "missing argument to %s", args[-2]); - return; - } - vec[vecp++] = cp; - continue; - case SHHEAD: - headersw++; - continue; - case SHNHEAD: - headersw = 0; - continue; - case SHSHOW: - if (!(proc = *args++) || *proc == '-') { - advise (NULL, "missing argument to %s", args[-2]); - return; - } - nshow = 0; - continue; - case SHNSHOW: - nshow++; - continue; - - case SHDRAFT: - advise (NULL, "sorry, -%s not allowed!", showswit[i].sw); - return; - } - if (*cp == '+' || *cp == '@') { - advise (NULL, "sorry, no folders allowed!"); - return; - } - else - if (mode) { - fprintf (stderr, - "usage: %s [switches] [switches for showproc]\n", - cmd_name); - return; - } - else - msgs[msgp++] = cp; - } - vec[vecp] = NULL; - - if (!msgp) - msgs[msgp++] = mode > 0 ? "next" : mode < 0 ? "prev" : "cur"; - for (msgnum = 0; msgnum < msgp; msgnum++) - if (!m_convert (mp, msgs[msgnum])) - return; - seq_setprev (mp); - - if (!nshow) - for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) - if (is_selected (mp, msgnum) && is_nontext (msgnum)) { - proc = showmimeproc; - vec[vecp++] = "-file"; - vec[vecp] = NULL; - goto finish; - } - - if (nshow) - proc = catproc; - else - if (strcmp (showproc, "mhl") == 0) { - proc = mhlproc; - mhl++; - } - -finish: ; - seqnum = seq_getnum (mp, "unseen"); - vec[0] = r1bindex (proc, '/'); - if (mhl) { - msgp = vecp; - for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) - if (is_selected (mp, msgnum)) { - vec[vecp++] = getcpy (m_name (msgnum)); - if (seqnum != -1) - seq_delmsg (mp, "unseen", msgnum); - } - vec[vecp] = NULL; - if (mp->numsel == 1 && headersw) - show (mp->lowsel); - mhlsbr (vecp, vec, mhl_action); - scan_eom_action ((int (*)()) 0); - while (msgp < vecp) - free (vec[msgp++]); - } else { - interrupted = 0; - for (msgnum = mp->lowsel; - msgnum <= mp->hghsel && !interrupted; - msgnum++) - if (is_selected (mp, msgnum)) { - switch (ask (msgnum)) { - case NOTOK: /* QUIT */ - break; - - case OK: /* INTR */ - continue; - - default: - if (mp->numsel == 1 && headersw) - show (msgnum); - if (nshow) - copy_message (msgnum, stdout); - else - process (msgnum, proc, vecp, vec); - - if (seqnum != -1) - seq_delmsg (mp, "unseen", msgnum); - continue; - } - break; - } - } - - seq_setcur (mp, mp->hghsel); -} - - -static void -show (int msgnum) -{ - if (Msgs[msgnum].m_bboard_id == 0) - readid (msgnum); - - printf ("(Message %d", msgnum); - if (Msgs[msgnum].m_bboard_id > 0) - printf (", %s: %d", BBoard_ID, Msgs[msgnum].m_bboard_id); - printf (")\n"); -} - - - -static int -eom_action (int c) -{ - NMH_UNUSED (c); - - return (ftell (mhlfp) >= Msgs[mhlnum].m_stop); -} - - -static FILE * -mhl_action (char *name) -{ - int msgnum; - - if ((msgnum = m_atoi (name)) < mp->lowmsg - || msgnum > mp->hghmsg - || !does_exist (mp, msgnum)) - return NULL; - mhlnum = msgnum; - - mhlfp = msh_ready (msgnum, 1); - if (!fmsh) - scan_eom_action (eom_action); - - return mhlfp; -} - - - -static int -ask (int msgnum) -{ - char buf[BUFSIZ]; - - if (mp->numsel == 1 || !interactive || redirected) - return DONE; - - if (SOprintf ("Press to list \"%d\"...", msgnum)) { - if (mp->lowsel != msgnum) - printf ("\n\n\n"); - printf ("Press to list \"%d\"...", msgnum); - } - fflush (stdout); - buf[0] = 0; - - read (fileno (stdout), buf, sizeof buf); - - if (strchr(buf, '\n') == NULL) - putchar ('\n'); - - if (told_to_quit) { - told_to_quit = interrupted = 0; - return NOTOK; - } - if (interrupted) { - interrupted = 0; - return OK; - } - - return DONE; -} - - -#include - -static int -is_nontext (int msgnum) -{ - int result, state; - char *bp, *dp, *cp; - char buf[BUFSIZ], name[NAMESZ]; - FILE *fp; - - if (Msgs[msgnum].m_flags & MHNCHK) - return (Msgs[msgnum].m_flags & MHNYES); - Msgs[msgnum].m_flags |= MHNCHK; - - fp = msh_ready (msgnum, 1); - - for (;;) { - int bufsz = sizeof buf; - switch (state = m_getfld (&gstate, name, buf, &bufsz, fp)) { - case FLD: - case FLDPLUS: - /* - * Check Content-Type field - */ - if (!strcasecmp (name, TYPE_FIELD)) { - int passno; - char c; - - cp = add (buf, NULL); - while (state == FLDPLUS) { - bufsz = sizeof buf; - state = m_getfld (&gstate, name, buf, &bufsz, fp); - cp = add (buf, cp); - } - bp = cp; - passno = 1; - -again: - for (; isspace ((unsigned char) *bp); bp++) - continue; - if (*bp == '(') { - int i; - - for (bp++, i = 0;;) { - switch (*bp++) { - case '\0': -invalid: - result = 0; - goto out; - case '\\': - if (*bp++ == '\0') - goto invalid; - continue; - case '(': - i++; - /* and fall... */ - default: - continue; - case ')': - if (--i < 0) - break; - continue; - } - break; - } - } - if (passno == 2) { - if (*bp != '/') - goto invalid; - bp++; - passno = 3; - goto again; - } - for (dp = bp; istoken (*dp); dp++) - continue; - c = *dp; - *dp = '\0'; - if (!*bp) - goto invalid; - if (passno > 1) { - if ((result = (strcasecmp (bp, "plain") != 0))) - goto out; - *dp = c; - for (dp++; isspace ((unsigned char) *dp); dp++) - continue; - if (*dp) { - if ((result = !uprf (dp, "charset"))) - goto out; - dp += sizeof "charset" - 1; - while (isspace ((unsigned char) *dp)) - dp++; - if (*dp++ != '=') - goto invalid; - while (isspace ((unsigned char) *dp)) - dp++; - if (*dp == '"') { - if ((bp = strchr(++dp, '"'))) - *bp = '\0'; - } else { - for (bp = dp; *bp; bp++) - if (isspace ((unsigned char) *bp)) { - *bp = '\0'; - break; - } - } - } else { - /* Default character set */ - dp = "US-ASCII"; - } - /* Check the character set */ - result = !check_charset (dp, strlen (dp)); - } else { - if (!(result = (strcasecmp (bp, "text") != 0))) { - *dp = c; - bp = dp; - passno = 2; - goto again; - } - } -out: - free (cp); - if (result) { - Msgs[msgnum].m_flags |= MHNYES; - return result; - } - break; - } - - /* - * Check Content-Transfer-Encoding field - */ - if (!strcasecmp (name, ENCODING_FIELD)) { - cp = add (buf, NULL); - while (state == FLDPLUS) { - bufsz = sizeof buf; - state = m_getfld (&gstate, name, buf, &bufsz, fp); - cp = add (buf, cp); - } - for (bp = cp; isspace ((unsigned char) *bp); bp++) - continue; - for (dp = bp; istoken (*dp); dp++) - continue; - *dp = '\0'; - result = (strcasecmp (bp, "7bit") - && strcasecmp (bp, "8bit") - && strcasecmp (bp, "binary")); - - free (cp); - if (result) { - Msgs[msgnum].m_flags |= MHNYES; - return result; - } - break; - } - - /* - * Just skip the rest of this header - * field and go to next one. - */ - while (state == FLDPLUS) { - bufsz = sizeof buf; - state = m_getfld (&gstate, name, buf, &bufsz, fp); - } - break; - - /* - * We've passed the message header, - * so message is just text. - */ - default: - return 0; - } - } -} - - -#define SORT_SWITCHES \ - X("datefield field", 0, SODATE) \ - X("textfield field", 0, SOSUBJ) \ - X("notextfield", 0, SONSUBJ) \ - X("limit days", 0, SOLIMT) \ - X("nolimit", 0, SONLIMT) \ - X("verbose", 0, SOVERB) \ - X("noverbose", 0, SONVERB) \ - X("help", 0, SOHELP) \ - -#define X(sw, minchars, id) id, -DEFINE_SWITCH_ENUM(SORT); -#undef X - -#define X(sw, minchars, id) { sw, minchars, id }, -DEFINE_SWITCH_ARRAY(SORT, sortswit); -#undef X - - -void -sortcmd (char **args) -{ - int msgp = 0, msgnum; - char *cp, *datesw = NULL, *subjsw = NULL; - char buf[BUFSIZ], *msgs[MAXARGS]; - struct tws tb; - - if (fmsh) { - forkcmd (args, cmd_name); - return; - } - - while ((cp = *args++)) { - if (*cp == '-') - switch (smatch (++cp, sortswit)) { - case AMBIGSW: - ambigsw (cp, sortswit); - return; - case UNKWNSW: - fprintf (stderr, "-%s unknown\n", cp); - return; - case SOHELP: - snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name); - print_help (buf, sortswit, 1); - return; - - case SODATE: - if (datesw) { - advise (NULL, "only one date field at a time!"); - return; - } - if (!(datesw = *args++) || *datesw == '-') { - advise (NULL, "missing argument to %s", args[-2]); - return; - } - continue; - - case SOSUBJ: - if (subjsw) { - advise (NULL, "only one text field at a time!"); - return; - } - if (!(subjsw = *args++) || *subjsw == '-') { - advise (NULL, "missing argument to %s", args[-2]); - return; - } - continue; - case SONSUBJ: - subjsw = (char *)0; - continue; - - case SOLIMT: /* too hard */ - if (!(cp = *args++) || *cp == '-') { - advise (NULL, "missing argument to %s", args[-2]); - return; - } - case SONLIMT: - case SOVERB: /* not implemented */ - case SONVERB: - continue; - } - if (*cp == '+' || *cp == '@') { - advise (NULL, "sorry, no folders allowed!"); - return; - } - else - msgs[msgp++] = cp; - } - - if (!msgp) - msgs[msgp++] = "all"; - if (!datesw) - datesw = "Date"; - for (msgnum = 0; msgnum < msgp; msgnum++) - if (!m_convert (mp, msgs[msgnum])) - return; - seq_setprev (mp); - - twscopy (&tb, dlocaltimenow ()); - - for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { - if (Msgs[msgnum].m_scanl) { - free (Msgs[msgnum].m_scanl); - Msgs[msgnum].m_scanl = NULL; - } - if (is_selected (mp, msgnum)) { - if (get_fields (datesw, subjsw, msgnum, &Msgs[msgnum])) - twscopy (&Msgs[msgnum].m_tb, - msgnum != mp->lowsel ? &Msgs[msgnum - 1].m_tb : &tb); - } - else /* m_scaln is already NULL */ - twscopy (&Msgs[msgnum].m_tb, &tb); - Msgs[msgnum].m_stats = bvector_create (0); - bvector_copy (Msgs[msgnum].m_stats, msgstat (mp, msgnum)); - if (mp->curmsg == msgnum) - bvector_set (Msgs[msgnum].m_stats, CUR); - } - - qsort ((char *) &Msgs[mp->lowsel], mp->hghsel - mp->lowsel + 1, - sizeof(struct Msg), (qsort_comp) (subjsw ? subsort : msgsort)); - - for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { - if (subjsw && Msgs[msgnum].m_scanl) { - free (Msgs[msgnum].m_scanl); /* from subjsort */ - Msgs[msgnum].m_scanl = NULL; - } - bvector_clear (Msgs[msgnum].m_stats, CUR); - bvector_copy (msgstat (mp, msgnum), Msgs[msgnum].m_stats); - if (bvector_at (Msgs[msgnum].m_stats, CUR)) - seq_setcur (mp, msgnum); - } - - mp->msgflags |= MODIFIED; - modified++; -} - - -/* - * get_fields - parse message, and get date and subject if needed. - * We'll use the msgp->m_tb tws struct for the date, and overload - * the msgp->m_scanl field with our subject string. - */ -static int -get_fields (char *datesw, char *subjsw, int msgnum, struct Msg *msgp) -{ - int state, gotdate = 0; - char *bp, buf[BUFSIZ], name[NAMESZ]; - struct tws *tw = (struct tws *) 0; - register FILE *zp; - - zp = msh_ready (msgnum, 0); - - for (;;) { - int bufsz = sizeof buf; - switch (state = m_getfld (&gstate, name, buf, &bufsz, zp)) { - case FLD: - case FLDPLUS: - if (!strcasecmp (name, datesw)) { - bp = getcpy (buf); - while (state == FLDPLUS) { - bufsz = sizeof buf; - state = m_getfld (&gstate, name, buf, &bufsz, zp); - bp = add (buf, bp); - } - if ((tw = dparsetime (bp)) == NULL) - admonish (NULL, - "unable to parse %s field in message %d", - datesw, msgnum); - else - twscopy (&(msgp->m_tb), tw); - free (bp); - if (!subjsw) /* not using this, or already done */ - break; /* all done! */ - gotdate++; - } - else if (subjsw && !strcasecmp(name, subjsw)) { - bp = getcpy (buf); - while (state == FLDPLUS) { - bufsz = sizeof buf; - state = m_getfld (&gstate, name, buf, &bufsz, zp); - bp = add (buf, bp); - } - msgp->m_scanl = sosmash(subjsw, bp); - if (gotdate) - break; /* date done so we're done */ - else - subjsw = (char *)0;/* subject done, need date */ - } else { - while (state == FLDPLUS) { /* flush this one */ - bufsz = sizeof buf; - state = m_getfld (&gstate, name, buf, &bufsz, zp); - } - } - continue; - - case BODY: - case FILEEOF: - break; - - case LENERR: - case FMTERR: - admonish (NULL, "format error in message %d", msgnum); - if (msgp->m_scanl) { /* this might need free'd */ - free (msgp->m_scanl); /* probably can't use subj anyway */ - msgp->m_scanl = NULL; - } - return NOTOK; - - default: - adios (NULL, "internal error -- you lose"); - } - break; - } - if (tw) - return OK; /* not an error if subj not found */ - - admonish (NULL, "no %s field in message %d", datesw, msgnum); - return NOTOK; /* NOTOK means use some other date */ -} - - -/* - * sort routines - */ - -static int -msgsort (struct Msg *a, struct Msg *b) -{ - return twsort (&a->m_tb, &b->m_tb); -} - - -static int -subsort (struct Msg *a, struct Msg *b) -{ - register int i; - - if (a->m_scanl && b->m_scanl) - if ((i = strcmp (a->m_scanl, b->m_scanl))) - return (i); - - return twsort (&a->m_tb, &b->m_tb); -} - - -/* - * try to make the subject "canonical": delete leading "re:", everything - * but letters & smash letters to lower case. - */ -static char * -sosmash (char *subj, char *s) -{ - register char *cp, *dp; - register unsigned char c; - - if (s) { - cp = s; - dp = s; /* dst pointer */ - if (!strcasecmp (subj, "subject")) - while ((c = *cp)) { - if (! isspace(c)) { - if(uprf(cp, "re:")) - cp += 2; - else { - if (isalnum(c)) - *dp++ = isupper(c) ? tolower(c) : c; - break; - } - } - cp++; - } - while ((c = *cp++)) { - if (isalnum(c)) - *dp++ = isupper(c) ? tolower(c) : c; - - } - *dp = '\0'; - } - return s; -} - - -static int -process (int msgnum, char *proc, int vecp, char **vec) -{ - int child_id, status; - char tmpfil[BUFSIZ]; - FILE *out; - char *cp; - - if (fmsh) { - strncpy (tmpfil, m_name (msgnum), sizeof(tmpfil)); - context_del (pfolder); - context_replace (pfolder, fmsh);/* update current folder */ - seq_save (mp); - context_save (); /* save the context file */ - goto ready; - } - - cp = m_mktemp(invo_name, NULL, &out); - if (cp == NULL) { - /* Try again, but try to create under /tmp */ - int olderr = errno; - cp = m_mktemp2(NULL, invo_name, NULL, &out); - if (cp == NULL) { - errno = olderr; - advise (NULL, "unable to create temporary file"); - return NOTOK; - } - } - copy_message (msgnum, out); - fclose (out); - strncpy(tmpfil, cp, sizeof(tmpfil)); - -ready: ; - fflush (stdout); - switch (child_id = fork ()) { - case NOTOK: - advise ("fork", "unable to"); - status = NOTOK; - break; - - case OK: - closefds (3); - SIGNAL (SIGINT, istat); - SIGNAL (SIGQUIT, qstat); - - vec[vecp++] = tmpfil; - vec[vecp] = NULL; - - execvp (proc, vec); - fprintf (stderr, "unable to exec "); - perror (proc); - _exit (1); - - default: - status = pidXwait (child_id, NULL); - break; - } - - if (!fmsh) - (void) m_unlink (tmpfil); - return status; -} - - -static void -copy_message (int msgnum, FILE *out) -{ - long pos; - static char buffer[BUFSIZ]; - register FILE *zp; - - zp = msh_ready (msgnum, 1); - if (fmsh) { - while (fgets (buffer, sizeof buffer, zp) != NULL) { - fputs (buffer, out); - if (interrupted && out == stdout) - break; - } - } - else { - pos = ftell (zp); - while (fgets (buffer, sizeof buffer, zp) != NULL - && pos < Msgs[msgnum].m_stop) { - fputs (buffer, out); - pos += (long) strlen (buffer); - if (interrupted && out == stdout) - break; - } - } -} - - -static void -copy_digest (int msgnum, FILE *out) -{ - char c; - long pos = 0L; - static char buffer[BUFSIZ]; - register FILE *zp; - - c = '\n'; - zp = msh_ready (msgnum, 1); - if (!fmsh) - pos = ftell (zp); - while (fgets (buffer, sizeof buffer, zp) != NULL - && !fmsh && pos < Msgs[msgnum].m_stop) { - if (c == '\n' && *buffer == '-') - fputc (' ', out); - fputs (buffer, out); - c = buffer[strlen (buffer) - 1]; - if (!fmsh) - pos += (long) strlen (buffer); - if (interrupted && out == stdout) - break; - } -} diff --git a/uip/vmhsbr.c b/uip/vmhsbr.c deleted file mode 100644 index 4c0c8c18..00000000 --- a/uip/vmhsbr.c +++ /dev/null @@ -1,228 +0,0 @@ - -/* - * vmhsbr.c -- routines to help vmh along - * - * This code is Copyright (c) 2002, by the authors of nmh. See the - * COPYRIGHT file in the root directory of the nmh distribution for - * complete copyright information. - */ - -/* - * TODO (for vrsn 2): - * INI: include width of windows - */ - -#include -#include -#include - -static char *types[] = { - "OK", - "INI", "ACK", "ERR", "CMD", "QRY", "TTY", "WIN", "DATA", "EOF", "FIN", - "XXX", NULL -}; - -static FILE *fp = NULL; - -static int PEERrfd = NOTOK; -static int PEERwfd = NOTOK; - -/* - * static prototypes - */ -static int rclose (struct record *, char *, ...); - - -int -rcinit (int rfd, int wfd) -{ - char *cp, buffer[BUFSIZ]; - - PEERrfd = rfd; - PEERwfd = wfd; - - if ((cp = getenv ("MHVDEBUG")) && *cp) { - snprintf (buffer, sizeof(buffer), "%s.out", invo_name); - if ((fp = fopen (buffer, "w"))) { - fseek (fp, 0L, SEEK_END); - fprintf (fp, "%d: rcinit (%d, %d)\n", (int) getpid(), rfd, wfd); - fflush (fp); - } - } - - return OK; -} - - -int -rcdone (void) -{ - if (PEERrfd != NOTOK) - close (PEERrfd); - if (PEERwfd != NOTOK) - close (PEERwfd); - - if (fp) { - fclose (fp); - fp = NULL; - } - return OK; -} - - -int -rc2rc (char code, int len, char *data, struct record *rc) -{ - if (rc2peer (code, len, data) == NOTOK) - return NOTOK; - - return peer2rc (rc); -} - - -int -str2rc (char code, char *str, struct record *rc) -{ - return rc2rc (code, str ? strlen (str) : 0, str, rc); -} - - -int -peer2rc (struct record *rc) -{ - if (rc->rc_data) - free (rc->rc_data); - - if (read (PEERrfd, (char *) rc_head (rc), RHSIZE (rc)) != RHSIZE (rc)) - return rclose (rc, "read from peer lost(1)"); - if (rc->rc_len) { - rc->rc_data = mh_xmalloc ((unsigned) rc->rc_len + 1); - if (read (PEERrfd, rc->rc_data, rc->rc_len) != rc->rc_len) - return rclose (rc, "read from peer lost(2)"); - rc->rc_data[rc->rc_len] = 0; - } - else - rc->rc_data = NULL; - - if (fp) { - fseek (fp, 0L, SEEK_END); - fprintf (fp, "%d: <--- %s %d: \"%*.*s\"\n", (int) getpid(), - types[(unsigned char)rc->rc_type], rc->rc_len, - rc->rc_len, rc->rc_len, rc->rc_data); - fflush (fp); - } - - return rc->rc_type; -} - - -int -rc2peer (char code, int len, char *data) -{ - struct record rcs; - register struct record *rc = &rcs; - - rc->rc_type = code; - rc->rc_len = len; - - if (fp) { - fseek (fp, 0L, SEEK_END); - fprintf (fp, "%d: ---> %s %d: \"%*.*s\"\n", (int) getpid(), - types[(unsigned char)rc->rc_type], rc->rc_len, - rc->rc_len, rc->rc_len, data); - fflush (fp); - } - - if (write (PEERwfd, (char *) rc_head (rc), RHSIZE (rc)) != RHSIZE (rc)) - return rclose (rc, "write to peer lost(1)"); - - if (rc->rc_len) - if (write (PEERwfd, data, rc->rc_len) != rc->rc_len) - return rclose (rc, "write to peer lost(2)"); - - return OK; -} - - -int -str2peer (char code, char *str) -{ - return rc2peer (code, str ? strlen (str) : 0, str); -} - - -int -fmt2peer (char code, char *fmt, ...) -{ - int return_value; - va_list ap; - - va_start(ap, fmt); - return_value = verr2peer (code, NULL, fmt, ap); - va_end(ap); - return return_value; -} - - -int -err2peer (char code, char *what, char *fmt, ...) -{ - int return_value; - va_list ap; - - va_start(ap, fmt); - return_value = verr2peer(code, what, fmt, ap); - va_end(ap); - return return_value; /* This routine returned garbage before 1999-07-15. */ -} - - -int -verr2peer (char code, char *what, char *fmt, va_list ap) -{ - int eindex = errno; - int len, buflen; - char *bp, *s, buffer[BUFSIZ * 2]; - - /* Get buffer ready to go */ - bp = buffer; - buflen = sizeof(buffer); - - vsnprintf (bp, buflen, fmt, ap); - len = strlen (bp); - bp += len; - buflen -= len; - - if (what) { - if (*what) { - snprintf (bp, buflen, " %s: ", what); - len = strlen (bp); - bp += len; - buflen -= len; - } - if ((s = strerror (eindex))) - strncpy (bp, s, buflen); - else - snprintf (bp, buflen, "unknown error %d", eindex); - len = strlen (bp); - bp += len; - buflen -= len; - } - - return rc2peer (code, bp - buffer, buffer); -} - - -static int -rclose (struct record *rc, char *fmt, ...) -{ - va_list ap; - static char buffer[BUFSIZ * 2]; - - va_start(ap, fmt); - vsnprintf (buffer, sizeof(buffer), fmt, ap); - va_end(ap); - - rc->rc_len = strlen (rc->rc_data = getcpy (buffer)); - return (rc->rc_type = RC_XXX); -}