/sbr/dtimep.c
/cscope.files
/cscope.out
+/cscope.in.out
+/cscope.po.out
# Removed by distclean:
.deps/
/test/fakepop
/test/getfullname
/test/getfqdn
+/test/getcwidth
# Removed by mostlyclean:
*.o
test/format/test-dp test/format/test-fmtdump \
test/format/test-localmbox test/format/test-myname \
test/format/test-myhost test/format/test-mymbox \
+ test/format/test-rightjustify \
test/forw/test-forw-digest test/forw/test-forw-format \
test/inc/test-deb359167 test/inc/test-eom-align \
test/inc/test-inc-scanout test/inc/test-msgchk \
test/mhlist/test-mhlist test/mhmail/test-mhmail \
test/mhparam/test-mhparam test/mhpath/test-mhpath \
test/mhshow/test-cte-binary test/mhshow/test-qp \
- test/mhshow/test-subpart test/mhstore/test-mhstore \
- test/new/test-basic \
+ test/mhshow/test-subpart test/mhshow/test-msg-buffer-boundaries \
+ test/mhstore/test-mhstore test/new/test-basic \
test/pick/test-pick test/pick/test-stderr \
test/post/test-post-aliases test/post/test-post-basic \
test/post/test-post-multiple test/post/test-post-bcc \
test/repl/test-multicomp test/repl/test-repl \
test/scan/test-scan test/scan/test-scan-multibyte \
test/sequences/test-flist test/sequences/test-mark \
+ test/sequences/test-out-of-range \
test/slocal/test-slocal \
test/whatnow/test-attach-detach test/whatnow/test-cd \
test/whatnow/test-ls test/whom/test-whom \
test/cleanup ## The "cleanup" test should always be last.
check_SCRIPTS = test/common.sh
-check_PROGRAMS = test/getfullname test/getfqdn test/fakepop test/fakesmtp
+check_PROGRAMS = test/getfullname test/getfqdn test/fakepop test/fakesmtp \
+ test/getcwidth
DISTCHECK_CONFIGURE_FLAGS = DISABLE_SETGID_MAIL=1
##
##
## Stuff that should be cleaned via "make maintainer-clean"
##
-MAINTAINERCLEANFILES = cscope.files cscope.out
+MAINTAINERCLEANFILES = cscope.files cscope.out cscope.in.out cscope.po.out
##
## And our own superclean, to get everything left by maintainer-clean.
man/sendfiles.1 man/show.1 man/slocal.1 man/sortm.1 man/unseen.1 \
man/whatnow.1 man/whom.1
+##
+## Sources for our man pages
+##
+man_SRCS = man/ali.man man/anno.man man/ap.man man/burst.man man/comp.man \
+ man/conflict.man man/dist.man man/dp.man man/flist.man \
+ man/flists.man man/fmtdump.man man/fnext.man man/folder.man \
+ man/folders.man man/forw.man man/fprev.man man/inc.man \
+ man/install-mh.man man/mark.man man/mh-alias.man \
+ man/mh-chart-gen.sh man/mh-draft.man man/mh-format.man \
+ man/mh-mail.man man/mh-profile.man man/mh_profile.man \
+ man/mh-sequence.man man/mh-tailor.man man/mhbuild.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/msgchk.man \
+ man/msh.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 \
+ man/rmf.man man/rmm.man man/scan.man man/send.man \
+ man/sendfiles.man man/show.man man/slocal.man man/sortm.man \
+ man/unseen.man man/whatnow.man man/whom.man
+
##
## Files we need to include in the distribution which aren't found by
## Automake using the automatic rules
etc/mhn.defaults.sh etc/sendfiles $(MHNSEARCHPROG) DATE MACHINES \
docs/ChangeLog_MH-3_to_MH-6.6 \
docs/ChangeLog_MH-6.7.0_to_MH-6.8.4.html \
- man/ali.man man/anno.man man/ap.man man/burst.man man/comp.man \
- man/conflict.man man/dist.man man/dp.man man/flist.man \
- man/flists.man man/fmtdump.man man/fnext.man man/folder.man \
- man/folders.man man/forw.man man/fprev.man man/inc.man \
- man/install-mh.man man/mark.man man/mh-alias.man \
- man/mh-chart-gen.sh man/mh-draft.man man/mh-format.man \
- man/mh-mail.man man/mh-profile.man man/mh_profile.man \
- man/mh-sequence.man man/mh-tailor.man man/mhbuild.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/msgchk.man \
- man/msh.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 \
- man/rmf.man man/rmm.man man/scan.man man/send.man \
- man/sendfiles.man man/show.man man/slocal.man man/sortm.man \
- man/unseen.man man/whatnow.man man/whom.man \
test/README test/fakesendmail $(TESTS) test/inc/deb359167.mbox \
test/inc/fromline.txt test/inc/msgheader.txt test/inc/filler.txt \
test/inc/md5sums test/mhmail/attachment.txt \
test/post/test-post-common.sh uip/mhmail \
- SPECS/nmh.spec SPECS/build-nmh-cygwin
+ SPECS/nmh.spec SPECS/build-nmh-cygwin $(man_SRCS)
##
## These are all of the definitions for each of the programs listed above.
uip_mhtest_LDADD = $(LDADD) $(TERMLIB)
uip_post_SOURCES = uip/post.c uip/aliasbr.c
-uip_post_LDADD = mts/libmts.a $(LDADD) $(SASLLIB)
+uip_post_LDADD = mts/libmts.a $(LDADD) $(SASLLIB) $(TLSLIB)
uip_rcvdist_SOURCES = uip/rcvdist.c uip/distsbr.c
uip_rcvdist_LDADD = $(LDADD) $(ICONVLIB)
##
## Our rules to build our internal libraries (libmh.a, libmts.a)
##
-sbr_libmh_a_SOURCES = sbr/addrsbr.c sbr/ambigsw.c sbr/atooi.c sbr/base64.c \
+sbr_libmh_a_SOURCES = sbr/addrsbr.c sbr/ambigsw.c sbr/atooi.c sbr/arglist.c \
+ sbr/base64.c \
sbr/brkstring.c sbr/check_charset.c sbr/client.c \
sbr/closefds.c sbr/concat.c sbr/context_del.c \
sbr/context_find.c sbr/context_foil.c sbr/context_read.c \
sbr/folder_free.c sbr/folder_pack.c \
sbr/folder_read.c sbr/folder_realloc.c sbr/gans.c \
sbr/getans.c sbr/getanswer.c sbr/getarguments.c \
- sbr/getcpy.c sbr/getfolder.c sbr/getpass.c \
+ sbr/getcpy.c sbr/geteditor.c sbr/getfolder.c \
+ sbr/getpass.c \
sbr/fmt_addr.c sbr/fmt_compile.c sbr/fmt_new.c \
sbr/fmt_rfc2047.c sbr/fmt_scan.c sbr/lock_file.c \
sbr/m_atoi.c sbr/m_backup.c sbr/m_convert.c \
sbr/showfile.c sbr/signals.c sbr/smatch.c \
sbr/snprintb.c sbr/ssequal.c sbr/strcasecmp.c \
sbr/strindex.c sbr/trimcpy.c sbr/uprf.c sbr/vfgets.c \
- sbr/fmt_def.c sbr/m_msgdef.c sbr/mf.c sbr/utils.c \
+ sbr/fmt_def.c sbr/mf.c sbr/utils.c \
sbr/m_mktemp.c sbr/getansreadline.c config/config.c \
config/version.c
sbr_libmh_a_CPPFLAGS = -I./sbr -DNMHETCDIR='"$(sysconfdir)"' \
-DMAILSPOOL='"$(mailspool)"' \
-DSENDMAILPATH='"$(sendmailpath)"' -DNMHBINDIR='"$(bindir)"' \
- -DNMHLIBDIR='"$(libdir)"' \
- -DDEFAULT_EDITOR='"$(editorpath)"' \
- -DDEFAULT_PAGER='"$(pagerpath)"'
+ -DNMHLIBDIR='"$(libdir)"'
sbr_libdtimep_a_SOURCES = sbr/dtimep.l
sbr_libdtimep_a_CFLAGS = $(sbr_libmh_a_CPPFLAGS) \
@echo 's,%mandir%,$(mandir),g' >> $@
@echo 's,%mailspool%,$(mailspool),g' >> $@
@echo 's,%sendmailpath%,$(sendmailpath),g' >> $@
- @echo 's,%default_editor%,$(editorpath),g' >> $@
- @echo 's,%default_pager%,$(pagerpath),g' >> $@
@echo 's,%manext1%,$(manext1),g' >> $@
@echo 's,%manext5%,$(manext5),g' >> $@
@echo 's,%manext7%,$(manext7),g' >> $@
@echo '/%mhl_reply%/r $(top_srcdir)/etc/mhl.reply' >> $@
@echo ' s,%mhl_reply%,,g' >> $@
-man/mh-chart.man:
+man/mh-chart.man: $(man_SRCS)
$(srcdir)/man/mh-chart-gen.sh > $@
.man.$(manext1):
-ba SPECS/nmh.spec
.PHONY: rpm
-##
-## A target to build information needed by cscope
-##
-cscope:
- echo "-I $(srcdir)/h -I $(srcdir)/sbr -I $(srcdir)/uip -I $(srcdir)/mts/smtp" > cscope.files
- find $(srcdir) \( -name docs -prune \) -o \( -name \*.c -o -name \*.l \) -print | grep -v dtimep.c >> cscope.files
-.PHONY: cscope
-
##
## Use GNU gcov to find the coverage of the test suite.
*/
struct swit anoyes[] = {
- { "no", 0 },
- { "yes", 0 },
- { NULL, 0 }
+ { "no", 0, 0 },
+ { "yes", 0, 1 },
+ { NULL, 0, 0 }
};
/*
char *whomproc = nmhbindir (/whom);
-/*
- * This is the editor invoked by the various message
- * composition programs. It SHOULD be a full screen
- * editor, such as vi or emacs, but any editor will work.
- */
-
-char *defaulteditor = DEFAULT_EDITOR;
-
/*
* This is the global nmh alias file. It is somewhat obsolete, since
* global aliases should be handled by the Mail Transport Agent (MTA).
dnl
dnl Move this up a bit
-AC_PREREQ([2.61])
+AC_PREREQ([2.68])
AC_INIT([nmh], m4_normalize(m4_include([VERSION])), [nmh-workers@nongnu.org])
AC_CONFIG_SRCDIR([h/nmh.h])
AC_CONFIG_HEADER([config.h])
-AM_INIT_AUTOMAKE([-Wall foreign subdir-objects])
+AM_INIT_AUTOMAKE([-Wall color-tests foreign serial-tests subdir-objects 1.12])
AC_CANONICAL_HOST
dnl Do you want to debug nmh?
AC_ARG_ENABLE([debug],
AS_HELP_STRING([--enable-debug],[enable nmh code debugging]))
-dnl The old redundant --enable-nmh-debug is deprecated and undocumented.
-AS_IF([test x"$enable_nmh_debug" = x"yes"], [enable_debug=yes])
dnl Do you want to disable use of locale functions
AH_TEMPLATE([LOCALE],
AC_DEFINE([TLS_SUPPORT], [1], [Support TLS for session encryption.])dnl
tls_support=yes],[tls_support=no])
-dnl What should be the default editor?
-AC_ARG_WITH([editor],
- AS_HELP_STRING([--with-editor=EDITOR],[specify the default editor]))
-
-AS_IF([test -n "$with_editor"], [editorpath="$with_editor"])
-
dnl Set the backup prefix
AC_ARG_WITH([hash-backup],
AS_HELP_STRING([--with-hash-backup],[use # as the backup prefix (default: ,)]))
[freebsd*|openbsd*|darwin*], [default_locktype="flock"; default_locking=FLOCK_LOCKING],
[default_locktype="dot"; default_locking=DOT_LOCKING])
-AC_ARG_WITH(locking,
+AC_ARG_WITH([locking],
AS_HELP_STRING([--with-locking=@<:@dot|fcntl|flock|lockf@:>@],
[specify the file locking method]))
-if test x"$with_locking" = x"dot"; then
- LOCKTYPE="dot"
- AC_DEFINE(DOT_LOCKING, 1, [Define to use dot based file locking.])dnl
-elif test x"$with_locking" = x"flock"; then
- LOCKTYPE="flock"
- AC_DEFINE(FLOCK_LOCKING, 1, [Define to use flock() based locking.])dnl
-elif test x"$with_locking" = x"lockf"; then
- LOCKTYPE="lockf"
- AC_DEFINE(LOCKF_LOCKING, 1, [Define to use lockf() based locking.])dnl
-elif test x"$with_locking" = x"fcntl"; then
- LOCKTYPE="fcntl"
- AC_DEFINE(FCNTL_LOCKING, 1, [Define to use fnctl() based locking.])dnl
-else
- LOCKTYPE="$default_locktype"
- AC_DEFINE_UNQUOTED($default_locking, 1)dnl
-fi
+AS_IF([test x"$with_locking" = x"dot"],
+ [LOCKTYPE="dot"
+ AC_DEFINE([DOT_LOCKING], [1], [Define to use dot based file locking.])],
+ [test x"$with_locking" = x"flock"],
+ [LOCKTYPE="flock"
+ AC_DEFINE([FLOCK_LOCKING], [1], [Define to use flock() based locking.])],
+ [test x"$with_locking" = x"lockf"],
+ [LOCKTYPE="lockf"
+ AC_DEFINE([LOCKF_LOCKING], [1], [Define to use lockf() based locking.])],
+ [test x"$with_locking" = x"fcntl"],
+ [LOCKTYPE="fcntl"
+ AC_DEFINE([FCNTL_LOCKING], [1], [Define to use fnctl() based locking.])],
+ [LOCKTYPE="$default_locktype"
+ AC_DEFINE_UNQUOTED([$default_locking], [1])])
dnl Should we use a locking directory?
AC_ARG_ENABLE([lockdir],
[MTS="smtp"])
AC_SUBST([MTS])dnl
-dnl What should be the default pager?
-AC_ARG_WITH([pager],
- AS_HELP_STRING([--with-pager=PAGER],[specify the default pager]))
-
-AS_IF([test -n "$with_pager"], [pagerpath="$with_pager"])
-
-dnl If a pager is not explicitly specified, then look for one.
-dnl Fall back to `cat', to avoid catastrophic failure of
-dnl `mhshow', et al., if pagerpath is set to `no'.
-if test -z "$pagerpath"; then
- pathtmp=/usr/bin:/bin:/usr/ucb:/usr/local/bin
- AC_PATH_PROGS([pagerpath], [more less most cat], [no], [$pathtmp])
-fi
-AC_SUBST(pagerpath)dnl
-
dnl What should be the default mail server(s)?
-AC_ARG_WITH(smtpservers,
- AS_HELP_STRING([--with-smtpservers='SMTPSERVER1@<:@ SMTPSERVER2...@:>@'],
- [specify the default SMTP server(s) @<:@localhost@:>@]))
+AC_ARG_WITH([smtpservers],
+ [AS_HELP_STRING([--with-smtpservers='SMTPSERVER1@<:@ SMTPSERVER2...@:>@'],
+ [specify the default SMTP server(s) @<:@localhost@:>@])])
AS_IF([test -n "$with_smtpservers"], [smtpservers="$with_smtpservers"],
[smtpservers="localhost"])
AC_SUBST([smtpservers])dnl
|| CPPFLAGS="$CPPFLAGS -Wunused-macros"
DISABLE_UNUSED_MACROS_WARNING=-Wno-unused-macros
fi
-AC_SUBST(DISABLE_UNUSED_MACROS_WARNING)dnl
+AC_SUBST([DISABLE_UNUSED_MACROS_WARNING])dnl
AC_CACHE_CHECK([whether compiler supports -Wno-sign-compare],
[nmh_cv_has_nosigncompare],
if test "$nmh_cv_has_nosigncompare" = 'yes'; then
DISABLE_SIGN_COMPARE_WARNING=-Wno-sign-compare
fi
-AC_SUBST(DISABLE_SIGN_COMPARE_WARNING)dnl
+AC_SUBST([DISABLE_SIGN_COMPARE_WARNING])dnl
AC_CACHE_CHECK([whether compiler supports -Wextra], [nmh_cv_has_wextra],
[nmh_saved_cflags="$CFLAGS"
fi
fi
-AC_C_CONST dnl Does compiler support `const'.
-
dnl ------------------
dnl CHECK FOR PROGRAMS
dnl ------------------
AC_PROG_RANLIB dnl Check for `ranlib'
AC_PROG_AWK dnl Check for mawk,gawk,nawk, then awk
AC_PROG_SED dnl Check for Posix-compliant sed
-AC_PROG_LEX dnl Check for lex/flex
+AM_PROG_LEX dnl Check for lex/flex
AM_PROG_AR
dnl ----------------------------------------------
dnl check for lclint, and lint if it doesn't exist
dnl ----------------------------------------------
-AC_CHECK_PROG(linttmp1, lclint, lclint, no)dnl
-if test x$ac_cv_prog_linttmp1 != xno ; then
- LINT=$ac_cv_prog_linttmp1
- LINTFLAGS="-weak +posixlib -macrovarprefixexclude"
-else
- AC_CHECK_PROG(linttmp2, lint, lint, no)dnl
- if test x$ac_cv_prog_linttmp2 != xno ; then
- LINT=$ac_cv_prog_linttmp2
- LINTFLAGS=""
- else
- LINT="echo 'No lint program found'"
- LINTFLAGS=""
- fi
-fi
+AC_CHECK_PROG([linttmp1], [lclint], [lclint], [no])dnl
+AS_IF([test x$ac_cv_prog_linttmp1 != xno],
+ [LINT=$ac_cv_prog_linttmp1
+ LINTFLAGS="-weak +posixlib -macrovarprefixexclude"],
+ [AC_CHECK_PROG([linttmp2], [lint], [lint], [no])dnl
+ AS_IF([test x$ac_cv_prog_linttmp2 != xno],
+ [LINT=$ac_cv_prog_linttmp2
+ LINTFLAGS=""],
+ [LINT="echo 'No lint program found'"
+ LINTFLAGS=""])])
AC_SUBST([LINT])dnl
AC_SUBST([LINTFLAGS])dnl
AC_PATH_PROG([lspath], [ls], [no], [$pathtmp])
dnl See how we get ls to display the owner and the group
-if test "$lspath" != "no"; then
- AC_CACHE_CHECK([how to get ls to show us the group ownership of a file],
+AS_IF([test "$lspath" != "no"],
+ [AC_CACHE_CHECK([how to get ls to show us the group ownership of a file],
[nmh_cv_ls_grpopt],
- [if test x"`$lspath -dl / | $AWK '{print $9}'`" = x"/"; then
+ [AS_IF([test x"`$lspath -dl / | $AWK '{print $9}'`" = x"/"],[
dnl There were 9 parameters, so unless this is a really bizarre, nonstandard
dnl ls, it would seem -l gave us both the user and group. On this type of
dnl ls, -g makes _only_ the group be displayed (and not the user).
- nmh_cv_ls_grpopt="-l"
- else
+ nmh_cv_ls_grpopt="-l"],[
dnl Looks like -l only gave us the user, so we need -g to get the group too.
- nmh_cv_ls_grpopt="-lg"
- fi])
-fi
+ nmh_cv_ls_grpopt="-lg"])])])
dnl Look for `sendmail'
pathtmp=/usr/lib:/usr/sbin:/usr/etc:/usr/ucblib:/usr/bin:/bin
AC_PATH_PROG([sendmailpath], [sendmail], [/usr/sbin/sendmail], [$pathtmp])
-dnl Look for `vi'
-pathtmp=/usr/bin:/bin:/usr/ucb:/usr/local/bin
-AC_PATH_PROG([vipath], [vi], [/bin/vi], [$pathtmp])
-
-dnl If editor is not specified yet,
-dnl then use `vi' as the default.
-AS_IF([test -z "$editorpath"], [editorpath="$vipath"])
-AC_SUBST([editorpath])dnl
-
dnl Cygwin FAT filesystems do not support hard links. So default to
dnl cp instead, even if running on an NTFS or other filesystem.
AS_CASE(["$host_os"],
dnl Provide a way for distcheck to disable setgid_mail via
dnl DISTCHECK_CONFIGURE_FLAGS.
-if test x"$DISABLE_SETGID_MAIL" != x -a x"$DISABLE_SETGID_MAIL" != x0; then
- nmh_cv_dotlockfile_setgid=yes
-fi
+AS_IF([test x"$DISABLE_SETGID_MAIL" != x -a x"$DISABLE_SETGID_MAIL" != x0],
+ [nmh_cv_dotlockfile_setgid=yes])
dnl If mailspool is not world-writable and dotlockfile is not setgid,
dnl we need to #define MAILGROUP to 1 and make inc setgid.
[Define to 1 if you need to make `inc' set-group-id because your mail spool is not world writable. There are no guarantees as to the safety of doing this, but this #define will add some extra security checks.])dnl
SETGID_MAIL=1
fi
-AC_SUBST(SETGID_MAIL)dnl
+AC_SUBST([SETGID_MAIL])dnl
dnl Use ls to see which group owns the mail spool directory.
AC_CACHE_CHECK(what group owns the mail spool, nmh_cv_ls_mail_grp,
AS_IF([test -z "$CPPFLAGS"],[CPPFLAGS="-D_GNU_SOURCE"],
[CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"])])
-AC_HEADER_STDC
AC_HEADER_TIOCGWINSZ
-AC_CHECK_HEADERS([errno.h fcntl.h crypt.h ncurses/termcap.h termcap.h \
- langinfo.h wchar.h wctype.h iconv.h netdb.h \
- sys/param.h sys/time.h sys/stream.h])
-
-dnl
-dnl Checks for _IO_write_ptr. A Linuxism used by nmh on linux. We
-dnl really use a whole set of them, but this check should be
-dnl sufficient.
-dnl
-AC_CHECK_HEADER(libio.h, [
- AC_EGREP_HEADER(_IO_write_ptr, libio.h, [
- AC_DEFINE(LINUX_STDIO,1,[Use the Linux _IO_*_ptr defines from <libio.h>.]) ]) ])
+AC_CHECK_HEADERS([fcntl.h ncurses/termcap.h termcap.h langinfo.h \
+ wchar.h wctype.h sys/param.h sys/time.h sys/stream.h])
AC_CHECK_HEADER([sys/ptem.h], AC_DEFINE(WINSIZE_IN_PTEM,1,
[Define to 1 if `struct winsize' requires <sys/ptem.h>.]),,
dnl Checks for network libraries (nsl, socket)
NMH_CHECK_NETLIBS
+dnl Check for readline support
NMH_READLINE
+dnl Check for iconv
+NMH_CHECK_ICONV
+
termcap_curses_order="termcap curses ncurses"
for lib in $termcap_curses_order; do
AC_CHECK_LIB(${lib}, tgetent, [TERMLIB="-l$lib"; break])
[AC_MSG_FAILURE([Could not find tgetent in any library. Is there a curses
or ncurses library or package that you can install?])])
-
-dnl ---------------
-dnl CHECK FOR ICONV
-dnl ---------------
-
-dnl Find iconv. It may be in libiconv and may be iconv() or libiconv()
-if test "x$ac_cv_header_iconv_h" = "xyes"; then
- AC_CHECK_FUNC(iconv, ac_found_iconv=yes, ac_found_iconv=no)
- if test "x$ac_found_iconv" = "xno"; then
- AC_CHECK_LIB(iconv, iconv, ac_found_iconv=yes)
- if test "x$ac_found_iconv" = "xno"; then
- AC_CHECK_LIB(iconv, libiconv, ac_found_iconv=yes)
- fi
- if test "x$ac_found_iconv" != "xno"; then
- ICONVLIB="-liconv"
- fi
- else
- dnl Handle case where there is a native iconv but iconv.h is from libiconv
- AC_CHECK_DECL(_libiconv_version,
- [ AC_CHECK_LIB(iconv, libiconv, LIBS="-liconv $LIBS") ],,
- [ #include <iconv.h> ])
- fi
-fi
-if test "x$ac_found_iconv" = xyes; then
- AC_DEFINE([HAVE_ICONV], [1], [Define if you have the iconv() function.])
-fi
-AC_SUBST([ICONVLIB])
-
-dnl Check if iconv uses const in prototype declaration
-if test "x$ac_found_iconv" = "xyes"; then
- AC_CACHE_CHECK(for iconv declaration, ac_cv_iconv_const,
- [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdlib.h>
- #include <iconv.h>]],
- [[#ifdef __cplusplus
- "C"
- #endif
- #if defined(__STDC__) || defined(__cplusplus)
- size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
- #else
- size_t iconv();
- #endif]])],
- [ac_cv_iconv_const=],
- [ac_cv_iconv_const=const])])
- AC_DEFINE_UNQUOTED([ICONV_CONST], $ac_cv_iconv_const,
- [Define as const if the declaration of iconv() needs const.])
-fi
-
dnl --------------
dnl CHECK FOR NDBM
dnl --------------
dnl nmhrpm is used in the final summary, see below. The default value is
dnl reported there as ./RPM, consistent with the reporting of the default
dnl source code location as ., but its absolute path is used in the Makefile.
-AC_ARG_WITH(rpmdir,
- AS_HELP_STRING([--with-rpmdir=RPMDIR], [RPM build directory @<:@RPM@:>@]))
+AC_ARG_WITH([rpmdir],
+ [AS_HELP_STRING([--with-rpmdir=RPMDIR], [RPM build directory @<:@RPM@:>@])])
AS_IF([test x"$with_rpmdir" = x], [rpmdir='$(abs_srcdir)/RPM'; nmhrpm=./RPM],
[rpmdir="$with_rpmdir"; eval "nmhrpm=${rpmdir}"])
AC_SUBST([rpmdir])
AS_IF([test x"$tls_support" = x"yes"],[
AC_CHECK_HEADER([openssl/ssl.h], , [AC_MSG_ERROR([openssl/ssl.h not found])])
- AC_CHECK_LIB([crypto], [BIO_write], ,
+ AC_CHECK_LIB([crypto], [BIO_write], [TLSLIB="-lcrypto"],
[AC_MSG_ERROR([OpenSSL crypto library not found])])
- AC_CHECK_LIB([ssl], [SSL_library_init], ,
- [AC_MSG_ERROR([OpenSSL library not found])])])
+ AC_CHECK_LIB([ssl], [SSL_library_init], [TLSLIB="-lssl $TLSLIB"],
+ [AC_MSG_ERROR([OpenSSL library not found])])],
+ [TLSLIB=])
+AC_SUBST([TLSLIB])
dnl ---------------------
dnl CHECK TERMCAP LIBRARY
dnl
AC_CONFIG_COMMANDS([build-directories],
-[test -d etc || ${MKDIR_P} etc
-test -d man || ${MKDIR_P} man])
+[test -d etc || AS_MKDIR_P([etc])
+test -d man || AS_MKDIR_P([man])])
AC_CONFIG_COMMANDS_POST([
file locking type : ${LOCKTYPE}
default smtp servers : ${smtpservers}
default editor : ${editorpath}
-default pager : ${pagerpath}
SASL support : ${sasl_support}
TLS support : ${tls_support}
])])dnl
compctl -K mhfseq -x 's[+][@]' -K mhcomp -S / -q - 's[-]' \
-k "(file part type list headers noheaders realsize norealsize nolist \
show serialonly noserialonly form pause nopause noshow store auto noauto \
- nostore cache nocache rcache wcache check nocheck ebcdicsafe noebcdicsafe \
+ nostore cache nocache rcache wcache check nocheck \
rfc934mode norfc934mode verbose noverbose help)" - \
'c[-1,-file]' -f - 'c[-1,-form]' -K mhfile - \
'C[-1,-[rw]cache]' -k '(public private never ask)' -- mhn
from <ftp://ftp.gnu.org/pub/gnu/m4/>, then GNU autoconf
(<ftp://ftp.gnu.org/pub/gnu/autoconf/>) and GNU automake
(<ftp://ftp.gnu.org/pub/gnu/automake/>). Nmh is currently using a
-minimum of autoconf 2.61 and automake 1.12.
+minimum of autoconf 2.68 and automake 1.12.
Most of the configure-related files are automatically generated.
The only files you should need to manually edit are configure.ac
# Configures and builds nmh.
# * This script must be invoked from an nmh source directory.
# * This script retrieves configuration from the first existing nmh
-# installation on your $PATH, if any, as well as any $EDITOR/$VISUAL
-# and $PAGER environment variable settings.
+# installation on your $PATH, if any.
# * Unless the -y option is provided, this script then interactively
# walks you through confirmation of common configuration settings.
#
####
#### OS-specific setup.
####
-which=which
ldd=ldd
####
config_smtpservers=localhost
config_sasl=n
config_tls=n
-config_editor=vi
-for i in more less most cat; do
- if which $i >/dev/null 2>&1; then
- config_pager=$i
- break
- fi
-done
config_debug=n
+
+#### Find location of a program. Bourne shell just puts the name in
+#### $0 if it's found from the PATH, so search that if necessary.
+finddir() {
+ case $1 in
+ */*) dirname "$1" ;;
+ * ) IFS=:
+ for d in $PATH; do
+ [ -f "${d:=.}/$1" -a -x "$d/$1" ] && printf %s "$d" && break
+ done ;;
+ esac
+}
+
+
if install-mh -check >/dev/null 2>&1; then
# Determine config options from installed nmh.
- mhparam=`which mhparam`
- mhbin=`dirname "$mhparam"`
+ mhbin=`finddir install-mh`
config_prefix=`cd $mhbin/.. && pwd`
fi
fi
-if [ "$EDITOR" ]; then
- config_editor="$EDITOR"
-elif [ "$VISUAL" ]; then
- config_editor="$VISUAL"
-fi
-
-[ "$PAGER" ] && config_pager="$PAGER"
-
[ $debug -ge 1 ] && config_debug=y
if [ $yes -eq 0 ]; then
config_tls=n
fi
- printf 'Default editor [%s]: ' $config_editor
- read editor
- [ "$editor" ] && config_editor="$editor"
-
- printf 'Pager [%s]: ' $config_pager
- read pager
- [ "$pager" ] && config_pager="$pager"
-
#### Don't confirm debug here: obey the -d option to this script.
fi
config_opts="$config_opts --with-cyrus-sasl"
[ "$config_tls" = y ] && \
config_opts="$config_opts --with-tls"
-[ "$config_editor" ] && \
- config_opts="$config_opts --with-editor=$config_editor"
-[ "$config_pager" ] && \
- config_opts="$config_opts --with-pager=$config_pager"
[ $config_debug = y ] && \
config_opts="$config_opts --enable-debug"
fi
[ $verbose -ge 1 ] && echo testing . . .
- checkoutput=`make $check 2>>"$logfile"`
+ checkoutput=`make $check AM_COLOR_TESTS=always 2>>"$logfile"`
status=$?
tests_summary=`echo "$checkoutput" | grep tests`
#### If multiple tests not run, that line will be caught by the
#### "grep tests" above.
test_not_run=`echo "$checkoutput" | grep 'test was not run'`
+ fails=`echo "$checkoutput" | grep FAIL`
if [ "$tests_summary" ]; then
echo '===================' >>"$logfile"
- echo "$tests_summary" >>"$logfile"
[ "$test_not_run" ] && echo "$test_not_run" >>"$logfile"
+ [ "$fails" ] && echo "$fails" >>"$logfile"
+ echo "$tests_summary" >>"$logfile"
echo '===================' >>"$logfile"
[ "$check" = distcheck ] && \
echo "$checkoutput" | tail -n 4 >>"$logfile"
- inc(1) now supports a -port switch to specify the port used by the
POP server.
- pick(1) now decodes MIME-encoded header fields before searching.
+- The VISUAL and EDITOR environment variables are now supported as fallbacks
+ if the user does not configure an editor entry in their profile.
+- The format engine (mh_format(5)) now properly accounts for multibyte
+ characters when accounting for column widths.
----------------------------
http://smtpfilter.sourceforge.net/esmtp.html
- conflict(8) is deprecated and will be removed from the next release.
- mhtest(8) is deprecated and will be removed from the next release.
+- msh(1) is deprecated and will be removed from the next release.
- spost(8) has been merged into post(8). Its functionality is enabled
by selecting the sendmail/pipe mail transport method, described in
the mh-tailor(5) man page. The spost -noalias, -backup/-nobackup,
refuses to do that. For backward compatibility, spost has been
replaced by a simple shell script that exec's post -mts
sendmail/pipe.
+- Support for the undocumented and deprecated --enable-nmh-debug configure
+ flag has been removed.
+- Support for encoding some characters designated as EBCDIC-unsafe
+ via the -ebcdicsafe and -noebcdicsafe switches to mhbuild has
+ been removed.
+- The configure flag --with-pager has been removed; the default pager
+ is now hardcoded as "more". Users are still free to override the
+ default using the PAGER environment variable or entries in .mh_profile.
+- The configure flag --with-editor has been removed; the fallback editor
+ if none is configured is "vi".
---------
BUG FIXES
- Fixed pick(1) to properly unfold multiple-line header fields by
removing newlines instead of replacing them with spaces [Bug #15215].
- Removed the artificial limit of 1000 messages at a time for rmmproc.
+- Fixed decoding of header fields when they contain a character that
+ can't be converted.
#define FT_CONCATADDR 70 /* formataddr w/out duplicate removal */
#define FT_MYMBOX 71 /* do "mymbox" test on comp */
-/* misc. */ /* ADDTOSEQ only works if you include "options LBL" */
-#define FT_ADDTOSEQ 72 /* add current msg to a sequence */
-
/* conditionals & control flow (must be last) */
-#define FT_SAVESTR 73 /* save current str reg */
-#define FT_DONE 74 /* stop formatting */
-#define FT_PAUSE 75 /* pause */
-#define FT_NOP 76 /* nop */
-#define FT_GOTO 77 /* (relative) goto */
-#define FT_IF_S_NULL 78 /* test if "str" null */
-#define FT_IF_S 79 /* test if "str" non-null */
-#define FT_IF_V_EQ 80 /* test if "value" = literal */
-#define FT_IF_V_NE 81 /* test if "value" != literal */
-#define FT_IF_V_GT 82 /* test if "value" > literal */
-#define FT_IF_MATCH 83 /* test if "str" contains literal */
-#define FT_IF_AMATCH 84 /* test if "str" starts with literal */
-#define FT_S_NULL 85 /* V = 1 if "str" null */
-#define FT_S_NONNULL 86 /* V = 1 if "str" non-null */
-#define FT_V_EQ 87 /* V = 1 if "value" = literal */
-#define FT_V_NE 88 /* V = 1 if "value" != literal */
-#define FT_V_GT 89 /* V = 1 if "value" > literal */
-#define FT_V_MATCH 90 /* V = 1 if "str" contains literal */
-#define FT_V_AMATCH 91 /* V = 1 if "str" starts with literal */
+#define FT_SAVESTR 72 /* save current str reg */
+#define FT_DONE 73 /* stop formatting */
+#define FT_PAUSE 74 /* pause */
+#define FT_NOP 75 /* nop */
+#define FT_GOTO 76 /* (relative) goto */
+#define FT_IF_S_NULL 77 /* test if "str" null */
+#define FT_IF_S 78 /* test if "str" non-null */
+#define FT_IF_V_EQ 79 /* test if "value" = literal */
+#define FT_IF_V_NE 80 /* test if "value" != literal */
+#define FT_IF_V_GT 81 /* test if "value" > literal */
+#define FT_IF_MATCH 82 /* test if "str" contains literal */
+#define FT_IF_AMATCH 83 /* test if "str" starts with literal */
+#define FT_S_NULL 84 /* V = 1 if "str" null */
+#define FT_S_NONNULL 85 /* V = 1 if "str" non-null */
+#define FT_V_EQ 86 /* V = 1 if "value" = literal */
+#define FT_V_NE 87 /* V = 1 if "value" != literal */
+#define FT_V_GT 88 /* V = 1 if "value" > literal */
+#define FT_V_MATCH 89 /* V = 1 if "str" contains literal */
+#define FT_V_AMATCH 90 /* V = 1 if "str" starts with literal */
#define IF_FUNCS FT_S_NULL /* start of "if" functions */
#define UNKWNSW (-1) /* from smatch() on unknown switch */
struct swit {
+
+ /*
+ * Switch name
+ */
+
char *sw;
/* The minchars field is apparently used like this:
0 : Switch can't be abbreviated; switch shown in -help.
# : Switch can be abbreviated to # characters; switch shown in -help. */
int minchars;
+
+ /*
+ * If we pick this switch, return this value from smatch
+ */
+
+ int swret;
};
+/*
+ * Macros to use when declaring struct swit arrays.
+ *
+ * These macros are what known as X-Macros. In your source code you
+ * use them like this:
+ *
+ * #define FOO_SWITCHES \
+ * X("switch1", 0, SWITCHSW) \
+ * X("switch2", 0, SWITCH2SW) \
+ * X("thirdswitch", 2, SWITCH3SW) \
+ *
+ * The argument to each entry in FOO_SWITCHES are the switch name (sw),
+ * the minchars field (see above) and the return value for this switch.
+ *
+ * After you define FOO_SWITCHES, you instantiate it as follows:
+ *
+ * #define X(sw, minchars, id) id,
+ * DEFINE_SWITCH_ENUM(FOO);
+ * #undef X
+ *
+ * #define X(sw, minchars, id) { sw, minchars, id },
+ * DEFINE_SWITCH_ARRAY(FOO);
+ * #undef X
+ *
+ * DEFINE_SWITCH_ENUM defines an extra enum at the end of the list called
+ * LEN_FOO.
+ */
+
+#define DEFINE_SWITCH_ENUM(name) \
+ enum { \
+ name ## _SWITCHES \
+ LEN_ ## name \
+ }
+
+#define DEFINE_SWITCH_ARRAY(name, array) \
+ static struct swit array[] = { \
+ name ## _SWITCHES \
+ { NULL, 0, 0 } \
+ }
+
extern struct swit anoyes[]; /* standard yes/no switches */
#define ATTACHFORMATS 3 /* Number of send attach formats. */
#define FMTERR (-3) /* Message Format error */
#define FLD 0 /* Field returned */
#define FLDPLUS 1 /* Field returned with more to come */
-#define FLDEOF 2 /* Field returned ending at eom */
#define BODY 3 /* Body returned with more to come */
-#define BODYEOF 4 /* Body returned ending at eom */
#define FILEEOF 5 /* Reached end of input file */
+struct m_getfld_state;
+typedef struct m_getfld_state *m_getfld_state_t;
+
/*
* Maildrop styles
*/
#define MS_MMDF 3 /* string mmdlm2 */
#define MS_MSH 4 /* whacko msh */
-extern int msg_count; /* m_getfld() indicators */
-extern int msg_style; /* .. */
-extern char *msg_delim; /* .. */
-
#define NOUSE 0 /* draft being re-used */
#define TFOLDER 0 /* path() given a +folder */
extern char *components;
extern char *context;
extern char *current;
-extern char *defaulteditor;
extern char *defaultfolder;
extern char *digestcomps;
extern char *distcomps;
/*
* various cache policies
*/
-static struct swit caches[] = {
-#define CACHE_NEVER 0
- { "never", 0 },
-#define CACHE_PRIVATE 1
- { "private", 0 },
-#define CACHE_PUBLIC 2
- { "public", 0 },
-#define CACHE_ASK 3
- { "ask", 0 },
- { NULL, 0 }
-};
+
+#define CACHE_SWITCHES \
+ X("never", 0, CACHE_NEVER) \
+ X("private", 0, CACHE_PRIVATE) \
+ X("public", 0, CACHE_PUBLIC) \
+ X("ask", 0, CACHE_ASK) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(CACHE);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(CACHE, caches);
+#undef X
# endif
#endif
+/*
+ * Defaults for programs if they aren't configured in a user's profile
+ */
+
+#define DEFAULT_PAGER "more"
+#define DEFAULT_EDITOR "vi"
+
#include <signal.h>
void admonish (char *, char *, ...);
void advertise (char *, char *, char *, va_list);
void advise (char *, char *, ...);
+char **argsplit (char *, char **, int *);
+void arglist_free (char *, char **);
void ambigsw (char *, struct swit *);
int atooi(char *);
char **brkstring (char *, char *, char *);
char **getarguments (char *, int, char **, int);
char *get_charset(void);
char *getcpy (char *);
+char *get_default_editor(void);
char *getfolder(int);
int lkclose(int, char*);
int lkfclose(FILE *, char *);
char *m_backup (char *);
int m_convert (struct msgs *, char *);
char *m_draft (char *, char *, int, int *);
-void m_eomsbr (int (*)(int));
-int m_getfld (int, unsigned char *, unsigned char *, int, FILE *);
+void m_eomsbr (m_getfld_state_t, int (*)(int));
+void m_getfld_state_reset (m_getfld_state_t *);
+void m_getfld_state_destroy (m_getfld_state_t *);
+void m_getfld_track_filepos (m_getfld_state_t *, FILE *);
+int m_getfld (m_getfld_state_t *, unsigned char[NAMESZ], unsigned char *, int *, FILE *);
int m_gmprot (void);
char *m_maildir (char *);
char *m_mailpath (char *);
int m_rand (unsigned char *, size_t);
char *m_mktemp(const char *, int *, FILE **);
char *m_mktemp2(const char *, const char *, int *, FILE **);
-void m_unknown(FILE *);
+void m_unknown(m_getfld_state_t *, FILE *);
int makedir (char *);
char *message_id (time_t, int);
char *nmh_getpass(const char *);
int refile (char **, char *);
void ruserpass(char *, char **, char **);
int remdir (char *);
+void scan_detect_mbox_style (FILE *);
+void scan_finished ();
+void scan_eom_action (int (*)());
+void scan_reset_m_getfld_state ();
int seq_addmsg (struct msgs *, char *, int, int, int);
int seq_addsel (struct msgs *, char *, int, int);
char *seq_bits (struct msgs *);
--- /dev/null
+dnl
+dnl Check for iconv support. It may be in libiconv and may be iconv()
+dnl or libiconv()
+dnl
+
+AC_DEFUN([NMH_CHECK_ICONV],
+[AC_CHECK_HEADER([iconv.h],
+ [AC_CHECK_FUNC([iconv],
+ [dnl This is where iconv is found in the default libraries (LIBS)
+ nmh_found_iconv=yes
+ dnl Handle the case where there is a native iconv but iconv.h is
+ dnl from libiconv
+ AC_CHECK_DECL([_libiconv_version],
+ [AC_CHECK_LIB([iconv], [libiconv], [LIBS="-liconv $LIBS"])],,
+ [#include <iconv.h>])],
+ [dnl Since we didn't find iconv in LIBS, check libiconv
+ AC_CHECK_LIB([iconv], [iconv], [nmh_found_iconv=yes],
+ [dnl Also check for a function called libiconv()
+ AC_CHECK_LIB([iconv], [libiconv], [nmh_found_iconv=yes])])
+ dnl If either of these tests pass, set ICONVLIB
+ AS_IF([test "x$nmh_found_iconv" = "xyes"], [ICONVLIB="-liconv"])])
+ dnl If we came out of that by finding iconv in some form, define
+ dnl HAVE_ICONV
+ AS_IF([test "x$nmh_found_iconv" = "xyes"],
+ [AC_DEFINE([HAVE_ICONV], [1],
+ [Define if you have the iconv() function.])
+ AC_CACHE_CHECK([for iconv declaration], [nmh_cv_iconv_const],
+ [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdlib.h>
+ #include <iconv.h>]],
+ [[#ifdef __cplusplus
+ "C"
+ #endif
+ #if defined(__STDC__) || defined(__cplusplus)
+ size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
+ #else
+ size_t iconv();
+ #endif]])],
+ [nmh_cv_iconv_const=],
+ [nmh_cv_iconv_const=const])])
+ AC_DEFINE_UNQUOTED([ICONV_CONST], [$nmh_cv_iconv_const],
+ [Define as const if the declaration of iconv() needs const.])])])
+AC_SUBST([ICONVLIB])])
.RE
.PP
.BR Editor :
-/usr/bin/vi
+vi
.RS 5
Defines the editor to be used by the commands
.BR comp ,
.BR forw ,
and
.BR repl .
-(profile, default: %default_editor%)
+If not set in profile the value will be taken from the VISUAL and
+EDITOR environment variables.
+(profile, default: vi)
.RE
.PP
.BR automimeproc :
.RE
.PP
.BR lproc :
-%default_pager%
+more
.RS 5
This program is used to list the contents of a message in response
to the
.RE
.PP
.BR moreproc :
-%default_pager%
+more
.RS 5
This is the program used by
.B mhl
-.TH MHBUILD %manext1% "May 31, 2012" "%nmhversion%"
+.TH MHBUILD %manext1% "January 4, 2013" "%nmhversion%"
.\"
.\" %nmhwarning%
.\"
.RB [ \-realsize " | " \-norealsize ]
.RB [ \-headers " | " \-noheaders ]
.RB [ \-directives " | " \-nodirectives ]
-.RB [ \-ebcdicsafe " | " \-noebcdicsafe ]
.RB [ \-rfc934mode " | " \-norfc934mode ]
.RB [ \-contentid " | " \-nocontentid ]
.RB [ \-verbose " | " \-noverbose ]
.B mhbuild
is given the
.B \-check
-switch, then it will also associate
-an integrity check with each \*(lqleaf\*(rq content. This will add a
-Content-MD5 header field to the content, along with the md5 sum of the
-unencoded contents. This may be used by the receiver of the message to
-verify that the contents of the message were not changed in transport.
+switch, then it will also associate an integrity check with each
+\*(lqleaf\*(rq content. This will add a Content-MD5 header field to
+the content, along with the md5 sum of the unencoded contents, per RFC
+1864. This may be used by the receiver of the message to verify that
+the contents of the message were not changed in transport.
.SS "Transfer Encodings"
After
.B mhbuild
a transfer encoding, even it the content contains only 7\-bit data. This
is to increase the likelihood that the content is not changed while in
transport.
-.PP
-The switch
-.B \-ebcdicsafe
-will cause
-.B mhbuild
-to slightly change
-the way in which it performs the \*(lqquoted-printable\*(rq transfer
-encoding. Along with encoding 8\-bit characters, it will now also encode
-certain common punctuation characters as well. This slightly reduces the
-readability of the message, but allows the message to pass more reliably
-through mail gateways which involve the EBCDIC character encoding.
.SS "Invoking mhbuild"
Typically,
.B mhbuild
.I "Proposed Standard for Message Encapsulation"
(RFC\-934),
.PP
+.I "The Content-MD5 Header Field"
+(RFC\-1864),
+.PP
.I "Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies"
(RFC\-2045),
.PP
.RB ` \-norfc934mode '
.RB ` \-contentid '
.RB ` \-nocheck '
-.RB ` \-noebcdicsafe '
.RB ` \-noverbose '
.fi
.B mhn
.B \-build
.I file
-.RB [ \-ebcdicsafe " | " \-noebcdicsafe ]
.RB [ \-rfc934mode " | " \-norfc934mode ]
.ad
.SH DESCRIPTION
-.TH MSH %manext1% "November 6, 2012" "%nmhversion%"
+.TH MSH %manext1% "January 26, 2013" "%nmhversion%"
.\"
.\" %nmhwarning%
.\"
.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 packf 'd
+.BR mmdf
format.
That is,
.B msh
if (sm_mts == MTS_SMTP)
smtalk (SM_QUIT, "QUIT");
else {
+ /* The SIGPIPE block replaces old calls to discard ().
+ We're not sure what the discard () calls were for,
+ maybe to prevent deadlock on old systems. In any
+ case, blocking SIGPIPE should be harmless.
+ Because the file handles are closed below, leave it
+ blocked. */
+ sigset_t set, oset;
+ sigemptyset (&set);
+ sigaddset (&set, SIGPIPE);
+ sigprocmask (SIG_BLOCK, &set, &oset);
+
kill (sm_child, SIGKILL);
- discard (sm_rfp);
- discard (sm_wfp);
+ sm_child = NOTOK;
}
if (type == NOTOK) {
sm_reply.code = sm_note.code;
if (sasl_inbuffer)
free(sasl_inbuffer);
#endif /* CYRUS_SASL */
- } else {
+ } else if (sm_child != NOTOK) {
status = pidwait (sm_child, OK);
sm_child = NOTOK;
+ } else {
+ status = OK;
}
sm_rfp = sm_wfp = NULL;
--- /dev/null
+
+/*
+ * arglist.c -- Routines for handling argument lists for execvp() and friends
+ *
+ * This code is Copyright (c) 2013, by the authors of nmh. See the
+ * COPYRIGHT file in the root directory of the nmh distribution for
+ * complete copyright information.
+ */
+
+#include <h/mh.h>
+#include <h/utils.h>
+
+/*
+ * Split up a command into an appropriate array to pass to execvp()
+ * or similar function. Returns an allocated argv[] array.
+ *
+ * Function arguments:
+ *
+ * command - String to split up
+ * file - the first argument to "command", suitable for the first argument
+ * to execvp(). Returns allocated memory that must be free()d.
+ * argp - Index to last element (NULL) of returned argv[] array.
+ *
+ * Our basic algorithm is this:
+ *
+ * - If there are no spaces or shell metacharacters in "command", then
+ * take it as-is.
+ * - If there are spaces in command, space-split command string.
+ * - If we have shell metacharacters, run the command using
+ * /bin/sh -c 'command "$@"'. In this case, any additional arguments
+ * appended to the arglist will be expanded by "$@".
+ *
+ * In all cases additional arguments can be added to the argv[] array.
+ */
+
+/* Shell metacharacters we use to trigger a call to the shell */
+
+#define METACHARS "$&*(){}[]'\";\\|?<>~`\n"
+
+char **
+argsplit(char *command, char **file, int *argp)
+{
+ char **argvarray, *p;
+ int space = 0, metachar = 0, i;
+
+ for (p = command; *p; p++) {
+ if (*p == ' ' || *p == '\t') {
+ space = 1;
+ } else if (strchr(METACHARS, *p)) {
+ metachar = 1;
+ break;
+ }
+ }
+
+ argvarray = (char **) mh_xmalloc((sizeof(char **) * MAXARGS));
+
+ /*
+ * The simple case - no spaces or shell metacharacters
+ */
+
+ if (!space && !metachar) {
+ argvarray[0] = getcpy(r1bindex(command, '/'));
+ argvarray[1] = NULL;
+ *file = getcpy(command);
+ if (argp)
+ *argp = 1;
+ return argvarray;
+ }
+
+ /*
+ * Spaces, but no shell metacharacters; space-split into seperate
+ * arguments
+ */
+
+ if (space && !metachar) {
+ char **split;
+ p = getcpy(command);
+ split = brkstring(p, " \t", NULL);
+ if (split[0] == NULL) {
+ adios(NULL, "Invalid blank command found");
+ }
+ argvarray[0] = getcpy(r1bindex(split[0], '/'));
+ for (i = 1; split[i] != NULL; i++) {
+ if (i > MAXARGS) {
+ adios(NULL, "Command exceeded argument limit");
+ }
+ argvarray[i] = getcpy(split[i]);
+ }
+ argvarray[i] = NULL;
+ *file = getcpy(split[0]);
+ if (argp)
+ *argp = i;
+ free(p);
+ return argvarray;
+ }
+
+ /*
+ * Remaining option - pass to the shell.
+ *
+ * Some notes here:
+ *
+ * - The command passed to "sh -c" is actually:
+ * command "$@"
+ *
+ * If there are additional arguments they will be expanded by the
+ * shell, otherwise "$@" expands to nothing.
+ *
+ * - Every argument after the -c string gets put into positional
+ * parameters starting at $0, but $@ starts expanding with $1.
+ * So we put in a dummy argument (we just use /bin/sh)
+ */
+
+ *file = getcpy("/bin/sh");
+ argvarray[0] = getcpy("sh");
+ argvarray[1] = getcpy("-c");
+ argvarray[2] = getcpy(command);
+ argvarray[2] = add(" \"$@\"", argvarray[2]);
+ argvarray[3] = getcpy("/bin/sh");
+ argvarray[4] = NULL;
+
+ if (argp)
+ *argp = 4;
+
+ return argvarray;
+}
+
+/*
+ * Free our argument array
+ */
+
+void
+arglist_free(char *command, char **argvarray)
+{
+ int i;
+
+ if (command != NULL)
+ free(command);
+
+ if (argvarray != NULL) {
+ for (i = 0; argvarray[i] != NULL; i++)
+ free(argvarray[i]);
+ free(argvarray);
+ }
+}
tcflush (fileno(io), TCOFLUSH);
-#if defined(_FSTDIO) || defined(__DragonFly__)
- fpurge (io);
-#else
-# ifdef LINUX_STDIO
- io->_IO_write_ptr = io->_IO_write_base;
-# else
- if ((io->_ptr = io->_base))
- io->_cnt = 0;
-# endif
-#endif
+ /* There used to be an fpurge() here on some platforms, stdio
+ hackery on others. But it didn't seem necessary. */
}
{ "friendly", TF_COMP, FT_LS_FRIENDLY, FT_PARSEADDR, TFL_PUTS },
{ "mymbox", TF_COMP, FT_LV_COMPFLAG, FT_MYMBOX, TFL_PUTN },
- { "addtoseq", TF_STR, FT_ADDTOSEQ, 0, 0 },
{ "unquote", TF_EXPR, FT_LS_UNQUOTE, 0, TFL_PUTS},
break;
/* skip to next input character */
if (fromutf8) {
- for (start++;(start < q) && ((*start & 192) == 128);start++)
- inbytes--;
+ for (++start, --inbytes;
+ start < q && (*start & 192) == 128;
+ ++start, --inbytes)
+ continue;
} else
start++, inbytes--;
if (start >= q)
# include <wchar.h>
#endif
-#ifdef LBL
-struct msgs *fmt_current_folder; /* current folder (set by main program) */
-#endif
-
extern int fmt_norm; /* defined in sbr/fmt_def.c = AD_NAME */
struct mailname fmt_mnull = { NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0,
NULL, NULL };
* no more than n bytes are copied
*/
static void
-cptrimmed(char **dest, char *str, unsigned int wid, char fill, size_t n) {
+cptrimmed(char **dest, char **ep, char *str, unsigned int wid, char fill,
+ char *epmax) {
int remaining; /* remaining output width available */
int c, ljust;
int end; /* number of input bytes remaining in str */
#endif
char *sp; /* current position in source string */
char *cp = *dest; /* current position in destination string */
- char *ep = cp + n; /* end of destination buffer */
int prevCtrl = 1;
/* get alignment */
ljust++;
}
if ((sp = (str))) {
+#ifdef MULTIBYTE_SUPPORT
mbtowc(NULL, NULL, 0); /* reset shift state */
+#endif
end = strlen(str);
while (*sp && remaining > 0 && end > 0) {
#ifdef MULTIBYTE_SUPPORT
char_len = mbtowc(&wide_char, sp, end);
- if (char_len <= 0 || (cp + char_len > ep))
+
+ if (char_len <= 0)
+ break;
+
+ w = wcwidth(wide_char);
+
+ /*
+ * Multibyte characters can have a variable number of column
+ * widths, so use the column width to bump the end pointer when
+ * appropriate.
+ */
+ if (char_len > 1 && epmax - *ep >= char_len - w) {
+ *ep += char_len - w;
+ }
+
+ if (cp + w > *ep)
break;
end -= char_len;
prevCtrl = 0;
#ifdef MULTIBYTE_SUPPORT
- w = wcwidth(wide_char);
if (w >= 0 && remaining >= w) {
strncpy(cp, sp, char_len);
cp += char_len;
}
if (ljust) {
- if (cp + remaining > ep)
- remaining = ep - cp;
- ep = cp + remaining;
+ char *endfield;
+ if (cp + remaining > *ep)
+ remaining = *ep - cp;
+ endfield = cp + remaining;
if (remaining > 0) {
/* copy string to the right */
while (--cp >= *dest)
for (c=remaining; c>0; c--)
*cp-- = fill;
}
- *dest = ep;
+ *dest = endfield;
} else {
/* pad remaining space */
- while (remaining-- > 0 && cp < ep)
+ while (remaining-- > 0 && cp < *ep)
*cp++ = fill;
*dest = cp;
}
}
static void
-cpstripped (char **dest, char *end, char *str)
+cpstripped (char **dest, char **end, char *max, char *str)
{
int prevCtrl = 1; /* This is 1 so we strip out leading spaces */
int len;
#ifdef MULTIBYTE_SUPPORT
- int char_len;
+ int char_len, w;
wchar_t wide_char;
#endif /* MULTIBYTE_SUPPORT */
* then deal with that here.
*/
- while (*str != '\0' && len > 0 && *dest < end) {
+ while (*str != '\0' && len > 0 && *dest < *end) {
#ifdef MULTIBYTE_SUPPORT
char_len = mbtowc(&wide_char, str, len);
+ w = wcwidth(wide_char);
+
+ /*
+ * Account for multibyte characters, and increment the end pointer
+ * by the number of "extra" bytes in this character. That's the
+ * character length (char_len) minus the column width (w).
+ */
+ if (char_len > 1 && max - *end >= char_len - w) {
+ *end += char_len - w;
+ }
- if (char_len <= 0 || *dest + char_len > end)
+ if (char_len <= 0 || *dest + char_len > *end)
break;
len -= char_len;
comp = fmt->f_comp;
- if (! (comp->c_flags & CF_TRIMMED) && comp->c_text) {
- i = strlen(comp->c_text);
+ if (! (comp->c_flags & CF_TRIMMED) && comp->c_text &&
+ (i = strlen(comp->c_text)) > 0) {
if (comp->c_text[i - 1] == '\n' &&
- strcmp(comp->c_name, "body") != 0 &&
- strcmp(comp->c_name, "text") != 0)
+ strcmp(comp->c_name, "body") != 0 &&
+ strcmp(comp->c_name, "text") != 0)
comp->c_text[i - 1] = '\0';
comp->c_flags |= CF_TRIMMED;
}
switch (fmt->f_type) {
case FT_COMP:
- cpstripped (&cp, ep, fmt->f_comp->c_text);
+ cpstripped (&cp, &ep, scanl + max - 1, fmt->f_comp->c_text);
break;
case FT_COMPF:
- cptrimmed (&cp, fmt->f_comp->c_text, fmt->f_width, fmt->f_fill, ep - cp);
+ cptrimmed (&cp, &ep, fmt->f_comp->c_text, fmt->f_width, fmt->f_fill,
+ scanl + max - 1);
break;
case FT_LIT:
break;
case FT_STR:
- cpstripped (&cp, ep, str);
+ cpstripped (&cp, &ep, scanl + max - 1, str);
break;
case FT_STRF:
- cptrimmed (&cp, str, fmt->f_width, fmt->f_fill, ep - cp);
+ cptrimmed (&cp, &ep, str, fmt->f_width, fmt->f_fill,
+ scanl + max - 1);
break;
case FT_STRLIT:
sp = str;
*cp++ = ' ';
}
}
- cpstripped (&cp, ep, lp);
+ cpstripped (&cp, &ep, scanl + max - 1, lp);
}
break;
comp->c_mn = &fmt_mnull;
}
break;
-
- case FT_ADDTOSEQ:
-#ifdef LBL
- /* If we're working on a folder (as opposed to a file), add the
- * current msg to sequence given in literal field. Don't
- * disturb string or value registers.
- */
- if (fmt_current_folder)
- seq_addmsg(fmt_current_folder, fmt->f_text, dat[0], -1);
-#endif
- break;
}
fmt++;
}
{
pid_t pid;
int msgnum, vecp, retval = 0;
- char buf[100], *dp, **vec;
+ char buf[100], *dp, **vec, *prog;
char msgpath[BUFSIZ];
/*
/* Mark that the sequence information has changed */
mp->msgflags |= SEQMOD;
- vec = (char **) calloc ((size_t) (mp->numsel + 2), sizeof(*vec));
+ vec = argsplit(rmmproc, &prog, &vecp);
+
+ /*
+ * argsplit allocates a MAXARGS vector by default, If we need
+ * something bigger, allocate it ourselves
+ */
+
+ if (mp->numsel + vecp + 1 > MAXARGS)
+ vec = (char **) realloc (vec, (size_t) ((mp->numsel + vecp + 1) *
+ sizeof(*vec)));
if (vec == NULL)
adios (NULL, "unable to allocate exec vector");
- vecp = 1;
for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
if (is_selected (mp, msgnum) &&
!(vec[vecp++] = strdup (m_name (msgnum))))
vec[vecp] = NULL;
fflush (stdout);
- vec[0] = r1bindex (rmmproc, '/');
switch (pid = vfork()) {
case -1:
return -1;
case 0:
- execvp (rmmproc, vec);
+ execvp (prog, vec);
fprintf (stderr, "unable to exec ");
perror (rmmproc);
_exit (-1);
default:
+ arglist_free(prog, vec);
return (pidwait (pid, -1));
}
}
--- /dev/null
+
+/*
+ * geteditor.c -- Determine the default editor to use
+ *
+ * This code is Copyright (c) 2013, by the authors of nmh. See the
+ * COPYRIGHT file in the root directory of the nmh distribution for
+ * complete copyright information.
+ */
+
+#include <h/mh.h>
+#include <h/utils.h>
+
+static char *default_editor = NULL;
+
+char *
+get_default_editor(void)
+{
+ char *str;
+
+ if (default_editor)
+ return default_editor;
+
+ if (!(str = context_find("editor")) && !(str = getenv("VISUAL")) &&
+ !(str = getenv("EDITOR"))) {
+ str = DEFAULT_EDITOR;
+ }
+
+ return (default_editor = str);
+}
* check if message is in-range and exists.
*/
if (mp->msgflags & ALLOW_NEW) {
+ /*
+ * We can get into a case where the "cur" sequence is way out
+ * of range, and because it's allowed to not exist (think
+ * of "rmm; next") it doesn't get checked to make sure it's
+ * within the range of messages in seq_init(). So if our
+ * desired sequence is out of range of the allocated folder
+ * limits simply reallocate the folder so it's within range.
+ */
+ if (first < mp->lowoff || first > mp->hghoff)
+ mp = folder_realloc(mp, first < mp->lowoff ? first : mp->lowoff,
+ first > mp->hghoff ? first : mp->hghoff);
+
set_select_empty (mp, first);
} else {
if (first > mp->hghmsg
#include <h/mts.h>
#include <h/utils.h>
+/*
+ Purpose
+ =======
+ Reads an Internet message (RFC 5322), or one or more messages
+ stored in a maildrop in mbox (RFC 4155) or MMDF format, from a file
+ stream. Each call to m_getfld() reads one header field, or a
+ portion of the body, in sequence.
+
+ Inputs
+ ======
+ gstate: opaque parse state
+ bufsz: maximum number of characters to load into buf
+ iob: input file stream
+
+ Outputs
+ =======
+ name: header field name (array of size NAMESZ=999)
+ buf: either a header field body or message body
+ bufsz: number of characters loaded into buf
+ (return value): message parse state on return from function
+
+ Functions
+ =========
+ void m_getfld_state_destroy (m_getfld_state_t *gstate): destroys
+ the parse state pointed to by the gstate argument.
+
+ m_getfld_state_reset (m_getfld_state_t *gstate): resets the parse
+ state to FLD.
+
+ void m_unknown(FILE *iob): Determines the message delimiter string
+ for the maildrop. Called by inc, scan, and msh when reading from a
+ maildrop file.
+
+ void m_eomsbr (int (*action)(int)): Sets the hook to check for end
+ of message in a maildrop. Called only by msh.
+
+ State variables
+ ===============
+ m_getfld() retains state internally between calls in the
+ m_getfld_state_t variable. These are used for detecting the end of
+ each message when reading maildrops:
+
+ unsigned char **pat_map
+ unsigned char *fdelim
+ unsigned char *delimend
+ int fdelimlen
+ unsigned char *edelim
+ int edelimlen
+ char *msg_delim
+ int msg_style
+ int (*eom_action)(int)
+
+ Usage
+ =====
+ m_getfld_state_t gstate = 0;
+ ...
+ int state = m_getfld (&gstate, ...);
+ ...
+ m_getfld_state_destroy (&gstate);
+
+ The state is retained internally by gstate. To reset its state to FLD:
+ m_getfld_state_reset (&gstate);
+*/
+
+/* The following described the old implementation. The high-level
+ structure hasn't changed, but some of the details have. I'm
+ leaving this as-is, though, for posterity.
+ */
+
/* This module has a long and checkered history. First, it didn't burst
maildrops correctly because it considered two CTRL-A:s in a row to be
an inter-message delimiter. It really is four CTRL-A:s followed by a
it knows that _filbuf ignores the _ptr & _cnt and simply fills
the buffer. If stdio on your system doesn't work this way, you
may have to make small changes in this routine.
-
+
This routine also "knows" that an EOF indication on a stream is
"sticky" (i.e., you will keep getting EOF until you reposition the
stream). If your system doesn't work this way it is broken and you
there is data in "name" or "buf").
*/
-
/*
* static prototypes
*/
-static int m_Eom (int, FILE *);
+struct m_getfld_state;
+static int m_Eom (m_getfld_state_t, int);
static unsigned char *matchc(int, char *, int, char *);
-static unsigned char *locc(int, unsigned char *, unsigned char);
-
-#define Getc(iob) getc(iob)
-#define eom(c,iob) (msg_style != MS_DEFAULT && \
- (((c) == *msg_delim && m_Eom(c,iob)) ||\
- (eom_action && (*eom_action)(c))))
-static unsigned char **pat_map;
+#define eom(c,s) (s->msg_style != MS_DEFAULT && \
+ (((c) == *s->msg_delim && m_Eom(s,c)) || \
+ (s->eom_action && (*s->eom_action)(c))))
-/*
- * defined in sbr/m_msgdef.c = 0
- * This is a disgusting hack for "inc" so it can know how many
- * characters were stuffed in the buffer on the last call
- * (see comments in uip/scansbr.c).
+/* This replaces the old approach, with its direct access to stdio
+ * internals. It uses one fread() to load a buffer that we manage.
+ *
+ * MSG_INPUT_SIZE is the size of the buffer.
+ * MAX_DELIMITER_SIZE is the maximum size of the delimiter used to
+ * separate messages in a maildrop, such as mbox "From ".
+ *
+ * Some of the tests in the test suite assume a MSG_INPUT_SIZE
+ * of 4096.
*/
-extern int msg_count;
+#define MSG_INPUT_SIZE 4096
+#define MAX_DELIMITER_SIZE 5
+
+struct m_getfld_state {
+ unsigned char msg_buf[2 * MSG_INPUT_SIZE + MAX_DELIMITER_SIZE];
+ unsigned char *readpos;
+ unsigned char *end; /* One past the last character read in. */
+ /* The following support tracking of the read position in the
+ input file stream so that callers can interleave m_getfld()
+ calls with ftell() and fseek(). ytes_read replaces the old
+ m_getfld() msg_count global. last_caller_pos is stored when
+ leaving m_getfld()/m_unknown(), then checked on the next entry.
+ last_internal_pos is used to remember the position used
+ internally by m_getfld() (read_more(), actually). */
+ off_t bytes_read;
+ off_t total_bytes_read; /* by caller, not necessarily from input file */
+ off_t last_caller_pos;
+ off_t last_internal_pos;
+ FILE *iob;
+
+ unsigned char **pat_map;
+ int msg_style;
+ /*
+ * The "full" delimiter string for a packed maildrop consists
+ * of a newline followed by the actual delimiter. E.g., the
+ * full string for a Unix maildrop would be: "\n\nFrom ".
+ * "Fdelim" points to the start of the full string and is used
+ * in the BODY case of the main routine to search the buffer for
+ * a possible eom. Msg_delim points to the first character of
+ * the actual delim. string (i.e., fdelim+1). Edelim
+ * points to the 2nd character of actual delimiter string. It
+ * is used in m_Eom because the first character of the string
+ * has been read and matched before m_Eom is called.
+ */
+ char *msg_delim;
+ unsigned char *fdelim;
+ unsigned char *delimend;
+ int fdelimlen;
+ unsigned char *edelim;
+ int edelimlen;
+ int (*eom_action)(int);
+ int state;
+ int track_filepos;
+};
+
+static
+void
+m_getfld_state_init (m_getfld_state_t *gstate, FILE *iob) {
+ m_getfld_state_t s;
+
+ s = *gstate = (m_getfld_state_t) mh_xmalloc(sizeof (struct m_getfld_state));
+ s->readpos = s->end = s->msg_buf;
+ s->bytes_read = s->total_bytes_read = 0;
+ s->last_caller_pos = s->last_internal_pos = 0;
+ s->iob = iob;
+ s->pat_map = NULL;
+ s->msg_style = MS_DEFAULT;
+ s->msg_delim = "";
+ s->fdelim = s->delimend = s->edelim = NULL;
+ s->fdelimlen = s->edelimlen = 0;
+ s->eom_action = NULL;
+ s->state = FLD;
+ s->track_filepos = 0;
+}
-/*
- * defined in sbr/m_msgdef.c = MS_DEFAULT
- */
-extern int msg_style;
+/* scan() needs to force a state an initial state of FLD for each message. */
+void
+m_getfld_state_reset (m_getfld_state_t *gstate) {
+ if (*gstate) {
+ (*gstate)->state = FLD;
+ }
+}
+
+/* If the caller interleaves ftell*()/fseek*() calls with m_getfld()
+ calls, m_getfld() must keep track of the file position. The caller
+ must use this function to inform m_getfld(). */
+void
+m_getfld_track_filepos (m_getfld_state_t *gstate, FILE *iob) {
+ if (! *gstate) {
+ m_getfld_state_init (gstate, iob);
+ }
+
+ (*gstate)->track_filepos = 1;
+}
+
+void m_getfld_state_destroy (m_getfld_state_t *gstate) {
+ m_getfld_state_t s = *gstate;
+
+ if (s) {
+ if (s->fdelim) free (s->fdelim-1);
+ free (s);
+ *gstate = 0;
+ }
+}
/*
- * The "full" delimiter string for a packed maildrop consists
- * of a newline followed by the actual delimiter. E.g., the
- * full string for a Unix maildrop would be: "\n\nFrom ".
- * "Fdelim" points to the start of the full string and is used
- * in the BODY case of the main routine to search the buffer for
- * a possible eom. Msg_delim points to the first character of
- * the actual delim. string (i.e., fdelim+1). Edelim
- * points to the 2nd character of actual delimiter string. It
- * is used in m_Eom because the first character of the string
- * has been read and matched before m_Eom is called.
- */
-extern char *msg_delim; /* defined in sbr/m_msgdef.c = "" */
-static unsigned char *fdelim;
-static unsigned char *delimend;
-static int fdelimlen;
-static unsigned char *edelim;
-static int edelimlen;
+ Summary of file and message input buffer positions:
+
+ input file -------------------------------------------EOF
+ | |
+ last_caller_pos last_internal_pos
+
+
+ msg_buf --------------------EOF
+ | | |
+ msg_buf readpos end
+
+ |<>|=retained characters, difference
+ between last_internal_pos and
+ first readpos value after reading
+ in new chunk in read_more()
-static int (*eom_action)(int) = NULL;
+ When returning from m_getfld()/m_unknown():
+ 1) Save the internal file position in last_internal_pos. That's the
+ m_getfld() position reference in the input file.
+ 2) Set file stream position so that callers can use ftell().
-#ifdef _FSTDIO
-# define _ptr _p /* Gag */
-# define _cnt _r /* Retch */
-# define _filbuf __srget /* Puke */
-# define DEFINED__FILBUF_TO_SOMETHING_SPECIFIC
+ When entering m_getfld()/m_unknown():
+ Check to see if the call had changed the file position. If so,
+ adjust the internal position reference accordingly. If not, restore
+ the internal file position from last_internal_pos.
+*/
-# if defined __CYGWIN__
- /* Cygwin's stdio.h does not declare __srget(). */
- int __srget(FILE *);
-# endif /* __CYGWIN__ */
-#endif
-#ifndef DEFINED__FILBUF_TO_SOMETHING_SPECIFIC
-extern int _filbuf(FILE*);
-#endif
+static void
+enter_getfld (m_getfld_state_t *gstate, FILE *iob) {
+ m_getfld_state_t s;
+ off_t pos = ftello (iob);
+
+ if (! *gstate) {
+ m_getfld_state_init (gstate, iob);
+ }
+ s = *gstate;
+ s->bytes_read = 0;
+
+ /* This is ugly and no longer necessary, but is retained just in
+ case it's needed again. The parser used to open the input file
+ multiple times, so we had to always use the FILE * that's
+ passed to m_getfld(). Now the parser inits a new
+ m_getfld_state for each file. See comment below about the
+ readpos shift code being currently unused. */
+ s->iob = iob;
+
+ if (s->track_filepos && (pos != 0 || s->last_internal_pos != 0)) {
+ if (s->last_internal_pos == 0) {
+ s->total_bytes_read = pos;
+ } else {
+ off_t pos_movement = pos - s->last_caller_pos; /* Can be < 0. */
+
+ if (pos_movement == 0) {
+ pos = s->last_internal_pos;
+ } else {
+ /* The current file stream position differs from the
+ last one, so caller must have called ftell/o().
+ Or, this is the first call and the file position
+ was not at 0. */
+
+ if (s->readpos + pos_movement >= s->msg_buf &&
+ s->readpos + pos_movement < s->end) {
+ /* This is currently unused. It could be used by
+ parse_mime() if it was changed to use a global
+ m_getfld_state. */
+ /* We can shift readpos and remain within the
+ bounds of msg_buf. */
+ s->readpos += pos_movement;
+ s->total_bytes_read += pos_movement;
+ pos = s->last_internal_pos;
+ } else {
+ size_t num_read;
+
+ /* This seek skips past an integral number of
+ chunks of size MSG_INPUT_SIZE. */
+ fseeko (iob, pos/MSG_INPUT_SIZE * MSG_INPUT_SIZE, SEEK_SET);
+ num_read = fread (s->msg_buf, 1, MSG_INPUT_SIZE, iob);
+ s->readpos = s->msg_buf + pos % MSG_INPUT_SIZE;
+ s->end = s->msg_buf + num_read;
+ s->total_bytes_read = pos;
+ }
+ }
+
+ fseeko (iob, pos, SEEK_SET);
+ }
+ }
+}
+
+static void
+leave_getfld (m_getfld_state_t s) {
+ s->total_bytes_read += s->bytes_read;
+
+ if (s->track_filepos) {
+ /* Save the internal file position that we use for the input buffer. */
+ s->last_internal_pos = ftello (s->iob);
+
+ /* Set file stream position so that callers can use ftell(). */
+ fseeko (s->iob, s->total_bytes_read, SEEK_SET);
+ s->last_caller_pos = ftello (s->iob);
+ }
+}
+
+static size_t
+read_more (m_getfld_state_t s) {
+ /* Retain at least edelimlen characters that have already been
+ read so that we can back up to them in m_Eom(). */
+ ssize_t retain = s->edelimlen;
+ size_t num_read;
+
+ if (retain < s->end - s->readpos) retain = s->end - s->readpos;
+ /* assert (retain <= s->readpos - s->msg_buf <= sizeof msg_buf); */
+
+ /* Move what we want to retain at end of the buffer to the beginning. */
+ memmove (s->msg_buf, s->readpos - retain, retain);
+
+ s->readpos = s->msg_buf + retain;
+ num_read = fread (s->readpos, 1, MSG_INPUT_SIZE, s->iob);
+ s->end = s->readpos + num_read;
+
+ return num_read;
+}
+
+static int
+Getc (m_getfld_state_t s) {
+ if (s->end - s->readpos < 1) {
+ if (read_more (s) == 0) {
+ /* Pretend that we read a character. That's what stdio does. */
+ ++s->readpos;
+ return EOF;
+ }
+ }
+
+ ++s->bytes_read;
+ return s->readpos < s->end ? *s->readpos++ : EOF;
+}
+
+static int
+Peek (m_getfld_state_t s) {
+ if (s->end - s->readpos < 1) {
+ if (read_more (s) == 0) {
+ /* Pretend that we read a character. That's what stdio does. */
+ ++s->readpos;
+ return EOF;
+ }
+ }
+
+ return s->readpos < s->end ? *s->readpos : EOF;
+}
+
+static int
+Ungetc (int c, m_getfld_state_t s) {
+ if (s->readpos == s->msg_buf) {
+ return EOF;
+ } else {
+ --s->bytes_read;
+ return *--s->readpos = c;
+ }
+}
int
-m_getfld (int state, unsigned char *name, unsigned char *buf,
- int bufsz, FILE *iob)
+m_getfld (m_getfld_state_t *gstate, unsigned char name[NAMESZ],
+ unsigned char *buf, int *bufsz, FILE *iob)
{
- register unsigned char *bp, *cp, *ep, *sp;
- register int cnt, c, i, j;
+ m_getfld_state_t s;
+ register unsigned char *cp;
+ register int max, n, c;
- if ((c = Getc(iob)) < 0) {
- msg_count = 0;
- *buf = 0;
- return FILEEOF;
+ enter_getfld (gstate, iob);
+ s = *gstate;
+
+ if ((c = Getc(s)) < 0) {
+ *bufsz = *buf = 0;
+ leave_getfld (s);
+ return s->state = FILEEOF;
}
- if (eom (c, iob)) {
- if (! eom_action) {
+ if (eom (c, s)) {
+ if (! s->eom_action) {
/* flush null messages */
- while ((c = Getc(iob)) >= 0 && eom (c, iob))
+ while ((c = Getc(s)) >= 0 && eom (c, s))
;
+
if (c >= 0)
- ungetc(c, iob);
+ Ungetc(c, s);
}
- msg_count = 0;
- *buf = 0;
- return FILEEOF;
+ *bufsz = *buf = 0;
+ leave_getfld (s);
+ return s->state = FILEEOF;
}
- switch (state) {
- case FLDEOF:
- case BODYEOF:
- case FLD:
+ switch (s->state) {
+ case FLD:
if (c == '\n' || c == '-') {
/* we hit the header/body separator */
- while (c != '\n' && (c = Getc(iob)) >= 0)
- ;
+ while (c != '\n' && (c = Getc(s)) >= 0) continue;
- if (c < 0 || (c = Getc(iob)) < 0 || eom (c, iob)) {
- if (! eom_action) {
+ if (c < 0 || (c = Getc(s)) < 0 || eom (c, s)) {
+ if (! s->eom_action) {
/* flush null messages */
- while ((c = Getc(iob)) >= 0 && eom (c, iob))
+ while ((c = Getc(s)) >= 0 && eom (c, s))
;
if (c >= 0)
- ungetc(c, iob);
+ Ungetc(c, s);
}
- msg_count = 0;
- *buf = 0;
- return FILEEOF;
+ *bufsz = *buf = 0;
+ leave_getfld (s);
+ return s->state = FILEEOF;
}
- state = BODY;
+ s->state = BODY;
goto body;
}
/*
* get the name of this component. take characters up
* to a ':', a newline or NAMESZ-1 characters, whichever
- * comes first.
+ * comes first.
*/
cp = name;
- i = NAMESZ - 1;
- for (;;) {
-#ifdef LINUX_STDIO
- bp = sp = (unsigned char *) iob->_IO_read_ptr - 1;
- j = (cnt = ((long) iob->_IO_read_end -
- (long) iob->_IO_read_ptr) + 1) < i ? cnt : i;
-#elif defined(__DragonFly__)
- bp = sp = (unsigned char *) ((struct __FILE_public *)iob)->_p - 1;
- j = (cnt = ((struct __FILE_public *)iob)->_r+1) < i ? cnt : i;
-#else
- bp = sp = (unsigned char *) iob->_ptr - 1;
- j = (cnt = iob->_cnt+1) < i ? cnt : i;
-#endif
- while (--j >= 0 && (c = *bp++) != ':' && c != '\n')
- *cp++ = c;
-
- j = bp - sp;
- if ((cnt -= j) <= 0) {
-#ifdef LINUX_STDIO
- iob->_IO_read_ptr = iob->_IO_read_end;
- if (__underflow(iob) == EOF) {
-#elif defined(__DragonFly__)
- if (__srget(iob) == EOF) {
-#else
- if (_filbuf(iob) == EOF) {
-#endif
- *cp = *buf = 0;
- advise (NULL, "eof encountered in field \"%s\"", name);
- return FMTERR;
- }
-#ifdef LINUX_STDIO
- iob->_IO_read_ptr++; /* NOT automatic in __underflow()! */
-#endif
- } else {
-#ifdef LINUX_STDIO
- iob->_IO_read_ptr = bp + 1;
-#elif defined(__DragonFly__)
- ((struct __FILE_public *)iob)->_p = bp + 1;
- ((struct __FILE_public *)iob)->_r = cnt - 1;
-#else
- iob->_ptr = bp + 1;
- iob->_cnt = cnt - 1;
-#endif
- }
- if (c == ':')
- break;
+ max = NAMESZ - 1;
+ /* Get the field name. The first time through the loop,
+ this copies out the first character, which was loaded
+ into c prior to loop entry. Initialize n to 1 to
+ account for that. */
+ for (n = 1;
+ c != ':' && c != '\n' && c != EOF && n < max;
+ ++n, c = Getc (s)) {
+ *cp++ = c;
+ }
- /*
- * something went wrong. possibilities are:
- * . hit a newline (error)
- * . got more than namesz chars. (error)
- * . hit the end of the buffer. (loop)
- */
- if (c == '\n') {
- /* We hit the end of the line without seeing ':' to
- * terminate the field name. This is usually (always?)
- * spam. But, blowing up is lame, especially when
- * scan(1)ing a folder with such messages. Pretend such
- * lines are the first of the body (at least mutt also
- * handles it this way). */
-
- /* See if buf can hold this line, since we were assuming
- * we had a buffer of NAMESZ, not bufsz. */
- /* + 1 for the newline */
- if (bufsz < j + 1) {
- /* No, it can't. Oh well, guess we'll blow up. */
- *cp = *buf = 0;
- advise (NULL, "eol encountered in field \"%s\"", name);
- state = FMTERR;
- goto finish;
- }
- memcpy (buf, name, j - 1);
- buf[j - 1] = '\n';
- buf[j] = '\0';
- /* mhparse.c:get_content wants to find the position of the
- * body start, but it thinks there's a blank line between
- * the header and the body (naturally!), so seek back so
- * that things line up even though we don't have that
- * blank line in this case. Simpler parsers (e.g. mhl)
- * get extra newlines, but that should be harmless enough,
- * right? This is a corrupt message anyway. */
- fseek (iob, ftell (iob) - 2, SEEK_SET);
- return BODY;
+ /* Check for next character, which is either the space after
+ the ':' or the first folded whitespace. */
+ {
+ int next_char;
+ if (c == EOF || (next_char = Peek (s)) == EOF) {
+ *bufsz = *cp = *buf = 0;
+ advise (NULL, "eof encountered in field \"%s\"", name);
+ leave_getfld (s);
+ return s->state = FMTERR;
}
- if ((i -= j) <= 0) {
- *cp = *buf = 0;
- advise (NULL, "field name \"%s\" exceeds %d bytes", name, NAMESZ - 2);
- state = LENERR;
- goto finish;
+ }
+
+ /* If c isn't ':' here, something went wrong. Possibilities are:
+ * . hit a newline (error)
+ * . got more than namesz chars. (error)
+ */
+ if (c == ':') {
+ /* Finished header name, fall through to FLDPLUS below. */
+ } else if (c == '\n') {
+ /* We hit the end of the line without seeing ':' to
+ * terminate the field name. This is usually (always?)
+ * spam. But, blowing up is lame, especially when
+ * scan(1)ing a folder with such messages. Pretend such
+ * lines are the first of the body (at least mutt also
+ * handles it this way). */
+
+ /* See if buf can hold this line, since we were assuming
+ * we had a buffer of NAMESZ, not bufsz. */
+ /* + 1 for the newline */
+ if (*bufsz < n + 1) {
+ /* No, it can't. Oh well, guess we'll blow up. */
+ *bufsz = *cp = *buf = 0;
+ advise (NULL, "eol encountered in field \"%s\"", name);
+ s->state = FMTERR;
+ break;
}
+ memcpy (buf, name, n - 1);
+ buf[n - 1] = '\n';
+ buf[n] = '\0';
+ /* The last character read was '\n'. s->bytes_read
+ (and n) include that, but it was not put into the
+ name array in the for loop above. So subtract 1. */
+ *bufsz = --s->bytes_read; /* == n - 1 */
+ leave_getfld (s);
+ return s->state = BODY;
+ } else if (max <= n) {
+ /* By design, the loop above discards the last character
+ it had read. It's in c, use it. */
+ *cp++ = c;
+ *bufsz = *cp = *buf = 0;
+ advise (NULL, "field name \"%s\" exceeds %d bytes", name,
+ NAMESZ - 2);
+ s->state = LENERR;
+ break;
}
- while (isspace (*--cp) && cp >= name)
- ;
+ /* Trim any trailing spaces from the end of name. */
+ while (isspace (*--cp) && cp >= name) continue;
*++cp = 0;
+ /* readpos points to the first character of the field body. */
/* fall through */
- case FLDPLUS:
+ case FLDPLUS: {
/*
- * get (more of) the text of a field. take
+ * get (more of) the text of a field. Take
* characters up to the end of this field (newline
* followed by non-blank) or bufsz-1 characters.
*/
- cp = buf; i = bufsz-1;
- for (;;) {
-#ifdef LINUX_STDIO
- cnt = (long) iob->_IO_read_end - (long) iob->_IO_read_ptr;
- bp = (unsigned char *) --iob->_IO_read_ptr;
-#elif defined(__DragonFly__)
- cnt = ((struct __FILE_public *)iob)->_r++;
- bp = (unsigned char *) --((struct __FILE_public *)iob)->_p;
-#else
- cnt = iob->_cnt++;
- bp = (unsigned char *) --iob->_ptr;
-#endif
- c = cnt < i ? cnt : i;
- while ((ep = locc( c, bp, '\n' ))) {
- /*
- * if we hit the end of this field, return.
- */
- if ((j = *++ep) != ' ' && j != '\t') {
-#ifdef LINUX_STDIO
- j = ep - (unsigned char *) iob->_IO_read_ptr;
- memcpy (cp, iob->_IO_read_ptr, j);
- iob->_IO_read_ptr = ep;
-#elif defined(__DragonFly__)
- j = ep - (unsigned char *) ((struct __FILE_public *)iob)->_p;
- memcpy (cp, ((struct __FILE_public *)iob)->_p, j);
- ((struct __FILE_public *)iob)->_p = ep;
- ((struct __FILE_public *)iob)->_r -= j;
-#else
- j = ep - (unsigned char *) iob->_ptr;
- memcpy (cp, iob->_ptr, j);
- iob->_ptr = ep;
- iob->_cnt -= j;
-#endif
- cp += j;
- state = FLD;
- goto finish;
- }
- c -= ep - bp;
- bp = ep;
+ int finished;
+
+ cp = buf;
+ max = *bufsz-1;
+ n = 0;
+ for (finished = 0; ! finished; ) {
+ while (c != '\n' && c != EOF && n++ < max) {
+ *cp++ = c = Getc (s);
}
- /*
- * end of input or dest buffer - copy what we've found.
- */
-#ifdef LINUX_STDIO
- c += bp - (unsigned char *) iob->_IO_read_ptr;
- memcpy( cp, iob->_IO_read_ptr, c);
-#elif defined(__DragonFly__)
- c += bp - (unsigned char *) ((struct __FILE_public *)iob)->_p;
- memcpy( cp, ((struct __FILE_public *)iob)->_p, c);
-#else
- c += bp - (unsigned char *) iob->_ptr;
- memcpy( cp, iob->_ptr, c);
-#endif
- i -= c;
- cp += c;
- if (i <= 0) {
+
+ if (c != EOF) c = Peek (s);
+ if (max < n) {
/* the dest buffer is full */
-#ifdef LINUX_STDIO
- iob->_IO_read_ptr += c;
-#elif defined(__DragonFly__)
- ((struct __FILE_public *)iob)->_r -= c;
- ((struct __FILE_public *)iob)->_p += c;
-#else
- iob->_cnt -= c;
- iob->_ptr += c;
-#endif
- state = FLDPLUS;
- break;
- }
- /*
- * There's one character left in the input buffer.
- * Copy it & fill the buffer. If the last char
- * was a newline and the next char is not whitespace,
- * this is the end of the field. Otherwise loop.
- */
- --i;
-#ifdef LINUX_STDIO
- *cp++ = j = *(iob->_IO_read_ptr + c);
- iob->_IO_read_ptr = iob->_IO_read_end;
- c = __underflow(iob);
- iob->_IO_read_ptr++; /* NOT automatic! */
-#elif defined(__DragonFly__)
- *cp++ =j = *(((struct __FILE_public *)iob)->_p + c);
- c = __srget(iob);
-#else
- *cp++ = j = *(iob->_ptr + c);
- c = _filbuf(iob);
-#endif
- if (c == EOF ||
- ((j == '\0' || j == '\n') && c != ' ' && c != '\t')) {
- if (c != EOF) {
-#ifdef LINUX_STDIO
- --iob->_IO_read_ptr;
-#elif defined(__DragonFly__)
- --((struct __FILE_public *)iob)->_p;
- ++((struct __FILE_public *)iob)->_r;
-#else
- --iob->_ptr;
- ++iob->_cnt;
-#endif
- }
- state = FLD;
- break;
+ s->state = FLDPLUS;
+ finished = 1;
+ } else if (c != ' ' && c != '\t') {
+ /* The next character is not folded whitespace, so
+ prepare to move on to the next field. It's OK
+ if c is EOF, it will be handled on the next
+ call to m_getfld (). */
+ s->state = FLD;
+ finished = 1;
+ } else {
+ /* Folded header field, continues on the next line. */
}
}
+ *bufsz = s->bytes_read;
break;
+ }
- case BODY:
body:
+ case BODY: {
/*
* get the message body up to bufsz characters or the
- * end of the message. Sleazy hack: if bufsz is negative
- * we assume that we were called to copy directly into
- * the output buffer and we don't add an eos.
+ * end of the message.
*/
- i = (bufsz < 0) ? -bufsz : bufsz-1;
-#ifdef LINUX_STDIO
- bp = (unsigned char *) --iob->_IO_read_ptr;
- cnt = (long) iob->_IO_read_end - (long) iob->_IO_read_ptr;
-#elif defined(__DragonFly__)
- bp = (unsigned char *) --((struct __FILE_public *)iob)->_p;
- cnt = ++((struct __FILE_public *)iob)->_r;
-#else
- bp = (unsigned char *) --iob->_ptr;
- cnt = ++iob->_cnt;
-#endif
- c = (cnt < i ? cnt : i);
- if (msg_style != MS_DEFAULT && c > 1) {
+ unsigned char *bp;
+
+ max = *bufsz-1;
+ /* Back up and store the current position. */
+ bp = --s->readpos;
+ c = s->end - s->readpos < max ? s->end - s->readpos : max;
+ if (s->msg_style != MS_DEFAULT && c > 1) {
/*
* packed maildrop - only take up to the (possible)
* start of the next message. This "matchc" should
* algorithms vs. brute force.) Since I (currently)
* run MH on a vax, we use the matchc instruction. --vj
*/
- if ((ep = matchc( fdelimlen, fdelim, c, bp )))
+ unsigned char *ep;
+
+ if ((ep = matchc( s->fdelimlen, s->fdelim, c, bp )))
c = ep - bp + 1;
else {
/*
* ends with one of the characters in the pattern
* (excluding the first and last), we do only one test.
*/
+ unsigned char *sp;
+
ep = bp + c - 1;
- if ((sp = pat_map[*ep])) {
+ if ((sp = s->pat_map[*ep])) {
do {
/* This if() is true unless (a) the buffer is too
* small to contain this delimiter prefix, or
* should have found it. Thus it's not a delim
* and we know we won't get a match.
*/
- if (((sp - fdelim) + 2) <= c) {
+ if (((sp - s->fdelim) + 2) <= c) {
cp = sp;
/* Unfortunately although fdelim has a preceding NUL
* we can't use this as a sentinel in case the buffer
* would cause us to run off the front of fdelim).
*/
while (*--ep == *--cp)
- if (cp < fdelim)
+ if (cp < s->fdelim)
break;
- if (cp < fdelim) {
+ if (cp < s->fdelim) {
/* we matched the entire delim prefix,
* so only take the buffer up to there.
* we know ep >= bp -- check above prevents underrun
}
/* try matching one less char of delim string */
ep = bp + c - 1;
- } while (--sp > fdelim);
+ } while (--sp > s->fdelim);
}
}
}
memcpy( buf, bp, c );
-#ifdef LINUX_STDIO
- iob->_IO_read_ptr += c;
-#elif defined(__DragonFly__)
- ((struct __FILE_public *)iob)->_r -= c;
- ((struct __FILE_public *)iob)->_p += c;
-#else
- iob->_cnt -= c;
- iob->_ptr += c;
-#endif
- if (bufsz < 0) {
- msg_count = c;
- return (state);
- }
+ /* Advance the current position to reflect the copy out.
+ c is less than or equal to the number of bytes remaining
+ in the read buffer, so will not overrun it. */
+ s->readpos += c;
cp = buf + c;
+ /* Subtract 1 from c because the first character was read by
+ Getc(), and therefore already accounted for in s->bytes_read. */
+ s->bytes_read += c - 1;
+ *bufsz = s->bytes_read;
break;
+ }
- default:
- adios (NULL, "m_getfld() called with bogus state of %d", state);
+ default:
+ adios (NULL, "m_getfld() called with bogus state of %d", s->state);
}
-finish:
+
*cp = 0;
- msg_count = cp - buf;
- return (state);
+ leave_getfld (s);
+
+ return s->state;
}
void
-m_unknown(FILE *iob)
+m_unknown(m_getfld_state_t *gstate, FILE *iob)
{
+ m_getfld_state_t s;
register int c;
- register long pos;
- char text[10];
+ char text[MAX_DELIMITER_SIZE];
+ char from[] = "From ";
register char *cp;
register char *delimstr;
+ unsigned int i;
+
+ enter_getfld (gstate, iob);
+ s = *gstate;
/*
* Figure out what the message delimitter string is for this
* specified when nmh was built (or from the mts.conf file).
*/
- msg_style = MS_UNKNOWN;
+ s->msg_style = MS_UNKNOWN;
+
+ for (i = 0, cp = text; i < sizeof text; ++i, ++cp) {
+ if ((*cp = Getc (s)) == EOF) {
+ break;
+ }
+ }
- pos = ftell (iob);
- if (fread (text, sizeof(*text), 5, iob) == 5
- && strncmp (text, "From ", 5) == 0) {
- msg_style = MS_MBOX;
+ if (i == sizeof from-1 && strncmp (text, "From ", sizeof from-1) == 0) {
+ s->msg_style = MS_MBOX;
delimstr = "\nFrom ";
- while ((c = getc (iob)) != '\n' && c >= 0)
- ;
+ while ((c = Getc (s)) != '\n' && c >= 0) continue;
} else {
/* not a Unix style maildrop */
- fseek (iob, pos, SEEK_SET);
- if (mmdlm2 == NULL || *mmdlm2 == 0)
- mmdlm2 = "\001\001\001\001\n";
+ s->readpos -= s->bytes_read;
delimstr = mmdlm2;
- msg_style = MS_MMDF;
+ s->msg_style = MS_MMDF;
}
c = strlen (delimstr);
- fdelim = (unsigned char *) mh_xmalloc((size_t) (c + 3));
- *fdelim++ = '\0';
- *fdelim = '\n';
- msg_delim = (char *)fdelim+1;
- edelim = (unsigned char *)msg_delim+1;
- fdelimlen = c + 1;
- edelimlen = c - 1;
- strcpy (msg_delim, delimstr);
- delimend = (unsigned char *)msg_delim + edelimlen;
- if (edelimlen <= 1)
+ s->fdelim = (unsigned char *) mh_xmalloc((size_t) (c + 3));
+ *s->fdelim++ = '\0';
+ *s->fdelim = '\n';
+ s->msg_delim = (char *)s->fdelim+1;
+ s->edelim = (unsigned char *)s->msg_delim+1;
+ s->fdelimlen = c + 1;
+ s->edelimlen = c - 1; /* == strlen (delimstr) */
+ strcpy (s->msg_delim, delimstr);
+ s->delimend = (unsigned char *)s->msg_delim + s->edelimlen;
+ if (s->edelimlen <= 1)
adios (NULL, "maildrop delimiter must be at least 2 bytes");
/*
* build a Boyer-Moore end-position map for the matcher in m_getfld.
* separator) or the last char (since the matchc would have found it
* if it was a real delim).
*/
- pat_map = (unsigned char **) calloc (256, sizeof(unsigned char *));
+ s->pat_map = (unsigned char **) calloc (256, sizeof(unsigned char *));
- for (cp = (char *) fdelim + 1; cp < (char *) delimend; cp++ )
- pat_map[(unsigned char)*cp] = (unsigned char *) cp;
+ for (cp = (char *) s->fdelim + 1; cp < (char *) s->delimend; cp++ )
+ s->pat_map[(unsigned char)*cp] = (unsigned char *) cp;
- if (msg_style == MS_MMDF) {
+ if (s->msg_style == MS_MMDF) {
/* flush extra msg hdrs */
- while ((c = Getc(iob)) >= 0 && eom (c, iob))
+ while ((c = Getc(s)) >= 0 && eom (c, s))
;
if (c >= 0)
- ungetc(c, iob);
+ Ungetc(c, s);
}
+
+ leave_getfld (s);
}
void
-m_eomsbr (int (*action)(int))
+m_eomsbr (m_getfld_state_t s, int (*action)(int))
{
- if ((eom_action = action)) {
- msg_style = MS_MSH;
- *msg_delim = 0;
- fdelimlen = 1;
- delimend = fdelim;
+ if ((s->eom_action = action)) {
+ s->msg_style = MS_MSH;
+ *s->msg_delim = 0;
+ s->fdelimlen = 1;
+ s->delimend = s->fdelim;
} else {
- msg_style = MS_MMDF;
- msg_delim = (char *)fdelim + 1;
- fdelimlen = strlen((char *)fdelim);
- delimend = (unsigned char *)(msg_delim + edelimlen);
+ s->msg_style = MS_MMDF;
+ s->msg_delim = (char *)s->fdelim + 1;
+ s->fdelimlen = strlen((char *)s->fdelim);
+ s->delimend = (unsigned char *)(s->msg_delim + s->edelimlen);
}
}
*/
static int
-m_Eom (int c, FILE *iob)
+m_Eom (m_getfld_state_t s, int c)
{
- register long pos = 0L;
register int i;
- char text[10];
+ char text[MAX_DELIMITER_SIZE];
+ char *cp;
- pos = ftell (iob);
- if ((i = fread (text, sizeof *text, edelimlen, iob)) != edelimlen
- || strncmp (text, (char *)edelim, edelimlen)) {
- if (i == 0 && msg_style == MS_MBOX)
+ for (i = 0, cp = text; i < s->edelimlen; ++i, ++cp) {
+ if ((*cp = Getc (s)) == EOF) {
+ break;
+ }
+ }
+
+ if (i != s->edelimlen ||
+ strncmp (text, (char *)s->edelim, s->edelimlen)) {
+ if (i == 0 && s->msg_style == MS_MBOX)
/* the final newline in the (brain damaged) unix-format
* maildrop is part of the delimitter - delete it.
*/
return 1;
-#if 0
- fseek (iob, pos, SEEK_SET);
-#endif
-
- fseek (iob, (long)(pos-1), SEEK_SET);
- getc (iob); /* should be OK */
+ /* Did not find delimiter, so restore the read position.
+ Note that on input, a character had already been read
+ with Getc(). It will be unget by m_getfld () on return. */
+ s->readpos -= s->bytes_read - 1;
return 0;
}
- if (msg_style == MS_MBOX) {
- while ((c = getc (iob)) != '\n')
+ if (s->msg_style == MS_MBOX) {
+ while ((c = Getc (s)) != '\n')
if (c < 0)
break;
}
sp = str; pp = pat;
while (pp < ep && *sp++ == *pp)
pp++;
- if (pp >= ep)
+ if (pp >= ep)
return ((unsigned char *)--str);
}
}
-
-
-/*
- * Locate character "term" in the next "cnt" characters of "src".
- * If found, return its address, otherwise return 0.
- */
-
-static unsigned char *
-locc(int cnt, unsigned char *src, unsigned char term)
-{
- while (*src++ != term && --cnt > 0);
-
- return (cnt > 0 ? --src : (unsigned char *)0);
-}
-
+++ /dev/null
-
-/*
- * m_msgdef.c -- some defines for sbr/m_getfld.c
- *
- * 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 <h/mh.h>
-
-/*
- * disgusting hack for "inc" so it can know how many characters
- * were stuffed in the buffer on the last call (see comments
- * in uip/scansbr.c)
- */
-int msg_count = 0;
-
-int msg_style = MS_DEFAULT;
-
-/*
- * The "full" delimiter string for a packed maildrop consists
- * of a newline followed by the actual delimiter. E.g., the
- * full string for a Unix maildrop would be: "\n\nFrom ".
- * "Fdelim" points to the start of the full string and is used
- * in the BODY case of the main routine to search the buffer for
- * a possible eom. Msg_delim points to the first character of
- * the actual delim. string (i.e., fdelim+1). Edelim
- * points to the 2nd character of actual delimiter string. It
- * is used in m_Eom because the first character of the string
- * has been read and matched before m_Eom is called.
- */
-char *msg_delim = "";
char name[NAMESZ], field[BUFSIZ];
register struct node *np;
register struct procstr *ps;
+ m_getfld_state_t gstate = 0;
if (npp == NULL && (npp = opp) == NULL) {
admonish (NULL, "bug: readconfig called but pump not primed");
return;
}
- for (state = FLD;;) {
- switch (state = m_getfld (state, name, field, sizeof(field), ib)) {
+ for (;;) {
+ int fieldsz = sizeof field;
+ switch (state = m_getfld (&gstate, name, field, &fieldsz, ib)) {
case FLD:
case FLDPLUS:
- case FLDEOF:
np = (struct node *) mh_xmalloc (sizeof(*np));
*npp = np;
*(npp = &np->n_next) = NULL;
if (state == FLDPLUS) {
cp = getcpy (field);
while (state == FLDPLUS) {
- state = m_getfld (state, name, field, sizeof(field), ib);
+ fieldsz = sizeof field;
+ state = m_getfld (&gstate, name, field, &fieldsz, ib);
cp = add (field, cp);
}
np->n_field = trimcpy (cp);
*ps->procnaddr = np->n_field;
break;
}
- if (state == FLDEOF)
- break;
continue;
case BODY:
- case BODYEOF:
adios (NULL, "no blank lines are permitted in %s", file);
case FILEEOF:
}
break;
}
+ m_getfld_state_destroy (&gstate);
/*
* Special handling for the pager processes: lproc and moreproc.
char *cp, seqfile[PATH_MAX];
char name[NAMESZ], field[BUFSIZ];
FILE *fp;
+ m_getfld_state_t gstate = 0;
/*
* If mh_seq == NULL (such as if nmh been compiled with
return;
/* Use m_getfld to scan sequence file */
- for (state = FLD;;) {
- switch (state = m_getfld (state, name, field, sizeof(field), fp)) {
+ for (;;) {
+ int fieldsz = sizeof field;
+ switch (state = m_getfld (&gstate, name, field, &fieldsz, fp)) {
case FLD:
case FLDPLUS:
- case FLDEOF:
if (state == FLDPLUS) {
cp = getcpy (field);
while (state == FLDPLUS) {
- state = m_getfld (state, name, field, sizeof(field), fp);
+ fieldsz = sizeof field;
+ state = m_getfld (&gstate, name, field, &fieldsz, fp);
cp = add (field, cp);
}
seq_init (mp, getcpy (name), trimcpy (cp));
} else {
seq_init (mp, getcpy (name), trimcpy (field));
}
- if (state == FLDEOF)
- break;
continue;
case BODY:
- case BODYEOF:
adios (NULL, "no blank lines are permitted in %s", seqfile);
/* fall */
}
break; /* break from for loop */
}
+ m_getfld_state_destroy (&gstate);
lkfclose (fp, seqfile);
}
continue; /* no match */
for (sp = string; *sp == *tcp++;) {
if (*sp++ == '\0')
- return (tp - swp); /* exact match */
+ return tp->swret; /* exact match */
}
if (*sp) {
if (*sp != ' ')
continue; /* no match */
if (*--tcp == '\0')
- return (tp - swp); /* exact match */
+ return tp->swret; /* exact match */
}
if (firstone == UNKWNSW)
- firstone = tp - swp;
+ firstone = tp->swret;
else
firstone = AMBIGSW;
}
#!/bin/sh
######################################################
#
-# Test bogus headers (no blank line before body).
+# Test bogus headers (no blank line before body, etc.)
#
######################################################
+set -e
+
if test -z "${MH_OBJ_DIR}"; then
srcdir=`dirname "$0"`/../..
MH_OBJ_DIR=`cd "$srcdir" && pwd`; export MH_OBJ_DIR
setup_test
-expected=$MH_TEST_DIR/$$.expected
-actual=$MH_TEST_DIR/$$.actual
+expected="$MH_TEST_DIR/$$.expected"
+expected_err="$MH_TEST_DIR/$$.expected_err"
+actual="$MH_TEST_DIR/$$.actual"
+actual_err="$MH_TEST_DIR/$$.actual_err"
# Write message with bogus header field (missing blank line, really).
-msgfile=`mhpath new`
-msgnum=`basename $msgfile`
-cat > $msgfile <<EOF
+msgfile="$MH_TEST_DIR/Mail/inbox/11"
+cat >"$msgfile" <<EOF
Date: Sun, 18 Dec 2005 00:52:39 +0100
From: foo@example.edu
To: bar@example.edu
EOF
# check scan
-cat > $expected <<EOF
+cat >"$expected" <<EOF
11 12/18 foo@example.edu test<<This is a multi-part message in MIME forma
EOF
-scan -width 80 $msgnum > $actual 2>&1
-check $expected $actual
+scan -width 80 last > "$actual" 2>&1
+check "$expected" "$actual"
# check show (mhl)
-cat > $expected <<EOF
+cat >"$expected" <<EOF
(Message inbox:11)
Date: Sun, 18 Dec 2005 00:52:39 +0100
This is a multi-part message in MIME format.
-
I am a stupid spammer.
EOF
-show $msgnum > $actual 2>&1
-check $expected $actual
+show last > "$actual" 2>&1
+check "$expected" "$actual"
# check mhshow
-cat > $expected <<EOF
+cat >"$expected" <<EOF
Date: Sun, 18 Dec 2005 00:52:39 +0100
To: bar@example.edu
From: foo@example.edu
I am a stupid spammer.
EOF
-mhshow -nopause $msgnum > $actual 2>&1
-check $expected $actual
+mhshow -nopause last > "$actual" 2>&1
+check "$expected" "$actual"
+
+# check m_getfld() handling of empty header field
+msgfile="$MH_TEST_DIR/Mail/inbox/12"
+printf 'Date: Sat, 12 Jan 2013 09:07:01 -0600\nReceived:' >"$msgfile"
+cat >"$expected" <<EOF
+ 12 01/12
+EOF
+cat >"$expected_err" <<EOF
+scan: eof encountered in field "Received"
+??Format error (message 12) in component 2
+EOF
+
+scan -width 13 last >"$actual" 2>"$actual_err"
+check "$expected" "$actual"
+check "$expected_err" "$actual_err"
+
+# check m_getfld() handling of excessively long header field name
+msgfile="$MH_TEST_DIR/Mail/inbox/13"
+cat >"$msgfile" <<EOF
+Date: Tue, 15 Jan 2013 21:13:12 -0600
+ThisHeaderFieldNameIsWaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaayTooLong: OK
+EOF
+cat >"$expected" <<EOF
+ 13 01/15
+EOF
+
+scan -width 13 last >"$actual" 2>"$actual_err"
+check "$expected" "$actual"
+# Cygwin has a BUFSIZ of 1024 so the error message gets truncated.
+# Deal with that by grepping to verify that scan showed the proper error.
+verify_string_in_file() {
+ if grep "$1" "$2" >/dev/null; then
+ :
+ else
+ echo "$0: did not receive expected error message \"$1\""
+ failed=`expr ${failed:-0} + 1`
+ fi
+}
+verify_string_in_file 'scan: field name "ThisHeaderFieldNameIsWa' "$actual_err"
+verify_string_in_file 'exceeds 997' "$actual_err"
+verify_string_in_file '??Format error (message 13) in component 2' "$actual_err"
+rm -f "$actual_err"
+
+# check m_getfld() handling of long header field name without a colon
+msgfile="$MH_TEST_DIR/Mail/inbox/14"
+cat >"$msgfile" <<EOF
+Date: Thu, 17 Jan 2013 19:33:46 -0600
+If a header field name has at least 512 characters without a newline or colon, it will raise a format error in m_getfld(). Here is a test of that. 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901
+
+Test
+
+
+EOF
+cat >"$expected" <<EOF
+ 14 01/17
+EOF
+cat >"$expected_err" <<EOF
+scan: eol encountered in field "If a header field name has at least 512 characters without a newline or colon, it will raise a format error in m_getfld(). Here is a test of that. 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901"
+??Format error (message 14) in component 2
+EOF
+
+scan -width 13 last >"$actual" 2>"$actual_err"
+check "$expected" "$actual"
+check "$expected_err" "$actual_err"
+
exit $failed
test -z "$bindir" && bindir="@bindir@"
test -z "$mandir" && mandir="@mandir@"
test -z "$sysconfdir" && sysconfdir="@sysconfdir@"
-test -z "$pagerpath" && pagerpath="@pagerpath@"
test -z "$MULTIBYTE_ENABLED" && MULTIBYTE_ENABLED="@MULTIBYTE_ENABLED@"
-export MH_TEST_DIR auxexecdir bindir mandir sysconfdir pagerpath
+export MH_TEST_DIR auxexecdir bindir mandir sysconfdir
export MULTIBYTE_ENABLED
test -z "$MH_INST_DIR" && MH_INST_DIR="${MH_TEST_DIR}/inst"
# check -check
cat >"$expected" <<EOF
-sortm: can't parse date field in message 14, continuing...
+sortm: can't parse date field in message 14, will use file modification time
sortm: errors found, no messages sorted
EOF
sed -e 's/Sep//' $MH_TEST_DIR/Mail/inbox/7 > $MH_TEST_DIR/Mail/inbox/14
run_test 'sortm -check -nocheck' \
- "sortm: can't parse date field in message 14, continuing..."
+ "sortm: can't parse date field in message 14, will use file \
+modification time"
scan >"$actual"
check "$expected" "$actual"
--- /dev/null
+#!/bin/sh
+#
+# Test that the right justification feature works correctly.
+#
+
+if test -z "${MH_OBJ_DIR}"; then
+ srcdir=`dirname "$0"`/../..
+ MH_OBJ_DIR=`cd "$srcdir" && pwd`; export MH_OBJ_DIR
+fi
+
+. "$MH_OBJ_DIR/test/common.sh"
+
+setup_test
+
+actual=`${MH_LIB_DIR}/ap -format "%-30(friendly{text})<<End of test" "No Such User <nosuch@user.com>"`
+expected=" No Such User<<End of test"
+##########123456789012345678901234567890
+
+if test x"$actual" != x"$expected"; then
+ echo "$0: right justification test expected:" 1>&2
+ echo " $expected" 1>&2
+ echo "but instead got:" 1>&2
+ echo " $actual" 1>&2
+ failed=`expr ${failed:-0} + 1`
+fi
+
+exit $failed
--- /dev/null
+/*
+ * getcwidth - Get the OS's idea of the width of a combining character
+ *
+ * This code is Copyright (c) 2012, by the authors of nmh. See the
+ * COPYRIGHT file in the root directory of the nmh distribution for
+ * complete copyright information.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef MULTIBYTE_SUPPORT
+#include <locale.h>
+#include <wchar.h>
+#endif
+
+int
+main(int argc, char *argv[])
+{
+ wchar_t c;
+ int charlen;
+ char *p;
+
+ /*
+ * This is the UTF-8 for "n" + U+0308 (Combining Diaeresis)
+ */
+
+ unsigned char string[] = "n\xcc\x88";
+
+ setlocale(LC_ALL, "");
+
+ if (argc != 1) {
+ fprintf(stderr, "Usage: %s\n", argv[0]);
+ fprintf(stderr, "Returns the column width of a UTF-8 "
+ "multibyte character\n");
+ exit(1);
+ }
+
+#ifndef MULTIBYTE_SUPPORT
+ fprintf(stderr, "Nmh was not configured with multibyte support\n");
+ exit(1);
+#else
+ /*
+ * It's not clear to me that we can just call mbtowc() with a
+ * combining character; just to be safe, feed it in a base
+ * character first.
+ */
+
+ mbtowc(NULL, NULL, 0);
+
+ charlen = mbtowc(&c, string, strlen(string));
+
+ if (charlen != 1) {
+ fprintf(stderr, "We expected a beginning character length "
+ "of 1, got %d instead\n", charlen);
+ exit(1);
+ }
+
+ p = string + charlen;
+
+ charlen = mbtowc(&c, p, strlen(p));
+
+ if (charlen != 2) {
+ fprintf(stderr, "We expected a multibyte character length "
+ "of 2, got %d instead\n", charlen);
+ fprintf(stderr, "Are you using a UTF-8 locale?\n");
+ exit(1);
+ }
+
+ printf("%d\n", wcwidth(c));
+
+ exit(0);
+#endif /* MULTIBYTE_SUPPORT */
+}
setup_test
+thisdir="$srcdir/test/inc"
+expected="$MH_TEST_DIR/$$.expected"
+actual="$MH_TEST_DIR/$$.actual"
+
cat > "${MH_TEST_DIR}/test.mbox" <<EOF
From nobody@nowhereville Jan 1 1970
Received: I am the very model of a modern Major-General,
run_test "scan -width 120 +inbox 11" \
" 11+ 03/01 Mr Nobody Who is on first?<<Abbott: Every dollar of it. And why not, the man's entitled to it. Cos"
+# check header field name with ':' character than lands on m_getfld() buffer
+cat >"$MH_TEST_DIR/mess" <<EOF
+Comments: The important characteristic of this message is that the 4097'th
+Comments: byte is the ':' at the end of header field name. That tests some
+Comments: logic in m_getfld (), assuming its MSG_INPUT_SIZE is 4096.
+Comments: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+Comments: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
+Comments: CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
+Comments: DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
+Comments: EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
+Comments: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+Comments: GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
+Comments: HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
+Comments: IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
+Comments: JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ
+Comments: KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
+Comments: LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL
+Comments: MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
+Comments: NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
+Comments: OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
+Comments: PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
+Comments: QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
+Comments: RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
+Comments: SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
+Comments: TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
+Comments: UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
+Comments: VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
+Comments: WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
+Comments: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+Comments: YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
+Comments: ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
+Comments: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+Comments: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+Comments: cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+Comments: dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
+Comments: eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
+Comments: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+Comments: gggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg
+Comments: hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
+Comments: iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii
+Comments: jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj
+Comments: kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
+Comments: llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
+Comments: mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
+Comments: nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn
+Comments: oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
+Comments: pppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp
+Comments: qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
+Comments: rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
+Comments: ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
+Comments: tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
+Comments: uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
+Comments: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
+Comments: wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
+Comments: This is it, the line with the 4097'th character of ':'.
+Comments: From somewhere
+From: No Such User <nosuch@example.com>
+To: Some Other User <someother@example.com>
+Subject: all that and nothing to say?
+Date: Thu, 10 Jan 2013 19:54:01 -0500
+
+EOF
+
+run_test 'scan -width 60 -file '"$MH_TEST_DIR/mess" \
+ ' 1 01/10 No Such User all that and nothing to say?'
+rm -f "$MH_TEST_DIR/mess"
+
+# check m_getfld() handling of fields with trailing whitespace
+# Even though header field names aren't supposed to have spaces (RFC
+# 28220, m_getfld () trims trailing whitespace from them.
+cat >`mhpath new` <<EOF
+Date : Sun, 18 Dec 2005 00:52:39 +0100
+From : foo@example.edu
+To: bar@example.edu
+Subject: test
+EOF
+run_test 'scan last' ' 12 12/18 foo@example.edu test'
+
+# check header field body with more than 511 characters
+cat >"$MH_TEST_DIR/mess" <<EOF
+Comments: The important characteristic of this message is that this header
+ field body is more than 511 bytes long. That tests the logic in
+ m_getfld () for transitioning to the FLDPLUS state. This is the
+ only use for the FLDPLUS state, handling header field bodies that
+ are longer than the buffer used to retrieve them. The trailing
+ newline after the last character is the 512th character. The 511th
+ character, counting all spaces, even the leading one, is*
+From: No Such User <nosuch@example.com>
+To: Some Other User <someother@example.com>
+Subject: FLDPLUS test
+Date: Wed, 16 Jan 2013 20:33:58 -0600
+
+EOF
+
+run_test 'scan -width 80 -file '"$MH_TEST_DIR"'/mess' \
+ ' 1 01/16 No Such User FLDPLUS test'
+rm -f "$MH_TEST_DIR/mess"
+
+# check scan and inc of mbox with multiple messages
+echo y | packf -file "$MH_TEST_DIR/msgbox"
+run_test "scan -width 80 -file $MH_TEST_DIR/msgbox" \
+' 1 09/29 Test1 Testing message 1<<This is message number 1 >>
+ 2 09/29 Test2 Testing message 2<<This is message number 2 >>
+ 3 09/29 Test3 Testing message 3<<This is message number 3 >>
+ 4 09/29 Test4 Testing message 4<<This is message number 4 >>
+ 5 09/29 Test5 Testing message 5<<This is message number 5 >>
+ 6 09/29 Test6 Testing message 6<<This is message number 6 >>
+ 7 09/29 Test7 Testing message 7<<This is message number 7 >>
+ 8 09/29 Test8 Testing message 8<<This is message number 8 >>
+ 9 09/29 Test9 Testing message 9<<This is message number 9 >>
+ 10 09/29 Test10 Testing message 10<<This is message number 10 >>
+ 11 03/01 Mr Nobody Who is on first?<<Abbott: Every dollar of it. An
+ 12 12/18 foo@example.edu test'
+run_test "inc -width 80 -file $MH_TEST_DIR/msgbox -truncate" \
+'Incorporating new mail into inbox...
+
+ 13+ 09/29 Test1 Testing message 1<<This is message number 1 >>
+ 14 09/29 Test2 Testing message 2<<This is message number 2 >>
+ 15 09/29 Test3 Testing message 3<<This is message number 3 >>
+ 16 09/29 Test4 Testing message 4<<This is message number 4 >>
+ 17 09/29 Test5 Testing message 5<<This is message number 5 >>
+ 18 09/29 Test6 Testing message 6<<This is message number 6 >>
+ 19 09/29 Test7 Testing message 7<<This is message number 7 >>
+ 20 09/29 Test8 Testing message 8<<This is message number 8 >>
+ 21 09/29 Test9 Testing message 9<<This is message number 9 >>
+ 22 09/29 Test10 Testing message 10<<This is message number 10 >>
+ 23 03/01 Mr Nobody Who is on first?<<Abbott: Every dollar of it. An
+ 24 12/18 foo@example.edu test'
+rm -f "$MH_TEST_DIR/msgbox"
+
+
exit ${failed:-0}
testport=65413
HOME="${MH_TEST_DIR}"; export HOME
-echo "default login ${TESTUSER} password ${TESTPASS}" > ${HOME}/.netrc
-chmod 600 ${HOME}/.netrc
+netrc="${HOME}/.netrc"
+echo "default login ${TESTUSER} password ${TESTPASS}" > "$netrc"
+chmod 600 "$netrc"
expected=$MH_TEST_DIR/$$.expected
expected_err=$MH_TEST_DIR/$$.expected_err
"Incorporating new mail into inbox...
11+ 12/17 No Such User Hello<<Hey man, how's it going? . Hope you're do"
+check $testmessage `mhpath +inbox 11` 'keep first'
-check `mhpath +inbox 11` $testmessage
-rm -f $testmessage
+# check -pack
+pid=`"${MH_OBJ_DIR}/test/fakepop" "$testmessage" "$testport" \
+ "$TESTUSER" "$TESTPASS"`
+
+touch "$MH_TEST_DIR/inc.mbox"
+run_test "inc -user ${TESTUSER} -host 127.0.0.1 -port $testport -width 80 \
+ -pack $MH_TEST_DIR/inc.mbox" \
+ "Incorporating new mail into (null)...
+
+ 1 12/17 No Such User Hello<<Hey man, how's it going? . Hope you're do"
+run_test "inc -file $MH_TEST_DIR/inc.mbox -truncate" \
+ "Incorporating new mail into inbox...
+
+ 11+ 12/17 No Such User Hello<<Hey man, how's it going? . Hope you're do"
+
+check $testmessage `mhpath +inbox 11`
+rm -f "$MH_TEST_DIR/inc.mbox" "$MH_TEST_DIR/.inc.map" "$netrc"
exit ${failed:-0}
Subject: Test
Nmh-Attachment: $MH_TEST_DIR/attachment.txt
-¡Ay, caramba!
+¡Ay, caramba!
EOF
cat > "${testname}.expected" <<EOF
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable
-=A1Ay, caramba!
+=C2=A1Ay, caramba!
------- =_aaaaaaaaaa0
Content-Type: text/plain; name="attachment.txt"
rm -f ${MHMTSCONF} "${MH_TEST_DIR}/attachment.txt"
exit ${failed:-0}
+
+# emacs hackage to ensure that it writes the inverted exclamation
+# point as UTF-8 multibyte character \xC2\xA1 instead of just \xA1.
+# Local Variables:
+# coding: utf-8
+# End:
700
$bindir/inc
$auxexecdir/install-mh
-$pagerpath
+more
$bindir/mhmail
$MH_INST_DIR$auxexecdir/mhl
cat
--- /dev/null
+#!/bin/sh
+######################################################
+#
+# Test m_getfld() with various parts of messages
+# falling on buffer boundaries
+#
+######################################################
+
+set -e
+
+if test -z "${MH_OBJ_DIR}"; then
+ srcdir=`dirname "$0"`/../..
+ MH_OBJ_DIR=`cd "$srcdir" && pwd`; export MH_OBJ_DIR
+fi
+
+. "$MH_OBJ_DIR/test/common.sh"
+
+setup_test
+
+expected="$MH_TEST_DIR/$$.expected"
+actual="$MH_TEST_DIR/$$.actual"
+
+# check a boundary condition in m_getfld(): its internal message
+# buffer holds exactly up to the end of a header field body in a
+# message part
+msgfile=`mhpath new`
+msgnum=`basename $msgfile`
+cat >"$msgfile" <<EOF
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary="NextPart_001"
+Content-class: urn:content-classes:message
+Date: Thu, 19 May 2011 00:00:00 -0000
+From: sender@example.com
+To: recipient@example.com
+
+This is a multi-part message in MIME format.
+
+--NextPart_001
+Content-Type: multipart/related;
+ type="multipart/alternative";
+ boundary="NextPart_002"
+
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXX
+
+--NextPart_002
+Content-Type: text/plain;
+ charset="utf-8"
+
+This is the text/plain part.
+
+--NextPart_002--
+
+--NextPart_001--
+EOF
+
+# Write the expected output.
+cat >"$expected" <<EOF
+part 1.1 text/plain 29
+This is the text/plain part.
+EOF
+
+mhshow -part 1.1 -form mhl.null -nopause $msgnum >"$actual" 2>&1
+check "$expected" "$actual"
+
+# check a boundary condition in m_getfld(): its internal message
+# buffer holds exactly up to the end of a header field name in a
+# message part
+msgfile=`mhpath new`
+msgnum=`basename $msgfile`
+cat >"$msgfile" <<EOF
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary="NextPart_001"
+Content-class: urn:content-classes:message
+Date: Thu, 19 May 2011 00:00:00 -0000
+From: sender@example.com
+To: recipient@example.com
+
+This is a multi-part message in MIME format.
+
+--NextPart_001
+Content-Type: multipart/related;
+ type="multipart/alternative";
+ boundary="NextPart_002"
+
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+
+--NextPart_002
+Content-Type: text/plain;
+ charset="utf-8"
+
+This is the text/plain part.
+
+--NextPart_002--
+
+--NextPart_001--
+EOF
+
+# Write the expected output.
+cat >"$expected" <<EOF
+part 1.1 text/plain 29
+This is the text/plain part.
+EOF
+
+mhshow -part 1.1 -form mhl.null -nopause $msgnum >"$actual" 2>&1
+check "$expected" "$actual"
+
+# check a boundary condition in m_getfld(): its internal message
+# buffer holds exactly up to the end of a message part boundary
+msgfile=`mhpath new`
+msgnum=`basename $msgfile`
+cat >"$msgfile" <<EOF
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary="NextPart_001"
+Content-class: urn:content-classes:message
+Date: Thu, 19 May 2011 00:00:00 -0000
+From: sender@example.com
+To: recipient@example.com
+
+This is a multi-part message in MIME format.
+
+--NextPart_001
+Content-Type: multipart/related;
+ type="multipart/alternative";
+ boundary="NextPart_002"
+
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+XXXXXXXX
+The 4096'th character is the '2' at the end of the following NextPart_002.
+
+--NextPart_002
+Content-Type: text/plain;
+ charset="utf-8"
+
+This is the text/plain part.
+
+--NextPart_002--
+
+--NextPart_001--
+EOF
+
+# Write the expected output.
+cat >"$expected" <<EOF
+part 1.1 text/plain 29
+This is the text/plain part.
+EOF
+
+mhshow -part 1.1 -form mhl.null -nopause $msgnum >"$actual" 2>&1
+check "$expected" "$actual"
+
+
+exit $failed
setup_test
-expected=$MH_TEST_DIR/$$.expected
-actual=$MH_TEST_DIR/$$.actual
+expected="$MH_TEST_DIR/$$.expected"
+actual="$MH_TEST_DIR/$$.actual"
-cat > $expected <<EOF
+cat >"$expected" <<EOF
1 09/29 Test1 Testing message 1<<This is message number 1 >>
2 09/29 Test2 Testing message 2<<This is message number 2 >>
3 09/29 Test3 Testing message 3<<This is message number 3 >>
10 09/29 Test10 Testing message 10<<This is message number 10 >>
EOF
-scan +inbox -width 80 > $actual || exit 1
-
+scan +inbox -width 80 >"$actual" || exit 1
check "$expected" "$actual"
# check highlighting
-cat > $expected <<EOF
+cat >"$expected" <<EOF
1 09/29 Test1 Testing message 1<<This is message number 1 >>\e[m
2 09/29 Test2 Testing message 2<<This is message number 2 >>\e[m
3 09/29 Test3 Testing message 3<<This is message number 3 >>\e[m
printf 'Unseen-Sequence: unseen\n' >> $MH
mark -sequence cur 5
mark -sequence unseen 10
-scan -form scan.highlighted -width 80 > $actual || exit 1
-
+scan -form scan.highlighted -width 80 >"$actual" || exit 1
check "$expected" "$actual"
#
# Create a test message with RFC 2047 headers we can scan
#
+# In this Subject header in this message is a "n" with a Combining Diaeresis
+# (U+0308). There is different interpretation of this character with respect
+# to wcwidth() (which is supposed to return the column width of a character).
+# We use a test program to determine what the output width of U+0308 is
+# and adjust our test output appropriately.
+#
cat > "${MH_TEST_DIR}/Mail/inbox/11" <<EOF
From: David =?utf-8?q?=EF=AC=86?= Hubbins <hubbins@example.com>
To: Sir Denis =?utf-8?q?Eton=E2=80=93Hogg? <sirdenis@example.com>
Date: Friday, 2 Mar 1984 00:00:00
-Subject: =?utf-8?q?Spin=CC=88al_Tap_=E2=86=92_Tap_into_America!?=
+Subject: =?utf-8?q?Sp=C4=B1n=CC=88al_Tap_=E2=86=92_Tap_into_America!?=
Things are looking great!
EOF
-expected=$MH_TEST_DIR/$$.expected
-actual=$MH_TEST_DIR/$$.actual
+width=`${MH_OBJ_DIR}/test/getcwidth`
+if test $? -ne 0; then
+ echo "getcwidth failed to run"
+ exit 1
+fi
+
+expected="$MH_TEST_DIR/$$.expected"
+actual="$MH_TEST_DIR/$$.actual"
-cat > $expected <<EOF
- 11 03/02 David st Hubbins Spin̈al Tap → Tap into America!<<Things are
+if test "$width" -eq 1; then
+cat > "$expected" <<EOF
+ 11 03/02 David st Hubbins Spın̈al Tap → Tap into America!<<Things are look
+EOF
+elif test "$width" -eq 0; then
+cat > "$expected" <<EOF
+ 11 03/02 David st Hubbins Spın̈al Tap → Tap into America!<<Things are looki
EOF
+else
+ echo "Unsupported width for combining diaeresis: $width"
+ exit 1
+fi
scan -width 80 +inbox 11 > $actual || exit 1
+check "$expected" "$actual"
+
+# check decoding with an invalid multibyte sequence
+cat >`mhpath new` <<EOF
+From: Test12 <test12@example.com>
+To: Some User <user@example.com>
+Date: Mon, 31 Dec 2012 00:00:00
+Message-Id: 12@test.nmh
+Subject: =?UTF-8?B?MjAxMyBOZXcgWWVhcuKAmXMgRGVhbHMhIFN0YXJ0IHRoZSB5ZWFy?=
+ =?UTF-8?B?IHJpZ2h0IHdpdGggYmlnIHNhdmluZ3M=?=
+
+This message has an encoded Subject with an invalid character for the
+ISO-8859-1 character set, but it (U+2019) is valid UTF-8.
+EOF
+
+cat >"$expected" <<EOF
+ 12 12/31 Test12 2013 New Year?s Deals! Start the year right
+EOF
+
+LC_CTYPE=ISO-8859-1 MM_CHARSET=ISO-8859-1 scan -width 75 last >"$actual"
+check "$expected" "$actual"
+
+# check scan width with a valid multibyte sequence
+cat >"$expected" <<EOF
+ 12 12/31 Test12 2013 New Year’s Deals! Start the year right
+EOF
+LC_CTYPE=en_US.UTF-8 MM_CHARSET=UTF-8 scan -width 75 last >"$actual"
check "$expected" "$actual"
+
exit $failed
--- /dev/null
+#!/bin/sh
+############################################################
+#
+# Test to see if a out-of-range sequence is handled properly
+#
+############################################################
+
+set -e
+
+if test -z "${MH_OBJ_DIR}"; then
+ srcdir=`dirname $0`/../..
+ MH_OBJ_DIR=`cd $srcdir && pwd`; export MH_OBJ_DIR
+fi
+
+. "$MH_OBJ_DIR/test/common.sh"
+
+setup_test
+
+cat > $MH_TEST_DIR/Mail/inbox/.mh_sequences <<EOS
+cur: 120
+test: 121
+EOS
+
+run_test 'mhpath +inbox test' 'mhpath: sequence test empty'
+
+cat > $MH_TEST_DIR/Mail/inbox/.mh_sequences <<EOS
+cur: 120
+test: 121
+EOS
+
+#
+# Yes, this is right. "cur" is special in that it can refer to messages
+# that don't exist.
+#
+run_test 'mhpath +inbox cur' "$MH_TEST_DIR/Mail/inbox/120"
+
+exit $failed
#include <h/mts.h>
#include <h/utils.h>
-static struct swit switches[] = {
-#define ALIASW 0
- { "alias aliasfile", 0 },
-#define NALIASW 1
- { "noalias", -7 },
-#define LISTSW 2
- { "list", 0 },
-#define NLISTSW 3
- { "nolist", 0 },
-#define NORMSW 4
- { "normalize", 0 },
-#define NNORMSW 5
- { "nonormalize", 0 },
-#define USERSW 6
- { "user", 0 },
-#define NUSERSW 7
- { "nouser", 0 },
-#define VERSIONSW 8
- { "version", 0 },
-#define HELPSW 9
- { "help", 0 },
- { NULL, 0 }
-};
+#define ALI_SWITCHES \
+ X("alias aliasfile", 0, ALIASW) \
+ X("noalias", -7, NALIASW) \
+ X("list", 0, LISTSW) \
+ X("nolist", 0, NLISTSW) \
+ X("normalize", 0, NORMSW) \
+ X("nonormalize", 0, NNORMSW) \
+ X("user", 0, USERSW) \
+ X("nouser", 0, NUSERSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(ALI);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(ALI, switches);
+#undef X
static int pos = 1;
#include <h/mh.h>
#include <h/utils.h>
-static struct swit switches[] = {
-#define COMPSW 0
- { "component field", 0 },
-#define INPLSW 1
- { "inplace", 0 },
-#define NINPLSW 2
- { "noinplace", 0 },
-#define DATESW 3
- { "date", 0 },
-#define NDATESW 4
- { "nodate", 0 },
-#define TEXTSW 5
- { "text body", 0 },
-#define VERSIONSW 6
- { "version", 0 },
-#define HELPSW 7
- { "help", 0 },
-#define DRFTSW 8
- { "draft", 2 },
-#define LISTSW 9
- { "list", 1 },
-#define DELETESW 10
- { "delete", 2 },
-#define NUMBERSW 11
- { "number", 2 },
-#define APPENDSW 12
- { "append", 1 },
-#define PRESERVESW 13
- { "preserve", 1 },
-#define NOPRESERVESW 14
- { "nopreserve", 3 },
- { NULL, 0 }
-};
+#define ANNO_SWITCHES \
+ X("component field", 0, COMPSW) \
+ X("inplace", 0, INPLSW) \
+ X("noinplace", 0, NINPLSW) \
+ X("date", 0, DATESW) \
+ X("nodate", 0, NDATESW) \
+ X("text body", 0, TEXTSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+ X("draft", 2, DRFTSW) \
+ X("list", 1, LISTSW) \
+ X("delete", 2, DELETESW) \
+ X("number", 2, NUMBERSW) \
+ X("append", 1, APPENDSW) \
+ X("preserve", 1, PRESERVESW) \
+ X("nopreserve", 3, NOPRESERVESW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(ANNO);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(ANNO, switches);
+#undef X
/*
* static prototypes
#define FORMAT "%<{error}%{error}: %{text}%|%(putstr(proper{text}))%>"
-static struct swit switches[] = {
-#define FORMSW 0
- { "form formatfile", 0 },
-#define FMTSW 1
- { "format string", 5 },
-#define NORMSW 2
- { "normalize", 0 },
-#define NNORMSW 3
- { "nonormalize", 0 },
-#define WIDTHSW 4
- { "width columns", 0 },
-#define VERSIONSW 5
- { "version", 0 },
-#define HELPSW 6
- { "help", 0 },
- { NULL, 0 }
-};
+#define AP_SWITCHES \
+ X("form formatfile", 0, FORMSW) \
+ X("format string", 5, FMTSW) \
+ X("normalize", 0, NORMSW) \
+ X("nonormalize", 0, NNORMSW) \
+ X("width columns", 0, WIDTHSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(AP);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(AP, switches);
+#undef X
static struct format *fmt;
#include <h/mh.h>
#include <h/utils.h>
-static struct swit switches[] = {
-#define INPLSW 0
- { "inplace", 0 },
-#define NINPLSW 1
- { "noinplace", 0 },
-#define QIETSW 2
- { "quiet", 0 },
-#define NQIETSW 3
- { "noquiet", 0 },
-#define VERBSW 4
- { "verbose", 0 },
-#define NVERBSW 5
- { "noverbose", 0 },
-#define VERSIONSW 6
- { "version", 0 },
-#define HELPSW 7
- { "help", 0 },
- { NULL, 0 }
-};
+#define BURST_SWITCHES \
+ X("inplace", 0, INPLSW) \
+ X("noinplace", 0, NINPLSW) \
+ X("quiet", 0, QIETSW) \
+ X("noquiet", 0, NQIETSW) \
+ X("verbose", 0, VERBSW) \
+ X("noverbose", 0, NVERBSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(BURST);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(BURST, switches);
+#undef X
struct smsg {
off_t s_start;
#include <h/fmt_scan.h>
#include <fcntl.h>
-static struct swit switches[] = {
-#define DFOLDSW 0
- { "draftfolder +folder", 0 },
-#define DMSGSW 1
- { "draftmessage msg", 0 },
-#define NDFLDSW 2
- { "nodraftfolder", 0 },
-#define EDITRSW 3
- { "editor editor", 0 },
-#define NEDITSW 4
- { "noedit", 0 },
-#define FILESW 5
- { "file file", 0 },
-#define FORMSW 6
- { "form formfile", 0 },
-#define USESW 7
- { "use", 0 },
-#define NUSESW 8
- { "nouse", 0 },
-#define WHATSW 9
- { "whatnowproc program", 0 },
-#define NWHATSW 10
- { "nowhatnowproc", 0 },
-#define VERSIONSW 11
- { "version", 0 },
-#define HELPSW 12
- { "help", 0 },
-#define TOSW 13
- { "to address", 0 },
-#define CCSW 14
- { "cc address", 0 },
-#define FROMSW 15
- { "from address", 0 },
-#define FCCSW 16
- { "fcc mailbox", 0 },
-#define WIDTHSW 17
- { "width colums", 0 },
-#define SUBJECTSW 18
- { "subject text", 0 },
- { NULL, 0 }
-};
-
-static struct swit aqrunl[] = {
-#define NOSW 0
- { "quit", 0 },
-#define YESW 1
- { "replace", 0 },
-#define USELSW 2
- { "use", 0 },
-#define LISTDSW 3
- { "list", 0 },
-#define REFILSW 4
- { "refile +folder", 0 },
-#define NEWSW 5
- { "new", 0 },
- { NULL, 0 }
-};
+#define COMP_SWITCHES \
+ X("draftfolder +folder", 0, DFOLDSW) \
+ X("draftmessage msg", 0, DMSGSW) \
+ X("nodraftfolder", 0, NDFLDSW) \
+ X("editor editor", 0, EDITRSW) \
+ X("noedit", 0, NEDITSW) \
+ X("file file", 0, FILESW) \
+ X("form formfile", 0, FORMSW) \
+ X("use", 0, USESW) \
+ X("nouse", 0, NUSESW) \
+ X("whatnowproc program", 0, WHATSW) \
+ X("nowhatnowproc", 0, NWHATSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+ X("to address", 0, TOSW) \
+ X("cc address", 0, CCSW) \
+ X("from address", 0, FROMSW) \
+ X("fcc mailbox", 0, FCCSW) \
+ X("width colums", 0, WIDTHSW) \
+ X("subject text", 0, SUBJECTSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(COMP);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(COMP, switches);
+#undef X
+
+#define DISPO_SWITCHES \
+ X("quit", 0, NOSW) \
+ X("replace", 0, YESW) \
+ X("use", 0, USELSW) \
+ X("list", 0, LISTDSW) \
+ X("refile +folder", 0, REFILSW) \
+ X("new", 0, NEWSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(DISPO);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(DISPO, aqrunl);
+#undef X
static struct swit aqrul[] = {
- { "quit", 0 },
- { "replace", 0 },
- { "use", 0 },
- { "list", 0 },
- { "refile", 0 },
- { NULL, 0 }
+ { "quit", 0, NOSW },
+ { "replace", 0, YESW },
+ { "use", 0, USELSW },
+ { "list", 0, LISTDSW },
+ { "refile", 0, REFILSW },
+ { NULL, 0, 0 }
};
int
*/
#define NGRPS 100
-static struct swit switches[] = {
-#define MAILSW 0
- { "mail name", 0 },
-#define SERCHSW 1
- { "search directory", 0 },
-#define VERSIONSW 2
- { "version", 0 },
-#define HELPSW 3
- { "help", 0 },
- { NULL, 0 }
-};
+#define CONFLICT_SWITCHES \
+ X("mail name", 0, MAILSW) \
+ X("search directory", 0, SERCHSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(CONFLICT);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(CONFLICT, switches);
+#undef X
static char *mail = NULL;
static char *dirs[NDIRS];
#include <h/utils.h>
#include <fcntl.h>
-static struct swit switches[] = {
-#define ANNOSW 0
- { "annotate", 0 },
-#define NANNOSW 1
- { "noannotate", 0 },
-#define DFOLDSW 2
- { "draftfolder +folder", 0 },
-#define DMSGSW 3
- { "draftmessage msg", 0 },
-#define NDFLDSW 4
- { "nodraftfolder", 0 },
-#define EDITRSW 5
- { "editor editor", 0 },
-#define NEDITSW 6
- { "noedit", 0 },
-#define FORMSW 7
- { "form formfile", 0 },
-#define INPLSW 8
- { "inplace", 0 },
-#define NINPLSW 9
- { "noinplace", 0 },
-#define WHATSW 10
- { "whatnowproc program", 0 },
-#define NWHATSW 11
- { "nowhatnowproc", 0 },
-#define VERSIONSW 12
- { "version", 0 },
-#define HELPSW 13
- { "help", 0 },
-#define FILESW 14
- { "file file", -4 }, /* interface from msh */
-#define FROMSW 15
- { "from address", 0 },
-#define TOSW 16
- { "to address", 0 },
-#define CCSW 17
- { "cc address", 0 },
-#define FCCSW 18
- { "fcc mailbox", 0 },
-#define WIDTHSW 19
- { "width columns", 0 },
-#define ATFILESW 20
- { "atfile", 0 },
-#define NOATFILESW 21
- { "noatfile", 0 },
- { NULL, 0 }
-};
-
-static struct swit aqrnl[] = {
-#define NOSW 0
- { "quit", 0 },
-#define YESW 1
- { "replace", 0 },
-#define LISTDSW 2
- { "list", 0 },
-#define REFILSW 3
- { "refile +folder", 0 },
-#define NEWSW 4
- { "new", 0 },
- { NULL, 0 }
-};
+#define DIST_SWITCHES \
+ X("annotate", 0, ANNOSW) \
+ X("noannotate", 0, NANNOSW) \
+ X("draftfolder +folder", 0, DFOLDSW) \
+ X("draftmessage msg", 0, DMSGSW) \
+ X("nodraftfolder", 0, NDFLDSW) \
+ X("editor editor", 0, EDITRSW) \
+ X("noedit", 0, NEDITSW) \
+ X("form formfile", 0, FORMSW) \
+ X("inplace", 0, INPLSW) \
+ X("noinplace", 0, NINPLSW) \
+ X("whatnowproc program", 0, WHATSW) \
+ X("nowhatnowproc", 0, NWHATSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+ X("file file", -4, FILESW) \
+ X("from address", 0, FROMSW) \
+ X("to address", 0, TOSW) \
+ X("cc address", 0, CCSW) \
+ X("fcc mailbox", 0, FCCSW) \
+ X("width columns", 0, WIDTHSW) \
+ X("atfile", 0, ATFILESW) \
+ X("noatfile", 0, NOATFILESW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(DIST);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(DIST, switches);
+#undef X
+
+#define DISPO_SWITCHES \
+ X("quit", 0, NOSW) \
+ X("replace", 0, YESW) \
+ X("list", 0, LISTDSW) \
+ X("refile +folder", 0, REFILSW) \
+ X("new", 0, NEWSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(DISPO);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(DISPO, aqrnl);
+#undef X
static struct swit aqrl[] = {
- { "quit", 0 },
- { "replace", 0 },
- { "list", 0 },
- { "refile +folder", 0 },
- { NULL, 0 }
+ { "quit", 0, NOSW },
+ { "replace", 0, YESW },
+ { "list", 0, LISTDSW },
+ { "refile +folder", 0, REFILSW },
+ { NULL, 0, 0 }
};
register char *resent;
char name[NAMESZ], buffer[BUFSIZ];
register FILE *ifp, *ofp;
+ m_getfld_state_t gstate = 0;
if (rename (drft, strcpy (backup, m_backup (drft))) == NOTOK)
adios (backup, "unable to rename %s to",drft);
lseek (hdrfd, (off_t) 0, SEEK_SET); /* msgnam not accurate */
cpydata (hdrfd, fileno (ofp), msgnam, drft);
- for (state = FLD, resent = NULL;;)
- switch (state =
- m_getfld (state, name, buffer, sizeof buffer, ifp)) {
+ for (resent = NULL;;) {
+ int buffersz = sizeof buffer;
+ switch (state = m_getfld (&gstate, name, buffer, &buffersz, ifp)) {
case FLD:
case FLDPLUS:
- case FLDEOF:
if (uprf (name, "distribute-"))
snprintf (name, sizeof(name), "%s%s", "Resent", &name[10]);
if (uprf (name, "distribution-"))
resent = add (buffer, resent);
fprintf (ofp, "%s: %s", name, buffer);
while (state == FLDPLUS) {
- state = m_getfld (state, name,
- buffer, sizeof buffer, ifp);
+ buffersz = sizeof buffer;
+ state = m_getfld (&gstate, name, buffer, &buffersz, ifp);
resent = add (buffer, resent);
fputs (buffer, ofp);
}
- if (state == FLDEOF)
- goto process;
break;
case BODY:
- case BODYEOF:
for (dp = buffer; *dp; dp++)
if (!isspace (*dp)) {
advise (NULL, BADTXT, "draft");
default:
adios (NULL, "getfld() returned %d", state);
}
+ }
process: ;
+ m_getfld_state_destroy (&gstate);
fclose (ifp);
fflush (ofp);
char name[NAMESZ], buffer[BUFSIZ], tmpfil[BUFSIZ];
register FILE *ifp, *ofp;
char *cp = NULL;
+ m_getfld_state_t gstate = 0;
if (hdrfd != NOTOK)
close (hdrfd), hdrfd = NOTOK;
adios (NULL, "no file descriptors -- you lose big");
unlink (tmpfil);
- for (state = FLD;;)
- switch (state =
- m_getfld (state, name, buffer, sizeof buffer, ifp)) {
+ for (;;) {
+ int buffersz = sizeof buffer;
+ switch (state = m_getfld (&gstate, name, buffer, &buffersz, ifp)) {
case FLD:
case FLDPLUS:
- case FLDEOF:
if (uprf (name, "resent"))
fprintf (ofp, "Prev-");
fprintf (ofp, "%s: %s", name, buffer);
while (state == FLDPLUS) {
- state = m_getfld (state, name,
- buffer, sizeof buffer, ifp);
+ buffersz = sizeof buffer;
+ state = m_getfld (&gstate, name, buffer, &buffersz, ifp);
fputs (buffer, ofp);
}
- if (state == FLDEOF)
- goto process;
break;
case BODY:
- case BODYEOF:
fclose (ofp);
cp = m_mktemp2(NULL, "dist", &txtfd, NULL);
unlink (tmpfil);
fprintf (ofp, "\n%s", buffer);
while (state == BODY) {
- state = m_getfld (state, name,
- buffer, sizeof buffer, ifp);
+ buffersz = sizeof buffer;
+ state = m_getfld (&gstate, name, buffer, &buffersz, ifp);
fputs (buffer, ofp);
}
case FILEEOF:
default:
adios (NULL, "getfld() returned %d", state);
}
+ }
process: ;
+ m_getfld_state_destroy (&gstate);
fclose (ifp);
fclose (ofp);
}
#define FORMAT "%<(nodate{text})error: %{text}%|%(putstr(pretty{text}))%>"
-static struct swit switches[] = {
-#define FORMSW 0
- { "form formatfile", 0 },
-#define FMTSW 1
- { "format string", 5 },
-#define WIDTHSW 2
- { "width columns", 0 },
-#define VERSIONSW 3
- { "version", 0 },
-#define HELPSW 4
- { "help", 0 },
- { NULL, 0 }
-};
+#define DP_SWITCHES \
+ X("form formatfile", 0, FORMSW) \
+ X("format string", 5, FMTSW) \
+ X("width columns", 0, WIDTHSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(DP);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(DP, switches);
+#undef X
static struct format *fmt;
#define MAXFOLDERS 100
-static struct swit switches[] = {
-#define SEQSW 0
- { "sequence name", 0 },
-#define ALLSW 1
- { "all", 0 },
-#define NOALLSW 2
- { "noall", 0 },
-#define RECURSE 3
- { "recurse", 0 },
-#define NORECURSE 4
- { "norecurse", 0 },
-#define SHOWZERO 5
- { "showzero", 0 },
-#define NOSHOWZERO 6
- { "noshowzero", 0 },
-#define ALPHASW 7
- { "alpha", 0 },
-#define NOALPHASW 8
- { "noalpha", 0 },
-#define FASTSW 9
- { "fast", 0 },
-#define NOFASTSW 10
- { "nofast", 0 },
-#define TOTALSW 11
- { "total", -5 },
-#define NOTOTALSW 12
- { "nototal", -7 },
-#define VERSIONSW 13
- { "version", 0 },
-#define HELPSW 14
- { "help", 0 },
- { NULL, 0 }
-};
+#define FLIST_SWITCHES \
+ X("sequence name", 0, SEQSW) \
+ X("all", 0, ALLSW) \
+ X("noall", 0, NOALLSW) \
+ X("recurse", 0, RECURSE) \
+ X("norecurse", 0, NORECURSE) \
+ X("showzero", 0, SHOWZERO) \
+ X("noshowzero", 0, NOSHOWZERO) \
+ X("alpha", 0, ALPHASW) \
+ X("noalpha", 0, NOALPHASW) \
+ X("fast", 0, FASTSW) \
+ X("nofast", 0, NOFASTSW) \
+ X("total", -5, TOTALSW) \
+ X("nototal", -7, NOTOTALSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(FLIST);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(FLIST, switches);
+#undef X
struct Folder {
char *name; /* name of folder */
#include <h/fmt_compile.h>
#include <h/scansbr.h>
-static struct swit switches[] = {
-#define FORMSW 0
- { "form formatfile", 0 },
-#define FMTSW 1
- { "format string", 5 },
-#define VERSIONSW 2
- { "version", 0 },
-#define HELPSW 3
- { "help", 0 },
- { NULL, 0 }
-};
+#define FMTDUMP_SWITCHES \
+ X("form formatfile", 0, FORMSW) \
+ X("format string", 5, FMTSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(FMTDUMP);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(FMTDUMP, switches);
+#undef X
/* for assignlabel */
static struct format *lvec[128];
case FT_FORMATADDR: return("FORMATADDR");
case FT_CONCATADDR: return("CONCATADDR");
case FT_MYMBOX: return("MYMBOX");
-#ifdef FT_ADDTOSEQ
- case FT_ADDTOSEQ: return("ADDTOSEQ");
-#endif
case FT_SAVESTR: return("SAVESTR");
#ifdef FT_PAUSE
case FT_PAUSE: return ("PAUSE");
#include <h/utils.h>
#include <errno.h>
-static struct swit switches[] = {
-#define ALLSW 0
- { "all", 0 },
-#define NALLSW 1
- { "noall", 0 },
-#define CREATSW 2
- { "create", 0 },
-#define NCREATSW 3
- { "nocreate", 0 },
-#define FASTSW 4
- { "fast", 0 },
-#define NFASTSW 5
- { "nofast", 0 },
-#define HDRSW 6
- { "header", 0 },
-#define NHDRSW 7
- { "noheader", 0 },
-#define PACKSW 8
- { "pack", 0 },
-#define NPACKSW 9
- { "nopack", 0 },
-#define VERBSW 10
- { "verbose", 0 },
-#define NVERBSW 11
- { "noverbose", 0 },
-#define RECURSW 12
- { "recurse", 0 },
-#define NRECRSW 13
- { "norecurse", 0 },
-#define TOTALSW 14
- { "total", 0 },
-#define NTOTLSW 15
- { "nototal", 0 },
-#define LISTSW 16
- { "list", 0 },
-#define NLISTSW 17
- { "nolist", 0 },
-#define PRNTSW 18
- { "print", 0 },
-#define NPRNTSW 19
- { "noprint", -4 },
-#define PUSHSW 20
- { "push", 0 },
-#define POPSW 21
- { "pop", 0 },
-#define VERSIONSW 22
- { "version", 0 },
-#define HELPSW 23
- { "help", 0 },
- { NULL, 0 }
-};
+#define FOLDER_SWITCHES \
+ X("all", 0, ALLSW) \
+ X("noall", 0, NALLSW) \
+ X("create", 0, CREATSW) \
+ X("nocreate", 0, NCREATSW) \
+ X("fast", 0, FASTSW) \
+ X("nofast", 0, NFASTSW) \
+ X("header", 0, HDRSW) \
+ X("noheader", 0, NHDRSW) \
+ X("pack", 0, PACKSW) \
+ X("nopack", 0, NPACKSW) \
+ X("verbose", 0, VERBSW) \
+ X("noverbose", 0, NVERBSW) \
+ X("recurse", 0, RECURSW) \
+ X("norecurse", 0, NRECRSW) \
+ X("total", 0, TOTALSW) \
+ X("nototal", 0, NTOTLSW) \
+ X("list", 0, LISTSW) \
+ X("nolist", 0, NLISTSW) \
+ X("print", 0, PRNTSW) \
+ X("noprint", -4, NPRNTSW) \
+ X("push", 0, PUSHSW) \
+ X("pop", 0, POPSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(FOLDER);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(FOLDER, switches);
+#undef X
static int fshort = 0; /* output only folder names */
static int fcreat = 0; /* should we ask to create new folders? */
#define IFORMAT "digest-issue-%s"
#define VFORMAT "digest-volume-%s"
-static struct swit switches[] = {
-#define ANNOSW 0
- { "annotate", 0 },
-#define NANNOSW 1
- { "noannotate", 0 },
-#define DFOLDSW 2
- { "draftfolder +folder", 0 },
-#define DMSGSW 3
- { "draftmessage msg", 0 },
-#define NDFLDSW 4
- { "nodraftfolder", 0 },
-#define EDITRSW 5
- { "editor editor", 0 },
-#define NEDITSW 6
- { "noedit", 0 },
-#define FILTSW 7
- { "filter filterfile", 0 },
-#define FORMSW 8
- { "form formfile", 0 },
-#define FRMTSW 9
- { "format", 5 },
-#define NFRMTSW 10
- { "noformat", 7 },
-#define INPLSW 11
- { "inplace", 0 },
-#define NINPLSW 12
- { "noinplace", 0 },
-#define MIMESW 13
- { "mime", 0 },
-#define NMIMESW 14
- { "nomime", 0 },
-#define DGSTSW 15
- { "digest list", 0 },
-#define ISSUESW 16
- { "issue number", 0 },
-#define VOLUMSW 17
- { "volume number", 0 },
-#define WHATSW 18
- { "whatnowproc program", 0 },
-#define NWHATSW 19
- { "nowhatnowproc", 0 },
-#define BITSTUFFSW 20
- { "dashstuffing", 0 }, /* interface to mhl */
-#define NBITSTUFFSW 21
- { "nodashstuffing", 0 },
-#define VERSIONSW 22
- { "version", 0 },
-#define HELPSW 23
- { "help", 0 },
-#define FILESW 24
- { "file file", 4 }, /* interface from msh */
-#define BILDSW 25
- { "build", 5 }, /* interface from mhe */
-#define FROMSW 26
- { "from address", 0 },
-#define TOSW 27
- { "to address", 0 },
-#define CCSW 28
- { "cc address", 0 },
-#define SUBJECTSW 29
- { "subject text", 0 },
-#define FCCSW 30
- { "fcc mailbox", 0 },
-#define WIDTHSW 31
- { "width columns", 0 },
- { NULL, 0 }
-};
-
-static struct swit aqrnl[] = {
-#define NOSW 0
- { "quit", 0 },
-#define YESW 1
- { "replace", 0 },
-#define LISTDSW 2
- { "list", 0 },
-#define REFILSW 3
- { "refile +folder", 0 },
-#define NEWSW 4
- { "new", 0 },
- { NULL, 0 }
-};
+#define FORW_SWITCHES \
+ X("annotate", 0, ANNOSW) \
+ X("noannotate", 0, NANNOSW) \
+ X("draftfolder +folder", 0, DFOLDSW) \
+ X("draftmessage msg", 0, DMSGSW) \
+ X("nodraftfolder", 0, NDFLDSW) \
+ X("editor editor", 0, EDITRSW) \
+ X("noedit", 0, NEDITSW) \
+ X("filter filterfile", 0, FILTSW) \
+ X("form formfile", 0, FORMSW) \
+ X("format", 5, FRMTSW) \
+ X("noformat", 7, NFRMTSW) \
+ X("inplace", 0, INPLSW) \
+ X("noinplace", 0, NINPLSW) \
+ X("mime", 0, MIMESW) \
+ X("nomime", 0, NMIMESW) \
+ X("digest list", 0, DGSTSW) \
+ X("issue number", 0, ISSUESW) \
+ X("volume number", 0, VOLUMSW) \
+ X("whatnowproc program", 0, WHATSW) \
+ X("nowhatnowproc", 0, NWHATSW) \
+ X("dashstuffing", 0, BITSTUFFSW) /* interface to mhl */ \
+ X("nodashstuffing", 0, NBITSTUFFSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+ X("file file", 4, FILESW) /* interface from msh */ \
+ X("build", 5, BILDSW) /* interface from mhe */ \
+ X("from address", 0, FROMSW) \
+ X("to address", 0, TOSW) \
+ X("cc address", 0, CCSW) \
+ X("subject text", 0, SUBJECTSW) \
+ X("fcc mailbox", 0, FCCSW) \
+ X("width columns", 0, WIDTHSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(FORW);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(FORW, switches);
+#undef X
+
+#define DISPO_SWITCHES \
+ X("quit", 0, NOSW) \
+ X("replace", 0, YESW) \
+ X("list", 0, LISTDSW) \
+ X("refile +folder", 0, REFILSW) \
+ X("new", 0, NEWSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(DISPO);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(DISPO, aqrnl);
+#undef X
static struct swit aqrl[] = {
- { "quit", 0 },
- { "replace", 0 },
- { "list", 0 },
- { "refile +folder", 0 },
- { NULL, 0 }
+ { "quit", 0, NOSW },
+ { "replace", 0, YESW },
+ { "list", 0, LISTDSW },
+ { "refile +folder", 0, REFILSW },
+ { NULL, 0, 0 }
};
static char drft[BUFSIZ];
char *cc, char *fcc, char *subject, char *inputfile)
{
int in;
- int fmtsize, state, char_read = 0;
+ int fmtsize, state;
int i;
register char *nfs;
char *line, tmpfil[BUFSIZ], name[NAMESZ], **ap;
register struct comp *cptr;
struct format *fmt;
char *cp = NULL;
+ m_getfld_state_t gstate = 0;
/*
* Open the message we'll be scanning for components
* these routines?
*/
- for (state = FLD;;) {
- state = m_getfld(state, name, msgbuf, sizeof(msgbuf), tmp);
+ for (;;) {
+ int msg_count = sizeof msgbuf;
+ state = m_getfld (&gstate, name, msgbuf, &msg_count, tmp);
switch (state) {
case FLD:
case FLDPLUS:
i = fmt_addcomptext(name, msgbuf);
if (i != -1) {
- char_read += msg_count;
while (state == FLDPLUS) {
- state = m_getfld(state, name, msgbuf,
- sizeof(msgbuf), tmp);
+ msg_count = sizeof msgbuf;
+ state = m_getfld (&gstate, name, msgbuf, &msg_count, tmp);
fmt_appendcomp(i, name, msgbuf);
- char_read += msg_count;
}
}
- while (state == FLDPLUS)
- state = m_getfld(state, name, msgbuf, sizeof(msgbuf), tmp);
+ while (state == FLDPLUS) {
+ msg_count = sizeof msgbuf;
+ state = m_getfld (&gstate, name, msgbuf, &msg_count, tmp);
+ }
break;
case LENERR:
adios(NULL, "m_getfld() returned %d", state);
}
}
+ m_getfld_state_destroy (&gstate);
/*
* Override any components just in case they were included in the
# define SASLminc(a) 0
#endif
-static struct swit switches[] = {
-#define AUDSW 0
- { "audit audit-file", 0 },
-#define NAUDSW 1
- { "noaudit", 0 },
-#define CHGSW 2
- { "changecur", 0 },
-#define NCHGSW 3
- { "nochangecur", 0 },
-#define FILESW 4
- { "file name", 0 },
-#define FORMSW 5
- { "form formatfile", 0 },
-#define FMTSW 6
- { "format string", 5 },
-#define HOSTSW 7
- { "host hostname", 0 },
-#define USERSW 8
- { "user username", 0 },
-#define PACKSW 9
- { "pack file", 0},
-#define NPACKSW 10
- { "nopack", 0 },
-#define PORTSW 11
- { "port name/number", 0 },
-#define SILSW 12
- { "silent", 0 },
-#define NSILSW 13
- { "nosilent", 0 },
-#define TRNCSW 14
- { "truncate", 0 },
-#define NTRNCSW 15
- { "notruncate", 0 },
-#define WIDTHSW 16
- { "width columns", 0 },
-#define VERSIONSW 17
- { "version", 0 },
-#define HELPSW 18
- { "help", 0 },
-#define SNOOPSW 19
- { "snoop", -5 },
-#define SASLSW 20
- { "sasl", SASLminc(-4) },
-#define NOSASLSW 21
- { "nosasl", SASLminc(-6) },
-#define SASLMECHSW 22
- { "saslmech", SASLminc(-8) },
-#define PROXYSW 23
- { "proxy command", 0 },
- { NULL, 0 }
-};
+#define INC_SWITCHES \
+ X("audit audit-file", 0, AUDSW) \
+ X("noaudit", 0, NAUDSW) \
+ X("changecur", 0, CHGSW) \
+ X("nochangecur", 0, NCHGSW) \
+ X("file name", 0, FILESW) \
+ X("form formatfile", 0, FORMSW) \
+ X("format string", 5, FMTSW) \
+ X("host hostname", 0, HOSTSW) \
+ X("user username", 0, USERSW) \
+ X("pack file", 0, PACKSW) \
+ X("nopack", 0, NPACKSW) \
+ X("port name/number", 0, PORTSW) \
+ X("silent", 0, SILSW) \
+ X("nosilent", 0, NSILSW) \
+ X("truncate", 0, TRNCSW) \
+ X("notruncate", 0, NTRNCSW) \
+ X("width columns", 0, WIDTHSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+ X("snoop", -5, SNOOPSW) \
+ X("sasl", SASLminc(-4), SASLSW) \
+ X("nosasl", SASLminc(-6), NOSASLSW) \
+ X("saslmech", SASLminc(-8), SASLMECHSW) \
+ X("proxy command", 0, PROXYSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(INC);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(INC, switches);
+#undef X
/*
* flags for the mail source
fflush (stdout);
}
+
/*
* Get the mail from a POP server
*/
* Get the mail from file (usually mail spool)
*/
if (inc_type == INC_FILE && Maildir == NULL) {
- m_unknown (in); /* the MAGIC invocation... */
+ scan_detect_mbox_style (in); /* the MAGIC invocation... */
hghnum = msgnum = mp->hghmsg;
for (;;) {
/*
free (Maildir); /* From now on Maildir is just a flag - don't dref! */
}
+ scan_finished ();
+
if (incerr < 0) { /* error */
if (locked) {
GETGROUPPRIVS(); /* Be sure we can unlock mail file */
#include <h/utils.h>
#include <pwd.h> /* structure for getpwuid() results */
-static struct swit switches[] = {
-#define AUTOSW 0
- { "auto", 0 },
-#define VERSIONSW 1
- { "version", 0 },
-#define HELPSW 2
- { "help", 0 },
-#define CHECKSW 3
- { "check", 1 },
- { NULL, 0 }
-};
+#define INSTALLMH_SWITCHES \
+ X("auto", 0, AUTOSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+ X("check", 1, CHECKSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(INSTALLMH);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(INSTALLMH, switches);
+#undef X
/*
* static prototypes
#include <h/mh.h>
#include <h/utils.h>
-static struct swit switches[] = {
-#define ADDSW 0
- { "add", 0 },
-#define DELSW 1
- { "delete", 0 },
-#define LSTSW 2
- { "list", 0 },
-#define SEQSW 3
- { "sequence name", 0 },
-#define PUBLSW 4
- { "public", 0 },
-#define NPUBLSW 5
- { "nopublic", 0 },
-#define ZEROSW 6
- { "zero", 0 },
-#define NZEROSW 7
- { "nozero", 0 },
-#define VERSIONSW 8
- { "version", 0 },
-#define HELPSW 9
- { "help", 0 },
-#define DEBUGSW 10
- { "debug", -5 },
- { NULL, 0 }
-};
+#define MARK_SWITCHES \
+ X("add", 0, ADDSW) \
+ X("delete", 0, DELSW) \
+ X("list", 0, LSTSW) \
+ X("sequence name", 0, SEQSW) \
+ X("public", 0, PUBLSW) \
+ X("nopublic", 0, NPUBLSW) \
+ X("zero", 0, ZEROSW) \
+ X("nozero", 0, NZEROSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+ X("debug", -5, DEBUGSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(MARK);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(MARK, switches);
+#undef X
/*
* static prototypes
#include <h/mhcachesbr.h>
#include <h/utils.h>
-static struct swit switches[] = {
-#define CHECKSW 0
- { "check", 0 },
-#define NCHECKSW 1
- { "nocheck", 0 },
-#define DIRECTIVES 2
- { "directives", 0 },
-#define NDIRECTIVES 3
- { "nodirectives", 0 },
-#define EBCDICSW 4
- { "ebcdicsafe", 0 },
-#define NEBCDICSW 5
- { "noebcdicsafe", 0 },
-#define HEADSW 6
- { "headers", 0 },
-#define NHEADSW 7
- { "noheaders", 0 },
-#define LISTSW 8
- { "list", 0 },
-#define NLISTSW 9
- { "nolist", 0 },
-#define SIZESW 10
- { "realsize", 0 },
-#define NSIZESW 11
- { "norealsize", 0 },
-#define RFC934SW 12
- { "rfc934mode", 0 },
-#define NRFC934SW 13
- { "norfc934mode", 0 },
-#define VERBSW 14
- { "verbose", 0 },
-#define NVERBSW 15
- { "noverbose", 0 },
-#define RCACHESW 16
- { "rcache policy", 0 },
-#define WCACHESW 17
- { "wcache policy", 0 },
-#define CONTENTIDSW 18
- { "contentid", 0 },
-#define NCONTENTIDSW 19
- { "nocontentid", 0 },
-#define VERSIONSW 20
- { "version", 0 },
-#define HELPSW 21
- { "help", 0 },
-#define DEBUGSW 22
- { "debug", -5 },
- { NULL, 0 }
-};
+#define MHBUILD_SWITCHES \
+ X("check", 0, CHECKSW) \
+ X("nocheck", 0, NCHECKSW) \
+ X("directives", 0, DIRECTIVES) \
+ X("nodirectives", 0, NDIRECTIVES) \
+ X("headers", 0, HEADSW) \
+ X("noheaders", 0, NHEADSW) \
+ X("list", 0, LISTSW) \
+ X("nolist", 0, NLISTSW) \
+ X("realsize", 0, SIZESW) \
+ X("norealsize", 0, NSIZESW) \
+ X("rfc934mode", 0, RFC934SW) \
+ X("norfc934mode", 0, NRFC934SW) \
+ X("verbose", 0, VERBSW) \
+ X("noverbose", 0, NVERBSW) \
+ X("rcache policy", 0, RCACHESW) \
+ X("wcache policy", 0, WCACHESW) \
+ X("contentid", 0, CONTENTIDSW) \
+ X("nocontentid", 0, NCONTENTIDSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+ X("debug", -5, DEBUGSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(MHBUILD);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(MHBUILD, switches);
+#undef X
/* mhbuildsbr.c */
int debugsw = 0;
int verbosw = 0;
-int ebcdicsw = 0;
int listsw = 0;
int rfc934sw = 0;
int contentidsw = 1;
checksw = 0;
continue;
- case EBCDICSW:
- ebcdicsw++;
- continue;
- case NEBCDICSW:
- ebcdicsw = 0;
- continue;
-
case HEADSW:
headsw++;
continue;
extern int debugsw;
extern int verbosw;
-extern int ebcdicsw;
extern int listsw;
extern int rfc934sw;
extern int contentidsw;
struct part **pp;
CT ct;
FILE *in;
+ m_getfld_state_t gstate = 0;
directive_init(directives);
* draft into the linked list of header fields for
* the new MIME message.
*/
- for (compnum = 1, state = FLD;;) {
- switch (state = m_getfld (state, name, buf, sizeof(buf), in)) {
+ m_getfld_track_filepos (&gstate, in);
+ for (compnum = 1;;) {
+ int bufsz = sizeof buf;
+ switch (state = m_getfld (&gstate, name, buf, &bufsz, in)) {
case FLD:
case FLDPLUS:
- case FLDEOF:
compnum++;
/* abort if draft has Mime-Version header field */
/* ignore any Content-Type fields in the header */
if (!mh_strcasecmp (name, TYPE_FIELD)) {
- while (state == FLDPLUS)
- state = m_getfld (state, name, buf, sizeof(buf), in);
+ while (state == FLDPLUS) {
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, in);
+ }
goto finish_field;
}
/* if necessary, get rest of field */
while (state == FLDPLUS) {
- state = m_getfld (state, name, buf, sizeof(buf), in);
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, in);
vp = add (buf, vp); /* add to previous value */
}
finish_field:
/* if this wasn't the last header field, then continue */
- if (state != FLDEOF)
- continue;
- /* else fall... */
+ continue;
case FILEEOF:
adios (NULL, "draft has empty body -- no directives!");
/* NOTREACHED */
case BODY:
- case BODYEOF:
fseek (in, (long) (-strlen (buf)), SEEK_CUR);
break;
}
break;
}
+ m_getfld_state_destroy (&gstate);
/*
* Now add the MIME-Version header field
}
-static char ebcdicsafe[0x100] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-
/*
* Fill out, or expand the various contents in the composition
* draft. Read-in any necessary files. Parse and execute any
int checklinelen = 0, linelen = 0; /* check for long lines */
int checkboundary = 0, boundaryclash = 0; /* check if clashes with multipart boundary */
int checklinespace = 0, linespace = 0; /* check if any line ends with space */
- int checkebcdic = 0, ebcdicunsafe = 0; /* check if contains ebcdic unsafe characters */
unsigned char *cp = NULL, buffer[BUFSIZ];
struct text *t = NULL;
FILE *in = NULL;
check8bit = 1;
checkboundary = 1;
if (ct->c_subtype == TEXT_PLAIN) {
- checkebcdic = 0;
checklinelen = 0;
checklinespace = 0;
} else {
- checkebcdic = ebcdicsw;
checklinelen = 1;
checklinespace = 1;
}
case CT_APPLICATION:
check8bit = 1;
- checkebcdic = ebcdicsw;
checklinelen = 1;
checklinespace = 1;
checkboundary = 1;
case CT_MESSAGE:
check8bit = 0;
- checkebcdic = 0;
checklinelen = 0;
checklinespace = 0;
* since we are forcing use of base64.
*/
check8bit = 0;
- checkebcdic = 0;
checklinelen = 0;
checklinespace = 0;
checkboundary = 0;
contains8bit = 1;
check8bit = 0; /* no need to keep checking */
}
- /*
- * Check if character is ebcdic-safe. We only check
- * this if also checking for 8bit data.
- */
- if (checkebcdic && !ebcdicsafe[*cp & 0xff]) {
- ebcdicunsafe = 1;
- checkebcdic = 0; /* no need to keep checking */
- }
}
}
*ep = cp;
}
- if (contains8bit || ebcdicunsafe || linelen || linespace || checksw)
+ if (contains8bit || linelen || linespace || checksw)
ct->c_encoding = CE_QUOTED;
else
ct->c_encoding = CE_7BIT;
case CT_APPLICATION:
/* For application type, use base64, except when postscript */
- if (contains8bit || ebcdicunsafe || linelen || linespace || checksw)
+ if (contains8bit || linelen || linespace || checksw)
ct->c_encoding = (ct->c_subtype == APPLICATION_POSTSCRIPT)
? CE_QUOTED : CE_BASE64;
else
int state;
char buf[BUFSIZ], name[NAMESZ];
FILE *fp;
+ m_getfld_state_t gstate = 0;
if (!(fp = lkfopen (mapfile, "r")))
return NOTOK;
- for (state = FLD;;) {
+ for (;;) {
int result;
char *cp, *dp;
+ int bufsz = sizeof buf;
- switch (state = m_getfld (state, name, buf, sizeof(buf), fp)) {
+ switch (state = m_getfld (&gstate, name, buf, &bufsz, fp)) {
case FLD:
case FLDPLUS:
- case FLDEOF:
strncpy (mapname, name, namelen);
if (state != FLDPLUS)
cp = buf;
else {
cp = add (buf, NULL);
while (state == FLDPLUS) {
- state = m_getfld (state, name, buf, sizeof(buf), fp);
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, fp);
cp = add (buf, cp);
}
}
lkfclose (fp, mapfile);
return OK;
}
- if (state != FLDEOF)
- continue;
- /* else fall... */
+ continue;
case BODY:
- case BODYEOF:
case FILEEOF:
default:
break;
}
break;
}
+ m_getfld_state_destroy (&gstate);
lkfclose (fp, mapfile);
return NOTOK;
#include <h/mhcachesbr.h>
#include <h/utils.h>
-static struct swit switches[] = {
-#define CHECKSW 0
- { "check", 0 },
-#define NCHECKSW 1
- { "nocheck", 0 },
-#define HEADSW 2
- { "headers", 0 },
-#define NHEADSW 3
- { "noheaders", 0 },
-#define SIZESW 4
- { "realsize", 0 },
-#define NSIZESW 5
- { "norealsize", 0 },
-#define VERBSW 6
- { "verbose", 0 },
-#define NVERBSW 7
- { "noverbose", 0 },
-#define FILESW 8 /* interface from show */
- { "file file", 0 },
-#define PARTSW 9
- { "part number", 0 },
-#define TYPESW 10
- { "type content", 0 },
-#define RCACHESW 11
- { "rcache policy", 0 },
-#define WCACHESW 12
- { "wcache policy", 0 },
-#define VERSIONSW 13
- { "version", 0 },
-#define HELPSW 14
- { "help", 0 },
-
-/*
- * switches for debugging
- */
-#define DEBUGSW 15
- { "debug", -5 },
- { NULL, 0 }
-};
+#define MHLIST_SWITCHES \
+ X("check", 0, CHECKSW) \
+ X("nocheck", 0, NCHECKSW) \
+ X("headers", 0, HEADSW) \
+ X("noheaders", 0, NHEADSW) \
+ X("realsize", 0, SIZESW) \
+ X("norealsize", 0, NSIZESW) \
+ X("verbose", 0, VERBSW) \
+ X("noverbose", 0, NVERBSW) \
+ X("file file", 0, FILESW) \
+ X("part number", 0, PARTSW) \
+ X("type content", 0, TYPESW) \
+ X("rcache policy", 0, RCACHESW) \
+ X("wcache policy", 0, WCACHESW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+ X("debug", -5, DEBUGSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(MHLIST);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(MHLIST, switches);
+#undef X
/* mhparse.c */
#define QUOTE '\\'
-static struct swit mhlswitches[] = {
-#define BELLSW 0
- { "bell", 0 },
-#define NBELLSW 1
- { "nobell", 0 },
-#define CLRSW 2
- { "clear", 0 },
-#define NCLRSW 3
- { "noclear", 0 },
-#define FOLDSW 4
- { "folder +folder", 0 },
-#define FORMSW 5
- { "form formfile", 0 },
-#define PROGSW 6
- { "moreproc program", 0 },
-#define NPROGSW 7
- { "nomoreproc", 0 },
-#define LENSW 8
- { "length lines", 0 },
-#define WIDTHSW 9
- { "width columns", 0 },
-#define SLEEPSW 10
- { "sleep seconds", 0 },
-#define BITSTUFFSW 11
- { "dashstuffing", -12 }, /* interface from forw */
-#define NBITSTUFFSW 12
- { "nodashstuffing", -14 }, /* interface from forw */
-#define VERSIONSW 13
- { "version", 0 },
-#define HELPSW 14
- { "help", 0 },
-#define FORW1SW 15
- { "forward", -7 }, /* interface from forw */
-#define FORW2SW 16
- { "forwall", -7 }, /* interface from forw */
-#define DGSTSW 17
- { "digest list", -6 },
-#define VOLUMSW 18
- { "volume number", -6 },
-#define ISSUESW 19
- { "issue number", -5 },
-#define NBODYSW 20
- { "nobody", -6 },
-#define FMTPROCSW 21
- { "fmtproc program", 0 },
-#define NFMTPROCSW 22
- { "nofmtproc", 0 },
- { NULL, 0 }
-};
+#define MHL_SWITCHES \
+ X("bell", 0, BELLSW) \
+ X("nobell", 0, NBELLSW) \
+ X("clear", 0, CLRSW) \
+ X("noclear", 0, NCLRSW) \
+ X("folder +folder", 0, FOLDSW) \
+ X("form formfile", 0, FORMSW) \
+ X("moreproc program", 0, PROGSW) \
+ X("nomoreproc", 0, NPROGSW) \
+ X("length lines", 0, LENSW) \
+ X("width columns", 0, WIDTHSW) \
+ X("sleep seconds", 0, SLEEPSW) \
+ X("dashstuffing", -12, BITSTUFFSW) /* interface from forw */ \
+ X("nodashstuffing", -14, NBITSTUFFSW) /* interface from forw */ \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+ X("forward", -7, FORW1SW) /* interface from forw */ \
+ X("forwall", -7, FORW2SW) /* interface from forw */ \
+ X("digest list", -6, DGSTSW) \
+ X("volume number", -6, VOLUMSW) \
+ X("issue number", -5, ISSUESW) \
+ X("nobody", -6, NBODYSW) \
+ X("fmtproc program", 0, FMTPROCSW) \
+ X("nofmtproc", 0, NFMTPROCSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(MHL);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(MHL, mhlswitches);
+#undef X
#define NOCOMPONENT 0x000001 /* don't show component name */
#define UPPERCASE 0x000002 /* display in all upper case */
static void mhladios (char *, char *, ...);
static void mhldone (int);
static void m_popen (char *);
-static void filterbody (struct mcomp *, char *, int, int, FILE *);
+static void filterbody (struct mcomp *, char *, int, int, FILE *,
+ m_getfld_state_t);
static void compile_formatfield(struct mcomp *);
static void compile_filterargs (void);
int state, bucket;
struct mcomp *c1, *c2, *c3;
char **ip, name[NAMESZ], buf[BUFSIZ];
+ m_getfld_state_t gstate = 0;
compile_filterargs();
}
}
- for (state = FLD;;) {
- switch (state = m_getfld (state, name, buf, sizeof(buf), fp)) {
+ for (;;) {
+ int bufsz = sizeof buf;
+ switch (state = m_getfld (&gstate, name, buf, &bufsz, fp)) {
case FLD:
case FLDPLUS:
bucket = fmt_addcomptext(name, buf);
for (ip = ignores; *ip; ip++)
if (!mh_strcasecmp (name, *ip)) {
while (state == FLDPLUS) {
- state = m_getfld (state, name, buf, sizeof(buf), fp);
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, fp);
fmt_appendcomp(bucket, name, buf);
}
break;
if (c1 == NULL)
c1 = add_queue (&msghd, &msgtl, name, buf, 0);
while (state == FLDPLUS) {
- state = m_getfld (state, name, buf, sizeof(buf), fp);
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, fp);
c1->c_text = add (buf, c1->c_text);
fmt_appendcomp(bucket, name, buf);
}
if (dobody && !mh_strcasecmp (c1->c_name, "body")) {
if (c1->c_flags & FMTFILTER && state == BODY &&
formatproc != NULL) {
- filterbody(c1, buf, sizeof(buf), state, fp);
+ filterbody(c1, buf, sizeof(buf), state, fp, gstate);
} else {
holder.c_text = mh_xmalloc (sizeof(buf));
strncpy (holder.c_text, buf, sizeof(buf));
while (state == BODY) {
putcomp (c1, &holder, BODYCOMP);
- state = m_getfld (state, name, holder.c_text,
- sizeof(buf), fp);
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, holder.c_text,
+ &bufsz, fp);
}
free (holder.c_text);
holder.c_text = NULL;
adios (NULL, "getfld() returned %d", state);
}
}
+ m_getfld_state_destroy (&gstate);
}
m_popen (char *name)
{
int pd[2];
+ char *file;
+ char **arglist;
if (mhl_action && (sd = dup (fileno (stdout))) == NOTOK)
adios ("standard output", "unable to dup()");
dup2 (pd[0], fileno (stdin));
close (pd[0]);
}
- execlp (name, r1bindex (name, '/'), NULL);
+ arglist = argsplit(name, &file, NULL);
+ execvp (file, arglist);
fprintf (stderr, "unable to exec ");
perror (name);
_exit (-1);
*/
static void
-filterbody (struct mcomp *c1, char *buf, int bufsz, int state, FILE *fp)
+filterbody (struct mcomp *c1, char *buf, int bufsz, int state, FILE *fp,
+ m_getfld_state_t gstate)
{
struct mcomp holder;
char name[NAMESZ];
*/
while (state == BODY) {
+ int bufsz2 = bufsz;
write(fdinput[1], buf, strlen(buf));
- state = m_getfld(state, name, buf, bufsz, fp);
+ state = m_getfld (&gstate, name, buf, &bufsz2, fp);
}
/*
#include <h/mhcachesbr.h>
#include <h/utils.h>
-static struct swit switches[] = {
-#define AUTOSW 0
- { "auto", 0 },
-#define NAUTOSW 1
- { "noauto", 0 },
-#define CACHESW 2
- { "cache", 0 },
-#define NCACHESW 3
- { "nocache", 0 },
-#define CHECKSW 4
- { "check", 0 },
-#define NCHECKSW 5
- { "nocheck", 0 },
-#define HEADSW 6
- { "headers", 0 },
-#define NHEADSW 7
- { "noheaders", 0 },
-#define LISTSW 8
- { "list", 0 },
-#define NLISTSW 9
- { "nolist", 0 },
-#define PAUSESW 10
- { "pause", 0 },
-#define NPAUSESW 11
- { "nopause", 0 },
-#define SIZESW 12
- { "realsize", 0 },
-#define NSIZESW 13
- { "norealsize", 0 },
-#define SERIALSW 14
- { "serialonly", 0 },
-#define NSERIALSW 15
- { "noserialonly", 0 },
-#define SHOWSW 16
- { "show", 0 },
-#define NSHOWSW 17
- { "noshow", 0 },
-#define STORESW 18
- { "store", 0 },
-#define NSTORESW 19
- { "nostore", 0 },
-#define VERBSW 20
- { "verbose", 0 },
-#define NVERBSW 21
- { "noverbose", 0 },
-#define FILESW 22 /* interface from show */
- { "file file", 0 },
-#define FORMSW 23
- { "form formfile", 0 },
-#define PARTSW 24
- { "part number", 0 },
-#define TYPESW 25
- { "type content", 0 },
-#define RCACHESW 26
- { "rcache policy", 0 },
-#define WCACHESW 27
- { "wcache policy", 0 },
-#define VERSIONSW 28
- { "version", 0 },
-#define HELPSW 29
- { "help", 0 },
-
-/*
- * switches for debugging
- */
-#define DEBUGSW 30
- { "debug", -5 },
-
-/*
- * switches for moreproc/mhlproc
- */
-#define PROGSW 31
- { "moreproc program", -4 },
-#define NPROGSW 32
- { "nomoreproc", -3 },
-#define LENSW 33
- { "length lines", -4 },
-#define WIDTHSW 34
- { "width columns", -4 },
-
-/*
- * switches for mhbuild
- */
-#define BUILDSW 35
- { "build", -5 },
-#define NBUILDSW 36
- { "nobuild", -7 },
-#define EBCDICSW 37
- { "ebcdicsafe", -10 },
-#define NEBCDICSW 38
- { "noebcdicsafe", -12 },
-#define RFC934SW 39
- { "rfc934mode", -10 },
-#define NRFC934SW 40
- { "norfc934mode", -12 },
- { NULL, 0 }
-};
+#define MHN_SWITCHES \
+ X("auto", 0, AUTOSW) \
+ X("noauto", 0, NAUTOSW) \
+ X("cache", 0, CACHESW) \
+ X("nocache", 0, NCACHESW) \
+ X("check", 0, CHECKSW) \
+ X("nocheck", 0, NCHECKSW) \
+ X("headers", 0, HEADSW) \
+ X("noheaders", 0, NHEADSW) \
+ X("list", 0, LISTSW) \
+ X("nolist", 0, NLISTSW) \
+ X("pause", 0, PAUSESW) \
+ X("nopause", 0, NPAUSESW) \
+ X("realsize", 0, SIZESW) \
+ X("norealsize", 0, NSIZESW) \
+ X("serialonly", 0, SERIALSW) \
+ X("noserialonly", 0, NSERIALSW) \
+ X("show", 0, SHOWSW) \
+ X("noshow", 0, NSHOWSW) \
+ X("store", 0, STORESW) \
+ X("nostore", 0, NSTORESW) \
+ X("verbose", 0, VERBSW) \
+ X("noverbose", 0, NVERBSW) \
+ X("file file", 0, FILESW) \
+ X("form formfile", 0, FORMSW) \
+ X("part number", 0, PARTSW) \
+ X("type content", 0, TYPESW) \
+ X("rcache policy", 0, RCACHESW) \
+ X("wcache policy", 0, WCACHESW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+ /* \
+ * for debugging \
+ */ \
+ X("debug", -5, DEBUGSW) \
+ /* \
+ * switches for moreproc/mhlproc \
+ */ \
+ X("moreproc program", -4, PROGSW) \
+ X("nomoreproc", -3, NPROGSW) \
+ X("length lines", -4, LENSW) \
+ X("width columns", -4, WIDTHSW) \
+ /* \
+ * switches for mhbuild \
+ */ \
+ X("build", -5, BUILDSW) \
+ X("nobuild", -7, NBUILDSW) \
+ X("rfc934mode", -10, RFC934SW) \
+ X("norfc934mode", -12, NRFC934SW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(MHN);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(MHN, switches);
+#undef X
/* mhparse.c */
* variables for mhbuild (mhn -build)
*/
static int buildsw = 0;
-static int ebcdicsw = 0;
static int rfc934sw = 0;
/*
case NRFC934SW:
rfc934sw = -1;
continue;
- case EBCDICSW:
- ebcdicsw = 1;
- continue;
- case NEBCDICSW:
- ebcdicsw = -1;
- continue;
case VERBSW:
verbosw = 1;
vecp = 0;
vec[vecp++] = "mhbuild";
- if (ebcdicsw == 1)
- vec[vecp++] = "-ebcdicsafe";
- else if (ebcdicsw == -1)
- vec[vecp++] = "-noebcdicsafe";
-
if (rfc934sw == 1)
vec[vecp++] = "-rfc934mode";
else if (rfc934sw == -1)
vecp = 0;
vec[vecp++] = "mhbuild";
- if (ebcdicsw == 1)
- vec[vecp++] = "-ebcdicsafe";
- else if (ebcdicsw == -1)
- vec[vecp++] = "-noebcdicsafe";
-
if (rfc934sw == 1)
vec[vecp++] = "-rfc934mode";
else if (rfc934sw == -1)
#include <h/mhparse.h>
-extern int ebcdicsw;
-
-static char ebcdicsafe[0x100] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
/*
* prototypes
*/
break;
default:
- if (*cp < '!' || *cp > '~'
- || (ebcdicsw && !ebcdicsafe[*cp & 0xff]))
+ if (*cp < '!' || *cp > '~')
goto three_print;
putc (*cp, out);
n++;
char *sbackup = BACKUP_PREFIX;
-static struct swit switches[] = {
-#define COMPSW 0
- { "components", 0 },
-#define NCOMPSW 1
- { "nocomponents", 0 },
-#define ALLSW 2
- { "all", 0 },
-#define VERSIONSW 3
- { "version", 0 },
-#define HELPSW 4
- { "help", 0 },
-#define DEBUGSW 5
- { "debug", 5 },
- { NULL, 0 }
-};
+#define MHPARAM_SWITCHES \
+ X("components", 0, COMPSW) \
+ X("nocomponents", 0, NCOMPSW) \
+ X("all", 0, ALLSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+ X("debug", 5, DEBUGSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(MHPARAM);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(MHPARAM, switches);
+#undef X
struct proc {
char *p_name;
char *np, *vp;
CT ct;
HF hp;
+ m_getfld_state_t gstate = 0;
/* allocate the content structure */
if (!(ct = (CT) calloc (1, sizeof(*ct))))
* Parse the header fields for this
* content into a linked list.
*/
- for (compnum = 1, state = FLD;;) {
- switch (state = m_getfld (state, name, buf, sizeof(buf), in)) {
+ m_getfld_track_filepos (&gstate, in);
+ for (compnum = 1;;) {
+ int bufsz = sizeof buf;
+ switch (state = m_getfld (&gstate, name, buf, &bufsz, in)) {
case FLD:
case FLDPLUS:
- case FLDEOF:
compnum++;
/* get copies of the buffers */
/* if necessary, get rest of field */
while (state == FLDPLUS) {
- state = m_getfld (state, name, buf, sizeof(buf), in);
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, in);
vp = add (buf, vp); /* add to previous value */
}
/* Now add the header data to the list */
add_header (ct, np, vp);
- /* continue, if this isn't the last header field */
- if (state != FLDEOF) {
- ct->c_begin = ftell (in) + 1;
- continue;
- }
- /* else fall... */
+ /* continue, to see if this isn't the last header field */
+ ct->c_begin = ftell (in) + 1;
+ continue;
case BODY:
- case BODYEOF:
ct->c_begin = ftell (in) - strlen (buf);
break;
/* break out of the loop */
break;
}
+ m_getfld_state_destroy (&gstate);
/*
* Read the content headers. We will parse the
*/
if (ct->c_encoding != CE_7BIT && ct->c_encoding != CE_8BIT
&& ct->c_encoding != CE_BINARY) {
+ /* Copy the Content-Transfer-Encoding header field body so we can
+ remove any trailing whitespace and leading blanks from it. */
+ char *cte = add (ct->c_celine ? ct->c_celine : "(null)", NULL);
+
+ bp = cte + strlen (cte) - 1;
+ while (bp >= cte && isspace (*bp)) *bp-- = '\0';
+ for (bp = cte; *bp && isblank (*bp); ++bp) continue;
+
admonish (NULL,
- "\"%s/%s\" type in message %s must be encoded in 7bit, 8bit, or binary",
- ci->ci_type, ci->ci_subtype, ct->c_file);
+ "\"%s/%s\" type in message %s must be encoded in\n"
+ "7bit, 8bit, or binary, per RFC 2045 (6.4). One workaround "
+ "is to\nmanually edit the file and change the \"%s\"\n"
+ "Content-Transfer-Encoding to one of those. For now",
+ ci->ci_type, ci->ci_subtype, ct->c_file, bp);
+ free (cte);
+
return NOTOK;
}
#include <h/mh.h>
#include <h/utils.h>
-static struct swit switches[] = {
-#define VERSIONSW 0
- { "version", 0 },
-#define HELPSW 1
- { "help", 0 },
- { NULL, 0 }
-};
+#define MHPATH_SWITCHES \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(MHPATH);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(MHPATH, switches);
+#undef X
int
main(int argc, char **argv)
#include <h/mhcachesbr.h>
#include <h/utils.h>
-static struct swit switches[] = {
-#define CHECKSW 0
- { "check", 0 },
-#define NCHECKSW 1
- { "nocheck", 0 },
-#define PAUSESW 2
- { "pause", 0 },
-#define NPAUSESW 3
- { "nopause", 0 },
-#define SERIALSW 4
- { "serialonly", 0 },
-#define NSERIALSW 5
- { "noserialonly", 0 },
-#define VERBSW 6
- { "verbose", 0 },
-#define NVERBSW 7
- { "noverbose", 0 },
-#define FILESW 8 /* interface from show */
- { "file file", 0 },
-#define FORMSW 9
- { "form formfile", 0 },
-#define PARTSW 10
- { "part number", 0 },
-#define TYPESW 11
- { "type content", 0 },
-#define RCACHESW 12
- { "rcache policy", 0 },
-#define WCACHESW 13
- { "wcache policy", 0 },
-#define VERSIONSW 14
- { "version", 0 },
-#define HELPSW 15
- { "help", 0 },
-
-/*
- * switches for moreproc/mhlproc
- */
-#define PROGSW 16
- { "moreproc program", -4 },
-#define NPROGSW 17
- { "nomoreproc", -3 },
-#define LENSW 18
- { "length lines", -4 },
-#define WIDTHSW 19
- { "width columns", -4 },
-
-/*
- * switches for debugging
- */
-#define DEBUGSW 20
- { "debug", -5 },
- { NULL, 0 }
-};
+#define MHSHOW_SWITCHES \
+ X("check", 0, CHECKSW) \
+ X("nocheck", 0, NCHECKSW) \
+ X("pause", 0, PAUSESW) \
+ X("nopause", 0, NPAUSESW) \
+ X("serialonly", 0, SERIALSW) \
+ X("noserialonly", 0, NSERIALSW) \
+ X("verbose", 0, VERBSW) \
+ X("noverbose", 0, NVERBSW) \
+ X("file file", 0, FILESW) \
+ X("form formfile", 0, FORMSW) \
+ X("part number", 0, PARTSW) \
+ X("type content", 0, TYPESW) \
+ X("rcache policy", 0, RCACHESW) \
+ X("wcache policy", 0, WCACHESW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+ /* \
+ * switches for moreproc/mhlproc \
+ */ \
+ X("moreproc program", -4, PROGSW) \
+ X("nomoreproc", -3, NPROGSW) \
+ X("length lines", -4, LENSW) \
+ X("width columns", -4, WIDTHSW) \
+ /* \
+ * switches for debugging \
+ */ \
+ X("debug", -5, DEBUGSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(MHSHOW);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(MHSHOW, switches);
+#undef X
/* mhparse.c */
{
pid_t child_id;
int i, vecp;
- char *vec[8];
+ char **vec;
+ char *file;
- vecp = 0;
- vec[vecp++] = r1bindex (mhlproc, '/');
- vec[vecp++] = "-form";
- vec[vecp++] = form;
- vec[vecp++] = "-nobody";
- vec[vecp++] = ct->c_file;
+ vec = argsplit(mhlproc, &file, &vecp);
+ vec[vecp++] = getcpy("-form");
+ vec[vecp++] = getcpy(form);
+ vec[vecp++] = getcpy("-nobody");
+ vec[vecp++] = getcpy(ct->c_file);
/*
* If we've specified -(no)moreproc,
* then just pass that along.
*/
if (nomore) {
- vec[vecp++] = "-nomoreproc";
+ vec[vecp++] = getcpy("-nomoreproc");
} else if (progsw) {
- vec[vecp++] = "-moreproc";
- vec[vecp++] = progsw;
+ vec[vecp++] = getcpy("-moreproc");
+ vec[vecp++] = getcpy(progsw);
}
vec[vecp] = NULL;
/* NOTREACHED */
case OK:
- execvp (mhlproc, vec);
+ execvp (file, vec);
fprintf (stderr, "unable to exec ");
perror (mhlproc);
_exit (-1);
xpid = -child_id;
break;
}
+
+ arglist_free(file, vec);
}
#include <h/mhcachesbr.h>
#include <h/utils.h>
-static struct swit switches[] = {
-#define AUTOSW 0
- { "auto", 0 },
-#define NAUTOSW 1
- { "noauto", 0 },
-#define CHECKSW 2
- { "check", 0 },
-#define NCHECKSW 3
- { "nocheck", 0 },
-#define VERBSW 4
- { "verbose", 0 },
-#define NVERBSW 5
- { "noverbose", 0 },
-#define FILESW 6 /* interface from show */
- { "file file", 0 },
-#define PARTSW 7
- { "part number", 0 },
-#define TYPESW 8
- { "type content", 0 },
-#define RCACHESW 9
- { "rcache policy", 0 },
-#define WCACHESW 10
- { "wcache policy", 0 },
-#define VERSIONSW 11
- { "version", 0 },
-#define HELPSW 12
- { "help", 0 },
-#define CLOBBERSW 13
- { "clobber always|auto|suffix|ask|never", 0 },
-
-/*
- * switches for debugging
- */
-#define DEBUGSW 14
- { "debug", -5 },
- { NULL, 0 }
-};
+#define MHSTORE_SWITCHES \
+ X("auto", 0, AUTOSW) \
+ X("noauto", 0, NAUTOSW) \
+ X("check", 0, CHECKSW) \
+ X("nocheck", 0, NCHECKSW) \
+ X("verbose", 0, VERBSW) \
+ X("noverbose", 0, NVERBSW) \
+ X("file file", 0, FILESW) /* interface from show */ \
+ X("part number", 0, PARTSW) \
+ X("type content", 0, TYPESW) \
+ X("rcache policy", 0, RCACHESW) \
+ X("wcache policy", 0, WCACHESW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+ X("clobber always|auto|suffix|ask|never", 0, CLOBBERSW) \
+ X("debug", -5, DEBUGSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(MHSTORE);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(MHSTORE, switches);
+#undef X
int save_clobber_policy (const char *);
if (stat (file, &st) == OK) {
enum answers { NMH_YES, NMH_NO, NMH_RENAME };
static struct swit answer[4] = {
- { "yes", 0 }, { "no", 0 }, { "rename", 0 }, { NULL, 0 } };
+ { "yes", 0, NMH_YES }, { "no", 0, NMH_NO }, { "rename", 0, NMH_RENAME }, { NULL, 0, 0 } };
char **ans;
if (isatty (fileno (stdin))) {
#include <h/mhcachesbr.h>
#include <h/utils.h>
-static struct swit switches[] = {
-#define CHECKSW 0
- { "check", 0 },
-#define NCHECKSW 1
- { "nocheck", 0 },
-#define VERBSW 2
- { "verbose", 0 },
-#define NVERBSW 3
- { "noverbose", 0 },
-#define FILESW 4
- { "file file", 0 },
-#define OUTFILESW 5
- { "outfile file", 0 },
-#define PARTSW 6
- { "part number", 0 },
-#define TYPESW 7
- { "type content", 0 },
-#define RCACHESW 8
- { "rcache policy", 0 },
-#define WCACHESW 9
- { "wcache policy", 0 },
-#define VERSIONSW 10
- { "version", 0 },
-#define HELPSW 11
- { "help", 0 },
+#define MHTEST_SWITCHES \
+ X("check", 0, CHECKSW) \
+ X("nocheck", 0, NCHECKSW) \
+ X("verbose", 0, VERBSW) \
+ X("noverbose", 0, NVERBSW) \
+ X("file file", 0, FILESW) \
+ X("outfile file", 0, OUTFILESW) \
+ X("part number", 0, PARTSW) \
+ X("type content", 0, TYPESW) \
+ X("rcache policy", 0, RCACHESW) \
+ X("wcache policy", 0, WCACHESW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+ X("debug", -5, DEBUGSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(MHTEST);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(MHTEST, switches);
+#undef X
-/*
- * switches for debugging
- */
-#define DEBUGSW 12
- { "debug", -5 },
- { NULL, 0 }
-};
-
-
-int ebcdicsw = 0; /* hack for linking purposes */
/* mhparse.c */
extern char *tmp; /* directory to place temp files */
# define SASLminc(a) 0
#endif
-static struct swit switches[] = {
-#define DATESW 0
- { "date", 0 },
-#define NDATESW 1
- { "nodate", 0 },
-#define NOTESW 2
- { "notify type", 0 },
-#define NNOTESW 3
- { "nonotify type", 0 },
-#define HOSTSW 4
- { "host hostname", 0 },
-#define USERSW 5
- { "user username", 0 },
-#define PORTSW 6
- { "port name/number", 0 },
-#define VERSIONSW 7
- { "version", 0 },
-#define HELPSW 8
- { "help", 0 },
-#define SNOOPSW 9
- { "snoop", -5 },
-#define SASLSW 10
- { "sasl", SASLminc(-4) },
-#define SASLMECHSW 11
- { "saslmech", SASLminc(-5) },
-#define PROXYSW 12
- { "proxy command", 0 },
- { NULL, 0 }
-};
+#define MSGCHK_SWITCHES \
+ X("date", 0, DATESW) \
+ X("nodate", 0, NDATESW) \
+ X("notify type", 0, NOTESW) \
+ X("nonotify type", 0, NNOTESW) \
+ X("host hostname", 0, HOSTSW) \
+ X("user username", 0, USERSW) \
+ X("port name/number", 0, PORTSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+ X("snoop", -5, SNOOPSW) \
+ X("sasl", SASLminc(-4), SASLSW) \
+ X("saslmech", SASLminc(-5), SASLMECHSW) \
+ X("proxy command", 0, PROXYSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(MSGCHK);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(MSGCHK, switches);
+#undef X
/*
* Maximum numbers of users we can check (plus
}
-static struct swit ntswitches[] = {
-#define NALLSW 0
- { "all", 0 },
-#define NMAISW 1
- { "mail", 0 },
-#define NNMAISW 2
- { "nomail", 0 },
- { NULL, 0 }
-};
+#define NOTE_SWITCHES \
+ X("all", 0, NALLSW) \
+ X("mail", 0, NMAISW) \
+ X("nomail", 0, NNMAISW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(NOTE);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(NOTE, ntswitches);
+#undef X
static int
#define QUOTE '\\' /* sigh */
-static struct swit switches[] = {
-#define IDSW 0
- { "idstart number", -7 }, /* interface from bbc */
-#define FDSW 1
- { "idstop number", -6 }, /* .. */
-#define QDSW 2
- { "idquit number", -6 }, /* .. */
-#define NMSW 3
- { "idname BBoard", -6 }, /* .. */
-#define PRMPTSW 4
- { "prompt string", 0 },
-#define SCANSW 5
- { "scan", 0 },
-#define NSCANSW 6
- { "noscan", 0 },
-#define READSW 7
- { "vmhread fd", -7 },
-#define WRITESW 8
- { "vmhwrite fd", -8 },
-#define PREADSW 9
- { "popread fd", -7 },
-#define PWRITSW 10
- { "popwrite fd", -8 },
-#define TCURSW 11
- { "topcur", 0 },
-#define NTCURSW 12
- { "notopcur", 0 },
-#define VERSIONSW 13
- { "version", 0 },
-#define HELPSW 14
- { "help", 0 },
- { NULL, 0 }
-};
+#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;
void padios (char *, char *, ...);
void padvise (char *, char *, ...);
+extern m_getfld_state_t gstate; /* use the gstate in scansbr.c */
+
/*
* static prototypes
display_info (id > 0 ? scansw : 0);
msh (id > 0 ? scansw : 0);
+ scan_finished ();
m_reset ();
}
-static struct swit mshcmds[] = {
-#define ADVCMD 0
- { "advance", -7 },
-#define ALICMD 1
- { "ali", 0 },
-#define EXPLCMD 2
- { "burst", 0 },
-#define COMPCMD 3
- { "comp", 0 },
-#define DISTCMD 4
- { "dist", 0 },
-#define EXITCMD 5
- { "exit", 0 },
-#define FOLDCMD 6
- { "folder", 0 },
-#define FORWCMD 7
- { "forw", 0 },
-#define HELPCMD 8
- { "help", 0 },
-#define INCMD 9
- { "inc", 0 },
-#define MARKCMD 10
- { "mark", 0 },
-#define MAILCMD 11
- { "mhmail", 0 },
-#define MHNCMD 12
- { "mhn", 0 },
-#define MSGKCMD 13
- { "msgchk", 0 },
-#define NEXTCMD 14
- { "next", 0 },
-#define PACKCMD 15
- { "packf", 0 },
-#define PICKCMD 16
- { "pick", 0 },
-#define PREVCMD 17
- { "prev", 0 },
-#define QUITCMD 18
- { "quit", 0 },
-#define FILECMD 19
- { "refile", 0 },
-#define REPLCMD 20
- { "repl", 0 },
-#define RMMCMD 21
- { "rmm", 0 },
-#define SCANCMD 22
- { "scan", 0 },
-#define SENDCMD 23
- { "send", 0 },
-#define SHOWCMD 24
- { "show", 0 },
-#define SORTCMD 25
- { "sortm", 0 },
-#define WHATCMD 26
- { "whatnow", 0 },
-#define WHOMCMD 27
- { "whom", 0 },
- { NULL, 0 }
-};
+#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
mp->msgattrs[0] = getcpy ("unseen");
mp->msgattrs[1] = NULL;
- m_unknown (fp); /* the MAGIC invocation */
+ scan_detect_mbox_style (fp); /* the MAGIC invocation */
if (fmsh) {
free (fmsh);
fmsh = NULL;
return yp;
}
- m_eomsbr ((int (*)()) 0); /* XXX */
+ scan_reset_m_getfld_state ();
+ scan_eom_action ((int (*)()) 0); /* XXX */
fseek (fp, Msgs[msgnum].m_start, SEEK_SET);
return fp;
}
return Msgs[msgnum].m_bboard_id;
zp = msh_ready (msgnum, 0);
- for (state = FLD;;)
- switch (state = m_getfld (state, name, buf, sizeof(buf), zp)) {
+ for (;;) {
+ int bufsz = sizeof buf;
+ switch (state = m_getfld (&gstate, name, buf, &bufsz, zp)) {
case FLD:
- case FLDEOF:
case FLDPLUS:
if (!mh_strcasecmp (name, BBoard_ID)) {
bp = getcpy (buf);
while (state == FLDPLUS) {
- state = m_getfld (state, name, buf, sizeof(buf), zp);
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, zp);
bp = add (buf, bp);
}
i = atoi (bp);
else
continue;
}
- while (state == FLDPLUS)
- state = m_getfld (state, name, buf, sizeof(buf), zp);
- if (state != FLDEOF)
- continue;
+ while (state == FLDPLUS) {
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, zp);
+ }
+ continue;
default:
return 0;
}
+ }
}
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)
{
}
-static struct swit distswit[] = {
-#define DIANSW 0
- { "annotate", 0 },
-#define DINANSW 1
- { "noannotate", 0 },
-#define DIDFSW 2
- { "draftfolder +folder", 0 },
-#define DIDMSW 3
- { "draftmessage msg", 0 },
-#define DINDFSW 4
- { "nodraftfolder", 0 },
-#define DIEDTSW 5
- { "editor editor", 0 },
-#define DINEDSW 6
- { "noedit", 0 },
-#define DIFRMSW 7
- { "form formfile", 0 },
-#define DIINSW 8
- { "inplace", 0 },
-#define DININSW 9
- { "noinplace", 0 },
-#define DIWHTSW 10
- { "whatnowproc program", 0 },
-#define DINWTSW 11
- { "nowhatnowproc", 0 },
-#define DIHELP 12
- { "help", 0 },
- { NULL, 0 }
-};
+#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
}
-static struct swit explswit[] = {
-#define EXINSW 0
- { "inplace", 0 },
-#define EXNINSW 1
- { "noinplace", 0 },
-#define EXQISW 2
- { "quiet", 0 },
-#define EXNQISW 3
- { "noquiet", 0 },
-#define EXVBSW 4
- { "verbose", 0 },
-#define EXNVBSW 5
- { "noverbose", 0 },
-#define EXHELP 6
- { "help", 0 },
- { NULL, 0 }
-};
+#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
}
-static struct swit fileswit[] = {
-#define FIDRFT 0
- { "draft", 0 },
-#define FILINK 1
- { "link", 0 },
-#define FINLINK 2
- { "nolink", 0 },
-#define FIPRES 3
- { "preserve", 0 },
-#define FINPRES 4
- { "nopreserve", 0 },
-#define FISRC 5
- { "src +folder", 0 },
-#define FIFILE 6
- { "file file", 0 },
-#define FIPROC 7
- { "rmmproc program", 0 },
-#define FINPRC 8
- { "normmproc", 0 },
-#define FIHELP 9
- { "help", 0 },
- { NULL, 0 }
-};
+#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
}
-static struct swit foldswit[] = {
-#define FLALSW 0
- { "all", 0 },
-#define FLFASW 1
- { "fast", 0 },
-#define FLNFASW 2
- { "nofast", 0 },
-#define FLHDSW 3
- { "header", 0 },
-#define FLNHDSW 4
- { "noheader", 0 },
-#define FLPKSW 5
- { "pack", 0 },
-#define FLNPKSW 6
- { "nopack", 0 },
-#define FLRCSW 7
- { "recurse", 0 },
-#define FLNRCSW 8
- { "norecurse", 0 },
-#define FLTLSW 9
- { "total", 0 },
-#define FLNTLSW 10
- { "nototal", 0 },
-#define FLPRSW 11
- { "print", 0 },
-#define FLPUSW 12
- { "push", 0 },
-#define FLPOSW 13
- { "pop", 0 },
-#define FLLISW 14
- { "list", 0 },
-#define FLHELP 15
- { "help", 0 },
- { NULL, 0 }
-};
+#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
}
-static struct swit forwswit[] = {
-#define FOANSW 0
- { "annotate", 0 },
-#define FONANSW 1
- { "noannotate", 0 },
-#define FODFSW 2
- { "draftfolder +folder", 0 },
-#define FODMSW 3
- { "draftmessage msg", 0 },
-#define FONDFSW 4
- { "nodraftfolder", 0 },
-#define FOEDTSW 5
- { "editor editor", 0 },
-#define FONEDSW 6
- { "noedit", 0 },
-#define FOFTRSW 7
- { "filter filterfile", 0 },
-#define FOFRMSW 8
- { "form formfile", 0 },
-#define FOFTSW 9
- { "format", 5 },
-#define FONFTSW 10
- { "noformat", 7 },
-#define FOINSW 11
- { "inplace", 0 },
-#define FONINSW 12
- { "noinplace", 0 },
-#define FOMISW 13
- { "mime", 0 },
-#define FONMISW 14
- { "nomime", 0 },
-#define FOWHTSW 15
- { "whatnowproc program", 0 },
-#define FONWTSW 16
- { "nowhatnow", 0 },
-#define FOHELP 17
- { "help", 0 },
- { NULL, 0 }
-};
+#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
args[i++] = getcpy (m_name (msgnum));
args[i] = NULL;
mhlsbr (i, args, mhl_action);
- m_eomsbr ((int (*) ()) 0);
+ scan_eom_action ((int (*) ()) 0);
fclose (stdout);
_exit (0);
}
-static struct swit markswit[] = {
-#define MADDSW 0
- { "add", 0 },
-#define MDELSW 1
- { "delete", 0 },
-#define MLSTSW 2
- { "list", 0 },
-#define MSEQSW 3
- { "sequence name", 0 },
-#define MPUBSW 4
- { "public", 0 },
-#define MNPUBSW 5
- { "nopublic", 0 },
-#define MZERSW 6
- { "zero", 0 },
-#define MNZERSW 7
- { "nozero", 0 },
-#define MHELP 8
- { "help", 0 },
-#define MDBUGSW 9
- { "debug", -5 },
- { NULL, 0 }
-};
+#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
}
-static struct swit mhnswit[] = {
-#define MHNAUTOSW 0
- { "auto", 0 },
-#define MHNNAUTOSW 1
- { "noauto", 0 },
-#define MHNDEBUGSW 2
- { "debug", -5 },
-#define MHNEBCDICSW 3
- { "ebcdicsafe", 0 },
-#define MHNNEBCDICSW 4
- { "noebcdicsafe", 0 },
-#define MHNFORMSW 5
- { "form formfile", 4 },
-#define MHNHEADSW 6
- { "headers", 0 },
-#define MHNNHEADSW 7
- { "noheaders", 0 },
-#define MHNLISTSW 8
- { "list", 0 },
-#define MHNNLISTSW 9
- { "nolist", 0 },
-#define MHNPARTSW 10
- { "part number", 0 },
-#define MHNSIZESW 11
- { "realsize", 0 },
-#define MHNNSIZESW 12
- { "norealsize", 0 },
-#define MHNRFC934SW 13
- { "rfc934mode", 0 },
-#define MHNNRFC934SW 14
- { "norfc934mode", 0 },
-#define MHNSERIALSW 15
- { "serialonly", 0 },
-#define MHNNSERIALSW 16
- { "noserialonly", 0 },
-#define MHNSHOWSW 17
- { "show", 0 },
-#define MHNNSHOWSW 18
- { "noshow", 0 },
-#define MHNSTORESW 19
- { "store", 0 },
-#define MHNNSTORESW 20
- { "nostore", 0 },
-#define MHNTYPESW 21
- { "type content", 0 },
-#define MHNVERBSW 22
- { "verbose", 0 },
-#define MHNNVERBSW 23
- { "noverbose", 0 },
-#define MHNHELPSW 24
- { "help", 0 },
-#define MHNPROGSW 25
- { "moreproc program", -4 },
-#define MHNNPROGSW 26
- { "nomoreproc", -3 },
-#define MHNLENSW 27
- { "length lines", -4 },
-#define MHNWIDSW 28
- { "width columns", -4 },
- { NULL, 0 }
-};
+#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
case MHNAUTOSW:
case MHNNAUTOSW:
case MHNDEBUGSW:
- case MHNEBCDICSW:
- case MHNNEBCDICSW:
case MHNHEADSW:
case MHNNHEADSW:
case MHNLISTSW:
}
-static struct swit packswit[] = {
-#define PAFISW 0
- { "file name", 0 },
-#define PAHELP 1
- { "help", 0 },
- { NULL, 0 }
-};
+#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;
}
-static struct swit pickswit[] = {
-#define PIANSW 0
- { "and", 0 },
-#define PIORSW 1
- { "or", 0 },
-#define PINTSW 2
- { "not", 0 },
-#define PILBSW 3
- { "lbrace", 0 },
-#define PIRBSW 4
- { "rbrace", 0 },
-#define PICCSW 5
- { "cc pattern", 0 },
-#define PIDASW 6
- { "date pattern", 0 },
-#define PIFRSW 7
- { "from pattern", 0 },
-#define PISESW 8
- { "search pattern", 0 },
-#define PISUSW 9
- { "subject pattern", 0 },
-#define PITOSW 10
- { "to pattern", 0 },
-#define PIOTSW 11
- { "-othercomponent pattern", 15 },
-#define PIAFSW 12
- { "after date", 0 },
-#define PIBFSW 13
- { "before date", 0 },
-#define PIDFSW 14
- { "datefield field", 5 },
-#define PISQSW 15
- { "sequence name", 0 },
-#define PIPUSW 16
- { "public", 0 },
-#define PINPUSW 17
- { "nopublic", 0 },
-#define PIZRSW 18
- { "zero", 0 },
-#define PINZRSW 19
- { "nozero", 0 },
-#define PILISW 20
- { "list", 0 },
-#define PINLISW 21
- { "nolist", 0 },
-#define PIHELP 22
- { "help", 0 },
- { NULL, 0 }
-};
+#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
}
-static struct swit replswit[] = {
-#define REANSW 0
- { "annotate", 0 },
-#define RENANSW 1
- { "noannotate", 0 },
-#define RECCSW 2
- { "cc type", 0 },
-#define RENCCSW 3
- { "nocc type", 0 },
-#define REDFSW 4
- { "draftfolder +folder", 0 },
-#define REDMSW 5
- { "draftmessage msg", 0 },
-#define RENDFSW 6
- { "nodraftfolder", 0 },
-#define REEDTSW 7
- { "editor editor", 0 },
-#define RENEDSW 8
- { "noedit", 0 },
-#define REFCCSW 9
- { "fcc +folder", 0 },
-#define REFLTSW 10
- { "filter filterfile", 0 },
-#define REFRMSW 11
- { "form formfile", 0 },
-#define REINSW 12
- { "inplace", 0 },
-#define RENINSW 13
- { "noinplace", 0 },
-#define REQUSW 14
- { "query", 0 },
-#define RENQUSW 15
- { "noquery", 0 },
-#define REWHTSW 16
- { "whatnowproc program", 0 },
-#define RENWTSW 17
- { "nowhatnow", 0 },
-#define REWIDSW 19
- { "width columns", 0 },
-#define REHELP 20
- { "help", 0 },
- { NULL, 0 }
-};
+#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
}
-static struct swit rmmswit[] = {
-#define RMHELP 0
- { "help", 0 },
- { NULL, 0 }
-};
+#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
}
-static struct swit scanswit[] = {
-#define SCCLR 0
- { "clear", 0 },
-#define SCNCLR 1
- { "noclear", 0 },
-#define SCFORM 2
- { "form formatfile", 0 },
-#define SCFMT 3
- { "format string", 5 },
-#define SCHEAD 4
- { "header", 0 },
-#define SCNHEAD 5
- { "noheader", 0 },
-#define SCWID 6
- { "width columns", 0 },
-#define SCHELP 7
- { "help", 0 },
- { NULL, 0 }
-};
+#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
}
-static struct swit showswit[] = {
-#define SHDRAFT 0
- { "draft", 5 },
-#define SHFORM 1
- { "form formfile", 4 },
-#define SHPROG 2
- { "moreproc program", 4 },
-#define SHNPROG 3
- { "nomoreproc", 3 },
-#define SHLEN 4
- { "length lines", 4 },
-#define SHWID 5
- { "width columns", 4 },
-#define SHSHOW 6
- { "showproc program", 4 },
-#define SHNSHOW 7
- { "noshowproc", 3 },
-#define SHHEAD 8
- { "header", 4 },
-#define SHNHEAD 9
- { "noheader", 3 },
-#define SHHELP 10
- { "help", 0 },
- { NULL, 0 }
-};
+#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
if (mp->numsel == 1 && headersw)
show (mp->lowsel);
mhlsbr (vecp, vec, mhl_action);
- m_eomsbr ((int (*)()) 0);
+ scan_eom_action ((int (*)()) 0);
while (msgp < vecp)
free (vec[msgp++]);
} else {
mhlfp = msh_ready (msgnum, 1);
if (!fmsh)
- m_eomsbr (eom_action);
+ scan_eom_action (eom_action);
return mhlfp;
}
fp = msh_ready (msgnum, 1);
- for (state = FLD;;)
- switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
+ for (;;) {
+ int bufsz = sizeof buf;
+ switch (state = m_getfld (&gstate, name, buf, &bufsz, fp)) {
case FLD:
case FLDPLUS:
- case FLDEOF:
/*
* Check Content-Type field
*/
cp = add (buf, NULL);
while (state == FLDPLUS) {
- state = m_getfld (state, name, buf, sizeof buf, fp);
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, fp);
cp = add (buf, cp);
}
bp = cp;
if (!mh_strcasecmp (name, ENCODING_FIELD)) {
cp = add (buf, NULL);
while (state == FLDPLUS) {
- state = m_getfld (state, name, buf, sizeof buf, fp);
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, fp);
cp = add (buf, cp);
}
for (bp = cp; isspace (*bp); bp++)
* Just skip the rest of this header
* field and go to next one.
*/
- while (state == FLDPLUS)
- state = m_getfld (state, name, buf, sizeof(buf), fp);
+ while (state == FLDPLUS) {
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, fp);
+ }
break;
/*
default:
return 0;
}
+ }
}
-static struct swit sortswit[] = {
-#define SODATE 0
- { "datefield field", 0 },
-#define SOSUBJ 1
- { "textfield field", 0 },
-#define SONSUBJ 2
- { "notextfield", 0 },
-#define SOLIMT 3
- { "limit days", 0 },
-#define SONLIMT 4
- { "nolimit", 0 },
-#define SOVERB 5
- { "verbose", 0 },
-#define SONVERB 6
- { "noverbose", 0 },
-#define SOHELP 7
- { "help", 0 },
- { NULL, 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
register FILE *zp;
zp = msh_ready (msgnum, 0);
- for (state = FLD;;) {
- switch (state = m_getfld (state, name, buf, sizeof buf, zp)) {
+
+ for (;;) {
+ int bufsz = sizeof buf;
+ switch (state = m_getfld (&gstate, name, buf, &bufsz, zp)) {
case FLD:
- case FLDEOF:
case FLDPLUS:
if (!mh_strcasecmp (name, datesw)) {
bp = getcpy (buf);
while (state == FLDPLUS) {
- state = m_getfld (state, name, buf, sizeof buf, zp);
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, zp);
bp = add (buf, bp);
}
if ((tw = dparsetime (bp)) == NULL)
else if (subjsw && !mh_strcasecmp(name, subjsw)) {
bp = getcpy (buf);
while (state == FLDPLUS) {
- state = m_getfld (state, name, buf, sizeof buf, zp);
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, zp);
bp = add (buf, bp);
}
msgp->m_scanl = sosmash(subjsw, bp);
else
subjsw = (char *)0;/* subject done, need date */
} else {
- while (state == FLDPLUS) /* flush this one */
- state = m_getfld (state, name, buf, sizeof buf, zp);
+ while (state == FLDPLUS) { /* flush this one */
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, zp);
+ }
}
continue;
case BODY:
- case BODYEOF:
case FILEEOF:
break;
#include <h/crawl_folders.h>
#include <h/utils.h>
-static struct swit switches[] = {
-#define MODESW 0
- { "mode", 1 },
-#define FOLDERSSW 1
- { "folders", 1 },
-#define VERSIONSW 2
- { "version", 1 },
-#define HELPSW 3
- { "help", 1 },
- { NULL, 0 }
-};
+#define NEW_SWITCHES \
+ X("mode", 1, MODESW) \
+ X("folders", 1, FOLDERSSW) \
+ X("version", 1, VERSIONSW) \
+ X("help", 1, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(NEW);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(NEW, switches);
+#undef X
static enum { NEW, FNEXT, FPREV, UNSEEN } run_mode = NEW;
char name[NAMESZ], field[BUFSIZ];
char *cp;
char *msgnums = NULL, *this_msgnums, *old_msgnums;
+ m_getfld_state_t gstate = 0;
/* no sequences file -> no messages */
if (fp == NULL) {
}
/* copied from seq_read.c:seq_public */
- for (state = FLD;;) {
- switch (state = m_getfld (state, name, field, sizeof(field), fp)) {
+ for (;;) {
+ int fieldsz = sizeof field;
+ switch (state = m_getfld (&gstate, name, field, &fieldsz, fp)) {
case FLD:
case FLDPLUS:
- case FLDEOF:
if (state == FLDPLUS) {
cp = getcpy (field);
while (state == FLDPLUS) {
- state = m_getfld (state, name, field,
- sizeof(field), fp);
+ fieldsz = sizeof field;
+ state = m_getfld (&gstate, name, field, &fieldsz, fp);
cp = add (field, cp);
}
}
}
- if (state == FLDEOF)
- break;
continue;
case BODY:
- case BODYEOF:
adios (NULL, "no blank lines are permitted in %s", seqfile);
/* fall */
}
break; /* break from for loop */
}
+ m_getfld_state_destroy (&gstate);
fclose(fp);
#include <h/utils.h>
#include <errno.h>
-static struct swit switches[] = {
-#define FILESW 0
- { "file name", 0 },
-#define MBOXSW 1
- { "mbox", 0 },
-#define MMDFSW 2
- { "mmdf", 0 },
-#define VERSIONSW 3
- { "version", 0 },
-#define HELPSW 4
- { "help", 0 },
- { NULL, 0 }
-};
+#define PACKF_SWITCHES \
+ X("file name", 0, FILESW) \
+ X("mbox", 0, MBOXSW) \
+ X("mmdf", 0, MMDFSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(PACKF);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(PACKF, switches);
+#undef X
static int md = NOTOK;
static int mbx_style = MBOX_FORMAT;
#include <h/picksbr.h>
#include <h/utils.h>
-static struct swit switches[] = {
-#define ANDSW 0
- { "and", 0 },
-#define ORSW 1
- { "or", 0 },
-#define NOTSW 2
- { "not", 0 },
-#define LBRSW 3
- { "lbrace", 0 },
-#define RBRSW 4
- { "rbrace", 0 },
-#define CCSW 5
- { "cc pattern", 0 },
-#define DATESW 6
- { "date pattern", 0 },
-#define FROMSW 7
- { "from pattern", 0 },
-#define SRCHSW 8
- { "search pattern", 0 },
-#define SUBJSW 9
- { "subject pattern", 0 },
-#define TOSW 10
- { "to pattern", 0 },
-#define OTHRSW 11
- { "-othercomponent pattern", 0 },
-#define AFTRSW 12
- { "after date", 0 },
-#define BEFRSW 13
- { "before date", 0 },
-#define DATFDSW 14
- { "datefield field", 5 },
-#define SEQSW 15
- { "sequence name", 0 },
-#define NSEQSW 16
- { "nosequence", 0 },
-#define PUBLSW 17
- { "public", 0 },
-#define NPUBLSW 18
- { "nopublic", 0 },
-#define ZEROSW 19
- { "zero", 0 },
-#define NZEROSW 20
- { "nozero", 0 },
-#define LISTSW 21
- { "list", 0 },
-#define NLISTSW 22
- { "nolist", 0 },
-#define VERSIONSW 23
- { "version", 0 },
-#define HELPSW 24
- { "help", 0 },
- { NULL, 0 }
-};
+#define PICK_SWITCHES \
+ X("and", 0, ANDSW) \
+ X("or", 0, ORSW) \
+ X("not", 0, NOTSW) \
+ X("lbrace", 0, LBRSW) \
+ X("rbrace", 0, RBRSW) \
+ X("cc pattern", 0, CCSW) \
+ X("date pattern", 0, DATESW) \
+ X("from pattern", 0, FROMSW) \
+ X("search pattern", 0, SRCHSW) \
+ X("subject pattern", 0, SUBJSW) \
+ X("to pattern", 0, TOSW) \
+ X("-othercomponent pattern", 0, OTHRSW) \
+ X("after date", 0, AFTRSW) \
+ X("before date", 0, BEFRSW) \
+ X("datefield field", 5, DATFDSW) \
+ X("sequence name", 0, SEQSW) \
+ X("nosequence", 0, NSEQSW) \
+ X("public", 0, PUBLSW) \
+ X("nopublic", 0, NPUBLSW) \
+ X("zero", 0, ZEROSW) \
+ X("nozero", 0, NZEROSW) \
+ X("list", 0, LISTSW) \
+ X("nolist", 0, NLISTSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(PICK);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(PICK, switches);
+#undef X
static int listsw = -1;
#endif
#include <time.h>
-static struct swit parswit[] = {
-#define PRAND 0
- { "and", 0 },
-#define PROR 1
- { "or", 0 },
-#define PRNOT 2
- { "not", 0 },
-#define PRLBR 3
- { "lbrace", 0 },
-#define PRRBR 4
- { "rbrace", 0 },
-#define PRCC 5
- { "cc pattern", 0 },
-#define PRDATE 6
- { "date pattern", 0 },
-#define PRFROM 7
- { "from pattern", 0 },
-#define PRSRCH 8
- { "search pattern", 0 },
-#define PRSUBJ 9
- { "subject pattern", 0 },
-#define PRTO 10
- { "to pattern", 0 },
-#define PROTHR 11
- { "-othercomponent pattern", 15 },
-#define PRAFTR 12
- { "after date", 0 },
-#define PRBEFR 13
- { "before date", 0 },
-#define PRDATF 14
- { "datefield field", 5 },
- { NULL, 0 }
-};
+#define PARSE_SWITCHES \
+ X("and", 0, PRAND) \
+ X("or", 0, PROR) \
+ X("not", 0, PRNOT) \
+ X("lbrace", 0, PRLBR) \
+ X("rbrace", 0, PRRBR) \
+ X("cc pattern", 0, PRCC) \
+ X("date pattern", 0, PRDATE) \
+ X("from pattern", 0, PRFROM) \
+ X("search pattern", 0, PRSRCH) \
+ X("subject pattern", 0, PRSUBJ) \
+ X("to pattern", 0, PRTO) \
+ X("-othercomponent pattern", 15, PROTHR) \
+ X("after date", 0, PRAFTR) \
+ X("before date", 0, PRBEFR) \
+ X("datefield field", 5, PRDATF) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(PARSE);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(PARSE, parswit);
+#undef X
/* DEFINITIONS FOR PATTERN MATCHING */
register char *bp;
char buf[BUFSIZ], name[NAMESZ];
register struct tws *tw;
+ m_getfld_state_t gstate = 0;
NMH_UNUSED (stop);
fseek (fp, start, SEEK_SET);
- for (state = FLD, bp = NULL;;) {
- switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
+ for (bp = NULL;;) {
+ int bufsz = sizeof buf;
+ switch (state = m_getfld (&gstate, name, buf, &bufsz, fp)) {
case FLD:
- case FLDEOF:
case FLDPLUS:
if (bp != NULL)
free (bp), bp = NULL;
bp = add (buf, NULL);
while (state == FLDPLUS) {
- state = m_getfld (state, name, buf, sizeof buf, fp);
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, fp);
bp = add (buf, bp);
}
if (!mh_strcasecmp (name, n->n_datef))
break;
- if (state != FLDEOF)
- continue;
+ continue;
case BODY:
- case BODYEOF:
case FILEEOF:
case LENERR:
case FMTERR:
}
break;
}
+ m_getfld_state_destroy (&gstate);
if ((tw = dparsetime (bp)) == NULL)
advise (NULL, "unable to parse %s field in message %d, matching...",
0 : Switch can't be abbreviated; switch shown in -help.
# : Switch can be abbreviated to # characters; switch shown in -help. */
-static struct swit switches[] = {
-#define ALIASW 0
- { "alias aliasfile", 0 },
-#define CHKSW 1
- { "check", -5 }, /* interface from whom */
-#define NCHKSW 2
- { "nocheck", -7 }, /* interface from whom */
-#define DEBUGSW 3
- { "debug", -5 },
-#define DISTSW 4
- { "dist", -4 }, /* interface from dist */
-#define FILTSW 5
- { "filter filterfile", 0 },
-#define NFILTSW 6
- { "nofilter", 0 },
-#define FRMTSW 7
- { "format", 0 },
-#define NFRMTSW 8
- { "noformat", 0 },
-#define LIBSW 9
- { "library directory", -7 }, /* interface from send, whom */
-#define MIMESW 10
- { "mime", 0 },
-#define NMIMESW 11
- { "nomime", 0 },
-#define MSGDSW 12
- { "msgid", 0 },
-#define NMSGDSW 13
- { "nomsgid", 0 },
-#define VERBSW 14
- { "verbose", 0 },
-#define NVERBSW 15
- { "noverbose", 0 },
-#define WATCSW 16
- { "watch", 0 },
-#define NWATCSW 17
- { "nowatch", 0 },
-#define WHOMSW 18
- { "whom", -4 }, /* interface from whom */
-#define WIDTHSW 19
- { "width columns", 0 },
-#define VERSIONSW 20
- { "version", 0 },
-#define HELPSW 21
- { "help", 0 },
-#define BITSTUFFSW 22
- { "dashstuffing", -12 }, /* should we dashstuff BCC messages? */
-#define NBITSTUFFSW 23
- { "nodashstuffing", -14 },
-#define ANNOSW 24
- { "idanno number", -6 }, /* interface from send */
-#define CLIESW 25
- { "client host", -6 },
-#define SERVSW 26
- { "server host", 6 }, /* specify alternate SMTP server */
-#define SNOOPSW 27
- { "snoop", -5 }, /* snoop the SMTP transaction */
-#define PARTSW 28
- { "partno", -6 },
-#define QUEUESW 29
- { "queued", -6 },
-#define SASLSW 30
- { "sasl", SASLminc(-4) },
-#define NOSASLSW 31
- { "nosasl", SASLminc(-6) },
-#define SASLMXSSFSW 32
- { "saslmaxssf", SASLminc(-10) },
-#define SASLMECHSW 33
- { "saslmech", SASLminc(-5) },
-#define USERSW 34
- { "user", SASLminc(-4) },
-#define PORTSW 35
- { "port server port name/number", 4 },
-#define TLSSW 36
- { "tls", TLSminc(-3) },
-#define NTLSSW 37
- { "notls", TLSminc(-5) },
-#define FILEPROCSW 38
- { "fileproc", -4 },
-#define MHLPROCSW 39
- { "mhlproc", -3 },
-#define MTSSW 40
- { "mts smtp|sendmail/smtp|sendmail/pipe", 2 },
-#define MESSAGEIDSW 41
- { "messageid localname|random", 2 },
- { NULL, 0 }
-};
+#define POST_SWITCHES \
+ X("alias aliasfile", 0, ALIASW) \
+ X("check", -5, CHKSW) /* interface from whom */ \
+ X("nocheck", -7, NCHKSW) /* interface from whom */ \
+ X("debug", -5, DEBUGSW) \
+ X("dist", -4, DISTSW) /* interface from dist */ \
+ X("filter filterfile", 0, FILTSW) \
+ X("nofilter", 0, NFILTSW) \
+ X("format", 0, FRMTSW) \
+ X("noformat", 0, NFRMTSW) \
+ X("library directory", -7, LIBSW) /* interface from send, whom */ \
+ X("mime", 0, MIMESW) \
+ X("nomime", 0, NMIMESW) \
+ X("msgid", 0, MSGDSW) \
+ X("nomsgid", 0, NMSGDSW) \
+ X("verbose", 0, VERBSW) \
+ X("noverbose", 0, NVERBSW) \
+ X("watch", 0, WATCSW) \
+ X("nowatch", 0, NWATCSW) \
+ X("whom", -4, WHOMSW) /* interface from whom */ \
+ X("width columns", 0, WIDTHSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+ X("dashstuffing", -12, BITSTUFFSW) /* should we dashstuff BCC messages? */ \
+ X("nodashstuffing", -14, NBITSTUFFSW) \
+ X("idanno number", -6, ANNOSW) /* interface from send */ \
+ X("client host", -6, CLIESW) \
+ X("server host", 6, SERVSW) /* specify alternate SMTP server */ \
+ X("snoop", -5, SNOOPSW) /* snoop the SMTP transaction */ \
+ X("partno", -6, PARTSW) \
+ X("queued", -6, QUEUESW) \
+ X("sasl", SASLminc(-4), SASLSW) \
+ X("nosasl", SASLminc(-6), NOSASLSW) \
+ X("saslmaxssf", SASLminc(-10), SASLMXSSFSW) \
+ X("saslmech", SASLminc(-5), SASLMECHSW) \
+ X("user", SASLminc(-4), USERSW) \
+ X("port server port name/number", 4, PORTSW) \
+ X("tls", TLSminc(-3), TLSSW) \
+ X("notls", TLSminc(-5), NTLSSW) \
+ X("fileproc", -4, FILEPROCSW) \
+ X("mhlproc", -3, MHLPROCSW) \
+ X("mts smtp|sendmail/smtp|sendmail/pipe", 2, MTSSW) \
+ X("messageid localname|random", 2, MESSAGEIDSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(POST);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(POST, switches);
+#undef X
struct headers {
char *cp, *msg = NULL, **argp, **arguments, *envelope;
char buf[BUFSIZ], name[NAMESZ];
FILE *in, *out;
+ m_getfld_state_t gstate = 0;
#ifdef LOCALE
setlocale(LC_ALL, "");
start_headers ();
if (debug) {
verbose++;
- discard (out = stdout); /* XXX: reference discard() to help loader */
+ out = stdout;
} else {
if (whomsw) {
if ((out = fopen ("/dev/null", "w")) == NULL)
hdrtab = msgstate == NORMAL ? NHeaders : RHeaders;
- for (compnum = 1, state = FLD;;) {
- switch (state = m_getfld (state, name, buf, sizeof(buf), in)) {
+ for (compnum = 1;;) {
+ int bufsz = sizeof buf;
+ switch (state = m_getfld (&gstate, name, buf, &bufsz, in)) {
case FLD:
- case FLDEOF:
case FLDPLUS:
compnum++;
cp = add (buf, NULL);
while (state == FLDPLUS) {
- state = m_getfld (state, name, buf, sizeof(buf), in);
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, in);
cp = add (buf, cp);
}
putfmt (name, cp, out);
free (cp);
- if (state != FLDEOF)
- continue;
- finish_headers (out);
- break;
+ continue;
case BODY:
- case BODYEOF:
finish_headers (out);
if (whomsw)
break;
fprintf (out, "\n%s", buf);
while (state == BODY) {
- state = m_getfld (state, name, buf, sizeof(buf), in);
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, in);
fputs (buf, out);
}
break;
}
break;
}
+ m_getfld_state_destroy (&gstate);
if (pfd != NOTOK)
anno ();
fcc (char *file, char *folder)
{
pid_t child_id;
- int i, status;
+ int i, status, argp;
char fold[BUFSIZ];
+ char **arglist, *program;
if (verbose)
printf (" %sFcc %s: ", msgstate == RESENT ? "Resent-" : "", folder);
*folder == '+' || *folder == '@' ? "" : "+", folder);
/* now exec the fileproc */
- execlp (fileproc, r1bindex (fileproc, '/'),
- "-link", "-file", file, fold, NULL);
+
+ arglist = argsplit(fileproc, &program, &argp);
+ arglist[argp++] = "-link";
+ arglist[argp++] = "-file";
+ arglist[argp++] = file;
+ arglist[argp++] = fold;
+ arglist[argp] = NULL;
+ execvp (program, arglist);
_exit (-1);
default:
# define CERASE '#'
#endif
-static struct swit switches[] = {
-#define ERASESW 0
- { "erase chr", 0 },
-#define KILLSW 1
- { "kill chr", 0 },
-#define PREPSW 2
- { "prepend", 0 },
-#define NPREPSW 3
- { "noprepend", 0 },
-#define RAPDSW 4
- { "rapid", 0 },
-#define NRAPDSW 5
- { "norapid", 0 },
-#define BODYSW 6
- { "body", -4 },
-#define NBODYSW 7
- { "nobody", -6 },
-#define DOTSW 8
- { "doteof", 0 },
-#define NDOTSW 9
- { "nodoteof", 0 },
-#define VERSIONSW 10
- { "version", 0 },
-#define HELPSW 11
- { "help", 0 },
- { NULL, 0 }
-};
+#define PROMPTER_SWITCHES \
+ X("erase chr", 0, ERASESW) \
+ X("kill chr", 0, KILLSW) \
+ X("prepend", 0, PREPSW) \
+ X("noprepend", 0, NPREPSW) \
+ X("rapid", 0, RAPDSW) \
+ X("norapid", 0, NRAPDSW) \
+ X("body", -4, BODYSW) \
+ X("nobody", -6, NBODYSW) \
+ X("doteof", 0, DOTSW) \
+ X("nodoteof", 0, NDOTSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(PROMPTER);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(PROMPTER, switches);
+#undef X
static struct termios tio;
char **arguments, **argp;
FILE *in, *out;
char *tfile = NULL;
+ m_getfld_state_t gstate = 0;
#ifdef LOCALE
setlocale(LC_ALL, "");
/*
* Loop through the lines of the draft skeleton.
*/
- for (state = FLD;;) {
- switch (state = m_getfld (state, name, field, sizeof(field), in)) {
+ for (;;) {
+ int fieldsz = sizeof field;
+ switch (state = m_getfld (&gstate, name, field, &fieldsz, in)) {
case FLD:
- case FLDEOF:
case FLDPLUS:
/*
* Check if the value of field contains anything
printf ("%s:%s", name, field);
fprintf (out, "%s:%s", name, field);
while (state == FLDPLUS) {
- state =
- m_getfld (state, name, field, sizeof(field), in);
+ fieldsz = sizeof field;
+ state = m_getfld (&gstate, name, field, &fieldsz, in);
printf ("%s", field);
fprintf (out, "%s", field);
}
}
}
- if (state == FLDEOF) { /* moby hack */
- fprintf (out, "--------\n");
- printf ("--------\n");
- if (!body)
- break;
- goto no_body;
- }
continue;
case BODY:
- case BODYEOF:
case FILEEOF:
if (!body)
break;
if (!rapid && !sigint)
printf ("%s", field);
} while (state == BODY &&
- (state = m_getfld (state, name, field, sizeof(field), in)));
+ (fieldsz = sizeof field,
+ state = m_getfld (&gstate, name, field, &fieldsz, in)));
if (prepend || !body)
break;
else
printf ("\n--------Enter additional text\n\n");
}
-no_body:
+
fflush (stdout);
for (;;) {
getln (field, sizeof(field));
}
break;
}
+ m_getfld_state_destroy (&gstate);
if (body)
printf ("--------\n");
#include <h/mts.h>
#include <h/utils.h>
-static struct swit switches[] = {
-#define FORMSW 0
- { "form formfile", 4 },
-#define VERSIONSW 1
- { "version", 0 },
-#define HELPSW 2
- { "help", 0 },
- { NULL, 0 }
-};
+#define RCVDIST_SWITCHES \
+ X("form formfile", 4, FORMSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(RCVDIST);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(RCVDIST, switches);
+#undef X
static char backup[BUFSIZ] = "";
static char drft[BUFSIZ] = "";
char *cp, *scanl, name[NAMESZ], tmpbuf[SBUFSIZ];
register struct comp *cptr;
FILE *out;
+ m_getfld_state_t gstate = 0;
if (!(out = fopen (drft, "w")))
adios (drft, "unable to create");
if (cptr)
cptr->c_text = addrs;
- for (state = FLD;;) {
- switch (state = m_getfld (state, name, tmpbuf, SBUFSIZ, inb)) {
+ for (;;) {
+ int msg_count = SBUFSIZ;
+ switch (state = m_getfld (&gstate, name, tmpbuf, &msg_count, inb)) {
case FLD:
case FLDPLUS:
i = fmt_addcomptext(name, tmpbuf);
if (i != -1) {
char_read += msg_count;
while (state == FLDPLUS) {
- state = m_getfld (state, name, tmpbuf, SBUFSIZ, inb);
+ msg_count = SBUFSIZ;
+ state = m_getfld (&gstate, name, tmpbuf, &msg_count, inb);
fmt_appendcomp(i, name, tmpbuf);
char_read += msg_count;
}
}
- while (state == FLDPLUS)
- state = m_getfld (state, name, tmpbuf, SBUFSIZ, inb);
+ while (state == FLDPLUS) {
+ msg_count = SBUFSIZ;
+ state = m_getfld (&gstate, name, tmpbuf, &msg_count, inb);
+ }
break;
case LENERR:
}
}
finished: ;
+ m_getfld_state_destroy (&gstate);
i = format_len + char_read + 256;
scanl = mh_xmalloc ((size_t) i + 2);
#include <h/tws.h>
#include <h/mts.h>
-static struct swit switches[] = {
-#define MBOXSW 0
- { "mbox", 0 },
-#define MMDFSW 1
- { "mmdf", 0 },
-#define VERSIONSW 2
- { "version", 0 },
-#define HELPSW 3
- { "help", 0 },
- { NULL, 0 }
-};
+#define RCVPACK_SWITCHES \
+ X("mbox", 0, MBOXSW) \
+ X("mmdf", 0, MMDFSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(RCVPACK);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(RCVPACK, switches);
+#undef X
/*
* default format in which to save messages
#include <signal.h>
#include <h/mts.h>
-static struct swit switches[] = {
-#define CRETSW 0
- { "create", 0 },
-#define NCRETSW 1
- { "nocreate", 0 },
-#define UNSEENSW 2
- { "unseen", 0 },
-#define NUNSEENSW 3
- { "nounseen", 0 },
-#define PUBSW 4
- { "public", 0 },
-#define NPUBSW 5
- { "nopublic", 0 },
-#define ZEROSW 6
- { "zero", 0 },
-#define NZEROSW 7
- { "nozero", 0 },
-#define SEQSW 8
- { "sequence name", 0 },
-#define VERSIONSW 9
- { "version", 0 },
-#define HELPSW 10
- { "help", 0 },
- { NULL, 0 }
-};
+#define RCVSTORE_SWITCHES \
+ X("create", 0, CRETSW) \
+ X("nocreate", 0, NCRETSW) \
+ X("unseen", 0, UNSEENSW) \
+ X("nounseen", 0, NUNSEENSW) \
+ X("public", 0, PUBSW) \
+ X("nopublic", 0, NPUBSW) \
+ X("zero", 0, ZEROSW) \
+ X("nozero", 0, NZEROSW) \
+ X("sequence name", 0, SEQSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(RCVSTORE);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(RCVSTORE, switches);
+#undef X
/*
%<(mymbox{from})%<{to}To:%14(friendly{to})%>%>%<(zero)%17(friendly{from})%> \
%{subject}%<{body}<<%{body}>>%>"
-static struct swit switches[] = {
-#define BIFFSW 0
- { "biff", 0 },
-#define FORMSW 1
- { "form formatfile", 0 },
-#define FMTSW 2
- { "format string", 5 },
-#define WIDTHSW 3
- { "width columns", 0 },
-#define NLSW 4
- { "newline", 0 },
-#define NNLSW 5
- { "nonewline", 0 },
-#define BELSW 6
- { "bell", 0 },
-#define NBELSW 7
- { "nobell", 0 },
-#define VERSIONSW 8
- { "version", 0 },
-#define HELPSW 9
- { "help", 0 },
- { NULL, 0 }
-};
+#define RCVTTY_SWITCHES \
+ X("biff", 0, BIFFSW) \
+ X("form formatfile", 0, FORMSW) \
+ X("format string", 5, FMTSW) \
+ X("width columns", 0, WIDTHSW) \
+ X("newline", 0, NLSW) \
+ X("nonewline", 0, NNLSW) \
+ X("bell", 0, BELSW) \
+ X("nobell", 0, NBELSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(RCVTTY);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(RCVTTY, switches);
+#undef X
static jmp_buf myctx;
static int bell = 1;
/* get new format string */
nfs = new_fs (form, format, SCANFMT);
scan (stdin, 0, 0, nfs, width, 0, 0, NULL, 0L, 0);
+ scan_finished ();
if (newline)
write (fd, "\n\r", 2);
write (fd, scanl, strlen (scanl));
#include <fcntl.h>
#include <errno.h>
-static struct swit switches[] = {
-#define DRAFTSW 0
- { "draft", 0 },
-#define LINKSW 1
- { "link", 0 },
-#define NLINKSW 2
- { "nolink", 0 },
-#define PRESSW 3
- { "preserve", 0 },
-#define NPRESSW 4
- { "nopreserve", 0 },
-#define UNLINKSW 5
- { "unlink", 0 },
-#define NUNLINKSW 6
- { "nounlink", 0 },
-#define SRCSW 7
- { "src +folder", 0 },
-#define FILESW 8
- { "file file", 0 },
-#define RPROCSW 9
- { "rmmproc program", 0 },
-#define NRPRCSW 10
- { "normmproc", 0 },
-#define VERSIONSW 11
- { "version", 0 },
-#define HELPSW 12
- { "help", 0 },
- { NULL, 0 }
-};
+#define REFILE_SWITCHES \
+ X("draft", 0, DRAFTSW) \
+ X("link", 0, LINKSW) \
+ X("nolink", 0, NLINKSW) \
+ X("preserve", 0, PRESSW) \
+ X("nopreserve", 0, NPRESSW) \
+ X("unlink", 0, UNLINKSW) \
+ X("nounlink", 0, NUNLINKSW) \
+ X("src +folder", 0, SRCSW) \
+ X("file file", 0, FILESW) \
+ X("rmmproc program", 0, RPROCSW) \
+ X("normmproc", 0, NRPRCSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(REFILE);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(REFILE, switches);
+#undef X
static char maildir[BUFSIZ];
#include <h/utils.h>
-static struct swit switches[] = {
-#define GROUPSW 0
- { "group", 0 },
-#define NGROUPSW 1
- { "nogroup", 0 },
-#define ANNOSW 2
- { "annotate", 0 },
-#define NANNOSW 3
- { "noannotate", 0 },
-#define CCSW 4
- { "cc all|to|cc|me", 0 },
-#define NCCSW 5
- { "nocc type", 0 },
-#define DFOLDSW 6
- { "draftfolder +folder", 0 },
-#define DMSGSW 7
- { "draftmessage msg", 0 },
-#define NDFLDSW 8
- { "nodraftfolder", 0 },
-#define EDITRSW 9
- { "editor editor", 0 },
-#define NEDITSW 10
- { "noedit", 0 },
-#define FCCSW 11
- { "fcc folder", 0 },
-#define FILTSW 12
- { "filter filterfile", 0 },
-#define FORMSW 13
- { "form formfile", 0 },
-#define FRMTSW 14
- { "format", 5 },
-#define NFRMTSW 15
- { "noformat", 7 },
-#define INPLSW 16
- { "inplace", 0 },
-#define NINPLSW 17
- { "noinplace", 0 },
-#define MIMESW 18
- { "mime", 0 },
-#define NMIMESW 19
- { "nomime", 0 },
-#define QURYSW 20
- { "query", 0 },
-#define NQURYSW 21
- { "noquery", 0 },
-#define WHATSW 22
- { "whatnowproc program", 0 },
-#define NWHATSW 23
- { "nowhatnowproc", 0 },
-#define WIDTHSW 24
- { "width columns", 0 },
-#define VERSIONSW 25
- { "version", 0 },
-#define HELPSW 26
- { "help", 0 },
-#define FILESW 27
- { "file file", 4 }, /* interface from msh */
-#define BILDSW 28
- { "build", 5 }, /* interface from mhe */
-#define ATFILESW 29
- { "atfile", 0 },
-#define NOATFILESW 30
- { "noatfile", 0 },
-#define FMTPROCSW 31
- { "fmtproc program", 0 },
-#define NFMTPROCSW 32
- { "nofmtproc", 0 },
-
- { NULL, 0 }
-};
-
-static struct swit ccswitches[] = {
-#define CTOSW 0
- { "to", 0 },
-#define CCCSW 1
- { "cc", 0 },
-#define CMESW 2
- { "me", 0 },
-#define CALSW 3
- { "all", 0 },
- { NULL, 0 }
-};
-
-static struct swit aqrnl[] = {
-#define NOSW 0
- { "quit", 0 },
-#define YESW 1
- { "replace", 0 },
-#define LISTDSW 2
- { "list", 0 },
-#define REFILSW 3
- { "refile +folder", 0 },
-#define NEWSW 4
- { "new", 0 },
- { NULL, 0 }
-};
+#define REPL_SWITCHES \
+ X("group", 0, GROUPSW) \
+ X("nogroup", 0, NGROUPSW) \
+ X("annotate", 0, ANNOSW) \
+ X("noannotate", 0, NANNOSW) \
+ X("cc all|to|cc|me", 0, CCSW) \
+ X("nocc type", 0, NCCSW) \
+ X("draftfolder +folder", 0, DFOLDSW) \
+ X("draftmessage msg", 0, DMSGSW) \
+ X("nodraftfolder", 0, NDFLDSW) \
+ X("editor editor", 0, EDITRSW) \
+ X("noedit", 0, NEDITSW) \
+ X("fcc folder", 0, FCCSW) \
+ X("filter filterfile", 0, FILTSW) \
+ X("form formfile", 0, FORMSW) \
+ X("format", 5, FRMTSW) \
+ X("noformat", 7, NFRMTSW) \
+ X("inplace", 0, INPLSW) \
+ X("noinplace", 0, NINPLSW) \
+ X("mime", 0, MIMESW) \
+ X("nomime", 0, NMIMESW) \
+ X("query", 0, QURYSW) \
+ X("noquery", 0, NQURYSW) \
+ X("whatnowproc program", 0, WHATSW) \
+ X("nowhatnowproc", 0, NWHATSW) \
+ X("width columns", 0, WIDTHSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+ X("file file", 4, FILESW) /* interface from msh */ \
+ X("build", 5, BILDSW) /* interface from mhe */ \
+ X("atfile", 0, ATFILESW) \
+ X("noatfile", 0, NOATFILESW) \
+ X("fmtproc program", 0, FMTPROCSW) \
+ X("nofmtproc", 0, NFMTPROCSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(REPL);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(REPL, switches);
+#undef X
+
+#define CC_SWITCHES \
+ X("to", 0, CTOSW) \
+ X("cc", 0, CCCSW) \
+ X("me", 0, CMESW) \
+ X("all", 0, CALSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(CC);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(CC, ccswitches);
+#undef X
+
+#define DISPO_SWITCHES \
+ X("quit", 0, NOSW) \
+ X("replace", 0, YESW) \
+ X("list", 0, LISTDSW) \
+ X("refile +folder", 0, REFILSW) \
+ X("new", 0, NEWSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(DISPO);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(DISPO, aqrnl);
+#undef X
static struct swit aqrl[] = {
- { "quit", 0 },
- { "replace", 0 },
- { "list", 0 },
- { "refile +folder", 0 },
- { NULL, 0 }
+ { "quit", 0, NOSW },
+ { "replace", 0, YESW },
+ { "list", 0, LISTDSW },
+ { "refile +folder", 0, REFILSW },
+ { NULL, 0, 0 }
};
short ccto = -1; /* global for replsbr */
char name[NAMESZ], *scanl;
unsigned char *cp;
static int dat[5]; /* aux. data for format routine */
+ m_getfld_state_t gstate = 0;
FILE *out;
NMH_UNUSED (msg);
/*
* pick any interesting stuff out of msg "inb"
*/
- for (state = FLD;;) {
- state = m_getfld (state, name, tmpbuf, sizeof(tmpbuf), inb);
+ for (;;) {
+ int msg_count = sizeof tmpbuf;
+ state = m_getfld (&gstate, name, tmpbuf, &msg_count, inb);
switch (state) {
case FLD:
case FLDPLUS:
if (i != -1) {
char_read += msg_count;
while (state == FLDPLUS) {
- state = m_getfld(state, name, tmpbuf,
- sizeof(tmpbuf), inb);
+ msg_count= sizeof tmpbuf;
+ state = m_getfld (&gstate, name, tmpbuf, &msg_count, inb);
fmt_appendcomp(i, name, tmpbuf);
char_read += msg_count;
}
}
- while (state == FLDPLUS)
- state = m_getfld (state, name, tmpbuf, SBUFSIZ, inb);
+ while (state == FLDPLUS) {
+ msg_count= sizeof tmpbuf;
+ state = m_getfld (&gstate, name, tmpbuf, &msg_count, inb);
+ }
break;
case LENERR:
adios (NULL, "m_getfld() returned %d", state);
}
}
+ m_getfld_state_destroy (&gstate);
/*
* format and output the header lines.
int pid;
char *mhl;
char *errstr;
- char *arglist[7];
+ char **arglist;
+ int argnum;
if (filter == NULL)
return;
if (access (filter, R_OK) == NOTOK)
adios (filter, "unable to read");
- mhl = r1bindex (mhlproc, '/');
-
rewind (in);
lseek (fileno(in), (off_t) 0, SEEK_SET);
dup2 (fileno (out), fileno (stdout));
closefds (3);
- arglist[0] = mhl;
- arglist[1] = "-form";
- arglist[2] = filter;
- arglist[3] = "-noclear";
+ /*
+ * We're not allocating the memory for the extra arguments,
+ * because we never call arglist_free(). But if we ever change
+ * that be sure to use getcpy() for the extra arguments.
+ */
+ arglist = argsplit(mhlproc, &mhl, &argnum);
+ arglist[argnum++] = "-form";
+ arglist[argnum++] = filter;
+ arglist[argnum++] = "-noclear";
switch (fmtproc) {
case 1:
- arglist[4] = "-fmtproc";
- arglist[5] = formatproc;
- arglist[6] = NULL;
+ arglist[argnum++] = "-fmtproc";
+ arglist[argnum++] = formatproc;
break;
case 0:
- arglist[4] = "-nofmtproc";
- arglist[5] = NULL;
+ arglist[argnum++] = "-nofmtproc";
break;
- default:
- arglist[4] = NULL;
}
- execvp (mhlproc, arglist);
+ arglist[argnum++] = NULL;
+
+ execvp (mhl, arglist);
errstr = strerror(errno);
write(2, "unable to exec ", 15);
write(2, mhlproc, strlen(mhlproc));
#include <h/mh.h>
-static struct swit switches[] = {
-#define INTRSW 0
- { "interactive", 0 },
-#define NINTRSW 1
- { "nointeractive", 0 },
-#define VERSIONSW 2
- { "version", 0 },
-#define HELPSW 3
- { "help", 0 },
- { NULL, 0 }
-};
+#define RMF_SWITCHES \
+ X("interactive", 0, INTRSW) \
+ X("nointeractive", 0, NINTRSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(RMF);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(RMF, switches);
+#undef X
/*
* static prototypes
#include <h/mh.h>
#include <h/utils.h>
-static struct swit switches[] = {
-#define UNLINKSW 0
- { "unlink", 0 },
-#define NUNLINKSW 1
- { "nounlink", 0 },
-#define VERSIONSW 2
- { "version", 0 },
-#define HELPSW 3
- { "help", 0 },
- { NULL, 0 }
-};
+#define RMM_SWITCHES \
+ X("unlink", 0, UNLINKSW) \
+ X("nounlink", 0, NUNLINKSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(RMM);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(RMM, switches);
+#undef X
int
#include <h/utils.h>
#include <errno.h>
-static struct swit switches[] = {
-#define CLRSW 0
- { "clear", 0 },
-#define NCLRSW 1
- { "noclear", 0 },
-#define FORMSW 2
- { "form formatfile", 0 },
-#define FMTSW 3
- { "format string", 5 },
-#define HEADSW 4
- { "header", 0 },
-#define NHEADSW 5
- { "noheader", 0 },
-#define WIDTHSW 6
- { "width columns", 0 },
-#define REVSW 7
- { "reverse", 0 },
-#define NREVSW 8
- { "noreverse", 0 },
-#define FILESW 9
- { "file file", 4 },
-#define VERSIONSW 10
- { "version", 0 },
-#define HELPSW 11
- { "help", 0 },
- { NULL, 0 }
-};
+#define SCAN_SWITCHES \
+ X("clear", 0, CLRSW) \
+ X("noclear", 0, NCLRSW) \
+ X("form formatfile", 0, FORMSW) \
+ X("format string", 5, FMTSW) \
+ X("header", 0, HEADSW) \
+ X("noheader", 0, NHEADSW) \
+ X("width columns", 0, WIDTHSW) \
+ X("reverse", 0, REVSW) \
+ X("noreverse", 0, NREVSW) \
+ X("file file", 4, FILESW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(SCAN);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(SCAN, switches);
+#undef X
-/*
- * global for sbr/formatsbr.c - yech!
- */
-#ifdef LBL
-extern struct msgs *fmt_current_folder;
-#endif
-
/*
* prototypes
*/
printf ("FOLDER %s\t%s\n", file, dtimenow (1));
}
- m_unknown (in);
+ scan_detect_mbox_style (in);
for (msgnum = 1; ; ++msgnum) {
state = scan (in, msgnum, -1, nfs, width, 0, 0,
hdrflag ? file : NULL, 0L, 1);
if (state != SCNMSG && state != SCNENC)
break;
}
+ scan_finished ();
fclose (in);
done (0);
}
ontty = isatty (fileno (stdout));
-#ifdef LBL
- else
- fmt_current_folder = mp;
-#endif
-
for (msgnum = revflag ? mp->hghsel : mp->lowsel;
(revflag ? msgnum >= mp->lowsel : msgnum <= mp->hghsel);
msgnum += (revflag ? -1 : 1)) {
advise (NULL, "message %d: empty", msgnum);
break;
}
+ scan_finished ();
hdrflag = 0;
fclose (in);
if (ontty)
}
}
-#ifdef LBL
- seq_save (mp); /* because formatsbr might have made changes */
-#endif
-
folder_free (mp); /* free folder/message structure */
if (clearflag)
clear_screen ();
static int dat[5]; /* aux. data for format routine */
char *scanl = 0; /* text of most recent scanline */
+m_getfld_state_t gstate; /* for access by msh */
#define DIEWRERR() adios (scnmsg, "write error on")
char *scnmsg = NULL;
FILE *scnout = NULL;
char name[NAMESZ];
+ int bufsz;
static int rlwidth, slwidth;
static size_t scanl_size;
* Get the first field. If the message is non-empty
* and we're doing an "inc", open the output file.
*/
- if ((state = m_getfld (FLD, name, tmpbuf, rlwidth, inb)) == FILEEOF) {
+ bufsz = rlwidth;
+ m_getfld_state_reset (&gstate);
+ if ((state = m_getfld (&gstate, name, tmpbuf, &bufsz, inb)) == FILEEOF) {
if (ferror(inb)) {
advise("read", "unable to"); /* "read error" */
return SCNFAT;
}
/* scan - main loop */
- for (compnum = 1; ; state = m_getfld (state, name, tmpbuf, rlwidth, inb)) {
+ for (compnum = 1; ;
+ bufsz = rlwidth, state = m_getfld (&gstate, name, tmpbuf, &bufsz, inb)) {
switch (state) {
case FLD:
case FLDPLUS:
}
while (state == FLDPLUS) {
- state = m_getfld (state, name, tmpbuf, rlwidth, inb);
+ bufsz = rlwidth;
+ state = m_getfld (&gstate, name, tmpbuf, &bufsz, inb);
if (outnum)
FPUTS (tmpbuf);
}
*/
if ((i = strlen(tmpbuf)) < rlwidth) {
- state = m_getfld (state, name, tmpbuf + i,
- rlwidth - i, inb);
+ bufsz = rlwidth - i;
+ state = m_getfld (&gstate, name, tmpbuf + i, &bufsz, inb);
}
if (! outnum) {
}
while (state == BODY) {
- state = m_getfld(state, name, tmpbuf, rlwidth, inb);
+ bufsz = rlwidth;
+ state = m_getfld (&gstate, name, tmpbuf, &bufsz, inb);
FPUTS(tmpbuf);
}
goto finished;
/* return dynamically allocated buffers to pool */
while ((cptr = *savecomp++)) {
- *--nxtbuf = cptr->c_text;
cptr->c_text = NULL;
}
- *--nxtbuf = tmpbuf;
if (outnum && (ferror(scnout) || fclose (scnout) == EOF))
DIEWRERR();
return (0);
}
+/* The following three functions allow access to the global gstate above. */
+void
+scan_finished () {
+ m_getfld_state_destroy (&gstate);
+}
+
+void
+scan_detect_mbox_style (FILE *f) {
+ m_unknown (&gstate, f);
+}
+
+void
+scan_eom_action (int (*action)()) {
+ m_eomsbr (gstate, action);
+}
+
+void
+scan_reset_m_getfld_state () {
+ m_getfld_state_reset (&gstate);
+}
# define TLSminc(a) 0
#endif /* TLS_SUPPORT */
-static struct swit switches[] = {
-#define ALIASW 0
- { "alias aliasfile", 0 },
-#define DEBUGSW 1
- { "debug", -5 },
-#define DRAFTSW 2
- { "draft", 0 },
-#define DFOLDSW 3
- { "draftfolder +folder", 6 },
-#define DMSGSW 4
- { "draftmessage msg", 6 },
-#define NDFLDSW 5
- { "nodraftfolder", 0 },
-#define FILTSW 6
- { "filter filterfile", 0 },
-#define NFILTSW 7
- { "nofilter", 0 },
-#define FRMTSW 8
- { "format", 0 },
-#define NFRMTSW 9
- { "noformat", 0 },
-#define FORWSW 10
- { "forward", 0 },
-#define NFORWSW 11
- { "noforward", 0 },
-#define MIMESW 12
- { "mime", 0 },
-#define NMIMESW 13
- { "nomime", 0 },
-#define MSGDSW 14
- { "msgid", 0 },
-#define NMSGDSW 15
- { "nomsgid", 0 },
-#define PUSHSW 16
- { "push", 0 },
-#define NPUSHSW 17
- { "nopush", 0 },
-#define SPLITSW 18
- { "split seconds", 0 },
-#define UNIQSW 19
- { "unique", -6 },
-#define NUNIQSW 20
- { "nounique", -8 },
-#define VERBSW 21
- { "verbose", 0 },
-#define NVERBSW 22
- { "noverbose", 0 },
-#define WATCSW 23
- { "watch", 0 },
-#define NWATCSW 24
- { "nowatch", 0 },
-#define WIDTHSW 25
- { "width columns", 0 },
-#define VERSIONSW 26
- { "version", 0 },
-#define HELPSW 27
- { "help", 0 },
-#define BITSTUFFSW 28
- { "dashstuffing", -12 },
-#define NBITSTUFFSW 29
- { "nodashstuffing", -14 },
-#define MAILSW 30
- { "mail", -4 },
-#define SAMLSW 31
- { "saml", -4 },
-#define SENDSW 32
- { "send", -4 },
-#define SOMLSW 33
- { "soml", -4 },
-#define CLIESW 34
- { "client host", -6 },
-#define SERVSW 35
- { "server host", 6 },
-#define SNOOPSW 36
- { "snoop", 5 },
-#define SASLSW 37
- { "sasl", SASLminc(4) },
-#define NOSASLSW 38
- { "nosasl", SASLminc(-6) },
-#define SASLMXSSFSW 39
- { "saslmaxssf", SASLminc(-10) },
-#define SASLMECHSW 40
- { "saslmech mechanism", SASLminc(-5) },
-#define USERSW 41
- { "user username", SASLminc(-4) },
-#define ATTACHSW 42
- { "attach", 6 },
-#define NOATTACHSW 43
- { "noattach", 0 },
-#define ATTACHFORMATSW 44
- { "attachformat", 7 },
-#define PORTSW 45
- { "port server-port-name/number" , 4 },
-#define TLSSW 46
- { "tls", TLSminc(-3) },
-#define NTLSSW 47
- { "notls", TLSminc(-5) },
-#define MTSSW 48
- { "mts smtp|sendmail/smtp|sendmail/pipe", 2 },
-#define MESSAGEIDSW 49
- { "messageid localname|random", 2 },
- { NULL, 0 }
-};
-
-static struct swit anyl[] = {
-#define NOSW 0
- { "no", 0 },
-#define YESW 1
- { "yes", 0 },
-#define LISTDSW 2
- { "list", 0 },
- { NULL, 0 }
-};
+#define SEND_SWITCHES \
+ X("alias aliasfile", 0, ALIASW) \
+ X("debug", -5, DEBUGSW) \
+ X("draft", 0, DRAFTSW) \
+ X("draftfolder +folder", 6, DFOLDSW) \
+ X("draftmessage msg", 6, DMSGSW) \
+ X("nodraftfolder", 0, NDFLDSW) \
+ X("filter filterfile", 0, FILTSW) \
+ X("nofilter", 0, NFILTSW) \
+ X("format", 0, FRMTSW) \
+ X("noformat", 0, NFRMTSW) \
+ X("forward", 0, FORWSW) \
+ X("noforward", 0, NFORWSW) \
+ X("mime", 0, MIMESW) \
+ X("nomime", 0, NMIMESW) \
+ X("msgid", 0, MSGDSW) \
+ X("nomsgid", 0, NMSGDSW) \
+ X("push", 0, PUSHSW) \
+ X("nopush", 0, NPUSHSW) \
+ X("split seconds", 0, SPLITSW) \
+ X("unique", -6, UNIQSW) \
+ X("nounique", -8, NUNIQSW) \
+ X("verbose", 0, VERBSW) \
+ X("noverbose", 0, NVERBSW) \
+ X("watch", 0, WATCSW) \
+ X("nowatch", 0, NWATCSW) \
+ X("width columns", 0, WIDTHSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+ X("dashstuffing", -12, BITSTUFFSW) \
+ X("nodashstuffing", -14, NBITSTUFFSW) \
+ X("mail", -4, MAILSW) \
+ X("saml", -4, SAMLSW) \
+ X("send", -4, SENDSW) \
+ X("soml", -4, SOMLSW) \
+ X("client host", -6, CLIESW) \
+ X("server host", 6, SERVSW) \
+ X("snoop", 5, SNOOPSW) \
+ X("sasl", SASLminc(4), SASLSW) \
+ X("nosasl", SASLminc(-6), NOSASLSW) \
+ X("saslmaxssf", SASLminc(-10), SASLMXSSFSW) \
+ X("saslmech mechanism", SASLminc(-5), SASLMECHSW) \
+ X("user username", SASLminc(-4), USERSW) \
+ X("attach", 6, ATTACHSW) \
+ X("noattach", 0, NOATTACHSW) \
+ X("attachformat", 7, ATTACHFORMATSW) \
+ X("port server-port-name/number", 4, PORTSW) \
+ X("tls", TLSminc(-3), TLSSW) \
+ X("notls", TLSminc(-5), NTLSSW) \
+ X("mts smtp|sendmail/smtp|sendmail/pipe", 2, MTSSW) \
+ X("messageid localname|random", 2, MESSAGEIDSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(SEND);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(SEND, switches);
+#undef X
+
+#define USE_SWITCHES \
+ X("no", 0, NOSW) \
+ X("yes", 0, YESW) \
+ X("list", 0, LISTDSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(USE);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(USE, anyl);
+#undef X
extern int debugsw; /* from sendsbr.c */
extern int forwsw;
char subject[BUFSIZ];
char name[NAMESZ], partnum[BUFSIZ];
FILE *in;
+ m_getfld_state_t gstate = 0;
if ((in = fopen (drft, "r")) == NULL)
adios (drft, "unable to open for reading");
* Scan through the message and examine the various header fields,
* as well as locate the beginning of the message body.
*/
- for (compnum = 1, state = FLD;;) {
- switch (state = m_getfld (state, name, buffer, sizeof(buffer), in)) {
+ m_getfld_track_filepos (&gstate, in);
+ for (compnum = 1;;) {
+ int bufsz = sizeof buffer;
+ switch (state = m_getfld (&gstate, name, buffer, &bufsz, in)) {
case FLD:
case FLDPLUS:
- case FLDEOF:
compnum++;
/*
* This header field is discarded.
*/
if (!mh_strcasecmp (name, "Message-ID")) {
- while (state == FLDPLUS)
- state = m_getfld (state, name, buffer, sizeof(buffer), in);
+ while (state == FLDPLUS) {
+ bufsz = sizeof buffer;
+ state = m_getfld (&gstate, name, buffer, &bufsz, in);
+ }
} else if (uprf (name, XXX_FIELD_PRF)
|| !mh_strcasecmp (name, VRSN_FIELD)
|| !mh_strcasecmp (name, "Subject")
dp = add (concat (name, ":", buffer, NULL), dp);
while (state == FLDPLUS) {
- state = m_getfld (state, name, buffer, sizeof(buffer), in);
+ bufsz = sizeof buffer;
+ state = m_getfld (&gstate, name, buffer, &bufsz, in);
dp = add (buffer, dp);
}
} else {
*/
cp = add (concat (name, ":", buffer, NULL), cp);
while (state == FLDPLUS) {
- state = m_getfld (state, name, buffer, sizeof(buffer), in);
+ bufsz = sizeof buffer;
+ state = m_getfld (&gstate, name, buffer, &bufsz, in);
cp = add (buffer, cp);
}
}
- if (state != FLDEOF) {
- start = ftell (in) + 1;
- continue;
- }
- /* else fall... */
+ start = ftell (in) + 1;
+ continue;
case BODY:
- case BODYEOF:
case FILEEOF:
break;
break;
}
+ m_getfld_state_destroy (&gstate);
if (cp == NULL)
adios (NULL, "headers missing from draft");
alert (char *file, int out)
{
pid_t child_id;
- int i, in;
+ int i, in, argp;
char buf[BUFSIZ];
+ char *program;
+ char **arglist;
for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++)
sleep (5);
snprintf (buf, sizeof(buf), "send failed on %s",
forwsw ? "enclosed draft" : file);
- execlp (mailproc, r1bindex (mailproc, '/'), getusername (),
- "-subject", buf, NULL);
+ arglist = argsplit(mailproc, &program, &argp);
+
+ arglist[argp++] = getusername();
+ arglist[argp++] = "-subject";
+ arglist[argp++] = buf;
+ arglist[argp] = NULL;
+
+ execvp (program, arglist);
fprintf (stderr, "unable to exec ");
perror (mailproc);
_exit (-1);
#include <h/mime.h>
#include <h/utils.h>
-static struct swit switches[] = {
-#define CHECKMIMESW 0
- { "checkmime", 0 },
-#define NOCHECKMIMESW 1
- { "nocheckmime", 0 },
-#define HEADSW 2
- { "header", 0 },
-#define NHEADSW 3
- { "noheader", 0 },
-#define FORMSW 4
- { "form formfile", 0 },
-#define PROGSW 5
- { "moreproc program", 0 },
-#define NPROGSW 6
- { "nomoreproc", 0 },
-#define LENSW 7
- { "length lines", 0 },
-#define WIDTHSW 8
- { "width columns", 0 },
-#define SHOWSW 9
- { "showproc program", 0 },
-#define SHOWMIMESW 10
- { "showmimeproc program", 0 },
-#define NSHOWSW 11
- { "noshowproc", 0 },
-#define DRFTSW 12
- { "draft", 0 },
-#define FILESW 13
- { "file file", -4 }, /* interface from showfile */
-#define FMTPROCSW 14
- { "fmtproc program", 0 },
-#define NFMTPROCSW 15
- { "nofmtproc", 0 },
-#define VERSIONSW 16
- { "version", 0 },
-#define HELPSW 17
- { "help", 0 },
- { NULL, 0 }
-};
+#define SHOW_SWITCHES \
+ X("checkmime", 0, CHECKMIMESW) \
+ X("nocheckmime", 0, NOCHECKMIMESW) \
+ X("header", 0, HEADSW) \
+ X("noheader", 0, NHEADSW) \
+ X("form formfile", 0, FORMSW) \
+ X("moreproc program", 0, PROGSW) \
+ X("nomoreproc", 0, NPROGSW) \
+ X("length lines", 0, LENSW) \
+ X("width columns", 0, WIDTHSW) \
+ X("showproc program", 0, SHOWSW) \
+ X("showmimeproc program", 0, SHOWMIMESW) \
+ X("noshowproc", 0, NSHOWSW) \
+ X("draft", 0, DRFTSW) \
+ X("file file", -4, FILESW) /* interface from showfile */ \
+ X("fmtproc program", 0, FMTPROCSW) \
+ X("nofmtproc", 0, NFMTPROCSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(SHOW);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(SHOW, switches);
+#undef X
/*
* static prototypes
char *cp;
char buf[BUFSIZ], name[NAMESZ];
FILE *fp;
+ m_getfld_state_t gstate = 0;
if ((fp = fopen (msgnam, "r")) == NULL)
return 0;
- for (state = FLD;;) {
- switch (state = m_getfld (state, name, buf, sizeof(buf), fp)) {
+ for (;;) {
+ int bufsz = sizeof buf;
+ switch (state = m_getfld (&gstate, name, buf, &bufsz, fp)) {
case FLD:
case FLDPLUS:
- case FLDEOF:
/*
* Check Content-Type field
*/
cp = add (buf, NULL);
while (state == FLDPLUS) {
- state = m_getfld (state, name, buf, sizeof(buf), fp);
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, fp);
cp = add (buf, cp);
}
bp = cp;
if (!mh_strcasecmp (name, ENCODING_FIELD)) {
cp = add (buf, NULL);
while (state == FLDPLUS) {
- state = m_getfld (state, name, buf, sizeof(buf), fp);
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, fp);
cp = add (buf, cp);
}
for (bp = cp; isspace (*bp); bp++)
* Just skip the rest of this header
* field and go to next one.
*/
- while (state == FLDPLUS)
- state = m_getfld (state, name, buf, sizeof(buf), fp);
+ while (state == FLDPLUS) {
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, fp);
+ }
break;
/*
return 0;
}
}
+ m_getfld_state_destroy (&gstate);
}
#include <utmpx.h>
#endif /* HAVE_GETUTXENT */
-static struct swit switches[] = {
-#define ADDRSW 0
- { "addr address", 0 },
-#define USERSW 1
- { "user name", 0 },
-#define FILESW 2
- { "file file", 0 },
-#define SENDERSW 3
- { "sender address", 0 },
-#define MAILBOXSW 4
- { "mailbox file", 0 },
-#define HOMESW 5
- { "home directory", -4 },
-#define INFOSW 6
- { "info data", 0 },
-#define MAILSW 7
- { "maildelivery file", 0 },
-#define VERBSW 8
- { "verbose", 0 },
-#define NVERBSW 9
- { "noverbose", 0 },
-#define SUPPRESSDUP 10
- { "suppressdup", 0 },
-#define NSUPPRESSDUP 11
- { "nosuppressdup", 0 },
-#define DEBUGSW 12
- { "debug", 0 },
-#define VERSIONSW 13
- { "version", 0 },
-#define HELPSW 14
- { "help", 0 },
- { NULL, 0 }
-};
+#define SLOCAL_SWITCHES \
+ X("addr address", 0, ADDRSW) \
+ X("user name", 0, USERSW) \
+ X("file file", 0, FILESW) \
+ X("sender address", 0, SENDERSW) \
+ X("mailbox file", 0, MAILBOXSW) \
+ X("home directory", -4, HOMESW) \
+ X("info data", 0, INFOSW) \
+ X("maildelivery file", 0, MAILSW) \
+ X("verbose", 0, VERBSW) \
+ X("noverbose", 0, NVERBSW) \
+ X("suppressdup", 0, SUPPRESSDUP) \
+ X("nosuppressdup", 0, NSUPPRESSDUP) \
+ X("debug", 0, DEBUGSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(SLOCAL);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(SLOCAL, switches);
+#undef X
static int globbed = 0; /* have we built "vars" table yet? */
static int parsed = 0; /* have we built header field table yet */
char name[NAMESZ], field[BUFSIZ];
struct pair *p, *q;
FILE *in;
+ m_getfld_state_t gstate = 0;
if (parsed++)
return 0;
* Scan the headers of the message and build
* a lookup table.
*/
- for (i = 0, state = FLD;;) {
- switch (state = m_getfld (state, name, field, sizeof(field), in)) {
+ for (i = 0;;) {
+ int fieldsz = sizeof field;
+ switch (state = m_getfld (&gstate, name, field, &fieldsz, in)) {
case FLD:
- case FLDEOF:
case FLDPLUS:
lp = add (field, NULL);
while (state == FLDPLUS) {
- state = m_getfld (state, name, field, sizeof(field), in);
+ fieldsz = sizeof field;
+ state = m_getfld (&gstate, name, field, &fieldsz, in);
lp = add (field, lp);
}
for (p = hdrs; p->p_name; p++) {
p++, i++;
p->p_name = NULL;
}
- if (state != FLDEOF)
- continue;
- break;
+ continue;
case BODY:
- case BODYEOF:
case FILEEOF:
break;
}
break;
}
+ m_getfld_state_destroy (&gstate);
fclose (in);
if ((p = lookup (vars, "reply-to"))) {
datum key, value;
DBM *db;
FILE *in;
+ m_getfld_state_t gstate = 0;
if ((fd1 = dup (fd)) == -1)
return -1;
}
rewind (in);
- for (state = FLD;;) {
- state = m_getfld (state, name, buf, sizeof(buf), in);
+ for (;;) {
+ int bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, in);
switch (state) {
case FLD:
case FLDPLUS:
- case FLDEOF:
/* Search for the message ID */
if (mh_strcasecmp (name, "Message-ID")) {
- while (state == FLDPLUS)
- state = m_getfld (state, name, buf, sizeof(buf), in);
+ while (state == FLDPLUS) {
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, in);
+ }
continue;
}
cp = add (buf, NULL);
while (state == FLDPLUS) {
- state = m_getfld (state, name, buf, sizeof(buf), in);
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, in);
cp = add (buf, cp);
}
key.dptr = trimcpy (cp);
break;
case BODY:
- case BODYEOF:
case FILEEOF:
break;
break;
}
+ m_getfld_state_destroy (&gstate);
fclose (in);
return 0;
#include <h/tws.h>
#include <h/utils.h>
-static struct swit switches[] = {
-#define DATESW 0
- { "datefield field", 0 },
-#define TEXTSW 1
- { "textfield field", 0 },
-#define NSUBJSW 2
- { "notextfield", 0 },
-#define SUBJSW 3
- { "subject", -3 }, /* backward-compatibility */
-#define LIMSW 4
- { "limit days", 0 },
-#define NLIMSW 5
- { "nolimit", 0 },
-#define VERBSW 6
- { "verbose", 0 },
-#define NVERBSW 7
- { "noverbose", 0 },
-#define ALLMSGS 8
- { "all", 0 },
-#define NALLMSGS 9
- { "noall", 0 },
-#define CHECKSW 10
- { "check", 0 },
-#define NCHECKSW 11
- { "nocheck", 0 },
-#define VERSIONSW 12
- { "version", 0 },
-#define HELPSW 13
- { "help", 0 },
- { NULL, 0 }
-};
+#define SORTM_SWITCHES \
+ X("datefield field", 0, DATESW) \
+ X("textfield field", 0, TEXTSW) \
+ X("notextfield", 0, NSUBJSW) \
+ X("subject", -3, SUBJSW) /* backward-compatibility */ \
+ X("limit days", 0, LIMSW) \
+ X("nolimit", 0, NLIMSW) \
+ X("verbose", 0, VERBSW) \
+ X("noverbose", 0, NVERBSW) \
+ X("all", 0, ALLMSGS) \
+ X("noall", 0, NALLMSGS) \
+ X("check", 0, CHECKSW) \
+ X("nocheck", 0, NCHECKSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(SORTM);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(SORTM, switches);
+#undef X
struct smsg {
int s_msg;
register struct tws *tw;
register char *datecomp = NULL, *subjcomp = NULL;
register FILE *in;
+ m_getfld_state_t gstate = 0;
if ((in = fopen (msgnam = m_name (msg), "r")) == NULL) {
admonish (msgnam, "unable to read message");
return (0);
}
- for (compnum = 1, state = FLD;;) {
- switch (state = m_getfld (state, nam, buf, sizeof(buf), in)) {
+ for (compnum = 1;;) {
+ int bufsz = sizeof buf;
+ switch (state = m_getfld (&gstate, nam, buf, &bufsz, in)) {
case FLD:
- case FLDEOF:
case FLDPLUS:
compnum++;
if (!mh_strcasecmp (nam, datesw)) {
datecomp = add (buf, datecomp);
while (state == FLDPLUS) {
- state = m_getfld (state, nam, buf, sizeof(buf), in);
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, nam, buf, &bufsz, in);
datecomp = add (buf, datecomp);
}
if (!subjsort || subjcomp)
} else if (subjsort && !mh_strcasecmp (nam, subjsort)) {
subjcomp = add (buf, subjcomp);
while (state == FLDPLUS) {
- state = m_getfld (state, nam, buf, sizeof(buf), in);
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, nam, buf, &bufsz, in);
subjcomp = add (buf, subjcomp);
}
if (datecomp)
break;
} else {
/* just flush this guy */
- while (state == FLDPLUS)
- state = m_getfld (state, nam, buf, sizeof(buf), in);
+ while (state == FLDPLUS) {
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, nam, buf, &bufsz, in);
+ }
}
continue;
case BODY:
- case BODYEOF:
case FILEEOF:
break;
}
break;
}
+ m_getfld_state_destroy (&gstate);
/*
* If no date component, then use the modification
if (!datecomp || (tw = dparsetime (datecomp)) == NULL) {
struct stat st;
- admonish (NULL, "can't parse %s field in message %d", datesw, msg);
+ advise (NULL,
+ "can't parse %s field in message %d, "
+ "will use file modification time",
+ datesw, msg);
fstat (fileno (in), &st);
smsg->s_clock = st.st_mtime;
check_failed = 1;
#include <h/mime.h>
#include <h/mhparse.h>
-static struct swit switches[] = {
-#define TOSW 0
- { "to mailpath", 0 },
-#define FROMSW 1
- { "from mailpath", 0 },
-#define SUBJECTSW 2
- { "subject subject", 0 },
-#define PARAMSW 3
- { "parameters arguments", 0 },
-#define DESCRIPTSW 4
- { "description text", 0 },
-#define COMMENTSW 5
- { "comment text", 0 },
-#define DELAYSW 6
- { "delay seconds", 0 },
-#define VERBSW 7
- { "verbose", 0 },
-#define NVERBSW 8
- { "noverbose", 0 },
-#define VERSIONSW 9
- { "version", 0 },
-#define HELPSW 10
- { "help", 0 },
-#define DEBUGSW 11
- { "debug", -5 },
- { NULL, 0 }
-};
+#define VIAMAIL_SWITCHES \
+ X("to mailpath", 0, TOSW) \
+ X("from mailpath", 0, FROMSW) \
+ X("subject subject", 0, SUBJECTSW) \
+ X("parameters arguments", 0, PARAMSW) \
+ X("description text", 0, DESCRIPTSW) \
+ X("comment text", 0, COMMENTSW) \
+ X("delay seconds", 0, DELAYSW) \
+ X("verbose", 0, VERBSW) \
+ X("noverbose", 0, NVERBSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+ X("debug", -5, DEBUGSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(VIAMAIL);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(VIAMAIL, switches);
+#undef X
extern int debugsw;
extern int splitsw;
extern int verbsw;
-int ebcdicsw = 0; /* hack for linking purposes */
-
/*
* static prototypes
*/
if (nedit) {
unputenv ("mheditor");
} else {
- m_putenv ("mheditor", ed ? ed : (ed = context_find ("editor"))
- ? ed : defaulteditor);
+ m_putenv ("mheditor", ed ? ed : (ed = get_default_editor()));
}
snprintf (buffer, sizeof(buffer), "%d", use);
m_putenv ("mhuse", buffer);
#include <h/mime.h>
#include <h/utils.h>
-static struct swit whatnowswitches[] = {
-#define DFOLDSW 0
- { "draftfolder +folder", 0 },
-#define DMSGSW 1
- { "draftmessage msg", 0 },
-#define NDFLDSW 2
- { "nodraftfolder", 0 },
-#define EDITRSW 3
- { "editor editor", 0 },
-#define NEDITSW 4
- { "noedit", 0 },
-#define PRMPTSW 5
- { "prompt string", 4 },
-#define VERSIONSW 6
- { "version", 0 },
-#define HELPSW 7
- { "help", 0 },
-#define ATTACHSW 8
- { "attach header-field-name", 0 },
-#define NOATTACHSW 9
- { "noattach", 0 },
- { NULL, 0 }
-};
+#define WHATNOW_SWITCHES \
+ X("draftfolder +folder", 0, DFOLDSW) \
+ X("draftmessage msg", 0, DMSGSW) \
+ X("nodraftfolder", 0, NDFLDSW) \
+ X("editor editor", 0, EDITRSW) \
+ X("noedit", 0, NEDITSW) \
+ X("prompt string", 4, PRMPTSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+ X("attach header-field-name", 0, ATTACHSW) \
+ X("noattach", 0, NOATTACHSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(WHATNOW);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(WHATNOW, whatnowswitches);
+#undef X
/*
* Options at the "whatnow" prompt
*/
-static struct swit aleqs[] = {
-#define EDITSW 0
- { "edit [<editor> <switches>]", 0 },
-#define REFILEOPT 1
- { "refile [<switches>] +folder", 0 },
-#define BUILDMIMESW 2
- { "mime [<switches>]", 0 },
-#define DISPSW 3
- { "display [<switches>]", 0 },
-#define LISTSW 4
- { "list [<switches>]", 0 },
-#define SENDSW 5
- { "send [<switches>]", 0 },
-#define PUSHSW 6
- { "push [<switches>]", 0 },
-#define WHOMSW 7
- { "whom [<switches>]", 0 },
-#define QUITSW 8
- { "quit [-delete]", 0 },
-#define DELETESW 9
- { "delete", 0 },
-#define CDCMDSW 10
- { "cd [directory]", 0 },
-#define PWDCMDSW 11
- { "pwd", 0 },
-#define LSCMDSW 12
- { "ls", 2 },
-#define ATTACHCMDSW 13
- { "attach", 0 },
-#define DETACHCMDSW 14
- { "detach [-n]", 2 },
-#define ALISTCMDSW 15
- { "alist [-ln] ", 2 },
- { NULL, 0 }
-};
+#define PROMPT_SWITCHES \
+ X("edit [<editor> <switches>]", 0, EDITSW) \
+ X("refile [<switches>] +folder", 0, REFILEOPT) \
+ X("mime [<switches>]", 0, BUILDMIMESW) \
+ X("display [<switches>]", 0, DISPSW) \
+ X("list [<switches>]", 0, LISTSW) \
+ X("send [<switches>]", 0, SENDSW) \
+ X("push [<switches>]", 0, PUSHSW) \
+ X("whom [<switches>]", 0, WHOMSW) \
+ X("quit [-delete]", 0, QUITSW) \
+ X("delete", 0, DELETESW) \
+ X("cd [directory]", 0, CDCMDSW) \
+ X("pwd", 0, PWDCMDSW) \
+ X("ls", 2, LSCMDSW) \
+ X("attach", 0, ATTACHCMDSW) \
+ X("detach [-n]", 2, DETACHCMDSW) \
+ X("alist [-ln] ", 2, ALISTCMDSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(PROMPT);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(PROMPT, aleqs);
+#undef X
static char *myprompt = "\nWhat now? ";
{
int pid, status, vecp;
char altpath[BUFSIZ], linkpath[BUFSIZ];
- char *cp, *vec[MAXARGS];
+ char *cp, *prog, **vec;
struct stat st;
#ifdef HAVE_LSTAT
}
} else {
/* set initial editor */
- if (*ed == NULL && (*ed = context_find ("editor")) == NULL)
- *ed = defaulteditor;
+ if (*ed == NULL)
+ *ed = get_default_editor();
}
if (altmsg) {
m_putenv ("editalt", altpath);
}
- vecp = 0;
- vec[vecp++] = r1bindex (*ed, '/');
+ vec = argsplit(*ed, &prog, &vecp);
+
if (arg)
while (*arg)
vec[vecp++] = *arg++;
vec[vecp++] = file;
vec[vecp] = NULL;
- execvp (*ed, vec);
+ execvp (prog, vec);
fprintf (stderr, "unable to exec ");
perror (*ed);
_exit (-1);
int state;
char buf[BUFSIZ], name[NAMESZ];
FILE *fp;
+ m_getfld_state_t gstate = 0;
if ((fp = fopen (msgnam, "r")) == NULL)
return 0;
- for (state = FLD;;)
- switch (state = m_getfld (state, name, buf, sizeof(buf), fp)) {
+ for (;;) {
+ int bufsz = sizeof buf;
+ switch (state = m_getfld (&gstate, name, buf, &bufsz, fp)) {
case FLD:
case FLDPLUS:
- case FLDEOF:
/*
* If draft already contains any of the
* Content-XXX fields, then assume it already
fclose (fp);
return 0;
}
- while (state == FLDPLUS)
- state = m_getfld (state, name, buf, sizeof(buf), fp);
+ while (state == FLDPLUS) {
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, fp);
+ }
break;
case BODY:
return 1;
}
- state = m_getfld (state, name, buf, sizeof(buf), fp);
+ bufsz = sizeof buf;
+ state = m_getfld (&gstate, name, buf, &bufsz, fp);
} while (state == BODY);
/* and fall... */
fclose (fp);
return 0;
}
+ }
+ m_getfld_state_destroy (&gstate);
}
# define TLSminc(a) 0
#endif /* TLS_SUPPORT */
-static struct swit sendswitches[] = {
-#define ALIASW 0
- { "alias aliasfile", 0 },
-#define DEBUGSW 1
- { "debug", -5 },
-#define FILTSW 2
- { "filter filterfile", 0 },
-#define NFILTSW 3
- { "nofilter", 0 },
-#define FRMTSW 4
- { "format", 0 },
-#define NFRMTSW 5
- { "noformat", 0 },
-#define FORWSW 6
- { "forward", 0 },
-#define NFORWSW 7
- { "noforward", 0 },
-#define MIMESW 8
- { "mime", 0 },
-#define NMIMESW 9
- { "nomime", 0 },
-#define MSGDSW 10
- { "msgid", 0 },
-#define NMSGDSW 11
- { "nomsgid", 0 },
-#define SPSHSW 12
- { "push", 0 },
-#define NSPSHSW 13
- { "nopush", 0 },
-#define SPLITSW 14
- { "split seconds", 0 },
-#define UNIQSW 15
- { "unique", -6 },
-#define NUNIQSW 16
- { "nounique", -8 },
-#define VERBSW 17
- { "verbose", 0 },
-#define NVERBSW 18
- { "noverbose", 0 },
-#define WATCSW 19
- { "watch", 0 },
-#define NWATCSW 20
- { "nowatch", 0 },
-#define WIDTHSW 21
- { "width columns", 0 },
-#define SVERSIONSW 22
- { "version", 0 },
-#define SHELPSW 23
- { "help", 0 },
-#define BITSTUFFSW 24
- { "dashstuffing", -12 },
-#define NBITSTUFFSW 25
- { "nodashstuffing", -14 },
-#define MAILSW 26
- { "mail", -4 },
-#define SAMLSW 27
- { "saml", -4 },
-#define SSNDSW 28
- { "send", -4 },
-#define SOMLSW 29
- { "soml", -4 },
-#define CLIESW 30
- { "client host", -6 },
-#define SERVSW 31
- { "server host", 6 },
-#define SNOOPSW 32
- { "snoop", -5 },
-#define SDRFSW 33
- { "draftfolder +folder", -6 },
-#define SDRMSW 34
- { "draftmessage msg", -6 },
-#define SNDRFSW 35
- { "nodraftfolder", -3 },
-#define SASLSW 36
- { "sasl", SASLminc(-4) },
-#define NOSASLSW 37
- { "nosasl", SASLminc(-6) },
-#define SASLMXSSFSW 38
- { "saslmaxssf", SASLminc(-10) },
-#define SASLMECHSW 39
- { "saslmech", SASLminc(-5) },
-#define USERSW 40
- { "user", SASLminc(-4) },
-#define SNDATTACHSW 41
- { "attach file", 6 },
-#define SNDNOATTACHSW 42
- { "noattach", 0 },
-#define SNDATTACHFORMAT 43
- { "attachformat", 7 },
-#define PORTSW 44
- { "port server-port-name/number", 4 },
-#define TLSSW 45
- { "tls", TLSminc(-3) },
-#define NTLSSW 46
- { "notls", TLSminc(-5) },
-#define MTSSW 47
- { "mts smtp|sendmail/smtp|sendmail/pipe", 2 },
-#define MESSAGEIDSW 48
- { "messageid localname|random", 2 },
- { NULL, 0 }
-};
+#define SEND_SWITCHES \
+ X("alias aliasfile", 0, ALIASW) \
+ X("debug", -5, DEBUGSW) \
+ X("filter filterfile", 0, FILTSW) \
+ X("nofilter", 0, NFILTSW) \
+ X("format", 0, FRMTSW) \
+ X("noformat", 0, NFRMTSW) \
+ X("forward", 0, FORWSW) \
+ X("noforward", 0, NFORWSW) \
+ X("mime", 0, MIMESW) \
+ X("nomime", 0, NMIMESW) \
+ X("msgid", 0, MSGDSW) \
+ X("nomsgid", 0, NMSGDSW) \
+ X("push", 0, SPSHSW) \
+ X("nopush", 0, NSPSHSW) \
+ X("split seconds", 0, SPLITSW) \
+ X("unique", -6, UNIQSW) \
+ X("nounique", -8, NUNIQSW) \
+ X("verbose", 0, VERBSW) \
+ X("noverbose", 0, NVERBSW) \
+ X("watch", 0, WATCSW) \
+ X("nowatch", 0, NWATCSW) \
+ X("width columns", 0, WIDTHSW) \
+ X("version", 0, SVERSIONSW) \
+ X("help", 0, SHELPSW) \
+ X("dashstuffing", -12, BITSTUFFSW) \
+ X("nodashstuffing", -14, NBITSTUFFSW) \
+ X("mail", -4, MAILSW) \
+ X("saml", -4, SAMLSW) \
+ X("send", -4, SSNDSW) \
+ X("soml", -4, SOMLSW) \
+ X("client host", -6, CLIESW) \
+ X("server host", 6, SERVSW) \
+ X("snoop", -5, SNOOPSW) \
+ X("draftfolder +folder", -6, SDRFSW) \
+ X("draftmessage msg", -6, SDRMSW) \
+ X("nodraftfolder", -3, SNDRFSW) \
+ X("sasl", SASLminc(-4), SASLSW) \
+ X("nosasl", SASLminc(-6), NOSASLSW) \
+ X("saslmaxssf", SASLminc(-10), SASLMXSSFSW) \
+ X("saslmech", SASLminc(-5), SASLMECHSW) \
+ X("user", SASLminc(-4), USERSW) \
+ X("attach file", 6, SNDATTACHSW) \
+ X("noattach", 0, SNDNOATTACHSW) \
+ X("attachformat", 7, SNDATTACHFORMAT) \
+ X("port server-port-name/number", 4, PORTSW) \
+ X("tls", TLSminc(-3), TLSSW) \
+ X("notls", TLSminc(-5), NTLSSW) \
+ X("mts smtp|sendmail/smtp|sendmail/pipe", 2, MTSSW) \
+ X("messageid localname|random", 2, MESSAGEIDSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(SEND);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(SEND, sendswitches);
+#undef X
extern int debugsw; /* from sendsbr.c */
# define TLSminc(a) 0
#endif /* TLS_SUPPORT */
-static struct swit switches[] = {
-#define ALIASW 0
- { "alias aliasfile", 0 },
-#define CHKSW 1
- { "check", 0 },
-#define NOCHKSW 2
- { "nocheck", 0 },
-#define DRAFTSW 3
- { "draft", 0 },
-#define DFOLDSW 4
- { "draftfolder +folder", 6 },
-#define DMSGSW 5
- { "draftmessage msg", 6 },
-#define NDFLDSW 6
- { "nodraftfolder", 0 },
-#define VERSIONSW 7
- { "version", 0 },
-#define HELPSW 8
- { "help", 0 },
-#define CLIESW 9
- { "client host", -6 },
-#define SERVSW 10
- { "server host", -6 },
-#define SNOOPSW 11
- { "snoop", -5 },
-#define SASLSW 12
- { "sasl", SASLminc(4) },
-#define SASLMECHSW 13
- { "saslmech mechanism", SASLminc(-5) },
-#define USERSW 14
- { "user username", SASLminc(-4) },
-#define PORTSW 15
- { "port server port name/number", 4 },
-#define TLSSW 16
- { "tls", TLSminc(-3) },
-#define NTLSSW 17
- { "notls", TLSminc(-5) },
-#define MTSSW 18
- { "mts smtp|sendmail/smtp|sendmail/pipe", 0 },
- { NULL, 0 }
-};
+#define WHOM_SWITCHES \
+ X("alias aliasfile", 0, ALIASW) \
+ X("check", 0, CHKSW) \
+ X("nocheck", 0, NOCHKSW) \
+ X("draft", 0, DRAFTSW) \
+ X("draftfolder +folder", 6, DFOLDSW) \
+ X("draftmessage msg", 6, DMSGSW) \
+ X("nodraftfolder", 0, NDFLDSW) \
+ X("version", 0, VERSIONSW) \
+ X("help", 0, HELPSW) \
+ X("client host", -6, CLIESW) \
+ X("server host", -6, SERVSW) \
+ X("snoop", -5, SNOOPSW) \
+ X("sasl", SASLminc(4), SASLSW) \
+ X("saslmech mechanism", SASLminc(-5), SASLMECHSW) \
+ X("user username", SASLminc(-4), USERSW) \
+ X("port server port name/number", 4, PORTSW) \
+ X("tls", TLSminc(-3), TLSSW) \
+ X("notls", TLSminc(-5), NTLSSW) \
+ X("mts smtp|sendmail/smtp|sendmail/pipe", 0, MTSSW) \
+
+#define X(sw, minchars, id) id,
+DEFINE_SWITCH_ENUM(WHOM);
+#undef X
+
+#define X(sw, minchars, id) { sw, minchars, id },
+DEFINE_SWITCH_ARRAY(WHOM, switches);
+#undef X
int