nmh-1.7.1-RC3/000755 007761 000024 00000000000 13243043705 012763 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/aclocal.m4000644 007761 000024 00000127567 13243043452 014644 0ustar00kenhstaff000000 000000 # generated automatically by aclocal 1.15 -*- Autoconf -*- # Copyright (C) 1996-2014 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # Copyright (C) 2002-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.15' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.15], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.15])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # Copyright (C) 2011-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_AR([ACT-IF-FAIL]) # ------------------------- # Try to determine the archiver interface, and trigger the ar-lib wrapper # if it is needed. If the detection of archiver interface fails, run # ACT-IF-FAIL (default is to abort configure with a proper error message). AC_DEFUN([AM_PROG_AR], [AC_BEFORE([$0], [LT_INIT])dnl AC_BEFORE([$0], [AC_PROG_LIBTOOL])dnl AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([ar-lib])dnl AC_CHECK_TOOLS([AR], [ar lib "link -lib"], [false]) : ${AR=ar} AC_CACHE_CHECK([the archiver ($AR) interface], [am_cv_ar_interface], [AC_LANG_PUSH([C]) am_cv_ar_interface=ar AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int some_variable = 0;]])], [am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([am_ar_try]) if test "$ac_status" -eq 0; then am_cv_ar_interface=ar else am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([am_ar_try]) if test "$ac_status" -eq 0; then am_cv_ar_interface=lib else am_cv_ar_interface=unknown fi fi rm -f conftest.lib libconftest.a ]) AC_LANG_POP([C])]) case $am_cv_ar_interface in ar) ;; lib) # Microsoft lib, so override with the ar-lib wrapper script. # FIXME: It is wrong to rewrite AR. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__AR in this case, # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something # similar. AR="$am_aux_dir/ar-lib $AR" ;; unknown) m4_default([$1], [AC_MSG_ERROR([could not determine $AR interface])]) ;; esac AC_SUBST([AR])dnl ]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each '.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi dnl The trailing newline in this macro's definition is deliberate, for dnl backward compatibility and to allow trailing 'dnl'-style comments dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Copyright (C) 1998-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_LEX # ----------- # Autoconf leaves LEX=: if lex or flex can't be found. Change that to a # "missing" invocation, for better error output. AC_DEFUN([AM_PROG_LEX], [AC_PREREQ([2.50])dnl AC_REQUIRE([AM_MISSING_HAS_RUN])dnl AC_REQUIRE([AC_PROG_LEX])dnl if test "$LEX" = :; then LEX=${am_missing_run}flex fi]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 1999-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_CC_C_O # --------------- # Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2014 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([m4/cppflags.m4]) m4_include([m4/iconv.m4]) m4_include([m4/locking.m4]) m4_include([m4/mimetype.m4]) m4_include([m4/ndbm.m4]) m4_include([m4/netlibs.m4]) m4_include([m4/readline.m4]) m4_include([m4/tputs.m4]) nmh-1.7.1-RC3/ar-lib000755 007761 000024 00000013302 12070326177 014062 0ustar00kenhstaff000000 000000 #! /bin/sh # Wrapper for Microsoft lib.exe me=ar-lib scriptversion=2012-03-01.08; # UTC # Copyright (C) 2010-2012 Free Software Foundation, Inc. # Written by Peter Rosin . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . # func_error message func_error () { echo "$me: $1" 1>&2 exit 1 } file_conv= # func_file_conv build_file # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv in mingw) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin) file=`cygpath -m "$file" || echo "$file"` ;; wine) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_at_file at_file operation archive # Iterate over all members in AT_FILE performing OPERATION on ARCHIVE # for each of them. # When interpreting the content of the @FILE, do NOT use func_file_conv, # since the user would need to supply preconverted file names to # binutils ar, at least for MinGW. func_at_file () { operation=$2 archive=$3 at_file_contents=`cat "$1"` eval set x "$at_file_contents" shift for member do $AR -NOLOGO $operation:"$member" "$archive" || exit $? done } case $1 in '') func_error "no command. Try '$0 --help' for more information." ;; -h | --h*) cat < to specify branch to check out, only if downloading sources # -i to install nmh # -v to display progress # Subsequent uses, assuming installed nmh bin directory is on $PATH: # -y to accept all configuration options without confirmation # Output control: # -l , default 'build_nmh.log', - for stdout/stderr # Advanced/developer use: # -c to run 'make distcheck' instead of 'make check' # -d to build nmh with asserts enabled and optimization disabled # -s to use 'make superclean': requires recent autoconf and automake, # see docs/README.developers # -r to build rpm # # To disable colorization of the test summary, either unset the TERM # environment variable or set it to dumb, e.g., TERM=dumb build_nmh. # # See the nmh MACHINES file for build prerequisites. In addition, the rpmbuild # is required to be available if the -r option is used. logfile=build_nmh.log usage="usage: [-b , only if downloading] [-c to run 'make distcheck' instead of 'make check'] [-d to build nmh with asserts enabled and optimization disabled] [-i to install nmh] [-l , default '$logfile'] [-r to build rpm] [-s to use 'make superclean': requires recent autoconf and automake] [-v to display progress] [-y to accept all configuration options without confirmation]" #### 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 } #### Make sure user sees error output even on early termination. cleanup() { if [ "$tmpfile" ]; then #### Disable output redirection (and flush) so that we can grep. #### If $tmpfile is null, don't need to do this because the #### outputs weren't redirected, modulo a small race condition #### between setting tmpfile and redirecting the outputs. exec 1>&3 3>&- 2>&4 4>&- if [ "$logfile" != - ]; then exec 3>&1 >"$logfile" 2>&1 fi if [ -f "$tmpfile" ]; then cat "$tmpfile" grep -E 'Error|warn' "$tmpfile" rm "$tmpfile" fi fi #### Put info message on stdout, and in log if not stdout. if [ $status -ne 0 -o $verbose -ge 1 -o "$directory" ]; then [ $status -eq 0 ] && result=succeeded || result=failed if [ "$logfile" = - ]; then echo "build $result" else message="build $result, build log is in ${directory:+$directory/}$logfile" echo "$message" >&3 fi fi #### Heirloom shell does not like "trap - signal". trap '' EXIT exit $status } #### Exit with error message. die() { status=1 # It should already be, but just in case the code below changes. echo "$0: $*" 1>&2 cleanup } #### Download sources from repo. With git and on master, the #### directory will be nmh, but with snapshot, it will be #### nmh-master. download_sources() { [ $verbose -ge 1 ] && echo downloading . . . >&3 gitdir=`finddir git` if [ "$gitdir" ]; then #### Use git repo. [ "$verbose" -eq 0 ] && git_opts=--quiet [ "$branch" = master ] || git_opts="${git_opts:+$git_opts }--branch $branch" if "$gitdir"/git clone --depth 1 $git_opts "git://$gitrepo/nmh.git" >&3 then directory=nmh cd "$directory" || die "failed to clone $directory" printf "commit %s\n" `git log --max-count=1 --pretty=format:%H` else die 'failed to clone git repo' fi else [ -e nmh-"$branch" ] && die "nmh-$branch exists, will not overrwrite" #### Use snapshot. tarball="nmh-$branch.tar.gz" repo="http://$gitrepo/cgit/nmh.git/snapshot" snapshot="$repo/$tarball" if [ "`finddir wget`" ]; then [ "$verbose" -eq 0 ] && wget_opts='--quiet' wget --output-document - $wget_opts "$snapshot" 2>&3 | gzip -d | tar xf - elif [ "`finddir curl`" ]; then [ "$verbose" -eq 0 ] && curl_opts='--silent --show-error' curl --location $curl_opts "$snapshot" 2>&3 | gzip -d | tar xf - else die 'unable to find program to download nmh sources' fi if [ -d nmh-"$branch" ]; then directory=nmh-"$branch" cd "$directory" || die "failed to download and extract $directory" else die "failed to download nmh-$branch sources" fi fi } directory= download=0 gitrepo=git.savannah.nongnu.org invocation="$0 $*" status=1 tmpfile=/tmp/build_nmh-$$.log #### Redirect all output to tmp file. Then on EXIT, copy it to either #### logfile or stdout. Also, grep it for errors and warnings. Set #### tmpfile just prior to this, see cleanup(). exec 3>&1 4>&2 >"$tmpfile" 2>&1 #### #### Interpret command arguments. #### branch=master check=check debug=0 install=0 build_rpm=0 superclean=0 verbose=0 yes=0 #### With dash, heirloom shell, and posh, need to catch INT and QUIT #### in order for cleanup to be call: just EXIT isn't sufficient. trap cleanup EXIT INT QUIT while getopts 'cb:dil:rsvy?' arg; do case $arg in b ) branch="$OPTARG" ;; c ) check=distcheck ;; d ) debug=1 ;; i ) install=1 ;; l ) logfile=$OPTARG ;; r ) build_rpm=1 ;; s ) superclean=1 ;; v ) verbose=1 ;; y ) yes=1 ;; '?') echo "$0: $usage"; logfile=-; status=0; exit ;; esac done shift `expr $OPTIND - 1` echo "$invocation" #### No non-option command line arguments are supported. [ $# -gt 0 ] && die "$usage" #### Check to see that we're in a nmh source directory. if grep 'the authors of nmh' COPYRIGHT >/dev/null 2>&1; then : else download=1 fi #### #### Set up configure options. #### #### Here are the config options that we will try to detect, then #### confirm, and finally set. config_prefix=/usr/local/nmh config_locking= config_mts=smtp config_smtpserver=localhost config_sasl='determined by configure' config_tls='determined by configure' config_debug=n #### Figure out whether or not to use -n with tail. case `printf 'OK\n' | tail -n 1 2>&1` in OK) tail='tail -n ' ;; *) tail='tail -' ;; esac if install-mh -check >/dev/null 2>&1; then #### Determine config options from installed nmh. mhbin=`finddir install-mh` config_prefix=`cd $mhbin/.. && pwd` mtsconf=`mhparam etcdir`/mts.conf if [ -f "$mtsconf" ]; then mts_entry=`grep '^mts:' "$mtsconf"` if [ "$mts_entry" ]; then mts=`echo "$mts_entry" | sed -e 's/^mts: *//'` if [ "$mts" -a "$mts" != smtp ]; then config_mts="$mts" fi fi mtsconfservers=`grep '^servers:' "$mtsconf"` if [ "$mtsconfservers" ]; then servers=`echo "$mtsconfservers" | sed -e 's/^servers: *//'` [ "$servers" ] && config_smtpserver="$servers" fi fi if test -x "$mhbin/mhparam"; then if mhparam sasl >/dev/null; then case `$mhbin/mhparam sasl` in *sasl*) config_sasl=y ;; esac case `$mhbin/mhparam tls` in *tls*) config_tls=y ;; esac else tput smso echo "$0: SASL and TLS detection not supported with current nmh" [ $yes -eq 1 ] && echo "configure will determine whether to enable" tput rmso fi fi fi #### Don't confirm debug interactively below; obey the -d option. [ $debug -ge 1 ] && config_debug=y if [ $yes -eq 0 ]; then #### Confirm each config setting with user. printf 'Install prefix [%s]: ' $config_prefix >&3 read prefix [ "$prefix" ] && config_prefix="$prefix" printf 'Locking type (dot|fcntl|flock|lockf) [determined by configure]: ' >&3 read locking [ "$locking" ] && config_locking="$locking" printf 'MTS (smtp|sendmail/smtp|sendmail/pipe) [%s]: ' $config_mts >&3 read mts [ "$mts" ] && config_mts="$mts" if [ "$config_mts" = smtp ]; then printf 'SMTP server [%s]: ' $config_smtpserver >&3 read server [ "$server" ] && config_smtpserver="$servers" fi printf 'Cyrus SASL support (y|n) [%s]: ' "$config_sasl" >&3 read response [ "$response" = y -o "$response" = Y ] && config_sasl=y printf 'TLS support (y|n) [%s]: ' "$config_tls" >&3 read response [ "$response" = y -o "$response" = Y ] && config_tls=y fi config_opts="--prefix=$config_prefix" [ "$config_locking" ] && config_opts="$config_opts --with-locking=$config_locking" [ "$config_mts" -a "$config_mts" != smtp ] && config_opts="$config_opts --with-mts=$config_mts" [ "$config_smtpserver" -a "$config_smtpserver" != localhost ] && config_opts="$config_opts --with-smtpserver=$config_smtpserver" [ "$config_sasl" = y ] && config_opts="$config_opts --with-cyrus-sasl" [ "$config_tls" = y ] && config_opts="$config_opts --with-tls" [ $config_debug = y ] && config_opts="$config_opts --enable-assert" #### dotlocking, the usual default, requires chgrp and chmod of inc. installpriv= if [ $install -ge 1 -a "$LOGNAME" != root ]; then if [ "$config_locking" = dot ]; then echo "$0: "'install requires chgrp and chmod 2755' echo 'so will sudo to install. Terminate with Ctrl-C if unacceptable.' installpriv=sudo fi fi printf '\n%s %s %s %s\n\n' "`uname -m`" "`uname -s`" "`uname -r`" "`uname -v`" [ -f /etc/os-release ] && printf '%s\n\n' "`cat /etc/os-release`" [ $download -eq 1 ] && download_sources #### #### Set up with autoconfig if necessary. #### if [ -f Makefile ]; then [ $verbose -ge 1 ] && echo cleaning . . . >&3 if [ $superclean -ge 1 ]; then make superclean >/dev/null else make distclean >/dev/null fi fi if [ ! -f configure -o ! -f Makefile.in ]; then [ $verbose -ge 1 ] && echo autoconfiguring . . . >&3 ./autogen.sh [ $? -ne 0 ] && die "autogen failed, see MACHINES file for autoconf, automake, flex, and bison requirements" fi #### #### Build. #### [ $verbose -ge 1 ] && echo configuring . . . >&3 if [ -z "$CFLAGS" ]; then #### Only use these flags with gcc. if cc -dM -E - &1 | grep __GNUC__ >/dev/null; then #### configure will supply -g -O2 with gcc, but only if CFLAGS #### isn't defined. CFLAGS='-g -std=c99 -pedantic' if [ "$config_debug" = n ]; then CFLAGS="$CFLAGS -O2 -D_FORTIFY_SOURCE=2" else CFLAGS="$CFLAGS -O0" fi fi fi printf "\n./configure ${CFLAGS:+CFLAGS=\"${CFLAGS}\" }$config_opts\n" ./configure ${CFLAGS:+CFLAGS="${CFLAGS}"" "}$config_opts status=$? if [ $status -eq 0 ]; then [ $verbose -ge 1 ] && echo building . . . >&3 make status=$? if [ $status -eq 0 ]; then if [ "$TESTS_SHELL"x = x ]; then #### Bonus: use heirloom shell to test, if available, and if #### TESTS_SHELL hadn't already been set. heirloom_shell=/usr/lib/heirloom/5bin/sh if [ -x "$heirloom_shell" ]; then TESTS_SHELL="$heirloom_shell"; export TESTS_SHELL fi fi if [ "$CFLAGS" ]; then #### Pass DISTCHECK_CONFIGURE_FLAGS through an environment #### variable to avoid automake's quoting. DISTCHECK_CONFIGURE_FLAGS="CFLAGS='${CFLAGS}'" export DISTCHECK_CONFIGURE_FLAGS fi [ $verbose -ge 1 ] && echo testing . . . >&3 [ "${TERM:-dumb}" = dumb ] && color=no || color=always checkoutput=`make $check AM_COLOR_TESTS=$color` 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 '===================' [ "$test_not_run" ] && echo "$test_not_run" [ "$fails" ] && echo "$fails" echo "$tests_summary" echo '===================' [ "$check" = distcheck ] && echo "$checkoutput" | ${tail}4 fi if [ $status -eq 0 ]; then if [ $install -ge 1 ]; then [ $verbose -ge 1 ] && echo installing . . . >&3 ($installpriv make install) >/dev/null status=$? fi if [ $status -eq 0 -a $build_rpm -ge 1 ]; then [ $verbose -ge 1 ] && echo building rpm . . . >&3 make rpm >/dev/null status=$? fi fi fi else echo "see nmh MACHINES file for build dependences" fi #### Will call cleanup, which will exit with $status. exit nmh-1.7.1-RC3/ChangeLog000644 007761 000024 00003154002 13243043703 014540 0ustar00kenhstaff000000 000000 Author: Ken Hornstein Date: Tue Feb 20 10:57:44 2018 -0500 Update DATE and VERSION for third release candidate Author: David Levine Date: Mon Feb 19 21:30:17 2018 -0500 Fixed mhshow/test-charset to work on all tested platforms. Restores the functionality of commit f81046da6. Also, skips the last two tests if iconv isn't enabled. And removes the test files if the last test, without iconv_elides_question_marks, behaves as expected. Finally, some comments have been updated. (cherry picked from commit 8ed8876c673325b1af92d67012dc2e8ae3cf1019) Author: David Levine Date: Sat Feb 3 08:00:36 2018 -0500 Removed comment about testing noiconv portion of get_param_value(). I'm not sure if it ever did, but it doesn't seem to now. (cherry picked from commit 63041ccfe270ccecede25ac4f4c18d71aa43b1a4) Author: Ralph Corderoy Date: Sat Feb 3 10:49:40 2018 +0000 test-charset: Fix test when HAVE_ICONV is false. When the Content-Type's charset parameter's encoding is `invalid', it makes no difference whether HAVE_ICONV is defined or not as the parameter's value can't be decoded. (cherry picked from commit d4814561eafc238a9ed2b4fa67ef2755e5e83858) Author: Ralph Corderoy Date: Thu Jan 25 00:16:15 2018 +0000 test-charset: Divulge mhshow output if iconv_open(3) doesn't gripe. Andy Bradford was finding the grep failed, but was left with no explanation that's what happened, or what the file that didn't match contained. (cherry picked from commit 695ed941eb3d907a7c2912d9ea8fdad06a3fd0f5) Author: Ken Hornstein Date: Mon Feb 12 16:01:08 2018 -0500 Avoid free() in format engine for now. This free() call messes up the buffer handling in scansbr.c:scan(); for now we're going to live with the leak and fix this properly when we normalize the format engine's memory handling. (cherry picked from commit 19c69cf39d0ab9aee0cf45caa13d39edf1997fef) Author: Ken Hornstein Date: Sat Feb 10 01:29:46 2018 -0500 Add a few more MacOS X valgrind suppressions (cherry picked from commit 42db3a2c36e26e0106b1e480407e32d3c8c09bef) Author: Ken Hornstein Date: Fri Feb 9 23:15:32 2018 -0500 Clean up memory leaks by callers of scan(). Make sure we reuse the "scanl" argument to the scan() function, as that's the signal to have scan() reuse it's buffers. Otherwise repeated calls to scan will leak a TON of memory. Reported by Ralph Corderoy. (cherry picked from commit 946ddda2565e28600b65cb666a59182a6d95ff48) Author: Ken Hornstein Date: Sun Jan 21 17:59:13 2018 -0500 Update for second release candidate. Author: Ralph Corderoy Date: Sat Jan 20 11:48:30 2018 +0000 test-whom: Send whom's stderr down pipe; don't discard. Fixes 2a02eef3. (cherry picked from commit c349c172bd195190c0ddb7754644f16ba8545fda) Author: Ralph Corderoy Date: Sat Jan 20 11:45:32 2018 +0000 test-msgchk: Send msgchk's stderr down pipe; don't discard. Present since original 26ac907a. (cherry picked from commit 341ac166ef0f1e9b0eac5ab3fa74899e5323c242) Author: Ralph Corderoy Date: Sat Jan 20 11:38:24 2018 +0000 test: Send command's stderr down pipe; don't discard. Fixes 880ff2a4 that turned `foo >$actual 2>&1' into `foo | sed ... >$actual 2>&1'. (cherry picked from commit 025963d5fe8ca0781eee8c83c23b4ea1209a3b0b) Author: Ralph Corderoy Date: Sat Jan 20 08:57:40 2018 +0000 test/common.sh.in: Unset libcurl(3)'s proxy environment variables. Debian's packager, Alexander Zanger, reported test/oauth/test-* problems due to environment variables for the system's network proxies. David Levine suggested the unsetting of them. The tests only make HTTP connections so just the variables affecting those are unset. (cherry picked from commit 5303e0f65b71e1336944a5b10356d6a99528511a) Author: Ralph Corderoy Date: Sat Jan 20 07:33:36 2018 +0000 test-subpart: Send mhshow's stderr down pipe; don't discard. Fixes 2f1e191a. (cherry picked from commit ca079bfa8e3812ebf21ffec1c27edeaa03cb9280) Author: Ralph Corderoy Date: Sat Jan 20 07:28:29 2018 +0000 test-textcharset: Send mhshow's stderr down pipe; don't discard. Fixes 67bb0fc0. (cherry picked from commit f7a2498729e0c642c7c7fb573deee3a35176de44) Author: Ralph Corderoy Date: Sat Jan 20 00:08:33 2018 +0000 fmttest.c: Avoid `++' with bools, silencing compiler warnings. A partial application of fmttest.c's changes in 8c6e995a to fix the errors introduced by the cherry-picking of another commit in 88ba19fc. Author: David Levine Date: Thu Jan 18 21:46:13 2018 -0500 Removed quotes around "%{charset}" in mhbuild-convert-text. They broke test/repl/test-convert on Cygwin. It looks like parameter quoting differs between mhbuild and mhshow. Fix to commit 47629e9e87a324531be881cebfca38dd38f8afaa. (cherry picked from commit 73e1f01148bb9709a405e27f7d3c5a95ea03b859) Author: David Levine Date: Thu Jan 18 20:21:40 2018 -0500 Removed quotes from charset argument to iconv. Fix to commit 47629e9e87a324531be881cebfca38dd38f8afaa. Ken noticed that it broke test/repl/test-convert on MacOS X. (cherry picked from commit a3953e07ac53f83373326301d049faea82eb97d0) Author: David Levine Date: Thu Jan 18 19:03:52 2018 -0500 Filter test output to remove added whitespace. Ralph noticed that lynx added whitespace to the (empty) converted html document, breaking the test. Fix to commit 47629e9e87a324531be881cebfca38dd38f8afaa. (cherry picked from commit 67bb0fc0c930d5c91b6a2881b4596e1044546297) Author: David Levine Date: Wed Jan 17 19:36:12 2018 -0500 Wrapped uses of %{charset} in mhn.defaults with double quotes. (cherry picked from commit 47629e9e87a324531be881cebfca38dd38f8afaa) Author: Ken Hornstein Date: Tue Jan 16 21:16:32 2018 -0500 Update for first release candidate of 1.7.1. Author: Ralph Corderoy Date: Wed Nov 22 13:44:01 2017 +0000 Rewrite cpnumber() to fix `%2(msg)' with 123 overflowing to `?23'. Reported in 1.7 by Ken on nmh-workers yesterday. `It seems this was introduced in commit 92128dacf'. We now use the C library to format the number, and then manipulate the result. A temporary charstring_t is no longer used. Also adds left justification using negative width. (cherry picked from commit a034d7e5edab2f0d56a62f6e1fcbbc76f3e5f31b) Author: Ralph Corderoy Date: Mon Jan 15 16:25:35 2018 +0000 Add test-fmttest for cpstripped(), cptrimmed(), and cpnumber(). Many more tests could be done, and some, like those below, would produce known erroneous results, but this is a start and helps spot regressions. create mode 100755 test/format/test-fmttest (cherry picked from commit 3e2ca6f83691294fece17b00f8f08b203821c91f) Author: Ralph Corderoy Date: Sat Jan 13 13:54:15 2018 +0000 fmttest: Allow `-outsize 0' to mean no output, not default size. `0' might be arrived at by a script tracking remaining space. (cherry picked from commit 4fd4b0afa64f34a399c0b1bbbffacb859d1e55b8) Author: Ralph Corderoy Date: Wed Nov 29 17:28:50 2017 +0000 Add Arch Linux to the often-built-and-tested distro list. And correct a `Mac OS' to have an `X', and `HPUX' to be `HP-UX'. (cherry picked from commit 9283525375671f0c4c6d0c021440074b3c96ac0a) Author: David Levine Date: Sat Dec 2 15:43:16 2017 -0500 Removed version number from OpenBSD, it's in the "recent" section. (cherry picked from commit 0813132987677a8b0cf3b4d0e8bf851657deeadd) Author: David Levine Date: Sat Dec 2 09:44:19 2017 -0500 Moved OpenBSD back to "routinely built and tested" category. (cherry picked from commit a640546144e14bc303c3ca0de019b40818ccc319) Author: David Levine Date: Mon Nov 27 20:56:30 2017 -0500 Updated platform lists in MACHINES. (cherry picked from commit ac30294d6103652024539ebb76af348977812050) Author: Ralph Corderoy Date: Mon Sep 25 17:43:04 2017 +0100 Delete "blank" lines at start of files to bring content into view. (cherry picked from commit a7c1ec95e26ca515d95bfda1e260e3827ba25a1e) Author: David Levine Date: Mon Jan 15 17:30:49 2018 -0500 Also trap ambiguous post switch. Fix to commit d321a6ee82fce5d187f4342199c090909a72e9b8. (cherry picked from commit ff7b97ca9ddcf66640aaeef01934a6b45a5f183b) Author: David Levine Date: Mon Jan 15 17:16:41 2018 -0500 Fixed rcvdist to pass switch arguments to post(1). Looks like this has always been broken. Found by Steven Winikoff when he tried to pass a -port switch, to override the default submission port. This is intended to be a temporary fix. The post switches should be factored out into one place. (cherry picked from commit d321a6ee82fce5d187f4342199c090909a72e9b8) and manually changed die() to adios() Author: David Levine Date: Sun Jan 14 15:04:53 2018 -0500 Removed escape before newline. It was causing a *roff font selection code to appear in the formatted man page. Fix to commit 95e0df2af. That commit removed a space after the escape, which used to cause a double space in the formatted output. (cherry picked from commit 28ebf6bb835e9954c0f959b56c8abac2bf3decd5) Author: David Levine Date: Sat Nov 18 10:35:19 2017 -0500 Move etc/rmmproc.messageid to fix its install permissions. And removed duplicate docs/contrib/replaliases to fix its install permissions. (cherry picked from commit f102d048fdd4679534460ac5cb0c610ee228d063) Author: David Levine Date: Mon Nov 27 20:11:30 2017 -0500 Removed sbr/dtimep.c from CLEANFILES. automake puts it in maintainer-clean-generic, which is where it belongs. Reversal of commit 1353a95720e4049e5f8357cd009b76c0450ec39f. (cherry picked from commit babec898bb63d36349aae85a8cbde6b97b274192) Author: Ralph Corderoy Date: Mon Nov 27 15:20:44 2017 +0000 test-mhfixmsg: pwd(1)'s `-P' needed to avoid failure with symlinks. Steven Winikoff reported to nmh-workers that one of this file's tests failed in 1.7. It attempts to manipulate the output of mhpath(1) assuming it starts with the result of `pwd', but symlinks in the latter may cause this to fail. Use POSIX's `-P' option to ensure no symlinks, as done in some other tests. (cherry picked from commit 0e593b90e45687680b8ea9eb6c7643b44abde0fb) Author: David Levine Date: Sun Nov 26 17:27:48 2017 -0500 Use ISO-2022-KR instead of EBCDIC-US in test-charset, because Robert Elz reported that it is installed on his NetBSD host. Also, don't run that check without iconv. (cherry picked from commit f81046da683a14b2265a501f0de00df264a77413) Author: Ralph Corderoy Date: Sun Nov 26 12:09:22 2017 +0000 Fix tests that assume the backup prefix is a comma. Steven Winikoff reported to nmh-workers that some tests failed in 1.7 configured with --with-hash-backup because they assume the backup prefix is comma rather than hash. Alter those tests to use `mhparam sbackup', as other tests already do. PATH is already set to use the mhparam being tested. test-mhfixmsg used find(1) to check for leftover files that globbed `mhfix*' or `,mhfix*'. Changed to just `*mhfix*' as I think any file containing that would be unwanted, and it will also spot mhfixmsg hard-coding the comma prefix. (cherry picked from commit 47b86722957cca6057bf5fcd07c9d1f01b4516f8) Author: Ralph Corderoy Date: Sat Nov 25 15:42:09 2017 +0000 mhshow/test-charset: Protect question mark from shell globbing. (cherry picked from commit f227479ac47aea8bc8f31f9c6d97a94af72ee147) Author: David Levine Date: Fri Nov 24 18:41:23 2017 -0500 Reworked parameter value tests to reflect Ralph's (re-?) discovery that GNU iconv elides the ? from charset names. nmh uses it as a replacement character when decoding fails. (cherry picked from commit 523641d2282ce5606a8b83250f9e45f33650edf6) Author: Ralph Corderoy Date: Wed Nov 22 15:12:11 2017 +0000 fmttest.c: Clear output buffer after each write. Otherwise each write outputs the whole buffer again, including what's already appeared. Instead of the three lines 1, 2, 3, one sees 1, 1, 2, 1, 2, 3. (cherry picked from commit 1670e4d1af608291d93f02e74c57b6aef69a83ad) Author: David Levine Date: Sun Dec 17 20:41:34 2017 -0500 Removed sysconfdir overrides from SPECS examples. Author: Ken Hornstein Date: Fri Nov 17 10:23:34 2017 -0500 Update for 1.7 final release. Author: David Levine Date: Tue Sep 5 10:51:00 2017 -0400 Revised expected output with -prefer in test/mhlist/test-mhlist. Update to commit 5dce1b38ace6cf61398df3ee4ca5aee0e1dedb5d. (cherry picked from commit f6d438b5e08d12eacb62f93a8ce1a6c22d2ae16d) Author: Ralph Corderoy Date: Fri Nov 17 12:04:01 2017 +0000 NEWS: Encourage nmh-announce subscription. Capitalise `Gmail'. (cherry picked from commit 532e14e4e60411b4375b34f6c99b0c988259415c) Author: Ken Hornstein Date: Sat Nov 4 09:59:18 2017 -0400 Use va_copy() to get a copy of va_list, instead of using original. netsec_vprintf() can call vsnprintf() twice if the outgoing buffer is full (but it happens rarely in practice, given the way the current code uses it). But if this DOES happen, vsnprintf() will use the same va_list argument twice, and the second time around either it will grab a random bit of memory off of the stack OR it will segfault. So we always use va_copy() to get our own copy of the passed-in va_list and work on that. (cherry picked from commit b47b562525f149f175c3d216feea20a6db2e9ff5) Author: Paul Fox Date: Sat Sep 2 11:24:01 2017 -0400 Add -noprefer switch to mhshow, mhstore, and mhlist Allow profile-specified -prefer switches to be cancelled from the command line. (cherry picked from commit ceeb47c04f8abb144a3fbaeae3a54010175c2d36) Author: Paul Fox Date: Sat Sep 2 09:13:44 2017 -0400 Change the priority ordering for multiple -prefer switches Interpreting multiple -prefer switches in ascending priority order allows the command line to override the user's profile. (cherry picked from commit 5dce1b38ace6cf61398df3ee4ca5aee0e1dedb5d) Author: Ken Hornstein Date: Fri Sep 8 12:08:41 2017 -0400 Add a -credentials argument when we call post. If we are using -check, post(8) will need to talk to a remote SMTP server, and it might need to perform authentication when doing so. So include a -credentials option if there is the appropriate line in the user's profile. (cherry picked from commit 9a4413187b1cf9562bceef8cfe442278ed67afd9) Author: Ken Hornstein Date: Fri Sep 8 13:46:08 2017 -0400 Send a QUIT instead of RSET at session end when doing 'whom'. When running 'whom -check' (which really invokes post(8)), at the end of the SMTP session we would send a RSET instead of a QUIT. This was technically a RFC violation (RFC 5321 says a QUIT has to be the last thing you send), and this would cause some SMTP servers to complain. So make sure if we're being invoked by whom to send a QUIT at the end of the session. Reported by Ralph Corderoy. (cherry picked from commit 6396778780e014c789e3d18a0880525ee1cde4f6) Author: Ken Hornstein Date: Wed Aug 23 14:35:21 2017 -0400 Update for release candidate 3 Author: Ken Hornstein Date: Wed Aug 23 12:08:24 2017 -0400 Make sure we return the descriptor from the file handle. Noted by Ralph Corderoy. (cherry picked from commit 15fde7dd84cc29c054857e5d8a7fdd4a8db10a97) Author: David Levine Date: Mon Aug 21 16:44:07 2017 -0400 Removed conditional addition of -D_FORTIFY_SOURCE=2 from CPPFLAGS. And added to CFLAGS in build_nmh. (cherry picked from commit 7d728514c2c11f194afd433445666ae6c3b7dba7) Author: Ralph Corderoy Date: Sun Aug 20 14:59:26 2017 +0100 man: Vet the NAME sections, especially mhfixmsg's. Don't limit mhfixmsg to fixing "nmh MIME" emails. (cherry picked from commit aae36dd297503787301fef6b9573c749846a6392) Author: David Levine Date: Sun Aug 20 09:20:49 2017 -0400 Add -D_FORTIFY_SOURCE=2 to CPPFLAGS instead of AM_CPPFLAGS. To make it easier for packagers to override. Fix to commit 35d2b4dc00d705e6816bcb0ccab491aabda688dc. (cherry picked from commit 73a94823f58fa921f9e6c58632f9cecead0e10fd) Author: David Levine Date: Sun Aug 20 08:50:17 2017 -0400 Restored old NAME in mhical(1) man page. mhical only operates on iCalendar event requests, not messages. Fix to commit 0e7daaa2daf6c668c8c6feb9da3c9a6639fa4e7e. (cherry picked from commit b1fb6f46efb8956aae6397c704db26e1310a6564) Author: Ralph Corderoy Date: Sun Aug 20 12:33:38 2017 +0100 scan.man: Note that %{body} does not decode MIME. (cherry picked from commit b852bee5757ed6aaee4046f68cbe458a1ffa623d) Author: Ralph Corderoy Date: Sun Aug 20 10:34:01 2017 +0100 NEWS: Add bug fix: EPIPE when writing error no longer recurses. Also move an existing item into the Bug Fixes section. (cherry picked from commit 5da45d9802e59261cba09af83ebc77e106345b04) Author: Ralph Corderoy Date: Sun Aug 20 09:31:18 2017 +0100 NEWS: Consistent punctuation. Mention SI and IEC quantities. (cherry picked from commit 7ec9aaa931525abed3df348a22f824c49c828225) Author: Ralph Corderoy Date: Sat Aug 19 15:58:49 2017 +0100 test-sendfiles: Feed `lzma -cd' stdin rather than a filename. Håkon Alstadheim reported that Debian's lzma-9.22-2 would complain at `lzma -cd foo.tar' with `unknown suffix -- unchanged' even though it was not being asked to alter the file, or produce a new one based on its filename. This appears to be https://bugs.debian.org/700681. The lzma from Arch Linux's xz 5.2.3-1 does no have this fault. Work around it by feeding the file to decompress on standard input for all the compression programs being tested; none of the others should mind. (cherry picked from commit 937ee92013bed7b3ebd30fff2c17a751d37b1a61) Author: David Levine Date: Fri Aug 18 23:18:15 2017 -0400 Protect fileno() call against NULL argument. Fix to commit 337b4e616e8f53ba06285b1645e1df9918ed5c16. Thanks to Norm for reporting and Ken for diagnosing the bug. (cherry picked from commit c8815b7b63b710e1480d4be759744583e59308e9) Author: Ralph Corderoy Date: Fri Aug 18 14:29:59 2017 +0100 lock_file.c: Compiler warns of unused isnewlock if HAVE_LIBLOCKFILE. (cherry picked from commit bb8a255634719c63cfae1ee4d0fb12f056efa71b) Author: David Levine Date: Thu Aug 17 19:45:20 2017 -0400 Default CFLAGS to -std=c99 instead of -ansi. gcc -ansi -pedantic issued a few warnings about C90 not supporting the "ll" printf length modifier. Ralph pointed out that http://www.unix.org/version4/overview.html says: The following source code portability standards lie at the core of the Single UNIX Specification: POSIX.1-2008 (This is technically identical to the Base Specifications, Issue 7; they are one and the same document.) The ISO/IEC 9899:1999 standard So perhaps we're wrong to expect modern POSIX code to compile as C90. (cherry picked from commit f4ec967205c6fa0f3d37aad24335337251f17e16) Author: Ralph Corderoy Date: Thu Aug 17 12:42:57 2017 +0100 Both f_typestr(): Remove parenthesis from long list of returns. It's not a function call, they're just noise. (cherry picked from commit 16b794c5709dc07a81534fd90fed5d1f25f3fbea) Author: Ralph Corderoy Date: Thu Aug 17 12:36:50 2017 +0100 Both f_typestr(): Rebuild switch from FT_* to string from scratch. Adds missing cases, e.g. FT_LS_CFIND. Removes inconsistent "FT_" prefix from some strings, e.g. FT_LS_DECODE. Re-orders cases to match definitions. (cherry picked from commit ce8a66e8b8e9a818d165d09f8df56178e0b40dc9) Author: Ralph Corderoy Date: Thu Aug 17 12:20:16 2017 +0100 fmtdump.c, fmttest.c: Remove tests for FT_LIT_FORCE. It isn't defined, and git-grep(1) suggests it was a local Lawrence Berkeley Laboratory modification that output a literal without consuming any of the width budget. (cherry picked from commit efb2c94fbc4861fc81307cd5d0ce22eb16e6de26) Author: Ralph Corderoy Date: Thu Aug 17 11:35:51 2017 +0100 cpnumber(): Cast desired width to size_t to silence gcc's warning. Add a comment on `wid = -wid' that it's OK because wid's value was originally a short so won't remain the same value. (cherry picked from commit ac0bb0e1e19bedfd9d7105db0aad1cdfc5ef994f) Author: Ralph Corderoy Date: Wed Aug 16 13:44:32 2017 +0100 INSTALL: Update c89(1) mention to c99(1), that exists today. (cherry picked from commit 0d0d0e65a4c093f3f8827d4cd3375dcde4d4aab0) Author: Ralph Corderoy Date: Wed Aug 9 16:00:17 2017 +0100 fmtdump.c: Add string for FT_LS_UNQUOTE case. It was missing since e8635a8a1 and the default case that attempted to format it as a number was faulty, fixed in 39ecf70bb. That fix broke test/format/test-fmtdump as it expected the broken "blank line" to be output instead. (cherry picked from commit 4bdd57be745679ee8fc97a3029fa837b14a80b50) Author: Ralph Corderoy Date: Sun Aug 13 15:04:58 2017 +0100 post.man: Detail -port's default value: submission, 587. (cherry picked from commit d9c165f79476d60ac59515d3b23ede004759fe06) Author: Leonardo Taccari Date: Thu Aug 17 19:42:48 2017 -0400 mhical expected an ics file as input and after just pressing ^D I've found that mhical wasn't happy about an empty input. A trivial patch that should fix this issue. (cherry picked from commit 76b9af849ba1c93eb2b6807e57268b7a7a2e205c) Author: Ken Hornstein Date: Thu Aug 17 13:01:09 2017 -0400 Update for release candidate 2. Author: Ralph Corderoy Date: Thu Aug 17 11:59:38 2017 +0100 Makefile.am: Remove multiple `mkdir -p' for etc; use ./configure. A `mkdir -p' was used in each rule that created a file in etc to ensure the directory already existed. Ken pointed out existing ./configure code to do that for the man directory, just once. Use that for etc too. Remove the `test -d' because `mkdir -p' does that itself. (cherry picked from commit 1009a32da2ba2b0caae7b71708625e00d8cf58c6) Author: Ken Hornstein Date: Thu Aug 17 01:24:08 2017 -0400 Fix bug in cpnumber(). The cpnumber() function (which handles the NUMF instruction, among others) would hang if a 0 width was given to it. Make sure that (and negative widths) are handled correctly. Note that normally NUMF did not handle left padding which is indicated by a negative width; that may change in the future. (cherry picked from commit 58fa16ef1e6d6c3a698d220409416bccec187287) Author: Ken Hornstein Date: Thu Aug 17 01:12:22 2017 -0400 Improve installation documentation Fix up the various installation information so it matches reality. (cherry picked from commit b7a676587f92187d2270be73a1ede5be0af9f104) Author: Ken Hornstein Date: Wed Aug 16 23:55:23 2017 -0400 Make sure the %(kilo) and %(kibi) instructions are in fmttest(1). Man, we should really merge fmttest and fmtdump at some point. (cherry picked from commit 877306f0cf8700241efc2e245f66df5ba95113f9) Author: Ralph Corderoy Date: Sun Aug 6 18:15:41 2017 +0100 cpstripped(): Rewrite multi-byte version. Removes the assert(3) failure reported on the list for 1.7-RC1 when a non-space, non-cntrl, rune has a wcwidth(3) of -1; output L'?' in its place. The old code also didn't reset mbtowc(3)'s state before trying to parse "?"; that's handled differently now so isn't an issue. Pad with the multi-byte encoding of L" ", having ensured the wcwidth(1) of L' ' is one, rather than with a non-wchar_t ' '. Point out padding only occurs in one particular case, and not the other two; quite odd. (cherry picked from commit a091c28b416f83aa46dcb0bd0da81ca1d3b8a7f9) Author: Ralph Corderoy Date: Sat Aug 5 18:20:07 2017 +0100 cpstripped(), single-byte: Simplify logic. Now that it doesn't have to fit in with the multi-byte version's logic, it can be re-structured to be simpler. No functional change intended. (cherry picked from commit 8ba2c2e0a5c0e2c087cd1684a885b959c101e010) Author: Ralph Corderoy Date: Sat Aug 5 17:57:48 2017 +0100 cpstripped: Split into two versions, each with a single #ifdef. Got fed up trying to read C logic when the preprocessor's logic didn't nest neatly with the function's. No intentional change to either version. (cherry picked from commit 0a934c0ff1b5623956da677751e485c52e1ab361) Author: David Levine Date: Tue Aug 8 20:10:49 2017 -0400 Fixed scan to handle empty files without violating an assert [Bug #51693]. (cherry picked from commit 0d593e1ce1a218332af78b83987543756b0c6cf4) Author: Ralph Corderoy Date: Thu Aug 3 12:22:07 2017 +0100 NEWS: Move "new features" that might bite a user to the top. Author: Ralph Corderoy Date: Thu Aug 3 12:17:30 2017 +0100 NEWS: Re-order 1.7's sections, as discussed on nmh-workers. Author: Ken Hornstein Date: Wed Aug 2 22:20:46 2017 -0400 Updates for 1.7 release. Author: Ken Hornstein Date: Wed Aug 2 00:03:40 2017 -0400 Update DATE and VERSION for start of 1.7 release. Author: Ken Hornstein Date: Tue Aug 1 23:53:05 2017 -0400 Use correct error code for SSL context retrieval. Make sure we use the correct error code if we are unable to retrieve the SSL context from the context from the BIO. Author: Ken Hornstein Date: Tue Aug 1 13:28:04 2017 -0400 Document bug fix Merge: 8f460dd a2d70b2 Author: Ken Hornstein Date: Tue Aug 1 13:22:36 2017 -0400 Merge branch 'fix-post-bcc' This branch fixes bug #51098; the lack of alias expansion on a From line when doing a Bcc. Admittedly, this is rather an obscure bug, and AFAICT it never worked in any version of MH or nmh, but it is fixed now. Author: Ken Hornstein Date: Tue Aug 1 13:21:21 2017 -0400 Implemented test for this patch. This patch tests the code that does alias expansion in a From line when doing bcc. Which is, now that I think about it, one heck of a corner case. Author: Ralph Corderoy Date: Tue Aug 1 14:41:20 2017 +0100 Move m_getfld's MS_* mbox-type macros to the only user. Author: David Levine Date: Mon Jul 31 22:00:39 2017 -0400 Restricted application of the adjustment in m_Eom(). Per Ralph's suggestion. Update to commit 29db9a64a. Also, consolidated print statments in test-eom-align. Author: David Levine Date: Sun Jul 30 20:24:34 2017 -0400 Hacked m_Eom() to fix test-eom-align. Author: David Levine Date: Sat Jul 29 17:55:25 2017 -0400 Restored local variable to m_Eom(), to not truncate EOF. Reversion of significant part of commit d3e11c5e9. Thanks to Ralph for noticing that it wasn't a good change. Author: David Levine Date: Sat Jul 29 17:07:06 2017 -0400 Removed a local variable from m_Eom(). Minor code simplification in preparation for upcoming fix. Author: David Levine Date: Sat Jul 29 12:42:35 2017 -0400 Simplified m_strn() per Ralph's suggestions. Update to commit 4a56a28ac. Author: David Levine Date: Sat Jul 29 10:47:16 2017 -0400 Use m_strn() to allow restoration of buffer size to 26 bytes. Fix to commit a3724ed39. Author: Ralph Corderoy Date: Sat Jul 29 15:06:11 2017 +0100 dtimezone(): Explain abs(3) is undefined on INT_MIN. That's why a negative int is flipped over into unsigned by assuming two's complement. Author: David Levine Date: Sat Jul 29 10:02:28 2017 -0400 Added m_str() and m_strn() functions to convert int to string. Allows better fix to uip/forw.c than commit d711510305. Author: Ralph Corderoy Date: Sat Jul 29 14:29:15 2017 +0100 Simplify dtimezone()'s logic by working with unsigned int. Character buffer is resized down from arbitrary 64 to suit 32-bit int, a change to the recent a3724ed3. Author: Ken Hornstein Date: Tue Jul 25 15:40:28 2017 -0400 Finished implementation, but tests need to be written. Author: David Levine Date: Sun Jul 23 11:39:24 2017 -0400 Added some specific tests to test-eom-align. These were found by scanning a much larger range of buffer sizes, over nmh versions from cvs, 1.4, 1.5, 1.6, and current HEAD. Author: Ralph Corderoy Date: Mon Jul 17 12:58:38 2017 +0100 Bump up size of two static char[] so gcc knows they won't overflow. Author: David Levine Date: Sun Jul 16 20:06:01 2017 -0400 Increase size of buffer to avoid warning from gcc -Wformat-truncation. Author: David Levine Date: Sun Jul 16 17:25:51 2017 -0400 Replaced snprintf() to convert an int with m_name(). At Ralph's suggestion. The goal was to get rid of a warning from gcc -Wformat-truncation, but the code ends up being cleaner as well. Author: David Levine Date: Sun Jul 16 09:02:08 2017 -0400 Enhanced mhical syntax error message to provide some context. Specifically for the case of improperly folded lines. Author: David Levine Date: Sat Jul 15 09:37:26 2017 -0400 Fixed flex fixups to not break LFLAGS. Addresses comment added in commit 4ac978448. Author: David Levine Date: Sat Jul 15 09:16:47 2017 -0400 Added flex fixup for Fedora 26's flex 2.6.1. The fix is compatible with unpatched flex 2.6.1. Author: Ken Hornstein Date: Fri Jun 23 11:53:28 2017 -0400 Start of work to fix lack of address rewriting for bcc This is the start of work to fix the problems described in #51098. Is not finished yet. Author: David Levine Date: Sat Jun 17 13:42:59 2017 -0400 Rearranged statements to eliminate memory allocation. Update to commit a5bf16c0928cb4044b082f9cf6f44f9bb3998824. Author: David Levine Date: Sat Jun 17 11:01:32 2017 -0400 Show display program name and arguments in error message if it fails. Author: David Levine Date: Sat Jun 17 09:32:00 2017 -0400 Don't bypass scan_content() when expanding pseudoheaders. expand_pseudoheader() would avoid the call to scan_content() in order to inhibit use of quoted-printable for text content. Removed that; the user still has control over the use of quoted-printable via -maxunencoded. Though now, lines over 998 bytes long will always be encoded. Author: Ralph Corderoy Date: Sat Jun 10 18:32:08 2017 +0100 sbr/netsec.c: Report popped TLS error code, don't pop again. ERR_get_error() pops an error code so having tested that value it should also be the one that's reported in an error message, not another popped error code by calling ERR_get_error() again as this misleads as to the error's cause. Author: Ralph Corderoy Date: Tue May 30 23:00:10 2017 +0100 uip/inc.c: Don't increment variable of type bool. gcc 7.1.1 is warning against incrementing `bool' variables. Assign true instead. Author: David Levine Date: Thu Jun 1 19:54:21 2017 -0400 Fixed double fclose(). Author: Ken Hornstein Date: Thu Jun 1 12:26:23 2017 -0400 Remove ancient SENDMAILBUG code. Old SMTP code used to treat a code 451 the same as code 250 (success). It's not clear if this was ever a real bug in sendmail, but regardless this code is long obsolete. Author: Ken Hornstein Date: Thu Jun 1 12:25:15 2017 -0400 Comment cleanup; removed ancient reference to 4.2BSD systems. Author: Ken Hornstein Date: Wed May 31 14:39:48 2017 -0400 Normalize connection shutdown handling. I originally tried to make things work so that the netsec client code gave the client the option of closing the file descriptors if it wanted to, but I was running into a problem where if TLS negotiation failed part of the negotiation would be interpreted as connection data. The code has been changed to have the sockets close when the SSL BIO is released and to have netsec_shutdown unconditionally close the file descriptors. Author: Ken Hornstein Date: Wed May 31 11:53:47 2017 -0400 Use original error code from OpenSSL. Reuse the error code we already retrieved from OpenSSL, otherwise the error might be cleared the next time we call ERR_get_error(). Author: Ralph Corderoy Date: Mon May 29 13:20:00 2017 +0100 sbr/brkstring.c: Use strchr(3) in brkany(), not own loop. Author: Ralph Corderoy Date: Mon May 29 12:56:10 2017 +0100 sizeof char is always 1, so don't bother to divide by it. Author: Ralph Corderoy Date: Mon May 29 12:53:24 2017 +0100 Use DIM(a) macro a few more times; array's dimension using sizeof. Author: Ralph Corderoy Date: Mon May 29 12:23:38 2017 +0100 uip/scansbr.c: Add PUTC() macro, similar to FPUTS(). FPUTS() exists, but all the putc(3) checks for error were written alongside in longhand. May as well have a PUTC() to match, though perhaps just the existing check of the FILE's sticky error state with ferror(3) is sufficient and neither macro is required. Author: Ralph Corderoy Date: Mon May 29 11:49:29 2017 +0100 uip/scansbr.c: Stop `scan -file' copying mailbox to /dev/null. scan() was copying the mailbox to /dev/null when called for `scan -file foo.mbox' because it used outnum being non-zero as the test of whether to write instead of FILE pointer scnout being non-NULL. By switching, we can avoid the opening of /dev/null that was just to give scnout a valid value for the needless fputs(3), etc. Add comment explaining scan()'s outnum input parameter's three functions: -1, 0, and positive. Author: Ralph Corderoy Date: Sun May 28 13:07:25 2017 +0100 h/mts.h: Replace char pointer mmdlm1 with macro MMDF_DELIM. mmdlm1 only ever pointed to its initial string constant. Author: Ralph Corderoy Date: Sun May 28 12:32:28 2017 +0100 sbr/mts.c: Delete mmdlm2; use same-valued mmdlm1 instead. mmdlm1 and mmdlm2 had the same compile-time value. Both could be changed at run-time by mts.conf(5), but d205d39a stopped that. Use mmdlm1 instead of mmdlm2 and delete mmdlm2. Author: Ralph Corderoy Date: Sun May 28 12:21:12 2017 +0100 sbr/mts.c: Make MMDF's delimeters fixed at compile time. mts.conf(5) allowed `mmdelim1' and `mmdelim2' to alter the default MMDF begin and end markers of four ASCII SOHs and an LF. There doesn't seem to be a modern use for this, and nmh wouldn't have handled longer markers correctly so remove the capability. Author: Ralph Corderoy Date: Sat May 27 17:04:48 2017 +0100 uip/forw.c, uip/repl.c: Remove -file's "msh" comment. The comment claims -file is "interface from msh", but msh(1) was removed in e6917522. The options remain as discussion on the list prompted David to say he uses them occasionally. Author: Ralph Corderoy Date: Fri May 26 23:34:10 2017 +0100 uip/mhparse.c: Fix body starting a byte too soon when no blank line. m_getfld() returns BODY when the headers run into a line without a colon instead of being separated from the body by a blank line. The file's position and the returned `bufsz' differ from the normal case of a blank line and then the start of the body, causing confusion. get_content() was aware of the difference, documented it, and attempted to correct for it, but got it wrong and included the `\n' that terminates the last real header at the start of the "body". This affected a struct Content's c_begin. Use the correct file position for c_begin, adding a comment that explains the theory for both cases. Add a test-mhlist case that checks mhlist(1) states the body size is the same whether it is separated from the headers by a blank line or not. Correct existing test/bad-input/test-header test that expected the extra blank line to be counted and to appear in the output. Author: Ralph Corderoy Date: Fri May 26 12:36:32 2017 +0100 Remove mention of msh in comments and to-do list. msh(1) was removed in e6917522. Author: Ralph Corderoy Date: Fri May 26 11:56:37 2017 +0100 Makefile.am: Add test/inc/test-eom-align to XFAIL_TESTS. Since 5f34de43, it's expected the test will fail. Add it to XFAIL_TESTS so it's still run, but its failure doesn't cause the `check' target to fail. Author: Ralph Corderoy Date: Thu May 25 18:12:55 2017 +0100 Don't cast lseek(2)'s offset to off_t when it's 0. `lseek(fd, (off_t)0, SEEK_SET)' does not need the cast when a prototype is in scope, and is #include'd. Author: Ralph Corderoy Date: Thu May 25 17:23:10 2017 +0100 uip/slocal.c: Tidy `verbose' logic in usr_file(). Boolean was being tested three times instead of once after recent dead-code deletions. Author: Ralph Corderoy Date: Thu May 25 16:29:33 2017 +0100 uip/popsbr.c: Delete unused pop_list(), etc. Those deleted: pop_list(), pop_noop(), pop_rset(), and pop_top(). Author: Ralph Corderoy Date: Thu May 25 16:23:00 2017 +0100 sbr/utils.c: Delete dead-code open_form(); not called. Author: Ralph Corderoy Date: Thu May 25 14:36:59 2017 +0100 uip/comp.c: Delete single-use NULLMP macro. It just cast 0 to a pointer to struct msgs and was used once, as a function's parameter. Replace that with NULL since a prototype for the function is visible. Author: Ralph Corderoy Date: Thu May 25 14:36:33 2017 +0100 sbr/fmt_compile.c: Delete single-use NEWFMT macro. Its simple content was to increment a variable; doing that in situ is more clear. Author: Ralph Corderoy Date: Thu May 25 13:53:27 2017 +0100 Remove support for ./.foo.map index for ./foo mailbox. An MH-only index of a mailbox, mbox or MMDF format, called a map file, could be built and maintained by packf(1), rcvpack(1), and slocal(1), but since msh(1) was removed in e6917522, there hasn't been a user of the index file so stop producing it and delete all the supporting code in uip/dropsbr.c. mbx_copy() loses its `mapping' and `noisy' parameters; noisy was only used when mapping. Delete mbx_read() and mbx_size() as they have no callers without maps. Author: Ralph Corderoy Date: Thu May 25 13:03:53 2017 +0100 test/runpty.c: Add more detail to "timed out" message. test/install-mh/test-version-check was skipped due to timeout, but it took a lot less than the thirty-second timeout to run. Add start time and the time now to the diagnostic, and select(2)'s return value. Author: Ralph Corderoy Date: Thu May 25 11:24:54 2017 +0100 uip/prompter.c: Make getln() static; only called locally. Author: Ralph Corderoy Date: Thu May 25 11:21:40 2017 +0100 uip/prompter.c: Delete obfuscating ERASE, etc., macros. Their few uses are clearer as `t_io.c_cc[VERASE]' as otherwise the storage, t_io, isn't mentioned, and c_cc and VERASE match termios.h's man page. Author: Ralph Corderoy Date: Thu May 25 11:18:11 2017 +0100 uip/prompter.c: Delete unused macros CKILL and CERASE. They haven't been used in git's history. Their definitions of `@' and `#' might surprise younger users if put into use. :-) Author: Ralph Corderoy Date: Wed May 24 19:22:02 2017 +0100 uip/inc.c: Delete POP3's -pack option for msh users. inc(1)'s -pack option, only available with POP3 access, stored the emails in a spool file instead of a folder. The man page says this was intended for msh(1) users, but msh was deleted in e6917522. The spool file was always in packf(1)'s MMDF format, no option of -mbox, and was a rare producer of `map' files that indexed the spool file, again intended for msh. Removing -pack makes deletion of map files elsewhere in the code easier. Author: Ralph Corderoy Date: Wed May 24 13:50:25 2017 +0100 uip/dropsbr.c: Delete unused mbx_write() and map_read(). Most recently used by msh(1), removed by e6917522. Author: Ralph Corderoy Date: Tue May 23 12:56:00 2017 +0100 Replace some "FALLTHRU" comments with control flow. Instead of a case statement falling through, with a "FALLTHRU" comment, to the follow case that just does a break, continue, goto, etc., control-flow statement, duplicate the statement in place of the comment. Fall-through should be the exception, and saving a break statement doesn't offset the cognitive cost when reading the source. Author: Ralph Corderoy Date: Tue May 23 12:53:32 2017 +0100 config/config.c: Fix indentation of "FALLTHRU" comment. It's not part of the preceding if-statement, but unconditional. Author: Ralph Corderoy Date: Sun May 21 12:45:54 2017 +0100 sbr/m_getfld.c: Fix and improve `delim' comment. fdelimlen is one higher than was described in 86c5ebc87. Describe pointer positions pictorially. Author: David Levine Date: Mon May 22 20:17:48 2017 -0400 Fixed a couple of typos. Author: Ralph Corderoy Date: Sat May 20 12:46:04 2017 +0100 test/inc/test-eom-align: Show size of test email as progress. Don't bother over-printing; Perhaps when it's working again and lots of output is being produced. Author: Ralph Corderoy Date: Sat May 20 12:38:22 2017 +0100 test/inc/test-eom-align: Fix tests; they've never worked. Instead of cycling through lots of mbox sizes, $STDIO_BUFSZ was always used as the desired size resulting in tests A and B being duplicated 221 times each. Slowly, if using valgrind. The tests fail now they're fixed. Author: Ralph Corderoy Date: Sat May 20 12:09:13 2017 +0100 test/common.sh.in: test_skip(): Remove unused variable. `$Test' was being interpolated into the output, but has never existed. Rephrase the output given a /^SKIP: / line follows from the test harness due to the `exit 77'. Author: Ralph Corderoy Date: Sat May 20 11:53:55 2017 +0100 test/runpty.c: Add missing exit(3) after child fails to execvp(3). Author: Ralph Corderoy Date: Sat May 20 11:48:10 2017 +0100 uip/aliasbr.c: Remove dead code used for Unix groups. Main functionality removed in afaab789. Author: Ken Hornstein Date: Thu May 18 14:03:09 2017 -0400 Remove support for aliases based on Unix groups. Remove support for expanding aliases based on group membership (=) and all users who have a particular primary group (+). This was the result of a discussion on nmh-workers; these features were of dubious value, likely not used, and interfered with RFC-2047 encoded names in alias files. Author: Ralph Corderoy Date: Wed May 17 17:56:00 2017 +0100 uip/mhshowsbr.c: Increase buffer size for showing-content command. Experimenting with small BUFSIZ to try and trigger programs caused one test to fail because the code detected BUFSIZ was too small a string to hold the command to execute. Use NMH_BUFSIZ instead. Author: Ken Hornstein Date: Wed May 17 23:28:02 2017 -0400 After further reflection, I decided I didn't like that previous implementation. Instead, allocate two ptys and connect one to standard input and the other to standard output and standard error of the child process. After the first data is received from the slave, close the master connected to standard input; that will generate an EOF on input to the child process. This ends up being much cleaner than looping and waiting to send the EOF character to the child process. Author: Ken Hornstein Date: Wed May 17 21:40:57 2017 -0400 Apparently on Linux if a slave pty is closed, instead of the master getting an EOF they get an EIO, which strikes me as unfriendly. So make sure we exit the main read loop without complaint on an EOF or error. Author: Ken Hornstein Date: Wed May 17 21:00:47 2017 -0400 Switch from using script(1) to a new custom utility, runpty. It turns out on some systems script(1) has a bug that results in hangs that is simply too difficult to test for, and this custom utility is simpler. Author: Ralph Corderoy Date: Wed May 17 15:15:18 2017 +0100 uip/mhbuildsbr.c: Fix long-line truncation when BUFSIZ is 1024. a23477eb changed one char array from BUFSIZ to NMH_BUFSIZ elements, but the long line read into it was passed to user_content() that strncpy(3)'d it, silently truncating, to another char array, still BUFSIZ long. This show up on platforms where BUFSIZ is 1024 versus NMH_BUFSIZ's minimum of 8192. Author: Ralph Corderoy Date: Wed May 17 13:06:40 2017 +0100 test/common.sh.in: Clarify it's the first failure by a *named* test. Unnamed tests may have failed earlier. Author: Ralph Corderoy Date: Wed May 17 12:58:15 2017 +0100 test/mhbuild/test-cte: Move run_prog() to just before check(). Prepare the input and output files, then run the program and check the result. Makes it easier to see every run is being checked if a, sometimes large, expected-output file isn't being produced in between. Author: Ralph Corderoy Date: Wed May 17 12:47:07 2017 +0100 test/mhbuild/test-cte: Add missing check() for earlier run_prog(). be6c3984 added a new run_prog and swiped the earlier check. Author: Ralph Corderoy Date: Wed May 17 12:45:26 2017 +0100 test/common.sh.in: Clarify test name in failure message. Some test names don't stand out as that when suffixed with `failed' amidst all the other output. Change `foo failed' to `first test failure: foo' instead. Also makes clear there's possibly other tests that failed later. Author: Ken Hornstein Date: Tue May 16 21:30:10 2017 -0400 Make sure we are in the correct directory when we do "git describe". Author: Ralph Corderoy Date: Wed May 17 00:27:54 2017 +0100 sbr/check_charset.c: Fix warning on unspecified struct initialisers. A different C compiler disliked `{NULL}' as the initialiser for a two-member struct so specify NULL for the other member too. Author: Ralph Corderoy Date: Tue May 16 12:57:25 2017 +0100 Rewrite norm_charmap(), moving code into data. Also removes return of static char array, and is more precise, e.g. `CP1242' doesn't become `WINDOWS-1242' as it's not a known code page. Merge: 684716b 3d0e5b6 Author: Ralph Corderoy Date: Tue May 16 11:44:18 2017 +0100 Merge commit '3d0e5b6a4383a5228732edd6cb1532375b771262' Author: Ralph Corderoy Date: Tue May 16 11:35:49 2017 +0100 Merge sbr/norm_charmap.c into sbr/check_charset.c. Alter norm_charmap() to be static now its only caller is in the same file. I've checked the upstream cam.ac.uk source and it's still the same and hasn't changed in years, so I don't think there's much benefit from having it standalone to ease checking. Author: Ralph Corderoy Date: Tue May 16 11:29:17 2017 +0100 Part 1 of merging sbr/norm_charmap.c into sbr/check_charset.c. This commit won't compile, but I'm attempting to get the rename into git so the history after the next, merge, commit will continue through both parents. Author: Ralph Corderoy Date: Tue May 16 11:21:50 2017 +0100 sbr/unquote.c: Move prototype from h/prototypes.h to new header. Author: Ralph Corderoy Date: Tue May 16 10:59:07 2017 +0100 sbr/mime_type.c: Move prototype from h/prototypes.h to new header. Author: Ralph Corderoy Date: Tue May 16 10:53:17 2017 +0100 sbr/message_id.c: Move duplicate prototypes to new header. Author: Ralph Corderoy Date: Tue May 16 10:41:35 2017 +0100 sbr/makedir.c: Move prototype from h/prototypes.h to new header. Author: Ralph Corderoy Date: Tue May 16 10:36:02 2017 +0100 sbr/m_popen.c: Move prototypes from h/prototypes.h to new header. Author: Ralph Corderoy Date: Tue May 16 00:30:59 2017 +0100 sbr/m_maildir.c: Move prototypes from h/prototypes.h to new header. Author: Ralph Corderoy Date: Tue May 16 00:02:30 2017 +0100 sbr/m_rand.c: Move prototype from h/prototypes.h to new header. Author: Ralph Corderoy Date: Mon May 15 23:54:05 2017 +0100 h/prototypes.h: Give sbr/lock_file.c's prototypes their own header. Author: Ralph Corderoy Date: Mon May 15 18:58:19 2017 +0100 sbr/utils.c: Delete unused upcase() function. Author: Ralph Corderoy Date: Mon May 15 18:52:32 2017 +0100 h/utils.h: Move in PLURALS() macro from h/mh.h. Author: Ralph Corderoy Date: Mon May 15 18:47:46 2017 +0100 h/prototypes.h: Remove duplicate prototype for pwd(). It is already in h/utils.h. Author: Ralph Corderoy Date: Mon May 15 18:39:45 2017 +0100 h/utils.h: Move in nmh_init() prototype from h/prototypes.h. Author: Ralph Corderoy Date: Mon May 15 18:06:19 2017 +0100 uip/mhshowsbr.h: Move in declarations from h/mhparse.h. Delete non-existent markerform parameter from show_all_messages()'s comment. Alter show_all_messages()'s definition's concatsw parameter to match comment and prototype. Author: Ralph Corderoy Date: Mon May 15 17:14:01 2017 +0100 uip/mhshowsbr.c: Create header file with exports' declarations. Create a single set of externs for mhshowsbr.c's global variables. Have the other users of those use the new include file instead of their own declarations. Author: Ralph Corderoy Date: Mon May 15 16:09:28 2017 +0100 uip/mhcachesbr.c: Move exported symbols to existing h/mhcachesbr.h. Remove the user's copies of the declarations. A static struct swit caches[] was declared everywhere that included h/mhcachesbr.h. The larger number of includers causes `variable not used' for `caches'. Move that declaration to uip/mhcachesbr.c and have an exported `cache_policy' symbol that points to it for the existing users. Author: Ralph Corderoy Date: Mon May 15 15:14:44 2017 +0100 uip/mhoutsbr.c: Move exported prototype to new header file. Alter the callers to include the new header file instead of having their own copy of the prototype. Author: Ralph Corderoy Date: Mon May 15 15:07:10 2017 +0100 sbr/m_mktemp.h: Move remaining prototypes from h/prototypes.h. Gives the normal one header file showing interface exported by one C file. Author: Ralph Corderoy Date: Mon May 15 14:40:52 2017 +0100 sbr/m_mktemp.h: Create with missing prototypes. Some of sbr/m_mktemp.c's functions didn't have prototypes in a header file so callers were declaring prototypes themselves. Have them include the new header file instead. Author: Ralph Corderoy Date: Mon May 15 14:31:36 2017 +0100 sbr/utils.c: Use h/signals.h for setup_signal_handlers prototype. Deleted its own prototype for setup_signal_handlers() and added it to the existing h/signals.h as it's defined in h/signals.c. Author: Ralph Corderoy Date: Mon May 15 14:23:53 2017 +0100 uip/picksbr.c: Use function prototypes for `nexus' functions. Prototypes for ORaction(), etc., now state the parameters they expect. Removed the args() macro, instead explicitly listing the arguments being passed to functions. Author: Ralph Corderoy Date: Mon May 15 14:12:21 2017 +0100 Specify function parameters in prototypes, mainly void. These prototypes are all in *.[cl] source compared with the *.h of the earlier commit. All but one had void added, that one's parameter was a char pointer. Author: Ralph Corderoy Date: Mon May 15 13:45:39 2017 +0100 h/prototypes.h: Remove scan_reset_m_getfld_state() prototype. Function removed back in 2014 by 58eaf2c2. Author: Ralph Corderoy Date: Mon May 15 13:39:08 2017 +0100 Use `void' in prototypes for functions with no parameters. The old-style `int foo()' still lived on in a few places. Author: Ralph Corderoy Date: Mon May 15 13:29:28 2017 +0100 h/mhparse.h: Move mhfree.c's free_content prototype to new header. It was the only thing of mhfree.c's in h/mhparse.h. Author: Ralph Corderoy Date: Mon May 15 13:25:23 2017 +0100 Match `NORETURN' function prototypes by adding it to definition. Author: Ralph Corderoy Date: Mon May 15 13:13:45 2017 +0100 Create and use header file for uip/mhfree.c's exports. Remove all the duplicate inconsistent prototypes from mhfree.c's users. Author: Ralph Corderoy Date: Mon May 15 13:10:30 2017 +0100 test/mhical/test-mhical: Force UTC timezone for mhical. Commit c3238c0e added a test but mhical's output depends on its timezone; force it to UTC for consistent results. Author: Ralph Corderoy Date: Mon May 15 12:52:23 2017 +0100 uip/mhfree.c: Make free_header() static. Author: Ralph Corderoy Date: Mon May 15 12:38:26 2017 +0100 uip/flist.c: Make locally defined and used functions static. Author: David Levine Date: Sun May 14 17:27:23 2017 -0400 Support iCalendar event request files that don't end with a newline. Such files do not conform to RFC 5545 § 3.1, which requires that each contentline end with a CRLF. But be liberal in what we accept. Author: David Levine Date: Sun May 14 13:08:03 2017 -0400 Added explicit dependency to build sbr/icalparse.h before running LEX. "Fix" to commit 665dfc96. The build had been relying upon the listed order of files. Author: David Levine Date: Sun May 14 12:18:35 2017 -0400 Have post(1) report name of fileproc if it fails. Author: Ralph Corderoy Date: Sun May 14 23:17:36 2017 +0100 Replace calls to unputenv() with unsetenv(3). Author: Ralph Corderoy Date: Sun May 14 22:56:52 2017 +0100 Replace calls to m_putenv() with setenv(3). Author: Ralph Corderoy Date: Sun May 14 19:35:13 2017 +0100 sbr/dtimep.l: Remove redundant wrapping parenthesis in definitions. It's been decades since a lex(1) didn't follow POSIX and treat `{foo}' as parenthesis surrounding foo's definition. Other nmh lex files work without the extra wrapping. Author: Ralph Corderoy Date: Sun May 14 12:53:33 2017 +0100 uip/mhstoresbr.c: Fix single-character nmh-storage bug. If the profile component nmh-storage was a single character, e.g. the relative directory `d', then it would be dropped from the output path so instead of `d/foo' being written, `/foo' would probably fail. I think this was due to a faulty check for nmh-storage being `/'. Add a test for a non-/ single-character nmh-storage. Author: Ralph Corderoy Date: Sun May 14 12:08:06 2017 +0100 sbr/fmt_rfc2047.c: Simplify test for /^=\?./. Author: Ralph Corderoy Date: Sun May 14 11:23:33 2017 +0100 Use new PLURALS(n) macro instead of variety of tests. Whether to output a plural noun in a message was decided by ternary operators that tested n==1, n!=1, n>1, etc. Make them all consistent by using PLURALS(n). Author: Ralph Corderoy Date: Sat May 13 23:40:50 2017 +0100 uip/folder.c: Use `%s' for plural, not `%c'. Instead of a ternary operator with 's' and ' ' as the outcomes, switch the format specifier from `%c' to `%s' and use strings "s" and " ". Author: Ralph Corderoy Date: Sat May 13 18:39:06 2017 +0100 uip/folder.c: Rewrite plural test to common form. The common form is a choice between "" and "s". This one occurrence was using " " and "s" so either output was a fixed width. Alter the printf(3) format string from `%s' to `%1s' to provide that instead. Allows the new code to be altered by an upcoming `plural' change. Author: Ralph Corderoy Date: Sat May 13 18:35:15 2017 +0100 Makefile.am: Alter long lists to be sorted, one entry per line. It was hard to see what files were included in some variables when searching for the best place for new content. Some variables had definitions that were almost sorted, by weren't. Switch to a one-entry-per-line list, in `LC_ALL=C sort' order, documented at the start of the file. Makes it easy to run through the lists and see the patterns. Author: Ralph Corderoy Date: Sat May 13 13:24:03 2017 +0100 Use FENDNULL() instead of duplicate, locally defined, empty(). Three files had an empty() that was defined using FENDNULL(); use the latter directly. Author: Ralph Corderoy Date: Sat May 13 13:13:18 2017 +0100 Add FENDNULL(s): fends off NULL by giving an empty string instead. Use it in place of all the `foo->bar_xyzzy ? foo->bar_xyzzy : ""'. Avoids the reader having to check first two of the ternary operands are the same. Author: Ralph Corderoy Date: Sat May 13 12:56:58 2017 +0100 sbr/mf.c: Rename path to routepath to avoid h/mh.h clash. Adding #include of h/mh.h brings two path global symbols together; path() and char *path. Rename the latter. h/mh.h is needed by a future commit. Author: Ralph Corderoy Date: Fri May 12 23:29:31 2017 +0100 Replace `a == b ? 1 : 0' and similar with `a == b'. Author: Ralph Corderoy Date: Fri May 12 23:14:43 2017 +0100 Replace `e ? 0 : 1' with `!e'. Needs less thought to read. Author: Ralph Corderoy Date: Fri May 12 22:45:34 2017 +0100 sbr/icalparse.y: Replace max(BUFSIZ, 8192) with NMH_BUFSIZ. Author: Ralph Corderoy Date: Fri May 12 22:42:35 2017 +0100 Use existing macros min() and max() more. Author: David Levine Date: Thu May 11 22:41:02 2017 -0400 Clarified the phrasing added by commit 44ce2010. Author: David Levine Date: Thu May 11 20:20:16 2017 -0400 Added warning about when post(1) can't refile(1) a draft. Author: Ralph Corderoy Date: Wed May 10 12:13:28 2017 +0100 sbr/fmt_scan.c: Fix `foo%-42{bar}' right-justification bug. The space padding was added at the start of the output buffer, not the start of the component being formatted. Caused by 92128dac's move to dynamic allocation for fmt_scan()'s output. Only shows if the component isn't at the start of the buffer. Expand existing test/format/test-rightjustify to cover this. Author: Ralph Corderoy Date: Tue May 9 23:10:06 2017 +0100 config/version.sh: Rewrite. Use uname(1), git-describe(1), and UTC. Not sure why it searched through PATH manually for uname(1) and hostname(1). uname and its -n option are POSIX so just use those. It was the preference over hostname anyway. Use git-describe(1), not just git-branch(1), as it gives more detail, including --dirty to show the built source differs from the commit. Specify the format for the build date, and its timezone; +0000. Author: Ralph Corderoy Date: Tue May 9 22:48:11 2017 +0100 sbr/mf.c: Simplify isat(); it's /^ at /i. This one's for all those RFC 733 emails out there. You know who you are. Author: Ralph Corderoy Date: Sun May 7 23:30:46 2017 +0100 uip/inc.c: Use bool, not int, for some of the options. Makes clear there's no special meaning to repeating these options more than once. Author: Ralph Corderoy Date: Sun May 7 22:43:19 2017 +0100 sbr/netsec.c: Remove extraneous semicolon. Author: Ralph Corderoy Date: Sun May 7 22:35:41 2017 +0100 Split some comma-operator terms into separate statements. Some uses of the comma operator weren't the idiomatic `p++, len--'. Split its terms into two statements instead, e.g. `close(fd); fd = -1'. Author: Ralph Corderoy Date: Sun May 7 18:02:03 2017 +0100 uip/picksbr.c: Increase line-buffer size for "grep" action. Alter LBSIZE from 1024 to NMH_BUFSIZ, e.g. 8192. This dominates the size of the char array used to hold a single unfolded header line when evaluating a "grep" action, e.g. `-to foo' becomes `^to[ ^I]*:.*foo'. Author: Ralph Corderoy Date: Sun May 7 14:01:48 2017 +0100 uip/scansbr.c: Replace uses of SBUFSIZ with NMH_BUFSIZ. Now that the former is defined as the latter, the uses of SBUFSIZ were all in the same expression and it simplifies from a ternary expression to NMH_BUFSIZ. Author: Ralph Corderoy Date: Sun May 7 13:57:39 2017 +0100 uip/rcvdist.c: Replace SBUFSIZ with NMH_BUFSIZ. The former was defined as the latter and had only one proper use: to size a char array. The other uses should have been the sizeof operator on that array, and now are. Author: Ralph Corderoy Date: Sun May 7 13:56:40 2017 +0100 uip/replsbr.c: Replace single use of SBUFSIZ with NMH_BUFSIZ. The former was defined as the latter; not a lot of point having it. Author: Ralph Corderoy Date: Sun May 7 13:03:01 2017 +0100 Make many m_getfld() buffer parameters NMH_BUFSIZ big. char arrays were often stdio.h's BUFSIZ large, and that's 8192 with here with glibc 2.25-1 on Linux x86_64, so using NMH_BUFSIZ is no different as that's max(BUFSIZ, 8192). But some were 256 or 512 with a local SBUFSIZ macro and they caused scan(1) to truncate a field, or pick(1) to not spot text because the field was truncated. Delete bad-input/test-header's test for m_getfld()'s detection for a header without a colon that's under the header-length NAMESZ limit, but longer than the passed in buffer. This no longer happens in scan as the buffer is larger than the longest allowed header. Author: Ralph Corderoy Date: Fri May 5 13:11:15 2017 +0100 configure.ac: Enable assert(3) by default. Revert 167e542b that disabled assert(3) by default after private email discussion with David Levine. I suggested it being enabled by default in git so those running nmh from git were testing them for us, with it being disabled as part of the release process so packagers continue with it disabled. David pointed out that would make the release intentionally different from what had been long tested so the default is now enabled assertions everywhere unless disabled by a packager. Author: Ralph Corderoy Date: Mon May 1 23:02:06 2017 +0100 mhstoresbr.c: Flip logic to simplify. Remove else after continue. Former in store_partial(), latter in parse_format_string(). Author: Ralph Corderoy Date: Mon May 1 22:57:44 2017 +0100 mhlsbr.c: Flip parse()'s logic. Remove oneline()'s else after break. Author: Ralph Corderoy Date: Mon May 1 22:56:30 2017 +0100 dropsbr.c: Flip mbx_open()'s logic to simplify. Author: Ralph Corderoy Date: Mon May 1 22:47:38 2017 +0100 base64.c: Remove some else after break. Flip logic to simplify. Author: Ralph Corderoy Date: Mon May 1 22:46:38 2017 +0100 mhfixmsg.c: Flip logic to simplify. Remove else after break. Author: Ralph Corderoy Date: Mon May 1 22:36:30 2017 +0100 path.c: Simplify compath()'s flow; return, don't break twice. Author: Ralph Corderoy Date: Mon May 1 21:49:38 2017 +0100 mhshowsbr.c: Remove else after break in iconv_start(). Author: Ralph Corderoy Date: Mon May 1 21:46:20 2017 +0100 mhparse.c: Remove a couple of else after continue. In openQuoted() and parse_header_attrs(). Author: Ralph Corderoy Date: Mon May 1 21:43:36 2017 +0100 m_getfld.c: Remove else after break in m_unknown() and m_Eom(). Author: Ralph Corderoy Date: Mon May 1 21:42:59 2017 +0100 picksbr.c: Remove some else after break in plist(). Author: Ralph Corderoy Date: Mon May 1 18:42:07 2017 +0100 fmt_rfc2047.c: Remove else after decode_rfc2047()'s break. Author: Ralph Corderoy Date: Mon May 1 18:33:15 2017 +0100 sortm.c: Flip get_fields()'s logic to simplify. Author: Ralph Corderoy Date: Sun Apr 30 15:25:20 2017 +0100 README.developers: Add pointers to Debian's Lintian's complaints. Author: Ralph Corderoy Date: Sun Apr 30 15:14:46 2017 +0100 README.developers: Add blank lines for consistent headers. Author: Ralph Corderoy Date: Sat Apr 29 00:01:58 2017 +0100 Fix spelling in C comments. Author: Ralph Corderoy Date: Fri Apr 28 22:42:46 2017 +0100 bvector_copy: Use bvector's tiny storage if big enough. Otherwise a source bvector that's using tiny storage has its bits duplicated into a malloc'd area when the destination's tiny storage was sufficient. Author: Ralph Corderoy Date: Fri Apr 28 22:08:26 2017 +0100 sbr/oauth.c: Remove const to avoid curl's debug_callback warning. The curl_debug_callback typedef doesn't use const for any of the function's parameters. On one of the compilation platforms here, oauth.c's debug_callback having const specifiers for some parameters causes compilation warnings, and -Werror stops the compilation. Remove them. Author: Ralph Corderoy Date: Fri Apr 28 17:12:31 2017 +0100 sbr/folder_read.c: Don't malloc() once per message. Instead of struct msgs having a pointer to a malloc'd array of pointers, each to a malloc'd struct bvector, 1+N, it now has a pointer to a malloc'd array of struct bvector; one malloc for all of them. This avoids the large number of calls to malloc() and free() that's linear with the size of the folder. But there are some downsides. In order to step through an array of struct bvector, code outside of sbr/vector.c needs to know the struct's size. The simplest way to do this is to make the struct's definition public, with a comment that access should be through vector.c. New functions are needed to initialise the content of an already allocated bvector, and to finish with its content prior to deallocation. bvector_create() and bvector_free() now also use these new functions. Before, it was the array of pointers to bvector that would be realloc'd. That doesn't work for the array of bvectors as they may contain pointers to within themselves. The solution is to malloc a new array and bvector_copy() the ones to keep across, as folder_realloc() now does. The other half of its logic that coped with growth at the end of the array, has been deleted. Also deleted, is the code to clear the bvectors before and after the old ones as they start in that state. Author: Ralph Corderoy Date: Fri Apr 28 17:00:54 2017 +0100 valgrind: Add suppression for dbm_open(3)'s write(2). It writes bytes from an area it mallocs, but doesn't set all of those bytes first. See with gdbm 1.13-1 on Arch Linux. Author: Ralph Corderoy Date: Fri Apr 28 12:45:26 2017 +0100 sbr/vector.c: Only allocate bvector storage for set bits. Now that a pointer to all the bit storage doesn't escape vector.c, there's no need to allocate storage, that's initialised to 0, just to then clear a bit in it. Only extend the bits's storage for set bits. Remove the unused initial size parameter from bvector_create() as it simplifies the implementation. Author: Ralph Corderoy Date: Fri Apr 28 12:27:44 2017 +0100 sbr/vector.c: Add bvector comments, tidy identifiers. Author: Ralph Corderoy Date: Fri Apr 28 12:16:01 2017 +0100 sbr/vector.c: Rewrite BVEC_BYTES(n) macro to remove branch. Use the idiom of integer truncation. Author: Ralph Corderoy Date: Fri Apr 28 12:12:15 2017 +0100 sbr/vector.c: Use new BVEC_BITS_BITS macro. Factors out a common expression from a few other places. Author: Ralph Corderoy Date: Thu Apr 27 00:14:28 2017 +0100 sbr/vector.c: Zero the growth with memset(3), not loop. When the resize functions grow the vectors, as they always do, zero the new slots with memset(3) rather than a for loop. Particularly of note for the bit vector where it was bvector_clear()ing one bit at a time. Although a NULL pointer needn't have a representation of all-zero bits, the code was already assuming that, e.g. on the initial allocation, so we're no worse off. Author: Ralph Corderoy Date: Wed Apr 26 13:41:27 2017 +0100 sbr/vector.c: Change bvector_bits() to return first word. Rename it to bvector_first_bits() to represent its new behaviour. It has only one caller that uses it to produce debug. Tighten the API so other callers don't get access to the location of the bvector's bits. Author: Ralph Corderoy Date: Tue Apr 25 23:21:21 2017 +0100 sbr/vector.c: Embed initial vector storage in header struct. Instead of a malloc(3)'d struct bvector having a pointer to a separately malloc'd area for the bits in the normal case of the default initial size, have non-malloc'd storage in the struct itself, and set the pointer to that. It's two unsigned longs, which is less than the previous default of 256 bits for struct bvector, but still double the pre-bvector norm of one word on 32 and 64-bit architectures. This halves the mallocs needed to create a struct bvector in the common case, but does mean that embedded memory is wasted should it not be enough. That's probably an unusual case. It also means derefencing the pointer to the bits probably hits the same cache line. Have separate initial sizes for string and int vectors. Author: Ralph Corderoy Date: Tue Apr 25 00:20:08 2017 +0100 sbr/vector.c: Remove `vec' argument from BVEC_OFFSET(), etc. A few macros took a struct bvector pointer as their first argument just to get the sizeof one of its fields. This can be done with a NULL pointer so remove that argument from all of them. Author: Ralph Corderoy Date: Mon Apr 24 23:47:46 2017 +0100 sbr/vector.c: Delete unused bvector_maxsize() and ivector_size(). May as well keep the proffered interface as small as possible so the implementation can make greater assumptions knowing some internal details aren't available. Author: Ralph Corderoy Date: Mon Apr 24 22:58:56 2017 +0100 sbr/vector.c: Move assert(3)s into bvector_create(). Rather than asserting on every bit-related operation, assert just when creating the vector. Whether the assertion is true is decided at compile time, so it only needs checking once; once for every vector is an easy compromise. Author: Ralph Corderoy Date: Mon Apr 24 22:08:09 2017 +0100 sbr/vector.c: Replace Nbby with 's CHAR_BIT. POSIX mandates CHAR_BIT is 8; see stdint.h(0p). Author: Ralph Corderoy Date: Mon Apr 24 21:19:56 2017 +0100 sbr/vector.c: calloc(3) rather than malloc(3) and memset(3). calloc(3) tells libc upfront that the memory needs to be zeroed rather than giving it the news later with memset. Perhaps this allows it to allocate from a CoW page of zero bytes, or it benefits from some other way in memset not having to clear each bit, but it knocks about 15% off the wall-clock time and the number of library calls under ltrace(1). Author: Ralph Corderoy Date: Mon Apr 24 21:13:52 2017 +0100 sbr/folder_read.c: Don't clear newly created bvectors. The newly created bvectors are already clear; don't loop clearing each again with memset(3). Author: Ralph Corderoy Date: Wed Apr 26 00:14:26 2017 +0100 sbr/fmt_scan.c: Only wcwidth(3) a valid mbtowc(3) result. The assert(3) added by 80a9e99f7078199500d2d53c8d77d1b92af06fbc is failing, but not reproducibly. It's probable that mbtowc() is returning a negative, and not altering wide_char, leaving it as random stack content. Taking its wcwidth() then sometimes also returns negative, causing the assert() failure. Initialising wide_char before the call isn't a solution as it isn't documented if it's modified to an invalid value on an error return. Instead, delay calculating the wcwidth() until after the possible substitution of "?". Leave the assert() in place. Author: Ralph Corderoy Date: Sun Apr 23 16:17:09 2017 +0100 Remove return statements at end of void functions. Author: Ralph Corderoy Date: Sun Apr 23 16:10:59 2017 +0100 tws.h: Remove ADJUST_NUMERIC_ONLY_TZ_OFFSETS_WRT_DST. Code that's conditional on its definition has been kept; just the tests removed. The comment explaining its purpose has been kept, just without the "If defined...". Author: Ralph Corderoy Date: Sun Apr 23 15:48:53 2017 +0100 Use C's `++', `+=', etc., not the longhand. Author: Ralph Corderoy Date: Sun Apr 23 15:19:33 2017 +0100 Remove unneeded incomplete, member-less `struct tag;'. The forward declaration isn't needed to typedef based on the struct. Author: Ralph Corderoy Date: Sun Apr 23 14:47:20 2017 +0100 mh.h: Compact the reserved sequence bit-masks. Removes the gap created by axing DELETED. Author: Ralph Corderoy Date: Sun Apr 23 14:36:57 2017 +0100 mh.h: Remove unused MODIFIED and DELETED macros. MODIFIED was a folder attribute used by msh(1), and DELETED a message attribute that may have last been used in the 1980s. Adjust corresponding FBITS and MBITS definitions. Author: Ralph Corderoy Date: Sun Apr 23 14:36:47 2017 +0100 md5.h: Remove unused UINT2 typedef for unsigned short. Author: Ralph Corderoy Date: Sun Apr 23 13:50:02 2017 +0100 ap.man, dp.man: Add fmttest(1) to SEE ALSO section. Author: Ralph Corderoy Date: Sun Apr 23 13:33:57 2017 +0100 tws.h: Remove zero-valued TW_SNIL macro, used once. Macro TW_SNIL was the zero value for a two-bit field. It was only used once, and that is better ordered to check for bits set with none set being the last, else, case, rather than in the middle. Kept the behaviour of undefined value 3 being treated as TW_SIMP, 2. Author: Ralph Corderoy Date: Sun Apr 23 13:18:20 2017 +0100 tws.h: Remove redundant TW_SZONE and TW_SZNIL bit-masks. TW_SZONE is a mask of one bit that can either be 0, TW_SZNIL, or set, TW_SZEXP. Rather than three macros for the single bit, have one, TW_SZEXP. Simplifies the test too when the mask is known to be one-bit wide. Author: Ralph Corderoy Date: Sun Apr 23 11:01:18 2017 +0100 mh-format.man: Fix `Return' column heading alignment. Two of the column headings were separated by spaces rather than a tab. The other two similar tables used `Return' instead of `Result', so switch to that at the same time. Author: Ralph Corderoy Date: Sun Apr 23 09:48:13 2017 +0100 sbr/dtime.c: Remove struct-assigning twscopy(). Historically, twscopy() assigned all the struct's members individually, but that was `#if 0'd as far back as the repository goes. The one caller now uses assignment, making clear the direction of data flow. Author: Ralph Corderoy Date: Sun Apr 23 09:28:24 2017 +0100 uip/sortm.c: Remove unused variable and dlocaltimenow() call. read_hdrs() has a auto `struct tws tb'. It's only use is as the destination for dlocaltimenow()'s result. Remove the variable. Also remove the dlocaltimenow() call; this I'm unsure about as it has a side effect of calling tzset(3). However, tests pass. Repository history sheds no light. Author: Ralph Corderoy Date: Sun Apr 23 09:19:13 2017 +0100 sbr/dtimep.l: Remove always false `europeandate' flag. Switched from reverse-podium MM/DD/YY interpretation to DD/MM/YY. Never set so conditional code unused. Author: Ralph Corderoy Date: Sun Apr 23 00:47:32 2017 +0100 Append descriptions to C source files with first-line filenames. Author: Ralph Corderoy Date: Sun Apr 23 00:29:02 2017 +0100 Add first-line comment describing C source's purpose. I had a stab at them after a bit of a skim; they're better than nothing. Author: Ralph Corderoy Date: Sun Apr 23 00:02:41 2017 +0100 Ensure a space after `#!'. The majority of the `#!' scripts have a space before the `/'; add one to the three deviants. Author: Ralph Corderoy Date: Sat Apr 22 23:36:19 2017 +0100 Correct first-line comments where filename is wrong. Having jiggled the start-of-file comment about, it's apparent that a few files either don't know their own name, or the format the rest of the gang follow. To wit, "basename(filename) -- ...". Author: Ralph Corderoy Date: Sat Apr 22 23:19:39 2017 +0100 Replace "/*\n * " with "/* " at the start of a file. Pulls the meat of the comment onto the file's first line, now that the blank line at the start of the file has been deleted. Allows `sed -ns 1p ...' or similar to give a summary of lots of files. Author: Ralph Corderoy Date: Sat Apr 22 19:05:32 2017 +0100 Remove leading and trailing blank lines from code. Many of the main source file start with a blank line, and many end with one or more too. They seem to serve little purpose so delete them. This makes all the files consistent in not having them and ideally the first line of a C source file will say something about its content in time instead of just "/*". Avoided editing format files, etc,. where the line could be significant, and historical files. Author: Ralph Corderoy Date: Sat Apr 22 18:37:15 2017 +0100 mts/smtp/smtp.h: Remove one-use rp_isbad() macro. It just cast its argument to signed char, and the sole user can do that itself a few lines later. Author: Ralph Corderoy Date: Sat Apr 22 18:32:55 2017 +0100 mts/smtp/smtp.h: Remove unused `MMDF' macros. The header file has a specification of a historical interface and removing the unused parts leaves it incomplete, but it's unlikely those parts will be needed and what remains seems more understandable; partly due to it being less to grok, and also because it relates more to modern use. Author: Ralph Corderoy Date: Sat Apr 22 18:21:01 2017 +0100 mts/smtp/smtp.c: Remove unused SM_... timeout macros. SM_TEXT, SM_CLOS, and SM_AUTH are unused. Alter the comment for the block of macros to state they're timeouts in seconds. Author: Ralph Corderoy Date: Sat Apr 22 17:28:18 2017 +0100 h/mf.h: Remove many unused macros; some UUCP related. MF... were "Codes returned by uucp2mmdf(), mmdf2uucp()". A spot check of the others shows they've not been used in this git repository. Author: Ralph Corderoy Date: Sat Apr 22 17:16:54 2017 +0100 sbr/mf.c: Remove unused functions: isfrom, lequal, mfgets. isfrom(s) checked for /^>?From /. lequal(a, b) was another case-insensitive strcmp(3). mfgets(fp, line) fetched a header at a time from fp, indicating when the end of headers was reached. Investigating their historical usage was, ironically, made too tedious to complete by the pollution of mass commits of historical MH. Author: Ralph Corderoy Date: Sat Apr 22 16:51:02 2017 +0100 uip/mhbuildsbr.c: Remove unusused MAXURLTOKEN macro. "Maximum size of URL token in message/external-body". Uses deleted in 95ad91ca30e1cda09efe454d12ed790a60661f56. Author: Ralph Corderoy Date: Sat Apr 22 16:48:13 2017 +0100 sbr/dtime.c: Remove unused `struct zone' definition. The uses went in 6a68057d8ef48bef3ee752741a53a629a2840e68. Author: Ralph Corderoy Date: Sat Apr 22 16:46:33 2017 +0100 uip/post.c: Don't bother naming `struct oauth_profile'. It's never used, and one more identifier to track when reading. If there's no name, that's a signal it's not used elsewhere. Author: Ralph Corderoy Date: Sat Apr 22 16:42:51 2017 +0100 h/nmh.h: Remove unused NLENGTH(dirent) macro. It just does a strlen(3) of its argument's d_name; that's not even done longhand anyway. And its name is very generic for such a narrow task. Author: Ralph Corderoy Date: Sat Apr 22 16:41:00 2017 +0100 h/mts.h: Remove unused isdlm{1,2}() macros. They just do a strcmp(3) of their argument against mmdlm{1,2} and test it's "equal". That's more clearly written longhand than have yet another small-scope, specialised, macro to recall; as practice bears out. Author: Ralph Corderoy Date: Sat Apr 22 16:39:29 2017 +0100 h/mh.h: Remove unused set_deleted() macro. Its comment says "for msh only". Author: Ralph Corderoy Date: Sat Apr 22 14:31:10 2017 +0100 h/tws.h: Remove TW_YES and TW_NO; TW_SUCC good enough. TW_SUCC is a macro for the bit-mask 0x0040. TW_YES, a vague name, was the same value. TW_NO was 0, and unused by the code. Ditch both those as TW_SUCC is sufficient for setting and testing. Alter its comment to make clear it means parsing was successful. Author: Ralph Corderoy Date: Sat Apr 22 14:10:41 2017 +0100 docs/FAQ: Replace suggestion of NOMHNPROC with -nocheckmime. Environment variable NOMHNPROC was removed in 1.6, as stated in NEWS. Author: Ralph Corderoy Date: Sat Apr 22 01:00:29 2017 +0100 sbr/discard.c: Simplify by inverting initial test. The function used to return early, but these days that's just avoiding a single statement, so execute that conditionally instead. Author: Ralph Corderoy Date: Sat Apr 22 00:48:47 2017 +0100 sbr/lock_file.c: Move static variables into their functions. A couple of file-scoped statc ints were the typical "if this function is being called for the first time" flags. Move each into their respective functions. Make them bools. Name them so the initial value is zero, thus placing them in BSS. Author: Ralph Corderoy Date: Fri Apr 21 14:01:21 2017 +0100 send and whatnow: Remove deprecated -attach... switches. They were changed to do nothing but warn on stderr that they were deprecated in 521674623 and 035c5db34, both before 1.6's release, and so can be removed ready for 1.7's release. Author: Ralph Corderoy Date: Thu Apr 20 14:27:46 2017 +0100 uip/dropsbr.c: Fix buffer overrun in mbx_copy(). The overrun occurs frequently, but typically zeroes a byte of a character pointer on the stack that's not yet been used. Caused by 28610ff9a604a75ae0c383be03aa19415ddb1965 appending a NUL after the bytes stored by read(2). Author: Ralph Corderoy Date: Tue Apr 18 15:37:54 2017 +0100 h/mime.h: Delete unused isatom(c) macro. Author: Ralph Corderoy Date: Tue Apr 18 12:54:28 2017 +0100 man/*.man: Fix some multi-word .B invocations. Some needed to be .B for the first word, but .I for the second, or just plain text for the rest of the words that should be on their own line. Others were just plain wrong and became .IR for a man-page reference. Then the .TP macro uses an input trap so only a single following line of source is used and this prevents a two-line `.B .I', so use embedded font escapes instead. Author: Ralph Corderoy Date: Tue Apr 18 01:14:57 2017 +0100 man/*.man: Use italic for emphasis, not bold or SHOUTING. When reading a body of text, italic is sufficient to add emphasis to what's already being read. Bold draws the eye to the word on the page and is more useful for keywords, concepts, etc. Some `.B' remain that should probably be `.I', but they looked to have other problems so I left them out of this pass. Author: Ralph Corderoy Date: Tue Apr 18 00:27:35 2017 +0100 README.manpages: `user ID', not `user-id'. Author: Ralph Corderoy Date: Tue Apr 18 00:24:07 2017 +0100 man/*.man: Replace minus sign with hyphen: `\-' with `-'. Conservatively changed many of the troff minus-signs, `\-', with a troff hyphen, `-'. Where it wasn't quickly obviously, I left it unchanged. There were also cases that shouldn't be either minus sign or hyphen. Those were changed to hyphen and still need to be fixed properly. Author: Ralph Corderoy Date: Mon Apr 17 23:36:28 2017 +0100 README.manpages: It's a `From header', not a `From: header'. Author: David Levine Date: Mon Apr 17 18:06:05 2017 -0400 Use stat(3) instead of lstat(3), to dereference symbolic links. Fix to commit 4318012376e06229307c0ed4f62a00faae9edc63. Author: Ralph Corderoy Date: Mon Apr 17 14:53:28 2017 +0100 Don't ignore bit 5 of a char when comparing alias names. It's a crude method of ignoring case, but makes `^' equal to `~'. Use tolower(3) instead. http://lists.nongnu.org/archive/html/nmh-workers/2017-03/msg00050.html Author: Ralph Corderoy Date: Mon Apr 17 14:34:14 2017 +0100 man/mh-profile.man: Note MHTMPDIR is deprecated. In future, only TMPDIR and /tmp will be used, e.g. not `mhpath +'. Author: Ralph Corderoy Date: Mon Apr 17 14:06:36 2017 +0100 README.manpages: Add `Common errors and subjective conventions'. Based partly on recent mailing-list posts about Larry's patches. Author: Ralph Corderoy Date: Mon Apr 17 13:32:47 2017 +0100 README.manpages: Add question to guide update of .TH's date. Author: Ralph Corderoy Date: Mon Apr 17 13:29:38 2017 +0100 README.manpages: Clarify that man-page source is ASCII. Author: Ralph Corderoy Date: Mon Apr 17 12:10:35 2017 +0100 Fix post's die() to save errno before unlink(2)ing. Author: Ralph Corderoy Date: Mon Apr 17 11:50:39 2017 +0100 Allow advertise() to assume strerror(3) won't fail. The code already assumes that elsewhere when it calls strerror(). Author: Ralph Corderoy Date: Mon Apr 17 11:42:39 2017 +0100 Change admonish(NULL, "foo") to inform("foo, continuing..."). Removes more uses of the ad... functions with unneeded parameters. Puts the "continuing" at the call site rather than the reader having to remember it's being magically appended. (Some calls were passing "foo\n" that would result in "foo\n, continuing...\n" appearing.) Author: Ralph Corderoy Date: Mon Apr 17 11:13:36 2017 +0100 Don't store getname()'s return value during flushing. `cp' after the loop is overwritten before being read. Not storing the return value makes it clear it's not used. Author: Ralph Corderoy Date: Mon Apr 17 11:06:12 2017 +0100 Improve function comments for the ad... diagnostic functions. Give the resulting layout of parameters that appears on stderr. Author: Ralph Corderoy Date: Mon Apr 17 10:57:54 2017 +0100 Fix bug in advertise("", "", "foo", ap). A non-NULL but empty `what' would result in "fooerrno\n" without separation. Improve the function's comment to try and make it obvious how its out of order parameters appear. Author: Ralph Corderoy Date: Mon Apr 17 10:42:09 2017 +0100 Replace advise(NULL, fmt, ...) with inform(fmt, ...). Author: Ralph Corderoy Date: Mon Apr 17 10:16:51 2017 +0100 Add inform() to provide an equivalent to advise(NULL, ...). A small step in clearing up the confusing ad... names of the diagnostic routines. `inform' isn't great, but err(3) nabs `warn' already. Author: Ralph Corderoy Date: Sun Apr 16 23:49:00 2017 +0100 Replace add(nonnull, NULL) with mh_xstrdup(nonnull). Only a few cases where it's obvious that the first parameter will not be NULL. Author: Ralph Corderoy Date: Sun Apr 16 23:36:07 2017 +0100 uip/aliasbr.c: Add FIXME to prove test of add()'s return value. add() always returns true so perhaps some other test is intended instead. Author: Ralph Corderoy Date: Sun Apr 16 23:25:32 2017 +0100 man/*.man: Replace \(ru with an underscore, e.g. .mh_profile. The character is an underscore, and that's what's wanted. \(ru gives a "rule", which draws as a thick baseline in PDFs; not a character at all. Other devices map \(ru onto underscore, e.g. ASCII, but an underscore should be used in the first place. Author: Ralph Corderoy Date: Sun Apr 16 14:01:42 2017 +0100 Replace some strdup() with mh_xstrdup(). (This is an old patch I had stashed.) Some surrounding `if...adios()' are removed too, but most of the strdup() calls weren't being checked for success, thus their replacement. Author: Ralph Corderoy Date: Sun Apr 16 00:35:11 2017 +0100 Remove unneeded `\&' from man pages. The zero-width character is used before a command character that is intended to be literal but may end up at the start of a line. Similarly, it's used after an end-of-sentence character when it may end up at the end of the line but isn't the end of a sentence. Remove the other cases because they're noise that confuses the issue of when `\&' should be used. Author: Ralph Corderoy Date: Sun Apr 16 00:34:01 2017 +0100 Alter mh-chart(7)'s NAME to be lowercase. And mention the commands' options. Author: Ralph Corderoy Date: Sat Apr 15 20:14:42 2017 +0100 man/*.man: No need for empty comment to be comments. A line that's just a `.' suffices. Author: Ralph Corderoy Date: Sat Apr 15 20:11:33 2017 +0100 Ensure .TH is the first line of a man page. Author: Ralph Corderoy Date: Sat Apr 15 19:17:31 2017 +0100 Fix errors in man-page NAME sections. man/fmttest.man didn't have a NAME section, but a FMTTEST one. And it broke lexgrog(1) by splitting the section over multiple lines and using `.IR'. Re-write to use inline escapes. man/rcvtty.man had two spaces before the `\-'. Author: Ralph Corderoy Date: Sat Apr 15 15:29:02 2017 +0100 Switch date to yyyy-mm-dd in generated mh-chart.man. It's still today's date, but improving on that seems non-trivial. Author: Ralph Corderoy Date: Sat Apr 15 14:48:02 2017 +0100 Specify yyyy-mm-dd date format for a man page's .TH date. Author: Ralph Corderoy Date: Sat Apr 15 14:36:51 2017 +0100 Use `Unix', not `UNIX', in man pages. "...in deference to dmr's wishes." — http://catb.org/jargon/html/U/Unix.html Author: Ralph Corderoy Date: Sat Apr 15 14:25:12 2017 +0100 Fix forward-reference and `news.*' in mh-alias(5)'s example. Spotted by Bob Carragher. The example's forward reference was made a backward one, and `news.*' explanation removed, in ff3060cefb460cce2174058eefff38b6e11ee2f1. Author: Ralph Corderoy Date: Sat Apr 15 11:31:22 2017 +0100 Set man-page date to last significant change, UTC. Author: Ralph Corderoy Date: Sat Apr 15 13:26:42 2017 +0100 Wind man-page date back to last significant change, UTC. Author: Ralph Corderoy Date: Fri Apr 14 18:34:43 2017 +0100 Wind man-page date back to the earliest git revision, UTC. No significant changes since then, and I can't find an earlier reference date. Author: Ralph Corderoy Date: Sat Apr 15 13:21:07 2017 +0100 Convert, already correct, man-page date to UTC. Author: Ralph Corderoy Date: Fri Apr 14 23:49:21 2017 +0100 Convert, already correct, man-page date to yyyy-mm-dd format. Author: Ralph Corderoy Date: Fri Apr 14 15:55:47 2017 +0100 Remove trailing spaces from lines in man pages. Author: Ralph Corderoy Date: Fri Apr 14 15:51:58 2017 +0100 Escape literal leading full stop in man/new.man. Error made in 5e32ede8e40251bf02f35b864e32a86e91599b3f. Author: Larry Hynes Date: Fri Mar 24 23:20:07 2017 +0000 Editing of man/rmm.man. - formatting, mostly - don't make NOT bold Author: Larry Hynes Date: Fri Mar 24 23:09:32 2017 +0000 Editing of man/rmf.man. - delete trailing whitespace - remove some \- things - some formatting - sort SEE ALSO Author: Larry Hynes Date: Fri Mar 24 23:02:00 2017 +0000 Editing of man/repl.com. - unashamedly add nmh to .SH NAME - replace the delightfully baroque 'may be used to produce a reply to an existing message' with 'may be used to reply to a message'. - remove some \- objects - deflower 'repl uses a reply template to guide its actions' - remove multiple instances of 'replied\-to', with 'replied to' - change 'tab\-stop' to 'tab stop' - some formatting - replace .B mhbuild with .IR mhbuild (1) - replace whatnow with .B whatnow Author: Larry Hynes Date: Fri Mar 24 19:05:21 2017 +0000 Editing of man/refile.man. - some formatting - change .B mh\-sequence (5) to .IR mh\-sequence (5) Author: Larry Hynes Date: Fri Mar 24 18:54:52 2017 +0000 Editing of man/rcvstore.man. - delete some \- things - some formatting - change protection to mode, in line with inc.man - Uncapitalize .SS Locking and \-unseen - sort SEE ALSO Author: Larry Hynes Date: Fri Mar 24 18:21:58 2017 +0000 Editing of man/prompter.man. - remove some \- items; quite a few, actually - put .B prompter on a line by itself, a number of times - some formatting Author: Larry Hynes Date: Fri Mar 24 17:54:58 2017 +0000 Editing of man/prev.man. - Delete trailing whitespace Author: Larry Hynes Date: Fri Mar 24 17:52:22 2017 +0000 Editing of man/post.man. - Delete trailing whitespace - Change inline mh-profile(5) refs to .IR mh-profile (5) - Some formatting - Change take to read - Say 'all message drafts' instead of 'all message draft' Author: Larry Hynes Date: Fri Mar 24 17:35:37 2017 +0000 Editing of man/pick.man. - Some formatting - Delete trailing whitespace - Change complimentary to complementary, because English - delete some \- things Author: Larry Hynes Date: Fri Mar 24 17:21:19 2017 +0000 Editing of man/packf.man. Author: Larry Hynes Date: Fri Mar 24 17:08:00 2017 +0000 Editing of man/next.man. - Delete trailing whitespace Author: Larry Hynes Date: Fri Mar 24 01:19:47 2017 +0000 Editing of man/rcvtty.man. - Add missing 'command' - Some formatting - Remove a \-, the mark that dare not speak its name - Use 'switches' instead of 'options' - Sort SEE ALSO programs Author: Larry Hynes Date: Fri Mar 24 00:54:05 2017 +0000 Editing of man/mhfixmsg.man. - 8bit -> 8-bit, nbit -> n-bit, except in flags and error msgs - Add nmh to .SH NAME - Formatting - use .B for -outfile - use .IR for mh-profile (5) - sort SEE ALSO programs Author: Larry Hynes Date: Thu Mar 23 22:52:46 2017 +0000 Editing of man/mhstore.man. - store -> stored - some formatting Author: Larry Hynes Date: Thu Mar 23 22:08:44 2017 +0000 Editing of man/mhshow.man. - Add some stray s's - Some formatting - Remove an \- object (I now pronounce \- as uh-unh; it's easier this way) - Use alternative instead of alternate Author: Larry Hynes Date: Thu Mar 23 21:07:49 2017 +0000 Editing of man/mhpath.man. - Add some commas - Some formatting - Delete empty .PP Author: Larry Hynes Date: Thu Mar 23 20:24:19 2017 +0000 Editing of man/mhparam.man. - Add some commas - Some formatting - Delete 'just' Author: Larry Hynes Date: Thu Mar 23 20:11:10 2017 +0000 Editing of man/mhmail.man. - Add reference to nmh in .SH NAME - Delete empty .PP - Remove a few 'various'es - Some formatting - SEE ALSO in alphabetical order Author: Larry Hynes Date: Thu Mar 23 18:12:46 2017 +0000 Editing of man/mhlist.man. - Make clear that -headers is the default - Some formatting Author: Larry Hynes Date: Thu Mar 23 17:31:12 2017 +0000 Editing of man/mhl.man. - Refer to environment variables (in text) without preceding $ - Don't put environment variables in bold (as per most other pages) - Some better formatting Author: Larry Hynes Date: Thu Mar 23 17:05:26 2017 +0000 Editing of man/mhical.man. - Don't use capitalised .SH, when uncapitalised .SS will do - Remove some early .SH/.SS to improve narrative - Delete superfluous .fi It could be argued that each of the (now) .SSs, which have been demoted from .SHs, are unnecessary or, at least, not in line with the other man pages . Demotion may suffice, for now. Author: Larry Hynes Date: Thu Mar 23 14:15:46 2017 +0000 Editing of man/mhbuild.man. - EDTIOR -> EDITOR - remove some \- things - formatting - use 8-bit, like 7-bit Author: Larry Hynes Date: Thu Mar 23 01:49:06 2017 +0000 Editing of man/mh-tailor.man. - Straighten up some formatting - Don't escape hyphens unecessarily - Pluralise message (so that outgoing messages...) Author: Larry Hynes Date: Thu Mar 23 01:29:20 2017 +0000 Editing of man/mh-sequence.man. - Don't escape hyphens unecessarily - Remove duplicate 'when' (when when) - Straighten up some formatting - Bring RFC reference into line (don't hyphenate) Author: Larry Hynes Date: Thu Mar 23 00:46:53 2017 +0000 Editing of man/mh-profile.man. - Clean up some formatting - Replace an .sp with a .PP - Remove a couple of empty .PPs and .REs - Make the good English, yes please Author: Larry Hynes Date: Wed Mar 22 22:57:13 2017 +0000 Editing of man/mh-mime.man. - Clean up .SH NAME to one line without .IR nmh (7) on it - Don't use escaped hyphens when not necessary - Clean up some formatting - Use 'Attach:' consistently (instead of 'Attach') Author: Larry Hynes Date: Tue Mar 21 22:56:39 2017 +0000 Editing of man/mh-mail.man. I think we can rise above ourselves, and delete 'antiquated'. Author: Larry Hynes Date: Tue Mar 21 22:35:50 2017 +0000 Editing of man/mh-folders.man. Author: Larry Hynes Date: Tue Mar 21 19:54:56 2017 +0000 Editing of man/mh-draft.man. Author: Larry Hynes Date: Tue Mar 21 01:48:34 2017 +0000 Editing of man/new.man. Author: Larry Hynes Date: Tue Mar 21 01:31:52 2017 +0000 Mention `nmh' in man-page NAME section for apropos(1). Author: Larry Hynes Date: Sun Mar 19 23:40:59 2017 +0000 Replace `maildrop' with `mail drop' in man pages. Author: Larry Hynes Date: Sun Mar 19 14:51:30 2017 +0000 Review inc.man. First cut at a cleanup of inc.man, including: maildrop -> mail drop; Ralph's mode/octal suggestion, with a change (by me) to refer to chmod(1). Author: David Levine Date: Sun Apr 2 09:26:17 2017 -0400 Attempt to fix test-ap on fbsd-10 build host. Author: David Levine Date: Sat Apr 1 18:53:26 2017 -0400 Check for sufficient room for multi-column character. Fix to commit 92128dacf8d5db02379e8f872dc50d31c6aaa55f. The sympton, reported by Valdis, was overrun of scan -width. Author: David Levine Date: Sat Mar 25 07:47:53 2017 -0400 Escaped repl, in case the user has it as a shell alias. Author: David Levine Date: Sat Mar 25 07:46:45 2017 -0400 Added etc/rmmproc.messageid. Author: Ralph Corderoy Date: Wed Mar 22 14:47:18 2017 +0000 Fix free(3) of unmalloc()'d string in whatnow's refile. `ref +foo' at comp(1)'s whatnow prompt was trying to free "+foo". Take a copy of the string so the later free works. Tom Rodman reported the problem to nmh-workers. Bug introduced in 3b6be5607a251a3a793e97382e251ce66ea2bca0. Author: Ralph Corderoy Date: Wed Mar 22 10:51:34 2017 +0000 Work around flex 2.6.3 bug by conditionally #undef yywrap. There's no sign on https://github.com/westes/flex/issues/162 that they will release a new flex with the fix soon. Author: Larry Hynes Date: Tue Mar 21 12:49:12 2017 -0400 Cleanup of .SH NAME sections. Author: Larry Hynes Date: Sat Mar 18 13:49:06 2017 +0000 Fixed forw.man to pass test-manpages. Author: David Levine Date: Sat Mar 18 16:53:15 2017 -0400 Added test case for commit 4318012376e06229307c0ed4f62a00faae9edc63. Author: David Levine Date: Sat Mar 18 09:49:31 2017 -0400 Don't let parse_mime() try to parse a directory. Author: Larry Hynes Date: Fri Mar 17 12:36:06 2017 -0400 Cleanup to forw(1) man page. Author: David Levine Date: Sun Feb 26 22:50:42 2017 -0500 Added /* FALLTHRU */ comments where gcc 7 noticed their need. And replaced similar comments to be consistent. Used that comment because it satisfies gcc -Wimplicit-fallthrough=4. Author: David Levine Date: Sun Feb 26 14:07:38 2017 -0500 Separate out backquote expression to please Heirloom shell. Author: David Levine Date: Sun Feb 26 13:41:34 2017 -0500 Tweaked to work with Heirloom shell. Shell parameter expansion ending in space needs it to be quoted. Author: David Levine Date: Tue Feb 21 10:31:57 2017 -0500 Echo CFLAGS in configure line, and only include if set. Author: Ken Hornstein Date: Sun Feb 19 17:05:12 2017 -0500 Change "servers" mts.conf entry to only support a single SMTP server. As part of this change, fix SMTP code so the chosen SMTP server is configured correctly for the netsec code. Author: David Levine Date: Sun Feb 19 14:05:25 2017 -0500 Reworked handling of multiple, space separated, smtp servers. Author: David Levine Date: Sun Feb 19 14:00:04 2017 -0500 Suppress getcanon exit status check. To allow tests to run when the local hostname doesn't resolve. Author: David Levine Date: Sun Feb 19 13:58:20 2017 -0500 Support mhparam -debug along with -all. Fix to commit 234c9cc4829d86589a079ace49cfa5bc251ef62c. Author: Ralph Corderoy Date: Sat Feb 18 14:47:56 2017 +0000 Limit mhparam's exit status to 120 missing components. Otherwise, 126 and 127 would clash with bash and zsh's use. Higher than 127 would look like signals. And 256 would wrap to a falsely succesful zero. Author: Ralph Corderoy Date: Tue Jan 17 12:54:02 2017 +0000 mhfixmsg: Use folder name to open second message of a sequence. `mhfixmsg foo' where foo was sequence of more than one message would sucessfully process the lowest numbered message of the sequence, but fail to open(2) the second one as the folder was missing from the path. For example, /home/ralph/mail/inbox/1 was used to open the first, but /home/ralph/mail/2 was attempted for the second. I guess this was because a static array was being trampled during the first's processing, though didn't try too hard to find where. Making a copy of it fixed the problem. Author: David Levine Date: Sat Jan 14 10:57:09 2017 -0500 Remove unused test file. Author: David Levine Date: Sat Jan 14 10:51:40 2017 -0500 Added delay for output file to be closed. Author: David Levine Date: Sat Jan 14 10:16:22 2017 -0500 Fixed references to --with-cyrus-sasl, and --without-, in comments. Author: Ken Hornstein Date: Wed Jan 11 21:37:52 2017 -0500 Make sure we always generate a Content-ID header for message/external-body entities, as required by RFC 2045. Author: David Levine Date: Wed Jan 11 21:32:20 2017 -0500 Fixed permissions on test script. Fix to commit 77fff244ad1bb1e746c78bedc87659400e2c6535. Author: David Levine Date: Wed Jan 11 20:53:41 2017 -0500 Rearranged check for whether to skip param value checks so that no files are left over. Update of commit 2cf4ff9dd2fba77c7f98bbd706b00d2e79a11a3b. Author: David Levine Date: Wed Jan 11 20:49:12 2017 -0500 Added valgrind suppressions for system libs on MacOS El Capitan. Author: David Levine Date: Sat Jan 7 18:54:40 2017 -0500 Fixed commit 60052b95778a065760a437859ee9b8a1cc4e39a9, wrong sense. Author: David Levine Date: Sat Jan 7 18:00:05 2017 -0500 Removed if ! bash-ism. Author: David Levine Date: Sat Jan 7 17:38:27 2017 -0500 Fixed a couple of tests to not fail when there is no text browser. Author: David Levine Date: Sat Jan 7 17:37:52 2017 -0500 Added missing AC_SUBST of AM_LDFLAGS. Author: Ralph Corderoy Date: Sat Dec 10 23:55:50 2016 +0000 crawl_context: Remove unused struct member `total'. It was maintained inconsistently, and checking what problems that caused showed it wasn't used. Author: Larry Hynes Date: Sun Jan 1 23:15:56 2017 +0000 Changes to folder.man Kill a couple of empty .PPs, resurrect a lost .SS, a little bit of slash and burn, stray whitespace, the usual. As far as I know, which is not far, the \- construct is only required for \-args, not, e.g., sub\-folder. I've changed instances of 'subfolder' to sub-folder. I've changed the 'the' in These folders are all preceded by the read-only... to 'any'. Author: Larry Hynes Date: Sat Dec 31 17:57:13 2016 +0000 Changes to install-mh.man Some more simple wordsmithing... Change instances of 'Install-mh' to 'install-mh', in line with other pages, switch to single `' around 'Mail', in line with other pages, option -> switch, clean up a little. Author: Larry Hynes Date: Sat Dec 31 15:57:42 2016 +0000 A cleanup, and possibly some controversy: I've replaced Rather than standard message skeleton with User message skeleton My thinking here is that a) we can do away with the kinda weird 'Rather than', b) I find the distinction between 'default' and 'standard' to be vague and c) it only appears in a few pages and is easily remedied. It turns up in comp(1) as "An alternative to the standard skeleton.", where 'standard' is used in the same way as 'default' is used in rcvdist(1), so I think it's worth settling on something 'better' and applying it consistently. My proposal is 'Default foo', for the foo in %nmhetcdir% and 'User foo' for the foo in the user's . Author: Larry Hynes Date: Sat Dec 31 15:54:55 2016 +0000 Fix skeletons in comp(1), forw(1) and dist(1) While I was here, I removed two 'empty' paragraphs (.PP) in forw(1). They may have been intended as line breaks, but I think they are unnecessary; feel free to overrule me! Aside: I would not be unhappy if, some day, 'skeleton' was replaced by something utilitarian like 'template'. Author: David Levine Date: Sat Dec 31 09:30:07 2016 -0500 Remove .w3m from test directory. Author: David Levine Date: Sat Dec 31 09:22:19 2016 -0500 Reverted commit 316068ee3b7105ea802c63b732ee4cfb584a2600. It was a repeat of commit 30a9c9b62fa92df289079080eb5ee57d2fda3951. Also, wrapped a few $MH_TEST_DIR with quotes. Author: Larry Hynes Date: Thu Dec 29 21:47:21 2016 -0500 Clean up, and change .SS case to Title Case, from UPPER, in line with other pages. Author: Larry Hynes Date: Fri Dec 23 16:29:36 2016 +0000 Changes to rcvpack.man Author: Ken Hornstein Date: Wed Dec 21 15:38:11 2016 -0500 Make the -fcc switch to repl actually work properly, and make sure that any Fcc header in a replied-to message is not carried over to the draft. Author: Larry Hynes Date: Wed Dec 21 16:58:51 2016 +0000 Changes to fmtdump.man Add a reference to fmttest(1), delete a superfluous 'the', delete the '...is simply...' line. Author: David Levine Date: Tue Dec 20 11:49:20 2016 -0500 Added check of -fcc with no fcc in components. Author: David Levine Date: Tue Dec 20 11:48:27 2016 -0500 Protect repl -file against dereference of null mp. Author: David Levine Date: Mon Dec 19 11:20:54 2016 -0500 Removed #ifdef FT_PAUSE protection. FT_PAUSE is unconditionally defined in h/fmt_compile.h. Author: David Levine Date: Mon Dec 19 11:18:38 2016 -0500 Removed unused references to FT_ADDTOSEQ. They were #ifdef LBL relics. Author: Larry Hynes Date: Mon Dec 19 01:17:10 2016 +0000 Changes to mh-format.man This is a beast, and we may not tame it at the first attempt. Mostly language simplification, some grammar and formatting, trailing whitespace, that sort of thing. There are one or two instances where I've taken (small) liberties with language, in favour of 'comprehension at first glance'. There are some commented lines hanging around in this. I've left them in, but I think they should go at the first opportunity. Author: David Levine Date: Mon Dec 19 11:11:27 2016 -0500 Removed obsolete comment about use of getcpy(). Author: Larry Hynes Date: Sat Dec 17 19:28:30 2016 +0000 Changes to dist.man Switch 'in place' for inplace, remove 'in truth of fact'. Author: Larry Hynes Date: Sat Dec 17 19:28:31 2016 +0000 Changes to flist.man Replace 'option' with 'switch' in a couple of places, correct (hopefully) a few sentences, restore '.SS "Multiple Folders" to its rightful place. Author: Larry Hynes Date: Fri Dec 16 22:55:39 2016 +0000 Changes to comp.man Remove the slightly legalistic 'in truth of fact', and bring the mention of man whatnow into the preceding sentence. The line 'If the draft already exists, comp will ask you as to the disposition of the draft.' makes no sense to me, and I'm struggling to make it make sense. If we put to one side the fact that I think it's a broken sentence, I still haven't managed to get comp to accept - or prompt me for - a 'replace' option when 'the draft already exists', so I'm afraid I have to admit defeat here and seek the wisdom of the elders. Author: Larry Hynes Date: Thu Dec 15 21:57:35 2016 +0000 Changes to burst.man I'm not sure how relevant burst(1) is these days, but here goes... Author: David Levine Date: Thu Dec 15 17:44:56 2016 -0500 Added clarifications to abbreviations. 1) N must be a positive number. 2) The + can be omitted. 3) As many of the N messages that exist. 4) Can also use - (or +) with first, prev, next, and last. Author: Larry Hynes Date: Thu Dec 15 18:33:15 2016 +0000 Changes to nmh.man This adds a reference to the 'COMMANDS' section, corrects - and hopefully simplifies - a couple of things, and tries to untangle the line beginning 'show displays...' in the seventh paragraph. The line 'The first, previous, next or last messages, if they exist.' doesn't seem to accurately cover the accompanying 'foo:N' listing in the following, or am I missing something? first:N prev:N next:N last:N The first, previous, next or last messages, if they exist. Author: Larry Hynes Date: Tue Dec 13 20:14:11 2016 +0000 Changes to ali.man The following is the beginning of an attempt to clean up the manual pages somewhat. grep tells me that 'switch' is used 193 times, whereas 'option' is only used 51 times, so I've tried to standardise on 'switch'. Author: David Levine Date: Tue Dec 13 16:06:38 2016 -0500 Fixed description of anno -list switch. As noted in commit 98c2e7d95bda262ef23e8f0838e5b86d08ed4e4f. If -text is used with -list, its argument is required but ignored. Author: Larry Hynes Date: Tue Dec 13 20:14:11 2016 +0000 Changes to anno.man. (Also noted that description of -list needs to be fixed, will do in next commit.) Author: Ralph Corderoy Date: Sat Dec 10 14:51:06 2016 +0000 showbuildenv: Add comment describing exit-status convention. It helps explain why some commands are `... || true' despite no `set -e' being in effect. Author: Ralph Corderoy Date: Sat Dec 10 14:48:19 2016 +0000 Revert "Test if the buildbots care about tools/showbuildenv's exit status." This reverts commit c92a4119fca5d677055dc616255a7d1efec9d750. They do care, showing "environment failed". Author: Ralph Corderoy Date: Sat Dec 10 14:46:04 2016 +0000 Rename recently added ToUpper() to to_upper(). Author: Ralph Corderoy Date: Sat Dec 10 14:45:00 2016 +0000 Rename recently added ToLower() to to_lower(). Author: Ralph Corderoy Date: Sat Dec 10 14:43:59 2016 +0000 Rename recently added TrimSuffixC() to trim_suffix_c(). Author: Ralph Corderoy Date: Sat Dec 10 14:42:47 2016 +0000 Rename recently added HasSuffixC() to has_suffix_c(). Author: Ralph Corderoy Date: Sat Dec 10 14:39:21 2016 +0000 Rename recently added HasSuffix() to has_suffix(). Author: Ralph Corderoy Date: Sat Dec 10 14:36:43 2016 +0000 Rename recently added HasPrefix() to has_prefix(). Sticking with local convention, as Ken requested. Author: Ralph Corderoy Date: Sat Dec 10 14:24:27 2016 +0000 Test if the buildbots care about tools/showbuildenv's exit status. Author: Ralph Corderoy Date: Sat Dec 10 14:19:43 2016 +0000 Document that adios() does not return. abort() ensures it won't. Discussion with David confirmed that adios()'s de facto contract with the caller is that it won't return. Document that, and add an abort(3) to ensure it won't occur. Better that than return and blunder on until a SEGV or corruption later. Author: Ralph Corderoy Date: Sat Dec 10 14:11:13 2016 +0000 mhlsbr.c: Don't hide mhladios and mhldone behind macros. Locally defined mhladios() and mhldone() were called as adios() and done() thanks to #defines that hid the widely-used functions with those names. Don't bother as it confuses the reader. Just call the local variations directly to make clear it's not the standard implementation. Author: David Levine Date: Fri Dec 9 09:34:59 2016 -0500 Generalized condition for support of parameter value tests. Author: David Levine Date: Thu Dec 8 21:04:52 2016 -0500 One last fix to test-charset. Author: David Levine Date: Thu Dec 8 20:53:36 2016 -0500 Fixed condition to enable skipping parameter value tests. Author: David Levine Date: Thu Dec 8 20:45:57 2016 -0500 And skip the other parameter value test on the FreeBSD10 buildbot. Author: David Levine Date: Thu Dec 8 20:18:14 2016 -0500 That didnt work, so skip Encoded parameter value test on that buildbot. Author: David Levine Date: Thu Dec 8 20:03:28 2016 -0500 Use locale that the FreeBSD10 buildbot has. It has EBCDIC-UK but not EBCDIC-US. Author: David Levine Date: Thu Dec 8 19:51:25 2016 -0500 Added temporary debug code. Author: David Levine Date: Thu Dec 8 19:37:40 2016 -0500 Try to fix Encoded parameter value test on FreeBSD10 buildbot. Author: David Levine Date: Thu Dec 8 16:27:40 2016 -0500 Replaced !iscntrl() with isprint(). To address Ralph's FIXME comment. One example where a byte would have been printed with !iscntrl() is 0x24 is ISO 646 BASIC (Inv), which is undefined. Also, added test cases to cover most of get_param_value(). Also, replaced a couple of other FIXME's with code comments. Author: David Levine Date: Mon Dec 5 11:50:40 2016 -0500 Fixed and restored commit 9a4b4a3d3b27fe4a7ff6d0b8724ce1c06b5917eb. Using AC_CHECK_MEMBERS instead of AC_CHECK_MEMBER. I don't know why the former works but the latter doesn't. Author: David Levine Date: Sun Dec 4 17:13:09 2016 -0500 Reverted commit 9a4b4a3d3b27fe4a7ff6d0b8724ce1c06b5917eb. It broke the build on the FreeBSD 10 buildbot, not sure why. Author: David Levine Date: Sun Dec 4 17:02:13 2016 -0500 Enabled detection of tm_gmtoff on _GNU_SOURCE platforms, e.g., Linux. By temporarily adding $AM_CPPFLAGS to CPPFLAGS. Author: David Levine Date: Sat Dec 3 12:03:53 2016 -0500 Added filename completion to bash_completion_nmh. Author: David Levine Date: Fri Nov 25 09:02:08 2016 -0500 Close temp file. Author: David Levine Date: Wed Nov 23 10:05:38 2016 -0500 Added flex 2.6.0 (with Fedora 25) output fixup. Author: David Levine Date: Sun Nov 20 14:25:11 2016 -0500 Open infile before fixing each message. Though the input file won't need to be opened if everything goes well, do it early just in case there's a failure, and that failure is running out of file descriptors. Author: Larry Hynes Date: Sun Nov 20 10:32:40 2016 -0500 Fix nmh man page so it shows correct name of profile. Author: Ralph Corderoy Date: Mon Nov 14 00:14:31 2016 +0000 mhstoresbr.c: Factor MIME-parameter-can-be-used-for-filename test. It was several lines repeated each time, and it saves having to check they're all identical. The original test pressed on if the MIME parameter's value was an empty string; preserve that as it's spotted later on. Author: Ralph Corderoy Date: Sun Nov 13 23:05:37 2016 +0000 Split a few more if-then statements into two lines to help gcov. It's interesting to see how often some of them have the then-branch taken. Author: David Levine Date: Sat Nov 19 10:37:06 2016 -0500 Open outfile before parsing message(s). So that we don't have to risk opening it after running out of fds. Author: David Levine Date: Sat Nov 19 10:28:08 2016 -0500 Added application/ics entries, and "file was generated" comment. application/ics is odd but does appear in the wild, and sometimes without a corresponding text/calendar part. Author: David Levine Date: Sat Nov 19 10:24:43 2016 -0500 Added mhshow-suffix-text entry. I don't know why it wasn't there already, it's in the mhshow man page. Author: David Levine Date: Sun Nov 13 19:40:53 2016 -0500 Tweaked to work with Heirloom shell. Author: David Levine Date: Sun Nov 13 17:56:44 2016 -0500 Removed bash-ism "function" declaration. Author: David Levine Date: Sun Nov 13 14:50:08 2016 -0500 Replaced docs/COMPLETION-BASH with etc/bash_completions_nmh. It's generated from man/mh-chart.man, which in turn is generated. Automake doesn't like generated files in docs, hence the move to etc. And the new filename better fits usage, I think. Did not provide support for completing message numbers. It can be fooled by programs that take multiple switches with + arguments. COMPLETION-BASH was broken with current bash, anyway. Also, removed sbr/sigmsg.h from CLEANFILES in Makefile.am. It was a leftover from commit 5776f9b783afe8e6bdbe430adb5d5b9435d25b19. Author: David Levine Date: Sun Nov 13 09:39:01 2016 -0500 Added copyright noticed. Author: David Levine Date: Sun Nov 13 09:38:24 2016 -0500 Removed unused declaration of output_message(). Author: Ralph Corderoy Date: Sun Nov 13 01:05:09 2016 +0000 Replace many add(s, NULL) with mh_xstrdup(s). Where s is known to be non-NULL. Author: Ralph Corderoy Date: Sat Nov 12 18:48:20 2016 +0000 Replace some add(FIELD, NULL) with mh_xstrdup(FIELD). The various FIELD are macros for string constants so can not be NULL. Author: Ralph Corderoy Date: Sat Nov 12 18:40:46 2016 +0000 m_getfld: Shuffle `delim' assignments slightly. Document end state of the four pointers to parts of the delimiter. fdelimlen can be, wrongly, one less without causing problems because a second check uses edelimlen. The only side effect is an extra iteration through m_getfld(). Author: Ralph Corderoy Date: Sat Nov 12 15:35:35 2016 +0000 Revert "m_getfld: Shorten fdelimlen by one; it was too long." This reverts commit 36a12f6a1a5a57799e48b23fd5ae47fe2351be68. I think it was right after all, but currently trying to get a test to fail with the faulty change. Author: Ralph Corderoy Date: Sat Nov 12 00:55:17 2016 +0000 Replace copy(s, d) with POSIX-1.2008's stpcpy(d, s). Author: Ralph Corderoy Date: Sat Nov 12 00:39:23 2016 +0000 m_getfld: Replace matchc() with memmem(3). libc is more likely to find one lump of memory inside another quicker than a home-grown quadratic emulation of the VAX's MATCHC instruction. memmem() isn't POSIX, but exists on Linux and FreeBSD. This will see if the buildbot is happy. Author: Ralph Corderoy Date: Sat Nov 12 00:31:36 2016 +0000 m_getfld: Remove never-true test in matchc(). Now the fdelimlen doesn't include the NUL it is never true. I didn't understand how it could ever be true but gcov on the test suite was showing 22e6 tests had three positives; that's what put me on to fdelimlen's overshoot. Author: Ralph Corderoy Date: Fri Nov 11 23:23:11 2016 +0000 m_getfld: Shorten fdelimlen by one; it was too long. The fdelimlen bytes starting at fdelim included a NUL at the end, e.g. 7 for "\nFrom \0". Other code seems not to expect this and has conditional bits to work around it, perhaps without understanding why. All the tests still pass, including with valgrind. Author: Ralph Corderoy Date: Fri Nov 11 21:25:39 2016 +0000 configure.ac: Add FIXME regarding _BSD_SOURCE for tm.tm_gmtoff test. Author: Ralph Corderoy Date: Fri Nov 11 00:38:29 2016 +0000 dlocaltime(): Only call tzset(3) once. This avoids the stat(2) of /etc/localtime per message scan if TZ isn't set in the environment; that's the default case on this Linux system. I can't see a way the TZ environment variable is likely to change between messages, or that it's intended an invocation of scan(1), say, copes with the timezone shifting underneath it by /etc/localtime being changed. Author: Ralph Corderoy Date: Thu Nov 10 22:44:59 2016 +0000 uip/scansbr.c: Use fputs(3) instead of mh_fputs(). I can't see any reason a local one exists. It loops, calling putc(3). The stdlib has the opportunity to be more efficient. Author: Ralph Corderoy Date: Thu Nov 10 21:39:40 2016 +0000 Add test-forw-coverage to improve uip/forw.c's coverage. Author: Ralph Corderoy Date: Wed Nov 9 04:50:01 2016 +0000 test-mhl-flags: Improve coverage of uip/mhlsbr.c. Author: Ralph Corderoy Date: Wed Nov 9 03:02:02 2016 +0000 test-fmtdump: Increase uip/fmtdump.c coverage. Author: Ralph Corderoy Date: Tue Nov 8 23:55:13 2016 +0000 test-flist: Increase coverage on argv[] processing. Author: Ralph Corderoy Date: Tue Nov 8 23:32:23 2016 +0000 Add test/format/test-ap to get 100% uip/ap.c coverage. Author: Ralph Corderoy Date: Thu Nov 3 10:23:31 2016 +0000 uip/dp.c: Increase coverage to 100%. Author: David Levine Date: Tue Nov 8 08:25:50 2016 -0500 Replaced add(s, NULL) with mh_xstrdup(s). Author: David Levine Date: Tue Nov 8 08:16:24 2016 -0500 Removed unused global from MIME parser. Author: David Levine Date: Mon Nov 7 21:01:31 2016 -0500 Initialize mhparse global for each message. Globals are evil. It's tricky to test, so no test was added. Just cleaned up test-mhfixmsg. Author: David Levine Date: Mon Nov 7 16:43:01 2016 -0500 Forgot to commit test-mhbuild. And thank Tom Lane for reporting bug. Update to commit 6c359ae82651d117af71c55ce1e56f3c5db18bfe. Author: David Levine Date: Mon Nov 7 16:28:14 2016 -0500 Don't parse parse # lines with mhbuild -nodirectives. Author: David Levine Date: Sun Nov 6 17:41:01 2016 -0500 Plugged remaining mhfixmsg(1) memory leaks. Author: David Levine Date: Sun Nov 6 17:39:13 2016 -0500 Made static char strings const. Author: David Levine Date: Sun Nov 6 16:48:40 2016 -0500 Plug memory leak with parameter continuations. Author: David Levine Date: Sun Nov 6 16:46:42 2016 -0500 Free c_ctparams for all content types, not just text. Author: Ralph Corderoy Date: Thu Nov 3 10:41:50 2016 +0000 uip/ap, uip/dp: Remove unneeded char **arguments. Author: Ralph Corderoy Date: Wed Nov 2 23:25:14 2016 +0000 dp: Fix write past end of dates[] array. Not spotted by valgrind because that doesn't check heap or stack arrays. Author: Ralph Corderoy Date: Thu Nov 3 10:36:30 2016 +0000 ap: Fix write past end of addrs[] array. Not spotted by valgrind because that doesn't check heap or stack arrays. Author: David Levine Date: Sat Nov 5 09:49:59 2016 -0400 Just show relevant portion of invalid encoded string. Author: David Levine Date: Sat Nov 5 09:46:17 2016 -0400 Replaced use of freects_done() with free_content() for each message. Thereby not holding on to open file descriptors until termination. Author: David Levine Date: Thu Nov 3 15:50:40 2016 -0400 Pass through message even if from relative folder. Author: David Levine Date: Thu Nov 3 08:52:53 2016 -0400 Use result, because (void) didn't prevent warning on FreeBSD 10. Author: Ralph Corderoy Date: Thu Nov 3 11:14:55 2016 +0000 test-rfc6532: Export LC_CTYPE after setting it. Updates commit 2c4ac164edefd18861595ec7624e5ad344b10198. Author: David Levine Date: Wed Nov 2 20:33:52 2016 -0400 Changed type of flags from signed to unsigned long. Author: David Levine Date: Wed Nov 2 20:24:32 2016 -0400 Replace non-ASCII characters in headers with ?'s with non-UTF8 locale. Author: David Levine Date: Wed Nov 2 20:08:27 2016 -0400 Fixed display of header field values with multibyte characters. Author: David Levine Date: Wed Nov 2 11:36:07 2016 -0400 Removed NMH_UNUSED(hostname) because it no longer exists. Author: Ken Hornstein Date: Wed Nov 2 10:45:16 2016 -0400 Add some Autoconf support for older OpenSSL libraries that don't support hostname verification. Author: Ralph Corderoy Date: Wed Nov 2 12:08:04 2016 +0000 State netsec_set_tls()'s noverify is unused if no TLS. Stops compiler warning. Author: Ken Hornstein Date: Tue Nov 1 23:30:34 2016 -0400 Update docs a bit. Author: Ken Hornstein Date: Tue Nov 1 23:13:04 2016 -0400 Add support for certificate verification when using TLS. Author: Ken Hornstein Date: Sun Oct 30 21:20:36 2016 -0400 Print out more TLS information if -snoop is turned on. Author: Ralph Corderoy Date: Tue Nov 1 17:49:08 2016 +0000 test/folder: Add test-coverage; lots of check_exit. Author: Ralph Corderoy Date: Tue Nov 1 17:03:14 2016 +0000 Split one-line condition+body to get gcov results. Author: Ralph Corderoy Date: Tue Nov 1 12:37:48 2016 +0000 uip/dist.c: Increase coverage. Author: Ralph Corderoy Date: Tue Nov 1 12:23:12 2016 +0000 uip/send: -saslmech lacking argument indexed outside array. Similar to problem in commit 171ad462ce7582196f91f93f91f99fc60a21189e. Author: Ralph Corderoy Date: Tue Nov 1 11:51:26 2016 +0000 man: Fix spelling mistakes. Author: Ralph Corderoy Date: Tue Nov 1 11:49:43 2016 +0000 Fix spelling mistake in comment. Only done because the same typo appears in the man pages. Author: Ralph Corderoy Date: Tue Nov 1 11:49:11 2016 +0000 Fix spelling mistakes in UI text. Author: Ralph Corderoy Date: Tue Nov 1 11:11:11 2016 +0000 test: Remove the " # gcov" comment from check_exit calls. Now the command is passed to check_exit, that is sufficient to indicate it's for coverage uses only, and a candidate to be fleshed out into a test that checks the output. Author: Ralph Corderoy Date: Tue Nov 1 00:41:58 2016 +0000 uip/comp.c: Increase coverage. Author: Ralph Corderoy Date: Tue Nov 1 00:17:47 2016 +0000 uip/burst.c: Increase coverage. Author: Ralph Corderoy Date: Tue Nov 1 00:08:02 2016 +0000 uip/anno.c: Increase coverage. Author: Ralph Corderoy Date: Tue Nov 1 00:05:42 2016 +0000 anno: Stop segmentation violation on `-number 0'. If atoi(3) returned zero, either because `0' was given or the number could not be parsed, then the error message dereferenced an invalid pointer. Found when trying to increase coverage with check_exit. Author: Ralph Corderoy Date: Mon Oct 31 23:13:02 2016 +0000 uip/ali.c: Increase coverage. Author: Ralph Corderoy Date: Mon Oct 31 18:36:19 2016 +0000 ali: Fix a memory leak spotted by valgrind. Author: Ralph Corderoy Date: Mon Oct 31 18:18:07 2016 +0000 mhbuild's fgetstr(): simplify source, logic untouched. The tests aren't getting 100% coverage and the nested assignments make it harder to see what's happening, and what needs to happen to gain coverage. Hoist invariants so it's clear they're such to the reader and not just the compiler. Author: David Levine Date: Mon Oct 31 19:01:36 2016 -0400 Remove test files that aren't removed by check(). Author: David Levine Date: Mon Oct 31 15:17:55 2016 -0400 Replaced BUFSIZ with NMH_BUFSIZ in a few places. This allows the test suite to succeed with BUFSIZ of 256. We should consider using different constants for different purposes. Author: David Levine Date: Mon Oct 31 15:03:07 2016 -0400 Don't set CT type if reformat failed. Author: Ralph Corderoy Date: Mon Oct 31 17:56:13 2016 +0000 Uncapitalise a few more mentions of commands in man pages. Author: Ralph Corderoy Date: Mon Oct 31 17:47:22 2016 +0000 mh-mkstemp.man: Detail exit status as 255 rather than -1. Since that's what the outside kernel and outside world sees. Author: Ralph Corderoy Date: Mon Oct 31 17:44:24 2016 +0000 Use new check_exit in `# gcov' tests. It showed up fmtdump wasn't being found because $? was 127, not 1. And mkstemp exits 255 on error, unusually amongst MH commands. Author: Ralph Corderoy Date: Mon Oct 31 17:18:11 2016 +0000 test/common.sh.in: Add test_exit() for $? checking. The stdout and stderr of the command being tested are saved but ignored, only regurgitated if the test fails. The test is stated as a fragment of a test(1) condition, e.g. '-eq 1'. This is mainly intended for the quick one-liners to increase gcov coverage and thus valgrind's scope. Over time, better tests that check more of the command's behaviour can replace these, keeping the coverage level. Author: David Levine Date: Mon Oct 31 11:39:11 2016 -0400 Replaced use of ! with || true, for ultimate Bourne shell compatiblity. Update to commit c3ba36f92bcbf44e071961f3d0bb5e6ddab317d6. Author: Ralph Corderoy Date: Sun Oct 30 21:45:22 2016 +0000 test-nocreate: Don't use run_test and run_prog together. valgrind tries to run run_prog and can't find the command. Author: Ralph Corderoy Date: Sun Oct 30 21:06:06 2016 +0000 fgets() reserves space for the NUL itself. No need to knock one off the buffer size when calling it as that suggests something special is going on. Author: Ralph Corderoy Date: Sun Oct 30 20:51:07 2016 +0000 Gain coverage with `mhparam localmbox'. Now 100% for uip/mhparam.c Author: Ralph Corderoy Date: Sun Oct 30 20:48:25 2016 +0000 Remove mhparam's p_find()'s ability to take NULL argument. It can't be passed NULL and couldn't get coverage. Author: Ralph Corderoy Date: Sun Oct 30 20:41:29 2016 +0000 Get coverage of quite a few of the `ambiguous switch' case. Typically by adding a `foo -', discarding stdout and stderr, and expecting it to exit non-zero. A `# gcov' comment states its purpose, and makes it easier to see if they can be deleted in time as other coverage tests improve. Author: Ralph Corderoy Date: Sun Oct 30 20:18:28 2016 +0000 Split gcov target into multiple sub-targets. Allows them to be run individually. Author: Ralph Corderoy Date: Sun Oct 30 15:55:30 2016 +0000 Clarify trunccpy()'s src and dest must not overlap. Author: Ralph Corderoy Date: Sun Oct 30 15:25:44 2016 +0000 Replace printf("%s", foo) with fputs(foo, stdout). Author: Ralph Corderoy Date: Sun Oct 30 15:09:55 2016 +0000 Replace strlen(foo) > 0 with *foo. Author: Ralph Corderoy Date: Sun Oct 30 15:07:41 2016 +0000 Add outputs from Makefile.am's gcov target. *.gcda, *.gcno, and *.gcov. Author: Ralph Corderoy Date: Sun Oct 30 15:04:38 2016 +0000 Remove sbr/peekc.c containing unused peekc(). gcov showed it wasn't getting any; we've all been there. It didn't check for EOF, nor that the ungetc(3) succeeded. Author: Ralph Corderoy Date: Sun Oct 30 14:46:01 2016 +0000 Replace fprintf(fp, "%s", foo) with fputs(foo, fp). Author: Ralph Corderoy Date: Sun Oct 30 14:44:07 2016 +0000 Replace printf("%s", foo) with fputs(foo, stdout). Author: Ralph Corderoy Date: Sun Oct 30 14:05:16 2016 +0000 Replace printf("%s\n", foo) with puts(foo). Author: Ralph Corderoy Date: Sun Oct 30 13:45:40 2016 +0000 Add trunccpy(), and the convenience TRUNCCPY(). truncpy copies at most size - 1 chars from non-NULL src to non-NULL dst, and ensures dst is NUL terminated. If size is zero then it aborts as dst cannot be NUL terminated. It's to be used when truncation is intended and correct, e.g. reporting a possibly very long external string back to the user. One of its advantages over strncpy(3) is it doesn't pad in the common case of no truncation. Author: Ralph Corderoy Date: Sun Oct 30 00:03:34 2016 +0100 Fix test-header-parsing test script. It was using sh's backticks that chomped the last linefeed! Add comment referencing the commit that fixed the code this is testing. Have fewer test cases, sticking to just one or two character headers with empty or one-character bodies. Avoids slowing the tests too much and the fixed bug was to do with hashing one-character headers. Author: Ralph Corderoy Date: Sat Oct 29 23:11:52 2016 +0100 Simplify folder_exists() to just testing stat(2)'s return value. Author: Ralph Corderoy Date: Fri Oct 28 23:51:41 2016 +0100 Replace printf("...\n") with puts("..."). Author: Ralph Corderoy Date: Fri Oct 28 23:10:55 2016 +0100 Replace v?fprintf(stdout, ...) with v?printf(...). Author: David Levine Date: Sat Oct 29 22:24:25 2016 -0400 Added (y|n) domain to a couple of build_nmh config prompts. Author: David Levine Date: Sat Oct 29 22:12:37 2016 -0400 Set first character of name[] buffer in BODY state. Fix to 47313b9bc395470311e383b57eb184c830662c4a to prevent uninitialized read, revealed by test/burst/test-burst-mime with NMH_VALGRIND=1. Author: David Levine Date: Wed Oct 26 19:08:53 2016 -0400 Removed configure options now that it determines them automatically. Author: David Levine Date: Wed Oct 26 11:38:45 2016 -0400 Moved build_nmh to top level directory. Author: David Levine Date: Wed Oct 26 11:31:49 2016 -0400 Reworked output handling. Author: David Levine Date: Tue Oct 25 12:10:51 2016 -0400 Reworked default SASL support to enable if header and lib are found. Author: David Levine Date: Tue Oct 25 11:35:20 2016 -0400 Added -r to gcov invocation. Author: David Levine Date: Tue Oct 25 11:10:01 2016 -0400 Add -O0 instead of -O2 to CFLAGS with build_nmh -d option. Author: David Levine Date: Tue Oct 25 11:05:54 2016 -0400 Don't add -D_FORTIFY_SOURCE to AM_CPPFLAGS with -O0. Merge: 7b27ac3 9cca3d0 Author: Ralph Corderoy Date: Tue Oct 25 00:23:49 2016 +0100 Merge branch 'master' of git.sv.gnu.org:/srv/git/nmh Author: Ralph Corderoy Date: Tue Oct 25 00:04:12 2016 +0100 Replace fputc() with putchar(). Author: David Levine Date: Mon Oct 24 19:01:14 2016 -0400 Changed build_nmh sasl and tls defaults to be configure's. Merge: e00c601 1e7b41c Author: Ralph Corderoy Date: Mon Oct 24 23:49:11 2016 +0100 Merge branch 'master' of git.sv.gnu.org:/srv/git/nmh Author: Ralph Corderoy Date: Mon Oct 24 23:37:50 2016 +0100 Replace putc() with putchar(). Author: Ralph Corderoy Date: Mon Oct 24 23:37:34 2016 +0100 Replace putc() with putchar(). Author: Ralph Corderoy Date: Mon Oct 24 23:36:52 2016 +0100 Replace putc() with putchar(). Others already existed. Not being a macro probably won't hurt. Author: David Levine Date: Mon Oct 24 18:31:27 2016 -0400 Removed unnecessary definition of tls_support. Author: Ralph Corderoy Date: Mon Oct 24 23:22:06 2016 +0100 Replace puts() with putchar(). Author: Ralph Corderoy Date: Mon Oct 24 23:21:57 2016 +0100 Replace puts() with putchar(). Author: David Levine Date: Mon Oct 24 18:07:48 2016 -0400 Reworked default TLS support to enable if header and libs are found. Also, fixed AC_CHECK_LIB for libssl. The crypto lib needs to be the fifth, not fourth, argument. Author: David Levine Date: Mon Oct 24 14:33:23 2016 -0400 Removed OAUTH support detection from because configure does it. Author: Ralph Corderoy Date: Mon Oct 24 19:11:07 2016 +0100 sbr/netsec.c: Add NMH_UNUSED(nsc) twice for if !TLS_SUPPORT. Author: Ralph Corderoy Date: Mon Oct 24 18:59:30 2016 +0100 netsec_set_tls(): Return a value in the !TLS_SUPPORT && !tls case. Silences clang. Author: David Levine Date: Mon Oct 24 12:58:04 2016 -0400 More enhancements to build_nmh. 1) Display failure messages that were hidden. 2) Display location of log file at end, if not in current directory, the build failed, or verbose was enabled. 3) Replaced use of showbuildenv with less invasive platform info. 4) Don't colorize tests summary if TERM is unset or dumb. Author: Ralph Corderoy Date: Mon Oct 24 16:34:17 2016 +0100 nmh.h: Add getline() prototype, conditional on HAVE_GETLINE. Author: Ralph Corderoy Date: Mon Oct 24 12:12:29 2016 +0100 Fix flex 2.6.1's output regarding signed/unsigned comparisons. Add comment referencing flex bug. Note this workaround breaks $(LFLAGS). Author: Ralph Corderoy Date: Mon Oct 24 12:12:09 2016 +0100 mhical.c: display(): Replace memcpy() with struct assignment. Author: Ralph Corderoy Date: Mon Oct 24 00:18:18 2016 +0100 fix_filename_param(): Remove redundant strlen(). Author: Ralph Corderoy Date: Mon Oct 24 00:15:33 2016 +0100 fix_filename_param(): Replace strncmp() with HasSuffix(). Author: Ralph Corderoy Date: Mon Oct 24 00:11:42 2016 +0100 sbr/utils.c: Add HasSuffix(s, suffix). HasSuffix returns true if non-NULL s ends with non-NULL suffix. Author: Ralph Corderoy Date: Mon Oct 24 00:03:48 2016 +0100 Use LEN() to save having to consider the -1. Author: Ralph Corderoy Date: Mon Oct 24 00:03:12 2016 +0100 Use LEN() to save having to consider the -1. Author: Ralph Corderoy Date: Mon Oct 24 00:02:33 2016 +0100 Use LEN() to save having to consider the -1. Author: Ralph Corderoy Date: Mon Oct 24 00:01:54 2016 +0100 Remove unused NCWD and NPWD #defines. Author: Ralph Corderoy Date: Sun Oct 23 23:45:34 2016 +0100 Use HasPrefix() instead of strncmp(). Author: Ralph Corderoy Date: Sun Oct 23 23:44:58 2016 +0100 Use HasPrefix() instead of strncmp(). Author: Ralph Corderoy Date: Sun Oct 23 23:44:38 2016 +0100 Use HasPrefix() instead of strncmp(). Author: Ralph Corderoy Date: Sun Oct 23 23:43:41 2016 +0100 Use HasPrefix() instead of strncmp(). Author: Ralph Corderoy Date: Sun Oct 23 23:43:19 2016 +0100 Use HasPrefix() instead of strncmp(). Author: Ralph Corderoy Date: Sun Oct 23 23:20:58 2016 +0100 Use HasPrefix() instead of strncmp(). Author: Ralph Corderoy Date: Sun Oct 23 23:20:45 2016 +0100 Use HasPrefix() instead of strncmp(). Author: Ralph Corderoy Date: Sun Oct 23 23:20:31 2016 +0100 Use HasPrefix() instead of strncmp(). Author: Ralph Corderoy Date: Sun Oct 23 23:02:49 2016 +0100 Use HasPrefix() instead of strncmp(). Author: Ralph Corderoy Date: Sun Oct 23 23:02:01 2016 +0100 Use HasPrefix() instead of strncmp(). Author: Ralph Corderoy Date: Sun Oct 23 22:59:57 2016 +0100 nmh_command_generator(): Fix indentation. Author: Ralph Corderoy Date: Sun Oct 23 22:51:24 2016 +0100 Use HasPrefix() instead of strncmp(). Author: Ralph Corderoy Date: Sun Oct 23 22:49:25 2016 +0100 Use HasPrefix() instead of strncmp(). Author: Ralph Corderoy Date: Sun Oct 23 22:48:49 2016 +0100 Use HasPrefix() instead of strncmp(). Author: Ralph Corderoy Date: Sun Oct 23 22:47:08 2016 +0100 Use HasPrefix() instead of strncmp(). Author: Ralph Corderoy Date: Sun Oct 23 22:36:26 2016 +0100 Use HasPrefix() instead of strncmp(). Author: Ralph Corderoy Date: Sun Oct 23 18:56:58 2016 +0100 Use HasPrefix() instead of strncmp(). Author: Ralph Corderoy Date: Sun Oct 23 18:56:33 2016 +0100 Use HasPrefix() instead of strncmp(). Author: Ralph Corderoy Date: Sun Oct 23 12:08:31 2016 +0100 Alter HasSuffixC()'s char * to be const. Author: Ralph Corderoy Date: Sun Oct 23 12:02:55 2016 +0100 utils.c: Add HasPrefix(s, prefix). HasPrefix returns true if non-NULL s starts with non-NULL prefix. Author: Ralph Corderoy Date: Sun Oct 23 01:18:49 2016 +0100 Rename EndsWithC() to HasSuffixC(). Author: Ralph Corderoy Date: Sun Oct 23 01:13:57 2016 +0100 mh-folders.man: Remove empty `.I' immediately followed by `.IR'. Author: Ralph Corderoy Date: Mon Oct 24 09:59:44 2016 +0100 build_nmh: If cloning with git, make a shallow clone. Author: Ralph Corderoy Date: Mon Oct 24 09:46:52 2016 +0100 showbuildenv: Drop lsb_release(1); /etc/lsb_release tested earlier. Author: Ralph Corderoy Date: Mon Oct 24 09:33:56 2016 +0100 build_nmh: Use `gzip -d' rather than assume tar has -z. Author: Ralph Corderoy Date: Mon Oct 24 09:31:00 2016 +0100 build_nmh: Have a silent curl still show errors. Arguably, -sS should be curl's defaults! Author: David Levine Date: Sun Oct 23 17:16:31 2016 -0400 Fixed output of commit hash by git log command. Author: David Levine Date: Sun Oct 23 17:12:04 2016 -0400 Check for existence of tools/showbuildenv. Author: David Levine Date: Sun Oct 23 16:25:00 2016 -0400 Redirect verbose build_nmh messages so they're visible while running. Author: David Levine Date: Sun Oct 23 16:03:11 2016 -0400 Enhanced build_nmh to support standalone use. 1) If not in nmh directory, download the nmh sources from savannah using git clone, wget, or curl. 2) Added -b branch option, for use when downloading. 3) Support -l -. 4) Capture build environment with tools/showbuildenv. Author: Ralph Corderoy Date: Sun Oct 23 01:10:58 2016 +0100 man: Use lowercase for command name at start of sentence. `Inc' is a different command to `inc'. Author: Ralph Corderoy Date: Sun Oct 23 00:08:17 2016 +0100 uprf(): Rewrite, using types rather than masking ints. Author: Ralph Corderoy Date: Sat Oct 22 23:37:19 2016 +0100 Add comment describing uprf(). Author: Ralph Corderoy Date: Sat Oct 22 19:56:52 2016 +0100 Use ToLower() instead of loop. Author: Ralph Corderoy Date: Sat Oct 22 19:53:01 2016 +0100 Use ToUpper() instead of loop. Author: Ralph Corderoy Date: Sat Oct 22 19:52:42 2016 +0100 Use ToUpper() instead of loop. Author: Ralph Corderoy Date: Sat Oct 22 19:43:12 2016 +0100 Add ToLower(s) and ToUpper(s). Author: Ralph Corderoy Date: Sat Oct 22 19:33:24 2016 +0100 putcomp(): Use local to avoid repeating tautological ternary. Author: Ralph Corderoy Date: Sat Oct 22 19:18:15 2016 +0100 Alter netrc permissions error message to match code. Add test. The code wants `go=', but the error message, and FAQ, said to clear read permission from group and other. Add test to inc/test-pop as that is the existing netrc test location, but it might be better in its own test file as other tests for netrc parsing could be added. Author: Ralph Corderoy Date: Sat Oct 22 18:09:02 2016 +0100 Fix netrc's token()'s bug if backslash escapes EOF. Discard the whole token so the user hopefully investigates. Author: Ralph Corderoy Date: Sat Oct 22 18:01:16 2016 +0100 Fix netrc's token() bug of first character being backslash. Author: Ralph Corderoy Date: Sat Oct 22 17:47:06 2016 +0100 Merge .netrc's token() file-reading loops; quoted and not. Check for ferror(3) as well as feof(3) on entry. Comment on lack of definition of quoted-string syntax, e.g. «"foo""bar"» is two tokens without needing a separator. Add comments on bugs for first non-quote character of a token being backslash, and if a backslash escapes EOF. Author: Ralph Corderoy Date: Sat Oct 22 16:17:42 2016 +0100 Have ruserpass() return TOK_EOF and put "" in the token table. Gives 0 a name and removes a little logic. Author: Ralph Corderoy Date: Sat Oct 22 16:04:58 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Sat Oct 22 15:53:51 2016 +0100 Check advertise()'s iob[] isn't too short with assert(3). Using DIM(a) added to h/mh.h Author: Ralph Corderoy Date: Sat Oct 22 15:36:40 2016 +0100 Use macros in advertise() to simplify source. Happens to remove strlen() of literals at the same time. Author: Ralph Corderoy Date: Sat Oct 22 14:43:11 2016 +0100 Document advise(), adios(), admonish(), and advertise(). It doesn't make their design any better. Their "ad" prefix goes against common advice of having distinguishable identifiers to avoid mix-ups, and seems to be a theme that got out of hand. The out-of-order parameters to advertise seem due to lack of strerror(3) that's no longer a problem. Before: advertise("open", "continuing...", "couldn't read profile: %s", path); Could be: error("couldn't read profile: %s: open: %s, continuing...\n", path, strerror(errno)); And the "open" is typically dropped as superfluous so there's a repetitive leading NULL passed a lot. Author: Ralph Corderoy Date: Sat Oct 22 13:58:43 2016 +0100 POSIX, 2016 Ed, removes bcopy(3). Stop referring to it. Even though it's in a comment, it shows up in searches. Author: Ralph Corderoy Date: Sat Oct 22 13:45:35 2016 +0100 Don't need to cast to `char *' for free(3) these days. Author: Ralph Corderoy Date: Sat Oct 22 13:45:24 2016 +0100 Don't need to cast to `char *' for free(3) these days. Author: Ralph Corderoy Date: Sat Oct 22 13:45:22 2016 +0100 Don't need to cast to `char *' for free(3) these days. Author: Ralph Corderoy Date: Sat Oct 22 13:45:19 2016 +0100 Don't need to cast to `char *' for free(3) these days. Author: Ralph Corderoy Date: Sat Oct 22 13:45:16 2016 +0100 Don't need to cast to `char *' for free(3) these days. Author: Ralph Corderoy Date: Sat Oct 22 13:45:11 2016 +0100 Don't need to cast to `char *' for free(3) these days. Author: Ralph Corderoy Date: Sat Oct 22 13:44:47 2016 +0100 Don't need to cast to `char *' for free(3) these days. But still need a cast to discard the const. Use `void *' as it saves needing to check the original type. Author: Ralph Corderoy Date: Sat Oct 22 13:42:52 2016 +0100 Don't need to cast to `char *' for free(3) these days. Author: Ralph Corderoy Date: Sat Oct 22 13:42:47 2016 +0100 Don't need to cast to `char *' for free(3) these days. Author: Ralph Corderoy Date: Sat Oct 22 13:42:45 2016 +0100 Don't need to cast to `char *' for free(3) these days. Author: Ralph Corderoy Date: Sat Oct 22 13:42:43 2016 +0100 Don't need to cast to `char *' for free(3) these days. Author: Ralph Corderoy Date: Sat Oct 22 13:42:39 2016 +0100 Don't need to cast to `char *' for free(3) these days. Author: Ralph Corderoy Date: Sat Oct 22 00:45:09 2016 +0100 Move smtp_init's last-ditch attempt for client inside first test. Didn't realise there was a second lot of similar code before the last commit. Author: Ralph Corderoy Date: Sat Oct 22 00:41:44 2016 +0100 Move smtp_init's last-ditch attempt for client inside first test. No point checking it twice in a row if it was false the first time. Author: Ralph Corderoy Date: Sat Oct 22 00:40:30 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Sat Oct 22 00:27:58 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Sat Oct 22 00:27:54 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Sat Oct 22 00:27:51 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Sat Oct 22 00:27:48 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Sat Oct 22 00:27:42 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Sat Oct 22 00:27:29 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Sat Oct 22 00:27:22 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Sat Oct 22 00:27:16 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Sat Oct 22 00:26:57 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Sat Oct 22 00:26:54 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Sat Oct 22 00:26:35 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Sat Oct 22 00:26:02 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Sat Oct 22 00:25:53 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Sat Oct 22 00:21:16 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Sat Oct 22 00:20:55 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Sat Oct 22 00:20:49 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Sat Oct 22 00:20:46 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Sat Oct 22 00:18:54 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Sat Oct 22 00:18:50 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Sat Oct 22 00:18:43 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Sat Oct 22 00:18:39 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Sat Oct 22 00:18:32 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Sat Oct 22 00:18:26 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Sat Oct 22 00:09:10 2016 +0100 Don't test boundary in output_content() for NULL; it never is. Author: Ralph Corderoy Date: Fri Oct 21 23:21:30 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Fri Oct 21 23:20:41 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Fri Oct 21 23:20:06 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Fri Oct 21 23:17:48 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Fri Oct 21 23:16:11 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Fri Oct 21 23:15:53 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Fri Oct 21 23:15:47 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Fri Oct 21 23:15:32 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Fri Oct 21 22:01:54 2016 +0100 Replace `if (p) free(p)' with `mh_xfree(p)'. Author: Ralph Corderoy Date: Fri Oct 21 21:18:38 2016 +0100 Add FIXME raising if iscntrl(3) test should be based on isprint(3) !iscntrl blocks characters that could be isspace or isblank whereas isprint would let them through unharmed. Author: Ralph Corderoy Date: Fri Oct 21 21:18:16 2016 +0100 Assume POSIX ctype.h; don't vet toupper()'s parameter. Author: Ralph Corderoy Date: Fri Oct 21 21:14:24 2016 +0100 Explain isascii() test more in netsec_set_sasl_params(). It stops non-ASCII lower in the SASL mechanism being uppered, just in case there is some. Author: Ralph Corderoy Date: Fri Oct 21 21:10:42 2016 +0100 Assume POSIX ctype.h; don't vet toupper()'s parameter. Author: Ralph Corderoy Date: Fri Oct 21 20:39:11 2016 +0100 Assume POSIX ctype.h; don't vet tolower()'s parameter. Author: Ralph Corderoy Date: Fri Oct 21 20:37:32 2016 +0100 Assume POSIX ctype.h; don't vet tolower()'s parameter. Author: Ralph Corderoy Date: Fri Oct 21 20:23:55 2016 +0100 Oops, stop showbuildenv reading from stdin when run from a TTY. David spotted the problem I introduced with 8374c3c. Alter offset to process any arguments, falling back to stdin if none. Author: Ralph Corderoy Date: Fri Oct 21 14:42:35 2016 +0100 Assume POSIX ctype.h; don't vet tolower()'s parameter. Author: Ralph Corderoy Date: Fri Oct 21 14:41:17 2016 +0100 Assume POSIX ctype.h; don't vet tolower()'s parameter. Author: Ralph Corderoy Date: Fri Oct 21 14:35:47 2016 +0100 Assume POSIX ctype.h; don't vet tolower()'s parameter. Author: David Levine Date: Fri Oct 21 13:26:43 2016 -0400 Fixed MIME parser so it can read binary content. Second of two-part fix. Replaced use of strlen(). Author: David Levine Date: Fri Oct 21 13:22:22 2016 -0400 Have m_getfld() pass back indication of missing blank line. This is part one of a two part fix to the MIME parser to read binary content. It should have no effect. Also added start/finish test calls to test-header. Author: Ralph Corderoy Date: Fri Oct 21 09:53:45 2016 +0100 Fix warnings caused by recent edits; don't mix declarations and code. Quite right too, I prefer all the declarations, codeless, up front. The standard -Wall didn't pick this up. David pointed it out, probably due to his defaults of `-pedantic -ansi'. Author: Ralph Corderoy Date: Fri Oct 21 00:06:11 2016 +0100 Don't `else' after goto. Simplify control flow. Author: Ralph Corderoy Date: Fri Oct 21 00:06:07 2016 +0100 Don't `else' after goto. Simplify control flow. Author: Ralph Corderoy Date: Fri Oct 21 00:05:50 2016 +0100 Don't `else' after goto. Simplify control flow. Author: Ralph Corderoy Date: Fri Oct 21 00:05:46 2016 +0100 Don't `else' after goto. Simplify control flow. Author: David Levine Date: Thu Oct 20 19:38:01 2016 -0400 Added test/mhshow/test-binary. The MIME parser doesn't properly handle null bytes because it uses getline(). Author: Ralph Corderoy Date: Thu Oct 20 23:57:56 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:57:09 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:30:39 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:30:07 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:30:02 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:29:56 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:29:49 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:29:46 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:29:35 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:29:19 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:27:42 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:27:37 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:27:21 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:27:08 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:27:05 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:23:46 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:23:41 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:23:38 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:23:35 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:23:28 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:23:00 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:22:21 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:22:15 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:22:11 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:22:04 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:22:00 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:21:45 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:21:34 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:21:05 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:20:25 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:20:20 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:20:17 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:20:07 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:19:59 2016 +0100 Don't `else' after return or goto. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:19:28 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:18:47 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:16:32 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:16:21 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 23:15:53 2016 +0100 Don't `else' after return. Simplify control flow. Author: Ralph Corderoy Date: Thu Oct 20 00:43:52 2016 +0100 Hoist test of search string for NULL out of loop. Author: Ken Hornstein Date: Thu Oct 20 13:37:29 2016 -0400 Rototill credentials code so that we only prompt for the username and password when it is necessary. Author: David Levine Date: Wed Oct 19 19:53:42 2016 -0400 Added locale profile component, value is passed to nmh_init(). Author: David Levine Date: Wed Oct 19 15:00:56 2016 -0400 Pass CFLAGS to make distcheck via DISTCHECK_CONFIGURE_FLAGS. Author: Ralph Corderoy Date: Thu Oct 20 00:32:37 2016 +0100 Replace sizeof string constant - 1 with LEN(). Author: Ralph Corderoy Date: Thu Oct 20 00:32:30 2016 +0100 Replace sizeof string constant - 1 with LEN(). Author: Ralph Corderoy Date: Thu Oct 20 00:24:20 2016 +0100 Replace strlen(), malloc(), and sprintf() with concat(). Author: Ralph Corderoy Date: Thu Oct 20 00:09:47 2016 +0100 Use LEN() on string constants instead of strlen(). Author: Ralph Corderoy Date: Thu Oct 20 00:09:47 2016 +0100 Use LEN() on string constants instead of strlen(). Author: Ralph Corderoy Date: Thu Oct 20 00:09:47 2016 +0100 Use LEN() on string constants instead of strlen(). Author: Ralph Corderoy Date: Thu Oct 20 00:08:50 2016 +0100 Add LEN(s) definition. LEN gives the strlen() of string constant s, excluding the terminating NUL. Author: Ralph Corderoy Date: Thu Oct 20 00:02:14 2016 +0100 Put, rather than print, single characters. Author: Ralph Corderoy Date: Thu Oct 20 00:02:14 2016 +0100 Put, rather than print, single characters. Author: Ralph Corderoy Date: Thu Oct 20 00:02:14 2016 +0100 Put, rather than print, single characters. Author: Ralph Corderoy Date: Thu Oct 20 00:02:14 2016 +0100 Put, rather than print, single characters. Author: Ralph Corderoy Date: Thu Oct 20 00:02:14 2016 +0100 Put, rather than print, single characters. Author: Ralph Corderoy Date: Thu Oct 20 00:02:14 2016 +0100 Put, rather than print, single characters. Author: Ralph Corderoy Date: Thu Oct 20 00:02:14 2016 +0100 Put, rather than print, single characters. Author: Ralph Corderoy Date: Thu Oct 20 00:02:14 2016 +0100 Put, rather than print, single characters. Author: Ralph Corderoy Date: Thu Oct 20 00:02:14 2016 +0100 Put, rather than print, single characters. Author: Ralph Corderoy Date: Wed Oct 19 23:38:04 2016 +0100 Put, rather than print, single characters. Author: Ralph Corderoy Date: Wed Oct 19 23:38:04 2016 +0100 Put, rather than print, single characters. Author: Ralph Corderoy Date: Wed Oct 19 23:38:04 2016 +0100 Put, rather than print, single characters. Author: Ralph Corderoy Date: Wed Oct 19 23:27:13 2016 +0100 Replace `(char *)0' et al with `NULL'. None of them are vararg parameters. Author: Ralph Corderoy Date: Wed Oct 19 23:27:13 2016 +0100 Replace `(char *)0' et al with `NULL'. None of them are vararg parameters. Author: Ralph Corderoy Date: Wed Oct 19 23:27:13 2016 +0100 Replace `(char *)0' et al with `NULL'. None of them are vararg parameters. Author: Ralph Corderoy Date: Wed Oct 19 23:27:13 2016 +0100 Replace `(char *)0' et al with `NULL'. None of them are vararg parameters. Author: Ralph Corderoy Date: Wed Oct 19 23:27:13 2016 +0100 Replace `(char *)0' et al with `NULL'. None of them are vararg parameters. Author: Ralph Corderoy Date: Wed Oct 19 23:27:12 2016 +0100 Replace `(char *)0' et al with `NULL'. None of them are vararg parameters. Author: Ralph Corderoy Date: Wed Oct 19 23:27:12 2016 +0100 Replace `(char *)0' et al with `NULL'. None of them are vararg parameters. Author: Ralph Corderoy Date: Wed Oct 19 23:27:12 2016 +0100 Replace `(char *)0' et al with `NULL'. None of them are vararg parameters. Author: Ralph Corderoy Date: Wed Oct 19 23:27:12 2016 +0100 Replace `(char *)0' et al with `NULL'. None of them are vararg parameters. Author: Ralph Corderoy Date: Wed Oct 19 23:27:12 2016 +0100 Replace `(char *)0' et al with `NULL'. None of them are vararg parameters. Author: Ralph Corderoy Date: Wed Oct 19 23:27:12 2016 +0100 Replace `(char *)0' et al with `NULL'. None of them are vararg parameters. Author: Ralph Corderoy Date: Wed Oct 19 23:27:12 2016 +0100 Replace `(char *)0' et al with `NULL'. None of them are vararg parameters. Author: Ralph Corderoy Date: Wed Oct 19 23:27:12 2016 +0100 Replace `(char *)0' et al with `NULL'. None of them are vararg parameters. Author: Ralph Corderoy Date: Wed Oct 19 23:27:12 2016 +0100 Replace `(char *)0' et al with `NULL'. None of them are vararg parameters. Author: Ralph Corderoy Date: Wed Oct 19 23:27:12 2016 +0100 Replace `(char *)0' et al with `NULL'. None of them are vararg parameters. Author: Ralph Corderoy Date: Wed Oct 19 19:18:48 2016 +0100 Replace strlen(), malloc(), and sprintf() with concat(). Author: Ralph Corderoy Date: Wed Oct 19 18:47:30 2016 +0100 Replace sprintf() with strcpy(); it's no worse. Author: Ralph Corderoy Date: Wed Oct 19 18:47:04 2016 +0100 Replace sprintf() with strcpy(); it's no worse. Author: Ralph Corderoy Date: Wed Oct 19 18:44:58 2016 +0100 Add comment describing concat(). Author: Ralph Corderoy Date: Wed Oct 19 18:30:41 2016 +0100 Use the imperfect snprintf(3) instead of sprintf(3). Author: Ralph Corderoy Date: Wed Oct 19 18:29:56 2016 +0100 Use the imperfect snprintf(3) instead of sprintf(3). Author: Ralph Corderoy Date: Wed Oct 19 18:29:43 2016 +0100 Use the imperfect snprintf(3) instead of sprintf(3). Author: Ralph Corderoy Date: Wed Oct 19 18:29:18 2016 +0100 Use the imperfect snprintf(3) instead of sprintf(3). Author: Ralph Corderoy Date: Wed Oct 19 18:13:10 2016 +0100 Add EndsWithC(char *s, int c) and call it in some initial places. EndsWithC returns true if non-NULL string s ends with a c before the terminating NUL. Author: Ralph Corderoy Date: Wed Oct 19 17:52:44 2016 +0100 Add stdbool.h plus fallback to h/nmh.h. Change h/mh.h's FALSE and TRUE to use stdbool.h's. In time, everything can switch over and FALSE and TRUE can go. Delete some local re-definitions of FALSE and TRUE. Author: Ralph Corderoy Date: Wed Oct 19 16:34:05 2016 +0100 Fix ruserpass() to not assume `\n' present before trimming. Author: David Levine Date: Wed Oct 19 12:09:37 2016 -0400 Removed remaining relics of generated ctypoe-checked.[hc]. Author: Ralph Corderoy Date: Wed Oct 19 15:43:12 2016 +0100 Alter ctype-checked to handle EOF and be hand-written. Along the way, replace the code generation with code that punts the work onto the stdlib's C functions, needing only a single `identity' array for all the macros. A mkdir needed to be added in Makefile.am because otherwise etc didn't exist in a distcheck and attempting to redirect stdout to a file in etc failed. I'm not happy that's the best automake way to achieve this, i.e. what if another rule attempts to create in etc first? Author: Ralph Corderoy Date: Wed Oct 19 14:39:53 2016 +0100 Remove ./configure's --enable-debug support; it did nothing. David on nmh-workers said "that looks like a relic that can be removed". Author: Ralph Corderoy Date: Wed Oct 19 13:04:12 2016 +0100 Don't recurse in advertise() on writev(2) error, just write(2). Some errors, e.g. EPIPE, cause the advise()'s call to another advertise() to fail again, ad segvinitum when stack busts. Instead, snprintf(3) and write(2) that single string, ignoring any error. Author: Ralph Corderoy Date: Wed Oct 19 12:22:47 2016 +0100 Add check-programs target to Makefile.am to add to `make all'. Author: Ralph Corderoy Date: Wed Oct 19 11:30:55 2016 +0100 Ignore etags ugly TAGS output file. Makefile prefers etags over ctags. Author: Ralph Corderoy Date: Wed Oct 19 10:09:47 2016 +0100 Replace strchr() condition with TrimSuffixC(), fixing assumptions. A couple of the existing strchr()-based trims assumed fgets() returned a string containing `\n' if it didn't return NULL. Author: Ralph Corderoy Date: Wed Oct 19 10:06:44 2016 +0100 Replace strchr() condition with TrimSuffixC(). Author: Ralph Corderoy Date: Wed Oct 19 10:06:24 2016 +0100 Replace strchr() condition with TrimSuffixC(). Author: Ralph Corderoy Date: Wed Oct 19 10:04:59 2016 +0100 Replace strchr() condition with TrimSuffixC(). Author: Ralph Corderoy Date: Wed Oct 19 10:04:12 2016 +0100 Replace strchr() condition with TrimSuffixC(). Author: Ralph Corderoy Date: Wed Oct 19 10:03:31 2016 +0100 Replace strchr() condition with TrimSuffixC(). Author: Ralph Corderoy Date: Wed Oct 19 00:50:28 2016 +0100 Replace strchr() condition with TrimSuffixC(). Author: Ralph Corderoy Date: Tue Oct 18 17:05:24 2016 +0100 Add TrimSuffixC(char *s, int c). TrimSuffixC deletes c from the end of non-NULL string s if it's present, shortening s by 1. Only one instance of c is removed. Author: David Levine Date: Tue Oct 18 19:55:49 2016 -0400 With EAI (mhbuild -headerencoding utf-8), force message header to show 8-bit UTF-8, even if the message body is ASCII. Author: David Levine Date: Tue Oct 18 16:45:30 2016 -0400 Output an error message from post(8) when user specifies mhbuild -headerencoding utf-8 but the SMTP server doesn't support SMTPUTF8. Author: Ralph Corderoy Date: Tue Oct 18 16:33:12 2016 +0100 Rewrite r1bindex() using strrchr(3). Author: Ralph Corderoy Date: Tue Oct 18 16:23:44 2016 +0100 Use concat() in m_putenv. Add FIXME about memory leaks. POSIX defines setenv(3) and unsetenv(3). They seem like a good route, just need to preserve the existing functions' behaviour. Author: Ralph Corderoy Date: Tue Oct 18 16:22:41 2016 +0100 Shrink the static char[] for "%d" from 8KiB to just right. Author: Ralph Corderoy Date: Tue Oct 18 14:52:26 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:26 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:26 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:26 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:26 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:26 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:26 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:26 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:26 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:26 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:26 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:26 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:26 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:26 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:25 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:25 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:25 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:25 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:25 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:25 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:25 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:25 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:25 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:25 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:25 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:25 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:25 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:25 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:25 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:25 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:25 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:25 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:25 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 14:52:25 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 13:37:15 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 13:37:15 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 13:37:14 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 13:37:14 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 13:37:14 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 13:37:14 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 13:37:14 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 13:37:14 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 13:37:14 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 13:37:14 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 13:37:14 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 13:37:14 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 13:37:14 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 13:09:27 2016 +0100 Replace getcpy() with mh_xstrdup() where the string isn't NULL. Author: Ralph Corderoy Date: Tue Oct 18 01:27:27 2016 +0100 Fix unlikely bug in oauth's make_query_url() of base_url overflow. Author: Ralph Corderoy Date: Tue Oct 18 01:18:24 2016 +0100 Replace a few calculations of string lengths with concat(). Saves the reader have to keep checking all the +1 are correct. Passed the oauth tests; they weren't skipped. Author: Ralph Corderoy Date: Mon Oct 17 23:52:00 2016 +0100 Close FILE pointer in anno for -append as well as -delete. https://savannah.nongnu.org/bugs/?23465 has Peter Maydell pointing out the assymetric open and close of a FILE pointer. He's right on that AFAICS so change the test to be for a non-NULL pointer rather than the more wordy and prone to error flag-testing. Author: Ralph Corderoy Date: Mon Oct 17 21:46:47 2016 +0100 Oops, should have offset file in showbuildenv rather than cat. Author: Ralph Corderoy Date: Mon Oct 17 21:16:38 2016 +0100 Look for a platform-specific /etc/*-release or similar. /etc/os-release is becoming standard due to systemd. Author: Ralph Corderoy Date: Mon Oct 17 20:51:09 2016 +0100 Protect showbuildenv's headers from glob expansion. Author: Ralph Corderoy Date: Mon Oct 17 20:35:51 2016 +0100 A-ha! automake has support for tests expected to fail; use that. Backing out my recent addition of an `expectedfail` parameter to the `check' function. Author: Ralph Corderoy Date: Mon Oct 17 20:14:33 2016 +0100 Remove use of C's register keyword. Author: David Levine Date: Mon Oct 17 09:42:32 2016 -0400 Added reference to mh-profile(5) man page for more information on postproc. And note that "Nmh-" header lines are filtered out. Author: Ralph Corderoy Date: Mon Oct 17 11:55:12 2016 +0100 Add FIXME for more documentation to showbuildenv. Author: Ralph Corderoy Date: Mon Oct 17 11:51:32 2016 +0100 Have showbuildenv only indent non-blank lines. Author: Ralph Corderoy Date: Mon Oct 17 11:50:22 2016 +0100 Run lsb_release(1) if uname is Linux. Author: Ralph Corderoy Date: Mon Oct 17 11:30:24 2016 +0100 Oops, fc31cece had a syntax error that gcc ignored, clang doesn't. Two logical-or operators in a row don't upset gcc. Who said parsing was a solved problem? Author: Ralph Corderoy Date: Mon Oct 17 01:41:32 2016 +0100 Replace NEW() then memset() of 0 with NEW0(). Author: Ralph Corderoy Date: Mon Oct 17 01:36:35 2016 +0100 Don't call strlen() twice; save result. The second instance was attempting to write strlen(mmdlm2) bytes and checking the return value against strlen(mmdlm1). I assumed that was an error without digging. Author: Ralph Corderoy Date: Mon Oct 17 01:35:15 2016 +0100 Don't call strlen() twice; save result. Author: Ralph Corderoy Date: Mon Oct 17 01:34:18 2016 +0100 Deference char pointer to test for empty string instead of strlen(3). Author: Ralph Corderoy Date: Mon Oct 17 01:28:53 2016 +0100 Replace getcpy() with mh_xstrdup(). Author: Ralph Corderoy Date: Mon Oct 17 01:28:13 2016 +0100 Replace mh_xmalloc() with mh_xstrdup(). Author: Ralph Corderoy Date: Mon Oct 17 01:26:53 2016 +0100 Replace mh_xmalloc() with mh_xstrdup(). Author: Ralph Corderoy Date: Mon Oct 17 00:32:46 2016 +0100 Delete client_getcpy(); don't know why it exists. Replace with calls to getcpy() or mh_xstrdup(). Author: Ralph Corderoy Date: Mon Oct 17 00:22:23 2016 +0100 Use mh_xstrdup() instead of getcpy() for a string constant. It cannot be NULL. Author: Ralph Corderoy Date: Mon Oct 17 00:08:26 2016 +0100 Rewrite getcpy() using mh_x*() allocation functions. Author: Ralph Corderoy Date: Mon Oct 17 00:07:24 2016 +0100 Add const specifier to mh_xstrdup()'s src parameter. Author: Ralph Corderoy Date: Sun Oct 16 23:35:35 2016 +0100 Rename fmt_compile.c's NEW macro to NEW_FP to avoid redefine. It grabs and fills in a pointer called `fp' so a more specific name seems OK. Author: Ralph Corderoy Date: Sun Oct 16 23:16:26 2016 +0100 Rename local enum to avoid clashing with NEW() macro. Even if it doesn't in practice due to the lack of parenthesis, it makes things more clean if all the enumerates have a common abbreviation prefix. Author: Ralph Corderoy Date: Sun Oct 16 22:53:23 2016 +0100 Add mh_xstrdup() that exits on allocation failure. Call it from a few simple places. Author: Ralph Corderoy Date: Sun Oct 16 19:38:36 2016 +0100 Add NEW(p) that sets p to mh_xmalloc'd memory sized by *p. Use it for the simple cases. Again, saves having to check the same identifier is given, possibly far apart after a superfluous cast. Author: Ralph Corderoy Date: Sun Oct 16 18:49:32 2016 +0100 Add macro NEW0(p) that callocs, and use it in simple calls. p is a pointer, the size of the contents of the pointer is allocated with calloc via mh_xcalloc. It saves having to check every calloc to ensure the space requested matches the pointer to which it is assigned. Author: Ralph Corderoy Date: Sun Oct 16 18:24:51 2016 +0100 Put parameter names in h/utils.h memory function prototypes. It can be a problem if there is a system creeps in a clashing macro, e.g. `size', but that's unlikely and I think the documentation benefits. Author: Ralph Corderoy Date: Sun Oct 16 18:21:15 2016 +0100 Add mh_xfree(), guarding free(3) from NULLs. Perhaps all nmh's platforms cope with free(3) these days, but it gives symmetry with the other mh_x* memory functions and if there is code testing the pointer before calling free then it can use this instead. Author: Ralph Corderoy Date: Sun Oct 16 18:17:31 2016 +0100 Tweak mh_xcalloc(); print size on error, follow POSIX. Using `%zu' for the size_t value. That might be a problem on older platforms, but we'll see. If asked for zero bytes then allocate one to get a unique pointer. Author: Ralph Corderoy Date: Sun Oct 16 18:08:29 2016 +0100 Tweak mh_xrealloc(); print size on error, follow POSIX. Using `%zu' for the size_t value. That might be a problem on older platforms, but we'll see. If asked for zero bytes then free an existing pointer, only passing it to free(3) if it's non-NULL, and then allocate a byte so a unique pointer is returned. Author: Ralph Corderoy Date: Sun Oct 16 17:43:56 2016 +0100 Tweak mh_xmalloc(); print size in error, allocate zero bytes. Using `%zu' for the size_t value. That might be a problem on older platforms, but we'll see. If asked for zero bytes then allocate one rather than exit; it's sometimes useful to allocate zero, but some older platforms might not like it. Author: Ralph Corderoy Date: Sun Oct 16 17:36:03 2016 +0100 Don't check mh_xcalloc() and friends for a NULL return. They never return NULL. That's their prime purpose. Author: Ralph Corderoy Date: Sun Oct 16 15:50:12 2016 +0100 Expand the test of scan's -forma; fails on first attempt. For an email that's just `a:\nb:\nc:\n', a scan with `%{a}\n%{b}\n%{c}' is one blank line short. If the `%{c}' has anything added then its line prints. Break out of the loop so all the other tests are skipped. Author: Ralph Corderoy Date: Sun Oct 16 15:25:37 2016 +0100 Don't test -reverse's boolean on every message number. Test just once before the loop and define start, end, and increment. Keep going whilst start is not end. Happy for underflow or overflow in calculating end because msgnum will make the same transition. It can't affect whether the loop runs at all since 0 is not a valid message number. Author: Ralph Corderoy Date: Sun Oct 16 14:28:38 2016 +0100 Update pending-release-notes with a couple of my recent fixes. Author: Ralph Corderoy Date: Sun Oct 16 14:19:56 2016 +0100 Fix bug where single-character headers were sometimes missed. The hash function used to check if a header was of interest always used its first three characters. For a single-character header that third byte wasn't particularly set and so it was pot luck if the two hashes matched, swayed by what was previously in the format string and in the email's headers. Alter it to cope, including with an empty string. Comment that it never gives 127 so leaves the last element of the hash-table array unused. Alter test-header-parsing to stop declaring it expects to fail. Author: Ralph Corderoy Date: Sun Oct 16 12:44:32 2016 +0100 Change all Getc() callers to use EOF, not comparisons with 0. Makes the logic that bit easier when you don't have to convert to EOF mentally. No functional change intended. Author: Ralph Corderoy Date: Sun Oct 16 12:23:57 2016 +0100 Don't increment bytes_read if returning EOF. Don't know if this was actually causing a problem, or if it was wrong, but bytes_read was always being incremented even if the later test showed readpos was to be left unincremented and EOF returned instead. All tests still pass so any breakage must be subtle! Author: Ralph Corderoy Date: Sun Oct 16 12:13:59 2016 +0100 Fix spelling in comment. Alter case to match identifier. vim will search matching case on `*', for example, so if searching for `\' the comment shouldn't use `Fdelim'. Author: Ralph Corderoy Date: Sun Oct 16 11:43:45 2016 +0100 Add failing test case for single-character header parsing. `scan -format '%{x}'' fails to find single-character header `x' in some cases, depending on the position of the header in the file. Add a simple test case, scan/test-header-parsing, for this that fails. Alter the test harness to allow a test to indicate it expects to fail. When it does, that's ignored. If it passes, that's then an error instead. Did this because I don't know if or when it will be fixed and didn't want it to be forgotten in the meantime. When it is fixed, the test can be enhanced to cover many more possibilities. First noticed it with ad hoc testing of my fewer-lseek change, but it is present in the released 1.6. Author: Ralph Corderoy Date: Sun Oct 16 10:52:39 2016 +0100 Fix spelling in warning message; s/conext/context/. Author: Ralph Corderoy Date: Sun Oct 16 10:13:46 2016 +0100 Simply enter_getfld()'s structure, no functional change. Return ASAP to avoid having to mentally track those states as the code indents further. Author: Ralph Corderoy Date: Sun Oct 16 09:58:34 2016 +0100 Explicitly state a postproc's last argument will be the draft. Update the sample postproc script to make clear it's the -whom detection that sucks. Author: Ralph Corderoy Date: Sun Oct 16 09:35:03 2016 +0100 Document fmttest(1)'s existing -help and -version options. Author: Ralph Corderoy Date: Sun Oct 16 09:17:51 2016 +0100 Move -help and -version to the front of the man page options. The man pages had -verbose and -help listed at the end of the synopsis. This put them after mandatory arguments in some cases, e.g. post(8). Put then at the front, swapping the order so -help is first, as novices will want to know -help exists early on, and others can simply skip over them rather than encounter them at the end when they're trying to track the combinations of what they've read so far. Author: Ralph Corderoy Date: Sun Oct 16 08:52:10 2016 +0100 Fix end of sentence spacing in man pages, and related problems. troff(1) input that ends a sentence at the end of the line gets the proper inter-sentence spacing when formatted. If the sentence ends midline then two spaces must follow to get the same result, otherwise the spacing looks odd. Similarly, if a full stop is not the end of a sentence then it should have the zero-width escape appended so if re-formatting the source happens to place it at the end of the line then no large gap follows it: e.g. `e.g.\&'. Replace `et. al.' with `et al'. Author: Ralph Corderoy Date: Sun Oct 16 08:34:35 2016 +0100 Reference the buildbot in docs/README.developers. Author: Ralph Corderoy Date: Sun Oct 16 08:23:51 2016 +0100 Stop one lseek(2) per header fetched by m_getfld.c in common case. Only call ftello(3) in enter_getfld() when track_filepos has been requested; not often. Author: Ralph Corderoy Date: Sat Oct 15 23:40:00 2016 +0100 Fix error message when attempting to xmh_realloc() 0 bytes. Though really, I'd expect it to perform a free(3) then, as the real realloc(3) does. Author: David Levine Date: Sat Oct 15 14:21:13 2016 -0400 Plugged memory leak in convert_content_charset(). Author: David Levine Date: Sat Oct 15 11:53:24 2016 -0400 Fixed mhshow warn message when it can't convert character set, "from" instead of "to", as reported by Ralph. Author: David Levine Date: Sat Oct 15 11:33:34 2016 -0400 Changed "existant" to "existent". Found by misspell_fixer. Author: David Levine Date: Sat Oct 15 09:58:24 2016 -0400 Added to convertargs documentation. Author: David Levine Date: Fri Oct 14 16:53:27 2016 -0400 Try running script(1) for SHELL test in subshell. Author: David Levine Date: Fri Oct 14 16:40:16 2016 -0400 Check that script(1) supports SHELL in test-version-check. Author: David Levine Date: Fri Oct 14 14:36:21 2016 -0400 Added check to test-version-check to ensure that script(1) makes the program look like it's connected to a terminal. Author: David Levine Date: Fri Oct 14 13:40:14 2016 -0400 Didn't work on buildbot hosts. Added debug statements. Author: David Levine Date: Fri Oct 14 13:27:32 2016 -0400 Instead of feeding stdin to script(1) in test-version-check, create a simple shell script with the command to be run and feed it to script via the SHELL environment variable or -S option. Thanks to Ralph for suggesting this approach. We'll see if it works on all of the buildbot hosts. Author: David Levine Date: Fri Oct 14 09:54:59 2016 -0400 Tweaked formatting of welcome message. Author: David Levine Date: Thu Oct 13 19:12:59 2016 -0400 Disable test-version-check, again, when not connected to terminal. I can't otherwise explain why it fails on the ubuntu buildbot. Author: David Levine Date: Thu Oct 13 18:54:16 2016 -0400 Added debug printouts to test-version-check. Author: David Levine Date: Thu Oct 13 18:45:06 2016 -0400 Use "script file" in test-version-check for maximum portability. Feed its stdin, which might be problematic. Author: David Levine Date: Wed Oct 12 21:48:11 2016 -0400 Added check that replied-to text is not quoted-printable encoded. It's up to the external converter to generate RFC 5322-legal text. Author: David Levine Date: Wed Oct 12 21:47:16 2016 -0400 Split ${charset:+-I "$charset"} and another similar case into two separate options, because Solaris didn't like the space between them. Author: Oliver Kiddle Date: Tue Oct 11 10:20:52 2016 -0400 For the autoconf/automake stuff to replace getline, the following patch seems to work. The final change on configure.ac is to cope with cc -V output having slightly changed in the most recent version of the compiler. Author: Ralph Corderoy Date: Tue Oct 11 10:14:14 2016 -0400 I've written a getline(3) from scratch based on https://manned.org/getdelim.3p and am happy for it to have whatever licence nmh needs. Author: David Levine Date: Tue Oct 11 09:31:42 2016 -0400 Removed test-local-mailbox that was mistakenly committed. Author: David Levine Date: Tue Oct 11 08:55:12 2016 -0400 Only set CFLAGS with gcc. Author: David Levine Date: Tue Oct 11 08:53:32 2016 -0400 Moved gcc warning options from AM_CFLAGS back to CFLAGS, to make it easier for packagers to override. This is a partial rollback of commit f7eb978bd395752d3d9037ea4436b8e2db41f135. Author: David Levine Date: Tue Oct 11 08:41:10 2016 -0400 Added LANG to procmail example in mhfixmsg man page. Author: David Levine Date: Mon Oct 10 16:43:56 2016 -0400 Corrected date in forw man page. Author: David Levine Date: Mon Oct 10 16:42:57 2016 -0400 Tweaked OAuth documentation in mhlogin and send man pages. Author: David Levine Date: Mon Oct 10 16:42:20 2016 -0400 Removed reference to nmh User's Manual because there is no such thing. There was an MH User's Manual, but that is not distributed with nmh. Author: David Levine Date: Mon Oct 10 09:54:51 2016 -0400 Changed test suite's require_locale() to set the locale that it finds, and added upper case versions of locale names to each test. This should allow the tests to succeed on old Solaris. Author: David Levine Date: Sun Oct 9 13:59:11 2016 -0400 Added -sasl to -saslmech xoauth examples in man pages. Author: David Levine Date: Fri Oct 7 22:21:02 2016 -0400 Replace `id -u` with $$ so that tests have a chance of working on old Solaris hosts. Author: David Levine Date: Fri Oct 7 11:07:03 2016 -0400 Added comments about sidestepping check for checks to determine whether replied-to text needs to be encoded in mhbuildsbr.c. Author: David Levine Date: Fri Oct 7 09:40:23 2016 -0400 Added example of decoding RFC-2047 filename to mhstore man page. Author: David Levine Date: Thu Oct 6 18:01:50 2016 -0400 A better fix than e87f37c27828723317a71291e31b34f39ec09098, because c_reqencoding should be set for text content in replies if we don't want it to be encoded. Scan the text content to see if it is 7- or 8-bit, and set c_reqencoding accordingly. Author: David Levine Date: Thu Oct 6 17:53:00 2016 -0400 Moved scan_input() from uip/post.c to sbr/utils.c. Author: David Levine Date: Thu Oct 6 13:10:19 2016 -0400 Updated test-version-check test_skip message. Author: David Levine Date: Thu Oct 6 13:07:20 2016 -0400 Fixed test negations in test-version-check to work with make distcheck. Author: David Levine Date: Thu Oct 6 12:57:45 2016 -0400 OK, don't run test-version-check if not connected to terminal. Author: David Levine Date: Thu Oct 6 12:47:52 2016 -0400 More debugging test-version-check. Author: David Levine Date: Thu Oct 6 12:45:52 2016 -0400 Replaced strtod() with strtof(). Author: David Levine Date: Thu Oct 6 12:16:53 2016 -0400 More debugging. Author: David Levine Date: Thu Oct 6 11:59:24 2016 -0400 More test-version-check debugging, on Linux buildbot hosts. Author: David Levine Date: Thu Oct 6 11:47:26 2016 -0400 1) Use script(1) -t 0 instead of -f on FreeBSD. 2) Added another debug printout. Author: David Levine Date: Thu Oct 6 11:30:19 2016 -0400 Accommodate FreeBSD script(1), and add debugging statement to diagnose failure on ubuntu buildbot host. Merge: 641e461 84eab76 Author: David Levine Date: Thu Oct 6 09:39:27 2016 -0400 Merge branch 'welcome' Author: David Levine Date: Thu Oct 6 09:11:45 2016 -0400 Enable SMTP 8BITMIME for messages with 8-bit content: 1) In post, look for a Content-Transfer-Encoding header. It has to be the header for the message, not any MIME parts. If found, post trusts that it's correct. If there isn't one, post scans the entire message body for any 8-bit bytes. 2) If the message body is 8-bit: If the server supports 8BITMIME, enable it. If the server doesn't support 8BITMIME, fail with a message to user that they need to encode the message for 7-bit transport. Author: David Levine Date: Wed Oct 5 16:04:11 2016 -0400 Call c_ceclosefnx in mhfixmsg set_ce(). It doesn't seem to help reduce file descriptor leaks, but can't hurt. Author: David Levine Date: Wed Oct 5 16:02:47 2016 -0400 Don't set c_reqencoding in repl, let mhbuild set it based on the content. Author: Ken Hornstein Date: Tue Oct 4 22:00:12 2016 -0400 Improve these comments a bit. Author: David Levine Date: Tue Oct 4 21:24:10 2016 -0400 Enabled check for 8-bit content in all text parts, not just those with no specified character set, so that a Content-Transfer-Encoding header will be added if needed. Author: David Levine Date: Tue Oct 4 19:08:42 2016 -0400 Have mhfixmsg add a C-T-E at the message level, based on the least restrictive C-T-E of its parts. Author: David Levine Date: Mon Oct 3 21:30:14 2016 -0400 Base Content-Transfer-Encoding on decoded and new text parts on content rather than the user's charset. Author: David Levine Date: Mon Oct 3 17:59:51 2016 -0400 Fixed typo. Author: David Levine Date: Mon Oct 3 17:50:35 2016 -0400 Fix C-T-E of message, as well as multipart, types to be 7bit, 8bit, or binary. Author: David Levine Date: Sun Oct 2 09:53:56 2016 -0400 Added test of SMTP server that doesn't support SMTPUTF8. Author: Ken Hornstein Date: Sun Oct 2 02:05:44 2016 -0400 Fix some typos in the comments. Author: Ken Hornstein Date: Sun Oct 2 01:47:15 2016 -0400 Move the read buffer shuffling to BEFORE where we call the network read routines; otherwise we can end up calling the lower layers with a length of zero, which messes everything up. Also make sure we reshuffle our pointers around if that happens. Author: David Levine Date: Sat Oct 1 14:37:27 2016 -0400 mhfixmsg now replaces RFC 2047 encoding with RFC 2231 encoding of name and filename parameters in Content-Type and Content-Disposition headers, respectively. Author: David Levine Date: Sat Oct 1 12:49:12 2016 -0400 Cleaned up a bit, mostly in comments for each function. Author: Ken Hornstein Date: Sat Oct 1 01:02:34 2016 -0400 Sigh, the return value from SSL_get_error() isn't suitable to give to ERR_get_error(), so use a different function to get the error. Author: Ken Hornstein Date: Fri Sep 30 21:24:43 2016 -0400 Print even more errors. Author: Ken Hornstein Date: Fri Sep 30 15:15:08 2016 -0400 Add -initialtls/-notls flags to msgchk. Author: Ken Hornstein Date: Fri Sep 30 15:07:03 2016 -0400 Make sure we retry if possible upon a TLS read, and give a more meaningful error if we can't. Author: David Levine Date: Fri Sep 30 10:35:06 2016 -0400 Added --sysconfdir to nmh.cygport. Author: David Levine Date: Fri Sep 30 09:18:27 2016 -0400 Replaced some hard-coded strings with variables in nmh.cygport. Author: Eric Gillespie Date: Fri Sep 30 00:55:55 2016 -0700 Fix typos and drop declaractions of 2 undefined functions. Author: David Levine Date: Thu Sep 29 15:18:02 2016 -0400 Updated comments in h/prototypes.h. Author: David Levine Date: Thu Sep 29 15:13:05 2016 -0400 Welcome message enhancements: 1) Disable if Welcome: disable component is in profile. 2) If MHCONTEXT is set, only print the message if the context file already has a Version: reference where the version is old. Author: David Levine Date: Thu Sep 29 11:40:10 2016 -0400 Instead of relying on invo_name to decide whether to call nmh_version_changed(), use a read_context setting of 1. Author: David Levine Date: Thu Sep 29 09:58:27 2016 -0400 Make sure stderr is directed to terminal, as well as stdin and stdout, when deciding whether to check for nmh version update. Author: David Levine Date: Wed Sep 28 18:48:16 2016 -0400 Wait for user to ack new version message. Author: David Levine Date: Wed Sep 28 15:01:43 2016 -0400 Added welcome message when nmh detects that its version changed. Author: Oliver Kiddle Date: Wed Sep 28 09:58:54 2016 +0200 back out use of RFC 2047 decoding on the filename The RFCs clearly state that an encoded word should not be used in the MIME parameters and the scheme from RFC2231 should be used instead. nmh supports that. Unfortunately, other mail clients, in particular gmail and IBM/Lotus Notes, produce messages with the invalid encoding. Author: David Levine Date: Tue Sep 27 08:29:05 2016 -0400 Added start_test/finish_test. Author: David Levine Date: Tue Sep 27 08:28:47 2016 -0400 Updated start_test() and finish_test() to not update the test name if there was a test failure. run_test disables exit on non-zero status, but does increment failed. Author: Oliver Kiddle Date: Tue Sep 27 01:42:55 2016 +0200 Do RFC 2047 decoding on filename for mhstore Author: David Levine Date: Mon Sep 26 16:50:38 2016 -0400 Replaced use of GNU sed extension. Author: David Levine Date: Mon Sep 26 15:41:22 2016 -0400 Added debug statements to test-mhparam. Author: David Levine Date: Mon Sep 26 14:33:55 2016 -0400 Fixed typo in -help message. Author: David Levine Date: Mon Sep 26 12:07:50 2016 -0400 Reworked BUGS section of nmh(7) man page, and added excerpt to end of each -help message and to end of install-mh output. Merge: aaf014c 60048af Author: David Levine Date: Mon Sep 26 08:58:55 2016 -0400 Merge remote-tracking branch 'origin' into smtputf8 Author: David Levine Date: Sun Sep 25 12:58:05 2016 -0400 Added MH(7) man page, as an alias of nmh(7). Author: David Levine Date: Sun Sep 25 12:18:42 2016 -0400 Added mention of replaliases to mh-mime(7) man page. Merge: 2c00d44 38e17e1 Author: David Levine Date: Sun Sep 25 09:28:05 2016 -0400 Merge remote-tracking branch 'origin' into smtputf8 Author: David Levine Date: Sat Sep 24 17:08:01 2016 -0400 Replace profile-based hack to allow getname() to handle 8-bit addresses with a global data-based hack. At least the global data is hidden in addrsbr.c. Author: David Levine Date: Sat Sep 24 17:01:32 2016 -0400 Removed send and post -eai switches. Instead, post now enables SMTPUTF8 if it finds any 8-bit characters in header field bodies. Author: David Levine Date: Sat Sep 24 12:21:40 2016 -0400 Disabled incompatible locale check because the output varies too much between platforms. (cherry picked from commit 38e17e1b8ba306ed6137b174f2f196d09d02816f) Author: David Levine Date: Sat Sep 24 12:21:40 2016 -0400 Disabled incompatible locale check because the output varies too much between platforms. Author: David Levine Date: Sat Sep 24 12:10:28 2016 -0400 Wrapped some variables and arguments to prevent compile warnings when configured without SASL and OAUTH support. Author: David Levine Date: Sat Sep 24 10:42:58 2016 -0400 Added incompatible locale test to test/mhl/test-rfc6532. It's a placeholder to show that 8-bit header field values aren't properly handled if the locale is incompatible. (cherry picked from commit 2cfa2ea56602d3bb0465a46c0b144017b497b558) Author: David Levine Date: Sat Sep 24 10:42:58 2016 -0400 Added incompatible locale test to test/mhl/test-rfc6532. It's a placeholder to show that 8-bit header field values aren't properly handled if the locale is incompatible. Author: David Levine Date: Sat Sep 24 09:44:39 2016 -0400 Added descriptive/usage information to top of replaliases. Author: Ken Hornstein Date: Sat Sep 24 02:01:05 2016 -0400 Change from an autoconf test for SSL_library_init to SSL_new, for compatibility with OpenSSL 1.1.0. Author: Ken Hornstein Date: Fri Sep 23 23:12:58 2016 -0400 Improve and update comments a bit, and also improve the error messages when we don't have Cyrus-SASL support compiled in. Author: David Levine Date: Fri Sep 23 22:13:04 2016 -0400 Specify that mhbuild -autoheaderencoding picks either base64 or q-p, but not utf-8. Author: Ken Hornstein Date: Fri Sep 23 22:04:44 2016 -0400 Add our sample localpostprox, and also pick up replaliases while we're at it. Author: David Levine Date: Fri Sep 23 21:54:26 2016 -0400 Renamed mhbuild -headerencoding 8bit to utf-8. Author: Ken Hornstein Date: Fri Sep 23 19:52:09 2016 -0400 Make it so we always return the chosen mechanism, even if we aren't using the Cyrus SASL library; this makes XOAUTH2 work without Cyrus-SASL. Author: Ken Hornstein Date: Fri Sep 23 19:51:36 2016 -0400 Missed removing SASLminc() from authservice switch. Author: Ken Hornstein Date: Fri Sep 23 19:30:21 2016 -0400 Switch to AM_DISTCHECK_CONFIGURE_FLAGS. Author: Ken Hornstein Date: Fri Sep 23 15:08:25 2016 -0400 Make the SASL flags work even without support for Cyrus-SASL. Author: Ken Hornstein Date: Fri Sep 23 15:07:51 2016 -0400 Move things around so you can still initialize netsec with SASL parameters even if you don't have Cyrus-SASL enabled. Author: Ken Hornstein Date: Fri Sep 23 14:48:50 2016 -0400 Move some of the SASL variables outside of the ifdef, so OAUTH can make use of them. Also, clean up some warnings. Author: Ken Hornstein Date: Fri Sep 23 14:22:29 2016 -0400 Update documentation a bit. Author: Ken Hornstein Date: Fri Sep 23 14:21:23 2016 -0400 Whoops, a typo from the last merge; when the one variable got reformatted continuation escapes weren't included. Merge: f3cd885 2ebd126 Author: Ken Hornstein Date: Fri Sep 23 14:14:26 2016 -0400 Merge branch 'pop-tls' Author: Ken Hornstein Date: Fri Sep 23 14:13:23 2016 -0400 Don't output snoop information when doing RETR or TOP. Author: Ken Hornstein Date: Fri Sep 23 14:00:59 2016 -0400 Switch decodeBase64() second argument to an unsigned char **. Author: Ken Hornstein Date: Fri Sep 23 13:59:52 2016 -0400 Don't always output a decoded SASL token; if it's a large binary blob, just stick with the base64 output. Author: David Levine Date: Fri Sep 23 11:55:20 2016 -0400 Added SMTPUTF8 (RFC 6531) support: 1) Allow 8-bit characters in addresses. 2) Disable RFC 2047 encoding of (all) header field bodies, via mhbuild -headerencoding 8bit. 3) Have post enable it in the SMTP transaction. 4) If enabled, add the commands to the SMTP transaction (MAIL FROM:
BODY=8BITMIME SMTPUTF8). Some things may changed, such as the 8bit encoding algorithm name. Author: David Levine Date: Fri Sep 23 08:21:57 2016 -0400 Rearranged statements to avoid compile warning about mixed declarations and code. Author: David Levine Date: Fri Sep 23 08:20:27 2016 -0400 Fixed typo (NOTLSSW). Author: Ken Hornstein Date: Thu Sep 22 23:27:36 2016 -0400 Garbage collect the saslmaxssf flag, and update documentation for new -initialtls flag and -notls flags for inc. Author: Ken Hornstein Date: Thu Sep 22 23:10:59 2016 -0400 Forgot to reset the snoop callback one time. Author: Ken Hornstein Date: Thu Sep 22 21:26:39 2016 -0400 Fix some typos and warnings. Author: Ken Hornstein Date: Thu Sep 22 20:01:34 2016 -0400 Switched to "server" instead of "client" for SASL remote hostname. Author: Ken Hornstein Date: Thu Sep 22 19:31:57 2016 -0400 Garbage collect unused code. Author: Ken Hornstein Date: Thu Sep 22 19:24:50 2016 -0400 Whoops, turns out I originally ran this test with XOAUTH set. Fix the output and make sure the common script unsets XOAUTH so this doesn't happen again. Author: Ken Hornstein Date: Thu Sep 22 19:12:36 2016 -0400 Change the tests to make them work with the new program output and slight change in the interface. Author: Ken Hornstein Date: Thu Sep 22 19:12:12 2016 -0400 Add error reporting for one case, and move around the return code in the SASL callback a bit. Author: Ken Hornstein Date: Thu Sep 22 19:11:32 2016 -0400 Add the SASL callback; things work now! Author: Ken Hornstein Date: Thu Sep 22 19:10:23 2016 -0400 Disable the original call to BIO_flush() now that we're doing our own buffering. Author: Ken Hornstein Date: Thu Sep 22 19:05:39 2016 -0400 I had forgotten that nesec_set_tls() has to be called AFTER the descriptors are set. Author: David Levine Date: Thu Sep 22 14:08:10 2016 -0400 Fixed test-mhfixmsg by using octal instead of hex bytes with printf(1). Author: David Levine Date: Thu Sep 22 13:54:50 2016 -0400 Removed temporary debuggin printout. Author: David Levine Date: Thu Sep 22 13:39:55 2016 -0400 Added start_test/finish_test. Author: David Levine Date: Thu Sep 22 13:39:42 2016 -0400 Added temporary diagnostic printout. Author: David Levine Date: Thu Sep 22 13:07:32 2016 -0400 Allow -decodetext binary, though 8bit is still the default because binary can produce messages that are not RFC 2045 compliant. Author: David Levine Date: Thu Sep 22 08:24:49 2016 -0400 Specify full path to mhl in test because it might not be on PATH. Author: Ken Hornstein Date: Thu Sep 22 00:05:13 2016 -0400 Alright, things compile now, but don't link yet; need to write the SMTP sasl callback. Author: Ken Hornstein Date: Thu Sep 22 00:04:43 2016 -0400 Okay, fixed a few more things. Almost there? Merge: 64a5aa1 cff807b Author: Ken Hornstein Date: Wed Sep 21 23:33:29 2016 -0400 Merge branch 'pop-tls' of git.sv.gnu.org:/srv/git/nmh into pop-tls Author: Ken Hornstein Date: Wed Sep 21 23:32:11 2016 -0400 Change things so we can take two file descriptors, one for input and one for output. Author: Ken Hornstein Date: Wed Sep 21 16:51:21 2016 -0400 Okay! Squashed a few bugs, now have POP OAuth tests working. Author: David Levine Date: Wed Sep 21 13:49:21 2016 -0400 Fixed test-rfc6532: MIME-Version isn't ignored by mhl.headers. Maybe it should be? Author: David Levine Date: Wed Sep 21 11:54:49 2016 -0400 Added test/mhl/test-rfc6532. Author: Ken Hornstein Date: Wed Sep 21 00:06:52 2016 -0400 Add support for a base64-decoding snoop callback. Author: Ken Hornstein Date: Tue Sep 20 23:30:51 2016 -0400 Garbage-collect all of this unused code. Author: Ken Hornstein Date: Tue Sep 20 22:11:25 2016 -0400 We have OAauth working! But the tests don't work yet. Author: Ken Hornstein Date: Tue Sep 20 20:09:37 2016 -0400 Shuffle some stuff around, change some prototypes, and modify the oauth code a bit to fit our new structure. Author: David Levine Date: Tue Sep 20 12:23:04 2016 -0400 Plugged memory leak in openBase64(). Author: Ken Hornstein Date: Mon Sep 19 23:29:39 2016 -0400 Maybe ... it works? Sort of! Needs more testing, and for me to finish OAuth support. Author: Ken Hornstein Date: Mon Sep 19 19:59:40 2016 -0400 More work, but not there just yet. Author: Ken Hornstein Date: Sun Sep 18 22:03:18 2016 -0400 Okay, we're finally getting to implementation stage! Hopefully we'll be able to make it all work with POP first, then SMTP. Author: David Levine Date: Sun Sep 18 12:22:10 2016 -0400 Moved LDFLAGS to AM_LDFLAGS. Author: David Levine Date: Sun Sep 18 10:29:17 2016 -0400 Moved CFLAGS additions to AM_CFLAGS. Author: David Levine Date: Sun Sep 18 09:57:06 2016 -0400 Moved restore of CFLAGS outside of AC_CHECK_HEADER, so that it's done unconditionally. Author: Ken Hornstein Date: Sun Sep 18 01:15:20 2016 -0400 I think I've written all of these functions; now we just need to have everyone else use them. Author: David Levine Date: Sat Sep 17 17:11:23 2016 -0400 Added AM_CPPFLAGS to CFLAGS that are used for curl checks, because they're needed on Cygwin. (Without _GNU_SOURCE, sys/types.h doesn't include sys/select.h.) Also added AM_CFLAGS, which we don't currently use but might in the future. Author: David Levine Date: Sat Sep 17 10:15:11 2016 -0400 Updated Makefile.am to correspond to file replacement in commit 4a007bacfa67e69923b15500e2b2c3a6bcde541a. Author: David Levine Date: Sat Sep 17 10:08:22 2016 -0400 Updated cygport script in preparation for nmh 1.7 release. Author: David Levine Date: Sat Sep 17 10:06:56 2016 -0400 Replaced cygwin build script with cygport script. Author: David Levine Date: Sat Sep 17 10:05:35 2016 -0400 Added libcurl to Cygwin package requirements, if configured with --with-oauth. Author: David Levine Date: Fri Sep 16 17:47:31 2016 -0400 Added oauth to mhparam examples. Author: Ken Hornstein Date: Fri Sep 16 15:59:27 2016 -0400 Still closer, but not quite there yet. Author: David Levine Date: Fri Sep 16 12:08:55 2016 -0400 Moved LFLAGS additions to AM_LFLAGS. Author: David Levine Date: Fri Sep 16 11:56:42 2016 -0400 Use CPPFLAGS instead of AM_CPPFLAGS for FreeBSD additions. Otherwise, it will miss -liconv. I think. Author: David Levine Date: Fri Sep 16 11:15:45 2016 -0400 Cleaned up cppflags.m4 a bit and fixed its mode. Author: David Levine Date: Fri Sep 16 08:28:18 2016 -0400 Moved CPPFLAGS additions to AM_CPPFLAGS. Author: Ken Hornstein Date: Thu Sep 15 22:36:17 2016 -0400 Okay, a bit closer. Author: David Levine Date: Thu Sep 15 20:00:02 2016 -0400 Added 2 second timeout to curl command in post() in oauth.c, for localhost requests only, because the default timeout on Cygwin is 5 minutes. Author: David Levine Date: Thu Sep 15 18:58:14 2016 -0400 Added NMH_ADDL_CPPFLAGS macro in new m4/cppflags.m4, to remove explicit OS dependencies when deciding whether -DGNU_SOURCE is needed. (Cygwin now needs it.) Author: Ken Hornstein Date: Thu Sep 15 16:00:07 2016 -0400 Fleshed out some more, but we're not there just yet. Author: Ken Hornstein Date: Wed Sep 14 00:00:48 2016 -0400 A bit more code. Author: Ken Hornstein Date: Tue Sep 13 16:00:46 2016 -0400 Save this for now. Author: Ken Hornstein Date: Mon Sep 12 21:37:06 2016 -0400 More functions documented. Author: Ken Hornstein Date: Mon Sep 12 19:07:29 2016 -0400 Beginnings of a new library API. Author: David Levine Date: Sun Sep 11 11:49:44 2016 -0400 Exposed a bunch of switches that are now documented. Author: David Levine Date: Sun Sep 11 11:30:42 2016 -0400 Added Examples section to mhlogin man page. Author: Ken Hornstein Date: Sun Sep 11 00:41:18 2016 -0400 Add a "file-nopermcheck" credential entry. Author: Ken Hornstein Date: Sun Sep 11 00:05:25 2016 -0400 Change this so the MTS_SMTP is the default, to match the value of mts_method and the original code. Author: Ken Hornstein Date: Sun Sep 11 00:01:28 2016 -0400 Remove the unused argument from mts_init() (as far as I can tell, it has never been used, for anything). Author: Ken Hornstein Date: Fri Sep 9 15:49:26 2016 -0400 Closer, but not there yet. Author: Ken Hornstein Date: Thu Sep 8 15:40:04 2016 -0400 Started ... not quite working yet. Author: Ken Hornstein Date: Thu Sep 8 13:13:57 2016 -0400 Only get a write lock on the sequences file if we're performing a pack operation. Author: David Levine Date: Tue Sep 6 18:02:46 2016 -0400 Added some NMH_UNUSED's to prevent compile warnings without OAUTH_SUPPORT. Author: David Levine Date: Tue Sep 6 17:49:59 2016 -0400 Protected call of mh_oauth_do_xoauth() with #ifdef OAUTH_SUPPORT to allow post(1) to link when configured without it. Author: David Levine Date: Tue Sep 6 17:36:16 2016 -0400 Protected use of setup_oauth_params() with #ifdef OAUTH_SUPPORT. Author: Ken Hornstein Date: Tue Sep 6 15:32:28 2016 -0400 Under some circumstances, some version of MacOS X can return EPROTOTYPE if you try to write to a connection that is being torn down. Handle that case. Author: David Levine Date: Tue Sep 6 09:16:15 2016 -0400 Removed incorrect increment of read position pointer, which caused first character of some very short (less than 4 characters) message bodies to be dropped. It seems that the message needed to start with a "From " line to reveal the problem. Merge: 5776f9b da91c15 Author: Ken Hornstein Date: Mon Sep 5 20:32:03 2016 -0400 Merge branch 'xoauth' Author: Ken Hornstein Date: Mon Sep 5 20:21:55 2016 -0400 Change things so if -authservice wasn't given, throw an error. At the same time, improve the code so -authservice doesn't have to be given before the other oauth flags. Author: Ken Hornstein Date: Sun Sep 4 22:20:40 2016 -0400 Switch from our horrible awk script that parses the signal header file to the POSIX function strsignal(). Author: Ken Hornstein Date: Sun Sep 4 20:42:21 2016 -0400 Fix up a few minor nits to make OAuth2 (finally!) work right in post(8). Change the tests to support the new error output. Author: Ken Hornstein Date: Sat Sep 3 23:46:45 2016 -0400 Add new signal include file location for El Capitan. I am not sure this is in general the right approach. Author: David Levine Date: Mon Aug 29 09:26:38 2016 -0400 Added warning message on stderr if folder -nocreate is provided a non-existant folder. (cherry picked from commit d51964a51fdc08d92dab9825a8357c9adba34aa7) Author: David Levine Date: Mon Aug 29 09:26:38 2016 -0400 Added warning message on stderr if folder -nocreate is provided a non-existant folder. Author: David Levine Date: Sun Aug 21 13:04:59 2016 -0400 Removed jsmn license from COPYRIGHT. In keeping what appears to be standard practice, the COPYRIGHT file just contains the nmh copyright. We retain the jsmn license in thirdparty/jsmn/LICENSE. Author: David Levine Date: Sun Aug 21 12:22:42 2016 -0400 Check result of setup_oauth_params() for != OK instead of non-zero. Author: Ken Hornstein Date: Sun Aug 21 00:39:36 2016 -0400 Very close, but it doesn't passes the tests just yet. Author: Ken Hornstein Date: Sat Aug 20 01:18:13 2016 -0400 Retrieve appropriate profile entries and pass them to post(8). Not quite working yet. Author: Ken Hornstein Date: Tue Aug 16 23:35:09 2016 -0400 Start of adding arguments for transmitting OAuth parameters to post. (cherry picked from commit 68246559a5087f3a3c13ef2a6240a7c18dd9c155) Author: Ken Hornstein Date: Tue Aug 16 23:35:09 2016 -0400 Start of adding arguments for transmitting OAuth parameters to post. Author: Ken Hornstein Date: Mon Aug 15 14:39:04 2016 -0400 Add $(ICONVLIB) to programs that need it. (cherry picked from commit 8c9441dc98bb4ce98ae70528d5415d9f5507713e) Author: Ken Hornstein Date: Mon Aug 15 14:39:04 2016 -0400 Add $(ICONVLIB) to programs that need it. Author: David Levine Date: Mon Aug 15 10:58:33 2016 -0400 Create $MH_OBJ_DIR/test/testdir if it doesn't already exist. This allows a test to be run standalone, now that said directory must exist before defining $MH_TEST_DIR. (cherry picked from commit 0f53d91688c0fab28b900ad27a1610a755dea526) Author: David Levine Date: Mon Aug 15 10:58:33 2016 -0400 Create $MH_OBJ_DIR/test/testdir if it doesn't already exist. This allows a test to be run standalone, now that said directory must exist before defining $MH_TEST_DIR. Author: David Levine Date: Mon Aug 15 10:31:43 2016 -0400 Plug a couple of (harmless) memory leaks in mhfixmsg. (cherry picked from commit 58d22c00deb7bc9c771c5293079f6f89bc28274a) Author: David Levine Date: Mon Aug 15 10:31:43 2016 -0400 Plug a couple of (harmless) memory leaks in mhfixmsg. Author: David Levine Date: Sun Aug 14 20:45:43 2016 -0400 Handle base64 decoding decoding of initial response for all AUTH mechanisms the same way, based on RFC 4954 spec. Also, don't try to decode = or * response. (cherry picked from commit b3ebdfc56e7a0199a60d80f54872e86969d96933) Author: David Levine Date: Sun Aug 14 20:45:43 2016 -0400 Handle base64 decoding decoding of initial response for all AUTH mechanisms the same way, based on RFC 4954 spec. Also, don't try to decode = or * response. Author: Ken Hornstein Date: Sun Aug 14 13:26:59 2016 -0400 Newer versions of Automake want to include the test-driver script, so make sure we ignore it. (cherry picked from commit bd6f799b1d98c11b50a4121c9ac763bcf1b1b3fe) Author: Ken Hornstein Date: Sun Aug 14 13:25:51 2016 -0400 Use isascii() with isprint(), since using isprint() on bytes > 127 is undefined. (cherry picked from commit 7054379384884f0975c687ce9b2cd8c20e3f2c12) Author: Ken Hornstein Date: Sun Aug 14 13:26:59 2016 -0400 Newer versions of Automake want to include the test-driver script, so make sure we ignore it. Author: Ken Hornstein Date: Sun Aug 14 13:25:51 2016 -0400 Use isascii() with isprint(), since using isprint() on bytes > 127 is undefined. Author: David Levine Date: Sun Aug 14 13:11:50 2016 -0400 Set HOME in tests if unset, to avoid warning from w3m about not being about to create config directory. (cherry picked from commit 30a9c9b62fa92df289079080eb5ee57d2fda3951) Author: David Levine Date: Sun Aug 14 13:11:50 2016 -0400 Set HOME in tests if unset, to avoid warning from w3m about not being about to create config directory. Author: David Levine Date: Sun Aug 14 11:04:07 2016 -0400 Fixed typo in man page. Author: David Levine Date: Sun Aug 14 11:02:50 2016 -0400 Fixed a couple of typos in man pages. Author: David Levine Date: Sun Aug 14 10:59:13 2016 -0400 Attempt to decode base64-encoded strings in -snoop traffic. Author: David Levine Date: Sun Aug 14 10:57:51 2016 -0400 Attempt to decode base64-encoded strings in -snoop traffic. Author: David Levine Date: Wed Aug 10 11:58:45 2016 -0400 Canonicalize MH_TEST_DIR in TESTS_ENVIRONMENT. (cherry picked from commit 28c31eb83bf6113dd72182bb5f13c4da99372d9e) Author: David Levine Date: Wed Aug 10 11:47:36 2016 -0400 Use pwd -P to canonicalize MH_TEST_DIR. (cherry picked from commit 6f94c7d978b034d34319236e8a868a5b225605c0) Author: David Levine Date: Wed Aug 10 11:41:01 2016 -0400 Added debug printouts. (cherry picked from commit 5d8bc1288d5bd672bfb81b347e4c7742fbe644d1) Author: David Levine Date: Wed Aug 10 11:19:00 2016 -0400 Canonicalized MH_TEST_DIR, and replaced use of `pwd` with it, to try to prevent test failures on fbsd10 test host. (cherry picked from commit 1846c42228ff68f328cb046027bc7a03ec3ba596) Author: David Levine Date: Wed Aug 10 11:58:45 2016 -0400 Canonicalize MH_TEST_DIR in TESTS_ENVIRONMENT. Author: David Levine Date: Wed Aug 10 11:47:36 2016 -0400 Use pwd -P to canonicalize MH_TEST_DIR. Author: David Levine Date: Wed Aug 10 11:41:01 2016 -0400 Added debug printouts. Author: David Levine Date: Wed Aug 10 11:19:00 2016 -0400 Canonicalized MH_TEST_DIR, and replaced use of `pwd` with it, to try to prevent test failures on fbsd10 test host. Author: David Levine Date: Fri Jul 22 10:08:24 2016 -0400 Fixed comments describing decodeBase64(). (cherry picked from commit 06b87ce464beb93a7929541c355edf580ccec023) Author: David Levine Date: Fri Jul 22 10:08:24 2016 -0400 Fixed comments describing decodeBase64(). Author: David Levine Date: Wed Jul 20 21:25:01 2016 -0400 Factored out base64 decoding code into decodeBase64(). (cherry picked from commit 522c66eae1a144e0631dfaa61f1632e341ea7ce6) Author: David Levine Date: Wed Jul 20 21:14:25 2016 -0400 Moved md5.c from uip to sbr. (cherry picked from commit 98c792e2effa2656e4fce979d6f6eec44d64131c) Author: David Levine Date: Wed Jul 20 21:25:01 2016 -0400 Factored out base64 decoding code into decodeBase64(). Author: David Levine Date: Wed Jul 20 21:14:25 2016 -0400 Moved md5.c from uip to sbr. Author: David Levine Date: Fri Jul 8 11:01:07 2016 -0400 Updated send(1) man page to note that sendfrom looks in Envelope-From and Sender headers as well as the From header. (cherry picked from commit b347135ed8e4c15c6562d7b3d7924bd9ef7f1589) Author: David Levine Date: Fri Jul 8 11:01:07 2016 -0400 Updated send(1) man page to note that sendfrom looks in Envelope-From and Sender headers as well as the From header. Merge: ae54f99 75ac400 Author: David Levine Date: Fri Jul 8 10:48:59 2016 -0400 Merge remote-tracking branch 'origin' into xoauth Author: David Levine Date: Fri Jul 8 10:35:52 2016 -0400 Added Envelope-From and Sender support to sendfrom. Author: David Levine Date: Fri Jul 8 10:28:20 2016 -0400 Changed addresses to use example.com. Author: David Levine Date: Fri Jul 8 09:59:58 2016 -0400 export MH_TEST_DIR so that test/dist/test-dist can be run standalone. Author: David Levine Date: Tue Jul 5 12:10:05 2016 -0400 Moved sendfrom code from contrib into send(1). Author: David Levine Date: Tue Jul 5 12:02:59 2016 -0400 Moved sendfrom code from contrib into send(1). Author: David Levine Date: Tue Jul 5 09:57:07 2016 -0400 Added context_find_prefix(). Author: David Levine Date: Mon Jul 4 18:25:53 2016 -0400 Added context_find_prefix(). Author: David Levine Date: Sat Jun 25 21:22:37 2016 -0400 Wrapped code block of conditional statement with {}, so that the second statement is now included in the conditional. Found by gcc 6 -Wmisleading-indentation. (cherry picked from commit 9626eb33ed5ff7c59776081e1a58a20a1eed96be) Author: David Levine Date: Sat Jun 25 21:19:37 2016 -0400 Moved free(cp) to right after last (and only) use of cp. The statement was flagged by gcc 6 -Wmisleading-indentation. In its original location, it would not always have been called, resulting in leaked memory. (cherry picked from commit 79f012b76eba04d50a36a4a37c57458a8d521434) Author: David Levine Date: Sat Jun 25 21:17:05 2016 -0400 Fixed indentation to prevent warning from gcc 6 -Wmisleading-indentation. (cherry picked from commit a814c930041c1e238f1826b1ac9c46b67e4cfb70) Author: David Levine Date: Sat Jun 25 21:22:37 2016 -0400 Wrapped code block of conditional statement with {}, so that the second statement is now included in the conditional. Found by gcc 6 -Wmisleading-indentation. Author: David Levine Date: Sat Jun 25 21:19:37 2016 -0400 Moved free(cp) to right after last (and only) use of cp. The statement was flagged by gcc 6 -Wmisleading-indentation. In its original location, it would not always have been called, resulting in leaked memory. Author: David Levine Date: Sat Jun 25 21:17:05 2016 -0400 Fixed indentation to prevent warning from gcc 6 -Wmisleading-indentation. Merge: c546ef9 235b62a Author: David Levine Date: Sat Jun 25 21:16:36 2016 -0400 Merge remote-tracking branch 'origin' into xoauth Author: David Levine Date: Sun Jun 12 10:38:19 2016 -0400 Added const to filename args of cpydata(). Then added const to some args in mhfixmsg.c. (cherry picked from commit 9f7d48c36f01ba29974834cbcdc24e4c2e1f07d9) Author: David Levine Date: Sun Jun 12 10:36:43 2016 -0400 Added const to arg of m_backup(). (cherry picked from commit d42ab414c8bce17b6b437ef9ebfd194a8ac4111c) Author: David Levine Date: Sun Jun 12 11:34:59 2016 -0400 Synched common.sh.in from master to nmh-oauth. Author: David Levine Date: Sun Jun 12 11:33:27 2016 -0400 No longer need const cast in sendfrom.c. Author: David Levine Date: Sun Jun 12 11:27:21 2016 -0400 Added consts to adios(), advise(), and advertise() to sync master and nmh-oauth branch. Author: David Levine Date: Sun Jun 12 11:26:37 2016 -0400 Added consts to adios(), advise(), and advertise() to sync master and nmh-oauth branch. Author: David Levine Date: Sun Jun 12 10:38:19 2016 -0400 Added const to filename args of cpydata(). Then added const to some args in mhfixmsg.c. Author: David Levine Date: Sun Jun 12 10:36:43 2016 -0400 Added const to arg of m_backup(). Author: David Levine Date: Sun Jun 12 10:35:47 2016 -0400 Added const to first arg of adios(). Author: David Levine Date: Sun Jun 12 10:05:16 2016 -0400 If parse_mime() fails and the -file switch was used, pass the input message to it unchanged so that pipelines won't break. (cherry picked from commit 564b5b785c7cc709f92a83afb547267ed7418f18) Author: David Levine Date: Sun Jun 12 10:05:16 2016 -0400 If parse_mime() fails and the -file switch was used, pass the input message to it unchanged so that pipelines won't break. Author: David Levine Date: Mon May 30 11:49:20 2016 -0400 Plugged leak in mh_oauth_cred_load(). Author: David Levine Date: Mon May 30 11:48:46 2016 -0400 Added free_fs() call to plug leak from fmt_compile(). Author: David Levine Date: Mon May 30 11:48:28 2016 -0400 Added free_fs() call to plug leak from fmt_compile(). Author: klemens Date: Sun May 29 14:39:05 2016 +0200 spelling-fixes ( code-comments in .c, .h. .y ... ) (cherry picked from commit 942561da2455ee50a1eb82c8c4f2bdb5e25133d1) Author: klemens Date: Sun May 29 14:37:11 2016 +0200 spelling-fixes ( docs, man, readme ) (cherry picked from commit fa92642a21119eda8bfc961f8d5a8d3e9ee7d494) Author: klemens Date: Sun May 29 14:39:05 2016 +0200 spelling-fixes ( code-comments in .c, .h. .y ... ) Author: klemens Date: Sun May 29 14:37:11 2016 +0200 spelling-fixes ( docs, man, readme ) Author: David Levine Date: Sun May 29 09:40:12 2016 -0400 Added sendfrom to docs/contrib. Author: David Levine Date: Sun May 29 09:39:36 2016 -0400 Added sendfrom to docs/contrib. Author: David Levine Date: Sat May 21 09:15:56 2016 -0400 Added docdir to mhparam. (cherry picked from commit 89d69fbd2ae1f9c8c989850ec7057814c655a727) Author: David Levine Date: Sat May 21 08:06:36 2016 -0400 Removed unnecessary memset on fmt_mnull: it gets initialized to all 0's. (cherry picked from commit 56c4ac49d7b8ad674c0a66e9999186bcb98bd048) Author: Ken Hornstein Date: Wed May 18 12:44:21 2016 -0400 Check to see if cross-directory links are supported; if they are not, then don't run the refile -link test. (cherry picked from commit 35fce21b692a6259138fc81caf13f4d07bb58da0) Author: David Levine Date: Sat May 21 09:15:56 2016 -0400 Added docdir to mhparam. Author: David Levine Date: Sat May 21 08:06:36 2016 -0400 Removed unnecessary memset on fmt_mnull: it gets initialized to all 0's. Author: Ken Hornstein Date: Wed May 18 12:44:21 2016 -0400 Check to see if cross-directory links are supported; if they are not, then don't run the refile -link test. Author: David Levine Date: Mon May 2 12:55:31 2016 -0400 For slocal, changed default user, if -user switch isn't used, to be the user part of the Local-Mailbox profile entry, if present, or the current user. addr uses the same default. This allows addr to contain a '.', which slocal did not allow before. Author: David Levine Date: Mon Apr 25 22:20:39 2016 -0400 Added test of negative return code from jsmn_parse() to test-send. Author: David Levine Date: Mon Apr 25 22:19:37 2016 -0400 Added test of empty authorization code to test-mhlogin. Author: David Levine Date: Mon Apr 25 21:58:10 2016 -0400 Added explicit OATH_SUPPORT=1 to configure.ac when oauth support is enabled, otherwise it didn't get set to 1. Author: Eric Gillespie Date: Mon Apr 25 03:33:15 2016 +0000 Fix tests with oauth disabled. Author: David Levine Date: Sun Apr 24 22:09:39 2016 -0400 Check for empty code. Author: David Levine Date: Sun Apr 24 21:42:20 2016 -0400 Return false from parse_json() if jmsn_parse() returns a negative (or zero, as it did before) value. Author: Eric Gillespie Date: Mon Apr 25 01:23:04 2016 +0000 Improve oauth autoconf support. - By default, enable OAuth if curl is found. - If OAuth requested (--with-oauth), error if curl not found. - If OAuth disabled (--without-oauth), don't enable it even if found. - Sanity-check curl-config --version output so we don't send anything crazy in our HTTP requests if curl-config changes. Author: Eric Gillespie Date: Wed Apr 13 16:58:45 2016 +0000 Rename files to match renamed functions Follow-up to commit 840b3f0e45a43b8378e88c66f004b2f186662e35 Author: Eric Gillespie Date: Sun Apr 10 18:46:52 2016 +0000 Fix mhlogin(1) title. Author: David Levine Date: Sun Apr 10 11:42:29 2016 -0400 Added -user to mhlogin man page. Author: David Levine Date: Sat Mar 26 18:59:31 2016 -0400 Added start_test() and finish_test() functions to test/common.sh.in. See usage information in the (new) cleanup() function in that file. This allow us to isolate test failures based on naming of individual tests within a single test file. As part of this, added set -e to setup_test(). This required minor updates to test/new/basic and test/pick/test-stderr to conform. So, migrated test/new/test-basic to start_test()/finish_test(). (cherry picked from commit cd6133dd23422f92534328f768a322f63a5c6dfe) Author: David Levine Date: Sun Apr 10 11:16:55 2016 -0400 Fix to commit 84932d0a96c79bfb2f0384ebab806dc51a35f600 to insert blank line between header and content for non-text content. (cherry picked from commit fe36a7ee2f4304fd3797443d4f2f950d6dc2475d) Author: David Levine Date: Sun Apr 10 11:16:55 2016 -0400 Fix to commit 84932d0a96c79bfb2f0384ebab806dc51a35f600 to insert blank line between header and content for non-text content. Author: David Levine Date: Sun Apr 10 11:15:42 2016 -0400 Quoted variables in trap so that distcheck doesn't trip over them if not set. Author: David Levine Date: Sun Apr 10 11:14:54 2016 -0400 Moved "const" to after "register" to silence compile warning fron gcc. Author: Eric Gillespie Date: Sun Apr 10 06:19:19 2016 +0000 check curl_ctx->res_len > 0 not res_body != NULL res_body is not a pointer and is never NULL (Thanks clang!) Author: Eric Gillespie Date: Sun Apr 10 06:17:35 2016 +0000 oops, pass int to m_getfld not size_t Author: Eric Gillespie Date: Sat Apr 9 23:09:12 2016 -0700 support multiple oauth users; mhlogin now requires -user Author: Eric Gillespie Date: Sun Apr 10 05:03:14 2016 +0000 plug some memory leaks, in success cases only (staying clean at least on non-adios paths is not hard) Author: Eric Gillespie Date: Sun Apr 10 04:53:34 2016 +0000 fix mhlogin -browser test Author: Eric Gillespie Date: Sun Apr 3 08:23:11 2016 +0000 Rename and document functions that read from stdin. - gans becomes read_switch - getans becomes read_switch_multiword - getans_via_readline becomes read_switch_multiword_via_readline - getanswer becomes read_yes_or_no_if_tty - install-mh.c geta becomes read_line Author: Eric Gillespie Date: Sun Apr 3 01:32:23 2016 +0000 test mhlogin -browser Author: David Levine Date: Sun Mar 27 12:00:16 2016 -0400 Don't call sm_auth_sasl() for XAUTH2 with -sasl. Instead, call only sm_auth_xoauth2(). Author: David Levine Date: Sat Mar 26 19:09:50 2016 -0400 Added start_test()/finish_test() to README.developers. Author: David Levine Date: Sat Mar 26 19:05:10 2016 -0400 Migrated the oauth tests to start_test()/finish_test() so that they don't have any output on success, but do report the particular test on failure. Author: David Levine Date: Sat Mar 26 18:59:31 2016 -0400 Added start_test() and finish_test() functions to test/common.sh.in. See usage information in the (new) cleanup() function in that file. This allow us to isolate test failures based on naming of individual tests within a single test file. As part of this, added set -e to setup_test(). This required minor updates to test/new/basic and test/pick/test-stderr to conform. So, migrated test/new/test-basic to start_test()/finish_test(). Author: David Levine Date: Thu Mar 24 21:25:19 2016 -0400 Added -browser switch to mhlogin(1). Merge: 630af73 961d5bf Author: David Levine Date: Thu Mar 24 20:24:15 2016 -0400 Merge remote-tracking branch 'origin' into xoauth Author: David Levine Date: Thu Mar 24 19:57:15 2016 -0400 Changed minchars swit values for -[no]concat switches to show(1) from negative to 0, so that they can be abbreviated and so that they appear with -help. Added them to the man page, and fixed text that was copied from mhshow(1) man page. Author: David Levine Date: Thu Mar 24 19:55:58 2016 -0400 Use WIFXEXITED to check return status of system(), because comparison with NOTOK wasn't valid. Author: David Levine Date: Wed Mar 23 21:40:31 2016 -0400 Changed sign of minchars for the SASL-related switches from negative to positive so the won't be hidden from help messages. I think. Merge: 626b510 f1920d7 Author: David Levine Date: Wed Mar 23 20:41:46 2016 -0400 Merge remote-tracking branch 'origin' into xoauth merge is necessary, Author: David Levine Date: Wed Mar 23 20:25:32 2016 -0400 Replaced -oauth service switch with -saslmech xoauth2 -authservice service, because OAUTH2 is a SASL mechanism. Author: Lyndon Nerenberg Date: Sun Mar 20 17:28:27 2016 -0700 Another pass at cleaning up (some of) the manpages. This continues work I started a couple of years ago, but then got derailed on. There are two main goals behind these updates: 1) replace some low-level troff constructs with more modern man(7) facilities, and 2) adopt a more consistent visual style to the layout and formatting of the manpages, particularly in reference to typeset pages. This time around I have updated README.manpages to describe the new guidelines. They are mostly non-intrusive, and serve to clean up a lot of visual clutter that has crept in over the years. Author: David Levine Date: Sat Mar 19 10:15:43 2016 -0400 Added check of return value of write() to quash compiler warning. Author: Ken Hornstein Date: Sat Mar 19 00:06:24 2016 -0400 Recover properly if the character conversion fails. Author: Ken Hornstein Date: Sat Mar 19 00:04:56 2016 -0400 Fix substitution code so it uses the right pointer for the utf-8 test. Merge: c2a69f6 2885665 Author: David Levine Date: Fri Mar 18 08:30:21 2016 -0400 Merge remote-tracking branch 'origin' into xoauth Author: David Levine Date: Thu Mar 17 22:05:54 2016 -0400 Have fix_boundary() return NOTOK if it couldn't fix a boundary, so that mhfixmsg won't modify the message. Author: David Levine Date: Wed Mar 16 21:32:48 2016 -0400 Added oauth support to whatnow. Author: David Levine Date: Sun Mar 13 15:40:23 2016 -0400 Added oauth switch to whatnow. Author: David Levine Date: Sun Mar 13 13:11:21 2016 -0400 Added use of local variable user to prevent compiler warning when built without OAuth2 support. Author: David Levine Date: Sun Mar 13 12:58:25 2016 -0400 Sort JSON output from oauth tests so that comparisons don't depend on it being in a specific order. Also, clean up test tmp files. Author: David Levine Date: Sun Mar 13 12:57:18 2016 -0400 Set MH_VERSION, OAUTH_SUPPORT, and CURL_USER_AGENT in tests/common.sh.in so that oauth tests can be run individually (not just via make check). Author: David Levine Date: Sun Mar 13 11:00:05 2016 -0400 Added OAuth2 support to build_nmh. Merge: b7f1c78 ddb9e8c Author: David Levine Date: Sun Mar 13 10:42:39 2016 -0400 Merge branch 'master' into xoauth Author: David Levine Date: Sat Mar 12 13:25:36 2016 -0500 Have -nocrlflinebreaks apply to the message parts that -decodetypes designates. Author: David Levine Date: Sat Mar 12 10:41:03 2016 -0500 Added EXAMPLES and BUGS sections. Author: Eric Gillespie Date: Sat Mar 12 00:15:46 2016 -0500 Implement the -reverse option to pick(1) to change the search order. Author: David Levine Date: Sat Feb 27 11:44:51 2016 -0500 Updated date on mh-folders(5) man page. Author: David Levine Date: Sat Feb 27 11:33:39 2016 -0500 Added application/ics to default list if types to decode. Author: Paul Fox Date: Thu Feb 25 11:33:14 2016 -0500 mh-folders.man: note that folders should not be named numerically Author: David Levine Date: Wed Feb 24 20:32:10 2016 -0500 Added -[no]crlflinebreaks switches to mhfixmsg(1). Author: David Levine Date: Sun Feb 21 11:59:41 2016 -0500 Added check for successful decode of a different part with attempted -decodetext of binary text to test-mhfixmsg. Author: David Levine Date: Sun Feb 21 11:22:53 2016 -0500 Don't consider failure to build a text/plain part to be an error. This allows mhfixmsg to succeed even if there isn't a suitable mhfixmsg-format-text/subtype profile entry for every text part in the message. Author: David Levine Date: Sat Feb 20 13:41:52 2016 -0500 Added -decodetypes switch to mhfixmsg(1). Author: David Levine Date: Thu Jan 28 21:16:43 2016 -0500 Add missing -infile switch name to mhfixmsg-format-text/calendar rule in mhn.defaults. Author: David Levine Date: Sat Jan 23 15:14:33 2016 -0500 mhical enhancement: If a datetime is missing the time, assume midnight. If there is no end datetime (DTEND) and the DTSTART doesn't contain a time, assume that the event is for the entire day. Author: Richard M Kreuter Date: Tue Jan 19 21:39:11 2016 -0500 Set MH to the resolved, absolute pathname inside context_read() so that exec'd children can find it. Author: Richard M Kreuter Date: Tue Jan 19 21:19:16 2016 -0500 Added all of mhshow's documented switches to show's handling, on the notion that nmh's pieces should know about each other. Author: David Levine Date: Tue Jan 19 21:03:30 2016 -0500 Added mention of mhfixmsg -fixcte to error message for improper C-T-E in multipart message. Thanks to Conrad Hughes for suggesting this. Author: David Levine Date: Sun Nov 29 22:21:11 2015 -0500 Moved addition of -ansi -pedantic to CFLAGS with gcc from configure.ac to docs/contrib/build_nmh, so that they're not included by default with builds by users. Author: David Levine Date: Thu Nov 19 15:27:49 2015 -0500 Allow a RRULE in an iCalendar request to not have an INTERVAL on its yearly FREQ, because INTERVAL defaults to 1. Author: David Levine Date: Wed Nov 18 18:35:59 2015 -0500 Remove any enclosing quotes from a timezone identifier in an iCalendar event request. See comment added to format_datetime() that says that I don't believe that RFC 5545 allows them to be quoted. But Oliver Kiddle found them in the wild. Author: David Levine Date: Wed Nov 18 18:02:43 2015 -0500 If format_datetime() returns null, store a copy of node->value on c->c_text to prevent a double free(). Author: Ken Hornstein Date: Sat Aug 22 22:16:22 2015 -0400 If str == buffer, then do NOT do a strncpy(buffer, str). Many systems this works, but on some systems it causes a SIGABRT. POSIX says the behavior on overlapping copies with str*cpy() is officially undefined. Author: Ken Hornstein Date: Sat Aug 22 22:14:41 2015 -0400 Add support for setting the environment variable MH_TEST_NOCLEANUP to prevent a test from cleaning up the test working directory. Author: Leonardo Taccari Date: Fri Aug 21 13:26:53 2015 -0400 Add support for the -sendmail flag to send/post, to support changing the sendmail executable. Author: David Levine Date: Mon Jul 13 22:32:36 2015 -0400 Unquoted addresses in mhshow and scan output. Suggested by Anthony Bentley. Author: Ken Hornstein Date: Fri Mar 20 12:09:54 2015 -0400 Change the reference to the valgrind suppression file from $MH_OBJ_DIR to $srcdir so "make distcheck" works. Author: Ken Hornstein Date: Fri Mar 20 12:02:14 2015 -0400 Include a new valgrind warning suppression for MacOS X. Author: Alexander Zangerl Date: Fri Mar 20 10:26:02 2015 -0400 Make sure the valgrind suppression file is honored, and add some extra suppressions needed when running under the Debian fakeroot environment. Author: Ken Hornstein Date: Tue Mar 17 11:02:38 2015 -0400 Fix error message to correctly report the program that failed to execute when doing HTML conversion. Also, remove perl function prototypes as they are not considered best practice. Author: Ken Hornstein Date: Fri Mar 6 22:58:58 2015 -0500 Rearrange all callers of post(8) so that the filename is always last. Author: Paul Fox Date: Wed Mar 4 13:10:38 2015 -0500 mhparse.c: verify all MIME-Version: headers encountered in addition to verifying, silently ignore duplicate version headers. Merge: f9eb71e 3f60981 Author: David Levine Date: Sun Feb 22 21:21:40 2015 -0600 Merge remote-tracking branch 'origin/convertargs' Author: Paul Fox Date: Sat Feb 14 11:36:24 2015 -0500 use %l uniformly on all the text-mode browser display strings otherwise behavior changes depending on which browser was present when nmh is configured/installed. Author: David Levine Date: Fri Feb 13 23:30:03 2015 -0600 Filter converted text/html to remove blank lines and leading space that lynx inserts. Also, changed ISO-8859-1 to US-ASCII because it is, so it doesn't need to be converted. Author: David Levine Date: Fri Feb 13 22:22:21 2015 -0600 Removed m_chkids(), per suggestion of Marcin Cieslak. Author: David Levine Date: Fri Feb 13 21:31:48 2015 -0600 Removed unnecessary #include of h/signals.h. Author: David Levine Date: Fri Feb 13 21:30:41 2015 -0600 Removed #include of signal.h because it's in h/signals.h. Author: Marcin Cieslak Date: Fri Feb 13 21:01:09 2015 -0600 Reset done in inc_done() to prevent endless loop when setegid() fails (in which case adios() is called, which calls done()). Author: David Levine Date: Thu Feb 12 21:33:05 2015 -0600 That didn't work, so removed offset. Author: David Levine Date: Thu Feb 12 21:27:45 2015 -0600 Use +0000 isntead of -0000 offset because FreeBSD displays it that way. Author: Marcin Cieslak Date: Thu Feb 12 21:09:26 2015 -0600 Replaced setgid() calls with setegid() so that it works with dot locking on FreeBSD. setegid() should be supported on modern POSIX systems. Author: David Levine Date: Thu Feb 12 20:22:32 2015 -0600 Added showmimeproc to test/common.sh.in so that test-show will test it in the workspace, not the user's installation. Also added all of the other procs defined in config/config.c that are currently unused, just in case they some day are. Author: David Levine Date: Thu Feb 12 20:03:11 2015 -0600 Removed a few more msh (MS_MSH and mshproc) and vmh (vmhproc) relics. Author: David Levine Date: Wed Feb 11 21:38:51 2015 -0600 Replaced individual assignment of array elements, one of which was out of range, with array initialization. Author: Marcin Cieslak Date: Tue Feb 10 14:18:05 2015 +0000 Fixed the error message in lockit() when it fails to create tmp file. Author: Marcin Cieslak Date: Tue Feb 10 14:18:05 2015 +0000 Fixed "inc" to be installed setgid mail with dot locking. MAILGROUP=1 was not set in the config.h because we no longer use "LOCKTYPE" configure variable. Author: Paul Fox Date: Sun Feb 8 15:13:31 2015 -0500 update tests for new message separator header from mhshow also added test names to tests, in any file i touched Author: Paul Fox Date: Sun Feb 8 16:06:44 2015 -0500 update man pages for new mhshow message separator header Author: Paul Fox Date: Sun Feb 8 15:22:07 2015 -0500 add new message separator header to mhshow new switches to mhshow (-headerform and -[no]header) control whether and what is displayed before the display of every message's content. the default separator looks like "[ Message folder:msg ]". the implementation parallels the -markform feature. since mhshow is often started by show, show now passes the -[no]header options through to mhshow. (also, show no longer attempts to pass such options through to cat (in the case of -noshowproc)). Author: Paul Fox Date: Fri Feb 6 13:03:36 2015 -0500 fix typo in mh-format.man Author: Eric Gillespie Date: Thu Feb 5 12:46:28 2015 -0800 Test that show always shows message numbers. show shows message numbers in two different formats when showing one non-MIME, multiple non-MIME messages, or one MIME message. show does not show any message numbers when showing multiple messages any of which is MIME. This is not a new bug, just one that has bothered me since I started using mhshow with 1.6. Author: Paul Fox Date: Fri Feb 6 11:57:58 2015 -0500 test/common.sh: allow giving individual tests a name Author: Paul Fox Date: Fri Feb 6 11:32:44 2015 -0500 man pages -- clarify what -part and -type do when used together Merge: 991ae1d afea511 Author: David Levine Date: Sun Feb 8 09:23:34 2015 -0600 Merge remote-tracking branch 'origin' into convertargs Author: David Levine Date: Sun Feb 8 09:21:13 2015 -0600 Added support to mhfixmsg -reformat for multipart/related. If it has only a single part that is not text/plain and can be converted to text/plain, a text/plain part is added and the type of the part is changed to multipart/alternative. If the multipart/related has more than one part but does not have a text/plain part, try to add one. Author: David Levine Date: Wed Feb 4 19:19:54 2015 -0600 Fixed test-convert to work on Cygwin and other platforms that default to UTF-8 locale. Merge: 397195e ff6c0df Author: David Levine Date: Wed Feb 4 19:18:33 2015 -0600 Merge remote-tracking branch 'origin' into convertargs Author: David Levine Date: Wed Feb 4 19:05:16 2015 -0600 Removed unused local variable from move_preferred_part(). Author: Paul Fox Date: Wed Feb 4 18:52:53 2015 -0500 pending-release-notes: add mhshow's "-prefer", and mh-format's %(kibi/kilo) Author: Paul Fox Date: Wed Feb 4 14:44:36 2015 -0500 test-subpart: add mhlist and mhshow tests for -type/-part/-prefer Author: Paul Fox Date: Wed Feb 4 12:07:27 2015 -0500 update mhshow, mhlist, and mhstore man pages for -prefer switch Author: Paul Fox Date: Tue Feb 3 21:55:41 2015 -0500 implement -prefer, for multipart/alternative preferences Author: Paul Fox Date: Tue Feb 3 23:03:46 2015 -0500 mhshow.man: more detail on use of -part and -type switches Author: Paul Fox Date: Tue Feb 3 12:39:53 2015 -0500 mhshow: ensure that -part always shows every part requested previously, "mhshow -part 1 -part 1.3" would show 1.1 but not 1.3. Author: Paul Fox Date: Fri Jan 30 19:52:24 2015 -0500 mhshow: fix display of alternatives after certain nested multiparts adjust return codes so that we now have a clear indication of whether there was a hard error (NOTOK), a failure to display due to type mismatch (DONE), or complete success (OK). use those codes in show_multi_internal() to decide whether we're finished with this multipart or not. prior to this change, it was impossible to show part 1.2 of a message constructed like the following, because the disinction between (the new, as described above) DONE and OK states was lost while processing multipart/related part 1.1. msg part type/subtype size description 28 multipart/mixed 1040 1 multipart/alternative 623 1.1 multipart/related 275 1.1.1 text/html 105 1.2 text/plain 33 2 text/plain 83 this fix is related to 9cc2510 and c9794733. hopefully it's right this time. Author: Paul Fox Date: Fri Jan 30 20:14:59 2015 -0500 mhshow: simplify code -- the DONE status was adding no value Author: Paul Fox Date: Fri Jan 30 19:41:37 2015 -0500 drop the second argument to part_ok(), since it is always 1 the second argument hasn't been used since "historical" times. also add some commentary to part_ok(). Author: Lyndon Nerenberg Date: Tue Jan 27 15:17:20 2015 -0800 Add a note about new bindir option to mhparam. Author: Lyndon Nerenberg Date: Tue Jan 27 15:07:19 2015 -0800 'mhparam bindir' now prints NMH's idea of $(bindir). Author: David Levine Date: Tue Jan 20 19:10:56 2015 -0600 Added a line break to mhbuild man page because the %docdir%/contrib/replaliases line caused format complaints from groff. Merge: 4857a9e a70006b Author: David Levine Date: Sun Jan 18 21:31:20 2015 -0600 Merge remote-tracking branch 'origin' into convertargs Author: David Levine Date: Sun Jan 11 19:10:23 2015 -0600 Fixed check of return value of show_content_aux(). Author: David Levine Date: Sun Jan 11 19:05:11 2015 -0600 Have show_content_aux2(), and therefore show_content_aux(), return the status of the process used to show, instead of (usually) OK. (cherry picked from commit a70006bbdf676639961877b02a19e9e1f1d0ec78) Author: David Levine Date: Sun Jan 11 19:05:11 2015 -0600 Have show_content_aux2(), and therefore show_content_aux(), return the status of the process used to show, instead of (usually) OK. Author: David Levine Date: Sat Jan 10 17:23:54 2015 -0600 Fixed typo in mh-format.man page, which I wouldn't have noticed if I didn't go back in to update its date. Author: David Levine Date: Sat Jan 10 17:12:49 2015 -0600 Added multiply format function, requested by Norm. Merge: ebd5247 0706d36 Author: David Levine Date: Wed Jan 7 20:32:20 2015 -0600 Merge remote-tracking branch 'origin' into convertargs Author: David Levine Date: Wed Jan 7 20:15:06 2015 -0600 Pass along arguments to calaccept(), etc., functions in replaliases. Author: David Levine Date: Wed Jan 7 20:13:41 2015 -0600 Fix to commit 6b073f7b67a0afd64012ff7d00818ec1bd07b5f2 to properly detect a Content-Type header in output from converted content. Author: David Levine Date: Tue Jan 6 21:39:42 2015 -0600 Another fix to convertarg handling of multipart/related. Two, actually. One is a simple bug fix, the other restricts concatenation to text/plain, not just text, parts. Author: David Levine Date: Mon Jan 5 22:32:00 2015 -0600 Specifically look for Content-Type header in converted content. Author: David Levine Date: Mon Jan 5 19:10:33 2015 -0600 Fixed convertarg handling of text part in multipart/related. Author: David Levine Date: Sun Jan 4 11:22:18 2015 -0600 Forgot to commit test-mhical. Author: David Levine Date: Sun Jan 4 10:52:28 2015 -0600 Added mhical(1), to display, reply to, and cancel iCalendar (RFC 5545) event requests. Author: David Levine Date: Sun Jan 4 09:57:23 2015 -0600 Added yacc/bison support to configure.ac. Author: David Levine Date: Mon Dec 29 07:44:38 2014 -0600 Added rtm alias. Author: David Levine Date: Mon Dec 29 06:06:59 2014 -0600 More cleanup of the cp in tests/common.sh.in. Author: David Levine Date: Sun Dec 28 22:15:04 2014 -0600 Added -h and -p options to replaliases. The -p argument can be useful with improperly structured messages, such as those that use multipart/related when they should have used multipart/alternative. Alos, removed -editor mhbuild because it precludes use of WhatNow attach. Author: David Levine Date: Sun Dec 28 21:12:06 2014 -0600 Replaced explicit list of files to be copied in test/common.sh.in with *. It wasn't trivial, per the comments in the file about portability to posh, but close. Author: David Levine Date: Sun Dec 28 15:51:36 2014 -0600 OK, this fixes the problem referenced in the last commit. It removes the copy of the etc files only during make distcheck. Author: David Levine Date: Sun Dec 28 13:42:35 2014 -0600 Reverted commit a2b00e7053ca3be3d1389588580c71498222a267. It caused make check to pull etc files from where they were already installed, not from the test directory. Author: David Levine Date: Sun Dec 28 12:46:22 2014 -0600 Removed export of most of the variables in test/common.sh.in. The test scripts source common.sh so they don't need them to be exported. Author: David Levine Date: Sun Dec 28 12:32:14 2014 -0600 Removed copy of all of the etc files from test/common.sh.in. Instead, for make distcheck, pass the location of the installed etc directory via DISTCHECK_CONFIGURE_FLAGS, configure, and TESTS_ENVIRONMENT to a new nmhetcdirinst variable. Outside of make distcheck, nmhetcdir is valid by itself. Author: David Levine Date: Sun Dec 28 12:12:40 2014 -0600 Rearranged the variable settings at the top of test/common.sh.in. Author: David Levine Date: Sat Dec 27 11:25:48 2014 -0600 Changed direct access to etc files in a couple of tests to be the installed (for the test) versions, not the copies made by common.sh. Author: David Levine Date: Sat Dec 27 11:19:43 2014 -0600 Replaced nmhexecdir with nmhlibexecdir in test/common.sh.in (and test-mhparam) for consisitency with the Makefile. Author: David Levine Date: Thu Dec 25 11:10:52 2014 -0600 Added -fixtype switch to mhfixmsg(1). It ensures that each part of a message has the correct MIME type shown in its Content-Type header. Author: David Levine Date: Thu Dec 25 11:04:28 2014 -0600 Added const to char * arguments of uprf(). Author: David Levine Date: Thu Dec 25 00:05:36 2014 -0600 Added ct_str_type() and ct_str_subtype() functions, to translate MIME type and subtype names to the the internal MIME parser codes. Author: David Levine Date: Thu Dec 25 00:04:34 2014 -0600 Merged two adjacent if (verbose) blocks. Author: David Levine Date: Wed Dec 24 18:25:43 2014 -0600 Fixed memory leak in mime_type(). get_file_info() always allocates its return value. Author: David Levine Date: Wed Dec 24 14:35:41 2014 -0600 Always initialize those two variables made static in commit 771706ac9fed2b902bd4d3ddccb15ee27b0f58ae in case they were set in previous calls. Author: David Levine Date: Sun Dec 21 19:50:58 2014 -0600 And removed another improperly copied comment. Author: David Levine Date: Sun Dec 21 19:46:25 2014 -0600 Removed improperly copied comment from test-mhfixmsg. Author: David Levine Date: Sun Dec 21 19:41:12 2014 -0600 In expand_pseudoheader(), set Content-Type to 7-bit for ASCII text. Author: David Levine Date: Sun Dec 21 16:21:27 2014 -0600 Added mention of profile components that are described in other man pages. Suggested by Michael Richardson. Author: David Levine Date: Sun Dec 21 10:31:41 2014 -0600 Rearranged code to avoid "might be clobbered by longjmp" warnings from gcc 4.9.2 Author: David Levine Date: Sun Dec 21 10:22:41 2014 -0600 Removed unnecessary #includes of setjmp.h. Author: David Levine Date: Sat Dec 20 14:27:03 2014 -0600 Removed widths from mhbuild-convert-text/html lines that should have been removed by commit 5ab36412b5fc49feb41fa816129c68fd6d946e8b. Author: David Levine Date: Sat Dec 20 14:07:37 2014 -0600 Fixed use of text_plain_ct in mhbuildsbr.c so that it works with multiple text parts. Found by Clang static analyzer. Author: David Levine Date: Sat Dec 20 10:42:11 2014 -0600 Set COLUMNS in test-cd if using readline so that its wrapping doesn't disturb the test output. The problem arose with a long workspace path. Author: David Levine Date: Sat Dec 20 10:36:10 2014 -0600 posh didn't like use of file wildcard in common.sh.in. Author: David Levine Date: Sat Dec 20 09:21:50 2014 -0600 Removed R from default PARINIT environment variable so that par(1) does not consider an input word that is too long to be an error. Author: David Levine Date: Wed Dec 17 20:43:37 2014 -0600 Fixed format engine output of negative number with 0 fill character. Improper output was reported by Bob Carragher. Author: David Levine Date: Sun Dec 14 22:11:00 2014 -0600 Added -convertargs switch to repl(1), to pass arguments to programs specified in the user's profile or mhn.defaults to convert message content. Author: David Levine Date: Sat Dec 13 08:30:35 2014 -0600 Rearranged mhn.defaults.sh a bit: consolidated web-browser specific settings and put most of the mhstore-store- directives in a here doc. Author: David Levine Date: Sat Dec 13 08:04:13 2014 -0600 Clarified in repl(1) man page that -noformat is only the default when no -filter switch is used. Author: Eric Gillespie Date: Mon Dec 8 23:37:51 2014 -0800 Strip carriage returns fakehttprequest logging. Author: Eric Gillespie Date: Mon Dec 8 23:29:07 2014 -0800 Note curl dependencies for Linux and FreeBSD. Author: Eric Gillespie Date: Mon Dec 8 23:26:27 2014 -0800 Teach mhparam about oauth support. Author: Eric Gillespie Date: Mon Dec 8 23:20:01 2014 -0800 Implement OAuth 2.0 [1] for XOAUTH2 in SMTP [2] and POP3 [3]. Google defined XOAUTH2 for SMTP, and that's what we use here. If other providers implement XOAUTH2 or some similar OAuth-based SMTP authentication protocol, it should be simple to extend this. [1] https://tools.ietf.org/html/rfc6749 [2] https://developers.google.com/gmail/xoauth2_protocol [3] http://googleappsdeveloper.blogspot.com/2014/10/updates-on-authentication-for-gmail.html Technically, XOAUTH2 is a SASL auth mechanism, but the implementation is so trivial, I can't justify the code complexity or additional dependency requirement of using Cyrus SASL for this. So it's completely separate. Changes: - New dependencies: - jsmn (JSON processing library) bundled directly rather than linked to as an external library because there is no clear winner among JSON libraries for C and this one is tiny - libcurl is nearly ubiquitous and too heavy-weight to bundle, so link to the library the user must install separately - Add oauth.h / oauth.c which do almost all the work, with quite a bit of help from curl and jsmn. - Add new mhlogin program to authorize nmh to use the Gmail account and store the access and refresh tokens. - Add new user_agent global to version.c (version.sh); not too happy with such a generic name, but the others had no mh_ prefix or anything... - Add XOAUTH2 support to: mts/smtp/smtp.c uip/post.c uip/send.c uip/popsbr.c uip/inc.c uip/msgchk.c - Split duplicated serving code out of fakepop.c and fakesmtp.c to new server.c and also use that for new fakehttp.c. - Add XOAUTH2 support to fakepop.c and fakesmtp.c. Author: Eric Gillespie Date: Mon Dec 8 21:47:58 2014 -0800 import jsmn 86:19001fb4adb3 Author: David Levine Date: Sat Dec 6 09:30:52 2014 -0600 Only remove extraneous trailing semicolon from Content-Type and Content-Disposition headers because those are the only ones that parse_mime() warns about, but it does appear on others. Author: Eric Gillespie Date: Fri Dec 5 21:08:40 2014 -0800 Terminate last arg in proxy argv n popsbr.c:parse_proxy(). This bug seems to have existed since this code was born. I guess others have been lucky? Author: Ken Hornstein Date: Tue Dec 2 13:41:55 2014 -0500 Set all Content structure elements to NULL as they are free()'d; in a few cases a content structure is reused and you can get into problems with double-free()ing elements depending on your MIME composition content syntax. Merge: 330bdf6 8206fbf Author: Ken Hornstein Date: Tue Dec 2 13:12:45 2014 -0500 Merge commit '8206fbf', due to my screwup of committing it on a detached HEAD after a git-bisect. Author: Ken Hornstein Date: Tue Dec 2 13:00:47 2014 -0500 Turns out those warnings for ali(1) actually happen when the prefix is 33 characters, not 35. Author: Ken Hornstein Date: Tue Dec 2 09:35:02 2014 -0500 Explicitly depend on $(srcdir)/config/version.h rather than depend on VPATH. Author: Paul Fox Date: Mon Dec 1 13:32:26 2014 -0500 cast isspace() arg to unsigned char in previous commit Author: Paul Fox Date: Mon Dec 1 08:57:44 2014 -0500 handle extraneous trailing ';' characters that are followed by whitespace Author: David Levine Date: Sun Nov 30 21:35:19 2014 -0600 mhfixmsg now removes an extraneous trailing semicolon from header parameter lists. Author: David Levine Date: Sat Nov 22 19:00:32 2014 -0600 Use Nmh-Attach for attach header field name, and accept Attach. Author: David Levine Date: Sat Nov 22 18:55:39 2014 -0600 Have to check for missing type parameter in message/related part even though it's required according to RFC 2387 Sec. 3.1. Author: David Levine Date: Sat Nov 22 18:54:48 2014 -0600 Expanded explanation of mhfixmsg return status in its man page. Author: David Levine Date: Thu Nov 20 22:28:28 2014 -0600 Look at type of parent multipart/related when determining whether a non-plain text part already has a text/plain sibling. Author: David Levine Date: Thu Nov 20 22:27:58 2014 -0600 Added support for multipart/related to MIME parser. Author: David Levine Date: Thu Nov 20 20:25:14 2014 -0600 Added some checks to mhfixmsg.c to avoid dereferecing null pointers after a failed transformation. Author: David Levine Date: Thu Nov 20 19:48:58 2014 -0600 Fixed double fclose() in InitMultiPart() and leaks introduced in commit 5be8db81. Author: Paul Fox Date: Thu Nov 20 15:41:34 2014 -0500 prevent spurious errors when requesting specific message parts no one should be reporting NOTOK for failure to display parts that weren't actually requested. failure should be reserved for parts that we really attempted to display. (this fix is an extension of c9794733.) Author: David Levine Date: Wed Nov 19 21:04:33 2014 -0600 Updated simple integration example in mhfixmsg(1) man page and added return status values. Author: David Levine Date: Wed Nov 19 20:17:45 2014 -0600 Updated test-mhfixmsg to support -[no]changecur. Author: David Levine Date: Wed Nov 19 20:13:01 2014 -0600 Added -[no]changecur switches to mhfixmsg(1). Author: David Levine Date: Sun Nov 16 18:13:47 2014 -0600 Updated test-repl to compare with new -help message. Author: David Levine Date: Sun Nov 16 17:14:32 2014 -0600 Fixed repl help message to show "-[no]cc all|to|cc|me" instead of different options for -cc and -nocc. Author: David Levine Date: Sun Nov 16 17:10:52 2014 -0600 Fixed leak in content_charset(): if get_param() found the charset, it returns a copy. Author: David Levine Date: Sat Nov 15 10:20:42 2014 -0600 Moved mhstore declarations from uip/mhn.c, uip/mhstore.c, and uip/mhstoresbr.c to h/mhparse.h. Author: David Levine Date: Sat Nov 15 08:40:36 2014 -0600 Removed "If this draft originated on the local host, then" phrase from mh-alias man page. Alias resolution applies no matter where the draft originated. Author: David Levine Date: Fri Nov 7 23:08:13 2014 -0600 Changed content_charset() to not cache, so the user can always, and should, free the return value. Author: David Levine Date: Fri Nov 7 22:46:17 2014 -0600 Cleaned up leaks from calls to content_charset() in mhfixmsg. Author: David Levine Date: Fri Nov 7 22:42:34 2014 -0600 Added deallocation of cts to freects_done(). Author: David Levine Date: Tue Nov 4 21:47:13 2014 -0600 Fixed repl(1) man page to show "msg" instead of "msgs" because it only allows reply to one message. Author: David Levine Date: Tue Nov 4 17:04:30 2014 -0600 Fixed mlistfree() so that it doesn't dereference a free'd list node in order to find the next node. Author: David Levine Date: Tue Nov 4 17:00:28 2014 -0600 Fixed commit 6cc9e85e73ff6f6c67ae6e645d184bbf57ecc2f0 to properly return other than the first mbox/address if there's a match in getmymbox/getmyaddr. Author: David Levine Date: Wed Oct 29 21:27:55 2014 -0500 Fixed memory management in mhstore. The main problem was a double free when both -file and -outfile switches were used on a MIME message. Author: David Levine Date: Wed Oct 29 19:37:18 2014 -0500 Added initial "MH-Profile-Version: 1.0\n" line to newly created profiles. The main purpose of this first line is to fool file(1). Without it, if the first line of the profile is Path:, file 5.19 reports its type as message/news. With it, it reports the type as text/plain. Author: David Levine Date: Mon Oct 27 21:20:07 2014 -0500 Renamed getmymbox mh-format escape function to getmyaddr, and added new getmymbox that returns the user's address with any personal name. Author: David Levine Date: Sun Oct 26 10:41:04 2014 -0500 Added getmymbox function escape. Author: David Levine Date: Sat Oct 25 20:41:55 2014 -0500 Fixed memory leak in do_name() when multiple dates are parsed. Author: David Levine Date: Sat Oct 25 20:38:20 2014 -0500 Added free_fs(), corresponding to new_fs(). Author: David Levine Date: Sat Oct 25 18:54:50 2014 -0500 Fixed dst format escape to return 1 instead of 16, to agree with its documentation. Author: David Levine Date: Fri Oct 24 23:25:58 2014 -0500 Added mhstore-store-text/html formatting string to mhn.defaults. Author: David Levine Date: Fri Oct 24 23:19:54 2014 -0500 Fixed typo in mhstore man page. Author: David Levine Date: Fri Oct 24 22:22:47 2014 -0500 Reworked charstring_buffer_copy() to not use strdup() so that charstrings with null bytes can be supported. Added charstring_append_cstring(). Author: David Levine Date: Sat Oct 11 09:22:52 2014 -0500 Added mh_xcalloc(). Author: David Levine Date: Sat Oct 11 09:17:14 2014 -0500 The units of the zone format escape are minutes, not hours. Merge: edccf71 a92ba79 Author: Lyndon Nerenberg Date: Wed Oct 8 19:13:19 2014 -0700 Merge branch 'master' of ssh://git.sv.gnu.org/srv/git/nmh Author: Lyndon Nerenberg Date: Wed Oct 8 19:12:28 2014 -0700 no-op to force check the buildbots. Merge: cdec1be 64be852 Author: Lyndon Nerenberg Date: Sun Oct 5 12:32:20 2014 -0700 Merge branch 'master' of ssh://git.sv.gnu.org/srv/git/nmh Author: Lyndon Nerenberg Date: Sun Oct 5 12:28:56 2014 -0700 mhn.defaults: make fetch less agressive on FreeBSD. Drop the -a flag to fetch. Its retry logic has a bug where it will go into an endless loop when trying to re-fetch an object behind an https:// link when it is unable to validate the X.509 certificate chain. Author: David Levine Date: Sun Oct 5 10:18:25 2014 -0500 Use "mhparam etcdir" instead of hard-coded etc in build_nmh. Author: Lyndon Nerenberg Date: Sun Oct 5 01:50:59 2014 -0700 Clean atags file as part of maintainer-clean. Author: Lyndon Nerenberg Date: Sun Oct 5 01:27:56 2014 -0700 Add a missing option to mhn fetch command for FreeBSD. I *always* forget the '-o -' to redirect to stdout :-P Author: Lyndon Nerenberg Date: Sun Oct 5 01:20:56 2014 -0700 On FreeBSD, use fetch(1) to retrieve external content through URLs. fetch(1) is part of the base system, so it's guaranteed to always be there. And it is more likely to have been configured for any local site customizations (local caches, proxies, etc). Author: Lyndon Nerenberg Date: Sun Oct 5 00:26:11 2014 -0700 If building from a non-master git branch, include the branch name in the version string. Author: Lyndon Nerenberg Date: Sat Oct 4 22:49:01 2014 -0700 New locations for config files and support binaries, and smarter default for install root directory. The default locations for config files and back-end executables has changed. Config files have moved from ${sysconfdir} to ${sysconfdir}/nmh, and the back-end programs from ${libdir} to ${libexecdir}/nmh. The only user-visible change is the addition of a new mhparam(1) component 'libexecdir', which replaces the previous 'libdir'. User scripts invoking 'mhparam libdir' will need an update. 'libdir' has been kept around for the time being, to give people a chance to update their scripts. It returns the same value as 'libexecdir'. 'libdir' has been marked deprecated in the mhparam(1) manpage and the release notes; it will be removed in a couple of releases. In conjunction with this change there was an opportunity to do a bit of Makefile cleanup. The old 'auxexec' construct has been replaced with a new scheme that leverages automake's templating. The auxexec_* references have been replaced with nmhlibexec_* forms, and a corresponding nmhlibexecdir variable defined as ${libexecdir}/nmh. Likewise, etcdir has been replaced with nmhetcdir. These name changes have percolated downstream to some extent, primarily in the man pages and test scripts. Finally, configure has been made a bit smarter about setting the default ${prefix}. If it finds an existing nmh installation, it will set the default ${prefix} to match, falling back to /usr/local/nmh. configure looks for an existing installation by searching $PATH for a viable mhparam binary. Author: David Levine Date: Sat Oct 4 22:43:21 2014 -0500 Fixed commit 2adafe760a9c45b417727a3f5d9481de26471a8b to not try to allocate a charstring_t of length INT_MAX with -width 0. Author: David Levine Date: Sat Oct 4 22:17:08 2014 -0500 Simplified test-mhl-flags a bit. Author: Lyndon Nerenberg Date: Wed Oct 1 17:20:38 2014 -0700 Add a 'guide' file for acme(1). If we ever find more than one acme user working on the source, the single-guide-file premise might need a review. Ultimately, there should be a way for the configure script to search for and import a personal guide file from the developer's $HOME or some such. The next person to come along can figure that out. Author: Lyndon Nerenberg Date: Wed Oct 1 15:36:25 2014 -0700 git: ignore top-level tags files atags is the output from a ctags variant that generates its output in a format recognized by Plan 9's acme editor. (ftp://orthanc.ca/unix/atags/ for details.) Author: Lyndon Nerenberg Date: Mon Sep 29 22:42:28 2014 -0700 FreeBSD packages destination directory fixup. If the ports collection is not installed, assume ports/packages install under /usr/local. Also, when querying , use the value of the $(LOCALBASE) macro. ($(PREFIX) is for port-specific overrides of $(LOCALBASE).) Author: Lyndon Nerenberg Date: Mon Sep 29 15:52:18 2014 -0700 For FreeBSD builds, also search the ports tree for includes and libs. Author: David Levine Date: Sun Sep 14 20:24:24 2014 -0500 Added checks of return value of fwrite() calls where missing. Author: David Levine Date: Sun Sep 14 19:31:43 2014 -0500 Fixed formatting of rtrim/nortrim in mhl man page. Author: David Levine Date: Sun Sep 14 19:14:10 2014 -0500 An "rtrim" flag has been added to mhl to remove any trailing whitespace from filtered text lines. A corresponding "nortrim" flag has also been added. Author: David Levine Date: Sun Sep 14 19:04:21 2014 -0500 If a component has trailing whitespace, e.g., body:component="> ", mhl now trims that whitespace off when filtering blank text lines. Author: David Levine Date: Fri Sep 12 22:12:33 2014 -0500 Fixed all anomalies detected by clang static analyzer (with default checkers on Linux). One was notable: there was a break missing from a switch case in fmt_scan.c, which caused the result of the sday function escape to be garbage. Author: Ken Hornstein Date: Fri Sep 12 15:06:52 2014 -0400 Fix typo in man page Author: David Levine Date: Sun Sep 7 09:56:21 2014 -0500 On some platforms, -D_FORTIFY_SOURCE=2 warns about ignoring the return value from mbtowc() even when it is called to reset the shift state. So wrap that in an if statement with a null body. Author: David Levine Date: Sun Sep 7 09:18:20 2014 -0500 Added -D_FORTIFY_SOURCE=2 now that the build is clean with it. Removed -Wno-unused-result because it shold no longer be necessary. Adjusting all settings of CPPFLAGS to have consistent form. Author: David Levine Date: Sat Sep 6 20:26:42 2014 -0500 Added a couple of new directories and a note about valgrind warnings from debuginfo to README.developers. Author: David Levine Date: Sat Sep 6 08:00:52 2014 -0500 Check return values of system calls in uip/ and test/ .c files, found with gcc's -D_FORTIFY_SOURCE=2. Author: David Levine Date: Fri Sep 5 21:18:28 2014 -0500 Quote "$SEARCHPATH" in mhn.defaults.sh to allow spaces, etc., in PATH components. Author: David Levine Date: Mon Sep 1 21:09:04 2014 -0500 Doubled size of buffers used by m_getfld(), scan, and fmttest to 8192, on any platform, so that -width 0 and -outsize max are likely to include at least some part of the body of each message. Author: David Levine Date: Mon Sep 1 20:27:33 2014 -0500 Fixed typo in mh-profile.man. Author: David Levine Date: Mon Sep 1 20:14:52 2014 -0500 Don't let scan() use too large a width (BUFSIZ for now) to prevent allocating a huge output buffer. Author: David Levine Date: Sun Aug 31 15:40:57 2014 -0500 A value of 0 for the width switch of scan(1), inc(1), ap(1), dp(1), fmttest(1), and mhl(1) now means as many characters as the format engine can produce [Bug #15274]. That amount is limited by internal buffers. Author: David Levine Date: Sun Aug 31 15:39:47 2014 -0500 Fixed read of body in fmttest to limit size to that of rbuf, if smaller than outwidth, to avoid overrunning it. Author: David Levine Date: Fri Aug 29 08:50:51 2014 -0500 fmt_scan() no longer subtracts 1 from the width. This has the effect of no longer counting the trailing newline in the output of scan(1), inc(1), and the other programs that rely on it. Author: Ken Hornstein Date: Thu Aug 28 22:29:21 2014 -0400 Very very rough cut at trying to parse email addresses with Bison. Author: David Levine Date: Mon Aug 25 22:06:11 2014 -0500 Check return values of system calls in several sbr .c files, found with gcc's -D_FORTIFY_SOURCE=2. Updated checks added previously to mhfixmsg.c to be consistent. Author: David Levine Date: Mon Aug 25 20:49:39 2014 -0500 Moved reverse_alternative_parts() from mhfixmsg.c to mhparse.c and added declaration to mhparse.h. Author: David Levine Date: Mon Aug 25 19:50:23 2014 -0500 Removed msh relics from scansbr.c, including a global. Author: David Levine Date: Mon Aug 25 19:29:34 2014 -0500 Added size_t cast of another MB_CUR_MAX to silence the compiler on FreeBSD 9. Author: David Levine Date: Sun Aug 24 21:46:34 2014 -0500 Added cast of MB_CUR_MAX to size_t to silence compiler warning on FreeBSD. Author: David Levine Date: Sun Aug 24 21:19:10 2014 -0500 Dynamically allocate space for the output of fmt_scan(), using charstring_t, so a fixed sized output buffer is no longer needed. Also got rid of scanl global. Author: David Levine Date: Sun Aug 24 12:06:40 2014 -0500 Added const to last argument of trace_cb signature, it'll be needed for use with charstring. Author: David Levine Date: Sun Aug 24 08:23:55 2014 -0500 Added charstring "class". Author: David Levine Date: Wed Aug 20 07:53:56 2014 -0500 Refer to RFC 2046 instead of 1521 in mhlist.man. Author: David Levine Date: Mon Aug 18 20:47:03 2014 -0500 Changed dist_contrib_DATA to dist_contrib_SCRIPTS so that all of the scripts will be installed with execute permissions. Author: David Levine Date: Mon Aug 18 20:36:00 2014 -0500 Updated mhfixmsg(1) man page to refer to mh-mkstemp(1) instead of mktemp. Author: David Levine Date: Sat Aug 16 21:01:26 2014 -0500 Checked return value of write() calls in mhfixmsg.c, found with gcc's -D_FORTIFY_SOURCE=2. Author: David Levine Date: Fri Aug 15 21:00:57 2014 -0500 Removed h/msh, hopefully the last msh relic. Author: David Levine Date: Sat Aug 9 09:20:31 2014 -0500 ncurses package is required to run all of test suite on Linux and Cygwin. Author: Lyndon Nerenberg Date: Fri Aug 8 14:32:54 2014 -0700 Print information about the compiler toolchain on Darwin and FreeBSD. Author: Lyndon Nerenberg Date: Wed Aug 6 17:48:18 2014 -0700 Add new build tool: tools/showbuildenv This prints some basic information about the build environment. It's intended use is to print some information about the specific build environment for each of the builds in the buildbot cluster. In particular, the patch level of the OS, and the versions of 3rd-party packages installed on the system, compiler versions, etc. Author: David Levine Date: Sun Aug 3 22:08:23 2014 -0500 Removed second argument from m_Eom() in m_getfld.c because it was unused. Author: David Levine Date: Sun Aug 3 21:05:03 2014 -0500 Here's a better fix to m_Eom() in m_getfld.c than commit d2520ac7054ad75d60342606bf13c821305d958c. The comparison of the return value of Getc() with EOF must be as an integer, not a char. Author: David Levine Date: Sun Aug 3 21:01:16 2014 -0500 Removed eom_action from m_getfld.c because it was only used by m_eomsbr(), which was removed by commit 68e8c25f906e7353269502d2292c8e99aa8c6605. Author: David Levine Date: Sun Aug 3 20:35:07 2014 -0500 Removed mhlsbr(). It was only used by msh, too. Author: David Levine Date: Sun Aug 3 20:10:45 2014 -0500 Removed m_eomsbr() from m_getfld.c, and its scan_eom_action() wrapper. It was only used by msh, which was removed by commit e6917522a770cf2dba9997ca047977bc55fac061. Author: David Levine Date: Sun Aug 3 07:53:15 2014 -0500 Added -debug switch to pick(1) and deprecated $MHPDEBUG. Author: David Levine Date: Sat Aug 2 21:37:34 2014 -0500 Fixed refile(1) -retainsequences when the source and destination folders are the same. Author: David Levine Date: Sun Jul 27 08:32:13 2014 -0500 Separated out list of programs that are required to build from a source code snapshot from those that are required to build from a distribution. Author: David Levine Date: Thu Jul 24 13:10:23 2014 -0500 Fixed sed usage in flex fixup to not use -s (or -e, because even that's not needed). Author: David Levine Date: Wed Jul 23 21:20:34 2014 -0500 Removed "true" from end of flex fixups. I don't know why it was there. Author: David Levine Date: Wed Jul 23 21:10:47 2014 -0500 Apply flex fixup to dtimep.c with flex 2.5.37 as well as 2.5.36. Author: David Levine Date: Tue Jul 22 21:50:30 2014 -0500 When mhparam(1) is going to output the value for spoollocking, call mts_init() first in case it was set in mts.conf. Author: David Levine Date: Tue Jul 22 21:17:54 2014 -0500 Updated test-spoollocking to restore mts.conf when it's finished (successfully) so as to not upset subsequent tests. Also fixed removal of existing spoollocking option each time through. Author: David Levine Date: Tue Jul 22 20:46:04 2014 -0500 Note in mh-folders(5) man page that spoollocking can be overridden in mts.conf as well as with configure. Author: Ken Hornstein Date: Wed Jul 9 12:05:49 2014 -0400 Fix bug #42718; ali(1) still refers to removed options -normalize and -nonormalize. Author: David Levine Date: Tue Jul 8 19:58:12 2014 -0500 If the user didn't specify any of the tls switches to post(8), try to help them by implying -initialtls if they're using port 465 (smtps, until IANA revoked that registration in 1998). Author: David Levine Date: Sun Jul 6 22:22:38 2014 -0500 Here's an even simpler fix to enable TLS by default. Author: David Levine Date: Sun Jul 6 16:46:12 2014 -0500 Fix to commit 03e76aecdf671ca13b5912af8206e9bdcb6c0919 to enable TLS by default. Boolean logic is our friend. Author: Lyndon Nerenberg Date: Fri Jul 4 13:24:37 2014 -0700 Revert "Default to enabling (Cyrus) SASL, if available." This reverts commit fd23674a5829d5092c99a07110086f02f0b4a238. Author: Lyndon Nerenberg Date: Thu Jul 3 19:31:44 2014 -0700 Turn back the sasl test. Everything broke as a result. Not surprising. Revert "Comments should say why a chance matters ..." This reverts commit 7e6d0b76b1869b4fecc2412ac68f9739ee5916ea. Author: Lyndon Nerenberg Date: Thu Jul 3 17:49:31 2014 -0700 Comments should say why a chance matters ... Author: Lyndon Nerenberg Date: Thu Jul 3 16:40:37 2014 -0700 Default to enabling (Cyrus) SASL, if available. Author: Lyndon Nerenberg Date: Thu Jul 3 16:33:56 2014 -0700 Fix the release notes to put things in the correct section, Author: Lyndon Nerenberg Date: Thu Jul 3 16:25:13 2014 -0700 Note that post uses the submission port now. Author: Lyndon Nerenberg Date: Thu Jul 3 16:11:38 2014 -0700 Enable TLS by default. Author: David Levine Date: Mon Jun 16 21:04:47 2014 -0500 Check return value of setlocale(3) and admonish on failure. Author: Lyndon Nerenberg Date: Mon Jun 16 17:03:06 2014 -0700 Add missing variable initializations on fmt_scan(). Author: Lyndon Nerenberg Date: Mon Jun 16 16:03:25 2014 -0700 Ensure getline() is in scope on FreeBSD. On FreeBSD, to make the getline() prototype visible, you must '#define _WITH_GETLINE' before including . Author: David Levine Date: Sun Jun 15 22:43:16 2014 -0500 Fix to commit 0d3875d020fb17d34918f5e81ee7f87fbc5d1565: it seems that only Linux uses the locale name of en_US.utf8, so added check for the more common en_US.utf-8 to the tests that use it. Author: David Levine Date: Sun Jun 15 22:05:16 2014 -0500 Reordered #includes of sbr/terminal.c to allow compilation on Solaris 10. Thanks to Michael Urban for report the problem and verifying the fix. Author: David Levine Date: Sat Jun 14 11:52:42 2014 -0500 Skip (parts of) tests that require en_US.utf8 locale if it's not available. Thanks to Alexander Zangerl for reporting the issue. Author: Ken Hornstein Date: Fri Jun 13 15:17:48 2014 -0400 Test to make sure inc works properly with a POP server that has multiple messages on it. Author: Ken Hornstein Date: Fri Jun 13 15:07:26 2014 -0400 Support multiple messages with fakepop. Author: Ken Hornstein Date: Tue Jun 10 21:08:02 2014 -0400 Always default the username to the local username, even when not doing SASL. Fix suggested by Michael Urban. Author: Ken Hornstein Date: Tue Jun 10 19:06:54 2014 -0400 Use variable-size (but in one case, fixed but larger) buffers for the SASL exchange to deal with larger SASL messages (specifically, when doing GSSAPI with certain ticket extensions). Author: Paul Fox Date: Mon Jun 9 23:21:35 2014 -0400 mh-profile.man: rewrite the Profile Lookup section for clarity thanks to Ralph Corderoy for the text. Author: Ken Hornstein Date: Mon Jun 9 12:00:17 2014 -0400 If "curl" is available, create a nmh-access-url entry that uses it. Author: Ken Hornstein Date: Mon Jun 9 11:36:05 2014 -0400 Fix curl example for nmh-access-url entry. Author: Ken Hornstein Date: Sat Jun 7 23:14:12 2014 -0400 Return an appropriate error if the input characters are 8-bit, but the locale character set is US-ASCII. Author: Ken Hornstein Date: Sat Jun 7 22:40:12 2014 -0400 Whoops, this should be LC_CTYPE. Fixing that exposes the lack of an appropriate environment variable in test-utf8-body Author: Paul Fox Date: Wed Jun 4 12:18:12 2014 -0400 mhlist: don't truncate anything when -verbose without this change to the -verbose output, there's no easy way to use mhlist to get an unmodified content-type or content-description. (the non-verbose output isn't changed.) Author: David Levine Date: Thu May 29 21:08:59 2014 -0500 Clarified description in comments of context_find_by_type(). Author: David Levine Date: Thu May 29 21:07:25 2014 -0500 Added static to declaration of docc(). Author: David Levine Date: Thu May 29 21:05:36 2014 -0500 Undid commit 475fef2edee9db3c63fc089df76f8e93e3d598cd, it didn't seem popular. We'd be better off with a proper method, or using formail(1), to extract the addresses from a message. Author: David Levine Date: Thu May 29 21:02:49 2014 -0500 Split assignment and export of shell variable. Author: David Levine Date: Tue May 27 21:35:23 2014 -0500 Added mention of "Reply to
?" prompt to repl(1) man page and code, as comment. Suggested by Norm so that scripts can depend on it. Author: David Levine Date: Mon May 26 09:17:34 2014 -0500 Added context_find_by_type(), helper function to search first, if subtype is non-NULL, for invoname-string-type/subtype and then invoname-string-type. Also gets rid of some fixed-size temp buffers. Author: David Levine Date: Fri May 23 17:07:39 2014 -0500 Fixed test-mkstemp to work with valgrind. Author: David Levine Date: Thu May 22 20:39:45 2014 -0500 Fixed to commit 378589b17424bd78acbfc57d505383ffb8c256cb: when a -file switch will be used, insert -[no]concat before the filename (and therefore, the -file switch itself). Author: David Levine Date: Wed May 21 22:11:42 2014 -0500 Don't pass -[no]concat from show(1) to mhl(1). Author: David Levine Date: Wed May 21 20:56:25 2014 -0500 Fixed typos in comments. Author: David Levine Date: Wed May 21 20:50:22 2014 -0500 On platforms with no MIMETYPEPROC, declare the content to be binary if it contains any NUL characters. Author: Ken Hornstein Date: Mon May 19 13:37:26 2014 -0400 Explain how to get a literal % in format files. Author: David Levine Date: Sun May 18 21:55:13 2014 -0500 Documented steps to build RPM from tarball, without using autogen.sh. Author: David Levine Date: Sun May 18 21:43:20 2014 -0500 Added autogen.sh to EXTRA_DIST. Author: Ken Hornstein Date: Fri May 16 13:02:43 2014 -0400 Handle unknown message types in the generic content handler rather than in the RFC822 handler; this will cause them to be displayed using an output marker rather than throw an error. Author: Ken Hornstein Date: Fri May 16 12:14:21 2014 -0400 Output a newline if the last character in a text/plain part is not a newline (but only for mhshow). Author: Ken Hornstein Date: Fri May 16 00:04:24 2014 -0400 Move the prototype for show_content_aux() to a common header file; it got an extra argument recently but none of the other users of it noticed. When fixing this I discovered that the usage of show_content_aux() by mhstoresbr.c was wrong; the prototype had an extra argument in the middle of it. Apparently this has been broken for 15 years! Author: Ken Hornstein Date: Thu May 15 23:01:49 2014 -0400 Switch from %p to %l (%p is no longer supported, although we silently accept it). Author: Paul Fox Date: Thu May 15 14:02:07 2014 -0400 fix comment syntax Author: Paul Fox Date: Tue May 13 09:36:42 2014 -0400 clarify scan_content() logic for choosing encoding Author: David Levine Date: Thu May 15 10:28:03 2014 -0500 Added support for mhbuild-disposition-[/] profile entries when mhbuild expands Attach: headers. Default to 'attachment', but override with 'inline' entries for text/calendar and message/rfc822 in mhn.defaults. Author: Paul Fox Date: Thu May 15 08:55:45 2014 -0400 change mhlist to use decimal math when abbreviating sizes the K/M/G/T units imply factors of 1000, so make the code match. (the alternative would be to change the units to Ki/Mi/Gi/Ti.) mhlist output might someday be configurable using mh-format, in which case the user will be able to choose. Author: Paul Fox Date: Tue May 13 10:10:09 2014 -0400 add $(kibi) function, as complement to %(kilo) %(kibi) will convert a number to IEC prefix units, i.e. Ki, Mi, Gi, Ti, representing factors of 1024. (by comparison, %(kilo) represents factors of 1000.) Author: Paul Fox Date: Tue May 13 09:43:43 2014 -0400 rename %(units) to %(kilo) per discussion here: http://lists.nongnu.org/archive/html/nmh-workers/2014-05/msg00092.html Author: David Levine Date: Tue May 13 07:02:11 2014 -0500 Added --dereference option, if supported, to file(1) command in NMH_MIMETYPEPROC and NMH_MIMEENCODINGPROC macros. Author: David Levine Date: Fri May 9 18:58:11 2014 -0500 Fix to commit b828fcb1695393007a75c41d32b2173c296be9d7: a couple of commas were missing from the added line. Author: Paul Fox Date: Thu May 8 14:25:14 2014 -0400 add new sample files for mhbuild tests to Makefile.am Author: Paul Fox Date: Thu May 8 12:42:10 2014 -0400 add new test for 'mhbuild -check' Author: Paul Fox Date: Thu May 8 11:31:56 2014 -0400 eliminate use of fgets() from calculate_digest() in mhbuildsbr.c Author: Paul Fox Date: Thu May 8 10:57:40 2014 -0400 eliminate use of fgets() in mhbuild.c use getline() instead, which is more tolerant of NULs in the input. also cleaned up error and file cleanup paths a bit. Author: Paul Fox Date: Thu May 8 10:51:30 2014 -0400 eliminate use of fgets() in mhparse.c use getline() instead, which is more tolerant of NULs in the input. Author: Paul Fox Date: Wed May 7 19:43:04 2014 -0400 add new test for NUL bytes embedded in text/plain parts such parts should be encoded with quoted-printable Author: Paul Fox Date: Wed May 7 16:57:14 2014 -0400 add new test for attachment containing NULs Author: Paul Fox Date: Wed May 7 19:41:39 2014 -0400 clean up whitespace in mhbuildsbr.c lots of space-follows-tabs, and trailing whitespace. no code changes. Author: Paul Fox Date: Wed May 7 19:36:56 2014 -0400 make scan_content() work correctly with content containing NULs switched from fgets to getline for unambiguous reads in the face of NUL bytes. added a checkfornuls flag, and use it to cause the correct encoding when content-types of application or text contain NULs. Author: Paul Fox Date: Wed May 7 19:34:33 2014 -0400 make writeQuoted() work correctly with content containing NULs Author: Ken Hornstein Date: Thu May 8 12:37:50 2014 -0400 Treat unknown top-level content types as "application" types, instead of generating an "unknown content type 0" error. Author: David Levine Date: Wed May 7 21:16:46 2014 -0500 Fixed test-charset to pass without iconv. Author: David Levine Date: Wed May 7 21:14:45 2014 -0500 Moved norm_charmap() declaration from h/prototypes.h to sbr/check_charset.c. That's the only place where it's used and we want to keep it that way. Author: Lyndon Nerenberg Date: Wed May 7 12:33:56 2014 -0700 Add a doxygen config file. Sends its output to docs/doxygen/... (see docs/doxygen/html/index.html after you run doxygen). Requires graphviz, for the dependency graphs. Author: Lyndon Nerenberg Date: Wed May 7 12:09:21 2014 -0700 Revert "Increment VERSION on the head to 1.7+dev." This reverts commit 6cce62edaae4cc28ac42a1a796ff18f183407788. Author: Lyndon Nerenberg Date: Wed May 7 12:07:03 2014 -0700 Add a 'tools' subdirectory. This is a home for developer-oriented scripts and such which can't be run from the Makefile(s) due to system dependencies. Author: Lyndon Nerenberg Date: Wed May 7 11:49:10 2014 -0700 Increment VERSION on the head to 1.7+dev. Author: Lyndon Nerenberg Date: Wed May 7 11:44:05 2014 -0700 Scrub *.plist (Clang Static Analyzer) files when cleaning. Author: Lyndon Nerenberg Date: Wed May 7 11:43:09 2014 -0700 Git: ingore *.plist files (generated by the Clang Static Analyzer). Author: Paul Fox Date: Wed May 7 12:10:35 2014 -0400 remove binaries unintentionally committed oops. Author: Paul Fox Date: Mon May 5 22:41:43 2014 -0400 modify tests for the new mhshow mime part marker format also added a couple of Content-Description headers to better test the marker format. Author: Paul Fox Date: Wed May 7 10:19:56 2014 -0400 modify mhshow marker format to include the size of the part Author: Paul Fox Date: Tue May 6 17:28:18 2014 -0400 add "%(units)" function, to express numbers with SI units i.e., 1510 --> 1.5K, 15780000 --> 15.8M etc. useful with %(size), as in %(units(size)). Author: Paul Fox Date: Tue May 6 11:54:52 2014 -0400 make the %(size) function useful in mhshow marker line formats normally %(size) returns the size of the message. in mhshow marker lines, it returns the size of the (decoded, if necessary) part. Author: Ken Hornstein Date: Tue May 6 22:41:34 2014 -0400 Document these functions a bit better. Author: David Levine Date: Sun May 4 22:30:45 2014 -0500 Removed obsolete comment. Author: David Levine Date: Sun May 4 09:25:49 2014 -0500 Fixed typo in comment in sbr/readconfig.c. Author: David Levine Date: Sun May 4 21:51:52 2014 -0500 Replaced use of norm_charmap() in mhshow and mhfixmsg with case-insensitive string comparison against the charset name. norm_charmap() is intended for use with result of nl_langinfo(), and didn't add much value here. Author: David Levine Date: Sun May 4 09:03:33 2014 -0500 In mhshow, copy result of call to norm_charmap() and get_charset() because they return a static buffer. Thanks to Alexander Zangerl for tracking this down, when using an ISO-8859-1 locale. Author: Paul Fox Date: Wed Apr 23 21:44:54 2014 -0400 mhshow: apply marker form to all part separators the mhshow "-markform" format is now used for all part separators, not just those being left out. the format now overloads the %(unseen) function to indicate that the content of the part being marked has been suppressed. the built-in default and example formats both make use of this function. Author: Paul Fox Date: Sat Apr 26 10:45:47 2014 -0400 mhshow: suppress error for undisplayable parts, if they're not wanted consider this message: 1 multipart/mixed 1113K 1 multipart/alternative 292 1.1 text/html 66 1.2 text/plain 49 2 image/jpeg 823K if this is displayed using "mshow -part 2", in the presence of an MHSHOW variable which _only_ describes a rule for displaying images, then we don't want to get an error about how nothing in part 1 was displayable. Author: Paul Fox Date: Tue Apr 22 12:23:01 2014 -0400 man pages: clarify how profiles entries are searched (cherry picked from commit d7b59eb68168ead6a81ca40cf8aa5cccbf86c649) Author: Ken Hornstein Date: Mon Apr 21 23:00:47 2014 -0400 Fix minor typo in NEWS file. Pointed out by Norman Shapiro. Author: David Levine Date: Mon Apr 21 19:00:45 2014 -0500 Added yet another NDBM (gdbm, actually) header/lib pair, for Ralph's platform. Author: David Levine Date: Mon Apr 21 13:00:00 2014 -0500 Added mhfixmsg to nmh man page. Author: Paul Fox Date: Sun Apr 20 19:01:48 2014 -0400 mhshow.man: fix an incorrect 'mhn' reference Author: Ken Hornstein Date: Sun Apr 20 18:28:21 2014 -0400 Documentation improvements, from Ralph Corderoy. Author: Ken Hornstein Date: Sun Apr 20 18:08:47 2014 -0400 Move clsfolds() before the call to context_save(); that is required when using private sequences, since seq_save() only moves the sequence information into the context structure; a subsequent call to context_save() is required to actually write out the context file. Author: Ken Hornstein Date: Sun Apr 20 00:02:26 2014 -0400 Sigh. Of course I find another bug after I release RC2. Make sure to initialize the enclosing CT structure when creating a message/external-body part. Author: Ken Hornstein Date: Fri Apr 18 10:57:27 2014 -0400 Remove support for a "*" in alias files (which would add everyone in the password file to the alias). Author: Ken Hornstein Date: Fri Apr 18 10:44:19 2014 -0400 Remove msh(1). Author: Ken Hornstein Date: Fri Apr 18 10:03:27 2014 -0400 Remove mhtest(8). Author: Ken Hornstein Date: Fri Apr 18 09:30:22 2014 -0400 Remove conflict(8). Author: Ken Hornstein Date: Fri Apr 18 09:20:42 2014 -0400 Remove -queue support to post; it is now officially obsolete. Author: Ken Hornstein Date: Fri Apr 18 08:43:37 2014 -0400 Fix the same problem in scan that was fixed in commit 9eb9b47593181a3bf987eeaa0398ab5330ec12f8, but fix it for Maildir support. Patch from Eric Gillespie. Author: David Levine Date: Thu Apr 17 19:55:19 2014 -0500 Unset MAILDROP in test/common.sh so that it doesn't confuse test/inc/test-msgchk. Author: Ken Hornstein Date: Wed Apr 16 11:46:55 2014 -0400 Sigh. Mention that we have to do both a "git push" and a "git push --tags". Author: Ken Hornstein Date: Wed Apr 16 11:44:48 2014 -0400 Mention release branchpoint tagging. Author: David Levine Date: Tue Apr 15 21:57:30 2014 -0500 Fixed popsbr.c to look like its nmh 1.5 version, except it now uses nmh_get_credentials() instead of ruserpass() directly. Also, added checks of return values of nmh_get_credentials() to smtp.c. Author: David Levine Date: Tue Apr 15 21:10:41 2014 -0500 Consistently refer to $HOME/.mh_profile and mh-profile(5) in the man pages. Author: David Levine Date: Tue Apr 15 20:58:32 2014 -0500 Reworked retrieval of username and password with SMTP and sasl so that if getusername() and no password are accepted by the mechanism, then the user need not provide them. Author: Paul Fox Date: Tue Apr 15 21:39:38 2014 -0400 docs/contrib/ml: add a runtime check for known bash-ism i'm leaving the #! line as /bin/bash, because that's how i wrote and tested. but with this change i think the script will still function correctly on a wide variety of shells. Author: Ken Hornstein Date: Mon Apr 14 21:32:41 2014 -0400 It turns out that due to the changes to m_getfld() to support file position tracking, this broke the scan output from inc(1) when POPing more than one message at a time. Since a new filehandle was being passed to each call to scan(), it made the most sense to simply discard the m_getfld() state for each call to scan() when doing POP. Author: Paul Fox Date: Mon Apr 14 12:29:39 2014 -0400 replyfilter: flesh out the configuration instructions Author: Ken Hornstein Date: Mon Apr 14 11:58:54 2014 -0400 Updating release notes for new release. Author: Ken Hornstein Date: Mon Apr 14 09:57:59 2014 -0400 Update for post-1.6. Author: Ken Hornstein Date: Sun Apr 13 23:09:54 2014 -0400 Update these a bit. Author: Ken Hornstein Date: Sun Apr 13 23:07:45 2014 -0400 Add README-iCalendar to the distribution. Author: Ken Hornstein Date: Sun Apr 13 23:02:57 2014 -0400 Update developer documentation to match reality. Author: Ken Hornstein Date: Sun Apr 13 22:37:53 2014 -0400 If attaching a "message" content type, scan the content to see if it has 8bit characters and set the CTE on the enclosing MIME headers appropriately. Author: Ken Hornstein Date: Sun Apr 13 22:36:34 2014 -0400 Create a default CTE so routines in mhparse.c are happy. Author: Ken Hornstein Date: Sun Apr 13 22:17:23 2014 -0400 Make sure the draft filename ends up in the MIME structure, so error messages have the proper name in them. Author: Paul Fox Date: Sun Apr 13 16:18:07 2014 -0400 add rmf(1) and folder(1) to one another's SEE ALSO sections Author: David Levine Date: Sun Apr 13 15:13:21 2014 -0500 If mhfixmsg's call to convert_charset() fails, output why. Author: Ken Hornstein Date: Sun Apr 13 13:11:00 2014 -0400 If c_termproc is set, include a default display command so the charset conversion pipeline will work correctly. Author: David Levine Date: Fri Apr 11 17:20:02 2014 -0500 Fixed showproc for RFC 822 messages. Thanks to Mikhail for pointing this out. Author: Paul Fox Date: Fri Apr 11 15:55:54 2014 -0400 mhshow: properly report the name of a failing display program otherwise it's not clear what didn't work. Author: David Levine Date: Thu Apr 10 21:21:28 2014 -0500 If -[no]concat is given to show(1), have it use showmimeproc instead of showproc and pass those switches along. This way, show won't pass them to mhl, which doesn't accept them. Merge: 4c82793 236a2b6 Author: Lyndon Nerenberg Date: Thu Apr 10 18:49:18 2014 -0700 Merge branch 'master' of ssh://git.sv.gnu.org/srv/git/nmh Author: Lyndon Nerenberg Date: Thu Apr 10 18:47:43 2014 -0700 Add a note about devel/autotools as a pre-req for building on FreeBSD. Be a bit more specific about the versions of some OSes we build in the buildbot cluster. Author: Ken Hornstein Date: Thu Apr 10 21:45:14 2014 -0400 Use a dynamically-allocated buffer for character set conversion, and resize it if we get E2BIG. Also create a test that exercises this particular problem. Author: Ken Hornstein Date: Thu Apr 10 18:58:39 2014 -0400 Don't clobber "cp"; use dp instead. Author: Ken Hornstein Date: Thu Apr 10 14:09:18 2014 -0400 Fix bug in error message when reporting character set conversion failure. Author: Ken Hornstein Date: Thu Apr 10 12:29:28 2014 -0400 A bad cut-and-paste job made -noinlineonly not work. Patch from M. Levinson. Author: Ken Hornstein Date: Thu Apr 10 12:28:01 2014 -0400 Fix test for inlineonly. Author: David Levine Date: Thu Apr 10 07:52:41 2014 -0500 Added -dump to w3m and elinks invocations in mhn.defaults. Author: Lyndon Nerenberg Date: Thu Apr 10 04:10:34 2014 -0700 When lkfopendata() fails, seqfile is being freed too soon. Author: Lyndon Nerenberg Date: Thu Apr 10 04:00:18 2014 -0700 I missed one spot in getln() where the new quoting flag needs to be cleared. Author: Lyndon Nerenberg Date: Thu Apr 10 03:52:17 2014 -0700 If getln() sees a newline as its first character, it incorrectly references a character one byte before the start of its input buffer. Author: Lyndon Nerenberg Date: Thu Apr 10 03:07:16 2014 -0700 Clang's static analyzer reports a potential NULL pointer deref. This is a "shouldn't happen" case, so I have added an assert to quell the warning, and catch the failure in the off chance we do get here with last == NULL. Author: Lyndon Nerenberg Date: Thu Apr 10 02:43:36 2014 -0700 Remove dead initialization of fp in main(). Author: David Levine Date: Wed Apr 9 22:04:58 2014 -0500 Added -dump (and -child) to lynx invocation when it's used in mhshow-show-text/html. Author: Ken Hornstein Date: Wed Apr 9 21:05:07 2014 -0400 Formatting fix, from Mikhail . Merge: 6e94720 d6e398f Author: David Levine Date: Wed Apr 9 19:19:26 2014 -0500 Merge remote-tracking branch 'origin/fix-locking' Author: David Levine Date: Wed Apr 9 16:32:56 2014 -0500 The size reported by mhshow test-charset is different with and without iconv, so determine it at runtime. Author: David Levine Date: Wed Apr 9 16:31:06 2014 -0500 Use *ct->c_ceclosefnx() instead of clsoe_encoding() in show_content_aux(). Merge: 1f29440 e6ddebc Author: Ken Hornstein Date: Wed Apr 9 16:25:08 2014 -0400 Merge branch 'mhshow-fixup' Author: Ken Hornstein Date: Wed Apr 9 16:24:34 2014 -0400 Document and distribute mhshow.marker Author: Ken Hornstein Date: Wed Apr 9 16:16:18 2014 -0400 Document the changes made to mhshow. Author: Ken Hornstein Date: Wed Apr 9 14:53:00 2014 -0400 Change from "concat" to "concatsw" so we don't conflict with the function concat(). Author: Ken Hornstein Date: Wed Apr 9 13:30:42 2014 -0400 Add new flags for -concat/-noconcat, -inlineonly/-noinlineonly, and -textonly/-notextonly; Author: Ken Hornstein Date: Wed Apr 9 13:15:28 2014 -0400 Change things so we only supply a form filename; most programs don't do both, and this isn't work the extra hassle. Author: Ken Hornstein Date: Wed Apr 9 11:29:32 2014 -0400 Now only display text and inline content by default. Use mh-format(5) to display marker text for skipped content. Author: David Levine Date: Tue Apr 8 21:34:20 2014 -0500 lkopen_dot() would block forever if another process held a lock forever. Changed it to only retry for 60 seconds, like the other lkopen's. And have it indicate that it failed to acquire the lock. Author: David Levine Date: Sun Apr 6 13:55:27 2014 -0500 Instead of relying on errno to determine if locking failed, pass back explicit indication in int * argument to lk(f)opendata() and lkopenspool(). Author: David Levine Date: Sun Apr 6 11:12:14 2014 -0500 Don't ignore return value of lkfopendata(), most notably of seq_read() in folder_read(). Increased LOCK_RETRIES from 5 to 60. Author: David Levine Date: Fri Apr 4 20:05:51 2014 -0500 Update context and sequences before showing messages in mhn(1), just like in mhshow(1). Author: Ken Hornstein Date: Thu Apr 3 18:12:56 2014 -0400 Moving closer to fixing mhshow completely. Includes fix from David Levine for a slight bug in charset conversion. Author: Ken Hornstein Date: Tue Mar 25 22:41:13 2014 -0400 Start of changes for mhshow; compiles, but does nothing (yet). Author: David Levine Date: Sun Mar 23 08:43:56 2014 -0500 mhn.defaults.sh really doesn't need to look in /usr/demo/SOUND for helper programs any more. If the user has it in their PATH, it will anyway. Author: David Levine Date: Sun Mar 23 08:30:37 2014 -0500 Added mhshow-show-application/pdf detection to mhn.defaults.sh. Author: David Levine Date: Sun Mar 23 08:00:12 2014 -0500 Note that order is preserved for messages that have the same date, when sorting on dates. Author: Ken Hornstein Date: Fri Mar 21 18:53:26 2014 -0400 Move pidcheck() into mhshowsbr.c (the only consumer of it) and make it static. Author: Ken Hornstein Date: Fri Mar 21 14:22:58 2014 -0400 Remove support for -pause/-nopause switches to mhshow(1). This and commit 4c436246f048635446353dadaa68174445c58160 are based on work originally done by Markus Schnalke. Author: Ken Hornstein Date: Fri Mar 21 12:56:37 2014 -0400 Remove support for parallel content display. This means we can finally drive a stake in the heart of the horrible xpid global! Author: David Levine Date: Thu Mar 20 09:40:01 2014 -0500 Fixed quoting of charset value in mhn.defaults.sh. Author: David Levine Date: Sun Mar 16 15:03:37 2014 -0500 Renamed mkstemp(1) man page to mh-mkstemp(1), so it doesn't obscure any existing mkstemp(3) page. Author: Lyndon Nerenberg Date: Sun Mar 16 12:19:54 2014 -0700 Update the manpage style guide to be consistent about setting program names in boldface always. Author: David Levine Date: Sun Mar 16 10:40:27 2014 -0500 Fixed formatting of program name in mh-mime(7) man page. Removed CONTEXT section from mkstemp(1) man page. Author: David Levine Date: Sun Mar 16 10:15:41 2014 -0500 Moved "mhparam iconv" description to mhparam(1) man page and put references to it in mh-mime(7), mhfixmsg(1), and mhshow(1) man pages. Updated mhparam man page description of other configuration parameters. Added "Message Rewrite" section to mh-mime page. Author: David Levine Date: Fri Mar 14 20:25:06 2014 -0500 Fixed some of the issues noted by clang --analyze with mhfixmsg.c and mkstemp.c. Author: David Levine Date: Fri Mar 14 20:22:07 2014 -0500 Fixed fixup of sbr/dtimep.c with flex 2.5.36. Author: David Levine Date: Fri Mar 14 19:56:38 2014 -0500 Modified probe to output sbr/dtimep.c. The flex version is 2.5.36. Author: David Levine Date: Fri Mar 14 19:16:23 2014 -0500 Added probe to configure.ac to output flex version (for fed18arm7 build). Author: David Levine Date: Fri Mar 14 19:04:45 2014 -0500 Compare character with EOF using signed comparison because EOF can be (and is likely) negative. This showed up on arm7, which apparently uses unsigned char for char. Author: Ken Hornstein Date: Fri Mar 14 15:22:12 2014 -0400 Sigh. Make localmbox work even if we're not using -debug. Author: Ken Hornstein Date: Fri Mar 14 15:21:49 2014 -0400 Whoops, missed a warning groff found. Author: Ken Hornstein Date: Fri Mar 14 14:59:39 2014 -0400 Fix some typos and make some style changes suggested by Ralph Corderoy Author: Ken Hornstein Date: Fri Mar 14 12:31:23 2014 -0400 Add support for printing iconv and localmbox. Author: Ken Hornstein Date: Thu Mar 13 15:53:05 2014 -0400 Update for mh-mime. Author: Ken Hornstein Date: Thu Mar 13 15:51:32 2014 -0400 Create new mh-mime man page, with overview of how MIME handling works in nmh. Author: Ken Hornstein Date: Thu Mar 13 15:11:22 2014 -0400 Update and fix some formatting issues. Author: David Levine Date: Mon Mar 10 20:26:51 2014 -0500 Fixed test-mkstemp to work on platforms that don't have mkstemps(3), such as CentOS 5. Author: David Levine Date: Mon Mar 10 20:24:46 2014 -0500 Check for text/html display programs in this order: w3m, lynx, elinks. Author: Ken Hornstein Date: Fri Mar 7 12:04:46 2014 -0500 Fix minor typo. Author: Lyndon Nerenberg Date: Fri Mar 7 09:05:17 2014 -0800 Import Dave Crocker's brief history of email development at Rand. (Added with his permission.) Author: David Levine Date: Thu Mar 6 20:32:14 2014 -0600 Fixed test/getcwidth.c to build without MULTIBYTE_SUPPORT. Found by cppcheck. Author: David Levine Date: Thu Mar 6 20:15:45 2014 -0600 Fixed a few very minor issues that cppcheck noticed. Author: David Levine Date: Thu Mar 6 19:46:30 2014 -0600 Removed declaration of unused sm_reply from post.c. Author: David Levine Date: Thu Mar 6 19:45:37 2014 -0600 Made a couple of globals static in smtp.c. Author: David Levine Date: Thu Mar 6 19:43:47 2014 -0600 Changed unused symbol that gen-ctype-checked creates with NDEBUG from a data object to a function, to remove a global from libmh.a. Author: David Levine Date: Thu Mar 6 19:39:10 2014 -0600 Added remedy for compile warnings when built with --with-tls on Mac OS 10.7 or later. Author: David Levine Date: Thu Mar 6 19:35:22 2014 -0600 Remove backup file at end of test-ext-params, and a temp file. Author: Ken Hornstein Date: Thu Mar 6 15:45:19 2014 -0500 Put in check so "attach" is rejected when the draft already has MIME headers. Author: Ken Hornstein Date: Thu Mar 6 15:31:01 2014 -0500 Update test to match reality Author: Ken Hornstein Date: Thu Mar 6 15:25:55 2014 -0500 Update documentation to match reality. Author: Ken Hornstein Date: Thu Mar 6 14:59:35 2014 -0500 Prevent crash if editfile() is called and both "*ed" and editsave are NULL. This can happen if you call "mime" and then run "edit" without any arguments, if you're running whatnow standalone. Author: Ken Hornstein Date: Thu Mar 6 14:34:34 2014 -0500 Remove unneeded assignment. Author: Ken Hornstein Date: Wed Mar 5 23:31:31 2014 -0500 Fix up some warnings and problems when iconv doesn't exist. Merge: 7b9cb49 5c3a50d Author: Ken Hornstein Date: Wed Mar 5 23:17:17 2014 -0500 Merge branch 'extended-params' Author: Ken Hornstein Date: Wed Mar 5 21:27:25 2014 -0500 Update pending-release-notes. Author: Ken Hornstein Date: Wed Mar 5 21:26:02 2014 -0500 More tests for extended-parameter parsing. Author: Ken Hornstein Date: Wed Mar 5 18:22:56 2014 -0500 Add extra argument to add_param() so it can use the passed-in pointers directly without making copies first. Author: Ken Hornstein Date: Wed Mar 5 15:43:33 2014 -0500 A more complicated RFC 2231 parsing example. Author: Ken Hornstein Date: Wed Mar 5 15:42:59 2014 -0500 Whoops, a little TOO hasty on the last bugfix; put back an assignment. Author: Ken Hornstein Date: Wed Mar 5 15:11:54 2014 -0500 Switch over to using the token parser instead of isspace(), and make sure we have our pointer correct when doing an encoded parameter that isn't the first one. Author: Ken Hornstein Date: Wed Mar 5 14:36:43 2014 -0500 Move language tag parser into the block so it only gets invoked on index 0. Author: Ken Hornstein Date: Wed Mar 5 14:04:47 2014 -0500 Change disposition output slightly. Author: Ken Hornstein Date: Wed Mar 5 13:48:45 2014 -0500 Update information to mention RFC 2231. Author: Ken Hornstein Date: Wed Mar 5 13:40:13 2014 -0500 Add message/external-body test. Author: Ken Hornstein Date: Wed Mar 5 13:03:30 2014 -0500 Update mhlist and other relevant utilities to output disposition information with a new -disposition switch. Author: Ken Hornstein Date: Tue Mar 4 23:44:09 2014 -0500 Some tests for RFC 2231 decoding; seems like it works, but need to stress it some more. Author: Ken Hornstein Date: Tue Mar 4 23:43:26 2014 -0500 Fix up some error reporting, and reassemble partial parameters correctly. Author: Ken Hornstein Date: Tue Mar 4 22:49:13 2014 -0500 Fix up a few pointer mishaps; this should now get everything right! Author: Ken Hornstein Date: Tue Mar 4 22:37:10 2014 -0500 Whoops, forgot to set the name element of the partial parameter structure. Author: Ken Hornstein Date: Tue Mar 4 19:53:23 2014 -0500 A few minor fixups; the parser now passes the test suite! Author: Ken Hornstein Date: Tue Mar 4 13:45:19 2014 -0500 Fixes for the MIME parser; kinda works for regular parameters, but still needs some fixes. Author: Ken Hornstein Date: Mon Mar 3 21:52:35 2014 -0500 More work on extended parameter parser. Does not compile yet. Author: David Levine Date: Mon Mar 3 07:14:09 2014 -0800 In test/common.sh.in trap, cd to $MH_TEST_DIR before trying to remove its Mail subdirectory. rm on Solaris won't remove it if it's in the path of the current working directory. Author: Ken Hornstein Date: Mon Mar 3 00:43:46 2014 -0500 Make parse_header_attrs() a private function (there are no longer any public consumers of it). Author: Ken Hornstein Date: Mon Mar 3 00:42:56 2014 -0500 Convert unqp() to decode_qp(), and make it a public function. Also, handle the case where decode_qp() is passed a character outside of the normal ASCII range. Author: David Levine Date: Sun Mar 2 22:38:57 2014 -0600 Added mkstemp(1), wrapper around mkstemp(3)/mkstemps(3), to auxexec, for use by mhmail. Author: David Levine Date: Sun Mar 2 20:29:20 2014 -0600 Added convenience function die() to mhmail. Author: Ken Hornstein Date: Sun Mar 2 21:04:55 2014 -0500 Switch over get_ctinfo() to determine the filename based on the filename if one was not provided. Remove some unneeded functions as part of this work. Author: David Levine Date: Sun Mar 2 12:00:13 2014 -0600 Added recommendation to use nmh-storage profile setting or non-default -clobber with mhstore -always. Author: David Levine Date: Sun Mar 2 10:09:18 2014 -0600 Added check of -noverbose to test-mhstore. Author: David Levine Date: Sun Mar 2 09:30:01 2014 -0600 Added commented explaining use of ci_attrs[0] in build_multipart_alt() of mhfixmsg. Author: Ken Hornstein Date: Sun Mar 2 00:07:10 2014 -0500 Whoops, forgot to TEST THIS OUT first. Author: Ken Hornstein Date: Sun Mar 2 00:06:13 2014 -0500 For some reason viamail listed mhoutsbr as a dependency. It turned out it wasn't required, so we removed it so we don't have to pull in a complete MIME parser into viamail. Author: Ken Hornstein Date: Sat Mar 1 23:51:19 2014 -0500 More cleaned and conversion to the new parameter API. Author: Ken Hornstein Date: Sat Mar 1 23:24:47 2014 -0500 Add a new get_param_value(); redo iconv() parameter conversion code. Start having code use get_param() and get_param_value() rather than walking the whole parameter linked list. Author: David Levine Date: Sat Mar 1 13:55:24 2014 -0600 Removed recommendation from mhstore man page that users not put -auto in their profile. Added recommendation that users not use the %a escape string. Author: David Levine Date: Sat Mar 1 13:30:50 2014 -0600 Added description of switches. Author: David Levine Date: Sat Mar 1 12:00:18 2014 -0600 mhstore(1) now obeys its -noverbose switch. Author: David Levine Date: Sat Mar 1 08:32:20 2014 -0600 Fix to commit a2806483a53fcdb62ca8e2bec4f4e023355f4470 to properly handle quoting when text follows quoted text in a mhshow display string. Author: David Levine Date: Sat Mar 1 08:30:27 2014 -0600 Moved discussion when no messages are matched from BUGS section to new subsection under DESCRIPTION, per Ralph's suggestion. Author: David Levine Date: Fri Feb 28 22:59:09 2014 -0600 Removed a couple of unnecessary vector typedefs from h/mh.h. Author: David Levine Date: Fri Feb 28 22:05:37 2014 -0600 Updated MACHINES and SPECS/nmh.spec to reflect packages available for CentOS Linux. Author: Ken Hornstein Date: Thu Feb 27 21:43:18 2014 -0500 Fix iconv return value test warning. Author: Ken Hornstein Date: Thu Feb 27 21:38:09 2014 -0500 Support complete encoding for encoding Content-Type parameters. Start work on retrieving parameters and converting them to the correct charset. Author: Ken Hornstein Date: Thu Feb 27 11:50:33 2014 -0500 Use RFC 2047 encoding for Content-Description, and make sure to encode MIME parameters correctly when building the Content-Disposition header. Author: Ken Hornstein Date: Wed Feb 26 22:58:26 2014 -0500 Re-do length calculation for parameter output, and adapt test for new code. Author: David Levine Date: Wed Feb 26 21:48:29 2014 -0600 Fixed quoting of filename, expanded C-T parameter values, etc., in mhshow. Removed the workarounds that had built up when it was broken. Author: Ken Hornstein Date: Wed Feb 26 21:13:30 2014 -0500 Closer, but not quite right yet. Author: David Levine Date: Wed Feb 26 19:58:43 2014 -0600 Updated mhparam, man pages, and test-mhparam to reflect split of locking methods into datalocking and spoollocking. Author: Ken Hornstein Date: Tue Feb 25 21:31:18 2014 -0500 Add test for long + encoded line; does not pass right now. Author: Ken Hornstein Date: Tue Feb 25 21:30:52 2014 -0500 Make sure we include space in the list of characters we need to encode in a parameter line. Author: Ken Hornstein Date: Tue Feb 25 21:28:45 2014 -0500 Remove unused variable, and make sure we free c_dispo_type. Author: Ken Hornstein Date: Tue Feb 25 21:15:51 2014 -0500 A new test for longer lines. Author: Ken Hornstein Date: Tue Feb 25 21:14:51 2014 -0500 Calculate "characters to use in for current line" based on starting a new line, rather than the number of characters in the previous line. Author: Ken Hornstein Date: Tue Feb 25 15:23:56 2014 -0500 First basic test of extended parameter output: working! Author: Ken Hornstein Date: Mon Feb 24 21:34:12 2014 -0500 Beginnings of test suite for RFC 2231 support; does not work yet. Author: David Levine Date: Mon Feb 24 20:18:17 2014 -0600 Fixed m_getfld() to not return EOF indicator, so that files need not end with a newline. Author: Ken Hornstein Date: Mon Feb 24 13:39:19 2014 -0500 Make sure we don't modify the original text when processing the disposition header. Author: David Levine Date: Sun Feb 23 18:52:52 2014 -0600 Added mh-folders to nmh(7) man page. Split out Formats section of nmh man page. Author: Ken Hornstein Date: Sun Feb 23 21:29:52 2014 -0500 Fix up error reporting for the hook code. Author: Ken Hornstein Date: Sat Feb 22 00:07:55 2014 -0500 It compiles now! And actually sort of works, but still a LOT more that needs to be done before it is complete. Author: Ken Hornstein Date: Fri Feb 21 14:49:07 2014 -0500 Getting closer to getting something working. Author: Ken Hornstein Date: Thu Feb 20 14:55:01 2014 -0500 More work on handling encoded params; still does not compile. Author: David Levine Date: Wed Feb 19 22:01:45 2014 -0600 Cast argument to isspace() to unsigned char instead of int. Author: David Levine Date: Wed Feb 19 21:55:19 2014 -0600 Fix to commit ed3214f1518b36c8b96a1a17be4af0a708ea25e3 to not try to quote filenames in multipart parts. Author: David Levine Date: Wed Feb 19 21:36:16 2014 -0600 Generalized %{charset} display string escape to any Content-Type parameter. Also, always quote the expanded value, whether or not the escape was quoted in the profile. Author: David Levine Date: Wed Feb 19 20:09:28 2014 -0600 Added reason to mhfixmsg's printout when it fails to decode binary content. Author: David Levine Date: Wed Feb 19 18:57:29 2014 -0600 Refined commit ed3214f1518b36c8b96a1a17be4af0a708ea25e3 to only accept single quotes wrapping %f and %F display escapes. Author: David Levine Date: Tue Feb 18 21:26:52 2014 -0600 Migrated show_content_aux2() to argsplit(). Author: David Levine Date: Tue Feb 18 21:16:06 2014 -0600 Removed redundant quoting of %f and %F in display strings. Now, the code checks to see if those escapes are quoted before quoting them. Removed quoting of them in mhn.defaults.sh because it isn't (and wasn't) necessary. Author: David Levine Date: Tue Feb 18 19:16:39 2014 -0600 Removed leading "exec " inserted in show_content_aux2(), which allows use of shell expansion on Content-Type parameters in mhshow display straings. Author: Ken Hornstein Date: Tue Feb 18 12:38:06 2014 -0500 Fix for bug #41618: Supply charset to w3m when converting text/html parts. Author: David Levine Date: Tue Feb 18 07:54:37 2014 -0600 Silenced warnings when built without iconv. Author: David Levine Date: Sun Feb 16 15:25:34 2014 -0600 Added MH libdir to PATH in test-textcharset because it uses ap. Author: David Levine Date: Sun Feb 16 14:12:15 2014 -0600 Removed remaining TMP relics missed with commit d046c8f0992fddcd69f2172a6607a14dec3b1251. Also, have mhmail clean up a .orig tmp file, now that it always uses mhbuild. Author: David Levine Date: Sun Feb 16 13:12:39 2014 -0600 Added support for %{charset} display string escape to mhshow(1). Author: David Levine Date: Sun Feb 16 11:30:41 2014 -0600 Factored out duplicate code into parse_display_string() function. Author: David Levine Date: Sun Feb 16 10:26:34 2014 -0600 Instead of printing PostScript attachments, by default, from mhshow, try to find a suitable viewer. Author: David Levine Date: Sun Feb 16 10:06:47 2014 -0600 Added associations to mhn.defaults.sh from http://technet.microsoft.com/en-us/library/cc179224.aspx. Author: Ken Hornstein Date: Wed Feb 12 15:41:39 2014 -0500 More extended parameter work. Still non-functional. Author: Ken Hornstein Date: Wed Feb 12 15:41:04 2014 -0500 Move contains8bit() to a common file, and make it a bit more general. Author: Ken Hornstein Date: Tue Feb 11 23:17:00 2014 -0500 Beginnings of RFC 2231 support. Does not compile (yet). Author: David Levine Date: Mon Feb 10 23:17:28 2014 -0600 Removed the -[no]textcharset switches that were added to mhshow(1) in commit 721b0395fb2fceac4e66fed1009ed2f17fd5351f. They weren't needed. So the net effect is that, if built with iconv, mhshow will attempt to convert text/plain content to match the user's locale. Author: David Levine Date: Sun Feb 9 12:52:28 2014 -0600 Use test_skip in test-textcharset if not built with iconv. Author: David Levine Date: Sun Feb 9 10:32:46 2014 -0600 Need to set locale to something other than UTF-8 on Cygwin for the first couple of checks in test-textcharset. Author: David Levine Date: Sun Feb 9 09:59:23 2014 -0600 Removed potential buffer overflow from ruserpass(). It had been there a long time. Also, move the tokval buffer from global data to the stack. Author: David Levine Date: Sun Feb 9 09:58:00 2014 -0600 Added -[no]textcharset switches to mhshow(1). These only apply if nmh was configured with iconv(3) support. If -textcharset is not used, mhshow will convert, if necessary, the charset of text/plain content to match the user's locale setting. Author: David Levine Date: Sun Feb 9 09:05:14 2014 -0600 Use $MH shortcut for the profile in a few of the tests. Author: David Levine Date: Sun Feb 9 08:56:42 2014 -0600 In test-mhfixmsg, look at configuration to see if iconv is enabled rather than detecting it from test output. Author: David Levine Date: Sat Feb 8 22:23:17 2014 -0600 Remove mhbuild backup files at end of a couple of tests, if successful. Author: David Levine Date: Sat Feb 8 21:38:18 2014 -0600 Changed "codeset" to "charset" for (and in) mhfixmsg. Also cleaned up some comments in mhshowsbr.c. Author: David Levine Date: Sat Feb 8 11:11:25 2014 -0600 Moved upcase(), update_attr(), content_charset(), and convert_charset() out of mhfixmsg.c so that other programs can use them. Author: Ken Hornstein Date: Fri Feb 7 15:53:35 2014 -0500 Start of changes to support extended parameter parsing and decoding. Author: Ken Hornstein Date: Wed Feb 5 13:05:21 2014 -0500 Fix uninitialized variable warning Author: Ken Hornstein Date: Wed Feb 5 11:02:01 2014 -0500 Adjust the quoted-printable output routine to continue when the end of the buffer is reached, rather than adding a soft line break. Author: Ken Hornstein Date: Tue Feb 4 15:09:12 2014 -0500 Add test for -maxunencoded. Author: Ken Hornstein Date: Tue Feb 4 14:54:16 2014 -0500 A few more C-T-E tests. Author: Ken Hornstein Date: Tue Feb 4 13:36:29 2014 -0500 Still more CTE tests to cover (hopefully) all of tbe base64 cases. Author: Ken Hornstein Date: Tue Feb 4 13:34:22 2014 -0500 More CTE tests. Author: Ken Hornstein Date: Tue Feb 4 12:38:34 2014 -0500 More fixes (and tests) for the base64 encoder. Author: Ken Hornstein Date: Tue Feb 4 11:49:49 2014 -0500 Add a new base64 CTE test. Author: Ken Hornstein Date: Tue Feb 4 11:19:24 2014 -0500 Fix encoder so at least one case of LF -> CR LF conversion happens correctly. Author: David Levine Date: Mon Feb 3 22:48:38 2014 -0600 Reordered a bit of code in signal handler. Noted in comment that NetBSD doesn't have mkstemps(3). Author: David Levine Date: Mon Feb 3 21:42:44 2014 -0600 Use rename(2), not link(2), in m_mktemps() if mkstemps() is not available. Author: Ken Hornstein Date: Mon Feb 3 21:46:33 2014 -0500 Add a new (but incomplete) test for mhbuild's new functionality. Author: Ken Hornstein Date: Mon Feb 3 21:46:08 2014 -0500 Fix up mhbuild so the character set is always output when needed, even when the CTE is specified. Author: Ken Hornstein Date: Mon Feb 3 21:45:41 2014 -0500 Document changes to mhbuild. Author: Ken Hornstein Date: Mon Feb 3 20:14:55 2014 -0500 Support for selectable Content-Transfer-Encoding. Now default to 8bit for CTE for text types. Author: David Levine Date: Sun Feb 2 22:34:14 2014 -0600 netbsd uses flock by default for mail spool locking, as reported by Robert Elz. Use *netbsd* to also include knetbsd, though I don't know for sure that it uses flock. Author: David Levine Date: Sun Feb 2 22:16:25 2014 -0600 Restored setuid/setgid to slocal: it needs them when run as root, as a mail delivery agent. Author: David Levine Date: Sun Feb 2 16:45:23 2014 -0600 Removed some unused code that forked /bin/mkdir to make a new directory if an the effective and real uids differed. There are no setuid executables in nmh. Author: David Levine Date: Sun Feb 2 09:58:45 2014 -0600 Removed all unnecessary setuid/setgid calls. Using setuid as an example and not showing the setgid analogues: 1) setuid(getuid()); This dropped privileges before an exec and is normally a good thing. Except here, the return value isn't checked. And, we don't have any setuid programs in nmh now, so it was unnecessary. 2) if (geteuid() == 0) setuid(pw->pw_uid); This would have been a security hole if the executable was setuid root because the user specifies the source of the pw data. This was in slocal(1), which is not setuid, so this was certainly not needed. 3) setuid(geteuid()); This was in post(8) for when it called the sendmail executable directly (-mts sendmail or -mts sendmail/pipe. It's not necessary with modern sendmail or replacements. Author: David Levine Date: Sun Feb 2 08:46:25 2014 -0600 Added m_mktemps(), which creates a temporary file with a specified suffix. It uses mkstemps(3) where available, which should be most modern platforms. If not available, it tries link(2), and if that fails, rename(2). Author: Ken Hornstein Date: Sat Feb 1 16:13:00 2014 -0500 Change mhstore test slightly to test canonical line ending handling for text MIME parts that are encoded with base64. Author: Ken Hornstein Date: Sat Feb 1 15:57:49 2014 -0500 Document changes to base64 encoder/decoder. Merge: 3235599 d722ee2 Author: Ken Hornstein Date: Sat Feb 1 12:48:20 2014 -0500 Merge branch 'base64-text-fixup' Author: David Levine Date: Sat Feb 1 11:32:53 2014 -0600 Removed set +e where not needed in test-mhfixmsg. Author: David Levine Date: Sat Feb 1 11:24:16 2014 -0600 Fixed test-mhfixmsg check attempted -decode of binary text to work with the fixed base64 decoder. Author: David Levine Date: Sat Feb 1 10:11:08 2014 -0600 Added note that suffixes were removed from filenames of temporary files. Author: David Levine Date: Sat Feb 1 10:09:13 2014 -0600 Look for w3m if lynx isn't available for mhshow-show-text. Author: David Levine Date: Sat Feb 1 10:11:08 2014 -0600 Added note that suffixes were removed from filenames of temporary files. Author: David Levine Date: Sat Feb 1 10:09:13 2014 -0600 Look for w3m if lynx isn't available for mhshow-show-text. Author: Ken Hornstein Date: Fri Jan 31 15:53:04 2014 -0500 Fix base64 to handle text parts properly; currently this breaks mhfixmsg, and I'm not sure why yet. Author: Ken Hornstein Date: Fri Jan 31 15:00:57 2014 -0500 Add -width when appropriate for this test. Author: Ken Hornstein Date: Wed Jan 29 15:56:01 2014 -0500 Beginnings of selectable CTE; allow specification in mhbuild directives, but it doesn't do anything quite yet. Author: David Levine Date: Tue Jan 28 21:36:05 2014 -0600 Unset LANG, LC_ALL, and LC_TYPE in common.sh so that the tests don't accidentally rely on any of the user's settings. Author: David Levine Date: Mon Jan 27 18:56:20 2014 -0600 mhl() needs to set invo_name, too. Author: David Levine Date: Mon Jan 27 12:53:03 2014 -0600 WhatNow needs to set invo_name so that switches are interpreted properly. Author: David Levine Date: Sun Jan 26 11:57:29 2014 -0600 No longer look at TMP environment variable for temporary file storage. Author: David Levine Date: Sun Jan 26 11:26:11 2014 -0600 Merge branch 'tmpfiles' Merge: 1468359 dd259aa Author: David Levine Date: Sun Jan 26 11:23:53 2014 -0600 Merge branch 'tmpfiles' Author: David Levine Date: Sat Jan 25 10:50:29 2014 -0600 Added unregister_for_removal(0) calls to the couple of children that don't exec() or _exit() after fork(). Author: David Levine Date: Sat Jan 25 10:04:19 2014 -0600 Replaced nearly all unlink(3) calls with m_unlink(). Author: David Levine Date: Sat Jan 25 09:26:13 2014 -0600 Restored the unlinks of temporary files immediately after their creation in rcvtty.c, now that we have m_unlink(). Author: David Levine Date: Sat Jan 25 09:15:05 2014 -0600 Replaced boilerplate at beginning of each nmh program with new nmh_init() function. It sets up an atexit() function and signal handlers so that all temporary files are removed when the program terminates, however that happens. It relies on a call in m_mktemp() to register each temporary file for removal. See new "nmh temporary files" section in README.developers and comments in m_mktemp.c. Author: David Levine Date: Fri Jan 24 21:10:03 2014 -0600 Removed 3 renames of temporary files in mhparse.c. They added unnecessary filename extensions to the temp files. They weren't good from a security standpoint and added a failure mode. Author: David Levine Date: Fri Jan 24 20:29:38 2014 -0600 Replaced use of mkstemp() with m_mktemp() in lock_file.c. Author: Ken Hornstein Date: Fri Jan 24 13:17:56 2014 -0500 Move uip/attach.c to sbr/mime_type.c; it was used by enough programs that it deserved to be in libmh. Author: Ken Hornstein Date: Fri Jan 24 12:38:03 2014 -0500 In my over-eager trimming I didn't realize the fallback code that used the mhshow-suffix configuration information to determine the MIME type was removed; put that back into mime_type(). Author: David Levine Date: Thu Jan 23 22:16:34 2014 -0600 Replaced use of mkstemp() with m_mktemp2() in header_fd() of rcvtty.c. It never would have worked, anyway, because it had 5 instead of 6 X's in the template. Author: Ken Hornstein Date: Thu Jan 23 21:48:24 2014 -0500 Switch from volatile char * to the more correct char *volatile. Author: David Levine Date: Thu Jan 23 19:58:41 2014 -0600 Separate export from assignment in test-dist and test-attach. Author: Ken Hornstein Date: Thu Jan 23 14:55:21 2014 -0500 Whoops, forgot to initialize the linked list next pointer to NULL. Author: Ken Hornstein Date: Thu Jan 23 14:55:06 2014 -0500 Make sure we include tiny.jpg we need for the test suite. Author: Ken Hornstein Date: Thu Jan 23 14:40:44 2014 -0500 Try to suppress warnings from changes (but why is this thing complaining about drft being clobbered now??) Author: Ken Hornstein Date: Thu Jan 23 14:24:35 2014 -0500 Hm, maybe I can't put environment variable assignments in front of functions? Author: Ken Hornstein Date: Thu Jan 23 14:01:53 2014 -0500 Whoops, forgot a newline. Merge: 05b74a0 18a3694 Author: Ken Hornstein Date: Thu Jan 23 13:35:31 2014 -0500 Merge branch 'mhbuild-always' Author: Ken Hornstein Date: Thu Jan 23 13:35:03 2014 -0500 Document changes to mhbuild and send. Author: Ken Hornstein Date: Thu Jan 23 00:34:18 2014 -0500 Garbage collect unused code. Author: Ken Hornstein Date: Thu Jan 23 00:32:18 2014 -0500 Remove automimeproc functionality; it's redundant now. Author: Ken Hornstein Date: Thu Jan 23 00:31:55 2014 -0500 Update the pending-release-notes for changes. Author: Ken Hornstein Date: Thu Jan 23 00:07:54 2014 -0500 Flesh out test-attach, and set it to run as part of the test suite. Author: Ken Hornstein Date: Wed Jan 22 18:59:07 2014 -0500 Fix mhmail so it works with the new world order. Author: Ken Hornstein Date: Wed Jan 22 15:22:07 2014 -0500 Convert whatnow over to using the new Attach header. Mark the old -attach switches as deprecated (and make them not show up in help). Still more documentation cleanup to do. Author: Ken Hornstein Date: Wed Jan 22 12:06:49 2014 -0500 Fixed this to use Attach instead of Nmh-Attachment. Author: David Levine Date: Tue Jan 21 22:09:49 2014 -0600 Added svector_find() function. Author: Ken Hornstein Date: Tue Jan 21 22:35:35 2014 -0500 Make viamail read the user's profile; this is required because sendsbr() wants to call mhbuild, which can be overridden via the user's profile (which is required for the test suite to work). Author: David Levine Date: Tue Jan 21 20:55:57 2014 -0600 Always check that mktemp()/mktemp2() succeeds before trying to use result. And if it fails, have the error message report the directory where the failed temporary file creation occurred. And, removed all chmod()'s of temporary files created by mktemp()/ mktemp2() because they set the umask to 077 before calling mkstemp(3). Author: David Levine Date: Tue Jan 21 20:51:00 2014 -0600 Expose get_temp_dir(). Author: David Levine Date: Tue Jan 21 20:50:11 2014 -0600 Enable asserts when debug is enabled, in build_nmh. Author: Ken Hornstein Date: Tue Jan 21 20:12:29 2014 -0500 Fix a bunch of tests for the mhbuild changes; still more to do. Author: David Levine Date: Mon Jan 20 21:08:47 2014 -0600 Replaced use of m_mktemp() with m_mktemp2() so that tmp files created by attach, burst, mhbuild, and post will be in the directory specified by the first non-null of {MHTMPDIR, TMPDIR, TMP, MH Path directory}. Author: David Levine Date: Mon Jan 20 21:07:08 2014 -0600 Removed remaining occurrences of char *tmp from uip/mh* programs. Author: David Levine Date: Mon Jan 20 20:53:10 2014 -0600 Expanded mhpath(1) man page discussion of its handling of out-of-range message numbers, and fixed a couple of formatting glitches. Author: David Levine Date: Mon Jan 20 10:52:07 2014 -0600 Use LC_ALL instead of LC_CTYPE in test-pick because LC_ALL has precendence. Author: David Levine Date: Mon Jan 20 10:31:16 2014 -0600 Fixed three LC_ALL settings: 1) Replaced en_US.ISO8859-1 with C because that's sufficient to show decoding with an invalid multibyte sequence. 2) Removed redundant LC_ALL=en_US.UTF-8; that is set for the entire test. 3) Removed the last en_US.ISO8859-1 because it hid what the test was trying to show. Author: Ken Hornstein Date: Mon Jan 20 01:27:15 2014 -0500 Remove autoconf checks for nl_langinfo() and langinfo.h Author: Ken Hornstein Date: Mon Jan 20 01:15:55 2014 -0500 Completely deprecate support for MM_CHARSET. Author: David Levine Date: Sun Jan 19 23:21:51 2014 -0600 Removed "tmp" from the uip/mh* programs, so that they no longer use the nmh-storage profile component for their tmp files. Or their invoname, but that will be taken care of later. Author: Ken Hornstein Date: Sun Jan 19 23:21:32 2014 -0500 Remove the --disable-locale configure option and make locale support unconditional. Author: Ken Hornstein Date: Sun Jan 19 13:47:07 2014 -0500 Document the -dist flag. Author: Ken Hornstein Date: Sun Jan 19 11:59:25 2014 -0500 Change error message so "Unknown error 0" doesn't get printed if there is an error parsing an address. Author: Ken Hornstein Date: Sun Jan 19 11:52:47 2014 -0500 Add a test for dist to make sure it works with headers that need RFC-2047 encoding. Author: David Levine Date: Sun Jan 19 10:48:14 2014 -0600 Updated MACHINES to show package requirements on Linux and Cygwin. Author: Ken Hornstein Date: Sun Jan 19 01:11:59 2014 -0500 Add support for not outputting any MIME headers when using dist. Author: Ken Hornstein Date: Sun Jan 19 00:50:49 2014 -0500 Allow mhbuild to work when the message body is empty. You know, that was actually a giant pain! Author: Ken Hornstein Date: Sat Jan 18 23:34:41 2014 -0500 Removed unused argument "file" to user_content(). Author: Ken Hornstein Date: Sat Jan 18 01:17:12 2014 -0500 Beginning of work to run mhbuild always. A bit more complicated than I originally expected. Author: Ken Hornstein Date: Sat Jan 18 00:38:39 2014 -0500 Explictly return the exit code, so we can portably guarantee that pidstatus() will return 0 on a successful command execution. Author: David Levine Date: Fri Jan 17 18:42:52 2014 -0600 Removed -a option from whatnow attach, in anticipation of removal of send -attachformat. Author: Ken Hornstein Date: Fri Jan 17 15:45:31 2014 -0500 Add support for -auto flag to mhbuild. Author: Ken Hornstein Date: Fri Jan 17 14:20:12 2014 -0500 Remove WHATNOW #ifdefs; that code was obsolete a long time ago. Author: David Levine Date: Thu Jan 16 21:48:01 2014 -0600 Moved readline check to after termcap/curses check in configure.ac. This way, $TERMLIB can be included in the readline check. That's neeed on CentOS 5.9. Author: David Levine Date: Thu Jan 16 19:55:58 2014 -0600 Moved readconfig() of mhn.defaults into construct_build_directive(). This way, platforms that don't define MIMETYPEPROC will display the proper directive with attach -v. Author: David Levine Date: Tue Jan 14 20:09:40 2014 -0600 Added check to get_file_info() in attach.c for failed fgets() call. It can happen on Cygwin for mysterious reasons, http://cygwin.com/faq/faq.html#faq.using.bloda. Author: David Levine Date: Tue Jan 14 19:39:42 2014 -0600 Removed the tests of attach -v -a from test-attach-detach, and added -prompt '' to try to get the test to pass on Mac OS X. Author: David Levine Date: Tue Jan 14 07:41:28 2014 -0600 Modified last check added to test-scan-multibyte so that it also works without iconv support. Author: David Levine Date: Mon Jan 13 20:29:19 2014 -0600 Skip the last check that I added to test-scan-multibyte if we don't have iconv support because it requires converting from ISO-8859-1 to UTF-8. Author: David Levine Date: Mon Jan 13 20:08:55 2014 -0600 In cpstripped(), check for negative return value from wcwidth(). Author: David Levine Date: Mon Jan 13 14:33:44 2014 -0800 Better fix for test-attach-detach on platforms without readline. Author: David Levine Date: Mon Jan 13 13:35:41 2014 -0800 Fixed build on Solaris by only checking for -Wno-unused-result with gcc. Author: David Levine Date: Sun Jan 12 12:18:47 2014 -0600 Hacked test-attach-detach to pass on Solaris. Author: David Levine Date: Sun Jan 12 11:45:16 2014 -0600 Final fix to test-attach-detach: on some platforms, there's no charset for a text/plain file. Author: David Levine Date: Sun Jan 12 11:32:11 2014 -0600 Really fix mode of file that's used in test-attach-detach. Author: David Levine Date: Sun Jan 12 11:26:07 2014 -0600 One final fix to test-attach-detach. Author: David Levine Date: Sun Jan 12 11:22:57 2014 -0600 Fixed test-attach-detach to work with any umask, and without readline. Author: David Levine Date: Sun Jan 12 10:18:20 2014 -0600 Added -v and -a switches to whatnow attach so the user can see the mhbuild directive that send(1) will use. Author: David Levine Date: Sat Jan 11 16:30:42 2014 -0600 Refined the POSTLINK used on OpenBSD so that it leaves the warnings, but capitalizes the "w" so that they don't color the buildbot waterfall. Author: David Levine Date: Sat Jan 11 16:00:14 2014 -0600 Refined the autoconf test for -Wno-unused-result so that it's only used where we need it (currently Ubuntu gcc 4.8.1 with -O2). Author: David Levine Date: Sat Jan 11 11:22:50 2014 -0600 Calculate port numbers in test suite based on uid so that different users can run the test suite on a host simultaneously. Author: David Levine Date: Sat Jan 11 11:02:19 2014 -0600 Updated Cygwin and Linux build notes. Author: David Levine Date: Sat Jan 11 11:01:21 2014 -0600 Added more .exe files to .gitignore. Author: David Levine Date: Sat Jan 11 10:15:27 2014 -0600 Work around OpenBSD 5.4 file(1), which reports the --mime-encoding of text files as "binary". Author: David Levine Date: Sat Jan 11 09:22:36 2014 -0600 Reworked attach to add charset to Content-Type string for text content. Author: David Levine Date: Sat Jan 11 08:09:20 2014 -0600 Changed how build_nmh deals with older mhparam that doesn't report SASL/TLS. Author: David Levine Date: Sat Jan 11 08:00:55 2014 -0600 Reorganized autoconf test for -Qunused-warnings so that it outputs something when configuring on any platform. Author: Ken Hornstein Date: Sat Jan 11 01:41:44 2014 -0500 Change test-mhmail so it can handle a MIMETYPEPROC that doesn't output the character set. Author: Ken Hornstein Date: Sat Jan 11 01:11:45 2014 -0500 Switch over to using --mime-type, since --mime seems to include a charset for non-text MIME types. Author: David Levine Date: Fri Jan 10 23:41:04 2014 -0600 Fixed POSTLINK (on OpenBSD) now that it doesn't use -Qunused-arguments. Author: Ken Hornstein Date: Sat Jan 11 00:32:54 2014 -0500 More tests, but not quite there yet. Author: Ken Hornstein Date: Fri Jan 10 13:31:05 2014 -0500 Don't error out if the message body is empty. Author: David Levine Date: Fri Jan 10 23:25:19 2014 -0600 Only add -Qunused-arguments to LDFLAGS if compiler is clang. Author: David Levine Date: Fri Jan 10 20:49:24 2014 -0800 Reworked LFLAGS hack for flex 2.5.35 and 2.5.36 to work on Ubuntu. And use sed instead of ed. Author: David Levine Date: Fri Jan 10 19:36:34 2014 -0600 No longer add -g or -s to LDFLAGS. autoconf handles -g. And "make install-strip" is the approved way to install stripped executables. Author: David Levine Date: Fri Jan 10 19:03:56 2014 -0600 Added -Wno-unused-result to silence warnings on Ubuntu. Author: Ken Hornstein Date: Fri Jan 10 00:45:38 2014 -0500 Make sure we use the 'short' filename and add newlines where appropriate. Author: Ken Hornstein Date: Thu Jan 9 23:17:25 2014 -0500 A bit closer, but don't run the test just yet. Author: Ken Hornstein Date: Thu Jan 9 16:03:21 2014 -0500 Preliminary Attach: header support. Untested just yet. Author: David Levine Date: Wed Jan 8 20:54:50 2014 -0600 OpenBSD 5 needs an other-libraries (fourth argument) to the AC_CHECK_LIB for SSL_library_init, because it doesn't automatically append -lcrypto when linking with -lssl. Author: David Levine Date: Wed Jan 8 20:14:57 2014 -0600 Hard-code the config/version.c target, instead of using $@, so its rule works for the distcheck target with Solaris (System V) make. distcheck uses VPATH, causes that make to prepend the VPATH to $@. Author: David Levine Date: Wed Jan 8 19:02:58 2014 -0600 Replace use of awk with sed in test-anno because it failed on Solaris (gawk). Author: David Levine Date: Wed Jan 8 18:23:10 2014 -0600 Detect whether or not to use -n with tail in build_nmh. Synched that to uip/mhmail. Author: David Levine Date: Tue Jan 7 22:51:41 2014 -0600 Fixed typo in last commit of test-curses. Author: David Levine Date: Tue Jan 7 22:49:51 2014 -0600 Added -Txterm-color to tput invocations that didn't have it. Author: David Levine Date: Tue Jan 7 22:27:55 2014 -0600 In test-curses, use termcap codes if terminfo capabilities are not supported, such as on FreeBSD 9. Author: David Levine Date: Tue Jan 7 20:18:52 2014 -0600 Added sbr/dtimep.c to CLEANFILES so that make distcheck passes on FreeBSD 9. Author: David Levine Date: Tue Jan 7 19:51:58 2014 -0600 Clarified advisory message it test-mhfixmsg if a text browser isn't available. Author: Ken Hornstein Date: Tue Jan 7 23:15:39 2014 -0500 Update this for From, Resent-From, and Envelope-From. Also document Attach even though the code hasn't been written yet. Author: Ken Hornstein Date: Tue Jan 7 11:45:24 2014 -0500 Prevent message status allocation code from overflowing if we get a message number that is too high; simply abort instead. Author: David Levine Date: Mon Jan 6 20:49:18 2014 -0600 Replaced hidden make_mime_composition_file_entry() used by attach() with public construct_build_directive(). Author: David Levine Date: Mon Jan 6 19:14:20 2014 -0600 Here's a better fix for the whatnow tests: set and export TERM at the beginning of each test so that valgrind can be supported. Author: David Levine Date: Mon Jan 6 11:30:42 2014 -0600 Removed remaining run_prog's from tests that set an environment variable. Author: Ken Hornstein Date: Mon Jan 6 11:20:47 2014 -0500 Add a test for the new curses-based format escapes. Author: David Levine Date: Sun Jan 5 14:48:18 2014 -0600 Fixed description of send -attach switch in whatnow: its argument is the header file name, not a filename. Author: David Levine Date: Sun Jan 5 10:01:48 2014 -0600 Removed remaining globals in uip/attach.c. Author: David Levine Date: Sun Jan 5 09:51:53 2014 -0600 Got rid of a couple of globals used by attach get_line(). Author: David Levine Date: Sun Jan 5 09:39:11 2014 -0600 Moved the functions that implement whatnow attach from uip/sendsbr.c to new uip/attach.c. Author: David Levine Date: Sun Jan 5 08:28:58 2014 -0600 In whatnow help, don't show that detached can be abbreviated with "de", because that conflicts with "delete". Author: Ken Hornstein Date: Sat Jan 4 20:44:21 2014 -0500 Whoops, I'm supposed to NUL-terminate the string, not set the actual pointer itself! Author: Ken Hornstein Date: Sat Jan 4 14:01:58 2014 -0500 Make sure scan.curses is installed & distributed. Author: Ken Hornstein Date: Sat Jan 4 00:59:38 2014 -0500 Support for sending color escape sequences retrieved from terminfo(5). Author: Ken Hornstein Date: Fri Jan 3 15:55:10 2014 -0500 Add support for %(hascolor), and a new function for parameterized terminfo capabilities. Author: Ken Hornstein Date: Fri Jan 3 14:40:35 2014 -0500 Document %(nodate), and update things a bit. Author: Ken Hornstein Date: Fri Jan 3 11:43:16 2014 -0500 Garbage collect some Autoconf cruft that has been around a lot longer than necessary. Author: Ken Hornstein Date: Fri Jan 3 11:06:29 2014 -0500 Also make sure outc() uses TPUTS_PUTC_ARG. Author: Ken Hornstein Date: Fri Jan 3 11:05:18 2014 -0500 Whoops, I forgot that AC_CACHE_CHECK calls AC_MSG_RESULT. Author: Ken Hornstein Date: Fri Jan 3 10:44:59 2014 -0500 Create an autoconf test to determine the argument of the tputs() callback. Author: Ken Hornstein Date: Fri Jan 3 09:27:39 2014 -0500 Remove checks for termcap.h and ncurses/termcap.h, since we're not using those header files anymore. Author: Ken Hornstein Date: Fri Jan 3 00:42:05 2014 -0500 Sigh. Fix up missing conversion from clear->ti_clear. Author: Ken Hornstein Date: Fri Jan 3 00:30:15 2014 -0500 I guess we can't include both termcap and terminfo headers on Solaris. Author: Ken Hornstein Date: Fri Jan 3 00:15:56 2014 -0500 include curses.h so this (hopefully) now works on Solaris. Author: Ken Hornstein Date: Thu Jan 2 23:59:57 2014 -0500 Convert all of the terminal functions over to terminfo(5) instead of the older termcap. Move the terminal-specific code from fmt_compile.c to terminal.c, so it is all in one place. Author: Ken Hornstein Date: Thu Jan 2 15:55:33 2014 -0500 Garbage collect unused code. Author: Ken Hornstein Date: Thu Jan 2 15:52:49 2014 -0500 Remove baudrate-handing code. Author: Ken Hornstein Date: Thu Jan 2 15:04:17 2014 -0500 Always emit an STR instruction for terminal escape sequences, otherwise you can get unintended results (like printint the previous contents of the str register, which is almost certainly what you don't want). Author: Ken Hornstein Date: Thu Jan 2 15:00:46 2014 -0500 Switch from the M-X format for characters with the high bit set to \xXX instead when printing format strings and other characters. Author: Ken Hornstein Date: Thu Jan 2 14:46:52 2014 -0500 Fix problem with %(putlit) and %(zputlit) causing a SIGSEGV if str is NULL. Author: Ken Hornstein Date: Thu Jan 2 13:54:07 2014 -0500 Drop support for different behavior on hardcopy terminals. It's 2014, I'm assuming this is not a valid concern anymore. Author: Ken Hornstein Date: Thu Jan 2 11:38:20 2014 -0500 Move the termsbr code into the libmh library, where it belongs. Author: David Levine Date: Wed Jan 1 13:43:51 2014 -0600 Give up on fmt_compile.c for now. Author: David Levine Date: Wed Jan 1 13:21:56 2014 -0600 That didn't work. Try including termcap.h first, instead of ncurses/termcap.h. Author: David Levine Date: Wed Jan 1 13:18:08 2014 -0600 Changed several globals to be static, to avoid collision, notably with "filter" in libtermcap.so, on Solaris. Author: David Levine Date: Wed Jan 1 13:16:48 2014 -0600 Try including termcap.h before curses.h to see if that solves the tputs() mismatch on Solaris. Author: Ken Hornstein Date: Tue Dec 31 15:29:40 2013 -0500 It looks like some systems also need curses.h as well as term.h Author: Ken Hornstein Date: Tue Dec 31 15:20:22 2013 -0500 Add support for outputing a few (limited) terminal attributes in format sequences. Needs documentation and some expansion. Author: Ken Hornstein Date: Tue Dec 31 15:19:21 2013 -0500 Make sure that branching instructions are traced even if we're executing the branch (previously, they would only be traced if they did not execute the branch). Author: Ken Hornstein Date: Tue Dec 31 00:13:21 2013 -0500 Change fmttest to use litputs() on str and output buffers during tracing. Author: David Levine Date: Sun Dec 29 08:01:28 2013 -0600 Generalized the valgrind suppression for sendmsg via readLine. Author: David Levine Date: Sat Dec 28 18:24:54 2013 -0600 Added test/valgrind.supp to EXTRA_DIST in Makefile.am so that NMH_VALGRIND=1 works with make distcheck. Author: David Levine Date: Sat Dec 28 18:23:49 2013 -0600 Removed one run_prog from test-pick because it loses the setting of the LC_CTYPE environment variable. Author: David Levine Date: Sat Dec 28 11:55:12 2013 -0600 Fixed chmod of temp file in prompter. Noticed by valgrind. Author: David Levine Date: Sat Dec 28 11:54:05 2013 -0600 Null-terminate buffer in mbx_copy() in dropsbr.c. Noticed by valgrind. Author: David Levine Date: Sat Dec 28 11:51:01 2013 -0600 Added support for running the test suite with valgrind by setting the NMH_VALGRIND environment variable. To support that, nmh programs that are invoked in the test suite should be run via (the new function) run_prog or run_test. Author: David Levine Date: Tue Dec 24 09:02:15 2013 -0600 Have configure print out what it detects for the program to detect the MIME type string for a file. Author: David Levine Date: Mon Dec 23 15:32:45 2013 -0600 Added "true" to end of flex fixups in configure.ac, in case the user has hacked flex to not produce the errant code. Author: David Levine Date: Mon Dec 23 15:09:23 2013 -0600 Removed flex fixup for version 2.5.37, it's not necessary with flex 2.5.37 on Fedora 20. Author: David Levine Date: Sun Dec 22 18:09:55 2013 -0600 Use --brief option, if supported, with file --mime. Author: David Levine Date: Sun Dec 22 17:38:59 2013 -0600 In test-mhmail, insert semicolon in output of "file --mime" if needed. Author: David Levine Date: Sun Dec 22 16:42:34 2013 -0600 file --mime on OpenBSD returns strings such as "text/plain charset=us-ascii", without an intervening semilcolon. Insert one if there isn't one. Author: David Levine Date: Sun Dec 22 16:12:02 2013 -0600 Removed support for file -i, it just spits out "regular file" on Solaris. Author: David Levine Date: Sun Dec 22 16:11:18 2013 -0600 Removed temporary printouts. Author: David Levine Date: Sun Dec 22 15:30:30 2013 -0600 More debugging statements for OpenBSD. Author: David Levine Date: Sun Dec 22 15:08:30 2013 -0600 Added debuging printouts. Author: David Levine Date: Sun Dec 22 15:05:38 2013 -0600 Whooops, gcc on OpenBSD noticed a nasty in the last commit. Author: David Levine Date: Sun Dec 22 14:42:26 2013 -0600 With whatnow attach, determine the content MIME type that's inserted into the Content-Type header using file --mime or file -i, if available on the platform at configuration time. If not, continue to use the mhshow-suffix- method. Added a mimetypeproc component to mhparam so that a user can query the configuration. Author: David Levine Date: Sun Dec 22 14:38:49 2013 -0600 Updated date on a few man pages. Author: David Levine Date: Sun Dec 22 10:41:09 2013 -0600 Removed temporary probes added in commit 3441b5648a0c21e067c05f428a51bf96352735e7. Author: David Levine Date: Sun Dec 22 09:02:29 2013 -0600 Added temporary probes to see what file --mime and file -i do on OpenBSD and Solaris. Author: David Levine Date: Sun Dec 22 09:01:41 2013 -0600 Increased size of file command buffer in make_mime_composition_file_entry() because it was a bit too small. Author: David Levine Date: Sat Dec 14 10:41:01 2013 -0600 Cleaned up setting of CFLAGS in configure.ac. Author: David Levine Date: Sat Dec 14 10:29:33 2013 -0600 Added POSTLINK to remainder of executables in Makefile.am. Replaced hard-coded sbr/libmh.a with $(LDADD) in LDADD macro for test/getfullname. Author: David Levine Date: Sat Dec 14 09:51:47 2013 -0600 The buildbot was reporting "warning" on stdin, not stderr. Escape "warning" so that it doesn't snag it. Author: David Levine Date: Sat Dec 14 08:51:42 2013 -0600 The build failed mysteriously on the OpenBSD buildbot host ("Provide an AUTOCONF_VERSION environment variable, please"). This was in the compile, not autogen, phase. Committing trivial change to kick off another build. Author: David Levine Date: Sat Dec 14 08:37:11 2013 -0600 That didn't quite work, try reducing size of warning filter temporarily. Author: David Levine Date: Sat Dec 14 08:24:14 2013 -0600 Filter out "often/almost always misused" warnings from OpenBSD linker. Added POSTLINK macro to configure/Makefile for this purpose. Author: David Levine Date: Fri Dec 13 19:23:27 2013 -0600 Added mention of filename completion at whatnow prompt if nmh was configured with readline enabled. Author: David Levine Date: Fri Dec 13 19:20:12 2013 -0600 Moved the set -x after the uname and string test in autogen.sh to reduce build log clutter. Author: David Levine Date: Fri Dec 13 19:12:15 2013 -0600 Generalized -Wel fix in test-manpages of commit 27659f0aa30c07081f7b8647c51a6ca82837e5d1 to apply on any platform. Author: Pascal Stumpf Date: Fri Dec 13 18:57:57 2013 -0600 rand()/srand() are not cryptographically secure PRNGs. Some systems have the much better suited arc4random() family of functions; there's no reason to not use it if it is available. Make m_rand() just a wrapper around arc4random_buf() in that case. (There's no need to ever seed it manually.) As a bonus, silences some warnings on OpenBSD. Author: David Levine Date: Fri Dec 13 16:48:02 2013 -0600 groff -man silence the test-manpages warnings. One more try: -Wel. Author: David Levine Date: Fri Dec 13 16:25:24 2013 -0600 Try using -man instead of -mandoc in test-manpages on OpenBSD to see if it silences the warnings. Author: David Levine Date: Fri Dec 13 15:33:14 2013 -0600 Disable assertions by default. Author: Ken Hornstein Date: Fri Dec 13 15:38:58 2013 -0500 Minor autoconf style cleanup. Author: David Levine Date: Thu Dec 12 20:15:14 2013 -0600 Minor changes to configure.ac: 1) Replaced direct manipulation of NDEBUG with AC_HEADER_ASSERT. 2) Removed unnecessary level of quoting around LFLAGS assignments. Author: David Levine Date: Thu Dec 12 20:11:42 2013 -0600 Moved all LDFLAGS manipulations in configure.ac to one place. Author: David Levine Date: Thu Dec 12 18:37:58 2013 -0600 Tweaked rcvtty.c to squelch warnings on OpenBSD. Three of the four were due to unused artifacts with HAVE_GETUTXENT not defined. The fourth was due to control reaching the end of non-void function message_id(), which had an _exit() call at the end. Author: David Levine Date: Thu Dec 12 18:29:31 2013 -0600 Initialize local child_id in main() of whom.c to squelch warning from cc on OpenBSD. Author: David Levine Date: Thu Dec 12 18:27:17 2013 -0600 Squelch warning from cc on OpenBSD that fd argument of usr_pipe() in slocal.c might get clobbered by vfork() by copying it to a volatile local. Author: David Levine Date: Thu Dec 12 18:23:45 2013 -0600 Removed --posix from awk invocation in test-anno. Author: David Levine Date: Thu Dec 12 18:08:01 2013 -0600 It looks like the sed "a" in test-anno didn't emit a trailing newline on OpenBSD. It does on other platforms. Try using awk instead. Author: Lyndon Nerenberg Date: Thu Dec 12 11:55:58 2013 -0800 Add buildbot hacks for OpenBSD. OpenBSD auto{conf,make} want a version specified in the environment for each of the tools. For now, hardwire this into autogen.sh until we can figure out a better way of dealing with this. Author: David Levine Date: Wed Dec 11 20:52:49 2013 -0600 Sun Studio cc -V must output to stderr. Author: David Levine Date: Wed Dec 11 20:28:10 2013 -0600 Try 9efa994ecac2790dbc56113f78c464eed1371590 again. Author: David Levine Date: Wed Dec 11 19:47:29 2013 -0600 Undid last commit of temporary printouts because buildbot is down. Author: David Levine Date: Wed Dec 11 17:19:48 2013 -0600 Temporarily add some printouts to configure.ac to see why -v isn't added to Sun Studio cc on Solaris build host. Author: Lyndon Nerenberg Date: Wed Dec 11 10:53:28 2013 -0800 Prefer cc over gcc. Author: Lyndon Nerenberg Date: Wed Dec 11 10:42:04 2013 -0800 One more attempt at getting the buildbot $PATH correct on Solaris. Author: David Levine Date: Tue Dec 10 19:17:00 2013 -0600 OK, this should work to detect Sun Studio cc. Author: David Levine Date: Tue Dec 10 19:07:25 2013 -0600 Oops, that didn't work. Disable -v with SunStudio cc for now. Author: David Levine Date: Tue Dec 10 19:05:32 2013 -0600 OK, use SunStudio cc, if present, on Solaris if user didn't set CC. And with it, use -v and suppress the statement not reached warning. Author: David Levine Date: Tue Dec 10 18:45:26 2013 -0600 Suppress E_STATEMENT_NOT_REACHED warning from SunStudio cc. Author: David Levine Date: Tue Dec 10 18:35:08 2013 -0600 Added -errtags=yes to SunStudio cc options. Author: David Levine Date: Tue Dec 10 18:22:23 2013 -0600 Removed a bunch of unreachable break statements found by SunStudio cc -v. Also fixed an "end-of-loop code not reached" condition in uip/dropsbr.c. That one is significant because it meant that retries were not attempted when attempting to open and lock a file. Author: David Levine Date: Tue Dec 10 16:43:20 2013 -0600 Need full path to cc on Solaris buildbot host, at this point. Author: David Levine Date: Tue Dec 10 16:16:59 2013 -0600 Try -v with SunStudio cc. Also, try setting CC instead of modifying AC_PROC_CC to pick up cc on the buildbot Solaris host. Author: Lyndon Nerenberg Date: Tue Dec 10 14:05:08 2013 -0800 Remove the Solaris cc hack; the buildbot should have the correct cc in its $PATH now. Author: David Levine Date: Tue Dec 10 08:40:59 2013 -0600 Removed +w from SunStudio cc, it caused compilation failure. Maybe it can only be used with CC. Author: David Levine Date: Tue Dec 10 08:36:15 2013 -0600 That worked. Now try +w2 with SunStudio cc. Author: David Levine Date: Tue Dec 10 08:15:22 2013 -0600 Of course that didn't work. Try specifying the SunStudio compiler in CC. Author: David Levine Date: Tue Dec 10 07:53:14 2013 -0600 That didn't work. Set PATH to pick up SunStudio cc. Author: David Levine Date: Mon Dec 9 23:45:54 2013 -0600 Use SolarisStudio cc if available. Author: David Levine Date: Mon Dec 9 23:20:27 2013 -0600 Added temporary probe to find cc on Solaris. Author: David Levine Date: Mon Dec 9 18:25:03 2013 -0600 Removed temporary favor of cc over gcc. Author: David Levine Date: Mon Dec 9 18:19:17 2013 -0600 Temporarily favor cc over gcc to try it out on Solaris. Author: David Levine Date: Sun Dec 8 23:17:50 2013 -0600 Commit 9c663383ab54e0290781ac1c25d790ce03160e08 introduced a backward incompatibility to build_nmh. Refuse to support -y if the current nmh installation has an mhparam that doesn't support the sasl and tls components. Author: Ken Hornstein Date: Sun Dec 8 22:18:46 2013 -0500 Clean up comments, and update information on file locking. Author: David Levine Date: Sun Dec 8 19:02:28 2013 -0600 Removed dependence of build_nmh on ldd by adding sasl and tls components to mhparam(1). Author: Ken Hornstein Date: Sun Dec 8 18:05:42 2013 -0500 Fix one of the POP tests to work on wide terminals. Author: David Levine Date: Sun Dec 8 13:27:33 2013 -0600 Removed temporary diagnostic to determine gcc version on Solaris buildbot host. It's 4.5.2. 4.6.0 and later return an error status with an unrecognized option, which we rely on for the test for -Qunused-arguments. 4.5.2 doesn't. But that option doesn't produce any errors, just warnings that don't contain "warning". So ignore it. Author: David Levine Date: Sun Dec 8 13:16:19 2013 -0600 Added temporary diagnostic to see what version of gcc is used on the buildbot Solaris host. Author: David Levine Date: Sun Dec 8 12:50:39 2013 -0600 With the fix of 4929cad323afc87404752a1e88664a7f42cbb737, prepare_space() no longer needs to insert initial space. Author: David Levine Date: Sun Dec 8 12:15:18 2013 -0600 Try this sed command for squeeze_lines(). Author: David Levine Date: Sun Dec 8 11:19:13 2013 -0600 Added -eval 'set document.browse.margin_width = 0' to elinks command in mhfixmsg-format-text/html in mhn.defaults, to disable indentation of converted text. Thanks to Rickard Carlsson for this suggestion. Author: David Levine Date: Sun Dec 8 10:56:35 2013 -0600 That didn't work, so try this awk command from Robert Elz. Author: David Levine Date: Sun Dec 8 10:29:00 2013 -0600 Fixed squeeze_lines() test function to be compatible with POSIX awk. Author: David Levine Date: Sat Dec 7 20:27:37 2013 -0600 Fixed test-mhfixmsg to work with elinks, which inserted leading space on a line. Thanks to Valdis for reporting that and to Ralph for the awk and sed magic to emulate diff -w (and cat -s). Author: David Levine Date: Sat Dec 7 10:44:31 2013 -0600 Added notes to README.developers about write access to the git repo and git rebase. Author: David Levine Date: Sat Dec 7 10:39:16 2013 -0600 Replaced hard-coded use of "," with `mhparam sbackup` in test-header-encode. Author: David Levine Date: Sat Dec 7 09:34:05 2013 -0600 Disable clang complaint about unused -ansi when linking by adding -Qunused-arguments to LDFLAGS, if supported. Author: David Levine Date: Fri Dec 6 18:56:11 2013 -0600 Removed bash-isms from inc/test-deb359167. Author: David Levine Date: Fri Dec 6 18:43:20 2013 -0600 Skip inc/test-deb359167 on FreeBSD >= 10 because its valgrind throws a strange error. Code provided by Lyndon. Author: Lyndon Nerenberg Date: Fri Dec 6 14:52:03 2013 -0800 test/common.sh.in: use awk to pick off first output field. md5 and md5sum are inconsistent in their use of SP vs HT as a field separator. cut(1) can only handle a single field delimiter character; awk is more forgiving. Merge: 2734ae8 7d7ed69 Author: David Levine Date: Thu Dec 5 22:49:54 2013 -0600 Merge branch 'master' of git.sv.nongnu.org:/srv/git/nmh Author: David Levine Date: Thu Dec 5 22:49:49 2013 -0600 Renamed test/getfqdn to test/getcanon. Author: Ken Hornstein Date: Thu Dec 5 23:40:44 2013 -0500 I give up for now; revert these debugging commits. Author: Ken Hornstein Date: Thu Dec 5 23:28:44 2013 -0500 One final check to make sure the binary isn't stripped Author: Ken Hornstein Date: Thu Dec 5 23:15:57 2013 -0500 Sigh. Make sure the binaries aren't stripped as well. Author: Ken Hornstein Date: Thu Dec 5 22:56:57 2013 -0500 Switch to default of -g so hopefully we can get something useful from the FreeBSD buildbot valgrind output. Author: Ken Hornstein Date: Thu Dec 5 22:48:04 2013 -0500 Sigh, I always forget this is errno.h, not sys/errno.h. Author: Ken Hornstein Date: Thu Dec 5 21:59:22 2013 -0500 Have getfqdn fall back to printing out the given hostname if the DNS lookup fails, to replicate the behavior of LocalName(). Author: David Levine Date: Thu Dec 5 18:38:16 2013 -0600 That didn't work, either. Restoring configure.ac. Author: David Levine Date: Thu Dec 5 18:35:00 2013 -0600 That didn't work, try adding -pedantic-errors. Author: David Levine Date: Thu Dec 5 18:10:01 2013 -0600 The linker on FreeBSD 10 doesn't like -ansi. So added a configure check to not put -ansi in CFLAGS if the linker doesn't like it. Though may need to add -pedantic-errors. There doesn't seem to be an easy way to get automake to not put CFLAGS in the link command. Author: David Levine Date: Thu Dec 5 17:48:08 2013 -0600 Clean up mhbuild backup files left by test-header-encode. Author: David Levine Date: Thu Dec 5 08:02:27 2013 -0600 Better fix than commit 605d80e7cf0d02d4bab9387f03b4e1d43177e33e for test-mhfixmsg: always overwrite HOME environment variable if mhfixmsg uses w3m. Author: David Levine Date: Thu Dec 5 07:04:51 2013 -0600 Fix to commit 7e40862e6a4da7810a46aa1e28b05e527fdc208a: only one of the variables should have ICONV_CONST. Author: David Levine Date: Wed Dec 4 22:25:14 2013 -0600 In test-mhfixmsg, make sure that $HOME is writeable, in case nmh has been configured to use w3m. Author: David Levine Date: Wed Dec 4 21:48:04 2013 -0600 Really fixed mhmail. Author: David Levine Date: Wed Dec 4 21:18:38 2013 -0600 Removed temporary hack. Author: David Levine Date: Wed Dec 4 21:15:31 2013 -0600 Removed temporary hack to enable debug from configure.ac. Author: David Levine Date: Wed Dec 4 21:13:55 2013 -0600 Fixed test-mhmail failure on Solaris: its tail doesn't suport -n. Author: Ken Hornstein Date: Wed Dec 4 22:03:23 2013 -0500 Update pending-release-notes regarding removal of the -normalize and -nonormalize switches. Author: Ken Hornstein Date: Wed Dec 4 21:56:50 2013 -0500 Garbage collect "normalize". The code to normalize addresses (look up the hostnames in DNS for the "official" hostnames) was disabled when we made DUMB the default configuration in 1.5. Since them, the -normalize switch was still around in various utilities, but it didn't do anything. Remove all of those switches and garbage collect various other bits of the "normalize" functionality. At the same time, improve getm() a bit; it now takes an argument specifying the length of the error buffer. Author: David Levine Date: Wed Dec 4 20:54:03 2013 -0600 Added temporary diagnostic hack to test-mhmail. Author: David Levine Date: Wed Dec 4 20:40:59 2013 -0600 The buildbot is up, put in hacks to enable debug and print out hostname. Author: David Levine Date: Wed Dec 4 20:30:04 2013 -0600 Fixed m_getfld() bug introduced in commit 0c7ac5073c24f01663fadc78b5112c86d52e4452. This bug caused parsing of messages with long (>= 8K) header field values to fail. The fix was easy: decrement the counter of bytes read when decrementing the current read position, in FLDPLUS state. Author: David Levine Date: Wed Dec 4 20:29:05 2013 -0600 Use ICONV_CONST in declaration of variable that's passed to iconv(), to quiet warning in FreeBSD 10. Author: David Levine Date: Wed Dec 4 19:49:36 2013 -0600 Added identifier to each check in test-mhlist to help diagnose test failure. Author: David Levine Date: Wed Dec 4 19:38:11 2013 -0600 Added comment about not supporting trailing semicolons for aliases (in alias file). Author: David Levine Date: Wed Dec 4 19:37:00 2013 -0600 Undid temporary hacks, it looks like the buildbot is down. Author: David Levine Date: Wed Dec 4 19:24:57 2013 -0600 Temporarily added a few hacks to diagnose problems found by buildbot. Author: Ken Hornstein Date: Wed Dec 4 18:11:31 2013 -0500 Fix another warning. Author: Ken Hornstein Date: Wed Dec 4 15:49:52 2013 -0500 A few more tests; I think that's enough for now. Author: Ken Hornstein Date: Wed Dec 4 14:29:54 2013 -0500 Fix a few warnings. Author: Ken Hornstein Date: Wed Dec 4 12:57:20 2013 -0500 More tests (but not quite finished yet). Author: Ken Hornstein Date: Wed Dec 4 12:56:54 2013 -0500 Fix cut & paste mistake. Author: Ken Hornstein Date: Wed Dec 4 12:12:55 2013 -0500 More man page minor fixup. Author: Ken Hornstein Date: Wed Dec 4 11:56:34 2013 -0500 Slightly clarify mhbuild man page. Author: Ken Hornstein Date: Wed Dec 4 11:40:52 2013 -0500 Minor typo fix. Author: Ken Hornstein Date: Tue Dec 3 21:57:01 2013 -0500 Note changes to mhbuild. Merge: 4c1236a 4fcf75e Author: Ken Hornstein Date: Tue Dec 3 21:52:30 2013 -0500 Merge branch 'encode-rfc2047' Author: Ken Hornstein Date: Tue Dec 3 21:52:11 2013 -0500 Support for more tests. Author: Ken Hornstein Date: Tue Dec 3 21:36:39 2013 -0500 Whoops, shouldn't use autoincrement with a macro; forgot about side effects! Author: Ken Hornstein Date: Tue Dec 3 15:52:00 2013 -0500 First round of tests! Still want to do more before it gets merged. Author: Ken Hornstein Date: Tue Dec 3 15:21:29 2013 -0500 Add support for a -file switch to handle messages that are not in folders. Author: Ken Hornstein Date: Mon Dec 2 23:34:02 2013 -0500 Don't put a space after the trailing semicolon for group termination. Author: Ken Hornstein Date: Mon Dec 2 23:14:47 2013 -0500 Use pref_encoding() to select the default encoding for all headers. Author: Ken Hornstein Date: Mon Dec 2 23:11:27 2013 -0500 Do proper group handling, and fix a bug in the q-p encoder. Author: Ken Hornstein Date: Mon Dec 2 15:49:35 2013 -0500 I think we're very close to get address encoding working, but still have to test it more. Author: Ken Hornstein Date: Mon Dec 2 13:47:34 2013 -0500 Document a few more things. Author: Ken Hornstein Date: Mon Dec 2 13:41:51 2013 -0500 Since our last caller of getlocaladdr() was removed, garbage-collect this function. Author: Ken Hornstein Date: Mon Dec 2 13:39:34 2013 -0500 Remove code to set the signature buffer; it turns out that with our refactoring for 1.5, it was no longer used. Author: Ken Hornstein Date: Wed Nov 27 12:49:07 2013 -0500 More work, but still stuff to do. Author: Ken Hornstein Date: Mon Nov 25 14:06:38 2013 -0500 Fix up a few warnings and problems. Author: Ken Hornstein Date: Thu Nov 21 15:59:21 2013 -0500 More work on address portion of RFC 2047 encoder. Author: Ken Hornstein Date: Thu Nov 14 15:30:15 2013 -0500 A little bit closer to working for address headers. Author: Ken Hornstein Date: Thu Nov 14 11:43:33 2013 -0500 Break out the unquote functionality to a separate function. Author: Ken Hornstein Date: Thu Nov 14 10:16:22 2013 -0500 Fix up the unquote test, with help from Lyndon and Ralph. Author: Ken Hornstein Date: Wed Nov 13 22:26:09 2013 -0500 Test for unquoting, but it doesn't work yet. Author: Ken Hornstein Date: Wed Nov 13 20:54:48 2013 -0500 Switch fmttest over to using snprintb() instead of the private custom version we originally cribbed from fmtdump. Author: Ken Hornstein Date: Wed Nov 13 20:54:22 2013 -0500 Document snprintb() a bit. Author: Ken Hornstein Date: Wed Nov 13 20:54:05 2013 -0500 Actually check the output buffer length all of the time. Author: Ken Hornstein Date: Wed Nov 13 15:51:08 2013 -0500 Start work on address header parsing. Author: Ken Hornstein Date: Wed Nov 13 11:03:12 2013 -0500 Fix up date mode so it works without providing a format string. Author: Ken Hornstein Date: Sun Nov 10 22:46:49 2013 -0500 Document things a bit more. Author: Ken Hornstein Date: Sun Nov 10 00:46:23 2013 -0500 A number of bug fixes: - Fix macro to calculate the number of characters that will fit within a specified base64 encoding length. - Refactor code to handle leading spaces, and insert a leading space correctly after the start of a header. With all this, it seems to work! Author: Ken Hornstein Date: Sat Nov 9 14:27:12 2013 -0500 Don't increment the buffer pointer for the NUL string terminator; this lets us concatenate new text on the end of the current output buffer. Author: Ken Hornstein Date: Sat Nov 9 10:39:48 2013 -0500 Add support for -changecur and -nochangecur to mhlist(1). Author: Ken Hornstein Date: Thu Nov 7 22:44:13 2013 -0500 A little closer, but still has problems. Author: Ken Hornstein Date: Thu Nov 7 22:43:50 2013 -0500 Fix handling of -headerencoding switch. Author: Ken Hornstein Date: Thu Nov 7 16:02:14 2013 -0500 Getting closer to getting base64 header encoding working. Author: David Levine Date: Sun Nov 3 12:36:10 2013 -0600 Removed spurious space before a period in rcvpack man page. Author: David Levine Date: Sun Nov 3 12:34:12 2013 -0600 Cleaned up the "stripped CRs" mhfixmsg verbose message. Author: Ken Hornstein Date: Thu Oct 31 11:51:52 2013 -0400 Beginning stubs to support base64 header encoding. Author: Ken Hornstein Date: Thu Oct 31 11:37:52 2013 -0400 Support the -headerencoding switch to select the header encoding algorithm. Author: Ken Hornstein Date: Thu Oct 31 11:36:46 2013 -0400 Switch to the (correct) casting of char to unsigned char for is*() macros. Author: Ken Hornstein Date: Wed Oct 30 20:44:19 2013 -0400 Fix some space calculation/whitespace handling bugs. Author: Ken Hornstein Date: Wed Oct 30 15:32:03 2013 -0400 Fix qpspecial() macro test, and do proper casts to handle signed chars. Author: Ken Hornstein Date: Wed Oct 30 14:04:16 2013 -0400 It looks like simple quoted-printable encoding of headers works! Author: Ken Hornstein Date: Tue Oct 29 22:52:06 2013 -0400 Remove unused argument. Author: Ken Hornstein Date: Tue Oct 29 22:42:51 2013 -0400 Fix up a few miscalculations. Author: Ken Hornstein Date: Tue Oct 29 15:58:35 2013 -0400 A hopefully-functional quoted-printable encoder Author: Ken Hornstein Date: Mon Oct 28 14:44:30 2013 -0400 Test to make sure mhshow is actually invoking a charset conversion program if one is defined. Author: Ken Hornstein Date: Sun Oct 27 22:31:50 2013 -0400 Fix bug found by LLVM. Author: Ken Hornstein Date: Sun Oct 27 22:31:35 2013 -0400 Fix up warnings reported by LLVM. Author: David Levine Date: Sun Oct 27 08:57:55 2013 -0500 Interpret a full path argument to mhfixmsg as a filename, not a message. Author: Ken Hornstein Date: Wed Oct 23 14:40:02 2013 -0400 A little tiny bit closer to working. Author: David Levine Date: Wed Oct 23 11:24:34 2013 -0500 Success! Clean build on the buildbot Solaris11 host. Author: David Levine Date: Wed Oct 23 11:04:52 2013 -0500 Ooops, fixed typo in configure.ac. Author: David Levine Date: Wed Oct 23 11:02:47 2013 -0500 See if this cleans up the Solaris build on the buildbot. Author: David Levine Date: Wed Oct 23 10:47:23 2013 -0500 More probing: print out sbr/dtimep.c. Author: David Levine Date: Wed Oct 23 10:20:49 2013 -0500 OK, Solaris on the buildbot uses flex 2.5.35. Author: David Levine Date: Wed Oct 23 10:16:31 2013 -0500 More probing: added flex -V. Author: David Levine Date: Wed Oct 23 09:57:16 2013 -0500 Added back an enhanced hack to configure.ac to try to diagnose the flex 2.5.36/.36 bug workaround. Changed test-dist a bit to help isolate where it just failed. (My last commit message was incorrect: it was test-dist that failed, not test-comp-format.) Author: David Levine Date: Tue Oct 22 22:54:08 2013 -0500 Reverted commit 9caa7da143644ed93c6ba6351f48fa1327ad4392 because it didn't solve the problem on Solaris, and apparently broke test-comp-format, though I don't see how. Author: David Levine Date: Tue Oct 22 19:46:51 2013 -0500 Added hack to configure.ac to work around bug in flex 2.5.36 and 2.5.37 that prevents the builds from being completely green. According to http://sourceforge.net/p/flex/bugs/140/, this should be fixed in the next release of flex. The hack is confined to just configure.ac so it'll be easy to remove. Author: Ken Hornstein Date: Mon Oct 21 23:51:57 2013 -0400 Minor comment update. Author: Ken Hornstein Date: Mon Oct 21 16:01:02 2013 -0400 Start of RFC 2047 encoding code. Not complete in the slightest. Author: Ken Hornstein Date: Mon Oct 21 12:48:23 2013 -0400 Some comments describing the MIME structures. Author: David Levine Date: Sat Oct 19 09:58:14 2013 -0500 Added volatile qualifier in a couple of places to get rid of "might be clobbered" warning from when -Wno-clobbered isn't supported. And I removed the check for Wno-clobbered from configure.ac. It's no longer needed on any of the platforms I use, we'll see if others need it. Author: David Levine Date: Sat Oct 19 09:19:58 2013 -0500 Allow mhfixmsg to strip carriage returns from ISO-8850, UTF-8, and Windows-12xx text, in addition to ASCII. Author: David Levine Date: Sat Oct 19 09:17:22 2013 -0500 Added docs/README-iCalendar. Author: Ken Hornstein Date: Thu Oct 17 22:03:07 2013 -0400 Implemented -build switch for comp, at the request of the MH-E developers. Author: Ken Hornstein Date: Thu Oct 17 21:44:52 2013 -0400 Minor comment cleanup. Author: Ken Hornstein Date: Thu Oct 17 15:43:15 2013 -0400 Update the mh-sequence(5) man page with details of the format of the sequence file. Also mention that nonexistant messages will be removed from sequences. Author: Ken Hornstein Date: Tue Oct 15 20:21:32 2013 -0400 Add locking support to the version of the sequence file reading code used by the "new" command. Based on a patch by Harvey Eneman. Author: Ken Hornstein Date: Tue Oct 15 15:02:18 2013 -0400 Remove support for NOPUBLICSEQ. Author: Ken Hornstein Date: Tue Oct 15 14:48:19 2013 -0400 Remove unneeded stat() call; was a leftover from the original MH code where the owner of the folder was checked against the results of getuid(). Author: David Levine Date: Sun Oct 6 08:45:22 2013 -0500 The Content-Disposition type needs to be "inline" for MS Outlook and BlackBerry calendar programs to properly handle a text/calendar attachment. So do that with attachformat values of 1 and 2. Author: David Levine Date: Thu Sep 19 18:30:19 2013 -0500 Added script name to test-mhfixmsg printout. Author: David Levine Date: Thu Sep 19 08:13:24 2013 -0500 Don't check -replacetextplain in test-mhfixmsg if skipping -reformat check. Author: David Levine Date: Wed Sep 18 21:40:19 2013 -0500 Run output of -replacetextplain test through uniq. Author: David Levine Date: Mon Aug 19 00:42:01 2013 -0500 Added -replacetextplain switch to mhfixmsg. If enabled, -reformat will replace any existing text/plain part, such as those that are empty or that don't match their corresponding text/html part. Author: David Levine Date: Tue Jul 2 18:33:37 2013 -0500 Added unsigned char cast of char argument to isascii() call. Author: Ken Hornstein Date: Mon Jul 1 15:44:22 2013 -0400 Reject email addresses which contain 8-bit characters. Author: Ken Hornstein Date: Mon Jul 1 15:07:16 2013 -0400 Add warnings about the use of %(decode) on addresses. Author: Ken Hornstein Date: Mon Jul 1 14:31:51 2013 -0400 If mbtowc() fails to handle a character, replace the offending character with a '?' and continue. Author: David Levine Date: Mon Jul 1 07:11:27 2013 -0500 In test-mhfixmsg, run output through uniq before head instead of after. Author: David Levine Date: Sun Jun 30 22:29:12 2013 -0500 Punted on comparing that html part in test-mhfixmsg: it can get reformatted legally. Author: David Levine Date: Sun Jun 30 21:20:00 2013 -0500 Try this formatting change to test-mhfixmsg. Author: David Levine Date: Sun Jun 30 20:46:18 2013 -0500 One more formatting chagned to the input in test-mhfixmsg. One of the lines is one character longer than the others and that's about where the problem shows up, so yanked a character out of it. Merge: 1863e69 03da1d1 Author: Lyndon Nerenberg Date: Sun Jun 30 18:11:42 2013 -0700 Merge branch 'master' of ssh://git.sv.gnu.org/srv/git/nmh Author: Lyndon Nerenberg Date: Sun Jun 30 18:11:13 2013 -0700 Revert "Move a variable manipulation outside the context of setjmp() to quell a compiler warning." Turns out it didn't fix it after all. This reverts commit 0152658e840581077e5cd575b5195faf18b9df8b. Author: David Levine Date: Sun Jun 30 20:11:08 2013 -0500 Changed formatting of the input in test-mhfixmsg that breaks on Solaris 11, maybe this will fix it. Merge: 0152658 7970ff4 Author: Lyndon Nerenberg Date: Sun Jun 30 17:59:59 2013 -0700 Merge branch 'master' of ssh://git.sv.gnu.org/srv/git/nmh Author: Lyndon Nerenberg Date: Sun Jun 30 17:59:31 2013 -0700 Move a variable manipulation outside the context of setjmp() to quell a compiler warning. Author: David Levine Date: Sun Jun 30 19:40:34 2013 -0500 Restored test-mhfixmsg. Not sure what to do about failure on Solaris. Author: Lyndon Nerenberg Date: Sun Jun 30 17:24:48 2013 -0700 Copy a parameter off the call stack to quell a longjmp warning. Merge: 5fb90fa daae5d9 Author: David Levine Date: Sun Jun 30 19:14:46 2013 -0500 Merge branch 'master' of git.sv.nongnu.org:/srv/git/nmh Author: David Levine Date: Sun Jun 30 19:12:58 2013 -0500 See if the rest of test-mhfixmsg will pass on Solaris. Author: Lyndon Nerenberg Date: Sun Jun 30 16:58:23 2013 -0700 Remove spurious return statements after exit(). These are holdovers from a long forgotten era. Author: David Levine Date: Sun Jun 30 18:50:50 2013 -0500 OK, fixed test-mhfixmsg on Solaris 11, where BUFSIZ is 1024. The problem was in the content_encoding() function of mhfixmsg: it would restart its counter of the characters on a line whenever new characters were read in. The fix was easy, just move the initialization of that counter outside of the fread() loop. Author: David Levine Date: Sun Jun 30 18:28:56 2013 -0500 Added to the Solaris debug printout. Author: David Levine Date: Sun Jun 30 18:11:43 2013 -0500 Removed exit() after a longjmp() in uip/sendsbr.c to quiet compile warning on Solaris 11. Author: David Levine Date: Sun Jun 30 18:03:28 2013 -0500 More debugging of test-mhfixmsg on Solaris. Author: David Levine Date: Sun Jun 30 17:50:44 2013 -0500 Fixed removal of <> in test-dist and test-rcvdist. Author: David Levine Date: Sun Jun 30 16:44:23 2013 -0500 Remove any <> surrounding localmbox in test-dist and test-rcvdist, so that the tests pass when the user doesn't have a SIGNATURE set. Author: David Levine Date: Sun Jun 30 16:35:39 2013 -0500 That didn't work, fixed location of mhn.defaults in test. Author: David Levine Date: Sun Jun 30 16:19:56 2013 -0500 Added debug printouts to see why the test fails on Solaris 11. Author: Lyndon Nerenberg Date: Sun Jun 30 13:14:12 2013 -0700 Prefer /usr/sbin/sendmail over /usr/lib/sendmail. If the site installs a sendmail replacement, or updates to a newer version, odds are better for the new sendmail preferring to install in /usr/sbin over /usr/lib. Author: Lyndon Nerenberg Date: Sun Jun 30 12:39:46 2013 -0700 Add compilation guard around lkopen_flock. Oracle Solaris 11 doesn't have flock(). Author: Lyndon Nerenberg Date: Sun Jun 30 12:16:07 2013 -0700 If we're searching for commands, prefer xpg4 versions on Solaris. Author: David Levine Date: Tue Jun 11 20:30:31 2013 -0500 Removed hyphen from all occurrences of RFC-*. Author: David Levine Date: Tue Jun 11 20:17:29 2013 -0500 Changed all bare occurrences of 822/2822 to RFC 822/RFC 2822. Reported by Norm. Author: David Levine Date: Tue Jun 11 19:46:51 2013 -0500 Changed "separated by spaces" in mh-sequence man page to "as separate arguments", as suggested by Norm. Author: David Levine Date: Tue Jun 11 19:45:47 2013 -0500 Changed a couple of occurrences of "white-space" to "whitespace" to be consistent with other man pages. Author: Lyndon Nerenberg Date: Sun May 26 12:37:40 2013 -0700 conflict(8): style - move deprecation notice into DESCRIPTION. Author: Lyndon Nerenberg Date: Sun May 26 12:28:24 2013 -0700 Remove SYNOPSIS from nmh(7). Author: Lyndon Nerenberg Date: Sun May 26 12:23:00 2013 -0700 Delete SYNOPSIS from section 5 manpages. This isn't applicable to section 5 manpages. Merge: c943fb3 4859041 Author: Lyndon Nerenberg Date: Sun May 26 12:17:41 2013 -0700 Merge branch 'master' of ssh://git.sv.gnu.org/srv/git/nmh Author: Lyndon Nerenberg Date: Sun May 26 12:17:31 2013 -0700 Fix typo. Author: David Levine Date: Sun May 26 11:11:48 2013 -0500 Added note to pending-release-notes that "*" address-group is obsolescent. Split obsolete and deprecated features into separate sections. Author: Lyndon Nerenberg Date: Sat May 25 20:19:50 2013 -0700 Stupid typo in manpage. Author: Lyndon Nerenberg Date: Sat May 25 20:14:04 2013 -0700 Clean up mh-alias(5) manpage. Word-smithing, update to use *.example domains for addresses, literal text in bold rather than italic, use typographers quotes on single character references, etc. Re-organize sections to match documentation convention. Mark "*" address-group as obsolescent. Author: David Levine Date: Sun May 12 08:29:34 2013 -0500 Fixed strip_crs() in mhfixmsg to work even if it's the only modification to the message. Also, fixed the test so that it succeeds even if there is no lynx, w3m, etc. Author: David Levine Date: Mon May 6 20:14:57 2013 -0500 Fixed number of bytes to fread() in strip_crs() in mhfixmsg. Author: Lyndon Nerenberg Date: Sun May 5 14:41:34 2013 -0700 More .ta -> .TP manpage cleanup. Author: David Levine Date: Sat May 4 10:38:35 2013 -0500 Per Ralph's suggestion, added note that "moreproc" is not supported in user profile display strings. Author: David Levine Date: Sat May 4 10:30:21 2013 -0500 Replaced hard-coded "more" with DEFAULT_PAGER in show_text(). Author: David Levine Date: Sat May 4 09:36:42 2013 -0500 When the mhfixmsg -decodetext switch is enabled, each carriage return character that precedes a linefeed character is removed from ASCII-encoded text parts. Author: David Levine Date: Sat May 4 09:03:27 2013 -0500 Removed unused declaration of "nolist" from mhshow.c. Author: David Levine Date: Sat May 4 09:01:42 2013 -0500 Replaced raw hack to add the credentials profile entry in post.c with new add_profile_entry() function. Author: David Levine Date: Thu May 2 20:36:21 2013 -0500 Fixed failure reported by Valdis of post to retrieve login and password with legacy credentials. Author: David Levine Date: Wed May 1 20:40:55 2013 -0500 Fixed problem with m_getfld() with long headers reported by Paul Fox. The problem occurred with the 512th byte of the header was a newline: it then skipped the next character. Author: David Levine Date: Wed May 1 20:38:48 2013 -0500 Set the return status from the check() function of the test suite if the check failed. Author: David Levine Date: Tue Apr 30 20:59:55 2013 -0500 Removed remaining #includes of stdio.h and stdlib.h because they're #include'd by h/nmh.h. Author: David Levine Date: Tue Apr 30 20:54:43 2013 -0500 Applied what was done to uip/send.c in commit af429a902add614e35cd76d15172a4ccb70a3be1 to uip/viamail.c and uip/whatnowsbr.c, because they call sendsbr() directly. Author: David Levine Date: Sun Apr 28 19:42:09 2013 -0500 Removed some #includes of stdio.h, ctype.h, stdlib.h, and string.h because they're #include'd by h/nmh.h. Author: David Levine Date: Sun Apr 28 19:32:44 2013 -0500 Removed some #includes of unistd.h and stdio.h because they're in h/nmh.h. Author: David Levine Date: Sun Apr 28 19:26:58 2013 -0500 Redirect some outputs in the test suite to standard error. Author: David Levine Date: Sun Apr 28 14:59:34 2013 -0500 Fix to commit af429a902add614e35cd76d15172a4ccb70a3be1 to use the user found by nmh_get_credentials() in sm_auth_sasl(). Author: David Levine Date: Sun Apr 28 13:07:31 2013 -0500 Tweaked check of -outfile in test-mhstore. Author: David Levine Date: Sun Apr 28 12:49:44 2013 -0500 Allow -clobber with mhstore -outfile. Author: David Levine Date: Sun Apr 28 11:29:47 2013 -0500 Added -outfile switch to mhstore(1). Author: David Levine Date: Sun Apr 28 11:13:41 2013 -0500 Refined error message from check() shell function of test suite. Author: Ken Hornstein Date: Sat Apr 27 20:32:55 2013 -0400 Remove extra arguments from two anno tests; the check() function now complains about them. Looks like they were always there. Author: David Levine Date: Sat Apr 27 14:08:49 2013 -0500 Removed #include of sys/param.h from sbr/makedir.c. It's #include'd by h/nmh.h, with HAVE_SYS_PARAM_H protection. Author: David Levine Date: Sat Apr 27 13:26:18 2013 -0500 Allow mhfixmsg -reformat to succeed even when decode of binary text fails. This is a refinement of commit ebf35185aa9256b0cd09234f39bd14db9e90e81c. Author: David Levine Date: Sat Apr 27 13:24:53 2013 -0500 Added support for 'ignore space' argument to check() function of test/common.sh.in. Author: David Levine Date: Mon Apr 22 22:00:38 2013 -0500 Completed commit 52a236230220232fd632b5aa88eb9bb31dba346e so that send(1)/post(1) use "credentials" profile entry. post doesn't read the profile so pass the credentials setting to it via a new switch. Author: David Levine Date: Sun Apr 21 09:49:48 2013 -0500 Replaced calls to static getcpy() in mf.c with calls to strdup() Author: David Levine Date: Sun Apr 21 09:43:27 2013 -0500 Added quoting of local part of invalid address in message being replied to [Bug #26780]. Author: David Levine Date: Sun Apr 21 09:42:00 2013 -0500 Fixed small formatting glitch in repl man page. Author: David Levine Date: Sun Apr 21 09:41:03 2013 -0500 Added const to arguments of mf functions. Author: David Levine Date: Sun Apr 21 09:39:44 2013 -0500 Added const to argument of getname(). Author: David Levine Date: Sun Apr 21 09:39:20 2013 -0500 Added const to argument of getcpy(). Author: David Levine Date: Sat Apr 20 08:36:12 2013 -0500 Refined commit 9b70e8396d50989db2177547515594bc15ee8b17 to allow options to be passed to ls from whatnow prompt. This way, "ls -l" works as expected. Author: David Levine Date: Fri Apr 19 21:06:50 2013 -0500 Added mention to mhlist(1) man page, in response to question from Ralph, that it lists multipart/alternative parts in reverse order of their placement in a message. And in response to suggestion from Ralph, trimmed whitespace from ends of mhlist output lines. Author: Paul Fox Date: Tue Apr 9 14:32:32 2013 -0400 test-mark: add tests for relative message selections Author: Paul Fox Date: Thu Apr 4 08:21:19 2013 -0400 mh-sequence.man: document new '=+' and '=-' for selecting relative msgs also add a line-item to docs/pending-release-notes. Author: Paul Fox Date: Thu Apr 4 08:21:50 2013 -0400 m_convert: 'foo=n' and 'foo=+/-n' now select msgs with relative offsets Author: David Levine Date: Thu Apr 18 21:30:33 2013 -0500 Fixed permissions of maildelivery file in test-slocal to fix test failure reported by Paul Fox. Also added code to the test to help diagnose any failure. Author: David Levine Date: Tue Apr 16 08:00:54 2013 -0500 Plugged memory leak in m_unknown(). Author: David Levine Date: Tue Apr 16 07:59:54 2013 -0500 Added date to test message with two blank lines between header and body so that the test can pass on other days. Author: David Levine Date: Mon Apr 15 21:01:12 2013 -0500 Fixed problem in m_getfld() reported by Paul Fox. When inc'ing a message from a maildrop with two blank lines between the header and body, the last 3 or 4 characters of the last header would be copied into the body. Author: David Levine Date: Sun Apr 14 10:47:31 2013 -0500 Moved #include of signal.h to h/signals.h. And it was already in h/nmh.h. Author: David Levine Date: Sun Apr 14 10:27:47 2013 -0500 Moved #include of errno.h to h/nmh.h. Author: David Levine Date: Sun Apr 14 10:13:42 2013 -0500 Removed #include of sys/wait.h from sbr/pidstatus.c. I missed it with b523a72928c0ef630be33cf5f5aab9fc301958e1. Author: David Levine Date: Sun Apr 14 09:53:32 2013 -0500 A "credentials" mh-profile entry has been added. This allows post(8), whom(1), send(1), inc(1), and msgchk(1) to (optionally) honour the username in the .netrc file [Bug #23168]. And, it allows specification of any valid filename in place of $HOME/.netrc. Author: David Levine Date: Tue Apr 9 20:26:43 2013 -0500 Fixed typo in several man pages. Author: David Levine Date: Wed Apr 3 20:06:19 2013 -0500 Added vpick to dist_contib_DATA so it gets distributed. Author: David Levine Date: Wed Apr 3 19:56:54 2013 -0500 Be sure that mhfixmsg returns a status of non-zero if it can't reformat a part. Author: David Levine Date: Wed Apr 3 18:46:22 2013 -0500 Added port number to "Connecting to" message with -snoop. Author: Ken Hornstein Date: Mon Apr 1 12:10:28 2013 -0400 Document new -initialtls option. Author: David Levine Date: Sun Mar 31 20:56:49 2013 -0500 Cast away constness of SSL_CTX_new() arg because that's what older versions of ssl use. Author: David Levine Date: Sun Mar 31 20:39:55 2013 -0500 Look at post instead of inc to determine build options in build_nmh. Author: David Levine Date: Sun Mar 31 20:39:22 2013 -0500 Added const to SSL_METHOD *. Author: Ken Hornstein Date: Sun Mar 31 18:33:46 2013 -0400 Preliminary support for TLS negotiation at the very start of SMTP session. Author: David Levine Date: Sun Mar 31 16:32:10 2013 -0500 Moved #include to h/nmh.h. Author: David Levine Date: Sun Mar 31 11:45:09 2013 -0500 Removed limit on maximum number of sequences in a folder. Dynamically sized vectors in sbr/vector.c were added to support this. Their sizes are limited only by virtual memory. Author: David Levine Date: Sat Mar 30 09:53:10 2013 -0500 Moved #include to h/nmh.h. Author: David Levine Date: Fri Mar 29 12:09:15 2013 -0500 A bug fix and an enhancement to mhfixmsg based on patches provided by M. Levinson: 1) Set status to NOTOK in get_multipart_boundary() if the message is missing its end boundary. This avoids a seg fault in fix_boundary(); also added check for null return from parse_mime(). If this turns out to be a common problem, we could consider adding code to repair it. Now, mhfixmsg ignores the condition and proceeeds with any other transformations. 2) With -decodetext 7bit, mhfixmsg now converts base64-encoded parts to quoted-printable 8bit if the part will not fit into 7bit. Author: Ken Hornstein Date: Wed Mar 27 14:56:44 2013 -0400 Document changes regarding increased per-folder sequence limits. Author: Ken Hornstein Date: Wed Mar 27 14:51:33 2013 -0400 Warn the user if too many sequences exist during sequence initialization. Author: Ken Hornstein Date: Wed Mar 27 14:22:40 2013 -0400 Change seqset_t to unsigned long to support more sequences on LP64 systems. Also include necessary casts to make sequence macros worked properly. Based on code contributed by M. Levinson. Author: David Levine Date: Mon Mar 25 22:29:06 2013 -0500 Reworded description of "mark -seq foo delete all" example in mark(1) man page. Author: David Levine Date: Sun Mar 24 13:37:47 2013 -0500 Finished replacing mh_strcasecmp() with strcasecmp(). Removed sbr/strcasecmp.c. Author: David Levine Date: Sun Mar 24 13:23:59 2013 -0500 More replacements of mh_strcasecmp() with strcasecmp(). Author: David Levine Date: Sun Mar 24 11:45:42 2013 -0500 More replacements of mh_strcasecmp() with strcasecmp(). Author: David Levine Date: Sun Mar 24 11:28:51 2013 -0500 More replacements of mh_strcasecmp() with strcasecmp(). Author: David Levine Date: Sun Mar 24 11:15:27 2013 -0500 More replacements of mh_strcasecmp() with strcasecmp(). Author: David Levine Date: Sun Mar 24 10:36:18 2013 -0500 More replacements of mh_strcasecmp() with strcasecmp(). Author: David Levine Date: Sun Mar 24 09:09:02 2013 -0500 Started replacing uses of mh_strcasecmp() with strcasecmp(). Author: Ken Hornstein Date: Sat Mar 23 22:59:24 2013 -0400 Change folder_delmsgs() to save context and sequence files (and make sure those changes are before calling rmmproc(). Update programs that use folder_delmsgs() to make all changes to sequences and the context before calling folder_delmsgs(). Author: Ken Hornstein Date: Fri Mar 22 00:28:35 2013 -0400 Make some formatting changes to conform to our manpage style. Author: David Levine Date: Fri Mar 22 08:33:40 2013 -0500 Always update sequences and context in mhfixmsg, not just when there is a rmmproc. Author: David Levine Date: Thu Mar 21 21:05:09 2013 -0500 Fixes from M. Levinson: 1) Fixed typo in elinks option in etc/mhn.defaults.sh. 2) Added #include to mhfixmsg.c. 3) Fixed seg fault when there's no corresponding profile entry for a message part in mhfixmsg. 4) If rename() fails in write_content() of mhfixmsg, attempt to copy and then remove the file. Author: Ken Hornstein Date: Thu Mar 21 21:49:29 2013 -0400 Minor formatting fix for fmttest man page. Author: Alexander Zangerl Date: Thu Mar 21 20:22:21 2013 -0500 Went through the sources and checked where etcpath() is used, and added/cloned an explanatory bit of text from the fmttest man page to the files section for all affected programs. Author: Ken Hornstein Date: Thu Mar 21 18:28:21 2013 -0400 Make sure to mark the sequence file as closed in the msgs struct. Author: Ken Hornstein Date: Thu Mar 21 17:19:46 2013 -0400 Change mhfixmsg to the new world folder_read() API. Merge: 6f70907 85bb87a Author: Ken Hornstein Date: Thu Mar 21 17:14:30 2013 -0400 Merge branch 'newlock' Author: Ken Hornstein Date: Thu Mar 21 17:12:42 2013 -0400 More documentation about locking changes. Author: Ken Hornstein Date: Thu Mar 21 17:12:13 2013 -0400 Support for sequence file locking in inc(1). Author: Ken Hornstein Date: Thu Mar 21 13:47:04 2013 -0400 Don't lock and write the sequence files until after the searching is complete. Author: David Levine Date: Thu Mar 21 09:13:13 2013 -0500 Replaced reference to mktemp(3) with mkstemp(3) in rmmproc.messageid. Author: David Levine Date: Wed Mar 20 21:48:57 2013 -0500 Added support for Content-Disposition header (RFC 2183) to mhstore(1) and mhn(1) when used with -auto. Author: David Levine Date: Wed Mar 20 20:52:10 2013 -0500 Removed hard-coded locking selection from SPECS/nmh.spec. Author: David Levine Date: Wed Mar 20 20:25:31 2013 -0500 Fixed typo in rmf man page. Author: David Levine Date: Tue Mar 19 07:32:24 2013 -0500 Added -[no]rmmproc switches to rmm and mhfixmsg. Author: Ken Hornstein Date: Tue Mar 19 01:02:45 2013 -0400 Make sure the building of config/config.o and sbr/mts.o depend on the Makefile so changes to the Makefile are properly reflected in the build. Author: David Levine Date: Mon Mar 18 20:00:10 2013 -0500 Added -[no]rmmproc switches to rmm and mhfixmsg. Author: Ken Hornstein Date: Mon Mar 18 15:29:35 2013 -0400 Add code for (and convert world to) the new world lock order. Still need to add some code to make inc and pick behave better (not hold locks for as long). Author: Ken Hornstein Date: Mon Mar 18 10:38:06 2013 -0400 Add ICONVLIB to build rule for mhfixmsg Author: David Levine Date: Mon Mar 18 08:54:55 2013 -0500 Fixed use of WIFEXITED in mhfixmsg.c. Author: David Levine Date: Sun Mar 17 21:55:56 2013 -0500 Fixed procmail example in mhfixmsg man page. Author: David Levine Date: Sun Mar 17 15:40:36 2013 -0500 Removed color-tests from AM_INIT_AUTOMAKE because the build breaks if not supported, and automake 1.13 enables it by default. Author: David Levine Date: Sun Mar 17 10:32:57 2013 -0500 Added mhfixmsg(1). Author: David Levine Date: Sun Mar 17 10:29:26 2013 -0500 Fixed typo in fmmtest man page. Author: Ken Hornstein Date: Sat Mar 16 00:04:38 2013 -0400 Add information about locking support entries to the man pages. Author: Ken Hornstein Date: Fri Mar 15 23:45:54 2013 -0400 Support for locking tests in the test suite. Author: Ken Hornstein Date: Fri Mar 15 19:42:43 2013 -0400 Turns out the close function can be called with FILE * == NULL, so handle that case. Author: Ken Hornstein Date: Fri Mar 15 15:57:56 2013 -0400 Mostly complete now, but not yet functional. Author: David Levine Date: Fri Mar 15 08:50:23 2013 -0500 Corrected comment describing copy_seqs(). Author: David Levine Date: Thu Mar 14 22:02:30 2013 -0500 Changed c_cefile member of struct Content from pointer to struct cefile. The memory cost will be negligible and it simplifies the MIME parser code a bit. Author: David Levine Date: Thu Mar 14 20:58:31 2013 -0500 Added -[no]retainsequences switches to refile(1). Author: David Levine Date: Thu Mar 14 20:37:49 2013 -0500 Changed loop in dumpwidth() to go from [0, 0xffff) because wchar_t is 2 bytes wide on Cygwin. gcc noticed that the loop would never terminate because 0xffff would increment to 0. Author: David Levine Date: Thu Mar 14 19:08:15 2013 -0500 Changed detection of warning in build_nmh for sign mismatch in sbr/dtimep.c to work with older gcc. Author: Ken Hornstein Date: Thu Mar 14 15:57:07 2013 -0400 More locking updates; still doesn't compile yet. Author: Ken Hornstein Date: Wed Mar 13 21:02:48 2013 -0400 Start of the changes for the new lock code. Does not compile yet. Author: Ken Hornstein Date: Tue Mar 12 14:22:49 2013 -0400 Add support for RFC-2017, message/external-body content which contains URLs. Author: Ken Hornstein Date: Tue Mar 12 12:57:41 2013 -0400 Change sample disposition from "application" to "attachment" Author: David Levine Date: Mon Mar 11 18:57:01 2013 -0500 Added check that writesomecmd() isn't at the end of argp before dereferencing ++argp. I'm surprised that no one, including me, tripped over this before: whatnow(1) would seg fault when handling, e.g., detach -n 4. But until I upgraded to Fedora 18, I never noticed it. (valgrind did.) Author: David Levine Date: Mon Mar 11 18:42:16 2013 -0500 Ignore the sign mismatch warning when sbr/dtimep.c is built with flex 2.5.36 or 2.5.37. Author: David Levine Date: Fri Mar 8 06:40:07 2013 -0600 Fixed spelling of "preserve" in refile man page. Author: David Levine Date: Thu Mar 7 20:11:22 2013 -0600 In the locking discussion of mh-folders(5), discourage direct access to the nmh state files. Author: David Levine Date: Tue Mar 5 20:17:08 2013 -0600 Added lockmethod pseudocomponent to mhparam so that users can easily find out what locking method was configured in. Author: Ken Hornstein Date: Tue Mar 5 14:30:51 2013 -0500 Update with more information. Author: David Levine Date: Sun Mar 3 21:45:09 2013 -0600 Added a bit more on sequences to mh-folders.man. Author: David Levine Date: Sun Mar 3 09:53:10 2013 -0600 Added beginnings of storage format spec to new mh-folders.man. Author: David Levine Date: Sun Mar 3 09:49:05 2013 -0600 Fixed typo in rmmproc.messageid. Author: David Levine Date: Wed Feb 27 19:32:38 2013 -0600 Reworked internals of MIME parser's reverse_parts() and made it public. Author: David Levine Date: Wed Feb 27 19:31:31 2013 -0600 Added tolower(), toupper(), and toascii() to gen-ctype-checked.c. Author: David Levine Date: Tue Feb 26 19:23:58 2013 -0600 Added a handful of functions to the parser to allow access to init functions and string representations of enum valus for content types and encodings. Author: David Levine Date: Tue Feb 26 19:08:38 2013 -0600 Added nmh_strcasestr() because POSIX doesn't have strcasestr(). Author: Ken Hornstein Date: Tue Feb 26 13:19:06 2013 -0500 Support RFC 2231 language tags in RFC 2047 header strings. Author: David Levine Date: Mon Feb 25 23:02:05 2013 -0600 Added cpytrim() function. Unlike trimcpy(), it does not modify its argument. Author: David Levine Date: Mon Feb 25 22:46:00 2013 -0600 Added const qualifier to arguments of concat() and copy(). Author: David Levine Date: Sun Feb 24 21:55:28 2013 -0600 Added find_str() and rfind_str() to sbr/utils.c Author: David Levine Date: Sun Feb 24 21:38:33 2013 -0600 Added const qualifier to char * arguments of add(), addlist(), and folder_exists() in sbr/utils.{h,c}. Author: Ken Hornstein Date: Fri Feb 22 00:52:50 2013 -0500 Add support for LS_UNQUOTE instruction. Author: Ken Hornstein Date: Fri Feb 22 00:47:47 2013 -0500 Fix the code to print out an unknown instruction. Wow, this never worked back from the original fmtdump. Author: Ken Hornstein Date: Thu Feb 21 23:56:02 2013 -0500 Whoops, forgot a \ when adding fmttest.man to man_SRCS. Author: Ken Hornstein Date: Thu Feb 21 23:03:31 2013 -0500 Quote the arguments to the .I macro so the manpage test doesn't complain. Author: Ken Hornstein Date: Thu Feb 21 22:55:41 2013 -0500 Document new fmttest program. Author: Ken Hornstein Date: Thu Feb 21 22:55:23 2013 -0500 Fix a few issues resulting from m_getfld() API changes. Merge: b5f3b74 7344831 Author: Ken Hornstein Date: Thu Feb 21 22:40:48 2013 -0500 Merge branch 'format-test' Author: Ken Hornstein Date: Thu Feb 21 22:38:18 2013 -0500 Add a lot more text to the man page; it should be in reasonable shape now. Author: Ken Hornstein Date: Thu Feb 21 22:37:47 2013 -0500 Update instruction output to be a bit more cleaner Author: David Levine Date: Thu Feb 21 21:01:55 2013 -0600 Fixed write8Bit() to use fread()/fwrite() instead of fgets()/fputs(). Author: Ken Hornstein Date: Thu Feb 21 15:53:06 2013 -0500 Flesh this out so finally it's halfway useful. Author: Ken Hornstein Date: Thu Feb 21 15:52:36 2013 -0500 Rearrange options a bit and support the -nodump flag. Also clean up how -raw mode works. Author: Ken Hornstein Date: Thu Feb 21 15:52:09 2013 -0500 Bring this up to best practices. Author: Ken Hornstein Date: Wed Feb 20 22:37:50 2013 -0500 Minor updates for fmttest man page. Author: Ken Hornstein Date: Wed Feb 20 15:53:54 2013 -0500 Basic format tracing support; seems to work! Author: Ken Hornstein Date: Wed Feb 20 15:19:11 2013 -0500 Support for the address duplication done by repl, and also clean up some stuff. Author: Ken Hornstein Date: Wed Feb 20 12:01:05 2013 -0500 Support callbacks into the format engine. This is so we can add in proper hooks for %(formataddr), %(concataddr), and (eventually) tracing. Author: Ken Hornstein Date: Tue Feb 19 21:57:32 2013 -0500 Make generating the ChangeLog work if you're building a distribution from an object directory. Author: Ken Hornstein Date: Tue Feb 19 21:54:14 2013 -0500 The beginnings of a fmttest man page. Author: David Levine Date: Tue Feb 19 19:45:25 2013 -0600 In m_getfld.c, cast the returns of valid characters to unsigned char. This differentiates them from EOF and matches the behavior prior to the recent m_getfld() rework. But that behavior is very broken on 8-bit input. Author: Ken Hornstein Date: Tue Feb 19 13:51:47 2013 -0500 Apply David Levine's fix from whomfile() to sendfile() as well. Author: David Levine Date: Mon Feb 18 21:32:24 2013 -0600 Removed addition of whomproc to the vec array in whomfile() now that argsplit() does it. Author: David Levine Date: Mon Feb 18 21:24:29 2013 -0600 Added locking discussion to rcvstore(1) man page. Author: Ken Hornstein Date: Mon Feb 18 20:51:46 2013 -0500 fmttest is actually starting to get useful now. Some changes were required to the format code to make this code cleaner. Author: David Levine Date: Sun Feb 17 22:04:51 2013 -0600 "RFC-2045 to RFC-2049" instead of "thru". Author: David Levine Date: Sat Feb 16 08:27:29 2013 -0600 When output_content() outputs a non-MIME message with no body, suppress the newline after the headers. Author: David Levine Date: Sat Feb 16 08:23:10 2013 -0600 Added mention of rcvstore(1) to inc(1) man page. Author: David Levine Date: Sat Feb 16 08:21:10 2013 -0600 Plugged small memory leak in etcpath(). Author: David Levine Date: Sat Feb 16 08:19:45 2013 -0600 In InitMultiPart(), always set bogus_mp_content if boundaries don't match. Author: Ken Hornstein Date: Sat Feb 16 00:37:36 2013 -0500 Remove dead UUCP address parsing code. Sadly, this is not the complete removal of UUCP support, but it's a good start. Author: Ken Hornstein Date: Sat Feb 16 00:31:16 2013 -0500 Slightly more useful, but still more work to do. Author: Ken Hornstein Date: Fri Feb 15 15:58:21 2013 -0500 Add more functionality to fmttest; it's starting to get semi-useful. Author: David Levine Date: Thu Feb 14 21:53:50 2013 -0600 Added a couple of global variables to mhparse.c to allow suppression of the warning about bogus multipart content, and detection of it. Author: Ken Hornstein Date: Thu Feb 14 13:50:28 2013 -0500 More work on fmttest, but still plenty more to go. Author: Ken Hornstein Date: Thu Feb 14 13:49:54 2013 -0500 Correct man page information for %(width) format instruction. Author: David Levine Date: Wed Feb 13 21:11:59 2013 -0600 Added support for multiple message/file arguments to rmmproc.message.id. Added mention of it to rmm man page. Author: Ken Hornstein Date: Wed Feb 13 15:53:13 2013 -0500 Clean up argument handling to fmttest, as a precursor to actually getting it done. Author: Ken Hornstein Date: Wed Feb 13 14:42:50 2013 -0500 Remove support for -mail, -saml, -send, and -soml switches in send and whatnow. The code in post implementing these options was removed as part of commit 537e02c38f4bb. Author: Ken Hornstein Date: Wed Feb 13 14:24:11 2013 -0500 Convert fmttest over to the new argument processing world order. Author: Ken Hornstein Date: Wed Feb 13 10:47:26 2013 -0500 Document argsplit changes in mh-profile man page. Author: David Levine Date: Tue Feb 12 22:03:54 2013 -0600 Fixed typo in mhlist man page. Also removed sendfiles(1) from its SEE ALSO list. Author: Ken Hornstein Date: Tue Feb 12 20:05:17 2013 -0500 Remove installproc from the test since we don't have it anymore. Author: Ken Hornstein Date: Tue Feb 12 15:39:18 2013 -0500 Remove "installproc" since it is no longer used. Author: Ken Hornstein Date: Tue Feb 12 15:37:00 2013 -0500 Final conversion to new argsplit() code. Author: Ken Hornstein Date: Mon Feb 11 15:57:31 2013 -0500 Add a new test for the MIME functionality in burst. Author: David Levine Date: Sun Feb 10 20:55:54 2013 -0600 Multipart parts might have content before the first subpart and/or after the last subpart that hasn't been stored anywhere else, so do that at the end of InitMultiPart(), and output it in output_content(). Author: David Levine Date: Sun Feb 10 19:05:37 2013 -0600 Added etc/rmmproc.messageid, which shows how to try to move a message or file to a file that's named based on Message-ID. Author: Ken Hornstein Date: Fri Feb 8 15:46:31 2013 -0500 Make burst(1) be able to burst MIME-formatted messages with message/rfc822 parts in them. Author: Ken Hornstein Date: Fri Feb 8 13:02:00 2013 -0500 Create a central prototype for free_content(). Author: Ken Hornstein Date: Thu Feb 7 14:34:12 2013 -0500 More conversion to argsplit(). Author: Ken Hornstein Date: Thu Feb 7 11:31:45 2013 -0500 Move etc/gen-ctype-checked into an Automake primary so dependency information can properly be recorded for it. Author: David Levine Date: Wed Feb 6 20:39:06 2013 -0600 When debugging is enabled, replace the ctype functions with macros that index into arrays. This allows the compiler to catch use of char, instead of unsigned char, arguments to those functions. gcc uses -Wchar-subscripts, which is enabled with the -Wall that we use by default. Thanks to Tom Lane for suggesting this approach. This feature can be enabled by undef'ing NDEBUG in config.h. configure --enable-debug does that. We can now use the same mechanism to enable and disable assert(3), too. Author: David Levine Date: Wed Feb 6 20:31:18 2013 -0600 Added global variable skip_mp_cte_check to turn off that check for incorrect encoding of multipart messages in InitMultiPart(). Author: David Levine Date: Wed Feb 6 20:28:29 2013 -0600 output_content() assumed that ci->ci_values[0] was the boundary, but that's not always the case. Added search for the boundary in ci->ci_attrs[]. Author: Ken Hornstein Date: Wed Feb 6 15:51:04 2013 -0500 More work to convert programs over to the use of argsplit(). Author: Ken Hornstein Date: Wed Feb 6 11:12:56 2013 -0500 Make sure these stdarg lists are properly terminated with pointer-context NULLs. Author: Ken Hornstein Date: Tue Feb 5 21:06:35 2013 -0500 Remove warning suppression we no longer need. Hooray! Author: Ken Hornstein Date: Tue Feb 5 21:00:40 2013 -0500 FINALLY clean up our signed/unsigned character warning mess. In short, we have switched to using "char" almost everywhere, and casting char to unsigned char when using the ctype macros/functions. Author: David Levine Date: Tue Feb 5 16:20:53 2013 -0600 Changed m_getfld() to use char instead of unsigned char. Author: David Levine Date: Tue Feb 5 15:25:23 2013 -0600 Changed m_getfld() to use char instead of unsigned char. Author: Ken Hornstein Date: Tue Feb 5 13:01:09 2013 -0500 Start of the signed/unsigned char cleanup. Author: David Levine Date: Sun Feb 3 22:51:00 2013 -0600 Tweaked logic in brkstring.c and showfile.c to get rid of the remaining "statement not reached" warnings from Solaris cc. Author: Ken Hornstein Date: Sat Feb 2 14:28:39 2013 -0500 Make sure we don't link getcwidth with the nmh libraries. Author: David Levine Date: Sat Feb 2 12:56:53 2013 -0600 Added support for "-" to indicate stdout to output_message(). Author: David Levine Date: Sat Feb 2 12:54:55 2013 -0600 Removed unlink of "core" from signal handler of mhlist, mhn, mhshow, and mhstore. Those programs shouldn't remove a file that has nothing to do with them. Author: David Levine Date: Sat Feb 2 12:40:59 2013 -0600 Removed myuid and mygid variables, they're no longer used and the Solaris C compiler complained about their initializers. Author: Ken Hornstein Date: Sat Feb 2 13:30:24 2013 -0500 Cast wchar_t to long unsigned int to deal with differing types of wchar_t across systems. Author: David Levine Date: Sat Feb 2 11:55:23 2013 -0600 Suppress warning from test-manpages that groff can't break a line if the user's prefix is too long. Author: David Levine Date: Sat Feb 2 10:54:32 2013 -0600 The Solaris compiler was right about unreachable statements. Fixed all of them in uip/. Author: David Levine Date: Sat Feb 2 10:21:14 2013 -0600 Added l modifier to X printf conversions of wchar_t's. Author: David Levine Date: Sat Feb 2 10:18:24 2013 -0600 Removed unused vec[0] relic from before argsplit conversion. Author: David Levine Date: Sat Feb 2 10:12:57 2013 -0600 Added trailing newline to sed input in mhmail when processing -headerfield argument, to squelch complain from Solaris sed. Author: David Levine Date: Sat Feb 2 09:59:28 2013 -0600 Set MHTMPDIR to try to keep all test-related files together. Author: David Levine Date: Sat Feb 2 09:58:20 2013 -0600 More test-mhmail probing. Author: David Levine Date: Sat Feb 2 09:23:49 2013 -0600 Try this test-mhmail probe. Author: David Levine Date: Sat Feb 2 08:43:32 2013 -0600 More test-mhmail probing. Author: David Levine Date: Sat Feb 2 08:26:43 2013 -0600 Modified test-mhmail probe. Author: David Levine Date: Sat Feb 2 08:15:15 2013 -0600 Added temporary probe to test-mhmail. Author: Ken Hornstein Date: Sat Feb 2 01:10:06 2013 -0500 Convert post over to use new argsplit code. Author: Ken Hornstein Date: Sat Feb 2 00:48:54 2013 -0500 Handle the case where (on Solaris) the width of U+2019 is 2 (which seems TOTALLY bizarre to me, but there you have it). Author: Ken Hornstein Date: Sat Feb 2 00:33:51 2013 -0500 Rework multibyte test so it will calculate the width of all of the Unicode characters we are using. Author: David Levine Date: Fri Feb 1 23:24:27 2013 -0600 In setup_test(), set PATH after install. Author: David Levine Date: Fri Feb 1 23:12:09 2013 -0600 Added set -x to test-ali. Author: David Levine Date: Fri Feb 1 22:52:00 2013 -0600 Maybe the mkdir in setup_test() needs a -p? Author: David Levine Date: Fri Feb 1 22:39:49 2013 -0600 More test-ali diagnostics for Solaris. Author: David Levine Date: Fri Feb 1 22:25:51 2013 -0600 Use test -t 1 instead of test -w in test-pick. Author: David Levine Date: Fri Feb 1 22:24:48 2013 -0600 More setup_test() and test-ali attempts on Solaris. Author: David Levine Date: Fri Feb 1 18:46:02 2013 -0600 Removed the ls of folder from setup_test(). Author: David Levine Date: Fri Feb 1 18:35:13 2013 -0600 Try full path to folder in setup_test(). Author: David Levine Date: Fri Feb 1 18:16:26 2013 -0600 Maybe the PATH needs to be exported again in setup_test()? Author: David Levine Date: Fri Feb 1 17:37:02 2013 -0600 So folder does exist the first time through setup_test(). Let's see its stdout. Author: David Levine Date: Fri Feb 1 17:20:37 2013 -0600 Suppressed display of info message when test-eom-align isn't run with stdout to a terminal. Author: David Levine Date: Fri Feb 1 17:19:40 2013 -0600 Temporarily added ls of folder to setup_test(). Author: David Levine Date: Fri Feb 1 15:08:32 2013 -0600 In setup_test(), create the Mail directory if it doesn't already exist. Author: Ken Hornstein Date: Fri Feb 1 15:41:00 2013 -0500 Ignore the return status of diff, so we don't exit if diff fails when using set -e. Author: Ken Hornstein Date: Fri Feb 1 15:18:47 2013 -0500 Add some diagnostics to determine what is going wrong. Author: David Levine Date: Fri Feb 1 14:08:45 2013 -0600 It looks like the first test fails on Solaris because it can't find folder. So, added a test/sleep before its first use, in setup_test(). Author: Ken Hornstein Date: Fri Feb 1 15:03:16 2013 -0500 If the multibyte width test fails, dump the values of wcwidth() for the complete BMP. Author: David Levine Date: Fri Feb 1 13:38:36 2013 -0600 Added diagnostic to setup_test() to try to figure out why the first test fails on the Solaris buildbot. Author: David Levine Date: Fri Feb 1 13:36:23 2013 -0600 Restored test-ali to its prior condition. It failed on the Solaris buildbot because it was the first test. Author: Ken Hornstein Date: Fri Feb 1 14:06:49 2013 -0500 Make sure we created the test file even if we don't have iconv support; it's needed for two tests. Author: Ken Hornstein Date: Fri Feb 1 13:42:51 2013 -0500 Move ICONV_ENABLED so it always gets initialized even if the header check for iconv.h fails. Author: Ken Hornstein Date: Fri Feb 1 13:25:17 2013 -0500 If we don't have iconv, skip the multibyte test that requires character set conversion. Author: Ken Hornstein Date: Fri Feb 1 12:30:45 2013 -0500 Finally switch over from vfork() to fork() completely. Author: Ken Hornstein Date: Fri Feb 1 12:11:59 2013 -0500 More code converted to use argsplit(). Author: Lyndon Nerenberg Date: Fri Feb 1 07:25:44 2013 -0800 Fix configure tests for -Wfoo option support. Drooped support for -Wunused-macros and -Wno-unused-macros. The warnings serve no useful purpose, and causing subsequent configure checks for -Wfoo flags to get messed up. Split each test of -Wfoo into a separate check. Include -Werror in the individual flag tests to ensure the test compile fails if the other flag isn't supported. Without this, clang issues a diagnostic message about the flag being ignored, but otherwise carries on, fooling configure into thinking the flag is in fact supported. Merge: ae9b723 b78be76 Author: Lyndon Nerenberg Date: Fri Feb 1 04:44:29 2013 -0800 Merge branch 'master' into savannah Author: Lyndon Nerenberg Date: Fri Feb 1 00:20:44 2013 -0800 Update manpages to use .TP for tagged paragraphs (part I). This replaces .fc/.nf and friends with the man(7) .TP macro. This commit covers about half of the man pages. The rest will follow in a couple of days. Author: Lyndon Nerenberg Date: Fri Feb 1 00:20:44 2013 -0800 Update manpages to use .TP for tagged paragraphs (part I). This replaces .fc/.nf and friends with the man(7) .TP macro. This commit covers about half of the man pages. The rest will follow in a couple of days. Author: Lyndon Nerenberg Date: Thu Jan 31 21:28:51 2013 -0800 Update the manpage template documentation. Update the section ordering to follow the UNIX order. This pulls nmh-specific sections into the body of the manpage, and pushes FILES, SEE ALSO, and BUGS to the end. Clarifies a few other minor points. Author: David Levine Date: Thu Jan 31 22:32:26 2013 -0600 More probing of test-ali on Solaris: exit before the setup_test call, which has the folder invocation. Author: David Levine Date: Thu Jan 31 22:30:36 2013 -0600 OK, test-pick should be good on Solaris now. Author: David Levine Date: Thu Jan 31 21:27:46 2013 -0600 Added exit to test-ali, temporarily, to isolate failure on Solaris. Author: David Levine Date: Thu Jan 31 21:24:53 2013 -0600 More homing in on the test-pick warning. Also, removed warning to user that the tty test is being skipped, it's not that important. Author: David Levine Date: Thu Jan 31 20:10:59 2013 -0600 Removed an used sed invocation from test-mhmail. I don't know if it was causing the warnings on Solaris, we'll see. Author: Ken Hornstein Date: Thu Jan 31 21:04:43 2013 -0500 Fix some warnings for Solaris. Author: David Levine Date: Thu Jan 31 20:04:50 2013 -0600 it looks like the write to /dev/tty is causing the warning from test-pick on Solaris, here's an attempt to squelch that. Author: David Levine Date: Thu Jan 31 19:44:47 2013 -0600 Removed sizes from mhlist output. Apparently tar files are so much smaller on Solaris that they cause the check of its output to break. The test also compares the contents of the tar file, so it's still adequate. Author: David Levine Date: Thu Jan 31 19:43:09 2013 -0600 Redirected stderr to /dev/null in the test for presence of /dev/tty. Solaris warns that it can't create the device. This may not fix it, but it should help isolate which part of the test is causing the warning. Author: Ken Hornstein Date: Thu Jan 31 20:01:27 2013 -0500 Set the locale for one of the "pick" invocations to UTF-8, so we can decode the UTF-8 header correctly in the test. Author: Lyndon Nerenberg Date: Thu Jan 31 03:56:55 2013 -0800 Use cmp(1) to compare acheieved and expected test results. 'diff -c' on Solaris 11 generate a spurious 'No differences encountered' message (on stdout, no less!) when the compared files are identical. This changes the test logic to compare with 'cmp -s', and then perform a 'diff -c' if the results don't match expectations. Author: Lyndon Nerenberg Date: Thu Jan 31 01:44:03 2013 -0800 Wrap 'pick -subject foobar 13' test with set +e/-e. The command was failing silently on FreeBSD, leading to premature script termination. Author: Lyndon Nerenberg Date: Wed Jan 30 23:55:26 2013 -0800 Change the MD5FMT macro in configure.ac to not emit filename. Author: Lyndon Nerenberg Date: Wed Jan 30 23:07:17 2013 -0800 How hard can it be to write a portable shell function that does nothing? Pretty hard, apparently :-P Author: Lyndon Nerenberg Date: Wed Jan 30 21:45:16 2013 -0800 Hush progress indicator during tests when stdout is not a tty. This eliminates 100 lines of logfile spam during buildbot runs. Merge: e716be9 f1722de Author: Lyndon Nerenberg Date: Wed Jan 30 19:58:16 2013 -0800 Merge branch 'master' of ssh://git.sv.gnu.org/srv/git/nmh into nmh Author: Lyndon Nerenberg Date: Wed Jan 30 19:57:22 2013 -0800 IPPROTO_TCP requires At least on BSD it does. Author: Ken Hornstein Date: Wed Jan 30 15:47:32 2013 -0500 More changes to use argsplit() for helper programs. Author: Ken Hornstein Date: Tue Jan 29 15:58:34 2013 -0500 Switch the editor invocation over to use argsplit(). Author: Ken Hornstein Date: Tue Jan 29 15:30:36 2013 -0500 The start of the use of argsplit() to process command strings. Author: David Levine Date: Mon Jan 28 21:38:39 2013 -0600 Changed m_getfld() buffer size to 4096 from 8192, to benefit scan(1). We could consider using a larger buffer size when readying message bodies. But I expect any benefit would be overshadowed by the way parse_mime() currently reads MIME messages: it reopens the file for each part. Author: David Levine Date: Mon Jan 28 21:20:22 2013 -0600 Added m_getfld_track_filepos() for callers to indicate that they may interleave fseek*/ftell* calls with m_getfld() calls. This eliminates the need for m_getfld() to call fseek() when called by inc(1) and scan(1). Author: David Levine Date: Mon Jan 28 19:12:17 2013 -0600 Added scan_reset_m_getfld_state(), for msh only. It needs to call that so that it can support more than one operation on its mailbox. Merge: a5a4757 4538251 Author: David Levine Date: Sun Jan 27 10:37:54 2013 -0600 Merge branch 'm_getfld' Author: David Levine Date: Sun Jan 27 10:11:10 2013 -0600 In the sortm warning message, say "file modification time" instead of "file mtime", per Paul F.'s suggestion. Author: David Levine Date: Sun Jan 27 09:34:58 2013 -0600 Changed sortm warning message from an amonish() to and advise(), and included the remedy of using the file mtime, per suggestions of Norm and Ralph. Author: David Levine Date: Sun Jan 27 08:37:31 2013 -0600 Fixed a couple of calls to m_getfld(): they were in while loops and the loop bodies were missing brackets. Author: David Levine Date: Sat Jan 26 09:42:25 2013 -0600 Deprecated msh(1). Author: David Levine Date: Sat Jan 26 09:00:48 2013 -0600 In build_nmh's output from the test suite: retain colorization and list any test failures. Author: David Levine Date: Sat Jan 26 08:52:50 2013 -0600 Enabled colorized test output (PASS/FAIL/summary) by default via "color-tests" automake option. To disable at runtime, either set your AM_COLOR_TESTS environment variable to "no", or provide that on the make check command line. Author: David Levine Date: Fri Jan 25 22:21:53 2013 -0600 Reworked the new documentation in m_getfld.c. Author: Ken Hornstein Date: Fri Jan 25 22:22:46 2013 -0500 Handle the case in the test suite where wcwidth() can return different values for combining Unicode codepoints on different operating systems. Author: Ken Hornstein Date: Thu Jan 24 16:05:36 2013 -0500 Fix the format engine so it properly keeps track of multibyte characters and column positions when processing components and other functions. When working on this code I realized we have nothing that checks to make sure right justification of format function output works properly, so a test for right justification is also included. Author: David Levine Date: Wed Jan 23 20:24:21 2013 -0600 Added functions for inc, msh, rcvtty, and scan to access scansbr's gstate instance so it can be hidden, except for msh's uses of m_getfld(). Author: Ken Hornstein Date: Mon Jan 21 10:32:37 2013 -0500 Fix a bug leading to message corruption with inc when incorporation more than one message at a time. When I reworked the scan() code to remove the use of stdio internals, two code paths were created. The inc code path consumed another buffer from the nxtbuf list for processing the message body. At the end of scan() there was code to push back all of the consumed buffers to the nxtbuf list. The extra buffer consumed in the inc code path wasn't being pushed back, and as a result the nxtbuf list would end up with duplicate pointers in it. This would result in two components sharing the same text buffer, which caused the message corruption. When I looked at this closer, I realized that there was no reason to push those buffers back to the list; nxtbuf gets reset to compbuffers at the start of every call to scan(), and nxtbuf isn't used after the buffers are pushed back. Some researched revealed that this was the same back in the original MH code. I decided it was simplest to simply delete the buffer recycling code. (cherry picked from commit 22d2acba60374851c291260ff6aa716e9bf44a6d) Author: David Levine Date: Wed Jan 23 19:42:56 2013 -0600 Brought over changes to test-pop from master to m_getfld branch. Author: David Levine Date: Sun Jan 20 08:38:18 2013 -0600 Added scan and inc from mbox with multiple messages. (cherry picked from commit c4c53777458bfcfd288d45b7708e52eb47c56405) Author: David Levine Date: Thu Jan 17 20:58:25 2013 -0600 Added test-msg-buffer-boundaries. (cherry picked from commit dbd0fa0a56a222bd118fea627eba53e5d9811d01) Author: David Levine Date: Wed Jan 23 19:20:40 2013 -0600 Brought over changes to test-pop from m_getfld branch. Author: David Levine Date: Tue Jan 22 21:02:49 2013 -0600 Changed m_getfld() to automatically allocate a new state instance as needed. Callers no longer use m_getfld_state_init(). Author: David Levine Date: Tue Jan 22 17:08:21 2013 -0600 Removed unnecessary m_getfld_state_destroy() from scan.c. Author: David Levine Date: Tue Jan 22 17:07:47 2013 -0600 Reworked enter_getfld() and Peek(). Merge: 2f5c4e8 22d2acb Author: Ken Hornstein Date: Mon Jan 21 10:58:07 2013 -0500 Merge branch 'master' into format-test Author: Ken Hornstein Date: Mon Jan 21 10:32:37 2013 -0500 Fix a bug leading to message corruption with inc when incorporation more than one message at a time. When I reworked the scan() code to remove the use of stdio internals, two code paths were created. The inc code path consumed another buffer from the nxtbuf list for processing the message body. At the end of scan() there was code to push back all of the consumed buffers to the nxtbuf list. The extra buffer consumed in the inc code path wasn't being pushed back, and as a result the nxtbuf list would end up with duplicate pointers in it. This would result in two components sharing the same text buffer, which caused the message corruption. When I looked at this closer, I realized that there was no reason to push those buffers back to the list; nxtbuf gets reset to compbuffers at the start of every call to scan(), and nxtbuf isn't used after the buffers are pushed back. Some researched revealed that this was the same back in the original MH code. I decided it was simplest to simply delete the buffer recycling code. Author: David Levine Date: Mon Jan 21 08:42:20 2013 -0600 Plugged small memory leak in m_unknown(). Author: David Levine Date: Sun Jan 20 22:22:17 2013 -0600 Replaced hard-coded value with MAX_DELIMITER_SIZE in m_getfld.c. Author: David Levine Date: Sun Jan 20 21:27:54 2013 -0600 Removed the static m_getfld() state instance and replaced with functions for callers to create and destroy their own instances. This also allows inc, msh, and pick to call m_getfld() with an initial file stream position other than 0. There is now a global state instance so that scan can call m_unknown() on maildrop files. It'd be nice to get rid of that. Author: Ken Hornstein Date: Sun Jan 20 22:23:58 2013 -0500 Fix memory leak in arglist code Author: David Levine Date: Sun Jan 20 08:38:18 2013 -0600 Added scan and inc from mbox with multiple messages. Author: David Levine Date: Sun Jan 20 07:49:58 2013 -0600 Updated test-inc-scanout on master to match version of m_getfld branch. Author: David Levine Date: Sat Jan 19 08:33:38 2013 -0600 Added a FILE * to the m_getfld_state struct so that most functions don't need to pass it explicitly. Note that m_getfld() must still be passed the FILE * because some callers, e.g., those in mhparse.c, reopen their input file and therefore pass different FILE *'s for the same input. Author: David Levine Date: Sat Jan 19 08:00:03 2013 -0600 Moved all file static data in m_getfld.c into the m_getfld_state struct. Changed MSG_INPUT_SIZE from hard-coded number to BUFSIZ. Author: David Levine Date: Sat Jan 19 06:54:10 2013 -0600 Added check of -pack to test-pop. Author: David Levine Date: Fri Jan 18 19:19:00 2013 -0600 Fixed test-header to work on Cygwin, which has a BUFSIZ of only 1024. That caused an error message to be truncated. Author: Ken Hornstein Date: Fri Jan 18 16:03:26 2013 -0500 Beginning of implementation of new argsplit() function to handle arguments to profile-defined commands. Author: David Levine Date: Thu Jan 17 21:58:50 2013 -0600 Removed all traces of m_getfld() FLDEOF and BODYEOF states. They were never set by m_getfld(), so all caller code that supported them was completely unexercised. Author: David Levine Date: Thu Jan 17 21:46:54 2013 -0600 Minimized message files reads in m_getfld() when the caller interleaves calls to fseek(). Added check of handling of long header field name without a colon to test-header. Author: David Levine Date: Thu Jan 17 20:58:25 2013 -0600 Added test-msg-buffer-boundaries. Author: David Levine Date: Wed Jan 16 22:02:12 2013 -0600 More cleanup of m_getfld(), changed some variable names. Author: David Levine Date: Wed Jan 16 21:48:11 2013 -0600 Added check of header field body with more than 511 characters to test-inc-scanout. Also changed a couple of test message files to be generated on the fly. Author: David Levine Date: Wed Jan 16 20:13:04 2013 -0600 Cleaned up m_getfld() code a bit. The most notable change was to remove the check for mmdlm2 not being null. It's global data so that shouldn't happen. Author: David Levine Date: Tue Jan 15 22:56:33 2013 -0600 Added check of a header with name that's 998 bytes long to test-header. Author: David Levine Date: Tue Jan 15 20:11:41 2013 -0600 Removed the for-loop that was used to get a header field name in m_getfld (). It was no longer necessary when not drawing directly from the stdio buffer. Author: David Levine Date: Tue Jan 15 19:38:16 2013 -0600 Check that a character array isn't empty before looking for its next-to-last element. Author: David Levine Date: Tue Jan 15 18:14:46 2013 -0600 In build_nmh, removed configuration of pager and editor. And replaced use of which(1) with a self-contained function. Author: Ken Hornstein Date: Tue Jan 15 15:30:17 2013 -0500 Support the VISUAL and EDITOR environment variables, and remove support for configuring a default editor with --with-editor. Author: Ken Hornstein Date: Tue Jan 15 13:22:13 2013 -0500 Remove the --with-pager configure option and replace it with a default of "more". Author: David Levine Date: Mon Jan 14 22:05:38 2013 -0600 Renamed a couple of m_getfld auxiliary functions. Author: David Levine Date: Mon Jan 14 21:34:08 2013 -0600 Cleaned up m_getfld's read_more(). Author: David Levine Date: Mon Jan 14 21:05:22 2013 -0600 In m_getfld(), fixed the loop that handles the FLDPLUS case. In Getc(), removed the increment of the byte count at EOF, it didn't seem correct or necessary. Author: David Levine Date: Mon Jan 14 20:58:56 2013 -0600 m_getfld() now supports interleaving calls with fseek()/ftell(). Reverted the changes to uip/mhparse.c of commit 484eb1003ae647e4b751e4d7829c7daf44fb99c9 because they're no longer necessary. Author: David Levine Date: Mon Jan 14 09:45:23 2013 -0600 Moved test of empty header field from test/inc/test-inc-scanout to test/bad-input/test-header. Author: David Levine Date: Mon Jan 14 09:41:50 2013 -0600 Cleaned up a bit. Author: David Levine Date: Sun Jan 13 21:56:07 2013 -0600 Added support for m_getfld() callers interleaving fseek() calls with their m_getfld() calls. Author: David Levine Date: Sun Jan 13 11:08:28 2013 -0600 Added bytes_read to m_getfld() buffer state. This is the next step in supporting ftell()/fseek(). Author: David Levine Date: Sun Jan 13 09:43:15 2013 -0600 Removed unused local char_read from forwsbr.c. Author: David Levine Date: Sun Jan 13 09:17:47 2013 -0600 Added check of m_getfld() handling of fields with trailing whitespace to test-inc-scanout.' Author: David Levine Date: Sat Jan 12 11:14:45 2013 -0600 Removed "sleazy hack" of negative bufsz because commit 05d8af21d26673279a1ca079ad9c6f301426fe0e removed the only use of it. Author: David Levine Date: Sat Jan 12 10:58:31 2013 -0600 Cleaned up FLDPLUS handling in m_getfld(). As part of this, removed the backing up of the read pointer in the "something went wrong" portion of the FLD handling. It had been moved back two positions. The first is no longer necessary because a Getc() was replace by a Peek(), and the second caused the extra blank line noted in the old comments. Updated the expected output in test/bad-input/test-header to correspond. Author: David Levine Date: Sat Jan 12 09:23:19 2013 -0600 Fixed addition to test-inc-scanout in 683e0fb1a14da5b9ce7bc5db6e76951d14d79348 to not depend on current date. Author: David Levine Date: Sat Jan 12 09:21:59 2013 -0600 Very minor cleanup to m_getfld() to remove an increment of j. Author: Ken Hornstein Date: Fri Jan 11 11:13:44 2013 -0500 We never use the autoconf checks for errno.h, crypt.h, or netdb.h, so remove them. Author: Ken Hornstein Date: Fri Jan 11 11:07:51 2013 -0500 At this point we're assuming at least C89 support, so there's no reason we should check for support for const and standard header files. Author: David Levine Date: Thu Jan 10 22:52:59 2013 -0600 Started revising m_getfld() code to replace direct buffer access with Getc(). The goal is to again support fseek() after return from m_getfld(). Author: Ken Hornstein Date: Thu Jan 10 14:18:15 2013 -0500 Convert the MIME content cache switches over to the smatch() New World Order. Author: David Levine Date: Thu Jan 10 08:00:20 2013 -0600 Added explicit third initializer to some swit struct values to silence gcc -Wmissing-field-initialziers warning. Author: Ken Hornstein Date: Wed Jan 9 22:04:23 2013 -0500 Convert all argument processing over to using X-Macros for cleanup. Based on a suggestion by Ralph Corderoy. Author: David Levine Date: Wed Jan 9 20:58:03 2013 -0600 Added comments to and started cleaning up m_getfld.c. Author: David Levine Date: Wed Jan 9 20:50:58 2013 -0600 When read_more() loads more bytes, save some from the end of the current chunk and move them to the front of the buffer. This allows backing up of the current position, which is necessary when looking for the message delimiter in a maildrop file. Author: Ken Hornstein Date: Mon Jan 7 17:41:27 2013 -0500 Fix bug where a "cur" sequence that was outside the folder allocation limits could trigger a core dump on some systems. Author: David Levine Date: Sun Jan 6 15:04:24 2013 -0600 Removed support for #ifdef LBL. It was broken anyways, sometime between MH 6.8.5 and the Apr 1999 entry into CVS. Also removed the addtoseq format function that could only be accessed with it. Author: David Levine Date: Sun Jan 6 09:38:21 2013 -0600 Fixed test-utf8-body to actually contain the UTF-8 character instead of the single byte, 8-bit character. This was caught using Heirloom shell with a UTF-8 locale: when it wrote the test draft from a here document, it converted the single byte character to UTF-8. This verifies that behavior: LANG=en_US.utf-8 /usr/lib/heirloom/5bin/sh -c "od -x < Date: Sat Jan 5 09:55:35 2013 -0600 Expanded warning message for invalid Content-Transfer-Encoding. Author: David Levine Date: Fri Jan 4 18:50:06 2013 -0600 Added reference to RFC-1864 to mhbuild man page. Author: Ken Hornstein Date: Fri Jan 4 15:12:15 2013 -0500 Remove support for -ebcdicsafe/-noebcdicsafe switches in various utilities. Author: Ken Hornstein Date: Fri Jan 4 15:03:32 2013 -0500 Create a dependency for mh-chart.man on all of the man page sources so it gets rebuilt correctly if the man pages change. Author: David Levine Date: Thu Jan 3 22:33:42 2013 -0600 Block SIGPIPE before killing the child in sm_end(). This replaces the discard() calls that were removed in commit 4548a3ecc4248a1d4. Author: David Levine Date: Thu Jan 3 22:32:28 2013 -0600 Removed discard() call in post(8). It was only used with -debug and seemed to serve no useful purpose any more. Its comment said that it was needed to help the loader. Author: David Levine Date: Thu Jan 3 21:59:44 2013 -0600 In cpstripped() and cptrimmed(), if a multibyte character is found, only count it as taking up one character in the destination buffer (if it has enought room). This way, scan(1)'s output won't be jagged if there are any subjects, for example, that have multibyte characters. Added a test for this to test-scan-multibyte, and moved the test for an invalid multibyte sequence from test-scan to it. Author: David Levine Date: Thu Jan 3 21:51:56 2013 -0600 Removed empty file name .null from the historical mh-6.8.5 tree. Author: David Levine Date: Wed Jan 2 20:07:43 2013 -0600 Fixed decoding of header fields when they contain a character that can't be converted. Added test case to test-scan. valgrind also noticed that things went amiss. Author: David Levine Date: Wed Jan 2 18:13:59 2013 -0600 Remove test .netrc file at the end of test-pop. Author: Ken Hornstein Date: Wed Jan 2 15:23:29 2013 -0500 Switch to using native automake rules for cscope. Author: Ken Hornstein Date: Tue Jan 1 22:06:33 2013 -0500 Change TLS support to only link the TLS libraries with the programs that need them. Author: Ken Hornstein Date: Tue Jan 1 02:40:30 2013 -0500 Clean up (and hopefully improve) the autoconf iconv tests. Author: Ken Hornstein Date: Tue Jan 1 01:50:06 2013 -0500 Still MORE autoconf cleanup. Author: Ken Hornstein Date: Tue Jan 1 01:27:08 2013 -0500 Autoconf/automake cleanup Author: Ken Hornstein Date: Tue Jan 1 01:01:32 2013 -0500 Document removal of --enable-nmh-debug Author: Ken Hornstein Date: Tue Jan 1 01:00:03 2013 -0500 Finally deprecate --enable-nmh-debug Author: Ken Hornstein Date: Sun Dec 30 20:17:01 2012 -0500 Note changes to autoconf requirements here. Author: Ken Hornstein Date: Sun Dec 30 19:40:42 2012 -0500 We are now requiring autoconf 2.68 and automake 1.13. Author: Lyndon Nerenberg Date: Sun Dec 30 12:19:47 2012 -0800 Note that the minimum required version of automake is 1.12. Author: Lyndon Nerenberg Date: Sun Dec 30 09:38:46 2012 -0800 Ignore top-level ar-lib file. This is detritus from the AM_PROG_AR macro I added to configure.ac. Author: Lyndon Nerenberg Date: Sun Dec 30 01:27:49 2012 -0800 Add an AM_PROG_AR program check to configure.ac This quells a warning when configuring on FreeBSD 10. Author: David Levine Date: Thu Dec 27 13:53:33 2012 -0600 Corrected fseek() emulation to fix test/bad-input/test-header. Author: David Levine Date: Thu Dec 27 09:51:09 2012 -0600 Replace use of ftell() in mhparse.c:get_content() by keeping track of bytes read by m_getfld(). Author: David Levine Date: Wed Dec 26 14:03:20 2012 -0600 Tweaked last commit to test/common.sh.in to eliminate a mv. Author: David Levine Date: Wed Dec 26 11:09:28 2012 -0600 Added note about PATH when running "make check" on Cygwin. Author: David Levine Date: Wed Dec 26 11:04:23 2012 -0600 Fixed test-slocal to work with mmdfldir set to /dev/null, and on Cygwin, which needs the full path to tee(1). Author: David Levine Date: Wed Dec 26 09:52:12 2012 -0600 Restored an explicit refill of the buffer in m_getfld() that I removed in the big stdio cleanup. Its need is shown by reducing the message buffer size to 2048. Author: David Levine Date: Tue Dec 25 19:25:43 2012 -0600 Removed call to fpurge() and its platform-specific emulations from discard.c. discard() is called on stdout from mhl(1) and msh(1) in interrupt handlers, and post(8) but only with -debug. tcflush() should do the purge when stdout is a terminal. If it's a file or pipe, well, maybe some garbage could get flushed out. And it's called on the streams that post uses to talk to its smtp server, so removed those calls because they no longer do anything. And removed LINUX_STDIO define from configure.ac. Author: David Levine Date: Tue Dec 25 11:57:31 2012 -0600 Replaced all the stdio buffer access in m_getfld.c with a single call to fread() and then some almost straightforward buffer manipulations. Author: David Levine Date: Tue Dec 25 11:57:02 2012 -0600 Fixed formatting of last change to scansbr.c. Author: David Levine Date: Sun Dec 23 09:27:03 2012 -0600 Updated m_getfld() interface description. Author: David Levine Date: Sat Dec 22 11:51:21 2012 -0600 Changed bufsz argument of m_getfld() to be in-out instead of in. This allowed removal of the msg_count global, in turn allowing removal of sbr/m_msgdef.c Author: David Levine Date: Sat Dec 22 10:14:36 2012 -0600 Changed msg_style and msg_delim to be file static to m_getfld.c instead of global. Author: David Levine Date: Sat Dec 22 10:05:51 2012 -0600 Changed type of name argument to m_getfld() from unsigned char * to unsigned char[NAMESZ]. Author: David Levine Date: Sat Dec 22 09:51:25 2012 -0600 Added m_getfld () interface description. Author: David Levine Date: Tue Dec 11 23:24:19 2012 -0600 Removed a few #ifndef JLR/#endif pairs because they're not needed. Author: David Levine Date: Tue Dec 11 19:45:29 2012 -0600 Removed some dead code, all inside #if 0's. I tried to not remove anything useful, so there are a few #if 0's remaining. Author: Lyndon Nerenberg Date: Mon Dec 10 20:54:15 2012 -0800 Import a copy of Markus Schnalke's master's thesis: The Modern Mail Handler. (Added with Markus' permission.) Author: Ken Hornstein Date: Mon Dec 10 23:23:44 2012 -0500 Remove the peeking into the stdio internals inside of scan(). Hm, this was more complicated than I originally thought. Author: Ken Hornstein Date: Mon Dec 10 16:01:59 2012 -0500 The beginnings of a program to test format functions/files. Author: David Levine Date: Sun Dec 9 21:26:49 2012 -0600 Added release notes for releases 1.4 and 1.3 to tail of NEWS. Author: Paul Fox Date: Fri Dec 7 10:27:52 2012 -0500 mhshow: properly treat unknown multipart subtypes as "mixed" Author: David Levine Date: Thu Dec 6 09:46:18 2012 -0600 Added test of -nosequence to test-pick. Author: Paul Fox Date: Wed Dec 5 21:47:12 2012 -0500 pick: add -nosequence command line switch Author: David Levine Date: Mon Dec 3 18:45:55 2012 -0600 Note in dist, mh-profile, and repl man pages that the @ link is only created with -atfile. Author: David Levine Date: Mon Dec 3 08:54:21 2012 -0600 Fix to 25581a94c5113eb78b2baf7110408df96efc4418: always set $editalt, even without -atfile. Author: Jerrad Pierce Date: Sun Dec 2 21:02:11 2012 -0600 Added docs/contrib/vpick. Author: David Levine Date: Sun Dec 2 09:19:21 2012 -0600 Cleaned up sendfiles(1) man page just a bit. Author: Ralph Corderoy Date: Sun Dec 2 09:05:37 2012 -0600 Corrected the last addition to man/nmh.man. Might be nicer to explain the warty truth from the off. Author: David Levine Date: Sat Dec 1 10:53:36 2012 -0600 Updated the TODO file. Author: David Levine Date: Sat Dec 1 10:52:27 2012 -0600 Copied atexit() code from fakesmtp.c to fakepop.c so that its pid file gets cleaned up. Also copied the sig handler. Author: David Levine Date: Fri Nov 30 18:42:40 2012 -0600 Fixed formatting glitch in msh.man. Author: Jerrad Pierce Date: Fri Nov 30 18:40:52 2012 -0600 Added description of @folder format to nmh.man. Merge: d6c134e b6f8e44 Author: Ken Hornstein Date: Thu Nov 29 15:28:12 2012 -0500 Merge branch 'master' of git.sv.nongnu.org:/srv/git/nmh Author: Paul Fox Date: Thu Nov 29 14:54:49 2012 -0500 show: remove unused variable this should have been part of the previous removal of unreachable code. Author: Paul Fox Date: Thu Nov 29 13:59:55 2012 -0500 show: remove unreachable code the stanza in question has been impossible to reach for some time. i believe its purpose was to give a non-mh display proc full pathname arguments to work with. since we've chdir'd to the folder, giving it message numbers (i.e., relative pathnames) is fine. Author: Paul Fox Date: Tue Nov 27 00:20:55 2012 -0500 show: remove MAXARGS limit when running any of the helper procs use app_msgarg() to maintain both the msgs[] and vec[] string vectors. Author: Paul Fox Date: Mon Nov 26 23:43:00 2012 -0500 forw: remove MAXARGS limit when running mhlproc use app_msgarg() to maintain both the msgs[] and vec[] string vectors. Author: Paul Fox Date: Tue Nov 27 09:53:56 2012 -0500 burst: eliminate use of MAXARGS use the already available app_msgarg() utility to make this easy. (the MAXARGS limit was highly unlikely to be exceeded, in practice.) Author: Ken Hornstein Date: Wed Nov 28 11:21:50 2012 -0500 Update about changes to rmmproc support. Author: Paul Fox Date: Tue Nov 27 12:05:56 2012 -0500 app_msgarg: de-obfuscate add some whitespace and break things up. and add comment to reflect that this might be (and is) used for more than just msg parameters. Author: Paul Fox Date: Mon Nov 26 21:00:28 2012 -0500 Artificial argv limits. when i skimmed the code earlier, i was looking at all the uses of MAXARGS -- many of which are used to size local arrays. converting them all to be dynamically-sized might be a fair amount of work. but looking at rmm.c, refile.c, and folder_delmsgs(), i don't think that issue applies. the patch below fixes the problem, and makes rmmproc and refile do the right thing (well, at least, the modern thing). NB: i didn't test to the limit where execvp should return E2BIG. as for the rest of mh -- it's certainly possible to hit the MAXARGS limit with other commands (show, for instance), but i suspect the frequency is much lower, and those, too, can be fixed as needed. paul >From 9636bc0e1697829966f51d2c301cd5d730c38c0a Mon Sep 17 00:00:00 2001 From: Paul Fox Date: Mon, 26 Nov 2012 20:49:55 -0500 Subject: [PATCH] rmm/refile: remove the MAXARGS limit when running rmmproc Author: Ken Hornstein Date: Mon Nov 26 11:25:31 2012 -0500 Since pick now uses decode_rfc2047, we need to be sure to link in the iconv library (if we need it). Author: David Levine Date: Sun Nov 25 09:17:15 2012 -0600 In pick(1), attempt to decode each header field as if it were MIME encoded. Author: David Levine Date: Sun Nov 25 09:06:20 2012 -0600 In pick(1), attempt to decode each header field as if it were MIME encoded. Author: Ken Hornstein Date: Sun Nov 25 00:49:04 2012 -0500 A new test for the POP support in inc. Very simple for now, but it seems to at least check the basic functionality. Author: Ken Hornstein Date: Sat Nov 24 23:50:31 2012 -0500 Add support for a -nosasl switch. Author: David Levine Date: Sat Nov 24 09:08:31 2012 -0600 Fixed pick(1) to properly unfold multiple-line header fields by removing newlines instead of replacing them with spaces [Bug #15215]. Author: Bill Wohler Date: Sat Nov 24 01:41:06 2012 -0500 The big news for this update is nmh 1.5. Author: Ken Hornstein Date: Fri Nov 23 20:54:28 2012 -0500 Fix the race condition with fakesmtp so it works without needing retries. Author: Ken Hornstein Date: Fri Nov 23 19:59:37 2012 -0500 Document changes to inc. Author: Ken Hornstein Date: Fri Nov 23 19:58:34 2012 -0500 Document the -port switch to inc. Also, fix the -port switch to inc so it actually works. Author: David Levine Date: Fri Nov 23 09:27:44 2012 -0600 Added test-slocal. Author: David Levine Date: Fri Nov 23 09:26:21 2012 -0600 slocal used to support two different formats for three of its arguments: [address info sender] [-addr address] [-info data] [-sender sender] But it hasn't properly supported the first form since at least April 1999. So, I removed that first form from the man page and the broken support from the code. Score another for the test suite! Author: David Levine Date: Fri Nov 23 09:25:15 2012 -0600 Added Message-Id to messages in test suite. Author: David Levine Date: Mon Nov 19 19:19:59 2012 -0600 Fixed a couple of signed-unsigned comparisons. Author: Oliver Kiddle Date: Tue Nov 20 00:47:24 2012 +0100 Yozo TODA: fix for mhshow-charset- directives in .mh_profile being broken Merge: ea28cc1 c616181 Author: Ken Hornstein Date: Mon Nov 19 15:31:21 2012 -0500 Merge branch 'format-memory-rework' Author: Ken Hornstein Date: Mon Nov 19 15:29:01 2012 -0500 Make sure we strip off a newline from components we want to display (we were stripping off a newline from the wrong copy of the component). Author: Ken Hornstein Date: Mon Nov 19 14:37:14 2012 -0500 Convert repl to the new world format API. Author: Ken Hornstein Date: Mon Nov 19 14:19:30 2012 -0500 Support for the new world format API for comp and forw. Author: Ken Hornstein Date: Mon Nov 19 14:18:55 2012 -0500 Whoops, with the new world order we need to make sure we allocate memory for all strings in format instructions. Author: Ken Hornstein Date: Mon Nov 19 13:48:16 2012 -0500 Convert scan() to the new world format API. Author: Ken Hornstein Date: Mon Nov 19 13:47:46 2012 -0500 Change fmt_findcasecmp() to fmt_findcasecomp(). The new name is more consistent. Author: Ken Hornstein Date: Mon Nov 19 12:23:16 2012 -0500 Change API a bit. Rename fmt_addcomp() to fmt_addcomptext(). Create new function fmt_addcompentry(). Author: Ken Hornstein Date: Mon Nov 19 12:22:26 2012 -0500 Remove unused variable. Author: David Levine Date: Sat Nov 17 12:05:22 2012 -0600 Removed leading space from lines in mhbuild and rmm man pages to correct formatting. Author: Ken Hornstein Date: Fri Nov 16 23:56:26 2012 -0500 Finished work on rcvdist to convert to new world format API. Author: Ken Hornstein Date: Fri Nov 16 23:41:10 2012 -0500 More (and hopefully for now) the final cleanup for mhl. Author: Ken Hornstein Date: Fri Nov 16 23:22:23 2012 -0500 Basic support for the new world API; seems to work! Author: Ken Hornstein Date: Fri Nov 16 23:21:54 2012 -0500 Add missing functions for manipulating component text. Author: Ken Hornstein Date: Fri Nov 16 23:20:28 2012 -0500 Fix up documentation a bit. Author: Ken Hornstein Date: Thu Nov 15 21:47:59 2012 -0500 Partial work for mhl; still more stuff to do. Author: Ken Hornstein Date: Thu Nov 15 21:47:36 2012 -0500 Fix missing argument to fmt_free(). Author: Ken Hornstein Date: Thu Nov 15 15:53:24 2012 -0500 Beginnings of conversion of code to new format interface. Author: Ken Hornstein Date: Thu Nov 15 15:50:46 2012 -0500 Update documentation to match code change. Author: Ken Hornstein Date: Thu Nov 15 14:21:20 2012 -0500 Fix a few bugs: Make sure to add a ref when adding to the hash table. Forgot the increment the format array inside of fmt_free(). Marked an allocated string when doing FT_LIT. Author: Ken Hornstein Date: Thu Nov 15 13:30:30 2012 -0500 Add some comments to explain how format loop support was supposed to work. Author: Ken Hornstein Date: Thu Nov 15 11:05:55 2012 -0500 Add refcounting to struct comp. Move CHASH and FINDCOMP into fmt_compile.c to make private. Author: Ken Hornstein Date: Thu Nov 15 09:19:36 2012 -0500 Beginnings of the changes to fmt_compile for memory rework. Author: Ken Hornstein Date: Thu Nov 15 09:18:11 2012 -0500 Update with new functions and comments describing them. Author: David Levine Date: Wed Nov 14 08:47:14 2012 -0600 Removed support for zip from sendfiles. I added it as part of the sendfiles rewrite, f8baa5a34335fc0fc8ccabfabc601d0af73ab769, a few weeks ago. But because sendfiles fed zip from standard input, zip would use Zip64 extensions. That would require unzip 6.0 or later to extract, according to the zip man page. But current MacOS X uses unzip 5.52, so it broke there. Author: David Levine Date: Tue Nov 13 22:35:57 2012 -0600 1) Don't bother checking stderr output from sendfiles because tar's output format isn't standardized. 2) Added -c to uncompress. Author: David Levine Date: Tue Nov 13 22:32:22 2012 -0600 Updated scan.highlighted to feed an expression to %(zputlit). Author: Ken Hornstein Date: Tue Nov 13 22:23:02 2012 -0500 Make sure we stick to POSIX-sed only. I _think_ this portable enough to work everywhere. Author: Ken Hornstein Date: Tue Nov 13 18:53:55 2012 -0500 Change %(putlit) and %(zputlit) to take TF_EXPR instead of TF_STR. This was originally my fault; TF_STR means a string literal as an argument, but the documentation (and the code) really means for it to take an expression. Author: David Levine Date: Fri Nov 9 15:02:53 2012 -0600 Updated test-scan to correspond to commit 112b90c43391644f24559f5aa58752214de0e8a5. Author: Paul Fox Date: Fri Nov 9 14:53:21 2012 -0600 Added ml script to docs/contrib. Author: David Levine Date: Fri Nov 9 14:39:59 2012 -0600 Refer to just "root" in slocal man page. Author: Paul Fox Date: Fri Nov 9 14:37:59 2012 -0600 Added ml script to docs/contrib. Author: David Levine Date: Wed Nov 7 16:48:05 2012 -0600 In scan.highlighted, set black background on the colorized lines to enhance visibility if the user has a light background. Author: David Levine Date: Tue Nov 6 18:43:42 2012 -0600 Removed note from BUGS section of several man pages saying that command line arguments must be quoted for protection from the shell. That's not a bug, and has nothing to do with nmh. Changed "back-quoted" to "backquoted" for consistency in a few man pages. Author: David Levine Date: Tue Nov 6 18:42:45 2012 -0600 Fixed typo in mhn.man. Author: David Levine Date: Mon Nov 5 13:10:16 2012 -0600 Fixed typo in mh-format man page description of zputlit. Author: David Levine Date: Mon Nov 5 11:25:33 2012 -0600 Added application/vnd.openxmlformats-officedocument.spreadsheetml.sheet for .xlsx files. Author: David Levine Date: Sun Nov 4 20:58:47 2012 -0600 Added format support for zputlit function escape. It requires that the str contents have zero display width, such as for terminal escape sequences. Author: Lyndon Nerenberg Date: Sat Nov 3 19:22:49 2012 -0700 nmh.7 isn't the place to advise people how to change their $PATH. Author: David Levine Date: Sat Nov 3 08:13:34 2012 -0500 Fixed comparison to be signed instead of unsigned. Author: David Levine Date: Sat Nov 3 07:37:40 2012 -0500 Added description of "all" range abbreviation. Author: David Levine Date: Fri Nov 2 22:45:07 2012 -0500 Added argument to fmt_scan() to specify the buffer size. Author: David Levine Date: Sun Oct 28 22:35:45 2012 -0500 Updated date on sortm(1) man page. Author: David Levine Date: Sun Oct 28 13:21:46 2012 -0500 Updated build-nmh-cygwin for release of Cygwin nmh 1.5-2. To use: 1) Change VERSION to 1.5-2. 2) make dist 3) Symlink build-nmh-cygwin to nmh-1.5-2 and run that with "all". Author: David Levine Date: Sat Oct 27 12:36:29 2012 -0500 Fixed typo reported by Ralph. I also should have mentioned in the commit message for sortm(1) -check/-nocheck that Norm proposed their addition. Author: David Levine Date: Sat Oct 27 12:18:45 2012 -0500 In test-post-common.sh and test-mhmail, wait for fakesmtp to start for up to 40 seconds. 10 seconds wasn't long enough when I leaned on my machine. Also, print out a message if exiting due to that timeout. Author: David Levine Date: Sat Oct 27 12:14:01 2012 -0500 Added -check/-nocheck switches to sortm(1). Also removed obsolete note in the BUGS portion of its man page about how it sorts messages that are missing or have an invalid Date: field. It actually sorts them using their file modification times. Author: David Levine Date: Tue Oct 23 19:18:20 2012 -0500 Fixed typo in Cygwin section of MACHINES. Author: David Levine Date: Tue Oct 23 19:16:56 2012 -0500 Cyrus SASL 2.1.25 introduced the sasl_callback_ft prototype, which has an explicit void parameter list, according to best practice. So we need to cast to avoid compile warnings. And provide a sasl_callback_ft prototype for earlier versions. Author: Lyndon Nerenberg Date: Sun Oct 21 12:39:43 2012 -0700 Clarify that manpage references use the .IR macro everywhere. Author: Lyndon Nerenberg Date: Sun Oct 21 12:38:40 2012 -0700 Fix one last missed %nmhdate% substitution. Remove empty CONTEXT section. Author: Lyndon Nerenberg Date: Sun Oct 21 12:37:49 2012 -0700 Remove %nmhdate% substitution from man.sed. It's no longer used. Merge: 9dedfb1 cbaaccc Author: Lyndon Nerenberg Date: Sun Oct 21 12:33:21 2012 -0700 Merge branch 'master' of ssh://git.sv.gnu.org/srv/git/nmh Author: David Levine Date: Sun Oct 21 12:02:40 2012 -0500 Corrected date in sendfiles.man Author: David Levine Date: Sun Oct 21 09:52:46 2012 -0500 Updated sendfiles(1): 1) Added -from switch. 2) sendfiles will now construct a From address, using the sender's localmbox, if the user does not specify it with -from or the PERSON environment variable. 3) Added support for bzip2, lzma, and zip compression methods. Added a new switch to select the method: -compress . Because support for the old -compress with was broken (it did not use -c with compress/uncompress) and it was undocumented, it has been replaced. Retained old -gzip and -none switches for backward compatibility even though they were undocumented. 4) Allow the recipient argument to be preceded by the optional -to switch iff the subject argument is preceded by the optional -subject switch. Allow the delay value to be specified using the optional -delay switch. 5) Added -version and -help switches. 6) All switches can now be abbreviated. /etc/sendfiles no longer needs to be configured. It's easier to support make distcheck by having it figure out its path at runtime. In viamail, set postproc to post in the same directory as itself, if invoked with a full path. This allows it to support make distcheck. viamail does not read the profile so its postproc is otherwise hard-coded at compile time. Added test-sendfiles. Author: Lyndon Nerenberg Date: Sat Oct 20 16:51:01 2012 -0700 Update the manpage style guide. Merge: d1cb667 a69289c Author: Lyndon Nerenberg Date: Sat Oct 20 15:02:16 2012 -0700 Merge branch 'master' of ssh://git.sv.gnu.org/srv/git/nmh Author: Lyndon Nerenberg Date: Sat Oct 20 14:42:32 2012 -0700 Rationalize .TH manpage macro invocations. This patch addresses the following issues with .TH macro usage: .TH COMP %manext1% "%nmhdate%" MH.6.8 [%nmhverion%] 1) "MH.6.8" is no longer relevant. 2) %nmhdate% is a hardwired value that only gets updated along with %nmhversion% and is therefore redundant. This patch nukes the MH.6.8 tag, and replaces the hardwired %nmhdate% field with the latest date the associated manpage has been updated. I pulled the dates - as best I could - from the git logs. Going forward, it is incumbent on developers to update the manpage date stamps as they update the pages themselves. Author: David Levine Date: Sat Oct 20 16:40:06 2012 -0500 Cleaned up a couple of shell variables. Author: David Levine Date: Sat Oct 20 16:39:25 2012 -0500 Fixed the trap to work with posh. Author: David Levine Date: Sat Oct 20 10:41:43 2012 -0500 Fixed printf's in test suite. Author: David Levine Date: Sat Oct 20 07:44:34 2012 -0500 Fixed the trap in mhmail. Author: David Levine Date: Fri Oct 19 14:23:17 2012 -0500 Cleaned up uip/mhmail. Added chmod +x of spost in configure.ac. Author: Lyndon Nerenberg Date: Tue Oct 16 20:18:03 2012 -0700 Manpage cross-reference cleanups: convert '.BR cmd (section)' to '.IR cmd (section)' throughout the text. Author: Lyndon Nerenberg Date: Tue Oct 16 19:48:02 2012 -0700 A couple more manpage typo cleanups. Author: Lyndon Nerenberg Date: Tue Oct 16 19:45:38 2012 -0700 Typo. Author: Lyndon Nerenberg Date: Tue Oct 16 19:39:37 2012 -0700 Manpage SEE ALSO cleanup. Convert to '.IR cmd (section)' format for manpage references. Fixed a couple of inline '.BR cmd (section)' instances as well. Removed HISTORY from new(1); this stuff doesn't belong in manpages. Author: Lyndon Nerenberg Date: Tue Oct 16 18:20:18 2012 -0700 Elide spurious empty lines in manpage source files. Author: Lyndon Nerenberg Date: Tue Oct 16 17:29:30 2012 -0700 Ensure the .TH macro is the first line of the manpage source files. Some versions of man(1) get upset if .TH doesn't come first. Author: Lyndon Nerenberg Date: Tue Oct 16 17:08:17 2012 -0700 Update the manpage authors guide, primarily for .TP, but also fixes a couple of other incorrect style recommendations. These updates are incomplete ... more to follow. Merge: 956ddac e2d655d Author: Lyndon Nerenberg Date: Tue Oct 16 16:40:17 2012 -0700 Merge branch 'master' of ssh://git.sv.gnu.org/srv/git/nmh Author: Lyndon Nerenberg Date: Tue Oct 16 16:32:48 2012 -0700 Incorporate Paul Fox's changes that group the commands by functional groups. Move the "generated code" warning comment below the .TH macro to work around some buggy man(1) implementations. Removed all the .RS/.RE indenting and replaced the use of .fc and tab indenting with .TP macros. Move the BUGS section below SEE ALSO to follow the usual section ordering convention. Fixed up some italic vs. bold usage. Use '.IR foo (section)' in the SEE ALSO section. Removed some irrelevant text, along with a small amount of word-smithing. Author: David Levine Date: Tue Oct 16 14:53:04 2012 -0500 Unset PAGER in test/common.sh so that make distcheck passes. Merge: a7b486a 342e355 Author: Lyndon Nerenberg Date: Tue Oct 16 12:39:59 2012 -0700 Merge branch 'master' of ssh://git.sv.gnu.org/srv/git/nmh Author: Lyndon Nerenberg Date: Tue Oct 16 12:36:30 2012 -0700 Add new make targets 'man' and 'cleanman' to build and clean just the man/ sub-directory. I also removed the '@' supressors for the internal manpage targets. There's no net benefit to hiding this stuff. Author: David Levine Date: Tue Oct 16 13:27:32 2012 -0500 Cleaned up some printf's. Author: David Levine Date: Tue Oct 16 13:23:43 2012 -0500 Updated sendfiles(1) man page to reflect upcoming code update. Author: Lyndon Nerenberg Date: Tue Oct 16 11:12:27 2012 -0700 Some version of man(1) barf if the first line of the manpage is not the .TH macro. Re-order the generated mh-chart.man so that the 'auto-generated' comment appears after the .TH macro. Author: Lyndon Nerenberg Date: Mon Oct 15 17:08:29 2012 -0700 Slightly reformat the FINDCOMP macro to quell a clang warning about an empty for()-loop body. Author: Lyndon Nerenberg Date: Mon Oct 15 17:06:40 2012 -0700 automake 1.12 generates some (apparently) harmless warnings, but the build fails becuase we invoke automake with -Werror. Remove -Werror from the automake options until the autotools gurus can patch things up. Merge: 5548c9a 47dca82 Author: Lyndon Nerenberg Date: Mon Oct 15 15:22:39 2012 -0700 Merge branch 'master' of ssh://git.sv.gnu.org/srv/git/nmh Author: Lyndon Nerenberg Date: Mon Oct 15 15:21:48 2012 -0700 Allow $PAGER to override the compiled-in default pager command. Author: David Levine Date: Sun Oct 14 21:13:05 2012 -0500 Removed unused function seek_home(). Author: David Levine Date: Sun Oct 14 19:27:17 2012 -0500 The first alias contained in a blind list is now expanded. The mh-alias(5) man page was updated to show that blind lists must not be terminated with, or contain, a trailing semicolon [Bug #15604]. Author: David Levine Date: Sun Oct 14 19:02:43 2012 -0500 Changed error message to say that blind lists aren't compatible with sendmail/pipe. Author: Ralph Corderoy Date: Sun Oct 14 18:59:06 2012 -0500 Fixed "mark -sequence cur -delete all" to work for cur as well as any other sequence, to allow clearing of the current message indication. Author: David Levine Date: Sat Oct 13 18:00:39 2012 -0500 Don't allow blind aliases with sendmail/pipe mts. Before this change, they would be fed to sendmail, which would reject them anyway. This change catches that in post and presents a more helpful error message to the user (at the "What now?" prompt, if used). A possible future enhancement might be, with sendmail/pipe, to expand out blind aliases and put the addresses in Bcc: header fields, but then the recipients would get messages with the Blind-Carbon-Copy indication. (Note that Dcc isn't supported with sendmail/pipe, either.) Just for information: old spost fed the addresses of blind aliases to sendmail, making them visible to all recipients. Oops. Author: David Levine Date: Sat Oct 13 09:56:08 2012 -0500 Removed potential buffer overflow in ali.c by replacing array of hard-coded maximum size with dynamically-sized array. Author: David Levine Date: Thu Oct 11 23:00:43 2012 -0500 Fixed sortm(1) verbose message and man page to reflect that with -limit 0, the sort is only on the text field. Author: David Levine Date: Thu Oct 11 21:48:42 2012 -0500 Added -noall/-all switches to sortm(1). Author: David Levine Date: Sun Oct 7 22:55:33 2012 -0500 Fixed typo in mh-alias man page. Author: David Levine Date: Sun Oct 7 11:25:01 2012 -0500 Added newline to "send" that's piped to dist. Old 2.6 Linux needs it. Author: David Levine Date: Sun Oct 7 10:31:12 2012 -0500 Added test-anno, test-dist, test-msgchk, and test-rcvtty. Author: David Levine Date: Sun Oct 7 10:27:31 2012 -0500 Changed nmh-fcc to fcc. See etc/forwcomps. Another catch by the test suite! Author: David Levine Date: Sun Oct 7 10:18:54 2012 -0500 Updates to test/common.sh.in: 1) Added function check_for_hard_links. Moved this code out of test-refile so that other tests can use it. 2) Added mmdfldir and mmdflfil settings to the mts.conf for tests, to support test-msgchk. Author: David Levine Date: Sun Sep 23 09:02:18 2012 -0500 Removed double quotes around case arguments in test scripts. Author: David Levine Date: Sun Sep 23 09:00:11 2012 -0500 When determining the path of the script inside mhmail, handle case where $0 is just the script name, without any directory. Bourne shell does that if the script is found using PATH. Author: David Levine Date: Tue Sep 18 22:18:21 2012 -0500 Disabled echo of rm -f lines in Makefile to quiet builds and installs a bit. Author: David Levine Date: Tue Sep 18 22:00:00 2012 -0500 Replaced spost with script that exec's post -mts sendmail/pipe. Author: David Levine Date: Mon Sep 17 19:42:27 2012 -0500 Removed mhmail.c because it was no longer needed and could get in the way of make if its timestamp was newer than that of the mhmail script. Thanks to Johan Viklund for reporting this. Author: David Levine Date: Sun Sep 16 23:12:19 2012 -0500 For the mhstore -clobber test, cd to the Mail subdirectory so that the stored files will get cleaned up by the exit trap in common.sh. Merge: b471d7a 2b7b705 Author: Lyndon Nerenberg Date: Sun Sep 16 14:39:27 2012 -0700 Merge branch 'master' of ssh://git.sv.gnu.org/srv/git/nmh Author: Lyndon Nerenberg Date: Sun Sep 16 14:38:54 2012 -0700 Fix a comment typo. Author: David Levine Date: Sun Sep 16 13:54:23 2012 -0500 With mhstore -clobber auto/suffix, when looking for a new filename, actually open(2) the file with O_CREAT | O_EXCL to avoid the race condition when figuring out the filename first and opening it later. Author: David Levine Date: Sun Sep 16 12:45:12 2012 -0500 Added "-d --" to invocation of ls when figuring out what files to attach in whatnow. Author: David Levine Date: Sat Sep 15 21:18:38 2012 -0500 Fixed description of n with mhstore -clobber auto/suffix. Author: David Levine Date: Sat Sep 15 14:07:07 2012 -0500 Clarified description of clobber -auto/-suffix per Ralph's suggestion. Author: David Levine Date: Sat Sep 15 13:40:50 2012 -0500 Added -clobber switch to mhstore(1) [Bug #11160]. Author: David Levine Date: Sat Sep 15 13:14:18 2012 -0500 Changed ; to && in shell command, per Ralph's suggestion. There were two remaining places that still used ";". Though they weren't of consequence, it's the right thing to do. Author: David Levine Date: Sat Sep 15 08:24:37 2012 -0500 Allow whatnow to accept "l" as an abbreviation for "list", instead of requiring at lest "li". Author: David Levine Date: Fri Sep 14 20:46:02 2012 -0500 Filter out all Nmh-* headers in post(1). Do that silently for empty ones (no header body), and warn about non-empty ones. Author: David Levine Date: Fri Sep 14 17:05:24 2012 -0500 Added check in send(1) of attach (default Nmh-Attachment) headers to ensure that only plain files are attached. Otherwise, it is a fatal error. Note that whatnow's attach will continue to allow attachment of directories because it expands those out to their contents. It doesn't check what the contents are, though. That's why we needed to add this check. Also added a check to skip attach headers that are empty so that they can be put in drafts, per Norm's request. Author: David Levine Date: Tue Sep 11 08:44:43 2012 -0500 Updated docs/README-ATTACHMENTS, mainly to reflect that no setup is required with nmh 1.5 and beyond. And the user documentation is in the send(1) and whatnow(1) man pages. Author: David Levine Date: Tue Sep 11 08:42:58 2012 -0500 Added references to the whatnow(1) man page description of its attach support to the nmh(7) and send(1) man pages. Author: Eric Schnoebelen Date: Fri Aug 31 09:49:37 2012 -0400 Move chdir() call so -recurse option works again. Author: Ken Hornstein Date: Fri Aug 31 09:46:03 2012 -0400 New test for folder -recurse Author: Ken Hornstein Date: Thu Aug 23 10:08:59 2012 -0400 Change the Bcc: code in post so it includes the From: header from the original message. Author: David Levine Date: Fri Aug 17 19:31:22 2012 -0500 Cleaned up message_id(). Author: David Levine Date: Fri Aug 17 19:29:49 2012 -0500 Removed chmod of bccfil from make_bcc_file(). It was done before bccfil was defined so it had no useful effect. m_mktemp2() sets the umask so it wasn't necessary, anyway. Author: David Levine Date: Fri Aug 10 05:20:25 2012 -0500 Cleaned up test-utf8-body a bit. Author: David Levine Date: Fri Aug 10 03:33:38 2012 -0500 Added mhbuild: -nocontentid to profile used for tests, to simplify output checking. Author: David Levine Date: Thu Aug 9 17:13:38 2012 -0500 Added default_content_type argument to make_mime_composition_file_entry(). It's used only to force message bodies to always use text/plain content type, which allows mhbuild to do the right thing with them. Thanks to Steve Rader for reporting that UTF-8 characters in message bodies had previously caused them to be encoded as octet-streams (with attachments managed by send), and to Ken for coming up with the fix. Author: David Levine Date: Mon Jul 23 18:17:11 2012 -0500 Removed nmh-from condition from rcvdistcomps. Author: David Levine Date: Sun Jul 22 20:19:19 2012 -0500 Fixed explanation of why the unset SHELL test is uselessif /bin/sh is bash. Author: David Levine Date: Sun Jul 22 12:04:47 2012 -0500 Reworked test-rcvdist so that it sees the output of post. Author: David Levine Date: Sun Jul 22 12:03:36 2012 -0500 Added test of whatnow with SHELL unset to test-ls, though it doesn't reveal anything on Linux, at least. Author: Alexander Zangerl Date: Sun Jul 22 12:01:00 2012 -0500 whatnow cooks up strings for executing external commands, and then feeds these strings to popen or system. These command strings rely on $SHELL being present - and if that is not the case, then we get weird error messages ("sh: -c not found" or similar). (Because both system() and popen() start up fine with the std shell, but their arg string to parse doesn't include a cmdname/path before the -c.) As far as i understand the POSIX standard, SHELL is recommended but not actually mandatory, so i think it would be good to handle this a bit more robustly: by setting SHELL to /bin/sh if not present. Author: David Levine Date: Sat Jul 21 20:00:14 2012 -0500 Tidied up for loop in message_id(). Author: David Levine Date: Sat Jul 21 19:45:48 2012 -0500 With -messageid random, make the part after the @ more resemble a hostname by inserting a couple of dots, and using - and _ instead of + and /. Author: David Levine Date: Sat Jul 21 16:17:41 2012 -0500 Added -messageid switch to send(1) and post(8). This allows selection of the style to use for generated Message-ID and Content-ID header fields. The default localname style is pid.time@localname, where time is in seconds, and matches previous behavior. The random style replaces the localname with some (pseudo)random bytes and uses microsecond-resolution time. Author: David Levine Date: Sat Jul 21 12:42:14 2012 -0500 Here's a better test of Resent-From: in test-rcvdist: use the user's actual localmbox. Author: David Levine Date: Sat Jul 21 12:19:18 2012 -0500 Added check to notpost for presence of Resent-From:. Author: David Levine Date: Sat Jul 21 12:01:41 2012 -0500 If post or send fail, exit with their exit status. Author: David Levine Date: Sat Jul 21 11:58:57 2012 -0500 Removed #ifndef RAND/#endif that no longer had any effect. Author: Harvey Eneman Date: Sat Jul 21 11:57:29 2012 -0500 Fixed the default rcvdistcomps and rcvdistcomps.outbox to to insert the Resent-From: header. Author: David Levine Date: Sun Jul 15 13:35:42 2012 -0500 Removed debugging statement and added comments to the duplicate check of readconfig (). Author: David Levine Date: Wed Jul 11 21:37:39 2012 -0500 Added -mts switch to post, send, and whom. Replaced test-sendmail-pipe with test-mts. Author: David Levine Date: Mon Jul 9 22:49:59 2012 -0500 Removed -m from sendmail invocation with sendmail/pipe. Modern sendmail and postfix, at least, ignore it. Author: David Levine Date: Mon Jul 9 21:25:36 2012 -0500 Correction to previous commit, 704bdde497da69854846d51d86c440fc980c5489, to restore the behavior when using SMTP and with any blind addresses. Don't quit the SMTP session between sending the message and bcc's, but instead reset it. Author: David Levine Date: Mon Jul 9 19:47:47 2012 -0500 Removed use of the ONEX sendmail verb. It is obsolete, according to http://smtpfilter.sourceforge.net/esmtp.html. And was removed over 10 years ago from sendmail (8.12), according to http://www.irbs.net/internet/postfix/0111/2237.html. Author: David Levine Date: Mon Jul 9 19:15:13 2012 -0500 Renamed "sendmail" mts method to "sendmail/smtp", allowing "sendmail" as an alias. Renamed "pipe" to "sendmail/pipe". Author: David Levine Date: Sun Jul 8 23:17:04 2012 -0500 spost(8) has been merged into post(8). Its functionality is enabled by selecting the "pipe" mail transport method in etc/mts.conf, which in turn can be configured using --with-mts=pipe. The spost -noalias, -backup/-nobackup, -push/-nopush, and -remove/-noremove switches are not supported by post. Note that spost did not support -whom or Dcc, and neither does post when using mts: pipe. spost is now deprecated. Author: David Levine Date: Wed Jul 4 09:57:49 2012 -0500 Added test-packf. Author: David Levine Date: Wed Jul 4 07:27:15 2012 -0500 test-prompter: removed an unused input that was piped to the program because it sometimes caused printf to complain about a write error. Author: David Levine Date: Tue Jul 3 20:50:23 2012 -0500 Filtered out "From " lines when comparing mboxes because their timestamps sometimes differed by a second. Author: David Levine Date: Sun Jul 1 20:20:42 2012 -0500 Updated pending-release-notes. Author: David Levine Date: Sun Jul 1 19:24:36 2012 -0500 Rather than fix the reported bug, backslash in commented lines in alias file is interpreted, I documented that behavior in the mh-format man page and etc/MailAliases. This behavior is unfortunate, but it is a result of the implementation of nmh's vfgets() function. That function is used by other callers that expect the behavior. [Bug #23553] Author: David Levine Date: Sun Jul 1 19:20:22 2012 -0500 Added test-dp, test-fmtdump, test-prompter, test-rcvstore, test-rcvpack, and test-rcvdist. Author: David Levine Date: Sun Jul 1 16:44:43 2012 -0500 Applied patch #5571, Propagate Mail-Followup-To. Also clarified man page: replgroupcomps won't be used if you specify another forms file on the command line or in your profile. Author: David Levine Date: Sun Jul 1 10:21:22 2012 -0500 Added note that mhmail does not read context file itself. Author: David Levine Date: Sun Jul 1 10:09:06 2012 -0500 Removed unused #ifdef NRTC and reference to its contents in the rcvdist man page. Author: David Levine Date: Sun Jul 1 09:14:27 2012 -0500 Updated man page descriptions of Msg-Protect: it defaults to 0600 and is not supported on some filesystems, such as FAT32. Author: David Levine Date: Sun Jul 1 08:32:18 2012 -0500 Wrapped some shell variables with quotes so the tests have a chance of running if the current directory has a character such as a space in it. Though the tests themselves need the same help for them to work. Also, added mention of Heirloom shell to test/README. Author: David Levine Date: Thu Jun 28 21:59:47 2012 -0500 Replaced utilities that operate on pbm files with those that operate on pnm files, per the bug report referenced below (from Dec 2005!). And changed the mhshow-show-image/x-pbm mime type to mhshow-show-image/x-pnm. [Bug #15152] Author: David Levine Date: Thu Jun 28 21:19:06 2012 -0500 Removed BUGS section at end of rcvstore(1) man page. It said to not use rcvstore if you use the "Unseen-Sequence" profile entry because the context (sequences file, actually) could be corrupted if multiple nmh processes tried to update it simultaneously. The locking added by commit 82a21b6f3cddf8ab048dcb02c080ea9797c73c5a serialized that simultaneous update. [Bug #4361] Author: David Levine Date: Thu Jun 28 21:12:13 2012 -0500 Removed the one remaining unused #ifdef ISI. Author: David Levine Date: Thu Jun 28 21:11:07 2012 -0500 Simplified getm() a bit, removing a goto. Author: David Levine Date: Thu Jun 28 20:59:23 2012 -0500 Fixed ismymbox() to look at Local-Mailbox as well as Alternate-Mailboxes. The problem was that when an alternate mailbox was added to the list, the node for the local mailbox information was lost. Added check to test-mymbox. Added test-repl, because this is where it was first noticed. Also enhanced output with MHWDEBUG set to show the entire list, not just each alternate mailbox as it is added to the list. [Bug #36635]. Author: David Levine Date: Mon Jun 25 08:42:14 2012 -0500 Deprecated mhtest. Author: David Levine Date: Mon Jun 25 08:21:03 2012 -0500 Removed unused UUCPDIR and UUCPFIL #defines. Author: David Levine Date: Sun Jun 24 22:26:27 2012 -0500 Added test-sortm. Also clarified some details in the sortm man page. Author: David Levine Date: Sun Jun 24 19:03:05 2012 -0500 Added status to conflict(8) man page to note that it is deprecated. Author: David Levine Date: Sat Jun 23 09:55:01 2012 -0500 Allow optional -to in front of To: addresses with mhmail. Author: David Levine Date: Sat Jun 23 08:04:08 2012 -0500 Added checks for missing mandatory arguments to mhmail. Author: David Levine Date: Fri Jun 22 10:45:33 2012 -0500 Changed -header-field to -headerfield. And refer to its argument as name:value instead of name:body, to avoid the obvious confusion. Author: Lyndon Nerenberg Date: Thu Jun 21 11:11:40 2012 -0700 Default to flock() locking on OpenBSD and Darwin. Author: David Levine Date: Wed Jun 20 19:19:31 2012 -0500 Refined 48959daf724bb10802ca489654035f69e701efc0 by setting up a LN variable in the Makefile that can be used to override the link command at install time. For example, on Cygwin, LN will be configured to cp. If installing on an NTFS filesystem, the user could install with make LN=ln to use ln instead of cp. Author: David Levine Date: Wed Jun 20 19:16:18 2012 -0500 Truncated -help test in test-whom because its output depends on whether sasl support was configured in. It's not configured in by distcheck. Author: David Levine Date: Wed Jun 20 09:09:24 2012 -0500 For whatever reason, gcov got fooled by test-whom until a test of -help was added. Author: David Levine Date: Wed Jun 20 08:13:46 2012 -0500 Quoted a bunch of shell variables in build_nmh. Author: David Levine Date: Tue Jun 19 21:30:54 2012 -0500 Added test-ali. Author: David Levine Date: Tue Jun 19 20:36:14 2012 -0500 Added printout to build_nmh to report number of tests not run. Author: David Levine Date: Tue Jun 19 20:15:18 2012 -0500 Added a few clarifications and more DEFAULTS to mhmail(1) man page. Author: David Levine Date: Tue Jun 19 19:54:04 2012 -0500 Refinement to e30560d793ff5bc704dadc2eab9d31100ad4636b: don't warn about profile components that are null, e.g., : This could be a comment. or just a hash, e.g., Author: David Levine Date: Tue Jun 19 10:29:47 2012 -0500 Changed permissions from 0755 to 0644 on a few .c files. Author: David Levine Date: Tue Jun 19 10:25:54 2012 -0500 Forget to add test/mhmail/attachment.txt to last commit. Author: David Levine Date: Tue Jun 19 10:13:28 2012 -0500 Added -attach switch to mhmail. Author: David Levine Date: Mon Jun 18 21:49:01 2012 -0500 Moved test-mhmail to its own test directory. Author: David Levine Date: Mon Jun 18 21:30:58 2012 -0500 Added mention of checkbashims script to test/README. And fixed false positive that it reported for test-mhmail. Author: David Levine Date: Mon Jun 18 21:28:26 2012 -0500 Added -header-field switch to mhmail. Author: David Levine Date: Mon Jun 18 18:25:10 2012 -0500 Added Jerrad Pierce's suggestion to use -editor prompter. Author: David Levine Date: Sun Jun 17 22:56:23 2012 -0500 Removed possible tmp file leak. Author: David Levine Date: Sun Jun 17 22:51:51 2012 -0500 mhmail now supports -profile -resend. Author: David Levine Date: Sun Jun 17 20:59:16 2012 -0500 Here's a better fix that e194fdf11df779597e19039a67454e9b42a77ef0 for support `mhparam libdir` under "make distcheck": explicitly set libdir in the profile. Author: David Levine Date: Sun Jun 17 15:25:28 2012 -0500 Replaced mhmail -debug switch with -nosend, and added -send. Author: David Levine Date: Sun Jun 17 14:35:14 2012 -0500 Added -resent support to mhmail. It doesn't work with -profile, though. Author: David Levine Date: Sat Jun 16 10:56:53 2012 -0500 Fixed warning introduced by last change to man/mhmail.man. Author: David Levine Date: Sat Jun 16 10:08:18 2012 -0500 Removed extra [ from synopsis. Author: David Levine Date: Sat Jun 16 09:24:29 2012 -0500 Replaced compiled mhmail with script that was formerly named mhmail.in. Added test-mhmail. Author: David Levine Date: Sat Jun 16 09:16:18 2012 -0500 Reworked to be as compatible as possible with compiled mhmail. Author: David Levine Date: Fri Jun 15 21:00:28 2012 -0500 Added mention of mhmail as a message composition utility. Author: David Levine Date: Fri Jun 15 20:53:03 2012 -0500 Added nmh lib directory to PATH in setup_test (). This is necessary with "make distcheck" for scripts to access the lib directory that it installs for testing. (The distcheck target does not configure them; they retain their build configuration.) If we ever add a test for etc/sendfiles, we'll have to deal with its configured %libdir%. Author: David Levine Date: Thu Jun 14 23:28:05 2012 -0500 Fixed temporary autoconf workaround by hard-coding nmhbindir. Author: David Levine Date: Thu Jun 14 23:17:33 2012 -0500 Add trailing newline to body, if needed. Author: Ken Hornstein Date: Thu Jun 14 10:36:09 2012 -0400 Fix test for changes to mhparam. Author: Ken Hornstein Date: Thu Jun 14 10:33:21 2012 -0400 Make the base64 encoder endian-agnostic, and remove the function set_endian() since it's no longer needed. Author: David Levine Date: Thu Jun 14 09:10:23 2012 -0500 Documented mhparam -debug option. Author: David Levine Date: Thu Jun 14 08:54:35 2012 -0500 If heirloom shell is in /usr/lib/heirloom/5bin/sh, use it to run tests. Author: David Levine Date: Thu Jun 14 08:35:14 2012 -0500 If post/send fail, save the draft in dead.letter, the same as compiled mhmail. Author: David Levine Date: Thu Jun 14 08:30:30 2012 -0500 Added etcdir and libdir. And added mention that component name matching is case-insensitive. Author: Alexander Zangerl Date: Thu Jun 14 07:31:40 2012 -0500 The base64-decoder doesn't work on 64-bit big-endian architectures: mhstore and co. write files of the correct length but which consist only of \0s. The culprit is uip/mhparse.c, which contains a pretty ugly base64 decoder (in two places). that thing allocates a "long int" as a container for the 24 bits that you get from four base-64 chars. the container is then accessed both as a single entity and as a byte array, which naturally depends on how wide the long int is and in what order things end up in there. The code distinguishes between big- and little-endian systems but wrongly assumes that sizeof(long int) == 4, which isn't universally true (quel surprise...). The attached patch fixes the issue, but in the long run we should insist on posix and use a64l(). Author: David Levine Date: Wed Jun 13 23:12:22 2012 -0500 Support empty message body in mhmail.in the same way as in mhmail. Author: David Levine Date: Wed Jun 13 22:59:05 2012 -0500 Added support to mhmail.in to read message from stdin. Author: David Levine Date: Wed Jun 13 22:32:46 2012 -0500 Removed newline before generated From:. Author: David Levine Date: Wed Jun 13 22:19:19 2012 -0500 Added mhmail.in. start of a replacement for compiled mhmail. Author: David Levine Date: Wed Jun 13 22:18:43 2012 -0500 Removed unnecessary comment. Author: David Levine Date: Wed Jun 13 22:16:46 2012 -0500 Removed another faceproc relic. Author: David Levine Date: Wed Jun 13 08:55:19 2012 -0500 Added BUGS section to mh-tailor man file to note that failure to open mts.conf is silently ignored.. And added to its DEFAULTS section. Also changed to consistent use of "mail transport configuration file". Author: David Levine Date: Tue Jun 12 21:36:16 2012 -0500 Generate a From: header, using localmbox, if the user doesn't provide a -from when sending with mhmail. Author: David Levine Date: Tue Jun 12 21:16:34 2012 -0500 Fixed the export of LC_ALL so that it work with old Bourne shell. Author: Alexander Zangerl Date: Tue Jun 12 21:06:44 2012 -0500 Occasionally the post tests attempt to talk to fakesmtp before that has completly started up. Inserted a check between starting up fakesmtp and talking to it, and delay and retry if necessary, to avoid that scenario. Author: Alexander Zangerl Date: Tue Jun 12 19:11:57 2012 -0500 Changed remaining uses of MAXPATHLEN to PATH_MAX. Author: David Levine Date: Mon Jun 11 22:02:55 2012 -0500 Can't use -ansi with gcc 4.5.3 on Cygwin, at least through setup setup version 2.763, because it disables some features in the system system header files. Added configure check, when using gcc, for -ansi (and don't use -pedantic without it). Author: Ken Hornstein Date: Mon Jun 11 00:26:21 2012 -0400 Fix typo in gpg command and handle the .sig file properly. Author: David Levine Date: Sun Jun 10 22:50:24 2012 -0500 Replaced run-time detection of hard-link support with compile- time detection. This way, Cygwin packages can be built on NTFS or other filesystems but still bee installed on FAT file systems, which do not support hard links. Author: David Levine Date: Sun Jun 10 09:58:52 2012 -0500 Added section 7 to man pages. Author: David Levine Date: Sun Jun 10 09:53:48 2012 -0500 Updates to SPECS/build-nmh-cygwin: 1) Configure with sysconfdir=/etc/nmh so to minimize pollution of /etc. 2) Disabled install_docs because nmh's make install takes care of it. Though it installs in /usr/share/doc/nmh/ instead of /usr/share/doc/nmh-/, that seems to be more common on Cygwin than using the -. 3) Added comments (also added to MACHINES) about the packages that would be needed to configure with --with-cyrus-sasl and --with-tls. Author: David Levine Date: Sun Jun 10 09:51:03 2012 -0500 Moved nmh and mh-chart man pages from section 1 to section 7. Alexander Zangerl noted that Debian already did this, and it seems appropriate. Author: Alexander Zangerl Date: Sun Jun 10 09:20:08 2012 -0500 Corrected install-mh man page to show that it is installed in section 1, not 8. Author: Alexander Zangerl Date: Sun Jun 10 09:19:20 2012 -0500 Ensure that writes to /dev/tty succeed to determine if it is writeable. Author: Alexander Zangerl Date: Sun Jun 10 09:18:22 2012 -0500 Use cat for moreproc in testsuite in case it is run without tty. Author: David Levine Date: Sat Jun 9 09:31:19 2012 -0500 Added warning to all nmh programs for multiple profile entries for the same component. Until now, all but the first were silently ignored. Author: David Levine Date: Fri Jun 8 20:59:32 2012 -0500 Added INSTALL, NEWS, and README to dist_doc_DATA so that they get installed. Author: David Levine Date: Thu Jun 7 22:07:54 2012 -0500 Changed repl and dist default to -noatfile. Author: David Levine Date: Thu Jun 7 11:07:00 2012 -0500 Removed docs/pending-release-notes-tmp, which was added by mistake. Author: David Levine Date: Wed Jun 6 22:41:29 2012 -0500 Removed faceproc support, deprecated in nmh 1.5. Author: David Levine Date: Wed Jun 6 22:02:21 2012 -0500 Removed the following environment variables, deprecated in nmh 1.5: MHPOPDEBUG (use -snoop command line switch instead) MM_NOASK (use -nolist and -nopause command line switches instead) NOMHNPROC (use -nocheckmime command line switch instead) Author: David Levine Date: Wed Jun 6 21:08:53 2012 -0500 Changed exit status of each nmh command's -version and -help switches from 1 to 0. Author: Ken Hornstein Date: Sun Jun 3 15:38:39 2012 -0400 Fix incorrect documentation about the install process for files in 'etc'. Noted by Norm Shapiro. Author: Ken Hornstein Date: Sun Jun 3 15:29:27 2012 -0400 One more lowercase for the content-transfer-encoding. Author: Ken Hornstein Date: Fri Jun 1 10:25:37 2012 -0400 Fix off-by-one error, noticed by Ralph Corderoy. Author: Paul Fox Date: Thu May 31 15:15:36 2012 -0400 Implement the following changes: - Special #on/#off/#pop directives to control the MIME directive processing state - A flag (-directives) to control whether or not mhbuild will honor MIME directives by default. Author: Ken Hornstein Date: Thu May 31 14:56:47 2012 -0400 Convert the content-transfer-encoding to lower-case always. Author: David Levine Date: Tue May 29 07:57:30 2012 -0500 Unset MM_CHARSET so it doesn't interfere with test-scan-multibyte. Author: Ken Hornstein Date: Sat May 26 01:55:08 2012 -0400 Support for handling multibyte encodings in cpstripped(), which means that multibyte character encodings should work correctly on all systems which support the POSIX wide character functions. Author: David Levine Date: Wed May 23 22:16:14 2012 -0500 Update the current folder and current message and synchronize sequences before showing the messages instead of after. This way, the context will be updated even if the user exists while viewing the messages. Author: David Levine Date: Mon May 21 20:05:19 2012 -0500 comp and dist cannot take multiple message arguments. mhbuild does not set context. Author: David Levine Date: Mon May 21 20:03:57 2012 -0500 Changed wording to say that the last message selected (not necessarily shown) will become the current message. That's consistent with the mhlist and mhstore man pages. Author: Ken Hornstein Date: Thu May 17 08:34:29 2012 -0400 Minor changes to replyfilter to make it compatible with older versions of Perl. Author: David Levine Date: Sat May 12 11:02:21 2012 -0500 Used this version, renamed nmh-1.5-1.sh, in application for Cygwin package. Author: David Levine Date: Sat May 12 09:30:27 2012 -0500 Allow selection of locking type. Author: David Levine Date: Sat May 12 07:44:16 2012 -0500 SIGNATURE/Local-Mailbox are not used by post, but just by front ends (comp, forw, repl, etc.) that read the profile. Author: David Levine Date: Thu May 10 21:23:09 2012 -0500 Don't test with sendmail because it would really send the mail. If configured to use sendmail, change the mts.conf used by the test suite to use smtp instead. Author: David Levine Date: Wed May 9 22:05:28 2012 -0500 Wrap local part (username) of address with double quotes if needed. Author: David Levine Date: Tue May 8 22:19:29 2012 -0500 Skip the Cygwin package (.bz2) file when searching for the input (.gz) file. Author: David Levine Date: Tue May 8 20:29:57 2012 -0500 Added test script constructs to avoid. Author: David Levine Date: Tue May 8 10:16:46 2012 -0500 Fixed patch section of prep(). Author: David Levine Date: Tue May 8 10:16:17 2012 -0500 Added MACHINES to EXTRA_DIST so that it gets put in the distribution. Author: David Levine Date: Mon May 7 18:35:28 2012 -0500 Removed locking type selection from build_nmh now that it's in configure. Author: David Levine Date: Mon May 7 18:33:18 2012 -0500 build-nmh-cygwin no longer needs to DISABLE_SETGID_MAIL now that configure uses fcntl on Cygwin. Author: David Levine Date: Mon May 7 17:25:43 2012 -0500 Added -ansi -pedantic with gcc. Author: David Levine Date: Mon May 7 16:45:32 2012 -0500 Added $(TESTS_SHELL) at end of TESTS_ENVIRONMENT. This lets the user run the tests using a shell other than the default /bin/sh by using, e.g., make check TESTS_SHELL=/bin/bash. Thanks to Tom Lane for suggesting this. Author: David Levine Date: Mon May 7 16:35:16 2012 -0500 Fixed some more problems caught by gcc -ansi -pedantic. Author: Tom Lane Date: Mon May 7 16:14:37 2012 -0500 Fixed places in the code relying the C99-ism of declarations in the midst of a code block. Author: David Levine Date: Mon May 7 08:57:38 2012 -0500 Removed --enable-pop and SETGID_MAIL= from nmh.spec. Author: Ken Hornstein Date: Mon May 7 09:45:38 2012 -0400 Fix test so it will work on terminal widths other than 80. Author: David Levine Date: Sun May 6 21:53:18 2012 -0500 Default to fcntl locking for AIX, Cygwin, and Linux. Without it on Cygwin, nmh is unusable on FAT32 filesystems. Default to flock on FreeBSD. Author: David Levine Date: Sun May 6 21:52:22 2012 -0500 Added note about test/inc/test-deb359167 failing because valgrind detects use of an uninitialized variable on older Linux distributions. Author: Ken Hornstein Date: Sun May 6 13:41:07 2012 -0400 Fix the case of the MacOS X dSYM directories. Author: David Levine Date: Sun May 6 11:14:49 2012 -0500 Remove any existing Local-Mailbox: profile component before adding one. Author: David Levine Date: Sun May 6 10:59:42 2012 -0500 Added check for EPERM when checking errno after a failed link(2). Cygwin will produce that on FAT32 filesystems. Must do this at runtime rather than configure time because link() succeeds on NTFS filesystems. Author: David Levine Date: Sat May 5 10:05:36 2012 -0500 Check for success of hard links of bin files. If they fail, try sym links. On Cygwin, the choice of ln or ln -s must be made at install time, not configure time, because some filesystems (NTFS) support hard links but others (FAT32) don't. Fallback to cp -p, though might not be needed, just in case. Author: David Levine Date: Sat May 5 10:04:35 2012 -0500 Customized generic SPECS/build-nmh-cygwin for nmh. Author: David Levine Date: Sat May 5 09:54:10 2012 -0500 Replaced mh_profile man page hard link with new man/mh_profile.man. The hard link isn't be supported by SPECS/build-nmh-cygwin. And it's consistent with the handling of other aliased man pages. Author: David Levine Date: Sat May 5 09:16:49 2012 -0500 Added SPECS/build-nmh-cygwin. This version isn't ready: it's a renamed download of http://sourceware.org/cgi-bin/cvsweb.cgi/~checkout~/packaging/templates/generic-build-script?content-type=text/plain&cvsroot=cygwin-apps It's committed in its original form so we can easily view changes to it. Author: David Levine Date: Sat May 5 09:14:48 2012 -0500 Moved nmh.spec to new SPECS directory. Author: David Levine Date: Mon Apr 30 21:56:26 2012 -0500 Removed documentation of obsolete WHATNOW configuration option and built-in FTP client. Removed some completed and obsolete tasks from TODO. Author: David Levine Date: Sat Apr 28 15:56:36 2012 -0500 Allow a user to enable setgid of inc when running distcheck with: make distcheck DISTCHECK_CONFIGURE_FLAGS=DISABLE_SETGID_MAIL=0 though that's probably never going to be used. (cherry picked from commit b83b264039d4245810cb845a540c024032a45ac4) Author: David Levine Date: Sat Apr 28 07:55:16 2012 -0500 Disable setgid of inc (SETGID_MAIL=1) when running distcheck. (cherry picked from commit 9ba93ac9c535b678bb602094997a797ba8b33666) Author: Lyndon Nerenberg Date: Fri Apr 27 18:31:36 2012 -0700 Formatting cleanup. Author: Ken Hornstein Date: Fri Apr 27 20:25:20 2012 -0400 Updates OS specific notes. Author: David Levine Date: Thu Apr 26 20:37:59 2012 -0500 Moved the set +e up to capture one more test in test-pick. That test heirloom-sh to exit. (cherry picked from commit f793aa71e4f7375daeb2cc9ef25512172fcb1451) Author: David Levine Date: Wed Apr 25 20:32:10 2012 -0500 Use case statement to check for proper result from "mhparam sbackup". Also replaced a couple of other uses of grep with case statements. (cherry picked from commit 2f4fc229fd6578389b0435b044dc559d9d9bc292) Author: David Levine Date: Wed Apr 25 20:08:55 2012 -0500 Removed the mv of the file after running sed on it. (cherry picked from commit 214da7bcd1ef52c46d4e77c787517d9403c97046) Author: David Levine Date: Wed Apr 25 20:08:03 2012 -0500 Unset all MH environment variables that aren't set below. (cherry picked from commit 16dba0d07e94832ef9a077e6524714d0e433a111) Author: David Levine Date: Wed Apr 25 14:21:42 2012 -0500 1) With SETGID_MAIL enabled (only with dot locking), if the chgrp of inc fails during install, don't attempt to chmod it. This will cause make install to fail, which is good in this case. 2) Added SETGID_MAIL= to the install by the test suite so that it does not attempt the chgrp+chmod. The test suite didn't need them. 3) Removed the SETGID_MAIL= from the test suite invocation in build_nmh. (cherry picked from commit 721276218bc03d4b0d86306c9b2990fae6f07426) Author: Ken Hornstein Date: Wed Apr 25 13:02:33 2012 -0500 Disable utmpx support for systems that lack getutxent. Author: Oliver Kiddle Date: Wed Apr 25 17:40:09 2012 +0200 futher test suite fixes to work on Solaris Author: David Levine Date: Tue Apr 24 21:04:54 2012 -0500 Fixed test suite to work with Solaris Bourne shell: 1) Removed ! (negation) of statuses. 2) Removed initializations from export statements. 3) Replaced $() with ``. 4) Replaced $(()) (and expr) with new function arith_eval (). (cherry picked from commit a6af3b6300e02ade9f223f8d91667f590d191dc9) Author: Ken Hornstein Date: Tue Apr 24 17:02:38 2012 -0500 Update info for mh-profile documenting comment format and the restriction on blank lines. Author: David Levine Date: Tue Apr 24 14:23:44 2012 -0500 Fixed to work with Solaris Bourne shell. Author: David Levine Date: Tue Apr 24 14:22:06 2012 -0500 Added build_nmh to dist_contrib_DATA. Author: Ken Hornstein Date: Sun Apr 22 14:47:57 2012 -0500 The mh-users list at UCI is no longer. Author: Ken Hornstein Date: Sun Apr 22 13:30:33 2012 -0500 Got the hostname for the savannah upload area wrong. Author: Ken Hornstein Date: Sun Apr 22 12:59:18 2012 -0500 Update for post-1.5 release. Author: Ken Hornstein Date: Sun Apr 22 09:37:36 2012 -0400 Clean up help messages a bit. Author: Ken Hornstein Date: Sun Apr 22 09:37:24 2012 -0400 Clean up install documentation a bit. Author: Ken Hornstein Date: Fri Apr 20 14:43:16 2012 -0400 Implment -noatfile in a different way; it turns out my previous change broke dist with -noatfile. Author: Ken Hornstein Date: Mon Apr 16 10:33:13 2012 -0400 Change the cscope target slightly so the source code from the historical tree isn't found. Author: David Levine Date: Sun Apr 15 10:02:23 2012 -0500 Added declaration of __srget() on Cygwin. Used point solution because this shouldn't be needed for much longer. Author: David Levine Date: Sun Apr 15 10:00:22 2012 -0500 Added -Wno-sign-compare, if supported, to compile of sbr/dtimep.c. It's code generated by flex and some versions produce a signed/unsigned mismatch. Author: Ken Hornstein Date: Fri Apr 13 11:23:20 2012 -0400 Sigh. More changes for newer versions of perl. Author: Ken Hornstein Date: Thu Apr 12 21:07:57 2012 -0400 Support -fmtproc -nofmtproc in show. Author: Ken Hornstein Date: Thu Apr 12 20:42:52 2012 -0400 More updates to replyfilter Author: Ken Hornstein Date: Thu Apr 12 11:40:42 2012 -0400 Clean up fakesmtp and the post tests a bit to hopefully reduce race conditions that make the tests fail sometimes. Author: David Levine Date: Wed Apr 11 20:59:57 2012 -0500 Undid wrapping of setjmp() and sigsetjmp() of 4548981fb45fbc917cc2c26b7c96b31cf a14bc9b. What a bad idea. Author: David Levine Date: Wed Apr 11 20:42:22 2012 -0500 Tweaked build_nmh to work with Cygwin. Author: David Levine Date: Tue Apr 10 20:47:46 2012 -0500 Removed unused Hesiod relic. Author: David Levine Date: Tue Apr 10 20:47:16 2012 -0500 Added docs/contrib/build_nmh script. Author: Ken Hornstein Date: Fri Apr 6 15:55:14 2012 -0400 Add support for -fmtproc and -nofmtproc switches to repl. Author: David Levine Date: Fri Apr 6 13:27:30 2012 -0500 Changed test-mhparam to allow # sbackup. Author: Ken Hornstein Date: Fri Apr 6 13:57:20 2012 -0400 Fix forw so it respects the -form switch again for non-digests. Author: Ken Hornstein Date: Fri Apr 6 13:56:03 2012 -0400 Refere to VERSION via srcdir so this works when doing objdir builds. Author: David Levine Date: Fri Apr 6 12:27:22 2012 -0500 Reworked mhparam tests of components in procs array to depend on values set in common.sh, notably $pagerpath. Author: David Levine Date: Thu Apr 5 20:15:06 2012 -0500 Added mhparam test of each component in procs array in uip/mhparam.c. Author: David Levine Date: Thu Apr 5 17:14:57 2012 -0500 Fixed install-mh -auto test by specifying HOME. Author: Ken Hornstein Date: Wed Apr 4 23:33:40 2012 -0400 Sigh. More corner cases to deal with! Author: David Levine Date: Wed Apr 4 21:41:39 2012 -0500 Changed rmm, send, and whatnow man pages to be consistent with the refile man page with mention of site-dependent prefix (usually a comma). Author: Ken Hornstein Date: Wed Apr 4 15:55:36 2012 -0400 Fixed some more charset/encoding stuff. Author: Lyndon Nerenberg Date: Tue Apr 3 19:07:52 2012 -0700 This is a test commit to se if the savannah git hub will stop spewing source diffs in commit email messages. In this case, there should be a half-dozen lines of my bable, and no context diffs from the one line change I made in this commit. Author: David Levine Date: Tue Apr 3 20:47:17 2012 -0500 Moved nmh.spec and docs/replyfilter to new docs/contrib/ directory. Author: Ken Hornstein Date: Tue Apr 3 15:56:41 2012 -0400 A few more bugs I didn't catch earlier. Author: Ken Hornstein Date: Tue Apr 3 13:04:47 2012 -0400 Fix some bugs in replyfilter. Author: Ken Hornstein Date: Mon Apr 2 15:58:12 2012 -0400 Whoops, fix a typo in my last commit. Author: Ken Hornstein Date: Mon Apr 2 15:39:00 2012 -0400 Bring in replyfilter to the docs directory. Author: Ken Hornstein Date: Mon Apr 2 15:38:40 2012 -0400 Implement fix in 59b086daa57105e8fbd8b1e6ba60be6a845faf95 here as well. Author: David Levine Date: Sat Mar 31 11:52:10 2012 -0500 Added const qualifier to a couple of local pointers to get rid of compile warnings with --with-tls. Author: David Levine Date: Mon Mar 26 21:28:54 2012 -0500 Removed hostable relics from h/mts.h and sbr/mts.c. Author: David Levine Date: Mon Mar 26 20:32:03 2012 -0500 Removed the hostable option from mts.conf because it's no longer used. This allowed removal of mts/smtp/hosts.c. Author: David Levine Date: Sun Mar 25 22:42:36 2012 -0500 Added test-install-mh. Author: David Levine Date: Sat Mar 24 21:47:31 2012 -0500 Note that %(myname) truncates the GECOS field at the first comma, if it contains one. Author: Ken Hornstein Date: Sat Mar 24 22:32:13 2012 -0400 Add support for %(size). Author: David Levine Date: Sat Mar 24 21:09:20 2012 -0500 Removed -realsize from man page because mhshow doesn't support it. Author: David Levine Date: Sat Mar 24 09:22:41 2012 -0500 Fixed Cygwin notes. Author: David Levine Date: Sat Mar 24 09:13:47 2012 -0500 Ensure that escape_display_name() can't overrun a buffer. Author: David Levine Date: Sat Mar 24 09:04:34 2012 -0500 Cleaned up compile warnings. Author: Ken Hornstein Date: Sat Mar 24 02:15:49 2012 -0400 Add this support for setting the CT_ADDR flag. Author: Ken Hornstein Date: Sat Mar 24 02:08:03 2012 -0400 Sigh. Turns out last change broke a few tests, because it trimmed the newline on the "body" component. Ignore that and the text component as well for trimming. Also create some tests for the repl changes. Author: Ken Hornstein Date: Sat Mar 24 01:16:42 2012 -0400 Revert commit 255d4c646c0d7aa6b049052fef47fa083b1b1506 and solve the problem another way. The component parser needs to save the newlines so it can combine multiple headers properly. So for us, strip out any trailing newlines when we call fmt_scan(). Author: Ken Hornstein Date: Fri Mar 23 23:21:35 2012 -0400 Modify the whatnow tests to deal with different versions of readline; some echo the input, some do not. Author: Ken Hornstein Date: Thu Mar 22 23:34:08 2012 -0400 If the number of messages in a folder is zero, then don't try to clear out the sequence list; this can cause you to run off the beginning of the malloc'd buffer. This can happen when you use "comp" with a draft folder, the draft folder is empty, and you have a previous sequence set in your .mh_profile. As far as I can tell this has been a problem for nearly forever, but I only ran into it recently when adding the readline support. Go figure. Author: David Levine Date: Thu Mar 22 21:06:47 2012 -0500 Added function escape_display_name() to double quote, if not already, a fullname that contains any of the special characters listed in RFC 5322, and escape unescaped, embedded double quotes. With this change, nmh should work with no special configuration on Cygwin, even if the user's fullname is of the form server\name. Author: David Levine Date: Thu Mar 22 19:40:17 2012 -0500 Moved NMH_READLINE to after our setting of CFLAGS, because AC_SEARCH_LIBS messes with them. Author: David Levine Date: Wed Mar 21 20:01:06 2012 -0500 If a pager isn't specified with configure --with-pager, look in order for more, less, and most. Fall back to cat, to avoid catastrophic failure of mhshow, et al., if pagerpath is set to "no". Updated Cygwin section of MACHINES. Author: Ken Hornstein Date: Wed Mar 21 15:27:15 2012 -0400 Support for readline command history, editing, and completion at the WhatNow? prompt. Based on work by Steve Rader. Author: Ken Hornstein Date: Wed Mar 21 12:22:16 2012 -0400 Revert previous change to get rid of MULTIBYTE_SUPPORT ifdef. It turns out this breaks the Plan 9 build. But include a check for the multibyte functions so we get MULTIBYTE_SUPPORT on systems that have it. This reverts commit bd4fca3a8a15b35a04bdc333503c901d677c12eb. Author: David Levine Date: Tue Mar 20 23:49:17 2012 -0500 Fixed harmless compile warnings. Author: Ken Hornstein Date: Tue Mar 20 21:36:37 2012 -0400 It turns out that as part of POSIXification we got rid of checks for wcwidth and mbtowc (because they're part of POSIX) but we didn't turn on MULTIBYTE_SUPPORT because configure was testing to see if those functions were supported ... and because the tests never ran, it always came back as not being supported. Time to bite the bullet and turn MULTIBYTE_SUPPORT on by default. Author: Ken Hornstein Date: Tue Mar 20 20:22:19 2012 -0400 Document formatarg. Author: Ken Hornstein Date: Tue Mar 20 19:52:29 2012 -0400 Use _exit() instead of exit() so our writer process doesn't flush out the stdio buffers on exit. Author: Ken Hornstein Date: Tue Mar 20 19:15:18 2012 -0400 Basic work to add arguments to formatproc calls. Author: Ken Hornstein Date: Mon Mar 19 21:37:14 2012 -0400 Just for sanity's sake, double check the "inc" results also with "scan". Merge: e8ed3af 740e258 Author: David Levine Date: Sun Mar 18 20:59:06 2012 -0500 Merge branch 'master' of git.sv.nongnu.org:/srv/git/nmh Author: Steve Rader Date: Sun Mar 18 20:57:08 2012 -0500 Added list of hand picked types initially genereted by... cat /etc/mime.types \ | perl -ane 'if ($F[1] ne "") {print "mhshow-suffix-$F[0]:.$F[1]\n"}' Author: Ken Hornstein Date: Sun Mar 18 21:29:39 2012 -0400 Fix a bug where a message header ending right on the stdio boundary would cause the body output in scan to be truncated. Also include a test for the aforementioned bug. Author: Ken Hornstein Date: Sat Mar 17 23:42:26 2012 -0400 Fix typo in man page Author: David Levine Date: Sun Mar 18 10:27:05 2012 -0500 Added release note that ./@ is obsolete/deprecated. Author: David Levine Date: Sun Mar 18 09:53:31 2012 -0500 Added test-whom. Author: David Levine Date: Sun Mar 18 09:17:56 2012 -0500 Added documentation of -sever, -port, -sasl, -saslmech, -snoop, -user, -tls, and -notls to whom man page. Author: David Levine Date: Sun Mar 18 09:15:30 2012 -0500 Added whom, it's the fifth program referred to in mh-draft man page. Author: David Levine Date: Sat Mar 17 14:33:43 2012 -0500 In gcov target, added warning if configured with --enable-debug. While gcov will work with it, it won't reflect optimizations that are disabled with that option. Merge: 7cc0e99 67c56ba Author: David Levine Date: Fri Mar 16 22:11:09 2012 -0500 Merge branch 'master' of git.sv.nongnu.org:/srv/git/nmh Conflicts: Makefile.am Author: David Levine Date: Fri Mar 16 21:07:52 2012 -0500 Automated generation of mh-chart.man. Author: David Levine Date: Fri Mar 16 21:07:52 2012 -0500 Automated generation of mh-chart.man. Author: David Levine Date: Fri Mar 16 21:05:21 2012 -0500 Commmiting last manual update of mh-chart.man before removing it. Author: David Levine Date: Fri Mar 16 21:02:57 2012 -0500 Removed some unused code having to do with permissions of symlinks. Author: David Levine Date: Fri Mar 16 21:01:30 2012 -0500 Added mhshow-suffix-text/calendar. Author: Ken Hornstein Date: Fri Mar 16 13:21:38 2012 -0400 Improve the documentation for "send" a bit in terms of how it maps file suffixes to MIME types. Author: Ken Hornstein Date: Fri Mar 16 13:02:43 2012 -0400 Make -attach Nmh-Attachment & -attachformat 1 the default. Author: Ken Hornstein Date: Fri Mar 16 11:37:31 2012 -0400 Update for changes to post. Author: Ken Hornstein Date: Fri Mar 16 11:32:35 2012 -0400 Create new switches -atfile and -noatfile to control the creation of the @ file when repl'ing or dist'ing a message. Author: Ken Hornstein Date: Fri Mar 16 00:21:35 2012 -0400 Update post(8) regarding the New World Order. Author: Ken Hornstein Date: Thu Mar 15 23:14:48 2012 -0400 Whoops, forgot to put "." before some of the suffixes. Author: Ken Hornstein Date: Thu Mar 15 23:09:41 2012 -0400 Add some more default MIME content suffixes. Author: Ken Hornstein Date: Thu Mar 15 23:00:06 2012 -0400 Call readconfig() on mhn.defaults so we get default entries in for use with attach. Author: Ken Hornstein Date: Thu Mar 15 22:23:20 2012 -0400 A test for the group addressing functionality handled by "post". Author: Ken Hornstein Date: Thu Mar 15 15:54:02 2012 -0400 Remove all masquerade support (draft_from is now the default, and the other two can be accomplished via the components file). Author: Ken Hornstein Date: Thu Mar 15 13:55:15 2012 -0400 Clean up prototypes. Author: Ken Hornstein Date: Thu Mar 15 13:04:38 2012 -0400 Fix some warnings. Author: Ken Hornstein Date: Thu Mar 15 11:55:34 2012 -0400 I guess the -i option to sed works differently on Linux and MacOS X; deal with it. Author: David Levine Date: Wed Mar 14 21:05:16 2012 -0500 Initialized local format_len. gcc on 64-bit Linux warned about it. Author: Ken Hornstein Date: Wed Mar 14 21:15:54 2012 -0400 New test suite for "post"; uses fakesmtp to trap the SMTP protocol. Author: Ken Hornstein Date: Wed Mar 14 21:15:17 2012 -0400 Make sure we don't send Envelope-From if we're using spost. Author: Ken Hornstein Date: Wed Mar 14 15:51:22 2012 -0400 A new test program, fakesmtp, to help us test post. Author: Ken Hornstein Date: Wed Mar 14 15:47:01 2012 -0400 Fix the SMTP code so it doesn't end up in a hard loop during a DATA command. Author: David Levine Date: Tue Mar 13 22:28:03 2012 -0500 Disabled the optimization to stop stat'ing directory entries in BuildFolderListRecurse() of flist.c under conditions where st_nlink is set to 1. That happens on Cygwin, for example: http://cygwin.com/ml/cygwin-apps/2008-08/msg00264.html Author: David Levine Date: Tue Mar 13 22:01:52 2012 -0500 Changed output_md5() to output just the checksum. If the filename needs to appear on the same line, the caller needs to add it. This avoids differences due to a leading '*' binary file indicator, even for text files, on Cygwin. Author: David Levine Date: Tue Mar 13 21:20:47 2012 -0500 Added test/getfqnd.c, a replacement for "hostname" that always tries to provide the fully qualified domainname of the host, even on Cygwin. It uses the code that LocalName in sbr/mts.c uses. Author: David Levine Date: Tue Mar 13 19:58:33 2012 -0500 On some platforms, need to be out of $SPDIR in order to remove it. So do that in test/whatnow/test-ls. Author: David Levine Date: Tue Mar 13 19:56:06 2012 -0500 Promote uid_t value to long and print with %ld to prevent compile warning on platforms, such as Cygwin, where it is a long. Author: Ken Hornstein Date: Tue Mar 13 15:25:41 2012 -0400 Modify getfullname so it performs the same processing that mts.c:getuserinfo() does. Author: Ken Hornstein Date: Tue Mar 13 15:15:42 2012 -0400 Create proper prototypes for formataddr() and concataddr(). Author: Ken Hornstein Date: Mon Mar 12 22:52:21 2012 -0400 New changes: Sender: cannot be blank, Sender: always overrides From: for SMTP envelope, and Envelope-From: will cause a Sender: header to be output if multiple From: addresses are used. Author: Ken Hornstein Date: Sun Mar 11 21:47:04 2012 -0400 Require From: header in all outgoing messages. Allow Sender: header (require if multiple addresses are in From:). Support new Envelope-From: header for overriding post's choice of SMTP envelope-from address. Author: Ken Hornstein Date: Sun Mar 11 18:08:03 2012 -0400 Add support for a -notls switch, for consistency's sake. Author: Ken Hornstein Date: Sat Mar 10 22:55:16 2012 -0500 Clean up a bunch of unused code and options. Specifically: - Remove support for SMTP SEND, SAML, and SOML commands - Remove -deliver, -fill-in and -fill-up switch for post (and related code) - Document -server and -port switches better in post man page. Author: Ken Hornstein Date: Tue Mar 6 09:25:00 2012 -0500 SMTPMTS has been the default for over a decade, so it's time to get rid of the #ifdefs to clean up the code a bit. Author: David Levine Date: Sun Mar 11 19:52:38 2012 -0500 Fixed mhstore to honor nmh-storage profile entry even with -auto [Bug #35303]. Author: David Levine Date: Sat Mar 10 20:33:24 2012 -0600 There were two fd leaks in mhparse.c: 1) In openQuoted(), the decoded contents file was opened twice in succession. The second open was added by a patch in March 2000. 2) openBase64(), openQuoted(), and open7Bit() could open the contents file, but it never would be closed. Added code to each to close the file if the function opened it. [Bug #24004: (debbug 344182)] Author: David Levine Date: Sat Mar 10 10:45:01 2012 -0600 Replaced UTC-8 with UTF-8. Author: David Levine Date: Sat Mar 10 10:44:30 2012 -0600 Removed bash-ism from test-pick. Author: David Levine Date: Thu Mar 8 21:29:28 2012 -0600 Enabled all groff warnings, with -ww, in manpages test. Fixed a bunch of minor problems that it revealed. Author: David Levine Date: Thu Mar 8 21:09:59 2012 -0600 Fixed mhlist -verbose to work with all content types [Bug #35219]. Author: David Levine Date: Thu Mar 8 20:19:53 2012 -0600 1) Removed -noverbose from defaults of mhshow man page. While it accepts -verbose/-noverbose, it ignores them. 2) Added -verbose/-noverbose to mhlist synopsis. Author: David Levine Date: Wed Mar 7 22:08:03 2012 -0600 Added test-refile. Author: David Levine Date: Wed Mar 7 20:20:13 2012 -0600 Replaced us-ascii with iso-8859-1 in examples, just because. Author: David Levine Date: Tue Mar 6 21:57:16 2012 -0600 Added test-mhparam and test-mhstore. Author: David Levine Date: Tue Mar 6 19:57:22 2012 -0600 Removed all traces of rmfproc. It had been used by bbl but was no longer used. Author: David Levine Date: Tue Mar 6 19:08:21 2012 -0600 Some of the man pages had mentioned that arguments should be double-quoted to protect them from the shell. Removed "double-" because single quoting is fine, too. Author: David Levine Date: Tue Mar 6 18:52:41 2012 -0600 Escape spaces in DEFAULTS sections of man pages so they no longer are lost. Author: David Levine Date: Tue Mar 6 18:51:12 2012 -0600 Removed ignored -verbose (and -noverbose) options to mhstore, just in the man pages. The code remains unchanged. Author: David Levine Date: Tue Mar 6 18:49:27 2012 -0600 Fixed example to show that mhparam preserves case of component name. Author: David Levine Date: Tue Mar 6 18:48:21 2012 -0600 Initialized local wasdlm to prevent uninitialized use. Author: Ken Hornstein Date: Mon Mar 5 13:55:04 2012 -0500 Finally got a reasonable burst test working. Author: Ken Hornstein Date: Mon Mar 5 13:24:41 2012 -0500 Update with recent fix. Author: Ken Hornstein Date: Mon Mar 5 13:21:04 2012 -0500 Change this to use "uint32_t" for a 32-bit type, otherwise we can get wrong MD5 checksums on 64-bit systems. Score another one for the test suite! Author: Ken Hornstein Date: Mon Mar 5 12:23:15 2012 -0500 Fix burst so it actually complies with RFC 934. This means discarding any extra stuff leftover at the end of an encapsulated message. Author: Ken Hornstein Date: Thu Mar 1 15:17:43 2012 -0500 A test for burst; still needs work. Author: David Levine Date: Sat Mar 3 12:23:58 2012 -0600 Added test-mhlist. Author: David Levine Date: Sat Mar 3 12:21:00 2012 -0600 mhbuild -check would always fail because it tried to build the digest for the decoded contents file (cefile), which can be null. If it is, use the contents file itself. Author: David Levine Date: Thu Mar 1 18:01:52 2012 -0600 Brought mh-chart man page up to date. Author: David Levine Date: Thu Mar 1 12:33:19 2012 -0600 Added documentation of -snoop. Author: David Levine Date: Thu Mar 1 12:32:23 2012 -0600 Removed RCS sparc object file. Author: David Levine Date: Thu Mar 1 12:29:33 2012 -0600 Under docs/historical/mh-6.8.5, mh.rf and mh.me were renamed to mh-intro.rf and mh-intro.me, respectively, to avoid name clashes with other files on case-insensitive file systems. Author: David Levine Date: Thu Mar 1 12:13:14 2012 -0600 Removed entire docs/historical/mh-6.8.5/local/ tree. It had a pair of files, Distfile and distfile, with clashing case-insensitive names. The rest of it was specific to UCI and LBL. Author: Ken Hornstein Date: Thu Mar 1 12:33:42 2012 -0500 %G isn't actually part of POSIX, so change to %Y. Author: Ken Hornstein Date: Thu Mar 1 12:02:29 2012 -0500 Fixed a problem that caused the test to fail if you ran it on the first nine days of the month. Author: David Levine Date: Wed Feb 29 20:33:24 2012 -0600 Initialized local msgnum to 0. Author: David Levine Date: Wed Feb 29 18:41:14 2012 -0600 Added all of the MH sources, including RCS files, in docs/historical/mh-6.8.5. Sources for the papers are below papers/. Sources for the MH User's Manual are in conf/doc/. Merge: c7f326f 7565efe Author: David Levine Date: Wed Feb 29 16:36:59 2012 -0600 Merge branch 'master' of git.sv.nongnu.org:/srv/git/nmh Conflicts: docs/historical/README Author: David Levine Date: Wed Feb 29 13:49:28 2012 -0600 Removed the sources to the historical documents just added, they're in the mh-6.8.5 tarball. Author: David Levine Date: Wed Feb 29 13:49:28 2012 -0600 Added sources to historical documents downloaded from http://stuff.mit.edu/afs/sipb/project/sipb-athena/src/mh/papers/ Author: Ken Hornstein Date: Wed Feb 29 08:52:26 2012 -0500 Fix a segfault that happens when using the -file option. Author: Ken Hornstein Date: Wed Feb 29 08:51:27 2012 -0500 Argh, I didn't mean to commit the distcomps I was using for testing! Author: Ken Hornstein Date: Tue Feb 28 15:38:56 2012 -0500 dist(1) now processes drafts using mh-format! The last of the programs to do so! Author: Ken Hornstein Date: Tue Feb 28 15:38:37 2012 -0500 Fix this man page for the New World Order. Author: Ken Hornstein Date: Tue Feb 28 15:29:56 2012 -0500 Improve these man pages a bit. Author: Ken Hornstein Date: Tue Feb 28 14:45:03 2012 -0500 Add support for %(msg) function working when not using -digest. I can't imagine what someone would use it for but it's cheap to do, so why not? Author: Ken Hornstein Date: Tue Feb 28 10:32:41 2012 -0500 Part of the patch from bug #4301; clean up our prototypes, a lot. Still plenty of work to do! Author: David Levine Date: Tue Feb 28 22:05:55 2012 -0600 Added docs/historical/. See README for where they were found. Merge: 56f140c e22a2c8 Author: David Levine Date: Mon Feb 27 21:12:22 2012 -0600 Merge branch 'master' of git.sv.nongnu.org:/srv/git/nmh Author: David Levine Date: Mon Feb 27 21:10:47 2012 -0600 Removed blank line after "End of Forwarded Message" lines. It's always bothered me. Author: Ken Hornstein Date: Mon Feb 27 22:11:34 2012 -0500 Add the note about the burst(1) change to pending-release-notes. Author: Ken Hornstein Date: Mon Feb 27 22:05:41 2012 -0500 Fix bug #1466. It turns out that RFC 934 specifies that any line starting with a "-" but NOT followed by a space is a valid message delimiter. We only supported one type of message delimiter. Adapt the code so any valid delimiter is supported. Author: David Levine Date: Mon Feb 27 20:56:58 2012 -0600 Added cast in conditional to prevent signed/unsigned comparison, and wrapped argument to prevent warning about unused argument when built without SASL support. Author: David Levine Date: Mon Feb 27 20:50:29 2012 -0600 Changed domains in man page and test examples to use example.com Author: David Levine Date: Mon Feb 27 20:42:19 2012 -0600 Fixed to report failure if getfulname hadn't been built yet. Author: David Levine Date: Mon Feb 27 20:40:15 2012 -0600 They test with output to a tty didn't work under make distcheck. Tried to work around it by writing directly to /dev/tty, if that's available. Author: Ken Hornstein Date: Mon Feb 27 20:50:49 2012 -0500 Add support for -nosasl and -saslmaxssf switches. Author: Ken Hornstein Date: Mon Feb 27 14:13:02 2012 -0500 Document changes to forw(1). Author: Ken Hornstein Date: Mon Feb 27 14:12:34 2012 -0500 Clean up some typos in here. Author: Ken Hornstein Date: Mon Feb 27 13:45:37 2012 -0500 Got the forw -digest test working. Author: Ken Hornstein Date: Mon Feb 27 13:37:09 2012 -0500 Update digestcomps and forwcomps with comments and better formatting. Author: Ken Hornstein Date: Mon Feb 27 12:56:00 2012 -0500 Make -volume switch actually work (it always got overridden). As far as I can tell, this never worked. Found by the test suite! Author: Ken Hornstein Date: Sun Feb 26 21:29:44 2012 -0500 Remove the forw-digest test until we have it working. Author: Ken Hornstein Date: Sun Feb 26 21:29:01 2012 -0500 A test for forw -digest. It doesn't quite work yet. Author: Ken Hornstein Date: Sun Feb 26 21:14:04 2012 -0500 Fix up some of the pick tests: - Change sed invocation around to get rid of GNU sed extensions - Put explicit times in the pick tests (if you don't, it uses the current hour/minutes as the timestamp, which means it could work or not work depending on what time of day you run the tests). Author: Ken Hornstein Date: Sun Feb 26 13:02:41 2012 -0500 Update the pending release notes with new features. Author: Ken Hornstein Date: Sun Feb 26 12:45:48 2012 -0500 Add a new README documenting the changes to the components files. Author: Ken Hornstein Date: Sun Feb 26 12:12:28 2012 -0500 Beginnings of a test suite for the mh-format support in forw. Author: David Levine Date: Sun Feb 26 10:55:46 2012 -0600 Added test-pick. Author: David Levine Date: Sun Feb 26 10:32:29 2012 -0600 Suppress echoing of man page build lines. One of them says "warning", and it's handy to check that build output doesn't say that. Author: David Levine Date: Sun Feb 26 10:10:35 2012 -0600 Changed type of a local to unsigned and removed local ncomps to suppress compile warnings. Author: David Levine Date: Sun Feb 26 10:09:35 2012 -0600 Added gcov and gcov-clean targets. Author: Ken Hornstein Date: Sun Feb 26 00:09:52 2012 -0500 Finally, some support for mh-format when using forw(1). Still needs some tests. Author: Ken Hornstein Date: Thu Feb 23 12:03:09 2012 -0500 Create a test for the new mh-format processing available in comp(1). Author: David Levine Date: Wed Feb 22 22:23:05 2012 -0600 Added test-flist and test-mark sequences tests. Author: David Levine Date: Wed Feb 22 22:21:56 2012 -0600 Don't list _sysconfdir/ directory in RPM spec. We don't list any other directories, so now it will be created with the same permissions as all of the others. Author: David Levine Date: Tue Feb 21 19:35:05 2012 -0600 Removed reference to mhost.com. Author: David Levine Date: Tue Feb 21 19:34:33 2012 -0600 Updated to reflect that all of the lists are on nongnu.org. Author: David Levine Date: Tue Feb 21 19:31:08 2012 -0600 With "make rpm", configure all modified files in sysconfdir (etc) to be saved when erasing or upgrading the package. Also, leave the doc directory whereever "make install" puts it. Author: Ken Hornstein Date: Tue Feb 21 15:56:06 2012 -0500 Add support for a -subject switch to comp. Author: Ken Hornstein Date: Tue Feb 21 12:58:50 2012 -0500 Switch from (me) to (localmbox) to make -cc me work correctly. Author: David Levine Date: Mon Feb 20 22:02:26 2012 -0600 Migrated a couple more tests to use run_test() in common.sh. Author: Ken Hornstein Date: Mon Feb 20 00:31:14 2012 -0500 Put default From: headers in these component files, and document the components file now that we can have comments. Author: Ken Hornstein Date: Mon Feb 20 00:31:01 2012 -0500 Clean up documentation formatting Author: David Levine Date: Sun Feb 19 22:29:14 2012 -0600 Removed unused local ncomps because gcc complained about it. Author: Ken Hornstein Date: Sun Feb 19 19:59:06 2012 -0500 Add support for "to", "cc", "from", and "fcc" components via command-line switches. Author: Ken Hornstein Date: Sun Feb 19 18:03:26 2012 -0500 Fix a bug leftover from the Automake conversion; the AC_SUBST'd variable names are really editorpath and pagerpath, use those instead. Author: David Levine Date: Sat Feb 18 22:36:50 2012 -0600 Ken noted that "make check" can be run before installation because the only program in lib that the tests currently use is mhlproc, and we have an mhlproc entry in the test .mh_profile for that. Added showproc and postproc entries in case they're ever needed. Author: David Levine Date: Sat Feb 18 17:32:15 2012 -0600 Moved "make check" to after "make install". Author: David Levine Date: Sat Feb 18 17:31:37 2012 -0600 gcc was warning about unused arguments to main, so added use of them in a usage check. Author: David Levine Date: Sat Feb 18 17:30:47 2012 -0600 Consolidated runtest and check_string test functions. Author: David Levine Date: Sat Feb 18 11:21:28 2012 -0600 Have each test clean up after itself if it completes successfully. Author: David Levine Date: Sat Feb 18 09:42:04 2012 -0600 Added mhpath test. Updated mhpath man page to reflect actual behavior for a message number greater than that of the highest existing message in a folder. Author: David Levine Date: Sat Feb 18 08:03:21 2012 -0600 The test check() function now removes the expected and actual output files if they're the same, by default. Added check-string() function. Author: David Levine Date: Fri Feb 17 19:10:08 2012 -0600 Initialized local "in" to suppress gcc warning about possible uninitialized use. Author: David Levine Date: Fri Feb 17 19:08:42 2012 -0600 Enclosed program name and directory in double quotes so that they can contain whitespace. Author: David Levine Date: Fri Feb 17 18:44:35 2012 -0600 Here's the proper fix instead of the hack of d28ce569fe233141f86fe516878361da01c9f9cb. Use ${srcdir} in to refer to extra files in tests, as before. Author: Ken Hornstein Date: Fri Feb 17 15:56:08 2012 -0500 Beginning support for mh-format support in comp(1). Includes changes to default component file. Author: Ken Hornstein Date: Fri Feb 17 15:10:06 2012 -0500 Sigh. Looks like we need a function after all; create a new function called %(localmbox). Author: Ken Hornstein Date: Fri Feb 17 14:02:44 2012 -0500 Switch to including h/mts.h for getusername() prototype. Author: David Levine Date: Thu Feb 16 22:56:02 2012 -0600 Added a couple of NMH_UNUSED's to suppress warnings when building without Cyrus SASL. Author: David Levine Date: Thu Feb 16 22:49:03 2012 -0600 Hacked to work with make distcheck. Maybe not the best way but it works for now. Author: David Levine Date: Thu Feb 16 22:02:21 2012 -0600 Moved check() function from individual tests to common.sh. Author: David Levine Date: Thu Feb 16 21:30:43 2012 -0600 Rearranged test suite environment variables so that individual tests can now be run standalone (outside of make). But see WARNING in test/README about how it's better to use "make check" because that ensures that the current code in your workspace is tested. Also, the clean script no longer needs to call setup_test. Author: Ken Hornstein Date: Thu Feb 16 11:46:16 2012 -0500 Report an error when the width used by putaddr is less than the label width. Author: Ken Hornstein Date: Thu Feb 16 00:17:49 2012 -0500 Hopefully made the format documentation a little bit clearer. Author: Ken Hornstein Date: Wed Feb 15 21:45:13 2012 -0500 Fix typo in repl man page. Author: Ken Hornstein Date: Wed Feb 15 15:54:47 2012 -0500 Create test cases for the new format functions for local address writing. Author: Ken Hornstein Date: Wed Feb 15 15:53:26 2012 -0500 Make it so we do NOT check our address against the "local" userid and hostname if Local-Mailbox is set. Author: Ken Hornstein Date: Wed Feb 15 15:46:28 2012 -0500 Sigh. Turns out the first entry in the list isn't actually checked, so we need to make sure that our Local-Mailbox entry starts second. Author: Ken Hornstein Date: Wed Feb 15 14:55:25 2012 -0500 Hm, it turns out we need to make sure we call getname() until we get a NULL, otherwise the next set of calls to it will be working from the "old" search string. Author: Ken Hornstein Date: Wed Feb 15 11:36:36 2012 -0500 Beginning of support for the Local-Mailbox profile entry. Author: Ken Hornstein Date: Wed Feb 15 10:48:52 2012 -0500 Support getting the "fullname" out of the Signature profile setting. Author: David Levine Date: Tue Feb 14 20:47:06 2012 -0600 Updated documentation of environment variables in mh-profile man page. Author: Ken Hornstein Date: Tue Feb 14 20:24:43 2012 -0500 Add two new format functions: %(myhost) and %(myname). Author: David Levine Date: Mon Feb 13 19:55:53 2012 -0600 Changed "make test" to "make check". Author: David Levine Date: Mon Feb 13 19:54:41 2012 -0600 Fixed progress indicator. Author: Ken Hornstein Date: Sat Feb 11 23:28:10 2012 -0500 Another problem discovered by the test suite. With multiple sequence arguments on the command line you might end up with garbage in the sequence[] array (it needs the last argument to be a NULL. So do two things: make the first two arguments NULL, and as we add arguments to sequence[] make sure the list has a NULL on the end. Author: Paul Fox Date: Sat Feb 11 13:06:47 2012 -0500 correct the maximum number of sequences in the mark(1) man page also add a note explaining the somewhat low limit. Author: Paul Fox Date: Sat Feb 11 12:41:30 2012 -0500 mhshow: suppress pause actions if stdout isn't a tty previously, "mhshow | cat" would both print a "Press return" prompt to, and attempt to read from, its piped output fd. Author: Ken Hornstein Date: Fri Feb 10 23:38:40 2012 -0500 Fix this so it works when valgrind is installed. Author: Ken Hornstein Date: Fri Feb 10 23:27:36 2012 -0500 Switch over to using the template files out of our inst directory. Author: Ken Hornstein Date: Fri Feb 10 23:22:12 2012 -0500 Switch to using the "inst" version of mhl for tests. Author: Ken Hornstein Date: Fri Feb 10 23:09:03 2012 -0500 Re-work the test suite so it now works with Automake (via "make check"). Author: Ken Hornstein Date: Fri Feb 10 20:59:21 2012 -0500 Fix typo in alternate mts.conf location support. Author: Ken Hornstein Date: Fri Feb 10 15:11:05 2012 -0500 Make the test suite work on systems other than Linux. Still needs work. Author: Ken Hornstein Date: Fri Feb 10 09:50:48 2012 -0500 With the fixing of the bug that caused CPPFLAGS to get tromped on, remove support for OURDEFS and direct people to use CPPFLAGS instead. Author: Ken Hornstein Date: Thu Feb 9 23:43:30 2012 -0500 Fix typo in variable test. Author: David Levine Date: Thu Feb 9 20:38:22 2012 -0600 Show assignment of configure variables using VAR=VALUE instead of in the shell environment. Author: David Levine Date: Wed Feb 8 22:29:59 2012 -0600 Updated INSTALL and MACHINES documentation a bit. Author: David Levine Date: Wed Feb 8 21:42:46 2012 -0600 Added mhshow subpart test. Author: David Levine Date: Wed Feb 8 21:41:48 2012 -0600 Always run setup-test from make test/runalltests, just in case the test build directory (test/testbuild) isn't up to date. It might be nice to replace all the copies in the test build directory with symlinks, then make could keep the test build up to date. Author: David Levine Date: Tue Feb 7 21:43:26 2012 -0600 Added OURDEFS to DEFS in Makefile.am, to restore it in the Makefile. Updated documentation in INSTALL. Author: David Levine Date: Tue Feb 7 21:23:37 2012 -0600 Removed use of tzset()/tzname in dtimezone(). They caused the returned timezone string to be for the user's current timezone, but the function is supposed to return the string representation of the timezone of its argument. That will be numeric, e.g., +0100, now because we no longer have timezone name support. Author: David Levine Date: Tue Feb 7 21:17:00 2012 -0600 Reverted TZ hack to tests, 9ea2daf5e74e3ff03043cfa6fb68033aea0da52a. A code fix is on its way Author: David Levine Date: Mon Feb 6 22:35:21 2012 -0600 Another one caught by the test suite: an indented line was too long in the slocal man page. Center it instead. Author: David Levine Date: Mon Feb 6 22:25:25 2012 -0600 Some tests failed because they displayed the user's local time zone but expected GMT. So, set TZ in runtest to fool them. Though I wonder if we're failing to correct for local time zone. Author: David Levine Date: Mon Feb 6 21:47:52 2012 -0600 Caught by the test suite: sequences[0] needs to be initialized to NULL at the beginning of the program. That explains why it seg faulted when invoked with a sequence argument. Author: David Levine Date: Mon Feb 6 21:19:57 2012 -0600 Reworked test suite to copy the configuration used in the main nmh directory. Added test target to Makefile. Not all the tests pass at this point. Author: Ken Hornstein Date: Mon Feb 6 14:12:00 2012 -0500 Still more autoconf cleanup (quoting & more use of M4sh). Author: Ken Hornstein Date: Mon Feb 6 11:31:18 2012 -0500 Patch from Harvey Eneman: fixes problem on some systems where a free() would be called on non-malloc'd memory (only would happen if you had more than one entry in the server: line in mts.conf). Author: Ken Hornstein Date: Mon Feb 6 10:27:43 2012 -0500 Update the developer documentation with the changes to the release process. Author: Ken Hornstein Date: Mon Feb 6 09:08:19 2012 -0500 More configure cleanup to modern constructs. Author: Ken Hornstein Date: Sun Feb 5 17:17:41 2012 -0500 Autoconf cleanup to suggested practice (AS_IF & AC_MSG_FAILURE). More to do. Author: David Levine Date: Sun Feb 5 15:26:16 2012 -0600 Added error message if the file is source directly, rather than through bash-completion. Author: David Levine Date: Sun Feb 5 14:13:07 2012 -0600 Exit with error message if no library could be found with tgetent. Author: Ken Hornstein Date: Sat Feb 4 00:11:27 2012 -0500 Whoops, used "buffer" when I meant "buf". Author: Ken Hornstein Date: Fri Feb 3 23:43:53 2012 -0500 Change LocalName() to take an argument (about whether or not to use local hostname versus entry in mts.conf). Merge: 24ccfac 196f981 Author: David Levine Date: Fri Feb 3 17:10:49 2012 -0600 Merge branch 'master' of git.sv.nongnu.org:/srv/git/nmh Author: David Levine Date: Fri Feb 3 17:10:44 2012 -0600 Use more up-to-date web page links of Jerry Peek's book sections at rand-mh.sourceforge.net instead of oreilly.com. Author: Ken Hornstein Date: Fri Feb 3 15:38:49 2012 -0500 Convert from the poorly-named and confusing adrsprintf() to getlocaladdr(). Author: Ken Hornstein Date: Fri Feb 3 15:03:00 2012 -0500 Make the upload target phony. Author: Ken Hornstein Date: Fri Feb 3 15:01:50 2012 -0500 Beginnings of an upload Makefile target. Author: Ken Hornstein Date: Fri Feb 3 13:50:19 2012 -0500 Update with new features. Author: Ken Hornstein Date: Fri Feb 3 13:49:46 2012 -0500 Document the formatproc entry. Author: Ken Hornstein Date: Thu Feb 2 22:13:57 2012 -0500 Move the eval statements inside of AC_CONFIG_COMMANDS_POST macro, otherwise the stuff we output might not be correct. Author: David Levine Date: Tue Jan 31 23:17:33 2012 -0600 Added #includes to pick up declaration of waitpid() Author: Ken Hornstein Date: Tue Jan 31 13:20:40 2012 -0500 Whoops, I need to make sure the buffer I pass to putcomp() is NULL-terminated. Author: Ken Hornstein Date: Tue Jan 31 12:58:04 2012 -0500 Add support for calling an external format program inside of mhl. Merge: abf5b4f c8206d4 Author: David Levine Date: Sat Jan 28 14:12:05 2012 -0600 Merge branch 'master' of git.sv.nongnu.org:/srv/git/nmh Author: David Levine Date: Sat Jan 28 13:52:59 2012 -0600 Made ChangeLog target phony so it will always get regenerated. But don't try to regenerate if git repository is not present. Author: David Levine Date: Sat Jan 28 13:52:59 2012 -0600 Made ChangeLog phony so it will always get regenerated. But don't try to regenerated if git repository is not present. Author: David Levine Date: Sat Jan 28 12:45:15 2012 -0600 The www.ics.uci.edu/~mh/ links are dead, so replaced them with corresponding oreilly.com links. Author: David Levine Date: Sat Jan 28 12:33:27 2012 -0600 Replaced static ChangeLog with one generated by git log. Author: Ken Hornstein Date: Sat Jan 28 00:29:13 2012 -0500 Create "nowrap" flag to turn off all line wrapping. Author: David Levine Date: Fri Jan 27 20:30:58 2012 -0600 Organized .gitignore to show which objects are deleted by the various Makefile clean targets. Author: David Levine Date: Fri Jan 27 19:56:50 2012 -0600 Added superclean Makefile target. Added a.out.DSYM's to clean target. Added .PHONY indication of rpm target. Author: David Levine Date: Fri Jan 27 19:40:48 2012 -0600 Removed config.guess and config.sub because they're generated by autoreconf -i. Author: David Levine Date: Fri Jan 27 19:39:47 2012 -0600 Updated to latest config.guess and config.sub before removing them from the repo, just in case someone needs them and can't generate them. Author: David Levine Date: Fri Jan 27 19:36:14 2012 -0600 Changed a variable to unsigned and noted an argument as unused to silence compile warnings in uip/popsbr.c Author: Ken Hornstein Date: Fri Jan 27 13:47:14 2012 -0500 Fix long-standing problem with getans(); handle the case if we get an interrupted by a signal during a character read and return an EINTR. Author: Ken Hornstein Date: Fri Jan 27 13:34:17 2012 -0500 Convert to the use of siglongjmp() Author: Ken Hornstein Date: Fri Jan 27 12:30:52 2012 -0500 Make POP support always be turned on. Merge: da6bfd3 d5c47f7 Author: Lyndon Nerenberg Date: Fri Jan 27 08:16:57 2012 -0800 Merge branch 'master' of ssh://git.sv.gnu.org/srv/git/nmh Author: Lyndon Nerenberg Date: Fri Jan 27 08:16:36 2012 -0800 Typo fix. Author: David Levine Date: Thu Jan 26 22:36:17 2012 -0600 Added clean-local target to remove RPM directory. Author: David Levine Date: Thu Jan 26 20:05:30 2012 -0600 Added uip/*.exe, for Cygwin. Author: David Levine Date: Thu Jan 26 20:04:33 2012 -0600 Removed slash in front of $(man5dir) of install-data-hook rule so that it now works on Cygwin. Author: David Levine Date: Wed Jan 25 22:22:02 2012 -0600 Fixed rpm target now that nmhdist is gone. Author: David Levine Date: Wed Jan 25 20:48:55 2012 -0600 Updated config test to add -Wextra to be consistent with others. So, it's back! Author: David Levine Date: Wed Jan 25 19:44:30 2012 -0600 If using gcc, use -Wno-unused-macros when compiling sbr/dtime.o. Author: David Levine Date: Wed Jan 25 19:38:49 2012 -0600 Removed unused local bp. Author: David Levine Date: Wed Jan 25 19:33:17 2012 -0600 Undid most of 3ef341abe440ece07f8deed59fb026ab020e805 because FreeBSD needs the HAVE_STRUCT_TM_TM_GMTOFF test. It has a timezone() function, not a timezone global variable (that's visible with our default configuration. Author: lyndon Date: Wed Jan 25 20:10:52 2012 -0800 Remove hardlink target before attempting new link. Author: lyndon Date: Wed Jan 25 18:15:47 2012 -0800 uip/termsbr.c: remove references to PC and ospeed(). These are no longer referenced by the code base now that vmh has been removed. Author: Ken Hornstein Date: Tue Jan 24 12:56:45 2012 -0500 Create a "cscope" target that creates the necessary files to use cscope. Author: lyndon Date: Mon Jan 23 22:48:24 2012 -0800 cscope.files was missing mts/smtp/*. Author: lyndon Date: Sun Jan 22 23:21:03 2012 -0800 Ignore cscope.out. Author: lyndon Date: Sun Jan 22 23:08:02 2012 -0800 Add a default configuration file for cscope(1). I generated the file list by hand. While it might be possible to generate it from the Makefile, it was much simpler to just ls */*.[cl]|grep -v sbr/dtimep.c If source files are added or removed down the road, cscope.files will need a hand edit to keep it in sync. Author: Ken Hornstein Date: Sun Jan 22 01:15:40 2012 -0500 Make sigmsg.h NOT depend on the Makefile. Author: Ken Hornstein Date: Sun Jan 22 01:14:34 2012 -0500 Clean up DESTDIR usage. Author: Ken Hornstein Date: Sun Jan 22 01:12:18 2012 -0500 Add the rule to install inc setgid if requested. Author: Ken Hornstein Date: Fri Jan 20 23:39:14 2012 -0500 Fix some problems that the Automake migration caused. Author: Ken Hornstein Date: Fri Jan 20 14:05:26 2012 -0500 Convert the build system over to the use of Automake. Author: David Levine Date: Tue Jan 17 17:33:29 2012 -0600 Well the wrap of vfork() calls didn't work: its semantics don't allow that. So removed the wrapper and added -Wno-clobbered to gcc -Wextra. Author: Ken Hornstein Date: Tue Jan 17 14:27:06 2012 -0500 Convert from our use of aclocal.m4 to a subdirectory with autoconf macros in it. Author: Ken Hornstein Date: Tue Jan 17 14:15:32 2012 -0500 Change the name of AC_CHECK_NETLIBS, since it's not a macro distributed by Autoconf. Author: Ken Hornstein Date: Tue Jan 17 10:58:40 2012 -0500 Update .gitignore with .DS_Store (seen occasionally on MacOS X systems). Author: Ken Hornstein Date: Tue Jan 17 10:57:54 2012 -0500 Convert from utmp functions to utmpx functions (which are in POSIX). Author: David Levine Date: Mon Jan 16 20:58:15 2012 -0600 Wrapped setjmp(), sigsetjmp(), and vfork() calls to silence gcc -Wclobbered for good. Undid ca34fbd0a5204d47ad019f64ef03d21ebd3397fd, which added volatile qualifiers but was not general. Author: David Levine Date: Mon Jan 16 18:35:21 2012 -0600 Removed HAVE_STRUCT_TM_TM_GMTOFF support because it didn't work on Cygwin and isn't needed: timezone, tzname, and tzset() are all POSIX. Author: David Levine Date: Mon Jan 16 18:33:57 2012 -0600 Pass int instead of char to iscntrl() and isspace() because that's what they require, and gcc on Cygwin warns about it. Author: David Levine Date: Mon Jan 16 18:30:40 2012 -0600 Added EXEEXT support, for Cygwin. Author: David Levine Date: Mon Jan 16 09:50:10 2012 -0600 Fixed build on Cygwin by adding configure check for ncurses/termcap.h. Author: David Levine Date: Sat Jan 14 15:33:39 2012 -0600 Argument to alrmser is unused. Author: David Levine Date: Sat Jan 14 15:28:25 2012 -0600 Fixed warnings from gcc -Wclobbered by adding volatile qualifiers. Author: David Levine Date: Sat Jan 14 15:04:54 2012 -0600 Cleaned up gcc warnings when CYRUS_SASL is not enabled. Author: David Levine Date: Sat Jan 14 14:56:16 2012 -0600 Added -Wextra with gcc, if supported. Author: David Levine Date: Sat Jan 14 14:49:57 2012 -0600 Changed types and added casts so that build is clean with gcc -Wsign-compare. Author: David Levine Date: Sat Jan 14 09:21:32 2012 -0600 gcc -Wmissing-field-initializers noticed several struct initializations that didn't explicitly list all fields. Most were of no consequence because they were for static data, so they were all initialized properly. However, the two in mhlsbr.c were missing an initialization of other than their last field, and they contained some subsequent values other than zero. So, those later fields were initialized incorrectly. Also, changed the initialization of global.c_ovtxt from "" to NULL because free_queue () freed it if non-NULL, though I think the "" was always overwritten. Author: David Levine Date: Sat Jan 14 09:19:49 2012 -0600 configure.ac and aclocal.m4 instead of configure.in and acconfig.h. Author: David Levine Date: Sat Jan 14 09:16:16 2012 -0600 Documented support of OURDEFS to pass compile flags to configure. Merge: c3ed95b 3a84d81 Author: Ken Hornstein Date: Fri Jan 13 12:05:13 2012 -0500 Merge branch 'master' of git.sv.nongnu.org:/srv/git/nmh Author: Ken Hornstein Date: Fri Jan 13 12:04:13 2012 -0500 Add some comments to the format compiler and engine. Author: Ken Hornstein Date: Fri Jan 13 09:30:03 2012 -0500 Update README.developers with the correct version of autoconf we need. Author: David Levine Date: Thu Jan 12 22:19:24 2012 -0600 Added NMH_UNUSED macro for suppressing warnings about unused parameters with gcc -Wunused-parameter Merge: b70215d 162f2a7 Author: David Levine Date: Thu Jan 12 22:17:54 2012 -0600 Merge branch 'master' of git.sv.nongnu.org:/srv/git/nmh Author: David Levine Date: Thu Jan 12 22:14:59 2012 -0600 Added -Wunused-macros with gcc, if supported. Added -Wno-unused-macros, if supported, to compile of sbr/dtimep.o with gcc because it uses generated code that would be too much trouble to clean up. Author: Ken Hornstein Date: Thu Jan 12 21:07:33 2012 -0500 Create two new mh-format functions: %(putlit) and %(concataddr). %(putlit) outputs a string without any space compression or control character conversion %(concataddr) is just like %(formataddr), except that inside of repl there will not be any duplicate address supression. Author: David Levine Date: Wed Jan 11 22:38:35 2012 -0600 Enabled support for tls switch. Author: David Levine Date: Wed Jan 11 22:36:20 2012 -0600 Removed unsupported format and check switches, and commented out unused macro HMNG. Author: David Levine Date: Wed Jan 11 22:33:45 2012 -0600 Removed, or added use of, unused macros to prevent warnings from gcc -Wunused-macros. Author: David Levine Date: Wed Jan 11 17:06:44 2012 -0600 Removed or protected some unused macros. Author: David Levine Date: Wed Jan 11 16:52:17 2012 -0600 Removed unused global zones and local z form dtimezone (). Author: David Levine Date: Wed Jan 11 16:45:53 2012 -0600 Added #include . It's needed on Linux, should be harmless on others. Author: Ken Hornstein Date: Wed Jan 11 15:04:39 2012 -0500 Completely remove the use of TIME_WITH_SYS_TIME (I removed the autoconf test but never removed the code, and this caused some problems on systems that needed some prototypes in ). Author: Ken Hornstein Date: Wed Jan 11 14:52:23 2012 -0500 Ignore a.out.DSYM (this file sometims shows up when using the debugger) Author: Ken Hornstein Date: Wed Jan 11 14:48:45 2012 -0500 Fix two errors in the conversion to m_mktemp2(): - There was an off-by-one error that prevented the temporary file from being created in the same directory as the message it was being linked to. - When using "dist", the assumption was that the temporary file would not exist when m_scratch was called (it wanted to link() to the name). This was solved by simply unlink()ing the temporary file after it was created. Merge: c2191f6 a2469f5 Author: Ken Hornstein Date: Mon Jan 9 15:52:34 2012 -0500 Merge branch 'master' of git.sv.nongnu.org:/srv/git/nmh Author: Ken Hornstein Date: Mon Jan 9 15:51:57 2012 -0500 Remove OS-specific defines. As part of it, remove scary longjmp() inside signal handlers that was part of the code under #ifdef BSD42. Author: David Levine Date: Mon Jan 9 14:08:38 2012 -0600 Removed a remaining RETSIGTYPE. Also change a few locals from int to unsigned to prevent signed-unsigned comparison mismatch. Author: Ken Hornstein Date: Mon Jan 9 14:43:35 2012 -0500 Clean up time handling; always assume we have tzset() and that the right prototypes are in time.h (both are valid in POSIX). Author: Ken Hornstein Date: Mon Jan 9 14:07:37 2012 -0500 Garbage collect autoconf support for checking for the header file for initgroups and snprintf() prototypes. Author: Ken Hornstein Date: Mon Jan 9 13:56:30 2012 -0500 We are making POSIX signal support a requirement; remove all support for other signal interfaces. Author: Ken Hornstein Date: Mon Jan 9 13:38:02 2012 -0500 Finally able to get rid of acconfig.h! Since we're doing slightly better in the autoconf universe, rename configure.in to configure.ac, the "more correct" name for the configure script template. Author: Ken Hornstein Date: Mon Jan 9 13:26:59 2012 -0500 Switch from using RETSIGTYPE via autoconf to void, since POSIX says that's type to use for a signal handler. Author: David Levine Date: Sun Jan 8 17:58:11 2012 -0600 Removed unused bcmp, bcopy, bcpy, and bzero #defines. Author: David Levine Date: Sun Jan 8 13:46:47 2012 -0600 gcc -Wempty-body warned that the check of the result from the call to parse_mime() was ignored. It has been that way since the beginning of history and was probably of no consequence, but fixed anyway. Author: David Levine Date: Sun Jan 8 10:51:05 2012 -0600 Removed traces of bboards and bbc from mh-profile and msh man pages. Added see also of msh to packf man page. Author: David Levine Date: Sun Jan 8 10:34:31 2012 -0600 Wrapped #include of config.h with #ifdef HAVE_CONFIG_H, just in case someone ever wants to build without using configure. Author: David Levine Date: Sun Jan 8 10:27:15 2012 -0600 Removed hard-coded -I.. and -I../.. from INCLUDES, it was redundant given -I$(top_srcdir). Author: David Levine Date: Sat Jan 7 10:03:35 2012 -0600 Added Content-Description header with the filename of the attachment, with attachformats 1 and 2. This seems to be common practice now and gives mhlist something useful to display. Author: David Levine Date: Sat Jan 7 09:53:36 2012 -0600 Added note about fileproc and mhlproc mh-profile entries. Author: David Levine Date: Sat Jan 7 09:19:59 2012 -0600 Added removal of autom4te.cache directory to mostlyclean-local. Author: David Levine Date: Sat Jan 7 09:17:34 2012 -0600 Quoted argument to AC_LINK_IFELSE to silence authoheader warnings. Merge: d2e40bd 0d56141 Author: David Levine Date: Sat Jan 7 08:22:24 2012 -0600 Merge branch 'fileproc_mhlproc_to_post' Author: Ken Hornstein Date: Fri Jan 6 14:40:31 2012 -0500 Move definition of LINK to mh header file, and garbage collect ATTVIBUG code. Author: Ken Hornstein Date: Fri Jan 6 14:18:46 2012 -0500 Hardcode the defaults for Msg-Protect and Folder-Protect. Also fix the documentation (had the wrong value for the default for Msg-Protect). Author: Ken Hornstein Date: Fri Jan 6 14:12:13 2012 -0500 Huh, apparantly I got rid of any support for POPSERVICE over a year ago! Good riddance, I say. Author: Ken Hornstein Date: Fri Jan 6 10:48:03 2012 -0500 Garbage collect all of the builtin ftp client support. Author: Ken Hornstein Date: Fri Jan 6 10:37:38 2012 -0500 Garbage-collect MHRC (and make it the default). Author: Ken Hornstein Date: Fri Jan 6 10:36:21 2012 -0500 Garbage-collect SLOCAL_MBOX (and make it the default). Author: Ken Hornstein Date: Fri Jan 6 10:35:16 2012 -0500 Garbage-collect RPATHS support. Author: Ken Hornstein Date: Fri Jan 6 10:29:35 2012 -0500 Huh, turns out this define hasn't worked in forever ... the original changes were made to the lexer output, and silently vanished a decade ago when code was reorganized from zotnet to sbr! Author: Ken Hornstein Date: Fri Jan 6 10:22:44 2012 -0500 Remove last vestiges of #ifdef BANG Author: Ken Hornstein Date: Fri Jan 6 10:21:17 2012 -0500 Remove DBMPWD, make it the default. Author: David Levine Date: Fri Jan 6 08:55:39 2012 -0600 Added datarootdir definitions to silence warnings from configure. Author: David Levine Date: Thu Jan 5 21:36:51 2012 -0600 Fixed trivial compile warnings. Author: Ken Hornstein Date: Thu Jan 5 22:13:08 2012 -0500 Not sure why we're checking for st_blksize; it's required by POSIX and we're not even using the define! Author: Ken Hornstein Date: Thu Jan 5 22:08:23 2012 -0500 Switch the use of LOCKDIR in acconfig.h to --enable-lockdir. Author: David Levine Date: Thu Jan 5 21:00:58 2012 -0600 Merge branch 'master', remote-tracking branch 'origin' Author: Ken Hornstein Date: Thu Jan 5 13:39:47 2012 -0500 Garbage collect all of the old UCI #ifdef'd code. Author: Ken Hornstein Date: Thu Jan 5 12:26:48 2012 -0500 Update this with mh-e changes. Merge: 220dcd2 edc8d46 Author: David Levine Date: Thu Jan 5 11:14:56 2012 -0600 Feed fileproc and mhlproc from rcvdist, send, and whatnow to post. Author: David Levine Date: Wed Jan 4 21:05:45 2012 -0600 Feed fileproc and mhlproc from rcvdist, send, and whatnow to post. Author: Ken Hornstein Date: Thu Jan 5 12:05:43 2012 -0500 Bring in all of the mh-e support that is actually used to be compiled by default, and garbage collect the stuff that is not used. Author: David Levine Date: Wed Jan 4 21:05:45 2012 -0600 Feed fileproc and mhlproc from rcvdist, send, whatnow, and whom to post. Author: Ken Hornstein Date: Tue Jan 3 22:28:44 2012 -0500 Whoops, for right now we do need those signal function checks. Author: Ken Hornstein Date: Tue Jan 3 22:21:07 2012 -0500 Switch to standard autoconf macro for checking d_type field in struct dirent. Author: Lyndon Nerenberg Date: Mon Dec 26 09:19:35 2011 -0800 Remove #ifdef around use of sigsetjmp(). Author: Lyndon Nerenberg Date: Sun Dec 25 19:17:58 2011 -0800 Remove overrides for 'broken' stat macros. Remove redundant SEEK_* macro definitions. Author: Lyndon Nerenberg Date: Sun Dec 25 17:20:26 2011 -0800 Include for snprintf() prototype. Author: Lyndon Nerenberg Date: Sun Dec 25 12:23:41 2011 -0800 Nuke directory processing conditionals; use dirent.h. Author: Lyndon Nerenberg Date: Sun Dec 25 12:16:08 2011 -0800 Add back missing include of Author: Lyndon Nerenberg Date: Sun Dec 25 12:09:21 2011 -0800 Clean up process wait to use POSIX waitpid() interface. Author: Ken Hornstein Date: Tue Jan 3 22:01:07 2012 -0500 No longer check for the mkstemp() function in the mkstemp library. Author: Lyndon Nerenberg Date: Sun Dec 25 11:58:38 2011 -0800 Make use of mkstemp() unconditional (vs. mktemp(). This patch also removes the m_scratch() and m_tmpfil() functions. They have been deprecated for a while, and are no longer used in any of the code base. Author: Lyndon Nerenberg Date: Sun Dec 25 11:28:07 2011 -0800 Remove compatibility functions that are always provided by the POSIX host environment. Author: Ken Hornstein Date: Tue Jan 3 21:54:07 2012 -0500 Get rid of checking for vfork(), since we no longer use. Author: Lyndon Nerenberg Date: Sat Dec 24 18:18:22 2011 -0800 Replace with "h/arpa_ftp.h". Author: Lyndon Nerenberg Date: Sat Dec 24 18:17:10 2011 -0800 Import non-Posix for uip/ftpsbr.c. Author: Lyndon Nerenberg Date: Sat Dec 24 18:15:06 2011 -0800 Remove HAVE_ARPA_FTP_H and arpa/ftp.h references. Author: Ken Hornstein Date: Tue Jan 3 21:38:07 2012 -0500 Remove autoconf ospeed checks Author: Lyndon Nerenberg Date: Sat Dec 24 16:38:47 2011 -0800 Ignore OSPEED/ospeed in termcap. Nothing current should need this. Author: Ken Hornstein Date: Tue Jan 3 21:12:11 2012 -0500 No longer check for termio.h or termios.h Author: Lyndon Nerenberg Date: Sat Dec 24 16:15:22 2011 -0800 Collapse termio/termios/sgtty terminal interface code down to the Posix termios interface. Author: Ken Hornstein Date: Tue Jan 3 21:06:45 2012 -0500 Update configure file for removal of POSIX-mandated header files. Author: Lyndon Nerenberg Date: Sat Dec 24 15:40:48 2011 -0800 Eliminate '#ifdef HAVE_FOO' for Posix-mandated FOOs. Author: Ken Hornstein Date: Tue Jan 3 20:27:45 2012 -0500 No longer need to check for the existance of sys/utsname.h Author: Lyndon Nerenberg Date: Sat Dec 24 15:30:53 2011 -0800 Deprecate uname() in favour of (Posix) gethostname(). Author: Ken Hornstein Date: Tue Jan 3 20:20:26 2012 -0500 Sigh. I put the documentation about the -tls switch in the long description, but not in the command summary. Author: Ken Hornstein Date: Tue Jan 3 16:30:50 2012 -0500 Updated pending-release-notes Author: David Levine Date: Tue Jan 3 15:16:29 2012 -0600 Added note about cpio failing to unpack an nmh tarball. Author: Ken Hornstein Date: Tue Jan 3 15:17:54 2012 -0500 Switch to using buffered I/O when doing TLS (but only for output). Author: Ken Hornstein Date: Tue Jan 3 10:36:14 2012 -0500 Updated these files since we've finally got 1.4 out the door. Author: David Levine Date: Tue Dec 27 22:41:24 2011 -0600 Moved #endif so that lockit () is only declared with DOT_LOCKING, to avoid compile warning without it. Author: David Levine Date: Tue Dec 27 22:38:52 2011 -0600 Reworked nmh.spec to support rpmbuild from source RPM. Author: David Levine Date: Sun Dec 25 15:00:49 2011 -0600 Removed unused vmh.c and wmh.c. Author: David Levine Date: Sat Dec 24 20:28:50 2011 -0600 Changed second argument of calls to part_ok() and type_ok() from 0 to 1, to match what store_multi() in mhstoresbr.c does. A test case is below. Without this fix, the following command: mhshow -part 1.1 -form mhl.null produced no output. mhlist showed a part 1.1: msg part type/subtype size description 1231 multipart/mixed 276 1 multipart/related 107 1.1 text/plain 29 and "mhstore -part 1.1" properly stored it. With this fix, mhshow behaves properly and shows the part. Analogous behavior happened with -type text/plain. test case: 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" --NextPart_002 Content-Type: text/plain; charset="utf-8" This is the text/plain part. --NextPart_002-- --NextPart_001-- Author: David Levine Date: Sat Dec 24 19:36:32 2011 -0600 Replaced cvs with git references. I'm not sure about the cgit URL at the very end. Also removed mention of source directories that were deprecated and removed long ago. Author: David Levine Date: Sat Dec 24 09:59:45 2011 -0600 Added --with-rpmdir configure option so that user can set location of RPM build root. Author: David Levine Date: Tue Dec 13 18:33:07 2011 -0600 Added comments about source of description, etc. Author: David Levine Date: Mon Dec 12 22:50:06 2011 -0600 Replaced use of GNU make shell function with backticks. These were for the rpm target, which would most likely only be build on Linux. So they probably would have been OK, but just in case. Author: David Levine Date: Mon Dec 12 22:25:52 2011 -0600 The docs/Makefile install target didn't do anything before. Added the files that go into doc to it, and removed them from nmh.spec. nmh.spec should now require zero maintenance. Author: David Levine Date: Mon Dec 12 21:45:17 2011 -0600 Added RPM/ so that git status doesn't mention that it's an untracked file. Merge: d7f7173 bc20acd Author: David Levine Date: Mon Dec 12 21:37:47 2011 -0600 Merge branch 'master' of git.sv.nongnu.org:/srv/git/nmh Author: David Levine Date: Mon Dec 12 21:35:52 2011 -0600 Moved version number from nmh.spec to Makefile.in, to minimize maintenance for nmh.spec. Author: Ken Hornstein Date: Mon Dec 12 12:59:42 2011 -0500 Make sure to not reset hghnum (in the Maildir code) if we are incorporating mail from a POP mailbox. Author: David Levine Date: Sun Dec 11 17:03:56 2011 -0600 Added first cut at nmh.spec, along with rpm: target in Makefile.in. Author: David Levine Date: Sun Dec 11 13:44:50 2011 -0600 Removed netdb.h because we no longer distribute it. Author: David Levine Date: Sun Dec 11 10:24:20 2011 -0600 Removed unused local variables to eliminate warnings from gcc 4.6.2. Author: Ken Hornstein Date: Wed Dec 7 12:00:26 2011 -0500 Make sure to ignore the nmh dist file. Author: Ken Hornstein Date: Wed Dec 7 11:36:53 2011 -0500 Since we're now moving past 1.4, bump this. Author: David Malone Date: Wed Dec 7 10:19:40 2011 -0500 Add support to inc for incorporting email from Maildir dropboxes. Add missing #include for to bring in definitions of PF_UNSPEC. Signed-off-by: Ken Hornstein Author: Ken Hornstein Date: Wed Apr 13 10:50:49 2011 -0400 Whoops, user & port were in the wrong order so msgchk didn't work for POP connections. Author: Ken Hornstein Date: Mon Feb 21 20:44:30 2011 -0500 Updated the developer README with a few notes about the git conversion. Signed-off-by: Ken Hornstein Author: Paul Vixie Date: Mon Feb 7 14:13:54 2011 -0500 Signed-off-by: Ken Hornstein More documentation about the hooks support. Author: Peter Maydell Date: Tue Dec 21 16:50:24 2010 +0000 Clean up code in inc.c Clean up the confusing use of a variable 'i' in inc.c. The case where it was being used as 'an error occurred which means we should not truncate the mailspool' is now called 'incerr' and merged with the equivalent 'p' variable used in the POP-specific code. Cases where it was being used as a random temporary are still called 'i' but now declared with a much more restricted scope. This fixes a compilation warning for some compilers. Signed-off-by: Peter Maydell Author: Peter Maydell Date: Mon Dec 20 21:13:32 2010 +0000 Suppress tsort diagnostic waffle tsort produces waffle to standard error if it detects loops in its input. For our purposes in ordering object files this is harmless, so just send it all to /dev/null. Signed-off-by: Peter Maydell Author: Peter Maydell Date: Mon Dec 20 21:13:32 2010 +0000 Fix unused-function warnings in lex output Fix the unused-function warnings in the output of lex. In particular, we silence a warning about yyunput being static but unused by exposing it as a global function. This costs us a few hundred bytes in the binary but the other available solutions are flex-specific or more complicated. YY_NO_UNPUT used to silence this but no longer works in recent flex. On the other hand YY_NO_INPUT does work to silence warnings about input(). Signed-off-by: Peter Maydell Author: Peter Maydell Date: Mon Dec 20 21:13:32 2010 +0000 Fix used-uninitialised warning in fmt_rfc2047.c Fix a used-uninitialised warning in fmt_rfc2047.c. I don't think it can actually be used uninitialised, but the code is too complicated for the compiler to realise this. Signed-off-by: Peter Maydell Author: Peter Maydell Date: Mon Dec 20 21:13:32 2010 +0000 Fix used-uninitialised warning in new.c Fix a used-uninitialised warning in new.c by having the check_folders() routine return first=last=NULL for empty folder lists. This is a more sensible API anyway. (It would not actually have been possible for the code to try to use last while it was uninitialised, as it happens.) Signed-off-by: Peter Maydell Author: Peter Maydell Date: Mon Dec 20 21:13:32 2010 +0000 Fix crash if fnext/fprev are given an empty folder list Add a check for a NULL pointer, which stops fnext/fprev from segfaulting if given an empty folder list (for example via 'fnext -folders emptyfile'). Signed-off-by: Peter Maydell Author: Peter Maydell Date: Mon Dec 20 19:54:43 2010 +0000 Fix warning in sbr/folder_addmsg.c by code cleanup Clean up some rather oddly written code in folder_addmsg() so it is easier to understand for both humans and for the compiler (and the compiler thus stops complaining about an uninitialised variable). Signed-off-by: Peter Maydell Author: Ken Hornstein Date: Thu Dec 16 13:20:31 2010 -0500 Fix so this compiles without SASL support. Damn you, Oliver Kiddle, for finding all of the bugs I add to nmh! Author: Ken Hornstein Date: Thu Dec 16 13:11:17 2010 -0500 All of the arguments to AC_ARG_ENABLE need to be quoted, otherwise the last action doesn't make it into the configure script. Author: Ken Hornstein Date: Thu Dec 16 13:02:32 2010 -0500 Make sure we ignore config.h.in~ Author: Markus Schnalke Date: Thu Dec 16 01:36:43 2010 +0100 fix typo and clarify two sentences in mhpath man page Author: Markus Schnalke Date: Thu Dec 16 01:25:11 2010 +0100 improve mhparam man page Author: Oliver Kiddle Date: Thu Dec 16 01:23:16 2010 +0100 fix badly formatted code found by Markus Schnalke Author: Scott Snyder Date: Wed Dec 15 22:17:52 2010 +0100 propagate and check return status of close() in slocal Author: Markus Schnalke Date: Wed Dec 15 22:02:30 2010 +0100 document msg parameter to folder Author: Oliver Kiddle Date: Tue Dec 14 18:04:01 2010 +0100 switches need to be renumbered following removal of some switches so, e.g. inc -version was not working Author: Ken Hornstein Date: Thu Dec 9 15:29:29 2010 -0500 Massive garbage collection. Remove functionality for APOP, RPOP, all NNTP support (including bboards) and MPOP. Author: David Levine Date: Wed Dec 8 14:36:36 2010 -0600 * uip/whatnowsbr.c: enforce requirement of at least one file argument to attach command. Author: David Levine Date: Wed Dec 8 10:47:03 2010 -0600 man/send.man: added name= portion to Content-Type headers to reflect 2006-10-24 change to uip/sendsbr.c. That change allowed mhstore to use the (file)name when extracting attachments. Author: Ken Hornstein Date: Fri Dec 3 15:23:11 2010 -0500 Remove RCS keywords, since they no longer work after git migration. Author: Ken Hornstein Date: Thu Dec 2 21:04:30 2010 -0500 Whoops, forgot to bracket the calls for TLS shutdown with a #ifdef TLS_SUPPORT Author: Ken Hornstein Date: Thu Dec 2 20:37:54 2010 -0500 Update for git conversions (and cleanup of autogen.sh to use autoreconf) Author: Ken Hornstein Date: Thu Dec 2 18:03:22 2010 -0500 Change configure.in to emit a warning when an argument is given to --with-cyrus-sasl. Author: Ken Hornstein Date: Sun Nov 21 22:19:51 2010 +0000 Fix the test for sasl.h to look in the correct place. Author: Ken Hornstein Date: Fri Nov 19 20:13:39 2010 +0000 (Minor) cleanup of some of the autoconf code with respect to the handling of compiler flags for SASL, and also rototill (and simplify) the autoconf handling for the same. Add TLS support for the SMTP MTA. Author: Peter Maydell Date: Fri Nov 12 23:28:26 2010 +0000 man/slocal.man: fix formatting error that meant a subsection heading wasn't displayed as such. Followon cleanup: since the new heading is too wide to fit in the margin, tidy the margin to 4 characters wide so we are consistent with how all the headings are displayed. Author: Peter Maydell Date: Wed Nov 10 22:26:07 2010 +0000 configure.in: add a level of expansion for mandir when printing the end-of-configure install path summary. Author: Peter Maydell Date: Tue Nov 9 21:33:22 2010 +0000 man/rmm.man: fix error in synopsis: the option is [no]unlink, not [no]link. Author: Peter Maydell Date: Fri Nov 5 22:06:10 2010 +0000 Silence a (harmless) uninitialized variable warning. Author: David Levine Date: Tue Aug 31 15:00:53 2010 +0000 * uip/.cvsignore: added "new". Author: Earl Hood Date: Sat Feb 6 07:47:38 2010 +0000 #ifdef AI_ADDRCONFIG since older IPv4-only systems may not define this flag, causing files that use to not compile. Author: Earl Hood Date: Sat Feb 6 07:45:47 2010 +0000 Fixed variable declaration so older compilers will not complain. I.e. Older compilers may not support C99, so variables must be declared at the beginning of a block. Author: Earl Hood Date: Thu Feb 4 01:39:21 2010 +0000 * Bug #15213, #18635: The use of the insecure m_scratch() and m_tmpfil() functions have been replaced by m_mktemp() or m_mktemp2() functions (defined in sbr/m_mktemp.c). The new functions use mkstemp() to securely create temporary files to avoid the numerous race conditions that exist with the old functions. This does assume that mkstemp() is available. Unsure if we need to create an alternative implementation if mkstemp() is not available. More information about new temp file functions in m_mktemp.c, including the support for MHTMPDIR, TMPDIR, and TMP envvars. NOTE: The files sbr/m_scratch.c and sbr/m_tmpfil.c should be removed. Until more testing verifies changes to support new functions have not broken functionality, the files are be left in the tree, but comments have been added stating the functions in them should not be called. Author: Earl Hood Date: Wed Feb 3 05:56:56 2010 +0000 * mts/smtp/smtp.c: added SASL support if mts configuration setting is set to "sendmail". This is useful if sendmail conf option is to a custom script that creates a proxy connection to an smtp server. * sbr/mts.c: added support for MHMTSCONF and MHMTSUSERCONF envvars. The former specifies an alternative system mts.conf to use. The later specifies a user-specific mts.conf to use. This one will be read after the system conf, so the user's conf only needs to set options they want to override. The MHMTSUSERCONF allows a user to set personal alternative mail submission methods w/o affecting other users on the system. * uip/whom.c: added SASL-based options so address checking can work against a server that requires SASL. Author: David Levine Date: Wed Dec 30 01:42:45 2009 +0000 * uip/mhlistsbr.c, uip/mhlsbr.c, uip/picksbr.c: cast pointers to unsigned long before casting to unsigned int to avoid warnings on 64-bit about casting from pointer to int of different size. Author: David Levine Date: Wed Dec 30 01:41:47 2009 +0000 * uip/new.c: cast folder_len to int to avoid warning on 64-bit about passing a size_t to an int conversion specifier. Author: David Levine Date: Fri Dec 25 14:47:39 2009 +0000 * uip/inc.c: gcc 4.4.1 noticed that maildir could have been used before initialization. In fact, if that code was ever reached, maildir would never have been initialized. It's in an adios call, so replaced with NULL. Author: David Levine Date: Mon Dec 21 17:18:04 2009 +0000 * mts/smtp/smtp.c: In sm_auth_sasl (), removed zeroing of sasl_inbuffer because it could be used in sm_fget (). Also, removed allocation of sasl_inbuffer because that was done in either smtp_init () or sendmail_init (). Author: Josh Bressers Date: Mon Jan 26 13:38:13 2009 +0000 Remove duplicate sm_fgetc() declaration Author: Ken Hornstein Date: Wed Jan 21 19:38:36 2009 +0000 Fix warning in getaddrinfo() call. Add missing support for -port in whatnow. Make sure the SASL input buffer is allocated when using the sendmail mts. Author: Eric Gillespie Date: Sun Jan 18 04:48:42 2009 +0000 * etc/mhn.defaults.sh: Never try to make mhshow start xterm. Author: Eric Gillespie Date: Sat Jan 17 16:53:07 2009 +0000 Note 'new' commands. Author: Eric Gillespie Date: Sat Jan 17 16:47:29 2009 +0000 * test/runtest, test/tests/inc/test-deb359167, test/tests/inc/test-eom-align, test/tests/manpages/test-manpages: Load common.sh via absolute path, otherwise some /bin/sh (e.g. dash) can't load it. * uip/Makefile.in, uip/new.c, test/tests/new/test-basic: Add new program, and fn/fp/unseen symlinks. * test/{runtest,setup-test}: Move MH profile under Mail directory so each test script will have its own to muck with, if needed. * h/Makefile.in, h/crawl_folders.h, sbr/Makefile.in, sbr/crawl_folders.c, uip/folder.c: Extract the folder crawling code from folder.c into new crawl_folders function, using a callback to assemble the folder info in folder.c. Drop compare function and use strcmp instead. Rename addfold and addir to add_folder and add_children (add dir vs. add folder? confusing names). Author: Ken Hornstein Date: Fri Jan 16 15:48:09 2009 +0000 Move freeaddrinfo() to inside of our loop; this prevents a memory leak and also prevents it from being called with a NULL pointer. Author: Ken Hornstein Date: Fri Jan 16 02:28:54 2009 +0000 Massive overhaul of networking code. Changes: - All networking interfaces now converted to new APIs (getaddrinfo() and the like). All networking now supports IPv6 (with the exception of the built-in FTP client). - SASL security layers are now supported for SMTP. - Command-line and profile-based selection of the SMTP server and port. Author: Peter Maydell Date: Fri Dec 26 21:54:19 2008 +0000 * sbr/m_getfld.c: fix two bugs which could cause us to walk off the beginning of the stdio or prefix-string buffer when checking for presence of the end-of-message delimiter in some situations. This might cause inc to dump core if you were unlucky. (This was Debian bug 359167.) * test/tests/inc/{md5sums,msgheader.txt,test-deb359167, test-eom-align,fromline.txt,filler.txt,deb359167.mbox}: new tests both for the specific problem and to try to check various alignments of the eom string with the stdio buffer ending. * test/common.sh: Added some functions for doing progress indicators. Author: Peter Maydell Date: Fri Dec 26 16:32:07 2008 +0000 test/common.sh: new file for common utility functions for the test scripts. Moved findprog out of manpage test script into this new file. Author: Peter Maydell Date: Thu Dec 25 23:30:33 2008 +0000 test/runtest: automatically run setup-test if it hasn't already been done. Improve error handling in test script with 'set -e'. Author: David Levine Date: Thu Oct 23 18:38:22 2008 +0000 * h/mh.h: raised NAMESZ from 128 to 999. RFC 2822 limits line lengths to 998 characters, so a header name can be at most that long. m_getfld limits header names to 2 less than NAMESZ, which is fine, because header names must be followed by a colon. Add one for terminating NULL. Author: David Levine Date: Thu Oct 23 18:14:52 2008 +0000 * sbr/m_getfld.c: in warning message, use NAMESZ-2 instead of NAMESZ-1 bytes because the message says "exceeds", not "is greater than or equal to". Author: David Levine Date: Thu Oct 23 16:45:36 2008 +0000 * docs/MAIL.FILTERING: added note on removing procmail -f or -r options to try to suppress generation of a "From " line on incoming messages. Author: Eric Gillespie Date: Tue Aug 19 04:36:42 2008 +0000 +mhn.defaults.sh.cfg Author: Eric Gillespie Date: Thu Aug 14 19:47:29 2008 +0000 * test/setup-test: Don't run autogen.sh unless needed. Build in a blddir under the temporary directory so as not to interfere with whatever the developer may be doing in the source directory. If the temporary directory already exists, rebuild and install it. Author: Eric Gillespie Date: Thu Aug 14 06:19:08 2008 +0000 This is what happens with last-minute "safe" improvements: actually point chset to something in the new merged InitText! Author: Eric Gillespie Date: Thu Aug 14 01:50:45 2008 +0000 * sbr/ambigsw.c: Send print_sw output to stderr. This avoids strange problems with scan `pick -bogus`, not to mention being nicer anyway. * sbr/getans.c, sbr/print_help.c, uip/msh.c: Send print_sw output to stdout. * h/prototypes.h, sbr/print_sw.c (print_sw): Add FILE * argument and send output there rather than to stdout. * test/tests/pick/test-stderr: Add test that error messages don't end up going to stdout. Author: Eric Gillespie Date: Thu Aug 14 01:31:11 2008 +0000 * uip/pick.c: Ensure valid sequence name as soon as we parse it from command, instead of searching the messages first. Author: Eric Gillespie Date: Thu Aug 14 01:28:56 2008 +0000 * uip/pick.c: Print matching messages immediately, instead of waiting until the very end to print anything. Author: Eric Gillespie Date: Thu Aug 14 01:11:12 2008 +0000 * uip/Makefile.in, uip/popi.c: Remove popi.c, which has been dead since PatchSet 257 (2000/06/12 11:07:34 UTC). Author: Eric Gillespie Date: Thu Aug 14 00:56:38 2008 +0000 * h/mhparse.h: Move interfaces also used by mhbuildsbr.c here from mhparse.c. * uip/Makefile.in (mhbuild): Build with mhparse.o. * uip/mhbuildsbr.c: Drop the duplication of mhparse.c. * uip/mhbuild.c, uip/mhlist.c, uip/mhn.c, uip/mhshow.c, uip/mhstore.c, uip/mhtest.c: Drop check swdeclaration, which is now in mhparse.h. * uip/mhparse.c: Move some declarations to mhparse.h, and remove 'static' from the definitions here. (get_ctinfo): Take magic mhbuild support from mhbuildsbr.c's copy, and adapt callers. (incl_name_value, extract_name_value): Move from mhbuildsbr.c to support get_ctinfo change). (get_content, open7Bit): Add Content-Disposition support, added to mhbuildsbr.c's copy in mhbuildsbr.c r1.12 (PatchSet 549). (InitText): Default to CHARSET_UNSPECIFIED instead of "US-ASCII", as mhbuildsbr.c's copy did. Explain termproc. (openBase64, openQuoted, open7Bit): Fix comment from r1.5: suffixes, not prefixes. (openMail): Explain showproc. * test/tests/mhshow/test-cte-binary: Add test for Content-Transfer-Encoding: binary (Debian #136976). * test/tests/mhbuild/test-forw: Add an mhbuild test, testing forw with and without RFC-934 mode. More mhbuild tests would be nice. Author: Eric Gillespie Date: Wed Aug 13 23:59:56 2008 +0000 Oops, meant to use $failed (number of failed checks) as the exit code. Author: Eric Gillespie Date: Wed Aug 13 23:32:03 2008 +0000 Add descriptive headers, as other tests have. Author: Eric Gillespie Date: Wed Aug 13 18:27:36 2008 +0000 * test/tests/bad-input/test-header: Add test for it. * sbr/m_getfld.c: If we reach the end of the line without finding a ':' when parsing a header field, treat that line as the beginning of the body rather than blowing up. These messages are usually spam, but it's nice to be able to at least scan them. Author: Eric Gillespie Date: Wed Aug 13 01:01:12 2008 +0000 * test/tests/mhshow/test-qp: Test various valid and invalid escape sequences. * uip/mhparse.c (openQuoted): Simplify the decode-or-show for loop by peeking ahead to the next byte(s) when encountering '=', and just let invalid escape sequences through as literals (fixes bug #15245). Author: Eric Gillespie Date: Wed Aug 13 01:00:20 2008 +0000 Ignore test-temp-dir. Author: Paul Fox Date: Tue Aug 12 21:01:30 2008 +0000 add one more hint for developers, to explicitly point at docs/README.developers Author: Peter Maydell Date: Tue Aug 12 18:04:29 2008 +0000 autogen.sh (new file): add script for running the GNU autotools in the right order. Mention and use new script in the appropriate places. Author: Eric Gillespie Date: Fri Aug 8 23:45:24 2008 +0000 * sbr/discard.c, sbr/m_getfld.c, uip/scansbr.c: Add support for DragonFlyBSD stdio (from NetBSD pkgsrc). Author: Eric Gillespie Date: Fri Aug 8 04:45:05 2008 +0000 s/ls/cd/ in comment (probably pasted from test-ls) Author: Peter Maydell Date: Tue Aug 5 21:06:00 2008 +0000 uip/folder.c: chdir(nmhdir) in main rather than in dodir, which is called many times. Drop the chdir in get_folder_info, which served no purpose at all. If struct stat has d_type (BSD), use that to skip processing (strcmp, stat, and so on) of message files, mostly undoing the slow-down from the last change. Plus autoconf machinery to detect d_type field. Patch from Eric Gillespie. Author: Peter Maydell Date: Tue Aug 5 19:09:03 2008 +0000 Dump hacky overoptimisation in addir -- it doesn't actually get the case of symlinks to directories right. Patch from Eric Gillespie. Author: Peter Maydell Date: Tue Aug 5 19:05:23 2008 +0000 Simplify dodir/addir/addfold (patch from Eric Gillespie) Author: Peter Maydell Date: Sun Aug 3 18:47:56 2008 +0000 bug #23319: rework the way we handle the working directory when invoking the user's shell, so that we don't have issues when the cwd contains a space or shell special character. Author: Peter Maydell Date: Sun Aug 3 18:45:34 2008 +0000 test/setup-test: use 'set -e' so we stop on compile failure. Configure --enable-debug for convenience in debugging. Author: Peter Maydell Date: Sun Aug 3 15:19:53 2008 +0000 Add protective 'do { ... } while (0)' wrappers to multistatement macros Author: Peter Maydell Date: Sun Aug 3 15:14:23 2008 +0000 Bug #23436: fix some minor manpage syntax errors and add a test which runs groff over them and checks that no warnings are emitted. Author: Peter Maydell Date: Sun Aug 3 15:13:34 2008 +0000 Allow tests to indicate that they have been skipped by printing their own message and returning with exit status 120. Author: Peter Maydell Date: Sun Aug 3 13:59:19 2008 +0000 Ignore editor backup files Author: Peter Maydell Date: Sun Aug 3 13:54:37 2008 +0000 etc/replcomps, etc/replgroupcomps: Trim trailing whitespace from Subject field (patch from Eric Gillespie) Author: Peter Maydell Date: Sun Aug 3 13:32:17 2008 +0000 When doing an if-test on the result of a function which returns a string result, check whether the string is non-empty (as the documentation says we do). Previously we were always testing the integer 'value'. Author: Josh Bressers Date: Fri Jul 25 01:07:39 2008 +0000 * test/setup-test: Run 'make clean' before building Author: Josh Bressers Date: Fri Jul 25 00:11:53 2008 +0000 * test/runtest: cat test-temp-dir only once. Destroy and create test Mail hierarchy here, so each test has its own independent test data. * test/setup-test: Drop needless pushd/popd, which don't exist in sh anyway. Don't use aclocal, which is part of automake. Don't create Mail hierarchy here (see test/runtest). * test/tests/folder/test-create, tests/folder/test-total: Drop unused BINDIR. * tests/pick/test-pick: Remove failing no-op test. * test/tests/scan/test-scan: Write expected and actual output to files and diff them. This way, if the output differs, diff provides the FAILing exit code and shows the differences. Author: Josh Bressers Date: Fri Jun 13 00:11:49 2008 +0000 * man/repl.man, etc/mhl.reply: Add an attribution line when replying to messages. Author: Josh Bressers Date: Thu Jun 12 23:29:16 2008 +0000 Remove an accidentally committed file Author: Peter Maydell Date: Mon Jun 2 22:37:01 2008 +0000 When building on gcc, use noreturn attribute on adios and the various done functions. Author: Peter Maydell Date: Mon Jun 2 22:05:11 2008 +0000 Back out previous, completely broken, change (due to a foulup I was compiling a different tree to the one I was committing to CVS). Author: Peter Maydell Date: Mon Jun 2 21:49:07 2008 +0000 If we're compiling with gcc, mark adios() as never returning (better code and fewer spurious 'uninitialized variable) warnings) Author: Peter Maydell Date: Sun Jun 1 16:50:22 2008 +0000 Update bit of docs about release announcements. Author: Peter Maydell Date: Thu May 22 10:37:55 2008 +0000 Don't use MB_CUR_MAX if we aren't compiled with multibyte support. Author: Peter Maydell Date: Thu May 22 10:21:48 2008 +0000 Factor out common code for writing ls shell command. Rework its length checking so it doesn't rely on the return value of sprintf(), for the benefit of SunOS 4. Author: Peter Maydell Date: Wed May 21 18:05:49 2008 +0000 Don't rely on realloc() to follow POSIX in handling a NULL pointer Author: Peter Maydell Date: Wed May 21 17:16:44 2008 +0000 Add some table size declarations for the benefit of elderly lexes with small defaults (eg SunOS 4) Author: Peter Maydell Date: Tue May 20 19:04:57 2008 +0000 Update comment now we don't use lex -o. Author: David Levine Date: Sun May 18 13:56:58 2008 +0000 * sbr/addrsbr.c: removed "err" from conditional, because gcc correctly warned that it would always evaluate as true. It's the address of a static array. Author: Oliver Kiddle Date: Fri May 16 15:31:26 2008 +0000 don't use $< in target rules in makefiles, as POSIX says it's only defined in inference rules Author: David Levine Date: Tue May 13 02:39:04 2008 +0000 * configure.in, INSTALL: if --enable-masquerade is not specified to configure, enable all supported masquerade forms. This allows users to masquerade with the default configuration. That seems to be more worthwhile now than trying to prevent users from using it, especially with single-user installations or those where a user can edit etc/mts.conf. Author: Peter Maydell Date: Sun May 4 20:58:35 2008 +0000 bug #23167: sbr/ruserpass.c (ruserpass): make bad permissions on .netrc be an instantly fatal error. Previously we returned an error value; however, no caller was checking it. So now ruserpass() has a void return type. Author: Peter Maydell Date: Sun May 4 16:09:08 2008 +0000 * bug #23163: various minor fixes for the benefit of older Unixes (specifically SunOS 4): reintroduce strerror() substitute implementation; provide memmove() substitute implementation * bug #23163: fix broken 'build outside source directory' feature * bug #23162: sbr/dtime.c: fix stray HAVE_TM_GMTOFF that wasn't updated to the new macro name. Author: Peter Maydell Date: Wed Apr 30 18:47:02 2008 +0000 Provide SASL_CB_AUTHNAME callback (avoids problem with wrong username being sent in some situations) Author: Peter Maydell Date: Tue Apr 29 21:05:30 2008 +0000 Correct various places in smtp.c where the reply string might not have been correctly NUL-terminated. Includes a fix for a particularly nasty and long standing screwup where the buffer length counting in smhear() was totally broken for continued lines from the server. Author: Peter Maydell Date: Tue Apr 29 20:59:04 2008 +0000 Fix SASL issue properly, by making sm_rrecord() and thus sm_hear() set the length of the reply string correctly (the SASL libraries now care if you pass in the wrong length). Author: Peter Maydell Date: Tue Apr 29 20:53:33 2008 +0000 Revert previous SASL fix (wrong approach) Author: Peter Maydell Date: Tue Apr 29 17:04:38 2008 +0000 Cope with sasl_decode64() returning SASL_CONTINUE as well as SASL_OK. Author: Peter Maydell Date: Mon Apr 28 21:13:53 2008 +0000 Add remark about how to update the homepage. Author: Peter Maydell Date: Sun Apr 27 20:58:50 2008 +0000 Update some of the 'how to do a release' documentation Author: Peter Maydell Date: Sun Apr 27 20:55:28 2008 +0000 Up version string to 1.3-dev for the CVS trunk. Author: Peter Maydell Date: Sun Apr 27 19:54:37 2008 +0000 Use hyphen, not plus (corresponding to previous RCx naming convention) Author: Peter Maydell Date: Sun Apr 27 19:44:58 2008 +0000 Bump version number, date for release of 1.3 RC1 Author: Oliver Kiddle Date: Fri Apr 11 14:12:54 2008 +0000 move most remaining macros out of acconfig.h which is an obsolete feature of autoconf Author: Peter Maydell Date: Sat Apr 5 19:04:41 2008 +0000 * bug #18655: fix use of admonish() for a fatal error (should be adios(); only actual effect would be wrong exit code). Thanks to Craig Leres for spotting this. Author: Peter Maydell Date: Sat Apr 5 18:41:37 2008 +0000 Bug #20028 (Debian bug 399271): fix code assuming that pointer differences were 32 bits -- thanks to Dean Gaudet for the patch. Author: Josh Bressers Date: Fri Jan 25 21:00:42 2008 +0000 * uip/mhshowsbr.c (show_all_messages): Be more generous when parsing multipart messages. Author: Joel Reicher Date: Thu Nov 8 02:28:38 2007 +0000 Insert types for args of some function pointers to improve type checking. Author: Joel Reicher Date: Sun Nov 4 11:54:32 2007 +0000 Return type of (*done)() changed to void. default_done() replaced by exit(). All dead code "return 1" lines removed from *_done()s and replaced by explicit "return 1" following done() calls in main()s (they should never be reached). This should make cleaning up program termination structures easier. Author: Joel Reicher Date: Sun Nov 4 08:52:17 2007 +0000 Refactor cts pointer and free()ing on abnormal exit of associated list into mhfree.c, eliminating duplication. Author: Joel Reicher Date: Sun Nov 4 04:47:17 2007 +0000 Change link-time overriding of done() to run-time reassigning of equivalent (*done)(). This should make changing the return type of done and the rationalisation of exit code easier. Author: Bill Wohler Date: Mon Sep 24 07:02:03 2007 +0000 The MH web site is now http://rand-mh.sourceforge.net/ and the MH book is now at http://rand-mh.sourceforge.net/book/. Changed Questions 1.02 ...current version? mailutils 1.2 1.03 Where can I get MH? Debian 4.0 nmh 1.1-RC4, update links, mu 1.2 1.04 ...references for MH? Refer to SourceForge 1.06 How...print a MH manual? Refer to SourceForge 2.17 How...build MH on a Mac? Use fink 4.05 ...tools to archive MH? Mention swish++, mairix, and namazu Author: Josh Bressers Date: Tue Aug 21 21:19:39 2007 +0000 * Red Hat Bug #253342: inc.c, utils.c, utils.h: When inc is run with the -silent flag, don't exit(1) for no apparent reason. Author: Peter Maydell Date: Sun Apr 29 22:57:36 2007 +0000 Rename functions to avoid clash with C library exp2(). Author: Peter Maydell Date: Sun Apr 29 22:34:04 2007 +0000 Suppress 'uninitialised variable' warning. Author: Peter Maydell Date: Sun Apr 29 22:05:02 2007 +0000 On Linux, define _GNU_SOURCE so that GNU libc exposes the wcwidth() prototype in wchar.h. Author: Peter Maydell Date: Sun Apr 29 22:01:04 2007 +0000 Change name of internal function to avoid potential conflicts with GNU libc's getline() function. Author: Peter Maydell Date: Sun Apr 29 20:49:32 2007 +0000 Minor rearrangement so variables/functions used only if !HAVE_LIBLOCKFILE are also declared only in that case. Author: Peter Maydell Date: Sun Apr 29 19:36:14 2007 +0000 For gcc, make the default CFLAGS include -Wno-pointer-sign if the compiler recognises it. gcc 4 now by default produces a large volume of these warnings, which I believe are probably spurious and definitely a lot of work to go through and fix. So we suppress them for now so that the other warnings are more easily visible. Author: Joel Reicher Date: Tue Apr 17 04:53:54 2007 +0000 buffer is compared with cp, and so needs to be changed to unsigned too. Author: Josh Bressers Date: Tue Apr 17 01:02:08 2007 +0000 Initial checkin of a testsuite Author: Joel Reicher Date: Fri Apr 13 11:53:08 2007 +0000 Change all chars being passed to the ctype macros (isalph(), etc.) to be unsigned chars, following through to change any other types as necessary (e.g. comparison between two pointers). Not all chars have been changed to unsigned chars; just those that were in danger of being sign extended when passed to the int-taking ctype macros. Author: Joel Reicher Date: Tue Apr 10 22:12:26 2007 +0000 We're not using the .Bu macro anymore. Author: Joel Reicher Date: Tue Apr 10 06:13:27 2007 +0000 Fix for bug #11139: mhl -form mhl.reply omits '> ' on some lines. putcomp() was assuming only the first call on the body had the buffer beginning at the start of a line. Author: Joel Reicher Date: Tue Apr 10 03:32:48 2007 +0000 Application of patch #5218: patch for bug #9742. Fixes a typo in the size arg of snprintf(). mhlist output which used to have incorrect lines such as 1.2 multipart/mixed 772 1.21 text/plain 9 1.22 multipart/mixed 162 now have the correct 1.2 multipart/mixed 772 1.2.1 text/plain 9 1.2.2 multipart/mixed 162 Author: Peter Maydell Date: Wed Mar 21 00:21:10 2007 +0000 bug #18630, #18631, #18632, #18634: various patches from Craig Leres fixing error message argument problems. Author: Peter Maydell Date: Wed Mar 21 00:18:19 2007 +0000 bug #15212: remove configure test for broken AT&T vi. This test was broken and unfixable. Support for manually defining ATTVIBUG remains. Author: Josh Bressers Date: Tue Jan 16 02:08:10 2007 +0000 Add a missing header file Author: Joel Reicher Date: Sun Nov 5 13:20:46 2006 +0000 Changed bold "-all" to unbolded "all". It's a reserved msgs word, not a flag. Author: David Levine Date: Tue Oct 24 14:31:40 2006 +0000 * uip/sendsbr.c: with attachformat values of 1 or 2, add name= portion to Content-Type header. This makes them consistent with attachformat value 0. And it allows mhstore to use that (file)name when extracting attachments. Author: Josh Bressers Date: Sun Aug 27 01:19:39 2006 +0000 * configure.in: If we're not using dotlocking, there is no need to set inc sgid. Author: Joel Reicher Date: Sun Jun 4 08:37:24 2006 +0000 Fixed bug introduced when changing from check_folder() to new create_folder() function. The folder name needed to be expanded to an absolute path first. Similar things may have happened with other conversions. Author: Joel Reicher Date: Thu Apr 27 12:00:28 2006 +0000 Created pluspath function to check for '+' prefix and change flag for path() appropriately. This eliminates some duplicate prefix processing, but not all. The path functions need to be restructed; this is the first step. Author: Joel Reicher Date: Mon Apr 24 07:10:03 2006 +0000 ssequal() does not check for a substring, but for a prefix, so added a comment to this effect. If this is sufficient, the function body should remain unchanged but the name and comments should be modified. If not, then the function needs to be corrected. Author: Paul Fox Date: Sat Apr 22 16:33:48 2006 +0000 fixes case where a very long character-class range (128 or more characters) causes negative indexing into pattern string. Author: Joel Reicher Date: Sun Apr 16 06:47:59 2006 +0000 Fixed a typo. Author: Joel Reicher Date: Fri Apr 14 14:10:15 2006 +0000 Created function open_form() to open form file or fallback to default components file, with error handling. Replaced duplicated code with call to this function. Author: Joel Reicher Date: Fri Apr 14 08:42:04 2006 +0000 Fixed a couple of typos. Author: Joel Reicher Date: Fri Apr 14 08:21:35 2006 +0000 Sanitised some dodgy homedir finding code, but it still might not make sense. Author: Joel Reicher Date: Fri Apr 14 07:54:26 2006 +0000 Get rid of some trivial warnings; unused variables, ambiguous if-else, missing headers. Author: Joel Reicher Date: Thu Apr 13 14:24:41 2006 +0000 Make print_aka() and print_usr() static. They're not used outside ali.c. Author: Joel Reicher Date: Tue Apr 11 14:09:11 2006 +0000 Created app_msgarg() (append message arg) and a simple resizable array struct to go with it that do almost exactly what the code they've replaced was doing. Replaced this (duplicated) code in many files with a call to app_msgarg(). Author: Joel Reicher Date: Tue Apr 11 05:48:43 2006 +0000 Completing the .cvsignore list(s). Author: Joel Reicher Date: Sun Apr 9 14:06:31 2006 +0000 Fixed a small typo. Author: Paul Fox Date: Fri Mar 31 15:14:49 2006 +0000 this commit: - adds range support to character classes - fixes out-of-bounds references to the case-folding array when doing case comparisons for 8-bit message text - makes character classes as case tolerant as the rest of the pick regexp machine. (where lowercase chars in patterns should match uppercase in the text.) - fixes an uninitialized pointer warning, which might actually have been a real bug Author: David Levine Date: Thu Mar 30 22:19:50 2006 +0000 * uip/sendsbr.c: with attachformat values of 1 or 2, only generate Content-Disposition headers for MIME attachments, not for the message contents themselves. Microsoft Outlook Build 10.0.6626, at least, doesn't show the message contents if they have Content-Disposition. Author: Bill Wohler Date: Fri Mar 10 09:00:20 2006 +0000 Changed Questions 1.03 Where can I get MH? nmh 1.2 Author: Bill Wohler Date: Fri Mar 10 06:58:28 2006 +0000 Since faqs.org appears to be moribund, I'm now using my site as the official location of the MH FAQ. I added some missing quotes in various places, so now Emacs highlighting works better. New Questions 5.26 How do I fix a bogus In-Reply-To or missing References field? Changed Questions 1.02 current version? nmh 1.2 1.04 references for MH? New FAQ official site. MH-E manual URL 5.15 make sense of replcomps? Use 1.1 version Author: Josh Bressers Date: Thu Mar 9 19:51:13 2006 +0000 * sbr/fmt_rfc2047.c (decode_rfc2047): Don't close the iconv descriptor if it isn't valid. Author: Josh Bressers Date: Wed Mar 8 12:14:15 2006 +0000 * (mh_strcasecmp): Rename the private strcasecmp function to mh_strcasecmp. Author: Oliver Kiddle Date: Sun Mar 5 14:48:05 2006 +0000 and close iconv handle if encoded block empty Author: Oliver Kiddle Date: Sun Mar 5 14:38:23 2006 +0000 don't try to malloc 0 bytes if an RFC2047 encoded block is empty Author: Peter Maydell Date: Sat Mar 4 22:14:18 2006 +0000 Install scripts with INSTALL_SCRIPT so INSTALL_PROGRAM can be set to 'install -s' without it causing the installation of the scripts to fail. Author: David Levine Date: Sat Feb 25 14:14:06 2006 +0000 * uip/sendsbr.c: replaced st_mtim with st_mtime, that's what it should have been. Added #include of h/tws.h to pick up dtime() prototype. Author: David Levine Date: Tue Feb 21 04:13:06 2006 +0000 Replaced second line of Content-Tyhpe of -attachformat 0 example. Author: David Levine Date: Tue Feb 21 03:58:31 2006 +0000 * h/mh.h, h/prototypes.h, uip/mhbuildsbr.c, uip/send.c, uip/sendsbr.c, uip/viamail.c, uip/whatnowsbr.c, man/send.man: added -attachformat switch to send, to support alternate MIME header contents when using -attach. See send man page for description. Author: David Levine Date: Tue Feb 21 03:51:53 2006 +0000 * man/mhbuild.man: wrapped one appearance of "Content-Disposition" with quotes, to be consistent with others. Author: Josh Bressers Date: Tue Feb 21 01:11:51 2006 +0000 * h/utils.h, sbr/utils.c, uip/flist.c, uip/folder.c: Move duplicate function num_digits into utils.c Author: Josh Bressers Date: Tue Feb 21 01:05:24 2006 +0000 Add missing create_folder prototype. Author: Josh Bressers Date: Mon Feb 20 03:09:07 2006 +0000 * sbr/m_draft.c, sbr/utils.c, uip/folder.c, uip/inc.c, uip/mhstoresbr.c, uip/popi.c, uip/refile.c: Add create_folder() function, replacing duplicate code during folder creation. Author: David Levine Date: Sat Feb 18 16:26:37 2006 +0000 Added support for optional Content_Disposition header in mhbuild directive.s Author: David Levine Date: Sun Feb 12 18:06:44 2006 +0000 Added RFC2183 to reference of RFC1806 for Content-Disposition header. Author: David Levine Date: Tue Jan 31 02:50:57 2006 +0000 Added -nocontentid (and -contentid, for symmetry) switch to mhbuild. This allows users to disable generation of the Content-ID: header in MIME messages, in order to placate broken version(s) of Outlook. Author: Oliver Kiddle Date: Sun Jan 29 19:34:42 2006 +0000 remove trailing newlines from components to fix bug with spaces at the end of Subject/References in replies Author: Oliver Kiddle Date: Wed Jan 18 18:08:16 2006 +0000 use AS_HELP_STRING for formatting help messages Author: Oliver Kiddle Date: Wed Jan 18 17:07:28 2006 +0000 add autoconf magic to support old systems that don't support multibyte charsets Author: Oliver Kiddle Date: Wed Jan 18 16:43:27 2006 +0000 fix bug with insertion of newline being wrong if the num function was used at the end of the format buffer Author: David Levine Date: Wed Jan 18 00:09:00 2006 +0000 Fixed make_bcc_file () to use contents of From: in draft, if draft_from masquerade flag is enabled. Author: Oliver Kiddle Date: Tue Jan 17 18:06:58 2006 +0000 more robust multi-byte/column support for field widths restore right justification feature Author: Josh Bressers Date: Mon Jan 16 17:07:14 2006 +0000 * uip/post.c, uip/spost.c: Move the uptolow macro from spost.c to post.c where it is needed. Author: Josh Bressers Date: Mon Jan 16 12:42:11 2006 +0000 * sbr/fmt_scan.c: Add the missing wchar.h include Author: Oliver Kiddle Date: Mon Jan 16 10:40:32 2006 +0000 *** empty log message *** Author: Oliver Kiddle Date: Mon Jan 16 10:00:46 2006 +0000 remove remnants of code for MMDF Author: Oliver Kiddle Date: Mon Jan 16 09:55:24 2006 +0000 multiply buffer size by MB_CUR_MAX so multi-byte chars fit Author: Josh Bressers Date: Sun Jan 15 02:52:12 2006 +0000 * sbr/fmt_scan.c:PUTSF() Fix an off by one formatting issue. Author: Josh Bressers Date: Sun Jan 15 02:29:38 2006 +0000 * sbr/fmt_scan.c: Turn the PUTSF macro into a function capable of handling multi column characters. Author: Josh Bressers Date: Sat Jan 7 15:22:19 2006 +0000 * Remove sbr/strerror.c -- strerror(3) is defined in C89. Author: Josh Bressers Date: Fri Jan 6 21:51:43 2006 +0000 * patch #3968: Move the add() function from its own file (add.c) and into utils.c. There was also a duplicate add() function in mf.c which has been removed. Author: Josh Bressers Date: Wed Jan 4 02:10:25 2006 +0000 * mh_xmalloc(), mh_xrealloc(), pwd(): Add comments describing the purpose of the function. Author: Josh Bressers Date: Tue Jan 3 01:08:33 2006 +0000 Remove sbr/pwd.c file, moving the pwd() function into sbr/utils.c. Author: Josh Bressers Date: Mon Jan 2 03:25:18 2006 +0000 * patch #3967: Create a mh_xrealloc function to prevent mistakes when calling realloc. Author: Josh Bressers Date: Mon Jan 2 03:17:41 2006 +0000 * patch #3966: Create a mh_xmalloc function to prevent mistakes when calling malloc. Author: Peter Maydell Date: Sat Dec 24 17:53:26 2005 +0000 Avoid non-portable use of $< outside an inference rule. Author: Peter Maydell Date: Sat Dec 24 17:17:38 2005 +0000 Rework detection and handling of ndbm: we now check for a working (library,header) combination, and configure defines variables for each which the makefile and C file just use, rather than a bunch of HAVE_foo switches. As a bonus, we no longer unnecessarily link every binary with the ndbm library even though only slocal uses it. Also you can now tell configure where to get the header/library so even if we guess wrong you can overrule us. Author: Peter Maydell Date: Thu Dec 22 10:38:32 2005 +0000 Fix stupid accidental dependence on a bash quirk in previous configure script change. Author: Jon Steinhart Date: Tue Dec 20 04:39:51 2005 +0000 Rolled release. Author: Peter Maydell Date: Thu Dec 15 00:45:36 2005 +0000 Improve the checks for where to find ndbm (dbm_open etc); should now work on systems with new gdbm and libdb4. Author: Peter Maydell Date: Thu Dec 15 00:12:52 2005 +0000 Change some non-standard formatting in a previous log entry so it matches the conventions used in other entries. Author: Josh Bressers Date: Wed Dec 14 01:48:24 2005 +0000 * Fedora Bug #163760: sbr/context_read.c (context_read): Ensure that the context is only read once. Author: Jon Steinhart Date: Mon Dec 12 22:30:44 2005 +0000 Fixed annotate call for new delete argument values. Author: Josh Bressers Date: Mon Dec 12 20:26:53 2005 +0000 * uip/sendsbr.c (annoaux): Fix the call to annotate() Author: Jon Steinhart Date: Thu Dec 8 15:57:34 2005 +0000 *** empty log message *** Author: Jon Steinhart Date: Wed Dec 7 21:25:46 2005 +0000 Fixed a bug where anno -append put the headers in the wrong place if applied to a message that didn't contain any headers. Added a special value of "all" to the -number option that causes anno -delete to delete all matching components instead of just the first one. Added new -preserve and -nopreserve options. Using -preserve retains the original last accessed and last modified times on annotated messages. Author: Josh Bressers Date: Mon Dec 5 13:38:41 2005 +0000 Fix the AC_PATH_PROG default when vi isn't found during build. Author: Jon Steinhart Date: Sat Dec 3 23:41:39 2005 +0000 Rolled version. Should have done it last time! Author: Peter Maydell Date: Sat Nov 19 16:32:34 2005 +0000 Make it clearer that lower-case envariables aren't supposed to be set by the user. Author: Peter Maydell Date: Sat Nov 19 16:04:25 2005 +0000 Special-case an MHCONTEXT of "/dev/null" and don't try to lock it -- some user scripts may use this to suppress modification of context. Author: Peter Maydell Date: Mon Nov 14 00:18:24 2005 +0000 [bug #9813] Don't crash after removing the folder if the context file has no Current-Folder entry. Author: Peter Maydell Date: Sun Nov 13 23:57:49 2005 +0000 Pass some globals into sm_init() so that it uses SASL if necessary. [NB that as I do not have a SASL setup I am relying on (a) the patch being obviously correct and (b) the original submitter having tested!] Author: Peter Maydell Date: Sun Nov 13 23:56:30 2005 +0000 Forgot to quote the bug number in the changelog comment. Author: Peter Maydell Date: Sun Nov 13 23:51:18 2005 +0000 Use context/ctxpath==NULL to indicate that no context file should be read, to avoid inadvertently trying to lock /dev/null (takes 30secs+ with some locking methods). Author: Peter Maydell Date: Sun Nov 13 22:36:07 2005 +0000 Fix buffer overrun in address parsing code (would only show up if scan was run with -width 16536 or similar) Author: Oliver Kiddle Date: Sun Nov 13 19:38:32 2005 +0000 remove link to install-mh that caused problems on some systems Author: Oliver Kiddle Date: Sun Nov 13 19:27:37 2005 +0000 bug #739: install target now depends on all to avoid problem on case-insensitive file systems with the INSTALL file Author: Josh Bressers Date: Thu Nov 10 21:37:10 2005 +0000 Fix the AC_PATH_PROG default when sendmail isn't found during build. Author: Peter Maydell Date: Wed Nov 9 22:56:35 2005 +0000 Fix a non-ANSI prototype. Author: Oliver Kiddle Date: Tue Nov 8 20:22:33 2005 +0000 Simon Burge: fix to handle getutent() on NetBSD Author: Oliver Kiddle Date: Tue Nov 8 17:18:09 2005 +0000 update most references to the web page and mailing list locations Author: Oliver Kiddle Date: Tue Nov 8 16:58:08 2005 +0000 prepend DESTDIR to install locations Author: Oliver Kiddle Date: Tue Nov 8 16:51:34 2005 +0000 replace obsolete autoconf macros Author: Peter Maydell Date: Sun Nov 6 21:54:40 2005 +0000 Fix various buffer overruns in fmt_scan.c; the bulk of this is passing buffer length through to decode_rfc2047() and having that function do sufficient bookkeeping to avoid running off the end of the buffer. Author: Peter Maydell Date: Sun Nov 6 00:34:56 2005 +0000 Fix a compile error if building nmh with --enable-apop. Author: Peter Maydell Date: Sun Nov 6 00:32:20 2005 +0000 Don't fclose() the file twice in error-exit paths from get_content() (was causing crashes on multipart mails with invalid Content-Type headers) Author: Peter Maydell Date: Sun Nov 6 00:28:12 2005 +0000 Remove space between -o and output filename so it works on older versions of flex as well as newer ones. Author: Peter Maydell Date: Sun Nov 6 00:23:48 2005 +0000 Add an AC_PREREQ so we don't just fail with an obscure error message if using old 2.13 era autoconf (or an autoconf-version-guessing wrapper). Author: Josh Bressers Date: Fri Nov 4 22:07:48 2005 +0000 Update the instructions for subscribing to the nmh-workers list Author: Oliver Kiddle Date: Wed Nov 2 17:43:21 2005 +0000 fail when kpop connection attempted without KPOP support compiled in Author: Oliver Kiddle Date: Wed Nov 2 17:29:50 2005 +0000 fix for newer version of flex and remove autogenerated file from cvs Author: Oliver Kiddle Date: Wed Nov 2 17:22:27 2005 +0000 speed up flist by skipping stat on files with numbers as names Author: Oliver Kiddle Date: Wed Nov 2 17:16:39 2005 +0000 include new files in distribution Author: Bill Wohler Date: Tue Oct 11 01:52:45 2005 +0000 A couple of questions from nmh's original FAQ were folded into the MH FAQ which is now a part of nmh. New Questions 1.09 What is the copyright status of nmh? 3.23 Why do folder and flist overlook some of my sub-folders? Changed Questions 1.02 current version? nmh history update, nmh 1.1-RC4, mailutils 0.6 Author: Oliver Kiddle Date: Wed Oct 5 10:05:24 2005 +0000 Harald Geyer: back out fork/vfork workaround and handle the issue directly Author: Oliver Kiddle Date: Wed May 18 13:45:03 2005 +0000 use fork instead of vfork on Linux Author: Oliver Kiddle Date: Wed May 18 13:27:44 2005 +0000 test/report error writing to stdout Author: Oliver Kiddle Date: Wed May 18 13:24:14 2005 +0000 correct SASL include file locations Author: Oliver Kiddle Date: Wed May 18 13:16:21 2005 +0000 add bash completion definitions from Debian Author: Oliver Kiddle Date: Wed May 18 12:57:40 2005 +0000 fix a bug affecting AFS where nmh was setting the READONLY flag for a folder even when you do have write access to the folder Author: Oliver Kiddle Date: Wed May 18 12:50:45 2005 +0000 Carl Mummert: add unquote() function for removing quotes from RFC-2822 headers Author: Oliver Kiddle Date: Tue May 17 16:30:15 2005 +0000 fill in a few of the missing ChangeLog entries Author: Oliver Kiddle Date: Wed Feb 23 16:20:47 2005 +0000 use iconv to convert RFC-2047 encoded headers to the character set used by the current locale Author: Oliver Kiddle Date: Wed Feb 23 14:07:52 2005 +0000 fix Debian bug #202667: crash when a message's filename overflows an int when converted Author: Oliver Kiddle Date: Wed Feb 23 11:55:25 2005 +0000 Updated config.guess and config.sub to the most recent versions (from automake 1.9.5) Author: Oliver Kiddle Date: Mon Feb 21 16:31:58 2005 +0000 fix bug where inc crashed on failing to reopen the terminal Author: Oliver Kiddle Date: Thu Jan 27 16:43:03 2005 +0000 acknowledge that my change was based on an older patch from Michael Richardson Author: Oliver Kiddle Date: Thu Jan 27 16:39:56 2005 +0000 Added -proxy option to inc and msgchk Author: Oliver Kiddle Date: Thu Jan 27 16:34:20 2005 +0000 Added -proxy option to inc and msgchk Author: Oliver Kiddle Date: Thu Jan 27 16:26:24 2005 +0000 On systems where it is available, use nl_langinfo to get the character set if MM_CHARSET is unset Author: Oliver Kiddle Date: Fri Jan 21 19:25:44 2005 +0000 US-ASCII is a subset of UTF-8 so can be handled directly when UTF-8 is being used Author: Oliver Kiddle Date: Fri Dec 17 15:16:04 2004 +0000 Fix -part option to mhshow/mhlist/mhstore to find sub-parts of the specified part Author: Jon Steinhart Date: Fri Nov 19 05:06:16 2004 +0000 Added mail directory argument to folder_addmsg in order to make it possible to provide a path to the ext_hook call that is mailpath-based. A problem existed when a folder was a symbolic link and the pwd call would return the path relative to the filesystem, not to mailpath. A new argument was needed because there was otherwise no reasonable way to get that path. Author: Jon Steinhart Date: Tue Nov 16 18:14:34 2004 +0000 Fixed problem where the refile hook was being called after a message was renamed so that it wasn't around for the hook. The hook is now called before the message file is renamed. Author: Jon Steinhart Date: Tue Nov 16 18:08:07 2004 +0000 Fixed typo in comment. Fixed problem with refile hook when refiling across filesystems. Author: Jon Steinhart Date: Tue Nov 16 17:37:41 2004 +0000 Removed unnecessary code. Author: Jon Steinhart Date: Tue Nov 16 17:28:33 2004 +0000 Fixed wrong directory for hook when refiling with -src option. Author: Jon Steinhart Date: Fri Oct 15 17:10:58 2004 +0000 Fixed calling of external hooks. Author: Jon Steinhart Date: Tue Oct 12 21:14:02 2004 +0000 Fixed another weird bug caused by the static mailpath being overwritten. Author: Jon Steinhart Date: Tue Oct 12 20:41:34 2004 +0000 Fixed bug that caused anno to mangle headers. Author: Jon Steinhart Date: Tue Oct 12 20:40:25 2004 +0000 Fixed strange bug that prevented a lock from ever being obtained if getting it failed the first time. The problem was that the string of XXXXXX that is required by mkstemp() was overwritten the first time through, and so all subsequent times failed because mkstemp() failed. The fix reinitializes the tmp file string. Author: Jon Steinhart Date: Tue Oct 12 20:38:10 2004 +0000 Fixed bug in which the static maildir was overwritted if a format string was read from the profile. Author: Jon Steinhart Date: Tue Oct 12 20:31:14 2004 +0000 Fixed bug that was producing an incorrect path for the external hook. Author: Glenn Burkhardt Date: Mon Oct 6 20:11:39 2003 +0000 db configuration fix for Debian; yet another location for ndbm. Author: Glenn Burkhardt Date: Tue Sep 30 19:55:12 2003 +0000 restored use of PUTDF() macro; was broken in versions 1.10-1.12; replacement implementation filled on right instead of on left. Author: Glenn Burkhardt Date: Tue Sep 30 16:57:26 2003 +0000 [bug #4302] errno is not always an extern int The errno declaration is best left to errno.h; several systems use #define errno (*(___errno())) or similar Author: Glenn Burkhardt Date: Tue Sep 30 16:22:54 2003 +0000 corrected termination condition for fill character introduced in last version Author: Glenn Burkhardt Date: Tue Sep 30 16:19:12 2003 +0000 [bug #4296] PUTD() macro can't hack 10 digit values Once the number exceeded 1000000000, the conversion would fail. An execution of dp -format "%(clock{text})" "Tue, 01 Jul 2003 21:38:05 +0700" would erroneously print 749660476, instead of 1057070285. The macros PUTD() and PUTDF() have been replaced by snprintf() calls; These macros should never have been written in the first place, when system functions exist to do the work. (prev version 1.10 was erroneously comitted). Author: Glenn Burkhardt Date: Tue Sep 30 16:07:49 2003 +0000 [bug #4296] PUTD() macro can't hack 10 digit values Once the number exceeded 1000000000, the conversion would fail. An execution of dp -format "%(clock{text})" "Tue, 01 Jul 2003 21:38:05 +0700" would erroneously print 749660476, instead of 1057070285. The macros PUTD() and PUTDF() have been replaced by snprintf() calls; These macros should never have been written in the first place, when system functions exist to do the work. Author: Glenn Burkhardt Date: Tue Sep 30 14:36:04 2003 +0000 [bug #4297] The strlen mh-format function can crash if 'str' is null. Author: Glenn Burkhardt Date: Tue Sep 30 14:30:36 2003 +0000 note recent changes Author: Glenn Burkhardt Date: Tue Sep 30 14:19:20 2003 +0000 fix handling of "-list" and "-seq" options, so behavior is orthoganal. Previously, "pick -list -seq seqname" meant "pick -nolist -seq seqname". Now "pick -list -seq seqname" and "pick -seq seqname -list" do the same thing. Thanks to Robert Elz. Author: Glenn Burkhardt Date: Sun Sep 28 14:27:34 2003 +0000 update 'mp->lowmsg' from 0 to 1 during regular 'inc' from mail spool; avoids failure of 'folder_realloc()' for case of no messages in folder, and more than 100 messages to incorporate. Initially, 'folder_read()' will initialize 'mp->lowmsg' to 0, and 'mp->lowoff' to 1. So the call would be folder_realloc(mp, 1, 200), and the comparison 'if (mp->nummsg > 0 && lo > mp->lowmsg)' will fail. Author: Glenn Burkhardt Date: Mon Sep 22 16:03:22 2003 +0000 Removed space between command name and man section number (e.g., "show (1)" --> "show(1)", so xemacs can recognize them as links to other man pages. Author: Glenn Burkhardt Date: Mon Sep 22 01:04:04 2003 +0000 make 'spost' handling of "masquerade:" line of mts.conf containing 'draft_from' same as for 'post'. Debian bug report 144098, filed by Terran Melconian. Author: Glenn Burkhardt Date: Mon Sep 22 00:43:09 2003 +0000 status of action wasn't saved for use by 'N' result, so when 'N' was used slocal could perform the action even if the previous action failed. Debian bug report #149745, filed by Daniel Müller. Author: Glenn Burkhardt Date: Sun Sep 21 18:08:35 2003 +0000 Increase timeouts to comply with RFC 1123; Debian bug report #152728 by Ian Jackson Author: Glenn Burkhardt Date: Sun Sep 21 17:34:31 2003 +0000 added cross references Author: Glenn Burkhardt Date: Sun Sep 21 17:09:31 2003 +0000 fixed typo: example for scan.default didn't include proper terminating %> for "%<{date} %|*%>"; reported as Debian bug #143427 by Peter Maydell Author: Glenn Burkhardt Date: Sun Sep 21 15:43:00 2003 +0000 Apply bug fix reported to Debian (#136976) by Peter Maydell; allows messages with "Content-Transfer-Encoding: binary" to be displayed, per RFC 2045 section 6.2 paragraph 4 Author: Glenn Burkhardt Date: Sun Sep 21 02:39:58 2003 +0000 corrected typo for nroff directive Author: Glenn Burkhardt Date: Tue Sep 16 14:27:55 2003 +0000 add command to remove $(libdir)/install-mh prior to creating the link Author: Jeffrey C Honig Date: Sun Sep 14 13:25:55 2003 +0000 The first ``inc'' into an empty folder would not update the unseen sequence. This is because seq_list() will return NULL if mp->nummsg is zero. Insure that mp->nummsg is incremented. Author: Ken Hornstein Date: Mon Sep 8 18:41:10 2003 +0000 Man page fix from Igor Sobrado Author: Glenn Burkhardt Date: Sat Sep 6 17:27:55 2003 +0000 Added documentation of "Dcc", per recent discussion on mailing list (main contributors Jerry Peek and Robert Elz) Author: Ken Hornstein Date: Fri Sep 5 21:07:49 2003 +0000 Merge in changes from the 1.1 branch. Author: Ken Hornstein Date: Fri Sep 5 19:10:21 2003 +0000 Fix from branch. Author: Ken Hornstein Date: Fri Sep 5 18:37:47 2003 +0000 Quiet lock warning. Author: Ken Hornstein Date: Fri Sep 5 18:36:36 2003 +0000 Merge in locking fixes into the main line. Author: Jeffrey C Honig Date: Mon Aug 11 01:20:52 2003 +0000 When compiling format strings, nmh attempts to avoid multiple parsing of address and date fields by only inserting calls to the parse functions (FT_PARSEADDR and FT_PARSEDATE) for a given component once. The problem with this method is that the initial invocation may actually be on a code path that is conditionally executed. This can result cached copies of data from the fields in previous messages to be used. My solution is to move this optimization from compile time to run time. Address and Date parsing calls (FT_PARSEADDR and FT_PARSEDATE) will always be included. Run time flags are used to prevent these functions from being run more than once per component per message. The c_flags field has being converted from a boolean to a bit-field to facilitate maintenance of the new CT_PARSED value. The result value that used to be in this field is now the bit CF_TRUE and the overloaded use of this field by scan() is now the CT_DATEFAB bit. Some unneeded flags (CT_ADDRPARSE, CT_MYMBOX) have also been removed. Author: Glenn Burkhardt Date: Fri Jul 4 16:15:02 2003 +0000 more detail for bugs fixed, so reader doesn't need to go to Bugzilla Author: Glenn Burkhardt Date: Fri Jul 4 15:55:55 2003 +0000 update Author: Glenn Burkhardt Date: Wed Jul 2 02:24:19 2003 +0000 restored use of %manext5% for man section, which was lost in version 1.4 Author: Glenn Burkhardt Date: Wed Jul 2 02:03:19 2003 +0000 Updated description of default template to reflect current change to In-Reply-To, and Fcc: Author: Glenn Burkhardt Date: Wed Jul 2 02:01:50 2003 +0000 Default templates for 'comp', 'forw', 'dist', 'repl' now include Fcc: +outbox Author: Glenn Burkhardt Date: Mon Jun 30 19:43:26 2003 +0000 use symbols for date and version so values are automatically updated during build. Author: Glenn Burkhardt Date: Mon Jun 30 19:40:05 2003 +0000 bump date so everything gets a new timestamp for 1.1 Author: Glenn Burkhardt Date: Mon Jun 30 18:58:07 2003 +0000 fix bug #1393, "sortm core dumps", using patch provided by Robert Elz, kre@munnari.oz.au. The core dump occurred when "Subject:" was immediately followed by an alphanumeric, and "-textfield subject" were used as arguments. Author: Glenn Burkhardt Date: Mon Jun 30 16:48:50 2003 +0000 Re-write for clarity, using major contributions from Bart Massey, and Jerry Peek. Author: Glenn Burkhardt Date: Mon Jun 30 16:40:09 2003 +0000 made RFC 2822 compliant, using an "In-reply-to:" format supplied by Jerry Peek. Author: Glenn Burkhardt Date: Fri Jun 27 17:02:13 2003 +0000 prevent double free of 'ce->cd_file' or later use of invalid data Author: Glenn Burkhardt Date: Thu Jun 26 01:30:36 2003 +0000 fix for bug #578 repl leaks umask; there are several other places in the code where the umask value is not restored, so there might be other similar bugs Author: Glenn Burkhardt Date: Mon Jun 23 00:44:28 2003 +0000 Changed use of GNU "simply expanded variables" for MAN1, MAN5, MAN8, so one makefile will work with SysV make (e.g., Solaris) and GNU make Author: Glenn Burkhardt Date: Sun Jun 22 23:59:16 2003 +0000 allow gdbm/ndbm.h in addition to db1/ndbm.h; needs corresponding change in configure.in Author: Glenn Burkhardt Date: Sun Jun 22 23:58:07 2003 +0000 Allowed gdbm as substitute for Berkeley db1/ndbm.h libdb1 (check for gdbm/ndbm.h, libgdbm now); send only stdout to /dev/null when checking for 'broken vi', this allows 'vim' on Solaris to work, since 'vim' closes stdin and uses stderr for input when running a script. Author: Kimmo Suominen Date: Thu Jan 2 04:07:49 2003 +0000 Fix detection of non-mime messages when the charset is not enclosed in double quotes. (Not perfect yet, but 97% effective.) Author: Jon Steinhart Date: Thu Nov 21 21:22:24 2002 +0000 Fixed a typo in the SRCS definition; had a .o where it should have been a .c Author: Jon Steinhart Date: Wed Nov 20 19:57:19 2002 +0000 Fixed a bug in the waitpid version where it would return incorrectly if a child process was interrupted. Author: Jon Steinhart Date: Tue Nov 19 20:39:21 2002 +0000 Removed the reference to the library directory since this now goes in bin. Author: Jon Steinhart Date: Tue Nov 19 20:37:50 2002 +0000 Changed to move install-mh to the bin directory instead of the lib directory. A link is made from the lib to the bin just in case. Author: Jon Steinhart Date: Mon Nov 18 18:25:00 2002 +0000 The file README-ATTACHMENTS was removed - it has been moved to the docs subdirectory. I thought that this had already been done but I guess not. It's unrelated to the rest of these changes. The remainder of these changes affect the way that nmh is installed. Nmh has historically prompted the user for installation when any nmh command is invoked if it doesn't think that it's installed. This is a problem for programs that want to, for example, interact with nmh programs via pipes. These changes alter this behavior. Now, when an nmh program thinks that nmh isn't installed, it tells the user to run install-mh to install it. A -check option has been added to install-mh that allows the existence of an installation to be silently checked and indicated via the exit status. The bulk of this change is in sbr/read_context.c. In the process of making these changes, I noticed a fair amount of useless code that I removed. In particular: 1. The program started with a test for whether or not defpath had already been set. This could only happen if context_read() was called more than once, which it isn't. This check also existed and was removed from the following places: sbr/context_del.c sbr/context_find.c sbr/context_replace.c sbr/seq_read.c sbr/seq_save.c uip/flist.c uip/folder.c uip/rmf.c 2. A similar test for mypath was removed. No need to test it since it doesn't happen. I'm just not a believer that a = 1; if (a != 1) error(); is a good way to write code! 3. I removed the code makes a copy of the $HOME environment variable as returned by getenv(). It's never changed, so it doesn't need copying. 4. I removed code that copied the pw_dir member of the passwd structure returned by getpwuid() if $HOME isn't set. Yes, the returned structure is static, but since the function is never called again the returned values stay valid and don't need copying. 5. I removed the test for a NULL pw_dir member in the passwd structure returned by getpwuid() since that never happens. 6. I removed code that removed a trailing / from mypath if mypath is more than one character long. Unnecessary as // is interpreted as / anyway. mypath never shows up in an error message, so nobody will ever see it. Besides, this code didn't handle the case of multiple trailing slashes. 7. I removed code that replaced the MH environment variable contents with an absolute path if it was a relative one. I'm a bit nervous about this one, only testing will tell. Any nmh program that's invoked will use the same context_read() code to convert a relative path to an absolute one anyway. And there's no guarantee (or discussion) of this feature in any of the documentation. 8. Althout context_read() tested the MH environment variable, install-mh didn't. This means that the behavior was not consistent between install-mh and all other nmh programs. I changed install-mh to be consistent with context_read(). 9. install-mh has been installed in the lib directory, not bin. So a user would be unlikely to find it when prompted to run it. The installation has been changed to add a link from bin to lib. Author: Anders Eriksson Date: Mon Oct 21 19:32:26 2002 +0000 Changed scan to always pass the folder argument. This is in line with the man page. Author: Jon Steinhart Date: Mon Sep 9 14:30:16 2002 +0000 New routine that provides interface to external programs. Author: Jon Steinhart Date: Fri Aug 23 20:37:01 2002 +0000 Added external program hooks. Author: Jon Steinhart Date: Thu Aug 22 22:06:18 2002 +0000 Moved this file here from the root directory. Author: Jon Steinhart Date: Mon Aug 19 20:50:41 2002 +0000 Added an improved user interface for sending messages with attachments. Author: Ken Hornstein Date: Mon Jul 8 19:29:24 2002 +0000 Remove this file on the head as well. Author: Ken Hornstein Date: Wed Jul 3 14:49:24 2002 +0000 Bring these changes over from the branch. Author: Ken Hornstein Date: Wed Jul 3 14:08:11 2002 +0000 Remove these undefines (why were they in there?) Author: Ken Hornstein Date: Tue Jul 2 22:10:55 2002 +0000 Update for new version. Author: Ken Hornstein Date: Tue Jul 2 22:09:12 2002 +0000 Add/update copyright notice in all source code files. Author: Ken Hornstein Date: Tue Jul 2 21:46:37 2002 +0000 Remove autoconf-generated files (and note such files in .cvsignore) Author: Dan Harkless Date: Sat Mar 17 11:28:27 2001 +0000 Ken Hornstein's configure.in Cyrus SASL checks were doing `x"$with_cyrus_sasl" != "no"' instead of `... != x"no"'. Author: Dan Harkless Date: Wed Mar 7 05:26:50 2001 +0000 Found some historical information about MH in RFC 808. Supplemented it with info from Jerry Peek's MH book and added it to docs/README.about. Author: Shantonu Sen Date: Tue Feb 6 20:47:54 2001 +0000 dtimp timezone fixes Author: Shantonu Sen Date: Tue Feb 6 20:35:40 2001 +0000 Be more picky about symbolic time zones, and accept either a symbolic or numeric time zone, but never both, since a DST offset might be subtracted twice. Also, be uniform about assuming that pre-1970 dates are Y2K problems. Author: Dan Harkless Date: Tue Feb 6 04:28:04 2001 +0000 Say in README.developers to use `\date' in case anyone is like me and has `date' aliased in their shell to use a nonstandard (but subjectively more readable) format. Author: Dan Harkless Date: Tue Feb 6 04:22:09 2001 +0000 Regenerated stamp-h.in using my tcsh alias `date', which uses a nonstandard format. Replacing it with the standard format. I'll update README.developers to say to use `\date'. Author: Dan Harkless Date: Tue Feb 6 03:46:27 2001 +0000 * -L isn't sufficient for specifying the path of the Cyrus SASL shared library. That'll allow us to link successfully, but on many/most OSes that won't allow us to find libsasl at runtime. On Solaris, we need to specify the library path with -R as well (or else the user will have to use the $LD_LIBRARY_PATH kludge, which is considered harmful). This fix should be extended to other OSes as well. * Print whether we have SASL support in the "nmh configuration" summary configure prints out. Author: Shantonu Sen Date: Thu Jan 25 21:28:30 2001 +0000 man/mh-chart Author: Shantonu Sen Date: Thu Jan 25 21:15:52 2001 +0000 use %etcdir% for spacing instead of hardcoding Author: Shantonu Sen Date: Thu Jan 25 21:14:32 2001 +0000 compiled mh-chart with synopses of commands Author: Shantonu Sen Date: Tue Jan 23 20:27:57 2001 +0000 digest Author: Shantonu Sen Date: Tue Jan 23 20:26:15 2001 +0000 Don't try to force year into a 19xx format Author: Shantonu Sen Date: Tue Jan 23 04:14:08 2001 +0000 SYNOPSIS formating to prevent filling Author: Shantonu Sen Date: Fri Jan 19 21:32:13 2001 +0000 manpages finished Author: Shantonu Sen Date: Fri Jan 19 21:22:08 2001 +0000 don't build vmh.1 since vmh isn't distributed, and we no longer need tmac.h Author: Shantonu Sen Date: Fri Jan 19 21:10:09 2001 +0000 show-whom Author: Shantonu Sen Date: Thu Jan 18 20:27:34 2001 +0000 prompter-sendfiles Author: Shantonu Sen Date: Tue Jan 9 06:55:21 2001 +0000 delete old files, manpage progress Author: Shantonu Sen Date: Tue Jan 9 06:45:26 2001 +0000 removed deprecated files. sendmail functionality exists in mts/smtp/ Author: Shantonu Sen Date: Tue Jan 9 06:41:44 2001 +0000 Add an entry for README.manpages Author: Shantonu Sen Date: Tue Jan 9 06:40:12 2001 +0000 Added popi.c to SRCS, even though it's not being built currently Author: Shantonu Sen Date: Tue Jan 9 06:13:55 2001 +0000 removing mts/generic Author: Shantonu Sen Date: Tue Jan 9 06:10:03 2001 +0000 deleting zotnet/ dir -- parts moved to sbr/ Author: Shantonu Sen Date: Tue Jan 9 06:01:19 2001 +0000 mh_profile-prev Author: Shantonu Sen Date: Sat Jan 6 23:38:12 2001 +0000 mh_tailor-mhbuild Author: Shantonu Sen Date: Thu Jan 4 07:07:41 2001 +0000 Updating mh_sequence Author: Shantonu Sen Date: Wed Jan 3 06:29:06 2001 +0000 mh_mail-mh_profile Author: Shantonu Sen Date: Tue Jan 2 08:10:46 2001 +0000 mh-format Author: Shantonu Sen Date: Tue Jan 2 07:12:46 2001 +0000 Modularizing the Makefile caused some variable expansion problems on non-GNU makes Author: Shantonu Sen Date: Tue Jan 2 06:43:07 2001 +0000 mh_chart-mh_draft Author: Shantonu Sen Date: Mon Jan 1 10:19:00 2001 +0000 Updating ali-mh_alias Author: Shantonu Sen Date: Sun Dec 31 20:58:29 2000 +0000 add about pointers to shared pages Author: Shantonu Sen Date: Sun Dec 31 20:55:48 2000 +0000 Add date to files i missed last time Author: Shantonu Sen Date: Sun Dec 31 20:55:06 2000 +0000 docs/README.manpages Author: Shantonu Sen Date: Sun Dec 31 20:48:50 2000 +0000 Add manpage style guide Author: Shantonu Sen Date: Sun Dec 31 09:25:09 2000 +0000 Updating inc Author: Shantonu Sen Date: Sun Dec 31 08:19:20 2000 +0000 Updating comp-forw Author: Shantonu Sen Date: Sun Dec 31 06:31:42 2000 +0000 add flists and folders as pointer pages to flist,folder. Modularize Makefile to allow easier addition of manpages Author: Shantonu Sen Date: Sun Dec 31 02:44:18 2000 +0000 replace %components% and %distcomps% in man pages with corresponding files Author: Shantonu Sen Date: Sun Dec 31 02:43:34 2000 +0000 updated ali-flist, with batch edit of others Author: Shantonu Sen Date: Sat Dec 30 23:18:28 2000 +0000 update ali,anno,ap.burst Author: Shantonu Sen Date: Sat Dec 30 10:01:29 2000 +0000 Updated man pages to remove dependence on tmac.h and have a more modern look Author: Shantonu Sen Date: Sat Dec 30 10:00:42 2000 +0000 DATE an manpage updating Author: Shantonu Sen Date: Sat Dec 30 09:51:55 2000 +0000 Use the DATE file Author: Shantonu Sen Date: Sat Dec 30 09:50:13 2000 +0000 Created DATE that contains a datestamp used in the man pages. It should be updated each release. Author: Shantonu Sen Date: Sun Dec 24 10:13:45 2000 +0000 hesiod and krb5 test changes. add --with-locking to INSTALL Author: Shantonu Sen Date: Sun Dec 24 10:06:30 2000 +0000 Add documentation for --with-locking option Author: Shantonu Sen Date: Sun Dec 24 10:06:00 2000 +0000 hesiod and krb5 test fixes Author: Shantonu Sen Date: Sun Dec 24 10:04:58 2000 +0000 Fixed up the hesiod library test so that the location of res_send actually helps to determine whether -lresolv needs to be passed as a hesiod lib. Also, fixed the krb5 test to look for -lk5crypto if it exists, since that's the new name for -lcrypto. The old -lcrypto remains in case the new version isn't found. Author: Dan Harkless Date: Sat Dec 23 06:11:03 2000 +0000 -apop and -noapop were not documented in msgchk.man. -snoop was documented but didn't appear in the usage SYNOPSIS. Author: Shantonu Sen Date: Fri Dec 22 23:49:08 2000 +0000 add --with-locking option Author: Shantonu Sen Date: Fri Dec 22 23:42:16 2000 +0000 Autoconfing the file locking options Author: Shantonu Sen Date: Fri Dec 22 19:30:41 2000 +0000 put both linux entries on one line Author: Shantonu Sen Date: Fri Dec 22 19:29:40 2000 +0000 dtimep, MACHINES Author: Shantonu Sen Date: Fri Dec 22 19:21:29 2000 +0000 Update to include Mac OS X and Linux 2.4 Author: Shantonu Sen Date: Fri Dec 22 19:18:09 2000 +0000 When building on Mac OS X, don't set LDFLAGS=-s, since the linker doesn't like the flag Author: Shantonu Sen Date: Fri Dec 22 19:15:02 2000 +0000 Take out memory hints, since we are assuming flex over lex, so this shouldn't be a problem Author: Shantonu Sen Date: Wed Dec 20 16:03:36 2000 +0000 doc/README.developers update, and fixed typo in last ChangeLog entry Author: Shantonu Sen Date: Wed Dec 20 16:00:46 2000 +0000 Marked deprecated directories in layout description, and added an entry for docs Author: Dan Harkless Date: Wed Dec 20 03:30:14 2000 +0000 Just changed a "can" to a "could" since I don't know if most POP3 servers are like qpopper in not allowing people with APOP activated to log in via normal POP3. Author: Dan Harkless Date: Wed Dec 20 03:18:33 2000 +0000 -apop and -noapop were not documented in inc.man. -snoop was documented but didn't appear in the usage SYNOPSIS. Author: Shantonu Sen Date: Sun Dec 17 19:52:04 2000 +0000 Fixed a type from 'his' to 'this' Author: Shantonu Sen Date: Thu Dec 14 14:55:17 2000 +0000 config.guess/sub update Author: Shantonu Sen Date: Thu Dec 14 14:35:40 2000 +0000 config update procedure (probably unneccessary) Author: Shantonu Sen Date: Thu Dec 14 14:32:09 2000 +0000 Updated config.guess and config.sub from most recent version from ftp.gnu.org/pub/gnu/config, with timestamp='2000-12-07'. Author: Dan Harkless Date: Thu Dec 14 03:14:08 2000 +0000 Shantonu did his commit in the wrong order earlier today, making configure get re-built due to a "newer" configure.in. Author: Shantonu Sen Date: Thu Dec 14 01:38:41 2000 +0000 Move mts/generic to sbr/ Author: Shantonu Sen Date: Thu Dec 14 01:30:43 2000 +0000 Resolve the circular dependency of libmh on libmts on libmh. The files mts/generic/client.c and mts.c are moved to sbr/, and mts/generic/mts.h is moved to h/mts.h. Thus, libmh is self-contained. All header includes have been appropriately updated, and the Makefiles and configure script no longer build mts/generic. Author: Dan Harkless Date: Tue Dec 12 06:19:25 2000 +0000 When Shantonu made the new libmts.a, he swapped $(MTSLIB) and libmh.a in sbr/Makefile.in so that libmh.a comes first, but this causes the build to fail on Solaris, because libmts.a has to get ruserpass() out of libmh.a. Swapping them back to the way Ken Hornstein's patch (which I applied on Jul 20) put them, with libmh.a correctly coming second. If there are times when libmts.a needs to come second, then it would appear there's a circular dependency and someone (Shantonu?) did an mts merge incorrectly. Author: Dan Harkless Date: Fri Sep 8 23:19:37 2000 +0000 Just fixed a formatting error. Author: Shantonu Sen Date: Fri Sep 8 01:39:10 2000 +0000 Took out bad zones in dtimep Author: Shantonu Sen Date: Fri Sep 8 01:36:23 2000 +0000 Took out incorrect time zones like JST and BST. Author: Shantonu Sen Date: Fri Sep 8 00:49:32 2000 +0000 Included code reorg of zotnet/mts Author: Shantonu Sen Date: Fri Sep 8 00:37:54 2000 +0000 Don't make Makefiles in zotnet or mts/mmdf or mts/sendmail Author: Shantonu Sen Date: Fri Sep 8 00:36:48 2000 +0000 Don't generate Makefiles for zotnet, or mts/mmdf and mts/sendmail, since they are no longer being compiled. Author: Shantonu Sen Date: Fri Sep 8 00:34:41 2000 +0000 Included h/nmh.h, since the MD5 algorithms were missing declarations for memcpy and memset (I think), which are indirectly included from strings.h Author: Shantonu Sen Date: Fri Sep 8 00:34:08 2000 +0000 Updated #include's to point to new location of mts.h on mts/generic Author: Shantonu Sen Date: Fri Sep 8 00:32:47 2000 +0000 No longer descend into zotnet/ Author: Shantonu Sen Date: Fri Sep 8 00:30:58 2000 +0000 Moved code from zotnet/mts to mts/generic. Also, unified generic mts code and smtp/sendmail into libmts.a as an intermediate, instead of having two static libs. Author: Shantonu Sen Date: Wed Sep 6 22:48:43 2000 +0000 Included changes to dtimep.lex to remove military zone parsing. Author: Shantonu Sen Date: Wed Sep 6 22:40:03 2000 +0000 Took out parsing of military time, which was causing issues when it encountered something like (MET), which it doesn't recognize as a timezone, and which was then read as military characters. Author: Dan Harkless Date: Fri Aug 11 20:43:07 2000 +0000 Further clarified Kimmo's etc/Makefile.in comments at his suggestion. Author: Dan Harkless Date: Thu Aug 10 21:32:33 2000 +0000 Changed my mind again on scan.MMDDYY and scan.YYYYMMDD. Put the replied / encrypted column back in, because it's useful to "always" (at least when you aren't using replied / encrypted) have a space in between the message number and date, so you can use awk (with the default field separators) to grab message numbers from scan output. Author: Dan Harkless Date: Thu Aug 10 20:33:25 2000 +0000 Decided that limiting the message number columns to 3 on my scan.MMDDYY and scan.YYYYMMDD (to try to regain space taken by extra date info) was ill-conceived. It's not that tough to get past 999 messages, though I imagine it's rather rare to exceed 9999. Changed these to 4. I had already removed the "replied / encrypted" column in YYYYMMDD, but this time I removed it on MMDDYY as well (I've never seen it used...). Author: Ruud de Rooij Date: Mon Aug 7 18:42:20 2000 +0000 Modify umask set by mhshow to enable user execute bit, so that viewers that create temporary directories (e.g., lynx) will be able to access them. Author: Dan Harkless Date: Sat Aug 5 16:00:49 2000 +0000 Kimmo's etc/Makefile.in change note implied that install was previously completely broken. Not the case. I asked Kimmo about it and he clarified that it failed when building outside the source tree. Fixed the entry to reflect. Author: Dan Harkless Date: Fri Aug 4 00:15:52 2000 +0000 TODO: Allow multiple simultaneous differing contexts, probably each tied to a parent (terminal) process. Author: Kimmo Suominen Date: Tue Aug 1 14:55:53 2000 +0000 Make "make install" work in etc/Makefile.in Author: Dan Harkless Date: Mon Jul 24 23:24:22 2000 +0000 Renamed DSTXXX as ADJUST_NUMERIC_ONLY_TZ_OFFSETS_WRT_DST and added an explanatory comment by its #definition. Author: Dan Harkless Date: Mon Jul 24 23:06:42 2000 +0000 Updated README.developers with the fact that zotnet/tws is going away. Author: Dan Harkless Date: Mon Jul 24 23:03:38 2000 +0000 When Shantonu wrote the new, more portable dtimep.lex, he left out the #ifdef DSTXXX stuff for some reason. Not a good idea, as that code is required for proper printing of numeric-offset timezones that have daylight saving time. Without that code, -0700 during DST gets printed as MST instead of PDT. Author: Dan Harkless Date: Fri Jul 21 03:31:39 2000 +0000 Fixed warnings from diff on first-time install of nmh. Also added 'echo's clarifying the etc file installation activities. Author: Dan Harkless Date: Fri Jul 21 02:35:43 2000 +0000 Applied Kurt J. Lidl 's $MAILHOST patch: I have a small patch that would be nice to be included -- basically, it allows the usage of the "MAILHOST" environment variable, without having to have HESIOD turned on. I need this functionality for my environment, where we have identical /usr/local on all my machines (so I cannot just hardcode into the mts.conf file), and I have multiple POP mail servers for my users. Modified inc.man to reflect that along with "pophost:" and -host, $MAILHOST can now activate POP mail inclusion as well. Author: Dan Harkless Date: Fri Jul 21 02:25:59 2000 +0000 Last pass at README.developers -- Kimmo's 5-step commit was overkill. You only need 3 steps, since configure.in is the only autoconf file with the RCS $Id keyword. Author: Dan Harkless Date: Fri Jul 21 02:11:59 2000 +0000 Meaningless modification to test autoconf file commit order stuff. Author: Dan Harkless Date: Fri Jul 21 02:04:37 2000 +0000 Meaningless change to test autoconf file commit order stuff. Author: Dan Harkless Date: Fri Jul 21 02:03:23 2000 +0000 Meaningless change for testing autoconf file commit order stuff. Author: Dan Harkless Date: Fri Jul 21 01:56:17 2000 +0000 Meaningless change to test autoconf commit order stuff. Author: Dan Harkless Date: Fri Jul 21 01:43:58 2000 +0000 People did not preserve my alphabetization of the --with options when they added new ones. Re-alphabetized. Author: Dan Harkless Date: Thu Jul 20 20:49:00 2000 +0000 Ken Hornstein's SASL patch was not integrated properly with Ruud's new merged mts/sendmail code. Kimmo has since fixed nmh so it compiles, but according to Ken, the SASL stuff still does not work. Integrating a patch from him for this. Author: Dan Harkless Date: Thu Jul 20 20:32:31 2000 +0000 One more pass at README.developers now that it's clear that my previously-suggested one-line autoconf-file commit can cause unnecessary local makes and an out-of-sync stamp-h.in file, but would not cause problems for other people using the CVS files. Author: Dan Harkless Date: Thu Jul 20 20:14:39 2000 +0000 Moved Kimmo's new "--with-hash-backup" to be output with the rest of the --with options in the configure --help output, rather than being in between two random --enable options. Author: Kimmo Suominen Date: Tue Jul 18 23:39:45 2000 +0000 Added answer. Author: Dan Harkless Date: Tue Jul 18 02:15:03 2000 +0000 Clarified and made some corrections to Kimmo's README.developers changes (BTW, if anyone can explain why the RCS Ids are able to cause problems with the dependencies, please fill in the explanation -- I never encountered a problem with the old single-commit method). Author: Dan Harkless Date: Tue Jul 18 02:07:51 2000 +0000 I don't understand why Kim's split-up of the autoconf-file cvs commits should be necessary, so I left a little note hoping for someone to explain technically why that should be the case. I certainly never ran into any problems with my old single-commit version (which I added back in along with an explanation of why it supposedly won't always work). Also Kim's text implied that the _only_ reason for the given order is the RCS Ids -- not true -- the timestamps are the main reason a particular order is necessary. Made a couple of other clarifications as well. Author: Kimmo Suominen Date: Sun Jul 16 06:18:03 2000 +0000 Iterating the commit a bit, I think this is how it works without extra runs of autoconf, autoheader and make. Author: Kimmo Suominen Date: Sun Jul 16 06:05:26 2000 +0000 Regen. Author: Kimmo Suominen Date: Sun Jul 16 06:01:28 2000 +0000 If $LIBTOOL is empty we should not try to run it. This gets rid of the "--version: not found" error. Author: Kimmo Suominen Date: Sun Jul 16 05:50:33 2000 +0000 Got rid of one mktemp. Author: Kimmo Suominen Date: Sun Jul 16 05:11:46 2000 +0000 Complete HAVE_MKSTEMP. Author: Kimmo Suominen Date: Sun Jul 16 04:23:50 2000 +0000 We ignore the fact that the user requested SASL, since the pipe to the mailer is secure. This allows for easier sharing of the MH profile across hosts. Author: Kimmo Suominen Date: Sun Jul 16 04:03:27 2000 +0000 Note replacement of GNU-makeism in sbr/Makefile.in with a common statement. Author: Kimmo Suominen Date: Sun Jul 16 03:58:57 2000 +0000 So I don't think you can commit these all in a single commit. README.developers recommends that (with precise ordering) but things still get regenerated when I run "make". Author: Kimmo Suominen Date: Sun Jul 16 03:57:47 2000 +0000 Keep this working with other makes than GNU. Author: Kimmo Suominen Date: Sun Jul 16 03:56:45 2000 +0000 Still missed one SASL stuff thing. Author: Kimmo Suominen Date: Sun Jul 16 03:36:42 2000 +0000 Changed "--with-backup-prefix" to "--with-hash-backup" because # is too difficult for config.status to get right. Author: Kimmo Suominen Date: Sun Jul 16 03:15:17 2000 +0000 Note "--with-backup-prefix". Author: Kimmo Suominen Date: Sun Jul 16 03:13:25 2000 +0000 Add "--with-backup-prefix" so it can be set easily. Author: Kimmo Suominen Date: Sun Jul 16 02:08:18 2000 +0000 SASL stuff. Author: Kimmo Suominen Date: Sun Jul 16 01:48:37 2000 +0000 SASL stuff. Author: Kimmo Suominen Date: Sun Jul 16 01:46:50 2000 +0000 SASL mods. Author: Dan Harkless Date: Thu Jul 13 21:49:45 2000 +0000 Deleted the timezone on Kim's SASL patch entry. Ruud has taken to adding the timezone even though all previous entries are missing it, and I don't really agree with that. True, on occasion someone in a different timezone will commit something later in the day than someone else, and even though the second change happens later, the time may be earlier, but that doesn't happen too often and isn't really a big deal, IMHO. Putting textual timezones like "EDT" isn't really the right solution, IMHO, since some of those tags are ambiguous. Either an offset-style timezone should be used or all times should be given as UTC. I'd just as soon stick with local times, though. Oh, one thing I forgot to mention in my last CVS entry was that I removed "IMAP" from the list of protocols supported by Ken's SASL patches -- nmh doesn't have any IMAP support! Author: Dan Harkless Date: Thu Jul 13 21:42:52 2000 +0000 Modified Kimmo's entry for the application of Ken Hornstein's SASL patches to clarify that it wasn't Ken applying them himself, and clarified what SASL support actually means. Author: Dan Harkless Date: Thu Jul 13 21:41:42 2000 +0000 Kimmo neglected to commit the regenerated versions of these after changing configure.in, forcing people using the CVS source to have to have the autoconf tools installed. Author: Dan Harkless Date: Tue Jul 11 21:20:04 2000 +0000 Clarified post.man and send.man for those not completely up on SASL terminology. "SASL encryption layers are not supported for SMTP" means that encryption is supported for the authentication but not for the subsequent data stream. Author: Kimmo Suominen Date: Sat Jul 8 05:36:58 2000 +0000 Note SASL commit. Author: Kimmo Suominen Date: Fri Jul 7 03:48:02 2000 +0000 SASL support from Ken Hornstein . Author: Ruud de Rooij Date: Mon Jun 12 18:07:34 2000 +0000 * Merged mts/sendmail functionality into mts/smtp; switching between smtp and sendmail delivery method is now controlled by mts.conf. * If tsort cannot deal with loops, in addition to defining tsort as cat, also define lorder as echo. * Removed uip/popi.c from list of sources. Author: Dan Harkless Date: Fri Jun 9 02:45:17 2000 +0000 New dtimep.lex didn't parse day names properly. Fixed. Also clarified ambiguous comments preceding day_map[] array (from old dtimep.lex) that probably led to the erroneous cp++ being added. Author: Ruud de Rooij Date: Wed Jun 7 19:06:52 2000 +0000 * Added one more mkstemp invocation to uip/spost.c (which was in a #if 0 block). * Applied patch from Peter Maydell to clean up permissions handling and error handling in uip/inc.c. Author: Ruud de Rooij Date: Mon Jun 5 20:13:54 2000 +0000 Use cat instead of tsort if tsort cannot deal with loops in its input (which is the case for tsort from GNU textutils). Author: Ruud de Rooij Date: Mon Jun 5 19:20:38 2000 +0000 If liblockfile is present, and its dotlockfile program is setgid, inc does not need to be setgid. Author: Ruud de Rooij Date: Sun Jun 4 20:24:39 2000 +0000 * Added autoconf test for Miquel van Smoorenburg's liblockfile library, as found on Debian systems. * Added liblockfile support to sbr/lock_file.c. Author: Shantonu Sen Date: Thu Jun 1 06:57:57 2000 +0000 make clean now removes generated bin files. Author: Shantonu Sen Date: Wed May 31 07:22:43 2000 +0000 Made dtimep.lex more lex-friendly. Author: Shantonu Sen Date: Wed May 31 07:19:30 2000 +0000 Added back memory options for AIX to increase available memory. Took out %option noyywrap, which wasn't understood by AT&T lex, as well as the -i case-insensitivity flag. Author: Doug Morris Date: Wed May 31 05:48:06 2000 +0000 added lint targets for Makefiles and a configure test to find whether lclint or lint is installed on the system. Author: Dan Harkless Date: Wed May 31 02:27:40 2000 +0000 Applied Alec Wolman 's dropsbr.c patch: In the map_write routine, a call is made to map_open and this call is supposed to set the "clear" variable to 0 or 1, depending on whether the map file is empty or not. In mh6.8.3, this worked because map_open would set "clear" by calling the mbx_Xopen routine. In nmh, the code for mbx_Xopen was merged into mbx_open, but the interface for mbx_open doesn't support the clear variable, so that functionality was lost. The map_open interface still contains "int *clear" in the prototype, but never sets it. My patch eliminates "clear" from the map_open interface (I checked to make sure that map_write is the only client of map_open). Furthermore, my patch also sets the "clear" variable properly at the beginning of map_write by calling fstat(). This eliminates the bug in that the value of "clear" being used later in the routine was just stack garbage. Having a bad value of clear causes this next bug to be triggered: The fp file pointer was being opened with fdopen, but in two of the three switch cases it wasn't being closed. In certain cases, this was causing packf to run out of file descriptors if you attempted to pack a large folder. Author: Dan Harkless Date: Wed May 31 02:13:57 2000 +0000 A couple more tweaks to etc/Makefile.in: Generated sendfiles script was not a dependency of the `all' target, and was incorrectly included in the distribution. Author: Dan Harkless Date: Wed May 31 00:53:20 2000 +0000 INSTALL never documented the etc/*.old thing. Documented the new etc/*.prev thing (including a note to watch for diff output). Author: Dan Harkless Date: Wed May 31 00:28:14 2000 +0000 Reworded my last entry a bit. Author: Dan Harkless Date: Wed May 31 00:22:05 2000 +0000 etc/Makefile.in was incorrectly installing mts.conf.in and sendfiles.in -- fixed. Changed the suffix for the backed-up previous versions of the etc files from the ambiguous .old to .prev. Use diff and only keep the .prev file around if different. Author: Dan Harkless Date: Tue May 30 22:52:43 2000 +0000 ChangeLog: I think we should use a uniform style in this file. Reformatted Ruud's recent entries. configure: Weird. There's some timestamp screwup somewhere, perhaps in the way Makefile.in is written, that caused autoconf to get run after I did a `cvs update'. It regenerated configure, and apparently I'm using a different version of autoconf, with a different order of awk alternatives. Author: Shantonu Sen Date: Mon May 29 08:00:33 2000 +0000 Added entry for new lexing function and moving from zotnet/tws to sbr Author: Shantonu Sen Date: Mon May 29 07:48:14 2000 +0000 Updating root-level files so that zotnet/tws/Makefile is not generated. Author: Shantonu Sen Date: Mon May 29 07:44:51 2000 +0000 Synchronizing Makefiles that had gotten out of sync with directory contents. Author: Shantonu Sen Date: Mon May 29 07:43:29 2000 +0000 Updated sbr functions to include instead of . Also, update Makefile to include new functions dtime.c and dtimep.c Author: Shantonu Sen Date: Mon May 29 07:35:32 2000 +0000 Updating user programs to use instead of Author: Shantonu Sen Date: Mon May 29 07:29:08 2000 +0000 Moved date/time functions from zotnet/tws to sbr. More importantly, wrote a new lexing function dparsetime (dtimep.lex) which plays nicely with flex, needs no "sed hackery". It might work with lex, but I haven't tried. Author: Ruud de Rooij Date: Sun May 28 16:17:49 2000 +0000 * Added autoconf check for getutent(). * Changed uip/rcvtty.c and uip/slocal.c to use getutent() and friends. Since I can only check on Linux, please check if this works on other systems. Author: Ruud de Rooij Date: Sun May 28 16:15:58 2000 +0000 Added autoconf check for getutent(). Author: Ruud de Rooij Date: Sun May 28 14:42:01 2000 +0000 * Applied patch from Peter Maydell to uip/scansbr.c for more checks for write failures. * Unlink temporary file properly in uip/rcvtty.c. * Moved viamail from bindir to libdir. * Changed sendfiles into sendfiles.in, so that path to viamail is patched in. * Added gzip support to sendfiles. * Added References header to replcomps and replgroupcomps. Author: Ruud de Rooij Date: Sun May 28 12:45:53 2000 +0000 Fixed m_getfld bug which caused segmentation faults when incorporating messages which ended in multiple linefeeds crossing a buffer boundary. Author: Dan Harkless Date: Fri May 26 20:35:30 2000 +0000 msh has been unable to show MIME messages ever since 1.0. Alec Wolman tracked down the problem to the -show flag being passed to mhshow. mhshow is equivalent to the old mhn -show, so we don't need the -show anymore. Removed it. Author: Shantonu Sen Date: Fri May 12 05:19:14 2000 +0000 Moved zotnet/mf to sbr. Author: Shantonu Sen Date: Fri May 12 04:16:46 2000 +0000 zotnet/bboards no longer built by default. Author: Shantonu Sen Date: Fri May 12 02:55:36 2000 +0000 zotnet/bboards is no longer built by default. Author: Shantonu Sen Date: Fri May 12 02:51:21 2000 +0000 Removed zotnet/bboards from default build. Author: Shantonu Sen Date: Thu May 11 02:55:11 2000 +0000 Change to MACHINES to include what platforms nmh *does* compile on. Author: Shantonu Sen Date: Thu May 11 02:53:07 2000 +0000 Added on whish platforms nmh is known to compile, as polled from recent mailings to nmh-workers. Please add liberally. Author: Shantonu Sen Date: Thu May 11 02:24:59 2000 +0000 Entered minor change to sbr/Makefile.in Author: Shantonu Sen Date: Thu May 11 02:21:34 2000 +0000 Removed explicit definition of both SRCS *and* OBJS, and made OBJS simple a pattern substitution of SRCS, with suffix .c -> .o Author: Shantonu Sen Date: Thu May 11 02:14:21 2000 +0000 Added my getpass() addition to ChangeLog (after the fact, but at least it's in now). Author: Dan Harkless Date: Wed May 10 03:39:46 2000 +0000 Added mts.conf.5 page per Neil W Rickert 's report: This happens on solaris: % man mts.conf windex entry incorrect: mts.conf(5) not found. No manual entry for mts.conf. It is fixed by % echo ".so man5/mh-tailor.5" > mts.conf.5 done in the man5 directory. We need to add 'mts.conf.5' as a reference sourcing mh-tailor.5. Author: Dan Harkless Date: Wed May 10 00:02:53 2000 +0000 Prepended "Portions of this code are" to the copyright message in ruserpass.c also. Author: Dan Harkless Date: Tue May 9 21:44:15 2000 +0000 * Changed configure.in to use gcc -Wall even without --enable-debug, to prevent developers compiling optimized from introducing warnings, and to give end-users a warm, fuzzy feeling as they (hopefully) see no warnings come out (except perhaps on the lex output file) even with -Wall. * Renamed getpass() to nmh_getpass() since the prototype for getpass() varies from OS to OS, and we want to _always_ use our version of the function. Fixed all the callers to use nmh_getpass() and added it to prototypes.h. Semi-arbitrarily upped MAX_PASSWORD_LEN from 128 to 256. buf was being calloc()'d and the memory leaked -- should have just been declared as static char array. Prepended "Portions of this code are" to the copyright message, as this version has been changed significantly from the BSD version. * Added "nmh-local functions to use in preference to OS versions" section to README.developers (currently just says to use nmh_getpass() instead of system getpass()). Author: Dan Harkless Date: Tue May 9 19:56:57 2000 +0000 Oops. Forgot to commit this when I made configure changes yesterday. Author: Dan Harkless Date: Tue May 9 08:16:18 2000 +0000 Added steps to README.developers saying to change the version number to X.Y.Z+dev. Did a little rearranging and changed the FTP dir from /home/ftp to /var/ftp to reflect Doug's new machine. Author: Dan Harkless Date: Tue May 9 07:55:58 2000 +0000 Got rid of four warnings in Shantonu's new getpass.c. Needed to #include for calloc(), for ttyname(), and "h/mh.h" for adios(). Also changed ch from char to int to get rid of "comparison is always 1 due to limited range of data type" on EOF. Author: Dan Harkless Date: Tue May 9 07:13:59 2000 +0000 Alphabetized Shantonu's $pop_kinds output on configure's "pop is enabled" line. If POP3 is the only kind of POP enabled, say so, rather than just saying "yes" (which is ambiguous). Author: Dan Harkless Date: Tue May 9 06:53:21 2000 +0000 Shantonu updated the DIFFERENCES file to no longer say that APOP isn't supported, but in so doing, he removed the note that RPOP isn't supported. Put it back. Author: Dan Harkless Date: Tue May 9 06:47:50 2000 +0000 * I had alphabetized the --configure options in the --help output awhile back, but Shantonu added --enable-apop just under --enable-pop. Put it in alphabetical order and clarified what --enable-apop does vs. --enable-pop and --with-krb4. Also changed --with-mts help line from "mail transport agent" to "mail transport agent/service" so the 's' in "mts" doesn't seem to come out of nowhere. * Added two steps to "releasing nmh" in README.developers. After making the tarball, it's a good idea to diff the tree vs. the CVS tree to make sure no files got left out, and then to chown the files so that they're owned by root, preventing a Trojaning attack by a malicious remote user with a UID matching yours. Author: Shantonu Sen Date: Tue May 9 06:27:38 2000 +0000 Updated POP capability to include APOP. Author: Shantonu Sen Date: Tue May 9 06:16:52 2000 +0000 Removed unnecessary comments, such as "*This warning no longer applies*" Author: Shantonu Sen Date: Tue May 9 06:09:05 2000 +0000 Fix some compile-time warnings. Author: Dan Harkless Date: Tue May 9 04:52:55 2000 +0000 Doug informed me that the way I had restored the "lost" version histories was wrong, because `cvs checkout's of old versions of nmh wouldn't work properly. It occurs to me that this could be fixed by simply deleting those tags in the new-location *,v files, but oh well. I'm putting everything back to the way Doug originally had it. To get the old version history for a file that used to be in the top directory, you'll need to "blindly" do a `cvs log' there (even though you won't have a local copy of the file in that directory). `cvs diff' will no longer be able to diff pre-move versions vs. post-move versions -- you'll have to do a lot of manual gyrations with `cvs checkout' and then use `diff'. Author: Dan Harkless Date: Tue May 9 04:08:55 2000 +0000 Okay, now that the old revisions have been recreated, deleting the file. The new version is in the 'docs' subdirectory. Author: Dan Harkless Date: Tue May 9 04:07:15 2000 +0000 This is the nmh-1.0.4 version from 2000-03-15 (I see that I was the one that originally made this change). Author: Dan Harkless Date: Tue May 9 04:05:46 2000 +0000 This is the nmh-1.0.3 version from 2000-01-18 (1.0.2 had no changes). Author: Dan Harkless Date: Tue May 9 04:03:55 2000 +0000 This is the nmh-1.0.1 version from 1999-05-17. Author: Dan Harkless Date: Tue May 9 03:58:04 2000 +0000 For reasons explained better elsewhere (e.g. Attic/README.developers), the version history for this file got lost. Recreating it. This version is from 1998-05-08 -- it's the original nmh-1.0 version. Author: Dan Harkless Date: Tue May 9 03:29:37 2000 +0000 After nmh 1.0.4, moved from top-level 'nmh' directory to 'nmh/docs'. Author: Dan Harkless Date: Tue May 9 03:27:53 2000 +0000 Okay. Removing it now. New location is in 'docs' subdirectory. Author: Dan Harkless Date: Tue May 9 03:25:24 2000 +0000 In the hullaballoo with moving stuff back and forth out of the docs/ directory, and trying to figure out the right way to preserve the old version history, this file's version history prior to the first move into docs/ got wiped. I introduced this file into the project after 1.0.3 was released, and was the only one to modify it until after the 1.0.4 release. The post-1.0.4 changes have survived in docs/README.developers, so I just need to check in the 1.0.4 version and tag it as such, then remove it again, to make a `cvs checkout' of nmh 1.0.4 work again. Author: Dan Harkless Date: Tue May 9 03:18:50 2000 +0000 Man, I'm a retard. Lemme try that again: Just a silly note 'cause I'm vain -- below where it currently says: Someone ("ssen" -- looks like Doug forgot to update a chroot() passwd file It originally said " u i d 6 0 0 0 4 " (or a different number), but minus the spaces. I guess after Doug added ssen into the chroot() passwd, he did a search-and-replace for the UID, which changed my comment as well, making it look like I had no way of determining who ssen was, which is silly. ;^> Author: Dan Harkless Date: Tue May 9 03:12:59 2000 +0000 Just a silly note 'cause I'm vain -- Author: Dan Harkless Date: Tue May 9 02:43:54 2000 +0000 After nmh 1.0.4, moved from top-level 'nmh' directory to 'nmh/docs'. Author: Dan Harkless Date: Tue May 9 02:36:42 2000 +0000 After nmh 1.0.4, moved from top-level 'nmh' directory to 'nmh/docs'. Author: Shantonu Sen Date: Sun May 7 06:59:15 2000 +0000 Updated pop instructions and indicated use of standard "./configure" instead of "sh configure" Author: Shantonu Sen Date: Sun May 7 06:16:43 2000 +0000 An nmh-specific getpass, to remove dependency on system getpass()es, which may or may not do what we want (including flushing input streams, and taking input from stdin in the absence of a controlling tty). Author: Shantonu Sen Date: Sun May 7 06:14:31 2000 +0000 Added getpass to SRCS and OBJS. Author: Dan Harkless Date: Sat May 6 15:53:40 2000 +0000 Removed "installing nmh" section. Moved its note about the DIFFERENCES file up next to the other MH discussion. Changed out-of-date "README" title (should have been "README.history") to "README.about -- about nmh". After committing, I'll rename the file to README.about inside the CVSROOT. Author: Dan Harkless Date: Sat May 6 15:29:19 2000 +0000 Restored lost version histories for those moved files by doing a manual `mv' in the CVSROOT on mhost. CVS badly needs a `cvs mv' command so that you can move files (without having physical access to the CVSROOT) without losing versioning. Put MACHINES back at the top level as it needs to be read before building. Fixed DIST variable in {.,docs}/Makefile.in to reflect that and to add missing entry for "INSTALL" file. Author: Dan Harkless Date: Sat May 6 15:05:02 2000 +0000 Fixed DIST targets to reflect that INSTALL and MACHINES are back at the top level. Author: Dan Harkless Date: Sat May 6 14:54:25 2000 +0000 Files that must be read before building nmh should not go in the docs directory. Moved this file back to the top level (and made a couple of stylistic and grammar tweaks while I was at it). Author: Dan Harkless Date: Sat May 6 14:19:23 2000 +0000 Deleting the versions Doug moved in with `cvs add', erasing the version history, in preparation for moving the original versions in the cvsroot. Author: Doug Morris Date: Sat May 6 11:34:02 2000 +0000 reorganized documentation to make it bit neater again Author: uid1005 Date: Fri Apr 21 17:36:37 2000 +0000 Corrected status printout when kpop is enabled Author: Dan Harkless Date: Tue Apr 18 00:17:50 2000 +0000 One final tweak to the configure --help output for --enable-masquerade. Author: Shantonu Sen Date: Mon Apr 17 22:49:39 2000 +0000 APOP supprt: Added info to ChangLog. Author: Dan Harkless Date: Mon Apr 17 22:09:00 2000 +0000 The syntax I gave in the --help output for --enable-masquerade incorrectly implied that the earlier options were prerequisites for the later options (pointed out by Scott Blachowicz). No compact, non-confusing way to specify the real syntax that I can see, so I'll just remove the []s and leave the explaining about it being okay to specify a subset to the INSTALL file. Also added a TODO item to put in proper parsing of the masquerade: line and/or --enable-masquerade so if you misspell an option you find out about it, rather than just having it silently fail (this weakness was currently only documented in comments in the mts.conf-handling code). Author: Dan Harkless Date: Mon Apr 17 22:04:33 2000 +0000 Someone (unfortunately original version history has been lost so I don't know who) changed "danh" to "your-id". That makes my introductory comment "we'll use version 1.0.4 and my mhost.com account, danh, as examples here" make no sense, though. If danh is going to be "parameterized", then 1.0.4 should be too. Doesn't make sense to parameterize one of the changing items and not the other one. If it's going to be done, danh should be changed to YOUR-ID or something and 1.0.4 (and 1_0_4) should be changed to X.Y.Z (and X_Y_Z). I just thought it'd be clearer to use real values and disclaim that fact up front. Anyhow, putting danh back until such time as someone wants to parameterize both items (and change the introductory text appropriately). Author: Dan Harkless Date: Mon Apr 17 21:25:23 2000 +0000 I had left out aclocal.m4 on the "use this order" line as I didn't think it'd ever need to be changed. Someone ("ssen" -- looks like Doug forgot to update a chroot() passwd file again) added it, but in a separate sentence. That doesn't really make sense -- added it to the main sentence. Also changed my note that none of the mailing lists require you to be subscribed to post -- not true. As I originally thought, the exmh ones do require that -- the bounce messages were just slow in coming. Author: Dan Harkless Date: Mon Apr 17 19:02:11 2000 +0000 Undeleted all the stuff Doug deleted at the top level for now. I think it's bad to lose the CVS revision history, and I don't agree that all of these files should go in the docs/ directory. Unfortunately Doug made modifications to FAQ and README.developers after moving them, and I didn't want to lose his changes, so I just mv'd the ones in the new directory to the top level. This lost the old version history for those two files -- I know there wasn't much to lose for README.developers (I originated the file and was the only one to make modifications to it until Doug's recent change), but I have no idea what information was lost in the FAQ's version history. The right thing to do on those two files probably would have been to re-make Doug's changes in the undeleted old versions and credit them to him in the CVS log. Author: Dan Harkless Date: Mon Apr 17 18:48:03 2000 +0000 Put a note saying that the paths this file refers to (stuff in docs/) are currently wrong. Author: Dan Harkless Date: Mon Apr 17 18:36:59 2000 +0000 Undeleting everything at the top level for now. Doug's comment: Sat Apr 15 10:33:00 2000 Doug Morris * moved the documentation into a "docs" subdirectory. The top-level directory was becoming messy. I also created another file MAILING-LISTS describing the various nmh lists and the archival system, and updated the FAQ to refer to it. I also created a new README in the top level that is basically a list of pointers to the various documentation. The old README I've moved to docs/README.history, since that seemed like the right thing to call it. will be lost, but he can put back a modified version when we agree on what should really go in docs/. Author: Dan Harkless Date: Mon Apr 17 18:34:40 2000 +0000 Undeleting everything at the top level for now. Author: Dan Harkless Date: Mon Apr 17 16:56:57 2000 +0000 Added note that user questions are acceptable on nmh-workers. Author: Shantonu Sen Date: Mon Apr 17 05:29:49 2000 +0000 Added that you should check in aclocal.m4 after acconfig.h, if you change it. Author: Shantonu Sen Date: Mon Apr 17 05:25:18 2000 +0000 APOP support: Making the apop option appear after pop in ./configure --help and committing in the right order to avoid unnecessary autoconfing. Author: Shantonu Sen Date: Mon Apr 17 05:12:14 2000 +0000 Don't try to figure out ruserpass - just use version from sbr/ Author: Shantonu Sen Date: Mon Apr 17 05:09:46 2000 +0000 APOP support: Use the ruserpass function in this directory for all password prompts, instead of using system functions. Author: Shantonu Sen Date: Mon Apr 17 05:08:32 2000 +0000 APOP support: If APOP is enabled, build it into inc and msgchk using $(APOPLIB). Author: Shantonu Sen Date: Mon Apr 17 05:07:03 2000 +0000 APOP support: Making APOP a ./configure option with --enable-apop, and giving more information about the types of POP support in the configuration summary. Author: Shantonu Sen Date: Mon Apr 17 05:04:05 2000 +0000 Adding APOP #defines Author: Shantonu Sen Date: Sun Apr 16 13:28:12 2000 +0000 Changed some string terminations from NULL to \0. Author: Doug Morris Date: Sat Apr 15 04:28:27 2000 +0000 Moved most of the documentation into a new "docs" subdirectory. Added a MAILING-LISTS file talking about the lists and archives, and updated the FAQ to refer to it. Author: Dan Harkless Date: Sat Apr 15 02:00:43 2000 +0000 Added a "releasing nmh" section to README.developers, while the process was fresh in my mind. Author: Dan Harkless Date: Fri Apr 14 21:38:37 2000 +0000 Okay, got that tag stuff straightened out. Now upping the version to 1.0.4+dev. Author: Dan Harkless Date: Fri Apr 14 21:26:56 2000 +0000 Oops. Had a duplicate entry. Author: Dan Harkless Date: Fri Apr 14 21:05:34 2000 +0000 Oops. Didn't do a `cvs rtag` before changing the version to 1.0.4+dev. Putting it back. Author: Dan Harkless Date: Fri Apr 14 20:47:32 2000 +0000 Upped the version number to 1.0.4+dev. Author: Dan Harkless Date: Fri Apr 14 20:40:31 2000 +0000 * Added new files README.developers, ChangeLog_MH-3_to_MH-6.6, and ChangeLog_MH-6.7.0_to_MH-6.8.4.html to DIST target in Makefile.in. * Released nmh-1.0.4. Author: Dan Harkless Date: Wed Apr 12 00:54:54 2000 +0000 Just reworded the bit about '%s' being safe not to quote (it's only safe not to quote on the -charset- line). Author: Dan Harkless Date: Wed Apr 12 00:25:23 2000 +0000 Applied Brian Campbell 's mhn.defaults.sh patch: It appears that there shouldn't be quotes around the %s in the iso-8859-1 charset entry; xterm passes the remaining arguments to the program, quoting them means that xterm thinks they're part of the program's name. %s doesn't come from MIME headers, so not quoting it is safe. Author: Doug Morris Date: Sun Apr 9 07:04:24 2000 +0000 bug fix - prevents core-dumping on scan -format '1' Author: Dan Harkless Date: Fri Apr 7 00:42:55 2000 +0000 Richard Coleman threw out a lot of old MH-specific files in nmh. Much of the stuff, indeed, is not worth saving, but there are nuggets that are very worthwhile, and should probably be added back in. Most important, IMHO, are the MH change logs, as they can help answer questions like "Why is this code like this?" or "How long has this been broken?" or "What was this ever used for?" I've added a new file to the nmh tree called ChangeLog_MH-3_to_MH-6.6. It's cobbled together from the mh-6.8.4/papers/mh*/MHCHANGES files. I've re-ordered the entries to go from newest at the top to oldest at the bottom to match the ChangeLog convention. Unfortunately there are no change logs for versions of MH prior to 3 in the MH tar files available at . Also, it appears to me that there are MH-6.6 changes that aren't documented in the logs. I've also added ChangeLog_MH-6.7.0_to_MH-6.8.4.html. This is based on mh-6.8.4/papers/changes/mh-changes.ms. The nroff format and its "catman"-type output are a pain to deal with, but I was loath to throw away the formatting, so I converted the file to HTML. The only actual markup in the body are the "" and "" tags, and "<" and ">" instead of '<' and '>', so it's quite doable to view the file in plain ASCII mode as well. Note that some of the changes this file documents as having been made in MH-6.8.4 may not be present in nmh -- Richard started with 6.8.3 and later put in certain 6.8.4 stuff. Author: Dan Harkless Date: Thu Apr 6 19:56:35 2000 +0000 Whoah, this should have been changed a long time ago. For one thing, Richard forgot to update the copyright date when he made modifications in 1999, but more significantly, this COPYRIGHT notice hasn't been changed since Richard ceded control of nmh development and it became an open-source project. Changed the COPYRIGHT notice to a BSD License, with a couple of minor wording tweaks. Copyright is assigned to "the authors of nmh", which is anyone who writes code, whether they have CVS accounts or not. Author: Dan Harkless Date: Thu Apr 6 00:22:06 2000 +0000 * Add some way to configure whether you prefer to see text/plain or text/html parts of multipart/alternative messages. Author: Dan Harkless Date: Thu Apr 6 00:11:50 2000 +0000 Applied Eric Schnoebelen 's mhshowsbr.c patch fixing apparent bugs in Dan Winship's new security quoting code: Since upgrading, I've been getting the following errors while attempting to process some MIME messages: (1) Syntax error: Unterminated quoted string exit 2 and: (2) line 1/10 (END)Segmentation fault (core dumped) (2) appears to be due to the testing of an unset pointer in mhshowsbr.c:show_multi_aux(). (1) appears to be caused by mis-quoting a filename being handed to the shell in mhshowsbr.c:show_content_aux(). Resolving the pointer reference issue in mhshowsbr.c:show_multi_aux() turned up a similar mis-quoting problem in the routine. Author: Dan Harkless Date: Fri Mar 31 04:25:26 2000 +0000 Terran Melconian pointed out that my theory as to why -help was printed as "-(help)" in the -help output was probably not the most likely scenario. Added his. ;^> Author: Doug Morris Date: Tue Mar 28 14:42:36 2000 +0000 added Todd Miller's packf patch Author: Dan Harkless Date: Fri Mar 17 20:19:43 2000 +0000 When I applied Wesley Craig's original KPOP patch, I made a change directly to config.h.in. That's a no-no since that file is automatically generated. Now that I've applied Wesley's second patch that makes things work as I had originally documented, I'm re-making the change here, but this time by properly modifying acconfig.h and then generating config.h.in from that. Author: Dan Harkless Date: Fri Mar 17 20:11:03 2000 +0000 wesley.craig@umich.edu did not document his previous KPOP patch, so I did so, and asked him to check what I wrote. Unfortunately he didn't notice my misunderstanding of his patch. I wrote that if you #define POPSERVICE "kpop", inc and msgchk will use KPOP exclusively, but if you leave it as "pop3", you can use Wesley's new -kpop switch on a given invocation. Instead, however, -kpop turned out to be necessary on every invocation, and a KPOP user complained. Applied Wesley's new patch, which makes things work like I thought his original patch did. After that, did one more clarifying pass to the documentation in inc.man and msgchk.man. Author: Dan Harkless Date: Thu Mar 16 02:40:42 2000 +0000 Added a new README.developers file. From the file: This file is intended to provide a few tips for anyone doing development on nmh. Developers who learn things "the hard way" about the nmh codebase (as opposed to local info best encoded in a comment) are encouraged to share their wisdom here. Currently the topics are "autoconf files" and "directory structure". Author: Dan Harkless Date: Wed Mar 15 23:37:30 2000 +0000 When I added my --enable-masquerade option, you'll note that I didn't make it --enable-nmh-masquerade. I find the --enable-nmh-* options too wordy and I'm not sure why Richard went that route. I've renamed them to just --enable-*, but the old versions will still work as well (they just aren't advertised). Added a line to the "nmh configuration" output saying whether POP is enabled. Author: Dan Harkless Date: Wed Mar 15 22:25:16 2000 +0000 When I fixed the long-standing makedir() bugs in January, I had the code call strtoul(..., 0), which I believed to be safe as all modes specified as ASCII constants in the nmh code started with a leading zero (signifying octal), which I did as it would work if internal constants were ever changed to hex. Unfortunately I was unaware of the "Folder-Protect:" .mh_profile entry, which mh-profile.man documents as an octal-only constant, with no leading zero required. I've changed the strtoul() call to an atooi() call and removed the misleading leading zeroes on the ASCII octal constants in the code and man pages. Also changed the "Folder-Protect:" example in the man page to something more interesting than a duplication of the default. Author: Dan Harkless Date: Tue Mar 14 21:21:28 2000 +0000 Added: I put Simon's patch under the control of a new #define called FIX_NON_Y2K_COMPLIANT_MUA_DATES. There's some commentary in acconfig.h about when you might not want to #define it. Author: Dan Harkless Date: Tue Mar 14 21:15:55 2000 +0000 Added missing dependency in zotnet/tws/Makefile.in for dtimep.c: dtimep.c-lexed. Author: Dan Harkless Date: Tue Mar 14 21:07:56 2000 +0000 Created new dtimep.c-lexed with Simon's change using dtimep.lex lexed on Solaris 2.6. Removed my comment about strdup(). The Solaris 2.6 failure was due to failing to do a make distclean after configuring for Ultrix 4.2A. I'll leave the change, though, since it's still a good one (just not worth reporting in the ChangeLog). Author: Dan Harkless Date: Tue Mar 14 20:50:19 2000 +0000 Changed strdup() in strdup.c to take a _const_ char*. Don't know why this didn't hit anyone before, but I wasn't able to compile on Solaris 2.6 without doing this, due to a "previous declaration" error. Author: Dan Harkless Date: Tue Mar 14 20:40:47 2000 +0000 Applied Simon Burge 's dtimep.lex patch: It seems that some MUA's didn't handle y2k very well - ELM seems to be one of them, and Ultrix's DXmail (based on MH!). I've got a few emails this month that look like: 575 Jan 00 Xxxxxx Xxxx 3603 ... and 22+ Jan 00 Xxx Xxxxx 1771 ... The first has "15 Jan 100" as the date and the second has "19 Jan 00" as the date. The following works around this so that scan, show, sortm, etc work ok. Added scan.MMDDYY and scan.YYYYMMDD format files. Author: Dan Harkless Date: Tue Mar 14 09:20:27 2000 +0000 * Applied, after some finessing, Simon Burge 's --with-smtpservers patch: Here's a patch that allows you to add --with-smtpservers= to the ./configure command line to set the "servers: " line in etc/mts.conf. Around here, we use "mailhost" so that all machines in the current domain just talk to a central machine and nothing else runs an MTA. Now, I can use --with-smtpservers=mailhost instead of having to remember to fix this by hand (and often forgetting to do so!). * Inspired by Simon's patch, added an --enable-masquerade option to configure. It will set the "masquerade:" line of mts.conf. You may specify a subset of the three types of masquerading, like --enable-masquerade="draft_from mmailid", or leave off explicit arguments to enable all three types. * Alphabetized the --enable and --with options in configure.in and INSTALL and added documentation of the two new options to the latter. * Added new dependency for mts.conf: Makefile. If this isn't done, then when you reconfigure nmh with new values for --enable-masquerade or --with-smtpservers, you'll fail to get an updated copy of mts.conf. Author: Dan Harkless Date: Tue Mar 14 05:24:57 2000 +0000 Applied Simon Burge 's dtime.c patch: There's a wrap-around problem that affects the implementation of Zeller's congruence in dtime.c. This causes the day-of-week calculations to fail for dates after Feb 29, 2000 (probably up until some year far in the future). Author: Dan Harkless Date: Tue Mar 14 05:05:49 2000 +0000 Modified username_extension masquerading to only use the extended address on generated [Resent-]From: lines and SMTP envelope From:. With Neil's original implementation, nmh's global idea of the username was changed, which would result in inc lying and saying you had no new mail because it was looking for a mailbox called, for instance, "dan-nmh" (where username was "dan" and $USERNAME_EXTENSION was "-nmh"). While in there (adrsprintf()), added checking of snprintf()'s return code and added calls to adios() when things are not kosher. Also simplfied the really confusing REALLYDUMB #ifdef'ing, which didn't even jibe with the comment explaining REALLYDUMB in acconfig.h. Now adrsprintf() will always return just the username, even if an explicit domain is passed in (which currently doesn't happen anywhere in nmh). Author: Dan Harkless Date: Tue Mar 14 02:39:13 2000 +0000 Just removed the odd space between the "!" and the "/bin/sh". I believe some OSes might choke on that, and certainly no OS requires it. Author: Dan Harkless Date: Tue Mar 14 02:29:26 2000 +0000 Applied Sullivan N. Beck 's mhshow-suffix patch: With the patch below, you can add lines like: mhshow-suffix-application/msword: .doc mhshow-suffix-application/PostScript: .ps to the mhn.defaults file to append the given suffix to a scratch file. This allows applications which require a certain suffix to run properly. Removed -force_html from lynx entry in mhn.defaults.sh (I believe older versions of lynx lack that option) and added "mhshow-suffix-text/html: .html". Author: Dan Harkless Date: Mon Mar 6 20:19:04 2000 +0000 Applied Neil W Rickert 's msh.c patch: I finally tracked down the problem in msh that was causing errors whenever I tried to examine a 'mmdf' style mailbox. It turns out that not enough memory was being allocated with calloc(), causing memory pointers to be overwritten and corrupted. Author: Dan Harkless Date: Sat Mar 4 00:02:46 2000 +0000 Changed the new "plussed_user" option to mts.conf's "masquerade:" to "username_extension" after getting feedback from qmail users, who use '-' as a separator rather than '+'. Removed checking of $USERPLUS variable. Now check $USERNAME_EXTENSION, which needs to include the appropriate separator for your MTA ('-', '+', or whatever) as its first character. Author: Dan Harkless Date: Fri Mar 3 07:30:31 2000 +0000 Oops. I was using an older email address for Neil -- now he uses the $USERPLUS feature that I'm crediting him for. ;^> Author: Dan Harkless Date: Fri Mar 3 07:24:41 2000 +0000 Added a new "boolean" type to mh.h and TRUE and FALSE constants. Added a note to DIFFERENCES stating that it's out-of-date (Richard was the last one to update it) and that we should consider only documenting incompatibilities with MH there. Implemented (and documented) a third kind of username masquerading: "plussed user" masquerading. This one was suggested by Neil Rickert . It's based on sendmail's "plussed user" feature, where mail sent to + will be delivered to . When it's enabled, it's controlled by the $USERPLUS environment variable. How is it enabled? Well, that leads me to: Renamed the "mmailid:" setting in mts.conf to "masquerade:", and changed it so that rather than being a boolean, it can be set to any combination of the three values "draft_from", "mmailid", and "plussed_user". Thus it is now possible to enable the three types of masquerading individually. Fixed a bug with "mmailid" masquerading (dating back to MH?) where if it was turned on, ','s would no longer be considered GECOS field delimiters. Author: Dan Harkless Date: Thu Mar 2 08:20:00 2000 +0000 Oops. You can't just change comments in configure.in, or configure won't be modified (it doesn't contain the comments) and you won't be able to commit it, and then the timestamps'll be messed up for everyone and unnecessary autoconf calls will occur. Added some unnecessary (but frequently used in the file) trailing 'dnl's on some AC_SUBST()s. Author: Dan Harkless Date: Thu Mar 2 07:56:00 2000 +0000 Oops. My last group commit comment failed to mention what I was doing in this file. I was adding: * Change all man pages to group all the commandline options together in one section with each as a separate mini-heading. Having to dig through prose to find what a particular option does is a pain in the nads. This time, moved it out of the [POSSIBILITIES] section and put it in the [TODO] section, as I feel it's very important (and wouldn't be that difficult to do -- somewhat time-consuming, yes, but not difficult). Author: Dan Harkless Date: Thu Mar 2 07:52:47 2000 +0000 Changed the GECOS-field '&' translation behavior to be controlled by the BSD42 #define rather than GCOS_HACK, since it's apparently always appropriate on OSes where BSD42 is #defined, and never appropriate on any other OSes. Thanks to Kimmo Suominen for responding to my "What is this code here for?" comment in mts.c and explaining the feature. Also added ULTRIX 4.2A to the list of OSes that have an initgroups() function but no prototype in the system headers. Author: Dan Harkless Date: Tue Feb 29 06:17:58 2000 +0000 Made a goofy change so that I could produce a new configure because when I checked in the last version I did it with "cvs commit ... configure configure.in ..." and that apparently gives configure.in a newer timestamp than configure, which results in spurious autoconf runs when people download the source. We need to write a little note to developers somewhere saying what in order you need to check in those autoconf files and how long you need to wait in between each one and such... Author: Dan Harkless Date: Tue Feb 29 05:59:16 2000 +0000 Changed "echo > stamp-h.in" in Makefile.in to "date > stamp-h.in" so that stamp-h.in will be different each time configure.in and related files are changed, making it easier to check it in (which is necessary to prevent unnecessary autoconf calls). My declaration of initgroups() in slocal.c to eliminate the "no prototype" warning wasn't portable (FreeBSD 3.[23] choked). Now use AC_EGREP_HEADER to see where initgroups() is declared, if anywhere. Author: Dan Harkless Date: Tue Feb 29 05:16:35 2000 +0000 Upped the version number to 1.0.3+dev (ideally this should be done by whoever makes a release tar file, immediately after doing so). Applied Paul Fox 's scansbr.c patch, posted to comp.mail.mh, which he says prevents loss of mail when inc'ing into a full filesystem. Author: Ruud de Rooij Date: Mon Feb 28 17:09:02 2000 +0000 * Fix security hole in mhshowsbr.c which allowed untrusted shell code to be executed. * Released nmh 1.0.3. Author: Dan Harkless Date: Thu Feb 10 18:50:23 2000 +0000 Oops. %-escapes on mhstore lines in mhn.defaults.sh should not be surrounded by single quotes, as a shell is not spawned when just saving files, and the filenames will end up with literal quotes embedded in them. Author: Dan Harkless Date: Fri Feb 4 20:36:43 2000 +0000 Removed an item that Richard did without removing its TODO, and removed an item that was duplicated in two different priority sections. Author: Dan Harkless Date: Fri Feb 4 20:34:07 2000 +0000 Whoever originally added the -help switch to all the commands got too cute and had the option itself print out as "-(help)" in the -help output. I guess the idea was to make reference to the fact that clearly you know about the -help option since you're currently looking at its output. I think it's a bad idea to overload the meaning of the parentheses, however -- they're supposed to indicate what abbreviated prefix of the switch you're allowed to specify. It doesn't make sense to show that you're allowed to "abbreviate" the switch to its entire length. Author: Dan Harkless Date: Fri Feb 4 20:28:23 2000 +0000 Whoever originally added the -help switch to all the commands got too cute and had the option itself print out as "-(help)" in the -help output. I guess the idea was to make reference to the fact that clearly you know about the -help option since you're currently looking at its output. I think it's a bad idea to overload the meaning of the parentheses, however -- they're supposed to indicate what abbreviated prefix of the switch you're allowed to specify. It doesn't make sense to show that you're allowed to "abbreviate" the switch to its entire length. Author: Dan Harkless Date: Fri Feb 4 01:46:29 2000 +0000 Modified INSTALL and config.h.in to reflect the new -kpop feature. Author: Dan Harkless Date: Fri Feb 4 01:32:12 2000 +0000 * Applied wesley.craig@umich.edu's KPOP patches. According to him: The following patch fixes a problem with requesting a service key for a machine that has multiple 'A' records. It also makes "-kpop" a command line option, for users who would like to use both "kpop" and "pop". Did no testing of the new features, as I don't have access to a KPOP server. One tweak I made to the patch he sent to nmh-workers was to move the declaration of his new hp2 variable into the #ifdef KPOP section so you don't get an "unused variable" warning when compiling without KPOP. * Modified inc.man and msgchk.man to document Wesley's new -kpop. Author: Dan Harkless Date: Sat Jan 29 01:34:20 2000 +0000 Added check for lynx to write mhshow-show-text/html line in mhn.defaults.sh. Author: Dan Harkless Date: Fri Jan 28 23:29:06 2000 +0000 Made a couple of minor whitespace changes to test if the latest beta version of CVS fixes this bug: dilvish-dan> cvs commit ../ChangeLog mhn.defaults.sh danh@mhost.com's password: Warning: Remote host denied X11 forwarding, perhaps xauth program could not be run on the server side. cvs: lock.c:179: lock_name: Assertion `*short_repos++ == '/'' failed. Terminated with fatal signal 6 cvs commit: saving log message in /tmp/cvslIx_yb Author: Dan Harkless Date: Fri Jan 28 22:00:33 2000 +0000 All %-escapes in mhn.defaults that actually expand to something should be surrounded by single quotes. Added quotes to the ones in mhn.defaults.sh that were missing them. Author: Dan Harkless Date: Thu Jan 27 20:20:01 2000 +0000 makedir() had multiple bugs dating back to MH. It passed an octal constant to atoi(), which interpreted it as decimal, resulting in directories with no user read or execute permissions, making nested directory creation fail. Also, when creating a nested directory, correct permissions were only set on the inner one. A second `make install' would always fail because the check for whether mh_profile.5 existed was written incorrectly. Author: Dan Harkless Date: Thu Jan 27 20:14:58 2000 +0000 Doug's check for whether mh_profile.5 exists was bad -- it looked in the local directory rather than the installation directory, so the check would always return false and re-installation when mh_profile.5 did exist would bomb out. Author: Dan Harkless Date: Thu Jan 27 20:12:38 2000 +0000 Fixed multiple bugs in makedir(). First off, when creating nested folders, it only set permissions properly on the innermost one. Secondly, it passwd an octal constant to atoi(), which only works on decimal numbers, resulting in directories with no user read or execute permission, making creation of nested dirs fail. Also added a comment wondering why we do special processing when euid != uid. If no one disagrees with my comments, I'll remove that weird code in the future. Author: Dan Harkless Date: Wed Jan 26 21:35:43 2000 +0000 Dan Winship informed me that the right fix when gcc -Wall complains about char indexes to arrays is to cast to unsigned char, not int. You want to prevent negative indexes into the array. Author: Dan Harkless Date: Wed Jan 26 10:16:32 2000 +0000 Added documentation on both types of masquerading to post's man page. Also clarified some wording and added a note that the new type of masquerading has been implemented only for post, not for the undocumented spost backend. Author: Dan Harkless Date: Wed Jan 26 10:14:14 2000 +0000 Expanded the mention of the $SIGNATURE environment variable to talk about the three different ways to override "From:" header construction. Also added mh-tailor(5) to the "SEE ALSO" section. Author: Dan Harkless Date: Wed Jan 26 09:27:59 2000 +0000 Just added a comment explaining that akvalue() does mh alias substitution. Author: Dan Harkless Date: Wed Jan 26 09:26:23 2000 +0000 I had my envelope-From:-setting in the wrong place in the code, before alias processing was done. Put it in the right place, and properly implemented Resent-From:-handling, which I had neglected before. Author: Dan Harkless Date: Wed Jan 26 09:24:15 2000 +0000 Added a comment bemoaning the lack of aliasing on the From: header and explaining why I wasn't going to bother implementing my new draft-From:-based email address masquerading right now. Author: Dan Harkless Date: Wed Jan 26 06:51:50 2000 +0000 Doug's portability fix of my setgid inc autodetection had a caching bug -- if you re-ran configure, uip/Makefile would be corrupted, and installation would fail on OSes where inc needs to be setgid. Implemented a new kind of email address masquerading. When a user writes a custom "From:" header in a draft, nmh uses it rather than generating one. However, the user's true address is used in the SMTP envelope "From:" and is revealed in the "Sender:" header. Now, when mmailid is set to non-zero, the envelope "From:" uses the address specified in the draft "From:" header, and there is no "Sender:" header. This is useful when sending on behalf of a remote POP3 account or when remote mail robots incorrectly use the envelope "From:" in preference to the body "From:". Author: Dan Harkless Date: Wed Jan 26 06:39:49 2000 +0000 I'm surprised this didn't hit anyone sooner. Doug's portability fix of my setgid inc autodetection didn't do its caching properly. It cached the variable $nmh_cv_ls_mail_grp (previously $nmh_group_mailspool), but did substitution on $MAIL_SPOOL_GRP (previously $MAILGROUP) without setting the latter to the former. That meant that when re-running configure, $MAIL_SPOOL_GRP would be NULL, so the $(MAIL_SPOOL_GRP) Make variable would be NULL, and installation would fail with the error "install: 2755 does not exist" (since the argument to -g was missing). Author: Dan Harkless Date: Wed Jan 26 05:40:30 2000 +0000 Implemented a new type of username masquerading, which is also activated by setting mmailid to non-zero in mts.conf. The new type is based on the From: header in the message draft rather than the GECOS field of the passwd file like the old type. With mmailid turned off, when a user specifies a custom From: header in a draft, it'll be used, but the user's real address will be revealed in the SMTP envelope From: and in the Sender: header. With mmailid on, this revelation is disabled. Also copied to here my new comment from mh.h explaining (if I understand it correctly) the functionality of struct swit's minchars field. Also, changed the minchars for "help" from 4 to 0. It doesn't make sense to use a positive integer that's the exact length of the option. That'll make it print out like "-(help)". The parentheses are supposed to go around the minimum part of the option you need to specify when abbreviating it. Perhaps someone thought it would be cute to put "help" in parentheses to imply that you know about it already as you just specified it be seeing the current output, but I think this "overloading" of the meaning of the parentheses is awkward. I need to go around and change "help" to 0 everywhere, but it's getting too late to do it tonight. Also added some other explanatory comments to existing code. Author: Dan Harkless Date: Wed Jan 26 05:28:33 2000 +0000 Updated to reflect that there are now two types of username masquerading (GECOS-based, the old one, and draft-From:-based, the new one). Also clarified existing wording. Author: Dan Harkless Date: Wed Jan 26 05:03:07 2000 +0000 Documented the minchars field of struct swit to the best of my understanding. Author: Dan Harkless Date: Wed Jan 26 05:01:06 2000 +0000 Modified the mmailid comment to reflect that there are now two types of masquerading (wouldn't want sysadmins to not realize that by allowing one, they're allowing the other). I also prefer my new wording of "allow" vs. the old "turn on" because the latter implied that masquerading would take effect just by setting that variable (not the case unless /etc/passwd had been previously modified to have the s). Author: Dan Harkless Date: Wed Jan 26 04:57:57 2000 +0000 Whoever changed all the references to nmh-workers@math.gatech.edu to nmh-workers@mhost.com missed this file. Author: Dan Harkless Date: Wed Jan 26 04:54:30 2000 +0000 Changed Mmailids to an extern so that we can access it from post.c to see if we should do the new draft-From:-based masquerading. Also clarified some comments now that there are two different types of masquerading. Author: Dan Harkless Date: Tue Jan 25 21:06:09 2000 +0000 Just clarified a couple of points in my last change description. Author: Dan Harkless Date: Tue Jan 25 07:45:10 2000 +0000 The prototype I gave for initgroups() which was documented in the AIX 4.1 info page conflicted with the real one that comes from grp.h on Solaris 2.6. Adjusted it so the local prototype is correct on both (hopefully all) platforms. Also added an include of , which is where initgroups() lives on HP-UX 10.20. Author: Dan Harkless Date: Tue Jan 25 07:10:25 2000 +0000 I kept going back and forth checking in new pointless revisions of configure[.in], but it now looks like the problem was that stamp-h.in was older than configure.in (or maybe there were two problems). Hopefully this'll get rid of the needless auto* calls. Author: Dan Harkless Date: Tue Jan 25 06:56:25 2000 +0000 Shoot. Apparently it gets the timestamp from the check-in time rather than preserving the actual timestamp on the file when you check it in, so the timestamp was the same for configure.in and configure, so the Makefile was doing an autoconf just in case. This time I'm checking in configure.in first and configure at least a second later. What a pain. Author: Dan Harkless Date: Tue Jan 25 06:46:13 2000 +0000 Accidentally checked in configure with older date than configure.in, but I hadn't made changes to configure.in that would result in a different configure, so I can't check one in with the right timestamp. Therefore, I made a meaningless change to configure.in (adding a "dnl" to the end of line that was like others that had "dnl" at the end but didn't have one itself) and regenerated configure. Author: Dan Harkless Date: Tue Jan 25 06:21:38 2000 +0000 The conditional definition of the "np" variable didn't make any sense. It was only defined if HAVE_GETHOSTBYNAME was defined and only used when HAVE_GETHOSTBYNAME wasn't defined. I'm kind of surprised that never blew up anywhere. Changed the definition conditional to match the usage conditional. Author: Dan Harkless Date: Tue Jan 25 06:19:51 2000 +0000 Got rid of the rest of the warnings that I didn't have time for on 1999-07-15 (and, it would seem, some new ones people introduced since then). The primary ones were the warnings that default prototypes were being used for [v]snprintf() and str[n]casecmp(). As of right now, there are _no_ compilation warnings except on the lex output file (at least under AIX 4.1.5 and Solaris 2.6). Author: Dan Harkless Date: Tue Jan 25 06:18:54 2000 +0000 On AIX 4.1, snprintf() is defined in libc.a but there's no prototype in or elsewhere. Apparently it's not officially supported (though it seems to work perfectly and IBM apparently uses it in internal code). Anyhow, if we omit our own snprintf() and vsnprintf() prototypes when we HAVE_SNPRINTF, we get a billion warnings at compile time. Use the C preprocessor to preprocess stdio.h and make sure that there's actually a prototype. Define HAVE_SNPRINTF_PROTOTYPE if so, and use that to control our local prototype definition. Also, define strcasecmp() and strncasecmp() here all the time since we define our own versions and always use them. The only way we could get into trouble doing this would be if the vendor's versions didn't have the same parameters, but I don't see that happening. If we don't define them here, we get warnings all over the place that default prototypes are being used for 'em, and the system header to include varies from OS to OS. Author: Dan Harkless Date: Tue Jan 25 06:13:38 2000 +0000 On AIX 4.1, snprintf() is defined in libc.a but there's no prototype in or elsewhere. Apparently it's not officially supported (though it seems to work perfectly and IBM apparently uses it in internal code). Anyhow, if we omit our own snprintf() and vsnprintf() prototypes when we HAVE_SNPRINTF, we get a billion warnings at compile time. Use the C preprocessor to preprocess stdio.h and make sure that there's actually a prototype. Define HAVE_SNPRINTF_PROTOTYPE if so, and use that to control our local prototype definition. Author: Dan Harkless Date: Tue Jan 25 06:06:18 2000 +0000 Added include of signals.h for SIGNAL() prototype. Author: Dan Harkless Date: Tue Jan 25 06:04:29 2000 +0000 Added include of mh.h for snprintf() prototype. Author: Dan Harkless Date: Tue Jan 25 06:00:22 2000 +0000 Added include of mh.h to get snprintf() prototype and changed all references to getcpy() to our_getcpy() to prevent conflict with the external one. Author: Dan Harkless Date: Tue Jan 25 05:58:26 2000 +0000 Put in a prototype for stdio internal function _filbuf() to get rid of the "default prototype" warning (only do this when we didn't #define it to something specific due to another #define telling us to do so). Author: Dan Harkless Date: Tue Jan 25 05:55:20 2000 +0000 Put in a prototype for client() to get rid of the "default prototype" warning. The prototype should really go in a new client.h file or somewhere, but I don't have time right now for that. Author: Dan Harkless Date: Tue Jan 25 05:53:40 2000 +0000 Typecast to get rid of warnings that index into cc[] is a char. Author: Dan Harkless Date: Tue Jan 25 05:52:31 2000 +0000 Put in prototype for initgroups() to get rid of "default prototype" warning. On AIX 4.1, at least, the function exists in libc.a but doesn't exist in any .h. Author: Dan Harkless Date: Tue Jan 25 05:50:12 2000 +0000 Typecast to get rid of warnings that array index into types[] is a char. Author: Ruud de Rooij Date: Thu Jan 6 21:30:07 2000 +0000 * Move mhtest from bindir to libdir. * Move sendfiles from libdir to bindir. * Updated sendfiles manpage to reflect this change. * Added documentation for -build and -file switches to repl and forw manpages (patch from Peter Maydell). * Fixed interaction between specifying -cc in profile and -group on command-line. Author: Dan Harkless Date: Thu Nov 11 01:01:07 1999 +0000 * Add command to reverse the action of rmm [-nounlink] -- "urmm"? "umm"? "um"? * Allow user customization of which kinds of text parts in multipart/alternative messages are preferred. It would be nice if one selectable behavior would be to be prompted at runtime for which version to show. * Add a new %-escape that makes temp files more permanent than %f, so that you can use gnuclient -q or netscape -remote on message parts. Put netscape -remote in mhn.defaults for text/html once this is done. Author: Dan Harkless Date: Tue Nov 2 21:49:47 1999 +0000 Changed the version number from 1.0.3 to 1.0.2+dev. There was not unanimous support for my proposed even/odd release/developer version number dichotomy. 1.0.2+dev implies release 1.0.2 plus some development. Author: Dan Harkless Date: Fri Oct 29 20:42:13 1999 +0000 Upped the version number to 1.0.3. If we don't do this, then when people report bugs against 1.0.2, we won't know "which" 1.0.2 they're talking about (since the development source is publically available via CVS). I think the Linux kernel version numbers are a good model, so the next time we roll a tarball, it should be version 1.0.4 (or higher -- anyhow, an even-numbered version). Author: Doug Morris Date: Fri Oct 29 05:10:18 1999 +0000 updated INSTALL directions Author: Doug Morris Date: Fri Oct 29 04:49:01 1999 +0000 release nmh-1.0.2 Author: Doug Morris Date: Fri Oct 29 04:32:50 1999 +0000 updated the TODO list and bumped the revision to 1.0.2. Author: Doug Morris Date: Wed Oct 27 05:21:12 1999 +0000 fixed test in Makefiles for LIBTOOL for the case where it doesn't exist Author: Doug Morris Date: Tue Oct 26 21:12:36 1999 +0000 fixed libtool check, sort of... Author: Doug Morris Date: Thu Oct 21 18:59:35 1999 +0000 changes to allow building under Mac OS X/Rhapsody Author: Ruud de Rooij Date: Sun Oct 17 17:39:22 1999 +0000 * Changed repl defaults to partly revert to MH behaviour: "-cc all" is now only implied with -group. * The replcomps template includes cc: header again (as in MH). * Updated repl man page to reflect these changes. Author: Doug Morris Date: Sat Oct 16 00:56:05 1999 +0000 sunos/solaris modifications Author: Doug Morris Date: Fri Oct 15 22:38:55 1999 +0000 replaced the BIND guess (based on BSDishness) with checks for gethostbyname and sethostent Author: Doug Morris Date: Wed Oct 13 14:56:41 1999 +0000 fixed bug in mh-profile/mh_profile manpage link - it did not check first Author: Doug Morris Date: Wed Oct 13 13:58:41 1999 +0000 updated manpage's Makefile and modified the way configure tests to see whether it should define LINUX_STDIO. Author: Dan Harkless Date: Mon Oct 4 22:23:29 1999 +0000 Added '-L' to the calls of 'ls' in configure.in -- I have seen multiple machines in the past where the mail spool was a symlink to a directory on another device with more free space. Author: Dan Harkless Date: Sat Oct 2 06:00:54 1999 +0000 * Fixed a portability problem in Doug's fix of a portability problem in my MAILGROUP autoconf support ('ls -l' vs. 'ls -lg'). Author: Dan Harkless Date: Sat Oct 2 06:00:11 1999 +0000 I didn't like the double use of "MAILGROUP" for two different variables used in different languages, with different values. I renamed Doug's new Makefile "MAILGROUP" to MAIL_SPOOL_GRP. Author: Dan Harkless Date: Sat Oct 2 05:57:23 1999 +0000 Touched because I changed configure.in. Author: Dan Harkless Date: Sat Oct 2 05:55:54 1999 +0000 Doug's fix for my MAILGROUP autoconf support on his platform (yep, I was ignorant about that "wheel" group) broke it on my platforms (AIX 4.1.5.0.01 and Solaris 2.6). `ls -lg` doesn't do what Doug was expecting on these platforms -- it displays _only_ the group rather than the user and the group (thus awk '{print $4}' did the wrong thing). Also did some miscellaneous cleanup, like making variables that were intended to be cached actually be cached (renamed to nmh_cv_*, etc.), and using the $AWK that we've auto-detected rather than relying on the $PATH to find one. Author: Ruud de Rooij Date: Sun Sep 26 17:45:55 1999 +0000 * Added config.sub and config.guess to the list of files to be distributed. * Fixed bug in sbr/fmt_scan.c where an extra newline would be added if a list of addresses was split over several header lines. * In mts/smtp/smtp.c, undefine strlen and strcpy if they are macros, regardless of platform. * Allow q to quit mhshow, and n to skip to next part. Patch from Kimmo Suominen . * Modified mhstore to recognize attachments created by sendfiles with x-conversions=gzip. Author: Doug Morris Date: Mon Sep 13 19:23:29 1999 +0000 moved canonical guesses back into user config section of config.h Author: Doug Morris Date: Mon Sep 13 18:20:28 1999 +0000 updates to post.c and termsbr.c that prevent warnings on OpenBSD Author: Doug Morris Date: Sun Sep 12 13:50:11 1999 +0000 Lots of little code cleanups to prevent warnings - mostly making sure some function prototypes are available at compile time. Also fixed Makefile.in so that make nmhdist will work -- it just blew up after COMPLETION-TCSH was added and ZSH-COMPLETION was changed to COMPLETION-ZSH. Author: Doug Morris Date: Sun Sep 12 07:19:40 1999 +0000 updating changelog, should have been done with last commit Author: Doug Morris Date: Sun Sep 12 06:44:02 1999 +0000 fix for configure to find db1/ndbm.h in new linux systems Author: Doug Morris Date: Fri Sep 10 05:22:40 1999 +0000 configure, configure.in stamp-h.in, and uip/Makefile.in modified to fix MAILGROUP test. m_getfld.c - added the patch submitted by Richard Cohen to fix crashing when mh_profile has no trailing newline. smtp.c, lock_file.c, m_scratch.c, m_tmpfil.c, mhscmds.c, rcvtty.c, and spost.c modified to fix mkstemp bugs. Some I've simply commented out because the repair requries either creating another new tempfile function (there are 3 already) or cleaning up the existing tmpfile functions and all the calls to them. I'm opting for the latter but it will take a while. Author: Dan Harkless Date: Tue Sep 7 23:45:20 1999 +0000 Renamed ZSH.COMPLETION to COMPLETION-ZSH and added COMPLETION-TCSH. Author: Dan Harkless Date: Tue Sep 7 23:41:37 1999 +0000 New file along the lines of the old ZSH.COMPLETION, but for tcsh. Pretty bare right now. Author: Dan Harkless Date: Tue Sep 7 23:34:00 1999 +0000 Renamed to COMPLETION-ZSH so it'll alphabetize next to new COMPLETION-TCSH. Author: Dan Harkless Date: Tue Sep 7 23:29:14 1999 +0000 Renamed from ZSH.COMPLETION so it'll alphabetize next to new COMPLETION-TCSH. Author: Dan Harkless Date: Wed Aug 18 00:05:24 1999 +0000 Crap. That's what I get for using vi instead of xemacs for a change. Inserted missing newline. Author: Dan Harkless Date: Wed Aug 18 00:01:28 1999 +0000 Just adding some text to this file so that cvs will see a difference and let me check it in. Every time acconfig.h or configure.in are changed (which I just did), the timestamp on this file needs to be updated or when people do a make an unnecessary `cd . && autoheader` will be done, and not everybody has the autoconf tools installed. The next person to change those two files (or aclocal.m4) will need to change this text, maybe just to a message saying which dependency files were changed and by whom. Author: Dan Harkless Date: Tue Aug 17 23:31:23 1999 +0000 Automated #define of MAILGROUP and installation of inc as setgid mail when the mail spool directory isn't world-writable. Author: Dan Harkless Date: Tue Aug 17 23:15:31 1999 +0000 Automated #define of MAILGROUP and installation of inc as setgid mail when the mail spool directory isn't world-writable. Author: Dan Harkless Date: Tue Aug 17 23:12:42 1999 +0000 Just removed some useless whitespace that [X]Emacs' Make mode highlights as being semi-bogus. Author: Dan Harkless Date: Tue Aug 17 23:09:46 1999 +0000 Automated #define of MAILGROUP and installation of inc as setgid mail when the mail spool directory isn't world-writable. Author: Dan Harkless Date: Fri Jul 16 01:39:09 1999 +0000 * slocal -debug used to leave a copy of each message processed in /tmp. * Got rid of a ton of compilation warnings output by gcc -Wall. * rcvdistcomps no longer has "Resent-Fcc: outbox"; new rcvdistcomps.outbox does. Author: Dan Harkless Date: Fri Jul 16 01:30:05 1999 +0000 Eliminated compilation warnings. Author: Dan Harkless Date: Fri Jul 16 01:19:29 1999 +0000 Eliminated unsued sigset_t variables set and oset. Author: Dan Harkless Date: Fri Jul 16 01:16:08 1999 +0000 Previously contained the code: if (numburst == 0) if (!quietsw) admonish (NULL, "message %d not in digest format", msgnum); else adios (NULL, "burst() botch -- you lose big"); If the indentation is to be believed, this is a bug. I trusted the indentation and added {}s around the inner if(). Author: Dan Harkless Date: Fri Jul 16 01:13:05 1999 +0000 Eliminated compilation warnings. pop_action() and pop_pack() used to return garbage. They now (arbitrarily) return 0. Dunno if their return values are ever used... Author: Dan Harkless Date: Fri Jul 16 01:11:44 1999 +0000 Eliminated compilation warnings. Author: Dan Harkless Date: Fri Jul 16 01:03:34 1999 +0000 donote() previously was written such that it could return garbage. Author: Dan Harkless Date: Fri Jul 16 01:01:24 1999 +0000 err2peer() previously returned garbage. Now it returns result of callee verr2peer(). Author: Dan Harkless Date: Fri Jul 16 00:59:36 1999 +0000 Eliminated compilation warnings. Author: Dan Harkless Date: Fri Jul 16 00:53:17 1999 +0000 Eliminated compilation warnings. Author: Dan Harkless Date: Fri Jul 16 00:52:20 1999 +0000 Eliminated compilation warnings. slocal -debug left a file in /tmp for every single message it processed! Totally unacceptable since some people like to have slocal -debug in their .forward files to get better logging. Author: Dan Harkless Date: Fri Jul 16 00:50:01 1999 +0000 Changed done() from returning void to returning int so that main()s who call done() at the end can instead return done() at the end to eliminate the compilation warning about falling off the end of a non-void function. Author: Dan Harkless Date: Fri Jul 16 00:48:59 1999 +0000 Changed from returning void to returning int so that main()s who call done() at the end can instead return done() at the end to eliminate the compilation warning about falling off the end of a non-void function. Author: Dan Harkless Date: Fri Jul 16 00:47:33 1999 +0000 Changed call of done() to return of done() to eliminate compilation warning. Author: Dan Harkless Date: Fri Jul 16 00:44:40 1999 +0000 I think it's totally inappropriate for the default rcvdistcomps to save all outgoing messages in an "outbox" folder. I have made a new file called rcvdistcomps.outbox which looks like this file used to. Author: Dan Harkless Date: Fri Jul 16 00:43:04 1999 +0000 New $(DIST_FILES) entry: rcvdistcomps.outbox. Author: Dan Harkless Date: Fri Jul 16 00:40:35 1999 +0000 I renamed the old rcvdistcomps to rcvdistcomps.outbox and removed the "Resent-Fcc: outbox" line from rcvdistcomps. Author: Doug Morris Date: Sat Jun 12 09:29:45 1999 +0000 added my name to the change Author: Doug Morris Date: Sat Jun 12 09:26:50 1999 +0000 added explanation of change made two nights ago. Author: Doug Morris Date: Wed Jun 9 20:51:59 1999 +0000 use mkstemp on systems that have it Author: Doug Morris Date: Thu May 13 14:42:34 1999 +0000 Added notes about the configure change. Author: Doug Morris Date: Thu May 13 14:28:25 1999 +0000 Modified configure to use config.guess and config.sub to auto-detect the system type and correctly set the #defines in config.h. Author: Dan Harkless Date: Thu May 13 03:42:11 1999 +0000 1.0.1 Author: Dan Harkless Date: Thu May 13 01:32:53 1999 +0000 1.0.1 patches Author: Dan Harkless Date: Thu May 13 01:31:47 1999 +0000 Update for the brave new world Author: Dan Harkless Date: Thu May 13 01:31:00 1999 +0000 Use "#include " instead of "extern int errno;". Suggested by Stephen Wilson Bailey Author: Dan Harkless Date: Thu May 13 01:28:40 1999 +0000 add a note about Irix make Author: Dan Harkless Date: Thu May 13 01:28:16 1999 +0000 man page updates from Jerry Peek Author: Dan Harkless Date: Thu May 13 01:26:41 1999 +0000 deal with SIGPIPE so mhl doesn't print "Broken pipe" if you quit out of the moreproc Author: Dan Harkless Date: Thu May 13 01:25:52 1999 +0000 Fixed a signal-handling bug that could cause whatnow to sometimes exit without prompting the user. Based on a patch by Richard Geiger . Author: Dan Harkless Date: Thu May 13 01:24:47 1999 +0000 Changed configure.in's check for sigsetjmp to properly deal with systems like Linux where it is a macro. From . Author: Dan Harkless Date: Thu May 13 01:22:54 1999 +0000 Added -library switch so it can parse user aliases like post does. From Ruud de Rooij . Author: Dan Harkless Date: Thu May 13 01:22:03 1999 +0000 Don't add line breaks in the middle of long addresses when building a draft. Fixes a bug where repl would generate invalid headers. From Ruud de Rooij . Author: Dan Harkless Date: Thu May 13 01:17:23 1999 +0000 Allow display of 8bit encoded messages. From Kimmo Suominen . Author: Dan Harkless Date: Thu May 13 01:16:14 1999 +0000 Change ordering of a conditional to prevent a bad pointer dereference. Fixes a segv in inc (and occasionally other programs). Originally from Ruud de Rooij Author: Dan Harkless Date: Thu May 13 01:13:58 1999 +0000 Fix a buffer overrun that caused packf -mbox to mess up on Return-Path: lines. From Kimmo Suominen Author: Dan Harkless Date: Thu May 13 01:12:12 1999 +0000 Make whatnow "list" work with "lproc: show" again. From Ruud de Rooij Author: Dan Harkless Date: Thu May 13 01:10:45 1999 +0000 add HAVE_LIBM Author: Dan Harkless Date: Thu May 13 01:07:15 1999 +0000 Add check for modf and link with -lm if it's not in libc. Needed for at least Digital UNIX. Problem noted by Kevin Oberman Author: Dan Harkless Date: Thu May 13 01:05:49 1999 +0000 Fix krb4 code to work with the original krb4 libraries as well as the krb5-compat ones. Based on a patch by Assar Westerlund Author: Dan Harkless Date: Thu May 13 01:03:23 1999 +0000 Properly deal with relative folder names. Problem noted by Jerry Peek Author: Doug Morris Date: Fri Apr 30 18:08:34 1999 +0000 Initial revision nmh-1.7.1-RC3/compile000755 007761 000024 00000016245 12070355546 014357 0ustar00kenhstaff000000 000000 #! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2012-10-14.11; # UTC # Copyright (C) 1999-2012 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' # We need space, tab and new line, in precisely that order. Quoting is # there to prevent tools from complaining about whitespace usage. IFS=" "" $nl" file_conv= # func_file_conv build_file lazy # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. If the determined conversion # type is listed in (the comma separated) LAZY, no conversion will # take place. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv/,$2, in *,$file_conv,*) ;; mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_cl_dashL linkdir # Make cl look for libraries in LINKDIR func_cl_dashL () { func_file_conv "$1" if test -z "$lib_path"; then lib_path=$file else lib_path="$lib_path;$file" fi linker_opts="$linker_opts -LIBPATH:$file" } # func_cl_dashl library # Do a library search-path lookup for cl func_cl_dashl () { lib=$1 found=no save_IFS=$IFS IFS=';' for dir in $lib_path $LIB do IFS=$save_IFS if $shared && test -f "$dir/$lib.dll.lib"; then found=yes lib=$dir/$lib.dll.lib break fi if test -f "$dir/$lib.lib"; then found=yes lib=$dir/$lib.lib break fi if test -f "$dir/lib$lib.a"; then found=yes lib=$dir/lib$lib.a break fi done IFS=$save_IFS if test "$found" != yes; then lib=$lib.lib fi } # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () { # Assume a capable shell lib_path= shared=: linker_opts= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. eat=1 case $2 in *.o | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift ;; *) func_file_conv "$2" set x "$@" -Fe"$file" shift ;; esac ;; -I) eat=1 func_file_conv "$2" mingw set x "$@" -I"$file" shift ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; -l) eat=1 func_cl_dashl "$2" set x "$@" "$lib" shift ;; -l*) func_cl_dashl "${1#-l}" set x "$@" "$lib" shift ;; -L) eat=1 func_cl_dashL "$2" ;; -L*) func_cl_dashL "${1#-L}" ;; -static) shared=false ;; -Wl,*) arg=${1#-Wl,} save_ifs="$IFS"; IFS=',' for flag in $arg; do IFS="$save_ifs" linker_opts="$linker_opts $flag" done IFS="$save_ifs" ;; -Xlinker) eat=1 linker_opts="$linker_opts $2" ;; -*) set x "$@" "$1" shift ;; *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) func_file_conv "$1" set x "$@" -Tp"$file" shift ;; *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) func_file_conv "$1" mingw set x "$@" "$file" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -n "$linker_opts"; then linker_opts="-link$linker_opts" fi exec "$@" $linker_opts exit 1 } eat= case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand '-c -o'. Remove '-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file 'INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac ofile= cfile= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. # So we strip '-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no '-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # '.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use '[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: nmh-1.7.1-RC3/config/000755 007761 000024 00000000000 13243043705 014230 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/config.guess000755 007761 000024 00000127607 12070355546 015326 0ustar00kenhstaff000000 000000 #! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012 Free Software Foundation, Inc. timestamp='2012-09-25' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner. Please send patches (context # diff format) to and include a ChangeLog # entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH="i386" # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH="x86_64" fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-gnu else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-gnueabi else echo ${UNAME_MACHINE}-unknown-linux-gnueabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-gnu exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-gnu exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; i*86:Linux:*:*) LIBC=gnu eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __dietlibc__ LIBC=dietlibc #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` echo "${UNAME_MACHINE}-pc-linux-${LIBC}" exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; or32:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; padre:Linux:*:*) echo sparc-unknown-linux-gnu exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-gnu exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configury will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown case $UNAME_PROCESSOR in i386) eval $set_cc_for_build if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then UNAME_PROCESSOR="x86_64" fi fi ;; unknown) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; esac eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; c34*) echo c34-convex-bsd exit ;; c38*) echo c38-convex-bsd exit ;; c4*) echo c4-convex-bsd exit ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: nmh-1.7.1-RC3/config.h.in000644 007761 000024 00000012051 13243043464 015007 0ustar00kenhstaff000000 000000 /* config.h.in. Generated from configure.ac by autoheader. */ /* The prefix that is prepended to the name of message files when they are "removed" by rmm. This should typically be `,' or `#'. */ #undef BACKUP_PREFIX /* Define to use the Cyrus SASL library for authentication of POP and SMTP. */ #undef CYRUS_SASL /* The default lock type for the mail spool file */ #undef DEFAULT_LOCKING /* Define to 1 if `TIOCGWINSZ' requires . */ #undef GWINSZ_IN_SYS_IOCTL /* Define to 1 if you have the `arc4random' function. */ #undef HAVE_ARC4RANDOM /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_DIRENT_H /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the `flock' function. */ #undef HAVE_FLOCK /* Define to 1 if you have the `getline' function. */ #undef HAVE_GETLINE /* Define to 1 if you have the `getutxent' function. */ #undef HAVE_GETUTXENT /* Define if you have the iconv() function. */ #undef HAVE_ICONV /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `lockfile' library (-llockfile). */ #undef HAVE_LIBLOCKFILE /* Define to 1 if you have the `lockf' function. */ #undef HAVE_LOCKF /* Define to 1 if you have the `mbtowc' function. */ #undef HAVE_MBTOWC /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `mkstemps' function. */ #undef HAVE_MKSTEMPS /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_NDIR_H /* Define to 1 if you have the header file. */ #undef HAVE_STDBOOL_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if `d_type' is a member of `struct dirent'. */ #undef HAVE_STRUCT_DIRENT_D_TYPE /* Define to 1 if `tm_gmtoff' is a member of `struct tm'. */ #undef HAVE_STRUCT_TM_TM_GMTOFF /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_SYS_DIR_H /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_SYS_NDIR_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PARAM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STREAM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIME_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the header file. */ #undef HAVE_WCHAR_H /* Define to 1 if you have the header file. */ #undef HAVE_WCTYPE_H /* Define to 1 if you have the `wcwidth' function. */ #undef HAVE_WCWIDTH /* Define to 1 if you have the `X509_VERIFY_PARAM_set1_host' function. */ #undef HAVE_X509_VERIFY_PARAM_SET1_HOST /* Define as const if the declaration of iconv() needs const. */ #undef ICONV_CONST /* Directory to store dot-locking lock files */ #undef LOCKDIR /* 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. */ #undef MAILGROUP /* Program, with arguments, to provide MIME encoding. */ #undef MIMEENCODINGPROC /* Program, with arguments, to provide MIME type. */ #undef MIMETYPEPROC /* Define to enable support for multibyte character sets. */ #undef MULTIBYTE_SUPPORT /* Define to the header containing the ndbm API prototypes. */ #undef NDBM_HEADER /* Define to 1 if assertions should be disabled. */ #undef NDEBUG /* Support OAuth2 in SMTP auth. */ #undef OAUTH_SUPPORT /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Support for using readline() in whatnow */ #undef READLINE_SUPPORT /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Support TLS for session encryption. */ #undef TLS_SUPPORT /* The type of the argument of the tputs() callback */ #undef TPUTS_PUTC_ARG /* Version number of package */ #undef VERSION /* Define to 1 if `struct winsize' requires . */ #undef WINSIZE_IN_PTEM /* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a `char[]'. */ #undef YYTEXT_POINTER nmh-1.7.1-RC3/config.sub000755 007761 000024 00000105656 12070355546 014771 0ustar00kenhstaff000000 000000 #! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012 Free Software Foundation, Inc. timestamp='2012-12-06' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to . Submit a context # diff and a properly formatted GNU ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | be32 | be64 \ | bfin \ | c4x | clipper \ | d10v | d30v | dlx | dsp16xx \ | epiphany \ | fido | fr30 | frv \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 \ | ns16k | ns32k \ | open8 \ | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i386-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -kaos*) os=-kaos ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: nmh-1.7.1-RC3/configure000755 007761 000024 00000770535 13243043454 014714 0ustar00kenhstaff000000 000000 #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for nmh 1.7.1-RC3. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and $0: nmh-workers@nongnu.org about your system, including any $0: error possibly output before this message. Then install $0: a modern shell, or manually run the script under such a $0: shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='nmh' PACKAGE_TARNAME='nmh' PACKAGE_VERSION='1.7.1-RC3' PACKAGE_STRING='nmh 1.7.1-RC3' PACKAGE_BUGREPORT='nmh-workers@nongnu.org' PACKAGE_URL='' ac_unique_file="h/nmh.h" ac_default_prefix=/usr/local/nmh # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_config_libobj_dir=sbr ac_c_werror_flag= ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS nmhetcdirinst NMHETCDIRINST AM_LFLAGS OAUTH_SUPPORT CURL_USER_AGENT CURLLIB curl_config TLS_SUPPORT TLSLIB CYRUS_SASL SASLLIB rpmdir NDBM_LIBS TERMLIB ICONVLIB supported_locks default_locking MAIL_SPOOL_GRP SETGID_MAIL dotlockfilepath mailspool LN sendmailpath lspath MD5FMT MD5SUM cutpath ac_ct_AR AR LEXLIB LEX_OUTPUT_ROOT LEX YFLAGS YACC SED RANLIB AM_LDFLAGS POSTLINK AM_CPPFLAGS AM_CFLAGS MULTIBYTE_ENABLED LIBOBJS EGREP GREP CPP am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC ac_prefix_program smtpserver MTS DATE host_os host_vendor host_cpu host build_os build_vendor build_cpu build AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL READLINELIB ICONV_ENABLED' ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules with_cyrus_sasl with_tls with_oauth with_hash_backup with_mts with_smtpserver enable_dependency_tracking enable_assert with_locking enable_lockdir with_readline with_ndbm with_ndbmheader with_rpmdir ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP YACC YFLAGS NMHETCDIRINST' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures nmh 1.7.1-RC3 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/nmh] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of nmh 1.7.1-RC3:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --disable-assert turn off assertions --enable-lockdir=dir Store dot-lock files in "dir" Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-cyrus-sasl Enable SASL support via the Cyrus SASL library --with-tls Enable TLS support --with-oauth Enable OAuth2 support in SMTP and POP auth --with-hash-backup use # as the backup prefix (default: ,) --with-mts=[smtp|sendmail/smtp|sendmail/pipe] specify the default mail transport agent/service --with-smtpserver='SMTPSERVER' specify the default SMTP server [localhost] --with-locking=[dot|fcntl|flock|lockf] The default locking method for the mail spool file --with-readline enable readline editing for whatnow (default=maybe) --with-ndbm=ARG use -lARG to link with ndbm --with-ndbmheader=ARG #include to use ndbm --with-rpmdir=RPMDIR RPM build directory [RPM] Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor YACC The `Yet Another Compiler Compiler' implementation to use. Defaults to the first program found out of: `bison -y', `byacc', `yacc'. YFLAGS The list of arguments that will be passed by default to $YACC. This script will default YFLAGS to the empty string to avoid a default value of `-d' given by some make applications. NMHETCDIRINST for internal use by nmh test suite Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF nmh configure 1.7.1-RC3 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## ------------------------------------- ## ## Report this to nmh-workers@nongnu.org ## ## ------------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES # --------------------------------------------- # Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR # accordingly. ac_fn_c_check_decl () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack as_decl_name=`echo $2|sed 's/ *(.*//'` as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 $as_echo_n "checking whether $as_decl_name is declared... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { #ifndef $as_decl_name #ifdef __cplusplus (void) $as_decl_use; #else (void) $as_decl_name; #endif #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_decl # ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES # ---------------------------------------------------- # Tries to find if the field MEMBER exists in type AGGR, after including # INCLUDES, setting cache variable VAR accordingly. ac_fn_c_check_member () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 $as_echo_n "checking for $2.$3... " >&6; } if eval \${$4+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (sizeof ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else eval "$4=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$4 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_member cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by nmh $as_me 1.7.1-RC3, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers config.h" am__api_version='1.15' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='nmh' VERSION='1.7.1-RC3' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar pax cpio none' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 fi fi # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: configuring for nmh-1.7.1-RC3" >&5 $as_echo "$as_me: configuring for nmh-1.7.1-RC3" >&6;} VERSION=1.7.1-RC3 DATE=`cat ${srcdir}/DATE` { $as_echo "$as_me:${as_lineno-$LINENO}: configuring for nmh dated $DATE" >&5 $as_echo "$as_me: configuring for nmh dated $DATE" >&6;} # Check whether --with-cyrus-sasl was given. if test "${with_cyrus_sasl+set}" = set; then : withval=$with_cyrus_sasl; fi if test x"$with_cyrus_sasl" != x -a x"$with_cyrus_sasl" != xyes -a \ x"$with_cyrus_sasl" != xno; then : { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Arguments to --with-cyrus-sasl now ignored" >&5 $as_echo "$as_me: WARNING: Arguments to --with-cyrus-sasl now ignored" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Please pass the appropriate arguments to CPPFLAGS/LDFLAGS" >&5 $as_echo "$as_me: WARNING: Please pass the appropriate arguments to CPPFLAGS/LDFLAGS" >&2;} fi # Check whether --with-tls was given. if test "${with_tls+set}" = set; then : withval=$with_tls; fi # Check whether --with-oauth was given. if test "${with_oauth+set}" = set; then : withval=$with_oauth; fi # Check whether --with-hash-backup was given. if test "${with_hash_backup+set}" = set; then : withval=$with_hash_backup; fi if test x"$with_hash_backup" != x -a x"$with_hash_backup" != x"no"; then : backup_prefix="#" else backup_prefix="," fi cat >>confdefs.h <<_ACEOF #define BACKUP_PREFIX "$backup_prefix" _ACEOF # Check whether --with-mts was given. if test "${with_mts+set}" = set; then : withval=$with_mts; fi if test x"$with_mts" = x"smtp"; then : MTS="smtp" elif test x"$with_mts" = x"sendmail"; then : MTS="sendmail/smtp" elif test x"$with_mts" = x"sendmail/smtp"; then : MTS="sendmail/smtp" elif test x"$with_mts" = x"sendmail/pipe"; then : MTS="sendmail/pipe" else MTS="smtp" fi # Check whether --with-smtpserver was given. if test "${with_smtpserver+set}" = set; then : withval=$with_smtpserver; fi if test -n "$with_smtpserver"; then : smtpserver="$with_smtpserver" else smtpserver="localhost" fi if test "x$prefix" = xNONE; then $as_echo_n "checking for prefix by " >&6 # Extract the first word of "mhparam", so it can be a program name with args. set dummy mhparam; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_prefix_program+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_prefix_program in [\\/]* | ?:[\\/]*) ac_cv_path_ac_prefix_program="$ac_prefix_program" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_prefix_program="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_prefix_program=$ac_cv_path_ac_prefix_program if test -n "$ac_prefix_program"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_prefix_program" >&5 $as_echo "$ac_prefix_program" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -n "$ac_prefix_program"; then prefix=`$as_dirname -- "$ac_prefix_program" || $as_expr X"$ac_prefix_program" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_prefix_program" : 'X\(//\)[^/]' \| \ X"$ac_prefix_program" : 'X\(//\)$' \| \ X"$ac_prefix_program" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_prefix_program" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` prefix=`$as_dirname -- "$prefix" || $as_expr X"$prefix" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$prefix" : 'X\(//\)[^/]' \| \ X"$prefix" : 'X\(//\)$' \| \ X"$prefix" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$prefix" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then for ac_prog in cc gcc do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cc gcc do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 $as_echo_n "checking whether $CC understands -c and -o together... " >&6; } if ${am_cv_prog_cc_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 $as_echo "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether termios.h defines TIOCGWINSZ" >&5 $as_echo_n "checking whether termios.h defines TIOCGWINSZ... " >&6; } if ${ac_cv_sys_tiocgwinsz_in_termios_h+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #ifdef TIOCGWINSZ yes #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "yes" >/dev/null 2>&1; then : ac_cv_sys_tiocgwinsz_in_termios_h=yes else ac_cv_sys_tiocgwinsz_in_termios_h=no fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_tiocgwinsz_in_termios_h" >&5 $as_echo "$ac_cv_sys_tiocgwinsz_in_termios_h" >&6; } if test $ac_cv_sys_tiocgwinsz_in_termios_h != yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether sys/ioctl.h defines TIOCGWINSZ" >&5 $as_echo_n "checking whether sys/ioctl.h defines TIOCGWINSZ... " >&6; } if ${ac_cv_sys_tiocgwinsz_in_sys_ioctl_h+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #ifdef TIOCGWINSZ yes #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "yes" >/dev/null 2>&1; then : ac_cv_sys_tiocgwinsz_in_sys_ioctl_h=yes else ac_cv_sys_tiocgwinsz_in_sys_ioctl_h=no fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_tiocgwinsz_in_sys_ioctl_h" >&5 $as_echo "$ac_cv_sys_tiocgwinsz_in_sys_ioctl_h" >&6; } if test $ac_cv_sys_tiocgwinsz_in_sys_ioctl_h = yes; then $as_echo "#define GWINSZ_IN_SYS_IOCTL 1" >>confdefs.h fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in fcntl.h stdbool.h wchar.h wctype.h \ sys/param.h sys/time.h sys/stream.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_header_compile "$LINENO" "sys/ptem.h" "ac_cv_header_sys_ptem_h" "#if HAVE_SYS_STREAM_H # include #endif " if test "x$ac_cv_header_sys_ptem_h" = xyes; then : $as_echo "#define WINSIZE_IN_PTEM 1" >>confdefs.h fi for ac_func in wcwidth mbtowc getutxent arc4random mkstemps do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_func "$LINENO" "getline" "ac_cv_func_getline" if test "x$ac_cv_func_getline" = xyes; then : $as_echo "#define HAVE_GETLINE 1" >>confdefs.h else case " $LIBOBJS " in *" getline.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS getline.$ac_objext" ;; esac fi if test "x$ac_cv_header_wchar_h" = "xyes" -a \ "x$ac_cv_header_wctype_h" = "xyes" -a \ "x$ac_cv_func_wcwidth" = "xyes" -a \ "x$ac_cv_func_mbtowc" = "xyes"; then : $as_echo "#define MULTIBYTE_SUPPORT 1" >>confdefs.h MULTIBYTE_ENABLED=1 else MULTIBYTE_ENABLED=0 fi if test "$GCC" != yes; then case `${CC} -V 2>&1` in #( cc:*\ Sun\ C*) : CFLAGS=\ "${CFLAGS:+$CFLAGS }-v -errtags=yes -erroff=E_STATEMENT_NOT_REACHED" ;; #( *) : ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Wall" >&5 $as_echo_n "checking whether compiler supports -Wall... " >&6; } if ${nmh_cv_has_wall+:} false; then : $as_echo_n "(cached) " >&6 else nmh_saved_cflags="$CFLAGS" CFLAGS="$AM_CFLAGS $CFLAGS -Wall -Werror" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : nmh_cv_has_wall=yes else nmh_cv_has_wall=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$nmh_saved_cflags" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $nmh_cv_has_wall" >&5 $as_echo "$nmh_cv_has_wall" >&6; } test "$nmh_cv_has_wall" = "yes" && CFLAGS="${CFLAGS:+$CFLAGS }-Wall" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether compiler supports -Wextra" >&5 $as_echo_n "checking whether compiler supports -Wextra... " >&6; } if ${nmh_cv_has_wextra+:} false; then : $as_echo_n "(cached) " >&6 else nmh_saved_cflags="$CFLAGS" CFLAGS="$AM_CFLAGS $CFLAGS -Wextra -Werror" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : nmh_cv_has_wextra=yes else nmh_cv_has_wextra=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$nmh_saved_cflags" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $nmh_cv_has_wextra" >&5 $as_echo "$nmh_cv_has_wextra" >&6; } test "$nmh_cv_has_wextra" = "yes" && CFLAGS="${CFLAGS:+$CFLAGS }-Wextra" { $as_echo "$as_me:${as_lineno-$LINENO}: checking platform-specific additional CPPFLAGS" >&5 $as_echo_n "checking platform-specific additional CPPFLAGS... " >&6; } if ${nmh_cv_addl_cppflags+:} false; then : $as_echo_n "(cached) " >&6 else ac_c_werror_flag=yes nmh_saved_cppflags="$CPPFLAGS" nmh_saved_cflags="$CFLAGS" CFLAGS="$AM_CFLAGS $CFLAGS" for nmh_cv_addl_cppflags in "" "-D_GNU_SOURCE"; do CPPFLAGS="$nmh_saved_cppflags" if test x"${nmh_cv_addl_cppflags}" != x; then : CPPFLAGS="${CPPFLAGS:+$CPPFLAGS }$nmh_cv_addl_cppflags" fi if test ${MULTIBYTE_ENABLED} = 1; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { return wcwidth(0) + strdup("x") == 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : AM_CPPFLAGS="${nmh_cv_addl_cppflags}"; break; fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { return strdup("x") == 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : AM_CPPFLAGS="${nmh_cv_addl_cppflags}"; break; fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $nmh_cv_addl_cppflags" >&5 $as_echo "$nmh_cv_addl_cppflags" >&6; } CFLAGS="$nmh_saved_cflags" CPPFLAGS="$nmh_saved_cppflags" { ac_c_werror_flag=; unset ac_c_werror_flag;} if test `uname` = FreeBSD; then : CPPFLAGS="${CPPFLAGS:+$CPPFLAGS }-D_WITH_GETLINE" nmh_cv_freebsd_localbase=`echo '.include ' \ | make -k -f /dev/stdin -V LOCALBASE 2>/dev/null | sed 1q` test -z "$nmh_cv_freebsd_localbase" && nmh_cv_freebsd_localbase=/usr/local CPPFLAGS="${CPPFLAGS:+$CPPFLAGS }-I$nmh_cv_freebsd_localbase/include" LDFLAGS="${LDFLAGS:+$LDFLAGS }-L$nmh_cv_freebsd_localbase/lib" fi if test `uname` = OpenBSD; then : POSTLINK="2>&1 | sed -e \ 's/: w\(arning: s.*() is .* misused, please use\)/: W\1/'" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether linker supports -Qunused-arguments" >&5 $as_echo_n "checking whether linker supports -Qunused-arguments... " >&6; } if ${nmh_cv_has_q_unused_arguments+:} false; then : $as_echo_n "(cached) " >&6 else if test "$GCC" = yes && `${CC} --version 2>&1 | \ grep clang >/dev/null`; then : nmh_saved_ldflags="$LDFLAGS" LDFLAGS="$AM_LDFLAGS $LDFLAGS -Qunused-arguments" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : nmh_cv_has_q_unused_arguments=yes else nmh_cv_has_q_unused_arguments=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$nmh_saved_ldflags" else nmh_cv_has_q_unused_arguments=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $nmh_cv_has_q_unused_arguments" >&5 $as_echo "$nmh_cv_has_q_unused_arguments" >&6; } test "$nmh_cv_has_q_unused_arguments" = "yes" && \ AM_LDFLAGS="${AM_LDFLAGS:+$AM_LDFLAGS }-Qunused-arguments" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable assertions" >&5 $as_echo_n "checking whether to enable assertions... " >&6; } # Check whether --enable-assert was given. if test "${enable_assert+set}" = set; then : enableval=$enable_assert; ac_enable_assert=$enableval if test "x$enableval" = xno; then : $as_echo "#define NDEBUG 1" >>confdefs.h elif test "x$enableval" != xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: invalid argument supplied to --enable-assert" >&5 $as_echo "$as_me: WARNING: invalid argument supplied to --enable-assert" >&2;} ac_enable_assert=yes fi else ac_enable_assert=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_enable_assert" >&5 $as_echo "$ac_enable_assert" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed for ac_prog in 'bison -y' byacc do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_YACC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$YACC"; then ac_cv_prog_YACC="$YACC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_YACC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi YACC=$ac_cv_prog_YACC if test -n "$YACC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5 $as_echo "$YACC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$YACC" && break done test -n "$YACC" || YACC="yacc" for ac_prog in flex lex do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LEX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LEX"; then ac_cv_prog_LEX="$LEX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LEX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LEX=$ac_cv_prog_LEX if test -n "$LEX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LEX" >&5 $as_echo "$LEX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$LEX" && break done test -n "$LEX" || LEX=":" if test "x$LEX" != "x:"; then cat >conftest.l <<_ACEOF %% a { ECHO; } b { REJECT; } c { yymore (); } d { yyless (1); } e { /* IRIX 6.5 flex 2.5.4 underquotes its yyless argument. */ yyless ((input () != 0)); } f { unput (yytext[0]); } . { BEGIN INITIAL; } %% #ifdef YYTEXT_POINTER extern char *yytext; #endif int main (void) { return ! yylex () + ! yywrap (); } _ACEOF { { ac_try="$LEX conftest.l" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$LEX conftest.l") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking lex output file root" >&5 $as_echo_n "checking lex output file root... " >&6; } if ${ac_cv_prog_lex_root+:} false; then : $as_echo_n "(cached) " >&6 else if test -f lex.yy.c; then ac_cv_prog_lex_root=lex.yy elif test -f lexyy.c; then ac_cv_prog_lex_root=lexyy else as_fn_error $? "cannot find output from $LEX; giving up" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_root" >&5 $as_echo "$ac_cv_prog_lex_root" >&6; } LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root if test -z "${LEXLIB+set}"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking lex library" >&5 $as_echo_n "checking lex library... " >&6; } if ${ac_cv_lib_lex+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_LIBS=$LIBS ac_cv_lib_lex='none needed' for ac_lib in '' -lfl -ll; do LIBS="$ac_lib $ac_save_LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ `cat $LEX_OUTPUT_ROOT.c` _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_lex=$ac_lib fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext test "$ac_cv_lib_lex" != 'none needed' && break done LIBS=$ac_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lex" >&5 $as_echo "$ac_cv_lib_lex" >&6; } test "$ac_cv_lib_lex" != 'none needed' && LEXLIB=$ac_cv_lib_lex fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether yytext is a pointer" >&5 $as_echo_n "checking whether yytext is a pointer... " >&6; } if ${ac_cv_prog_lex_yytext_pointer+:} false; then : $as_echo_n "(cached) " >&6 else # POSIX says lex can declare yytext either as a pointer or an array; the # default is implementation-dependent. Figure out which it is, since # not all implementations provide the %pointer and %array declarations. ac_cv_prog_lex_yytext_pointer=no ac_save_LIBS=$LIBS LIBS="$LEXLIB $ac_save_LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define YYTEXT_POINTER 1 `cat $LEX_OUTPUT_ROOT.c` _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_prog_lex_yytext_pointer=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_yytext_pointer" >&5 $as_echo "$ac_cv_prog_lex_yytext_pointer" >&6; } if test $ac_cv_prog_lex_yytext_pointer = yes; then $as_echo "#define YYTEXT_POINTER 1" >>confdefs.h fi rm -f conftest.l $LEX_OUTPUT_ROOT.c fi if test "$LEX" = :; then LEX=${am_missing_run}flex fi if test -n "$ac_tool_prefix"; then for ac_prog in ar lib "link -lib" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar lib "link -lib" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} { $as_echo "$as_me:${as_lineno-$LINENO}: checking the archiver ($AR) interface" >&5 $as_echo_n "checking the archiver ($AR) interface... " >&6; } if ${am_cv_ar_interface+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu am_cv_ar_interface=ar cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int some_variable = 0; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5 (eval $am_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then am_cv_ar_interface=ar else am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5 (eval $am_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then am_cv_ar_interface=lib else am_cv_ar_interface=unknown fi fi rm -f conftest.lib libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_ar_interface" >&5 $as_echo "$am_cv_ar_interface" >&6; } case $am_cv_ar_interface in ar) ;; lib) # Microsoft lib, so override with the ar-lib wrapper script. # FIXME: It is wrong to rewrite AR. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__AR in this case, # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something # similar. AR="$am_aux_dir/ar-lib $AR" ;; unknown) as_fn_error $? "could not determine $AR interface" "$LINENO" 5 ;; esac pathtmp=/usr/xpg4/bin:/usr/bin:/bin:/usr/local/bin:/usr/ucb # Extract the first word of "cut", so it can be a program name with args. set dummy cut; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_cutpath+:} false; then : $as_echo_n "(cached) " >&6 else case $cutpath in [\\/]* | ?:[\\/]*) ac_cv_path_cutpath="$cutpath" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $pathtmp do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_cutpath="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_cutpath" && ac_cv_path_cutpath="no" ;; esac fi cutpath=$ac_cv_path_cutpath if test -n "$cutpath"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cutpath" >&5 $as_echo "$cutpath" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi for ac_prog in md5sum md5 do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MD5SUM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MD5SUM"; then ac_cv_prog_MD5SUM="$MD5SUM" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MD5SUM="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MD5SUM=$ac_cv_prog_MD5SUM if test -n "$MD5SUM"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MD5SUM" >&5 $as_echo "$MD5SUM" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$MD5SUM" && break done test -n "$MD5SUM" || MD5SUM="missing" case "${MD5SUM}" in #( md5sum) : MD5FMT="cat" ;; #( md5) : MD5FMT="${SED} -e 's/MD5 *(.*) *= \([0-9a-f]*\)/\1/'" ;; #( *) : MD5FMT="missing" ;; esac pathtmp=/usr/xpg4/bin:/usr/bin:/bin:/usr/local/bin:/usr/ucb # Extract the first word of "ls", so it can be a program name with args. set dummy ls; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_lspath+:} false; then : $as_echo_n "(cached) " >&6 else case $lspath in [\\/]* | ?:[\\/]*) ac_cv_path_lspath="$lspath" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $pathtmp do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_lspath="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_lspath" && ac_cv_path_lspath="no" ;; esac fi lspath=$ac_cv_path_lspath if test -n "$lspath"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lspath" >&5 $as_echo "$lspath" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$lspath" != "no"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to get ls to show us the group ownership of a file" >&5 $as_echo_n "checking how to get ls to show us the group ownership of a file... " >&6; } if ${nmh_cv_ls_grpopt+:} false; then : $as_echo_n "(cached) " >&6 else if test x"`$lspath -dl / | $AWK '{print $9}'`" = x"/"; then : nmh_cv_ls_grpopt="-l" else nmh_cv_ls_grpopt="-lg" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $nmh_cv_ls_grpopt" >&5 $as_echo "$nmh_cv_ls_grpopt" >&6; } fi pathtmp=/usr/sbin:/usr/lib:/usr/etc:/usr/ucblib:/usr/bin:/bin # Extract the first word of "sendmail", so it can be a program name with args. set dummy sendmail; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_sendmailpath+:} false; then : $as_echo_n "(cached) " >&6 else case $sendmailpath in [\\/]* | ?:[\\/]*) ac_cv_path_sendmailpath="$sendmailpath" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $pathtmp do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_sendmailpath="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_sendmailpath" && ac_cv_path_sendmailpath="/usr/sbin/sendmail" ;; esac fi sendmailpath=$ac_cv_path_sendmailpath if test -n "$sendmailpath"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $sendmailpath" >&5 $as_echo "$sendmailpath" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi case "$host_os" in #( cygwin*) : LN=cp ;; #( *) : LN=ln ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking where mail spool is located" >&5 $as_echo_n "checking where mail spool is located... " >&6; } if ${nmh_cv_mailspool+:} false; then : $as_echo_n "(cached) " >&6 else for mailspool in /var/mail /var/spool/mail /usr/spool/mail /dev/null; do test -d $mailspool && break done nmh_cv_mailspool=$mailspool fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $nmh_cv_mailspool" >&5 $as_echo "$nmh_cv_mailspool" >&6; } mailspool=$nmh_cv_mailspool if test "$lspath" != "no" -a "$cutpath" != "no"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the mail spool is world-writable" >&5 $as_echo_n "checking whether the mail spool is world-writable... " >&6; } if ${nmh_cv_mailspool_world_writable+:} false; then : $as_echo_n "(cached) " >&6 else if test "`$lspath -dlL $mailspool | $cutpath -c9`" = "-"; then nmh_cv_mailspool_world_writable=no else nmh_cv_mailspool_world_writable=yes fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $nmh_cv_mailspool_world_writable" >&5 $as_echo "$nmh_cv_mailspool_world_writable" >&6; } fi ac_fn_c_check_header_mongrel "$LINENO" "lockfile.h" "ac_cv_header_lockfile_h" "$ac_includes_default" if test "x$ac_cv_header_lockfile_h" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lockfile_create in -llockfile" >&5 $as_echo_n "checking for lockfile_create in -llockfile... " >&6; } if ${ac_cv_lib_lockfile_lockfile_create+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-llockfile $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char lockfile_create (); int main () { return lockfile_create (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_lockfile_lockfile_create=yes else ac_cv_lib_lockfile_lockfile_create=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lockfile_lockfile_create" >&5 $as_echo "$ac_cv_lib_lockfile_lockfile_create" >&6; } if test "x$ac_cv_lib_lockfile_lockfile_create" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBLOCKFILE 1 _ACEOF LIBS="-llockfile $LIBS" fi fi # Extract the first word of "dotlockfile", so it can be a program name with args. set dummy dotlockfile; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_dotlockfilepath+:} false; then : $as_echo_n "(cached) " >&6 else case $dotlockfilepath in [\\/]* | ?:[\\/]*) ac_cv_path_dotlockfilepath="$dotlockfilepath" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_dotlockfilepath="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_dotlockfilepath" && ac_cv_path_dotlockfilepath="no" ;; esac fi dotlockfilepath=$ac_cv_path_dotlockfilepath if test -n "$dotlockfilepath"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dotlockfilepath" >&5 $as_echo "$dotlockfilepath" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$ac_cv_lib_lockfile_lockfile_create" != "no" ; then if test "$ac_cv_path_dotlockfilepath" != "no" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether dotlockfile is setgid" >&5 $as_echo_n "checking whether dotlockfile is setgid... " >&6; } if ${nmh_cv_dotlockfile_setgid+:} false; then : $as_echo_n "(cached) " >&6 else if test -g "$ac_cv_path_dotlockfilepath" ; then nmh_cv_dotlockfile_setgid=yes else nmh_cv_dotlockfile_setgid=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $nmh_cv_dotlockfile_setgid" >&5 $as_echo "$nmh_cv_dotlockfile_setgid" >&6; } fi fi if test x"$DISABLE_SETGID_MAIL" != x -a x"$DISABLE_SETGID_MAIL" != x0; then : nmh_cv_dotlockfile_setgid=yes fi if test x"$with_locking" = x"dot" -a x"$nmh_cv_mailspool_world_writable" = x"no" -a x"$nmh_cv_dotlockfile_setgid" != x"yes" ; then $as_echo "#define MAILGROUP 1" >>confdefs.h SETGID_MAIL=1 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking what group owns the mail spool" >&5 $as_echo_n "checking what group owns the mail spool... " >&6; } if ${nmh_cv_ls_mail_grp+:} false; then : $as_echo_n "(cached) " >&6 else nmh_cv_ls_mail_grp=`$lspath -dL $nmh_cv_ls_grpopt $mailspool|$AWK '{print $4}'` fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $nmh_cv_ls_mail_grp" >&5 $as_echo "$nmh_cv_ls_mail_grp" >&6; } MAIL_SPOOL_GRP=$nmh_cv_ls_mail_grp { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a program to provide a MIME type string" >&5 $as_echo_n "checking for a program to provide a MIME type string... " >&6; } if ${nmh_cv_mimetype_proc+:} false; then : $as_echo_n "(cached) " >&6 else nmh_cv_mimetype_proc= for mprog in 'file --brief --dereference --mime-type' \ 'file --dereference --mime-type' \ 'file --brief --mime-type' \ 'file --mime-type' do if $mprog "${srcdir}/configure" > /dev/null 2>&1; then : nmh_cv_mimetype_proc="$mprog"; break fi done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $nmh_cv_mimetype_proc" >&5 $as_echo "$nmh_cv_mimetype_proc" >&6; } if test X"$nmh_cv_mimetype_proc" != X; then : mimetype_proc="\"${nmh_cv_mimetype_proc}\"" cat >>confdefs.h <<_ACEOF #define MIMETYPEPROC $mimetype_proc _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a program to provide a MIME encoding string" >&5 $as_echo_n "checking for a program to provide a MIME encoding string... " >&6; } if ${nmh_cv_mimeencoding_proc+:} false; then : $as_echo_n "(cached) " >&6 else nmh_cv_mimeencoding_proc= for mprog in 'file --brief --dereference --mime-encoding' \ 'file --dereference --mime-encoding' \ 'file --brief --mime-encoding' \ 'file --mime-encoding' do if $mprog "${srcdir}/DATE" > /dev/null 2>&1; then : case `$mprog "${srcdir}/DATE"` in #( us-ascii) : nmh_cv_mimeencoding_proc="$mprog"; break ;; #( *) : ;; esac fi done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $nmh_cv_mimeencoding_proc" >&5 $as_echo "$nmh_cv_mimeencoding_proc" >&6; } if test X"$nmh_cv_mimeencoding_proc" != X; then : mimeencoding_proc="\"${nmh_cv_mimeencoding_proc}\"" cat >>confdefs.h <<_ACEOF #define MIMEENCODINGPROC $mimeencoding_proc _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5 $as_echo_n "checking for library containing gethostbyname... " >&6; } if ${ac_cv_search_gethostbyname+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyname (); int main () { return gethostbyname (); ; return 0; } _ACEOF for ac_lib in '' nsl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_gethostbyname=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_gethostbyname+:} false; then : break fi done if ${ac_cv_search_gethostbyname+:} false; then : else ac_cv_search_gethostbyname=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5 $as_echo "$ac_cv_search_gethostbyname" >&6; } ac_res=$ac_cv_search_gethostbyname if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else as_fn_error $? "gethostbyname not found" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing connect" >&5 $as_echo_n "checking for library containing connect... " >&6; } if ${ac_cv_search_connect+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char connect (); int main () { return connect (); ; return 0; } _ACEOF for ac_lib in '' socket; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_connect=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_connect+:} false; then : break fi done if ${ac_cv_search_connect+:} false; then : else ac_cv_search_connect=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_connect" >&5 $as_echo "$ac_cv_search_connect" >&6; } ac_res=$ac_cv_search_connect if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else as_fn_error $? "connect not found" "$LINENO" 5 fi for ac_func in flock lockf do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done case "$host_os" in #( aix*|cygwin*|linux*) : default_locktype="fcntl" ;; #( freebsd*|*netbsd*|openbsd*|darwin*) : default_locktype="flock" ;; #( *) : default_locktype="dot" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking default locking method for the mail spool" >&5 $as_echo_n "checking default locking method for the mail spool... " >&6; } # Check whether --with-locking was given. if test "${with_locking+set}" = set; then : withval=$with_locking; else with_locking="$default_locktype" fi case $with_locking in #( fcntl|dot) : ;; #( flock) : if test x"$ac_cv_func_flock" != x"yes"; then : as_fn_error $? "flock locks not supported on this system" "$LINENO" 5 fi ;; #( lockf) : if test x"$ac_cv_func_lockf" != x"yes"; then : as_fn_error $? "lockf locks not supported on this system" "$LINENO" 5 fi ;; #( no) : as_fn_error $? "--without-locking not supported" "$LINENO" 5 ;; #( *) : as_fn_error $? "Unknown locking type $with_locking" "$LINENO" 5 ;; esac cat >>confdefs.h <<_ACEOF #define DEFAULT_LOCKING "$with_locking" _ACEOF default_locking=$with_locking { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_locking" >&5 $as_echo "$with_locking" >&6; } supported_locks="fcntl dot" if test x"$ac_cv_func_flock" = x"yes"; then : supported_locks="$supported_locks flock" fi if test x"$ac_cv_func_lockf" = x"yes"; then : supported_locks="$supported_locks lockf" fi # Check whether --enable-lockdir was given. if test "${enable_lockdir+set}" = set; then : enableval=$enable_lockdir; if test "x$enableval" = xyes; then : as_fn_error $? "--enable-lockdir requires an argument" "$LINENO" 5 fi cat >>confdefs.h <<_ACEOF #define LOCKDIR "$enableval" _ACEOF fi ICONV_ENABLED=0 ac_fn_c_check_header_mongrel "$LINENO" "iconv.h" "ac_cv_header_iconv_h" "$ac_includes_default" if test "x$ac_cv_header_iconv_h" = xyes; then : ac_fn_c_check_func "$LINENO" "iconv" "ac_cv_func_iconv" if test "x$ac_cv_func_iconv" = xyes; then : nmh_found_iconv=yes ac_fn_c_check_decl "$LINENO" "_libiconv_version" "ac_cv_have_decl__libiconv_version" "#include " if test "x$ac_cv_have_decl__libiconv_version" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libiconv in -liconv" >&5 $as_echo_n "checking for libiconv in -liconv... " >&6; } if ${ac_cv_lib_iconv_libiconv+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-liconv $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char libiconv (); int main () { return libiconv (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_iconv_libiconv=yes else ac_cv_lib_iconv_libiconv=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_iconv_libiconv" >&5 $as_echo "$ac_cv_lib_iconv_libiconv" >&6; } if test "x$ac_cv_lib_iconv_libiconv" = xyes; then : LIBS="-liconv $LIBS" fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv in -liconv" >&5 $as_echo_n "checking for iconv in -liconv... " >&6; } if ${ac_cv_lib_iconv_iconv+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-liconv $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char iconv (); int main () { return iconv (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_iconv_iconv=yes else ac_cv_lib_iconv_iconv=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_iconv_iconv" >&5 $as_echo "$ac_cv_lib_iconv_iconv" >&6; } if test "x$ac_cv_lib_iconv_iconv" = xyes; then : nmh_found_iconv=yes else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libiconv in -liconv" >&5 $as_echo_n "checking for libiconv in -liconv... " >&6; } if ${ac_cv_lib_iconv_libiconv+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-liconv $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char libiconv (); int main () { return libiconv (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_iconv_libiconv=yes else ac_cv_lib_iconv_libiconv=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_iconv_libiconv" >&5 $as_echo "$ac_cv_lib_iconv_libiconv" >&6; } if test "x$ac_cv_lib_iconv_libiconv" = xyes; then : nmh_found_iconv=yes fi fi if test "x$nmh_found_iconv" = "xyes"; then : ICONVLIB="-liconv" fi fi if test "x$nmh_found_iconv" = "xyes"; then : $as_echo "#define HAVE_ICONV 1" >>confdefs.h ICONV_ENABLED=1 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv declaration" >&5 $as_echo_n "checking for iconv declaration... " >&6; } if ${nmh_cv_iconv_const+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #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 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : nmh_cv_iconv_const= else nmh_cv_iconv_const=const fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $nmh_cv_iconv_const" >&5 $as_echo "$nmh_cv_iconv_const" >&6; } cat >>confdefs.h <<_ACEOF #define ICONV_CONST $nmh_cv_iconv_const _ACEOF fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking the argument of the tputs() callback" >&5 $as_echo_n "checking the argument of the tputs() callback... " >&6; } if ${nmh_cv_tputs_putc_arg+:} false; then : $as_echo_n "(cached) " >&6 else for tputs_arg1 in 'const char *' 'char *'; do for tputs_putc_arg in 'int' 'char'; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default #include #include int main () { extern int tputs($tputs_arg1, int, int (*)($tputs_putc_arg)); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : nmh_cv_tputs_putc_arg="$tputs_putc_arg"; break 2 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done done if test "X$nmh_cv_tputs_putc_arg" = X; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot determine tputs callback argument See \`config.log' for more details" "$LINENO" 5; } fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $nmh_cv_tputs_putc_arg" >&5 $as_echo "$nmh_cv_tputs_putc_arg" >&6; } cat >>confdefs.h <<_ACEOF #define TPUTS_PUTC_ARG $nmh_cv_tputs_putc_arg _ACEOF termcap_curses_order="termcap curses ncurses" for lib in $termcap_curses_order; do as_ac_Lib=`$as_echo "ac_cv_lib_${lib}''_setupterm" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for setupterm in -l${lib}" >&5 $as_echo_n "checking for setupterm in -l${lib}... " >&6; } if eval \${$as_ac_Lib+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-l${lib} $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char setupterm (); int main () { return setupterm (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$as_ac_Lib=yes" else eval "$as_ac_Lib=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : TERMLIB="-l$lib"; break fi done if test "x$TERMLIB" = "x"; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "Could not find setupterm in any library. Is there a curses or ncurses library or package that you can install? See \`config.log' for more details" "$LINENO" 5; } fi # Check whether --with-readline was given. if test "${with_readline+set}" = set; then : withval=$with_readline; else with_readline=maybe fi if test x"$with_readline" = xyes -o x"$with_readline" = xmaybe; then : save_LIBS="$LIBS" LIBS= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing readline" >&5 $as_echo_n "checking for library containing readline... " >&6; } if ${ac_cv_search_readline+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char readline (); int main () { return readline (); ; return 0; } _ACEOF for ac_lib in '' readline editline; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $TERMLIB $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_readline=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_readline+:} false; then : break fi done if ${ac_cv_search_readline+:} false; then : else ac_cv_search_readline=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_readline" >&5 $as_echo "$ac_cv_search_readline" >&6; } ac_res=$ac_cv_search_readline if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" READLINELIB="$LIBS" $as_echo "#define READLINE_SUPPORT 1" >>confdefs.h else if test x"$with_readline" = xyes; then : as_fn_error $? "Unable to find a readline library" "$LINENO" 5 fi fi LIBS="$save_LIBS" fi # Check whether --with-ndbm was given. if test "${with_ndbm+set}" = set; then : withval=$with_ndbm; nmh_ndbm=$withval else nmh_ndbm=autodetect fi # Check whether --with-ndbmheader was given. if test "${with_ndbmheader+set}" = set; then : withval=$with_ndbmheader; nmh_ndbmheader=$withval else nmh_ndbmheader=autodetect fi if test "$nmh_ndbm" = "autodetect"; then if test "$nmh_ndbmheader" != "autodetect"; then as_fn_error $? "must specify both --with-ndbm and --with-ndbmheader or neither" "$LINENO" 5 else if test "x" = "x"; then nmh_libs= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm in ndbm.h" >&5 $as_echo_n "checking for dbm in ndbm.h... " >&6; } else nmh_libs="-l " { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm in ndbm.h and " >&5 $as_echo_n "checking for dbm in ndbm.h and ... " >&6; } fi nmh_saved_libs="$LIBS" LIBS="$nmh_libs $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define DB_DBM_HSEARCH 1 #include int main () { dbm_open("",0,0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : nmh_ndbm_found=yes else nmh_ndbm_found=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$nmh_saved_libs" if test "$nmh_ndbm_found" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } nmh_ndbmheader="ndbm.h" nmh_ndbm="" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if test "xdb" = "x"; then nmh_libs= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm in db.h" >&5 $as_echo_n "checking for dbm in db.h... " >&6; } else nmh_libs="-ldb " { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm in db.h and db" >&5 $as_echo_n "checking for dbm in db.h and db... " >&6; } fi nmh_saved_libs="$LIBS" LIBS="$nmh_libs $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define DB_DBM_HSEARCH 1 #include int main () { dbm_open("",0,0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : nmh_ndbm_found=yes else nmh_ndbm_found=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$nmh_saved_libs" if test "$nmh_ndbm_found" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } nmh_ndbmheader="db.h" nmh_ndbm="db" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if test "xdb" = "x"; then nmh_libs= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm in ndbm.h" >&5 $as_echo_n "checking for dbm in ndbm.h... " >&6; } else nmh_libs="-ldb " { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm in ndbm.h and db" >&5 $as_echo_n "checking for dbm in ndbm.h and db... " >&6; } fi nmh_saved_libs="$LIBS" LIBS="$nmh_libs $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define DB_DBM_HSEARCH 1 #include int main () { dbm_open("",0,0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : nmh_ndbm_found=yes else nmh_ndbm_found=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$nmh_saved_libs" if test "$nmh_ndbm_found" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } nmh_ndbmheader="ndbm.h" nmh_ndbm="db" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if test "xdb1" = "x"; then nmh_libs= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm in ndbm.h" >&5 $as_echo_n "checking for dbm in ndbm.h... " >&6; } else nmh_libs="-ldb1 " { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm in ndbm.h and db1" >&5 $as_echo_n "checking for dbm in ndbm.h and db1... " >&6; } fi nmh_saved_libs="$LIBS" LIBS="$nmh_libs $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define DB_DBM_HSEARCH 1 #include int main () { dbm_open("",0,0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : nmh_ndbm_found=yes else nmh_ndbm_found=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$nmh_saved_libs" if test "$nmh_ndbm_found" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } nmh_ndbmheader="ndbm.h" nmh_ndbm="db1" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if test "xndbm" = "x"; then nmh_libs= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm in ndbm.h" >&5 $as_echo_n "checking for dbm in ndbm.h... " >&6; } else nmh_libs="-lndbm " { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm in ndbm.h and ndbm" >&5 $as_echo_n "checking for dbm in ndbm.h and ndbm... " >&6; } fi nmh_saved_libs="$LIBS" LIBS="$nmh_libs $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define DB_DBM_HSEARCH 1 #include int main () { dbm_open("",0,0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : nmh_ndbm_found=yes else nmh_ndbm_found=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$nmh_saved_libs" if test "$nmh_ndbm_found" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } nmh_ndbmheader="ndbm.h" nmh_ndbm="ndbm" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if test "xdb1" = "x"; then nmh_libs= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm in db1/ndbm.h" >&5 $as_echo_n "checking for dbm in db1/ndbm.h... " >&6; } else nmh_libs="-ldb1 " { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm in db1/ndbm.h and db1" >&5 $as_echo_n "checking for dbm in db1/ndbm.h and db1... " >&6; } fi nmh_saved_libs="$LIBS" LIBS="$nmh_libs $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define DB_DBM_HSEARCH 1 #include int main () { dbm_open("",0,0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : nmh_ndbm_found=yes else nmh_ndbm_found=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$nmh_saved_libs" if test "$nmh_ndbm_found" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } nmh_ndbmheader="db1/ndbm.h" nmh_ndbm="db1" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if test "xgdbm" = "x"; then nmh_libs= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm in gdbm/ndbm.h" >&5 $as_echo_n "checking for dbm in gdbm/ndbm.h... " >&6; } else nmh_libs="-lgdbm " { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm in gdbm/ndbm.h and gdbm" >&5 $as_echo_n "checking for dbm in gdbm/ndbm.h and gdbm... " >&6; } fi nmh_saved_libs="$LIBS" LIBS="$nmh_libs $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define DB_DBM_HSEARCH 1 #include int main () { dbm_open("",0,0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : nmh_ndbm_found=yes else nmh_ndbm_found=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$nmh_saved_libs" if test "$nmh_ndbm_found" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } nmh_ndbmheader="gdbm/ndbm.h" nmh_ndbm="gdbm" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if test "xgdbm_compat -lgdbm" = "x"; then nmh_libs= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm in gdbm/ndbm.h" >&5 $as_echo_n "checking for dbm in gdbm/ndbm.h... " >&6; } else nmh_libs="-lgdbm_compat -lgdbm " { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm in gdbm/ndbm.h and gdbm_compat -lgdbm" >&5 $as_echo_n "checking for dbm in gdbm/ndbm.h and gdbm_compat -lgdbm... " >&6; } fi nmh_saved_libs="$LIBS" LIBS="$nmh_libs $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define DB_DBM_HSEARCH 1 #include int main () { dbm_open("",0,0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : nmh_ndbm_found=yes else nmh_ndbm_found=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$nmh_saved_libs" if test "$nmh_ndbm_found" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } nmh_ndbmheader="gdbm/ndbm.h" nmh_ndbm="gdbm_compat -lgdbm" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if test "xgdbm" = "x"; then nmh_libs= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm in ndbm.h" >&5 $as_echo_n "checking for dbm in ndbm.h... " >&6; } else nmh_libs="-lgdbm " { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm in ndbm.h and gdbm" >&5 $as_echo_n "checking for dbm in ndbm.h and gdbm... " >&6; } fi nmh_saved_libs="$LIBS" LIBS="$nmh_libs $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define DB_DBM_HSEARCH 1 #include int main () { dbm_open("",0,0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : nmh_ndbm_found=yes else nmh_ndbm_found=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$nmh_saved_libs" if test "$nmh_ndbm_found" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } nmh_ndbmheader="ndbm.h" nmh_ndbm="gdbm" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if test "xgdbm_compat -lgdbm" = "x"; then nmh_libs= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm in ndbm.h" >&5 $as_echo_n "checking for dbm in ndbm.h... " >&6; } else nmh_libs="-lgdbm_compat -lgdbm " { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm in ndbm.h and gdbm_compat -lgdbm" >&5 $as_echo_n "checking for dbm in ndbm.h and gdbm_compat -lgdbm... " >&6; } fi nmh_saved_libs="$LIBS" LIBS="$nmh_libs $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define DB_DBM_HSEARCH 1 #include int main () { dbm_open("",0,0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : nmh_ndbm_found=yes else nmh_ndbm_found=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$nmh_saved_libs" if test "$nmh_ndbm_found" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } nmh_ndbmheader="ndbm.h" nmh_ndbm="gdbm_compat -lgdbm" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if test "xgdbm_compat" = "x"; then nmh_libs= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm in gdbm-ndbm.h" >&5 $as_echo_n "checking for dbm in gdbm-ndbm.h... " >&6; } else nmh_libs="-lgdbm_compat " { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm in gdbm-ndbm.h and gdbm_compat" >&5 $as_echo_n "checking for dbm in gdbm-ndbm.h and gdbm_compat... " >&6; } fi nmh_saved_libs="$LIBS" LIBS="$nmh_libs $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define DB_DBM_HSEARCH 1 #include int main () { dbm_open("",0,0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : nmh_ndbm_found=yes else nmh_ndbm_found=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$nmh_saved_libs" if test "$nmh_ndbm_found" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } nmh_ndbmheader="gdbm-ndbm.h" nmh_ndbm="gdbm_compat" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } : fi : fi : fi : fi : fi : fi : fi : fi : fi : fi : fi fi else if test "x$nmh_ndbm" = "x"; then nmh_libs= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm in $nmh_ndbmheader" >&5 $as_echo_n "checking for dbm in $nmh_ndbmheader... " >&6; } else nmh_libs="-l$nmh_ndbm " { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dbm in $nmh_ndbmheader and $nmh_ndbm" >&5 $as_echo_n "checking for dbm in $nmh_ndbmheader and $nmh_ndbm... " >&6; } fi nmh_saved_libs="$LIBS" LIBS="$nmh_libs $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define DB_DBM_HSEARCH 1 #include <$nmh_ndbmheader> int main () { dbm_open("",0,0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : nmh_ndbm_found=yes else nmh_ndbm_found=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$nmh_saved_libs" if test "$nmh_ndbm_found" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } nmh_ndbmheader="$nmh_ndbmheader" nmh_ndbm="$nmh_ndbm" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } : fi fi if test "$nmh_ndbm_found" = "no"; then as_fn_error $? "could not find a working ndbm library/header combination" "$LINENO" 5 else if test x"$nmh_ndbmheader" != x; then cat >>confdefs.h <<_ACEOF #define NDBM_HEADER <$nmh_ndbmheader> _ACEOF fi if test x"$nmh_ndbm" != x; then NDBM_LIBS="-l$nmh_ndbm" else NDBM_LIBS= fi fi # Check whether --with-rpmdir was given. if test "${with_rpmdir+set}" = set; then : withval=$with_rpmdir; fi if test x"$with_rpmdir" = x; then : rpmdir='$(abs_srcdir)/RPM'; nmhrpm=./RPM else rpmdir="$with_rpmdir"; eval "nmhrpm=${rpmdir}" fi if test x"$with_cyrus_sasl" != x"no"; then : ac_fn_c_check_header_mongrel "$LINENO" "sasl/sasl.h" "ac_cv_header_sasl_sasl_h" "$ac_includes_default" if test "x$ac_cv_header_sasl_sasl_h" = xyes; then : HAVE_SASL_H=1 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sasl_client_new in -lsasl2" >&5 $as_echo_n "checking for sasl_client_new in -lsasl2... " >&6; } if ${ac_cv_lib_sasl2_sasl_client_new+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsasl2 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char sasl_client_new (); int main () { return sasl_client_new (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_sasl2_sasl_client_new=yes else ac_cv_lib_sasl2_sasl_client_new=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sasl2_sasl_client_new" >&5 $as_echo "$ac_cv_lib_sasl2_sasl_client_new" >&6; } if test "x$ac_cv_lib_sasl2_sasl_client_new" = xyes; then : SASLLIB="-lsasl2" fi fi sasl_support=no CYRUS_SASL=0 if test "x$with_cyrus_sasl" = xyes && test "x$HAVE_SASL_H" = x; then : as_fn_error $? "SASL requested but sasl.h not found" "$LINENO" 5 elif test "x$with_cyrus_sasl" = xyes && test "x$SASLLIB" = x; then : as_fn_error $? "SASL requested but Cyrus SASL library not found" "$LINENO" 5 elif test "x$with_cyrus_sasl" != xno && test "x$HAVE_SASL_H" = x1 && test "x$SASLLIB" != x; then : $as_echo "#define CYRUS_SASL 1" >>confdefs.h CYRUS_SASL=1 sasl_support=yes fi if test x"$with_tls" != x"no"; then : ac_fn_c_check_header_mongrel "$LINENO" "openssl/ssl.h" "ac_cv_header_openssl_ssl_h" "$ac_includes_default" if test "x$ac_cv_header_openssl_ssl_h" = xyes; then : HAVE_SSL_H=1 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BIO_write in -lcrypto" >&5 $as_echo_n "checking for BIO_write in -lcrypto... " >&6; } if ${ac_cv_lib_crypto_BIO_write+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lcrypto $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char BIO_write (); int main () { return BIO_write (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_crypto_BIO_write=yes else ac_cv_lib_crypto_BIO_write=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_BIO_write" >&5 $as_echo "$ac_cv_lib_crypto_BIO_write" >&6; } if test "x$ac_cv_lib_crypto_BIO_write" = xyes; then : TLSLIB="-lcrypto" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_new in -lssl" >&5 $as_echo_n "checking for SSL_new in -lssl... " >&6; } if ${ac_cv_lib_ssl_SSL_new+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lssl $TLSLIB $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char SSL_new (); int main () { return SSL_new (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ssl_SSL_new=yes else ac_cv_lib_ssl_SSL_new=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_new" >&5 $as_echo "$ac_cv_lib_ssl_SSL_new" >&6; } if test "x$ac_cv_lib_ssl_SSL_new" = xyes; then : TLSLIB="-lssl $TLSLIB" else TLSLIB= fi fi tls_support=no TLS_SUPPORT=0 if test "x$with_tls" = xyes && test "x$HAVE_SSL_H" = x; then : as_fn_error $? "TLS requested but openssl/ssl.h not found" "$LINENO" 5 elif test "x$with_tls" = xyes && test "x$TLSLIB" = x; then : as_fn_error $? "TLS requested but crypto or ssl library not found" "$LINENO" 5 elif test "x$with_tls" != xno && test "x$HAVE_SSL_H" = x1 && test "x$TLSLIB" != x; then : $as_echo "#define TLS_SUPPORT 1" >>confdefs.h TLS_SUPPORT=1 tls_support=yes save_LIBS="$LIBS" LIBS="$LIBS $TLSLIB" for ac_func in X509_VERIFY_PARAM_set1_host do : ac_fn_c_check_func "$LINENO" "X509_VERIFY_PARAM_set1_host" "ac_cv_func_X509_VERIFY_PARAM_set1_host" if test "x$ac_cv_func_X509_VERIFY_PARAM_set1_host" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_X509_VERIFY_PARAM_SET1_HOST 1 _ACEOF fi done LIBS="$save_LIBS" fi # Extract the first word of "curl-config", so it can be a program name with args. set dummy curl-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_curl_config+:} false; then : $as_echo_n "(cached) " >&6 else case $curl_config in [\\/]* | ?:[\\/]*) ac_cv_path_curl_config="$curl_config" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_curl_config="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi curl_config=$ac_cv_path_curl_config if test -n "$curl_config"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $curl_config" >&5 $as_echo "$curl_config" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$with_oauth" != xno && test -n "$curl_config"; then : save_CFLAGS="$CFLAGS" CFLAGS="$AM_CPPFLAGS $AM_CFLAGS $CFLAGS `$curl_config --cflags`" ac_fn_c_check_header_mongrel "$LINENO" "curl/curl.h" "ac_cv_header_curl_curl_h" "$ac_includes_default" if test "x$ac_cv_header_curl_curl_h" = xyes; then : HAVE_CURL_H=1 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for curl_easy_init in -lcurl" >&5 $as_echo_n "checking for curl_easy_init in -lcurl... " >&6; } if ${ac_cv_lib_curl_curl_easy_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lcurl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char curl_easy_init (); int main () { return curl_easy_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_curl_curl_easy_init=yes else ac_cv_lib_curl_curl_easy_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curl_curl_easy_init" >&5 $as_echo "$ac_cv_lib_curl_curl_easy_init" >&6; } if test "x$ac_cv_lib_curl_curl_easy_init" = xyes; then : CURLLIB="`$curl_config --libs`" CURL_USER_AGENT="`$curl_config --version | sed 's|^libcurl *|libcurl/|; q'`" if test "x$CURL_USER_AGENT" != "x`echo $CURL_USER_AGENT | sed 's/ //'`"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unexpected curl-config --version: $CURL_USER_AGENT" >&5 $as_echo "$as_me: WARNING: unexpected curl-config --version: $CURL_USER_AGENT" >&2;} CURL_USER_AGENT=libcurl/UNKNOWN fi fi fi CFLAGS="$save_CFLAGS" fi oauth_support=no OAUTH_SUPPORT=0 if test "x$with_oauth" = xyes && test "x$HAVE_CURL_H" = x; then : as_fn_error $? "OAuth requested but curl/curl.h not found" "$LINENO" 5 elif test "x$with_oauth" = xyes && test "x$CURLLIB" = x; then : as_fn_error $? "OAuth requested but curl library not found" "$LINENO" 5 elif test "x$with_oauth" != xno && test "x$HAVE_CURL_H" = x1 && test "x$CURLLIB" != x; then : $as_echo "#define OAUTH_SUPPORT 1" >>confdefs.h OAUTH_SUPPORT=1 oauth_support=yes fi if test "$LEX" = flex; then : case `$LEX -V` in #( flex\ 2.5.35) : AM_LFLAGS=\ '; sed "s/ int n;/ size_t n;/" $@ >$@.tmp && mv -f $@.tmp $@;' ;; #( flex\ 2.5.3[67]) : AM_LFLAGS=\ '; sed "s/\( \)int i;/\1yy_size_t i;/" $@ >$@.tmp && mv -f $@.tmp $@;' ;; #( flex\ 2.6.0) : AM_LFLAGS=\ '; sed "s/, num_to_read/, (size_t) num_to_read/" $@ >$@.tmp && mv -f $@.tmp $@;' ;; #( flex\ 2.6.1) : AM_LFLAGS=\ '; sed '\''/\/s/int/size_t/; \ s/\/int i/; \ s/int n; \\/yy_size_t n; \\/'\'' $@ >$@.tmp && mv -f $@.tmp $@;' ;; #( *) : ;; esac fi if test -n "$NMHETCDIRINST"; then : nmhetcdirinst=$NMHETCDIRINST fi nmh_saved_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$AM_CPPFLAGS $CPPFLAGS" ac_fn_c_check_member "$LINENO" "struct tm" "tm_gmtoff" "ac_cv_member_struct_tm_tm_gmtoff" "#include " if test "x$ac_cv_member_struct_tm_tm_gmtoff" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_TM_TM_GMTOFF 1 _ACEOF fi CPPFLAGS="$nmh_saved_CPPFLAGS" ac_header_dirent=no for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5 $as_echo_n "checking for $ac_hdr that defines DIR... " >&6; } if eval \${$as_ac_Header+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include <$ac_hdr> int main () { if ((DIR *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$as_ac_Header=yes" else eval "$as_ac_Header=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$as_ac_Header { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 _ACEOF ac_header_dirent=$ac_hdr; break fi done # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. if test $ac_header_dirent = dirent.h; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 $as_echo_n "checking for library containing opendir... " >&6; } if ${ac_cv_search_opendir+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char opendir (); int main () { return opendir (); ; return 0; } _ACEOF for ac_lib in '' dir; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_opendir=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_opendir+:} false; then : break fi done if ${ac_cv_search_opendir+:} false; then : else ac_cv_search_opendir=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 $as_echo "$ac_cv_search_opendir" >&6; } ac_res=$ac_cv_search_opendir if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 $as_echo_n "checking for library containing opendir... " >&6; } if ${ac_cv_search_opendir+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char opendir (); int main () { return opendir (); ; return 0; } _ACEOF for ac_lib in '' x; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_opendir=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_opendir+:} false; then : break fi done if ${ac_cv_search_opendir+:} false; then : else ac_cv_search_opendir=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 $as_echo "$ac_cv_search_opendir" >&6; } ac_res=$ac_cv_search_opendir if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi fi ac_fn_c_check_member "$LINENO" "struct dirent" "d_type" "ac_cv_member_struct_dirent_d_type" " #include #ifdef HAVE_DIRENT_H # include #else # define dirent direct # ifdef HAVE_SYS_NDIR_H # include # endif # ifdef HAVE_SYS_DIR_H # include # endif # ifdef HAVE_NDIR_H # include # endif #endif " if test "x$ac_cv_member_struct_dirent_d_type" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_DIRENT_D_TYPE 1 _ACEOF fi ac_config_commands="$ac_config_commands build-directories" ac_config_files="$ac_config_files Makefile test/common.sh" ac_config_files="$ac_config_files uip/spost" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by nmh $as_me 1.7.1-RC3, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ nmh config.status 1.7.1-RC3 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "build-directories") CONFIG_COMMANDS="$CONFIG_COMMANDS build-directories" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "test/common.sh") CONFIG_FILES="$CONFIG_FILES test/common.sh" ;; "uip/spost") CONFIG_FILES="$CONFIG_FILES uip/spost" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; "build-directories":C) as_dir=etc; as_fn_mkdir_p; as_dir=man; as_fn_mkdir_p ;; "uip/spost":F) chmod +x uip/spost ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 eval "nmhbin=${bindir}"; eval "nmhbin=${nmhbin}" eval "nmhlibexec=${libexecdir}"; eval "nmhlibexec=${nmhlibexec}" eval "nmhsysconf=${sysconfdir}"; eval "nmhsysconf=${nmhsysconf}" eval "nmhman=${mandir}"; eval "nmhman=${nmhman}" eval "nmhdoc=${docdir}"; eval "nmhdoc=${nmhdoc}" eval "nmhrpm=${nmhrpm}"; { $as_echo "$as_me:${as_lineno-$LINENO}: nmh configuration ----------------- nmh version : 1.7.1-RC3 host os : ${host} compiler : ${CC} compiler flags : ${AM_CFLAGS} ${CFLAGS} linker flags : ${AM_LDFLAGS} ${LDFLAGS} preprocessor flags : ${AM_CPPFLAGS} ${CPPFLAGS} source code location : ${srcdir} binary install path : ${nmhbin} libexec install path : ${nmhlibexec}/nmh config files install path : ${nmhsysconf}/nmh man page install path : ${nmhman} docs install path : ${nmhdoc} RPM build root : ${nmhrpm} backup prefix : ${backup_prefix} transport system : ${MTS} spool default locking type : ${with_locking} default smtp server : ${smtpserver} SASL support : ${sasl_support} TLS support : ${tls_support} OAuth support : ${oauth_support} " >&5 $as_echo "$as_me: nmh configuration ----------------- nmh version : 1.7.1-RC3 host os : ${host} compiler : ${CC} compiler flags : ${AM_CFLAGS} ${CFLAGS} linker flags : ${AM_LDFLAGS} ${LDFLAGS} preprocessor flags : ${AM_CPPFLAGS} ${CPPFLAGS} source code location : ${srcdir} binary install path : ${nmhbin} libexec install path : ${nmhlibexec}/nmh config files install path : ${nmhsysconf}/nmh man page install path : ${nmhman} docs install path : ${nmhdoc} RPM build root : ${nmhrpm} backup prefix : ${backup_prefix} transport system : ${MTS} spool default locking type : ${with_locking} default smtp server : ${smtpserver} SASL support : ${sasl_support} TLS support : ${tls_support} OAuth support : ${oauth_support} " >&6;} # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi nmh-1.7.1-RC3/configure.ac000644 007761 000024 00000060244 13243042053 015252 0ustar00kenhstaff000000 000000 dnl configure.ac -- autoconf template for nmh dnl 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 serial-tests subdir-objects 1.12]) AC_CANONICAL_HOST AC_MSG_NOTICE([configuring for AC_PACKAGE_NAME-AC_PACKAGE_VERSION]) AC_SUBST(VERSION,AC_PACKAGE_VERSION)dnl dnl What date of nmh are we building? DATE=`cat ${srcdir}/DATE` AC_MSG_NOTICE([configuring for nmh dated $DATE]) AC_SUBST([DATE])dnl dnl -------------------------- dnl CHECK COMMAND LINE OPTIONS dnl -------------------------- dnl Do you want client-side support for using SASL for authentication? dnl Note that this code will be enabled for both POP and SMTP AC_ARG_WITH([cyrus-sasl], AS_HELP_STRING([--with-cyrus-sasl], [Enable SASL support via the Cyrus SASL library])) AS_IF([test x"$with_cyrus_sasl" != x -a x"$with_cyrus_sasl" != xyes -a \ x"$with_cyrus_sasl" != xno],[ AC_MSG_WARN([Arguments to --with-cyrus-sasl now ignored]) AC_MSG_WARN([Please pass the appropriate arguments to CPPFLAGS/LDFLAGS])]) dnl Do you want client-side support for encryption with TLS? AC_ARG_WITH([tls], AS_HELP_STRING([--with-tls], [Enable TLS support])) dnl Do you want client-side support for using OAuth2 for SMTP & POP auth? AC_ARG_WITH([oauth], AS_HELP_STRING([--with-oauth], [Enable OAuth2 support in SMTP and POP auth])) dnl Set the backup prefix AC_ARG_WITH([hash-backup], AS_HELP_STRING([--with-hash-backup],[use # as the backup prefix (default: ,)])) AS_IF([test x"$with_hash_backup" != x -a x"$with_hash_backup" != x"no"], [backup_prefix="#"], [backup_prefix=","]) AC_DEFINE_UNQUOTED([BACKUP_PREFIX], "$backup_prefix", [The prefix that is prepended to the name of message files when they are "removed" by rmm. This should typically be `,' or `#'.])dnl dnl What method of posting should post use? AC_ARG_WITH([mts], AS_HELP_STRING([--with-mts=@<:@smtp|sendmail/smtp|sendmail/pipe@:>@], [specify the default mail transport agent/service])) AS_IF([test x"$with_mts" = x"smtp"], [MTS="smtp"], [test x"$with_mts" = x"sendmail"], [MTS="sendmail/smtp"], [test x"$with_mts" = x"sendmail/smtp"], [MTS="sendmail/smtp"], [test x"$with_mts" = x"sendmail/pipe"], [MTS="sendmail/pipe"], [MTS="smtp"]) AC_SUBST([MTS])dnl dnl What should be the default mail server? AC_ARG_WITH([smtpserver], [AS_HELP_STRING([--with-smtpserver='SMTPSERVER'], [specify the default SMTP server @<:@localhost@:>@])]) AS_IF([test -n "$with_smtpserver"], [smtpserver="$with_smtpserver"], [smtpserver="localhost"]) AC_SUBST([smtpserver])dnl dnl ------------------------------------------------------------------- dnl Default location is /usr/local/nmh/{bin,etc,libexec,man}, unless we dnl find an existing installation, in which case we use its location. dnl ------------------------------------------------------------------- AC_PREFIX_DEFAULT([/usr/local/nmh]) AC_PREFIX_PROGRAM([mhparam]) dnl ------------------ dnl CHECK THE COMPILER dnl ------------------ AC_PROG_CC([cc gcc]) AM_PROG_CC_C_O dnl ------------------ dnl CHECK HEADER FILES dnl ------------------ AC_HEADER_TIOCGWINSZ AC_CHECK_HEADERS([fcntl.h stdbool.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 .]),, [[#if HAVE_SYS_STREAM_H # include #endif ]]) dnl --------------- dnl CHECK FUNCTIONS dnl --------------- AC_CHECK_FUNCS([wcwidth mbtowc getutxent arc4random mkstemps]) dnl Use custom getline for platforms that don't have it. AC_CONFIG_LIBOBJ_DIR([sbr]) AC_REPLACE_FUNCS([getline]) dnl ----------------------- dnl CHECK MULTIBYTE SUPPORT dnl ----------------------- AS_IF([test "x$ac_cv_header_wchar_h" = "xyes" -a \ "x$ac_cv_header_wctype_h" = "xyes" -a \ "x$ac_cv_func_wcwidth" = "xyes" -a \ "x$ac_cv_func_mbtowc" = "xyes"], [AC_DEFINE([MULTIBYTE_SUPPORT], [1], [Define to enable support for multibyte character sets.]) MULTIBYTE_ENABLED=1], [MULTIBYTE_ENABLED=0]) AC_SUBST([MULTIBYTE_ENABLED]) dnl ---------------- dnl CUSTOMIZE CFLAGS dnl ---------------- dnl The user didn't specify CFLAGS, so customize them. if test "$GCC" != yes; then dnl Use -v and some other options with SunStudio cc. lex produces dnl code that causes unreachable-statement warnings. It might be dnl better to use an autoconf test, except -v will probably succeed dnl with many other compilers but have different meaning. AS_CASE([`${CC} -V 2>&1`], [cc:*\ Sun\ C*], [CFLAGS=\ "${CFLAGS:+$CFLAGS }-v -errtags=yes -erroff=E_STATEMENT_NOT_REACHED"]) fi AC_CACHE_CHECK([whether compiler supports -Wall], [nmh_cv_has_wall], [nmh_saved_cflags="$CFLAGS" CFLAGS="$AM_CFLAGS $CFLAGS -Wall -Werror" AC_TRY_COMPILE([],[],nmh_cv_has_wall=yes,nmh_cv_has_wall=no) CFLAGS="$nmh_saved_cflags"]) test "$nmh_cv_has_wall" = "yes" && CFLAGS="${CFLAGS:+$CFLAGS }-Wall" AC_CACHE_CHECK([whether compiler supports -Wextra], [nmh_cv_has_wextra], [nmh_saved_cflags="$CFLAGS" CFLAGS="$AM_CFLAGS $CFLAGS -Wextra -Werror" AC_TRY_COMPILE([],[],nmh_cv_has_wextra=yes, nmh_cv_has_wextra=no) CFLAGS="$nmh_saved_cflags"]) test "$nmh_cv_has_wextra" = "yes" && CFLAGS="${CFLAGS:+$CFLAGS }-Wextra" AC_SUBST([AM_CFLAGS]) dnl Check for any platform-specific additional AM_CPPFLAGS. This depends on dnl MULTIBYTE_ENABLED having already been set. NMH_ADDL_CPPFLAGS dnl FreeBSD needs a bit of magic to bring getline() into scope. dnl We do this here rather than in (say) h/mh.h because this macro must dnl be defined before is pulled in. dnl dnl And while we're here, add the packages tree to the cpp and ld search dnl paths. Note that FreeBSD's pkg(8) seems to be hardwired to use /usr/local. dnl If /usr/ports is installed, we use its idea of where things are installed, dnl otherwise we assume /usr/local. AS_IF([test `uname` = FreeBSD], [CPPFLAGS="${CPPFLAGS:+$CPPFLAGS }-D_WITH_GETLINE" nmh_cv_freebsd_localbase=`echo '.include ' \ | make -k -f /dev/stdin -V LOCALBASE 2>/dev/null | sed 1q` test -z "$nmh_cv_freebsd_localbase" && nmh_cv_freebsd_localbase=/usr/local CPPFLAGS="${CPPFLAGS:+$CPPFLAGS }-I$nmh_cv_freebsd_localbase/include" LDFLAGS="${LDFLAGS:+$LDFLAGS }-L$nmh_cv_freebsd_localbase/lib" ]) dnl -------------- dnl CUSTOMIZE LINK dnl -------------- AS_IF([test `uname` = OpenBSD], dnl Munge "often/almost always misused" warnings from OpenBSD linker dnl so that they don't color the waterfall. [POSTLINK="2>&1 | sed -e \ 's/: w\(arning: s.*() is .* misused, please use\)/: W\1/'"]) AC_SUBST([POSTLINK]) dnl ----------------- dnl CUSTOMIZE LDFLAGS dnl ----------------- dnl Disable clang complaint about unused -ansi when linking. AC_CACHE_CHECK([whether linker supports -Qunused-arguments], [nmh_cv_has_q_unused_arguments], [AS_IF([test "$GCC" = yes && `${CC} --version 2>&1 | \ grep clang >/dev/null`], [nmh_saved_ldflags="$LDFLAGS" LDFLAGS="$AM_LDFLAGS $LDFLAGS -Qunused-arguments" AC_TRY_LINK([],[],nmh_cv_has_q_unused_arguments=yes, nmh_cv_has_q_unused_arguments=no) LDFLAGS="$nmh_saved_ldflags"], [nmh_cv_has_q_unused_arguments=no])]) test "$nmh_cv_has_q_unused_arguments" = "yes" && \ AM_LDFLAGS="${AM_LDFLAGS:+$AM_LDFLAGS }-Qunused-arguments" AC_SUBST([AM_LDFLAGS]) AC_HEADER_ASSERT dnl ------------------ dnl CHECK FOR PROGRAMS dnl ------------------ AC_PROG_MAKE_SET dnl Does make define $MAKE AC_PROG_INSTALL dnl Check for BSD compatible `install' 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_YACC dnl Check for yacc/bison AM_PROG_LEX dnl Check for lex/flex AM_PROG_AR dnl Look for `cut' pathtmp=/usr/xpg4/bin:/usr/bin:/bin:/usr/local/bin:/usr/ucb AC_PATH_PROG([cutpath], [cut], [no], [$pathtmp]) dnl dnl Check for MD5 program and formatting command dnl AC_CHECK_PROGS([MD5SUM], [md5sum md5], [missing]) AS_CASE(["${MD5SUM}"], [md5sum], [MD5FMT="cat"], [md5], [[MD5FMT="${SED} -e 's/MD5 *(.*) *= \([0-9a-f]*\)/\1/'"]], [MD5FMT="missing"]) AC_SUBST([MD5FMT]) dnl Look for `ls' pathtmp=/usr/xpg4/bin:/usr/bin:/bin:/usr/local/bin:/usr/ucb AC_PATH_PROG([lspath], [ls], [no], [$pathtmp]) dnl See how we get ls to display the owner and the group 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], [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"],[ dnl Looks like -l only gave us the user, so we need -g to get the group too. nmh_cv_ls_grpopt="-lg"])])]) dnl Look for `sendmail' pathtmp=/usr/sbin:/usr/lib:/usr/etc:/usr/ucblib:/usr/bin:/bin AC_PATH_PROG([sendmailpath], [sendmail], [/usr/sbin/sendmail], [$pathtmp]) dnl Cygwin FAT filesystems do not support hard links. So default to dnl cp instead, even if running on an NTFS or other filesystem. (And dnl therefore, this cannot be made into a dynamic test, in order to dnl support the least common Cygwin denominator. AS_CASE(["$host_os"], [cygwin*], [LN=cp], [LN=ln]) AC_SUBST([LN]) dnl ---------------------------------------------------------- dnl FIND MAIL SPOOL AND SEE IF WE NEED TO MAKE inc SETGID MAIL dnl ---------------------------------------------------------- AC_CACHE_CHECK(where mail spool is located, nmh_cv_mailspool, [for mailspool in /var/mail dnl /var/spool/mail dnl /usr/spool/mail dnl /dev/null; dnl Just in case we fall through do test -d $mailspool && break done nmh_cv_mailspool=$mailspool ]) mailspool=$nmh_cv_mailspool AC_SUBST([mailspool])dnl dnl See whether the mail spool directory is world-writable. if test "$lspath" != "no" -a "$cutpath" != "no"; then AC_CACHE_CHECK(whether the mail spool is world-writable, nmh_cv_mailspool_world_writable, [if test "`$lspath -dlL $mailspool | $cutpath -c9`" = "-"; then nmh_cv_mailspool_world_writable=no else nmh_cv_mailspool_world_writable=yes fi]) fi dnl Also, check for liblockfile (as found on Debian systems) AC_CHECK_HEADER([lockfile.h], [AC_CHECK_LIB(lockfile, lockfile_create)]) dnl and whether its companion program dotlockfile is setgid AC_PATH_PROG(dotlockfilepath, dotlockfile, no) if test "$ac_cv_lib_lockfile_lockfile_create" != "no" ; then if test "$ac_cv_path_dotlockfilepath" != "no" ; then AC_CACHE_CHECK(whether dotlockfile is setgid, nmh_cv_dotlockfile_setgid, [ if test -g "$ac_cv_path_dotlockfilepath" ; then nmh_cv_dotlockfile_setgid=yes else nmh_cv_dotlockfile_setgid=no fi]) fi fi dnl Provide a way for distcheck to disable setgid_mail via dnl DISTCHECK_CONFIGURE_FLAGS. 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. if test x"$with_locking" = x"dot" -a x"$nmh_cv_mailspool_world_writable" = x"no" -a x"$nmh_cv_dotlockfile_setgid" != x"yes" ; then dnl do we really need both of these? AC_DEFINE([MAILGROUP],[1], [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 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, [nmh_cv_ls_mail_grp=`$lspath -dL $nmh_cv_ls_grpopt $mailspool|$AWK '{print $4}'` ]) MAIL_SPOOL_GRP=$nmh_cv_ls_mail_grp AC_SUBST([MAIL_SPOOL_GRP])dnl NMH_MIMETYPEPROC NMH_MIMEENCODINGPROC dnl ------------------- dnl CHECK FOR LIBRARIES dnl ------------------- dnl Checks for network libraries (nsl, socket) NMH_CHECK_NETLIBS dnl Check the locking functions supported and what we should use by default NMH_LOCKING dnl Check for iconv NMH_CHECK_ICONV dnl Check for tputs() callback argument NMH_TPUTS_PUTC_ARG termcap_curses_order="termcap curses ncurses" for lib in $termcap_curses_order; do AC_CHECK_LIB([${lib}], [setupterm], [TERMLIB="-l$lib"; break]) done AC_SUBST([TERMLIB])dnl AS_IF([test "x$TERMLIB" = "x"], [AC_MSG_FAILURE([Could not find setupterm in any library. Is there a curses or ncurses library or package that you can install?])]) dnl Check for readline support NMH_READLINE dnl -------------- dnl CHECK FOR NDBM dnl -------------- AC_ARG_WITH([ndbm],AS_HELP_STRING([--with-ndbm=ARG],[use -lARG to link with ndbm]), [nmh_ndbm=$withval],[nmh_ndbm=autodetect]) AC_ARG_WITH([ndbmheader],AS_HELP_STRING([--with-ndbmheader=ARG],[#include to use ndbm]), [nmh_ndbmheader=$withval],[nmh_ndbmheader=autodetect]) if test "$nmh_ndbm" = "autodetect"; then if test "$nmh_ndbmheader" != "autodetect"; then AC_MSG_ERROR([must specify both --with-ndbm and --with-ndbmheader or neither]) else dnl There are at least four implementations of ndbm, and dnl several of those can be in different places at the whim dnl of the system integrator. A good summary of this mess dnl can be found at http://www.unixpapa.com/incnote/dbm.html dnl Classic ndbm with no library required (eg NetBSD): try this dnl first so we don't accidentally link in a pointless but harmless dnl library in one of the later ndbm.h+libfoo tests: NMH_CHECK_NDBM(ndbm.h,,, dnl Berkeley DBv2 emulating ndbm: header in db.h, e.g., 32-bit Cygwin: NMH_CHECK_NDBM(db.h,db,, dnl Berkeley DBv1 emulating ndbm: NMH_CHECK_NDBM(ndbm.h,db,, NMH_CHECK_NDBM(ndbm.h,db1,, dnl Classic ndbm: NMH_CHECK_NDBM(ndbm.h,ndbm,, dnl glibc2.1 systems put db1 in a subdir: NMH_CHECK_NDBM(db1/ndbm.h,db1,, dnl GNU gdbm emulating ndbm, with header possibly in gdbm/ dnl and possibly needing gbdm_compat library: NMH_CHECK_NDBM(gdbm/ndbm.h,gdbm,, NMH_CHECK_NDBM(gdbm/ndbm.h,gdbm_compat -lgdbm,, NMH_CHECK_NDBM(ndbm.h,gdbm,, dnl 64-bit Cygwin: NMH_CHECK_NDBM(ndbm.h,gdbm_compat -lgdbm,, dnl On Linux, libgdbm_compat.so loads libgdbm.so as well, so it doesn't dnl need to be explicit: NMH_CHECK_NDBM(gdbm-ndbm.h,gdbm_compat))))))))))) fi else dnl We don't really need to check that the user-specified values work, dnl but it is a convenience to the user to bomb out early rather than dnl after configure and half the compile process. NMH_CHECK_NDBM([$nmh_ndbmheader],[$nmh_ndbm]) fi if test "$nmh_ndbm_found" = "no"; then AC_MSG_ERROR([could not find a working ndbm library/header combination]) else dnl Now export the lib/header to our makefile/config.h: if test x"$nmh_ndbmheader" != x; then AC_DEFINE_UNQUOTED(NDBM_HEADER, <$nmh_ndbmheader>, [Define to the header containing the ndbm API prototypes.]) fi if test x"$nmh_ndbm" != x; then NDBM_LIBS="-l$nmh_ndbm" else NDBM_LIBS= fi AC_SUBST([NDBM_LIBS]) fi dnl ------------------ dnl Set RPM build root 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@:>@])]) AS_IF([test x"$with_rpmdir" = x], [rpmdir='$(abs_srcdir)/RPM'; nmhrpm=./RPM], [rpmdir="$with_rpmdir"; eval "nmhrpm=${rpmdir}"]) AC_SUBST([rpmdir]) dnl -------------------- dnl CHECK FOR CYRUS-SASL dnl -------------------- AS_IF([test x"$with_cyrus_sasl" != x"no"],[ AC_CHECK_HEADER([sasl/sasl.h], HAVE_SASL_H=1) AC_CHECK_LIB([sasl2], [sasl_client_new], [SASLLIB="-lsasl2"])]) AC_SUBST([SASLLIB]) dnl ----------------- dnl Enable SASL? dnl ----------------- dnl By default (with_cyrus_sasl=''), enable SASL if header and lib are found. dnl If SASL requested (--with-cyrus-sasl with_cyrus_sasl=yes), error if header or lib not found. dnl If SASL disabled (--without-cyrus-sasl with_cyrus_sasl=no), don't enable it. sasl_support=no CYRUS_SASL=0 AC_SUBST([CYRUS_SASL]) AS_IF([test "x$with_cyrus_sasl" = xyes && test "x$HAVE_SASL_H" = x], [AC_MSG_ERROR([SASL requested but sasl.h not found])], [test "x$with_cyrus_sasl" = xyes && test "x$SASLLIB" = x], [AC_MSG_ERROR([SASL requested but Cyrus SASL library not found])], [test "x$with_cyrus_sasl" != xno && test "x$HAVE_SASL_H" = x1 && test "x$SASLLIB" != x], [AC_DEFINE([CYRUS_SASL], [1], [Define to use the Cyrus SASL library for authentication of POP and SMTP.]) CYRUS_SASL=1 sasl_support=yes]) dnl ----------------- dnl CHECK FOR OPENSSL dnl ----------------- AS_IF([test x"$with_tls" != x"no"],[ dnl OpenBSD 5 needs the other-libraries (fifth argument) to the dnl AC_CHECK_LIB for SSL_new, because it doesn't dnl automatically append -lcrypto when linking with -lssl. AC_CHECK_HEADER([openssl/ssl.h], HAVE_SSL_H=1) AC_CHECK_LIB([crypto], [BIO_write], [TLSLIB="-lcrypto"]) AC_CHECK_LIB([ssl], [SSL_new], [TLSLIB="-lssl $TLSLIB"], [TLSLIB=], [$TLSLIB])]) AC_SUBST([TLSLIB]) dnl ----------------- dnl Enable TLS? dnl ----------------- dnl By default (with_tls=''), enable TLS if header and libs were found. dnl If TLS requested (--with-tls with_tls=yes), error if header/lib not found. dnl If TLS disabled (--without-tls with_tls=no), don't enable it. tls_support=no TLS_SUPPORT=0 AC_SUBST([TLS_SUPPORT]) AS_IF([test "x$with_tls" = xyes && test "x$HAVE_SSL_H" = x], [AC_MSG_ERROR([TLS requested but openssl/ssl.h not found])], [test "x$with_tls" = xyes && test "x$TLSLIB" = x], [AC_MSG_ERROR([TLS requested but crypto or ssl library not found])], [test "x$with_tls" != xno && test "x$HAVE_SSL_H" = x1 && test "x$TLSLIB" != x], [AC_DEFINE([TLS_SUPPORT], [1], [Support TLS for session encryption.]) TLS_SUPPORT=1 tls_support=yes save_LIBS="$LIBS" LIBS="$LIBS $TLSLIB" AC_CHECK_FUNCS([X509_VERIFY_PARAM_set1_host]) LIBS="$save_LIBS"]) dnl ----------------- dnl CHECK FOR CURL dnl ----------------- dnl Look for curl if oauth not disabled (--without-oauth). AC_PATH_PROG([curl_config], [curl-config]) AS_IF([test "x$with_oauth" != xno && test -n "$curl_config"], [ save_CFLAGS="$CFLAGS" CFLAGS="$AM_CPPFLAGS $AM_CFLAGS $CFLAGS `$curl_config --cflags`" AC_CHECK_HEADER([curl/curl.h], [ HAVE_CURL_H=1 AC_CHECK_LIB([curl], [curl_easy_init], [ CURLLIB="`$curl_config --libs`" AC_SUBST([CURLLIB]) CURL_USER_AGENT="`$curl_config --version | sed 's|^libcurl *|libcurl/|; q'`" AS_IF([test "x$CURL_USER_AGENT" != "x`echo $CURL_USER_AGENT | sed 's/ //'`"], [AC_MSG_WARN([unexpected curl-config --version: $CURL_USER_AGENT]) CURL_USER_AGENT=libcurl/UNKNOWN]) AC_SUBST([CURL_USER_AGENT]) ]) ]) CFLAGS="$save_CFLAGS" ]) dnl ----------------- dnl Enable OAuth? dnl ----------------- dnl By default (with_oauth=''), enable OAuth if curl is found. dnl If OAuth requested (--with-oauth with_oauth=yes), error if curl not found. dnl If OAuth disabled (--without-oauth with_oauth=no), don't enable it. oauth_support=no OAUTH_SUPPORT=0 AC_SUBST([OAUTH_SUPPORT]) AS_IF([test "x$with_oauth" = xyes && test "x$HAVE_CURL_H" = x], [AC_MSG_ERROR([OAuth requested but curl/curl.h not found])], [test "x$with_oauth" = xyes && test "x$CURLLIB" = x], [AC_MSG_ERROR([OAuth requested but curl library not found])], [test "x$with_oauth" != xno && test "x$HAVE_CURL_H" = x1 && test "x$CURLLIB" != x], [AC_DEFINE([OAUTH_SUPPORT], [1], [Support OAuth2 in SMTP auth.]) OAUTH_SUPPORT=1 oauth_support=yes]) dnl ---------------- dnl CHECK FLEX FIXUP dnl ---------------- dnl Use AM_LFLAGS make variable setting to work around bugs in flex dnl 2.5.36-37 that cause signed/unsigned mismatch, dnl http://sourceforge.net/p/flex/bugs/140/ dnl 2.6.1 bug: https://github.com/westes/flex/issues/97 AS_IF([test "$LEX" = flex], [AS_CASE([`$LEX -V`], [flex\ 2.5.35], [AM_LFLAGS=\ '; sed "s/ int n;/ size_t n;/" $@ >$@.tmp && mv -f $@.tmp $@;'], [flex\ 2.5.3[[67]]], [AM_LFLAGS=\ '; sed "s/\( \)int i;/\1yy_size_t i;/" $@ >$@.tmp && mv -f $@.tmp $@;'], [flex\ 2.6.0], [AM_LFLAGS=\ '; sed "s/, num_to_read/, (size_t) num_to_read/" $@ >$@.tmp && mv -f $@.tmp $@;'], [flex\ 2.6.1], [AM_LFLAGS=\ '; sed '\''/\/s/int/size_t/; \ s/\/int i/; \ s/int n; \\/yy_size_t n; \\/'\'' $@ >$@.tmp && mv -f $@.tmp $@;']) AC_SUBST([AM_LFLAGS])]) dnl ------------------ dnl FOR INTERNAL USE by the NMH test suite dnl ------------------ AC_ARG_VAR([NMHETCDIRINST], [for internal use by nmh test suite]) AS_IF([test -n "$NMHETCDIRINST"], [nmhetcdirinst=$NMHETCDIRINST] AC_SUBST([nmhetcdirinst])) dnl ---------------- dnl CHECK STRUCTURES dnl ---------------- dnl For platforms such as FreeBSD that have tm_gmtoff in struct tm. dnl (FreeBSD has a timezone() function but not a timezone global dnl variable that is visible). dnl On Linux, $AM_CPPFLAGS contains -D_GNU_SOURCE, which makes dnl tm_gmtoff visible. nmh_saved_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$AM_CPPFLAGS $CPPFLAGS" AC_CHECK_MEMBERS([struct tm.tm_gmtoff],,,[[#include ]]) CPPFLAGS="$nmh_saved_CPPFLAGS" AC_STRUCT_DIRENT_D_TYPE dnl dnl Sigh, this is required because under the new world order autoconf has dnl nothing to create in a few of the build directories when doing an object dnl tree build. So make sure we created certain directories if they don't dnl exist. dnl AC_CONFIG_COMMANDS([build-directories], [AS_MKDIR_P([etc]); AS_MKDIR_P([man])]) AC_CONFIG_COMMANDS_POST([ dnl These odd looking assignments are done to expand out unexpanded dnl variables in bindir et al (for instance mandir is '${datarootdir}/man'), dnl but expanding that gives '${prefix}/share/man', so we need to expand dnl again to get the final answer. dnl We only use the expanded versions to print the install paths in dnl the final summary and should use them nowhere else (see the autoconf dnl docs for the rationale for bindir etc being unexpanded). eval "nmhbin=${bindir}"; eval "nmhbin=${nmhbin}" eval "nmhlibexec=${libexecdir}"; eval "nmhlibexec=${nmhlibexec}" eval "nmhsysconf=${sysconfdir}"; eval "nmhsysconf=${nmhsysconf}" eval "nmhman=${mandir}"; eval "nmhman=${nmhman}" eval "nmhdoc=${docdir}"; eval "nmhdoc=${nmhdoc}" eval "nmhrpm=${nmhrpm}"; AC_MSG_NOTICE([ nmh configuration ----------------- nmh version : AC_PACKAGE_VERSION host os : ${host} compiler : ${CC} compiler flags : ${AM_CFLAGS} ${CFLAGS} linker flags : ${AM_LDFLAGS} ${LDFLAGS} preprocessor flags : ${AM_CPPFLAGS} ${CPPFLAGS} source code location : ${srcdir} binary install path : ${nmhbin} libexec install path : ${nmhlibexec}/nmh config files install path : ${nmhsysconf}/nmh man page install path : ${nmhman} docs install path : ${nmhdoc} RPM build root : ${nmhrpm} backup prefix : ${backup_prefix} transport system : ${MTS} spool default locking type : ${with_locking} default smtp server : ${smtpserver} SASL support : ${sasl_support} TLS support : ${tls_support} OAuth support : ${oauth_support} ])])dnl dnl --------------- dnl OUTPUT MAKEFILE dnl --------------- AC_CONFIG_FILES([Makefile test/common.sh]) AC_CONFIG_FILES([uip/spost], [chmod +x uip/spost]) AC_OUTPUT nmh-1.7.1-RC3/COPYRIGHT000644 007761 000024 00000003123 12764337265 014273 0ustar00kenhstaff000000 000000 Copyright (c) 2002, the authors of nmh All rights reserved. Definition: The "authors of nmh" includes anyone, past or present, who has worked on the nmh source code. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name "the authors of nmh", nor variations such as "The nmh Developers", nor the names of the individual contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY ITS AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OF NMH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. nmh-1.7.1-RC3/DATE000644 007761 000024 00000000021 13243042504 013410 0ustar00kenhstaff000000 000000 20 February 2018 nmh-1.7.1-RC3/depcomp000755 007761 000024 00000055703 12070355546 014360 0ustar00kenhstaff000000 000000 #! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2012-10-18.11; # UTC # Copyright (C) 1999-2012 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: nmh-1.7.1-RC3/docs/000755 007761 000024 00000000000 13243043705 013713 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/etc/000755 007761 000024 00000000000 13243043705 013536 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/h/000755 007761 000024 00000000000 13243043704 013211 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/INSTALL000644 007761 000024 00000027763 13243042053 014026 0ustar00kenhstaff000000 000000 # INSTALL -- installation instructions # -------------------------------- Installing nmh, guided by script -------------------------------- For routine installation on popular platforms, the build_nmh shell script can be used to guide you through configuration. It will then build and optionally (with -i) install in the configured location. ------------------------ Installing nmh, manually ------------------------ Please read all of the following instructions before you begin building nmh. You should check the MACHINES file to see if there are any specific build instructions for your operating system. To build nmh, you will need an ANSI C compiler such as gcc. 0) If you have obtained nmh by checking it out of the git repository, you will need to run the GNU autotools to regenerate some files. (If your directory already contains a file 'config.h.in' then this has already been done and you do not need to do it.) You can regenerate the files by running the command ./autogen.sh (Note that if you're doing nmh development, you should look at docs/README.developers, since there is other developer-friendly advice there as well.) If you have obtained nmh in the form of a tar archive and are trying to unpack it with cpio: due to an apparent bug in cpio, it might fail with "Malformed number" error messages. Try another tool to unpack, such as tar or pax. 1) From the top-level source directory, run the command ./configure [options] This will check the configuration of your OS, and create the include file config.h, as well as the Makefile. The configure script accepts various options. The options of most interest are listed in a section below. To see the list of all available options, you can run ./configure --help 2) make 3) (Optional) make check This takes a bit of time, around one minute on a modern machine, but is highly recommended. test/inc/test-deb359167 uses valgrind, which detects use of an uninitialized variable on older Linux distributions such as Mandriva 2007.0 and CentOS 5.4. That particular failure is beyond the scope of nmh and can be ignored. 4) make install Note that if you have [n]mh files in your install directories with the same names as the files being installed, the old ones will get overwritten without any warning. 5) Edit the file `mts.conf' (installed in the nmh `etc' directory) and make any necessary changes for the mail transport interface you are using. The default `mts.conf' file assumes you retrieve new mail from a local (or NFS mounted) maildrop, and send outgoing mail by injecting the message to a mail transfer agent (such as sendmail) on the local machine via SMTP. If, instead, all your mail sending and receiving occurs on a remote POP/SMTP server, you will need to look at the values of the variables "localname", "pophost", and "servers": a) "localname" defines the hostname that nmh considers local. If not set, then nmh queries your OS for this value. You will want to change this if you wish your e-mail to appear as if it originated on the POP server. b) "pophost" defines the server that runs the POP daemon, and to which `inc' and `msgchk' will always query for new mail. c) "servers" defines the server to which you send outgoing SMTP traffic. See the discussion of the --with-smtpserver configure option below. If you don't want to hardcode pophost in `mts.conf', you can use the `-host' and `-user' options to `inc' and `msgchk'. Check the `mh-tailor' man page for a list of all the available options for this file. 6) Edit the file `mhn.defaults' (installed in the nmh `etc' directory). This file contains the default profile entries for the nmh command `mhn' and is created by the script `mhn.defaults.sh'. This script will search a generic path (essentially your $PATH) for programs to handle various content types (for example, xv to display images). You can re-run this script and give it a more tailored path. You may want to re-run this script later if you install new programs to display content. An example of this is: % cd support/general % ./mhn.defaults.sh /usr/local/bin:/usr/X11/bin:/usr/ucb > mhn.defaults and then move `mhn.defaults' into the nmh `etc' directory. The `mhn.defaults.sh' script only searches for a simple set of programs. If you have specialized programs to handle various types, you will need to edit the `mhn.defaults' file manually. The syntax of this file is described in the man page for `mhn', and in section 9.4 of the book "MH & xmh: Email for Users and Programmers", 3rd edition, by Jerry Peek, on the Internet at . 7) Add an optional global mh.profile, if desired. This profile should be placed in the nmh `etc' directory with the name `mh.profile'. This file will be used to construct the initial .mh_profile of a new nmh user, but will not be consulted after that. ----------------------------------------------- Compiler options, or using a different compiler ----------------------------------------------- By default, configure will use the "gcc" compiler if found. You can use a different compiler, or add unusual options for compiling or linking that the "configure" script does not know about, by giving "configure" initial values for these on its command line or in its environment. For example, ./configure CC=c99 CFLAGS=-O2 LIBS=-lposix If you wish to add options that are only used at compile time instead of link time, you can use the CPPFLAGS variable: ./configure CPPFLAGS='-Wextra -Wno-sign-compare' If you want to add to both compile and link flags at build time without putting them in the configuration, you can use the AM_CFLAGS Makefile macro: make AM_CFLAGS=--coverage ---------------------------------------- Building nmh on additional architectures ---------------------------------------- To build nmh on additional architectures, you can do a "make distclean". This should restore the nmh source distribution back to its original state. You can then configure nmh as above on other architectures in which you wish to build nmh. Or alternatively, you can use a different build directory for each architecture. --------------------------------- Using a different build directory --------------------------------- You can compile the nmh in a different directory from the one containing the source code. Doing so allows you to compile it on more than one architecture at the same time. To do this, you must use a version of "make" that supports the "VPATH" variable, such as GNU "make". "cd" to the directory where you want the object files and executables to go and run the "configure" script. "configure" automatically checks for the source code in the directory that "configure" is in. For example, cd /usr/local/solaris/nmh /usr/local/src/nmh-1.5/configure make --------------------- Options for configure --------------------- --prefix=DIR (DEFAULT is /usr/local/nmh) This will change the base prefix for the installation location for the various parts of nmh. Unless overridden, nmh is installed in ${prefix}/bin, ${prefix}/etc, ${prefix}/lib, ${prefix}/man. --bindir=DIR (DEFAULT is ${prefix}/bin) nmh's binaries (show, inc, comp, ...) are installed here. --libexecdir=DIR (DEFAULT is ${prefix}/libexec) nmh's support binaries (post, slocal, mhl, ...) are installed in ${libexecdir}/nmh. --sysconfdir=DIR (DEFAULT is ${prefix}/etc) nmh's config files (mts.conf, mhn.defaults, ...) are installed in ${sysconfdir}/nmh. --mandir=DIR (DEFAULT is ${prefix}/man) nmh's man pages are installed here. --with-editor=EDITOR (DEFAULT is vi) specify the full path of the default editor to use. If this option is not given, then the configuration process will search for the `vi' command and use it as the default. If you wish to specify an interface which is compatible with MH, then use the nmh command `prompter'. If you specify `prompter', then you don't need to give the full pathname. --with-locking=LOCKTYPE (DEFAULT is based on operating system) Specify the locking mechanism when attempting to "inc" or "msgchk" a local mail spool. Valid options are "dot", "fcntl", "flock", and "lockf". Of the four, dot-locking requires no special kernel or filesystem support, and simply creates a file called "FILE.lock" to indicate that "FILE" is locked. In order to be effective, you should contact the site administrator to find out what locking mechanisms other mail delivery and user programs respect. The most common reason not to use dot-locking is if the mail spool directory is not world- or user-writeable, and thus a lock file cannot be created. --enable-lockdir=DIR (DEFAULT is disabled) If dot locking is being used, store all dot-lock files in "DIR". The default is to store them in the directory of the file being locked. --with-mts=MTS (DEFAULT is smtp) Specify the default mail transport system you want to use. The three acceptable options are "smtp" (which is the default), "sendmail/smtp", and "sendmail/pipe". This value will be put into the mts.conf file. You may find it convenient to specify a value at configure-time, however, so that each time nmh is reinstalled, the right value will be there. If you use "smtp", this will enable a direct SMTP (simple mail transport protocol) interface in nmh. When sending mail, instead of passing the message to the mail transport agent, `post' will open a socket connection to the mail port on the machine specified in the `mts.conf' file (default is localhost), and speak SMTP directly. If you use "sendmail/smtp", then `post' will send messages by forking a local copy of sendmail. Currently it will still speak SMTP with this local copy of sendmail. If you use "sendmail/pipe", then `post' will open a pipe to the sendmail program and invoke it with the '-t' and '-i' options and write the message to sendmail's standard input. Note that some nmh functionality is not available in this mode. --with-ndbm=LIB (DEFAULT is to autodetect) --with-ndbmheader=HEADER (DEFAULT is to autodetect) Specify the header file (eg ndbm.h) and library (eg ndbm) to use to compile against the ndbm database library. By default, configure will try various possibilities until it finds one that works; this option only needs to be specified if the autodetection fails or makes the wrong choice. If either of these options is given then the other must also be specified. --with-smtpserver='SMTPSERVER' (DEFAULT is localhost) If this option is not specified, the mts.conf file will contain the line "servers: localhost", which may be manually edited later. You may find it convenient to specify a value at configure-time, however, so that each time nmh is reinstalled, the right value will be there. See the mh-tailor(5) man page for full documentation of "servers:". --with-cyrus-sasl (DEFAULT is to autodetect)) Enable SASL support for SMTP and POP via the Cyrus SASL library. This is used for the POP AUTH and SMTP AUTH protocols. This supports a wide variety of security mechanisms, including Kerberos/GSSAPI. Session encryption via SASL is supported for both POP and SMTP (depending on server-side support and the security mechanism in use). --with-tls (DEFAULT is to autodetect) Enable TLS session encryption support for SMTP via the STARTTLS command and TLS at connection start for both SMTP and POP. --with-oauth (DEFAULT is to enable if curl is installed) Enable OAuth2 authentication for SMTP and POP. --with-readline (DEFAULT is to autodetect) Enable support for readline functionality (command history/editing) at the WhatNow? prompt. -- The nmh team nmh-workers@nongnu.org nmh-1.7.1-RC3/install-sh000755 007761 000024 00000034523 12755125220 014776 0ustar00kenhstaff000000 000000 #!/bin/sh # install - install a program, script, or datafile scriptversion=2013-12-25.23; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. tab=' ' nl=' ' IFS=" $tab$nl" # Set DOITPROG to "echo" to test this script. doit=${DOITPROG-} doit_exec=${doit:-exec} # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false is_target_a_directory=possibly usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) is_target_a_directory=always dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done # We allow the use of options -d and -T together, by making -d # take the precedence; this is for compatibility with GNU install. if test -n "$dir_arg"; then if test -n "$dst_arg"; then echo "$0: target directory not allowed when installing a directory." >&2 exit 1 fi fi if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then if test $# -gt 1 || test "$is_target_a_directory" = always; then if test ! -d "$dst_arg"; then echo "$0: $dst_arg: Is not a directory." >&2 exit 1 fi fi fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac oIFS=$IFS IFS=/ set -f set fnord $dstdir shift set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: nmh-1.7.1-RC3/m4/000755 007761 000024 00000000000 13243043704 013302 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/MACHINES000644 007761 000024 00000013523 13240377015 014102 0ustar00kenhstaff000000 000000 # MACHINES -- operating system specific information # nmh is routinely built and tested on recent versions of the following platforms: Cygwin (32- and 64-bit) FreeBSD 10 Linux (Arch, CentOS, Fedora, and Ubuntu distributions) macOS OpenBSD nmh was known in the distant past to compile on the following platforms (save the exceptions noted below), using an ANSI C compiler, such as gcc: AIX 4.1.5.0.01 FreeBSD 9 IRIX 6.5 NetBSD 1.4.2 Solaris 7, 8, and 11 (sparc,x86) SunOS 4.1 On all platforms, the following programs are required to build nmh from a snapshot of the source code repository: autoconf 2.68 or later automake 1.12 or later flex 2.5.4 or later bison 2.3 or later, Berkeley yacc 1.9 or later, or Solaris yacc 4.0 They are not required if building from an nmh distribution (.tar.gz) file. Platform-specific notes follow. ------------------------------------------------------------------------------ Linux ------------------------------------------------------------------------------ Run-time package requirements: ncurses-libs gdbm, db4, or libdb (only needed for slocal(1)) readline (if you want readline support) cyrus-sasl-lib / libsasl2 (if configured with --with-cyrus-sasl) openssl-libs / libssl (if configured with --with-tls) libcurl (if configured with --with-oauth) Additional build-time package requirements: ncurses-devel / libncurses5-devel gdbm-devel, db4-devel or libdb-devel/libdb-dev (only needed for slocal(1)) readline-devel (if you want readline support) cyrus-sasl-devel / libsasl2-dev (if configuring with --with-cyrus-sasl) openssl-devel / libssl-dev (if configuring with --with-tls) libcurl-devel / libcurl-dev (if configured with --with-oauth) Test suite package requirements: ncurses (tput is needed to run test/format/test-curses) ------------------------------------------------------------------------------ Mac OS X ------------------------------------------------------------------------------ If configured with --with-tls on Mac OS X 10.7 or later, there will be compile warnings from mts/smtp/smtp.c about the deprecated OpenSSL that is supplied with that system. nmh will build and run with that OpenSSL, though it may be an old version. Alternatively, the OpenSSL source code is available from http://www.openssl.org/source/. To build 64-bit libraries, the OpenSSL configure command should start with, e.g., ./Configure darwin64-x86_64-cc To build nmh with those OpenSSL libraries, the CPPFLAGS and LDFLAGS can be set by adding the following to the nmh configure command line, or in the shell environment before calling configure or build_nmh: CPPFLAGS='-D__arch64__ -IOpenSSL-include-path' LDFLAGS=-LOpenSSL-lib-path ------------------------------------------------------------------------------ FreeBSD ------------------------------------------------------------------------------ Additional build-time package requirements: devel/autotools ftp/curl (if configured with --with-oauth) ------------------------------------------------------------------------------ Cygwin ------------------------------------------------------------------------------ Run-time package requirements: file libncurses10 or libncursesw10 libgdbm4 (only needed for slocal(1)) libiconv or libiconv2 (if you want iconv support) libreadline7 (if you want readline support) libsasl2_3 (if configured with --with-cyrus-sasl) openssl (if configured with --with-tls) libcurl (if configured with --with-oauth) Additional build-time package requirements: libncurses-devel or libncursesw-devel libgdbm4-devel (only needed for slocal(1)) libiconv-devel (if you want iconv support) libreadline-devel (if you want readline support) libsasl2-devel (if configuring with --with-cyrus-sasl) openssl-devel (if configuring with --with-tls) libcurl-devel (if configured with --with-oauth) Older versions of libncurses-devel do not install /usr/include/curses.h, /usr/include/term.h, and /usr/include/termcap.h. If yours does not, either add symlinks in /usr/include/ to those files in its ncurses/ subdirectory, or build with: make DEFAULT_INCLUDES='-I. -I/usr/include/ncurses' Test suite package requirements: ncurses (tput is needed to run test/format/test-curses) Note that the -link switch to refile cannot be used on FAT32 and other filesystems that do not support hard links. ------------------------------------------------------------------------------ HP-UX ------------------------------------------------------------------------------ Lots of problems have been reported with using HP-UX `cc'. In particular, problems with `scan' giving incorrect dates (everything is 01/00). It is highly recommended that you use `gcc' instead. ------------------------------------------------------------------------------ Irix (SGI) ------------------------------------------------------------------------------ Irix make is notoriously buggy. If you're using it, you should "touch config.h.in" before configuring to prevent a problem where it tries to rebuild targets that shouldn't be rebuilt. (Alternately, you can just use GNU make instead of Irix make.) ------------------------------------------------------------------------------ SunOS 4.1.1/4.1.3/4.1.4 ------------------------------------------------------------------------------ You can't use the C compiler that comes with SunOS 4 since it isn't ANSI C. But nmh builds just fine with gcc. ------------------------------------------------------------------------------ ---------- The nmh team nmh-workers@nongnu.org nmh-1.7.1-RC3/Makefile.am000644 007761 000024 00000076142 13243042053 015024 0ustar00kenhstaff000000 000000 ## Our Makefile.am template for Makefile.in (and, eventually, Makefile) ## ## Process this with automake to generate Makefile.in ## Lists are in `LC_ALL=C sort' order. ## ## We set this to get our autoconf macros in the m4 directory ACLOCAL_AMFLAGS = -I m4 AM_YFLAGS = -d ## ## This is the default set of libraries all programs link against. Some ## programs add extra libraries to this set, so they override this with ## a program-specific LDADD variable. Note that in all of the cases today ## LDADD is included in the program-specific LDADD since we want to add ## to this list of libraries, not replace it. ## LDADD = sbr/libmh.a ## ## These are used to create the default mhn.defaults config file ## MHNSEARCHPATH is the default path to look for MIME content handlers ## MHNSEARCHPROG is the script used to find the support programs ## MHNSEARCHPATH = "$(PATH)" MHNSEARCHPROG = $(srcdir)/etc/mhn.find.sh ## ## Install config files and back-end programs in our own subdirecctories. ## nmhetcdir = @sysconfdir@/nmh nmhlibexecdir = @libexecdir@/nmh ## ## nmh _does_ have a test suite! ## TESTS_ENVIRONMENT = MH_OBJ_DIR="@abs_builddir@" \ MH_VERSION="$(VERSION)" \ OAUTH_SUPPORT='@OAUTH_SUPPORT@' \ CURL_USER_AGENT='@CURL_USER_AGENT@' \ MH_TEST_DIR=`cd "@abs_builddir@" && pwd -P`/test/testdir \ nmhlibexecdir="$(nmhlibexecdir)" bindir="$(bindir)" \ mandir="$(mandir)" nmhetcdir="$(nmhetcdir)" \ nmhetcdirinst="@nmhetcdirinst@$(nmhetcdir)" \ supported_locks="$(supported_locks)" \ default_locking="${default_locking}" \ MULTIBYTE_ENABLED=$(MULTIBYTE_ENABLED) \ ICONV_ENABLED=$(ICONV_ENABLED) \ $(TESTS_SHELL) ## Keep at end of TESTS_ENVIRONMENT. ## ## Important note: the "cleanup" test should always be last ## TESTS = \ test/ali/test-ali \ test/anno/test-anno \ test/bad-input/test-header \ test/burst/test-burst \ test/burst/test-burst-mime \ test/comp/test-comp-format \ test/dist/test-dist \ test/folder/test-coverage \ test/folder/test-create \ test/folder/test-nocreate \ test/folder/test-packf \ test/folder/test-recurse \ test/folder/test-sortm \ test/folder/test-total \ test/format/test-ap \ test/format/test-curses \ test/format/test-dp \ test/format/test-fmtdump \ test/format/test-fmttest \ test/format/test-functions \ test/format/test-localmbox \ test/format/test-myhost \ test/format/test-mymbox \ test/format/test-myname \ test/format/test-nullstr \ test/format/test-rightjustify \ test/format/test-unquote \ test/forw/test-forw-coverage \ 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/inc/test-pop \ test/install-mh/test-install-mh \ test/install-mh/test-version-check \ test/locking/test-datalocking \ test/locking/test-spoollocking \ test/manpages/test-manpages \ test/mhbuild/test-attach \ test/mhbuild/test-cte \ test/mhbuild/test-ext-params \ test/mhbuild/test-forw \ test/mhbuild/test-header-encode \ test/mhbuild/test-mhbuild \ test/mhbuild/test-utf8-body \ test/mhfixmsg/test-mhfixmsg \ test/mhical/test-mhical \ test/mhl/test-mhl-flags \ test/mhl/test-rfc6532 \ test/mhlist/test-ext-params \ test/mhlist/test-mhlist \ test/mhmail/test-mhmail \ test/mhparam/test-mhparam \ test/mhpath/test-mhpath \ test/mhshow/test-binary \ test/mhshow/test-charset \ test/mhshow/test-cte-binary \ test/mhshow/test-msg-buffer-boundaries \ test/mhshow/test-qp \ test/mhshow/test-subpart \ test/mhshow/test-textcharset \ test/mhstore/test-mhstore \ test/mkstemp/test-mkstemp \ test/new/test-basic \ test/oauth/test-inc \ test/oauth/test-mhlogin \ test/oauth/test-mhparam \ test/oauth/test-send \ test/oauth/test-sendfrom \ test/oauth/test-share \ test/pick/test-pick \ test/pick/test-stderr \ test/post/test-messageid \ test/post/test-mts \ test/post/test-post-aliases \ test/post/test-post-basic \ test/post/test-post-bcc \ test/post/test-post-dcc \ test/post/test-post-envelope \ test/post/test-post-fcc \ test/post/test-post-group \ test/post/test-post-multifrom \ test/post/test-post-multiple \ test/post/test-rfc6531 \ test/post/test-sendfiles \ test/prompter/test-prompter \ test/rcv/test-rcvdist \ test/rcv/test-rcvpack \ test/rcv/test-rcvstore \ test/rcv/test-rcvtty \ test/refile/test-refile \ test/repl/test-convert \ test/repl/test-if-str \ test/repl/test-multicomp \ test/repl/test-repl \ test/repl/test-trailing-newline \ test/scan/test-header-parsing \ test/scan/test-scan \ test/scan/test-scan-multibyte \ test/send/test-sendfrom \ test/sequences/test-flist \ test/sequences/test-mark \ test/sequences/test-out-of-range \ test/show/test-show \ 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. XFAIL_TESTS = check_SCRIPTS = test/common.sh check_PROGRAMS = \ test/fakehttp \ test/fakepop \ test/fakesmtp \ test/getcanon \ test/getcwidth \ test/getfullname \ test/runpty \ # ## So they can be built without builing the `check' target. check-programs: $(check_PROGRAMS) ## The location of installed nmhetcdir is, for all purposes except ## distcheck, $nmhetcdir. For distcheck, prepend $MH_INST_DIR (from ## test/common.sh.in), which is based on $MH_TEST_DIR (from ## $TESTS_ENVIRONMENT). AM_DISTCHECK_CONFIGURE_FLAGS = DISABLE_SETGID_MAIL=1 \ NMHETCDIRINST='$${abs_builddir}/test/testdir/inst' ## ## Stuff that should be cleaned via "make clean" ## CLEANFILES = \ $(man_MANS) \ *.plist \ config/version.c \ etc/bash_completion_nmh \ etc/mhn.defaults \ etc/mts.conf \ man/man.sed \ man/mh-chart.man # clean-local: @rm -rf RPM a.out.dSYM uip/a.out.dSYM @rm -rf test/testdir ## ## Stuff that should be cleaned via "make maintainer-clean" ## MAINTAINERCLEANFILES = \ *.plist \ atags \ cscope.files \ cscope.in.out \ cscope.out \ cscope.po.out \ # ## ## And our own superclean, to get everything left by maintainer-clean. ## SUPERCLEANFILES = \ ChangeLog \ Makefile.in \ aclocal.m4 \ compile \ config.guess \ config.h.in \ config.h.in~ \ config.sub \ configure \ depcomp \ install-sh \ missing \ nmh-*.tar.gz \ nmh-*.tar.gz.sig \ test-driver \ ylwrap \ # superclean: maintainer-clean @rm -f $(SUPERCLEANFILES) .PHONY: superclean ## ## This is a list of all programs that get installed in the "bin" directory ## Note that primary difference between "PROGRAMS" and "SCRIPTS" is that ## the latter do not have $(EXEEXT) added on the end. ## bin_PROGRAMS = \ uip/ali \ uip/anno \ uip/burst \ uip/comp \ uip/dist \ uip/flist \ uip/fmttest \ uip/folder \ uip/forw \ uip/inc \ uip/install-mh \ uip/mark \ uip/mhbuild \ uip/mhfixmsg \ uip/mhical \ uip/mhlist \ uip/mhlogin \ uip/mhn \ uip/mhparam \ uip/mhpath \ uip/mhshow \ uip/mhstore \ uip/msgchk \ uip/new \ uip/packf \ uip/pick \ uip/prompter \ uip/refile \ uip/repl \ uip/rmf \ uip/rmm \ uip/scan \ uip/send \ uip/show \ uip/sortm \ uip/whatnow \ uip/whom \ # bin_SCRIPTS = \ etc/sendfiles \ uip/mhmail \ # ## ## This is all programs that get installed in the "libexec/nmh" directory ## nmhlibexec_PROGRAMS = \ uip/ap \ uip/dp \ uip/fmtdump \ uip/mhl \ uip/mkstemp \ uip/post \ uip/rcvdist \ uip/rcvpack \ uip/rcvstore \ uip/rcvtty \ uip/slocal \ uip/viamail \ # nmhlibexec_SCRIPTS = uip/spost ## ## Internal libraries that we create as part of the build process ## but do not install ## noinst_LIBRARIES = \ mts/libmts.a \ sbr/libmh.a \ # ## ## These are all of our header files. Right now we don't install any of ## them, but that might change in the future. ## noinst_HEADERS = \ h/addrsbr.h \ h/aliasbr.h \ h/crawl_folders.h \ h/dropsbr.h \ h/fmt_compile.h \ h/fmt_scan.h \ h/icalendar.h \ h/md5.h \ h/mf.h \ h/mh.h \ h/mhcachesbr.h \ h/mhparse.h \ h/mime.h \ h/mts.h \ h/netsec.h \ h/nmh.h \ h/oauth.h \ h/picksbr.h \ h/popsbr.h \ h/prototypes.h \ h/rcvmail.h \ h/scansbr.h \ h/signals.h \ h/tws.h \ h/utils.h \ mts/smtp/smtp.h \ sbr/ctype-checked.h \ sbr/lock_file.h \ sbr/m_maildir.h \ sbr/m_mktemp.h \ sbr/m_popen.h \ sbr/m_rand.h \ sbr/makedir.h \ sbr/message_id.h \ sbr/mime_type.h \ sbr/unquote.h \ thirdparty/jsmn/jsmn.h \ uip/mhfree.h \ uip/mhoutsbr.h \ uip/mhshowsbr.h \ # ## ## Extra files we need to install in various places ## dist_nmhetc_SCRIPTS = etc/rmmproc.messageid dist_nmhetc_DATA = \ etc/MailAliases \ etc/components \ etc/digestcomps \ etc/distcomps \ etc/forwcomps \ etc/mhical.12hour \ etc/mhical.24hour \ etc/mhl.body \ etc/mhl.digest \ etc/mhl.format \ etc/mhl.forward \ etc/mhl.headers \ etc/mhl.reply \ etc/mhl.replywithoutbody \ etc/mhshow.marker \ etc/rcvdistcomps \ etc/rcvdistcomps.outbox \ etc/replcomps \ etc/replgroupcomps \ etc/scan.MMDDYY \ etc/scan.YYYYMMDD \ etc/scan.curses \ etc/scan.default \ etc/scan.highlighted \ etc/scan.mailx \ etc/scan.nomime \ etc/scan.size \ etc/scan.time \ etc/scan.timely \ etc/scan.unseen \ # ## ## The same as above, but we don't include these in the distribution ## (because they're generated at compile time) ## nmhetc_DATA = \ etc/bash_completion_nmh \ etc/mhn.defaults \ etc/mts.conf \ # ## ## Documentation that gets installed in docdir ## dist_doc_DATA = \ COPYRIGHT \ INSTALL \ NEWS \ README \ VERSION \ docs/COMPLETION-TCSH \ docs/COMPLETION-ZSH \ docs/DIFFERENCES \ docs/FAQ \ docs/MAIL.FILTERING \ docs/MAILING-LISTS \ docs/README-ATTACHMENTS \ docs/README-HOOKS \ docs/README-components \ docs/README.SASL \ docs/README.about \ docs/README.developers \ docs/README.manpages \ docs/TODO \ # ## ## Contribs that get installed in docdir/contrib/ ## docs_contribdir = $(docdir)/contrib dist_docs_contrib_SCRIPTS = \ docs/contrib/localpostproc \ docs/contrib/ml \ docs/contrib/replyfilter \ docs/contrib/vpick \ # dist_docs_contrib_DATA = docs/contrib/replaliases ## ## Our man pages ## man_MANS = \ man/MH.7 \ man/ali.1 \ man/anno.1 \ man/ap.8 \ man/burst.1 \ man/comp.1 \ man/dist.1 \ man/dp.8 \ man/flist.1 \ man/flists.1 \ man/fmtdump.8 \ man/fmttest.1 \ man/fnext.1 \ man/folder.1 \ man/folders.1 \ man/forw.1 \ man/fprev.1 \ man/inc.1 \ man/install-mh.1 \ man/mark.1 \ man/mh-alias.5 \ man/mh-chart.7 \ man/mh-draft.5 \ man/mh-folders.5 \ man/mh-format.5 \ man/mh-mail.5 \ man/mh-mime.7 \ man/mh-mkstemp.1 \ man/mh-profile.5 \ man/mh-sequence.5 \ man/mh-tailor.5 \ man/mh_profile.5 \ man/mhbuild.1 \ man/mhfixmsg.1 \ man/mhical.1 \ man/mhl.1 \ man/mhlist.1 \ man/mhlogin.1 \ man/mhmail.1 \ man/mhn.1 \ man/mhparam.1 \ man/mhpath.1 \ man/mhshow.1 \ man/mhstore.1 \ man/msgchk.1 \ man/mts.conf.5 \ man/new.1 \ man/next.1 \ man/nmh.7 \ man/packf.1 \ man/pick.1 \ man/post.8 \ man/prev.1 \ man/prompter.1 \ man/rcvdist.1 \ man/rcvpack.1 \ man/rcvstore.1 \ man/rcvtty.1 \ man/refile.1 \ man/repl.1 \ man/rmf.1 \ man/rmm.1 \ man/scan.1 \ man/send.1 \ 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/MH.man \ man/ali.man \ man/anno.man \ man/ap.man \ man/burst.man \ man/comp.man \ man/dist.man \ man/dp.man \ man/flist.man \ man/flists.man \ man/fmtdump.man \ man/fmttest.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-folders.man \ man/mh-format.man \ man/mh-mail.man \ man/mh-mime.man \ man/mh-mkstemp.man \ man/mh-profile.man \ man/mh-sequence.man \ man/mh-tailor.man \ man/mh_profile.man \ man/mhbuild.man \ man/mhfixmsg.man \ man/mhical.man \ man/mhl.man \ man/mhlist.man \ man/mhlogin.man \ man/mhmail.man \ man/mhn.man \ man/mhparam.man \ man/mhpath.man \ man/mhshow.man \ man/mhstore.man \ man/msgchk.man \ man/mts.conf.man \ man/new.man \ man/next.man \ man/nmh.man \ man/packf.man \ man/pick.man \ man/post.man \ man/prev.man \ man/prompter.man \ man/rcvdist.man \ man/rcvpack.man \ man/rcvstore.man \ man/rcvtty.man \ man/refile.man \ man/repl.man \ 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 ## EXTRA_DIST = \ $(MHNSEARCHPROG) \ $(TESTS) \ $(man_SRCS) \ DATE \ MACHINES \ SPECS/nmh.cygport \ SPECS/nmh.spec \ autogen.sh \ build_nmh \ config/version.sh \ docs/ChangeLog_MH-3_to_MH-6.6 \ docs/ChangeLog_MH-6.7.0_to_MH-6.8.4.html \ etc/bash_completion_nmh-gen \ etc/mhn.defaults.sh \ etc/mts.conf.in \ etc/sendfiles \ sbr/icalparse.h \ test/README \ test/fakesendmail \ test/inc/deb359167.mbox \ test/inc/filler.txt \ test/inc/fromline.txt \ test/inc/md5sums \ test/inc/msgheader.txt \ test/mhbuild/nulls \ test/mhbuild/somebinary \ test/mhbuild/textplain \ test/mhbuild/tiny.jpg \ test/mhmail/attachment.txt \ test/oauth/common.sh \ test/post/test-post-common.sh \ test/send/README \ test/valgrind.supp \ uip/mhmail \ # ## ## These are all of the definitions for each of the programs listed above. ## They describe the source files that make up the programs and any particular ## overrides that are used to select different library options from the ## default. ## POSTLINK = @POSTLINK@ uip_ali_SOURCES = uip/ali.c uip/aliasbr.c uip_ali_LDADD = $(LDADD) $(POSTLINK) uip_anno_SOURCES = uip/anno.c uip/annosbr.c uip_anno_LDADD = $(LDADD) $(POSTLINK) uip_burst_SOURCES = uip/burst.c uip/mhparse.c uip/mhmisc.c uip/mhfree.c \ uip/mhcachesbr.c uip_burst_LDADD = $(LDADD) $(ICONVLIB) $(POSTLINK) uip_comp_SOURCES = uip/comp.c uip/whatnowproc.c uip/whatnowsbr.c uip/sendsbr.c \ uip/annosbr.c uip/distsbr.c uip_comp_LDADD = $(LDADD) $(READLINELIB) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_dist_SOURCES = uip/dist.c uip/whatnowproc.c uip/whatnowsbr.c uip/sendsbr.c \ uip/annosbr.c uip/distsbr.c uip/forwsbr.c uip_dist_LDADD = $(LDADD) $(READLINELIB) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_flist_SOURCES = uip/flist.c uip_flist_LDADD = $(LDADD) $(POSTLINK) uip_folder_SOURCES = uip/folder.c uip_folder_LDADD = $(LDADD) $(POSTLINK) uip_forw_SOURCES = uip/forw.c uip/whatnowproc.c uip/whatnowsbr.c uip/sendsbr.c \ uip/annosbr.c uip/distsbr.c uip/forwsbr.c uip_forw_LDADD = $(LDADD) $(READLINELIB) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_inc_SOURCES = uip/inc.c uip/scansbr.c uip/dropsbr.c uip/popsbr.c uip_inc_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(SASLLIB) $(CURLLIB) \ $(TLSLIB) $(POSTLINK) uip_install_mh_SOURCES = uip/install-mh.c uip_install_mh_LDADD = $(LDADD) $(POSTLINK) uip_mark_SOURCES = uip/mark.c uip_mark_LDADD = $(LDADD) $(POSTLINK) uip_mhbuild_SOURCES = uip/mhbuild.c uip/mhbuildsbr.c uip/mhcachesbr.c \ uip/mhlistsbr.c uip/mhoutsbr.c uip/mhmisc.c \ uip/mhfree.c uip/mhparse.c \ uip/mhstoresbr.c uip/mhshowsbr.c uip_mhbuild_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_mhfixmsg_SOURCES = uip/mhfixmsg.c uip/mhparse.c uip/mhcachesbr.c \ uip/mhoutsbr.c uip/mhmisc.c uip/mhfree.c \ uip/mhshowsbr.c uip/mhlistsbr.c uip_mhfixmsg_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_mhical_SOURCES = uip/mhical.c uip_mhical_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_mhlist_SOURCES = uip/mhlist.c uip/mhparse.c uip/mhcachesbr.c \ uip/mhlistsbr.c uip/mhmisc.c uip/mhfree.c uip_mhlist_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_mhn_SOURCES = uip/mhn.c uip/mhparse.c uip/mhcachesbr.c uip/mhshowsbr.c \ uip/mhlistsbr.c uip/mhstoresbr.c uip/mhmisc.c uip/mhfree.c uip_mhn_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_mhparam_SOURCES = uip/mhparam.c uip_mhparam_LDADD = $(LDADD) $(POSTLINK) uip_mhpath_SOURCES = uip/mhpath.c uip_mhpath_LDADD = $(LDADD) $(POSTLINK) uip_mhshow_SOURCES = uip/mhshow.c uip/mhparse.c uip/mhcachesbr.c \ uip/mhshowsbr.c uip/mhlistsbr.c uip/mhmisc.c \ uip/mhfree.c uip_mhshow_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_mhstore_SOURCES = uip/mhstore.c uip/mhparse.c uip/mhcachesbr.c \ uip/mhshowsbr.c uip/mhlistsbr.c uip/mhstoresbr.c \ uip/mhmisc.c uip/mhfree.c uip_mhstore_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_msgchk_SOURCES = uip/msgchk.c uip/popsbr.c uip_msgchk_LDADD = $(LDADD) $(SASLLIB) $(CURLLIB) $(TLSLIB) $(POSTLINK) uip_new_SOURCES = uip/new.c uip_new_LDADD = $(LDADD) $(POSTLINK) uip_packf_SOURCES = uip/packf.c uip/dropsbr.c uip_packf_LDADD = $(LDADD) $(POSTLINK) uip_pick_SOURCES = uip/pick.c uip/picksbr.c uip_pick_LDADD = $(LDADD) $(ICONVLIB) $(POSTLINK) uip_prompter_SOURCES = uip/prompter.c uip_prompter_LDADD = $(LDADD) $(POSTLINK) uip_refile_SOURCES = uip/refile.c uip_refile_LDADD = $(LDADD) $(POSTLINK) uip_repl_SOURCES = uip/repl.c uip/replsbr.c uip/whatnowproc.c uip/whatnowsbr.c \ uip/sendsbr.c uip/annosbr.c uip/distsbr.c uip_repl_LDADD = $(LDADD) $(READLINELIB) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_rmf_SOURCES = uip/rmf.c uip_rmf_LDADD = $(LDADD) $(POSTLINK) uip_rmm_SOURCES = uip/rmm.c uip_rmm_LDADD = $(LDADD) $(POSTLINK) uip_scan_SOURCES = uip/scan.c uip/scansbr.c uip_scan_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_send_SOURCES = uip/send.c uip/sendsbr.c uip/annosbr.c \ uip/distsbr.c uip_send_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_show_SOURCES = uip/show.c uip/mhlsbr.c uip_show_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_sortm_SOURCES = uip/sortm.c uip_sortm_LDADD = $(LDADD) $(POSTLINK) uip_whatnow_SOURCES = uip/whatnow.c uip/whatnowsbr.c uip/sendsbr.c \ uip/annosbr.c uip/distsbr.c uip_whatnow_LDADD = $(LDADD) $(READLINELIB) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_whom_SOURCES = uip/whom.c uip/distsbr.c uip_whom_LDADD = $(LDADD) $(POSTLINK) ## ## Program definitions for all utilities that end up in $(nmhlibexecdir) ## uip_ap_SOURCES = uip/ap.c uip_ap_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_dp_SOURCES = uip/dp.c uip_dp_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_fmtdump_SOURCES = uip/fmtdump.c uip_fmtdump_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_fmttest_SOURCES = uip/fmttest.c uip_fmttest_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_mhl_SOURCES = uip/mhl.c uip/mhlsbr.c uip_mhl_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_mhlogin_SOURCES = uip/mhlogin.c uip_mhlogin_LDADD = mts/libmts.a $(LDADD) $(CURLLIB) $(POSTLINK) uip_mkstemp_SOURCES = uip/mkstemp.c uip_mkstemp_LDADD = $(LDADD) $(POSTLINK) uip_post_SOURCES = uip/post.c uip/aliasbr.c uip_post_LDADD = mts/libmts.a $(LDADD) $(SASLLIB) $(CURLLIB) $(TLSLIB) \ $(POSTLINK) uip_rcvdist_SOURCES = uip/rcvdist.c uip/distsbr.c uip_rcvdist_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_rcvpack_SOURCES = uip/rcvpack.c uip/dropsbr.c uip_rcvpack_LDADD = $(LDADD) $(POSTLINK) uip_rcvstore_SOURCES = uip/rcvstore.c uip_rcvstore_LDADD = $(LDADD) $(POSTLINK) uip_rcvtty_SOURCES = uip/rcvtty.c uip/scansbr.c uip_rcvtty_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_slocal_SOURCES = uip/slocal.c uip/aliasbr.c uip/dropsbr.c uip_slocal_LDADD = $(LDADD) $(NDBM_LIBS) $(POSTLINK) uip_viamail_SOURCES = uip/viamail.c uip/mhmisc.c uip/sendsbr.c \ uip/annosbr.c uip/distsbr.c uip_viamail_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) ## ## Other program definitions ## test_getfullname_SOURCES = test/getfullname.c test_getfullname_LDADD = $(LDADD) $(POSTLINK) test_getcanon_SOURCES = test/getcanon.c test_getcanon_LDADD = $(POSTLINK) test_fakepop_SOURCES = test/fakepop.c test/server.c test_fakepop_LDADD = $(POSTLINK) test_fakesmtp_SOURCES = test/fakesmtp.c test/server.c test_fakesmtp_LDADD = $(POSTLINK) test_fakehttp_SOURCES = test/fakehttp.c test/server.c test_fakehttp_LDADD = $(LDADD) $(POSTLINK) test_getcwidth_SOURCES = test/getcwidth.c test_getcwidth_LDADD = $(POSTLINK) test_runpty_SOURCES = test/runpty.c test_runpty_LDADD = $(POSTLINK) ## ## Our rebuild rules for files that aren't built via the normal mechanisms ## ## Hard-code the config/version.c target, instead of using $@, so this ## rule works for the distcheck target with Solaris (System V) make. ## distcheck uses VPATH, causes that make to prepend the VPATH to $@. config/version.c: Makefile $(srcdir)/config/version.sh env srcdir="$(srcdir)" sh $(srcdir)/config/version.sh $(VERSION) > ./config/version.c etc/bash_completion_nmh: $(srcdir)/etc/bash_completion_nmh-gen $(srcdir)/etc/bash_completion_nmh-gen > $@ etc/mts.conf: $(srcdir)/etc/mts.conf.in Makefile @rm -f $@ $(SED) -e 's,%mts%,$(MTS),' \ -e 's,%mailspool%,$(mailspool),' \ -e 's,%smtpserver%,$(smtpserver),' \ -e 's,%default_locking%,$(default_locking),' \ -e 's,%supported_locks%,$(supported_locks),' \ < $(srcdir)/etc/mts.conf.in > $@ etc/mhn.defaults: $(srcdir)/etc/mhn.defaults.sh $(MHNSEARCHPROG) @rm -f $@ $(srcdir)/etc/mhn.defaults.sh $(MHNSEARCHPATH) $(MHNSEARCHPROG) > $@ ## ## Use configure to set up default LN, but through a make variable so ## that it can be overridden at install time. ## LN = @LN@ ## ## This rule gets called at "make install" time; we use it to create links ## between different programs. ## install-exec-hook: @rm -f $(DESTDIR)$(bindir)/flists$(EXEEXT) @rm -f $(DESTDIR)$(bindir)/folders$(EXEEXT) @rm -f $(DESTDIR)$(bindir)/fnext$(EXEEXT) @rm -f $(DESTDIR)$(bindir)/fprev$(EXEEXT) @rm -f $(DESTDIR)$(bindir)/unseen$(EXEEXT) @rm -f $(DESTDIR)$(bindir)/prev$(EXEEXT) @rm -f $(DESTDIR)$(bindir)/next$(EXEEXT) $(LN) $(DESTDIR)$(bindir)/flist$(EXEEXT) $(DESTDIR)$(bindir)/flists$(EXEEXT) $(LN) $(DESTDIR)$(bindir)/folder$(EXEEXT) $(DESTDIR)$(bindir)/folders$(EXEEXT) $(LN) $(DESTDIR)$(bindir)/new$(EXEEXT) $(DESTDIR)$(bindir)/fnext$(EXEEXT) $(LN) $(DESTDIR)$(bindir)/new$(EXEEXT) $(DESTDIR)$(bindir)/fprev$(EXEEXT) $(LN) $(DESTDIR)$(bindir)/new$(EXEEXT) $(DESTDIR)$(bindir)/unseen$(EXEEXT) $(LN) $(DESTDIR)$(bindir)/show$(EXEEXT) $(DESTDIR)$(bindir)/prev$(EXEEXT) $(LN) $(DESTDIR)$(bindir)/show$(EXEEXT) $(DESTDIR)$(bindir)/next$(EXEEXT) if test x$(SETGID_MAIL) != x; then \ chgrp $(MAIL_SPOOL_GRP) $(DESTDIR)$(bindir)/inc$(EXEEXT) && \ chmod 2755 $(DESTDIR)$(bindir)/inc$(EXEEXT); \ fi ## ## Make sure we remove those links at uninstall time ## uninstall-hook: rm -f $(DESTDIR)$(bindir)/flists$(EXEEXT) rm -f $(DESTDIR)$(bindir)/folders$(EXEEXT) rm -f $(DESTDIR)$(bindir)/fnext$(EXEEXT) rm -f $(DESTDIR)$(bindir)/fprev$(EXEEXT) rm -f $(DESTDIR)$(bindir)/unseen$(EXEEXT) rm -f $(DESTDIR)$(bindir)/prev$(EXEEXT) rm -f $(DESTDIR)$(bindir)/next$(EXEEXT) ## ## Our rules to build our internal libraries (libmh.a, libmts.a) ## sbr_libmh_a_SOURCES = \ config/config.c \ config/version.c \ sbr/addrsbr.c \ sbr/ambigsw.c \ sbr/arglist.c \ sbr/atooi.c \ sbr/base64.c \ sbr/brkstring.c \ sbr/charstring.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/context_replace.c \ sbr/context_save.c \ sbr/copyip.c \ sbr/cpydata.c \ sbr/cpydgst.c \ sbr/crawl_folders.c \ sbr/credentials.c \ sbr/ctype-checked.c \ sbr/datetime.c \ sbr/discard.c \ sbr/done.c \ sbr/dtime.c \ sbr/dtimep.l \ sbr/encode_rfc2047.c \ sbr/error.c \ sbr/escape_addresses.c \ sbr/ext_hook.c \ sbr/fdcompare.c \ sbr/fmt_addr.c \ sbr/fmt_compile.c \ sbr/fmt_new.c \ sbr/fmt_rfc2047.c \ sbr/fmt_scan.c \ sbr/folder_addmsg.c \ sbr/folder_delmsgs.c \ sbr/folder_free.c \ sbr/folder_pack.c \ sbr/folder_read.c \ sbr/folder_realloc.c \ sbr/getarguments.c \ sbr/getcpy.c \ sbr/geteditor.c \ sbr/getfolder.c \ sbr/getpass.c \ sbr/icalendar.l \ sbr/icalparse.y \ sbr/lock_file.c \ sbr/m_atoi.c \ sbr/m_backup.c \ sbr/m_convert.c \ sbr/m_draft.c \ sbr/m_getfld.c \ sbr/m_gmprot.c \ sbr/m_maildir.c \ sbr/m_mktemp.c \ sbr/m_name.c \ sbr/m_popen.c \ sbr/m_rand.c \ sbr/makedir.c \ sbr/md5.c \ sbr/message_id.c \ sbr/mf.c \ sbr/mime_type.c \ sbr/mts.c \ sbr/netsec.c \ sbr/oauth.c \ sbr/oauth_prof.c \ sbr/path.c \ sbr/pidstatus.c \ sbr/pidwait.c \ sbr/print_help.c \ sbr/print_sw.c \ sbr/print_version.c \ sbr/push.c \ sbr/r1bindex.c \ sbr/read_line.c \ sbr/read_switch.c \ sbr/read_switch_multiword.c \ sbr/read_switch_multiword_via_readline.c \ sbr/read_yes_or_no_if_tty.c \ sbr/readconfig.c \ sbr/refile.c \ sbr/remdir.c \ sbr/ruserpass.c \ sbr/seq_add.c \ sbr/seq_bits.c \ sbr/seq_del.c \ sbr/seq_getnum.c \ sbr/seq_list.c \ sbr/seq_nameok.c \ sbr/seq_print.c \ sbr/seq_read.c \ sbr/seq_save.c \ sbr/seq_setcur.c \ sbr/seq_setprev.c \ sbr/seq_setunseen.c \ sbr/showfile.c \ sbr/signals.c \ sbr/smatch.c \ sbr/snprintb.c \ sbr/ssequal.c \ sbr/strindex.c \ sbr/terminal.c \ sbr/trimcpy.c \ sbr/unquote.c \ sbr/uprf.c \ sbr/utils.c \ sbr/vector.c \ sbr/vfgets.c \ thirdparty/jsmn/jsmn.c \ # sbr_libmh_a_LIBADD = $(LIBOBJS) ## ## Need explicit dependency so that YACC is run before LEX. ## sbr/icalendar.c: sbr/icalparse.c ## ## Because these files use the definitions in the libmh rule below, ## they need to be rebuilt if the Makefile changes. ## config/sbr_libmh_a-config.$(OBJEXT) sbr/sbr_libmh_a-mts.$(OBJEXT): Makefile sbr_libmh_a_CPPFLAGS = ${AM_CPPFLAGS} -I./sbr \ -DNMHBINDIR='"$(bindir)"' \ -DNMHLIBEXECDIR='"$(nmhlibexecdir)"' \ -DNMHETCDIR='"@nmhetcdirinst@$(nmhetcdir)"' \ -DNMHDOCDIR='"@docdir@"' \ -DMAILSPOOL='"$(mailspool)"' \ -DSENDMAILPATH='"$(sendmailpath)"' mts_libmts_a_SOURCES = mts/smtp/smtp.c ## ## Our rules for generating man pages (both the rule for man.sed and ## the implicit rules for man page generation). ## manext1 = 1 manext5 = 5 manext7 = 7 manext8 = 8 $(man_MANS): man/man.sed man/man.sed: Makefile @echo 's,%nmhwarning%,THIS FILE HAS BEEN AUTOMATICALLY GENERATED. DO NOT EDIT.,g' > $@ @echo 's,%nmhversion%,nmh-$(VERSION),g' >> $@ @echo 's,%nmhetcdir%,$(nmhetcdir),g' >> $@ @echo 's,%nmhlibexecdir%,$(nmhlibexecdir),g' >> $@ @echo 's,%bindir%,$(bindir),g' >> $@ @echo 's,%docdir%,$(docdir),g' >> $@ @echo 's,%mandir%,$(mandir),g' >> $@ @echo 's,%mailspool%,$(mailspool),g' >> $@ @echo 's,%sendmailpath%,$(sendmailpath),g' >> $@ @echo 's,%default_locking%,$(default_locking),g' >> $@ @echo 's,%supported_locks%,$(supported_locks),g' >> $@ @echo 's,%manext1%,$(manext1),g' >> $@ @echo 's,%manext5%,$(manext5),g' >> $@ @echo 's,%manext7%,$(manext7),g' >> $@ @echo 's,%manext8%,$(manext8),g' >> $@ @echo '/%mhl_forward%/r $(top_srcdir)/etc/mhl.forward' >> $@ @echo ' s,%mhl_forward%,,g' >> $@ @echo '/%mhl_format%/r $(top_srcdir)/etc/mhl.format' >> $@ @echo ' s,%mhl_format%,,g' >> $@ @echo '/%mhl_reply%/r $(top_srcdir)/etc/mhl.reply' >> $@ @echo ' s,%mhl_reply%,,g' >> $@ man/mh-chart.man: $(man_SRCS) $(srcdir)/man/mh-chart-gen.sh > $@ .man.$(manext1): $(SED) -f man/man.sed $< > $@ .man.$(manext5): $(SED) -f man/man.sed $< > $@ .man.$(manext7): $(SED) -f man/man.sed $< > $@ .man.$(manext8): $(SED) -f man/man.sed $< > $@ man: $(man_MANS) cleanman: rm -f $(man_MANS) .PHONY: man cleanman ## Don't include commit hashes in ChangeLog. ChangeLog: @[ -d $(srcdir)/.git ] && (cd $(srcdir); git --no-pager log --abbrev-commit | \ egrep -v '^commit [0-9a-f]+$$' > $@) || true ## Make ChangeLog phony so it will always get regenerated. But don't ## fail if we don't have a git repository in order to allow ## regeneration of distribution archive or RPM. .PHONY: ChangeLog ## ## Our RPM build target ## rpm: dist @test -d $(rpmdir)/SOURCES || $(MKDIR_P) $(rpmdir)/SOURCES @mv -f $(DIST_ARCHIVES) $(rpmdir)/SOURCES @cp -p VERSION $(rpmdir)/SOURCES @rpmbuild --define '_topdir $(rpmdir)' \ --define '_tmppath %{_topdir}/TMP' \ --define "_sysconfdir $(DESTDIR)$(sysconfdir)" \ -ba SPECS/nmh.spec .PHONY: rpm ## ## Use GNU gcov to find the coverage of the test suite. ## These targets are not integrated into the other automake ## targets because they will be used so infrequently, if at all. ## gcov: gcov-rebuild gcov-run gcov-process gcov-report gcov-rebuild: @echo rebuilding with AM_CFLAGS=--coverage . . . @(make clean && make AM_CFLAGS=--coverage) > /dev/null gcov-run: make check AM_CFLAGS=--coverage gcov-process: @for i in `find . -name '*.gcda'`; do \ gcov -pro `echo $$i | $(SED) 's%\\(.*\\)/%\\1 %'`; \ done gcov-report: @for i in `find . -name '*.gcno'`; do \ if test -f `echo $$i | sed 's%\.gcno%.gcda%'`; then :; else \ echo untested: $$i; \ fi; \ done gcov-mostlyclean: @find . -name '*.gcno' -o -name '*.gcda' | xargs rm gcov-clean: gcov-mostlyclean @find . -name '*.gcov' | xargs rm .PHONY: gcov gcov-rebuild gcov-run gcov-process gcov-report \ gcov-mostlyclean gcov-clean ## ## Rules to upload the distribution to savannah ## upload: dist @if test -z "$(SAVANNAH_USERNAME)"; then \ echo "You need to set SAVANNAH_USERNAME to the your username on savannah.gnu.org." ;\ echo "You can set it either in your environment or on the make command line."; \ false; \ fi @echo "Did you run 'make distcheck' already?" @if test -z "$(SKIP_GPG_SIG)"; then \ echo "Creating GPG signature (set SKIP_GPG_SIG to bypass this step)"; \ gpg --output $(DIST_ARCHIVES).sig --detach-sig $(DIST_ARCHIVES); \ fi @echo "Setting permissions for savannah.gnu.org" chmod 664 $(DIST_ARCHIVES) if test -f $(DIST_ARCHIVES).sig; then \ chmod 664 $(DIST_ARCHIVES).sig; \ fi @echo "Uploading to savannah" scp -p $(DIST_ARCHIVES)* $(SAVANNAH_USERNAME)@dl.sv.nongnu.org:/releases/nmh .PHONY: upload nmh-1.7.1-RC3/Makefile.in000644 007761 000024 00001357236 13243043453 015051 0ustar00kenhstaff000000 000000 # Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ XFAIL_TESTS = check_PROGRAMS = test/fakehttp$(EXEEXT) test/fakepop$(EXEEXT) \ test/fakesmtp$(EXEEXT) test/getcanon$(EXEEXT) \ test/getcwidth$(EXEEXT) test/getfullname$(EXEEXT) \ test/runpty$(EXEEXT) bin_PROGRAMS = uip/ali$(EXEEXT) uip/anno$(EXEEXT) uip/burst$(EXEEXT) \ uip/comp$(EXEEXT) uip/dist$(EXEEXT) uip/flist$(EXEEXT) \ uip/fmttest$(EXEEXT) uip/folder$(EXEEXT) uip/forw$(EXEEXT) \ uip/inc$(EXEEXT) uip/install-mh$(EXEEXT) uip/mark$(EXEEXT) \ uip/mhbuild$(EXEEXT) uip/mhfixmsg$(EXEEXT) uip/mhical$(EXEEXT) \ uip/mhlist$(EXEEXT) uip/mhlogin$(EXEEXT) uip/mhn$(EXEEXT) \ uip/mhparam$(EXEEXT) uip/mhpath$(EXEEXT) uip/mhshow$(EXEEXT) \ uip/mhstore$(EXEEXT) uip/msgchk$(EXEEXT) uip/new$(EXEEXT) \ uip/packf$(EXEEXT) uip/pick$(EXEEXT) uip/prompter$(EXEEXT) \ uip/refile$(EXEEXT) uip/repl$(EXEEXT) uip/rmf$(EXEEXT) \ uip/rmm$(EXEEXT) uip/scan$(EXEEXT) uip/send$(EXEEXT) \ uip/show$(EXEEXT) uip/sortm$(EXEEXT) uip/whatnow$(EXEEXT) \ uip/whom$(EXEEXT) nmhlibexec_PROGRAMS = uip/ap$(EXEEXT) uip/dp$(EXEEXT) \ uip/fmtdump$(EXEEXT) uip/mhl$(EXEEXT) uip/mkstemp$(EXEEXT) \ uip/post$(EXEEXT) uip/rcvdist$(EXEEXT) uip/rcvpack$(EXEEXT) \ uip/rcvstore$(EXEEXT) uip/rcvtty$(EXEEXT) uip/slocal$(EXEEXT) \ uip/viamail$(EXEEXT) subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/cppflags.m4 \ $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/locking.m4 \ $(top_srcdir)/m4/mimetype.m4 $(top_srcdir)/m4/ndbm.m4 \ $(top_srcdir)/m4/netlibs.m4 $(top_srcdir)/m4/readline.m4 \ $(top_srcdir)/m4/tputs.m4 $(top_srcdir)/VERSION \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(dist_docs_contrib_SCRIPTS) \ $(dist_nmhetc_SCRIPTS) $(dist_doc_DATA) \ $(dist_docs_contrib_DATA) $(dist_nmhetc_DATA) \ $(noinst_HEADERS) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = test/common.sh uip/spost CONFIG_CLEAN_VPATH_FILES = LIBRARIES = $(noinst_LIBRARIES) ARFLAGS = cru AM_V_AR = $(am__v_AR_@AM_V@) am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) am__v_AR_0 = @echo " AR " $@; am__v_AR_1 = mts_libmts_a_AR = $(AR) $(ARFLAGS) mts_libmts_a_LIBADD = am__dirstamp = $(am__leading_dot)dirstamp am_mts_libmts_a_OBJECTS = mts/smtp/smtp.$(OBJEXT) mts_libmts_a_OBJECTS = $(am_mts_libmts_a_OBJECTS) sbr_libmh_a_AR = $(AR) $(ARFLAGS) LIBOBJDIR = sbr/ sbr_libmh_a_DEPENDENCIES = $(LIBOBJS) am_sbr_libmh_a_OBJECTS = config/sbr_libmh_a-config.$(OBJEXT) \ config/sbr_libmh_a-version.$(OBJEXT) \ sbr/sbr_libmh_a-addrsbr.$(OBJEXT) \ sbr/sbr_libmh_a-ambigsw.$(OBJEXT) \ sbr/sbr_libmh_a-arglist.$(OBJEXT) \ sbr/sbr_libmh_a-atooi.$(OBJEXT) \ sbr/sbr_libmh_a-base64.$(OBJEXT) \ sbr/sbr_libmh_a-brkstring.$(OBJEXT) \ sbr/sbr_libmh_a-charstring.$(OBJEXT) \ sbr/sbr_libmh_a-check_charset.$(OBJEXT) \ sbr/sbr_libmh_a-client.$(OBJEXT) \ sbr/sbr_libmh_a-closefds.$(OBJEXT) \ sbr/sbr_libmh_a-concat.$(OBJEXT) \ sbr/sbr_libmh_a-context_del.$(OBJEXT) \ sbr/sbr_libmh_a-context_find.$(OBJEXT) \ sbr/sbr_libmh_a-context_foil.$(OBJEXT) \ sbr/sbr_libmh_a-context_read.$(OBJEXT) \ sbr/sbr_libmh_a-context_replace.$(OBJEXT) \ sbr/sbr_libmh_a-context_save.$(OBJEXT) \ sbr/sbr_libmh_a-copyip.$(OBJEXT) \ sbr/sbr_libmh_a-cpydata.$(OBJEXT) \ sbr/sbr_libmh_a-cpydgst.$(OBJEXT) \ sbr/sbr_libmh_a-crawl_folders.$(OBJEXT) \ sbr/sbr_libmh_a-credentials.$(OBJEXT) \ sbr/sbr_libmh_a-ctype-checked.$(OBJEXT) \ sbr/sbr_libmh_a-datetime.$(OBJEXT) \ sbr/sbr_libmh_a-discard.$(OBJEXT) \ sbr/sbr_libmh_a-done.$(OBJEXT) sbr/sbr_libmh_a-dtime.$(OBJEXT) \ sbr/sbr_libmh_a-dtimep.$(OBJEXT) \ sbr/sbr_libmh_a-encode_rfc2047.$(OBJEXT) \ sbr/sbr_libmh_a-error.$(OBJEXT) \ sbr/sbr_libmh_a-escape_addresses.$(OBJEXT) \ sbr/sbr_libmh_a-ext_hook.$(OBJEXT) \ sbr/sbr_libmh_a-fdcompare.$(OBJEXT) \ sbr/sbr_libmh_a-fmt_addr.$(OBJEXT) \ sbr/sbr_libmh_a-fmt_compile.$(OBJEXT) \ sbr/sbr_libmh_a-fmt_new.$(OBJEXT) \ sbr/sbr_libmh_a-fmt_rfc2047.$(OBJEXT) \ sbr/sbr_libmh_a-fmt_scan.$(OBJEXT) \ sbr/sbr_libmh_a-folder_addmsg.$(OBJEXT) \ sbr/sbr_libmh_a-folder_delmsgs.$(OBJEXT) \ sbr/sbr_libmh_a-folder_free.$(OBJEXT) \ sbr/sbr_libmh_a-folder_pack.$(OBJEXT) \ sbr/sbr_libmh_a-folder_read.$(OBJEXT) \ sbr/sbr_libmh_a-folder_realloc.$(OBJEXT) \ sbr/sbr_libmh_a-getarguments.$(OBJEXT) \ sbr/sbr_libmh_a-getcpy.$(OBJEXT) \ sbr/sbr_libmh_a-geteditor.$(OBJEXT) \ sbr/sbr_libmh_a-getfolder.$(OBJEXT) \ sbr/sbr_libmh_a-getpass.$(OBJEXT) \ sbr/sbr_libmh_a-icalendar.$(OBJEXT) \ sbr/sbr_libmh_a-icalparse.$(OBJEXT) \ sbr/sbr_libmh_a-lock_file.$(OBJEXT) \ sbr/sbr_libmh_a-m_atoi.$(OBJEXT) \ sbr/sbr_libmh_a-m_backup.$(OBJEXT) \ sbr/sbr_libmh_a-m_convert.$(OBJEXT) \ sbr/sbr_libmh_a-m_draft.$(OBJEXT) \ sbr/sbr_libmh_a-m_getfld.$(OBJEXT) \ sbr/sbr_libmh_a-m_gmprot.$(OBJEXT) \ sbr/sbr_libmh_a-m_maildir.$(OBJEXT) \ sbr/sbr_libmh_a-m_mktemp.$(OBJEXT) \ sbr/sbr_libmh_a-m_name.$(OBJEXT) \ sbr/sbr_libmh_a-m_popen.$(OBJEXT) \ sbr/sbr_libmh_a-m_rand.$(OBJEXT) \ sbr/sbr_libmh_a-makedir.$(OBJEXT) \ sbr/sbr_libmh_a-md5.$(OBJEXT) \ sbr/sbr_libmh_a-message_id.$(OBJEXT) \ sbr/sbr_libmh_a-mf.$(OBJEXT) \ sbr/sbr_libmh_a-mime_type.$(OBJEXT) \ sbr/sbr_libmh_a-mts.$(OBJEXT) sbr/sbr_libmh_a-netsec.$(OBJEXT) \ sbr/sbr_libmh_a-oauth.$(OBJEXT) \ sbr/sbr_libmh_a-oauth_prof.$(OBJEXT) \ sbr/sbr_libmh_a-path.$(OBJEXT) \ sbr/sbr_libmh_a-pidstatus.$(OBJEXT) \ sbr/sbr_libmh_a-pidwait.$(OBJEXT) \ sbr/sbr_libmh_a-print_help.$(OBJEXT) \ sbr/sbr_libmh_a-print_sw.$(OBJEXT) \ sbr/sbr_libmh_a-print_version.$(OBJEXT) \ sbr/sbr_libmh_a-push.$(OBJEXT) \ sbr/sbr_libmh_a-r1bindex.$(OBJEXT) \ sbr/sbr_libmh_a-read_line.$(OBJEXT) \ sbr/sbr_libmh_a-read_switch.$(OBJEXT) \ sbr/sbr_libmh_a-read_switch_multiword.$(OBJEXT) \ sbr/sbr_libmh_a-read_switch_multiword_via_readline.$(OBJEXT) \ sbr/sbr_libmh_a-read_yes_or_no_if_tty.$(OBJEXT) \ sbr/sbr_libmh_a-readconfig.$(OBJEXT) \ sbr/sbr_libmh_a-refile.$(OBJEXT) \ sbr/sbr_libmh_a-remdir.$(OBJEXT) \ sbr/sbr_libmh_a-ruserpass.$(OBJEXT) \ sbr/sbr_libmh_a-seq_add.$(OBJEXT) \ sbr/sbr_libmh_a-seq_bits.$(OBJEXT) \ sbr/sbr_libmh_a-seq_del.$(OBJEXT) \ sbr/sbr_libmh_a-seq_getnum.$(OBJEXT) \ sbr/sbr_libmh_a-seq_list.$(OBJEXT) \ sbr/sbr_libmh_a-seq_nameok.$(OBJEXT) \ sbr/sbr_libmh_a-seq_print.$(OBJEXT) \ sbr/sbr_libmh_a-seq_read.$(OBJEXT) \ sbr/sbr_libmh_a-seq_save.$(OBJEXT) \ sbr/sbr_libmh_a-seq_setcur.$(OBJEXT) \ sbr/sbr_libmh_a-seq_setprev.$(OBJEXT) \ sbr/sbr_libmh_a-seq_setunseen.$(OBJEXT) \ sbr/sbr_libmh_a-showfile.$(OBJEXT) \ sbr/sbr_libmh_a-signals.$(OBJEXT) \ sbr/sbr_libmh_a-smatch.$(OBJEXT) \ sbr/sbr_libmh_a-snprintb.$(OBJEXT) \ sbr/sbr_libmh_a-ssequal.$(OBJEXT) \ sbr/sbr_libmh_a-strindex.$(OBJEXT) \ sbr/sbr_libmh_a-terminal.$(OBJEXT) \ sbr/sbr_libmh_a-trimcpy.$(OBJEXT) \ sbr/sbr_libmh_a-unquote.$(OBJEXT) \ sbr/sbr_libmh_a-uprf.$(OBJEXT) sbr/sbr_libmh_a-utils.$(OBJEXT) \ sbr/sbr_libmh_a-vector.$(OBJEXT) \ sbr/sbr_libmh_a-vfgets.$(OBJEXT) \ thirdparty/jsmn/sbr_libmh_a-jsmn.$(OBJEXT) sbr_libmh_a_OBJECTS = $(am_sbr_libmh_a_OBJECTS) am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(nmhlibexecdir)" \ "$(DESTDIR)$(bindir)" "$(DESTDIR)$(docs_contribdir)" \ "$(DESTDIR)$(nmhetcdir)" "$(DESTDIR)$(nmhlibexecdir)" \ "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" \ "$(DESTDIR)$(man7dir)" "$(DESTDIR)$(man8dir)" \ "$(DESTDIR)$(docdir)" "$(DESTDIR)$(docs_contribdir)" \ "$(DESTDIR)$(nmhetcdir)" "$(DESTDIR)$(nmhetcdir)" PROGRAMS = $(bin_PROGRAMS) $(nmhlibexec_PROGRAMS) am_test_fakehttp_OBJECTS = test/fakehttp.$(OBJEXT) \ test/server.$(OBJEXT) test_fakehttp_OBJECTS = $(am_test_fakehttp_OBJECTS) am__DEPENDENCIES_1 = test_fakehttp_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) am_test_fakepop_OBJECTS = test/fakepop.$(OBJEXT) test/server.$(OBJEXT) test_fakepop_OBJECTS = $(am_test_fakepop_OBJECTS) test_fakepop_DEPENDENCIES = $(am__DEPENDENCIES_1) am_test_fakesmtp_OBJECTS = test/fakesmtp.$(OBJEXT) \ test/server.$(OBJEXT) test_fakesmtp_OBJECTS = $(am_test_fakesmtp_OBJECTS) test_fakesmtp_DEPENDENCIES = $(am__DEPENDENCIES_1) am_test_getcanon_OBJECTS = test/getcanon.$(OBJEXT) test_getcanon_OBJECTS = $(am_test_getcanon_OBJECTS) test_getcanon_DEPENDENCIES = $(am__DEPENDENCIES_1) am_test_getcwidth_OBJECTS = test/getcwidth.$(OBJEXT) test_getcwidth_OBJECTS = $(am_test_getcwidth_OBJECTS) test_getcwidth_DEPENDENCIES = $(am__DEPENDENCIES_1) am_test_getfullname_OBJECTS = test/getfullname.$(OBJEXT) test_getfullname_OBJECTS = $(am_test_getfullname_OBJECTS) test_getfullname_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) am_test_runpty_OBJECTS = test/runpty.$(OBJEXT) test_runpty_OBJECTS = $(am_test_runpty_OBJECTS) test_runpty_DEPENDENCIES = $(am__DEPENDENCIES_1) am_uip_ali_OBJECTS = uip/ali.$(OBJEXT) uip/aliasbr.$(OBJEXT) uip_ali_OBJECTS = $(am_uip_ali_OBJECTS) uip_ali_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) am_uip_anno_OBJECTS = uip/anno.$(OBJEXT) uip/annosbr.$(OBJEXT) uip_anno_OBJECTS = $(am_uip_anno_OBJECTS) uip_anno_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) am_uip_ap_OBJECTS = uip/ap.$(OBJEXT) uip_ap_OBJECTS = $(am_uip_ap_OBJECTS) uip_ap_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_uip_burst_OBJECTS = uip/burst.$(OBJEXT) uip/mhparse.$(OBJEXT) \ uip/mhmisc.$(OBJEXT) uip/mhfree.$(OBJEXT) \ uip/mhcachesbr.$(OBJEXT) uip_burst_OBJECTS = $(am_uip_burst_OBJECTS) uip_burst_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_uip_comp_OBJECTS = uip/comp.$(OBJEXT) uip/whatnowproc.$(OBJEXT) \ uip/whatnowsbr.$(OBJEXT) uip/sendsbr.$(OBJEXT) \ uip/annosbr.$(OBJEXT) uip/distsbr.$(OBJEXT) uip_comp_OBJECTS = $(am_uip_comp_OBJECTS) uip_comp_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_uip_dist_OBJECTS = uip/dist.$(OBJEXT) uip/whatnowproc.$(OBJEXT) \ uip/whatnowsbr.$(OBJEXT) uip/sendsbr.$(OBJEXT) \ uip/annosbr.$(OBJEXT) uip/distsbr.$(OBJEXT) \ uip/forwsbr.$(OBJEXT) uip_dist_OBJECTS = $(am_uip_dist_OBJECTS) uip_dist_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_uip_dp_OBJECTS = uip/dp.$(OBJEXT) uip_dp_OBJECTS = $(am_uip_dp_OBJECTS) uip_dp_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_uip_flist_OBJECTS = uip/flist.$(OBJEXT) uip_flist_OBJECTS = $(am_uip_flist_OBJECTS) uip_flist_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) am_uip_fmtdump_OBJECTS = uip/fmtdump.$(OBJEXT) uip_fmtdump_OBJECTS = $(am_uip_fmtdump_OBJECTS) uip_fmtdump_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_uip_fmttest_OBJECTS = uip/fmttest.$(OBJEXT) uip_fmttest_OBJECTS = $(am_uip_fmttest_OBJECTS) uip_fmttest_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_uip_folder_OBJECTS = uip/folder.$(OBJEXT) uip_folder_OBJECTS = $(am_uip_folder_OBJECTS) uip_folder_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) am_uip_forw_OBJECTS = uip/forw.$(OBJEXT) uip/whatnowproc.$(OBJEXT) \ uip/whatnowsbr.$(OBJEXT) uip/sendsbr.$(OBJEXT) \ uip/annosbr.$(OBJEXT) uip/distsbr.$(OBJEXT) \ uip/forwsbr.$(OBJEXT) uip_forw_OBJECTS = $(am_uip_forw_OBJECTS) uip_forw_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_uip_inc_OBJECTS = uip/inc.$(OBJEXT) uip/scansbr.$(OBJEXT) \ uip/dropsbr.$(OBJEXT) uip/popsbr.$(OBJEXT) uip_inc_OBJECTS = $(am_uip_inc_OBJECTS) uip_inc_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_uip_install_mh_OBJECTS = uip/install-mh.$(OBJEXT) uip_install_mh_OBJECTS = $(am_uip_install_mh_OBJECTS) uip_install_mh_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) am_uip_mark_OBJECTS = uip/mark.$(OBJEXT) uip_mark_OBJECTS = $(am_uip_mark_OBJECTS) uip_mark_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) am_uip_mhbuild_OBJECTS = uip/mhbuild.$(OBJEXT) \ uip/mhbuildsbr.$(OBJEXT) uip/mhcachesbr.$(OBJEXT) \ uip/mhlistsbr.$(OBJEXT) uip/mhoutsbr.$(OBJEXT) \ uip/mhmisc.$(OBJEXT) uip/mhfree.$(OBJEXT) \ uip/mhparse.$(OBJEXT) uip/mhstoresbr.$(OBJEXT) \ uip/mhshowsbr.$(OBJEXT) uip_mhbuild_OBJECTS = $(am_uip_mhbuild_OBJECTS) uip_mhbuild_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_uip_mhfixmsg_OBJECTS = uip/mhfixmsg.$(OBJEXT) uip/mhparse.$(OBJEXT) \ uip/mhcachesbr.$(OBJEXT) uip/mhoutsbr.$(OBJEXT) \ uip/mhmisc.$(OBJEXT) uip/mhfree.$(OBJEXT) \ uip/mhshowsbr.$(OBJEXT) uip/mhlistsbr.$(OBJEXT) uip_mhfixmsg_OBJECTS = $(am_uip_mhfixmsg_OBJECTS) uip_mhfixmsg_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_uip_mhical_OBJECTS = uip/mhical.$(OBJEXT) uip_mhical_OBJECTS = $(am_uip_mhical_OBJECTS) uip_mhical_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_uip_mhl_OBJECTS = uip/mhl.$(OBJEXT) uip/mhlsbr.$(OBJEXT) uip_mhl_OBJECTS = $(am_uip_mhl_OBJECTS) uip_mhl_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_uip_mhlist_OBJECTS = uip/mhlist.$(OBJEXT) uip/mhparse.$(OBJEXT) \ uip/mhcachesbr.$(OBJEXT) uip/mhlistsbr.$(OBJEXT) \ uip/mhmisc.$(OBJEXT) uip/mhfree.$(OBJEXT) uip_mhlist_OBJECTS = $(am_uip_mhlist_OBJECTS) uip_mhlist_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_uip_mhlogin_OBJECTS = uip/mhlogin.$(OBJEXT) uip_mhlogin_OBJECTS = $(am_uip_mhlogin_OBJECTS) uip_mhlogin_DEPENDENCIES = mts/libmts.a $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_uip_mhn_OBJECTS = uip/mhn.$(OBJEXT) uip/mhparse.$(OBJEXT) \ uip/mhcachesbr.$(OBJEXT) uip/mhshowsbr.$(OBJEXT) \ uip/mhlistsbr.$(OBJEXT) uip/mhstoresbr.$(OBJEXT) \ uip/mhmisc.$(OBJEXT) uip/mhfree.$(OBJEXT) uip_mhn_OBJECTS = $(am_uip_mhn_OBJECTS) uip_mhn_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_uip_mhparam_OBJECTS = uip/mhparam.$(OBJEXT) uip_mhparam_OBJECTS = $(am_uip_mhparam_OBJECTS) uip_mhparam_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) am_uip_mhpath_OBJECTS = uip/mhpath.$(OBJEXT) uip_mhpath_OBJECTS = $(am_uip_mhpath_OBJECTS) uip_mhpath_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) am_uip_mhshow_OBJECTS = uip/mhshow.$(OBJEXT) uip/mhparse.$(OBJEXT) \ uip/mhcachesbr.$(OBJEXT) uip/mhshowsbr.$(OBJEXT) \ uip/mhlistsbr.$(OBJEXT) uip/mhmisc.$(OBJEXT) \ uip/mhfree.$(OBJEXT) uip_mhshow_OBJECTS = $(am_uip_mhshow_OBJECTS) uip_mhshow_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_uip_mhstore_OBJECTS = uip/mhstore.$(OBJEXT) uip/mhparse.$(OBJEXT) \ uip/mhcachesbr.$(OBJEXT) uip/mhshowsbr.$(OBJEXT) \ uip/mhlistsbr.$(OBJEXT) uip/mhstoresbr.$(OBJEXT) \ uip/mhmisc.$(OBJEXT) uip/mhfree.$(OBJEXT) uip_mhstore_OBJECTS = $(am_uip_mhstore_OBJECTS) uip_mhstore_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_uip_mkstemp_OBJECTS = uip/mkstemp.$(OBJEXT) uip_mkstemp_OBJECTS = $(am_uip_mkstemp_OBJECTS) uip_mkstemp_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) am_uip_msgchk_OBJECTS = uip/msgchk.$(OBJEXT) uip/popsbr.$(OBJEXT) uip_msgchk_OBJECTS = $(am_uip_msgchk_OBJECTS) uip_msgchk_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_uip_new_OBJECTS = uip/new.$(OBJEXT) uip_new_OBJECTS = $(am_uip_new_OBJECTS) uip_new_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) am_uip_packf_OBJECTS = uip/packf.$(OBJEXT) uip/dropsbr.$(OBJEXT) uip_packf_OBJECTS = $(am_uip_packf_OBJECTS) uip_packf_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) am_uip_pick_OBJECTS = uip/pick.$(OBJEXT) uip/picksbr.$(OBJEXT) uip_pick_OBJECTS = $(am_uip_pick_OBJECTS) uip_pick_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_uip_post_OBJECTS = uip/post.$(OBJEXT) uip/aliasbr.$(OBJEXT) uip_post_OBJECTS = $(am_uip_post_OBJECTS) uip_post_DEPENDENCIES = mts/libmts.a $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_uip_prompter_OBJECTS = uip/prompter.$(OBJEXT) uip_prompter_OBJECTS = $(am_uip_prompter_OBJECTS) uip_prompter_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) am_uip_rcvdist_OBJECTS = uip/rcvdist.$(OBJEXT) uip/distsbr.$(OBJEXT) uip_rcvdist_OBJECTS = $(am_uip_rcvdist_OBJECTS) uip_rcvdist_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_uip_rcvpack_OBJECTS = uip/rcvpack.$(OBJEXT) uip/dropsbr.$(OBJEXT) uip_rcvpack_OBJECTS = $(am_uip_rcvpack_OBJECTS) uip_rcvpack_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) am_uip_rcvstore_OBJECTS = uip/rcvstore.$(OBJEXT) uip_rcvstore_OBJECTS = $(am_uip_rcvstore_OBJECTS) uip_rcvstore_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) am_uip_rcvtty_OBJECTS = uip/rcvtty.$(OBJEXT) uip/scansbr.$(OBJEXT) uip_rcvtty_OBJECTS = $(am_uip_rcvtty_OBJECTS) uip_rcvtty_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_uip_refile_OBJECTS = uip/refile.$(OBJEXT) uip_refile_OBJECTS = $(am_uip_refile_OBJECTS) uip_refile_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) am_uip_repl_OBJECTS = uip/repl.$(OBJEXT) uip/replsbr.$(OBJEXT) \ uip/whatnowproc.$(OBJEXT) uip/whatnowsbr.$(OBJEXT) \ uip/sendsbr.$(OBJEXT) uip/annosbr.$(OBJEXT) \ uip/distsbr.$(OBJEXT) uip_repl_OBJECTS = $(am_uip_repl_OBJECTS) uip_repl_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_uip_rmf_OBJECTS = uip/rmf.$(OBJEXT) uip_rmf_OBJECTS = $(am_uip_rmf_OBJECTS) uip_rmf_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) am_uip_rmm_OBJECTS = uip/rmm.$(OBJEXT) uip_rmm_OBJECTS = $(am_uip_rmm_OBJECTS) uip_rmm_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) am_uip_scan_OBJECTS = uip/scan.$(OBJEXT) uip/scansbr.$(OBJEXT) uip_scan_OBJECTS = $(am_uip_scan_OBJECTS) uip_scan_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_uip_send_OBJECTS = uip/send.$(OBJEXT) uip/sendsbr.$(OBJEXT) \ uip/annosbr.$(OBJEXT) uip/distsbr.$(OBJEXT) uip_send_OBJECTS = $(am_uip_send_OBJECTS) uip_send_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_uip_show_OBJECTS = uip/show.$(OBJEXT) uip/mhlsbr.$(OBJEXT) uip_show_OBJECTS = $(am_uip_show_OBJECTS) uip_show_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_uip_slocal_OBJECTS = uip/slocal.$(OBJEXT) uip/aliasbr.$(OBJEXT) \ uip/dropsbr.$(OBJEXT) uip_slocal_OBJECTS = $(am_uip_slocal_OBJECTS) uip_slocal_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_uip_sortm_OBJECTS = uip/sortm.$(OBJEXT) uip_sortm_OBJECTS = $(am_uip_sortm_OBJECTS) uip_sortm_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) am_uip_viamail_OBJECTS = uip/viamail.$(OBJEXT) uip/mhmisc.$(OBJEXT) \ uip/sendsbr.$(OBJEXT) uip/annosbr.$(OBJEXT) \ uip/distsbr.$(OBJEXT) uip_viamail_OBJECTS = $(am_uip_viamail_OBJECTS) uip_viamail_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_uip_whatnow_OBJECTS = uip/whatnow.$(OBJEXT) \ uip/whatnowsbr.$(OBJEXT) uip/sendsbr.$(OBJEXT) \ uip/annosbr.$(OBJEXT) uip/distsbr.$(OBJEXT) uip_whatnow_OBJECTS = $(am_uip_whatnow_OBJECTS) uip_whatnow_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_uip_whom_OBJECTS = uip/whom.$(OBJEXT) uip/distsbr.$(OBJEXT) uip_whom_OBJECTS = $(am_uip_whom_OBJECTS) uip_whom_DEPENDENCIES = $(LDADD) $(am__DEPENDENCIES_1) am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } SCRIPTS = $(bin_SCRIPTS) $(dist_docs_contrib_SCRIPTS) \ $(dist_nmhetc_SCRIPTS) $(nmhlibexec_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = LEXCOMPILE = $(LEX) $(AM_LFLAGS) $(LFLAGS) AM_V_LEX = $(am__v_LEX_@AM_V@) am__v_LEX_ = $(am__v_LEX_@AM_DEFAULT_V@) am__v_LEX_0 = @echo " LEX " $@; am__v_LEX_1 = YLWRAP = $(top_srcdir)/ylwrap am__yacc_c2h = sed -e s/cc$$/hh/ -e s/cpp$$/hpp/ -e s/cxx$$/hxx/ \ -e s/c++$$/h++/ -e s/c$$/h/ YACCCOMPILE = $(YACC) $(AM_YFLAGS) $(YFLAGS) AM_V_YACC = $(am__v_YACC_@AM_V@) am__v_YACC_ = $(am__v_YACC_@AM_DEFAULT_V@) am__v_YACC_0 = @echo " YACC " $@; am__v_YACC_1 = SOURCES = $(mts_libmts_a_SOURCES) $(sbr_libmh_a_SOURCES) \ $(test_fakehttp_SOURCES) $(test_fakepop_SOURCES) \ $(test_fakesmtp_SOURCES) $(test_getcanon_SOURCES) \ $(test_getcwidth_SOURCES) $(test_getfullname_SOURCES) \ $(test_runpty_SOURCES) $(uip_ali_SOURCES) $(uip_anno_SOURCES) \ $(uip_ap_SOURCES) $(uip_burst_SOURCES) $(uip_comp_SOURCES) \ $(uip_dist_SOURCES) $(uip_dp_SOURCES) $(uip_flist_SOURCES) \ $(uip_fmtdump_SOURCES) $(uip_fmttest_SOURCES) \ $(uip_folder_SOURCES) $(uip_forw_SOURCES) $(uip_inc_SOURCES) \ $(uip_install_mh_SOURCES) $(uip_mark_SOURCES) \ $(uip_mhbuild_SOURCES) $(uip_mhfixmsg_SOURCES) \ $(uip_mhical_SOURCES) $(uip_mhl_SOURCES) $(uip_mhlist_SOURCES) \ $(uip_mhlogin_SOURCES) $(uip_mhn_SOURCES) \ $(uip_mhparam_SOURCES) $(uip_mhpath_SOURCES) \ $(uip_mhshow_SOURCES) $(uip_mhstore_SOURCES) \ $(uip_mkstemp_SOURCES) $(uip_msgchk_SOURCES) \ $(uip_new_SOURCES) $(uip_packf_SOURCES) $(uip_pick_SOURCES) \ $(uip_post_SOURCES) $(uip_prompter_SOURCES) \ $(uip_rcvdist_SOURCES) $(uip_rcvpack_SOURCES) \ $(uip_rcvstore_SOURCES) $(uip_rcvtty_SOURCES) \ $(uip_refile_SOURCES) $(uip_repl_SOURCES) $(uip_rmf_SOURCES) \ $(uip_rmm_SOURCES) $(uip_scan_SOURCES) $(uip_send_SOURCES) \ $(uip_show_SOURCES) $(uip_slocal_SOURCES) $(uip_sortm_SOURCES) \ $(uip_viamail_SOURCES) $(uip_whatnow_SOURCES) \ $(uip_whom_SOURCES) DIST_SOURCES = $(mts_libmts_a_SOURCES) $(sbr_libmh_a_SOURCES) \ $(test_fakehttp_SOURCES) $(test_fakepop_SOURCES) \ $(test_fakesmtp_SOURCES) $(test_getcanon_SOURCES) \ $(test_getcwidth_SOURCES) $(test_getfullname_SOURCES) \ $(test_runpty_SOURCES) $(uip_ali_SOURCES) $(uip_anno_SOURCES) \ $(uip_ap_SOURCES) $(uip_burst_SOURCES) $(uip_comp_SOURCES) \ $(uip_dist_SOURCES) $(uip_dp_SOURCES) $(uip_flist_SOURCES) \ $(uip_fmtdump_SOURCES) $(uip_fmttest_SOURCES) \ $(uip_folder_SOURCES) $(uip_forw_SOURCES) $(uip_inc_SOURCES) \ $(uip_install_mh_SOURCES) $(uip_mark_SOURCES) \ $(uip_mhbuild_SOURCES) $(uip_mhfixmsg_SOURCES) \ $(uip_mhical_SOURCES) $(uip_mhl_SOURCES) $(uip_mhlist_SOURCES) \ $(uip_mhlogin_SOURCES) $(uip_mhn_SOURCES) \ $(uip_mhparam_SOURCES) $(uip_mhpath_SOURCES) \ $(uip_mhshow_SOURCES) $(uip_mhstore_SOURCES) \ $(uip_mkstemp_SOURCES) $(uip_msgchk_SOURCES) \ $(uip_new_SOURCES) $(uip_packf_SOURCES) $(uip_pick_SOURCES) \ $(uip_post_SOURCES) $(uip_prompter_SOURCES) \ $(uip_rcvdist_SOURCES) $(uip_rcvpack_SOURCES) \ $(uip_rcvstore_SOURCES) $(uip_rcvtty_SOURCES) \ $(uip_refile_SOURCES) $(uip_repl_SOURCES) $(uip_rmf_SOURCES) \ $(uip_rmm_SOURCES) $(uip_scan_SOURCES) $(uip_send_SOURCES) \ $(uip_show_SOURCES) $(uip_slocal_SOURCES) $(uip_sortm_SOURCES) \ $(uip_viamail_SOURCES) $(uip_whatnow_SOURCES) \ $(uip_whom_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac man1dir = $(mandir)/man1 man5dir = $(mandir)/man5 man7dir = $(mandir)/man7 man8dir = $(mandir)/man8 NROFF = nroff MANS = $(man_MANS) DATA = $(dist_doc_DATA) $(dist_docs_contrib_DATA) $(dist_nmhetc_DATA) \ $(nmhetc_DATA) HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ $(LISP)config.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags CSCOPE = cscope AM_RECURSIVE_TARGETS = cscope am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ $(top_srcdir)/sbr/getline.c $(top_srcdir)/test/common.sh.in \ $(top_srcdir)/uip/spost.in ChangeLog INSTALL NEWS README \ ar-lib compile config.guess config.sub depcomp install-sh \ missing sbr/dtimep.c sbr/icalendar.c sbr/icalparse.c \ sbr/icalparse.h ylwrap DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_CFLAGS = @AM_CFLAGS@ AM_CPPFLAGS = @AM_CPPFLAGS@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AM_LDFLAGS = @AM_LDFLAGS@ AM_LFLAGS = @AM_LFLAGS@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CURLLIB = @CURLLIB@ CURL_USER_AGENT = @CURL_USER_AGENT@ CYGPATH_W = @CYGPATH_W@ CYRUS_SASL = @CYRUS_SASL@ DATE = @DATE@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GREP = @GREP@ ICONVLIB = @ICONVLIB@ ICONV_ENABLED = @ICONV_ENABLED@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN = @LN@ LTLIBOBJS = @LTLIBOBJS@ MAIL_SPOOL_GRP = @MAIL_SPOOL_GRP@ MAKEINFO = @MAKEINFO@ MD5FMT = @MD5FMT@ MD5SUM = @MD5SUM@ MKDIR_P = @MKDIR_P@ MTS = @MTS@ MULTIBYTE_ENABLED = @MULTIBYTE_ENABLED@ NDBM_LIBS = @NDBM_LIBS@ NMHETCDIRINST = @NMHETCDIRINST@ OAUTH_SUPPORT = @OAUTH_SUPPORT@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ POSTLINK = @POSTLINK@ RANLIB = @RANLIB@ READLINELIB = @READLINELIB@ SASLLIB = @SASLLIB@ SED = @SED@ SETGID_MAIL = @SETGID_MAIL@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TERMLIB = @TERMLIB@ TLSLIB = @TLSLIB@ TLS_SUPPORT = @TLS_SUPPORT@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_prefix_program = @ac_prefix_program@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ curl_config = @curl_config@ cutpath = @cutpath@ datadir = @datadir@ datarootdir = @datarootdir@ default_locking = @default_locking@ docdir = @docdir@ dotlockfilepath = @dotlockfilepath@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lspath = @lspath@ mailspool = @mailspool@ mandir = @mandir@ mkdir_p = @mkdir_p@ nmhetcdirinst = @nmhetcdirinst@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ rpmdir = @rpmdir@ sbindir = @sbindir@ sendmailpath = @sendmailpath@ sharedstatedir = @sharedstatedir@ smtpserver = @smtpserver@ srcdir = @srcdir@ supported_locks = @supported_locks@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I m4 AM_YFLAGS = -d LDADD = sbr/libmh.a MHNSEARCHPATH = "$(PATH)" MHNSEARCHPROG = $(srcdir)/etc/mhn.find.sh nmhetcdir = @sysconfdir@/nmh nmhlibexecdir = @libexecdir@/nmh TESTS_ENVIRONMENT = MH_OBJ_DIR="@abs_builddir@" \ MH_VERSION="$(VERSION)" \ OAUTH_SUPPORT='@OAUTH_SUPPORT@' \ CURL_USER_AGENT='@CURL_USER_AGENT@' \ MH_TEST_DIR=`cd "@abs_builddir@" && pwd -P`/test/testdir \ nmhlibexecdir="$(nmhlibexecdir)" bindir="$(bindir)" \ mandir="$(mandir)" nmhetcdir="$(nmhetcdir)" \ nmhetcdirinst="@nmhetcdirinst@$(nmhetcdir)" \ supported_locks="$(supported_locks)" \ default_locking="${default_locking}" \ MULTIBYTE_ENABLED=$(MULTIBYTE_ENABLED) \ ICONV_ENABLED=$(ICONV_ENABLED) \ $(TESTS_SHELL) ## Keep at end of TESTS_ENVIRONMENT. TESTS = \ test/ali/test-ali \ test/anno/test-anno \ test/bad-input/test-header \ test/burst/test-burst \ test/burst/test-burst-mime \ test/comp/test-comp-format \ test/dist/test-dist \ test/folder/test-coverage \ test/folder/test-create \ test/folder/test-nocreate \ test/folder/test-packf \ test/folder/test-recurse \ test/folder/test-sortm \ test/folder/test-total \ test/format/test-ap \ test/format/test-curses \ test/format/test-dp \ test/format/test-fmtdump \ test/format/test-fmttest \ test/format/test-functions \ test/format/test-localmbox \ test/format/test-myhost \ test/format/test-mymbox \ test/format/test-myname \ test/format/test-nullstr \ test/format/test-rightjustify \ test/format/test-unquote \ test/forw/test-forw-coverage \ 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/inc/test-pop \ test/install-mh/test-install-mh \ test/install-mh/test-version-check \ test/locking/test-datalocking \ test/locking/test-spoollocking \ test/manpages/test-manpages \ test/mhbuild/test-attach \ test/mhbuild/test-cte \ test/mhbuild/test-ext-params \ test/mhbuild/test-forw \ test/mhbuild/test-header-encode \ test/mhbuild/test-mhbuild \ test/mhbuild/test-utf8-body \ test/mhfixmsg/test-mhfixmsg \ test/mhical/test-mhical \ test/mhl/test-mhl-flags \ test/mhl/test-rfc6532 \ test/mhlist/test-ext-params \ test/mhlist/test-mhlist \ test/mhmail/test-mhmail \ test/mhparam/test-mhparam \ test/mhpath/test-mhpath \ test/mhshow/test-binary \ test/mhshow/test-charset \ test/mhshow/test-cte-binary \ test/mhshow/test-msg-buffer-boundaries \ test/mhshow/test-qp \ test/mhshow/test-subpart \ test/mhshow/test-textcharset \ test/mhstore/test-mhstore \ test/mkstemp/test-mkstemp \ test/new/test-basic \ test/oauth/test-inc \ test/oauth/test-mhlogin \ test/oauth/test-mhparam \ test/oauth/test-send \ test/oauth/test-sendfrom \ test/oauth/test-share \ test/pick/test-pick \ test/pick/test-stderr \ test/post/test-messageid \ test/post/test-mts \ test/post/test-post-aliases \ test/post/test-post-basic \ test/post/test-post-bcc \ test/post/test-post-dcc \ test/post/test-post-envelope \ test/post/test-post-fcc \ test/post/test-post-group \ test/post/test-post-multifrom \ test/post/test-post-multiple \ test/post/test-rfc6531 \ test/post/test-sendfiles \ test/prompter/test-prompter \ test/rcv/test-rcvdist \ test/rcv/test-rcvpack \ test/rcv/test-rcvstore \ test/rcv/test-rcvtty \ test/refile/test-refile \ test/repl/test-convert \ test/repl/test-if-str \ test/repl/test-multicomp \ test/repl/test-repl \ test/repl/test-trailing-newline \ test/scan/test-header-parsing \ test/scan/test-scan \ test/scan/test-scan-multibyte \ test/send/test-sendfrom \ test/sequences/test-flist \ test/sequences/test-mark \ test/sequences/test-out-of-range \ test/show/test-show \ 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 AM_DISTCHECK_CONFIGURE_FLAGS = DISABLE_SETGID_MAIL=1 \ NMHETCDIRINST='$${abs_builddir}/test/testdir/inst' CLEANFILES = \ $(man_MANS) \ *.plist \ config/version.c \ etc/bash_completion_nmh \ etc/mhn.defaults \ etc/mts.conf \ man/man.sed \ man/mh-chart.man MAINTAINERCLEANFILES = \ *.plist \ atags \ cscope.files \ cscope.in.out \ cscope.out \ cscope.po.out \ # SUPERCLEANFILES = \ ChangeLog \ Makefile.in \ aclocal.m4 \ compile \ config.guess \ config.h.in \ config.h.in~ \ config.sub \ configure \ depcomp \ install-sh \ missing \ nmh-*.tar.gz \ nmh-*.tar.gz.sig \ test-driver \ ylwrap \ # bin_SCRIPTS = \ etc/sendfiles \ uip/mhmail \ # nmhlibexec_SCRIPTS = uip/spost noinst_LIBRARIES = \ mts/libmts.a \ sbr/libmh.a \ # noinst_HEADERS = \ h/addrsbr.h \ h/aliasbr.h \ h/crawl_folders.h \ h/dropsbr.h \ h/fmt_compile.h \ h/fmt_scan.h \ h/icalendar.h \ h/md5.h \ h/mf.h \ h/mh.h \ h/mhcachesbr.h \ h/mhparse.h \ h/mime.h \ h/mts.h \ h/netsec.h \ h/nmh.h \ h/oauth.h \ h/picksbr.h \ h/popsbr.h \ h/prototypes.h \ h/rcvmail.h \ h/scansbr.h \ h/signals.h \ h/tws.h \ h/utils.h \ mts/smtp/smtp.h \ sbr/ctype-checked.h \ sbr/lock_file.h \ sbr/m_maildir.h \ sbr/m_mktemp.h \ sbr/m_popen.h \ sbr/m_rand.h \ sbr/makedir.h \ sbr/message_id.h \ sbr/mime_type.h \ sbr/unquote.h \ thirdparty/jsmn/jsmn.h \ uip/mhfree.h \ uip/mhoutsbr.h \ uip/mhshowsbr.h \ # dist_nmhetc_SCRIPTS = etc/rmmproc.messageid dist_nmhetc_DATA = \ etc/MailAliases \ etc/components \ etc/digestcomps \ etc/distcomps \ etc/forwcomps \ etc/mhical.12hour \ etc/mhical.24hour \ etc/mhl.body \ etc/mhl.digest \ etc/mhl.format \ etc/mhl.forward \ etc/mhl.headers \ etc/mhl.reply \ etc/mhl.replywithoutbody \ etc/mhshow.marker \ etc/rcvdistcomps \ etc/rcvdistcomps.outbox \ etc/replcomps \ etc/replgroupcomps \ etc/scan.MMDDYY \ etc/scan.YYYYMMDD \ etc/scan.curses \ etc/scan.default \ etc/scan.highlighted \ etc/scan.mailx \ etc/scan.nomime \ etc/scan.size \ etc/scan.time \ etc/scan.timely \ etc/scan.unseen \ # nmhetc_DATA = \ etc/bash_completion_nmh \ etc/mhn.defaults \ etc/mts.conf \ # dist_doc_DATA = \ COPYRIGHT \ INSTALL \ NEWS \ README \ VERSION \ docs/COMPLETION-TCSH \ docs/COMPLETION-ZSH \ docs/DIFFERENCES \ docs/FAQ \ docs/MAIL.FILTERING \ docs/MAILING-LISTS \ docs/README-ATTACHMENTS \ docs/README-HOOKS \ docs/README-components \ docs/README.SASL \ docs/README.about \ docs/README.developers \ docs/README.manpages \ docs/TODO \ # docs_contribdir = $(docdir)/contrib dist_docs_contrib_SCRIPTS = \ docs/contrib/localpostproc \ docs/contrib/ml \ docs/contrib/replyfilter \ docs/contrib/vpick \ # dist_docs_contrib_DATA = docs/contrib/replaliases man_MANS = \ man/MH.7 \ man/ali.1 \ man/anno.1 \ man/ap.8 \ man/burst.1 \ man/comp.1 \ man/dist.1 \ man/dp.8 \ man/flist.1 \ man/flists.1 \ man/fmtdump.8 \ man/fmttest.1 \ man/fnext.1 \ man/folder.1 \ man/folders.1 \ man/forw.1 \ man/fprev.1 \ man/inc.1 \ man/install-mh.1 \ man/mark.1 \ man/mh-alias.5 \ man/mh-chart.7 \ man/mh-draft.5 \ man/mh-folders.5 \ man/mh-format.5 \ man/mh-mail.5 \ man/mh-mime.7 \ man/mh-mkstemp.1 \ man/mh-profile.5 \ man/mh-sequence.5 \ man/mh-tailor.5 \ man/mh_profile.5 \ man/mhbuild.1 \ man/mhfixmsg.1 \ man/mhical.1 \ man/mhl.1 \ man/mhlist.1 \ man/mhlogin.1 \ man/mhmail.1 \ man/mhn.1 \ man/mhparam.1 \ man/mhpath.1 \ man/mhshow.1 \ man/mhstore.1 \ man/msgchk.1 \ man/mts.conf.5 \ man/new.1 \ man/next.1 \ man/nmh.7 \ man/packf.1 \ man/pick.1 \ man/post.8 \ man/prev.1 \ man/prompter.1 \ man/rcvdist.1 \ man/rcvpack.1 \ man/rcvstore.1 \ man/rcvtty.1 \ man/refile.1 \ man/repl.1 \ man/rmf.1 \ man/rmm.1 \ man/scan.1 \ man/send.1 \ man/sendfiles.1 \ man/show.1 \ man/slocal.1 \ man/sortm.1 \ man/unseen.1 \ man/whatnow.1 \ man/whom.1 \ # man_SRCS = \ man/MH.man \ man/ali.man \ man/anno.man \ man/ap.man \ man/burst.man \ man/comp.man \ man/dist.man \ man/dp.man \ man/flist.man \ man/flists.man \ man/fmtdump.man \ man/fmttest.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-folders.man \ man/mh-format.man \ man/mh-mail.man \ man/mh-mime.man \ man/mh-mkstemp.man \ man/mh-profile.man \ man/mh-sequence.man \ man/mh-tailor.man \ man/mh_profile.man \ man/mhbuild.man \ man/mhfixmsg.man \ man/mhical.man \ man/mhl.man \ man/mhlist.man \ man/mhlogin.man \ man/mhmail.man \ man/mhn.man \ man/mhparam.man \ man/mhpath.man \ man/mhshow.man \ man/mhstore.man \ man/msgchk.man \ man/mts.conf.man \ man/new.man \ man/next.man \ man/nmh.man \ man/packf.man \ man/pick.man \ man/post.man \ man/prev.man \ man/prompter.man \ man/rcvdist.man \ man/rcvpack.man \ man/rcvstore.man \ man/rcvtty.man \ man/refile.man \ man/repl.man \ 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 \ # EXTRA_DIST = \ $(MHNSEARCHPROG) \ $(TESTS) \ $(man_SRCS) \ DATE \ MACHINES \ SPECS/nmh.cygport \ SPECS/nmh.spec \ autogen.sh \ build_nmh \ config/version.sh \ docs/ChangeLog_MH-3_to_MH-6.6 \ docs/ChangeLog_MH-6.7.0_to_MH-6.8.4.html \ etc/bash_completion_nmh-gen \ etc/mhn.defaults.sh \ etc/mts.conf.in \ etc/sendfiles \ sbr/icalparse.h \ test/README \ test/fakesendmail \ test/inc/deb359167.mbox \ test/inc/filler.txt \ test/inc/fromline.txt \ test/inc/md5sums \ test/inc/msgheader.txt \ test/mhbuild/nulls \ test/mhbuild/somebinary \ test/mhbuild/textplain \ test/mhbuild/tiny.jpg \ test/mhmail/attachment.txt \ test/oauth/common.sh \ test/post/test-post-common.sh \ test/send/README \ test/valgrind.supp \ uip/mhmail \ # uip_ali_SOURCES = uip/ali.c uip/aliasbr.c uip_ali_LDADD = $(LDADD) $(POSTLINK) uip_anno_SOURCES = uip/anno.c uip/annosbr.c uip_anno_LDADD = $(LDADD) $(POSTLINK) uip_burst_SOURCES = uip/burst.c uip/mhparse.c uip/mhmisc.c uip/mhfree.c \ uip/mhcachesbr.c uip_burst_LDADD = $(LDADD) $(ICONVLIB) $(POSTLINK) uip_comp_SOURCES = uip/comp.c uip/whatnowproc.c uip/whatnowsbr.c uip/sendsbr.c \ uip/annosbr.c uip/distsbr.c uip_comp_LDADD = $(LDADD) $(READLINELIB) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_dist_SOURCES = uip/dist.c uip/whatnowproc.c uip/whatnowsbr.c uip/sendsbr.c \ uip/annosbr.c uip/distsbr.c uip/forwsbr.c uip_dist_LDADD = $(LDADD) $(READLINELIB) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_flist_SOURCES = uip/flist.c uip_flist_LDADD = $(LDADD) $(POSTLINK) uip_folder_SOURCES = uip/folder.c uip_folder_LDADD = $(LDADD) $(POSTLINK) uip_forw_SOURCES = uip/forw.c uip/whatnowproc.c uip/whatnowsbr.c uip/sendsbr.c \ uip/annosbr.c uip/distsbr.c uip/forwsbr.c uip_forw_LDADD = $(LDADD) $(READLINELIB) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_inc_SOURCES = uip/inc.c uip/scansbr.c uip/dropsbr.c uip/popsbr.c uip_inc_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(SASLLIB) $(CURLLIB) \ $(TLSLIB) $(POSTLINK) uip_install_mh_SOURCES = uip/install-mh.c uip_install_mh_LDADD = $(LDADD) $(POSTLINK) uip_mark_SOURCES = uip/mark.c uip_mark_LDADD = $(LDADD) $(POSTLINK) uip_mhbuild_SOURCES = uip/mhbuild.c uip/mhbuildsbr.c uip/mhcachesbr.c \ uip/mhlistsbr.c uip/mhoutsbr.c uip/mhmisc.c \ uip/mhfree.c uip/mhparse.c \ uip/mhstoresbr.c uip/mhshowsbr.c uip_mhbuild_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_mhfixmsg_SOURCES = uip/mhfixmsg.c uip/mhparse.c uip/mhcachesbr.c \ uip/mhoutsbr.c uip/mhmisc.c uip/mhfree.c \ uip/mhshowsbr.c uip/mhlistsbr.c uip_mhfixmsg_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_mhical_SOURCES = uip/mhical.c uip_mhical_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_mhlist_SOURCES = uip/mhlist.c uip/mhparse.c uip/mhcachesbr.c \ uip/mhlistsbr.c uip/mhmisc.c uip/mhfree.c uip_mhlist_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_mhn_SOURCES = uip/mhn.c uip/mhparse.c uip/mhcachesbr.c uip/mhshowsbr.c \ uip/mhlistsbr.c uip/mhstoresbr.c uip/mhmisc.c uip/mhfree.c uip_mhn_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_mhparam_SOURCES = uip/mhparam.c uip_mhparam_LDADD = $(LDADD) $(POSTLINK) uip_mhpath_SOURCES = uip/mhpath.c uip_mhpath_LDADD = $(LDADD) $(POSTLINK) uip_mhshow_SOURCES = uip/mhshow.c uip/mhparse.c uip/mhcachesbr.c \ uip/mhshowsbr.c uip/mhlistsbr.c uip/mhmisc.c \ uip/mhfree.c uip_mhshow_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_mhstore_SOURCES = uip/mhstore.c uip/mhparse.c uip/mhcachesbr.c \ uip/mhshowsbr.c uip/mhlistsbr.c uip/mhstoresbr.c \ uip/mhmisc.c uip/mhfree.c uip_mhstore_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_msgchk_SOURCES = uip/msgchk.c uip/popsbr.c uip_msgchk_LDADD = $(LDADD) $(SASLLIB) $(CURLLIB) $(TLSLIB) $(POSTLINK) uip_new_SOURCES = uip/new.c uip_new_LDADD = $(LDADD) $(POSTLINK) uip_packf_SOURCES = uip/packf.c uip/dropsbr.c uip_packf_LDADD = $(LDADD) $(POSTLINK) uip_pick_SOURCES = uip/pick.c uip/picksbr.c uip_pick_LDADD = $(LDADD) $(ICONVLIB) $(POSTLINK) uip_prompter_SOURCES = uip/prompter.c uip_prompter_LDADD = $(LDADD) $(POSTLINK) uip_refile_SOURCES = uip/refile.c uip_refile_LDADD = $(LDADD) $(POSTLINK) uip_repl_SOURCES = uip/repl.c uip/replsbr.c uip/whatnowproc.c uip/whatnowsbr.c \ uip/sendsbr.c uip/annosbr.c uip/distsbr.c uip_repl_LDADD = $(LDADD) $(READLINELIB) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_rmf_SOURCES = uip/rmf.c uip_rmf_LDADD = $(LDADD) $(POSTLINK) uip_rmm_SOURCES = uip/rmm.c uip_rmm_LDADD = $(LDADD) $(POSTLINK) uip_scan_SOURCES = uip/scan.c uip/scansbr.c uip_scan_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_send_SOURCES = uip/send.c uip/sendsbr.c uip/annosbr.c \ uip/distsbr.c uip_send_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_show_SOURCES = uip/show.c uip/mhlsbr.c uip_show_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_sortm_SOURCES = uip/sortm.c uip_sortm_LDADD = $(LDADD) $(POSTLINK) uip_whatnow_SOURCES = uip/whatnow.c uip/whatnowsbr.c uip/sendsbr.c \ uip/annosbr.c uip/distsbr.c uip_whatnow_LDADD = $(LDADD) $(READLINELIB) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_whom_SOURCES = uip/whom.c uip/distsbr.c uip_whom_LDADD = $(LDADD) $(POSTLINK) uip_ap_SOURCES = uip/ap.c uip_ap_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_dp_SOURCES = uip/dp.c uip_dp_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_fmtdump_SOURCES = uip/fmtdump.c uip_fmtdump_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_fmttest_SOURCES = uip/fmttest.c uip_fmttest_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_mhl_SOURCES = uip/mhl.c uip/mhlsbr.c uip_mhl_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_mhlogin_SOURCES = uip/mhlogin.c uip_mhlogin_LDADD = mts/libmts.a $(LDADD) $(CURLLIB) $(POSTLINK) uip_mkstemp_SOURCES = uip/mkstemp.c uip_mkstemp_LDADD = $(LDADD) $(POSTLINK) uip_post_SOURCES = uip/post.c uip/aliasbr.c uip_post_LDADD = mts/libmts.a $(LDADD) $(SASLLIB) $(CURLLIB) $(TLSLIB) \ $(POSTLINK) uip_rcvdist_SOURCES = uip/rcvdist.c uip/distsbr.c uip_rcvdist_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_rcvpack_SOURCES = uip/rcvpack.c uip/dropsbr.c uip_rcvpack_LDADD = $(LDADD) $(POSTLINK) uip_rcvstore_SOURCES = uip/rcvstore.c uip_rcvstore_LDADD = $(LDADD) $(POSTLINK) uip_rcvtty_SOURCES = uip/rcvtty.c uip/scansbr.c uip_rcvtty_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) uip_slocal_SOURCES = uip/slocal.c uip/aliasbr.c uip/dropsbr.c uip_slocal_LDADD = $(LDADD) $(NDBM_LIBS) $(POSTLINK) uip_viamail_SOURCES = uip/viamail.c uip/mhmisc.c uip/sendsbr.c \ uip/annosbr.c uip/distsbr.c uip_viamail_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) $(POSTLINK) test_getfullname_SOURCES = test/getfullname.c test_getfullname_LDADD = $(LDADD) $(POSTLINK) test_getcanon_SOURCES = test/getcanon.c test_getcanon_LDADD = $(POSTLINK) test_fakepop_SOURCES = test/fakepop.c test/server.c test_fakepop_LDADD = $(POSTLINK) test_fakesmtp_SOURCES = test/fakesmtp.c test/server.c test_fakesmtp_LDADD = $(POSTLINK) test_fakehttp_SOURCES = test/fakehttp.c test/server.c test_fakehttp_LDADD = $(LDADD) $(POSTLINK) test_getcwidth_SOURCES = test/getcwidth.c test_getcwidth_LDADD = $(POSTLINK) test_runpty_SOURCES = test/runpty.c test_runpty_LDADD = $(POSTLINK) sbr_libmh_a_SOURCES = \ config/config.c \ config/version.c \ sbr/addrsbr.c \ sbr/ambigsw.c \ sbr/arglist.c \ sbr/atooi.c \ sbr/base64.c \ sbr/brkstring.c \ sbr/charstring.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/context_replace.c \ sbr/context_save.c \ sbr/copyip.c \ sbr/cpydata.c \ sbr/cpydgst.c \ sbr/crawl_folders.c \ sbr/credentials.c \ sbr/ctype-checked.c \ sbr/datetime.c \ sbr/discard.c \ sbr/done.c \ sbr/dtime.c \ sbr/dtimep.l \ sbr/encode_rfc2047.c \ sbr/error.c \ sbr/escape_addresses.c \ sbr/ext_hook.c \ sbr/fdcompare.c \ sbr/fmt_addr.c \ sbr/fmt_compile.c \ sbr/fmt_new.c \ sbr/fmt_rfc2047.c \ sbr/fmt_scan.c \ sbr/folder_addmsg.c \ sbr/folder_delmsgs.c \ sbr/folder_free.c \ sbr/folder_pack.c \ sbr/folder_read.c \ sbr/folder_realloc.c \ sbr/getarguments.c \ sbr/getcpy.c \ sbr/geteditor.c \ sbr/getfolder.c \ sbr/getpass.c \ sbr/icalendar.l \ sbr/icalparse.y \ sbr/lock_file.c \ sbr/m_atoi.c \ sbr/m_backup.c \ sbr/m_convert.c \ sbr/m_draft.c \ sbr/m_getfld.c \ sbr/m_gmprot.c \ sbr/m_maildir.c \ sbr/m_mktemp.c \ sbr/m_name.c \ sbr/m_popen.c \ sbr/m_rand.c \ sbr/makedir.c \ sbr/md5.c \ sbr/message_id.c \ sbr/mf.c \ sbr/mime_type.c \ sbr/mts.c \ sbr/netsec.c \ sbr/oauth.c \ sbr/oauth_prof.c \ sbr/path.c \ sbr/pidstatus.c \ sbr/pidwait.c \ sbr/print_help.c \ sbr/print_sw.c \ sbr/print_version.c \ sbr/push.c \ sbr/r1bindex.c \ sbr/read_line.c \ sbr/read_switch.c \ sbr/read_switch_multiword.c \ sbr/read_switch_multiword_via_readline.c \ sbr/read_yes_or_no_if_tty.c \ sbr/readconfig.c \ sbr/refile.c \ sbr/remdir.c \ sbr/ruserpass.c \ sbr/seq_add.c \ sbr/seq_bits.c \ sbr/seq_del.c \ sbr/seq_getnum.c \ sbr/seq_list.c \ sbr/seq_nameok.c \ sbr/seq_print.c \ sbr/seq_read.c \ sbr/seq_save.c \ sbr/seq_setcur.c \ sbr/seq_setprev.c \ sbr/seq_setunseen.c \ sbr/showfile.c \ sbr/signals.c \ sbr/smatch.c \ sbr/snprintb.c \ sbr/ssequal.c \ sbr/strindex.c \ sbr/terminal.c \ sbr/trimcpy.c \ sbr/unquote.c \ sbr/uprf.c \ sbr/utils.c \ sbr/vector.c \ sbr/vfgets.c \ thirdparty/jsmn/jsmn.c \ # sbr_libmh_a_LIBADD = $(LIBOBJS) sbr_libmh_a_CPPFLAGS = ${AM_CPPFLAGS} -I./sbr \ -DNMHBINDIR='"$(bindir)"' \ -DNMHLIBEXECDIR='"$(nmhlibexecdir)"' \ -DNMHETCDIR='"@nmhetcdirinst@$(nmhetcdir)"' \ -DNMHDOCDIR='"@docdir@"' \ -DMAILSPOOL='"$(mailspool)"' \ -DSENDMAILPATH='"$(sendmailpath)"' mts_libmts_a_SOURCES = mts/smtp/smtp.c manext1 = 1 manext5 = 5 manext7 = 7 manext8 = 8 all: config.h $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .$(manext1) .$(manext5) .$(manext7) .$(manext8) .c .l .man .o .obj .y am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): config.h: stamp-h1 @test -f $@ || rm -f stamp-h1 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.h.in: $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 test/common.sh: $(top_builddir)/config.status $(top_srcdir)/test/common.sh.in cd $(top_builddir) && $(SHELL) ./config.status $@ uip/spost: $(top_builddir)/config.status $(top_srcdir)/uip/spost.in cd $(top_builddir) && $(SHELL) ./config.status $@ clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) mts/smtp/$(am__dirstamp): @$(MKDIR_P) mts/smtp @: > mts/smtp/$(am__dirstamp) mts/smtp/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) mts/smtp/$(DEPDIR) @: > mts/smtp/$(DEPDIR)/$(am__dirstamp) mts/smtp/smtp.$(OBJEXT): mts/smtp/$(am__dirstamp) \ mts/smtp/$(DEPDIR)/$(am__dirstamp) mts/$(am__dirstamp): @$(MKDIR_P) mts @: > mts/$(am__dirstamp) mts/libmts.a: $(mts_libmts_a_OBJECTS) $(mts_libmts_a_DEPENDENCIES) $(EXTRA_mts_libmts_a_DEPENDENCIES) mts/$(am__dirstamp) $(AM_V_at)-rm -f mts/libmts.a $(AM_V_AR)$(mts_libmts_a_AR) mts/libmts.a $(mts_libmts_a_OBJECTS) $(mts_libmts_a_LIBADD) $(AM_V_at)$(RANLIB) mts/libmts.a config/$(am__dirstamp): @$(MKDIR_P) config @: > config/$(am__dirstamp) config/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) config/$(DEPDIR) @: > config/$(DEPDIR)/$(am__dirstamp) config/sbr_libmh_a-config.$(OBJEXT): config/$(am__dirstamp) \ config/$(DEPDIR)/$(am__dirstamp) config/sbr_libmh_a-version.$(OBJEXT): config/$(am__dirstamp) \ config/$(DEPDIR)/$(am__dirstamp) sbr/$(am__dirstamp): @$(MKDIR_P) sbr @: > sbr/$(am__dirstamp) sbr/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) sbr/$(DEPDIR) @: > sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-addrsbr.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-ambigsw.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-arglist.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-atooi.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-base64.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-brkstring.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-charstring.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-check_charset.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-client.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-closefds.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-concat.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-context_del.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-context_find.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-context_foil.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-context_read.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-context_replace.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-context_save.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-copyip.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-cpydata.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-cpydgst.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-crawl_folders.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-credentials.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-ctype-checked.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-datetime.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-discard.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-done.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-dtime.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-dtimep.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-encode_rfc2047.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-error.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-escape_addresses.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-ext_hook.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-fdcompare.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-fmt_addr.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-fmt_compile.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-fmt_new.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-fmt_rfc2047.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-fmt_scan.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-folder_addmsg.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-folder_delmsgs.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-folder_free.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-folder_pack.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-folder_read.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-folder_realloc.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-getarguments.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-getcpy.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-geteditor.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-getfolder.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-getpass.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-icalendar.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/icalparse.h: sbr/icalparse.c @if test ! -f $@; then rm -f sbr/icalparse.c; else :; fi @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) sbr/icalparse.c; else :; fi sbr/sbr_libmh_a-icalparse.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-lock_file.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-m_atoi.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-m_backup.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-m_convert.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-m_draft.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-m_getfld.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-m_gmprot.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-m_maildir.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-m_mktemp.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-m_name.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-m_popen.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-m_rand.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-makedir.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-md5.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-message_id.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-mf.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-mime_type.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-mts.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-netsec.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-oauth.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-oauth_prof.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-path.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-pidstatus.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-pidwait.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-print_help.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-print_sw.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-print_version.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-push.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-r1bindex.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-read_line.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-read_switch.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-read_switch_multiword.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-read_switch_multiword_via_readline.$(OBJEXT): \ sbr/$(am__dirstamp) sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-read_yes_or_no_if_tty.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-readconfig.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-refile.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-remdir.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-ruserpass.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-seq_add.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-seq_bits.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-seq_del.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-seq_getnum.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-seq_list.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-seq_nameok.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-seq_print.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-seq_read.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-seq_save.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-seq_setcur.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-seq_setprev.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-seq_setunseen.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-showfile.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-signals.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-smatch.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-snprintb.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-ssequal.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-strindex.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-terminal.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-trimcpy.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-unquote.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-uprf.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-utils.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-vector.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) sbr/sbr_libmh_a-vfgets.$(OBJEXT): sbr/$(am__dirstamp) \ sbr/$(DEPDIR)/$(am__dirstamp) thirdparty/jsmn/$(am__dirstamp): @$(MKDIR_P) thirdparty/jsmn @: > thirdparty/jsmn/$(am__dirstamp) thirdparty/jsmn/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) thirdparty/jsmn/$(DEPDIR) @: > thirdparty/jsmn/$(DEPDIR)/$(am__dirstamp) thirdparty/jsmn/sbr_libmh_a-jsmn.$(OBJEXT): \ thirdparty/jsmn/$(am__dirstamp) \ thirdparty/jsmn/$(DEPDIR)/$(am__dirstamp) sbr/libmh.a: $(sbr_libmh_a_OBJECTS) $(sbr_libmh_a_DEPENDENCIES) $(EXTRA_sbr_libmh_a_DEPENDENCIES) sbr/$(am__dirstamp) $(AM_V_at)-rm -f sbr/libmh.a $(AM_V_AR)$(sbr_libmh_a_AR) sbr/libmh.a $(sbr_libmh_a_OBJECTS) $(sbr_libmh_a_LIBADD) $(AM_V_at)$(RANLIB) sbr/libmh.a install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) clean-checkPROGRAMS: -test -z "$(check_PROGRAMS)" || rm -f $(check_PROGRAMS) install-nmhlibexecPROGRAMS: $(nmhlibexec_PROGRAMS) @$(NORMAL_INSTALL) @list='$(nmhlibexec_PROGRAMS)'; test -n "$(nmhlibexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(nmhlibexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(nmhlibexecdir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(nmhlibexecdir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(nmhlibexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-nmhlibexecPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(nmhlibexec_PROGRAMS)'; test -n "$(nmhlibexecdir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(nmhlibexecdir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(nmhlibexecdir)" && rm -f $$files clean-nmhlibexecPROGRAMS: -test -z "$(nmhlibexec_PROGRAMS)" || rm -f $(nmhlibexec_PROGRAMS) test/$(am__dirstamp): @$(MKDIR_P) test @: > test/$(am__dirstamp) test/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) test/$(DEPDIR) @: > test/$(DEPDIR)/$(am__dirstamp) test/fakehttp.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/server.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/fakehttp$(EXEEXT): $(test_fakehttp_OBJECTS) $(test_fakehttp_DEPENDENCIES) $(EXTRA_test_fakehttp_DEPENDENCIES) test/$(am__dirstamp) @rm -f test/fakehttp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fakehttp_OBJECTS) $(test_fakehttp_LDADD) $(LIBS) test/fakepop.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/fakepop$(EXEEXT): $(test_fakepop_OBJECTS) $(test_fakepop_DEPENDENCIES) $(EXTRA_test_fakepop_DEPENDENCIES) test/$(am__dirstamp) @rm -f test/fakepop$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fakepop_OBJECTS) $(test_fakepop_LDADD) $(LIBS) test/fakesmtp.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/fakesmtp$(EXEEXT): $(test_fakesmtp_OBJECTS) $(test_fakesmtp_DEPENDENCIES) $(EXTRA_test_fakesmtp_DEPENDENCIES) test/$(am__dirstamp) @rm -f test/fakesmtp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_fakesmtp_OBJECTS) $(test_fakesmtp_LDADD) $(LIBS) test/getcanon.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/getcanon$(EXEEXT): $(test_getcanon_OBJECTS) $(test_getcanon_DEPENDENCIES) $(EXTRA_test_getcanon_DEPENDENCIES) test/$(am__dirstamp) @rm -f test/getcanon$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_getcanon_OBJECTS) $(test_getcanon_LDADD) $(LIBS) test/getcwidth.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/getcwidth$(EXEEXT): $(test_getcwidth_OBJECTS) $(test_getcwidth_DEPENDENCIES) $(EXTRA_test_getcwidth_DEPENDENCIES) test/$(am__dirstamp) @rm -f test/getcwidth$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_getcwidth_OBJECTS) $(test_getcwidth_LDADD) $(LIBS) test/getfullname.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/getfullname$(EXEEXT): $(test_getfullname_OBJECTS) $(test_getfullname_DEPENDENCIES) $(EXTRA_test_getfullname_DEPENDENCIES) test/$(am__dirstamp) @rm -f test/getfullname$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_getfullname_OBJECTS) $(test_getfullname_LDADD) $(LIBS) test/runpty.$(OBJEXT): test/$(am__dirstamp) \ test/$(DEPDIR)/$(am__dirstamp) test/runpty$(EXEEXT): $(test_runpty_OBJECTS) $(test_runpty_DEPENDENCIES) $(EXTRA_test_runpty_DEPENDENCIES) test/$(am__dirstamp) @rm -f test/runpty$(EXEEXT) $(AM_V_CCLD)$(LINK) $(test_runpty_OBJECTS) $(test_runpty_LDADD) $(LIBS) uip/$(am__dirstamp): @$(MKDIR_P) uip @: > uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) uip/$(DEPDIR) @: > uip/$(DEPDIR)/$(am__dirstamp) uip/ali.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/aliasbr.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/ali$(EXEEXT): $(uip_ali_OBJECTS) $(uip_ali_DEPENDENCIES) $(EXTRA_uip_ali_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/ali$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_ali_OBJECTS) $(uip_ali_LDADD) $(LIBS) uip/anno.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/annosbr.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/anno$(EXEEXT): $(uip_anno_OBJECTS) $(uip_anno_DEPENDENCIES) $(EXTRA_uip_anno_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/anno$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_anno_OBJECTS) $(uip_anno_LDADD) $(LIBS) uip/ap.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/ap$(EXEEXT): $(uip_ap_OBJECTS) $(uip_ap_DEPENDENCIES) $(EXTRA_uip_ap_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/ap$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_ap_OBJECTS) $(uip_ap_LDADD) $(LIBS) uip/burst.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/mhparse.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/mhmisc.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/mhfree.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/mhcachesbr.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/burst$(EXEEXT): $(uip_burst_OBJECTS) $(uip_burst_DEPENDENCIES) $(EXTRA_uip_burst_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/burst$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_burst_OBJECTS) $(uip_burst_LDADD) $(LIBS) uip/comp.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/whatnowproc.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/whatnowsbr.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/sendsbr.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/distsbr.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/comp$(EXEEXT): $(uip_comp_OBJECTS) $(uip_comp_DEPENDENCIES) $(EXTRA_uip_comp_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/comp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_comp_OBJECTS) $(uip_comp_LDADD) $(LIBS) uip/dist.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/forwsbr.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/dist$(EXEEXT): $(uip_dist_OBJECTS) $(uip_dist_DEPENDENCIES) $(EXTRA_uip_dist_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/dist$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_dist_OBJECTS) $(uip_dist_LDADD) $(LIBS) uip/dp.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/dp$(EXEEXT): $(uip_dp_OBJECTS) $(uip_dp_DEPENDENCIES) $(EXTRA_uip_dp_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/dp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_dp_OBJECTS) $(uip_dp_LDADD) $(LIBS) uip/flist.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/flist$(EXEEXT): $(uip_flist_OBJECTS) $(uip_flist_DEPENDENCIES) $(EXTRA_uip_flist_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/flist$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_flist_OBJECTS) $(uip_flist_LDADD) $(LIBS) uip/fmtdump.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/fmtdump$(EXEEXT): $(uip_fmtdump_OBJECTS) $(uip_fmtdump_DEPENDENCIES) $(EXTRA_uip_fmtdump_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/fmtdump$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_fmtdump_OBJECTS) $(uip_fmtdump_LDADD) $(LIBS) uip/fmttest.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/fmttest$(EXEEXT): $(uip_fmttest_OBJECTS) $(uip_fmttest_DEPENDENCIES) $(EXTRA_uip_fmttest_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/fmttest$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_fmttest_OBJECTS) $(uip_fmttest_LDADD) $(LIBS) uip/folder.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/folder$(EXEEXT): $(uip_folder_OBJECTS) $(uip_folder_DEPENDENCIES) $(EXTRA_uip_folder_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/folder$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_folder_OBJECTS) $(uip_folder_LDADD) $(LIBS) uip/forw.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/forw$(EXEEXT): $(uip_forw_OBJECTS) $(uip_forw_DEPENDENCIES) $(EXTRA_uip_forw_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/forw$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_forw_OBJECTS) $(uip_forw_LDADD) $(LIBS) uip/inc.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/scansbr.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/dropsbr.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/popsbr.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/inc$(EXEEXT): $(uip_inc_OBJECTS) $(uip_inc_DEPENDENCIES) $(EXTRA_uip_inc_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/inc$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_inc_OBJECTS) $(uip_inc_LDADD) $(LIBS) uip/install-mh.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/install-mh$(EXEEXT): $(uip_install_mh_OBJECTS) $(uip_install_mh_DEPENDENCIES) $(EXTRA_uip_install_mh_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/install-mh$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_install_mh_OBJECTS) $(uip_install_mh_LDADD) $(LIBS) uip/mark.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/mark$(EXEEXT): $(uip_mark_OBJECTS) $(uip_mark_DEPENDENCIES) $(EXTRA_uip_mark_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/mark$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_mark_OBJECTS) $(uip_mark_LDADD) $(LIBS) uip/mhbuild.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/mhbuildsbr.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/mhlistsbr.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/mhoutsbr.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/mhstoresbr.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/mhshowsbr.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/mhbuild$(EXEEXT): $(uip_mhbuild_OBJECTS) $(uip_mhbuild_DEPENDENCIES) $(EXTRA_uip_mhbuild_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/mhbuild$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_mhbuild_OBJECTS) $(uip_mhbuild_LDADD) $(LIBS) uip/mhfixmsg.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/mhfixmsg$(EXEEXT): $(uip_mhfixmsg_OBJECTS) $(uip_mhfixmsg_DEPENDENCIES) $(EXTRA_uip_mhfixmsg_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/mhfixmsg$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_mhfixmsg_OBJECTS) $(uip_mhfixmsg_LDADD) $(LIBS) uip/mhical.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/mhical$(EXEEXT): $(uip_mhical_OBJECTS) $(uip_mhical_DEPENDENCIES) $(EXTRA_uip_mhical_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/mhical$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_mhical_OBJECTS) $(uip_mhical_LDADD) $(LIBS) uip/mhl.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/mhlsbr.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/mhl$(EXEEXT): $(uip_mhl_OBJECTS) $(uip_mhl_DEPENDENCIES) $(EXTRA_uip_mhl_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/mhl$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_mhl_OBJECTS) $(uip_mhl_LDADD) $(LIBS) uip/mhlist.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/mhlist$(EXEEXT): $(uip_mhlist_OBJECTS) $(uip_mhlist_DEPENDENCIES) $(EXTRA_uip_mhlist_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/mhlist$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_mhlist_OBJECTS) $(uip_mhlist_LDADD) $(LIBS) uip/mhlogin.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/mhlogin$(EXEEXT): $(uip_mhlogin_OBJECTS) $(uip_mhlogin_DEPENDENCIES) $(EXTRA_uip_mhlogin_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/mhlogin$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_mhlogin_OBJECTS) $(uip_mhlogin_LDADD) $(LIBS) uip/mhn.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/mhn$(EXEEXT): $(uip_mhn_OBJECTS) $(uip_mhn_DEPENDENCIES) $(EXTRA_uip_mhn_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/mhn$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_mhn_OBJECTS) $(uip_mhn_LDADD) $(LIBS) uip/mhparam.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/mhparam$(EXEEXT): $(uip_mhparam_OBJECTS) $(uip_mhparam_DEPENDENCIES) $(EXTRA_uip_mhparam_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/mhparam$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_mhparam_OBJECTS) $(uip_mhparam_LDADD) $(LIBS) uip/mhpath.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/mhpath$(EXEEXT): $(uip_mhpath_OBJECTS) $(uip_mhpath_DEPENDENCIES) $(EXTRA_uip_mhpath_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/mhpath$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_mhpath_OBJECTS) $(uip_mhpath_LDADD) $(LIBS) uip/mhshow.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/mhshow$(EXEEXT): $(uip_mhshow_OBJECTS) $(uip_mhshow_DEPENDENCIES) $(EXTRA_uip_mhshow_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/mhshow$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_mhshow_OBJECTS) $(uip_mhshow_LDADD) $(LIBS) uip/mhstore.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/mhstore$(EXEEXT): $(uip_mhstore_OBJECTS) $(uip_mhstore_DEPENDENCIES) $(EXTRA_uip_mhstore_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/mhstore$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_mhstore_OBJECTS) $(uip_mhstore_LDADD) $(LIBS) uip/mkstemp.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/mkstemp$(EXEEXT): $(uip_mkstemp_OBJECTS) $(uip_mkstemp_DEPENDENCIES) $(EXTRA_uip_mkstemp_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/mkstemp$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_mkstemp_OBJECTS) $(uip_mkstemp_LDADD) $(LIBS) uip/msgchk.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/msgchk$(EXEEXT): $(uip_msgchk_OBJECTS) $(uip_msgchk_DEPENDENCIES) $(EXTRA_uip_msgchk_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/msgchk$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_msgchk_OBJECTS) $(uip_msgchk_LDADD) $(LIBS) uip/new.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/new$(EXEEXT): $(uip_new_OBJECTS) $(uip_new_DEPENDENCIES) $(EXTRA_uip_new_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/new$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_new_OBJECTS) $(uip_new_LDADD) $(LIBS) uip/packf.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/packf$(EXEEXT): $(uip_packf_OBJECTS) $(uip_packf_DEPENDENCIES) $(EXTRA_uip_packf_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/packf$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_packf_OBJECTS) $(uip_packf_LDADD) $(LIBS) uip/pick.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/picksbr.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/pick$(EXEEXT): $(uip_pick_OBJECTS) $(uip_pick_DEPENDENCIES) $(EXTRA_uip_pick_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/pick$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_pick_OBJECTS) $(uip_pick_LDADD) $(LIBS) uip/post.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/post$(EXEEXT): $(uip_post_OBJECTS) $(uip_post_DEPENDENCIES) $(EXTRA_uip_post_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/post$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_post_OBJECTS) $(uip_post_LDADD) $(LIBS) uip/prompter.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/prompter$(EXEEXT): $(uip_prompter_OBJECTS) $(uip_prompter_DEPENDENCIES) $(EXTRA_uip_prompter_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/prompter$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_prompter_OBJECTS) $(uip_prompter_LDADD) $(LIBS) uip/rcvdist.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/rcvdist$(EXEEXT): $(uip_rcvdist_OBJECTS) $(uip_rcvdist_DEPENDENCIES) $(EXTRA_uip_rcvdist_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/rcvdist$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_rcvdist_OBJECTS) $(uip_rcvdist_LDADD) $(LIBS) uip/rcvpack.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/rcvpack$(EXEEXT): $(uip_rcvpack_OBJECTS) $(uip_rcvpack_DEPENDENCIES) $(EXTRA_uip_rcvpack_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/rcvpack$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_rcvpack_OBJECTS) $(uip_rcvpack_LDADD) $(LIBS) uip/rcvstore.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/rcvstore$(EXEEXT): $(uip_rcvstore_OBJECTS) $(uip_rcvstore_DEPENDENCIES) $(EXTRA_uip_rcvstore_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/rcvstore$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_rcvstore_OBJECTS) $(uip_rcvstore_LDADD) $(LIBS) uip/rcvtty.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/rcvtty$(EXEEXT): $(uip_rcvtty_OBJECTS) $(uip_rcvtty_DEPENDENCIES) $(EXTRA_uip_rcvtty_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/rcvtty$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_rcvtty_OBJECTS) $(uip_rcvtty_LDADD) $(LIBS) uip/refile.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/refile$(EXEEXT): $(uip_refile_OBJECTS) $(uip_refile_DEPENDENCIES) $(EXTRA_uip_refile_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/refile$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_refile_OBJECTS) $(uip_refile_LDADD) $(LIBS) uip/repl.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/replsbr.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/repl$(EXEEXT): $(uip_repl_OBJECTS) $(uip_repl_DEPENDENCIES) $(EXTRA_uip_repl_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/repl$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_repl_OBJECTS) $(uip_repl_LDADD) $(LIBS) uip/rmf.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/rmf$(EXEEXT): $(uip_rmf_OBJECTS) $(uip_rmf_DEPENDENCIES) $(EXTRA_uip_rmf_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/rmf$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_rmf_OBJECTS) $(uip_rmf_LDADD) $(LIBS) uip/rmm.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/rmm$(EXEEXT): $(uip_rmm_OBJECTS) $(uip_rmm_DEPENDENCIES) $(EXTRA_uip_rmm_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/rmm$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_rmm_OBJECTS) $(uip_rmm_LDADD) $(LIBS) uip/scan.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/scan$(EXEEXT): $(uip_scan_OBJECTS) $(uip_scan_DEPENDENCIES) $(EXTRA_uip_scan_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/scan$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_scan_OBJECTS) $(uip_scan_LDADD) $(LIBS) uip/send.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/send$(EXEEXT): $(uip_send_OBJECTS) $(uip_send_DEPENDENCIES) $(EXTRA_uip_send_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/send$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_send_OBJECTS) $(uip_send_LDADD) $(LIBS) uip/show.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/show$(EXEEXT): $(uip_show_OBJECTS) $(uip_show_DEPENDENCIES) $(EXTRA_uip_show_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/show$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_show_OBJECTS) $(uip_show_LDADD) $(LIBS) uip/slocal.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/slocal$(EXEEXT): $(uip_slocal_OBJECTS) $(uip_slocal_DEPENDENCIES) $(EXTRA_uip_slocal_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/slocal$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_slocal_OBJECTS) $(uip_slocal_LDADD) $(LIBS) uip/sortm.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/sortm$(EXEEXT): $(uip_sortm_OBJECTS) $(uip_sortm_DEPENDENCIES) $(EXTRA_uip_sortm_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/sortm$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_sortm_OBJECTS) $(uip_sortm_LDADD) $(LIBS) uip/viamail.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/viamail$(EXEEXT): $(uip_viamail_OBJECTS) $(uip_viamail_DEPENDENCIES) $(EXTRA_uip_viamail_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/viamail$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_viamail_OBJECTS) $(uip_viamail_LDADD) $(LIBS) uip/whatnow.$(OBJEXT): uip/$(am__dirstamp) \ uip/$(DEPDIR)/$(am__dirstamp) uip/whatnow$(EXEEXT): $(uip_whatnow_OBJECTS) $(uip_whatnow_DEPENDENCIES) $(EXTRA_uip_whatnow_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/whatnow$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_whatnow_OBJECTS) $(uip_whatnow_LDADD) $(LIBS) uip/whom.$(OBJEXT): uip/$(am__dirstamp) uip/$(DEPDIR)/$(am__dirstamp) uip/whom$(EXEEXT): $(uip_whom_OBJECTS) $(uip_whom_DEPENDENCIES) $(EXTRA_uip_whom_DEPENDENCIES) uip/$(am__dirstamp) @rm -f uip/whom$(EXEEXT) $(AM_V_CCLD)$(LINK) $(uip_whom_OBJECTS) $(uip_whom_LDADD) $(LIBS) install-binSCRIPTS: $(bin_SCRIPTS) @$(NORMAL_INSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) install-dist_docs_contribSCRIPTS: $(dist_docs_contrib_SCRIPTS) @$(NORMAL_INSTALL) @list='$(dist_docs_contrib_SCRIPTS)'; test -n "$(docs_contribdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(docs_contribdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(docs_contribdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(docs_contribdir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(docs_contribdir)$$dir" || exit $$?; \ } \ ; done uninstall-dist_docs_contribSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(dist_docs_contrib_SCRIPTS)'; test -n "$(docs_contribdir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(docs_contribdir)'; $(am__uninstall_files_from_dir) install-dist_nmhetcSCRIPTS: $(dist_nmhetc_SCRIPTS) @$(NORMAL_INSTALL) @list='$(dist_nmhetc_SCRIPTS)'; test -n "$(nmhetcdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(nmhetcdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(nmhetcdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(nmhetcdir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(nmhetcdir)$$dir" || exit $$?; \ } \ ; done uninstall-dist_nmhetcSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(dist_nmhetc_SCRIPTS)'; test -n "$(nmhetcdir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(nmhetcdir)'; $(am__uninstall_files_from_dir) install-nmhlibexecSCRIPTS: $(nmhlibexec_SCRIPTS) @$(NORMAL_INSTALL) @list='$(nmhlibexec_SCRIPTS)'; test -n "$(nmhlibexecdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(nmhlibexecdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(nmhlibexecdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(nmhlibexecdir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(nmhlibexecdir)$$dir" || exit $$?; \ } \ ; done uninstall-nmhlibexecSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(nmhlibexec_SCRIPTS)'; test -n "$(nmhlibexecdir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(nmhlibexecdir)'; $(am__uninstall_files_from_dir) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f config/*.$(OBJEXT) -rm -f mts/smtp/*.$(OBJEXT) -rm -f sbr/*.$(OBJEXT) -rm -f test/*.$(OBJEXT) -rm -f thirdparty/jsmn/*.$(OBJEXT) -rm -f uip/*.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/sbr_libmh_a-config.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@config/$(DEPDIR)/sbr_libmh_a-version.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@mts/smtp/$(DEPDIR)/smtp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/getline.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-addrsbr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-ambigsw.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-arglist.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-atooi.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-base64.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-brkstring.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-charstring.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-check_charset.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-closefds.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-concat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-context_del.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-context_find.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-context_foil.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-context_read.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-context_replace.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-context_save.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-copyip.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-cpydata.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-cpydgst.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-crawl_folders.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-credentials.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-ctype-checked.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-datetime.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-discard.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-done.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-dtime.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-dtimep.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-encode_rfc2047.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-error.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-escape_addresses.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-ext_hook.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-fdcompare.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-fmt_addr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-fmt_compile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-fmt_new.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-fmt_rfc2047.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-fmt_scan.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-folder_addmsg.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-folder_delmsgs.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-folder_free.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-folder_pack.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-folder_read.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-folder_realloc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-getarguments.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-getcpy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-geteditor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-getfolder.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-getpass.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-icalendar.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-icalparse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-lock_file.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-m_atoi.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-m_backup.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-m_convert.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-m_draft.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-m_getfld.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-m_gmprot.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-m_maildir.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-m_mktemp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-m_name.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-m_popen.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-m_rand.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-makedir.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-md5.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-message_id.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-mf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-mime_type.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-mts.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-netsec.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-oauth.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-oauth_prof.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-path.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-pidstatus.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-pidwait.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-print_help.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-print_sw.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-print_version.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-push.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-r1bindex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-read_line.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-read_switch.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-read_switch_multiword.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-read_switch_multiword_via_readline.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-read_yes_or_no_if_tty.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-readconfig.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-refile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-remdir.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-ruserpass.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-seq_add.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-seq_bits.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-seq_del.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-seq_getnum.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-seq_list.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-seq_nameok.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-seq_print.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-seq_read.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-seq_save.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-seq_setcur.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-seq_setprev.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-seq_setunseen.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-showfile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-signals.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-smatch.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-snprintb.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-ssequal.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-strindex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-terminal.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-trimcpy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-unquote.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-uprf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-utils.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-vector.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@sbr/$(DEPDIR)/sbr_libmh_a-vfgets.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/fakehttp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/fakepop.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/fakesmtp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/getcanon.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/getcwidth.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/getfullname.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/runpty.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@thirdparty/jsmn/$(DEPDIR)/sbr_libmh_a-jsmn.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/ali.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/aliasbr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/anno.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/annosbr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/ap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/burst.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/comp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/dist.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/distsbr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/dp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/dropsbr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/flist.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/fmtdump.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/fmttest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/folder.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/forw.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/forwsbr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/inc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/install-mh.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/mark.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/mhbuild.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/mhbuildsbr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/mhcachesbr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/mhfixmsg.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/mhfree.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/mhical.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/mhl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/mhlist.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/mhlistsbr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/mhlogin.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/mhlsbr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/mhmisc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/mhn.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/mhoutsbr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/mhparam.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/mhparse.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/mhpath.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/mhshow.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/mhshowsbr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/mhstore.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/mhstoresbr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/mkstemp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/msgchk.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/new.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/packf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/pick.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/picksbr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/popsbr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/post.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/prompter.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/rcvdist.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/rcvpack.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/rcvstore.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/rcvtty.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/refile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/repl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/replsbr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/rmf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/rmm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/scan.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/scansbr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/send.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/sendsbr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/show.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/slocal.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/sortm.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/viamail.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/whatnow.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/whatnowproc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/whatnowsbr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@uip/$(DEPDIR)/whom.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` config/sbr_libmh_a-config.o: config/config.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT config/sbr_libmh_a-config.o -MD -MP -MF config/$(DEPDIR)/sbr_libmh_a-config.Tpo -c -o config/sbr_libmh_a-config.o `test -f 'config/config.c' || echo '$(srcdir)/'`config/config.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) config/$(DEPDIR)/sbr_libmh_a-config.Tpo config/$(DEPDIR)/sbr_libmh_a-config.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='config/config.c' object='config/sbr_libmh_a-config.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o config/sbr_libmh_a-config.o `test -f 'config/config.c' || echo '$(srcdir)/'`config/config.c config/sbr_libmh_a-config.obj: config/config.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT config/sbr_libmh_a-config.obj -MD -MP -MF config/$(DEPDIR)/sbr_libmh_a-config.Tpo -c -o config/sbr_libmh_a-config.obj `if test -f 'config/config.c'; then $(CYGPATH_W) 'config/config.c'; else $(CYGPATH_W) '$(srcdir)/config/config.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) config/$(DEPDIR)/sbr_libmh_a-config.Tpo config/$(DEPDIR)/sbr_libmh_a-config.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='config/config.c' object='config/sbr_libmh_a-config.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o config/sbr_libmh_a-config.obj `if test -f 'config/config.c'; then $(CYGPATH_W) 'config/config.c'; else $(CYGPATH_W) '$(srcdir)/config/config.c'; fi` config/sbr_libmh_a-version.o: config/version.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT config/sbr_libmh_a-version.o -MD -MP -MF config/$(DEPDIR)/sbr_libmh_a-version.Tpo -c -o config/sbr_libmh_a-version.o `test -f 'config/version.c' || echo '$(srcdir)/'`config/version.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) config/$(DEPDIR)/sbr_libmh_a-version.Tpo config/$(DEPDIR)/sbr_libmh_a-version.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='config/version.c' object='config/sbr_libmh_a-version.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o config/sbr_libmh_a-version.o `test -f 'config/version.c' || echo '$(srcdir)/'`config/version.c config/sbr_libmh_a-version.obj: config/version.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT config/sbr_libmh_a-version.obj -MD -MP -MF config/$(DEPDIR)/sbr_libmh_a-version.Tpo -c -o config/sbr_libmh_a-version.obj `if test -f 'config/version.c'; then $(CYGPATH_W) 'config/version.c'; else $(CYGPATH_W) '$(srcdir)/config/version.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) config/$(DEPDIR)/sbr_libmh_a-version.Tpo config/$(DEPDIR)/sbr_libmh_a-version.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='config/version.c' object='config/sbr_libmh_a-version.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o config/sbr_libmh_a-version.obj `if test -f 'config/version.c'; then $(CYGPATH_W) 'config/version.c'; else $(CYGPATH_W) '$(srcdir)/config/version.c'; fi` sbr/sbr_libmh_a-addrsbr.o: sbr/addrsbr.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-addrsbr.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-addrsbr.Tpo -c -o sbr/sbr_libmh_a-addrsbr.o `test -f 'sbr/addrsbr.c' || echo '$(srcdir)/'`sbr/addrsbr.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-addrsbr.Tpo sbr/$(DEPDIR)/sbr_libmh_a-addrsbr.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/addrsbr.c' object='sbr/sbr_libmh_a-addrsbr.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-addrsbr.o `test -f 'sbr/addrsbr.c' || echo '$(srcdir)/'`sbr/addrsbr.c sbr/sbr_libmh_a-addrsbr.obj: sbr/addrsbr.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-addrsbr.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-addrsbr.Tpo -c -o sbr/sbr_libmh_a-addrsbr.obj `if test -f 'sbr/addrsbr.c'; then $(CYGPATH_W) 'sbr/addrsbr.c'; else $(CYGPATH_W) '$(srcdir)/sbr/addrsbr.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-addrsbr.Tpo sbr/$(DEPDIR)/sbr_libmh_a-addrsbr.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/addrsbr.c' object='sbr/sbr_libmh_a-addrsbr.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-addrsbr.obj `if test -f 'sbr/addrsbr.c'; then $(CYGPATH_W) 'sbr/addrsbr.c'; else $(CYGPATH_W) '$(srcdir)/sbr/addrsbr.c'; fi` sbr/sbr_libmh_a-ambigsw.o: sbr/ambigsw.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-ambigsw.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-ambigsw.Tpo -c -o sbr/sbr_libmh_a-ambigsw.o `test -f 'sbr/ambigsw.c' || echo '$(srcdir)/'`sbr/ambigsw.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-ambigsw.Tpo sbr/$(DEPDIR)/sbr_libmh_a-ambigsw.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/ambigsw.c' object='sbr/sbr_libmh_a-ambigsw.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-ambigsw.o `test -f 'sbr/ambigsw.c' || echo '$(srcdir)/'`sbr/ambigsw.c sbr/sbr_libmh_a-ambigsw.obj: sbr/ambigsw.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-ambigsw.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-ambigsw.Tpo -c -o sbr/sbr_libmh_a-ambigsw.obj `if test -f 'sbr/ambigsw.c'; then $(CYGPATH_W) 'sbr/ambigsw.c'; else $(CYGPATH_W) '$(srcdir)/sbr/ambigsw.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-ambigsw.Tpo sbr/$(DEPDIR)/sbr_libmh_a-ambigsw.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/ambigsw.c' object='sbr/sbr_libmh_a-ambigsw.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-ambigsw.obj `if test -f 'sbr/ambigsw.c'; then $(CYGPATH_W) 'sbr/ambigsw.c'; else $(CYGPATH_W) '$(srcdir)/sbr/ambigsw.c'; fi` sbr/sbr_libmh_a-arglist.o: sbr/arglist.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-arglist.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-arglist.Tpo -c -o sbr/sbr_libmh_a-arglist.o `test -f 'sbr/arglist.c' || echo '$(srcdir)/'`sbr/arglist.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-arglist.Tpo sbr/$(DEPDIR)/sbr_libmh_a-arglist.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/arglist.c' object='sbr/sbr_libmh_a-arglist.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-arglist.o `test -f 'sbr/arglist.c' || echo '$(srcdir)/'`sbr/arglist.c sbr/sbr_libmh_a-arglist.obj: sbr/arglist.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-arglist.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-arglist.Tpo -c -o sbr/sbr_libmh_a-arglist.obj `if test -f 'sbr/arglist.c'; then $(CYGPATH_W) 'sbr/arglist.c'; else $(CYGPATH_W) '$(srcdir)/sbr/arglist.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-arglist.Tpo sbr/$(DEPDIR)/sbr_libmh_a-arglist.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/arglist.c' object='sbr/sbr_libmh_a-arglist.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-arglist.obj `if test -f 'sbr/arglist.c'; then $(CYGPATH_W) 'sbr/arglist.c'; else $(CYGPATH_W) '$(srcdir)/sbr/arglist.c'; fi` sbr/sbr_libmh_a-atooi.o: sbr/atooi.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-atooi.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-atooi.Tpo -c -o sbr/sbr_libmh_a-atooi.o `test -f 'sbr/atooi.c' || echo '$(srcdir)/'`sbr/atooi.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-atooi.Tpo sbr/$(DEPDIR)/sbr_libmh_a-atooi.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/atooi.c' object='sbr/sbr_libmh_a-atooi.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-atooi.o `test -f 'sbr/atooi.c' || echo '$(srcdir)/'`sbr/atooi.c sbr/sbr_libmh_a-atooi.obj: sbr/atooi.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-atooi.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-atooi.Tpo -c -o sbr/sbr_libmh_a-atooi.obj `if test -f 'sbr/atooi.c'; then $(CYGPATH_W) 'sbr/atooi.c'; else $(CYGPATH_W) '$(srcdir)/sbr/atooi.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-atooi.Tpo sbr/$(DEPDIR)/sbr_libmh_a-atooi.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/atooi.c' object='sbr/sbr_libmh_a-atooi.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-atooi.obj `if test -f 'sbr/atooi.c'; then $(CYGPATH_W) 'sbr/atooi.c'; else $(CYGPATH_W) '$(srcdir)/sbr/atooi.c'; fi` sbr/sbr_libmh_a-base64.o: sbr/base64.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-base64.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-base64.Tpo -c -o sbr/sbr_libmh_a-base64.o `test -f 'sbr/base64.c' || echo '$(srcdir)/'`sbr/base64.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-base64.Tpo sbr/$(DEPDIR)/sbr_libmh_a-base64.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/base64.c' object='sbr/sbr_libmh_a-base64.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-base64.o `test -f 'sbr/base64.c' || echo '$(srcdir)/'`sbr/base64.c sbr/sbr_libmh_a-base64.obj: sbr/base64.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-base64.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-base64.Tpo -c -o sbr/sbr_libmh_a-base64.obj `if test -f 'sbr/base64.c'; then $(CYGPATH_W) 'sbr/base64.c'; else $(CYGPATH_W) '$(srcdir)/sbr/base64.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-base64.Tpo sbr/$(DEPDIR)/sbr_libmh_a-base64.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/base64.c' object='sbr/sbr_libmh_a-base64.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-base64.obj `if test -f 'sbr/base64.c'; then $(CYGPATH_W) 'sbr/base64.c'; else $(CYGPATH_W) '$(srcdir)/sbr/base64.c'; fi` sbr/sbr_libmh_a-brkstring.o: sbr/brkstring.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-brkstring.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-brkstring.Tpo -c -o sbr/sbr_libmh_a-brkstring.o `test -f 'sbr/brkstring.c' || echo '$(srcdir)/'`sbr/brkstring.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-brkstring.Tpo sbr/$(DEPDIR)/sbr_libmh_a-brkstring.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/brkstring.c' object='sbr/sbr_libmh_a-brkstring.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-brkstring.o `test -f 'sbr/brkstring.c' || echo '$(srcdir)/'`sbr/brkstring.c sbr/sbr_libmh_a-brkstring.obj: sbr/brkstring.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-brkstring.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-brkstring.Tpo -c -o sbr/sbr_libmh_a-brkstring.obj `if test -f 'sbr/brkstring.c'; then $(CYGPATH_W) 'sbr/brkstring.c'; else $(CYGPATH_W) '$(srcdir)/sbr/brkstring.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-brkstring.Tpo sbr/$(DEPDIR)/sbr_libmh_a-brkstring.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/brkstring.c' object='sbr/sbr_libmh_a-brkstring.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-brkstring.obj `if test -f 'sbr/brkstring.c'; then $(CYGPATH_W) 'sbr/brkstring.c'; else $(CYGPATH_W) '$(srcdir)/sbr/brkstring.c'; fi` sbr/sbr_libmh_a-charstring.o: sbr/charstring.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-charstring.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-charstring.Tpo -c -o sbr/sbr_libmh_a-charstring.o `test -f 'sbr/charstring.c' || echo '$(srcdir)/'`sbr/charstring.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-charstring.Tpo sbr/$(DEPDIR)/sbr_libmh_a-charstring.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/charstring.c' object='sbr/sbr_libmh_a-charstring.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-charstring.o `test -f 'sbr/charstring.c' || echo '$(srcdir)/'`sbr/charstring.c sbr/sbr_libmh_a-charstring.obj: sbr/charstring.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-charstring.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-charstring.Tpo -c -o sbr/sbr_libmh_a-charstring.obj `if test -f 'sbr/charstring.c'; then $(CYGPATH_W) 'sbr/charstring.c'; else $(CYGPATH_W) '$(srcdir)/sbr/charstring.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-charstring.Tpo sbr/$(DEPDIR)/sbr_libmh_a-charstring.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/charstring.c' object='sbr/sbr_libmh_a-charstring.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-charstring.obj `if test -f 'sbr/charstring.c'; then $(CYGPATH_W) 'sbr/charstring.c'; else $(CYGPATH_W) '$(srcdir)/sbr/charstring.c'; fi` sbr/sbr_libmh_a-check_charset.o: sbr/check_charset.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-check_charset.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-check_charset.Tpo -c -o sbr/sbr_libmh_a-check_charset.o `test -f 'sbr/check_charset.c' || echo '$(srcdir)/'`sbr/check_charset.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-check_charset.Tpo sbr/$(DEPDIR)/sbr_libmh_a-check_charset.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/check_charset.c' object='sbr/sbr_libmh_a-check_charset.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-check_charset.o `test -f 'sbr/check_charset.c' || echo '$(srcdir)/'`sbr/check_charset.c sbr/sbr_libmh_a-check_charset.obj: sbr/check_charset.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-check_charset.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-check_charset.Tpo -c -o sbr/sbr_libmh_a-check_charset.obj `if test -f 'sbr/check_charset.c'; then $(CYGPATH_W) 'sbr/check_charset.c'; else $(CYGPATH_W) '$(srcdir)/sbr/check_charset.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-check_charset.Tpo sbr/$(DEPDIR)/sbr_libmh_a-check_charset.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/check_charset.c' object='sbr/sbr_libmh_a-check_charset.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-check_charset.obj `if test -f 'sbr/check_charset.c'; then $(CYGPATH_W) 'sbr/check_charset.c'; else $(CYGPATH_W) '$(srcdir)/sbr/check_charset.c'; fi` sbr/sbr_libmh_a-client.o: sbr/client.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-client.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-client.Tpo -c -o sbr/sbr_libmh_a-client.o `test -f 'sbr/client.c' || echo '$(srcdir)/'`sbr/client.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-client.Tpo sbr/$(DEPDIR)/sbr_libmh_a-client.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/client.c' object='sbr/sbr_libmh_a-client.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-client.o `test -f 'sbr/client.c' || echo '$(srcdir)/'`sbr/client.c sbr/sbr_libmh_a-client.obj: sbr/client.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-client.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-client.Tpo -c -o sbr/sbr_libmh_a-client.obj `if test -f 'sbr/client.c'; then $(CYGPATH_W) 'sbr/client.c'; else $(CYGPATH_W) '$(srcdir)/sbr/client.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-client.Tpo sbr/$(DEPDIR)/sbr_libmh_a-client.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/client.c' object='sbr/sbr_libmh_a-client.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-client.obj `if test -f 'sbr/client.c'; then $(CYGPATH_W) 'sbr/client.c'; else $(CYGPATH_W) '$(srcdir)/sbr/client.c'; fi` sbr/sbr_libmh_a-closefds.o: sbr/closefds.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-closefds.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-closefds.Tpo -c -o sbr/sbr_libmh_a-closefds.o `test -f 'sbr/closefds.c' || echo '$(srcdir)/'`sbr/closefds.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-closefds.Tpo sbr/$(DEPDIR)/sbr_libmh_a-closefds.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/closefds.c' object='sbr/sbr_libmh_a-closefds.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-closefds.o `test -f 'sbr/closefds.c' || echo '$(srcdir)/'`sbr/closefds.c sbr/sbr_libmh_a-closefds.obj: sbr/closefds.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-closefds.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-closefds.Tpo -c -o sbr/sbr_libmh_a-closefds.obj `if test -f 'sbr/closefds.c'; then $(CYGPATH_W) 'sbr/closefds.c'; else $(CYGPATH_W) '$(srcdir)/sbr/closefds.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-closefds.Tpo sbr/$(DEPDIR)/sbr_libmh_a-closefds.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/closefds.c' object='sbr/sbr_libmh_a-closefds.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-closefds.obj `if test -f 'sbr/closefds.c'; then $(CYGPATH_W) 'sbr/closefds.c'; else $(CYGPATH_W) '$(srcdir)/sbr/closefds.c'; fi` sbr/sbr_libmh_a-concat.o: sbr/concat.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-concat.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-concat.Tpo -c -o sbr/sbr_libmh_a-concat.o `test -f 'sbr/concat.c' || echo '$(srcdir)/'`sbr/concat.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-concat.Tpo sbr/$(DEPDIR)/sbr_libmh_a-concat.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/concat.c' object='sbr/sbr_libmh_a-concat.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-concat.o `test -f 'sbr/concat.c' || echo '$(srcdir)/'`sbr/concat.c sbr/sbr_libmh_a-concat.obj: sbr/concat.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-concat.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-concat.Tpo -c -o sbr/sbr_libmh_a-concat.obj `if test -f 'sbr/concat.c'; then $(CYGPATH_W) 'sbr/concat.c'; else $(CYGPATH_W) '$(srcdir)/sbr/concat.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-concat.Tpo sbr/$(DEPDIR)/sbr_libmh_a-concat.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/concat.c' object='sbr/sbr_libmh_a-concat.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-concat.obj `if test -f 'sbr/concat.c'; then $(CYGPATH_W) 'sbr/concat.c'; else $(CYGPATH_W) '$(srcdir)/sbr/concat.c'; fi` sbr/sbr_libmh_a-context_del.o: sbr/context_del.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-context_del.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-context_del.Tpo -c -o sbr/sbr_libmh_a-context_del.o `test -f 'sbr/context_del.c' || echo '$(srcdir)/'`sbr/context_del.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-context_del.Tpo sbr/$(DEPDIR)/sbr_libmh_a-context_del.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/context_del.c' object='sbr/sbr_libmh_a-context_del.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-context_del.o `test -f 'sbr/context_del.c' || echo '$(srcdir)/'`sbr/context_del.c sbr/sbr_libmh_a-context_del.obj: sbr/context_del.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-context_del.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-context_del.Tpo -c -o sbr/sbr_libmh_a-context_del.obj `if test -f 'sbr/context_del.c'; then $(CYGPATH_W) 'sbr/context_del.c'; else $(CYGPATH_W) '$(srcdir)/sbr/context_del.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-context_del.Tpo sbr/$(DEPDIR)/sbr_libmh_a-context_del.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/context_del.c' object='sbr/sbr_libmh_a-context_del.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-context_del.obj `if test -f 'sbr/context_del.c'; then $(CYGPATH_W) 'sbr/context_del.c'; else $(CYGPATH_W) '$(srcdir)/sbr/context_del.c'; fi` sbr/sbr_libmh_a-context_find.o: sbr/context_find.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-context_find.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-context_find.Tpo -c -o sbr/sbr_libmh_a-context_find.o `test -f 'sbr/context_find.c' || echo '$(srcdir)/'`sbr/context_find.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-context_find.Tpo sbr/$(DEPDIR)/sbr_libmh_a-context_find.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/context_find.c' object='sbr/sbr_libmh_a-context_find.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-context_find.o `test -f 'sbr/context_find.c' || echo '$(srcdir)/'`sbr/context_find.c sbr/sbr_libmh_a-context_find.obj: sbr/context_find.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-context_find.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-context_find.Tpo -c -o sbr/sbr_libmh_a-context_find.obj `if test -f 'sbr/context_find.c'; then $(CYGPATH_W) 'sbr/context_find.c'; else $(CYGPATH_W) '$(srcdir)/sbr/context_find.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-context_find.Tpo sbr/$(DEPDIR)/sbr_libmh_a-context_find.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/context_find.c' object='sbr/sbr_libmh_a-context_find.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-context_find.obj `if test -f 'sbr/context_find.c'; then $(CYGPATH_W) 'sbr/context_find.c'; else $(CYGPATH_W) '$(srcdir)/sbr/context_find.c'; fi` sbr/sbr_libmh_a-context_foil.o: sbr/context_foil.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-context_foil.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-context_foil.Tpo -c -o sbr/sbr_libmh_a-context_foil.o `test -f 'sbr/context_foil.c' || echo '$(srcdir)/'`sbr/context_foil.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-context_foil.Tpo sbr/$(DEPDIR)/sbr_libmh_a-context_foil.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/context_foil.c' object='sbr/sbr_libmh_a-context_foil.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-context_foil.o `test -f 'sbr/context_foil.c' || echo '$(srcdir)/'`sbr/context_foil.c sbr/sbr_libmh_a-context_foil.obj: sbr/context_foil.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-context_foil.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-context_foil.Tpo -c -o sbr/sbr_libmh_a-context_foil.obj `if test -f 'sbr/context_foil.c'; then $(CYGPATH_W) 'sbr/context_foil.c'; else $(CYGPATH_W) '$(srcdir)/sbr/context_foil.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-context_foil.Tpo sbr/$(DEPDIR)/sbr_libmh_a-context_foil.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/context_foil.c' object='sbr/sbr_libmh_a-context_foil.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-context_foil.obj `if test -f 'sbr/context_foil.c'; then $(CYGPATH_W) 'sbr/context_foil.c'; else $(CYGPATH_W) '$(srcdir)/sbr/context_foil.c'; fi` sbr/sbr_libmh_a-context_read.o: sbr/context_read.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-context_read.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-context_read.Tpo -c -o sbr/sbr_libmh_a-context_read.o `test -f 'sbr/context_read.c' || echo '$(srcdir)/'`sbr/context_read.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-context_read.Tpo sbr/$(DEPDIR)/sbr_libmh_a-context_read.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/context_read.c' object='sbr/sbr_libmh_a-context_read.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-context_read.o `test -f 'sbr/context_read.c' || echo '$(srcdir)/'`sbr/context_read.c sbr/sbr_libmh_a-context_read.obj: sbr/context_read.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-context_read.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-context_read.Tpo -c -o sbr/sbr_libmh_a-context_read.obj `if test -f 'sbr/context_read.c'; then $(CYGPATH_W) 'sbr/context_read.c'; else $(CYGPATH_W) '$(srcdir)/sbr/context_read.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-context_read.Tpo sbr/$(DEPDIR)/sbr_libmh_a-context_read.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/context_read.c' object='sbr/sbr_libmh_a-context_read.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-context_read.obj `if test -f 'sbr/context_read.c'; then $(CYGPATH_W) 'sbr/context_read.c'; else $(CYGPATH_W) '$(srcdir)/sbr/context_read.c'; fi` sbr/sbr_libmh_a-context_replace.o: sbr/context_replace.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-context_replace.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-context_replace.Tpo -c -o sbr/sbr_libmh_a-context_replace.o `test -f 'sbr/context_replace.c' || echo '$(srcdir)/'`sbr/context_replace.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-context_replace.Tpo sbr/$(DEPDIR)/sbr_libmh_a-context_replace.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/context_replace.c' object='sbr/sbr_libmh_a-context_replace.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-context_replace.o `test -f 'sbr/context_replace.c' || echo '$(srcdir)/'`sbr/context_replace.c sbr/sbr_libmh_a-context_replace.obj: sbr/context_replace.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-context_replace.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-context_replace.Tpo -c -o sbr/sbr_libmh_a-context_replace.obj `if test -f 'sbr/context_replace.c'; then $(CYGPATH_W) 'sbr/context_replace.c'; else $(CYGPATH_W) '$(srcdir)/sbr/context_replace.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-context_replace.Tpo sbr/$(DEPDIR)/sbr_libmh_a-context_replace.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/context_replace.c' object='sbr/sbr_libmh_a-context_replace.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-context_replace.obj `if test -f 'sbr/context_replace.c'; then $(CYGPATH_W) 'sbr/context_replace.c'; else $(CYGPATH_W) '$(srcdir)/sbr/context_replace.c'; fi` sbr/sbr_libmh_a-context_save.o: sbr/context_save.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-context_save.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-context_save.Tpo -c -o sbr/sbr_libmh_a-context_save.o `test -f 'sbr/context_save.c' || echo '$(srcdir)/'`sbr/context_save.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-context_save.Tpo sbr/$(DEPDIR)/sbr_libmh_a-context_save.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/context_save.c' object='sbr/sbr_libmh_a-context_save.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-context_save.o `test -f 'sbr/context_save.c' || echo '$(srcdir)/'`sbr/context_save.c sbr/sbr_libmh_a-context_save.obj: sbr/context_save.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-context_save.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-context_save.Tpo -c -o sbr/sbr_libmh_a-context_save.obj `if test -f 'sbr/context_save.c'; then $(CYGPATH_W) 'sbr/context_save.c'; else $(CYGPATH_W) '$(srcdir)/sbr/context_save.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-context_save.Tpo sbr/$(DEPDIR)/sbr_libmh_a-context_save.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/context_save.c' object='sbr/sbr_libmh_a-context_save.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-context_save.obj `if test -f 'sbr/context_save.c'; then $(CYGPATH_W) 'sbr/context_save.c'; else $(CYGPATH_W) '$(srcdir)/sbr/context_save.c'; fi` sbr/sbr_libmh_a-copyip.o: sbr/copyip.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-copyip.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-copyip.Tpo -c -o sbr/sbr_libmh_a-copyip.o `test -f 'sbr/copyip.c' || echo '$(srcdir)/'`sbr/copyip.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-copyip.Tpo sbr/$(DEPDIR)/sbr_libmh_a-copyip.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/copyip.c' object='sbr/sbr_libmh_a-copyip.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-copyip.o `test -f 'sbr/copyip.c' || echo '$(srcdir)/'`sbr/copyip.c sbr/sbr_libmh_a-copyip.obj: sbr/copyip.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-copyip.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-copyip.Tpo -c -o sbr/sbr_libmh_a-copyip.obj `if test -f 'sbr/copyip.c'; then $(CYGPATH_W) 'sbr/copyip.c'; else $(CYGPATH_W) '$(srcdir)/sbr/copyip.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-copyip.Tpo sbr/$(DEPDIR)/sbr_libmh_a-copyip.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/copyip.c' object='sbr/sbr_libmh_a-copyip.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-copyip.obj `if test -f 'sbr/copyip.c'; then $(CYGPATH_W) 'sbr/copyip.c'; else $(CYGPATH_W) '$(srcdir)/sbr/copyip.c'; fi` sbr/sbr_libmh_a-cpydata.o: sbr/cpydata.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-cpydata.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-cpydata.Tpo -c -o sbr/sbr_libmh_a-cpydata.o `test -f 'sbr/cpydata.c' || echo '$(srcdir)/'`sbr/cpydata.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-cpydata.Tpo sbr/$(DEPDIR)/sbr_libmh_a-cpydata.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/cpydata.c' object='sbr/sbr_libmh_a-cpydata.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-cpydata.o `test -f 'sbr/cpydata.c' || echo '$(srcdir)/'`sbr/cpydata.c sbr/sbr_libmh_a-cpydata.obj: sbr/cpydata.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-cpydata.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-cpydata.Tpo -c -o sbr/sbr_libmh_a-cpydata.obj `if test -f 'sbr/cpydata.c'; then $(CYGPATH_W) 'sbr/cpydata.c'; else $(CYGPATH_W) '$(srcdir)/sbr/cpydata.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-cpydata.Tpo sbr/$(DEPDIR)/sbr_libmh_a-cpydata.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/cpydata.c' object='sbr/sbr_libmh_a-cpydata.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-cpydata.obj `if test -f 'sbr/cpydata.c'; then $(CYGPATH_W) 'sbr/cpydata.c'; else $(CYGPATH_W) '$(srcdir)/sbr/cpydata.c'; fi` sbr/sbr_libmh_a-cpydgst.o: sbr/cpydgst.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-cpydgst.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-cpydgst.Tpo -c -o sbr/sbr_libmh_a-cpydgst.o `test -f 'sbr/cpydgst.c' || echo '$(srcdir)/'`sbr/cpydgst.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-cpydgst.Tpo sbr/$(DEPDIR)/sbr_libmh_a-cpydgst.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/cpydgst.c' object='sbr/sbr_libmh_a-cpydgst.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-cpydgst.o `test -f 'sbr/cpydgst.c' || echo '$(srcdir)/'`sbr/cpydgst.c sbr/sbr_libmh_a-cpydgst.obj: sbr/cpydgst.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-cpydgst.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-cpydgst.Tpo -c -o sbr/sbr_libmh_a-cpydgst.obj `if test -f 'sbr/cpydgst.c'; then $(CYGPATH_W) 'sbr/cpydgst.c'; else $(CYGPATH_W) '$(srcdir)/sbr/cpydgst.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-cpydgst.Tpo sbr/$(DEPDIR)/sbr_libmh_a-cpydgst.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/cpydgst.c' object='sbr/sbr_libmh_a-cpydgst.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-cpydgst.obj `if test -f 'sbr/cpydgst.c'; then $(CYGPATH_W) 'sbr/cpydgst.c'; else $(CYGPATH_W) '$(srcdir)/sbr/cpydgst.c'; fi` sbr/sbr_libmh_a-crawl_folders.o: sbr/crawl_folders.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-crawl_folders.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-crawl_folders.Tpo -c -o sbr/sbr_libmh_a-crawl_folders.o `test -f 'sbr/crawl_folders.c' || echo '$(srcdir)/'`sbr/crawl_folders.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-crawl_folders.Tpo sbr/$(DEPDIR)/sbr_libmh_a-crawl_folders.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/crawl_folders.c' object='sbr/sbr_libmh_a-crawl_folders.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-crawl_folders.o `test -f 'sbr/crawl_folders.c' || echo '$(srcdir)/'`sbr/crawl_folders.c sbr/sbr_libmh_a-crawl_folders.obj: sbr/crawl_folders.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-crawl_folders.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-crawl_folders.Tpo -c -o sbr/sbr_libmh_a-crawl_folders.obj `if test -f 'sbr/crawl_folders.c'; then $(CYGPATH_W) 'sbr/crawl_folders.c'; else $(CYGPATH_W) '$(srcdir)/sbr/crawl_folders.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-crawl_folders.Tpo sbr/$(DEPDIR)/sbr_libmh_a-crawl_folders.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/crawl_folders.c' object='sbr/sbr_libmh_a-crawl_folders.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-crawl_folders.obj `if test -f 'sbr/crawl_folders.c'; then $(CYGPATH_W) 'sbr/crawl_folders.c'; else $(CYGPATH_W) '$(srcdir)/sbr/crawl_folders.c'; fi` sbr/sbr_libmh_a-credentials.o: sbr/credentials.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-credentials.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-credentials.Tpo -c -o sbr/sbr_libmh_a-credentials.o `test -f 'sbr/credentials.c' || echo '$(srcdir)/'`sbr/credentials.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-credentials.Tpo sbr/$(DEPDIR)/sbr_libmh_a-credentials.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/credentials.c' object='sbr/sbr_libmh_a-credentials.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-credentials.o `test -f 'sbr/credentials.c' || echo '$(srcdir)/'`sbr/credentials.c sbr/sbr_libmh_a-credentials.obj: sbr/credentials.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-credentials.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-credentials.Tpo -c -o sbr/sbr_libmh_a-credentials.obj `if test -f 'sbr/credentials.c'; then $(CYGPATH_W) 'sbr/credentials.c'; else $(CYGPATH_W) '$(srcdir)/sbr/credentials.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-credentials.Tpo sbr/$(DEPDIR)/sbr_libmh_a-credentials.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/credentials.c' object='sbr/sbr_libmh_a-credentials.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-credentials.obj `if test -f 'sbr/credentials.c'; then $(CYGPATH_W) 'sbr/credentials.c'; else $(CYGPATH_W) '$(srcdir)/sbr/credentials.c'; fi` sbr/sbr_libmh_a-ctype-checked.o: sbr/ctype-checked.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-ctype-checked.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-ctype-checked.Tpo -c -o sbr/sbr_libmh_a-ctype-checked.o `test -f 'sbr/ctype-checked.c' || echo '$(srcdir)/'`sbr/ctype-checked.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-ctype-checked.Tpo sbr/$(DEPDIR)/sbr_libmh_a-ctype-checked.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/ctype-checked.c' object='sbr/sbr_libmh_a-ctype-checked.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-ctype-checked.o `test -f 'sbr/ctype-checked.c' || echo '$(srcdir)/'`sbr/ctype-checked.c sbr/sbr_libmh_a-ctype-checked.obj: sbr/ctype-checked.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-ctype-checked.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-ctype-checked.Tpo -c -o sbr/sbr_libmh_a-ctype-checked.obj `if test -f 'sbr/ctype-checked.c'; then $(CYGPATH_W) 'sbr/ctype-checked.c'; else $(CYGPATH_W) '$(srcdir)/sbr/ctype-checked.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-ctype-checked.Tpo sbr/$(DEPDIR)/sbr_libmh_a-ctype-checked.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/ctype-checked.c' object='sbr/sbr_libmh_a-ctype-checked.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-ctype-checked.obj `if test -f 'sbr/ctype-checked.c'; then $(CYGPATH_W) 'sbr/ctype-checked.c'; else $(CYGPATH_W) '$(srcdir)/sbr/ctype-checked.c'; fi` sbr/sbr_libmh_a-datetime.o: sbr/datetime.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-datetime.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-datetime.Tpo -c -o sbr/sbr_libmh_a-datetime.o `test -f 'sbr/datetime.c' || echo '$(srcdir)/'`sbr/datetime.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-datetime.Tpo sbr/$(DEPDIR)/sbr_libmh_a-datetime.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/datetime.c' object='sbr/sbr_libmh_a-datetime.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-datetime.o `test -f 'sbr/datetime.c' || echo '$(srcdir)/'`sbr/datetime.c sbr/sbr_libmh_a-datetime.obj: sbr/datetime.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-datetime.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-datetime.Tpo -c -o sbr/sbr_libmh_a-datetime.obj `if test -f 'sbr/datetime.c'; then $(CYGPATH_W) 'sbr/datetime.c'; else $(CYGPATH_W) '$(srcdir)/sbr/datetime.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-datetime.Tpo sbr/$(DEPDIR)/sbr_libmh_a-datetime.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/datetime.c' object='sbr/sbr_libmh_a-datetime.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-datetime.obj `if test -f 'sbr/datetime.c'; then $(CYGPATH_W) 'sbr/datetime.c'; else $(CYGPATH_W) '$(srcdir)/sbr/datetime.c'; fi` sbr/sbr_libmh_a-discard.o: sbr/discard.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-discard.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-discard.Tpo -c -o sbr/sbr_libmh_a-discard.o `test -f 'sbr/discard.c' || echo '$(srcdir)/'`sbr/discard.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-discard.Tpo sbr/$(DEPDIR)/sbr_libmh_a-discard.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/discard.c' object='sbr/sbr_libmh_a-discard.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-discard.o `test -f 'sbr/discard.c' || echo '$(srcdir)/'`sbr/discard.c sbr/sbr_libmh_a-discard.obj: sbr/discard.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-discard.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-discard.Tpo -c -o sbr/sbr_libmh_a-discard.obj `if test -f 'sbr/discard.c'; then $(CYGPATH_W) 'sbr/discard.c'; else $(CYGPATH_W) '$(srcdir)/sbr/discard.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-discard.Tpo sbr/$(DEPDIR)/sbr_libmh_a-discard.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/discard.c' object='sbr/sbr_libmh_a-discard.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-discard.obj `if test -f 'sbr/discard.c'; then $(CYGPATH_W) 'sbr/discard.c'; else $(CYGPATH_W) '$(srcdir)/sbr/discard.c'; fi` sbr/sbr_libmh_a-done.o: sbr/done.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-done.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-done.Tpo -c -o sbr/sbr_libmh_a-done.o `test -f 'sbr/done.c' || echo '$(srcdir)/'`sbr/done.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-done.Tpo sbr/$(DEPDIR)/sbr_libmh_a-done.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/done.c' object='sbr/sbr_libmh_a-done.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-done.o `test -f 'sbr/done.c' || echo '$(srcdir)/'`sbr/done.c sbr/sbr_libmh_a-done.obj: sbr/done.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-done.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-done.Tpo -c -o sbr/sbr_libmh_a-done.obj `if test -f 'sbr/done.c'; then $(CYGPATH_W) 'sbr/done.c'; else $(CYGPATH_W) '$(srcdir)/sbr/done.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-done.Tpo sbr/$(DEPDIR)/sbr_libmh_a-done.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/done.c' object='sbr/sbr_libmh_a-done.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-done.obj `if test -f 'sbr/done.c'; then $(CYGPATH_W) 'sbr/done.c'; else $(CYGPATH_W) '$(srcdir)/sbr/done.c'; fi` sbr/sbr_libmh_a-dtime.o: sbr/dtime.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-dtime.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-dtime.Tpo -c -o sbr/sbr_libmh_a-dtime.o `test -f 'sbr/dtime.c' || echo '$(srcdir)/'`sbr/dtime.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-dtime.Tpo sbr/$(DEPDIR)/sbr_libmh_a-dtime.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/dtime.c' object='sbr/sbr_libmh_a-dtime.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-dtime.o `test -f 'sbr/dtime.c' || echo '$(srcdir)/'`sbr/dtime.c sbr/sbr_libmh_a-dtime.obj: sbr/dtime.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-dtime.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-dtime.Tpo -c -o sbr/sbr_libmh_a-dtime.obj `if test -f 'sbr/dtime.c'; then $(CYGPATH_W) 'sbr/dtime.c'; else $(CYGPATH_W) '$(srcdir)/sbr/dtime.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-dtime.Tpo sbr/$(DEPDIR)/sbr_libmh_a-dtime.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/dtime.c' object='sbr/sbr_libmh_a-dtime.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-dtime.obj `if test -f 'sbr/dtime.c'; then $(CYGPATH_W) 'sbr/dtime.c'; else $(CYGPATH_W) '$(srcdir)/sbr/dtime.c'; fi` sbr/sbr_libmh_a-dtimep.o: sbr/dtimep.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-dtimep.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-dtimep.Tpo -c -o sbr/sbr_libmh_a-dtimep.o `test -f 'sbr/dtimep.c' || echo '$(srcdir)/'`sbr/dtimep.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-dtimep.Tpo sbr/$(DEPDIR)/sbr_libmh_a-dtimep.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/dtimep.c' object='sbr/sbr_libmh_a-dtimep.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-dtimep.o `test -f 'sbr/dtimep.c' || echo '$(srcdir)/'`sbr/dtimep.c sbr/sbr_libmh_a-dtimep.obj: sbr/dtimep.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-dtimep.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-dtimep.Tpo -c -o sbr/sbr_libmh_a-dtimep.obj `if test -f 'sbr/dtimep.c'; then $(CYGPATH_W) 'sbr/dtimep.c'; else $(CYGPATH_W) '$(srcdir)/sbr/dtimep.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-dtimep.Tpo sbr/$(DEPDIR)/sbr_libmh_a-dtimep.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/dtimep.c' object='sbr/sbr_libmh_a-dtimep.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-dtimep.obj `if test -f 'sbr/dtimep.c'; then $(CYGPATH_W) 'sbr/dtimep.c'; else $(CYGPATH_W) '$(srcdir)/sbr/dtimep.c'; fi` sbr/sbr_libmh_a-encode_rfc2047.o: sbr/encode_rfc2047.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-encode_rfc2047.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-encode_rfc2047.Tpo -c -o sbr/sbr_libmh_a-encode_rfc2047.o `test -f 'sbr/encode_rfc2047.c' || echo '$(srcdir)/'`sbr/encode_rfc2047.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-encode_rfc2047.Tpo sbr/$(DEPDIR)/sbr_libmh_a-encode_rfc2047.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/encode_rfc2047.c' object='sbr/sbr_libmh_a-encode_rfc2047.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-encode_rfc2047.o `test -f 'sbr/encode_rfc2047.c' || echo '$(srcdir)/'`sbr/encode_rfc2047.c sbr/sbr_libmh_a-encode_rfc2047.obj: sbr/encode_rfc2047.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-encode_rfc2047.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-encode_rfc2047.Tpo -c -o sbr/sbr_libmh_a-encode_rfc2047.obj `if test -f 'sbr/encode_rfc2047.c'; then $(CYGPATH_W) 'sbr/encode_rfc2047.c'; else $(CYGPATH_W) '$(srcdir)/sbr/encode_rfc2047.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-encode_rfc2047.Tpo sbr/$(DEPDIR)/sbr_libmh_a-encode_rfc2047.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/encode_rfc2047.c' object='sbr/sbr_libmh_a-encode_rfc2047.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-encode_rfc2047.obj `if test -f 'sbr/encode_rfc2047.c'; then $(CYGPATH_W) 'sbr/encode_rfc2047.c'; else $(CYGPATH_W) '$(srcdir)/sbr/encode_rfc2047.c'; fi` sbr/sbr_libmh_a-error.o: sbr/error.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-error.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-error.Tpo -c -o sbr/sbr_libmh_a-error.o `test -f 'sbr/error.c' || echo '$(srcdir)/'`sbr/error.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-error.Tpo sbr/$(DEPDIR)/sbr_libmh_a-error.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/error.c' object='sbr/sbr_libmh_a-error.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-error.o `test -f 'sbr/error.c' || echo '$(srcdir)/'`sbr/error.c sbr/sbr_libmh_a-error.obj: sbr/error.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-error.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-error.Tpo -c -o sbr/sbr_libmh_a-error.obj `if test -f 'sbr/error.c'; then $(CYGPATH_W) 'sbr/error.c'; else $(CYGPATH_W) '$(srcdir)/sbr/error.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-error.Tpo sbr/$(DEPDIR)/sbr_libmh_a-error.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/error.c' object='sbr/sbr_libmh_a-error.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-error.obj `if test -f 'sbr/error.c'; then $(CYGPATH_W) 'sbr/error.c'; else $(CYGPATH_W) '$(srcdir)/sbr/error.c'; fi` sbr/sbr_libmh_a-escape_addresses.o: sbr/escape_addresses.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-escape_addresses.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-escape_addresses.Tpo -c -o sbr/sbr_libmh_a-escape_addresses.o `test -f 'sbr/escape_addresses.c' || echo '$(srcdir)/'`sbr/escape_addresses.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-escape_addresses.Tpo sbr/$(DEPDIR)/sbr_libmh_a-escape_addresses.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/escape_addresses.c' object='sbr/sbr_libmh_a-escape_addresses.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-escape_addresses.o `test -f 'sbr/escape_addresses.c' || echo '$(srcdir)/'`sbr/escape_addresses.c sbr/sbr_libmh_a-escape_addresses.obj: sbr/escape_addresses.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-escape_addresses.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-escape_addresses.Tpo -c -o sbr/sbr_libmh_a-escape_addresses.obj `if test -f 'sbr/escape_addresses.c'; then $(CYGPATH_W) 'sbr/escape_addresses.c'; else $(CYGPATH_W) '$(srcdir)/sbr/escape_addresses.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-escape_addresses.Tpo sbr/$(DEPDIR)/sbr_libmh_a-escape_addresses.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/escape_addresses.c' object='sbr/sbr_libmh_a-escape_addresses.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-escape_addresses.obj `if test -f 'sbr/escape_addresses.c'; then $(CYGPATH_W) 'sbr/escape_addresses.c'; else $(CYGPATH_W) '$(srcdir)/sbr/escape_addresses.c'; fi` sbr/sbr_libmh_a-ext_hook.o: sbr/ext_hook.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-ext_hook.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-ext_hook.Tpo -c -o sbr/sbr_libmh_a-ext_hook.o `test -f 'sbr/ext_hook.c' || echo '$(srcdir)/'`sbr/ext_hook.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-ext_hook.Tpo sbr/$(DEPDIR)/sbr_libmh_a-ext_hook.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/ext_hook.c' object='sbr/sbr_libmh_a-ext_hook.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-ext_hook.o `test -f 'sbr/ext_hook.c' || echo '$(srcdir)/'`sbr/ext_hook.c sbr/sbr_libmh_a-ext_hook.obj: sbr/ext_hook.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-ext_hook.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-ext_hook.Tpo -c -o sbr/sbr_libmh_a-ext_hook.obj `if test -f 'sbr/ext_hook.c'; then $(CYGPATH_W) 'sbr/ext_hook.c'; else $(CYGPATH_W) '$(srcdir)/sbr/ext_hook.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-ext_hook.Tpo sbr/$(DEPDIR)/sbr_libmh_a-ext_hook.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/ext_hook.c' object='sbr/sbr_libmh_a-ext_hook.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-ext_hook.obj `if test -f 'sbr/ext_hook.c'; then $(CYGPATH_W) 'sbr/ext_hook.c'; else $(CYGPATH_W) '$(srcdir)/sbr/ext_hook.c'; fi` sbr/sbr_libmh_a-fdcompare.o: sbr/fdcompare.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-fdcompare.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-fdcompare.Tpo -c -o sbr/sbr_libmh_a-fdcompare.o `test -f 'sbr/fdcompare.c' || echo '$(srcdir)/'`sbr/fdcompare.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-fdcompare.Tpo sbr/$(DEPDIR)/sbr_libmh_a-fdcompare.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/fdcompare.c' object='sbr/sbr_libmh_a-fdcompare.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-fdcompare.o `test -f 'sbr/fdcompare.c' || echo '$(srcdir)/'`sbr/fdcompare.c sbr/sbr_libmh_a-fdcompare.obj: sbr/fdcompare.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-fdcompare.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-fdcompare.Tpo -c -o sbr/sbr_libmh_a-fdcompare.obj `if test -f 'sbr/fdcompare.c'; then $(CYGPATH_W) 'sbr/fdcompare.c'; else $(CYGPATH_W) '$(srcdir)/sbr/fdcompare.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-fdcompare.Tpo sbr/$(DEPDIR)/sbr_libmh_a-fdcompare.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/fdcompare.c' object='sbr/sbr_libmh_a-fdcompare.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-fdcompare.obj `if test -f 'sbr/fdcompare.c'; then $(CYGPATH_W) 'sbr/fdcompare.c'; else $(CYGPATH_W) '$(srcdir)/sbr/fdcompare.c'; fi` sbr/sbr_libmh_a-fmt_addr.o: sbr/fmt_addr.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-fmt_addr.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-fmt_addr.Tpo -c -o sbr/sbr_libmh_a-fmt_addr.o `test -f 'sbr/fmt_addr.c' || echo '$(srcdir)/'`sbr/fmt_addr.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-fmt_addr.Tpo sbr/$(DEPDIR)/sbr_libmh_a-fmt_addr.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/fmt_addr.c' object='sbr/sbr_libmh_a-fmt_addr.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-fmt_addr.o `test -f 'sbr/fmt_addr.c' || echo '$(srcdir)/'`sbr/fmt_addr.c sbr/sbr_libmh_a-fmt_addr.obj: sbr/fmt_addr.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-fmt_addr.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-fmt_addr.Tpo -c -o sbr/sbr_libmh_a-fmt_addr.obj `if test -f 'sbr/fmt_addr.c'; then $(CYGPATH_W) 'sbr/fmt_addr.c'; else $(CYGPATH_W) '$(srcdir)/sbr/fmt_addr.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-fmt_addr.Tpo sbr/$(DEPDIR)/sbr_libmh_a-fmt_addr.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/fmt_addr.c' object='sbr/sbr_libmh_a-fmt_addr.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-fmt_addr.obj `if test -f 'sbr/fmt_addr.c'; then $(CYGPATH_W) 'sbr/fmt_addr.c'; else $(CYGPATH_W) '$(srcdir)/sbr/fmt_addr.c'; fi` sbr/sbr_libmh_a-fmt_compile.o: sbr/fmt_compile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-fmt_compile.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-fmt_compile.Tpo -c -o sbr/sbr_libmh_a-fmt_compile.o `test -f 'sbr/fmt_compile.c' || echo '$(srcdir)/'`sbr/fmt_compile.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-fmt_compile.Tpo sbr/$(DEPDIR)/sbr_libmh_a-fmt_compile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/fmt_compile.c' object='sbr/sbr_libmh_a-fmt_compile.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-fmt_compile.o `test -f 'sbr/fmt_compile.c' || echo '$(srcdir)/'`sbr/fmt_compile.c sbr/sbr_libmh_a-fmt_compile.obj: sbr/fmt_compile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-fmt_compile.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-fmt_compile.Tpo -c -o sbr/sbr_libmh_a-fmt_compile.obj `if test -f 'sbr/fmt_compile.c'; then $(CYGPATH_W) 'sbr/fmt_compile.c'; else $(CYGPATH_W) '$(srcdir)/sbr/fmt_compile.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-fmt_compile.Tpo sbr/$(DEPDIR)/sbr_libmh_a-fmt_compile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/fmt_compile.c' object='sbr/sbr_libmh_a-fmt_compile.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-fmt_compile.obj `if test -f 'sbr/fmt_compile.c'; then $(CYGPATH_W) 'sbr/fmt_compile.c'; else $(CYGPATH_W) '$(srcdir)/sbr/fmt_compile.c'; fi` sbr/sbr_libmh_a-fmt_new.o: sbr/fmt_new.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-fmt_new.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-fmt_new.Tpo -c -o sbr/sbr_libmh_a-fmt_new.o `test -f 'sbr/fmt_new.c' || echo '$(srcdir)/'`sbr/fmt_new.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-fmt_new.Tpo sbr/$(DEPDIR)/sbr_libmh_a-fmt_new.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/fmt_new.c' object='sbr/sbr_libmh_a-fmt_new.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-fmt_new.o `test -f 'sbr/fmt_new.c' || echo '$(srcdir)/'`sbr/fmt_new.c sbr/sbr_libmh_a-fmt_new.obj: sbr/fmt_new.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-fmt_new.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-fmt_new.Tpo -c -o sbr/sbr_libmh_a-fmt_new.obj `if test -f 'sbr/fmt_new.c'; then $(CYGPATH_W) 'sbr/fmt_new.c'; else $(CYGPATH_W) '$(srcdir)/sbr/fmt_new.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-fmt_new.Tpo sbr/$(DEPDIR)/sbr_libmh_a-fmt_new.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/fmt_new.c' object='sbr/sbr_libmh_a-fmt_new.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-fmt_new.obj `if test -f 'sbr/fmt_new.c'; then $(CYGPATH_W) 'sbr/fmt_new.c'; else $(CYGPATH_W) '$(srcdir)/sbr/fmt_new.c'; fi` sbr/sbr_libmh_a-fmt_rfc2047.o: sbr/fmt_rfc2047.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-fmt_rfc2047.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-fmt_rfc2047.Tpo -c -o sbr/sbr_libmh_a-fmt_rfc2047.o `test -f 'sbr/fmt_rfc2047.c' || echo '$(srcdir)/'`sbr/fmt_rfc2047.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-fmt_rfc2047.Tpo sbr/$(DEPDIR)/sbr_libmh_a-fmt_rfc2047.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/fmt_rfc2047.c' object='sbr/sbr_libmh_a-fmt_rfc2047.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-fmt_rfc2047.o `test -f 'sbr/fmt_rfc2047.c' || echo '$(srcdir)/'`sbr/fmt_rfc2047.c sbr/sbr_libmh_a-fmt_rfc2047.obj: sbr/fmt_rfc2047.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-fmt_rfc2047.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-fmt_rfc2047.Tpo -c -o sbr/sbr_libmh_a-fmt_rfc2047.obj `if test -f 'sbr/fmt_rfc2047.c'; then $(CYGPATH_W) 'sbr/fmt_rfc2047.c'; else $(CYGPATH_W) '$(srcdir)/sbr/fmt_rfc2047.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-fmt_rfc2047.Tpo sbr/$(DEPDIR)/sbr_libmh_a-fmt_rfc2047.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/fmt_rfc2047.c' object='sbr/sbr_libmh_a-fmt_rfc2047.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-fmt_rfc2047.obj `if test -f 'sbr/fmt_rfc2047.c'; then $(CYGPATH_W) 'sbr/fmt_rfc2047.c'; else $(CYGPATH_W) '$(srcdir)/sbr/fmt_rfc2047.c'; fi` sbr/sbr_libmh_a-fmt_scan.o: sbr/fmt_scan.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-fmt_scan.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-fmt_scan.Tpo -c -o sbr/sbr_libmh_a-fmt_scan.o `test -f 'sbr/fmt_scan.c' || echo '$(srcdir)/'`sbr/fmt_scan.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-fmt_scan.Tpo sbr/$(DEPDIR)/sbr_libmh_a-fmt_scan.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/fmt_scan.c' object='sbr/sbr_libmh_a-fmt_scan.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-fmt_scan.o `test -f 'sbr/fmt_scan.c' || echo '$(srcdir)/'`sbr/fmt_scan.c sbr/sbr_libmh_a-fmt_scan.obj: sbr/fmt_scan.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-fmt_scan.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-fmt_scan.Tpo -c -o sbr/sbr_libmh_a-fmt_scan.obj `if test -f 'sbr/fmt_scan.c'; then $(CYGPATH_W) 'sbr/fmt_scan.c'; else $(CYGPATH_W) '$(srcdir)/sbr/fmt_scan.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-fmt_scan.Tpo sbr/$(DEPDIR)/sbr_libmh_a-fmt_scan.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/fmt_scan.c' object='sbr/sbr_libmh_a-fmt_scan.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-fmt_scan.obj `if test -f 'sbr/fmt_scan.c'; then $(CYGPATH_W) 'sbr/fmt_scan.c'; else $(CYGPATH_W) '$(srcdir)/sbr/fmt_scan.c'; fi` sbr/sbr_libmh_a-folder_addmsg.o: sbr/folder_addmsg.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-folder_addmsg.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-folder_addmsg.Tpo -c -o sbr/sbr_libmh_a-folder_addmsg.o `test -f 'sbr/folder_addmsg.c' || echo '$(srcdir)/'`sbr/folder_addmsg.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-folder_addmsg.Tpo sbr/$(DEPDIR)/sbr_libmh_a-folder_addmsg.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/folder_addmsg.c' object='sbr/sbr_libmh_a-folder_addmsg.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-folder_addmsg.o `test -f 'sbr/folder_addmsg.c' || echo '$(srcdir)/'`sbr/folder_addmsg.c sbr/sbr_libmh_a-folder_addmsg.obj: sbr/folder_addmsg.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-folder_addmsg.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-folder_addmsg.Tpo -c -o sbr/sbr_libmh_a-folder_addmsg.obj `if test -f 'sbr/folder_addmsg.c'; then $(CYGPATH_W) 'sbr/folder_addmsg.c'; else $(CYGPATH_W) '$(srcdir)/sbr/folder_addmsg.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-folder_addmsg.Tpo sbr/$(DEPDIR)/sbr_libmh_a-folder_addmsg.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/folder_addmsg.c' object='sbr/sbr_libmh_a-folder_addmsg.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-folder_addmsg.obj `if test -f 'sbr/folder_addmsg.c'; then $(CYGPATH_W) 'sbr/folder_addmsg.c'; else $(CYGPATH_W) '$(srcdir)/sbr/folder_addmsg.c'; fi` sbr/sbr_libmh_a-folder_delmsgs.o: sbr/folder_delmsgs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-folder_delmsgs.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-folder_delmsgs.Tpo -c -o sbr/sbr_libmh_a-folder_delmsgs.o `test -f 'sbr/folder_delmsgs.c' || echo '$(srcdir)/'`sbr/folder_delmsgs.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-folder_delmsgs.Tpo sbr/$(DEPDIR)/sbr_libmh_a-folder_delmsgs.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/folder_delmsgs.c' object='sbr/sbr_libmh_a-folder_delmsgs.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-folder_delmsgs.o `test -f 'sbr/folder_delmsgs.c' || echo '$(srcdir)/'`sbr/folder_delmsgs.c sbr/sbr_libmh_a-folder_delmsgs.obj: sbr/folder_delmsgs.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-folder_delmsgs.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-folder_delmsgs.Tpo -c -o sbr/sbr_libmh_a-folder_delmsgs.obj `if test -f 'sbr/folder_delmsgs.c'; then $(CYGPATH_W) 'sbr/folder_delmsgs.c'; else $(CYGPATH_W) '$(srcdir)/sbr/folder_delmsgs.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-folder_delmsgs.Tpo sbr/$(DEPDIR)/sbr_libmh_a-folder_delmsgs.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/folder_delmsgs.c' object='sbr/sbr_libmh_a-folder_delmsgs.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-folder_delmsgs.obj `if test -f 'sbr/folder_delmsgs.c'; then $(CYGPATH_W) 'sbr/folder_delmsgs.c'; else $(CYGPATH_W) '$(srcdir)/sbr/folder_delmsgs.c'; fi` sbr/sbr_libmh_a-folder_free.o: sbr/folder_free.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-folder_free.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-folder_free.Tpo -c -o sbr/sbr_libmh_a-folder_free.o `test -f 'sbr/folder_free.c' || echo '$(srcdir)/'`sbr/folder_free.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-folder_free.Tpo sbr/$(DEPDIR)/sbr_libmh_a-folder_free.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/folder_free.c' object='sbr/sbr_libmh_a-folder_free.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-folder_free.o `test -f 'sbr/folder_free.c' || echo '$(srcdir)/'`sbr/folder_free.c sbr/sbr_libmh_a-folder_free.obj: sbr/folder_free.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-folder_free.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-folder_free.Tpo -c -o sbr/sbr_libmh_a-folder_free.obj `if test -f 'sbr/folder_free.c'; then $(CYGPATH_W) 'sbr/folder_free.c'; else $(CYGPATH_W) '$(srcdir)/sbr/folder_free.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-folder_free.Tpo sbr/$(DEPDIR)/sbr_libmh_a-folder_free.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/folder_free.c' object='sbr/sbr_libmh_a-folder_free.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-folder_free.obj `if test -f 'sbr/folder_free.c'; then $(CYGPATH_W) 'sbr/folder_free.c'; else $(CYGPATH_W) '$(srcdir)/sbr/folder_free.c'; fi` sbr/sbr_libmh_a-folder_pack.o: sbr/folder_pack.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-folder_pack.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-folder_pack.Tpo -c -o sbr/sbr_libmh_a-folder_pack.o `test -f 'sbr/folder_pack.c' || echo '$(srcdir)/'`sbr/folder_pack.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-folder_pack.Tpo sbr/$(DEPDIR)/sbr_libmh_a-folder_pack.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/folder_pack.c' object='sbr/sbr_libmh_a-folder_pack.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-folder_pack.o `test -f 'sbr/folder_pack.c' || echo '$(srcdir)/'`sbr/folder_pack.c sbr/sbr_libmh_a-folder_pack.obj: sbr/folder_pack.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-folder_pack.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-folder_pack.Tpo -c -o sbr/sbr_libmh_a-folder_pack.obj `if test -f 'sbr/folder_pack.c'; then $(CYGPATH_W) 'sbr/folder_pack.c'; else $(CYGPATH_W) '$(srcdir)/sbr/folder_pack.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-folder_pack.Tpo sbr/$(DEPDIR)/sbr_libmh_a-folder_pack.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/folder_pack.c' object='sbr/sbr_libmh_a-folder_pack.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-folder_pack.obj `if test -f 'sbr/folder_pack.c'; then $(CYGPATH_W) 'sbr/folder_pack.c'; else $(CYGPATH_W) '$(srcdir)/sbr/folder_pack.c'; fi` sbr/sbr_libmh_a-folder_read.o: sbr/folder_read.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-folder_read.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-folder_read.Tpo -c -o sbr/sbr_libmh_a-folder_read.o `test -f 'sbr/folder_read.c' || echo '$(srcdir)/'`sbr/folder_read.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-folder_read.Tpo sbr/$(DEPDIR)/sbr_libmh_a-folder_read.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/folder_read.c' object='sbr/sbr_libmh_a-folder_read.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-folder_read.o `test -f 'sbr/folder_read.c' || echo '$(srcdir)/'`sbr/folder_read.c sbr/sbr_libmh_a-folder_read.obj: sbr/folder_read.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-folder_read.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-folder_read.Tpo -c -o sbr/sbr_libmh_a-folder_read.obj `if test -f 'sbr/folder_read.c'; then $(CYGPATH_W) 'sbr/folder_read.c'; else $(CYGPATH_W) '$(srcdir)/sbr/folder_read.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-folder_read.Tpo sbr/$(DEPDIR)/sbr_libmh_a-folder_read.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/folder_read.c' object='sbr/sbr_libmh_a-folder_read.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-folder_read.obj `if test -f 'sbr/folder_read.c'; then $(CYGPATH_W) 'sbr/folder_read.c'; else $(CYGPATH_W) '$(srcdir)/sbr/folder_read.c'; fi` sbr/sbr_libmh_a-folder_realloc.o: sbr/folder_realloc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-folder_realloc.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-folder_realloc.Tpo -c -o sbr/sbr_libmh_a-folder_realloc.o `test -f 'sbr/folder_realloc.c' || echo '$(srcdir)/'`sbr/folder_realloc.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-folder_realloc.Tpo sbr/$(DEPDIR)/sbr_libmh_a-folder_realloc.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/folder_realloc.c' object='sbr/sbr_libmh_a-folder_realloc.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-folder_realloc.o `test -f 'sbr/folder_realloc.c' || echo '$(srcdir)/'`sbr/folder_realloc.c sbr/sbr_libmh_a-folder_realloc.obj: sbr/folder_realloc.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-folder_realloc.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-folder_realloc.Tpo -c -o sbr/sbr_libmh_a-folder_realloc.obj `if test -f 'sbr/folder_realloc.c'; then $(CYGPATH_W) 'sbr/folder_realloc.c'; else $(CYGPATH_W) '$(srcdir)/sbr/folder_realloc.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-folder_realloc.Tpo sbr/$(DEPDIR)/sbr_libmh_a-folder_realloc.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/folder_realloc.c' object='sbr/sbr_libmh_a-folder_realloc.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-folder_realloc.obj `if test -f 'sbr/folder_realloc.c'; then $(CYGPATH_W) 'sbr/folder_realloc.c'; else $(CYGPATH_W) '$(srcdir)/sbr/folder_realloc.c'; fi` sbr/sbr_libmh_a-getarguments.o: sbr/getarguments.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-getarguments.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-getarguments.Tpo -c -o sbr/sbr_libmh_a-getarguments.o `test -f 'sbr/getarguments.c' || echo '$(srcdir)/'`sbr/getarguments.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-getarguments.Tpo sbr/$(DEPDIR)/sbr_libmh_a-getarguments.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/getarguments.c' object='sbr/sbr_libmh_a-getarguments.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-getarguments.o `test -f 'sbr/getarguments.c' || echo '$(srcdir)/'`sbr/getarguments.c sbr/sbr_libmh_a-getarguments.obj: sbr/getarguments.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-getarguments.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-getarguments.Tpo -c -o sbr/sbr_libmh_a-getarguments.obj `if test -f 'sbr/getarguments.c'; then $(CYGPATH_W) 'sbr/getarguments.c'; else $(CYGPATH_W) '$(srcdir)/sbr/getarguments.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-getarguments.Tpo sbr/$(DEPDIR)/sbr_libmh_a-getarguments.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/getarguments.c' object='sbr/sbr_libmh_a-getarguments.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-getarguments.obj `if test -f 'sbr/getarguments.c'; then $(CYGPATH_W) 'sbr/getarguments.c'; else $(CYGPATH_W) '$(srcdir)/sbr/getarguments.c'; fi` sbr/sbr_libmh_a-getcpy.o: sbr/getcpy.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-getcpy.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-getcpy.Tpo -c -o sbr/sbr_libmh_a-getcpy.o `test -f 'sbr/getcpy.c' || echo '$(srcdir)/'`sbr/getcpy.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-getcpy.Tpo sbr/$(DEPDIR)/sbr_libmh_a-getcpy.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/getcpy.c' object='sbr/sbr_libmh_a-getcpy.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-getcpy.o `test -f 'sbr/getcpy.c' || echo '$(srcdir)/'`sbr/getcpy.c sbr/sbr_libmh_a-getcpy.obj: sbr/getcpy.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-getcpy.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-getcpy.Tpo -c -o sbr/sbr_libmh_a-getcpy.obj `if test -f 'sbr/getcpy.c'; then $(CYGPATH_W) 'sbr/getcpy.c'; else $(CYGPATH_W) '$(srcdir)/sbr/getcpy.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-getcpy.Tpo sbr/$(DEPDIR)/sbr_libmh_a-getcpy.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/getcpy.c' object='sbr/sbr_libmh_a-getcpy.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-getcpy.obj `if test -f 'sbr/getcpy.c'; then $(CYGPATH_W) 'sbr/getcpy.c'; else $(CYGPATH_W) '$(srcdir)/sbr/getcpy.c'; fi` sbr/sbr_libmh_a-geteditor.o: sbr/geteditor.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-geteditor.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-geteditor.Tpo -c -o sbr/sbr_libmh_a-geteditor.o `test -f 'sbr/geteditor.c' || echo '$(srcdir)/'`sbr/geteditor.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-geteditor.Tpo sbr/$(DEPDIR)/sbr_libmh_a-geteditor.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/geteditor.c' object='sbr/sbr_libmh_a-geteditor.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-geteditor.o `test -f 'sbr/geteditor.c' || echo '$(srcdir)/'`sbr/geteditor.c sbr/sbr_libmh_a-geteditor.obj: sbr/geteditor.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-geteditor.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-geteditor.Tpo -c -o sbr/sbr_libmh_a-geteditor.obj `if test -f 'sbr/geteditor.c'; then $(CYGPATH_W) 'sbr/geteditor.c'; else $(CYGPATH_W) '$(srcdir)/sbr/geteditor.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-geteditor.Tpo sbr/$(DEPDIR)/sbr_libmh_a-geteditor.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/geteditor.c' object='sbr/sbr_libmh_a-geteditor.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-geteditor.obj `if test -f 'sbr/geteditor.c'; then $(CYGPATH_W) 'sbr/geteditor.c'; else $(CYGPATH_W) '$(srcdir)/sbr/geteditor.c'; fi` sbr/sbr_libmh_a-getfolder.o: sbr/getfolder.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-getfolder.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-getfolder.Tpo -c -o sbr/sbr_libmh_a-getfolder.o `test -f 'sbr/getfolder.c' || echo '$(srcdir)/'`sbr/getfolder.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-getfolder.Tpo sbr/$(DEPDIR)/sbr_libmh_a-getfolder.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/getfolder.c' object='sbr/sbr_libmh_a-getfolder.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-getfolder.o `test -f 'sbr/getfolder.c' || echo '$(srcdir)/'`sbr/getfolder.c sbr/sbr_libmh_a-getfolder.obj: sbr/getfolder.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-getfolder.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-getfolder.Tpo -c -o sbr/sbr_libmh_a-getfolder.obj `if test -f 'sbr/getfolder.c'; then $(CYGPATH_W) 'sbr/getfolder.c'; else $(CYGPATH_W) '$(srcdir)/sbr/getfolder.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-getfolder.Tpo sbr/$(DEPDIR)/sbr_libmh_a-getfolder.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/getfolder.c' object='sbr/sbr_libmh_a-getfolder.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-getfolder.obj `if test -f 'sbr/getfolder.c'; then $(CYGPATH_W) 'sbr/getfolder.c'; else $(CYGPATH_W) '$(srcdir)/sbr/getfolder.c'; fi` sbr/sbr_libmh_a-getpass.o: sbr/getpass.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-getpass.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-getpass.Tpo -c -o sbr/sbr_libmh_a-getpass.o `test -f 'sbr/getpass.c' || echo '$(srcdir)/'`sbr/getpass.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-getpass.Tpo sbr/$(DEPDIR)/sbr_libmh_a-getpass.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/getpass.c' object='sbr/sbr_libmh_a-getpass.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-getpass.o `test -f 'sbr/getpass.c' || echo '$(srcdir)/'`sbr/getpass.c sbr/sbr_libmh_a-getpass.obj: sbr/getpass.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-getpass.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-getpass.Tpo -c -o sbr/sbr_libmh_a-getpass.obj `if test -f 'sbr/getpass.c'; then $(CYGPATH_W) 'sbr/getpass.c'; else $(CYGPATH_W) '$(srcdir)/sbr/getpass.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-getpass.Tpo sbr/$(DEPDIR)/sbr_libmh_a-getpass.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/getpass.c' object='sbr/sbr_libmh_a-getpass.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-getpass.obj `if test -f 'sbr/getpass.c'; then $(CYGPATH_W) 'sbr/getpass.c'; else $(CYGPATH_W) '$(srcdir)/sbr/getpass.c'; fi` sbr/sbr_libmh_a-icalendar.o: sbr/icalendar.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-icalendar.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-icalendar.Tpo -c -o sbr/sbr_libmh_a-icalendar.o `test -f 'sbr/icalendar.c' || echo '$(srcdir)/'`sbr/icalendar.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-icalendar.Tpo sbr/$(DEPDIR)/sbr_libmh_a-icalendar.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/icalendar.c' object='sbr/sbr_libmh_a-icalendar.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-icalendar.o `test -f 'sbr/icalendar.c' || echo '$(srcdir)/'`sbr/icalendar.c sbr/sbr_libmh_a-icalendar.obj: sbr/icalendar.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-icalendar.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-icalendar.Tpo -c -o sbr/sbr_libmh_a-icalendar.obj `if test -f 'sbr/icalendar.c'; then $(CYGPATH_W) 'sbr/icalendar.c'; else $(CYGPATH_W) '$(srcdir)/sbr/icalendar.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-icalendar.Tpo sbr/$(DEPDIR)/sbr_libmh_a-icalendar.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/icalendar.c' object='sbr/sbr_libmh_a-icalendar.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-icalendar.obj `if test -f 'sbr/icalendar.c'; then $(CYGPATH_W) 'sbr/icalendar.c'; else $(CYGPATH_W) '$(srcdir)/sbr/icalendar.c'; fi` sbr/sbr_libmh_a-icalparse.o: sbr/icalparse.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-icalparse.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-icalparse.Tpo -c -o sbr/sbr_libmh_a-icalparse.o `test -f 'sbr/icalparse.c' || echo '$(srcdir)/'`sbr/icalparse.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-icalparse.Tpo sbr/$(DEPDIR)/sbr_libmh_a-icalparse.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/icalparse.c' object='sbr/sbr_libmh_a-icalparse.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-icalparse.o `test -f 'sbr/icalparse.c' || echo '$(srcdir)/'`sbr/icalparse.c sbr/sbr_libmh_a-icalparse.obj: sbr/icalparse.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-icalparse.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-icalparse.Tpo -c -o sbr/sbr_libmh_a-icalparse.obj `if test -f 'sbr/icalparse.c'; then $(CYGPATH_W) 'sbr/icalparse.c'; else $(CYGPATH_W) '$(srcdir)/sbr/icalparse.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-icalparse.Tpo sbr/$(DEPDIR)/sbr_libmh_a-icalparse.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/icalparse.c' object='sbr/sbr_libmh_a-icalparse.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-icalparse.obj `if test -f 'sbr/icalparse.c'; then $(CYGPATH_W) 'sbr/icalparse.c'; else $(CYGPATH_W) '$(srcdir)/sbr/icalparse.c'; fi` sbr/sbr_libmh_a-lock_file.o: sbr/lock_file.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-lock_file.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-lock_file.Tpo -c -o sbr/sbr_libmh_a-lock_file.o `test -f 'sbr/lock_file.c' || echo '$(srcdir)/'`sbr/lock_file.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-lock_file.Tpo sbr/$(DEPDIR)/sbr_libmh_a-lock_file.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/lock_file.c' object='sbr/sbr_libmh_a-lock_file.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-lock_file.o `test -f 'sbr/lock_file.c' || echo '$(srcdir)/'`sbr/lock_file.c sbr/sbr_libmh_a-lock_file.obj: sbr/lock_file.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-lock_file.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-lock_file.Tpo -c -o sbr/sbr_libmh_a-lock_file.obj `if test -f 'sbr/lock_file.c'; then $(CYGPATH_W) 'sbr/lock_file.c'; else $(CYGPATH_W) '$(srcdir)/sbr/lock_file.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-lock_file.Tpo sbr/$(DEPDIR)/sbr_libmh_a-lock_file.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/lock_file.c' object='sbr/sbr_libmh_a-lock_file.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-lock_file.obj `if test -f 'sbr/lock_file.c'; then $(CYGPATH_W) 'sbr/lock_file.c'; else $(CYGPATH_W) '$(srcdir)/sbr/lock_file.c'; fi` sbr/sbr_libmh_a-m_atoi.o: sbr/m_atoi.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-m_atoi.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-m_atoi.Tpo -c -o sbr/sbr_libmh_a-m_atoi.o `test -f 'sbr/m_atoi.c' || echo '$(srcdir)/'`sbr/m_atoi.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-m_atoi.Tpo sbr/$(DEPDIR)/sbr_libmh_a-m_atoi.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/m_atoi.c' object='sbr/sbr_libmh_a-m_atoi.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-m_atoi.o `test -f 'sbr/m_atoi.c' || echo '$(srcdir)/'`sbr/m_atoi.c sbr/sbr_libmh_a-m_atoi.obj: sbr/m_atoi.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-m_atoi.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-m_atoi.Tpo -c -o sbr/sbr_libmh_a-m_atoi.obj `if test -f 'sbr/m_atoi.c'; then $(CYGPATH_W) 'sbr/m_atoi.c'; else $(CYGPATH_W) '$(srcdir)/sbr/m_atoi.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-m_atoi.Tpo sbr/$(DEPDIR)/sbr_libmh_a-m_atoi.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/m_atoi.c' object='sbr/sbr_libmh_a-m_atoi.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-m_atoi.obj `if test -f 'sbr/m_atoi.c'; then $(CYGPATH_W) 'sbr/m_atoi.c'; else $(CYGPATH_W) '$(srcdir)/sbr/m_atoi.c'; fi` sbr/sbr_libmh_a-m_backup.o: sbr/m_backup.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-m_backup.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-m_backup.Tpo -c -o sbr/sbr_libmh_a-m_backup.o `test -f 'sbr/m_backup.c' || echo '$(srcdir)/'`sbr/m_backup.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-m_backup.Tpo sbr/$(DEPDIR)/sbr_libmh_a-m_backup.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/m_backup.c' object='sbr/sbr_libmh_a-m_backup.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-m_backup.o `test -f 'sbr/m_backup.c' || echo '$(srcdir)/'`sbr/m_backup.c sbr/sbr_libmh_a-m_backup.obj: sbr/m_backup.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-m_backup.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-m_backup.Tpo -c -o sbr/sbr_libmh_a-m_backup.obj `if test -f 'sbr/m_backup.c'; then $(CYGPATH_W) 'sbr/m_backup.c'; else $(CYGPATH_W) '$(srcdir)/sbr/m_backup.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-m_backup.Tpo sbr/$(DEPDIR)/sbr_libmh_a-m_backup.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/m_backup.c' object='sbr/sbr_libmh_a-m_backup.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-m_backup.obj `if test -f 'sbr/m_backup.c'; then $(CYGPATH_W) 'sbr/m_backup.c'; else $(CYGPATH_W) '$(srcdir)/sbr/m_backup.c'; fi` sbr/sbr_libmh_a-m_convert.o: sbr/m_convert.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-m_convert.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-m_convert.Tpo -c -o sbr/sbr_libmh_a-m_convert.o `test -f 'sbr/m_convert.c' || echo '$(srcdir)/'`sbr/m_convert.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-m_convert.Tpo sbr/$(DEPDIR)/sbr_libmh_a-m_convert.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/m_convert.c' object='sbr/sbr_libmh_a-m_convert.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-m_convert.o `test -f 'sbr/m_convert.c' || echo '$(srcdir)/'`sbr/m_convert.c sbr/sbr_libmh_a-m_convert.obj: sbr/m_convert.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-m_convert.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-m_convert.Tpo -c -o sbr/sbr_libmh_a-m_convert.obj `if test -f 'sbr/m_convert.c'; then $(CYGPATH_W) 'sbr/m_convert.c'; else $(CYGPATH_W) '$(srcdir)/sbr/m_convert.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-m_convert.Tpo sbr/$(DEPDIR)/sbr_libmh_a-m_convert.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/m_convert.c' object='sbr/sbr_libmh_a-m_convert.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-m_convert.obj `if test -f 'sbr/m_convert.c'; then $(CYGPATH_W) 'sbr/m_convert.c'; else $(CYGPATH_W) '$(srcdir)/sbr/m_convert.c'; fi` sbr/sbr_libmh_a-m_draft.o: sbr/m_draft.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-m_draft.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-m_draft.Tpo -c -o sbr/sbr_libmh_a-m_draft.o `test -f 'sbr/m_draft.c' || echo '$(srcdir)/'`sbr/m_draft.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-m_draft.Tpo sbr/$(DEPDIR)/sbr_libmh_a-m_draft.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/m_draft.c' object='sbr/sbr_libmh_a-m_draft.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-m_draft.o `test -f 'sbr/m_draft.c' || echo '$(srcdir)/'`sbr/m_draft.c sbr/sbr_libmh_a-m_draft.obj: sbr/m_draft.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-m_draft.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-m_draft.Tpo -c -o sbr/sbr_libmh_a-m_draft.obj `if test -f 'sbr/m_draft.c'; then $(CYGPATH_W) 'sbr/m_draft.c'; else $(CYGPATH_W) '$(srcdir)/sbr/m_draft.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-m_draft.Tpo sbr/$(DEPDIR)/sbr_libmh_a-m_draft.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/m_draft.c' object='sbr/sbr_libmh_a-m_draft.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-m_draft.obj `if test -f 'sbr/m_draft.c'; then $(CYGPATH_W) 'sbr/m_draft.c'; else $(CYGPATH_W) '$(srcdir)/sbr/m_draft.c'; fi` sbr/sbr_libmh_a-m_getfld.o: sbr/m_getfld.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-m_getfld.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-m_getfld.Tpo -c -o sbr/sbr_libmh_a-m_getfld.o `test -f 'sbr/m_getfld.c' || echo '$(srcdir)/'`sbr/m_getfld.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-m_getfld.Tpo sbr/$(DEPDIR)/sbr_libmh_a-m_getfld.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/m_getfld.c' object='sbr/sbr_libmh_a-m_getfld.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-m_getfld.o `test -f 'sbr/m_getfld.c' || echo '$(srcdir)/'`sbr/m_getfld.c sbr/sbr_libmh_a-m_getfld.obj: sbr/m_getfld.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-m_getfld.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-m_getfld.Tpo -c -o sbr/sbr_libmh_a-m_getfld.obj `if test -f 'sbr/m_getfld.c'; then $(CYGPATH_W) 'sbr/m_getfld.c'; else $(CYGPATH_W) '$(srcdir)/sbr/m_getfld.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-m_getfld.Tpo sbr/$(DEPDIR)/sbr_libmh_a-m_getfld.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/m_getfld.c' object='sbr/sbr_libmh_a-m_getfld.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-m_getfld.obj `if test -f 'sbr/m_getfld.c'; then $(CYGPATH_W) 'sbr/m_getfld.c'; else $(CYGPATH_W) '$(srcdir)/sbr/m_getfld.c'; fi` sbr/sbr_libmh_a-m_gmprot.o: sbr/m_gmprot.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-m_gmprot.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-m_gmprot.Tpo -c -o sbr/sbr_libmh_a-m_gmprot.o `test -f 'sbr/m_gmprot.c' || echo '$(srcdir)/'`sbr/m_gmprot.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-m_gmprot.Tpo sbr/$(DEPDIR)/sbr_libmh_a-m_gmprot.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/m_gmprot.c' object='sbr/sbr_libmh_a-m_gmprot.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-m_gmprot.o `test -f 'sbr/m_gmprot.c' || echo '$(srcdir)/'`sbr/m_gmprot.c sbr/sbr_libmh_a-m_gmprot.obj: sbr/m_gmprot.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-m_gmprot.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-m_gmprot.Tpo -c -o sbr/sbr_libmh_a-m_gmprot.obj `if test -f 'sbr/m_gmprot.c'; then $(CYGPATH_W) 'sbr/m_gmprot.c'; else $(CYGPATH_W) '$(srcdir)/sbr/m_gmprot.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-m_gmprot.Tpo sbr/$(DEPDIR)/sbr_libmh_a-m_gmprot.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/m_gmprot.c' object='sbr/sbr_libmh_a-m_gmprot.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-m_gmprot.obj `if test -f 'sbr/m_gmprot.c'; then $(CYGPATH_W) 'sbr/m_gmprot.c'; else $(CYGPATH_W) '$(srcdir)/sbr/m_gmprot.c'; fi` sbr/sbr_libmh_a-m_maildir.o: sbr/m_maildir.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-m_maildir.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-m_maildir.Tpo -c -o sbr/sbr_libmh_a-m_maildir.o `test -f 'sbr/m_maildir.c' || echo '$(srcdir)/'`sbr/m_maildir.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-m_maildir.Tpo sbr/$(DEPDIR)/sbr_libmh_a-m_maildir.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/m_maildir.c' object='sbr/sbr_libmh_a-m_maildir.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-m_maildir.o `test -f 'sbr/m_maildir.c' || echo '$(srcdir)/'`sbr/m_maildir.c sbr/sbr_libmh_a-m_maildir.obj: sbr/m_maildir.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-m_maildir.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-m_maildir.Tpo -c -o sbr/sbr_libmh_a-m_maildir.obj `if test -f 'sbr/m_maildir.c'; then $(CYGPATH_W) 'sbr/m_maildir.c'; else $(CYGPATH_W) '$(srcdir)/sbr/m_maildir.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-m_maildir.Tpo sbr/$(DEPDIR)/sbr_libmh_a-m_maildir.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/m_maildir.c' object='sbr/sbr_libmh_a-m_maildir.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-m_maildir.obj `if test -f 'sbr/m_maildir.c'; then $(CYGPATH_W) 'sbr/m_maildir.c'; else $(CYGPATH_W) '$(srcdir)/sbr/m_maildir.c'; fi` sbr/sbr_libmh_a-m_mktemp.o: sbr/m_mktemp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-m_mktemp.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-m_mktemp.Tpo -c -o sbr/sbr_libmh_a-m_mktemp.o `test -f 'sbr/m_mktemp.c' || echo '$(srcdir)/'`sbr/m_mktemp.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-m_mktemp.Tpo sbr/$(DEPDIR)/sbr_libmh_a-m_mktemp.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/m_mktemp.c' object='sbr/sbr_libmh_a-m_mktemp.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-m_mktemp.o `test -f 'sbr/m_mktemp.c' || echo '$(srcdir)/'`sbr/m_mktemp.c sbr/sbr_libmh_a-m_mktemp.obj: sbr/m_mktemp.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-m_mktemp.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-m_mktemp.Tpo -c -o sbr/sbr_libmh_a-m_mktemp.obj `if test -f 'sbr/m_mktemp.c'; then $(CYGPATH_W) 'sbr/m_mktemp.c'; else $(CYGPATH_W) '$(srcdir)/sbr/m_mktemp.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-m_mktemp.Tpo sbr/$(DEPDIR)/sbr_libmh_a-m_mktemp.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/m_mktemp.c' object='sbr/sbr_libmh_a-m_mktemp.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-m_mktemp.obj `if test -f 'sbr/m_mktemp.c'; then $(CYGPATH_W) 'sbr/m_mktemp.c'; else $(CYGPATH_W) '$(srcdir)/sbr/m_mktemp.c'; fi` sbr/sbr_libmh_a-m_name.o: sbr/m_name.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-m_name.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-m_name.Tpo -c -o sbr/sbr_libmh_a-m_name.o `test -f 'sbr/m_name.c' || echo '$(srcdir)/'`sbr/m_name.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-m_name.Tpo sbr/$(DEPDIR)/sbr_libmh_a-m_name.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/m_name.c' object='sbr/sbr_libmh_a-m_name.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-m_name.o `test -f 'sbr/m_name.c' || echo '$(srcdir)/'`sbr/m_name.c sbr/sbr_libmh_a-m_name.obj: sbr/m_name.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-m_name.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-m_name.Tpo -c -o sbr/sbr_libmh_a-m_name.obj `if test -f 'sbr/m_name.c'; then $(CYGPATH_W) 'sbr/m_name.c'; else $(CYGPATH_W) '$(srcdir)/sbr/m_name.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-m_name.Tpo sbr/$(DEPDIR)/sbr_libmh_a-m_name.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/m_name.c' object='sbr/sbr_libmh_a-m_name.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-m_name.obj `if test -f 'sbr/m_name.c'; then $(CYGPATH_W) 'sbr/m_name.c'; else $(CYGPATH_W) '$(srcdir)/sbr/m_name.c'; fi` sbr/sbr_libmh_a-m_popen.o: sbr/m_popen.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-m_popen.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-m_popen.Tpo -c -o sbr/sbr_libmh_a-m_popen.o `test -f 'sbr/m_popen.c' || echo '$(srcdir)/'`sbr/m_popen.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-m_popen.Tpo sbr/$(DEPDIR)/sbr_libmh_a-m_popen.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/m_popen.c' object='sbr/sbr_libmh_a-m_popen.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-m_popen.o `test -f 'sbr/m_popen.c' || echo '$(srcdir)/'`sbr/m_popen.c sbr/sbr_libmh_a-m_popen.obj: sbr/m_popen.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-m_popen.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-m_popen.Tpo -c -o sbr/sbr_libmh_a-m_popen.obj `if test -f 'sbr/m_popen.c'; then $(CYGPATH_W) 'sbr/m_popen.c'; else $(CYGPATH_W) '$(srcdir)/sbr/m_popen.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-m_popen.Tpo sbr/$(DEPDIR)/sbr_libmh_a-m_popen.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/m_popen.c' object='sbr/sbr_libmh_a-m_popen.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-m_popen.obj `if test -f 'sbr/m_popen.c'; then $(CYGPATH_W) 'sbr/m_popen.c'; else $(CYGPATH_W) '$(srcdir)/sbr/m_popen.c'; fi` sbr/sbr_libmh_a-m_rand.o: sbr/m_rand.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-m_rand.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-m_rand.Tpo -c -o sbr/sbr_libmh_a-m_rand.o `test -f 'sbr/m_rand.c' || echo '$(srcdir)/'`sbr/m_rand.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-m_rand.Tpo sbr/$(DEPDIR)/sbr_libmh_a-m_rand.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/m_rand.c' object='sbr/sbr_libmh_a-m_rand.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-m_rand.o `test -f 'sbr/m_rand.c' || echo '$(srcdir)/'`sbr/m_rand.c sbr/sbr_libmh_a-m_rand.obj: sbr/m_rand.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-m_rand.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-m_rand.Tpo -c -o sbr/sbr_libmh_a-m_rand.obj `if test -f 'sbr/m_rand.c'; then $(CYGPATH_W) 'sbr/m_rand.c'; else $(CYGPATH_W) '$(srcdir)/sbr/m_rand.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-m_rand.Tpo sbr/$(DEPDIR)/sbr_libmh_a-m_rand.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/m_rand.c' object='sbr/sbr_libmh_a-m_rand.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-m_rand.obj `if test -f 'sbr/m_rand.c'; then $(CYGPATH_W) 'sbr/m_rand.c'; else $(CYGPATH_W) '$(srcdir)/sbr/m_rand.c'; fi` sbr/sbr_libmh_a-makedir.o: sbr/makedir.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-makedir.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-makedir.Tpo -c -o sbr/sbr_libmh_a-makedir.o `test -f 'sbr/makedir.c' || echo '$(srcdir)/'`sbr/makedir.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-makedir.Tpo sbr/$(DEPDIR)/sbr_libmh_a-makedir.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/makedir.c' object='sbr/sbr_libmh_a-makedir.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-makedir.o `test -f 'sbr/makedir.c' || echo '$(srcdir)/'`sbr/makedir.c sbr/sbr_libmh_a-makedir.obj: sbr/makedir.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-makedir.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-makedir.Tpo -c -o sbr/sbr_libmh_a-makedir.obj `if test -f 'sbr/makedir.c'; then $(CYGPATH_W) 'sbr/makedir.c'; else $(CYGPATH_W) '$(srcdir)/sbr/makedir.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-makedir.Tpo sbr/$(DEPDIR)/sbr_libmh_a-makedir.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/makedir.c' object='sbr/sbr_libmh_a-makedir.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-makedir.obj `if test -f 'sbr/makedir.c'; then $(CYGPATH_W) 'sbr/makedir.c'; else $(CYGPATH_W) '$(srcdir)/sbr/makedir.c'; fi` sbr/sbr_libmh_a-md5.o: sbr/md5.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-md5.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-md5.Tpo -c -o sbr/sbr_libmh_a-md5.o `test -f 'sbr/md5.c' || echo '$(srcdir)/'`sbr/md5.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-md5.Tpo sbr/$(DEPDIR)/sbr_libmh_a-md5.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/md5.c' object='sbr/sbr_libmh_a-md5.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-md5.o `test -f 'sbr/md5.c' || echo '$(srcdir)/'`sbr/md5.c sbr/sbr_libmh_a-md5.obj: sbr/md5.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-md5.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-md5.Tpo -c -o sbr/sbr_libmh_a-md5.obj `if test -f 'sbr/md5.c'; then $(CYGPATH_W) 'sbr/md5.c'; else $(CYGPATH_W) '$(srcdir)/sbr/md5.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-md5.Tpo sbr/$(DEPDIR)/sbr_libmh_a-md5.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/md5.c' object='sbr/sbr_libmh_a-md5.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-md5.obj `if test -f 'sbr/md5.c'; then $(CYGPATH_W) 'sbr/md5.c'; else $(CYGPATH_W) '$(srcdir)/sbr/md5.c'; fi` sbr/sbr_libmh_a-message_id.o: sbr/message_id.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-message_id.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-message_id.Tpo -c -o sbr/sbr_libmh_a-message_id.o `test -f 'sbr/message_id.c' || echo '$(srcdir)/'`sbr/message_id.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-message_id.Tpo sbr/$(DEPDIR)/sbr_libmh_a-message_id.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/message_id.c' object='sbr/sbr_libmh_a-message_id.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-message_id.o `test -f 'sbr/message_id.c' || echo '$(srcdir)/'`sbr/message_id.c sbr/sbr_libmh_a-message_id.obj: sbr/message_id.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-message_id.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-message_id.Tpo -c -o sbr/sbr_libmh_a-message_id.obj `if test -f 'sbr/message_id.c'; then $(CYGPATH_W) 'sbr/message_id.c'; else $(CYGPATH_W) '$(srcdir)/sbr/message_id.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-message_id.Tpo sbr/$(DEPDIR)/sbr_libmh_a-message_id.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/message_id.c' object='sbr/sbr_libmh_a-message_id.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-message_id.obj `if test -f 'sbr/message_id.c'; then $(CYGPATH_W) 'sbr/message_id.c'; else $(CYGPATH_W) '$(srcdir)/sbr/message_id.c'; fi` sbr/sbr_libmh_a-mf.o: sbr/mf.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-mf.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-mf.Tpo -c -o sbr/sbr_libmh_a-mf.o `test -f 'sbr/mf.c' || echo '$(srcdir)/'`sbr/mf.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-mf.Tpo sbr/$(DEPDIR)/sbr_libmh_a-mf.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/mf.c' object='sbr/sbr_libmh_a-mf.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-mf.o `test -f 'sbr/mf.c' || echo '$(srcdir)/'`sbr/mf.c sbr/sbr_libmh_a-mf.obj: sbr/mf.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-mf.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-mf.Tpo -c -o sbr/sbr_libmh_a-mf.obj `if test -f 'sbr/mf.c'; then $(CYGPATH_W) 'sbr/mf.c'; else $(CYGPATH_W) '$(srcdir)/sbr/mf.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-mf.Tpo sbr/$(DEPDIR)/sbr_libmh_a-mf.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/mf.c' object='sbr/sbr_libmh_a-mf.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-mf.obj `if test -f 'sbr/mf.c'; then $(CYGPATH_W) 'sbr/mf.c'; else $(CYGPATH_W) '$(srcdir)/sbr/mf.c'; fi` sbr/sbr_libmh_a-mime_type.o: sbr/mime_type.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-mime_type.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-mime_type.Tpo -c -o sbr/sbr_libmh_a-mime_type.o `test -f 'sbr/mime_type.c' || echo '$(srcdir)/'`sbr/mime_type.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-mime_type.Tpo sbr/$(DEPDIR)/sbr_libmh_a-mime_type.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/mime_type.c' object='sbr/sbr_libmh_a-mime_type.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-mime_type.o `test -f 'sbr/mime_type.c' || echo '$(srcdir)/'`sbr/mime_type.c sbr/sbr_libmh_a-mime_type.obj: sbr/mime_type.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-mime_type.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-mime_type.Tpo -c -o sbr/sbr_libmh_a-mime_type.obj `if test -f 'sbr/mime_type.c'; then $(CYGPATH_W) 'sbr/mime_type.c'; else $(CYGPATH_W) '$(srcdir)/sbr/mime_type.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-mime_type.Tpo sbr/$(DEPDIR)/sbr_libmh_a-mime_type.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/mime_type.c' object='sbr/sbr_libmh_a-mime_type.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-mime_type.obj `if test -f 'sbr/mime_type.c'; then $(CYGPATH_W) 'sbr/mime_type.c'; else $(CYGPATH_W) '$(srcdir)/sbr/mime_type.c'; fi` sbr/sbr_libmh_a-mts.o: sbr/mts.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-mts.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-mts.Tpo -c -o sbr/sbr_libmh_a-mts.o `test -f 'sbr/mts.c' || echo '$(srcdir)/'`sbr/mts.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-mts.Tpo sbr/$(DEPDIR)/sbr_libmh_a-mts.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/mts.c' object='sbr/sbr_libmh_a-mts.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-mts.o `test -f 'sbr/mts.c' || echo '$(srcdir)/'`sbr/mts.c sbr/sbr_libmh_a-mts.obj: sbr/mts.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-mts.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-mts.Tpo -c -o sbr/sbr_libmh_a-mts.obj `if test -f 'sbr/mts.c'; then $(CYGPATH_W) 'sbr/mts.c'; else $(CYGPATH_W) '$(srcdir)/sbr/mts.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-mts.Tpo sbr/$(DEPDIR)/sbr_libmh_a-mts.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/mts.c' object='sbr/sbr_libmh_a-mts.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-mts.obj `if test -f 'sbr/mts.c'; then $(CYGPATH_W) 'sbr/mts.c'; else $(CYGPATH_W) '$(srcdir)/sbr/mts.c'; fi` sbr/sbr_libmh_a-netsec.o: sbr/netsec.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-netsec.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-netsec.Tpo -c -o sbr/sbr_libmh_a-netsec.o `test -f 'sbr/netsec.c' || echo '$(srcdir)/'`sbr/netsec.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-netsec.Tpo sbr/$(DEPDIR)/sbr_libmh_a-netsec.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/netsec.c' object='sbr/sbr_libmh_a-netsec.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-netsec.o `test -f 'sbr/netsec.c' || echo '$(srcdir)/'`sbr/netsec.c sbr/sbr_libmh_a-netsec.obj: sbr/netsec.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-netsec.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-netsec.Tpo -c -o sbr/sbr_libmh_a-netsec.obj `if test -f 'sbr/netsec.c'; then $(CYGPATH_W) 'sbr/netsec.c'; else $(CYGPATH_W) '$(srcdir)/sbr/netsec.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-netsec.Tpo sbr/$(DEPDIR)/sbr_libmh_a-netsec.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/netsec.c' object='sbr/sbr_libmh_a-netsec.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-netsec.obj `if test -f 'sbr/netsec.c'; then $(CYGPATH_W) 'sbr/netsec.c'; else $(CYGPATH_W) '$(srcdir)/sbr/netsec.c'; fi` sbr/sbr_libmh_a-oauth.o: sbr/oauth.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-oauth.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-oauth.Tpo -c -o sbr/sbr_libmh_a-oauth.o `test -f 'sbr/oauth.c' || echo '$(srcdir)/'`sbr/oauth.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-oauth.Tpo sbr/$(DEPDIR)/sbr_libmh_a-oauth.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/oauth.c' object='sbr/sbr_libmh_a-oauth.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-oauth.o `test -f 'sbr/oauth.c' || echo '$(srcdir)/'`sbr/oauth.c sbr/sbr_libmh_a-oauth.obj: sbr/oauth.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-oauth.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-oauth.Tpo -c -o sbr/sbr_libmh_a-oauth.obj `if test -f 'sbr/oauth.c'; then $(CYGPATH_W) 'sbr/oauth.c'; else $(CYGPATH_W) '$(srcdir)/sbr/oauth.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-oauth.Tpo sbr/$(DEPDIR)/sbr_libmh_a-oauth.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/oauth.c' object='sbr/sbr_libmh_a-oauth.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-oauth.obj `if test -f 'sbr/oauth.c'; then $(CYGPATH_W) 'sbr/oauth.c'; else $(CYGPATH_W) '$(srcdir)/sbr/oauth.c'; fi` sbr/sbr_libmh_a-oauth_prof.o: sbr/oauth_prof.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-oauth_prof.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-oauth_prof.Tpo -c -o sbr/sbr_libmh_a-oauth_prof.o `test -f 'sbr/oauth_prof.c' || echo '$(srcdir)/'`sbr/oauth_prof.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-oauth_prof.Tpo sbr/$(DEPDIR)/sbr_libmh_a-oauth_prof.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/oauth_prof.c' object='sbr/sbr_libmh_a-oauth_prof.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-oauth_prof.o `test -f 'sbr/oauth_prof.c' || echo '$(srcdir)/'`sbr/oauth_prof.c sbr/sbr_libmh_a-oauth_prof.obj: sbr/oauth_prof.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-oauth_prof.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-oauth_prof.Tpo -c -o sbr/sbr_libmh_a-oauth_prof.obj `if test -f 'sbr/oauth_prof.c'; then $(CYGPATH_W) 'sbr/oauth_prof.c'; else $(CYGPATH_W) '$(srcdir)/sbr/oauth_prof.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-oauth_prof.Tpo sbr/$(DEPDIR)/sbr_libmh_a-oauth_prof.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/oauth_prof.c' object='sbr/sbr_libmh_a-oauth_prof.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-oauth_prof.obj `if test -f 'sbr/oauth_prof.c'; then $(CYGPATH_W) 'sbr/oauth_prof.c'; else $(CYGPATH_W) '$(srcdir)/sbr/oauth_prof.c'; fi` sbr/sbr_libmh_a-path.o: sbr/path.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-path.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-path.Tpo -c -o sbr/sbr_libmh_a-path.o `test -f 'sbr/path.c' || echo '$(srcdir)/'`sbr/path.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-path.Tpo sbr/$(DEPDIR)/sbr_libmh_a-path.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/path.c' object='sbr/sbr_libmh_a-path.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-path.o `test -f 'sbr/path.c' || echo '$(srcdir)/'`sbr/path.c sbr/sbr_libmh_a-path.obj: sbr/path.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-path.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-path.Tpo -c -o sbr/sbr_libmh_a-path.obj `if test -f 'sbr/path.c'; then $(CYGPATH_W) 'sbr/path.c'; else $(CYGPATH_W) '$(srcdir)/sbr/path.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-path.Tpo sbr/$(DEPDIR)/sbr_libmh_a-path.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/path.c' object='sbr/sbr_libmh_a-path.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-path.obj `if test -f 'sbr/path.c'; then $(CYGPATH_W) 'sbr/path.c'; else $(CYGPATH_W) '$(srcdir)/sbr/path.c'; fi` sbr/sbr_libmh_a-pidstatus.o: sbr/pidstatus.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-pidstatus.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-pidstatus.Tpo -c -o sbr/sbr_libmh_a-pidstatus.o `test -f 'sbr/pidstatus.c' || echo '$(srcdir)/'`sbr/pidstatus.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-pidstatus.Tpo sbr/$(DEPDIR)/sbr_libmh_a-pidstatus.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/pidstatus.c' object='sbr/sbr_libmh_a-pidstatus.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-pidstatus.o `test -f 'sbr/pidstatus.c' || echo '$(srcdir)/'`sbr/pidstatus.c sbr/sbr_libmh_a-pidstatus.obj: sbr/pidstatus.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-pidstatus.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-pidstatus.Tpo -c -o sbr/sbr_libmh_a-pidstatus.obj `if test -f 'sbr/pidstatus.c'; then $(CYGPATH_W) 'sbr/pidstatus.c'; else $(CYGPATH_W) '$(srcdir)/sbr/pidstatus.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-pidstatus.Tpo sbr/$(DEPDIR)/sbr_libmh_a-pidstatus.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/pidstatus.c' object='sbr/sbr_libmh_a-pidstatus.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-pidstatus.obj `if test -f 'sbr/pidstatus.c'; then $(CYGPATH_W) 'sbr/pidstatus.c'; else $(CYGPATH_W) '$(srcdir)/sbr/pidstatus.c'; fi` sbr/sbr_libmh_a-pidwait.o: sbr/pidwait.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-pidwait.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-pidwait.Tpo -c -o sbr/sbr_libmh_a-pidwait.o `test -f 'sbr/pidwait.c' || echo '$(srcdir)/'`sbr/pidwait.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-pidwait.Tpo sbr/$(DEPDIR)/sbr_libmh_a-pidwait.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/pidwait.c' object='sbr/sbr_libmh_a-pidwait.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-pidwait.o `test -f 'sbr/pidwait.c' || echo '$(srcdir)/'`sbr/pidwait.c sbr/sbr_libmh_a-pidwait.obj: sbr/pidwait.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-pidwait.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-pidwait.Tpo -c -o sbr/sbr_libmh_a-pidwait.obj `if test -f 'sbr/pidwait.c'; then $(CYGPATH_W) 'sbr/pidwait.c'; else $(CYGPATH_W) '$(srcdir)/sbr/pidwait.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-pidwait.Tpo sbr/$(DEPDIR)/sbr_libmh_a-pidwait.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/pidwait.c' object='sbr/sbr_libmh_a-pidwait.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-pidwait.obj `if test -f 'sbr/pidwait.c'; then $(CYGPATH_W) 'sbr/pidwait.c'; else $(CYGPATH_W) '$(srcdir)/sbr/pidwait.c'; fi` sbr/sbr_libmh_a-print_help.o: sbr/print_help.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-print_help.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-print_help.Tpo -c -o sbr/sbr_libmh_a-print_help.o `test -f 'sbr/print_help.c' || echo '$(srcdir)/'`sbr/print_help.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-print_help.Tpo sbr/$(DEPDIR)/sbr_libmh_a-print_help.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/print_help.c' object='sbr/sbr_libmh_a-print_help.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-print_help.o `test -f 'sbr/print_help.c' || echo '$(srcdir)/'`sbr/print_help.c sbr/sbr_libmh_a-print_help.obj: sbr/print_help.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-print_help.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-print_help.Tpo -c -o sbr/sbr_libmh_a-print_help.obj `if test -f 'sbr/print_help.c'; then $(CYGPATH_W) 'sbr/print_help.c'; else $(CYGPATH_W) '$(srcdir)/sbr/print_help.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-print_help.Tpo sbr/$(DEPDIR)/sbr_libmh_a-print_help.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/print_help.c' object='sbr/sbr_libmh_a-print_help.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-print_help.obj `if test -f 'sbr/print_help.c'; then $(CYGPATH_W) 'sbr/print_help.c'; else $(CYGPATH_W) '$(srcdir)/sbr/print_help.c'; fi` sbr/sbr_libmh_a-print_sw.o: sbr/print_sw.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-print_sw.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-print_sw.Tpo -c -o sbr/sbr_libmh_a-print_sw.o `test -f 'sbr/print_sw.c' || echo '$(srcdir)/'`sbr/print_sw.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-print_sw.Tpo sbr/$(DEPDIR)/sbr_libmh_a-print_sw.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/print_sw.c' object='sbr/sbr_libmh_a-print_sw.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-print_sw.o `test -f 'sbr/print_sw.c' || echo '$(srcdir)/'`sbr/print_sw.c sbr/sbr_libmh_a-print_sw.obj: sbr/print_sw.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-print_sw.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-print_sw.Tpo -c -o sbr/sbr_libmh_a-print_sw.obj `if test -f 'sbr/print_sw.c'; then $(CYGPATH_W) 'sbr/print_sw.c'; else $(CYGPATH_W) '$(srcdir)/sbr/print_sw.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-print_sw.Tpo sbr/$(DEPDIR)/sbr_libmh_a-print_sw.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/print_sw.c' object='sbr/sbr_libmh_a-print_sw.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-print_sw.obj `if test -f 'sbr/print_sw.c'; then $(CYGPATH_W) 'sbr/print_sw.c'; else $(CYGPATH_W) '$(srcdir)/sbr/print_sw.c'; fi` sbr/sbr_libmh_a-print_version.o: sbr/print_version.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-print_version.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-print_version.Tpo -c -o sbr/sbr_libmh_a-print_version.o `test -f 'sbr/print_version.c' || echo '$(srcdir)/'`sbr/print_version.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-print_version.Tpo sbr/$(DEPDIR)/sbr_libmh_a-print_version.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/print_version.c' object='sbr/sbr_libmh_a-print_version.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-print_version.o `test -f 'sbr/print_version.c' || echo '$(srcdir)/'`sbr/print_version.c sbr/sbr_libmh_a-print_version.obj: sbr/print_version.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-print_version.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-print_version.Tpo -c -o sbr/sbr_libmh_a-print_version.obj `if test -f 'sbr/print_version.c'; then $(CYGPATH_W) 'sbr/print_version.c'; else $(CYGPATH_W) '$(srcdir)/sbr/print_version.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-print_version.Tpo sbr/$(DEPDIR)/sbr_libmh_a-print_version.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/print_version.c' object='sbr/sbr_libmh_a-print_version.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-print_version.obj `if test -f 'sbr/print_version.c'; then $(CYGPATH_W) 'sbr/print_version.c'; else $(CYGPATH_W) '$(srcdir)/sbr/print_version.c'; fi` sbr/sbr_libmh_a-push.o: sbr/push.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-push.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-push.Tpo -c -o sbr/sbr_libmh_a-push.o `test -f 'sbr/push.c' || echo '$(srcdir)/'`sbr/push.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-push.Tpo sbr/$(DEPDIR)/sbr_libmh_a-push.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/push.c' object='sbr/sbr_libmh_a-push.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-push.o `test -f 'sbr/push.c' || echo '$(srcdir)/'`sbr/push.c sbr/sbr_libmh_a-push.obj: sbr/push.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-push.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-push.Tpo -c -o sbr/sbr_libmh_a-push.obj `if test -f 'sbr/push.c'; then $(CYGPATH_W) 'sbr/push.c'; else $(CYGPATH_W) '$(srcdir)/sbr/push.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-push.Tpo sbr/$(DEPDIR)/sbr_libmh_a-push.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/push.c' object='sbr/sbr_libmh_a-push.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-push.obj `if test -f 'sbr/push.c'; then $(CYGPATH_W) 'sbr/push.c'; else $(CYGPATH_W) '$(srcdir)/sbr/push.c'; fi` sbr/sbr_libmh_a-r1bindex.o: sbr/r1bindex.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-r1bindex.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-r1bindex.Tpo -c -o sbr/sbr_libmh_a-r1bindex.o `test -f 'sbr/r1bindex.c' || echo '$(srcdir)/'`sbr/r1bindex.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-r1bindex.Tpo sbr/$(DEPDIR)/sbr_libmh_a-r1bindex.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/r1bindex.c' object='sbr/sbr_libmh_a-r1bindex.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-r1bindex.o `test -f 'sbr/r1bindex.c' || echo '$(srcdir)/'`sbr/r1bindex.c sbr/sbr_libmh_a-r1bindex.obj: sbr/r1bindex.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-r1bindex.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-r1bindex.Tpo -c -o sbr/sbr_libmh_a-r1bindex.obj `if test -f 'sbr/r1bindex.c'; then $(CYGPATH_W) 'sbr/r1bindex.c'; else $(CYGPATH_W) '$(srcdir)/sbr/r1bindex.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-r1bindex.Tpo sbr/$(DEPDIR)/sbr_libmh_a-r1bindex.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/r1bindex.c' object='sbr/sbr_libmh_a-r1bindex.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-r1bindex.obj `if test -f 'sbr/r1bindex.c'; then $(CYGPATH_W) 'sbr/r1bindex.c'; else $(CYGPATH_W) '$(srcdir)/sbr/r1bindex.c'; fi` sbr/sbr_libmh_a-read_line.o: sbr/read_line.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-read_line.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-read_line.Tpo -c -o sbr/sbr_libmh_a-read_line.o `test -f 'sbr/read_line.c' || echo '$(srcdir)/'`sbr/read_line.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-read_line.Tpo sbr/$(DEPDIR)/sbr_libmh_a-read_line.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/read_line.c' object='sbr/sbr_libmh_a-read_line.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-read_line.o `test -f 'sbr/read_line.c' || echo '$(srcdir)/'`sbr/read_line.c sbr/sbr_libmh_a-read_line.obj: sbr/read_line.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-read_line.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-read_line.Tpo -c -o sbr/sbr_libmh_a-read_line.obj `if test -f 'sbr/read_line.c'; then $(CYGPATH_W) 'sbr/read_line.c'; else $(CYGPATH_W) '$(srcdir)/sbr/read_line.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-read_line.Tpo sbr/$(DEPDIR)/sbr_libmh_a-read_line.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/read_line.c' object='sbr/sbr_libmh_a-read_line.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-read_line.obj `if test -f 'sbr/read_line.c'; then $(CYGPATH_W) 'sbr/read_line.c'; else $(CYGPATH_W) '$(srcdir)/sbr/read_line.c'; fi` sbr/sbr_libmh_a-read_switch.o: sbr/read_switch.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-read_switch.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-read_switch.Tpo -c -o sbr/sbr_libmh_a-read_switch.o `test -f 'sbr/read_switch.c' || echo '$(srcdir)/'`sbr/read_switch.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-read_switch.Tpo sbr/$(DEPDIR)/sbr_libmh_a-read_switch.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/read_switch.c' object='sbr/sbr_libmh_a-read_switch.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-read_switch.o `test -f 'sbr/read_switch.c' || echo '$(srcdir)/'`sbr/read_switch.c sbr/sbr_libmh_a-read_switch.obj: sbr/read_switch.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-read_switch.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-read_switch.Tpo -c -o sbr/sbr_libmh_a-read_switch.obj `if test -f 'sbr/read_switch.c'; then $(CYGPATH_W) 'sbr/read_switch.c'; else $(CYGPATH_W) '$(srcdir)/sbr/read_switch.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-read_switch.Tpo sbr/$(DEPDIR)/sbr_libmh_a-read_switch.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/read_switch.c' object='sbr/sbr_libmh_a-read_switch.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-read_switch.obj `if test -f 'sbr/read_switch.c'; then $(CYGPATH_W) 'sbr/read_switch.c'; else $(CYGPATH_W) '$(srcdir)/sbr/read_switch.c'; fi` sbr/sbr_libmh_a-read_switch_multiword.o: sbr/read_switch_multiword.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-read_switch_multiword.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-read_switch_multiword.Tpo -c -o sbr/sbr_libmh_a-read_switch_multiword.o `test -f 'sbr/read_switch_multiword.c' || echo '$(srcdir)/'`sbr/read_switch_multiword.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-read_switch_multiword.Tpo sbr/$(DEPDIR)/sbr_libmh_a-read_switch_multiword.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/read_switch_multiword.c' object='sbr/sbr_libmh_a-read_switch_multiword.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-read_switch_multiword.o `test -f 'sbr/read_switch_multiword.c' || echo '$(srcdir)/'`sbr/read_switch_multiword.c sbr/sbr_libmh_a-read_switch_multiword.obj: sbr/read_switch_multiword.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-read_switch_multiword.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-read_switch_multiword.Tpo -c -o sbr/sbr_libmh_a-read_switch_multiword.obj `if test -f 'sbr/read_switch_multiword.c'; then $(CYGPATH_W) 'sbr/read_switch_multiword.c'; else $(CYGPATH_W) '$(srcdir)/sbr/read_switch_multiword.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-read_switch_multiword.Tpo sbr/$(DEPDIR)/sbr_libmh_a-read_switch_multiword.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/read_switch_multiword.c' object='sbr/sbr_libmh_a-read_switch_multiword.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-read_switch_multiword.obj `if test -f 'sbr/read_switch_multiword.c'; then $(CYGPATH_W) 'sbr/read_switch_multiword.c'; else $(CYGPATH_W) '$(srcdir)/sbr/read_switch_multiword.c'; fi` sbr/sbr_libmh_a-read_switch_multiword_via_readline.o: sbr/read_switch_multiword_via_readline.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-read_switch_multiword_via_readline.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-read_switch_multiword_via_readline.Tpo -c -o sbr/sbr_libmh_a-read_switch_multiword_via_readline.o `test -f 'sbr/read_switch_multiword_via_readline.c' || echo '$(srcdir)/'`sbr/read_switch_multiword_via_readline.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-read_switch_multiword_via_readline.Tpo sbr/$(DEPDIR)/sbr_libmh_a-read_switch_multiword_via_readline.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/read_switch_multiword_via_readline.c' object='sbr/sbr_libmh_a-read_switch_multiword_via_readline.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-read_switch_multiword_via_readline.o `test -f 'sbr/read_switch_multiword_via_readline.c' || echo '$(srcdir)/'`sbr/read_switch_multiword_via_readline.c sbr/sbr_libmh_a-read_switch_multiword_via_readline.obj: sbr/read_switch_multiword_via_readline.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-read_switch_multiword_via_readline.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-read_switch_multiword_via_readline.Tpo -c -o sbr/sbr_libmh_a-read_switch_multiword_via_readline.obj `if test -f 'sbr/read_switch_multiword_via_readline.c'; then $(CYGPATH_W) 'sbr/read_switch_multiword_via_readline.c'; else $(CYGPATH_W) '$(srcdir)/sbr/read_switch_multiword_via_readline.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-read_switch_multiword_via_readline.Tpo sbr/$(DEPDIR)/sbr_libmh_a-read_switch_multiword_via_readline.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/read_switch_multiword_via_readline.c' object='sbr/sbr_libmh_a-read_switch_multiword_via_readline.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-read_switch_multiword_via_readline.obj `if test -f 'sbr/read_switch_multiword_via_readline.c'; then $(CYGPATH_W) 'sbr/read_switch_multiword_via_readline.c'; else $(CYGPATH_W) '$(srcdir)/sbr/read_switch_multiword_via_readline.c'; fi` sbr/sbr_libmh_a-read_yes_or_no_if_tty.o: sbr/read_yes_or_no_if_tty.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-read_yes_or_no_if_tty.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-read_yes_or_no_if_tty.Tpo -c -o sbr/sbr_libmh_a-read_yes_or_no_if_tty.o `test -f 'sbr/read_yes_or_no_if_tty.c' || echo '$(srcdir)/'`sbr/read_yes_or_no_if_tty.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-read_yes_or_no_if_tty.Tpo sbr/$(DEPDIR)/sbr_libmh_a-read_yes_or_no_if_tty.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/read_yes_or_no_if_tty.c' object='sbr/sbr_libmh_a-read_yes_or_no_if_tty.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-read_yes_or_no_if_tty.o `test -f 'sbr/read_yes_or_no_if_tty.c' || echo '$(srcdir)/'`sbr/read_yes_or_no_if_tty.c sbr/sbr_libmh_a-read_yes_or_no_if_tty.obj: sbr/read_yes_or_no_if_tty.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-read_yes_or_no_if_tty.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-read_yes_or_no_if_tty.Tpo -c -o sbr/sbr_libmh_a-read_yes_or_no_if_tty.obj `if test -f 'sbr/read_yes_or_no_if_tty.c'; then $(CYGPATH_W) 'sbr/read_yes_or_no_if_tty.c'; else $(CYGPATH_W) '$(srcdir)/sbr/read_yes_or_no_if_tty.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-read_yes_or_no_if_tty.Tpo sbr/$(DEPDIR)/sbr_libmh_a-read_yes_or_no_if_tty.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/read_yes_or_no_if_tty.c' object='sbr/sbr_libmh_a-read_yes_or_no_if_tty.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-read_yes_or_no_if_tty.obj `if test -f 'sbr/read_yes_or_no_if_tty.c'; then $(CYGPATH_W) 'sbr/read_yes_or_no_if_tty.c'; else $(CYGPATH_W) '$(srcdir)/sbr/read_yes_or_no_if_tty.c'; fi` sbr/sbr_libmh_a-readconfig.o: sbr/readconfig.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-readconfig.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-readconfig.Tpo -c -o sbr/sbr_libmh_a-readconfig.o `test -f 'sbr/readconfig.c' || echo '$(srcdir)/'`sbr/readconfig.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-readconfig.Tpo sbr/$(DEPDIR)/sbr_libmh_a-readconfig.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/readconfig.c' object='sbr/sbr_libmh_a-readconfig.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-readconfig.o `test -f 'sbr/readconfig.c' || echo '$(srcdir)/'`sbr/readconfig.c sbr/sbr_libmh_a-readconfig.obj: sbr/readconfig.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-readconfig.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-readconfig.Tpo -c -o sbr/sbr_libmh_a-readconfig.obj `if test -f 'sbr/readconfig.c'; then $(CYGPATH_W) 'sbr/readconfig.c'; else $(CYGPATH_W) '$(srcdir)/sbr/readconfig.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-readconfig.Tpo sbr/$(DEPDIR)/sbr_libmh_a-readconfig.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/readconfig.c' object='sbr/sbr_libmh_a-readconfig.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-readconfig.obj `if test -f 'sbr/readconfig.c'; then $(CYGPATH_W) 'sbr/readconfig.c'; else $(CYGPATH_W) '$(srcdir)/sbr/readconfig.c'; fi` sbr/sbr_libmh_a-refile.o: sbr/refile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-refile.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-refile.Tpo -c -o sbr/sbr_libmh_a-refile.o `test -f 'sbr/refile.c' || echo '$(srcdir)/'`sbr/refile.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-refile.Tpo sbr/$(DEPDIR)/sbr_libmh_a-refile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/refile.c' object='sbr/sbr_libmh_a-refile.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-refile.o `test -f 'sbr/refile.c' || echo '$(srcdir)/'`sbr/refile.c sbr/sbr_libmh_a-refile.obj: sbr/refile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-refile.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-refile.Tpo -c -o sbr/sbr_libmh_a-refile.obj `if test -f 'sbr/refile.c'; then $(CYGPATH_W) 'sbr/refile.c'; else $(CYGPATH_W) '$(srcdir)/sbr/refile.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-refile.Tpo sbr/$(DEPDIR)/sbr_libmh_a-refile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/refile.c' object='sbr/sbr_libmh_a-refile.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-refile.obj `if test -f 'sbr/refile.c'; then $(CYGPATH_W) 'sbr/refile.c'; else $(CYGPATH_W) '$(srcdir)/sbr/refile.c'; fi` sbr/sbr_libmh_a-remdir.o: sbr/remdir.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-remdir.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-remdir.Tpo -c -o sbr/sbr_libmh_a-remdir.o `test -f 'sbr/remdir.c' || echo '$(srcdir)/'`sbr/remdir.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-remdir.Tpo sbr/$(DEPDIR)/sbr_libmh_a-remdir.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/remdir.c' object='sbr/sbr_libmh_a-remdir.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-remdir.o `test -f 'sbr/remdir.c' || echo '$(srcdir)/'`sbr/remdir.c sbr/sbr_libmh_a-remdir.obj: sbr/remdir.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-remdir.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-remdir.Tpo -c -o sbr/sbr_libmh_a-remdir.obj `if test -f 'sbr/remdir.c'; then $(CYGPATH_W) 'sbr/remdir.c'; else $(CYGPATH_W) '$(srcdir)/sbr/remdir.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-remdir.Tpo sbr/$(DEPDIR)/sbr_libmh_a-remdir.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/remdir.c' object='sbr/sbr_libmh_a-remdir.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-remdir.obj `if test -f 'sbr/remdir.c'; then $(CYGPATH_W) 'sbr/remdir.c'; else $(CYGPATH_W) '$(srcdir)/sbr/remdir.c'; fi` sbr/sbr_libmh_a-ruserpass.o: sbr/ruserpass.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-ruserpass.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-ruserpass.Tpo -c -o sbr/sbr_libmh_a-ruserpass.o `test -f 'sbr/ruserpass.c' || echo '$(srcdir)/'`sbr/ruserpass.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-ruserpass.Tpo sbr/$(DEPDIR)/sbr_libmh_a-ruserpass.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/ruserpass.c' object='sbr/sbr_libmh_a-ruserpass.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-ruserpass.o `test -f 'sbr/ruserpass.c' || echo '$(srcdir)/'`sbr/ruserpass.c sbr/sbr_libmh_a-ruserpass.obj: sbr/ruserpass.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-ruserpass.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-ruserpass.Tpo -c -o sbr/sbr_libmh_a-ruserpass.obj `if test -f 'sbr/ruserpass.c'; then $(CYGPATH_W) 'sbr/ruserpass.c'; else $(CYGPATH_W) '$(srcdir)/sbr/ruserpass.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-ruserpass.Tpo sbr/$(DEPDIR)/sbr_libmh_a-ruserpass.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/ruserpass.c' object='sbr/sbr_libmh_a-ruserpass.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-ruserpass.obj `if test -f 'sbr/ruserpass.c'; then $(CYGPATH_W) 'sbr/ruserpass.c'; else $(CYGPATH_W) '$(srcdir)/sbr/ruserpass.c'; fi` sbr/sbr_libmh_a-seq_add.o: sbr/seq_add.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-seq_add.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-seq_add.Tpo -c -o sbr/sbr_libmh_a-seq_add.o `test -f 'sbr/seq_add.c' || echo '$(srcdir)/'`sbr/seq_add.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-seq_add.Tpo sbr/$(DEPDIR)/sbr_libmh_a-seq_add.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/seq_add.c' object='sbr/sbr_libmh_a-seq_add.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-seq_add.o `test -f 'sbr/seq_add.c' || echo '$(srcdir)/'`sbr/seq_add.c sbr/sbr_libmh_a-seq_add.obj: sbr/seq_add.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-seq_add.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-seq_add.Tpo -c -o sbr/sbr_libmh_a-seq_add.obj `if test -f 'sbr/seq_add.c'; then $(CYGPATH_W) 'sbr/seq_add.c'; else $(CYGPATH_W) '$(srcdir)/sbr/seq_add.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-seq_add.Tpo sbr/$(DEPDIR)/sbr_libmh_a-seq_add.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/seq_add.c' object='sbr/sbr_libmh_a-seq_add.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-seq_add.obj `if test -f 'sbr/seq_add.c'; then $(CYGPATH_W) 'sbr/seq_add.c'; else $(CYGPATH_W) '$(srcdir)/sbr/seq_add.c'; fi` sbr/sbr_libmh_a-seq_bits.o: sbr/seq_bits.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-seq_bits.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-seq_bits.Tpo -c -o sbr/sbr_libmh_a-seq_bits.o `test -f 'sbr/seq_bits.c' || echo '$(srcdir)/'`sbr/seq_bits.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-seq_bits.Tpo sbr/$(DEPDIR)/sbr_libmh_a-seq_bits.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/seq_bits.c' object='sbr/sbr_libmh_a-seq_bits.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-seq_bits.o `test -f 'sbr/seq_bits.c' || echo '$(srcdir)/'`sbr/seq_bits.c sbr/sbr_libmh_a-seq_bits.obj: sbr/seq_bits.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-seq_bits.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-seq_bits.Tpo -c -o sbr/sbr_libmh_a-seq_bits.obj `if test -f 'sbr/seq_bits.c'; then $(CYGPATH_W) 'sbr/seq_bits.c'; else $(CYGPATH_W) '$(srcdir)/sbr/seq_bits.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-seq_bits.Tpo sbr/$(DEPDIR)/sbr_libmh_a-seq_bits.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/seq_bits.c' object='sbr/sbr_libmh_a-seq_bits.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-seq_bits.obj `if test -f 'sbr/seq_bits.c'; then $(CYGPATH_W) 'sbr/seq_bits.c'; else $(CYGPATH_W) '$(srcdir)/sbr/seq_bits.c'; fi` sbr/sbr_libmh_a-seq_del.o: sbr/seq_del.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-seq_del.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-seq_del.Tpo -c -o sbr/sbr_libmh_a-seq_del.o `test -f 'sbr/seq_del.c' || echo '$(srcdir)/'`sbr/seq_del.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-seq_del.Tpo sbr/$(DEPDIR)/sbr_libmh_a-seq_del.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/seq_del.c' object='sbr/sbr_libmh_a-seq_del.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-seq_del.o `test -f 'sbr/seq_del.c' || echo '$(srcdir)/'`sbr/seq_del.c sbr/sbr_libmh_a-seq_del.obj: sbr/seq_del.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-seq_del.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-seq_del.Tpo -c -o sbr/sbr_libmh_a-seq_del.obj `if test -f 'sbr/seq_del.c'; then $(CYGPATH_W) 'sbr/seq_del.c'; else $(CYGPATH_W) '$(srcdir)/sbr/seq_del.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-seq_del.Tpo sbr/$(DEPDIR)/sbr_libmh_a-seq_del.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/seq_del.c' object='sbr/sbr_libmh_a-seq_del.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-seq_del.obj `if test -f 'sbr/seq_del.c'; then $(CYGPATH_W) 'sbr/seq_del.c'; else $(CYGPATH_W) '$(srcdir)/sbr/seq_del.c'; fi` sbr/sbr_libmh_a-seq_getnum.o: sbr/seq_getnum.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-seq_getnum.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-seq_getnum.Tpo -c -o sbr/sbr_libmh_a-seq_getnum.o `test -f 'sbr/seq_getnum.c' || echo '$(srcdir)/'`sbr/seq_getnum.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-seq_getnum.Tpo sbr/$(DEPDIR)/sbr_libmh_a-seq_getnum.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/seq_getnum.c' object='sbr/sbr_libmh_a-seq_getnum.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-seq_getnum.o `test -f 'sbr/seq_getnum.c' || echo '$(srcdir)/'`sbr/seq_getnum.c sbr/sbr_libmh_a-seq_getnum.obj: sbr/seq_getnum.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-seq_getnum.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-seq_getnum.Tpo -c -o sbr/sbr_libmh_a-seq_getnum.obj `if test -f 'sbr/seq_getnum.c'; then $(CYGPATH_W) 'sbr/seq_getnum.c'; else $(CYGPATH_W) '$(srcdir)/sbr/seq_getnum.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-seq_getnum.Tpo sbr/$(DEPDIR)/sbr_libmh_a-seq_getnum.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/seq_getnum.c' object='sbr/sbr_libmh_a-seq_getnum.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-seq_getnum.obj `if test -f 'sbr/seq_getnum.c'; then $(CYGPATH_W) 'sbr/seq_getnum.c'; else $(CYGPATH_W) '$(srcdir)/sbr/seq_getnum.c'; fi` sbr/sbr_libmh_a-seq_list.o: sbr/seq_list.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-seq_list.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-seq_list.Tpo -c -o sbr/sbr_libmh_a-seq_list.o `test -f 'sbr/seq_list.c' || echo '$(srcdir)/'`sbr/seq_list.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-seq_list.Tpo sbr/$(DEPDIR)/sbr_libmh_a-seq_list.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/seq_list.c' object='sbr/sbr_libmh_a-seq_list.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-seq_list.o `test -f 'sbr/seq_list.c' || echo '$(srcdir)/'`sbr/seq_list.c sbr/sbr_libmh_a-seq_list.obj: sbr/seq_list.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-seq_list.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-seq_list.Tpo -c -o sbr/sbr_libmh_a-seq_list.obj `if test -f 'sbr/seq_list.c'; then $(CYGPATH_W) 'sbr/seq_list.c'; else $(CYGPATH_W) '$(srcdir)/sbr/seq_list.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-seq_list.Tpo sbr/$(DEPDIR)/sbr_libmh_a-seq_list.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/seq_list.c' object='sbr/sbr_libmh_a-seq_list.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-seq_list.obj `if test -f 'sbr/seq_list.c'; then $(CYGPATH_W) 'sbr/seq_list.c'; else $(CYGPATH_W) '$(srcdir)/sbr/seq_list.c'; fi` sbr/sbr_libmh_a-seq_nameok.o: sbr/seq_nameok.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-seq_nameok.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-seq_nameok.Tpo -c -o sbr/sbr_libmh_a-seq_nameok.o `test -f 'sbr/seq_nameok.c' || echo '$(srcdir)/'`sbr/seq_nameok.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-seq_nameok.Tpo sbr/$(DEPDIR)/sbr_libmh_a-seq_nameok.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/seq_nameok.c' object='sbr/sbr_libmh_a-seq_nameok.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-seq_nameok.o `test -f 'sbr/seq_nameok.c' || echo '$(srcdir)/'`sbr/seq_nameok.c sbr/sbr_libmh_a-seq_nameok.obj: sbr/seq_nameok.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-seq_nameok.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-seq_nameok.Tpo -c -o sbr/sbr_libmh_a-seq_nameok.obj `if test -f 'sbr/seq_nameok.c'; then $(CYGPATH_W) 'sbr/seq_nameok.c'; else $(CYGPATH_W) '$(srcdir)/sbr/seq_nameok.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-seq_nameok.Tpo sbr/$(DEPDIR)/sbr_libmh_a-seq_nameok.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/seq_nameok.c' object='sbr/sbr_libmh_a-seq_nameok.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-seq_nameok.obj `if test -f 'sbr/seq_nameok.c'; then $(CYGPATH_W) 'sbr/seq_nameok.c'; else $(CYGPATH_W) '$(srcdir)/sbr/seq_nameok.c'; fi` sbr/sbr_libmh_a-seq_print.o: sbr/seq_print.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-seq_print.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-seq_print.Tpo -c -o sbr/sbr_libmh_a-seq_print.o `test -f 'sbr/seq_print.c' || echo '$(srcdir)/'`sbr/seq_print.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-seq_print.Tpo sbr/$(DEPDIR)/sbr_libmh_a-seq_print.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/seq_print.c' object='sbr/sbr_libmh_a-seq_print.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-seq_print.o `test -f 'sbr/seq_print.c' || echo '$(srcdir)/'`sbr/seq_print.c sbr/sbr_libmh_a-seq_print.obj: sbr/seq_print.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-seq_print.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-seq_print.Tpo -c -o sbr/sbr_libmh_a-seq_print.obj `if test -f 'sbr/seq_print.c'; then $(CYGPATH_W) 'sbr/seq_print.c'; else $(CYGPATH_W) '$(srcdir)/sbr/seq_print.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-seq_print.Tpo sbr/$(DEPDIR)/sbr_libmh_a-seq_print.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/seq_print.c' object='sbr/sbr_libmh_a-seq_print.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-seq_print.obj `if test -f 'sbr/seq_print.c'; then $(CYGPATH_W) 'sbr/seq_print.c'; else $(CYGPATH_W) '$(srcdir)/sbr/seq_print.c'; fi` sbr/sbr_libmh_a-seq_read.o: sbr/seq_read.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-seq_read.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-seq_read.Tpo -c -o sbr/sbr_libmh_a-seq_read.o `test -f 'sbr/seq_read.c' || echo '$(srcdir)/'`sbr/seq_read.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-seq_read.Tpo sbr/$(DEPDIR)/sbr_libmh_a-seq_read.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/seq_read.c' object='sbr/sbr_libmh_a-seq_read.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-seq_read.o `test -f 'sbr/seq_read.c' || echo '$(srcdir)/'`sbr/seq_read.c sbr/sbr_libmh_a-seq_read.obj: sbr/seq_read.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-seq_read.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-seq_read.Tpo -c -o sbr/sbr_libmh_a-seq_read.obj `if test -f 'sbr/seq_read.c'; then $(CYGPATH_W) 'sbr/seq_read.c'; else $(CYGPATH_W) '$(srcdir)/sbr/seq_read.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-seq_read.Tpo sbr/$(DEPDIR)/sbr_libmh_a-seq_read.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/seq_read.c' object='sbr/sbr_libmh_a-seq_read.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-seq_read.obj `if test -f 'sbr/seq_read.c'; then $(CYGPATH_W) 'sbr/seq_read.c'; else $(CYGPATH_W) '$(srcdir)/sbr/seq_read.c'; fi` sbr/sbr_libmh_a-seq_save.o: sbr/seq_save.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-seq_save.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-seq_save.Tpo -c -o sbr/sbr_libmh_a-seq_save.o `test -f 'sbr/seq_save.c' || echo '$(srcdir)/'`sbr/seq_save.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-seq_save.Tpo sbr/$(DEPDIR)/sbr_libmh_a-seq_save.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/seq_save.c' object='sbr/sbr_libmh_a-seq_save.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-seq_save.o `test -f 'sbr/seq_save.c' || echo '$(srcdir)/'`sbr/seq_save.c sbr/sbr_libmh_a-seq_save.obj: sbr/seq_save.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-seq_save.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-seq_save.Tpo -c -o sbr/sbr_libmh_a-seq_save.obj `if test -f 'sbr/seq_save.c'; then $(CYGPATH_W) 'sbr/seq_save.c'; else $(CYGPATH_W) '$(srcdir)/sbr/seq_save.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-seq_save.Tpo sbr/$(DEPDIR)/sbr_libmh_a-seq_save.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/seq_save.c' object='sbr/sbr_libmh_a-seq_save.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-seq_save.obj `if test -f 'sbr/seq_save.c'; then $(CYGPATH_W) 'sbr/seq_save.c'; else $(CYGPATH_W) '$(srcdir)/sbr/seq_save.c'; fi` sbr/sbr_libmh_a-seq_setcur.o: sbr/seq_setcur.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-seq_setcur.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-seq_setcur.Tpo -c -o sbr/sbr_libmh_a-seq_setcur.o `test -f 'sbr/seq_setcur.c' || echo '$(srcdir)/'`sbr/seq_setcur.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-seq_setcur.Tpo sbr/$(DEPDIR)/sbr_libmh_a-seq_setcur.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/seq_setcur.c' object='sbr/sbr_libmh_a-seq_setcur.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-seq_setcur.o `test -f 'sbr/seq_setcur.c' || echo '$(srcdir)/'`sbr/seq_setcur.c sbr/sbr_libmh_a-seq_setcur.obj: sbr/seq_setcur.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-seq_setcur.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-seq_setcur.Tpo -c -o sbr/sbr_libmh_a-seq_setcur.obj `if test -f 'sbr/seq_setcur.c'; then $(CYGPATH_W) 'sbr/seq_setcur.c'; else $(CYGPATH_W) '$(srcdir)/sbr/seq_setcur.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-seq_setcur.Tpo sbr/$(DEPDIR)/sbr_libmh_a-seq_setcur.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/seq_setcur.c' object='sbr/sbr_libmh_a-seq_setcur.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-seq_setcur.obj `if test -f 'sbr/seq_setcur.c'; then $(CYGPATH_W) 'sbr/seq_setcur.c'; else $(CYGPATH_W) '$(srcdir)/sbr/seq_setcur.c'; fi` sbr/sbr_libmh_a-seq_setprev.o: sbr/seq_setprev.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-seq_setprev.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-seq_setprev.Tpo -c -o sbr/sbr_libmh_a-seq_setprev.o `test -f 'sbr/seq_setprev.c' || echo '$(srcdir)/'`sbr/seq_setprev.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-seq_setprev.Tpo sbr/$(DEPDIR)/sbr_libmh_a-seq_setprev.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/seq_setprev.c' object='sbr/sbr_libmh_a-seq_setprev.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-seq_setprev.o `test -f 'sbr/seq_setprev.c' || echo '$(srcdir)/'`sbr/seq_setprev.c sbr/sbr_libmh_a-seq_setprev.obj: sbr/seq_setprev.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-seq_setprev.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-seq_setprev.Tpo -c -o sbr/sbr_libmh_a-seq_setprev.obj `if test -f 'sbr/seq_setprev.c'; then $(CYGPATH_W) 'sbr/seq_setprev.c'; else $(CYGPATH_W) '$(srcdir)/sbr/seq_setprev.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-seq_setprev.Tpo sbr/$(DEPDIR)/sbr_libmh_a-seq_setprev.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/seq_setprev.c' object='sbr/sbr_libmh_a-seq_setprev.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-seq_setprev.obj `if test -f 'sbr/seq_setprev.c'; then $(CYGPATH_W) 'sbr/seq_setprev.c'; else $(CYGPATH_W) '$(srcdir)/sbr/seq_setprev.c'; fi` sbr/sbr_libmh_a-seq_setunseen.o: sbr/seq_setunseen.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-seq_setunseen.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-seq_setunseen.Tpo -c -o sbr/sbr_libmh_a-seq_setunseen.o `test -f 'sbr/seq_setunseen.c' || echo '$(srcdir)/'`sbr/seq_setunseen.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-seq_setunseen.Tpo sbr/$(DEPDIR)/sbr_libmh_a-seq_setunseen.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/seq_setunseen.c' object='sbr/sbr_libmh_a-seq_setunseen.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-seq_setunseen.o `test -f 'sbr/seq_setunseen.c' || echo '$(srcdir)/'`sbr/seq_setunseen.c sbr/sbr_libmh_a-seq_setunseen.obj: sbr/seq_setunseen.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-seq_setunseen.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-seq_setunseen.Tpo -c -o sbr/sbr_libmh_a-seq_setunseen.obj `if test -f 'sbr/seq_setunseen.c'; then $(CYGPATH_W) 'sbr/seq_setunseen.c'; else $(CYGPATH_W) '$(srcdir)/sbr/seq_setunseen.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-seq_setunseen.Tpo sbr/$(DEPDIR)/sbr_libmh_a-seq_setunseen.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/seq_setunseen.c' object='sbr/sbr_libmh_a-seq_setunseen.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-seq_setunseen.obj `if test -f 'sbr/seq_setunseen.c'; then $(CYGPATH_W) 'sbr/seq_setunseen.c'; else $(CYGPATH_W) '$(srcdir)/sbr/seq_setunseen.c'; fi` sbr/sbr_libmh_a-showfile.o: sbr/showfile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-showfile.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-showfile.Tpo -c -o sbr/sbr_libmh_a-showfile.o `test -f 'sbr/showfile.c' || echo '$(srcdir)/'`sbr/showfile.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-showfile.Tpo sbr/$(DEPDIR)/sbr_libmh_a-showfile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/showfile.c' object='sbr/sbr_libmh_a-showfile.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-showfile.o `test -f 'sbr/showfile.c' || echo '$(srcdir)/'`sbr/showfile.c sbr/sbr_libmh_a-showfile.obj: sbr/showfile.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-showfile.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-showfile.Tpo -c -o sbr/sbr_libmh_a-showfile.obj `if test -f 'sbr/showfile.c'; then $(CYGPATH_W) 'sbr/showfile.c'; else $(CYGPATH_W) '$(srcdir)/sbr/showfile.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-showfile.Tpo sbr/$(DEPDIR)/sbr_libmh_a-showfile.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/showfile.c' object='sbr/sbr_libmh_a-showfile.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-showfile.obj `if test -f 'sbr/showfile.c'; then $(CYGPATH_W) 'sbr/showfile.c'; else $(CYGPATH_W) '$(srcdir)/sbr/showfile.c'; fi` sbr/sbr_libmh_a-signals.o: sbr/signals.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-signals.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-signals.Tpo -c -o sbr/sbr_libmh_a-signals.o `test -f 'sbr/signals.c' || echo '$(srcdir)/'`sbr/signals.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-signals.Tpo sbr/$(DEPDIR)/sbr_libmh_a-signals.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/signals.c' object='sbr/sbr_libmh_a-signals.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-signals.o `test -f 'sbr/signals.c' || echo '$(srcdir)/'`sbr/signals.c sbr/sbr_libmh_a-signals.obj: sbr/signals.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-signals.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-signals.Tpo -c -o sbr/sbr_libmh_a-signals.obj `if test -f 'sbr/signals.c'; then $(CYGPATH_W) 'sbr/signals.c'; else $(CYGPATH_W) '$(srcdir)/sbr/signals.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-signals.Tpo sbr/$(DEPDIR)/sbr_libmh_a-signals.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/signals.c' object='sbr/sbr_libmh_a-signals.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-signals.obj `if test -f 'sbr/signals.c'; then $(CYGPATH_W) 'sbr/signals.c'; else $(CYGPATH_W) '$(srcdir)/sbr/signals.c'; fi` sbr/sbr_libmh_a-smatch.o: sbr/smatch.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-smatch.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-smatch.Tpo -c -o sbr/sbr_libmh_a-smatch.o `test -f 'sbr/smatch.c' || echo '$(srcdir)/'`sbr/smatch.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-smatch.Tpo sbr/$(DEPDIR)/sbr_libmh_a-smatch.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/smatch.c' object='sbr/sbr_libmh_a-smatch.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-smatch.o `test -f 'sbr/smatch.c' || echo '$(srcdir)/'`sbr/smatch.c sbr/sbr_libmh_a-smatch.obj: sbr/smatch.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-smatch.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-smatch.Tpo -c -o sbr/sbr_libmh_a-smatch.obj `if test -f 'sbr/smatch.c'; then $(CYGPATH_W) 'sbr/smatch.c'; else $(CYGPATH_W) '$(srcdir)/sbr/smatch.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-smatch.Tpo sbr/$(DEPDIR)/sbr_libmh_a-smatch.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/smatch.c' object='sbr/sbr_libmh_a-smatch.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-smatch.obj `if test -f 'sbr/smatch.c'; then $(CYGPATH_W) 'sbr/smatch.c'; else $(CYGPATH_W) '$(srcdir)/sbr/smatch.c'; fi` sbr/sbr_libmh_a-snprintb.o: sbr/snprintb.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-snprintb.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-snprintb.Tpo -c -o sbr/sbr_libmh_a-snprintb.o `test -f 'sbr/snprintb.c' || echo '$(srcdir)/'`sbr/snprintb.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-snprintb.Tpo sbr/$(DEPDIR)/sbr_libmh_a-snprintb.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/snprintb.c' object='sbr/sbr_libmh_a-snprintb.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-snprintb.o `test -f 'sbr/snprintb.c' || echo '$(srcdir)/'`sbr/snprintb.c sbr/sbr_libmh_a-snprintb.obj: sbr/snprintb.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-snprintb.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-snprintb.Tpo -c -o sbr/sbr_libmh_a-snprintb.obj `if test -f 'sbr/snprintb.c'; then $(CYGPATH_W) 'sbr/snprintb.c'; else $(CYGPATH_W) '$(srcdir)/sbr/snprintb.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-snprintb.Tpo sbr/$(DEPDIR)/sbr_libmh_a-snprintb.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/snprintb.c' object='sbr/sbr_libmh_a-snprintb.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-snprintb.obj `if test -f 'sbr/snprintb.c'; then $(CYGPATH_W) 'sbr/snprintb.c'; else $(CYGPATH_W) '$(srcdir)/sbr/snprintb.c'; fi` sbr/sbr_libmh_a-ssequal.o: sbr/ssequal.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-ssequal.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-ssequal.Tpo -c -o sbr/sbr_libmh_a-ssequal.o `test -f 'sbr/ssequal.c' || echo '$(srcdir)/'`sbr/ssequal.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-ssequal.Tpo sbr/$(DEPDIR)/sbr_libmh_a-ssequal.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/ssequal.c' object='sbr/sbr_libmh_a-ssequal.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-ssequal.o `test -f 'sbr/ssequal.c' || echo '$(srcdir)/'`sbr/ssequal.c sbr/sbr_libmh_a-ssequal.obj: sbr/ssequal.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-ssequal.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-ssequal.Tpo -c -o sbr/sbr_libmh_a-ssequal.obj `if test -f 'sbr/ssequal.c'; then $(CYGPATH_W) 'sbr/ssequal.c'; else $(CYGPATH_W) '$(srcdir)/sbr/ssequal.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-ssequal.Tpo sbr/$(DEPDIR)/sbr_libmh_a-ssequal.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/ssequal.c' object='sbr/sbr_libmh_a-ssequal.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-ssequal.obj `if test -f 'sbr/ssequal.c'; then $(CYGPATH_W) 'sbr/ssequal.c'; else $(CYGPATH_W) '$(srcdir)/sbr/ssequal.c'; fi` sbr/sbr_libmh_a-strindex.o: sbr/strindex.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-strindex.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-strindex.Tpo -c -o sbr/sbr_libmh_a-strindex.o `test -f 'sbr/strindex.c' || echo '$(srcdir)/'`sbr/strindex.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-strindex.Tpo sbr/$(DEPDIR)/sbr_libmh_a-strindex.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/strindex.c' object='sbr/sbr_libmh_a-strindex.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-strindex.o `test -f 'sbr/strindex.c' || echo '$(srcdir)/'`sbr/strindex.c sbr/sbr_libmh_a-strindex.obj: sbr/strindex.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-strindex.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-strindex.Tpo -c -o sbr/sbr_libmh_a-strindex.obj `if test -f 'sbr/strindex.c'; then $(CYGPATH_W) 'sbr/strindex.c'; else $(CYGPATH_W) '$(srcdir)/sbr/strindex.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-strindex.Tpo sbr/$(DEPDIR)/sbr_libmh_a-strindex.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/strindex.c' object='sbr/sbr_libmh_a-strindex.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-strindex.obj `if test -f 'sbr/strindex.c'; then $(CYGPATH_W) 'sbr/strindex.c'; else $(CYGPATH_W) '$(srcdir)/sbr/strindex.c'; fi` sbr/sbr_libmh_a-terminal.o: sbr/terminal.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-terminal.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-terminal.Tpo -c -o sbr/sbr_libmh_a-terminal.o `test -f 'sbr/terminal.c' || echo '$(srcdir)/'`sbr/terminal.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-terminal.Tpo sbr/$(DEPDIR)/sbr_libmh_a-terminal.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/terminal.c' object='sbr/sbr_libmh_a-terminal.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-terminal.o `test -f 'sbr/terminal.c' || echo '$(srcdir)/'`sbr/terminal.c sbr/sbr_libmh_a-terminal.obj: sbr/terminal.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-terminal.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-terminal.Tpo -c -o sbr/sbr_libmh_a-terminal.obj `if test -f 'sbr/terminal.c'; then $(CYGPATH_W) 'sbr/terminal.c'; else $(CYGPATH_W) '$(srcdir)/sbr/terminal.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-terminal.Tpo sbr/$(DEPDIR)/sbr_libmh_a-terminal.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/terminal.c' object='sbr/sbr_libmh_a-terminal.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-terminal.obj `if test -f 'sbr/terminal.c'; then $(CYGPATH_W) 'sbr/terminal.c'; else $(CYGPATH_W) '$(srcdir)/sbr/terminal.c'; fi` sbr/sbr_libmh_a-trimcpy.o: sbr/trimcpy.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-trimcpy.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-trimcpy.Tpo -c -o sbr/sbr_libmh_a-trimcpy.o `test -f 'sbr/trimcpy.c' || echo '$(srcdir)/'`sbr/trimcpy.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-trimcpy.Tpo sbr/$(DEPDIR)/sbr_libmh_a-trimcpy.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/trimcpy.c' object='sbr/sbr_libmh_a-trimcpy.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-trimcpy.o `test -f 'sbr/trimcpy.c' || echo '$(srcdir)/'`sbr/trimcpy.c sbr/sbr_libmh_a-trimcpy.obj: sbr/trimcpy.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-trimcpy.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-trimcpy.Tpo -c -o sbr/sbr_libmh_a-trimcpy.obj `if test -f 'sbr/trimcpy.c'; then $(CYGPATH_W) 'sbr/trimcpy.c'; else $(CYGPATH_W) '$(srcdir)/sbr/trimcpy.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-trimcpy.Tpo sbr/$(DEPDIR)/sbr_libmh_a-trimcpy.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/trimcpy.c' object='sbr/sbr_libmh_a-trimcpy.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-trimcpy.obj `if test -f 'sbr/trimcpy.c'; then $(CYGPATH_W) 'sbr/trimcpy.c'; else $(CYGPATH_W) '$(srcdir)/sbr/trimcpy.c'; fi` sbr/sbr_libmh_a-unquote.o: sbr/unquote.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-unquote.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-unquote.Tpo -c -o sbr/sbr_libmh_a-unquote.o `test -f 'sbr/unquote.c' || echo '$(srcdir)/'`sbr/unquote.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-unquote.Tpo sbr/$(DEPDIR)/sbr_libmh_a-unquote.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/unquote.c' object='sbr/sbr_libmh_a-unquote.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-unquote.o `test -f 'sbr/unquote.c' || echo '$(srcdir)/'`sbr/unquote.c sbr/sbr_libmh_a-unquote.obj: sbr/unquote.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-unquote.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-unquote.Tpo -c -o sbr/sbr_libmh_a-unquote.obj `if test -f 'sbr/unquote.c'; then $(CYGPATH_W) 'sbr/unquote.c'; else $(CYGPATH_W) '$(srcdir)/sbr/unquote.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-unquote.Tpo sbr/$(DEPDIR)/sbr_libmh_a-unquote.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/unquote.c' object='sbr/sbr_libmh_a-unquote.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-unquote.obj `if test -f 'sbr/unquote.c'; then $(CYGPATH_W) 'sbr/unquote.c'; else $(CYGPATH_W) '$(srcdir)/sbr/unquote.c'; fi` sbr/sbr_libmh_a-uprf.o: sbr/uprf.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-uprf.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-uprf.Tpo -c -o sbr/sbr_libmh_a-uprf.o `test -f 'sbr/uprf.c' || echo '$(srcdir)/'`sbr/uprf.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-uprf.Tpo sbr/$(DEPDIR)/sbr_libmh_a-uprf.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/uprf.c' object='sbr/sbr_libmh_a-uprf.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-uprf.o `test -f 'sbr/uprf.c' || echo '$(srcdir)/'`sbr/uprf.c sbr/sbr_libmh_a-uprf.obj: sbr/uprf.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-uprf.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-uprf.Tpo -c -o sbr/sbr_libmh_a-uprf.obj `if test -f 'sbr/uprf.c'; then $(CYGPATH_W) 'sbr/uprf.c'; else $(CYGPATH_W) '$(srcdir)/sbr/uprf.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-uprf.Tpo sbr/$(DEPDIR)/sbr_libmh_a-uprf.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/uprf.c' object='sbr/sbr_libmh_a-uprf.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-uprf.obj `if test -f 'sbr/uprf.c'; then $(CYGPATH_W) 'sbr/uprf.c'; else $(CYGPATH_W) '$(srcdir)/sbr/uprf.c'; fi` sbr/sbr_libmh_a-utils.o: sbr/utils.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-utils.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-utils.Tpo -c -o sbr/sbr_libmh_a-utils.o `test -f 'sbr/utils.c' || echo '$(srcdir)/'`sbr/utils.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-utils.Tpo sbr/$(DEPDIR)/sbr_libmh_a-utils.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/utils.c' object='sbr/sbr_libmh_a-utils.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-utils.o `test -f 'sbr/utils.c' || echo '$(srcdir)/'`sbr/utils.c sbr/sbr_libmh_a-utils.obj: sbr/utils.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-utils.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-utils.Tpo -c -o sbr/sbr_libmh_a-utils.obj `if test -f 'sbr/utils.c'; then $(CYGPATH_W) 'sbr/utils.c'; else $(CYGPATH_W) '$(srcdir)/sbr/utils.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-utils.Tpo sbr/$(DEPDIR)/sbr_libmh_a-utils.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/utils.c' object='sbr/sbr_libmh_a-utils.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-utils.obj `if test -f 'sbr/utils.c'; then $(CYGPATH_W) 'sbr/utils.c'; else $(CYGPATH_W) '$(srcdir)/sbr/utils.c'; fi` sbr/sbr_libmh_a-vector.o: sbr/vector.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-vector.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-vector.Tpo -c -o sbr/sbr_libmh_a-vector.o `test -f 'sbr/vector.c' || echo '$(srcdir)/'`sbr/vector.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-vector.Tpo sbr/$(DEPDIR)/sbr_libmh_a-vector.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/vector.c' object='sbr/sbr_libmh_a-vector.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-vector.o `test -f 'sbr/vector.c' || echo '$(srcdir)/'`sbr/vector.c sbr/sbr_libmh_a-vector.obj: sbr/vector.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-vector.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-vector.Tpo -c -o sbr/sbr_libmh_a-vector.obj `if test -f 'sbr/vector.c'; then $(CYGPATH_W) 'sbr/vector.c'; else $(CYGPATH_W) '$(srcdir)/sbr/vector.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-vector.Tpo sbr/$(DEPDIR)/sbr_libmh_a-vector.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/vector.c' object='sbr/sbr_libmh_a-vector.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-vector.obj `if test -f 'sbr/vector.c'; then $(CYGPATH_W) 'sbr/vector.c'; else $(CYGPATH_W) '$(srcdir)/sbr/vector.c'; fi` sbr/sbr_libmh_a-vfgets.o: sbr/vfgets.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-vfgets.o -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-vfgets.Tpo -c -o sbr/sbr_libmh_a-vfgets.o `test -f 'sbr/vfgets.c' || echo '$(srcdir)/'`sbr/vfgets.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-vfgets.Tpo sbr/$(DEPDIR)/sbr_libmh_a-vfgets.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/vfgets.c' object='sbr/sbr_libmh_a-vfgets.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-vfgets.o `test -f 'sbr/vfgets.c' || echo '$(srcdir)/'`sbr/vfgets.c sbr/sbr_libmh_a-vfgets.obj: sbr/vfgets.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT sbr/sbr_libmh_a-vfgets.obj -MD -MP -MF sbr/$(DEPDIR)/sbr_libmh_a-vfgets.Tpo -c -o sbr/sbr_libmh_a-vfgets.obj `if test -f 'sbr/vfgets.c'; then $(CYGPATH_W) 'sbr/vfgets.c'; else $(CYGPATH_W) '$(srcdir)/sbr/vfgets.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) sbr/$(DEPDIR)/sbr_libmh_a-vfgets.Tpo sbr/$(DEPDIR)/sbr_libmh_a-vfgets.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbr/vfgets.c' object='sbr/sbr_libmh_a-vfgets.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o sbr/sbr_libmh_a-vfgets.obj `if test -f 'sbr/vfgets.c'; then $(CYGPATH_W) 'sbr/vfgets.c'; else $(CYGPATH_W) '$(srcdir)/sbr/vfgets.c'; fi` thirdparty/jsmn/sbr_libmh_a-jsmn.o: thirdparty/jsmn/jsmn.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT thirdparty/jsmn/sbr_libmh_a-jsmn.o -MD -MP -MF thirdparty/jsmn/$(DEPDIR)/sbr_libmh_a-jsmn.Tpo -c -o thirdparty/jsmn/sbr_libmh_a-jsmn.o `test -f 'thirdparty/jsmn/jsmn.c' || echo '$(srcdir)/'`thirdparty/jsmn/jsmn.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) thirdparty/jsmn/$(DEPDIR)/sbr_libmh_a-jsmn.Tpo thirdparty/jsmn/$(DEPDIR)/sbr_libmh_a-jsmn.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='thirdparty/jsmn/jsmn.c' object='thirdparty/jsmn/sbr_libmh_a-jsmn.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o thirdparty/jsmn/sbr_libmh_a-jsmn.o `test -f 'thirdparty/jsmn/jsmn.c' || echo '$(srcdir)/'`thirdparty/jsmn/jsmn.c thirdparty/jsmn/sbr_libmh_a-jsmn.obj: thirdparty/jsmn/jsmn.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT thirdparty/jsmn/sbr_libmh_a-jsmn.obj -MD -MP -MF thirdparty/jsmn/$(DEPDIR)/sbr_libmh_a-jsmn.Tpo -c -o thirdparty/jsmn/sbr_libmh_a-jsmn.obj `if test -f 'thirdparty/jsmn/jsmn.c'; then $(CYGPATH_W) 'thirdparty/jsmn/jsmn.c'; else $(CYGPATH_W) '$(srcdir)/thirdparty/jsmn/jsmn.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) thirdparty/jsmn/$(DEPDIR)/sbr_libmh_a-jsmn.Tpo thirdparty/jsmn/$(DEPDIR)/sbr_libmh_a-jsmn.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='thirdparty/jsmn/jsmn.c' object='thirdparty/jsmn/sbr_libmh_a-jsmn.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(sbr_libmh_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o thirdparty/jsmn/sbr_libmh_a-jsmn.obj `if test -f 'thirdparty/jsmn/jsmn.c'; then $(CYGPATH_W) 'thirdparty/jsmn/jsmn.c'; else $(CYGPATH_W) '$(srcdir)/thirdparty/jsmn/jsmn.c'; fi` .l.c: $(AM_V_LEX)$(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE) .y.c: $(AM_V_YACC)$(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h `echo $@ | $(am__yacc_c2h)` y.output $*.output -- $(YACCCOMPILE) install-man1: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man1dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.1[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) install-man5: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man5dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.5[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \ done; } uninstall-man5: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man5dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.5[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir) install-man7: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man7dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man7dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man7dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.7[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^7][0-9a-z]*$$,7,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man7dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man7dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man7dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man7dir)" || exit $$?; }; \ done; } uninstall-man7: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man7dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.7[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^7][0-9a-z]*$$,7,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man7dir)'; $(am__uninstall_files_from_dir) install-man8: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man8dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.8[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ done; } uninstall-man8: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man8dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.8[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) install-dist_docDATA: $(dist_doc_DATA) @$(NORMAL_INSTALL) @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ done uninstall-dist_docDATA: @$(NORMAL_UNINSTALL) @list='$(dist_doc_DATA)'; test -n "$(docdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) install-dist_docs_contribDATA: $(dist_docs_contrib_DATA) @$(NORMAL_INSTALL) @list='$(dist_docs_contrib_DATA)'; test -n "$(docs_contribdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(docs_contribdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(docs_contribdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docs_contribdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(docs_contribdir)" || exit $$?; \ done uninstall-dist_docs_contribDATA: @$(NORMAL_UNINSTALL) @list='$(dist_docs_contrib_DATA)'; test -n "$(docs_contribdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(docs_contribdir)'; $(am__uninstall_files_from_dir) install-dist_nmhetcDATA: $(dist_nmhetc_DATA) @$(NORMAL_INSTALL) @list='$(dist_nmhetc_DATA)'; test -n "$(nmhetcdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(nmhetcdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(nmhetcdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(nmhetcdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(nmhetcdir)" || exit $$?; \ done uninstall-dist_nmhetcDATA: @$(NORMAL_UNINSTALL) @list='$(dist_nmhetc_DATA)'; test -n "$(nmhetcdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(nmhetcdir)'; $(am__uninstall_files_from_dir) install-nmhetcDATA: $(nmhetc_DATA) @$(NORMAL_INSTALL) @list='$(nmhetc_DATA)'; test -n "$(nmhetcdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(nmhetcdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(nmhetcdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(nmhetcdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(nmhetcdir)" || exit $$?; \ done uninstall-nmhetcDATA: @$(NORMAL_UNINSTALL) @list='$(nmhetc_DATA)'; test -n "$(nmhetcdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(nmhetcdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files check-TESTS: $(TESTS) @failed=0; all=0; xfail=0; xpass=0; skip=0; \ srcdir=$(srcdir); export srcdir; \ list=' $(TESTS) '; \ $(am__tty_colors); \ if test -n "$$list"; then \ for tst in $$list; do \ if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$tst[\ \ ]*) \ xpass=`expr $$xpass + 1`; \ failed=`expr $$failed + 1`; \ col=$$red; res=XPASS; \ ;; \ *) \ col=$$grn; res=PASS; \ ;; \ esac; \ elif test $$? -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$tst[\ \ ]*) \ xfail=`expr $$xfail + 1`; \ col=$$lgn; res=XFAIL; \ ;; \ *) \ failed=`expr $$failed + 1`; \ col=$$red; res=FAIL; \ ;; \ esac; \ else \ skip=`expr $$skip + 1`; \ col=$$blu; res=SKIP; \ fi; \ echo "$${col}$$res$${std}: $$tst"; \ done; \ if test "$$all" -eq 1; then \ tests="test"; \ All=""; \ else \ tests="tests"; \ All="All "; \ fi; \ if test "$$failed" -eq 0; then \ if test "$$xfail" -eq 0; then \ banner="$$All$$all $$tests passed"; \ else \ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ fi; \ else \ if test "$$xpass" -eq 0; then \ banner="$$failed of $$all $$tests failed"; \ else \ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ fi; \ fi; \ dashes="$$banner"; \ skipped=""; \ if test "$$skip" -ne 0; then \ if test "$$skip" -eq 1; then \ skipped="($$skip test was not run)"; \ else \ skipped="($$skip tests were not run)"; \ fi; \ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$skipped"; \ fi; \ report=""; \ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ report="Please report to $(PACKAGE_BUGREPORT)"; \ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ dashes="$$report"; \ fi; \ dashes=`echo "$$dashes" | sed s/./=/g`; \ if test "$$failed" -eq 0; then \ col="$$grn"; \ else \ col="$$red"; \ fi; \ echo "$${col}$$dashes$${std}"; \ echo "$${col}$$banner$${std}"; \ test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \ test -z "$$report" || echo "$${col}$$report$${std}"; \ echo "$${col}$$dashes$${std}"; \ test "$$failed" -eq 0; \ else :; fi distdir: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build/sub \ && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(check_SCRIPTS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-am all-am: Makefile $(LIBRARIES) $(PROGRAMS) $(SCRIPTS) $(MANS) $(DATA) \ $(HEADERS) config.h installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(nmhlibexecdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(docs_contribdir)" "$(DESTDIR)$(nmhetcdir)" "$(DESTDIR)$(nmhlibexecdir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man7dir)" "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(docs_contribdir)" "$(DESTDIR)$(nmhetcdir)" "$(DESTDIR)$(nmhetcdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: -test -z "$(LIBOBJS)" || rm -f $(LIBOBJS) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f config/$(DEPDIR)/$(am__dirstamp) -rm -f config/$(am__dirstamp) -rm -f mts/$(am__dirstamp) -rm -f mts/smtp/$(DEPDIR)/$(am__dirstamp) -rm -f mts/smtp/$(am__dirstamp) -rm -f sbr/$(DEPDIR)/$(am__dirstamp) -rm -f sbr/$(am__dirstamp) -rm -f test/$(DEPDIR)/$(am__dirstamp) -rm -f test/$(am__dirstamp) -rm -f thirdparty/jsmn/$(DEPDIR)/$(am__dirstamp) -rm -f thirdparty/jsmn/$(am__dirstamp) -rm -f uip/$(DEPDIR)/$(am__dirstamp) -rm -f uip/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -rm -f sbr/dtimep.c -rm -f sbr/icalendar.c -rm -f sbr/icalparse.c -rm -f sbr/icalparse.h -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ clean-local clean-nmhlibexecPROGRAMS clean-noinstLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf config/$(DEPDIR) mts/smtp/$(DEPDIR) sbr/$(DEPDIR) test/$(DEPDIR) thirdparty/jsmn/$(DEPDIR) uip/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-dist_docDATA install-dist_docs_contribDATA \ install-dist_docs_contribSCRIPTS install-dist_nmhetcDATA \ install-dist_nmhetcSCRIPTS install-man install-nmhetcDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-binSCRIPTS \ install-nmhlibexecPROGRAMS install-nmhlibexecSCRIPTS @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-exec-hook install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man1 install-man5 install-man7 install-man8 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -rf config/$(DEPDIR) mts/smtp/$(DEPDIR) sbr/$(DEPDIR) test/$(DEPDIR) thirdparty/jsmn/$(DEPDIR) uip/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \ uninstall-dist_docDATA uninstall-dist_docs_contribDATA \ uninstall-dist_docs_contribSCRIPTS uninstall-dist_nmhetcDATA \ uninstall-dist_nmhetcSCRIPTS uninstall-man \ uninstall-nmhetcDATA uninstall-nmhlibexecPROGRAMS \ uninstall-nmhlibexecSCRIPTS @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) uninstall-hook uninstall-man: uninstall-man1 uninstall-man5 uninstall-man7 \ uninstall-man8 .MAKE: all check-am install-am install-exec-am install-strip \ uninstall-am .PHONY: CTAGS GTAGS TAGS all all-am am--refresh check check-TESTS \ check-am clean clean-binPROGRAMS clean-checkPROGRAMS \ clean-cscope clean-generic clean-local \ clean-nmhlibexecPROGRAMS clean-noinstLIBRARIES cscope \ cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \ dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \ distcheck distclean distclean-compile distclean-generic \ distclean-hdr distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-binSCRIPTS \ install-data install-data-am install-dist_docDATA \ install-dist_docs_contribDATA install-dist_docs_contribSCRIPTS \ install-dist_nmhetcDATA install-dist_nmhetcSCRIPTS install-dvi \ install-dvi-am install-exec install-exec-am install-exec-hook \ install-html install-html-am install-info install-info-am \ install-man install-man1 install-man5 install-man7 \ install-man8 install-nmhetcDATA install-nmhlibexecPROGRAMS \ install-nmhlibexecSCRIPTS install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-compile \ mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-binPROGRAMS uninstall-binSCRIPTS \ uninstall-dist_docDATA uninstall-dist_docs_contribDATA \ uninstall-dist_docs_contribSCRIPTS uninstall-dist_nmhetcDATA \ uninstall-dist_nmhetcSCRIPTS uninstall-hook uninstall-man \ uninstall-man1 uninstall-man5 uninstall-man7 uninstall-man8 \ uninstall-nmhetcDATA uninstall-nmhlibexecPROGRAMS \ uninstall-nmhlibexecSCRIPTS .PRECIOUS: Makefile check-programs: $(check_PROGRAMS) # clean-local: @rm -rf RPM a.out.dSYM uip/a.out.dSYM @rm -rf test/testdir superclean: maintainer-clean @rm -f $(SUPERCLEANFILES) .PHONY: superclean config/version.c: Makefile $(srcdir)/config/version.sh env srcdir="$(srcdir)" sh $(srcdir)/config/version.sh $(VERSION) > ./config/version.c etc/bash_completion_nmh: $(srcdir)/etc/bash_completion_nmh-gen $(srcdir)/etc/bash_completion_nmh-gen > $@ etc/mts.conf: $(srcdir)/etc/mts.conf.in Makefile @rm -f $@ $(SED) -e 's,%mts%,$(MTS),' \ -e 's,%mailspool%,$(mailspool),' \ -e 's,%smtpserver%,$(smtpserver),' \ -e 's,%default_locking%,$(default_locking),' \ -e 's,%supported_locks%,$(supported_locks),' \ < $(srcdir)/etc/mts.conf.in > $@ etc/mhn.defaults: $(srcdir)/etc/mhn.defaults.sh $(MHNSEARCHPROG) @rm -f $@ $(srcdir)/etc/mhn.defaults.sh $(MHNSEARCHPATH) $(MHNSEARCHPROG) > $@ install-exec-hook: @rm -f $(DESTDIR)$(bindir)/flists$(EXEEXT) @rm -f $(DESTDIR)$(bindir)/folders$(EXEEXT) @rm -f $(DESTDIR)$(bindir)/fnext$(EXEEXT) @rm -f $(DESTDIR)$(bindir)/fprev$(EXEEXT) @rm -f $(DESTDIR)$(bindir)/unseen$(EXEEXT) @rm -f $(DESTDIR)$(bindir)/prev$(EXEEXT) @rm -f $(DESTDIR)$(bindir)/next$(EXEEXT) $(LN) $(DESTDIR)$(bindir)/flist$(EXEEXT) $(DESTDIR)$(bindir)/flists$(EXEEXT) $(LN) $(DESTDIR)$(bindir)/folder$(EXEEXT) $(DESTDIR)$(bindir)/folders$(EXEEXT) $(LN) $(DESTDIR)$(bindir)/new$(EXEEXT) $(DESTDIR)$(bindir)/fnext$(EXEEXT) $(LN) $(DESTDIR)$(bindir)/new$(EXEEXT) $(DESTDIR)$(bindir)/fprev$(EXEEXT) $(LN) $(DESTDIR)$(bindir)/new$(EXEEXT) $(DESTDIR)$(bindir)/unseen$(EXEEXT) $(LN) $(DESTDIR)$(bindir)/show$(EXEEXT) $(DESTDIR)$(bindir)/prev$(EXEEXT) $(LN) $(DESTDIR)$(bindir)/show$(EXEEXT) $(DESTDIR)$(bindir)/next$(EXEEXT) if test x$(SETGID_MAIL) != x; then \ chgrp $(MAIL_SPOOL_GRP) $(DESTDIR)$(bindir)/inc$(EXEEXT) && \ chmod 2755 $(DESTDIR)$(bindir)/inc$(EXEEXT); \ fi uninstall-hook: rm -f $(DESTDIR)$(bindir)/flists$(EXEEXT) rm -f $(DESTDIR)$(bindir)/folders$(EXEEXT) rm -f $(DESTDIR)$(bindir)/fnext$(EXEEXT) rm -f $(DESTDIR)$(bindir)/fprev$(EXEEXT) rm -f $(DESTDIR)$(bindir)/unseen$(EXEEXT) rm -f $(DESTDIR)$(bindir)/prev$(EXEEXT) rm -f $(DESTDIR)$(bindir)/next$(EXEEXT) sbr/icalendar.c: sbr/icalparse.c config/sbr_libmh_a-config.$(OBJEXT) sbr/sbr_libmh_a-mts.$(OBJEXT): Makefile $(man_MANS): man/man.sed man/man.sed: Makefile @echo 's,%nmhwarning%,THIS FILE HAS BEEN AUTOMATICALLY GENERATED. DO NOT EDIT.,g' > $@ @echo 's,%nmhversion%,nmh-$(VERSION),g' >> $@ @echo 's,%nmhetcdir%,$(nmhetcdir),g' >> $@ @echo 's,%nmhlibexecdir%,$(nmhlibexecdir),g' >> $@ @echo 's,%bindir%,$(bindir),g' >> $@ @echo 's,%docdir%,$(docdir),g' >> $@ @echo 's,%mandir%,$(mandir),g' >> $@ @echo 's,%mailspool%,$(mailspool),g' >> $@ @echo 's,%sendmailpath%,$(sendmailpath),g' >> $@ @echo 's,%default_locking%,$(default_locking),g' >> $@ @echo 's,%supported_locks%,$(supported_locks),g' >> $@ @echo 's,%manext1%,$(manext1),g' >> $@ @echo 's,%manext5%,$(manext5),g' >> $@ @echo 's,%manext7%,$(manext7),g' >> $@ @echo 's,%manext8%,$(manext8),g' >> $@ @echo '/%mhl_forward%/r $(top_srcdir)/etc/mhl.forward' >> $@ @echo ' s,%mhl_forward%,,g' >> $@ @echo '/%mhl_format%/r $(top_srcdir)/etc/mhl.format' >> $@ @echo ' s,%mhl_format%,,g' >> $@ @echo '/%mhl_reply%/r $(top_srcdir)/etc/mhl.reply' >> $@ @echo ' s,%mhl_reply%,,g' >> $@ man/mh-chart.man: $(man_SRCS) $(srcdir)/man/mh-chart-gen.sh > $@ .man.$(manext1): $(SED) -f man/man.sed $< > $@ .man.$(manext5): $(SED) -f man/man.sed $< > $@ .man.$(manext7): $(SED) -f man/man.sed $< > $@ .man.$(manext8): $(SED) -f man/man.sed $< > $@ man: $(man_MANS) cleanman: rm -f $(man_MANS) .PHONY: man cleanman ChangeLog: @[ -d $(srcdir)/.git ] && (cd $(srcdir); git --no-pager log --abbrev-commit | \ egrep -v '^commit [0-9a-f]+$$' > $@) || true .PHONY: ChangeLog rpm: dist @test -d $(rpmdir)/SOURCES || $(MKDIR_P) $(rpmdir)/SOURCES @mv -f $(DIST_ARCHIVES) $(rpmdir)/SOURCES @cp -p VERSION $(rpmdir)/SOURCES @rpmbuild --define '_topdir $(rpmdir)' \ --define '_tmppath %{_topdir}/TMP' \ --define "_sysconfdir $(DESTDIR)$(sysconfdir)" \ -ba SPECS/nmh.spec .PHONY: rpm gcov: gcov-rebuild gcov-run gcov-process gcov-report gcov-rebuild: @echo rebuilding with AM_CFLAGS=--coverage . . . @(make clean && make AM_CFLAGS=--coverage) > /dev/null gcov-run: make check AM_CFLAGS=--coverage gcov-process: @for i in `find . -name '*.gcda'`; do \ gcov -pro `echo $$i | $(SED) 's%\\(.*\\)/%\\1 %'`; \ done gcov-report: @for i in `find . -name '*.gcno'`; do \ if test -f `echo $$i | sed 's%\.gcno%.gcda%'`; then :; else \ echo untested: $$i; \ fi; \ done gcov-mostlyclean: @find . -name '*.gcno' -o -name '*.gcda' | xargs rm gcov-clean: gcov-mostlyclean @find . -name '*.gcov' | xargs rm .PHONY: gcov gcov-rebuild gcov-run gcov-process gcov-report \ gcov-mostlyclean gcov-clean upload: dist @if test -z "$(SAVANNAH_USERNAME)"; then \ echo "You need to set SAVANNAH_USERNAME to the your username on savannah.gnu.org." ;\ echo "You can set it either in your environment or on the make command line."; \ false; \ fi @echo "Did you run 'make distcheck' already?" @if test -z "$(SKIP_GPG_SIG)"; then \ echo "Creating GPG signature (set SKIP_GPG_SIG to bypass this step)"; \ gpg --output $(DIST_ARCHIVES).sig --detach-sig $(DIST_ARCHIVES); \ fi @echo "Setting permissions for savannah.gnu.org" chmod 664 $(DIST_ARCHIVES) if test -f $(DIST_ARCHIVES).sig; then \ chmod 664 $(DIST_ARCHIVES).sig; \ fi @echo "Uploading to savannah" scp -p $(DIST_ARCHIVES)* $(SAVANNAH_USERNAME)@dl.sv.nongnu.org:/releases/nmh .PHONY: upload # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: nmh-1.7.1-RC3/man/000755 007761 000024 00000000000 13243043705 013536 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/missing000755 007761 000024 00000015331 12070355546 014373 0ustar00kenhstaff000000 000000 #! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2012-06-26.16; # UTC # Copyright (C) 1996-2012 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=http://www.perl.org/ flex_URL=http://flex.sourceforge.net/ gnu_software_URL=http://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'automa4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: nmh-1.7.1-RC3/mts/000755 007761 000024 00000000000 13243043703 013564 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/NEWS000644 007761 000024 00000074372 13240377015 013500 0ustar00kenhstaff000000 000000 # NEWS - Release notes for nmh 1.7 # Welcome to nmh, the new version of the classic MH mail handling system. It's been over three years since the last release of nmh, and there have been a number of significant changes since the last release. Long-time MH and nmh uses should read careful the NOTEABLE CHANGES section, as there are some significant changes to nmh behavior. Otherwise, please see the README and INSTALL files for help on getting started with nmh. For news of future releases, subscribe to the low-volume https://lists.nongnu.org/mailman/listinfo/nmh-announce --------------- NOTABLE CHANGES --------------- The largest notable changes in the 1.7 release are: - Complete unification of network security support. All network protocols (currently, POP and SMTP) have been refactored to use a common set of security routines. This means all protocols support all SASL mechanisms (via the Cyrus-SASL library) and TLS. TLS support has been strengthened to perform certificate name validation and to require TLS 1.1 as a minimum protocol. Also, all protocols can make use of the OAuth2/XOAUTH SASL mechanism, which is supported by Gmail. - send(1) now supports adding switches to post(8) based on the address or domain of the email address in the From: header; this more easily allows users to support multiple identities. - A generic facility for passing arguments to filter programs in repl(1) by use of the -convertargs switch. - Native support for the manipulation of iCalendar requests; see mhical(1) for more details. ------------ NEW FEATURES ------------ The following are new features for the 1.7 release of nmh: - When building from source, configure will derive ${prefix} from an existing nmh installation if it finds one in your $PATH. - Added welcome message when nmh detects that its version changed. - The default locations for configuration files and support binaries have been changed. Configuration files now install into ${sysconfdir}/nmh, and support binaries are placed in ${libexecdir}/nmh. If you are upgrading an existing installation you should look for old configuration files in ${sysconfdir} and merge any local customizations into the new files in ${sysconfdir}/nmh, then remove the old files. ${libdir} will also contain obsolete support programs that should be removed. - All TLS connections now perform certificate validation (including hostname matching) by default; can be disabled on a per-application basis. - post now defaults to port 587 on 'smtp' message submission. - A value of 0 for the width switch of scan(1), inc(1), ap(1), dp(1), fmttest(1), and mhl(1) now means as many characters as the format engine can produce [Bug #15274]. That amount is limited by internal buffers. - If a component has trailing whitespace, e.g., body:component="> ", mhl now trims that whitespace off when filtering blank text lines. - An "rtrim" flag has been added to mhl to remove any trailing whitespace from filtered text lines. A corresponding "nortrim" flag has also been added. - Added getmymbox and getmyaddr mh-format(5) function escapes. - New -[no]changecur, -fixtype, -decodetypes, and -[no]crlflinebreaks switches have been added to mhfixmsg(1). - mhfixmsg now removes an extraneous trailing semicolon from header parameter lists. - Added -convertargs switch to repl(1), to pass arguments to programs specified in the user's profile or mhn.defaults to convert message content. - Added mhical(1), to display, reply to, and cancel iCalendar (RFC 5545) event requests. - Added multiply mh-format(5) function. - "mhparam bindir" prints the path to the directory containing the public executables (${bindir}). - New "-prefer" switch for mhshow (and mhlist and mhshow), to allow specifying the preferred content types to show, if present in a multipart alternative. - mh-format now has %(kilo) and %(kibi) functions, to allow printing numbers with SI or IEC quantities, e.g. "10K", "2.3Mi". - Support for the -sendmail flag to send/post to change the sendmail binary when using the sendmail/pipe MTS. - Added support to send(1) to specify switches to post(1) based on address or domain name in From: header line in message draft. - post(8) -snoop now attempts to decode base64-encoded SMTP traffic. - folder(1) -nocreate now prints a warning message for a non-existent folder. - mhfixmsg(1) now allows -decodetext binary, though 8bit is still the default. - inc(1) and msgchk(1) now support TLS encryption natively. - All network protocols support the XOAUTH authentication mechanism. - Support for SMTPUTF8 (RFC 6531) has been added. mhshow(1) already supported RFC 6532, assuming all 8-bit message header field bodies are UTF-8 and use of a UTF-8 locale. - mhfixmsg now replaces RFC 2047 encoding with RFC 2231 encoding of name and filename parameters in Content-Type and Content-Disposition headers, respectively. - If a message body contains 8-bit bytes, post(8) uses SMTP 8BITMIME if the server supports it. If not, post fails with a message to the user to encode the message for 7-bit transport. - Fewer lseek(2)s will be used when reading headers in the common case. - ./configure's --enable-debug has been removed; it did nothing. - configure now defaults to enabling each of TLS and Cyrus SASL if the necessary headers and libraries are found. - Moved build_nmh to top-level directory. - Better error reporting for connections to network services. --------- BUG FIXES --------- - The format scanner no longer subtracts 1 from the width. This has the effect of no longer counting the trailing newline in the output of scan(1), inc(1), and the other programs that rely on the format scanner. - The first character of some very short (less than 4 characters) message bodies is no longer dropped. - Single-character headers can be reliably formatted, etc., instead of apparently being missing. - mhfixmsg now adds a Content-Transfer-Encoding header at the message level, if needed after decoding text parts. - mhbuild now checks whether all text parts need a Content-Transfer-Encoding header, not just those with a character set not specified. - mhbuild no longer parses lines that start with # as directives with -nodirectives. - repl now makes sure that any Fcc header in a replied-to message is not copied into the outgoing draft by default, and that the -fcc switch actually works in the absence of a Fcc header in the replied-to message. - A Content-ID is generated for message/external-body entities as required by RFC 2045, even if -nocontentid is supplied to mhbuild. - post will now expand aliases on a "From" line when doing a BCC [Bug #51098]. - scan can now handle empty files without violating an assert [Bug #51693]. - An error when writing an error message, e.g. EPIPE, no longer causes recursion until the stack is exhausted. - rcvdist(1) now passes switch arguments to post(8). - The uses of %{charset} in mhn.defaults were wrapped with double quotes. ------------------- DEPRECATED FEATURES ------------------- - Support for the MHPDEBUG environment variable is deprecated and will be removed from a future nmh release. Instead, use the -debug switch to pick. - With the move of support binaries from ${libdir} to ${libexecdir}/nmh, the mostly undocumented 'libdir' mhparam(1) component has been replaced by a new 'libexecdir' component. 'libdir' will be removed in a future release. ----------------- OBSOLETE FEATURES ----------------- - The undocumented -queue switch to post was deprecated in nmh 1.6, and was removed in this release. - conflict(8) was deprecated in nmh 1.6, and was removed in this release. - mhtest(8) was deprecated in nmh 1.6, and was removed in this release. - msh(1) was deprecated in nmh 1.6, and was removed in this release. - Support in alias files for the the "*" address-group (everyone) was deprecated in nmh 1.6, and was removed in this release. - Support for multiple hostnames in the "servers" entry of mts.conf has been removed. - Support in alias files for expanding aliases based on group membership (=) and primary group (+) has been removed. As always, feedback is welcome. -- The nmh team nmh-workers@nongnu.org ---------------------------------------------------------------------------- # # NEWS - Release notes for nmh 1.6 # Welcome to nmh, the new version of the classic MH mail handling system. It's been nearly two years since the last release of nmh, and there have been a number of significant changes since the last release. Long-time MH and nmh uses should read careful the NOTEABLE CHANGES section, as there are some significant changes to nmh behavior. Otherwise, please see the README and INSTALL files for help on getting started with nmh. ------------ NEW FEATURES ------------ The following are new features for the 1.6 release of nmh: - All nmh programs will now warn about multiple profile entries for the same non-null, non-comment component. In previous versions, all but the first were silently ignored. - mhmail now supports all post(8) options, or optionally can use send(1) with all of its options. Its formerly undocumented -resent switch has been documented. And it has new -attach, -headerfield, and -send/-nosend switches. - Default to flock() locking on OpenBSD and Darwin. - Added -directives support to mhbuild(1) to control whether or not mhbuild will honor MIME directives by default. And added support for special #on/#off/#pop directives to control the MIME directive processing state. - Added -messageid switch to send(1) and post(8). This allows selection of the style to use for generated Message-ID and Content-ID header fields. The default localname style is pid.time@localname, where time is in seconds, and matches previous behavior. The random style replaces the localname with some (pseudo)random bytes and uses microsecond-resolution time. - Added -clobber switch to mhstore(1) to control overwriting of existing files. - Added -outfile switch to mhstore(1). - Added -noall/-all switches to sortm(1). sortm -noall requires a messages argument. - $PAGER overrides the compiled-in default pager command. - Added etc/scan.highlighted format file, as an example of how to highlight/colorize the output of scan(1). - 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. - burst(1) now can burst MIME-formatted digests (messages that contain message/rfc822 parts instead of messages formatted with RFC 934). - All proc entries (showproc, moreproc, etc) can now accept entries that contain spaces and shell metacharacters. If found, such entries will either be space-split or processed by /bin/sh. - A new program, fmttest(1) is included to help debug format files. See NOTABLE CHANGES below. - mhshow/mhstore now have support for RFC-2017 (access-type=url) for external message bodies. - Added -retainsequences switch to refile(1). - A new program, mhfixmsg(1), is included to rewrite MIME messages with various transformations. See NOTABLE CHANGES below. - Added -[no]rmmproc switches to rmm(1). - Added support for Content-Disposition header (RFC 2183) to mhstore(1) and mhn(1) when used with -auto. - All nmh commands now support transactional locking for sequence files. See NOTABLE CHANGES below. - There is no longer a per-folder maximum number of sequences. - For the SMTP MTA TLS can now be negotiated at the beginning of the connection with the -initialtls switch. - Messages can now be selected using a relative offset from some other message, or from the start or end of a sequence. See mh-sequence(5). - The -changecur and -nochangecur switches have been added to mhlist(1). - mhbuild(1) can now encode 8-bit message headers using RFC-2047 encoding rules. See NOTABLE CHANGES below. - The whatnow(1) attach feature will determine the content type of an attachment using a program such as file --mime-type, if available at configuration time. If not, it will use mhshow-suffix- entries as before. The -v switch to attach causes it to display the mhbuild directive that send(1) will use. - mhbuild(1) now supports the -auto/-noauto flags (to be used by send(1) when invoking mhbuild automatically). - mhbuild(1) now is automatically run by send, to insure that all outgoing messages have proper MIME formatting. See NOTABLE CHANGES below. - A new header, "Attach", is supported by mhbuild; it is used to replace previous functionality (which by default used a header named Nmh-Attachment). See NOTABLE CHANGES below. - The default Content-Transfer-Encoding for text parts is now 8bit. - mhbuild(1) now supports a selectable Content-Transfer-Encoding - If nmh was configured with iconv(3) support, mhshow will convert, if necessary, the charset of text/plain content to match the user's locale setting. See NOTABLE CHANGES below. - Added support for %{charset} display string escape to mhshow(1). - The MIME parsing and generating routines now support RFC 2231 extended parameter information. - mh-mime(7) now provides an introduction to nmh's MIME handling. - mhshow(1) will now by default display all text content under one pager, and display markers for non-text and non-inline content. The content markers are changeable via mh-format(5). See NOTABLE CHANGES below. ----------------- OBSOLETE FEATURES ----------------- - Changed exit status of each nmh command's -version and -help switches from 1 to 0. - The following environment variables were deprecated in nmh 1.5 and removed from this release: MHPOPDEBUG (use -snoop command line switch instead) MM_NOASK (use -nolist and -nopause command line switches instead) NOMHNPROC (use -nocheckmime command line switch instead) FACEPROC (undocumented faceproc feature removed) - Changed repl and dist default to -noatfile. The default of -atfile was deprecated in nmh 1.5. If there are no requests to maintain -atfile, it will be removed in the future. - The undocumented -queue switch to mhmail has been removed. - 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, -push/-nopush, and -remove/-noremove switches are not supported by post. Note that spost did not support -whom or Dcc, and neither does post when using sendmail/pipe. And spost would expand blind aliases and send them in the message; post with sendmail/pipe refuses to do that. For backward compatibility, spost has been replaced by a simple shell script that exec's post -mts sendmail/pipe. See NOTABLE CHANGES below. - 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". - The support for the undocumented NOPUBLICSEQ preprocessor definition to disable public sequence support has been removed. - Support for the -normalize and -nonormalize switches to the ali(1) and ap(8) commands has been removed. - "make install" no longer strips executables. Use "make install-strip" instead. - The environment variable MM_CHARSET to indicate the native character set is no longer supported. The native character set will be solely determined by the locale settings. - Temporary files are stored in the first non-null location of {MHTMPDIR environment variable, TMPDIR environment variable, MH Path}. They are no longer be stored in the location specified by the TMP environment variable. - Instead of printing PostScript attachments, by default, from mhshow, try to find a suitable viewer. - Support for parallel display of multipart/parallel content has been removed from mhshow; all multipart content will be displayed in serial. - Support for -pause/-nopause switches on mhshow has been removed. ------------------- DEPRECATED FEATURES ------------------- - The undocumented -queue switch to post is deprecated/obsolete and will be removed in the next release. It supports the SMTP XQUE verb, which is obsolete according to 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. - Support in alias files for the the "*" address-group is obsolescent and will be removed in a future release. --------- BUG FIXES --------- - Replaced utilities that operate on pbm files with those that operate on pnm files in etc/mhn.defaults [Bug #15152]. - Removed obsolete BUGS section at end of rcvstore(1) man page [Bug #4361]. - Fixed -nocc me doesn't account for Alternate-Mailboxes [Bug #36635]. - Propagate Mail-Followup-To [Bug #5571]. - "mark -sequence cur -delete all" now works for cur as well as any other sequence, to allow clearing of the current message indication. - The first alias contained in a blind list is now expanded. The mh-alias(5) man page was updated to show that blind lists must not be terminated with, or contain, a trailing semicolon [Bug #15604]. - Fixed sendfiles(1) to always provide a From: address. Also, updated its switches. - 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. - post(8) -sasl now honours username in .netrc [Bug #23168]. whom(1), send(1), inc(1), and msgchk(1) also benefit from this fix. And, nmh now supports specification of any valid filename in place of $HOME/.netrc. - Added quoting of local part of invalid address in message being replied to [Bug #26780]. - Fix segmentation faults for %(putlit) and %(zputlit) format escapes when the "str" register was NULL. - Encode and decode text MIME types with canonical line breaks properly. - mhstore(1) now obeys its -noverbose switch. - Properly report the input filename when mhbuild encounters errors. - Set the content-transfer-encoding properly when attaching message/rfc822 content. --------------- NOTABLE CHANGES --------------- The biggest changes in this release are in the arena of MIME handling. Specifically relating to MIME composition and display. On the composition front, mhbuild(1) will now automatically be run by send(1) for all drafts. Specifically, mhbuild is now run with the new -auto flag, which will suppress the processing of mhbuild directives and cause mhbuild to silently exit if the draft is already MIME-formatted. When invoking mhbuild manually via the "mime" command at the WhatNow? prompt, mhbuild will behave as before and process mhbuild directives. In both cases (automatic and manual invocation) mhbuild will encode email headers according to RFC-2047 rules. Mhbuild also will use RFC 2231 encoding rules for MIME parameters when appropriate. In addition, the attach system has been substantially reworked; the new header name is now "Attach" (to better align with other MUA behavior) and cannot be changed by the end-user. The existing "attach" command simply adds the filename(s) to the draft in new Attach: headers, and the actual file processing is done by mhbuild; this attachment processing will take place in either automatic or manual mode. On the display front, mhshow(1) will now automatically convert text into the user's native character set using iconv, if nmh was built with iconv support. Also, mhshow will now by default only display text content that was not marked as an attachment. By default all displayed content wll be run under one pager, as opposed to individual pagers for each part as was in the past. Non-displayed parts will be indicated using a marker string, which can be customized by a new mh-format(5) string. All nmh utilities now understand RFC 2231-encoded MIME parameters and will automatically convert the encoded parameters into the native character set, when appropriate (again, assuming nmh was built with iconv support). In other changes, sequence files are now locked using transactional locks: locks that are held across sequence file reading, modification, and writing. The locking algorithm used for spool files and nmh data files is now runtime configurable. For people that struggle with mh-format(5) files, a new utility for testing them has been developed: fmttest(1). It includes the ability to trace the execution of format instructions. For users that wish to use Unix utilities on their mail, a new utility to transform MIME messages to more easily-digestable format is now available: mhfixmsg(1). It supports a number of options to control the message transformation. For users of spost(8), the support for spost has been rolled into post(8) under a new sendmail/pipe MTS. A shell script emulating the old behavior of spost has been provided. As always, feedback is welcome. -- The nmh team nmh-workers@nongnu.org ---------------------------------------------------------------------------- # # NEWS - Release notes for nmh 1.5 # Welcome to nmh, the new version of the classic MH mail handling system. Long-time MH and nmh users should read carefully the NOTABLE CHANGES section, as there are some subtle but significant changes to the way nmh now behaves. Otherwise, please see the README and INSTALL files for help on getting started with nmh. ------------ NEW FEATURES ------------ The following are new features for the 1.5 release of nmh. - Improved performance for TLS encryption of the SMTP protocol. - MH-E and POP support are now always compiled in. - The selection of a locking directory for dot-locking files is now controllable via configure. - fileproc and mhlproc mh-profile are now obeyed by send, rcvdist, and whatnow. - New mh-format instructions have been implemented: %(putlit), %(concataddr), %(myhost), %(myname), %(localmbox). See mh-format(5) for more details. - Nmh's idea of the local mailbox is now configurable via a new profile entry, Local-Mailbox. See mh-profile(5) for more details. - comp, forw, and dist now process all component templates through mh-format(5), and now all support new command line arguments -from, -to, -cc, -fcc, and -subject. - burst(1) now supports any valid message delimiter according to RFC 934. - post(8) now requires a From: header in all drafts that it processes; see NOTABLE CHANGES below for more details. - post(8) can now explicitly control the SMTP envelope address either via the Sender: header or the new Envelope-From: header. - The -attach option is now the default for send (using the header Nmh-Attachment) and -attachformat 1 is the default attachment type. - repl and dist now support new switches -atfile and -noatfile to control the creation of the ./@ link to the message being replied or redistributed. The current default is -atfile. - Support (if available) for readline editing and filename completion at the WhatNow? prompt. - Support for using an external command to filter the body of a message through in mhl. See mhl(1) for more details, specifically, the "format" keyword, the "formatproc" entry in mh-profile(5), and the -fmtproc switch for mhl and repl. - Preliminary support for improved MIME handling when replying to messages! Yes, a long requested feature has a solution. A perl script called replyfilter is available; it is designed to act as a mhl external filter to process MIME messages in a more logical way. It is available in $(srcdir)/docs/contrib/replyfilter or is typically installed as $(prefix)/share/doc/nmh/contrib/replyfilter. See the comments at the top of replyfilter for usage information; it will likely require some adjustment for your site. replyfilter requires the MIME-Tools and MailTools perl modules. ---------------------------- OBSOLETE/DEPRECATED FEATURES ---------------------------- The following features have either been removed completely or marked as officially deprecated for removal in a future release of nmh. - The creation of the ./@ link to the message being replied or redistributed is deprecated; -noatfile will be the default in the next release. If there are no requests to maintain -atfile it will be removed in a future release. - Old code enabled by the UCI preprocessor definition has been removed. - All configuration options that were formerly only adjustable by editing config.h have either been moved into configure or removed completely. - Support for the built-in ftp client (used when dealing with external-body message parts in MIME messages) has been removed. - The following environment variables are marked as obsolete/deprecated. Support for them will be removed from the next nmh release: MHPOPDEBUG (use -snoop command line switch instead) MM_NOASK (use -nolist and -nopause command line switches instead) NOMHNPROC (use -nocheckmime command line switch instead) FACEPROC (undocumented faceproc feature to be removed) - The hostable option of mts.conf is no longer needed and has been removed. --------------- NOTABLE CHANGES --------------- The largest change is that post(8) now requires a From: header in all drafts that it processes. The impetus for this change has been the evolution of email and client systems. When MH was first developed the norm was to have tightly managed clients that were part of the same domain as a user's email address. This is no longer a valid assumption, and the algorithm used by nmh to determine the user's local mailbox is no longer a reasonable default. Unfortunately, the way that nmh uses the user's local mailbox used to happen very late in the message process; it was handled by post during message submission. If no From: header exists in the current draft post would insert one based on it's idea of the local mailbox, which was frequently wrong. After a long discussion within the nmh development community, it was decided that the only reasonable way forward was to move the local mailbox handling up a level and place it under more direct control of the end user. post(8) no longer will try to determine the local mailbox name; it will take that information from the draft message. Thus a From: header is now required in all drafts. As part of these changes, all message composition utilities now process their component files using mh-format. All of the default component files have been modified to include a From: header in them; this will give the user a chance to see nmh's idea of the local mailbox and modify it if desired. The new mh-profile(5) entry Local-Mailbox can be used to adjust the local mailbox name if the system default is not appropriate. So how should end-users adapt to these changes? Here are some suggestions: 1) If you use the default component files, everything should basically work the same for you. You should see a From: header in the drafts of your messages. If the address you see in the From: header is incorrect you can change it via the Local-Mailbox profile entry. You can also use the -from switch to change it on a per-command basis. 2) If you have custom component files that include a From: header or you perform custom processing on drafts that end up placing a From: header in the draft message, everything should work as before. 3) If you have custom component files that do NOT include a From: header then you will have to adapt then to include a From: header. You can either simply hard-code the correct From: header or use the default component files as a guide (see mh-format(5) for more details, specifically the %(localmbox) function). The other significant change is the support for filters in mhl. Included in the distribution is replyfilter, a filter designed for sane processing of MIME messages during replies. Since this isn't as integrated into nmh as we would prefer, it's included in the contrib directory as an optional component. Please try it out and give us feedback. -- The nmh team nmh-workers@nongnu.org ---------------------------------------------------------------------------- # # NEWS - Release notes for nmh 1.4 # This releases contains numerous bugfixes and a number of new features. The new features include: - SASL security layers (encryption) are now supported for the SMTP MTA. - TLS is now supported for the SMTP MTA. - inc can now incorporate mail from Maildir drops. - You can now select the SMTP server and port from either "send" or a user's mh_profile (you could always select the server; that option is now documented). These are available via the -server and -port switches. - All networking code has been modified to use the new networking APIs (getaddrinfo and friends). All networking code (with the exception of the built-in ftp client) now supports IPv6. - New commands 'new', 'fnext', 'fprev', and 'unseen' for showing folders with unseen mail (or mail in any specified sequence), changing to next such folder, changing to previous such folder, and scanning all such folders, respectively. This is based on Luke Mewburn's 'new': http://www.mewburn.net/luke/src/new - nmh will no longer attempt to install a mhn.defaults file that causes mhshow to open its own xterms. A large chunk of old code has been garbage collected. Specifically, support for APOP, RPOP, NNTP (including bboards) and MPOP is now gone. Also gone is support for prefixing a \01 in the "servers" entry in mts.conf to iterate over all servers on a named network. ---------------------------------------------------------------------------- # # NEWS - Release notes for nmh 1.3 # It's been over two years since the 1.2 release; but the changes here are mostly minor; largely bugfixes. You should note that we have changed the default configuration to allow all supported forms of address masquerading. For more details please see the --enable-masquerade option to configure, and the mh-tailor and post man pages. nmh-1.7.1-RC3/README000644 007761 000024 00000002470 11732520431 013643 0ustar00kenhstaff000000 000000 Installing ---------- Please read the INSTALL file. Copying ------- nmh uses a BSD-style license, which should be in the top-level of the distribution in a file named COPYRIGHT. Developers ---------- Information of interest to nmh developers can be found in the README.developers file in the docs subdirectory of this distribution. If you're hacking on the code, you should also definitely subscribe to the nmh-workers mailing list. To do so, please visit the nmh-workers info page at . If you're interested in working on nmh, but aren't sure what to do, see the TODO file in the docs subdirectory. There's plenty of work there. Working with your shell ----------------------- The files COMPLETION-BASH, COMPLETION-TCSH and COMPLETION-ZSH in the docs subdirectory give cookbook examples of how to use the enhanced features of these shells with nmh. There is also a section in Jerry Peek's book covering nmh/MH and working with the shell. The section is available online at . For More information -------------------- There is more information, including a FAQ and a bit of historical information in the docs subdirectory. There are also links to further documentation on the nmh website located at . nmh-1.7.1-RC3/sbr/000755 007761 000024 00000000000 13243043704 013550 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/SPECS/000755 007761 000024 00000000000 13243043705 013640 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/000755 007761 000024 00000000000 13243043705 013742 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/thirdparty/000755 007761 000024 00000000000 13243043704 015154 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/uip/000755 007761 000024 00000000000 13243043705 013560 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/VERSION000644 007761 000024 00000000012 13243042457 014027 0ustar00kenhstaff000000 000000 1.7.1-RC3 nmh-1.7.1-RC3/ylwrap000755 007761 000024 00000015536 12070355546 014247 0ustar00kenhstaff000000 000000 #! /bin/sh # ylwrap - wrapper for lex/yacc invocations. scriptversion=2012-12-21.17; # UTC # Copyright (C) 1996-2012 Free Software Foundation, Inc. # # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . get_dirname () { case $1 in */*|*\\*) printf '%s\n' "$1" | sed -e 's|\([\\/]\)[^\\/]*$|\1|';; # Otherwise, we want the empty string (not "."). esac } # guard FILE # ---------- # The CPP macro used to guard inclusion of FILE. guard() { printf '%s\n' "$1" \ | sed \ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \ -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g' \ -e 's/__*/_/g' } # quote_for_sed [STRING] # ---------------------- # Return STRING (or stdin) quoted to be used as a sed pattern. quote_for_sed () { case $# in 0) cat;; 1) printf '%s\n' "$1";; esac \ | sed -e 's|[][\\.*]|\\&|g' } case "$1" in '') echo "$0: No files given. Try '$0 --help' for more information." 1>&2 exit 1 ;; --basedir) basedir=$2 shift 2 ;; -h|--h*) cat <<\EOF Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]... Wrapper for lex/yacc invocations, renaming files as desired. INPUT is the input file OUTPUT is one file PROG generates DESIRED is the file we actually want instead of OUTPUT PROGRAM is program to run ARGS are passed to PROG Any number of OUTPUT,DESIRED pairs may be used. Report bugs to . EOF exit $? ;; -v|--v*) echo "ylwrap $scriptversion" exit $? ;; esac # The input. input="$1" shift # We'll later need for a correct munging of "#line" directives. input_sub_rx=`get_dirname "$input" | quote_for_sed` case "$input" in [\\/]* | ?:[\\/]*) # Absolute path; do nothing. ;; *) # Relative path. Make it absolute. input="`pwd`/$input" ;; esac input_rx=`get_dirname "$input" | quote_for_sed` # Since DOS filename conventions don't allow two dots, # the DOS version of Bison writes out y_tab.c instead of y.tab.c # and y_tab.h instead of y.tab.h. Test to see if this is the case. y_tab_nodot=false if test -f y_tab.c || test -f y_tab.h; then y_tab_nodot=true fi # The parser itself, the first file, is the destination of the .y.c # rule in the Makefile. parser=$1 # A sed program to s/FROM/TO/g for all the FROM/TO so that, for # instance, we rename #include "y.tab.h" into #include "parse.h" # during the conversion from y.tab.c to parse.c. sed_fix_filenames= # Also rename header guards, as Bison 2.7 for instance uses its header # guard in its implementation file. sed_fix_header_guards= while test "$#" -ne 0; do if test "$1" = "--"; then shift break fi from=$1 # Handle y_tab.c and y_tab.h output by DOS if $y_tab_nodot; then case $from in "y.tab.c") from=y_tab.c;; "y.tab.h") from=y_tab.h;; esac fi shift to=$1 shift sed_fix_filenames="${sed_fix_filenames}s|"`quote_for_sed "$from"`"|$to|g;" sed_fix_header_guards="${sed_fix_header_guards}s|"`guard "$from"`"|"`guard "$to"`"|g;" done # The program to run. prog="$1" shift # Make any relative path in $prog absolute. case "$prog" in [\\/]* | ?:[\\/]*) ;; *[\\/]*) prog="`pwd`/$prog" ;; esac # FIXME: add hostname here for parallel makes that run commands on # other machines. But that might take us over the 14-char limit. dirname=ylwrap$$ do_exit="cd '`pwd`' && rm -rf $dirname > /dev/null 2>&1;"' (exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 mkdir $dirname || exit 1 cd $dirname case $# in 0) "$prog" "$input" ;; *) "$prog" "$@" "$input" ;; esac ret=$? if test $ret -eq 0; then for from in * do to=`printf '%s\n' "$from" | sed "$sed_fix_filenames"` if test -f "$from"; then # If $2 is an absolute path name, then just use that, # otherwise prepend '../'. case $to in [\\/]* | ?:[\\/]*) target=$to;; *) target="../$to";; esac # Do not overwrite unchanged header files to avoid useless # recompilations. Always update the parser itself: it is the # destination of the .y.c rule in the Makefile. Divert the # output of all other files to a temporary file so we can # compare them to existing versions. if test $from != $parser; then realtarget="$target" target=tmp-`printf '%s\n' "$target" | sed 's|.*[\\/]||g'` fi # Munge "#line" or "#" directives. Don't let the resulting # debug information point at an absolute srcdir. Use the real # output file name, not yy.lex.c for instance. Adjust the # include guards too. sed -e "/^#/!b" \ -e "s|$input_rx|$input_sub_rx|" \ -e "$sed_fix_filenames" \ -e "$sed_fix_header_guards" \ "$from" >"$target" || ret=$? # Check whether files must be updated. if test "$from" != "$parser"; then if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then echo "$to is unchanged" rm -f "$target" else echo "updating $to" mv -f "$target" "$realtarget" fi fi else # A missing file is only an error for the parser. This is a # blatant hack to let us support using "yacc -d". If -d is not # specified, don't fail when the header file is "missing". if test "$from" = "$parser"; then ret=1 fi fi done fi # Remove the directory. cd .. rm -rf $dirname exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: nmh-1.7.1-RC3/uip/ali.c000644 007761 000024 00000011561 13243042053 014470 0ustar00kenhstaff000000 000000 /* ali.c -- list nmh mail aliases * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #define ALI_SWITCHES \ X("alias aliasfile", 0, ALIASW) \ X("noalias", 0, NALIASW) \ X("list", 0, LISTSW) \ X("nolist", 0, NLISTSW) \ 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; extern struct aka *akahead; /* * prototypes */ static void print_aka (char *, int, int); static void print_usr (char *, int); int main (int argc, char **argv) { int i, vecp = 0, inverted = 0, list = 0; int noalias = 0; char *cp, **ap, **argp, buf[BUFSIZ]; /* Really only need to allocate for argc-1, but must allocate at least 1, so go ahead and allocate for argc char pointers. */ char **vec = mh_xmalloc (argc * sizeof (char *)), **arguments; struct aka *ak; if (nmh_init(argv[0], 1)) { return 1; } mts_init (); arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [switches] aliases ...", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version (invo_name); done (0); case ALIASW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if ((i = alias (cp)) != AK_OK) adios (NULL, "aliasing error in %s - %s", cp, akerror (i)); continue; case NALIASW: noalias++; continue; case LISTSW: list++; continue; case NLISTSW: list = 0; continue; case USERSW: inverted++; continue; case NUSERSW: inverted = 0; continue; } } if (vecp < argc) { vec[vecp++] = cp; } else { /* Should never happen, but try to protect against code changes that could allow it. */ adios (NULL, "too many arguments"); } } if (!noalias) { /* allow Aliasfile: profile entry */ if ((cp = context_find ("Aliasfile"))) { char *dp = NULL; for (ap = brkstring(dp = mh_xstrdup(cp), " ", "\n"); ap && *ap; ap++) if ((i = alias (*ap)) != AK_OK) adios (NULL, "aliasing error in %s - %s", *ap, akerror (i)); mh_xfree(dp); } alias (AliasFile); } /* * If -user is specified */ if (inverted) { if (vecp == 0) adios (NULL, "usage: %s -user addresses ... (you forgot the addresses)", invo_name); for (i = 0; i < vecp; i++) print_usr (vec[i], list); } else { if (vecp) { /* print specified aliases */ for (i = 0; i < vecp; i++) print_aka (akvalue (vec[i]), list, 0); } else { /* print them all */ for (ak = akahead; ak; ak = ak->ak_next) { char *res; printf ("%s: ", ak->ak_name); pos += strlen (ak->ak_name) + 1; res = akresult(ak); print_aka(res, list, pos); free(res); } } } free (vec); done (0); return 1; } static void print_aka (char *p, int list, int margin) { char c; if (p == NULL) { puts(""); return; } while ((c = *p++)) { switch (c) { case ',': if (*p) { if (list) printf ("\n%*s", margin, ""); else { if (pos >= 68) { printf (",\n "); pos = 2; } else { printf (", "); pos += 2; } } } case 0: break; default: pos++; putchar (c); } } putchar ('\n'); pos = 1; } static void print_usr (char *s, int list) { char *cp, *pp, *vp; struct aka *ak; struct mailname *mp, *np; if ((pp = getname (s)) == NULL) adios (NULL, "no address in \"%s\"", s); if ((mp = getm (pp, NULL, 0, NULL, 0)) == NULL) adios (NULL, "bad address \"%s\"", s); while (getname ("")) continue; vp = NULL; for (ak = akahead; ak; ak = ak->ak_next) { pp = akresult (ak); while ((cp = getname (pp))) { if ((np = getm (cp, NULL, 0, NULL, 0)) == NULL) continue; if (!strcasecmp (FENDNULL(mp->m_host), FENDNULL(np->m_host)) && !strcasecmp (FENDNULL(mp->m_mbox), FENDNULL(np->m_mbox))) { vp = vp ? add (ak->ak_name, add (",", vp)) : getcpy (ak->ak_name); mnfree (np); while (getname ("")) continue; break; } mnfree (np); } } mnfree (mp); print_aka (vp ? vp : s, list, 0); mh_xfree(vp); } nmh-1.7.1-RC3/uip/aliasbr.c000644 007761 000024 00000016606 13243042053 015345 0ustar00kenhstaff000000 000000 /* aliasbr.c -- new aliasing mechanism * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include static int akvis; static char *akerrst; struct aka *akahead = NULL; struct aka *akatail = NULL; /* * prototypes */ int alias (char *); int akvisible (void); char *akresult (struct aka *); char *akvalue (char *); char *akerror (int); static char *akval (struct aka *, char *); static int aleq (char *, char *); static char *scanp (char *); static char *getp (char *); static char *seekp (char *, char *, char **); static int addfile (struct aka *, char *); static char *getalias (char *); static void add_aka (struct aka *, char *); static struct aka *akalloc (char *); /* Do mh alias substitution on 's' and return the results. */ char * akvalue (char *s) { char *v; if (akahead == NULL) alias (AliasFile); akvis = -1; v = akval (akahead, s); if (akvis == -1) akvis = 0; return v; } int akvisible (void) { return akvis; } char * akresult (struct aka *ak) { char *cp = NULL, *dp, *pp; struct adr *ad; for (ad = ak->ak_addr; ad; ad = ad->ad_next) { pp = ad->ad_local ? akval (ak->ak_next, ad->ad_text) : getcpy (ad->ad_text); if (cp) { dp = cp; cp = concat (cp, ",", pp, NULL); free (dp); free (pp); } else cp = pp; } if (akvis == -1) akvis = ak->ak_visible; return cp; } static char * akval (struct aka *ak, char *s) { if (!s) return s; /* XXX */ /* It'd be tempting to check for a trailing semicolon and remove it. But that would break the EXMH alias parser on what would then be valid expressions: http://lists.gnu.org/archive/html/nmh-workers/2012-10/msg00039.html */ for (; ak; ak = ak->ak_next) { if (aleq (s, ak->ak_name)) { return akresult (ak); } if (strchr (s, ':')) { /* The first address in a blind list will contain the alias name, so try to match, but just with just the address (not including the list name). If there's a match, then replace the alias part with its expansion. */ char *name = getname (s); char *cp = NULL; if (name) { /* s is of the form "Blind list: address". If address is an alias, expand it. */ struct mailname *mp = getm (name, NULL, 0, NULL, 0); if (mp && mp->m_ingrp) { char *gname = add (mp->m_gname, NULL); /* FIXME: gname must be true; add() never returns NULL. * Is some other test required? */ if (gname && aleq (name, ak->ak_name)) { /* Will leak cp. */ cp = concat (gname, akresult (ak), NULL); free (gname); } } mnfree (mp); } /* Need to flush getname after use. */ while (getname ("")) continue; if (cp) { return cp; } } } return mh_xstrdup(s); } static int aleq (char *string, char *aliasent) { char c; while ((c = *string++)) { if (*aliasent == '*') return 1; if (tolower((unsigned char)c) != tolower((unsigned char)*aliasent)) return 0; aliasent++; } return (*aliasent == 0 || *aliasent == '*'); } int alias (char *file) { int i; char *bp, *cp, *pp; char lc, *ap; struct aka *ak = NULL; FILE *fp; if (*file != '/' && !has_prefix(file, "./") && !has_prefix(file, "../")) file = etcpath (file); if ((fp = fopen (file, "r")) == NULL) { akerrst = file; return AK_NOFILE; } while (vfgets (fp, &ap) == OK) { bp = ap; switch (*(pp = scanp (bp))) { case '<': /* recurse a level */ if (!*(cp = getp (pp + 1))) { akerrst = "'<' without alias-file"; fclose (fp); return AK_ERROR; } if ((i = alias (cp)) != AK_OK) { fclose (fp); return i; } continue; case ':': /* comment */ case ';': case '#': case 0: continue; } akerrst = bp; if (!*(cp = seekp (pp, &lc, &ap))) { fclose (fp); return AK_ERROR; } if (!(ak = akalloc (cp))) { fclose (fp); return AK_LIMIT; } switch (lc) { case ':': ak->ak_visible = 0; break; case ';': ak->ak_visible = 1; break; default: fclose (fp); return AK_ERROR; } switch (*(pp = scanp (ap))) { case 0: /* EOL */ fclose (fp); return AK_ERROR; case '<': /* read values from file */ if (!*(cp = getp (pp + 1))) { fclose (fp); return AK_ERROR; } if (!addfile (ak, cp)) { fclose (fp); return AK_NOFILE; } break; default: /* list */ while ((cp = getalias (pp))) add_aka (ak, cp); break; } } fclose (fp); return AK_OK; } char * akerror (int i) { static char buffer[BUFSIZ]; switch (i) { case AK_NOFILE: snprintf (buffer, sizeof(buffer), "unable to read '%s'", akerrst); break; case AK_ERROR: snprintf (buffer, sizeof(buffer), "error in line '%s'", akerrst); break; case AK_LIMIT: snprintf (buffer, sizeof(buffer), "out of memory while on '%s'", akerrst); break; default: snprintf (buffer, sizeof(buffer), "unknown error (%d)", i); break; } return buffer; } static char * scanp (char *p) { while (isspace ((unsigned char) *p)) p++; return p; } static char * getp (char *p) { char *cp = scanp (p); p = cp; while (!isspace ((unsigned char) *cp) && *cp) cp++; *cp = 0; return p; } static char * seekp (char *p, char *c, char **a) { char *cp; p = cp = scanp (p); while (!isspace ((unsigned char) *cp) && *cp && *cp != ':' && *cp != ';') cp++; *c = *cp; *cp++ = 0; *a = cp; return p; } static int addfile (struct aka *ak, char *file) { char *cp; char buffer[BUFSIZ]; FILE *fp; if (!(fp = fopen (etcpath (file), "r"))) { akerrst = file; return 0; } while (fgets (buffer, sizeof buffer, fp)) while ((cp = getalias (buffer))) add_aka (ak, cp); fclose (fp); return 1; } static char * getalias (char *addrs) { char *pp, *qp; static char *cp = NULL; if (cp == NULL) cp = addrs; else if (*cp == 0) return (cp = NULL); /* Remove leading any space from the address. */ for (pp = cp; isspace ((unsigned char) *pp); pp++) continue; if (*pp == 0) return (cp = NULL); /* Find the end of the address. */ for (qp = pp; *qp != 0 && *qp != ','; qp++) continue; /* Set cp to point to the remainder of the addresses. */ if (*qp == ',') *qp++ = 0; for (cp = qp, qp--; qp > pp; qp--) if (*qp != 0) { if (isspace ((unsigned char) *qp)) *qp = 0; else break; } return pp; } static void add_aka (struct aka *ak, char *pp) { struct adr *ad, *ld; for (ad = ak->ak_addr, ld = NULL; ad; ld = ad, ad = ad->ad_next) if (!strcmp (pp, ad->ad_text)) return; NEW(ad); ad->ad_text = mh_xstrdup(pp); ad->ad_local = strchr(pp, '@') == NULL && strchr(pp, '!') == NULL; ad->ad_next = NULL; if (ak->ak_addr) ld->ad_next = ad; else ak->ak_addr = ad; } static struct aka * akalloc (char *id) { struct aka *p; NEW(p); p->ak_name = getcpy (id); p->ak_visible = 0; p->ak_addr = NULL; p->ak_next = NULL; if (akatail != NULL) akatail->ak_next = p; if (akahead == NULL) akahead = p; akatail = p; return p; } nmh-1.7.1-RC3/uip/anno.c000644 007761 000024 00000020712 13243042053 014654 0ustar00kenhstaff000000 000000 /* anno.c -- annotate messages * * 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. * * Four new options have been added: delete, list, number, and draft. * Message header fields are used by the new MIME attachment code in * the send command. Adding features to generalize the anno command * seemed to be a better approach than the creation of a new command * whose features would overlap with those of the anno command. * * The -draft option causes anno to operate on the current draft file * instead of on a message sequence. * * The -delete option deletes header elements that match the -component * field name. If -delete is used without the -text option, the first * header field whose field name matches the component name is deleted. * If the -delete is used with the -text option, and the -text argument * begins with a /, the first header field whose field name matches the * component name and whose field body matches the text is deleted. If * the -text argument does not begin with a /, then the text is assumed * to be the last component of a path name, and the first header field * whose field name matches the component name and a field body whose * last path name component matches the text is deleted. If the -delete * option is used with the new -number option described below, the nth * header field whose field name matches the component name is deleted. * No header fields are deleted if none of the above conditions are met. * * The -list option outputs the field bodies from each header field whose * field name matches the component name, one per line. If no -text * option is specified, only the last path name component of each field * body is output. The entire field body is output if the -text option * is used; the contents of the -text argument are ignored. If the -list * option is used in conjunction with the new -number option described * below, each line is numbered starting with 1. A tab separates the * number from the field body. * * The -number option works with both the -delete and -list options as * described above. The -number option takes an optional argument. A * value of 1 is assumed if this argument is absent. */ #include #include #include "../sbr/m_maildir.h" #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 */ static void make_comp (char **); int main (int argc, char **argv) { int inplace = 1, datesw = 1; int msgnum; char *cp, *maildir; char *comp = NULL, *text = NULL, *folder = NULL, buf[BUFSIZ]; char **argp, **arguments; struct msgs_array msgs = { 0, 0, NULL }; struct msgs *mp; int append = 0; /* append annotations instead of default prepend */ int delete = -2; /* delete header element if set */ char *draft = NULL; /* draft file name */ int isdf = 0; /* return needed for m_draft() */ int list = 0; /* list header elements if set */ int number = 0; /* delete specific number of like elements if set */ if (nmh_init(argv[0], 1)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [+folder] [msgs] [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case COMPSW: if (comp) adios (NULL, "only one component at a time!"); if (!(comp = *argp++) || *comp == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case DATESW: datesw++; continue; case NDATESW: datesw = 0; continue; case INPLSW: inplace++; continue; case NINPLSW: inplace = 0; continue; case TEXTSW: if (text) adios (NULL, "only one body at a time!"); if (!(text = *argp++) || *text == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case DELETESW: /* delete annotations */ delete = 0; continue; case DRFTSW: /* draft message specified */ draft = ""; continue; case LISTSW: /* produce a listing */ list = 1; continue; case NUMBERSW: /* number listing or delete by number */ if (number != 0) adios (NULL, "only one number at a time!"); if (argp - arguments == argc - 1 || **argp == '-') number = 1; else { if (strcmp(*argp, "all") == 0) number = -1; else if (!(number = atoi(*argp))) adios (NULL, "missing argument to %s", argp[-1]); argp++; } delete = number; continue; case APPENDSW: /* append annotations instead of default prepend */ append = 1; continue; case PRESERVESW: /* preserve access and modification times on annotated message */ annopreserve(1); continue; case NOPRESERVESW: /* don't preserve access and modification times on annotated message (default) */ annopreserve(0); continue; } } if (*cp == '+' || *cp == '@') { if (folder) adios (NULL, "only one folder at a time!"); else folder = pluspath (cp); } else app_msgarg(&msgs, cp); } /* * We're dealing with the draft message instead of message numbers. * Get the name of the draft and deal with it just as we do with * message numbers below. */ if (draft != NULL) { if (msgs.size != 0) adios(NULL, "can only have message numbers or -draft."); draft = getcpy(m_draft(folder, NULL, 1, &isdf)); make_comp(&comp); if (list) annolist(draft, comp, text, number); else annotate (draft, comp, text, inplace, datesw, delete, append); done(0); return 1; } if (!context_find ("path")) free (path ("./", TFOLDER)); if (!msgs.size) app_msgarg(&msgs, "cur"); if (!folder) folder = getfolder (1); maildir = m_maildir (folder); if (chdir (maildir) == NOTOK) adios (maildir, "unable to change directory to"); /* read folder and create message structure */ if (!(mp = folder_read (folder, 1))) adios (NULL, "unable to read folder %s", folder); /* check for empty folder */ if (mp->nummsg == 0) adios (NULL, "no messages in %s", folder); /* parse all the message ranges/sequences and set SELECTED */ for (msgnum = 0; msgnum < msgs.size; msgnum++) if (!m_convert (mp, msgs.msgs[msgnum])) done (1); make_comp (&comp); /* annotate all the SELECTED messages */ for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { if (is_selected(mp, msgnum)) { if (list) annolist(m_name(msgnum), comp, text, number); else annotate (m_name (msgnum), comp, text, inplace, datesw, delete, append); } } context_replace (pfolder, folder); /* update current folder */ seq_setcur (mp, mp->lowsel); /* update current message */ seq_save (mp); /* synchronize message sequences */ folder_free (mp); /* free folder/message structure */ context_save (); /* save the context file */ done (0); return 1; } static void make_comp (char **ap) { char *cp, buffer[BUFSIZ]; if (*ap == NULL) { printf ("Enter component name: "); fflush (stdout); if (fgets (buffer, sizeof buffer, stdin) == NULL) done (1); *ap = trimcpy (buffer); } if ((cp = *ap + strlen (*ap) - 1) > *ap && *cp == ':') *cp = 0; if (!**ap) adios (NULL, "null component name"); if (**ap == '-') adios (NULL, "invalid component name %s", *ap); if (strlen (*ap) >= NAMESZ) adios (NULL, "too large component name %s", *ap); for (cp = *ap; *cp; cp++) if (!isalnum ((unsigned char) *cp) && *cp != '-') adios (NULL, "invalid component name %s", *ap); } nmh-1.7.1-RC3/uip/annosbr.c000644 007761 000024 00000030254 13243042053 015365 0ustar00kenhstaff000000 000000 /* annosbr.c -- prepend annotation to messages * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include "../sbr/lock_file.h" #include "../sbr/m_mktemp.h" #include #include /* * static prototypes */ static int annosbr (int, char *, char *, char *, int, int, int, int); /* * This "local" global and the annopreserve() function are a hack that allows additional * functionality to be added to anno without piling on yet another annotate() argument. */ static int preserve_actime_and_modtime = 0; /* set to preserve access and modification times on annotated message */ int annotate (char *file, char *comp, char *text, int inplace, int datesw, int delete, int append) { int i, fd; struct utimbuf b; struct stat s; int failed_to_lock = 0; /* open and lock the file to be annotated */ if ((fd = lkopendata (file, O_RDWR, 0, &failed_to_lock)) == NOTOK) { switch (errno) { case ENOENT: break; default: if (failed_to_lock) { admonish (file, "unable to lock"); } else { admonish (file, "unable to open"); } break; } return 1; } if (stat(file, &s) == -1) { advise("can't get access and modification times for %s", file); preserve_actime_and_modtime = 0; } b.actime = s.st_atime; b.modtime = s.st_mtime; i = annosbr (fd, file, comp, text, inplace, datesw, delete, append); if (preserve_actime_and_modtime && utime(file, &b) == -1) advise("can't set access and modification times for %s", file); lkclosedata (fd, file); return i; } /* * Produce a listing of all header fields (annotations) whose field name matches * comp. Number the listing if number is set. Treat the field bodies as path * names and just output the last component unless text is non-NULL. We don't * care what text is set to. */ void annolist(char *file, char *comp, char *text, int number) { int c; /* current character */ int count; /* header field (annotation) counter */ char *cp; /* miscellaneous character pointer */ char *field; /* buffer for header field */ int field_size; /* size of field buffer */ FILE *fp; /* file pointer made from locked file descriptor */ int length; /* length of field name */ int n; /* number of bytes written */ char *sp; /* another miscellaneous character pointer */ if ((fp = fopen(file, "r")) == NULL) adios(file, "unable to open"); /* * Allocate a buffer to hold the header components as they're read in. * This buffer might need to be quite large, so we grow it as needed. */ field = (char *)mh_xmalloc(field_size = 256); /* * Get the length of the field name since we use it often. */ length = strlen(comp); count = 0; do { /* * Get a line from the input file, growing the field buffer as needed. We do this * so that we can fit an entire line in the buffer making it easy to do a string * comparison on both the field name and the field body which might be a long path * name. */ for (n = 0, cp = field; (c = getc(fp)) != EOF; *cp++ = c) { if (c == '\n' && (c = getc(fp)) != ' ' && c != '\t') { (void)ungetc(c, fp); break; } if (++n >= field_size - 1) { field = (char *) mh_xrealloc((void *)field, field_size += 256); cp = field + n - 1; } } /* * NUL-terminate the field.. */ *cp = '\0'; if (strncasecmp(field, comp, length) == 0 && field[length] == ':') { for (cp = field + length + 1; *cp == ' ' || *cp == '\t'; cp++) ; if (number) (void)printf("%d\t", ++count); if (text == NULL && (sp = strrchr(cp, '/')) != (char *)0) cp = sp + 1; puts(cp); } } while (*field != '\0' && *field != '-'); /* * Clean up. */ free(field); (void)fclose(fp); } /* * Set the preserve-times flag. This hack eliminates the need for an additional argument to annotate(). */ void annopreserve(int preserve) { preserve_actime_and_modtime = preserve; } static int annosbr (int fd, char *file, char *comp, char *text, int inplace, int datesw, int delete, int append) { int mode, tmpfd; char *cp, *sp; char buffer[BUFSIZ], tmpfil[BUFSIZ]; struct stat st; FILE *tmp; int c; /* current character */ int count; /* header field (annotation) counter */ char *field = NULL; /* buffer for header field */ int field_size = 0; /* size of field buffer */ FILE *fp = NULL; /* file pointer made from locked file descriptor */ int length; /* length of field name */ int n; /* number of bytes written */ mode = fstat (fd, &st) != NOTOK ? (int) (st.st_mode & 0777) : m_gmprot (); if ((cp = m_mktemp2(file, "annotate", NULL, &tmp)) == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } strncpy (tmpfil, cp, sizeof(tmpfil)); chmod (tmpfil, mode); /* * We're going to need to copy some of the message file to the temporary * file while examining the contents. Convert the message file descriptor * to a file pointer since it's a lot easier and more efficient to use * stdio for this. Also allocate a buffer to hold the header components * as they're read in. This buffer is grown as needed later. */ if (delete >= -1 || append != 0) { if ((fp = fdopen(fd, "r")) == NULL) adios(NULL, "unable to fdopen file."); field = (char *)mh_xmalloc(field_size = 256); } /* * We're trying to delete a header field (annotation )if the delete flag is * not -2 or less. A value greater than zero means that we're deleting the * nth header field that matches the field (component) name. A value of * zero means that we're deleting the first field in which both the field * name matches the component name and the field body matches the text. * The text is matched in its entirety if it begins with a slash; otherwise * the text is matched against whatever portion of the field body follows * the last slash. This allows matching of both absolute and relative path * names. This is because this functionality was added to support attachments. * It might be worth having a separate flag to indicate path name matching to * make it more general. A value of -1 means to delete all matching fields. */ if (delete >= -1) { /* * Get the length of the field name since we use it often. */ length = strlen(comp); /* * Initialize the field counter. This is only used if we're deleting by * number. */ count = 0; /* * Copy lines from the input file to the temporary file until we either find the one * that we're looking for (which we don't copy) or we reach the end of the headers. * Both a blank line and a line beginning with a - terminate the headers so that we * can handle both drafts and RFC-2822 format messages. */ do { /* * Get a line from the input file, growing the field buffer as needed. We do this * so that we can fit an entire line in the buffer making it easy to do a string * comparison on both the field name and the field body which might be a long path * name. */ for (n = 0, cp = field; (c = getc(fp)) != EOF; *cp++ = c) { if (c == '\n' && (c = getc(fp)) != ' ' && c != '\t') { (void)ungetc(c, fp); c = '\n'; break; } if (++n >= field_size - 1) { field = (char *) mh_xrealloc((void *)field, field_size *= 2); cp = field + n - 1; } } /* * NUL-terminate the field.. */ *cp = '\0'; /* * Check for a match on the field name. We delete the line by not copying it to the * temporary file if * * o The delete flag is 0, meaning that we're going to delete the first matching * field, and the text is NULL meaning that we don't care about the field body. * * o The delete flag is 0, meaning that we're going to delete the first matching * field, and the text begins with a / meaning that we're looking for a full * path name, and the text matches the field body. * * o The delete flag is 0, meaning that we're going to delete the first matching * field, the text does not begin with a / meaning that we're looking for the * last path name component, and the last path name component matches the text. * * o The delete flag is positive meaning that we're going to delete the nth field * with a matching field name, and this is the nth matching field name. * * o The delete flag is -1 meaning that we're going to delete all fields with a * matching field name. */ if (strncasecmp(field, comp, length) == 0 && field[length] == ':') { if (delete == 0) { if (text == NULL) break; for (cp = field + length + 1; *cp == ' ' || *cp == '\t'; cp++) ; if (*text == '/') { if (strcmp(cp, text) == 0) break; } else { if ((sp = strrchr(cp, '/')) != NULL) cp = sp + 1; if (strcmp(cp, text) == 0) break; } } else if (delete == -1) continue; else if (++count == delete) break; } /* * This line wasn't a match so copy it to the temporary file. */ if ((n = fputs(field, tmp)) == EOF || (c == '\n' && fputc('\n', tmp) == EOF)) adios(NULL, "unable to write temporary file."); } while (*field != '\0' && *field != '-'); /* * Get rid of the field buffer because we're done with it. */ free((void *)field); } else { /* * Find the end of the headers before adding the annotations if we're * appending instead of the default prepending. A special check for * no headers is needed if appending. */ if (append) { /* * Copy lines from the input file to the temporary file until we * reach the end of the headers. */ if ((c = getc(fp)) == '\n') rewind(fp); else { (void)putc(c, tmp); while ((c = getc(fp)) != EOF) { (void)putc(c, tmp); if (c == '\n') { (void)ungetc(c = getc(fp), fp); if (c == '\n' || c == '-') break; } } } } if (datesw) fprintf (tmp, "%s: %s\n", comp, dtimenow (0)); if ((cp = text)) { do { while (*cp == ' ' || *cp == '\t') cp++; sp = cp; while (*cp && *cp++ != '\n') continue; if (cp - sp) fprintf (tmp, "%s: %*.*s", comp, (int)(cp - sp), (int)(cp - sp), sp); } while (*cp); if (cp[-1] != '\n' && cp != text) putc ('\n', tmp); } } fflush (tmp); /* * We've been messing with the input file position. Move the input file * descriptor to the current place in the file because the stock data * copying routine uses the descriptor, not the pointer. */ if (fp && lseek(fd, (off_t)ftell(fp), SEEK_SET) == (off_t)-1) adios(NULL, "can't seek."); cpydata (fd, fileno (tmp), file, tmpfil); fclose (tmp); if (inplace) { if ((tmpfd = open (tmpfil, O_RDONLY)) == NOTOK) adios (tmpfil, "unable to open for re-reading"); lseek(fd, 0, SEEK_SET); /* * We're making the file shorter if we're deleting a header field * so the file has to be truncated or it will contain garbage. */ if (delete >= -1 && ftruncate(fd, 0) == -1) adios(tmpfil, "unable to truncate."); cpydata (tmpfd, fd, tmpfil, file); close (tmpfd); (void) m_unlink (tmpfil); } else { strncpy (buffer, m_backup (file), sizeof(buffer)); if (rename (file, buffer) == NOTOK) { switch (errno) { case ENOENT: /* unlinked early - no annotations */ (void) m_unlink (tmpfil); break; default: admonish (buffer, "unable to rename %s to", file); break; } return 1; } if (rename (tmpfil, file) == NOTOK) { admonish (file, "unable to rename %s to", tmpfil); return 1; } } /* * Close the delete file so that we don't run out of file pointers if * we're doing piles of files. Note that this will make the close() in * lkclose() fail, but that failure is ignored so it's not a problem. */ if (fp) (void)fclose(fp); return 0; } nmh-1.7.1-RC3/uip/ap.c000644 007761 000024 00000010140 13243042053 014313 0ustar00kenhstaff000000 000000 /* ap.c -- parse addresses 822-style * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #define NADDRS 100 #define WIDTH 78 #define FORMAT "%<{error}%{error}: %{text}%|%(putstr(proper{text}))%>" #define AP_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(AP); #undef X #define X(sw, minchars, id) { sw, minchars, id }, DEFINE_SWITCH_ARRAY(AP, switches); #undef X static struct format *fmt; static int dat[5]; /* * static prototypes */ static int process (char *, int); int main (int argc, char **argv) { int addrp = 0; int width = -1, status = 0; char *cp, *form = NULL, *format = NULL, *nfs; char buf[BUFSIZ], **argp; char *addrs[NADDRS + 1]; /* Includes terminating NULL. */ if (nmh_init(argv[0], 2)) { return 1; } mts_init (); argp = getarguments (invo_name, argc, argv, 1); while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [switches] addrs ...", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version (invo_name); done (0); case FORMSW: if (!(form = *argp++) || *form == '-') adios (NULL, "missing argument to %s", argp[-2]); format = NULL; continue; case FMTSW: if (!(format = *argp++) || *format == '-') adios (NULL, "missing argument to %s", argp[-2]); form = NULL; continue; case WIDTHSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); width = atoi (cp); continue; } } if (addrp == NADDRS) adios (NULL, "more than %d addresses", NADDRS); else addrs[addrp++] = cp; } addrs[addrp] = NULL; if (addrp == 0) adios (NULL, "usage: %s [switches] addrs ...", invo_name); /* get new format string */ nfs = new_fs (form, format, FORMAT); if (width == -1) { if ((width = sc_width ()) < WIDTH / 2) { /* Default: width of the terminal, but at least WIDTH/2. */ width = WIDTH / 2; } width -= 2; } else if (width == 0) { /* Unlimited width. */ width = INT_MAX; } fmt_compile (nfs, &fmt, 1); dat[0] = 0; dat[1] = 0; dat[2] = 0; dat[3] = width; dat[4] = 0; for (addrp = 0; addrs[addrp]; addrp++) status += process (addrs[addrp], width); fmt_free (fmt, 1); done (status); return 1; } struct pqpair { char *pq_text; char *pq_error; struct pqpair *pq_next; }; static int process (char *arg, int length) { int status = 0; char *cp; char error[BUFSIZ]; struct comp *cptr; struct pqpair *p, *q; struct pqpair pq; struct mailname *mp; (q = &pq)->pq_next = NULL; while ((cp = getname (arg))) { NEW0(p); if ((mp = getm (cp, NULL, 0, error, sizeof(error))) == NULL) { p->pq_text = mh_xstrdup(cp); p->pq_error = mh_xstrdup(error); status++; } else { p->pq_text = getcpy (mp->m_text); mnfree (mp); } q = (q->pq_next = p); } for (p = pq.pq_next; p; p = q) { charstring_t scanl = charstring_create (length < NMH_BUFSIZ ? length : NMH_BUFSIZ); cptr = fmt_findcomp ("text"); if (cptr) { mh_xfree(cptr->c_text); cptr->c_text = p->pq_text; p->pq_text = NULL; } cptr = fmt_findcomp ("error"); if (cptr) { mh_xfree(cptr->c_text); cptr->c_text = p->pq_error; p->pq_error = NULL; } fmt_scan (fmt, scanl, length, dat, NULL); fputs (charstring_buffer (scanl), stdout); charstring_free (scanl); mh_xfree(p->pq_text); mh_xfree(p->pq_error); q = p->pq_next; free(p); } return status; } nmh-1.7.1-RC3/uip/burst.c000644 007761 000024 00000033647 13243042053 015073 0ustar00kenhstaff000000 000000 /* burst.c -- explode digests into individual messages * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include "../sbr/m_maildir.h" #include "../sbr/m_mktemp.h" #include "mhfree.h" #define BURST_SWITCHES \ X("inplace", 0, INPLSW) \ X("noinplace", 0, NINPLSW) \ X("mime", 0, MIMESW) \ X("nomime", 0, NMIMESW) \ X("automime", 0, AUTOMIMESW) \ 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; off_t s_stop; }; /* * For the MIME parsing routines */ int debugsw = 0; /* * static prototypes */ static int find_delim (int, struct smsg *, int *); static void find_mime_parts (CT, struct smsg *, int *); static void burst (struct msgs **, int, struct smsg *, int, int, int, char *, int); static void cpybrst (FILE *, FILE *, char *, char *, int, int); /* * A macro to check to see if we have reached a message delimiter * (an encapsulation boundary, EB, in RFC 934 parlance). * * According to RFC 934, an EB is simply a line which starts with * a "-" and is NOT followed by a space. So even a single "-" on a line * by itself would be an EB. */ #define CHECKDELIM(buffer) (buffer[0] == '-' && buffer[1] != ' ') int main (int argc, char **argv) { int inplace = 0, quietsw = 0, verbosw = 0, mimesw = 1; int hi, msgnum, numburst; char *cp, *maildir, *folder = NULL, buf[BUFSIZ]; char **argp, **arguments; struct msgs_array msgs = { 0, 0, NULL }; struct smsg *smsgs; struct msgs *mp; if (nmh_init(argv[0], 1)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown\n", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [+folder] [msgs] [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case INPLSW: inplace++; continue; case NINPLSW: inplace = 0; continue; case MIMESW: mimesw = 2; continue; case NMIMESW: mimesw = 0; continue; case AUTOMIMESW: mimesw = 1; continue; case QIETSW: quietsw++; continue; case NQIETSW: quietsw = 0; continue; case VERBSW: verbosw++; continue; case NVERBSW: verbosw = 0; continue; } } if (*cp == '+' || *cp == '@') { if (folder) adios (NULL, "only one folder at a time!"); else folder = pluspath (cp); } else { app_msgarg(&msgs, cp); } } if (!context_find ("path")) free (path ("./", TFOLDER)); if (!msgs.size) app_msgarg(&msgs, "cur"); if (!folder) folder = getfolder (1); maildir = m_maildir (folder); if (chdir (maildir) == NOTOK) adios (maildir, "unable to change directory to"); /* read folder and create message structure */ if (!(mp = folder_read (folder, 1))) adios (NULL, "unable to read folder %s", folder); /* check for empty folder */ if (mp->nummsg == 0) adios (NULL, "no messages in %s", folder); /* parse all the message ranges/sequences and set SELECTED */ for (msgnum = 0; msgnum < msgs.size; msgnum++) if (!m_convert (mp, msgs.msgs[msgnum])) done (1); seq_setprev (mp); /* set the previous-sequence */ smsgs = mh_xcalloc(MAXFOLDER + 2, sizeof *smsgs); hi = mp->hghmsg + 1; /* burst all the SELECTED messages */ for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { if (is_selected (mp, msgnum)) { if ((numburst = find_delim (msgnum, smsgs, &mimesw)) >= 1) { if (verbosw) printf ("%d message%s exploded from digest %d\n", numburst, PLURALS(numburst), msgnum); burst (&mp, msgnum, smsgs, numburst, inplace, verbosw, maildir, mimesw); } else { if (numburst == 0) { if (!quietsw) inform("message %d not in digest format, continuing...", msgnum); } /* this pair of braces was missing before 1999-07-15 */ else adios (NULL, "burst() botch -- you lose big"); } } } free(smsgs); context_replace (pfolder, folder); /* update current folder */ /* * If -inplace is given, then the first message burst becomes * the current message (which will now show a table of contents). * Otherwise, the first message extracted from the first digest * becomes the current message. */ if (inplace) { if (mp->lowsel != mp->curmsg) seq_setcur (mp, mp->lowsel); } else { if (hi <= mp->hghmsg) seq_setcur (mp, hi); } seq_save (mp); /* synchronize message sequences */ context_save (); /* save the context file */ folder_free (mp); /* free folder/message structure */ done (0); return 1; } /* * Scan the message and find the beginning and * end of all the messages in the digest. * * If requested, see if the message is MIME-formatted and contains any * message/rfc822 parts; if so, burst those parts. */ static int find_delim (int msgnum, struct smsg *smsgs, int *mimesw) { int wasdlm = 0, msgp; off_t pos; char c, *msgnam; char buffer[BUFSIZ]; FILE *in; CT content; msgnam = m_name (msgnum); /* * If mimesw is 1 or 2, try to see if it's got proper MIME formatting. */ if (*mimesw > 0) { content = parse_mime(msgnam); if (! content && *mimesw == 2) return 0; if (content) { smsgs[0].s_start = 0; smsgs[0].s_stop = content->c_begin - 1; msgp = 1; find_mime_parts(content, smsgs, &msgp); free_content(content); if (msgp == 1 && *mimesw == 2) { adios (msgnam, "does not have any message/rfc822 parts"); } else if (msgp > 1) { *mimesw = 1; return (msgp - 1); } } } *mimesw = 0; if ((in = fopen (msgnam, "r")) == NULL) adios (msgnam, "unable to read message"); for (msgp = 0, pos = 0L; msgp <= MAXFOLDER;) { /* * We're either at the beginning of the whole message, or * we're just past the delimiter of the last message. * Swallow lines until we get to something that's not a newline */ while (fgets (buffer, sizeof(buffer), in) && buffer[0] == '\n') pos += (long) strlen (buffer); if (feof (in)) break; /* * Reset to the beginning of the last non-blank line, and save our * starting position. This is where the encapsulated message * starts. */ fseeko (in, pos, SEEK_SET); smsgs[msgp].s_start = pos; /* * Read in lines until we get to a message delimiter. * * Previously we checked to make sure the preceding line and * next line was a newline. That actually does not comply with * RFC 934, so make sure we break on a message delimiter even * if the previous character was NOT a newline. */ for (c = 0; fgets (buffer, sizeof(buffer), in); c = buffer[0]) { if ((wasdlm = CHECKDELIM(buffer))) break; else pos += (long) strlen (buffer); } /* * Only count as a new message if we got the message delimiter. * Swallow a blank line if it was right before the message delimiter. */ if (smsgs[msgp].s_start != pos && wasdlm) smsgs[msgp++].s_stop = (c == '\n' && wasdlm) ? pos - 1 : pos; if (feof (in)) { #if 0 if (wasdlm) { smsgs[msgp - 1].s_stop -= ((long) strlen (buffer) + 1); msgp++; /* fake "End of XXX Digest" */ } #endif break; } pos += (long) strlen (buffer); } fclose (in); return (msgp - 1); /* return the number of messages burst */ } /* * Find any MIME content in the message that is a message/rfc822 and add * it to the list of messages to burst. */ static void find_mime_parts (CT content, struct smsg *smsgs, int *msgp) { struct multipart *m; struct part *part; /* * If we have a message/rfc822, then it's easy. */ if (content->c_type == CT_MESSAGE && content->c_subtype == MESSAGE_RFC822) { smsgs[*msgp].s_start = content->c_begin; smsgs[*msgp].s_stop = content->c_end; (*msgp)++; return; } /* * Otherwise, if we do have multiparts, try all of the sub-parts. */ if (content->c_type == CT_MULTIPART) { m = (struct multipart *) content->c_ctparams; for (part = m->mp_parts; part; part = part->mp_next) find_mime_parts(part->mp_part, smsgs, msgp); } } /* * Burst out the messages in the digest into the folder */ static void burst (struct msgs **mpp, int msgnum, struct smsg *smsgs, int numburst, int inplace, int verbosw, char *maildir, int mimesw) { int i, j, mode; char *msgnam; char f1[BUFSIZ], f2[BUFSIZ], f3[BUFSIZ]; FILE *in, *out; struct stat st; struct msgs *mp; if ((in = fopen (msgnam = m_name (msgnum), "r")) == NULL) adios (msgnam, "unable to read message"); mode = fstat (fileno(in), &st) != NOTOK ? (int) (st.st_mode & 0777) : m_gmprot(); mp = *mpp; /* * See if we have enough space in the folder * structure for all the new messages. */ if ((mp->hghmsg + numburst > mp->hghoff) && !(mp = folder_realloc (mp, mp->lowoff, mp->hghmsg + numburst))) adios (NULL, "unable to allocate folder storage"); *mpp = mp; j = mp->hghmsg; /* old value */ mp->hghmsg += numburst; mp->nummsg += numburst; /* * If this is not the highest SELECTED message, then * increment mp->hghsel by numburst, since the highest * SELECTED is about to be slid down by that amount. */ if (msgnum < mp->hghsel) mp->hghsel += numburst; /* * If -inplace is given, renumber the messages after the * source message, to make room for each of the messages * contained within the digest. * * This is equivalent to refiling a message from the point * of view of the external hooks. */ if (inplace) { for (i = mp->hghmsg; j > msgnum; i--, j--) { strncpy (f1, m_name (i), sizeof(f1)); strncpy (f2, m_name (j), sizeof(f2)); if (does_exist (mp, j)) { if (verbosw) printf ("message %d becomes message %d\n", j, i); if (rename (f2, f1) == NOTOK) admonish (f1, "unable to rename %s to", f2); (void)snprintf(f1, sizeof (f1), "%s/%d", maildir, i); (void)snprintf(f2, sizeof (f2), "%s/%d", maildir, j); ext_hook("ref-hook", f1, f2); copy_msg_flags (mp, i, j); clear_msg_flags (mp, j); mp->msgflags |= SEQMOD; } } } unset_selected (mp, msgnum); /* new hghmsg is hghmsg + numburst * * At this point, there is an array of numburst smsgs, each element of * which contains the starting and stopping offsets (seeks) of the message * in the digest. The inplace flag is set if the original digest is replaced * by a message containing the table of contents. smsgs[0] is that table of * contents. Go through the message numbers in reverse order (high to low). * * Set f1 to the name of the destination message, f2 to the name of a scratch * file. Extract a message from the digest to the scratch file. Move the * original message to a backup file if the destination message number is the * same as the number of the original message, which only happens if the * inplace flag is set. Then move the scratch file to the destination message. * * Moving the original message to the backup file is equivalent to deleting the * message from the point of view of the external hooks. And bursting each * message is equivalent to adding a new message. */ i = inplace ? msgnum + numburst : mp->hghmsg; for (j = numburst; j >= (inplace ? 0 : 1); i--, j--) { char *tempfile; if ((tempfile = m_mktemp2(NULL, invo_name, NULL, &out)) == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } strncpy (f2, tempfile, sizeof(f2)); strncpy (f1, m_name (i), sizeof(f1)); if (verbosw && i != msgnum) printf ("message %d of digest %d becomes message %d\n", j, msgnum, i); chmod (f2, mode); fseeko (in, smsgs[j].s_start, SEEK_SET); cpybrst (in, out, msgnam, f2, (int) (smsgs[j].s_stop - smsgs[j].s_start), mimesw); fclose (out); if (i == msgnum) { strncpy (f3, m_backup (f1), sizeof(f3)); if (rename (f1, f3) == NOTOK) admonish (f3, "unable to rename %s to", f1); (void)snprintf(f3, sizeof (f3), "%s/%d", maildir, i); ext_hook("del-hook", f3, NULL); } if (rename (f2, f1) == NOTOK) admonish (f1, "unable to rename %s to", f2); (void)snprintf(f3, sizeof (f3), "%s/%d", maildir, i); ext_hook("add-hook", f3, NULL); copy_msg_flags (mp, i, msgnum); mp->msgflags |= SEQMOD; } fclose (in); } #define S1 0 #define S2 1 #define S3 2 #define S4 3 /* * Copy a message which is being burst out of a digest. * It will remove any "dashstuffing" in the message. */ static void cpybrst (FILE *in, FILE *out, char *ifile, char *ofile, int len, int mime) { int c, state; for (state = mime ? S4 : S1; (c = fgetc (in)) != EOF && len > 0; len--) { if (c == 0) continue; switch (state) { case S1: switch (c) { case '-': state = S3; break; default: state = S2; /* FALLTHRU */ case '\n': fputc (c, out); break; } break; case S2: switch (c) { case '\n': state = S1; /* FALLTHRU */ default: fputc (c, out); break; } break; case S3: switch (c) { case ' ': state = S2; break; default: state = (c == '\n') ? S1 : S2; fputc ('-', out); fputc (c, out); break; } break; case S4: fputc (c, out); break; } } if (ferror (in) && !feof (in)) adios (ifile, "error reading"); if (ferror (out)) adios (ofile, "error writing"); } nmh-1.7.1-RC3/uip/comp.c000644 007761 000024 00000022634 13243042053 014664 0ustar00kenhstaff000000 000000 /* comp.c -- compose a message * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include "../sbr/m_maildir.h" #include #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("build", 5, BILDSW) \ 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 columns", 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, NOSW }, { "replace", 0, YESW }, { "use", 0, USELSW }, { "list", 0, LISTDSW }, { "refile", 0, REFILSW }, { NULL, 0, 0 } }; int main (int argc, char **argv) { int use = NOUSE, nedit = 0, nwhat = 0, build = 0; int i, in = NOTOK, isdf = 0, out, dat[5], format_len = 0; int outputlinelen = OUTPUTLINELEN; char *cp, *cwd, *maildir, *dfolder = NULL; char *ed = NULL, *file = NULL, *form = NULL; char *folder = NULL, *msg = NULL, buf[BUFSIZ]; char *to = NULL, *from = NULL, *cc = NULL, *fcc = NULL, *dp; char *subject = NULL; char drft[BUFSIZ], **argp, **arguments; struct msgs *mp = NULL; struct format *fmt; struct stat st; if (nmh_init(argv[0], 1)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [+folder] [msg] [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case EDITRSW: if (!(ed = *argp++) || *ed == '-') adios (NULL, "missing argument to %s", argp[-2]); nedit = 0; continue; case NEDITSW: nedit++; continue; case WHATSW: if (!(whatnowproc = *argp++) || *whatnowproc == '-') adios (NULL, "missing argument to %s", argp[-2]); nwhat = 0; continue; case BILDSW: build++; /* FALLTHRU */ case NWHATSW: nwhat++; continue; case FORMSW: if (!(form = *argp++) || *form == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case USESW: use++; continue; case NUSESW: use = NOUSE; continue; case FILESW: /* compatibility */ if (file) adios (NULL, "only one file at a time!"); if (!(file = *argp++) || *file == '-') adios (NULL, "missing argument to %s", argp[-2]); isdf = NOTOK; continue; case DFOLDSW: if (dfolder) adios (NULL, "only one draft folder at a time!"); if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); dfolder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp, *cp != '@' ? TFOLDER : TSUBCWF); continue; case DMSGSW: if (file) adios (NULL, "only one draft message at a time!"); if (!(file = *argp++) || *file == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case NDFLDSW: dfolder = NULL; isdf = NOTOK; continue; case TOSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); to = addlist(to, cp); continue; case CCSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); cc = addlist(cc, cp); continue; case FROMSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); from = addlist(from, cp); continue; case FCCSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); dp = NULL; if (*cp == '@') cp = dp = path(cp + 1, TSUBCWF); fcc = addlist(fcc, cp); mh_xfree(dp); continue; case WIDTHSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if ((outputlinelen = atoi(cp)) < 10) adios (NULL, "impossible width %d", outputlinelen); continue; case SUBJECTSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); subject = cp; continue; } } if (*cp == '+' || *cp == '@') { if (folder) adios (NULL, "only one folder at a time!"); else folder = pluspath (cp); } else { if (msg) adios (NULL, "only one message at a time!"); else msg = cp; } } cwd = mh_xstrdup(pwd ()); if (!context_find ("path")) free (path ("./", TFOLDER)); /* * Check if we are using a draft folder * and have specified a message in it. */ if ((dfolder || context_find ("Draft-Folder")) && !folder && msg && !file) { file = msg; msg = NULL; } if (form && (folder || msg)) adios (NULL, "can't mix forms and folders/msgs"); cp = NULL; if (folder || msg) { /* * Use a message as the "form" for the new message. */ if (!msg) msg = "cur"; if (!folder) folder = getfolder (1); maildir = m_maildir (folder); if (chdir (maildir) == NOTOK) adios (maildir, "unable to change directory to"); /* read folder and create message structure */ if (!(mp = folder_read (folder, 1))) adios (NULL, "unable to read folder %s", folder); /* check for empty folder */ if (mp->nummsg == 0) adios (NULL, "no messages in %s", folder); /* parse the message range/sequence/name and set SELECTED */ if (!m_convert (mp, msg)) done (1); seq_setprev (mp); /* set the previous-sequence */ seq_save (mp); if (mp->numsel > 1) adios (NULL, "only one message at a time!"); if ((in = open (form = mh_xstrdup(m_name (mp->lowsel)), O_RDONLY)) == NOTOK) adios (form, "unable to open message"); } else { struct comp *cptr; if (! form) form = components; cp = new_fs(form, NULL, NULL); format_len = strlen(cp); fmt_compile(cp, &fmt, 1); /* * Set up any components that were fed to us on the command line */ if (from) { cptr = fmt_findcomp("from"); if (cptr) cptr->c_text = from; } if (to) { cptr = fmt_findcomp("to"); if (cptr) cptr->c_text = to; } if (cc) { cptr = fmt_findcomp("cc"); if (cptr) cptr->c_text = cc; } if (fcc) { cptr = fmt_findcomp("fcc"); if (cptr) cptr->c_text = fcc; } if (subject) { cptr = fmt_findcomp("subject"); if (cptr) cptr->c_text = subject; } } try_it_again: strncpy (drft, build ? m_maildir ("draft") : m_draft (dfolder, file, use, &isdf), sizeof(drft)); /* * Check if we have an existing draft */ if (!build && (out = open (drft, O_RDONLY)) != NOTOK) { i = fdcompare (in, out); close (out); /* * If we have given -use flag, or if the * draft is just the same as the components * file, then no need to ask any questions. */ if (use || i) goto edit_it; if (stat (drft, &st) == NOTOK) adios (drft, "unable to stat"); printf ("Draft \"%s\" exists (%ld bytes).", drft, (long) st.st_size); for (i = LISTDSW; i != YESW;) { if (!(argp = read_switch_multiword ("\nDisposition? ", isdf ? aqrunl : aqrul))) done (1); switch (i = smatch (*argp, isdf ? aqrunl : aqrul)) { case NOSW: done (0); case NEWSW: file = NULL; use = NOUSE; goto try_it_again; case YESW: break; case USELSW: use++; goto edit_it; case LISTDSW: showfile (++argp, drft); break; case REFILSW: if (refile (++argp, drft) == 0) i = YESW; break; default: inform("say what?"); break; } } } else { if (use) adios (drft, "unable to open"); } if ((out = creat (drft, m_gmprot ())) == NOTOK) adios (drft, "unable to create"); if (cp) { charstring_t scanl; i = format_len + 1024; scanl = charstring_create (i + 2); dat[0] = 0; dat[1] = 0; dat[2] = 0; dat[3] = outputlinelen; dat[4] = 0; fmt_scan(fmt, scanl, i, dat, NULL); if (write(out, charstring_buffer (scanl), charstring_bytes (scanl)) < 0) { advise (drft, "write"); } charstring_free(scanl); } else { cpydata (in, out, form, drft); close (in); } close (out); edit_it: context_save (); /* save the context file */ if (nwhat) done (0); what_now (ed, nedit, use, drft, NULL, 0, NULL, NULL, 0, cwd, 0); done (1); return 1; } nmh-1.7.1-RC3/uip/dist.c000644 007761 000024 00000020045 13243042053 014663 0ustar00kenhstaff000000 000000 /* dist.c -- re-distribute a message * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include "../sbr/m_maildir.h" #include #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, NOSW }, { "replace", 0, YESW }, { "list", 0, LISTDSW }, { "refile +folder", 0, REFILSW }, { NULL, 0, 0 } }; int main (int argc, char **argv) { int anot = 0, inplace = 1, nedit = 0; int nwhat = 0, i, in, isdf = 0, out; int outputlinelen = OUTPUTLINELEN; int dat[5], atfile = 0; char *cp, *cwd, *maildir, *msgnam, *dfolder = NULL; char *dmsg = NULL, *ed = NULL, *file = NULL, *folder = NULL; char *form = NULL, *msg = NULL, buf[BUFSIZ], drft[BUFSIZ]; char *from = NULL, *to = NULL, *cc = NULL, *fcc = NULL; char **argp, **arguments; struct msgs *mp = NULL; struct stat st; if (nmh_init(argv[0], 1)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [+folder] [msg] [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case ANNOSW: anot++; continue; case NANNOSW: anot = 0; continue; case EDITRSW: if (!(ed = *argp++) || *ed == '-') adios (NULL, "missing argument to %s", argp[-2]); nedit = 0; continue; case NEDITSW: nedit++; continue; case WHATSW: if (!(whatnowproc = *argp++) || *whatnowproc == '-') adios (NULL, "missing argument to %s", argp[-2]); nwhat = 0; continue; case NWHATSW: nwhat++; continue; case FILESW: if (file) adios (NULL, "only one file at a time!"); if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); file = path (cp, TFILE); continue; case FORMSW: if (!(form = *argp++) || *form == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case INPLSW: inplace++; continue; case NINPLSW: inplace = 0; continue; case DFOLDSW: if (dfolder) adios (NULL, "only one draft folder at a time!"); if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); dfolder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp, *cp != '@' ? TFOLDER : TSUBCWF); continue; case DMSGSW: if (dmsg) adios (NULL, "only one draft message at a time!"); if (!(dmsg = *argp++) || *dmsg == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case NDFLDSW: dfolder = NULL; isdf = NOTOK; continue; case FROMSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); from = addlist(from, cp); continue; case TOSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); to = addlist(to, cp); continue; case CCSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); cc = addlist(cc, cp); continue; case FCCSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); fcc = addlist(fcc, cp); continue; case WIDTHSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if ((outputlinelen = atoi(cp)) < 10) adios (NULL, "impossible width %d", outputlinelen); continue; case ATFILESW: atfile++; continue; case NOATFILESW: atfile = 0; continue; } } if (*cp == '+' || *cp == '@') { if (folder) adios (NULL, "only one folder at a time!"); else folder = pluspath (cp); } else { if (msg) adios (NULL, "only one message at a time!"); else msg = cp; } } cwd = mh_xstrdup(pwd ()); if (!context_find ("path")) free (path ("./", TFOLDER)); if (file && (msg || folder)) adios (NULL, "can't mix files and folders/msgs"); try_it_again: strncpy (drft, m_draft (dfolder, dmsg, NOUSE, &isdf), sizeof(drft)); /* Check if draft already exists */ if (stat (drft, &st) != NOTOK) { printf ("Draft \"%s\" exists (%ld bytes).", drft, (long) st.st_size); for (i = LISTDSW; i != YESW;) { if (!(argp = read_switch_multiword ("\nDisposition? ", isdf ? aqrnl : aqrl))) done (1); switch (i = smatch (*argp, isdf ? aqrnl : aqrl)) { case NOSW: done (0); case NEWSW: dmsg = NULL; goto try_it_again; case YESW: break; case LISTDSW: showfile (++argp, drft); break; case REFILSW: if (refile (++argp, drft) == 0) i = YESW; break; default: inform("say what?"); break; } } } if (file) { /* * Dist a file */ anot = 0; /* don't want to annotate a file */ } else { /* * Dist a message */ if (!msg) msg = "cur"; if (!folder) folder = getfolder (1); maildir = m_maildir (folder); if (chdir (maildir) == NOTOK) adios (maildir, "unable to change directory to"); /* read folder and create message structure */ if (!(mp = folder_read (folder, 1))) adios (NULL, "unable to read folder %s", folder); /* check for empty folder */ if (mp->nummsg == 0) adios (NULL, "no messages in %s", folder); /* parse the message range/sequence/name and set SELECTED */ if (!m_convert (mp, msg)) done (1); seq_setprev (mp); /* set the previous-sequence */ if (mp->numsel > 1) adios (NULL, "only one message at a time!"); } msgnam = file ? file : mh_xstrdup(m_name (mp->lowsel)); dat[0] = mp ? mp->lowsel : 0; dat[1] = 0; dat[2] = 0; dat[3] = outputlinelen; dat[4] = 0; if (!form) form = distcomps; in = build_form(form, NULL, dat, from, to, cc, fcc, NULL, msgnam); if ((out = creat (drft, m_gmprot ())) == NOTOK) adios (drft, "unable to create"); cpydata (in, out, form, drft); close (in); close (out); if ((in = open (msgnam, O_RDONLY)) == NOTOK) adios (msgnam, "unable to open message"); if (!file) { context_replace (pfolder, folder);/* update current folder */ seq_setcur (mp, mp->lowsel); /* update current message */ seq_save (mp); /* synchronize sequences */ context_save (); /* save the context file */ } if (nwhat) done (0); what_now (ed, nedit, NOUSE, drft, msgnam, 1, mp, anot ? "Resent" : NULL, inplace, cwd, atfile); done (1); return 1; } nmh-1.7.1-RC3/uip/distsbr.c000644 007761 000024 00000012224 13243042053 015372 0ustar00kenhstaff000000 000000 /* distsbr.c -- routines to do additional "dist-style" processing * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include "../sbr/m_mktemp.h" static int hdrfd = NOTOK; static int txtfd = NOTOK; #define BADHDR "please re-edit %s to remove the ``%s'' header!" #define BADTXT "please re-edit %s to consist of headers only!" #define BADMSG "please re-edit %s to include a ``Resent-To:''!" #define BADRFT "please re-edit %s and fix that header!" /* * static prototypes */ static void ready_msg(char *); int distout (char *drft, char *msgnam, char *backup) { int state; char *dp, *resent; char name[NAMESZ], buffer[NMH_BUFSIZ]; 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); if ((ifp = fopen (backup, "r")) == NULL) adios (backup, "unable to read"); if ((ofp = fopen (drft, "w")) == NULL) adios (drft, "unable to create temporary file"); chmod (drft, m_gmprot ()); ready_msg (msgnam); lseek(hdrfd, 0, SEEK_SET); /* msgnam not accurate */ cpydata (hdrfd, fileno (ofp), msgnam, drft); for (resent = NULL;;) { int buffersz = sizeof buffer; switch (state = m_getfld (&gstate, name, buffer, &buffersz, ifp)) { case FLD: case FLDPLUS: if (uprf (name, "distribute-")) snprintf (name, sizeof(name), "%s%s", "Resent", &name[10]); if (uprf (name, "distribution-")) snprintf (name, sizeof(name), "%s%s", "Resent", &name[12]); if (!uprf (name, "resent")) { inform(BADHDR, "draft", name); goto leave_bad; } if (state == FLD) resent = add (":", add (name, resent)); resent = add (buffer, resent); fprintf (ofp, "%s: %s", name, buffer); while (state == FLDPLUS) { buffersz = sizeof buffer; state = m_getfld (&gstate, name, buffer, &buffersz, ifp); resent = add (buffer, resent); fputs (buffer, ofp); } break; case BODY: for (dp = buffer; *dp; dp++) if (!isspace ((unsigned char) *dp)) { inform(BADTXT, "draft"); goto leave_bad; } case FILEEOF: goto process; case LENERR: case FMTERR: inform(BADRFT, "draft"); leave_bad: ; fclose (ifp); fclose (ofp); (void) m_unlink (drft); if (rename (backup, drft) == NOTOK) adios (drft, "unable to rename %s to", backup); return NOTOK; default: adios (NULL, "getfld() returned %d", state); } } process: ; m_getfld_state_destroy (&gstate); fclose (ifp); fflush (ofp); if (!resent) { inform(BADMSG, "draft"); fclose (ofp); (void) m_unlink (drft); if (rename (backup, drft) == NOTOK) adios (drft, "unable to rename %s to", backup); return NOTOK; } free (resent); if (txtfd != NOTOK) { lseek(txtfd, 0, SEEK_SET); /* msgnam not accurate */ cpydata (txtfd, fileno (ofp), msgnam, drft); } fclose (ofp); return OK; } static void ready_msg (char *msgnam) { int state, out; char name[NAMESZ], buffer[NMH_BUFSIZ], tmpfil[BUFSIZ]; FILE *ifp, *ofp; char *cp = NULL; m_getfld_state_t gstate = 0; if (hdrfd != NOTOK) { close (hdrfd); hdrfd = NOTOK; } if (txtfd != NOTOK) { close (txtfd); txtfd = NOTOK; } if ((ifp = fopen (msgnam, "r")) == NULL) adios (msgnam, "unable to open message"); cp = m_mktemp2(NULL, "dist", &hdrfd, NULL); if (cp == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } strncpy(tmpfil, cp, sizeof(tmpfil)); if ((out = dup (hdrfd)) == NOTOK || (ofp = fdopen (out, "w")) == NULL) adios (NULL, "no file descriptors -- you lose big"); (void) m_unlink (tmpfil); for (;;) { int buffersz = sizeof buffer; switch (state = m_getfld (&gstate, name, buffer, &buffersz, ifp)) { case FLD: case FLDPLUS: if (uprf (name, "resent")) fprintf (ofp, "Prev-"); fprintf (ofp, "%s: %s", name, buffer); while (state == FLDPLUS) { buffersz = sizeof buffer; state = m_getfld (&gstate, name, buffer, &buffersz, ifp); fputs (buffer, ofp); } break; case BODY: fclose (ofp); cp = m_mktemp2(NULL, "dist", &txtfd, NULL); if (cp == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } fchmod(txtfd, 0600); strncpy (tmpfil, cp, sizeof(tmpfil)); if ((out = dup (txtfd)) == NOTOK || (ofp = fdopen (out, "w")) == NULL) adios (NULL, "no file descriptors -- you lose big"); (void) m_unlink (tmpfil); fprintf (ofp, "\n%s", buffer); while (state == BODY) { buffersz = sizeof buffer; state = m_getfld (&gstate, name, buffer, &buffersz, ifp); fputs (buffer, ofp); } case FILEEOF: goto process; case LENERR: case FMTERR: adios (NULL, "format error in message %s", msgnam); default: adios (NULL, "getfld() returned %d", state); } } process: ; m_getfld_state_destroy (&gstate); fclose (ifp); fclose (ofp); } nmh-1.7.1-RC3/uip/dp.c000644 007761 000024 00000006460 13243042053 014330 0ustar00kenhstaff000000 000000 /* dp.c -- parse dates 822-style * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #define NDATES 100 #define WIDTH 78 #define FORMAT "%<(nodate{text})error: %{text}%|%(putstr(pretty{text}))%>" #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; static int dat[5]; /* * static prototypes */ static int process (char *, int); int main (int argc, char **argv) { int datep = 0, width = -1, status = 0; char *cp, *form = NULL, *format = NULL, *nfs; char buf[BUFSIZ], **argp; char *dates[NDATES + 1]; /* Includes terminating NULL. */ if (nmh_init(argv[0], 2)) { return 1; } argp = getarguments (invo_name, argc, argv, 1); while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [switches] dates ...", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case FORMSW: if (!(form = *argp++) || *form == '-') adios (NULL, "missing argument to %s", argp[-2]); format = NULL; continue; case FMTSW: if (!(format = *argp++) || *format == '-') adios (NULL, "missing argument to %s", argp[-2]); form = NULL; continue; case WIDTHSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); width = atoi (cp); continue; } } if (datep == NDATES) adios (NULL, "more than %d dates", NDATES); else dates[datep++] = cp; } dates[datep] = NULL; if (datep == 0) adios (NULL, "usage: %s [switches] dates ...", invo_name); /* get new format string */ nfs = new_fs (form, format, FORMAT); if (width == -1) { if ((width = sc_width ()) < WIDTH / 2) { /* Default: width of the terminal, but at least WIDTH/2. */ width = WIDTH / 2; } width -= 2; } else if (width == 0) { /* Unlimited width. */ width = INT_MAX; } fmt_compile (nfs, &fmt, 1); dat[0] = 0; dat[1] = 0; dat[2] = 0; dat[3] = width; dat[4] = 0; for (datep = 0; dates[datep]; datep++) status += process (dates[datep], width); context_save (); /* save the context file */ fmt_free (fmt, 1); done (status); return 1; } static int process (char *date, int length) { int status = 0; charstring_t scanl = charstring_create (length < NMH_BUFSIZ ? length : NMH_BUFSIZ); struct comp *cptr; cptr = fmt_findcomp ("text"); if (cptr) { mh_xfree(cptr->c_text); cptr->c_text = mh_xstrdup(date); } fmt_scan (fmt, scanl, length, dat, NULL); fputs (charstring_buffer (scanl), stdout); charstring_free (scanl); return status; } nmh-1.7.1-RC3/uip/dropsbr.c000644 007761 000024 00000014022 13243042053 015371 0ustar00kenhstaff000000 000000 /* dropsbr.c -- create/read/manipulate mail drops * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #include "../sbr/lock_file.h" #include "../sbr/m_mktemp.h" #ifdef NTOHLSWAP # include #else # undef ntohl # define ntohl(n) (n) #endif #include /* * static prototypes */ static int mbx_chk_mbox (int); static int mbx_chk_mmdf (int); /* * Main entry point to open/create and lock * a file or maildrop. */ int mbx_open (char *file, int mbx_style, uid_t uid, gid_t gid, mode_t mode) { int j, count, fd = NOTOK; struct stat st; j = 0; /* attempt to open and lock file */ for (count = 4; count > 0; count--) { int failed_to_lock = 0; if ((fd = lkopenspool (file, O_RDWR | O_CREAT | O_NONBLOCK, mode, &failed_to_lock)) != NOTOK) break; if (!failed_to_lock) return NOTOK; j = errno; sleep (5); } errno = j; /* * Return if we still failed after 4 attempts, * or we just want to skip the sanity checks. */ if (fd == NOTOK || mbx_style == OTHER_FORMAT) return fd; /* * Do sanity checks on maildrop. */ if (fstat (fd, &st) == NOTOK) { /* * The stat failed. So we make sure file * has right ownership/modes */ if (chown (file, uid, gid) < 0) { advise (file, "chown"); } if (chmod (file, mode) < 0) { advise (file, "chmod"); } } else if (st.st_size > 0) { int status; /* check the maildrop */ switch (mbx_style) { case MMDF_FORMAT: default: status = mbx_chk_mmdf (fd); break; case MBOX_FORMAT: status = mbx_chk_mbox (fd); break; } /* if error, attempt to close it */ if (status == NOTOK) { close (fd); return NOTOK; } } return fd; } /* * Check/prepare MBOX style maildrop for appending. */ static int mbx_chk_mbox (int fd) { /* just seek to the end */ if (lseek(fd, 0, SEEK_END) == (off_t) NOTOK) return NOTOK; return OK; } /* * Check/prepare MMDF style maildrop for appending. */ static int mbx_chk_mmdf (int fd) { ssize_t count; char ldelim[BUFSIZ]; count = LEN(MMDF_DELIM); if (lseek (fd, -count, SEEK_END) == (off_t) NOTOK) return NOTOK; if (read (fd, ldelim, count) != count) return NOTOK; ldelim[count] = 0; if (strcmp (ldelim, MMDF_DELIM) && write (fd, "\n", 1) != 1 && write (fd, MMDF_DELIM, count) != count) return NOTOK; return OK; } /* * Append message to end of file or maildrop. */ int mbx_copy (char *mailbox, int mbx_style, int md, int fd, char *text) { int i, j, size; char *cp, buffer[BUFSIZ + 1]; /* Space for NUL. */ FILE *fp; size = 0; switch (mbx_style) { case MMDF_FORMAT: default: j = LEN(MMDF_DELIM); if (write (md, MMDF_DELIM, j) != j) return NOTOK; if (text) { i = strlen (text); if (write (md, text, i) != i) return NOTOK; for (cp = text; *cp++; size++) if (*cp == '\n') size++; } while ((i = read (fd, buffer, sizeof buffer - 1)) > 0) { buffer[i] = '\0'; /* Terminate for stringdex(). */ for ( ; (j = stringdex (MMDF_DELIM, buffer)) >= 0; buffer[j]++) continue; for ( ; (j = stringdex (MMDF_DELIM, buffer)) >= 0; buffer[j]++) continue; if (write (md, buffer, i) != i) return NOTOK; } j = LEN(MMDF_DELIM); if (write (md, MMDF_DELIM, j) != j) return NOTOK; return (i != NOTOK ? OK : NOTOK); case MBOX_FORMAT: if ((j = dup (fd)) == NOTOK) return NOTOK; if ((fp = fdopen (j, "r")) == NULL) { close (j); return NOTOK; } /* If text is given, we add it to top of message */ if (text) { i = strlen (text); if (write (md, text, i) != i) return NOTOK; for (cp = text; *cp++; size++) if (*cp == '\n') size++; } for (j = 0; fgets (buffer, sizeof(buffer), fp) != NULL; j++) { /* * Check the first line, and make some changes. */ if (j == 0 && !text) { /* * Change the "Return-Path:" field (if in first line) * back to "From ". */ if (has_prefix(buffer, "Return-Path:")) { char tmpbuffer[sizeof buffer]; char *tp, *ep, *fp; strncpy(tmpbuffer, buffer, sizeof(tmpbuffer)); ep = tmpbuffer + 13; if (!(fp = strchr(ep + 1, ' '))) fp = strchr(ep + 1, '\n'); tp = dctime(dlocaltimenow()); snprintf (buffer, sizeof(buffer), "From %.*s %s", (int)(fp - ep), ep, tp); } else if (has_prefix(buffer, "X-Envelope-From:")) { /* * Change the "X-Envelope-From:" field * (if first line) back to "From ". */ char tmpbuffer[sizeof buffer]; char *ep; strncpy(tmpbuffer, buffer, sizeof(tmpbuffer)); ep = tmpbuffer + 17; snprintf (buffer, sizeof(buffer), "From %s", ep); } else if (!has_prefix(buffer, "From ")) { /* * If there is already a "From " line, * then leave it alone. Else we add one. */ char tmpbuffer[sizeof buffer]; char *tp, *ep; strncpy(tmpbuffer, buffer, sizeof(tmpbuffer)); ep = "nobody@nowhere"; tp = dctime(dlocaltimenow()); snprintf (buffer, sizeof(buffer), "From %s %s%s", ep, tp, tmpbuffer); } } /* * If this is not first line, and begins with * "From ", then prepend line with ">". */ if (j != 0 && has_prefix(buffer, "From ")) { if (write (md, ">", 1) < 0) { advise (mailbox, "write"); } size++; } i = strlen (buffer); if (write (md, buffer, i) != i) { fclose (fp); return NOTOK; } } if (write (md, "\n", 1) != 1) { fclose (fp); return NOTOK; } fclose (fp); lseek(fd, 0, SEEK_END); return OK; } } /* * Close and unlock file/maildrop. */ int mbx_close (char *mailbox, int md) { if (lkclosespool (md, mailbox) == 0) return OK; return NOTOK; } nmh-1.7.1-RC3/uip/flist.c000644 007761 000024 00000041324 13243042053 015044 0ustar00kenhstaff000000 000000 /* flist.c -- list nmh folders containing messages * -- in a given sequence * * originally by * David Nichols, Xerox-PARC, November, 1992 * * Copyright (c) 1994 Xerox Corporation. * Use and copying of this software and preparation of derivative works based * upon this software are permitted. Any distribution of this software or * derivative works must comply with all applicable United States export * control laws. This software is made available AS IS, and Xerox Corporation * makes no warranty about the software, its performance or its conformity to * any specification. */ #include #include #include "../sbr/m_maildir.h" /* * We allocate space to record the names of folders * (foldersToDo array), this number of elements at a time. */ #define MAXFOLDERS 100 #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 */ int priority; int error; /* error == 1 for unreadable folder */ int nMsgs; /* number of messages in folder */ ivector_t nSeq; /* number of messages in each sequence */ ivector_t private; /* is given sequence, public or private */ }; static struct Folder *orders = NULL; static int nOrders = 0; static int nOrdersAlloced = 0; static struct Folder *folders = NULL; static unsigned int nFolders = 0; static int nFoldersAlloced = 0; /* info on folders to search */ static char **foldersToDo; static int numfolders; static int maxfolders; /* info on sequences to search for */ static svector_t sequencesToDo; static int all = FALSE; /* scan all folders in top level? */ static int alphaOrder = FALSE; /* want alphabetical order only */ static int recurse = FALSE; /* show nested folders? */ static int showzero = TRUE; /* show folders even if no messages in seq? */ static int Total = TRUE; /* display info on number of messages in * * sequence found, and total num messages */ static char curfolder[BUFSIZ]; /* name of the current folder */ static char *nmhdir; /* base nmh mail directory */ /* * Type for a compare function for qsort. This keeps * the compiler happy. */ typedef int (*qsort_comp) (const void *, const void *); /* * static prototypes */ static int CompareFolders(struct Folder *, struct Folder *); static void GetFolderOrder(void); static void ScanFolders(void); static int AddFolder(char *, int); static void BuildFolderList(char *, int); static void BuildFolderListRecurse(char *, struct stat *, int); static void PrintFolders(void); static void AllocFolders(struct Folder **, int *, int); static int AssignPriority(char *); static void do_readonly_folders(void); int main(int argc, char **argv) { char *cp, **argp; char **arguments; char buf[BUFSIZ]; if (nmh_init(argv[0], 1)) { return 1; } /* * If program was invoked with name ending * in `s', then add switch `-all'. */ all = has_suffix_c(argv[0], 's'); arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; /* allocate the initial space to record the folder names */ numfolders = 0; maxfolders = MAXFOLDERS; foldersToDo = (char **) mh_xmalloc ((size_t) (maxfolders * sizeof(*foldersToDo))); /* no sequences yet */ sequencesToDo = svector_create (0); /* parse arguments */ while ((cp = *argp++)) { if (*cp == '-') { switch (smatch(++cp, switches)) { case AMBIGSW: ambigsw(cp, switches); done(1); case UNKWNSW: adios(NULL, "-%s unknown", cp); case HELPSW: snprintf(buf, sizeof(buf), "%s [+folder1 [+folder2 ...]][switches]", invo_name); print_help(buf, switches, 1); done(0); case VERSIONSW: print_version(invo_name); done (0); case SEQSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); svector_push_back (sequencesToDo, cp); break; case ALLSW: all = TRUE; break; case NOALLSW: all = FALSE; break; case SHOWZERO: showzero = TRUE; break; case NOSHOWZERO: showzero = FALSE; break; case ALPHASW: alphaOrder = TRUE; break; case NOALPHASW: alphaOrder = FALSE; break; case NOFASTSW: case TOTALSW: Total = TRUE; break; case FASTSW: case NOTOTALSW: Total = FALSE; break; case RECURSE: recurse = TRUE; break; case NORECURSE: recurse = FALSE; break; } } else { /* * Check if we need to allocate more space * for folder names. */ if (numfolders >= maxfolders) { maxfolders += MAXFOLDERS; foldersToDo = (char **) mh_xrealloc (foldersToDo, (size_t) (maxfolders * sizeof(*foldersToDo))); } if (*cp == '+' || *cp == '@') { foldersToDo[numfolders++] = pluspath (cp); } else foldersToDo[numfolders++] = cp; } } if (!context_find ("path")) free (path ("./", TFOLDER)); /* get current folder */ strncpy (curfolder, getfolder(1), sizeof(curfolder)); /* get nmh base directory */ nmhdir = m_maildir (""); /* * If we didn't specify any sequences, we search * for the "Unseen-Sequence" profile entry and use * all the sequences defined there. */ if (svector_size (sequencesToDo) == 0) { if ((cp = context_find(usequence)) && *cp) { char **ap, *dp; dp = mh_xstrdup(cp); ap = brkstring (dp, " ", "\n"); for (; ap && *ap; ap++) svector_push_back (sequencesToDo, *ap); } else { adios (NULL, "no sequence specified or %s profile entry found", usequence); } } GetFolderOrder(); ScanFolders(); qsort(folders, nFolders, sizeof(struct Folder), (qsort_comp) CompareFolders); PrintFolders(); svector_free (sequencesToDo); done (0); return 1; } /* * Read the Flist-Order profile entry to determine * how to sort folders for output. */ static void GetFolderOrder(void) { char *p, *s; int priority = 1; struct Folder *o; if (!(p = context_find("Flist-Order"))) return; for (;;) { while (isspace((unsigned char) *p)) ++p; s = p; while (*p && !isspace((unsigned char) *p)) ++p; if (p != s) { /* Found one. */ AllocFolders(&orders, &nOrdersAlloced, nOrders + 1); o = &orders[nOrders++]; o->priority = priority++; o->name = (char *) mh_xmalloc(p - s + 1); strncpy(o->name, s, p - s); o->name[p - s] = 0; } else break; } } /* * Scan all the necessary folders */ static void ScanFolders(void) { int i; /* * change directory to base of nmh directory */ if (chdir (nmhdir) == NOTOK) adios (nmhdir, "unable to change directory to"); if (numfolders > 0) { /* Update context */ strncpy (curfolder, foldersToDo[numfolders - 1], sizeof(curfolder)); context_replace (pfolder, curfolder);/* update current folder */ context_save (); /* save the context file */ /* * Scan each given folder. If -all is given, * then also scan the 1st level subfolders under * each given folder. */ for (i = 0; i < numfolders; ++i) BuildFolderList(foldersToDo[i], all ? 1 : 0); } else { if (all) { /* * Do the readonly folders */ do_readonly_folders(); /* * Now scan the entire nmh directory for folders */ BuildFolderList(".", 0); } else { /* * Else scan current folder */ BuildFolderList(curfolder, 0); } } } /* * Initial building of folder list for * the top of our search tree. */ static void BuildFolderList(char *dirName, int searchdepth) { struct stat st; /* Make sure we have a directory */ if ((stat(dirName, &st) == -1) || !S_ISDIR(st.st_mode)) return; /* * If base directory, don't add it to the * folder list. We just recurse into it. */ if (!strcmp (dirName, ".")) { BuildFolderListRecurse (".", &st, 0); return; } /* * Add this folder to the list. * If recursing and directory has subfolders, * then build folder list for subfolders. */ if (AddFolder(dirName, showzero) && (recurse || searchdepth) && st.st_nlink > 2) BuildFolderListRecurse(dirName, &st, searchdepth - 1); } /* * Recursive building of folder list */ static void BuildFolderListRecurse(char *dirName, struct stat *s, int searchdepth) { char *base, name[PATH_MAX]; char *n; int nlinks; DIR *dir; struct dirent *dp; struct stat st; /* * Keep track of number of directories we've seen so we can * stop stat'ing entries in this directory once we've seen * them all. This optimization will fail if you have extra * directories beginning with ".", since we don't bother to * stat them. But that shouldn't generally be a problem. */ nlinks = s->st_nlink; if (nlinks == 1) { /* Disable the optimization under conditions where st_nlink is set to 1. That happens on Cygwin, for example: http://cygwin.com/ml/cygwin-apps/2008-08/msg00264.html */ nlinks = INT_MAX; } if (!(dir = opendir(dirName))) adios(dirName, "can't open directory"); /* * A hack so that we don't see a * leading "./" in folder names. */ base = strcmp (dirName, ".") ? dirName : dirName + 1; while (nlinks && (dp = readdir(dir))) { if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) { nlinks--; continue; } if (dp->d_name[0] == '.') continue; /* Check to see if the name of the file is a number * if it is, we assume it's a mail file and skip it */ for (n = dp->d_name; *n && isdigit((unsigned char) *n); n++); if (!*n) continue; strncpy (name, base, sizeof(name) - 2); if (*base) strcat(name, "/"); strncat(name, dp->d_name, sizeof(name) - strlen(name) - 1); if ((stat(name, &st) != -1) && S_ISDIR(st.st_mode)) { /* * Check if this was really a symbolic link pointing * to a directory. If not, then decrement link count. */ if (lstat (name, &st) == -1) nlinks--; /* Add this folder to the list */ if (AddFolder(name, showzero) && (recurse || searchdepth) && st.st_nlink > 2) BuildFolderListRecurse(name, &st, searchdepth - 1); } } closedir(dir); } /* * Add this folder to our list, counting the total number of * messages and the number of messages in each sequence. */ static int AddFolder(char *name, int force) { unsigned int i; int msgnum, nonzero; ivector_t seqnum = ivector_create (0), nSeq = ivector_create (0); struct Folder *f; struct msgs *mp; char *cp; /* Read folder and create message structure */ if (!(mp = folder_read (name, 0))) { /* Oops, error occurred. Record it and continue. */ AllocFolders(&folders, &nFoldersAlloced, nFolders + 1); f = &folders[nFolders++]; f->name = mh_xstrdup(name); f->error = 1; f->priority = AssignPriority(f->name); return 0; } for (i = 0; i < svector_size (sequencesToDo); i++) { /* Convert sequences to their sequence numbers */ if ((cp = svector_at (sequencesToDo, i))) ivector_push_back (seqnum, seq_getnum(mp, cp)); else ivector_push_back (seqnum, -1); /* Now count messages in this sequence */ ivector_push_back (nSeq, 0); if (mp->nummsg > 0 && ivector_at (seqnum, i) != -1) { for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg; msgnum++) { if (in_sequence(mp, ivector_at (seqnum, i), msgnum)) (*ivector_atp (nSeq, i))++; } } } /* Check if any of the sequence checks were nonzero */ nonzero = 0; for (i = 0; i < svector_size (sequencesToDo); i++) { if (ivector_at (nSeq, i) > 0) { nonzero = 1; break; } } if (nonzero || force) { /* save general folder information */ AllocFolders(&folders, &nFoldersAlloced, nFolders + 1); f = &folders[nFolders++]; f->name = mh_xstrdup(name); f->nMsgs = mp->nummsg; f->nSeq = ivector_create (0); f->private = ivector_create (0); f->error = 0; f->priority = AssignPriority(f->name); /* record the sequence information */ for (i = 0; i < svector_size (sequencesToDo); i++) { *ivector_atp (f->nSeq, i) = ivector_at (nSeq, i); ivector_push_back (f->private, ivector_at (seqnum, i) != -1 ? is_seq_private(mp, ivector_at (seqnum, i)) : 0); } } ivector_free (nSeq); ivector_free (seqnum); folder_free (mp); /* free folder/message structure */ return 1; } /* * Print the folder/sequence information */ static void PrintFolders(void) { char tmpname[BUFSIZ]; unsigned int i, j, len, has_private = 0; unsigned int maxfolderlen = 0, maxseqlen = 0; int maxnum = 0, maxseq = 0; if (!Total) { for (i = 0; i < nFolders; i++) puts(folders[i].name); return; } /* * Find the width we need for various fields */ for (i = 0; i < nFolders; ++i) { /* find the length of longest folder name */ len = strlen(folders[i].name); if (len > maxfolderlen) maxfolderlen = len; /* If folder had error, skip the rest */ if (folders[i].error) continue; /* find the maximum total messages */ if (folders[i].nMsgs > maxnum) maxnum = folders[i].nMsgs; for (j = 0; j < svector_size (sequencesToDo); j++) { /* find maximum width of sequence name */ len = strlen (svector_at (sequencesToDo, j)); if ((ivector_at (folders[i].nSeq, j) > 0 || showzero) && (len > maxseqlen)) maxseqlen = len; /* find the maximum number of messages in sequence */ if (ivector_at (folders[i].nSeq, j) > maxseq) maxseq = ivector_at (folders[i].nSeq, j); /* check if this sequence is private in any of the folders */ if (ivector_at (folders[i].private, j)) has_private = 1; } } /* Now print all the folder/sequence information */ for (i = 0; i < nFolders; i++) { for (j = 0; j < svector_size (sequencesToDo); j++) { if (ivector_at (folders[i].nSeq, j) > 0 || showzero) { /* Add `+' to end of name of current folder */ if (strcmp(curfolder, folders[i].name)) snprintf(tmpname, sizeof(tmpname), "%s", folders[i].name); else snprintf(tmpname, sizeof(tmpname), "%s+", folders[i].name); if (folders[i].error) { printf("%-*s is unreadable\n", maxfolderlen+1, tmpname); continue; } printf("%-*s has %*d in sequence %-*s%s; out of %*d\n", maxfolderlen+1, tmpname, num_digits(maxseq), ivector_at (folders[i].nSeq, j), maxseqlen, svector_at (sequencesToDo, j), !has_private ? "" : ivector_at (folders[i].private, j) ? " (private)" : " ", num_digits(maxnum), folders[i].nMsgs); } } } } /* * Put them in priority order. */ static int CompareFolders(struct Folder *f1, struct Folder *f2) { if (!alphaOrder && f1->priority != f2->priority) return f1->priority - f2->priority; return strcmp(f1->name, f2->name); } /* * Make sure we have at least n folders allocated. */ static void AllocFolders(struct Folder **f, int *nfa, int n) { if (n <= *nfa) return; if (*f == NULL) { *nfa = 10; *f = (struct Folder *) mh_xmalloc (*nfa * (sizeof(struct Folder))); } else { *nfa *= 2; *f = (struct Folder *) mh_xrealloc (*f, *nfa * (sizeof(struct Folder))); } } /* * Return the priority for a name. The highest comes from an exact match. * After that, the longest match (then first) assigns the priority. */ static int AssignPriority(char *name) { int i, ol, nl; int best = nOrders; int bestLen = 0; struct Folder *o; nl = strlen(name); for (i = 0; i < nOrders; ++i) { o = &orders[i]; if (!strcmp(name, o->name)) return o->priority; ol = strlen(o->name); if (nl < ol - 1) continue; if (ol < bestLen) continue; if (o->name[0] == '*' && !strcmp(o->name + 1, name + (nl - ol + 1))) { best = o->priority; bestLen = ol; } else if (o->name[ol - 1] == '*' && strncmp(o->name, name, ol - 1) == 0) { best = o->priority; bestLen = ol; } } return best; } /* * Do the read only folders */ static void do_readonly_folders (void) { int atrlen; char atrcur[BUFSIZ]; struct node *np; snprintf (atrcur, sizeof(atrcur), "atr-%s-", current); atrlen = strlen (atrcur); for (np = m_defs; np; np = np->n_next) if (ssequal (atrcur, np->n_name) && !ssequal (nmhdir, np->n_name + atrlen)) BuildFolderList (np->n_name + atrlen, 0); } nmh-1.7.1-RC3/uip/fmtdump.c000644 007761 000024 00000026731 13243042053 015404 0ustar00kenhstaff000000 000000 /* fmtdump.c -- compile format file and dump out instructions * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #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]; static int lused = 0; /* * static prototypes */ static void fmt_dump (struct format *); static void dumpone(struct format *); static int findlabel(struct format *); static void assignlabel(struct format *); static char *f_typestr(int); static char *c_typestr(int); static char *c_flagsstr(int); static void litputs(char *); static void litputc(char); int main (int argc, char **argv) { char *cp, *form = NULL, *format = NULL; char buf[BUFSIZ], *nfs, **argp, **arguments; struct format *fmt; if (nmh_init(argv[0], 2)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case FORMSW: if (!(form = *argp++) || *form == '-') adios (NULL, "missing argument to %s", argp[-2]); format = NULL; continue; case FMTSW: if (!(format = *argp++) || *format == '-') adios (NULL, "missing argument to %s", argp[-2]); form = NULL; continue; } } if (form) adios (NULL, "only one form at a time!"); else form = cp; } /* * Get new format string. Must be before chdir(). */ nfs = new_fs (form, format, FORMAT); (void) fmt_compile(nfs, &fmt, 1); fmt_dump(fmt); fmt_free(fmt, 1); done(0); return 1; } static void fmt_dump (struct format *fmth) { int i; struct format *fmt, *addr; /* Assign labels */ for (fmt = fmth; fmt; ++fmt) { i = fmt->f_type; if (i == FT_IF_S || i == FT_IF_S_NULL || i == FT_IF_V_EQ || i == FT_IF_V_NE || i == FT_IF_V_GT || i == FT_IF_MATCH || i == FT_IF_AMATCH || i == FT_GOTO) { addr = fmt + fmt->f_skip; if (findlabel(addr) < 0) assignlabel(addr); } if (fmt->f_type == FT_DONE && fmt->f_value == 0) break; } /* Dump them out! */ for (fmt = fmth; fmt; ++fmt) { dumpone(fmt); if (fmt->f_type == FT_DONE && fmt->f_value == 0) break; } } static void dumpone(struct format *fmt) { int i; if ((i = findlabel(fmt)) >= 0) printf("L%d:", i); putchar('\t'); fputs(f_typestr((int)fmt->f_type), stdout); switch (fmt->f_type) { case FT_COMP: case FT_LS_COMP: case FT_LV_COMPFLAG: case FT_LV_COMP: printf(", comp "); litputs(fmt->f_comp->c_name); if (fmt->f_comp->c_type) printf(", c_type %s", c_typestr(fmt->f_comp->c_type)); if (fmt->f_comp->c_flags) printf(", c_flags %s", c_flagsstr(fmt->f_comp->c_flags)); break; case FT_LV_SEC: case FT_LV_MIN: case FT_LV_HOUR: case FT_LV_MDAY: case FT_LV_MON: case FT_LS_MONTH: case FT_LS_LMONTH: case FT_LS_ZONE: case FT_LV_YEAR: case FT_LV_WDAY: case FT_LS_DAY: case FT_LS_WEEKDAY: case FT_LV_YDAY: case FT_LV_ZONE: case FT_LV_CLOCK: case FT_LV_RCLOCK: case FT_LV_DAYF: case FT_LV_ZONEF: case FT_LV_DST: case FT_LS_822DATE: case FT_LS_PRETTY: case FT_LOCALDATE: case FT_GMTDATE: case FT_PARSEDATE: printf(", c_name "); litputs(fmt->f_comp->c_name); if (fmt->f_comp->c_type) printf(", c_type %s", c_typestr(fmt->f_comp->c_type)); if (fmt->f_comp->c_flags) printf(", c_flags %s", c_flagsstr(fmt->f_comp->c_flags)); break; case FT_LS_ADDR: case FT_LS_PERS: case FT_LS_MBOX: case FT_LS_HOST: case FT_LS_PATH: case FT_LS_GNAME: case FT_LS_NOTE: case FT_LS_822ADDR: case FT_LV_HOSTTYPE: case FT_LV_INGRPF: case FT_LV_NOHOSTF: case FT_LS_FRIENDLY: case FT_PARSEADDR: case FT_MYMBOX: case FT_GETMYMBOX: case FT_GETMYADDR: printf(", c_name "); litputs(fmt->f_comp->c_name); if (fmt->f_comp->c_type) printf(", c_type %s", c_typestr(fmt->f_comp->c_type)); if (fmt->f_comp->c_flags) printf(", c_flags %s", c_flagsstr(fmt->f_comp->c_flags)); break; case FT_COMPF: printf(", width %d, fill '", fmt->f_width); litputc(fmt->f_fill); printf("' name "); litputs(fmt->f_comp->c_name); if (fmt->f_comp->c_type) printf(", c_type %s", c_typestr(fmt->f_comp->c_type)); if (fmt->f_comp->c_flags) printf(", c_flags %s", c_flagsstr(fmt->f_comp->c_flags)); break; case FT_STRF: case FT_NUMF: printf(", width %d, fill '", fmt->f_width); litputc(fmt->f_fill); putchar('\''); break; case FT_LIT: putchar(' '); litputs(fmt->f_text); break; case FT_LITF: printf(", width %d, fill '", fmt->f_width); litputc(fmt->f_fill); printf("' "); litputs(fmt->f_text); break; case FT_CHAR: putchar(' '); putchar('\''); litputc(fmt->f_char); putchar('\''); break; case FT_IF_S: case FT_IF_S_NULL: case FT_IF_MATCH: case FT_IF_AMATCH: printf(" continue else goto"); /* FALLTHRU */ case FT_GOTO: i = findlabel(fmt + fmt->f_skip); printf(" L%d", i); break; case FT_IF_V_EQ: case FT_IF_V_NE: case FT_IF_V_GT: i = findlabel(fmt + fmt->f_skip); printf(" %d continue else goto L%d", fmt->f_value, i); break; case FT_V_EQ: case FT_V_NE: case FT_V_GT: case FT_LV_LIT: case FT_LV_PLUS_L: case FT_LV_MINUS_L: case FT_LV_MULTIPLY_L: case FT_LV_DIVIDE_L: case FT_LV_MODULO_L: printf(" value %d", fmt->f_value); break; case FT_LS_LIT: printf(" str "); litputs(fmt->f_text); break; case FT_LS_GETENV: printf(" getenv "); litputs(fmt->f_text); break; case FT_LS_DECODECOMP: printf(", comp "); litputs(fmt->f_comp->c_name); break; case FT_LS_DECODE: break; case FT_LS_TRIM: printf(", width %d", fmt->f_width); break; case FT_LV_DAT: printf(", value dat[%d]", fmt->f_value); break; } putchar('\n'); } static int findlabel(struct format *addr) { int i; for (i = 0; i < lused; ++i) if (addr == lvec[i]) return(i); return(-1); } static void assignlabel(struct format *addr) { lvec[lused++] = addr; } static char * f_typestr(int t) { static char buf[32]; switch (t) { case FT_COMP: return "COMP"; case FT_COMPF: return "COMPF"; case FT_LIT: return "LIT"; case FT_LITF: return "LITF"; case FT_CHAR: return "CHAR"; case FT_NUM: return "NUM"; case FT_NUMF: return "NUMF"; case FT_STR: return "STR"; case FT_STRF: return "STRF"; case FT_STRFW: return "STRFW"; case FT_STRLIT: return "STRLIT"; case FT_STRLITZ: return "STRLITZ"; case FT_PUTADDR: return "PUTADDR"; case FT_LS_COMP: return "LS_COMP"; case FT_LS_LIT: return "LS_LIT"; case FT_LS_GETENV: return "LS_GETENV"; case FT_LS_CFIND: return "LS_CFIND"; case FT_LS_DECODECOMP: return "LS_DECODECOMP"; case FT_LS_DECODE: return "LS_DECODE"; case FT_LS_TRIM: return "LS_TRIM"; case FT_LV_COMP: return "LV_COMP"; case FT_LV_COMPFLAG: return "LV_COMPFLAG"; case FT_LV_LIT: return "LV_LIT"; case FT_LV_DAT: return "LV_DAT"; case FT_LV_STRLEN: return "LV_STRLEN"; case FT_LV_PLUS_L: return "LV_PLUS_L"; case FT_LV_MINUS_L: return "LV_MINUS_L"; case FT_LV_MULTIPLY_L: return "LV_MULTIPLY_L"; case FT_LV_DIVIDE_L: return "LV_DIVIDE_L"; case FT_LV_MODULO_L: return "LV_MODULO_L"; case FT_LV_CHAR_LEFT: return "LV_CHAR_LEFT"; case FT_LS_MONTH: return "LS_MONTH"; case FT_LS_LMONTH: return "LS_LMONTH"; case FT_LS_ZONE: return "LS_ZONE"; case FT_LS_DAY: return "LS_DAY"; case FT_LS_WEEKDAY: return "LS_WEEKDAY"; case FT_LS_822DATE: return "LS_822DATE"; case FT_LS_PRETTY: return "LS_PRETTY"; case FT_LS_KILO: return "LS_KILO"; case FT_LS_KIBI: return "LS_KIBI"; case FT_LV_SEC: return "LV_SEC"; case FT_LV_MIN: return "LV_MIN"; case FT_LV_HOUR: return "LV_HOUR"; case FT_LV_MDAY: return "LV_MDAY"; case FT_LV_MON: return "LV_MON"; case FT_LV_YEAR: return "LV_YEAR"; case FT_LV_YDAY: return "LV_YDAY"; case FT_LV_WDAY: return "LV_WDAY"; case FT_LV_ZONE: return "LV_ZONE"; case FT_LV_CLOCK: return "LV_CLOCK"; case FT_LV_RCLOCK: return "LV_RCLOCK"; case FT_LV_DAYF: return "LV_DAYF"; case FT_LV_DST: return "LV_DST"; case FT_LV_ZONEF: return "LV_ZONEF"; case FT_LS_PERS: return "LS_PERS"; case FT_LS_MBOX: return "LS_MBOX"; case FT_LS_HOST: return "LS_HOST"; case FT_LS_PATH: return "LS_PATH"; case FT_LS_GNAME: return "LS_GNAME"; case FT_LS_NOTE: return "LS_NOTE"; case FT_LS_ADDR: return "LS_ADDR"; case FT_LS_822ADDR: return "LS_822ADDR"; case FT_LS_FRIENDLY: return "LS_FRIENDLY"; case FT_LV_HOSTTYPE: return "LV_HOSTTYPE"; case FT_LV_INGRPF: return "LV_INGRPF"; case FT_LS_UNQUOTE: return "LS_UNQUOTE"; case FT_LV_NOHOSTF: return "LV_NOHOSTF"; case FT_LOCALDATE: return "LOCALDATE"; case FT_GMTDATE: return "GMTDATE"; case FT_PARSEDATE: return "PARSEDATE"; case FT_PARSEADDR: return "PARSEADDR"; case FT_FORMATADDR: return "FORMATADDR"; case FT_CONCATADDR: return "CONCATADDR"; case FT_MYMBOX: return "MYMBOX"; case FT_GETMYMBOX: return "GETMYMBOX"; case FT_GETMYADDR: return "GETMYADDR"; case FT_SAVESTR: return "SAVESTR"; case FT_DONE: return "DONE"; case FT_PAUSE: return "PAUSE"; case FT_NOP: return "NOP"; case FT_GOTO: return "GOTO"; case FT_IF_S_NULL: return "IF_S_NULL"; case FT_IF_S: return "IF_S"; case FT_IF_V_EQ: return "IF_V_EQ"; case FT_IF_V_NE: return "IF_V_NE"; case FT_IF_V_GT: return "IF_V_GT"; case FT_IF_MATCH: return "IF_MATCH"; case FT_IF_AMATCH: return "IF_AMATCH"; case FT_S_NULL: return "S_NULL"; case FT_S_NONNULL: return "S_NONNULL"; case FT_V_EQ: return "V_EQ"; case FT_V_NE: return "V_NE"; case FT_V_GT: return "V_GT"; case FT_V_MATCH: return "V_MATCH"; case FT_V_AMATCH: return "V_AMATCH"; default: printf(buf, "/* ??? #%d */", t); return(buf); } } #define FNORD(v, s) if (t & (v)) { \ if (i++ > 0) \ strcat(buf, "|"); \ strcat(buf, s); } static char * c_typestr(int t) { int i; static char buf[64]; buf[0] = '\0'; if (t & ~(CT_ADDR|CT_DATE)) printf(buf, "0x%x ", t); strcat(buf, "<"); i = 0; FNORD(CT_ADDR, "ADDR"); FNORD(CT_DATE, "DATE"); strcat(buf, ">"); return(buf); } static char * c_flagsstr(int t) { int i; static char buf[64]; buf[0] = '\0'; if (t & ~(CF_TRUE|CF_PARSED|CF_DATEFAB|CF_TRIMMED)) printf(buf, "0x%x ", t); strcat(buf, "<"); i = 0; FNORD(CF_TRUE, "TRUE"); FNORD(CF_PARSED, "PARSED"); FNORD(CF_DATEFAB, "DATEFAB"); FNORD(CF_TRIMMED, "TRIMMED"); strcat(buf, ">"); return(buf); } #undef FNORD static void litputs(char *s) { if (s) { putchar('"'); while (*s) litputc(*s++); putchar('"'); } else fputs("", stdout); } static void litputc(char c) { if (c & ~ 0177) { putchar('M'); putchar('-'); c &= 0177; } if (c < 0x20 || c == 0177) { if (c == '\b') { putchar('\\'); putchar('b'); } else if (c == '\f') { putchar('\\'); putchar('f'); } else if (c == '\n') { putchar('\\'); putchar('n'); } else if (c == '\r') { putchar('\\'); putchar('r'); } else if (c == '\t') { putchar('\\'); putchar('t'); } else { putchar('^'); putchar(c ^ 0x40); /* DEL to ?, others to alpha */ } } else putchar(c); } nmh-1.7.1-RC3/uip/fmttest.c000644 007761 000024 00000074357 13243042053 015425 0ustar00kenhstaff000000 000000 /* fmttest.c -- A program to help test and debug format instructions * * 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 #include #include #include #include #include #include "../sbr/m_maildir.h" #define FMTTEST_SWITCHES \ X("form formatfile", 0, FORMSW) \ X("format string", 5, FMTSW) \ X("address", 0, ADDRSW) \ X("raw", 0, RAWSW) \ X("date", 0, DATESW) \ X("message", 0, MESSAGESW) \ X("file", 0, FILESW) \ X("nofile", 0, NFILESW) \ X("-component-name component-text", 0, OTHERSW) \ X("dupaddrs", 0, DUPADDRSW) \ X("nodupaddrs", 0, NDUPADDRSW) \ X("ccme", 0, CCMESW) \ X("noccme", 0, NCCMESW) \ X("outsize size-in-characters", 0, OUTSIZESW) \ X("width column-width", 0, WIDTHSW) \ X("msgnum number", 0, MSGNUMSW) \ X("msgcur flag", 0, MSGCURSW) \ X("msgsize size", 0, MSGSIZESW) \ X("unseen flag", 0, UNSEENSW) \ X("dump", 0, DUMPSW) \ X("nodump", 0, NDUMPSW) \ X("trace", 0, TRACESW) \ X("notrace", 0, NTRACESW) \ X("version", 0, VERSIONSW) \ X("help", 0, HELPSW) \ #define X(sw, minchars, id) id, DEFINE_SWITCH_ENUM(FMTTEST); #undef X #define X(sw, minchars, id) { sw, minchars, id }, DEFINE_SWITCH_ARRAY(FMTTEST, switches); #undef X /* * An array containing labels used for branch instructions */ static struct format **lvec = NULL; static int lused = 0; static int lallocated = 0; enum mode_t { MESSAGE, ADDRESS, DATE, RAW }; #define DEFADDRFORMAT "%<{error}%{error}: %{text}%|%(putstr(proper{text}))%>" #define DEFDATEFORMAT "%<(nodate{text})error: %{text}%|%(putstr(pretty{text}))%>" /* * Context structure used by the tracing routines */ struct trace_context { int num; char *str; char *outbuf; }; /* * static prototypes */ static void fmt_dump (char *, struct format *); static void dumpone(struct format *); static void initlabels(struct format *); static int findlabel(struct format *); static void assignlabel(struct format *); static char *f_typestr(int); static char *c_typestr(int); static char *c_flagsstr(int); static void litputs(const char *); static void litputc(char); static void process_addresses(struct format *, struct msgs_array *, charstring_t, int, int *, struct fmt_callbacks *); static void process_raw(struct format *, struct msgs_array *, charstring_t, int, int *, struct fmt_callbacks *); static void process_messages(struct format *, struct msgs_array *, struct msgs_array *, charstring_t, char *, int, int, int *, struct fmt_callbacks *); static void process_single_file(FILE *, struct msgs_array *, int *, int, struct format *, charstring_t, int, struct fmt_callbacks *); static void test_trace(void *, struct format *, int, char *, const char *); static char *test_formataddr(char *, char *); static char *test_concataddr(char *, char *); static int insert(struct mailname *); static void mlistfree(void); static int nodupcheck = 0; /* If set, no check for duplicates */ static int ccme = 0; /* Should I cc myself? */ static struct mailname mq; /* Mail addresses to check for duplicates */ static char *dummy = "dummy"; int main (int argc, char **argv) { char *cp, *form = NULL, *format = NULL, *defformat = FORMAT, *folder = NULL; char buf[BUFSIZ], *nfs, **argp, **arguments; charstring_t buffer; struct format *fmt; struct comp *cptr; struct msgs_array msgs = { 0, 0, NULL }, compargs = { 0, 0, NULL}; bool dump = false; int i; bool dupaddrs = true; bool trace = false; int files = 0; bool outputsize_given = false; int outputsize; int colwidth = -1, msgnum = -1, msgcur = -1, msgsize = -1, msgunseen = -1; enum mode_t mode = MESSAGE; int dat[5]; struct fmt_callbacks cb, *cbp = NULL; if (nmh_init(argv[0], 1)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; while ((cp = *argp++)) { if (*cp == '-') { /* * A -- means that we have a component name (like pick); * save the component name and the next argument for the text. */ if (*++cp == '-') { if (*++cp == '\0') adios(NULL, "missing component name after --"); app_msgarg(&compargs, cp); /* Grab next argument for component text */ if (!(cp = *argp++)) adios(NULL, "missing argument to %s", argp[-2]); app_msgarg(&compargs, cp); continue; } switch (smatch (cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case OTHERSW: adios(NULL, "internal argument error!"); continue; case OUTSIZESW: outputsize_given = true; if (!(cp = *argp++) || *cp == '-') adios(NULL, "missing argument to %s", argp[-2]); if (strcmp(cp, "max") == 0) outputsize = INT_MAX; else if (strcmp(cp, "width") == 0) outputsize = sc_width(); else outputsize = atoi(cp); continue; case FORMSW: if (!(form = *argp++) || *form == '-') adios (NULL, "missing argument to %s", argp[-2]); format = NULL; continue; case FMTSW: if (!(format = *argp++) || *format == '-') adios (NULL, "missing argument to %s", argp[-2]); form = NULL; continue; case TRACESW: trace = true; continue; case NTRACESW: trace = false; continue; case ADDRSW: mode = ADDRESS; defformat = DEFADDRFORMAT; continue; case RAWSW: mode = RAW; continue; case MESSAGESW: mode = MESSAGE; defformat = FORMAT; dupaddrs = false; continue; case DATESW: mode = DATE; defformat = DEFDATEFORMAT; continue; case FILESW: files++; continue; case NFILESW: files = 0; continue; case DUPADDRSW: dupaddrs = true; continue; case NDUPADDRSW: dupaddrs = false; continue; case CCMESW: ccme++; continue; case NCCMESW: ccme = 0; continue; case WIDTHSW: if (!(cp = *argp++) || *cp == '-') adios(NULL, "missing argument to %s", argp[-2]); colwidth = atoi(cp); continue; case MSGNUMSW: if (!(cp = *argp++) || *cp == '-') adios(NULL, "missing argument to %s", argp[-2]); msgnum = atoi(cp); continue; case MSGCURSW: if (!(cp = *argp++) || *cp == '-') adios(NULL, "missing argument to %s", argp[-2]); msgcur = atoi(cp); continue; case MSGSIZESW: if (!(cp = *argp++) || *cp == '-') adios(NULL, "missing argument to %s", argp[-2]); msgsize = atoi(cp); continue; case UNSEENSW: if (!(cp = *argp++) || *cp == '-') adios(NULL, "missing argument to %s", argp[-2]); msgunseen = atoi(cp); continue; case DUMPSW: dump = true; continue; case NDUMPSW: dump = false; continue; } } /* * Only interpret as a folder if we're in message mode */ if (mode == MESSAGE && !files && (*cp == '+' || *cp == '@')) { if (folder) adios (NULL, "only one folder at a time!"); else folder = pluspath (cp); } else app_msgarg(&msgs, cp); } /* * Here's our weird heuristic: * * - We allow -dump without any other arguments. * - If you've given any component arguments, we don't require any * other arguments. * - The arguments are interpreted as folders/messages _if_ we're in * message mode, otherwise pass as strings in the text component. */ if (!dump && compargs.size == 0 && msgs.size == 0) { adios (NULL, "usage: [switches] [+folder] msgs | strings...", invo_name); } /* * If you're picking "raw" as a mode, then you have to select * a format. */ if (mode == RAW && form == NULL && format == NULL) { adios (NULL, "You must specify a format with -form or -format when " "using -raw"); } /* * Get new format string. Must be before chdir(). */ nfs = new_fs (form, format, defformat); (void) fmt_compile(nfs, &fmt, 1); if (dump || trace) { initlabels(fmt); if (dump) { fmt_dump(nfs, fmt); if (compargs.size == 0 && msgs.size == 0) done(0); } } buffer = charstring_create(BUFSIZ); if (!outputsize_given) { outputsize = mode == MESSAGE ? sc_width() : INT_MAX; } dat[0] = msgnum; dat[1] = msgcur; dat[2] = msgsize; dat[3] = colwidth == -1 ? outputsize : colwidth; dat[4] = msgunseen; /* * If we want to provide our own formataddr, concactaddr, or tracing * callback, do that now. Also, prime ismymbox if we use it. */ if (!dupaddrs || trace) { memset(&cb, 0, sizeof(cb)); cbp = &cb; if (!dupaddrs) { cb.formataddr = test_formataddr; cb.concataddr = test_concataddr; if (!ccme) ismymbox(NULL); } if (trace) { struct trace_context *ctx; NEW(ctx); ctx->num = -1; ctx->str = dummy; ctx->outbuf = mh_xstrdup(""); cb.trace_func = test_trace; cb.trace_context = ctx; } } if (mode == MESSAGE) { process_messages(fmt, &compargs, &msgs, buffer, folder, outputsize, files, dat, cbp); } else { if (compargs.size) { for (i = 0; i < compargs.size; i += 2) { cptr = fmt_findcomp(compargs.msgs[i]); if (cptr) cptr->c_text = getcpy(compargs.msgs[i + 1]); } } if (mode == ADDRESS) { process_addresses(fmt, &msgs, buffer, outputsize, dat, cbp); } else /* Fall-through for RAW or DATE */ process_raw(fmt, &msgs, buffer, outputsize, dat, cbp); } charstring_free(buffer); fmt_free(fmt, 1); done(0); return 1; } /* * Process each address with fmt_scan(). */ struct pqpair { char *pq_text; char *pq_error; struct pqpair *pq_next; }; static void process_addresses(struct format *fmt, struct msgs_array *addrs, charstring_t buffer, int outwidth, int *dat, struct fmt_callbacks *cb) { int i; char *cp, error[BUFSIZ]; struct mailname *mp; struct pqpair *p, *q; struct pqpair pq; struct comp *c; if (dat[0] == -1) dat[0] = 0; if (dat[1] == -1) dat[1] = 0; if (dat[2] == -1) dat[2] = 0; if (dat[4] == -1) dat[4] = 0; for (i = 0; i < addrs->size; i++) { (q = &pq)->pq_next = NULL; while ((cp = getname(addrs->msgs[i]))) { NEW0(p); if ((mp = getm(cp, NULL, 0, error, sizeof(error))) == NULL) { p->pq_text = mh_xstrdup(cp); p->pq_error = mh_xstrdup(error); } else { p->pq_text = getcpy(mp->m_text); mnfree(mp); } q = (q->pq_next = p); } for (p = pq.pq_next; p; p = q) { c = fmt_findcomp("text"); if (c) { mh_xfree(c->c_text); c->c_text = p->pq_text; p->pq_text = NULL; } c = fmt_findcomp("error"); if (c) { mh_xfree(c->c_text); c->c_text = p->pq_error; p->pq_error = NULL; } fmt_scan(fmt, buffer, outwidth, dat, cb); fputs(charstring_buffer(buffer), stdout); charstring_clear(buffer); mlistfree(); mh_xfree(p->pq_text); mh_xfree(p->pq_error); q = p->pq_next; free(p); } } } /* * Process messages and run them through the format engine. A lot taken * from scan.c. */ static void process_messages(struct format *fmt, struct msgs_array *comps, struct msgs_array *msgs, charstring_t buffer, char *folder, int outwidth, int files, int *dat, struct fmt_callbacks *cb) { int i, msgnum, msgsize = dat[2], num = dat[0], cur = dat[1]; int num_unseen_seq = 0; ivector_t seqnum = ivector_create (0); char *maildir, *cp; struct msgs *mp; FILE *in; /* * If 'files' is set, short-circuit everything else and just process * everything now. */ if (files) { for (i = 0; i < msgs->size; i++) { if ((in = fopen(cp = msgs->msgs[i], "r")) == NULL) { admonish(cp, "unable to open file"); continue; } process_single_file(in, comps, dat, msgsize, fmt, buffer, outwidth, cb); } return; } if (! folder) folder = getfolder(1); maildir = m_maildir(folder); if (chdir(maildir) < 0) adios(maildir, "unable to change directory to"); if (!(mp = folder_read(folder, 1))) adios(NULL, "unable to read folder %s", folder); if (mp->nummsg == 0) adios(NULL, "no messages in %s", folder); for (i = 0; i < msgs->size; i++) if (!m_convert(mp, msgs->msgs[i])) done(1); seq_setprev(mp); /* set the Previous-Sequence */ context_replace(pfolder, folder); /* update current folder */ seq_save(mp); /* synchronize message sequences */ context_save(); /* save the context file */ /* * We want to set the unseen flag if requested, so we have to check * the unseen sequence as well. */ if (dat[4] == -1) { if ((cp = context_find(usequence)) && *cp) { char **ap, *dp; dp = mh_xstrdup(cp); ap = brkstring(dp, " ", "\n"); for (i = 0; ap && *ap; i++, ap++) ivector_push_back (seqnum, seq_getnum(mp, *ap)); num_unseen_seq = i; mh_xfree(dp); } } for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { if (is_selected(mp, msgnum)) { if ((in = fopen(cp = m_name(msgnum), "r")) == NULL) { admonish(cp, "unable to open message"); continue; } fmt_freecomptext(); if (num == -1) dat[0] = msgnum; if (cur == -1) dat[1] = msgnum == mp->curmsg; /* * Check to see if this is in the unseen sequence */ dat[4] = 0; for (i = 0; i < num_unseen_seq; i++) { if (in_sequence(mp, ivector_at (seqnum, i), msgnum)) { dat[4] = 1; break; } } /* * Read in the message and process the components */ process_single_file(in, comps, dat, msgsize, fmt, buffer, outwidth, cb); } } ivector_free (seqnum); folder_free(mp); } /* * Process a single file in message mode */ static void process_single_file(FILE *in, struct msgs_array *comps, int *dat, int msgsize, struct format *fmt, charstring_t buffer, int outwidth, struct fmt_callbacks *cb) { int i, state; char name[NAMESZ], rbuf[NMH_BUFSIZ]; m_getfld_state_t gstate = 0; struct comp *c; int bufsz; /* * Get our size if we didn't include one */ if (msgsize == -1) { struct stat st; if (fstat(fileno(in), &st) < 0) dat[2] = 0; else dat[2] = st.st_size; } /* * Initialize everything else */ if (dat[0] == -1) dat[0] = 0; if (dat[1] == -1) dat[1] = 0; if (dat[4] == -1) dat[4] = 0; /* * Read in the message and process the components */ for (;;) { bufsz = sizeof(rbuf); state = m_getfld(&gstate, name, rbuf, &bufsz, in); switch (state) { case FLD: case FLDPLUS: i = fmt_addcomptext(name, rbuf); if (i != -1) { while (state == FLDPLUS) { bufsz = sizeof(rbuf); state = m_getfld(&gstate, name, rbuf, &bufsz, in); fmt_appendcomp(i, name, rbuf); } } while (state == FLDPLUS) { bufsz = sizeof(rbuf); state = m_getfld(&gstate, name, rbuf, &bufsz, in); } break; case BODY: if (fmt_findcomp("body")) { if ((i = strlen(rbuf)) < outwidth) { bufsz = min (outwidth, (int) sizeof rbuf - i); m_getfld(&gstate, name, rbuf + i, &bufsz, in); } fmt_addcomptext("body", rbuf); } goto finished; default: goto finished; } } finished: fclose(in); m_getfld_state_destroy(&gstate); /* * Do this now to override any components in the original message */ if (comps->size) { for (i = 0; i < comps->size; i += 2) { c = fmt_findcomp(comps->msgs[i]); if (c) { mh_xfree(c->c_text); c->c_text = getcpy(comps->msgs[i + 1]); } } } fmt_scan(fmt, buffer, outwidth, dat, cb); fputs(charstring_buffer (buffer), stdout); charstring_clear(buffer); mlistfree(); } /* * Run text through the format engine with no special processing */ static void process_raw(struct format *fmt, struct msgs_array *text, charstring_t buffer, int outwidth, int *dat, struct fmt_callbacks *cb) { int i; struct comp *c; if (dat[0] == -1) dat[0] = 0; if (dat[1] == -1) dat[1] = 0; if (dat[2] == -1) dat[2] = 0; if (dat[4] == -1) dat[4] = 0; c = fmt_findcomp("text"); for (i = 0; i < text->size; i++) { if (c != NULL) { mh_xfree(c->c_text); c->c_text = getcpy(text->msgs[i]); } fmt_scan(fmt, buffer, outwidth, dat, cb); fputs(charstring_buffer (buffer), stdout); charstring_clear(buffer); mlistfree(); } } /* * Our basic tracing support callback. * * Print out each instruction as it's executed, including the values of * the num and str registers if they've changed. */ static void test_trace(void *context, struct format *fmt, int num, char *str, const char *outbuf) { struct trace_context *ctx = (struct trace_context *) context; int changed = 0; dumpone(fmt); if (num != ctx->num) { printf("num=%d", num); ctx->num = num; changed++; } if (str != ctx->str) { if (changed++) putchar(' '); printf("str="); litputs(str); ctx->str = str; } if (changed) putchar('\n'); if (strcmp(outbuf, ctx->outbuf) != 0) { printf("outbuf="); litputs(outbuf); putchar('\n'); free(ctx->outbuf); ctx->outbuf = mh_xstrdup(outbuf); } } static void fmt_dump (char *nfs, struct format *fmth) { struct format *fmt; printf("Instruction dump of format string: \n%s\n", nfs); /* Dump them out! */ for (fmt = fmth; fmt; ++fmt) { dumpone(fmt); if (fmt->f_type == FT_DONE && fmt->f_value == 0) break; } } static void dumpone(struct format *fmt) { int i; if ((i = findlabel(fmt)) >= 0) printf("L%d:", i); putchar('\t'); fputs(f_typestr((int)fmt->f_type), stdout); switch (fmt->f_type) { case FT_COMP: case FT_LS_COMP: case FT_LV_COMPFLAG: case FT_LV_COMP: printf(", comp "); litputs(fmt->f_comp->c_name); if (fmt->f_comp->c_type) printf(", c_type %s", c_typestr(fmt->f_comp->c_type)); if (fmt->f_comp->c_flags) printf(", c_flags %s", c_flagsstr(fmt->f_comp->c_flags)); break; case FT_LV_SEC: case FT_LV_MIN: case FT_LV_HOUR: case FT_LV_MDAY: case FT_LV_MON: case FT_LS_MONTH: case FT_LS_LMONTH: case FT_LS_ZONE: case FT_LV_YEAR: case FT_LV_WDAY: case FT_LS_DAY: case FT_LS_WEEKDAY: case FT_LV_YDAY: case FT_LV_ZONE: case FT_LV_CLOCK: case FT_LV_RCLOCK: case FT_LV_DAYF: case FT_LV_ZONEF: case FT_LV_DST: case FT_LS_822DATE: case FT_LS_PRETTY: case FT_LOCALDATE: case FT_GMTDATE: case FT_PARSEDATE: printf(", c_name "); litputs(fmt->f_comp->c_name); if (fmt->f_comp->c_type) printf(", c_type %s", c_typestr(fmt->f_comp->c_type)); if (fmt->f_comp->c_flags) printf(", c_flags %s", c_flagsstr(fmt->f_comp->c_flags)); break; case FT_LS_ADDR: case FT_LS_PERS: case FT_LS_MBOX: case FT_LS_HOST: case FT_LS_PATH: case FT_LS_GNAME: case FT_LS_NOTE: case FT_LS_822ADDR: case FT_LV_HOSTTYPE: case FT_LV_INGRPF: case FT_LV_NOHOSTF: case FT_LS_FRIENDLY: case FT_PARSEADDR: case FT_MYMBOX: case FT_GETMYMBOX: case FT_GETMYADDR: printf(", c_name "); litputs(fmt->f_comp->c_name); if (fmt->f_comp->c_type) printf(", c_type %s", c_typestr(fmt->f_comp->c_type)); if (fmt->f_comp->c_flags) printf(", c_flags %s", c_flagsstr(fmt->f_comp->c_flags)); break; case FT_COMPF: printf(", width %d, fill '", fmt->f_width); litputc(fmt->f_fill); printf("' name "); litputs(fmt->f_comp->c_name); if (fmt->f_comp->c_type) printf(", c_type %s", c_typestr(fmt->f_comp->c_type)); if (fmt->f_comp->c_flags) printf(", c_flags %s", c_flagsstr(fmt->f_comp->c_flags)); break; case FT_STRF: case FT_NUMF: printf(", width %d, fill '", fmt->f_width); litputc(fmt->f_fill); putchar('\''); break; case FT_LIT: putchar(' '); litputs(fmt->f_text); break; case FT_LITF: printf(", width %d, fill '", fmt->f_width); litputc(fmt->f_fill); printf("' "); litputs(fmt->f_text); break; case FT_CHAR: putchar(' '); putchar('\''); litputc(fmt->f_char); putchar('\''); break; case FT_IF_S: case FT_IF_S_NULL: case FT_IF_MATCH: case FT_IF_AMATCH: printf(" continue else goto"); /* FALLTHRU */ case FT_GOTO: i = findlabel(fmt + fmt->f_skip); printf(" L%d", i); break; case FT_IF_V_EQ: case FT_IF_V_NE: case FT_IF_V_GT: i = findlabel(fmt + fmt->f_skip); printf(" %d continue else goto L%d", fmt->f_value, i); break; case FT_V_EQ: case FT_V_NE: case FT_V_GT: case FT_LV_LIT: case FT_LV_PLUS_L: case FT_LV_MINUS_L: case FT_LV_MULTIPLY_L: case FT_LV_DIVIDE_L: case FT_LV_MODULO_L: printf(" value %d", fmt->f_value); break; case FT_LS_LIT: printf(" str "); litputs(fmt->f_text); break; case FT_LS_GETENV: printf(" getenv "); litputs(fmt->f_text); break; case FT_LS_DECODECOMP: printf(", comp "); litputs(fmt->f_comp->c_name); break; case FT_LS_DECODE: break; case FT_LS_TRIM: printf(", width %d", fmt->f_width); break; case FT_LV_DAT: printf(", value dat[%d]", fmt->f_value); break; } putchar('\n'); } /* * Iterate over all instructions and assign labels to the targets of * branch statements */ static void initlabels(struct format *fmth) { struct format *fmt, *addr; int i; /* Assign labels */ for (fmt = fmth; fmt; ++fmt) { i = fmt->f_type; if (i == FT_IF_S || i == FT_IF_S_NULL || i == FT_IF_V_EQ || i == FT_IF_V_NE || i == FT_IF_V_GT || i == FT_IF_MATCH || i == FT_IF_AMATCH || i == FT_GOTO) { addr = fmt + fmt->f_skip; if (findlabel(addr) < 0) assignlabel(addr); } if (fmt->f_type == FT_DONE && fmt->f_value == 0) break; } } static int findlabel(struct format *addr) { int i; for (i = 0; i < lused; ++i) if (addr == lvec[i]) return(i); return(-1); } static void assignlabel(struct format *addr) { if (lused >= lallocated) { lallocated += 64; lvec = (struct format **) mh_xrealloc(lvec, sizeof(struct format *) * lallocated); } lvec[lused++] = addr; } static char * f_typestr(int t) { static char buf[32]; switch (t) { case FT_COMP: return "COMP"; case FT_COMPF: return "COMPF"; case FT_LIT: return "LIT"; case FT_LITF: return "LITF"; case FT_CHAR: return "CHAR"; case FT_NUM: return "NUM"; case FT_NUMF: return "NUMF"; case FT_STR: return "STR"; case FT_STRF: return "STRF"; case FT_STRFW: return "STRFW"; case FT_STRLIT: return "STRLIT"; case FT_STRLITZ: return "STRLITZ"; case FT_PUTADDR: return "PUTADDR"; case FT_LS_COMP: return "LS_COMP"; case FT_LS_LIT: return "LS_LIT"; case FT_LS_GETENV: return "LS_GETENV"; case FT_LS_CFIND: return "LS_CFIND"; case FT_LS_DECODECOMP: return "LS_DECODECOMP"; case FT_LS_DECODE: return "LS_DECODE"; case FT_LS_TRIM: return "LS_TRIM"; case FT_LV_COMP: return "LV_COMP"; case FT_LV_COMPFLAG: return "LV_COMPFLAG"; case FT_LV_LIT: return "LV_LIT"; case FT_LV_DAT: return "LV_DAT"; case FT_LV_STRLEN: return "LV_STRLEN"; case FT_LV_PLUS_L: return "LV_PLUS_L"; case FT_LV_MINUS_L: return "LV_MINUS_L"; case FT_LV_MULTIPLY_L: return "LV_MULTIPLY_L"; case FT_LV_DIVIDE_L: return "LV_DIVIDE_L"; case FT_LV_MODULO_L: return "LV_MODULO_L"; case FT_LV_CHAR_LEFT: return "LV_CHAR_LEFT"; case FT_LS_MONTH: return "LS_MONTH"; case FT_LS_LMONTH: return "LS_LMONTH"; case FT_LS_ZONE: return "LS_ZONE"; case FT_LS_DAY: return "LS_DAY"; case FT_LS_WEEKDAY: return "LS_WEEKDAY"; case FT_LS_822DATE: return "LS_822DATE"; case FT_LS_PRETTY: return "LS_PRETTY"; case FT_LS_KILO: return "LS_KILO"; case FT_LS_KIBI: return "LS_KIBI"; case FT_LV_SEC: return "LV_SEC"; case FT_LV_MIN: return "LV_MIN"; case FT_LV_HOUR: return "LV_HOUR"; case FT_LV_MDAY: return "LV_MDAY"; case FT_LV_MON: return "LV_MON"; case FT_LV_YEAR: return "LV_YEAR"; case FT_LV_YDAY: return "LV_YDAY"; case FT_LV_WDAY: return "LV_WDAY"; case FT_LV_ZONE: return "LV_ZONE"; case FT_LV_CLOCK: return "LV_CLOCK"; case FT_LV_RCLOCK: return "LV_RCLOCK"; case FT_LV_DAYF: return "LV_DAYF"; case FT_LV_DST: return "LV_DST"; case FT_LV_ZONEF: return "LV_ZONEF"; case FT_LS_PERS: return "LS_PERS"; case FT_LS_MBOX: return "LS_MBOX"; case FT_LS_HOST: return "LS_HOST"; case FT_LS_PATH: return "LS_PATH"; case FT_LS_GNAME: return "LS_GNAME"; case FT_LS_NOTE: return "LS_NOTE"; case FT_LS_ADDR: return "LS_ADDR"; case FT_LS_822ADDR: return "LS_822ADDR"; case FT_LS_FRIENDLY: return "LS_FRIENDLY"; case FT_LV_HOSTTYPE: return "LV_HOSTTYPE"; case FT_LV_INGRPF: return "LV_INGRPF"; case FT_LS_UNQUOTE: return "LS_UNQUOTE"; case FT_LV_NOHOSTF: return "LV_NOHOSTF"; case FT_LOCALDATE: return "LOCALDATE"; case FT_GMTDATE: return "GMTDATE"; case FT_PARSEDATE: return "PARSEDATE"; case FT_PARSEADDR: return "PARSEADDR"; case FT_FORMATADDR: return "FORMATADDR"; case FT_CONCATADDR: return "CONCATADDR"; case FT_MYMBOX: return "MYMBOX"; case FT_GETMYMBOX: return "GETMYMBOX"; case FT_GETMYADDR: return "GETMYADDR"; case FT_SAVESTR: return "SAVESTR"; case FT_DONE: return "DONE"; case FT_PAUSE: return "PAUSE"; case FT_NOP: return "NOP"; case FT_GOTO: return "GOTO"; case FT_IF_S_NULL: return "IF_S_NULL"; case FT_IF_S: return "IF_S"; case FT_IF_V_EQ: return "IF_V_EQ"; case FT_IF_V_NE: return "IF_V_NE"; case FT_IF_V_GT: return "IF_V_GT"; case FT_IF_MATCH: return "IF_MATCH"; case FT_IF_AMATCH: return "IF_AMATCH"; case FT_S_NULL: return "S_NULL"; case FT_S_NONNULL: return "S_NONNULL"; case FT_V_EQ: return "V_EQ"; case FT_V_NE: return "V_NE"; case FT_V_GT: return "V_GT"; case FT_V_MATCH: return "V_MATCH"; case FT_V_AMATCH: return "V_AMATCH"; default: snprintf(buf, sizeof(buf), "/* ??? #%d */", t); return(buf); } } static char * c_typestr(int t) { static char buf[64]; snprintb(buf, sizeof(buf), t, CT_BITS); return(buf); } static char * c_flagsstr(int t) { static char buf[64]; snprintb(buf, sizeof(buf), t, CF_BITS); return(buf); } static void litputs(const char *s) { if (s) { putchar('"'); while (*s) litputc(*s++); putchar('"'); } else fputs("", stdout); } static void litputc(char c) { if (c & ~ 0177) { printf("\\x%02x", (unsigned char) c); } else if (c < 0x20 || c == 0177) { if (c == '\b') { putchar('\\'); putchar('b'); } else if (c == '\f') { putchar('\\'); putchar('f'); } else if (c == '\n') { putchar('\\'); putchar('n'); } else if (c == '\r') { putchar('\\'); putchar('r'); } else if (c == '\t') { putchar('\\'); putchar('t'); } else { putchar('^'); putchar(c ^ 0x40); /* DEL to ?, others to alpha */ } } else putchar(c); } /* * Routines/code to support the duplicate address suppression code, adapted * from replsbr.c */ static char *buf; /* our current working buffer */ static char *bufend; /* end of working buffer */ static char *last_dst; /* buf ptr at end of last call */ static unsigned int bufsiz=0; /* current size of buf */ #define BUFINCR 512 /* how much to expand buf when if fills */ #define CPY(s) { cp = (s); while ((*dst++ = *cp++)) ; --dst; } /* * check if there's enough room in buf for str. * add more mem if needed */ #define CHECKMEM(str) \ if ((len = strlen (str)) >= bufend - dst) {\ int i = dst - buf;\ int n = last_dst - buf;\ bufsiz += ((dst + len - bufend) / BUFINCR + 1) * BUFINCR;\ buf = mh_xrealloc (buf, bufsiz);\ dst = buf + i;\ last_dst = buf + n;\ bufend = buf + bufsiz;\ } /* * These are versions of similar routines from replsbr.c; the purpose is * to suppress duplicate addresses from being added to a list when building * up addresses for the %(formataddr) format function. This is used by * repl to prevent duplicate addresses from being added to the "to" line. * See replsbr.c for more information. * * We can't use the functions in replsbr.c directly because they are slightly * different and depend on the rest of replsbr.c */ static char * test_formataddr (char *orig, char *str) { int len; char error[BUFSIZ]; int isgroup; char *dst; char *cp; char *sp; struct mailname *mp = NULL; /* if we don't have a buffer yet, get one */ if (bufsiz == 0) { buf = mh_xmalloc (BUFINCR); last_dst = buf; /* XXX */ bufsiz = BUFINCR - 6; /* leave some slop */ bufend = buf + bufsiz; } /* * If "orig" points to our buffer we can just pick up where we * left off. Otherwise we have to copy orig into our buffer. */ if (orig == buf) dst = last_dst; else if (!orig || !*orig) { dst = buf; *dst = '\0'; } else { dst = last_dst; /* XXX */ CHECKMEM (orig); CPY (orig); } /* concatenate all the new addresses onto 'buf' */ for (isgroup = 0; (cp = getname (str)); ) { if ((mp = getm (cp, NULL, 0, error, sizeof(error))) == NULL) { fprintf(stderr, "bad address \"%s\" -- %s\n", cp, error); continue; } if (isgroup && (mp->m_gname || !mp->m_ingrp)) { *dst++ = ';'; isgroup = 0; } if (insert (mp)) { /* if we get here we're going to add an address */ if (dst != buf) { *dst++ = ','; *dst++ = ' '; } if (mp->m_gname) { CHECKMEM (mp->m_gname); CPY (mp->m_gname); isgroup++; } sp = adrformat (mp); CHECKMEM (sp); CPY (sp); } } if (isgroup) *dst++ = ';'; *dst = '\0'; last_dst = dst; return (buf); } /* * The companion to test_formataddr(); it behaves the same way, except doesn't * do duplicate address detection. */ static char * test_concataddr(char *orig, char *str) { char *cp; nodupcheck = 1; cp = test_formataddr(orig, str); nodupcheck = 0; return cp; } static int insert (struct mailname *np) { struct mailname *mp; if (nodupcheck) return 1; if (np->m_mbox == NULL) return 0; for (mp = &mq; mp->m_next; mp = mp->m_next) { if (!strcasecmp (FENDNULL(np->m_host), FENDNULL(mp->m_next->m_host)) && !strcasecmp (FENDNULL(np->m_mbox), FENDNULL(mp->m_next->m_mbox))) return 0; } if (!ccme && ismymbox (np)) return 0; mp->m_next = np; return 1; } /* * Reset our duplicate address list */ void mlistfree(void) { struct mailname *mp, *mp2; for (mp = mq.m_next; mp; mp = mp2) { mp2 = mp->m_next; mnfree(mp); } } nmh-1.7.1-RC3/uip/folder.c000644 007761 000024 00000036244 13243042053 015203 0ustar00kenhstaff000000 000000 /* folder.c -- set/list the current message and/or folder * -- push/pop a folder onto/from the folder stack * -- list the folder stack * * This code is Copyright (c) 2002, 2008, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include "../sbr/m_maildir.h" #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", 0, 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? */ static int fpack = 0; /* are we packing the folder? */ static int fverb = 0; /* print actions taken while packing folder */ static int fheader = 0; /* should we output a header? */ static int frecurse = 0; /* recurse through subfolders */ static int ftotal = 0; /* should we output the totals? */ static int all = 0; /* should we output all folders */ static int total_folders = 0; /* total number of folders */ static char *nmhdir; static char *stack = "Folder-Stack"; static char folder[BUFSIZ]; /* * Structure to hold information about * folders as we scan them. */ struct FolderInfo { char *name; int nummsg; int curmsg; int lowmsg; int hghmsg; int others; /* others == 1 if other files in folder */ int error; /* error == 1 for unreadable folder */ }; /* * Dynamically allocated space to hold * all the folder information. */ static struct FolderInfo *fi; static int maxFolderInfo; /* * static prototypes */ static int get_folder_info (char *, char *); static crawl_callback_t get_folder_info_callback; static void print_folders (void); static int sfold (struct msgs *, char *); static void readonly_folders (void); /* * Function for printing error message if folder does not exist with * -nocreate. */ static void nonexistent_folder (int status) { NMH_UNUSED (status); adios (NULL, "folder %s does not exist", folder); } int main (int argc, char **argv) { int printsw = 0, listsw = 0; int pushsw = 0, popsw = 0; char *cp, *dp, *msg = NULL, *argfolder = NULL; char **ap, **argp, buf[BUFSIZ], **arguments; if (nmh_init(argv[0], 1)) { return 1; } /* * If program was invoked with name ending * in `s', then add switch `-all'. */ all = has_suffix_c(argv[0], 's'); arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [+folder] [msg] [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case ALLSW: all = 1; continue; case NALLSW: all = 0; continue; case CREATSW: fcreat = 1; continue; case NCREATSW: fcreat = -1; continue; case FASTSW: fshort++; continue; case NFASTSW: fshort = 0; continue; case HDRSW: fheader = 1; continue; case NHDRSW: fheader = -1; continue; case PACKSW: fpack++; continue; case NPACKSW: fpack = 0; continue; case VERBSW: fverb++; continue; case NVERBSW: fverb = 0; continue; case RECURSW: frecurse++; continue; case NRECRSW: frecurse = 0; continue; case TOTALSW: ftotal = 1; continue; case NTOTLSW: ftotal = -1; continue; case PRNTSW: printsw = 1; continue; case NPRNTSW: printsw = 0; continue; case LISTSW: listsw = 1; continue; case NLISTSW: listsw = 0; continue; case PUSHSW: pushsw = 1; listsw = 1; popsw = 0; continue; case POPSW: popsw = 1; listsw = 1; pushsw = 0; continue; } } if (*cp == '+' || *cp == '@') { if (argfolder) adios (NULL, "only one folder at a time!"); else argfolder = pluspath (cp); } else { if (msg) adios (NULL, "only one (current) message at a time!"); else msg = cp; } } if (!context_find ("path")) free (path ("./", TFOLDER)); nmhdir = concat (m_maildir (""), "/", NULL); /* * If we aren't working with the folder stack * (-push, -pop, -list) then the default is to print. */ if (pushsw == 0 && popsw == 0 && listsw == 0) printsw++; /* Pushing a folder onto the folder stack */ if (pushsw) { if (!argfolder) { /* If no folder is given, the current folder and */ /* the top of the folder stack are swapped. */ if ((cp = context_find (stack))) { dp = mh_xstrdup(cp); ap = brkstring (dp, " ", "\n"); argfolder = getcpy(*ap++); } else { adios (NULL, "no other folder"); } for (cp = getcpy (getfolder (1)); *ap; ap++) cp = add (*ap, add (" ", cp)); free (dp); context_replace (stack, cp); /* update folder stack */ } else { /* update folder stack */ context_replace (stack, (cp = context_find (stack)) ? concat (getfolder (1), " ", cp, NULL) : getcpy (getfolder (1))); } } /* Popping a folder off of the folder stack */ if (popsw) { if (argfolder) adios (NULL, "sorry, no folders allowed with -pop"); if ((cp = context_find (stack))) { dp = mh_xstrdup(cp); ap = brkstring (dp, " ", "\n"); argfolder = getcpy(*ap++); } else { adios (NULL, "folder stack empty"); } if (*ap) { /* if there's anything left in the stack */ cp = getcpy (*ap++); for (; *ap; ap++) cp = add (*ap, add (" ", cp)); context_replace (stack, cp); /* update folder stack */ } else { context_del (stack); /* delete folder stack entry from context */ } free (dp); } if (pushsw || popsw) { cp = m_maildir(argfolder); if (access (cp, F_OK) == NOTOK) adios (cp, "unable to find folder"); context_replace (pfolder, argfolder); /* update current folder */ context_save (); /* save the context file */ argfolder = NULL; } /* Listing the folder stack */ if (listsw) { fputs(argfolder ? argfolder : getfolder (1), stdout); if ((cp = context_find (stack))) { dp = mh_xstrdup(cp); for (ap = brkstring (dp, " ", "\n"); *ap; ap++) printf (" %s", *ap); free (dp); } putchar('\n'); if (!printsw) done (0); } /* Allocate initial space to record folder information */ maxFolderInfo = CRAWL_NUMFOLDERS; fi = mh_xmalloc (maxFolderInfo * sizeof(*fi)); /* * Scan the folders */ /* change directory to base of nmh directory for crawl_folders */ if (chdir (nmhdir) == NOTOK) adios (nmhdir, "unable to change directory to"); if (all || ftotal > 0) { /* * If no folder is given, do them all */ if (!argfolder) { if (msg) inform("no folder given for message %s, continuing...", msg); readonly_folders (); /* do any readonly folders */ cp = context_find(pfolder); strncpy (folder, FENDNULL(cp), sizeof(folder)); crawl_folders (".", get_folder_info_callback, NULL); } else { strncpy (folder, argfolder, sizeof(folder)); if (get_folder_info (argfolder, msg)) { context_replace (pfolder, argfolder);/* update current folder */ context_save (); /* save the context file */ } /* * Since recurse wasn't done in get_folder_info(), * we still need to list all level-1 sub-folders. */ if (!frecurse) crawl_folders (folder, get_folder_info_callback, NULL); } } else { strncpy (folder, argfolder ? argfolder : getfolder (1), sizeof(folder)); /* * Check if folder exists. If not, then see if * we should create it, or just exit. */ create_folder (m_maildir (folder), fcreat, nonexistent_folder); if (get_folder_info (folder, msg) && argfolder) { /* update current folder */ context_replace (pfolder, argfolder); } } /* * Print out folder information */ print_folders(); context_save (); /* save the context file */ done (0); return 1; } static int get_folder_info_body (char *fold, char *msg, boolean *crawl_children) { int i, retval = 1; struct msgs *mp = NULL; i = total_folders++; /* * if necessary, reallocate the space * for folder information */ if (total_folders >= maxFolderInfo) { maxFolderInfo += CRAWL_NUMFOLDERS; fi = mh_xrealloc (fi, maxFolderInfo * sizeof(*fi)); } fi[i].name = fold; fi[i].nummsg = 0; fi[i].curmsg = 0; fi[i].lowmsg = 0; fi[i].hghmsg = 0; fi[i].others = 0; fi[i].error = 0; if ((ftotal > 0) || !fshort || msg || fpack) { /* * create message structure and get folder info */ if (!(mp = folder_read (fold, fpack))) { inform("unable to read folder %s, continuing...", fold); *crawl_children = FALSE; return 0; } /* set the current message */ if (msg && !sfold (mp, msg)) retval = 0; if (fpack) { if (folder_pack (&mp, fverb) == -1) { *crawl_children = FALSE; /* to please clang static analyzer */ done (1); } seq_save (mp); /* synchronize the sequences */ context_save (); /* save the context file */ } /* record info for this folder */ if ((ftotal > 0) || !fshort) { fi[i].nummsg = mp->nummsg; fi[i].curmsg = mp->curmsg; fi[i].lowmsg = mp->lowmsg; fi[i].hghmsg = mp->hghmsg; fi[i].others = other_files (mp); } folder_free (mp); /* free folder/message structure */ } *crawl_children = (frecurse && (fshort || fi[i].others) && (fi[i].error == 0)); return retval; } static boolean get_folder_info_callback (char *fold, void *baton) { boolean crawl_children; NMH_UNUSED (baton); get_folder_info_body (fold, NULL, &crawl_children); fflush (stdout); return crawl_children; } static int get_folder_info (char *fold, char *msg) { boolean crawl_children; int retval; retval = get_folder_info_body (fold, msg, &crawl_children); if (crawl_children) { crawl_folders (fold, get_folder_info_callback, NULL); } return retval; } /* * Print folder information */ static void print_folders (void) { int i, len, hasempty = 0, curprinted; int maxlen = 0, maxnummsg = 0, maxlowmsg = 0; int maxhghmsg = 0, maxcurmsg = 0, total_msgs = 0; int nummsgdigits, lowmsgdigits; int hghmsgdigits, curmsgdigits; char tmpname[BUFSIZ]; /* * compute a few values needed to for * printing various fields */ for (i = 0; i < total_folders; i++) { /* length of folder name */ len = strlen (fi[i].name); if (len > maxlen) maxlen = len; /* If folder has error, skip the rest */ if (fi[i].error) continue; /* calculate total number of messages */ total_msgs += fi[i].nummsg; /* maximum number of messages */ if (fi[i].nummsg > maxnummsg) maxnummsg = fi[i].nummsg; /* maximum low message */ if (fi[i].lowmsg > maxlowmsg) maxlowmsg = fi[i].lowmsg; /* maximum high message */ if (fi[i].hghmsg > maxhghmsg) maxhghmsg = fi[i].hghmsg; /* maximum current message */ if (fi[i].curmsg >= fi[i].lowmsg && fi[i].curmsg <= fi[i].hghmsg && fi[i].curmsg > maxcurmsg) maxcurmsg = fi[i].curmsg; /* check for empty folders */ if (fi[i].nummsg == 0) hasempty = 1; } nummsgdigits = num_digits (maxnummsg); lowmsgdigits = num_digits (maxlowmsg); hghmsgdigits = num_digits (maxhghmsg); curmsgdigits = num_digits (maxcurmsg); if (hasempty && nummsgdigits < 2) nummsgdigits = 2; /* * Print the header */ if (fheader > 0 || (all && !fshort && fheader >= 0)) printf ("%-*s %*s %-*s; %-*s %*s\n", maxlen+1, "FOLDER", nummsgdigits + 13, "# MESSAGES", lowmsgdigits + hghmsgdigits + 4, " RANGE", curmsgdigits + 4, "CUR", 9, "(OTHERS)"); /* * Print folder information */ if (all || fshort || ftotal < 1) { for (i = 0; i < total_folders; i++) { if (fshort) { puts(fi[i].name); continue; } /* Add `+' to end of name, if folder is current */ if (strcmp (folder, fi[i].name)) snprintf (tmpname, sizeof(tmpname), "%s", fi[i].name); else snprintf (tmpname, sizeof(tmpname), "%s+", fi[i].name); if (fi[i].error) { printf ("%-*s is unreadable\n", maxlen+1, tmpname); continue; } printf ("%-*s ", maxlen+1, tmpname); curprinted = 0; /* remember if we print cur */ if (fi[i].nummsg == 0) { printf ("has %*s messages%*s", nummsgdigits, "no", fi[i].others ? lowmsgdigits + hghmsgdigits + 5 : 0, ""); } else { printf ("has %*d message%1s (%*d-%*d)", nummsgdigits, fi[i].nummsg, PLURALS(fi[i].nummsg), lowmsgdigits, fi[i].lowmsg, hghmsgdigits, fi[i].hghmsg); if (fi[i].curmsg >= fi[i].lowmsg && fi[i].curmsg <= fi[i].hghmsg) { curprinted = 1; printf ("; cur=%*d", curmsgdigits, fi[i].curmsg); } } if (fi[i].others) printf (";%*s (others)", curprinted ? 0 : curmsgdigits + 6, ""); puts("."); } } /* * Print folder/message totals */ if (ftotal > 0 || (all && !fshort && ftotal >= 0)) { if (all) putchar('\n'); printf ("TOTAL = %d message%s in %d folder%s.\n", total_msgs, PLURALS(total_msgs), total_folders, PLURALS(total_folders)); } fflush (stdout); } /* * Set the current message and synchronize sequences */ static int sfold (struct msgs *mp, char *msg) { /* parse the message range/sequence/name and set SELECTED */ if (!m_convert (mp, msg)) return 0; if (mp->numsel > 1) { inform("only one message at a time!, continuing..."); return 0; } seq_setprev (mp); /* set the previous-sequence */ seq_setcur (mp, mp->lowsel);/* set current message */ seq_save (mp); /* synchronize message sequences */ context_save (); /* save the context file */ return 1; } /* * Do the read only folders */ static void readonly_folders (void) { int atrlen; char atrcur[BUFSIZ]; struct node *np; snprintf (atrcur, sizeof(atrcur), "atr-%s-", current); atrlen = strlen (atrcur); for (np = m_defs; np; np = np->n_next) if (ssequal (atrcur, np->n_name) && !ssequal (nmhdir, np->n_name + atrlen)) get_folder_info (np->n_name + atrlen, NULL); } nmh-1.7.1-RC3/uip/forw.c000644 007761 000024 00000040662 13243042053 014704 0ustar00kenhstaff000000 000000 /* forw.c -- forward a message, or group of messages. * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include "../sbr/m_maildir.h" #define IFORMAT "digest-issue-%s" #define VFORMAT "digest-volume-%s" #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) \ 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, NOSW }, { "replace", 0, YESW }, { "list", 0, LISTDSW }, { "refile +folder", 0, REFILSW }, { NULL, 0, 0 } }; static char drft[BUFSIZ]; static char delim3[] = "\n------------------------------------------------------------\n\n"; static char delim4[] = "\n------------------------------\n\n"; static struct msgs *mp = NULL; /* used a lot */ /* * static prototypes */ static void mhl_draft (int, char *, int, int, char *, char *, int); static void copy_draft (int, char *, char *, int, int, int); static void copy_mime_draft (int); int main (int argc, char **argv) { int anot = 0, inplace = 1, mime = 0; int issue = 0, volume = 0, dashstuff = 0; int nedit = 0, nwhat = 0, i, in; int out, isdf = 0, msgnum = 0; int outputlinelen = OUTPUTLINELEN; int dat[5]; char *cp, *cwd, *maildir, *dfolder = NULL; char *dmsg = NULL, *digest = NULL, *ed = NULL; char *file = NULL, *filter = NULL, *folder = NULL, *fwdmsg = NULL; char *from = NULL, *to = NULL, *cc = NULL, *subject = NULL, *fcc = NULL; char *form = NULL, buf[BUFSIZ]; char **argp, **arguments; struct stat st; struct msgs_array msgs = { 0, 0, NULL }; int buildsw = 0; if (nmh_init(argv[0], 1)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [+folder] [msgs] [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case ANNOSW: anot++; continue; case NANNOSW: anot = 0; continue; case EDITRSW: if (!(ed = *argp++) || *ed == '-') adios (NULL, "missing argument to %s", argp[-2]); nedit = 0; continue; case NEDITSW: nedit++; continue; case WHATSW: if (!(whatnowproc = *argp++) || *whatnowproc == '-') adios (NULL, "missing argument to %s", argp[-2]); nwhat = 0; continue; case BILDSW: buildsw++; /* FALLTHRU */ case NWHATSW: nwhat++; continue; case FILESW: if (file) adios (NULL, "only one file at a time!"); if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); file = path (cp, TFILE); continue; case FILTSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); filter = getcpy (etcpath (cp)); mime = 0; continue; case FORMSW: if (!(form = *argp++) || *form == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case FRMTSW: filter = getcpy (etcpath (mhlforward)); continue; case NFRMTSW: filter = NULL; continue; case INPLSW: inplace++; continue; case NINPLSW: inplace = 0; continue; case MIMESW: mime++; filter = NULL; continue; case NMIMESW: mime = 0; continue; case DGSTSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); digest = mh_xstrdup(cp); mime = 0; continue; case ISSUESW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if ((issue = atoi (cp)) < 1) adios (NULL, "bad argument %s %s", argp[-2], cp); continue; case VOLUMSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if ((volume = atoi (cp)) < 1) adios (NULL, "bad argument %s %s", argp[-2], cp); continue; case DFOLDSW: if (dfolder) adios (NULL, "only one draft folder at a time!"); if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); dfolder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp, *cp != '@' ? TFOLDER : TSUBCWF); continue; case DMSGSW: if (dmsg) adios (NULL, "only one draft message at a time!"); if (!(dmsg = *argp++) || *dmsg == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case NDFLDSW: dfolder = NULL; isdf = NOTOK; continue; case BITSTUFFSW: dashstuff = 1; /* ternary logic */ continue; case NBITSTUFFSW: dashstuff = -1; /* ternary logic */ continue; case FROMSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); from = addlist(from, cp); continue; case TOSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); to = addlist(to, cp); continue; case CCSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); cc = addlist(cc, cp); continue; case FCCSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); fcc = addlist(fcc, cp); continue; case SUBJECTSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); subject = mh_xstrdup(cp); continue; case WIDTHSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if ((outputlinelen = atoi(cp)) < 10) adios (NULL, "impossible width %d", outputlinelen); continue; } } if (*cp == '+' || *cp == '@') { if (folder) adios (NULL, "only one folder at a time!"); else folder = pluspath (cp); } else { app_msgarg(&msgs, cp); } } cwd = mh_xstrdup(pwd ()); if (!context_find ("path")) free (path ("./", TFOLDER)); if (file && (msgs.size || folder)) adios (NULL, "can't mix files and folders/msgs"); try_it_again: strncpy (drft, buildsw ? m_maildir ("draft") : m_draft (dfolder, NULL, NOUSE, &isdf), sizeof(drft)); /* Check if a draft already exists */ if (!buildsw && stat (drft, &st) != NOTOK) { printf ("Draft \"%s\" exists (%ld bytes).", drft, (long) st.st_size); for (i = LISTDSW; i != YESW;) { if (!(argp = read_switch_multiword ("\nDisposition? ", isdf ? aqrnl : aqrl))) done (1); switch (i = smatch (*argp, isdf ? aqrnl : aqrl)) { case NOSW: done (0); case NEWSW: dmsg = NULL; goto try_it_again; case YESW: break; case LISTDSW: showfile (++argp, drft); break; case REFILSW: if (refile (++argp, drft) == 0) i = YESW; break; default: inform("say what?"); break; } } } if (file) { /* * Forwarding a file. */ anot = 0; /* don't want to annotate a file */ } else { /* * Forwarding a message. */ if (!msgs.size) app_msgarg(&msgs, "cur"); if (!folder) folder = getfolder (1); maildir = m_maildir (folder); if (chdir (maildir) == NOTOK) adios (maildir, "unable to change directory to"); /* read folder and create message structure */ if (!(mp = folder_read (folder, 1))) adios (NULL, "unable to read folder %s", folder); /* check for empty folder */ if (mp->nummsg == 0) adios (NULL, "no messages in %s", folder); /* parse all the message ranges/sequences and set SELECTED */ for (msgnum = 0; msgnum < msgs.size; msgnum++) if (!m_convert (mp, msgs.msgs[msgnum])) done (1); seq_setprev (mp); /* set the previous sequence */ /* * Find the first message in our set and use it as the input * for the component scanner */ for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) if (is_selected (mp, msgnum)) { fwdmsg = mh_xstrdup(m_name(msgnum)); break; } if (! fwdmsg) adios (NULL, "Unable to find input message"); } if (filter && access (filter, R_OK) == NOTOK) adios (filter, "unable to read"); /* * Open form (component) file. */ if (digest) { if (issue == 0) { snprintf (buf, sizeof(buf), IFORMAT, digest); if (volume == 0 && (cp = context_find (buf)) && ((issue = atoi (cp)) < 0)) issue = 0; issue++; } if (volume == 0) { snprintf (buf, sizeof(buf), VFORMAT, digest); if ((cp = context_find (buf)) == NULL || (volume = atoi (cp)) <= 0) volume = 1; } if (!form) form = digestcomps; } else { if (!form) form = forwcomps; } dat[0] = digest ? issue : msgnum; dat[1] = volume; dat[2] = 0; dat[3] = outputlinelen; dat[4] = 0; in = build_form (form, digest, dat, from, to, cc, fcc, subject, file ? file : fwdmsg); if ((out = creat (drft, m_gmprot ())) == NOTOK) adios (drft, "unable to create"); /* * copy the components into the draft */ cpydata (in, out, form, drft); close (in); if (file) { /* just copy the file into the draft */ if ((in = open (file, O_RDONLY)) == NOTOK) adios (file, "unable to open"); cpydata (in, out, file, drft); close (in); close (out); } else { /* * If filter file is defined, then format the * messages into the draft using mhlproc. */ if (filter) mhl_draft (out, digest, volume, issue, drft, filter, dashstuff); else if (mime) copy_mime_draft (out); else copy_draft (out, digest, drft, volume, issue, dashstuff); close (out); if (digest) { snprintf (buf, sizeof(buf), IFORMAT, digest); context_replace (buf, mh_xstrdup(m_str(issue))); snprintf (buf, sizeof(buf), VFORMAT, digest); context_replace (buf, mh_xstrdup(m_str(volume))); } context_replace (pfolder, folder); /* update current folder */ seq_setcur (mp, mp->lowsel); /* update current message */ seq_save (mp); /* synchronize sequences */ context_save (); /* save the context file */ } if (nwhat) done (0); what_now (ed, nedit, NOUSE, drft, NULL, 0, mp, anot ? "Forwarded" : NULL, inplace, cwd, 0); done (1); return 1; } /* * Filter the messages you are forwarding, into the * draft calling the mhlproc, and reading its output * from a pipe. */ static void mhl_draft (int out, char *digest, int volume, int issue, char *file, char *filter, int dashstuff) { pid_t child_id; int i, msgnum, pd[2]; char buf1[BUFSIZ]; char buf2[BUFSIZ]; char *program; struct msgs_array vec = { 0, 0, NULL }; if (pipe (pd) == NOTOK) adios ("pipe", "unable to create"); argsplit_msgarg(&vec, mhlproc, &program); for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++) sleep (5); switch (child_id) { case NOTOK: adios ("fork", "unable to"); case OK: close (pd[0]); dup2 (pd[1], 1); close (pd[1]); app_msgarg(&vec, "-forwall"); app_msgarg(&vec, "-form"); app_msgarg(&vec, filter); if (digest) { app_msgarg(&vec, "-digest"); app_msgarg(&vec, digest); app_msgarg(&vec, "-issue"); snprintf (buf1, sizeof(buf1), "%d", issue); app_msgarg(&vec, buf1); app_msgarg(&vec, "-volume"); snprintf (buf2, sizeof(buf2), "%d", volume); app_msgarg(&vec, buf2); } /* * Are we dashstuffing (quoting) the lines that begin * with `-'. We use the mhl default (don't add any flag) * unless the user has specified a specific flag. */ if (dashstuff > 0) app_msgarg(&vec, "-dashstuffing"); else if (dashstuff < 0) app_msgarg(&vec, "-nodashstuffing"); for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { if (is_selected (mp, msgnum)) app_msgarg(&vec, mh_xstrdup(m_name (msgnum))); } app_msgarg(&vec, NULL); execvp (program, vec.msgs); fprintf (stderr, "unable to exec "); perror (mhlproc); _exit (-1); default: close (pd[1]); cpydata (pd[0], out, vec.msgs[0], file); close (pd[0]); pidXwait(child_id, mhlproc); break; } } /* * Copy the messages into the draft. The messages are * not filtered through the mhlproc. Do dashstuffing if * necessary. */ static void copy_draft (int out, char *digest, char *file, int volume, int issue, int dashstuff) { int fd,i, msgcnt, msgnum; int len, buflen; char *bp, *msgnam; char buffer[BUFSIZ]; msgcnt = 1; for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { if (is_selected (mp, msgnum)) { if (digest) { strncpy (buffer, msgnum == mp->lowsel ? delim3 : delim4, sizeof(buffer)); } else { /* Get buffer ready to go */ bp = buffer; buflen = sizeof(buffer); strncpy (bp, "\n-------", buflen); len = strlen (bp); bp += len; buflen -= len; if (msgnum == mp->lowsel) { snprintf (bp, buflen, " Forwarded Message%s", PLURALS(mp->numsel)); } else { snprintf (bp, buflen, " Message %d", msgcnt); } len = strlen (bp); bp += len; buflen -= len; strncpy (bp, "\n\n", buflen); } if (write (out, buffer, strlen (buffer)) < 0) { advise (drft, "write"); } if ((fd = open (msgnam = m_name (msgnum), O_RDONLY)) == NOTOK) { admonish (msgnam, "unable to read message"); continue; } /* * Copy the message. Add RFC934 quoting (dashstuffing) * unless given the -nodashstuffing flag. */ if (dashstuff >= 0) cpydgst (fd, out, msgnam, file); else cpydata (fd, out, msgnam, file); close (fd); msgcnt++; } } if (digest) { strncpy (buffer, delim4, sizeof(buffer)); } else { snprintf (buffer, sizeof(buffer), "\n------- End of Forwarded Message%s\n", PLURALS(mp->numsel)); } if (write (out, buffer, strlen (buffer)) < 0) { advise (drft, "write"); } if (digest) { snprintf (buffer, sizeof(buffer), "End of %s Digest [Volume %d Issue %d]\n", digest, volume, issue); i = strlen (buffer); for (bp = buffer + i; i > 1; i--) *bp++ = '*'; *bp++ = '\n'; *bp = 0; if (write (out, buffer, strlen (buffer)) < 0) { advise (drft, "write"); } } } /* * Create a mhn composition file for forwarding message. */ static void copy_mime_draft (int out) { int msgnum; char buffer[BUFSIZ]; snprintf (buffer, sizeof(buffer), "#forw [forwarded message%s] +%s", PLURALS(mp->numsel), mp->foldpath); if (write (out, buffer, strlen (buffer)) < 0) { advise (drft, "write"); } for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) if (is_selected (mp, msgnum)) { snprintf (buffer, sizeof(buffer), " %s", m_name (msgnum)); if (write (out, buffer, strlen (buffer)) < 0) { advise (drft, "write"); } } if (write (out, "\n", 1) < 0) { advise (drft, "write newline"); } } nmh-1.7.1-RC3/uip/forwsbr.c000644 007761 000024 00000011147 13243042053 015407 0ustar00kenhstaff000000 000000 /* forwsbr.c -- subroutine to build a draft from a component file * * 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 #include #include #include #include #include "../sbr/m_mktemp.h" /* * Take from replsbr.c - a buffer big enough to read in data header lines * in reasonable chunks but not enough to slurp in the whole message */ static char msgbuf[NMH_BUFSIZ]; #define COMPFREE(c) mh_xfree(c->c_text) /* * A list of components we treat as addresses */ static char *addrcomps[] = { "from", "sender", "reply-to", "to", "cc", "bcc", "resent-from", "resent-sender", "resent-reply-to", "resent-to", "resent-cc", "resent-bcc", NULL }; int build_form (char *form, char *digest, int *dat, char *from, char *to, char *cc, char *fcc, char *subject, char *inputfile) { int in; int fmtsize, state; int i; char *nfs; char tmpfil[BUFSIZ], name[NAMESZ], **ap; charstring_t line; FILE *tmp; struct comp *cptr; struct format *fmt; char *cp = NULL; m_getfld_state_t gstate = 0; /* * Open the message we'll be scanning for components */ if ((tmp = fopen(inputfile, "r")) == NULL) adios (inputfile, "Unable to open"); /* Get new format string */ nfs = new_fs (form, NULL, NULL); fmtsize = strlen (nfs) + 256; /* Compile format string */ (void) fmt_compile (nfs, &fmt, 1); /* * Mark any components tagged as address components */ for (ap = addrcomps; *ap; ap++) { cptr = fmt_findcomp (*ap); if (cptr) cptr->c_type |= CT_ADDR; } /* * Process our message and save all relevant components * * A lot of this is taken from replsbr.c; should we try to merge * these routines? */ for (;;) { int msg_count = sizeof msgbuf; state = m_getfld (&gstate, name, msgbuf, &msg_count, tmp); switch (state) { case FLD: case FLDPLUS: /* * If we find a component that we're interested in, save * a copy. We don't do all of that weird buffer switching * that replout does. */ i = fmt_addcomptext(name, msgbuf); if (i != -1) { while (state == FLDPLUS) { msg_count = sizeof msgbuf; state = m_getfld (&gstate, name, msgbuf, &msg_count, tmp); fmt_appendcomp(i, name, msgbuf); } } while (state == FLDPLUS) { msg_count = sizeof msgbuf; state = m_getfld (&gstate, name, msgbuf, &msg_count, tmp); } break; case LENERR: case FMTERR: case BODY: case FILEEOF: goto finished; default: adios(NULL, "m_getfld() returned %d", state); } } /* * Override any components just in case they were included in the * input message. Also include command-line components given here * * With the memory rework I've changed things so we always get copies * of these strings; I don't like the idea that the caller of this * function has to know to pass in already-allocated memory (and that * it will be free()'d by us). */ finished: m_getfld_state_destroy (&gstate); cptr = fmt_findcomp ("digest"); if (cptr) { COMPFREE(cptr); cptr->c_text = getcpy(digest); } cptr = fmt_findcomp ("nmh-date"); if (cptr) { COMPFREE(cptr); cptr->c_text = getcpy(dtimenow (0)); } cptr = fmt_findcomp ("nmh-from"); if (cptr) { COMPFREE(cptr); cptr->c_text = getcpy(from); } cptr = fmt_findcomp ("nmh-to"); if (cptr) { COMPFREE(cptr); cptr->c_text = getcpy(to); } cptr = fmt_findcomp ("nmh-cc"); if (cptr) { COMPFREE(cptr); cptr->c_text = getcpy(cc); } cptr = fmt_findcomp ("nmh-subject"); if (cptr) { COMPFREE(cptr); cptr->c_text = getcpy(subject); } cptr = fmt_findcomp ("fcc"); if (cptr) { COMPFREE(cptr); cptr->c_text = getcpy(fcc); } cp = m_mktemp2(NULL, invo_name, NULL, &tmp); if (cp == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } strncpy (tmpfil, cp, sizeof(tmpfil)); (void) m_unlink (tmpfil); if ((in = dup (fileno (tmp))) == NOTOK) adios ("dup", "unable to"); line = charstring_create (fmtsize); fmt_scan (fmt, line, fmtsize, dat, NULL); fputs (charstring_buffer (line), tmp); charstring_free (line); if (fclose (tmp)) adios (tmpfil, "error writing"); lseek(in, 0, SEEK_SET); /* * Free any component buffers that we allocated */ fmt_free(fmt, 1); return in; } nmh-1.7.1-RC3/uip/inc.c000644 007761 000024 00000056303 13243042053 014477 0ustar00kenhstaff000000 000000 /* inc.c -- incorporate messages from a maildrop into a folder * * 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. */ #ifdef MAILGROUP /* * Thu Feb 12 21:00 CST 2015 Marcin Cieslak * Replaced setgid() calls with setegid() so that it works with dot * locking on FreeBSD. setegid() should be supported on modern POSIX * systems. * * Revised: Sat Apr 14 17:08:17 PDT 1990 (marvit@hplabs) * Added hpux hacks to set and reset gid to be "mail" as needed. The reset * is necessary so inc'ed mail is the group of the inc'er, rather than * "mail". We setgid to egid only when [un]locking the mail file. This * is also a major security precaution which will not be explained here. * * Fri Feb 7 16:04:57 PST 1992 John Romine * NB: I'm not 100% sure that this setgid stuff is secure even now. * * See the *GROUPPRIVS() macros later. I'm reasonably happy with the setgid * attribute. Running setuid root is probably not a terribly good idea, though. * -- Peter Maydell , 04/1998 * * Peter Maydell's patch slightly modified for nmh 0.28-pre2. * Ruud de Rooij Wed, 22 Jul 1998 13:24:22 +0200 */ #endif #include #include #include #include #include #include #include #include #include #include #include "../sbr/lock_file.h" #include "../sbr/m_maildir.h" #include "../sbr/m_mktemp.h" #ifndef TLS_SUPPORT # define TLSminc(a) (a) #else # define TLSminc(a) 0 #endif #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("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", 0, SNOOPSW) \ X("sasl", 0, SASLSW) \ X("nosasl", 0, NOSASLSW) \ X("saslmech", 0, SASLMECHSW) \ X("initialtls", TLSminc(-10), INITTLSSW) \ X("notls", TLSminc(-5), NOTLSSW) \ X("certverify", TLSminc(-10), CERTVERSW) \ X("nocertverify", TLSminc(-12), NOCERTVERSW) \ X("authservice", 0, AUTHSERVICESW) \ 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 */ #define INC_FILE 0 #define INC_POP 1 static int inc_type; static struct Maildir_entry { char *filename; time_t mtime; } *Maildir = NULL; static int num_maildir_entries = 0; static int snoop = 0; extern char response[]; static long start; static long stop; static FILE *pf = NULL; /* This is an attempt to simplify things by putting all the * privilege ops into macros. * *GROUPPRIVS() is related to handling the setgid MAIL property, * and only applies if MAILGROUP is defined. * Basically, SAVEGROUPPRIVS() is called right at the top of main() * to initialise things, and then DROPGROUPPRIVS() and GETGROUPPRIVS() * do the obvious thing. * * There's probably a better implementation if we're allowed to use * BSD-style setreuid() rather than using POSIX saved-ids. * Anyway, if you're euid root it's a bit pointless to drop the group * permissions... * * I'm pretty happy that the security is good provided we aren't setuid root. * The only things we trust with group=mail privilege are lkfopen() * and lkfclose(). */ /* * For setting and returning to "mail" gid */ #ifdef MAILGROUP static gid_t return_gid; #define TRYDROPGROUPPRIVS() DROPGROUPPRIVS() #define DROPGROUPPRIVS() \ if (setegid(getgid()) != 0) { \ adios ("setegid", "unable to restore group to %ld", (long) getgid()); \ } #define GETGROUPPRIVS() \ if (setegid(return_gid) != 0) { \ adios ("setegid", "unable to set group to %ld", (long) return_gid); \ } #define SAVEGROUPPRIVS() return_gid = getegid() #else /* define *GROUPPRIVS() as null; this avoids having lots of "#ifdef MAILGROUP"s */ #define TRYDROPGROUPPRIVS() #define DROPGROUPPRIVS() #define GETGROUPPRIVS() #define SAVEGROUPPRIVS() #endif /* not MAILGROUP */ /* these variables have to be globals so that done() can correctly clean up the lockfile */ static int locked = 0; static char *newmail; static FILE *in; /* * prototypes */ static void inc_done(int) NORETURN; static int pop_action(char *); int maildir_srt(const void *va, const void *vb) { const struct Maildir_entry *a = va, *b = vb; if (a->mtime > b->mtime) return 1; if (a->mtime < b->mtime) return -1; return 0; } int main (int argc, char **argv) { bool chgflag; int trnflag = 1; bool noisy; int width = -1; int hghnum = 0, msgnum = 0; bool sasl, tls, noverify; int incerr = 0; /* <0 if inc hits an error which means it should not truncate mailspool */ char *cp, *maildir = NULL, *folder = NULL; char *format = NULL, *form = NULL; char *host = NULL, *port = NULL, *user = NULL, *proxy = NULL; char *audfile = NULL, *from = NULL, *saslmech = NULL, *auth_svc = NULL; char buf[BUFSIZ], **argp, *nfs, **arguments; struct msgs *mp = NULL; struct stat st, s1; FILE *aud = NULL; char b[PATH_MAX + 1]; char *maildir_copy = NULL; /* copy of mail directory because the static gets overwritten */ charstring_t scanl = NULL; int nmsgs, nbytes; char *MAILHOST_env_variable; done=inc_done; /* absolutely the first thing we do is save our privileges, * and drop them if we can. */ SAVEGROUPPRIVS(); TRYDROPGROUPPRIVS(); if (nmh_init(argv[0], 1)) { return 1; } mts_init (); arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; /* * Scheme is: * use MAILHOST environment variable if present, * else try Hesiod. * If that fails, use the default (if any) * provided by mts.conf in mts_init() */ if ((MAILHOST_env_variable = getenv("MAILHOST")) != NULL) pophost = MAILHOST_env_variable; /* * If there is a valid "pophost" entry in mts.conf, * then use it as the default host. */ if (pophost && *pophost) host = pophost; sasl = tls = false; chgflag = noisy = noverify = true; while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [+folder] [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case AUDSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); audfile = getcpy (m_maildir (cp)); continue; case NAUDSW: audfile = NULL; continue; case CHGSW: chgflag = true; continue; case NCHGSW: chgflag = false; continue; /* * The flag `trnflag' has the value: * * 2 if -truncate is given * 1 by default (truncating is default) * 0 if -notruncate is given */ case TRNCSW: trnflag = 2; continue; case NTRNCSW: trnflag = 0; continue; case FILESW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); from = path (cp, TFILE); /* * If the truncate file is in default state, * change to not truncate. */ if (trnflag == 1) trnflag = 0; continue; case SILSW: noisy = false; continue; case NSILSW: noisy = true; continue; case FORMSW: if (!(form = *argp++) || *form == '-') adios (NULL, "missing argument to %s", argp[-2]); format = NULL; continue; case FMTSW: if (!(format = *argp++) || *format == '-') adios (NULL, "missing argument to %s", argp[-2]); form = NULL; continue; case WIDTHSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); width = atoi (cp); continue; case HOSTSW: if (!(host = *argp++) || *host == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case PORTSW: if (!(port = *argp++) || *port == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case USERSW: if (!(user = *argp++) || *user == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case SNOOPSW: snoop++; continue; case SASLSW: sasl = true; continue; case NOSASLSW: sasl = false; continue; case SASLMECHSW: if (!(saslmech = *argp++) || *saslmech == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case INITTLSSW: tls = true; continue; case NOTLSSW: tls = false; continue; case CERTVERSW: noverify = false; continue; case NOCERTVERSW: noverify = true; continue; case AUTHSERVICESW: #ifdef OAUTH_SUPPORT if (!(auth_svc = *argp++) || *auth_svc == '-') adios (NULL, "missing argument to %s", argp[-2]); #else adios (NULL, "not built with OAuth support"); #endif continue; case PROXYSW: if (!(proxy = *argp++) || *proxy == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; } } if (*cp == '+' || *cp == '@') { if (folder) adios (NULL, "only one folder at a time!"); else folder = pluspath (cp); } else { adios (NULL, "usage: %s [+folder] [switches]", invo_name); } } /* NOTE: above this point you should use TRYDROPGROUPPRIVS(), * not DROPGROUPPRIVS(). */ if (host && !*host) host = NULL; /* guarantee dropping group privileges; we might not have done so earlier */ DROPGROUPPRIVS(); /* * Where are we getting the new mail? */ if (from) inc_type = INC_FILE; else if (host) inc_type = INC_POP; else inc_type = INC_FILE; /* * Are we getting the mail from * a POP server? */ if (inc_type == INC_POP) { int tlsflag = 0; if (auth_svc == NULL) { if (saslmech && ! strcasecmp(saslmech, "xoauth2")) { adios (NULL, "must specify -authservice with -saslmech xoauth2"); } } else { if (user == NULL) { adios (NULL, "must specify -user with -saslmech xoauth2"); } } if (tls) tlsflag |= P_INITTLS; if (noverify) tlsflag |= P_NOVERIFY; /* * initialize POP connection */ if (pop_init (host, port, user, proxy, snoop, sasl, saslmech, tlsflag, auth_svc) == NOTOK) adios (NULL, "%s", response); /* Check if there are any messages */ if (pop_stat (&nmsgs, &nbytes) == NOTOK) adios (NULL, "%s", response); if (nmsgs == 0) { pop_quit(); adios (NULL, "no mail to incorporate"); } } /* * We will get the mail from a file * (typically the standard maildrop) */ if (inc_type == INC_FILE) { if (from) newmail = from; else if ((newmail = getenv ("MAILDROP")) && *newmail) newmail = m_mailpath (newmail); else if ((newmail = context_find ("maildrop")) && *newmail) newmail = m_mailpath (newmail); else { newmail = concat (MAILDIR, "/", MAILFIL, NULL); } if (stat (newmail, &s1) == NOTOK || s1.st_size == 0) adios (NULL, "no mail to incorporate"); if (s1.st_mode & S_IFDIR) { DIR *md; struct dirent *de; struct stat ms; int i; i = 0; cp = concat (newmail, "/new", NULL); if ((md = opendir(cp)) == NULL) adios (NULL, "unable to open %s", cp); while ((de = readdir (md)) != NULL) { if (de->d_name[0] == '.') continue; if (i >= num_maildir_entries) { if ((Maildir = realloc(Maildir, sizeof(*Maildir) * (2*i+16))) == NULL) adios(NULL, "not enough memory for %d messages", 2*i+16); num_maildir_entries = 2*i+16; } Maildir[i].filename = concat (cp, "/", de->d_name, NULL); if (stat(Maildir[i].filename, &ms) != 0) adios (Maildir[i].filename, "couldn't get delivery time"); Maildir[i].mtime = ms.st_mtime; i++; } free (cp); closedir (md); cp = concat (newmail, "/cur", NULL); if ((md = opendir(cp)) == NULL) adios (NULL, "unable to open %s", cp); while ((de = readdir (md)) != NULL) { if (de->d_name[0] == '.') continue; if (i >= num_maildir_entries) { if ((Maildir = realloc(Maildir, sizeof(*Maildir) * (2*i+16))) == NULL) adios(NULL, "not enough memory for %d messages", 2*i+16); num_maildir_entries = 2*i+16; } Maildir[i].filename = concat (cp, "/", de->d_name, NULL); if (stat(Maildir[i].filename, &ms) != 0) adios (Maildir[i].filename, "couldn't get delivery time"); Maildir[i].mtime = ms.st_mtime; i++; } free (cp); closedir (md); if (i == 0) adios (NULL, "no mail to incorporate"); num_maildir_entries = i; qsort (Maildir, num_maildir_entries, sizeof(*Maildir), maildir_srt); } cp = mh_xstrdup(newmail); newmail = cp; } if (!context_find ("path")) free (path ("./", TFOLDER)); if (!folder) folder = getfolder (0); maildir = m_maildir (folder); maildir_copy = mh_xstrdup(maildir); if (!folder_exists(maildir)) { /* If the folder doesn't exist, and we're given the -silent flag, * just fail. */ if (noisy) create_folder(maildir, 0, done); else done (1); } if (chdir (maildir) == NOTOK) adios (maildir, "unable to change directory to"); /* read folder and create message structure */ if (!(mp = folder_read (folder, 0))) adios (NULL, "unable to read folder %s", folder); if (inc_type == INC_FILE && Maildir == NULL) { if (access (newmail, W_OK) != NOTOK) { locked++; if (trnflag) { SIGNAL (SIGHUP, SIG_IGN); SIGNAL (SIGINT, SIG_IGN); SIGNAL (SIGQUIT, SIG_IGN); SIGNAL (SIGTERM, SIG_IGN); } GETGROUPPRIVS(); /* Reset gid to lock mail file */ in = lkfopenspool (newmail, "r"); DROPGROUPPRIVS(); if (in == NULL) adios (NULL, "unable to lock and fopen %s", newmail); fstat (fileno(in), &s1); } else { trnflag = 0; if ((in = fopen (newmail, "r")) == NULL) adios (newmail, "unable to read"); } } /* This shouldn't be necessary but it can't hurt. */ DROPGROUPPRIVS(); if (audfile) { int i; if ((i = stat (audfile, &st)) == NOTOK) inform("Creating Receive-Audit: %s", audfile); if ((aud = fopen (audfile, "a")) == NULL) adios (audfile, "unable to append to"); else if (i == NOTOK) chmod (audfile, m_gmprot ()); if (from) fprintf (aud, "<> %s -ms %s\n", dtimenow(0), from); else { if (host) fprintf (aud, "<> %s -host %s -user %s\n", dtimenow(0), host, user); else fprintf (aud, "<> %s\n", dtimenow (0)); } } /* Get new format string */ nfs = new_fs (form, format, FORMAT); if (noisy) { printf ("Incorporating new mail into %s...\n\n", folder); fflush (stdout); } /* * Get the mail from a POP server */ if (inc_type == INC_POP) { int i; hghnum = msgnum = mp->hghmsg; for (i = 1; i <= nmsgs; i++) { msgnum++; cp = mh_xstrdup(m_name (msgnum)); if ((pf = fopen (cp, "w+")) == NULL) adios (cp, "unable to write"); chmod (cp, m_gmprot ()); start = stop = 0L; if (pop_retr (i, pop_action) == NOTOK) adios (NULL, "%s", response); if (fflush (pf)) adios (cp, "write error on"); fseek (pf, 0L, SEEK_SET); switch (incerr = scan (pf, msgnum, 0, nfs, width, msgnum == mp->hghmsg + 1 && chgflag, 1, NULL, stop - start, noisy, &scanl)) { case SCNEOF: printf ("%*d empty\n", DMAXFOLDER, msgnum); break; case SCNFAT: trnflag = 0; noisy = true; /* advise (cp, "unable to read"); already advised */ break; case SCNERR: case SCNNUM: break; case SCNMSG: case SCNENC: default: if (aud) fputs (charstring_buffer (scanl), aud); if (noisy) fflush (stdout); break; } if (scanl) charstring_clear (scanl); if (ferror(pf) || fclose (pf)) { int e = errno; (void) m_unlink (cp); pop_quit (); errno = e; adios (cp, "write error on"); } free (cp); if (trnflag && pop_dele (i) == NOTOK) adios (NULL, "%s", response); scan_finished(); } charstring_free (scanl); scanl = NULL; if (pop_quit () == NOTOK) adios (NULL, "%s", response); } /* * Get the mail from file (usually mail spool) */ if (inc_type == INC_FILE && Maildir == NULL) { scan_detect_mbox_style (in); /* the MAGIC invocation... */ hghnum = msgnum = mp->hghmsg; for (;;) { /* create scanline for new message */ switch (incerr = scan (in, msgnum + 1, msgnum + 1, nfs, width, msgnum == hghnum && chgflag, 1, NULL, 0L, noisy, &scanl)) { case SCNFAT: case SCNEOF: break; case SCNERR: if (aud) fputs ("inc aborted!\n", aud); inform("aborted!"); /* doesn't clean up locks! */ break; case SCNNUM: inform("BUG in %s, number out of range", invo_name); break; default: inform("BUG in %s, scan() botch (%d)", invo_name, incerr); break; case SCNMSG: case SCNENC: /* * Run the external program hook on the message. */ (void)snprintf(b, sizeof (b), "%s/%d", maildir_copy, msgnum + 1); (void)ext_hook("add-hook", b, NULL); if (aud) fputs (charstring_buffer (scanl), aud); if (noisy) fflush (stdout); charstring_clear (scanl); msgnum++; continue; } /* If we get here there was some sort of error from scan(), * so stop processing anything more from the spool. */ break; } charstring_free (scanl); scanl = NULL; } else if (inc_type == INC_FILE) { /* Maildir inbox to process */ char *sp; FILE *sf; int i; hghnum = msgnum = mp->hghmsg; for (i = 0; i < num_maildir_entries; i++) { msgnum++; sp = Maildir[i].filename; cp = mh_xstrdup(m_name (msgnum)); pf = NULL; if (!trnflag || link(sp, cp) == -1) { static char buf[65536]; size_t nrd; if ((sf = fopen (sp, "r")) == NULL) adios (sp, "unable to read for copy"); if ((pf = fopen (cp, "w+")) == NULL) adios (cp, "unable to write for copy"); while ((nrd = fread(buf, 1, sizeof(buf), sf)) > 0) if (fwrite(buf, 1, nrd, pf) != nrd) break; if (ferror(sf) || fflush(pf) || ferror(pf)) { int e = errno; fclose(pf); fclose(sf); (void) m_unlink(cp); errno = e; adios(cp, "copy error %s -> %s", sp, cp); } fclose (sf); sf = NULL; } if (pf == NULL && (pf = fopen (cp, "r")) == NULL) adios (cp, "not available"); chmod (cp, m_gmprot ()); fseek (pf, 0L, SEEK_SET); switch (incerr = scan (pf, msgnum, 0, nfs, width, msgnum == mp->hghmsg + 1 && chgflag, 1, NULL, stop - start, noisy, &scanl)) { case SCNEOF: printf ("%*d empty\n", DMAXFOLDER, msgnum); break; case SCNFAT: trnflag = 0; noisy = true; /* advise (cp, "unable to read"); already advised */ break; case SCNERR: case SCNNUM: break; case SCNMSG: case SCNENC: default: /* * Run the external program hook on the message. */ (void)snprintf(b, sizeof (b), "%s/%d", maildir_copy, msgnum + 1); (void)ext_hook("add-hook", b, NULL); if (aud) fputs (charstring_buffer (scanl), aud); if (noisy) fflush (stdout); break; } charstring_clear (scanl); if (ferror(pf) || fclose (pf)) { int e = errno; (void) m_unlink (cp); errno = e; adios (cp, "write error on"); } pf = NULL; free (cp); if (trnflag && m_unlink (sp) == NOTOK) adios (sp, "couldn't unlink"); free (sp); /* Free Maildir[i]->filename */ scan_finished(); } free (Maildir); /* From now on Maildir is just a flag - don't dref! */ charstring_free (scanl); scanl = NULL; } scan_finished (); if (incerr < 0) { /* error */ if (locked) { GETGROUPPRIVS(); /* Be sure we can unlock mail file */ (void) lkfclosespool (in, newmail); in = NULL; DROPGROUPPRIVS(); /* And then return us to normal privileges */ } else { fclose (in); in = NULL; } adios (NULL, "failed"); } if (aud) fclose (aud); if (noisy) fflush (stdout); /* * truncate file we are incorporating from */ if (inc_type == INC_FILE && Maildir == NULL) { if (trnflag) { if (stat (newmail, &st) != NOTOK && s1.st_mtime != st.st_mtime) inform("new messages have arrived!\007"); else { int newfd; if ((newfd = creat (newmail, 0600)) != NOTOK) close (newfd); else admonish (newmail, "error zero'ing"); } } else { if (noisy) printf ("%s not zero'd\n", newmail); } } if (msgnum == hghnum) { inform("no messages incorporated, continuing..."); } else { /* * Lock the sequence file now, and loop to set the right flags * in the folder structure */ struct msgs *mp2; int i; context_replace (pfolder, folder); /* update current folder */ if ((mp2 = folder_read(folder, 1)) == NULL) { inform("Unable to reread folder %s, continuing...", folder); goto skip; } /* * Shouldn't happen, but just in case ... */ if (msgnum >= mp2->hghoff && !(mp2 = folder_realloc (mp2, mp2->lowoff, msgnum + 1))) { inform("unable to reallocate folder storage"); goto skip; } if (chgflag) mp2->curmsg = hghnum + 1; mp2->hghmsg = msgnum; if (mp2->lowmsg == 0) mp2->lowmsg = 1; if (chgflag) /* sigh... */ seq_setcur (mp2, mp2->curmsg); for (i = hghnum + 1; i <= msgnum; i++) { clear_msg_flags (mp2, i); set_exists (mp2, i); set_unseen (mp2, i); } mp2->msgflags |= SEQMOD; seq_setunseen(mp2, 0); /* Set the Unseen-Sequence */ seq_save(mp2); /* Save the sequence file */ folder_free(mp2); } skip: /* * unlock the mail spool */ if (inc_type == INC_FILE && Maildir == NULL) { if (locked) { GETGROUPPRIVS(); /* Be sure we can unlock mail file */ (void) lkfclosespool (in, newmail); in = NULL; DROPGROUPPRIVS(); /* And then return us to normal privileges */ } else { fclose (in); in = NULL; } } context_save (); /* save the context file */ done (0); return 1; } static void NORETURN inc_done (int status) { done = exit; if (locked) { GETGROUPPRIVS(); lkfclosespool(in, newmail); DROPGROUPPRIVS(); } exit (status); } static int pop_action (char *s) { fprintf (pf, "%s\n", s); stop += strlen (s) + 1; return 0; /* Is return value used? This was missing before 1999-07-15. */ } nmh-1.7.1-RC3/uip/install-mh.c000644 007761 000024 00000014227 13243042053 015775 0ustar00kenhstaff000000 000000 /* install-mh.c -- initialize the nmh environment of a new user * * 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 /* mh internals */ #include #include "../sbr/m_maildir.h" #include "../sbr/makedir.h" #include /* structure for getpwuid() results */ #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 int main (int argc, char **argv) { int autof = 0; char *cp, buf[BUFSIZ]; const char *pathname; char *dp, **arguments, **argp; struct node *np; struct passwd *pw; struct stat st; FILE *in, *out; int check; if (nmh_init(argv[0], 0 /* use context_foil() */ )) { return 1; } arguments = getarguments (invo_name, argc, argv, 0); argp = arguments; check = 0; while ((dp = *argp++)) { if (*dp == '-') { switch (smatch (++dp, switches)) { case AMBIGSW: ambigsw (dp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown\n", dp); case HELPSW: snprintf (buf, sizeof(buf), "%s [switches]", invo_name); print_help (buf, switches, 0); done (0); case VERSIONSW: print_version(invo_name); done (0); case AUTOSW: autof++; continue; case CHECKSW: check = 1; continue; } } else { adios (NULL, "%s is invalid argument", dp); } } /* * Find user's home directory. Try the HOME environment variable first, * the home directory field in the password file if that's not found. */ if ((mypath = getenv("HOME")) == NULL) { if ((pw = getpwuid(getuid())) == NULL || *pw->pw_dir == '\0') adios(NULL, "cannot determine your home directory"); else mypath = pw->pw_dir; } /* * Find the user's profile. Check for the existence of an MH environment * variable first with non-empty contents. Convert any relative path name * found there to an absolute one. Look for the profile in the user's home * directory if the MH environment variable isn't set. */ if ((cp = getenv("MH")) && *cp != '\0') defpath = path(cp, TFILE); else defpath = concat(mypath, "/", mh_profile, NULL); /* * Check for the existence of the profile file. It's an error if it exists and * this isn't an installation check. An installation check fails if it does not * exist, succeeds if it does. */ if (stat (defpath, &st) != NOTOK) { if (check) done(0); else if (autof) adios (NULL, "invocation error"); else adios (NULL, "You already have an nmh profile, use an editor to modify it"); } else if (check) { done(1); } if (!autof && read_switch ("Do you want help? ", anoyes)) { (void)printf( "\n" "Prior to using nmh, it is necessary to have a file in your login\n" "directory (%s) named %s which contains information\n" "to direct certain nmh operations. The only item which is required\n" "is the path to use for all nmh folder operations. The suggested nmh\n" "path for you is %s/Mail...\n" "\n", mypath, mh_profile, mypath); } cp = concat (mypath, "/", "Mail", NULL); if (stat (cp, &st) != NOTOK) { if (S_ISDIR(st.st_mode)) { cp = concat ("You already have the standard nmh directory \"", cp, "\".\nDo you want to use it for nmh? ", NULL); if (read_switch (cp, anoyes)) pathname = "Mail"; else goto query; } else { goto query; } } else { if (autof) puts("I'm going to create the standard nmh path for you."); else cp = concat ("Do you want the standard nmh path \"", mypath, "/", "Mail\"? ", NULL); if (autof || read_switch (cp, anoyes)) pathname = "Mail"; else { query: if (read_switch ("Do you want a path below your login directory? ", anoyes)) { printf ("What is the path? %s/", mypath); pathname = read_line (); if (pathname == NULL) done (1); } else { printf ("What is the whole path? /"); pathname = read_line (); if (pathname == NULL) done (1); pathname = concat ("/", pathname, NULL); } } } if (chdir (mypath) < 0) { advise (mypath, "chdir"); } if (chdir (pathname) == NOTOK) { cp = concat ("\"", pathname, "\" doesn't exist; Create it? ", NULL); if (autof || read_switch (cp, anoyes)) if (makedir (pathname) == 0) adios (NULL, "unable to create %s", pathname); } else { puts("[Using existing directory]"); } /* * Add some initial elements to the profile/context list */ NEW(np); m_defs = np; np->n_name = mh_xstrdup("Path"); np->n_field = mh_xstrdup(pathname); np->n_context = 0; np->n_next = NULL; /* * If there is a default profile file in the * nmh `etc' directory, then read it also. */ if ((in = fopen (mh_defaults, "r"))) { readconfig (&np->n_next, in, mh_defaults, 0); fclose (in); } ctxpath = getcpy (m_maildir (context = "context")); /* Initialize current folder to default */ context_replace (pfolder, defaultfolder); context_save (); /* * Now write out the initial .mh_profile */ if ((out = fopen (defpath, "w")) == NULL) adios (defpath, "unable to write"); /* * The main purpose of this first line is to fool file(1). * Without it, if the first line of the profile is Path:, * file 5.19 reports its type as message/news. With it, * it reports the type as text/plain. */ fprintf (out, "MH-Profile-Version: 1.0\n"); for (np = m_defs; np; np = np->n_next) { if (!np->n_context) fprintf (out, "%s: %s\n", np->n_name, np->n_field); } fclose (out); puts ("\nPlease see the nmh(7) man page for an introduction to nmh.\n"); print_intro (stdout, FALSE); /* Initialize the saved nmh version. The Path profile entry was added above, that's all this needs. */ (void) nmh_version_changed (0); done (0); return 1; } nmh-1.7.1-RC3/uip/mark.c000644 007761 000024 00000014743 13243042053 014662 0ustar00kenhstaff000000 000000 /* mark.c -- add message(s) to sequences in given folder * -- delete messages (s) from sequences in given folder * -- list sequences in given folder * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include "../sbr/m_maildir.h" #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 */ static void print_debug (struct msgs *); static void seq_printdebug (struct msgs *); int main (int argc, char **argv) { int addsw = 0, deletesw = 0, debugsw = 0; int listsw = 0, publicsw = -1, zerosw = 0, msgnum; unsigned int seqp = 0; char *cp, *maildir, *folder = NULL, buf[BUFSIZ]; char **argp, **arguments; svector_t seqs = svector_create (0); struct msgs_array msgs = { 0, 0, NULL }; struct msgs *mp; if (nmh_init(argv[0], 1)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; /* * Parse arguments */ while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown\n", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [+folder] [msgs] [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case ADDSW: addsw++; deletesw = listsw = 0; continue; case DELSW: deletesw++; addsw = listsw = 0; continue; case LSTSW: listsw++; addsw = deletesw = 0; continue; case SEQSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); svector_push_back (seqs, cp); seqp++; continue; case PUBLSW: publicsw = 1; continue; case NPUBLSW: publicsw = 0; continue; case DEBUGSW: debugsw++; continue; case ZEROSW: zerosw++; continue; case NZEROSW: zerosw = 0; continue; } } if (*cp == '+' || *cp == '@') { if (folder) adios (NULL, "only one folder at a time!"); else folder = pluspath (cp); } else app_msgarg(&msgs, cp); } /* * If we haven't specified -add, -delete, or -list, * then use -add if a sequence was specified, else * use -list. */ if (!addsw && !deletesw && !listsw) { if (seqp) addsw++; else listsw++; } if (!context_find ("path")) free (path ("./", TFOLDER)); if (!msgs.size) app_msgarg(&msgs, listsw ? "all" :"cur"); if (!folder) folder = getfolder (1); maildir = m_maildir (folder); if (chdir (maildir) == NOTOK) adios (maildir, "unable to change directory to"); /* read folder and create message structure */ if (!(mp = folder_read (folder, 1))) adios (NULL, "unable to read folder %s", folder); /* print some general debugging info */ if (debugsw) print_debug(mp); /* check for empty folder */ if (mp->nummsg == 0) adios (NULL, "no messages in %s", folder); /* parse all the message ranges/sequences and set SELECTED */ for (msgnum = 0; msgnum < msgs.size; msgnum++) if (!m_convert (mp, msgs.msgs[msgnum])) done (1); if (publicsw == 1 && is_readonly(mp)) adios (NULL, "folder %s is read-only, so -public not allowed", folder); /* * Make sure at least one sequence has been * specified if we are adding or deleting. */ if (seqp == 0 && (addsw || deletesw)) adios (NULL, "-%s requires at least one -sequence argument", addsw ? "add" : "delete"); /* Adding messages to sequences */ if (addsw) { for (seqp = 0; seqp < svector_size (seqs); seqp++) if (!seq_addsel (mp, svector_at (seqs, seqp), publicsw, zerosw)) done (1); } /* Deleting messages from sequences */ if (deletesw) { for (seqp = 0; seqp < svector_size (seqs); seqp++) if (!seq_delsel (mp, svector_at (seqs, seqp), publicsw, zerosw)) done (1); } /* Listing messages in sequences */ if (listsw) { if (seqp) { /* print the sequences given */ for (seqp = 0; seqp < svector_size (seqs); seqp++) seq_print (mp, svector_at (seqs, seqp)); } else { /* else print them all */ seq_printall (mp); } /* print debugging info about SELECTED messages */ if (debugsw) seq_printdebug (mp); } svector_free (seqs); seq_save (mp); /* synchronize message sequences */ context_replace (pfolder, folder); /* update current folder */ context_save (); /* save the context file */ folder_free (mp); /* free folder/message structure */ done (0); return 1; } /* * Print general debugging info */ static void print_debug (struct msgs *mp) { char buf[100]; printf ("invo_name = %s\n", invo_name); printf ("mypath = %s\n", mypath); printf ("defpath = %s\n", defpath); printf ("ctxpath = %s\n", ctxpath); printf ("context flags = %s\n", snprintb (buf, sizeof(buf), (unsigned) ctxflags, DBITS)); printf ("foldpath = %s\n", mp->foldpath); printf ("folder flags = %s\n\n", snprintb(buf, sizeof(buf), (unsigned) mp->msgflags, FBITS)); printf ("lowmsg=%d hghmsg=%d nummsg=%d curmsg=%d\n", mp->lowmsg, mp->hghmsg, mp->nummsg, mp->curmsg); printf ("lowsel=%d hghsel=%d numsel=%d\n", mp->lowsel, mp->hghsel, mp->numsel); printf ("lowoff=%d hghoff=%d\n\n", mp->lowoff, mp->hghoff); } /* * Print debugging info about all the SELECTED * messages and the sequences they are in. * Due to limitations of snprintb(), only a limited * number of sequences will be printed. See the * comments in sbr/seq_bits.c. */ static void seq_printdebug (struct msgs *mp) { int msgnum; char buf[BUFSIZ]; putchar('\n'); for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { if (is_selected (mp, msgnum)) printf ("%*d: %s\n", DMAXFOLDER, msgnum, snprintb (buf, sizeof buf, (unsigned) bvector_first_bits (msgstat (mp, msgnum)), seq_bits (mp))); } } nmh-1.7.1-RC3/uip/mhbuild.c000644 007761 000024 00000024215 13243042053 015347 0ustar00kenhstaff000000 000000 /* mhbuild.c -- expand/translate MIME composition files * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #include #include #include #include "../sbr/m_maildir.h" #include "../sbr/m_mktemp.h" #include "mhfree.h" #include "mhoutsbr.h" #define MHBUILD_SWITCHES \ X("auto", 0, AUTOSW) \ X("noauto", 0, NAUTOSW) \ 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("disposition", 0, DISPOSW) \ X("nodisposition", 0, NDISPOSW) \ X("rcache policy", 0, RCACHESW) \ X("wcache policy", 0, WCACHESW) \ X("contentid", 0, CONTENTIDSW) \ X("nocontentid", 0, NCONTENTIDSW) \ X("headerencoding encoding-algorithm", 0, HEADERENCSW) \ X("autoheaderencoding", 0, AUTOHEADERENCSW) \ X("maxunencoded", 0, MAXUNENCSW) \ X("version", 0, VERSIONSW) \ X("help", 0, HELPSW) \ X("debug", -5, DEBUGSW) \ X("dist", 0, DISTSW) \ #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 /* utf-8 is for Email Address Internationalization, using SMTPUTF8. */ #define MIMEENCODING_SWITCHES \ X("base64", 0, BASE64SW) \ X("quoted-printable", 0, QUOTEDPRINTSW) \ X("utf-8", 0, UTF8SW) \ #define X(sw, minchars, id) id, DEFINE_SWITCH_ENUM(MIMEENCODING); #undef X #define X(sw, minchars, id) { sw, minchars, id }, DEFINE_SWITCH_ARRAY(MIMEENCODING, encodingswitches); #undef X int debugsw = 0; int listsw = 0; int rfc934sw = 0; int contentidsw = 1; /* * Temporary files */ static char infile[BUFSIZ]; static int unlink_infile = 0; static char outfile[BUFSIZ]; static int unlink_outfile = 0; static void unlink_done (int) NORETURN; int main (int argc, char **argv) { int sizesw = 1, headsw = 1, directives = 1, autobuild = 0, dist = 0; int verbosw = 0, dispo = 0; size_t maxunencoded = MAXTEXTPERLN; int *icachesw; char *cp, buf[BUFSIZ]; char buffer[BUFSIZ], *compfile = NULL; char **argp, **arguments; CT ct, cts[2]; FILE *fp = NULL; FILE *fp_out = NULL; int header_encoding = CE_UNKNOWN; size_t n; if (nmh_init(argv[0], 2)) { return 1; } done=unlink_done; arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; while ((cp = *argp++)) { if (cp[0] == '-' && cp[1] == '\0') { if (compfile) adios (NULL, "cannot specify both standard input and a file"); else compfile = cp; listsw = 0; /* turn off -list if using standard in/out */ verbosw = 0; /* turn off -verbose listings */ break; } if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [switches] file", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case AUTOSW: /* -auto implies -nodirectives */ autobuild = 1; directives = 0; continue; case NAUTOSW: /* * We're turning directives back on since this is likely here * to override a profile entry */ autobuild = 0; directives = 1; continue; case RCACHESW: icachesw = &rcachesw; goto do_cache; case WCACHESW: icachesw = &wcachesw; do_cache: ; if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); switch (*icachesw = smatch (cp, cache_policy)) { case AMBIGSW: ambigsw (cp, cache_policy); done (1); case UNKWNSW: adios (NULL, "%s unknown", cp); default: break; } continue; case CHECKSW: checksw++; continue; case NCHECKSW: checksw = 0; continue; case HEADSW: headsw++; continue; case NHEADSW: headsw = 0; continue; case DIRECTIVES: directives = 1; continue; case NDIRECTIVES: directives = 0; continue; case LISTSW: listsw++; continue; case NLISTSW: listsw = 0; continue; case RFC934SW: rfc934sw++; continue; case NRFC934SW: rfc934sw = 0; continue; case SIZESW: sizesw++; continue; case NSIZESW: sizesw = 0; continue; case CONTENTIDSW: contentidsw = 1; continue; case NCONTENTIDSW: contentidsw = 0; continue; case HEADERENCSW: { int encoding; if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); switch (encoding = smatch (cp, encodingswitches)) { case AMBIGSW: ambigsw (cp, encodingswitches); done (1); case UNKWNSW: adios (NULL, "%s unknown encoding algorithm", cp); case BASE64SW: header_encoding = CE_BASE64; break; case QUOTEDPRINTSW: header_encoding = CE_QUOTED; break; case UTF8SW: header_encoding = CE_8BIT; break; default: adios (NULL, "Internal error: algorithm %s", cp); } continue; } case AUTOHEADERENCSW: header_encoding = CE_UNKNOWN; continue; case MAXUNENCSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if ((maxunencoded = atoi(cp)) < 1) adios (NULL, "Invalid argument for %s: %s", argp[-2], cp); if (maxunencoded > 998) adios (NULL, "limit of -maxunencoded is 998"); continue; case VERBSW: verbosw++; continue; case NVERBSW: verbosw = 0; continue; case DISPOSW: dispo = 1; continue; case NDISPOSW: dispo = 0; continue; case DEBUGSW: debugsw = 1; continue; case DISTSW: dist = 1; continue; } } if (compfile) adios (NULL, "only one composition file allowed"); else compfile = cp; } /* * Check if we've specified an additional profile */ if ((cp = getenv ("MHBUILD"))) { if ((fp = fopen (cp, "r"))) { readconfig ((struct node **) 0, fp, cp, 0); fclose (fp); } else { admonish ("", "unable to read $MHBUILD profile (%s)", cp); } } /* * Read the standard profile setup */ if ((fp = fopen (cp = etcpath ("mhn.defaults"), "r"))) { readconfig ((struct node **) 0, fp, cp, 0); fclose (fp); } /* Check for public cache location */ if ((cache_public = context_find (nmhcache)) && *cache_public != '/') cache_public = NULL; /* Check for private cache location */ if (!(cache_private = context_find (nmhprivcache))) cache_private = ".cache"; cache_private = getcpy (m_maildir (cache_private)); if (!context_find ("path")) free (path ("./", TFOLDER)); /* Check if we have a file to process */ if (!compfile) adios (NULL, "need to specify a %s composition file", invo_name); /* * Process the composition file from standard input. */ if (compfile[0] == '-' && compfile[1] == '\0') { if ((cp = m_mktemp2(NULL, invo_name, NULL, &fp)) == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } /* save a copy of the name for later removal */ strncpy (infile, cp, sizeof(infile)); unlink_infile = 1; /* copy standard input to temporary file */ while ((n = fread(buffer, 1, sizeof(buffer), stdin)) > 0) { if (fwrite(buffer, 1, n, fp) != n) { adios (NULL, "error copying to temporary file"); } } fclose (fp); /* build the content structures for MIME message */ ct = build_mime (infile, autobuild, dist, directives, header_encoding, maxunencoded, verbosw); /* * If ct == NULL, that means that -auto was set and a MIME version * header was already seen. Just use the input file as the output */ if (!ct) { if (! (fp = fopen(infile, "r"))) { adios(NULL, "Unable to open %s for reading", infile); } while ((n = fread(buffer, 1, sizeof(buffer), fp)) > 0) { if (fwrite(buffer, 1, n, stdout) != n) { adios(NULL, "error copying %s to stdout", infile); } } } else { /* output the message */ output_message_fp (ct, stdout, NULL); free_content (ct); } done (0); } /* * Process the composition file from a file. */ /* build the content structures for MIME message */ ct = build_mime (compfile, autobuild, dist, directives, header_encoding, maxunencoded, verbosw); /* * If ct == NULL, that means -auto was set and we found a MIME version * header. Simply exit and do nothing. */ if (! ct) done(0); cts[0] = ct; cts[1] = NULL; /* output MIME message to this temporary file */ if ((cp = m_mktemp2(compfile, invo_name, NULL, &fp_out)) == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } strncpy(outfile, cp, sizeof(outfile)); unlink_outfile = 1; /* output the message */ output_message_fp (ct, fp_out, outfile); fclose(fp_out); /* * List the message info */ if (listsw) list_all_messages (cts, headsw, sizesw, verbosw, debugsw, dispo); /* Rename composition draft */ snprintf (buffer, sizeof(buffer), "%s.orig", m_backup (compfile)); if (rename (compfile, buffer) == NOTOK) { adios (compfile, "unable to rename comp draft %s to", buffer); } /* Rename output file to take its place */ if (rename (outfile, compfile) == NOTOK) { advise (outfile, "unable to rename output %s to", compfile); rename (buffer, compfile); done (1); } unlink_outfile = 0; free_content (ct); done (0); return 1; } static void NORETURN unlink_done (int status) { /* * Check if we need to remove stray * temporary files. */ if (unlink_infile) (void) m_unlink (infile); if (unlink_outfile) (void) m_unlink (outfile); exit (status); } nmh-1.7.1-RC3/uip/mhbuildsbr.c000644 007761 000024 00000177027 13243042053 016070 0ustar00kenhstaff000000 000000 /* mhbuildsbr.c -- routines to expand/translate MIME composition files * * 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. */ /* * This code was originally part of mhn.c. I split it into * a separate program (mhbuild.c) and then later split it * again (mhbuildsbr.c). But the code still has some of * the mhn.c code in it. This program needs additional * streamlining and removal of unneeded code. */ #include #include #include #include #include #include #include #include #include #include "../sbr/m_mktemp.h" #include "../sbr/message_id.h" #include "../sbr/mime_type.h" #include "mhfree.h" #include "mhshowsbr.h" #ifdef HAVE_SYS_TIME_H # include #endif #include extern int debugsw; extern int listsw; extern int rfc934sw; extern int contentidsw; static char prefix[] = "----- =_aaaaaaaaaa"; struct attach_list { char *filename; struct attach_list *next; }; typedef struct convert_list { char *type; char *filename; char *argstring; struct convert_list *next; } convert_list; /* mhmisc.c */ void content_error (char *, CT, char *, ...); /* mhcachesbr.c */ int find_cache (CT, int, int *, char *, char *, int); /* * static prototypes */ static int init_decoded_content (CT, const char *); static void setup_attach_content(CT, char *); static void set_disposition (CT); static void set_charset (CT, int); static void expand_pseudoheaders (CT, struct multipart *, const char *, const convert_list *); static void expand_pseudoheader (CT, CT *, struct multipart *, const char *, const char *, const char *); static char *fgetstr (char *, int, FILE *); static int user_content (FILE *, char *, CT *, const char *infilename); static void set_id (CT, int); static int compose_content (CT, int); static int scan_content (CT, size_t); static int build_headers (CT, int); static char *calculate_digest (CT, int); static int extract_headers (CT, char *, FILE **); static unsigned char directives_stack[32]; static unsigned int directives_index; static int do_direct(void) { return directives_stack[directives_index]; } static void directive_onoff(int onoff) { if (directives_index >= sizeof(directives_stack) - 1) { fprintf(stderr, "mhbuild: #on/off overflow, continuing\n"); return; } directives_stack[++directives_index] = onoff; } static void directive_init(int onoff) { directives_index = 0; directives_stack[0] = onoff; } static void directive_pop(void) { if (directives_index > 0) directives_index--; else fprintf(stderr, "mhbuild: #pop underflow, continuing\n"); } /* * Main routine for translating composition file * into valid MIME message. It translates the draft * into a content structure (actually a tree of content * structures). This message then can be manipulated * in various ways, including being output via * output_message(). */ CT build_mime (char *infile, int autobuild, int dist, int directives, int header_encoding, size_t maxunencoded, int verbose) { int compnum, state; char buf[NMH_BUFSIZ], name[NAMESZ]; char *cp, *np, *vp; struct multipart *m; struct part **pp; CT ct; FILE *in; HF hp; m_getfld_state_t gstate = 0; struct attach_list *attach_head = NULL, *attach_tail = NULL, *at_entry; convert_list *convert_head = NULL, *convert_tail = NULL, *convert; directive_init(directives); umask (~m_gmprot ()); /* open the composition draft */ if ((in = fopen (infile, "r")) == NULL) adios (infile, "unable to open for reading"); /* * Allocate space for primary (outside) content */ NEW0(ct); /* * Allocate structure for handling decoded content * for this part. We don't really need this, but * allocate it to remain consistent. */ init_decoded_content (ct, infile); /* * Parse some of the header fields in the composition * draft into the linked list of header fields for * the new MIME message. */ 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: compnum++; /* abort if draft has Mime-Version or C-T-E header field */ if (strcasecmp (name, VRSN_FIELD) == 0 || strcasecmp (name, ENCODING_FIELD) == 0) { if (autobuild) { fclose(in); free (ct); return NULL; } adios (NULL, "draft shouldn't contain %s: field", name); } /* ignore any Content-Type fields in the header */ if (!strcasecmp (name, TYPE_FIELD)) { while (state == FLDPLUS) { bufsz = sizeof buf; state = m_getfld (&gstate, name, buf, &bufsz, in); } goto finish_field; } /* get copies of the buffers */ np = mh_xstrdup(name); vp = mh_xstrdup(buf); /* if necessary, get rest of field */ while (state == FLDPLUS) { 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, unless it's an attach * header; in that case, add it to our attach list */ if (strcasecmp(ATTACH_FIELD, np) == 0 || strcasecmp(ATTACH_FIELD_ALT, np) == 0) { struct attach_list *entry; char *s = vp, *e = vp + strlen(vp) - 1; free(np); /* * Make sure we can find the start of this filename. * If it's blank, we skip completely. Otherwise, strip * off any leading spaces and trailing newlines. */ while (isspace((unsigned char) *s)) s++; while (e > s && *e == '\n') *e-- = '\0'; if (*s == '\0') { free(vp); goto finish_field; } NEW(entry); entry->filename = mh_xstrdup(s); entry->next = NULL; free(vp); if (attach_tail) { attach_tail->next = entry; attach_tail = entry; } else { attach_head = attach_tail = entry; } } else if (strncasecmp(MHBUILD_FILE_PSEUDOHEADER, np, strlen (MHBUILD_FILE_PSEUDOHEADER)) == 0) { /* E.g., * Nmh-mhbuild-file-text/calendar: /home/user/Mail/inbox/9 */ char *type = np + strlen (MHBUILD_FILE_PSEUDOHEADER); char *filename = vp; /* vp should begin with a space because m_getfld() includes the space after the colon in buf. */ while (isspace((unsigned char) *filename)) { ++filename; } /* Trim trailing newline and any other whitespace. */ rtrim (filename); for (convert = convert_head; convert; convert = convert->next) { if (strcasecmp (convert->type, type) == 0) { break; } } if (convert) { if (convert->filename && strcasecmp (convert->filename, filename)) { adios (NULL, "Multiple %s headers with different files" " not allowed", type); } else { convert->filename = mh_xstrdup(filename); } } else { NEW0(convert); convert->filename = mh_xstrdup(filename); convert->type = mh_xstrdup(type); if (convert_tail) { convert_tail->next = convert; } else { convert_head = convert; } convert_tail = convert; } free (vp); free (np); } else if (strncasecmp(MHBUILD_ARGS_PSEUDOHEADER, np, strlen (MHBUILD_ARGS_PSEUDOHEADER)) == 0) { /* E.g., * Nmh-mhbuild-args-text/calendar: -reply accept */ char *type = np + strlen (MHBUILD_ARGS_PSEUDOHEADER); char *argstring = vp; /* vp should begin with a space because m_getfld() includes the space after the colon in buf. */ while (isspace((unsigned char) *argstring)) { ++argstring; } /* Trim trailing newline and any other whitespace. */ rtrim (argstring); for (convert = convert_head; convert; convert = convert->next) { if (strcasecmp (convert->type, type) == 0) { break; } } if (convert) { if (convert->argstring && strcasecmp (convert->argstring, argstring)) { adios (NULL, "Multiple %s headers with different " "argstrings not allowed", type); } else { convert->argstring = mh_xstrdup(argstring); } } else { NEW0(convert); convert->type = mh_xstrdup(type); convert->argstring = mh_xstrdup(argstring); if (convert_tail) { convert_tail->next = convert; } else { convert_head = convert; } convert_tail = convert; } free (vp); free (np); } else { add_header (ct, np, vp); } finish_field: /* if this wasn't the last header field, then continue */ continue; case BODY: fseek (in, (long) (-strlen (buf)), SEEK_CUR); break; case FILEEOF: break; case LENERR: case FMTERR: adios (NULL, "message format error in component #%d", compnum); default: adios (NULL, "getfld() returned %d", state); } break; } m_getfld_state_destroy (&gstate); if (header_encoding != CE_8BIT) { /* * Iterate through the list of headers and call the function to MIME-ify * them if required. */ for (hp = ct->c_first_hf; hp != NULL; hp = hp->next) { if (encode_rfc2047(hp->name, &hp->value, header_encoding, NULL)) { adios(NULL, "Unable to encode header \"%s\"", hp->name); } } } /* * Now add the MIME-Version header field * to the list of header fields. */ if (! dist) { np = mh_xstrdup(VRSN_FIELD); vp = concat (" ", VRSN_VALUE, "\n", NULL); add_header (ct, np, vp); } /* * We initially assume we will find multiple contents in the * draft. So create a multipart/mixed content to hold everything. * We can remove this later, if it is not needed. */ if (get_ctinfo ("multipart/mixed", ct, 0) == NOTOK) done (1); ct->c_type = CT_MULTIPART; ct->c_subtype = MULTI_MIXED; NEW0(m); ct->c_ctparams = (void *) m; pp = &m->mp_parts; /* * read and parse the composition file * and the directives it contains. */ while (fgetstr (buf, sizeof(buf) - 1, in)) { struct part *part; CT p; if (user_content (in, buf, &p, infile) == DONE) { inform("ignoring spurious #end, continuing..."); continue; } if (!p) continue; NEW0(part); *pp = part; pp = &part->mp_next; part->mp_part = p; } /* * Add any Attach headers to the list of MIME parts at the end of the * message. */ for (at_entry = attach_head; at_entry; ) { struct attach_list *at_prev = at_entry; struct part *part; CT p; if (access(at_entry->filename, R_OK) != 0) { adios("reading", "Unable to open %s for", at_entry->filename); } NEW0(p); init_decoded_content(p, infile); /* * Initialize our content structure based on the filename, * and fill in all of the relevant fields. Also place MIME * parameters in the attributes array. */ setup_attach_content(p, at_entry->filename); NEW0(part); *pp = part; pp = &part->mp_next; part->mp_part = p; at_entry = at_entry->next; free(at_prev->filename); free(at_prev); } /* * Handle the mhbuild pseudoheaders, which deal with specific * content types. */ if (convert_head) { CT *ctp; convert_list *next; done = freects_done; /* In case there are multiple calls that land here, prevent leak. */ for (ctp = cts; ctp && *ctp; ++ctp) { free_content (*ctp); } free (cts); /* Extract the type part (as a CT) from filename. */ cts = mh_xcalloc(2, sizeof *cts); if (! (cts[0] = parse_mime (convert_head->filename))) { adios (NULL, "failed to parse %s", convert_head->filename); } expand_pseudoheaders (cts[0], m, infile, convert_head); /* Free the convert list. */ for (convert = convert_head; convert; convert = next) { next = convert->next; free (convert->type); free (convert->filename); free (convert->argstring); free (convert); } convert_head = NULL; } /* * To allow for empty message bodies, if we've found NO content at all * yet cook up an empty text/plain part. */ if (!m->mp_parts) { CT p; struct part *part; struct text *t; NEW0(p); init_decoded_content(p, infile); if (get_ctinfo ("text/plain", p, 0) == NOTOK) done (1); p->c_type = CT_TEXT; p->c_subtype = TEXT_PLAIN; p->c_encoding = CE_7BIT; /* * Sigh. ce_file contains the "decoded" contents of this part. * So this seems like the best option available since we're going * to call scan_content() on this. */ p->c_cefile.ce_file = mh_xstrdup("/dev/null"); p->c_begin = ftell(in); p->c_end = ftell(in); NEW0(t); t->tx_charset = CHARSET_SPECIFIED; p->c_ctparams = t; NEW0(part); *pp = part; part->mp_part = p; } /* * close the composition draft since * it's not needed any longer. */ fclose (in); /* * If only one content was found, then remove and * free the outer multipart content. */ if (!m->mp_parts->mp_next) { CT p; p = m->mp_parts->mp_part; m->mp_parts->mp_part = NULL; /* move header fields */ p->c_first_hf = ct->c_first_hf; p->c_last_hf = ct->c_last_hf; ct->c_first_hf = NULL; ct->c_last_hf = NULL; free_content (ct); ct = p; } else { set_id (ct, 1); } /* * Fill out, or expand directives. Parse and execute * commands specified by profile composition strings. */ compose_content (ct, verbose); if ((cp = strchr(prefix, 'a')) == NULL) adios (NULL, "internal error(4)"); /* * If using EAI, force 8-bit charset. */ if (header_encoding == CE_8BIT) { set_charset (ct, 1); } /* * Scan the contents. Choose a transfer encoding, and * check if prefix for multipart boundary clashes with * any of the contents. */ while (scan_content (ct, maxunencoded) == NOTOK) { if (*cp < 'z') { (*cp)++; } else { if (*++cp == 0) adios (NULL, "giving up trying to find a unique delimiter string"); else (*cp)++; } } /* Build the rest of the header field structures */ if (! dist) build_headers (ct, header_encoding); return ct; } /* * Set up structures for placing unencoded * content when building parts. */ static int init_decoded_content (CT ct, const char *filename) { ct->c_ceopenfnx = open7Bit; /* since unencoded */ ct->c_ceclosefnx = close_encoding; ct->c_cesizefnx = NULL; /* since unencoded */ ct->c_encoding = CE_7BIT; /* Seems like a reasonable default */ ct->c_file = add(filename, NULL); return OK; } static char * fgetstr (char *s, int n, FILE *stream) { char *cp, *ep; ep = s + n; while(1) { for (cp = s; cp < ep;) { int len; if (!fgets (cp, n, stream)) return cp == s ? NULL : s; /* "\\\nEOF" ignored. */ if (! do_direct() || (cp == s && *cp != '#')) return s; /* Plaintext line. */ len = strlen(cp); if (len <= 1) break; /* Can't contain "\\\n". */ cp += len - 1; /* Just before NUL. */ if (*cp-- != '\n' || *cp != '\\') break; *cp = '\0'; /* Erase the trailing "\\\n". */ n -= (len - 2); } if (strcmp(s, "#on\n") == 0) { directive_onoff(1); } else if (strcmp(s, "#off\n") == 0) { directive_onoff(0); } else if (strcmp(s, "#pop\n") == 0) { directive_pop(); } else { return s; } } } /* * Parse the composition draft for text and directives. * Do initial setup of Content structure. */ static int user_content (FILE *in, char *buf, CT *ctp, const char *infilename) { int extrnal, vrsn; char *cp, **ap; char buffer[NMH_BUFSIZ]; struct multipart *m; struct part **pp; struct stat st; struct str2init *s2i; CI ci; CT ct; CE ce; if (buf[0] == '\n' || (do_direct() && strcmp (buf, "#\n") == 0)) { *ctp = NULL; return OK; } /* allocate basic Content structure */ NEW0(ct); *ctp = ct; /* allocate basic structure for handling decoded content */ init_decoded_content (ct, infilename); ce = &ct->c_cefile; ci = &ct->c_ctinfo; set_id (ct, 0); /* * Handle inline text. Check if line * is one of the following forms: * * 1) doesn't begin with '#' (implicit directive) * 2) begins with "##" (implicit directive) * 3) begins with "#<" */ if (!do_direct() || buf[0] != '#' || buf[1] == '#' || buf[1] == '<') { int headers; int inlineD; long pos; char content[BUFSIZ]; FILE *out; char *cp; if ((cp = m_mktemp2(NULL, invo_name, NULL, &out)) == NULL) { adios("mhbuildsbr", "unable to create temporary file in %s", get_temp_dir()); } /* use a temp file to collect the plain text lines */ ce->ce_file = mh_xstrdup(cp); ce->ce_unlink = 1; if (do_direct() && (buf[0] == '#' && buf[1] == '<')) { strncpy (content, buf + 2, sizeof(content)); inlineD = 1; goto rock_and_roll; } inlineD = 0; /* the directive is implicit */ strncpy (content, "text/plain", sizeof(content)); headers = 0; strncpy (buffer, (!do_direct() || buf[0] != '#') ? buf : buf + 1, sizeof(buffer)); for (;;) { int i; if (headers >= 0 && do_direct() && uprf (buffer, DESCR_FIELD) && buffer[i = strlen (DESCR_FIELD)] == ':') { headers = 1; again_descr: ct->c_descr = add (buffer + i + 1, ct->c_descr); if (!fgetstr (buffer, sizeof(buffer) - 1, in)) adios (NULL, "end-of-file after %s: field in plaintext", DESCR_FIELD); switch (buffer[0]) { case ' ': case '\t': i = -1; goto again_descr; case '#': adios (NULL, "#-directive after %s: field in plaintext", DESCR_FIELD); /* NOTREACHED */ default: break; } } if (headers >= 0 && do_direct() && uprf (buffer, DISPO_FIELD) && buffer[i = strlen (DISPO_FIELD)] == ':') { headers = 1; again_dispo: ct->c_dispo = add (buffer + i + 1, ct->c_dispo); if (!fgetstr (buffer, sizeof(buffer) - 1, in)) adios (NULL, "end-of-file after %s: field in plaintext", DISPO_FIELD); switch (buffer[0]) { case ' ': case '\t': i = -1; goto again_dispo; case '#': adios (NULL, "#-directive after %s: field in plaintext", DISPO_FIELD); /* NOTREACHED */ default: break; } } if (headers != 1 || buffer[0] != '\n') fputs (buffer, out); rock_and_roll: headers = -1; pos = ftell (in); if ((cp = fgetstr (buffer, sizeof(buffer) - 1, in)) == NULL) break; if (do_direct() && buffer[0] == '#') { char *bp; if (buffer[1] != '#') break; for (cp = (bp = buffer) + 1; *cp; cp++) *bp++ = *cp; *bp = '\0'; } } if (listsw) ct->c_end = ftell (out); fclose (out); /* parse content type */ if (get_ctinfo (content, ct, inlineD) == NOTOK) done (1); for (s2i = str2cts; s2i->si_key; s2i++) if (!strcasecmp (ci->ci_type, s2i->si_key)) break; if (!s2i->si_key && !uprf (ci->ci_type, "X-")) s2i++; /* * check type specified (possibly implicitly) */ switch (ct->c_type = s2i->si_val) { case CT_MESSAGE: if (!strcasecmp (ci->ci_subtype, "rfc822")) { ct->c_encoding = CE_7BIT; goto call_init; } /* FALLTHRU */ case CT_MULTIPART: adios (NULL, "it doesn't make sense to define an in-line %s content", ct->c_type == CT_MESSAGE ? "message" : "multipart"); /* NOTREACHED */ default: call_init: if ((ct->c_ctinitfnx = s2i->si_init)) (*ct->c_ctinitfnx) (ct); break; } if (cp) fseek (in, pos, SEEK_SET); return OK; } /* * If we've reached this point, the next line * must be some type of explicit directive. */ /* check if directive is external-type */ extrnal = (buf[1] == '@'); /* parse directive */ if (get_ctinfo (buf + (extrnal ? 2 : 1), ct, 1) == NOTOK) done (1); /* check directive against the list of MIME types */ for (s2i = str2cts; s2i->si_key; s2i++) if (!strcasecmp (ci->ci_type, s2i->si_key)) break; /* * Check if the directive specified a valid type. * This will happen if it was one of the following forms: * * #type/subtype (or) * #@type/subtype */ if (s2i->si_key) { if (!ci->ci_subtype) adios (NULL, "missing subtype in \"#%s\"", ci->ci_type); switch (ct->c_type = s2i->si_val) { case CT_MULTIPART: adios (NULL, "use \"#begin ... #end\" instead of \"#%s/%s\"", ci->ci_type, ci->ci_subtype); /* NOTREACHED */ case CT_MESSAGE: if (!strcasecmp (ci->ci_subtype, "partial")) adios (NULL, "sorry, \"#%s/%s\" isn't supported", ci->ci_type, ci->ci_subtype); if (!strcasecmp (ci->ci_subtype, "external-body")) adios (NULL, "use \"#@type/subtype ... [] ...\" instead of \"#%s/%s\"", ci->ci_type, ci->ci_subtype); use_forw: adios (NULL, "use \"#forw [+folder] [msgs]\" instead of \"#%s/%s\"", ci->ci_type, ci->ci_subtype); /* NOTREACHED */ default: if ((ct->c_ctinitfnx = s2i->si_init)) (*ct->c_ctinitfnx) (ct); break; } /* * #@type/subtype (external types directive) */ if (extrnal) { struct exbody *e; CT p; if (!ci->ci_magic) adios (NULL, "need external information for \"#@%s/%s\"", ci->ci_type, ci->ci_subtype); p = ct; snprintf (buffer, sizeof(buffer), "message/external-body; %s", ci->ci_magic); free (ci->ci_magic); ci->ci_magic = NULL; /* * Since we are using the current Content structure to * hold information about the type of the external * reference, we need to create another Content structure * for the message/external-body to wrap it in. */ NEW0(ct); init_decoded_content(ct, infilename); *ctp = ct; if (get_ctinfo (buffer, ct, 0) == NOTOK) done (1); ct->c_type = CT_MESSAGE; ct->c_subtype = MESSAGE_EXTERNAL; NEW0(e); ct->c_ctparams = (void *) e; e->eb_parent = ct; e->eb_content = p; p->c_ctexbody = e; if (params_external (ct, 1) == NOTOK) done (1); return OK; } /* Handle [file] argument */ if (ci->ci_magic) { /* check if specifies command to execute */ if (*ci->ci_magic == '|' || *ci->ci_magic == '!') { for (cp = ci->ci_magic + 1; isspace ((unsigned char) *cp); cp++) continue; if (!*cp) adios (NULL, "empty pipe command for #%s directive", ci->ci_type); cp = mh_xstrdup(cp); free (ci->ci_magic); ci->ci_magic = cp; } else { /* record filename of decoded contents */ ce->ce_file = ci->ci_magic; if (access (ce->ce_file, R_OK) == NOTOK) adios ("reading", "unable to access %s for", ce->ce_file); if (listsw && stat (ce->ce_file, &st) != NOTOK) ct->c_end = (long) st.st_size; ci->ci_magic = NULL; } return OK; } /* * No [file] argument, so check profile for * method to compose content. */ cp = context_find_by_type ("compose", ci->ci_type, ci->ci_subtype); if (cp == NULL) { content_error (NULL, ct, "don't know how to compose content"); done (1); } ci->ci_magic = mh_xstrdup(cp); return OK; } if (extrnal) adios (NULL, "external definition not allowed for \"#%s\"", ci->ci_type); /* * Message directive * #forw [+folder] [msgs] */ if (!strcasecmp (ci->ci_type, "forw")) { int msgnum; char *folder, *arguments[MAXARGS]; struct msgs *mp; if (ci->ci_magic) { ap = brkstring (ci->ci_magic, " ", "\n"); copyip (ap, arguments, MAXARGS); } else { arguments[0] = "cur"; arguments[1] = NULL; } folder = NULL; /* search the arguments for a folder name */ for (ap = arguments; *ap; ap++) { cp = *ap; if (*cp == '+' || *cp == '@') { if (folder) adios (NULL, "only one folder per #forw directive"); else folder = pluspath (cp); } } /* else, use the current folder */ if (!folder) folder = mh_xstrdup(getfolder(1)); if (!(mp = folder_read (folder, 0))) adios (NULL, "unable to read folder %s", folder); for (ap = arguments; *ap; ap++) { cp = *ap; if (*cp != '+' && *cp != '@') if (!m_convert (mp, cp)) done (1); } free (folder); free_ctinfo (ct); /* * If there is more than one message to include, make this * a content of type "multipart/digest" and insert each message * as a subpart. If there is only one message, then make this * a content of type "message/rfc822". */ if (mp->numsel > 1) { /* we are forwarding multiple messages */ if (get_ctinfo ("multipart/digest", ct, 0) == NOTOK) done (1); ct->c_type = CT_MULTIPART; ct->c_subtype = MULTI_DIGEST; NEW0(m); ct->c_ctparams = (void *) m; pp = &m->mp_parts; for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { if (is_selected(mp, msgnum)) { struct part *part; CT p; CE pe; NEW0(p); init_decoded_content (p, infilename); pe = &p->c_cefile; if (get_ctinfo ("message/rfc822", p, 0) == NOTOK) done (1); p->c_type = CT_MESSAGE; p->c_subtype = MESSAGE_RFC822; snprintf (buffer, sizeof(buffer), "%s/%d", mp->foldpath, msgnum); pe->ce_file = mh_xstrdup(buffer); if (listsw && stat (pe->ce_file, &st) != NOTOK) p->c_end = (long) st.st_size; NEW0(part); *pp = part; pp = &part->mp_next; part->mp_part = p; } } } else { /* we are forwarding one message */ if (get_ctinfo ("message/rfc822", ct, 0) == NOTOK) done (1); ct->c_type = CT_MESSAGE; ct->c_subtype = MESSAGE_RFC822; msgnum = mp->lowsel; snprintf (buffer, sizeof(buffer), "%s/%d", mp->foldpath, msgnum); ce->ce_file = mh_xstrdup(buffer); if (listsw && stat (ce->ce_file, &st) != NOTOK) ct->c_end = (long) st.st_size; } folder_free (mp); /* free folder/message structure */ return OK; } /* * #end */ if (!strcasecmp (ci->ci_type, "end")) { free_content (ct); *ctp = NULL; return DONE; } /* * #begin [ alternative | parallel ] */ if (!strcasecmp (ci->ci_type, "begin")) { if (!ci->ci_magic) { vrsn = MULTI_MIXED; cp = SubMultiPart[vrsn - 1].kv_key; } else if (!strcasecmp (ci->ci_magic, "alternative")) { vrsn = MULTI_ALTERNATE; cp = SubMultiPart[vrsn - 1].kv_key; } else if (!strcasecmp (ci->ci_magic, "parallel")) { vrsn = MULTI_PARALLEL; cp = SubMultiPart[vrsn - 1].kv_key; } else if (uprf (ci->ci_magic, "digest")) { goto use_forw; } else { vrsn = MULTI_UNKNOWN; cp = ci->ci_magic; } free_ctinfo (ct); snprintf (buffer, sizeof(buffer), "multipart/%s", cp); if (get_ctinfo (buffer, ct, 0) == NOTOK) done (1); ct->c_type = CT_MULTIPART; ct->c_subtype = vrsn; NEW0(m); ct->c_ctparams = (void *) m; pp = &m->mp_parts; while (fgetstr (buffer, sizeof(buffer) - 1, in)) { struct part *part; CT p; if (user_content (in, buffer, &p, infilename) == DONE) { if (!m->mp_parts) adios (NULL, "empty \"#begin ... #end\" sequence"); return OK; } if (!p) continue; NEW0(part); *pp = part; pp = &part->mp_next; part->mp_part = p; } inform("premature end-of-file, missing #end, continuing..."); return OK; } /* * Unknown directive */ adios (NULL, "unknown directive \"#%s\"", ci->ci_type); return NOTOK; /* NOT REACHED */ } static void set_id (CT ct, int top) { char contentid[BUFSIZ]; static int partno; static time_t clock = 0; static char *msgfmt; if (clock == 0) { time (&clock); snprintf (contentid, sizeof(contentid), "%s\n", message_id (clock, 1)); partno = 0; msgfmt = mh_xstrdup(contentid); } snprintf (contentid, sizeof(contentid), msgfmt, top ? 0 : ++partno); ct->c_id = mh_xstrdup(contentid); } /* * Fill out, or expand the various contents in the composition * draft. Read-in any necessary files. Parse and execute any * commands specified by profile composition strings. */ static int compose_content (CT ct, int verbose) { CE ce = &ct->c_cefile; switch (ct->c_type) { case CT_MULTIPART: { int partnum; char *pp; char partnam[BUFSIZ]; struct multipart *m = (struct multipart *) ct->c_ctparams; struct part *part; if (ct->c_partno) { snprintf (partnam, sizeof(partnam), "%s.", ct->c_partno); pp = partnam + strlen (partnam); } else { pp = partnam; } /* first, we call compose_content on all the subparts */ for (part = m->mp_parts, partnum = 1; part; part = part->mp_next, partnum++) { CT p = part->mp_part; sprintf (pp, "%d", partnum); p->c_partno = mh_xstrdup(partnam); if (compose_content (p, verbose) == NOTOK) return NOTOK; } /* * If the -rfc934mode switch is given, then check all * the subparts of a multipart/digest. If they are all * message/rfc822, then mark this content and all * subparts with the rfc934 compatibility mode flag. */ if (rfc934sw && ct->c_subtype == MULTI_DIGEST) { int is934 = 1; for (part = m->mp_parts; part; part = part->mp_next) { CT p = part->mp_part; if (p->c_subtype != MESSAGE_RFC822) { is934 = 0; break; } } ct->c_rfc934 = is934; for (part = m->mp_parts; part; part = part->mp_next) { CT p = part->mp_part; if ((p->c_rfc934 = is934)) p->c_end++; } } if (listsw) { ct->c_end = (partnum = strlen (prefix) + 2) + 2; if (ct->c_rfc934) ct->c_end++; for (part = m->mp_parts; part; part = part->mp_next) ct->c_end += part->mp_part->c_end + partnum; } } break; case CT_MESSAGE: /* Nothing to do for type message */ break; /* * Discrete types (text/application/audio/image/video) */ default: if (!ce->ce_file) { pid_t child_id; int i, xstdout, len, buflen; char *bp, *cp; char *vec[4], buffer[BUFSIZ]; FILE *out; CI ci = &ct->c_ctinfo; char *tfile = NULL; if (!(cp = ci->ci_magic)) adios (NULL, "internal error(5)"); if ((tfile = m_mktemp2(NULL, invo_name, NULL, NULL)) == NULL) { adios("mhbuildsbr", "unable to create temporary file in %s", get_temp_dir()); } ce->ce_file = mh_xstrdup(tfile); ce->ce_unlink = 1; xstdout = 0; /* Get buffer ready to go */ bp = buffer; bp[0] = '\0'; buflen = sizeof(buffer); /* * Parse composition string into buffer */ for ( ; *cp; cp++) { if (*cp == '%') { switch (*++cp) { case 'a': { /* insert parameters from directive */ char *s = ""; PM pm; for (pm = ci->ci_first_pm; pm; pm = pm->pm_next) { snprintf (bp, buflen, "%s%s=\"%s\"", s, pm->pm_name, get_param_value(pm, '?')); len = strlen (bp); bp += len; buflen -= len; s = " "; } } break; case 'F': /* %f, and stdout is not-redirected */ xstdout = 1; /* FALLTHRU */ case 'f': /* * insert temporary filename where * content should be written */ snprintf (bp, buflen, "%s", ce->ce_file); break; case 's': /* insert content subtype */ strncpy (bp, ci->ci_subtype, buflen); break; case '%': /* insert character % */ goto raw; default: *bp++ = *--cp; *bp = '\0'; buflen--; continue; } len = strlen (bp); bp += len; buflen -= len; } else { raw: *bp++ = *cp; *bp = '\0'; buflen--; } } if (verbose) printf ("composing content %s/%s from command\n\t%s\n", ci->ci_type, ci->ci_subtype, buffer); fflush (stdout); /* not sure if need for -noverbose */ vec[0] = "/bin/sh"; vec[1] = "-c"; vec[2] = buffer; vec[3] = NULL; if ((out = fopen (ce->ce_file, "w")) == NULL) adios (ce->ce_file, "unable to open for writing"); for (i = 0; (child_id = fork()) == NOTOK && i > 5; i++) sleep (5); switch (child_id) { case NOTOK: adios ("fork", "unable to fork"); /* NOTREACHED */ case OK: if (!xstdout) dup2 (fileno (out), 1); close (fileno (out)); execvp ("/bin/sh", vec); fprintf (stderr, "unable to exec "); perror ("/bin/sh"); _exit (-1); /* NOTREACHED */ default: fclose (out); if (pidXwait(child_id, NULL)) done (1); break; } } /* Check size of file */ if (listsw && ct->c_end == 0L) { struct stat st; if (stat (ce->ce_file, &st) != NOTOK) ct->c_end = (long) st.st_size; } break; } return OK; } /* * Scan the content. * * 1) choose a transfer encoding. * 2) check for clashes with multipart boundary string. * 3) for text content, figure out which character set is being used. * * If there is a clash with one of the contents and the multipart boundary, * this function will exit with NOTOK. This will cause the scanning process * to be repeated with a different multipart boundary. It is possible * (although highly unlikely) that this scan will be repeated multiple times. */ static int scan_content (CT ct, size_t maxunencoded) { int prefix_len; int check8bit = 0, contains8bit = 0; /* check if contains 8bit data */ int checknul = 0, containsnul = 0; /* check if contains NULs */ int checklinelen = 0, linelen = 0; /* check for long lines */ int checkllinelen = 0; /* check for extra-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 */ char *cp = NULL; char *bufp = NULL; size_t buflen; ssize_t gotlen; struct text *t = NULL; FILE *in = NULL; CE ce = &ct->c_cefile; /* * handle multipart by scanning all subparts * and then checking their encoding. */ if (ct->c_type == CT_MULTIPART) { struct multipart *m = (struct multipart *) ct->c_ctparams; struct part *part; /* initially mark the domain of enclosing multipart as 7bit */ ct->c_encoding = CE_7BIT; for (part = m->mp_parts; part; part = part->mp_next) { CT p = part->mp_part; if (scan_content (p, maxunencoded) == NOTOK) /* choose encoding for subpart */ return NOTOK; /* if necessary, enlarge encoding for enclosing multipart */ if (p->c_encoding == CE_BINARY) ct->c_encoding = CE_BINARY; if (p->c_encoding == CE_8BIT && ct->c_encoding != CE_BINARY) ct->c_encoding = CE_8BIT; } return OK; } /* * Decide what to check while scanning this content. Note that * for text content we always check for 8bit characters if the * charset is unspecified, because that controls whether or not the * character set is us-ascii or retrieved from the locale. And * we check even if the charset is specified, to allow setting * the proper Content-Transfer-Encoding. */ if (ct->c_type == CT_TEXT) { t = (struct text *) ct->c_ctparams; if (t->tx_charset == CHARSET_UNSPECIFIED) { checknul = 1; } check8bit = 1; } switch (ct->c_reqencoding) { case CE_8BIT: checkllinelen = 1; checkboundary = 1; break; case CE_QUOTED: checkboundary = 1; break; case CE_BASE64: break; case CE_UNKNOWN: /* Use the default rules based on content-type */ switch (ct->c_type) { case CT_TEXT: checkboundary = 1; checklinelen = 1; if (ct->c_subtype == TEXT_PLAIN) { checklinespace = 0; } else { checklinespace = 1; } break; case CT_APPLICATION: check8bit = 1; checknul = 1; checklinelen = 1; checklinespace = 1; checkboundary = 1; break; case CT_MESSAGE: checklinelen = 0; checklinespace = 0; /* don't check anything for message/external */ if (ct->c_subtype == MESSAGE_EXTERNAL) { checkboundary = 0; check8bit = 0; } else { checkboundary = 1; check8bit = 1; } break; case CT_AUDIO: case CT_IMAGE: case CT_VIDEO: /* * Don't check anything for these types, * since we are forcing use of base64, unless * the content-type was specified by a mhbuild directive. */ check8bit = 0; checklinelen = 0; checklinespace = 0; checkboundary = 0; break; } } /* * Scan the unencoded content */ if (check8bit || checklinelen || checklinespace || checkboundary || checkllinelen || checknul) { if ((in = fopen (ce->ce_file, "r")) == NULL) adios (ce->ce_file, "unable to open for reading"); prefix_len = strlen (prefix); while ((gotlen = getline(&bufp, &buflen, in)) != -1) { /* * Check for 8bit and NUL data. */ for (cp = bufp; (check8bit || checknul) && cp < bufp + gotlen; cp++) { if (!isascii ((unsigned char) *cp)) { contains8bit = 1; check8bit = 0; /* no need to keep checking */ } if (!*cp) { containsnul = 1; checknul = 0; /* no need to keep checking */ } } /* * Check line length. */ if (checklinelen && ((size_t)gotlen > maxunencoded + 1)) { linelen = 1; checklinelen = 0; /* no need to keep checking */ } /* * RFC 5322 specifies that a message cannot contain a line * greater than 998 characters (excluding the CRLF). If we * get one of those lines and linelen is NOT set, then abort. */ if (checkllinelen && !linelen && (gotlen > MAXLONGLINE + 1)) { adios(NULL, "Line in content exceeds maximum line limit (%d)", MAXLONGLINE); } /* * Check if line ends with a space. */ if (checklinespace && (cp = bufp + gotlen - 2) > bufp && isspace ((unsigned char) *cp)) { linespace = 1; checklinespace = 0; /* no need to keep checking */ } /* * Check if content contains a line that clashes * with our standard boundary for multipart messages. */ if (checkboundary && bufp[0] == '-' && bufp[1] == '-') { for (cp = bufp + gotlen - 1; cp >= bufp; cp--) if (!isspace ((unsigned char) *cp)) break; *++cp = '\0'; if (!strncmp(bufp + 2, prefix, prefix_len) && isdigit((unsigned char) bufp[2 + prefix_len])) { boundaryclash = 1; checkboundary = 0; /* no need to keep checking */ } } } fclose (in); free(bufp); } /* * If the content is text and didn't specify a character set, * we need to figure out which one was used. */ set_charset (ct, contains8bit); /* * Decide which transfer encoding to use. */ if (ct->c_reqencoding != CE_UNKNOWN) ct->c_encoding = ct->c_reqencoding; else { int wants_q_p = (containsnul || linelen || linespace || checksw); switch (ct->c_type) { case CT_TEXT: if (wants_q_p) ct->c_encoding = CE_QUOTED; else if (contains8bit) ct->c_encoding = CE_8BIT; else ct->c_encoding = CE_7BIT; break; case CT_APPLICATION: /* For application type, use base64, except when postscript */ if (wants_q_p || contains8bit) { if (ct->c_subtype == APPLICATION_POSTSCRIPT) ct->c_encoding = CE_QUOTED; /* historical */ else ct->c_encoding = CE_BASE64; } else { ct->c_encoding = CE_7BIT; } break; case CT_MESSAGE: ct->c_encoding = contains8bit ? CE_8BIT : CE_7BIT; break; case CT_AUDIO: case CT_IMAGE: case CT_VIDEO: /* For audio, image, and video contents, just use base64 */ ct->c_encoding = CE_BASE64; break; } } return (boundaryclash ? NOTOK : OK); } /* * Scan the content structures, and build header * fields that will need to be output into the * message. */ static int build_headers (CT ct, int header_encoding) { int cc, mailbody, extbody, len; char *np, *vp, buffer[BUFSIZ]; CI ci = &ct->c_ctinfo; /* * If message is type multipart, then add the multipart * boundary to the list of attribute/value pairs. */ if (ct->c_type == CT_MULTIPART) { static int level = 0; /* store nesting level */ snprintf (buffer, sizeof(buffer), "%s%d", prefix, level++); add_param(&ci->ci_first_pm, &ci->ci_last_pm, "boundary", buffer, 0); } /* * Skip the output of Content-Type, parameters, content * description and disposition, and Content-ID if the * content is of type "message" and the rfc934 compatibility * flag is set (which means we are inside multipart/digest * and the switch -rfc934mode was given). */ if (ct->c_type == CT_MESSAGE && ct->c_rfc934) goto skip_headers; /* * output the content type and subtype */ np = mh_xstrdup(TYPE_FIELD); vp = concat (" ", ci->ci_type, "/", ci->ci_subtype, NULL); /* keep track of length of line */ len = strlen (TYPE_FIELD) + strlen (ci->ci_type) + strlen (ci->ci_subtype) + 3; extbody = ct->c_type == CT_MESSAGE && ct->c_subtype == MESSAGE_EXTERNAL; mailbody = extbody && ((struct exbody *) ct->c_ctparams)->eb_body; /* * Append the attribute/value pairs to * the end of the Content-Type line. */ if (ci->ci_first_pm) { char *s = output_params(len, ci->ci_first_pm, &len, mailbody); if (!s) adios(NULL, "Internal error: failed outputting Content-Type " "parameters"); vp = add (s, vp); free(s); } /* * Append any RFC-822 comment to the end of * the Content-Type line. */ if (ci->ci_comment) { snprintf (buffer, sizeof(buffer), "(%s)", ci->ci_comment); if (len + 1 + (cc = 2 + strlen (ci->ci_comment)) >= CPERLIN) { vp = add ("\n\t", vp); len = 8; } else { vp = add (" ", vp); len++; } vp = add (buffer, vp); len += cc; } vp = add ("\n", vp); add_header (ct, np, vp); /* * output the Content-ID, unless disabled by -nocontentid. Note that * RFC 2045 always requires a Content-ID header for message/external-body * entities. */ if ((contentidsw || ct->c_ctexbody) && ct->c_id) { np = mh_xstrdup(ID_FIELD); vp = concat (" ", ct->c_id, NULL); add_header (ct, np, vp); } /* * output the Content-Description */ if (ct->c_descr) { np = mh_xstrdup(DESCR_FIELD); vp = concat (" ", ct->c_descr, NULL); if (header_encoding != CE_8BIT) { if (encode_rfc2047(DESCR_FIELD, &vp, header_encoding, NULL)) { adios(NULL, "Unable to encode %s header", DESCR_FIELD); } } add_header (ct, np, vp); } /* * output the Content-Disposition. If it's NULL but c_dispo_type is * set, then we need to build it. */ if (ct->c_dispo) { np = mh_xstrdup(DISPO_FIELD); vp = concat (" ", ct->c_dispo, NULL); add_header (ct, np, vp); } else if (ct->c_dispo_type) { vp = concat (" ", ct->c_dispo_type, NULL); len = strlen(DISPO_FIELD) + strlen(vp) + 1; np = output_params(len, ct->c_dispo_first, NULL, 0); vp = add(np, vp); vp = add("\n", vp); mh_xfree(np); add_header (ct, mh_xstrdup(DISPO_FIELD), vp); } skip_headers: /* * If this is the internal content structure for a * "message/external", then we are done with the * headers (since it has no body). */ if (ct->c_ctexbody) return OK; /* * output the Content-MD5 */ if (checksw) { np = mh_xstrdup(MD5_FIELD); vp = calculate_digest (ct, ct->c_encoding == CE_QUOTED); add_header (ct, np, vp); } /* * output the Content-Transfer-Encoding * If using EAI and message body is 7-bit, force 8-bit C-T-E. */ if (header_encoding == CE_8BIT && ct->c_encoding == CE_7BIT) { ct->c_encoding = CE_8BIT; } switch (ct->c_encoding) { case CE_7BIT: /* Nothing to output */ break; case CE_8BIT: np = mh_xstrdup(ENCODING_FIELD); vp = concat (" ", "8bit", "\n", NULL); add_header (ct, np, vp); break; case CE_QUOTED: if (ct->c_type == CT_MESSAGE || ct->c_type == CT_MULTIPART) adios (NULL, "internal error, invalid encoding"); np = mh_xstrdup(ENCODING_FIELD); vp = concat (" ", "quoted-printable", "\n", NULL); add_header (ct, np, vp); break; case CE_BASE64: if (ct->c_type == CT_MESSAGE || ct->c_type == CT_MULTIPART) adios (NULL, "internal error, invalid encoding"); np = mh_xstrdup(ENCODING_FIELD); vp = concat (" ", "base64", "\n", NULL); add_header (ct, np, vp); break; case CE_BINARY: if (ct->c_type == CT_MESSAGE) adios (NULL, "internal error, invalid encoding"); np = mh_xstrdup(ENCODING_FIELD); vp = concat (" ", "binary", "\n", NULL); add_header (ct, np, vp); break; default: adios (NULL, "unknown transfer encoding in content"); break; } /* * Additional content specific header processing */ switch (ct->c_type) { case CT_MULTIPART: { struct multipart *m; struct part *part; m = (struct multipart *) ct->c_ctparams; for (part = m->mp_parts; part; part = part->mp_next) { CT p; p = part->mp_part; build_headers (p, header_encoding); } } break; case CT_MESSAGE: if (ct->c_subtype == MESSAGE_EXTERNAL) { struct exbody *e; e = (struct exbody *) ct->c_ctparams; build_headers (e->eb_content, header_encoding); } break; default: /* Nothing to do */ break; } return OK; } static char nib2b64[0x40+1] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static char * calculate_digest (CT ct, int asciiP) { int cc; char *vp, *op; unsigned char *dp; unsigned char digest[16]; unsigned char outbuf[25]; MD5_CTX mdContext; CE ce = &ct->c_cefile; char *infilename = ce->ce_file ? ce->ce_file : ct->c_file; FILE *in; /* open content */ if ((in = fopen (infilename, "r")) == NULL) adios (infilename, "unable to open for reading"); /* Initialize md5 context */ MD5Init (&mdContext); /* calculate md5 message digest */ if (asciiP) { char *bufp = NULL; size_t buflen; ssize_t gotlen; while ((gotlen = getline(&bufp, &buflen, in)) != -1) { char c, *cp; cp = bufp + gotlen - 1; if ((c = *cp) == '\n') gotlen--; MD5Update (&mdContext, (unsigned char *) bufp, (unsigned int) gotlen); if (c == '\n') MD5Update (&mdContext, (unsigned char *) "\r\n", 2); } } else { char buffer[BUFSIZ]; while ((cc = fread (buffer, sizeof(*buffer), sizeof(buffer), in)) > 0) MD5Update (&mdContext, (unsigned char *) buffer, (unsigned int) cc); } /* md5 finalization. Write digest and zero md5 context */ MD5Final (digest, &mdContext); /* close content */ fclose (in); /* print debugging info */ if (debugsw) { unsigned char *ep; fprintf (stderr, "MD5 digest="); for (ep = (dp = digest) + sizeof digest; dp < ep; dp++) fprintf (stderr, "%02x", *dp & 0xff); fprintf (stderr, "\n"); } /* encode the digest using base64 */ for (dp = digest, op = (char *) outbuf, cc = sizeof digest; cc > 0; cc -= 3, op += 4) { unsigned long bits; char *bp; bits = (*dp++ & 0xff) << 16; if (cc > 1) { bits |= (*dp++ & 0xff) << 8; if (cc > 2) bits |= *dp++ & 0xff; } for (bp = op + 4; bp > op; bits >>= 6) *--bp = nib2b64[bits & 0x3f]; if (cc < 3) { *(op + 3) = '='; if (cc < 2) *(op + 2) = '='; } } /* null terminate string */ outbuf[24] = '\0'; /* now make copy and return string */ vp = concat (" ", outbuf, "\n", NULL); return vp; } /* * Set things up for the content structure for file "filename" that * we want to attach */ static void setup_attach_content(CT ct, char *filename) { char *type, *simplename = r1bindex(filename, '/'); struct str2init *s2i; PM pm; if (! (type = mime_type(filename))) { adios(NULL, "Unable to determine MIME type of \"%s\"", filename); } /* * Parse the Content-Type. get_ctinfo() parses MIME parameters, but * since we're just feeding it a MIME type we have to add those ourselves. * Map that to a valid content-type label and call any initialization * function. */ if (get_ctinfo(type, ct, 0) == NOTOK) done(1); free(type); for (s2i = str2cts; s2i->si_key; s2i++) if (strcasecmp(ct->c_ctinfo.ci_type, s2i->si_key) == 0) break; if (!s2i->si_key && !uprf(ct->c_ctinfo.ci_type, "X-")) s2i++; /* * Make sure the type isn't incompatible with what we can handle */ switch (ct->c_type = s2i->si_val) { case CT_MULTIPART: adios (NULL, "multipart types must be specified by mhbuild directives"); /* NOTREACHED */ case CT_MESSAGE: if (strcasecmp(ct->c_ctinfo.ci_subtype, "partial") == 0) adios(NULL, "Sorry, %s/%s isn't supported", ct->c_ctinfo.ci_type, ct->c_ctinfo.ci_subtype); if (strcasecmp(ct->c_ctinfo.ci_subtype, "external-body") == 0) adios(NULL, "external-body messages must be specified " "by mhbuild directives"); /* FALLTHRU */ default: /* * This sets the subtype, if it's significant */ if ((ct->c_ctinitfnx = s2i->si_init)) (*ct->c_ctinitfnx)(ct); break; } /* * Feed in a few attributes; specifically, the name attribute, the * content-description, and the content-disposition. */ for (pm = ct->c_ctinfo.ci_first_pm; pm; pm = pm->pm_next) { if (strcasecmp(pm->pm_name, "name") == 0) { mh_xfree(pm->pm_value); pm->pm_value = mh_xstrdup(simplename); break; } } if (pm == NULL) add_param(&ct->c_ctinfo.ci_first_pm, &ct->c_ctinfo.ci_last_pm, "name", simplename, 0); ct->c_descr = mh_xstrdup(simplename); ct->c_descr = add("\n", ct->c_descr); ct->c_cefile.ce_file = mh_xstrdup(filename); set_disposition (ct); add_param(&ct->c_dispo_first, &ct->c_dispo_last, "filename", simplename, 0); } /* * If disposition type hasn't already been set in ct: * Look for mhbuild-disposition-/ entry * that specifies Content-Disposition type. Only * 'attachment' and 'inline' are allowed. Default to * 'attachment'. */ void set_disposition (CT ct) { if (ct->c_dispo_type == NULL) { char *cp = context_find_by_type ("disposition", ct->c_ctinfo.ci_type, ct->c_ctinfo.ci_subtype); if (cp && strcasecmp (cp, "attachment") && strcasecmp (cp, "inline")) { inform("configuration problem: %s-disposition-%s%s%s specifies " "'%s' but only 'attachment' and 'inline' are allowed, " "continuing...", invo_name, ct->c_ctinfo.ci_type, ct->c_ctinfo.ci_subtype ? "/" : "", FENDNULL(ct->c_ctinfo.ci_subtype), cp); } if (!cp) cp = "attachment"; ct->c_dispo_type = mh_xstrdup(cp); } } /* * Set text content charset if it was unspecified. contains8bit * selections: * 0: content does not contain 8-bit characters * 1: content contains 8-bit characters * -1: ignore content and use user's locale to determine charset */ void set_charset (CT ct, int contains8bit) { if (ct->c_type == CT_TEXT) { struct text *t; if (ct->c_ctparams == NULL) { NEW0(t); ct->c_ctparams = t; t->tx_charset = CHARSET_UNSPECIFIED; } else { t = (struct text *) ct->c_ctparams; } if (t->tx_charset == CHARSET_UNSPECIFIED) { CI ci = &ct->c_ctinfo; char *eightbitcharset = write_charset_8bit(); char *charset = contains8bit ? eightbitcharset : "us-ascii"; if (contains8bit == 1 && strcasecmp (eightbitcharset, "US-ASCII") == 0) { adios (NULL, "Text content contains 8 bit characters, but " "character set is US-ASCII"); } add_param (&ci->ci_first_pm, &ci->ci_last_pm, "charset", charset, 0); t->tx_charset = CHARSET_SPECIFIED; } } } /* * Look at all of the replied-to message parts and expand any that * are matched by a pseudoheader. Except don't descend into * message parts. */ void expand_pseudoheaders (CT ct, struct multipart *m, const char *infile, const convert_list *convert_head) { /* text_plain_ct is used to concatenate all of the text/plain replies into one part, instead of having each one in a separate part. */ CT text_plain_ct = NULL; switch (ct->c_type) { case CT_MULTIPART: { struct multipart *mp = (struct multipart *) ct->c_ctparams; struct part *part; if (ct->c_subtype == MULTI_ALTERNATE) { int matched = 0; /* The parts are in descending priority order (defined by RFC 2046 Sec. 5.1.4) because they were reversed by parse_mime (). So, stop looking for matches with immediate subparts after the first match of an alternative. */ for (part = mp->mp_parts; ! matched && part; part = part->mp_next) { char *type_subtype = concat (part->mp_part->c_ctinfo.ci_type, "/", part->mp_part->c_ctinfo.ci_subtype, NULL); if (part->mp_part->c_type == CT_MULTIPART) { expand_pseudoheaders (part->mp_part, m, infile, convert_head); } else { const convert_list *c; for (c = convert_head; c; c = c->next) { if (! strcasecmp (type_subtype, c->type)) { expand_pseudoheader (part->mp_part, &text_plain_ct, m, infile, c->type, c->argstring); matched = 1; break; } } } free (type_subtype); } } else { for (part = mp->mp_parts; part; part = part->mp_next) { expand_pseudoheaders (part->mp_part, m, infile, convert_head); } } break; } default: { char *type_subtype = concat (ct->c_ctinfo.ci_type, "/", ct->c_ctinfo.ci_subtype, NULL); const convert_list *c; for (c = convert_head; c; c = c->next) { if (! strcasecmp (type_subtype, c->type)) { expand_pseudoheader (ct, &text_plain_ct, m, infile, c->type, c->argstring); break; } } free (type_subtype); break; } } } /* * Expand a single pseudoheader. It's for the specified type. */ void expand_pseudoheader (CT ct, CT *text_plain_ct, struct multipart *m, const char *infile, const char *type, const char *argstring) { char *reply_file; FILE *reply_fp = NULL; char *convert, *type_p, *subtype_p; char *convert_command; char *charset = NULL; char *cp; struct str2init *s2i; CT reply_ct; struct part *part; int status; type_p = getcpy (type); if ((subtype_p = strchr (type_p, '/'))) { *subtype_p++ = '\0'; convert = context_find_by_type ("convert", type_p, subtype_p); } else { free (type_p); type_p = concat ("mhbuild-convert-", type, NULL); convert = context_find (type_p); } free (type_p); if (! (convert)) { /* No mhbuild-convert- entry in mhn.defaults or profile for type. */ return; } /* reply_file is used to pass the output of the convert. */ reply_file = getcpy (m_mktemp2 (NULL, invo_name, NULL, NULL)); convert_command = concat (convert, " ", FENDNULL(argstring), " >", reply_file, NULL); /* Convert here . . . */ ct->c_storeproc = mh_xstrdup(convert_command); ct->c_umask = ~m_gmprot (); if ((status = show_content_aux (ct, 0, convert_command, NULL, NULL)) != OK) { inform("store of %s content failed, continuing...", type); } free (convert_command); /* Fill out the the new ct, reply_ct. */ NEW0(reply_ct); init_decoded_content (reply_ct, infile); if (extract_headers (reply_ct, reply_file, &reply_fp) == NOTOK) { free (reply_file); inform("failed to extract headers from convert output in %s, " "continuing...", reply_file); return; } /* This sets reply_ct->c_ctparams, and reply_ct->c_termproc if the charset can't be handled natively. */ for (s2i = str2cts; s2i->si_key; s2i++) { if (strcasecmp(reply_ct->c_ctinfo.ci_type, s2i->si_key) == 0) { break; } } if ((reply_ct->c_ctinitfnx = s2i->si_init)) { (*reply_ct->c_ctinitfnx)(reply_ct); } if ((cp = get_param (reply_ct->c_ctinfo.ci_first_pm, "charset", '?', 1))) { /* The reply Content-Type had the charset. */ charset = cp; } else { set_charset (reply_ct, -1); charset = get_param (reply_ct->c_ctinfo.ci_first_pm, "charset", '?', 1); } /* Concatenate text/plain parts. */ if (reply_ct->c_type == CT_TEXT && reply_ct->c_subtype == TEXT_PLAIN) { if (! *text_plain_ct && m->mp_parts && m->mp_parts->mp_part && m->mp_parts->mp_part->c_type == CT_TEXT && m->mp_parts->mp_part->c_subtype == TEXT_PLAIN) { *text_plain_ct = m->mp_parts->mp_part; /* Make sure that the charset is set in the text/plain part. */ set_charset (*text_plain_ct, -1); } if (*text_plain_ct) { /* Only concatenate if the charsets are identical. */ char *text_plain_ct_charset = get_param ((*text_plain_ct)->c_ctinfo.ci_first_pm, "charset", '?', 1); if (strcasecmp (text_plain_ct_charset, charset) == 0) { /* Append this text/plain reply to the first one. If there's a problem anywhere along the way, instead attach it is a separate part. */ int text_plain_reply = open ((*text_plain_ct)->c_cefile.ce_file, O_WRONLY | O_APPEND); int addl_reply = open (reply_file, O_RDONLY); if (text_plain_reply != NOTOK && addl_reply != NOTOK) { /* Insert blank line before each addl part. */ /* It would be nice not to do this for the first one. */ if (write (text_plain_reply, "\n", 1) == 1) { /* Copy the text from the new reply and then free its Content struct. */ cpydata (addl_reply, text_plain_reply, (*text_plain_ct)->c_cefile.ce_file, reply_file); if (close (text_plain_reply) == OK && close (addl_reply) == OK) { /* If appended text needed 8-bit but first text didn't, propagate the 8-bit indication. */ if ((*text_plain_ct)->c_reqencoding == CE_7BIT && reply_ct->c_reqencoding == CE_8BIT) { (*text_plain_ct)->c_reqencoding = CE_8BIT; } if (reply_fp) { fclose (reply_fp); } free (reply_file); free_content (reply_ct); return; } } } } } else { *text_plain_ct = reply_ct; } } reply_ct->c_cefile.ce_file = reply_file; reply_ct->c_cefile.ce_fp = reply_fp; reply_ct->c_cefile.ce_unlink = 1; /* Attach the new part to the parent multipart/mixed, "m". */ NEW0(part); part->mp_part = reply_ct; if (m->mp_parts) { struct part *p; for (p = m->mp_parts; p && p->mp_next; p = p->mp_next) { continue; } p->mp_next = part; } else { m->mp_parts = part; } } /* Extract any Content-Type header from beginning of convert output. */ int extract_headers (CT ct, char *reply_file, FILE **reply_fp) { char *buffer = NULL, *cp, *end_of_header; int found_header = 0; struct stat statbuf; /* Read the convert reply from the file to memory. */ if (stat (reply_file, &statbuf) == NOTOK) { admonish (reply_file, "failed to stat"); goto failed_to_extract_ct; } buffer = mh_xmalloc (statbuf.st_size + 1); if ((*reply_fp = fopen (reply_file, "r+")) == NULL || fread (buffer, 1, (size_t) statbuf.st_size, *reply_fp) < (size_t) statbuf.st_size) { admonish (reply_file, "failed to read"); goto failed_to_extract_ct; } buffer[statbuf.st_size] = '\0'; /* Look for a header in the convert reply. */ if (strncasecmp (buffer, TYPE_FIELD, strlen (TYPE_FIELD)) == 0 && buffer[strlen (TYPE_FIELD)] == ':') { if ((end_of_header = strstr (buffer, "\r\n\r\n"))) { end_of_header += 2; found_header = 1; } else if ((end_of_header = strstr (buffer, "\n\n"))) { ++end_of_header; found_header = 1; } } if (found_header) { CT tmp_ct; char *tmp_file; FILE *tmp_f; size_t n; /* Truncate buffer to just the C-T. */ *end_of_header = '\0'; n = strlen (buffer); if (get_ctinfo (buffer + 14, ct, 0) != OK) { inform("unable to get content info for reply, continuing..."); goto failed_to_extract_ct; } /* Hack. Use parse_mime() to detect the type/subtype of the reply, which we'll use below. */ tmp_file = getcpy (m_mktemp2 (NULL, invo_name, NULL, NULL)); if ((tmp_f = fopen (tmp_file, "w")) && fwrite (buffer, 1, n, tmp_f) == n) { fclose (tmp_f); } else { goto failed_to_extract_ct; } tmp_ct = parse_mime (tmp_file); if (tmp_ct) { /* The type and subtype were detected from the reply using parse_mime() above. */ ct->c_type = tmp_ct->c_type; ct->c_subtype = tmp_ct->c_subtype; free_content (tmp_ct); } free (tmp_file); /* Rewrite the content without the header. */ cp = end_of_header + 1; rewind (*reply_fp); if (fwrite (cp, 1, statbuf.st_size - (cp - buffer), *reply_fp) < (size_t) (statbuf.st_size - (cp - buffer))) { admonish (reply_file, "failed to write"); goto failed_to_extract_ct; } if (ftruncate (fileno (*reply_fp), statbuf.st_size - (cp - buffer)) != 0) { advise (reply_file, "ftruncate"); goto failed_to_extract_ct; } } else { /* No header section, assume the reply is text/plain. */ ct->c_type = CT_TEXT; ct->c_subtype = TEXT_PLAIN; if (get_ctinfo ("text/plain", ct, 0) == NOTOK) { /* This never should fail, but just in case. */ adios (NULL, "unable to get content info for reply"); } } /* free_encoding() will close reply_fp, which is passed through ct->c_cefile.ce_fp. */ free (buffer); return OK; failed_to_extract_ct: if (*reply_fp) { fclose (*reply_fp); } free (buffer); return NOTOK; } nmh-1.7.1-RC3/uip/mhcachesbr.c000644 007761 000024 00000021173 13243042053 016022 0ustar00kenhstaff000000 000000 /* mhcachesbr.c -- routines to manipulate the MIME content cache * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #include #include #include #include "../sbr/lock_file.h" #include "../sbr/m_mktemp.h" #ifdef HAVE_SYS_TIME_H # include #endif #include #define X(sw, minchars, id) { sw, minchars, id }, DEFINE_SWITCH_ARRAY(CACHE, caches); #undef X struct swit *cache_policy = caches; extern int debugsw; /* cache policies */ int rcachesw = CACHE_ASK; int wcachesw = CACHE_ASK; /* * Location of public and private cache. These must * be set before these routines are called. */ char *cache_public; char *cache_private; /* mhmisc.c */ int part_ok (CT); int type_ok (CT, int); void content_error (char *, CT, char *, ...); void flush_errors (void); /* * static prototypes */ static void cache_content (CT); static int find_cache_aux (int, char *, char *, char *, int); static int find_cache_aux2 (char *, char *, char *, int); /* * Top level entry point to cache content * from a group of messages */ void cache_all_messages (CT *cts) { CT ct, *ctp; for (ctp = cts; *ctp; ctp++) { ct = *ctp; if (type_ok (ct, 1)) { cache_content (ct); if (ct->c_fp) { fclose (ct->c_fp); ct->c_fp = NULL; } if (ct->c_ceclosefnx) (*ct->c_ceclosefnx) (ct); } } flush_errors (); } /* * Entry point to cache content from external sources. */ static void cache_content (CT ct) { int cachetype; char *file, cachefile[BUFSIZ]; CE ce = &ct->c_cefile; if (!ct->c_id) { inform("no %s: field in %s", ID_FIELD, ct->c_file); return; } if (!ce) { inform("unable to decode %s", ct->c_file); return; } if (find_cache (NULL, wcachesw != CACHE_NEVER ? wcachesw : CACHE_ASK, &cachetype, ct->c_id, cachefile, sizeof(cachefile)) == NOTOK) { inform("unable to cache %s's contents", ct->c_file); return; } if (wcachesw != CACHE_NEVER && wcachesw != CACHE_ASK) { fflush (stdout); fprintf (stderr, "caching message %s as file %s\n", ct->c_file, cachefile); } if (ce->ce_file) { int mask = umask (cachetype ? ~m_gmprot () : 0222); FILE *fp; if (debugsw) fprintf (stderr, "caching by copying %s...\n", ce->ce_file); file = NULL; if ((*ct->c_ceopenfnx) (ct, &file) == NOTOK) goto reset_umask; if ((fp = fopen (cachefile, "w"))) { int cc; char buffer[BUFSIZ]; FILE *gp = ce->ce_fp; fseek (gp, 0L, SEEK_SET); while ((cc = fread (buffer, sizeof(*buffer), sizeof(buffer), gp)) > 0) if ((int) fwrite (buffer, sizeof(*buffer), cc, fp) < cc) { advise ("cache_content", "fwrite"); } fflush (fp); if (ferror (gp)) { admonish (ce->ce_file, "error reading"); (void) m_unlink (cachefile); } else { if (ferror (fp)) { admonish (cachefile, "error writing"); (void) m_unlink (cachefile); } } fclose (fp); } else content_error (cachefile, ct, "unable to fopen for writing"); reset_umask: umask (mask); } else { if (debugsw) fprintf (stderr, "in place caching...\n"); file = cachefile; if ((*ct->c_ceopenfnx) (ct, &file) != NOTOK) chmod (cachefile, cachetype ? m_gmprot () : 0444); } } int find_cache (CT ct, int policy, int *writing, char *id, char *buffer, int buflen) { int status = NOTOK; if (id == NULL) return NOTOK; id = trimcpy (id); if (debugsw) fprintf (stderr, "find_cache %s(%d) %s %s\n", caches[policy].sw, policy, writing ? "writing" : "reading", id); switch (policy) { case CACHE_NEVER: default: break; case CACHE_ASK: case CACHE_PUBLIC: if (cache_private && !writing && find_cache_aux (writing ? 2 : 0, cache_private, id, buffer, buflen) == OK) { if (access (buffer, R_OK) != NOTOK) { got_private: if (writing) *writing = 1; got_it: status = OK; break; } } if (cache_public && find_cache_aux (writing ? 1 : 0, cache_public, id, buffer, buflen) == OK) { if (writing || access (buffer, R_OK) != NOTOK) { if (writing) *writing = 0; goto got_it; } } break; case CACHE_PRIVATE: if (cache_private && find_cache_aux (writing ? 2 : 0, cache_private, id, buffer, buflen) == OK) { if (writing || access (buffer, R_OK) != NOTOK) goto got_private; } break; } if (status == OK && policy == CACHE_ASK) { int len, buflen; char *bp, query[BUFSIZ]; /* Get buffer ready to go */ bp = query; buflen = sizeof(query); /* Now, construct query */ if (writing) { snprintf (bp, buflen, "Make cached, publicly-accessible copy"); } else { struct stat st; snprintf (bp, buflen, "Use cached copy"); len = strlen (bp); bp += len; buflen -= len; if (ct->c_partno) { snprintf (bp, buflen, " of content %s", ct->c_partno); len = strlen (bp); bp += len; buflen -= len; } stat (buffer, &st); snprintf (bp, buflen, " (size %lu octets)", (unsigned long) st.st_size); } len = strlen (bp); bp += len; buflen -= len; snprintf (bp, buflen, "\n in file %s? ", buffer); /* Now, check answer */ if (!read_yes_or_no_if_tty (query)) status = NOTOK; } if (status == OK && writing) { if (*writing && strchr(buffer, '/')) make_intermediates (buffer); (void) m_unlink (buffer); } free (id); return status; } static int find_cache_aux (int writing, char *directory, char *id, char *buffer, int buflen) { int mask, usemap; char mapfile[BUFSIZ], mapname[BUFSIZ]; FILE *fp; int failed_to_lock = 0; static int partno, pid; static time_t clock = 0; usemap = 1; if (debugsw) fprintf (stderr, "find_cache_aux %s usemap=%d\n", directory, usemap); snprintf (mapfile, sizeof(mapfile), "%s/cache.map", directory); if (find_cache_aux2 (mapfile, id, mapname, sizeof(mapname)) == OK) goto done_map; if (!writing) { if (usemap) return NOTOK; use_raw: snprintf (buffer, buflen, "%s/%s", directory, id); return OK; } if (!usemap && access (mapfile, W_OK) == NOTOK) goto use_raw; if (clock != 0) { time_t now; time (&now); if (now > clock) clock = 0; } else { pid = getpid (); } if (clock == 0) { time (&clock); partno = 0; } else { if (partno > 0xff) { clock++; partno = 0; } } snprintf (mapname, sizeof(mapname), "%08x%04x%02x", (unsigned int) (clock & 0xffffffff), (unsigned int) (pid & 0xffff), (unsigned int) (partno++ & 0xff)); if (debugsw) fprintf (stderr, "creating mapping %s->%s\n", mapname, id); make_intermediates (mapfile); mask = umask (writing == 2 ? 0077 : 0); if (!(fp = lkfopendata (mapfile, "a", &failed_to_lock)) && errno == ENOENT) { int fd; if ((fd = creat (mapfile, 0666)) != NOTOK) { close (fd); fp = lkfopendata (mapfile, "a", &failed_to_lock); if (failed_to_lock) { adios (mapfile, "failed to lock"); } } } umask (mask); if (!fp) return NOTOK; fprintf (fp, "%s: %s\n", mapname, id); lkfclosedata (fp, mapfile); done_map: if (*mapname == '/') strncpy (buffer, mapname, buflen); else snprintf (buffer, buflen, "%s/%s", directory, mapname); if (debugsw) fprintf (stderr, "use %s\n", buffer); return OK; } static int find_cache_aux2 (char *mapfile, char *id, char *mapname, int namelen) { int state; char buf[NMH_BUFSIZ], name[NAMESZ]; FILE *fp; m_getfld_state_t gstate = 0; int failed_to_lock = 0; if (!(fp = lkfopendata (mapfile, "r", &failed_to_lock))) return NOTOK; for (;;) { int result; char *cp, *dp; int bufsz = sizeof buf; switch (state = m_getfld (&gstate, name, buf, &bufsz, fp)) { case FLD: case FLDPLUS: strncpy (mapname, name, namelen); if (state != FLDPLUS) cp = buf; else { cp = mh_xstrdup(buf); while (state == FLDPLUS) { bufsz = sizeof buf; state = m_getfld (&gstate, name, buf, &bufsz, fp); cp = add (buf, cp); } } dp = trimcpy (cp); if (cp != buf) free (cp); if (debugsw) fprintf (stderr, "compare %s to %s <- %s\n", id, dp, mapname); result = strcmp (id, dp); free (dp); if (result == 0) { lkfclosedata (fp, mapfile); return OK; } continue; case BODY: case FILEEOF: default: break; } break; } m_getfld_state_destroy (&gstate); lkfclosedata (fp, mapfile); return NOTOK; } nmh-1.7.1-RC3/uip/mhfixmsg.c000644 007761 000024 00000264677 13243042054 015570 0ustar00kenhstaff000000 000000 /* mhfixmsg.c -- rewrite a message with various transformations * * This code is Copyright (c) 2002 and 2013, by the authors of nmh. * See the COPYRIGHT file in the root directory of the nmh * distribution for complete copyright information. */ #include #include #include #include #include #include #include "../sbr/m_maildir.h" #include "../sbr/m_mktemp.h" #include "../sbr/mime_type.h" #include "mhfree.h" #include "mhoutsbr.h" #include "mhshowsbr.h" #include #define MHFIXMSG_SWITCHES \ X("decodetext 8bit|7bit|binary", 0, DECODETEXTSW) \ X("nodecodetext", 0, NDECODETEXTSW) \ X("decodetypes", 0, DECODETYPESW) \ X("crlflinebreaks", 0, CRLFLINEBREAKSSW) \ X("nocrlflinebreaks", 0, NCRLFLINEBREAKSSW) \ X("textcharset", 0, TEXTCHARSETSW) \ X("notextcharset", 0, NTEXTCHARSETSW) \ X("reformat", 0, REFORMATSW) \ X("noreformat", 0, NREFORMATSW) \ X("replacetextplain", 0, REPLACETEXTPLAINSW) \ X("noreplacetextplain", 0, NREPLACETEXTPLAINSW) \ X("fixboundary", 0, FIXBOUNDARYSW) \ X("nofixboundary", 0, NFIXBOUNDARYSW) \ X("fixcte", 0, FIXCOMPOSITECTESW) \ X("nofixcte", 0, NFIXCOMPOSITECTESW) \ X("fixtype mimetype", 0, FIXTYPESW) \ X("file file", 0, FILESW) \ X("outfile file", 0, OUTFILESW) \ X("rmmproc program", 0, RPROCSW) \ X("normmproc", 0, NRPRCSW) \ X("changecur", 0, CHGSW) \ X("nochangecur", 0, NCHGSW) \ 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(MHFIXMSG); #undef X #define X(sw, minchars, id) { sw, minchars, id }, DEFINE_SWITCH_ARRAY(MHFIXMSG, switches); #undef X int verbosw; int debugsw; /* Needed by mhparse.c. */ #define quitser pipeser /* mhparse.c */ extern int skip_mp_cte_check; /* flag to InitMultiPart */ extern int suppress_bogus_mp_content_warning; /* flag to InitMultiPart */ extern int bogus_mp_content; /* flag from InitMultiPart */ /* flags to/from parse_header_attrs */ extern int suppress_extraneous_trailing_semicolon_warning; /* mhmisc.c */ void flush_errors (void); /* * static prototypes */ typedef struct fix_transformations { int fixboundary; int fixcompositecte; svector_t fixtypes; int reformat; int replacetextplain; int decodetext; char *decodetypes; /* Whether to use CRLF linebreaks, per RFC 2046 Sec. 4.1.1, par.1. */ int lf_line_endings; char *textcharset; } fix_transformations; int mhfixmsgsbr (CT *, char *, const fix_transformations *, FILE **, char *, FILE **); static int fix_boundary (CT *, int *); static int copy_input_to_output (const char *, FILE *, const char *, FILE *); static int get_multipart_boundary (CT, char **); static int replace_boundary (CT, char *, char *); static int fix_types (CT, svector_t, int *); static char *replace_substring (char **, const char *, const char *); static char *remove_parameter (char *, const char *); static int fix_composite_cte (CT, int *); static int set_ce (CT, int); static int ensure_text_plain (CT *, CT, int *, int); static int find_textplain_sibling (CT, int, int *); static int insert_new_text_plain_part (CT, int, CT); static CT build_text_plain_part (CT); static int insert_into_new_mp_alt (CT *, int *); static CT divide_part (CT); static void copy_ctinfo (CI, CI); static int decode_part (CT); static int reformat_part (CT, char *, char *, char *, int); static CT build_multipart_alt (CT, CT, int, int); static int boundary_in_content (FILE **, char *, const char *); static void transfer_noncontent_headers (CT, CT); static int set_ct_type (CT, int type, int subtype, int encoding); static int decode_text_parts (CT, int, const char *, int *); static int should_decode(const char *, const char *, const char *); static int content_encoding (CT, const char **); static int strip_crs (CT, int *); static void update_cte (CT); static int least_restrictive_encoding (CT); static int less_restrictive (int, int); static int convert_charsets (CT, char *, int *); static int fix_always (CT, int *); static int fix_filename_param (char *, char *, PM *, PM *); static int fix_filename_encoding (CT); static int write_content (CT, const char *, char *, FILE *, int, int); static void set_text_ctparams(CT, char *, int); static int remove_file (const char *); static void report (char *, char *, char *, char *, ...); static void pipeser (int); int main (int argc, char **argv) { int msgnum; char *cp, *file = NULL, *folder = NULL; char *maildir = NULL, buf[100], *outfile = NULL; char **argp, **arguments; struct msgs_array msgs = { 0, 0, NULL }; struct msgs *mp = NULL; CT *ctp; FILE *fp, *infp = NULL, *outfp = NULL; int using_stdin = 0; int chgflag = 1; int status = OK; fix_transformations fx; fx.reformat = fx.fixcompositecte = fx.fixboundary = 1; fx.fixtypes = NULL; fx.replacetextplain = 0; fx.decodetext = CE_8BIT; fx.decodetypes = "text,application/ics"; /* Default, per man page. */ fx.lf_line_endings = 0; fx.textcharset = NULL; if (nmh_init(argv[0], 2)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; /* * Parse arguments */ while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof buf, "%s [+folder] [msgs] [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case DECODETEXTSW: if (! (cp = *argp++) || *cp == '-') { adios (NULL, "missing argument to %s", argp[-2]); } if (! strcasecmp (cp, "8bit")) { fx.decodetext = CE_8BIT; } else if (! strcasecmp (cp, "7bit")) { fx.decodetext = CE_7BIT; } else if (! strcasecmp (cp, "binary")) { fx.decodetext = CE_BINARY; } else { adios (NULL, "invalid argument to %s", argp[-2]); } continue; case NDECODETEXTSW: fx.decodetext = 0; continue; case DECODETYPESW: if (! (cp = *argp++) || *cp == '-') { adios (NULL, "missing argument to %s", argp[-2]); } fx.decodetypes = cp; continue; case CRLFLINEBREAKSSW: fx.lf_line_endings = 0; continue; case NCRLFLINEBREAKSSW: fx.lf_line_endings = 1; continue; case TEXTCHARSETSW: if (! (cp = *argp++) || (*cp == '-' && cp[1])) { adios (NULL, "missing argument to %s", argp[-2]); } fx.textcharset = cp; continue; case NTEXTCHARSETSW: fx.textcharset = 0; continue; case FIXBOUNDARYSW: fx.fixboundary = 1; continue; case NFIXBOUNDARYSW: fx.fixboundary = 0; continue; case FIXCOMPOSITECTESW: fx.fixcompositecte = 1; continue; case NFIXCOMPOSITECTESW: fx.fixcompositecte = 0; continue; case FIXTYPESW: if (! (cp = *argp++) || (*cp == '-' && cp[1])) { adios (NULL, "missing argument to %s", argp[-2]); } if (! strncasecmp (cp, "multipart/", 10) || ! strncasecmp (cp, "message/", 8)) { adios (NULL, "-fixtype %s not allowed", cp); } else if (! strchr (cp, '/')) { adios (NULL, "-fixtype requires type/subtype"); } if (fx.fixtypes == NULL) { fx.fixtypes = svector_create (10); } svector_push_back (fx.fixtypes, cp); continue; case REFORMATSW: fx.reformat = 1; continue; case NREFORMATSW: fx.reformat = 0; continue; case REPLACETEXTPLAINSW: fx.replacetextplain = 1; continue; case NREPLACETEXTPLAINSW: fx.replacetextplain = 0; continue; case FILESW: if (! (cp = *argp++) || (*cp == '-' && cp[1])) { adios (NULL, "missing argument to %s", argp[-2]); } file = *cp == '-' ? mh_xstrdup (cp) : path (cp, TFILE); continue; case OUTFILESW: if (! (cp = *argp++) || (*cp == '-' && cp[1])) { adios (NULL, "missing argument to %s", argp[-2]); } outfile = *cp == '-' ? mh_xstrdup (cp) : path (cp, TFILE); continue; case RPROCSW: if (!(rmmproc = *argp++) || *rmmproc == '-') { adios (NULL, "missing argument to %s", argp[-2]); } continue; case NRPRCSW: rmmproc = NULL; continue; case CHGSW: chgflag = 1; continue; case NCHGSW: chgflag = 0; continue; case VERBSW: verbosw = 1; continue; case NVERBSW: verbosw = 0; continue; } } if (*cp == '+' || *cp == '@') { if (folder) { adios (NULL, "only one folder at a time!"); } else { folder = pluspath (cp); } } else { if (*cp == '/') { /* Interpret a full path as a filename, not a message. */ file = mh_xstrdup (cp); } else { app_msgarg (&msgs, cp); } } } SIGNAL (SIGQUIT, quitser); SIGNAL (SIGPIPE, pipeser); /* * Read the standard profile setup */ if ((fp = fopen (cp = etcpath ("mhn.defaults"), "r"))) { readconfig ((struct node **) 0, fp, cp, 0); fclose (fp); } suppress_bogus_mp_content_warning = skip_mp_cte_check = 1; suppress_extraneous_trailing_semicolon_warning = 1; if (! context_find ("path")) { free (path ("./", TFOLDER)); } if (file && msgs.size) { adios (NULL, "cannot specify msg and file at same time!"); } if (outfile) { /* Open the outfile now, so we don't have to risk opening it after running out of fds. */ if (strcmp (outfile, "-") == 0) { outfp = stdout; } else if ((outfp = fopen (outfile, "w")) == NULL) { adios (outfile, "unable to open for writing"); } } /* * check if message is coming from file */ if (file) { /* If file is stdin, create a tmp file name before parse_mime() has a chance, because it might put in on a different filesystem than the output file. Instead, put it in the user's preferred tmp directory. */ CT ct; if (! strcmp ("-", file)) { int fd; char *cp; using_stdin = 1; if ((cp = m_mktemp2 (NULL, invo_name, &fd, NULL)) == NULL) { adios (NULL, "unable to create temporary file in %s", get_temp_dir()); } else { free (file); file = mh_xstrdup (cp); cpydata (STDIN_FILENO, fd, "-", file); } if (close (fd)) { (void) m_unlink (file); adios (NULL, "failed to write temporary file"); } } cts = mh_xcalloc(2, sizeof *cts); ctp = cts; if ((ct = parse_mime (file))) { set_text_ctparams(ct, fx.decodetypes, fx.lf_line_endings); *ctp++ = ct; } else { inform("unable to parse message from file %s", file); status = NOTOK; /* If there's an outfile, pass the input message unchanged, so the message won't get dropped from a pipeline. */ if (outfile) { /* Something went wrong. Output might be expected, such as if this were run as a filter. Just copy the input to the output. */ if ((infp = fopen (file, "r")) == NULL) { adios (file, "unable to open for reading"); } if (copy_input_to_output (file, infp, outfile, outfp) != OK) { inform("unable to copy message to %s, " "it might be lost\n", outfile); } fclose (infp); infp = NULL; } } } else { /* * message(s) are coming from a folder */ CT ct; if (! msgs.size) { app_msgarg(&msgs, "cur"); } if (! folder) { folder = getfolder (1); } maildir = mh_xstrdup(m_maildir (folder)); /* chdir so that error messages, esp. from MIME parser, just refer to the message and not its path. */ if (chdir (maildir) == NOTOK) { adios (maildir, "unable to change directory to"); } /* read folder and create message structure */ if (! (mp = folder_read (folder, 1))) { adios (NULL, "unable to read folder %s", folder); } /* check for empty folder */ if (mp->nummsg == 0) { adios (NULL, "no messages in %s", folder); } /* parse all the message ranges/sequences and set SELECTED */ for (msgnum = 0; msgnum < msgs.size; msgnum++) if (! m_convert (mp, msgs.msgs[msgnum])) { done (1); } seq_setprev (mp); /* set the previous-sequence */ cts = mh_xcalloc(mp->numsel + 1, sizeof *cts); ctp = cts; for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { if (is_selected(mp, msgnum)) { char *msgnam = m_name (msgnum); if ((ct = parse_mime (msgnam))) { set_text_ctparams(ct, fx.decodetypes, fx.lf_line_endings); *ctp++ = ct; } else { inform("unable to parse message %s", msgnam); status = NOTOK; /* If there's an outfile, pass the input message unchanged, so the message won't get dropped from a pipeline. */ if (outfile) { /* Something went wrong. Output might be expected, such as if this were run as a filter. Just copy the input to the output. */ /* Can't use path() here because 1) it might have been called before and it caches the pwd, and 2) we call chdir() after that. */ char *input_filename = concat (maildir, "/", msgnam, NULL); if ((infp = fopen (input_filename, "r")) == NULL) { adios (input_filename, "unable to open for reading"); } if (copy_input_to_output (input_filename, infp, outfile, outfp) != OK) { inform("unable to copy message to %s, " "it might be lost\n", outfile); } fclose (infp); infp = NULL; free (input_filename); } } } } if (chgflag) { seq_setcur (mp, mp->hghsel); /* update current message */ } seq_save (mp); /* synchronize sequences */ context_replace (pfolder, folder);/* update current folder */ context_save (); /* save the context file */ } if (*cts) { for (ctp = cts; *ctp; ++ctp) { status += mhfixmsgsbr (ctp, maildir, &fx, &infp, outfile, &outfp); free_content (*ctp); if (using_stdin) { (void) m_unlink (file); if (! outfile) { /* Just calling m_backup() unlinks the backup file. */ (void) m_backup (file); } } } } else { status = 1; } mh_xfree(maildir); free (cts); if (fx.fixtypes != NULL) { svector_free (fx.fixtypes); } if (infp) { fclose (infp); } /* even if stdin */ if (outfp) { fclose (outfp); } /* even if stdout */ free (outfile); free (file); free (folder); free (arguments); done (status); return NOTOK; } /* * Apply transformations to one message. */ int mhfixmsgsbr (CT *ctp, char *maildir, const fix_transformations *fx, FILE **infp, char *outfile, FILE **outfp) { /* Store input filename in case one of the transformations, i.e., fix_boundary(), rewrites to a tmp file. */ char *input_filename = maildir ? concat (maildir, "/", (*ctp)->c_file, NULL) : mh_xstrdup ((*ctp)->c_file); int modify_inplace = 0; int message_mods = 0; int status = OK; /* Though the input file won't need to be opened if everything goes well, do it here just in case there's a failure, and that failure is running out of file descriptors. */ if ((*infp = fopen (input_filename, "r")) == NULL) { adios (input_filename, "unable to open for reading"); } if (outfile == NULL) { modify_inplace = 1; if ((*ctp)->c_file) { char *tempfile; /* outfp will be closed by the caller */ if ((tempfile = m_mktemp2 (NULL, invo_name, NULL, outfp)) == NULL) { adios (NULL, "unable to create temporary file in %s", get_temp_dir()); } outfile = mh_xstrdup (tempfile); } else { adios (NULL, "missing both input and output filenames\n"); } } /* else *outfp was defined by caller */ reverse_alternative_parts (*ctp); status = fix_always (*ctp, &message_mods); if (status == OK && fx->fixboundary) { status = fix_boundary (ctp, &message_mods); } if (status == OK && fx->fixtypes != NULL) { status = fix_types (*ctp, fx->fixtypes, &message_mods); } if (status == OK && fx->fixcompositecte) { status = fix_composite_cte (*ctp, &message_mods); } if (status == OK && fx->reformat) { status = ensure_text_plain (ctp, NULL, &message_mods, fx->replacetextplain); } if (status == OK && fx->decodetext) { status = decode_text_parts (*ctp, fx->decodetext, fx->decodetypes, &message_mods); update_cte (*ctp); } if (status == OK && fx->textcharset != NULL) { status = convert_charsets (*ctp, fx->textcharset, &message_mods); } if (status == OK && ! (*ctp)->c_umask) { /* Set the umask for the contents file. This currently isn't used but just in case it is in the future. */ struct stat st; if (stat ((*ctp)->c_file, &st) != NOTOK) { (*ctp)->c_umask = ~(st.st_mode & 0777); } else { (*ctp)->c_umask = ~m_gmprot(); } } /* * Write the content to a file */ if (status == OK) { status = write_content (*ctp, input_filename, outfile, *outfp, modify_inplace, message_mods); } else if (! modify_inplace) { /* Something went wrong. Output might be expected, such as if this were run as a filter. Just copy the input to the output. */ if (copy_input_to_output (input_filename, *infp, outfile, *outfp) != OK) { inform("unable to copy message to %s, it might be lost\n", outfile); } } if (modify_inplace) { if (status != OK) { (void) m_unlink (outfile); } free (outfile); outfile = NULL; } fclose (*infp); *infp = NULL; free (input_filename); return status; } /* * Copy input message to output. Assumes not modifying in place, so this * might be running as part of a pipeline. */ static int copy_input_to_output (const char *input_filename, FILE *infp, const char *output_filename, FILE *outfp) { int in = fileno (infp); int out = fileno (outfp); int status = OK; if (in != -1 && out != -1) { cpydata (in, out, input_filename, output_filename); } else { status = NOTOK; } return status; } /* * Fix mismatched outer level boundary. */ static int fix_boundary (CT *ct, int *message_mods) { struct multipart *mp; int status = OK; if (ct && (*ct)->c_type == CT_MULTIPART && bogus_mp_content) { mp = (struct multipart *) (*ct)->c_ctparams; /* * 1) Get boundary at end of part. * 2) Get boundary at beginning of part and compare to the end-of-part * boundary. * 3) Write out contents of ct to tmp file, replacing boundary in * header with boundary from part. Set c_unlink to 1. * 4) Free ct. * 5) Call parse_mime() on the tmp file, replacing ct. */ if (mp && mp->mp_start) { char *part_boundary; if (get_multipart_boundary (*ct, &part_boundary) == OK) { char *fixed; if ((fixed = m_mktemp2 (NULL, invo_name, NULL, &(*ct)->c_fp))) { if (replace_boundary (*ct, fixed, part_boundary) == OK) { char *filename = mh_xstrdup ((*ct)->c_file); CT fixed_ct; free_content (*ct); if ((fixed_ct = parse_mime (fixed))) { *ct = fixed_ct; (*ct)->c_unlink = 1; ++*message_mods; if (verbosw) { report (NULL, NULL, filename, "fix multipart boundary"); } } else { *ct = NULL; inform("unable to parse fixed part"); status = NOTOK; } free (filename); } else { inform("unable to replace broken boundary"); status = NOTOK; } } else { inform("unable to create temporary file in %s", get_temp_dir()); status = NOTOK; } free (part_boundary); } else { /* Couldn't fix the boundary. Report failure so that mhfixmsg doesn't modify the message. */ status = NOTOK; } } else { /* No multipart struct, even though the content type is CT_MULTIPART. Report failure so that mhfixmsg doesn't modify the message. */ status = NOTOK; } } return status; } /* * Find boundary at end of multipart. */ static int get_multipart_boundary (CT ct, char **part_boundary) { char buffer[NMH_BUFSIZ]; char *end_boundary = NULL; off_t begin = (off_t) ct->c_end > (off_t) (ct->c_begin + sizeof buffer) ? (off_t) (ct->c_end - sizeof buffer) : (off_t) ct->c_begin; size_t bytes_read; int status = OK; /* This will fail if the boundary spans fread() calls. NMH_BUFSIZ should be big enough, even if it's just 1024, to make that unlikely. */ /* free_content() will close ct->c_fp if bogus MP boundary is fixed. */ if (! ct->c_fp && (ct->c_fp = fopen (ct->c_file, "r")) == NULL) { advise (ct->c_file, "unable to open for reading"); return NOTOK; } /* Get boundary at end of multipart. */ while (begin >= (off_t) ct->c_begin) { fseeko (ct->c_fp, begin, SEEK_SET); while ((bytes_read = fread (buffer, 1, sizeof buffer, ct->c_fp)) > 0) { char *cp = rfind_str (buffer, bytes_read, "--"); if (cp) { char *end; /* Trim off trailing "--" and anything beyond. */ *cp-- = '\0'; if ((end = rfind_str (buffer, cp - buffer, "\n"))) { if (strlen (end) > 3 && *end++ == '\n' && *end++ == '-' && *end++ == '-') { end_boundary = mh_xstrdup (end); break; } } } } if (end_boundary || begin <= (off_t) (ct->c_begin + sizeof buffer)) break; begin -= sizeof buffer; } /* Get boundary at beginning of multipart. */ if (end_boundary) { fseeko (ct->c_fp, ct->c_begin, SEEK_SET); while ((bytes_read = fread (buffer, 1, sizeof buffer, ct->c_fp)) > 0) { if (bytes_read >= strlen (end_boundary)) { char *cp = find_str (buffer, bytes_read, end_boundary); if (cp && cp - buffer >= 2 && *--cp == '-' && *--cp == '-' && (cp > buffer && *--cp == '\n')) { status = OK; break; } } else { /* The start and end boundaries didn't match, or the start boundary doesn't begin with "\n--" (or "--" if at the beginning of buffer). Keep trying. */ status = NOTOK; } } } else { status = NOTOK; } if (ct->c_fp) { fclose (ct->c_fp); ct->c_fp = NULL; } if (status == OK) { *part_boundary = end_boundary; } else { *part_boundary = NULL; free (end_boundary); } return status; } /* * Open and copy ct->c_file to file, replacing the multipart boundary. */ static int replace_boundary (CT ct, char *file, char *boundary) { FILE *fpin, *fpout; int compnum, state; char buf[NMH_BUFSIZ], name[NAMESZ]; char *np, *vp; m_getfld_state_t gstate = 0; int status = OK; if (ct->c_file == NULL) { inform("missing input filename"); return NOTOK; } if ((fpin = fopen (ct->c_file, "r")) == NULL) { advise (ct->c_file, "unable to open for reading"); return NOTOK; } if ((fpout = fopen (file, "w")) == NULL) { fclose (fpin); advise (file, "unable to open for writing"); return NOTOK; } for (compnum = 1;;) { int bufsz = (int) sizeof buf; switch (state = m_getfld (&gstate, name, buf, &bufsz, fpin)) { case FLD: case FLDPLUS: compnum++; /* get copies of the buffers */ np = mh_xstrdup (name); vp = mh_xstrdup (buf); /* if necessary, get rest of field */ while (state == FLDPLUS) { bufsz = sizeof buf; state = m_getfld (&gstate, name, buf, &bufsz, fpin); vp = add (buf, vp); /* add to previous value */ } if (strcasecmp (TYPE_FIELD, np)) { fprintf (fpout, "%s:%s", np, vp); } else { char *new_ctline, *new_params; replace_param(&ct->c_ctinfo.ci_first_pm, &ct->c_ctinfo.ci_last_pm, "boundary", boundary, 0); new_ctline = concat(" ", ct->c_ctinfo.ci_type, "/", ct->c_ctinfo.ci_subtype, NULL); new_params = output_params(strlen(TYPE_FIELD) + strlen(new_ctline) + 1, ct->c_ctinfo.ci_first_pm, NULL, 0); fprintf (fpout, "%s:%s%s\n", np, new_ctline, FENDNULL(new_params)); free(new_ctline); mh_xfree(new_params); } free (vp); free (np); continue; case BODY: putc('\n', fpout); /* buf will have a terminating NULL, skip it. */ if ((int) fwrite (buf, 1, bufsz-1, fpout) < bufsz-1) { advise (file, "fwrite"); } continue; case FILEEOF: break; case LENERR: case FMTERR: inform("message format error in component #%d", compnum); status = NOTOK; break; default: inform("getfld() returned %d", state); status = NOTOK; break; } break; } m_getfld_state_destroy (&gstate); fclose (fpout); fclose (fpin); return status; } /* * Fix Content-Type header to reflect the content of its part. */ static int fix_types (CT ct, svector_t fixtypes, int *message_mods) { int status = OK; switch (ct->c_type) { case CT_MULTIPART: { struct multipart *m = (struct multipart *) ct->c_ctparams; struct part *part; for (part = m->mp_parts; status == OK && part; part = part->mp_next) { status = fix_types (part->mp_part, fixtypes, message_mods); } break; } case CT_MESSAGE: if (ct->c_subtype == MESSAGE_EXTERNAL) { struct exbody *e = (struct exbody *) ct->c_ctparams; status = fix_types (e->eb_content, fixtypes, message_mods); } break; default: { char **typep, *type; if (ct->c_ctinfo.ci_type && ct->c_ctinfo.ci_subtype) { for (typep = svector_strs (fixtypes); typep && (type = *typep); ++typep) { char *type_subtype = concat (ct->c_ctinfo.ci_type, "/", ct->c_ctinfo.ci_subtype, NULL); if (! strcasecmp (type, type_subtype) && decode_part (ct) == OK && ct->c_cefile.ce_file != NULL) { char *ct_type_subtype = mime_type (ct->c_cefile.ce_file); char *cp; if ((cp = strchr (ct_type_subtype, ';'))) { /* Truncate to remove any parameter list from mime_type () result. */ *cp = '\0'; } if (strcasecmp (type, ct_type_subtype)) { char *ct_type, *ct_subtype; HF hf; /* The Content-Type header does not match the content, so update these struct Content fields to match: * c_type, c_subtype * c_ctinfo.ci_type, c_ctinfo.ci_subtype * c_ctline */ /* Extract type and subtype from type/subtype. */ ct_type = mh_xstrdup(ct_type_subtype); if ((cp = strchr (ct_type, '/'))) { *cp = '\0'; ct_subtype = mh_xstrdup(++cp); } else { inform("missing / in MIME type of %s %s", ct->c_file, ct->c_partno); free (ct_type); return NOTOK; } ct->c_type = ct_str_type (ct_type); ct->c_subtype = ct_str_subtype (ct->c_type, ct_subtype); free (ct->c_ctinfo.ci_type); ct->c_ctinfo.ci_type = ct_type; free (ct->c_ctinfo.ci_subtype); ct->c_ctinfo.ci_subtype = ct_subtype; if (! replace_substring (&ct->c_ctline, type, ct_type_subtype)) { inform("did not find %s in %s", type, ct->c_ctline); } /* Update Content-Type header field. */ for (hf = ct->c_first_hf; hf; hf = hf->next) { if (! strcasecmp (TYPE_FIELD, hf->name)) { if (replace_substring (&hf->value, type, ct_type_subtype)) { ++*message_mods; if (verbosw) { report (NULL, ct->c_partno, ct->c_file, "change Content-Type in header " "from %s to %s", type, ct_type_subtype); } break; } inform("did not find %s in %s", type, hf->value); } } } free (ct_type_subtype); } free (type_subtype); } } }} return status; } /* * Replace a substring, allocating space to hold the new one. */ char * replace_substring (char **str, const char *old, const char *new) { char *cp; if ((cp = strstr (*str, old))) { char *remainder = cp + strlen (old); char *prefix, *new_str; if (cp - *str) { prefix = mh_xstrdup(*str); *(prefix + (cp - *str)) = '\0'; new_str = concat (prefix, new, remainder, NULL); free (prefix); } else { new_str = concat (new, remainder, NULL); } free (*str); return *str = new_str; } return NULL; } /* * Remove a name=value parameter, given just its name, from a header value. */ char * remove_parameter (char *str, const char *name) { /* It looks to me, based on the BNF in RFC 2045, than there can't be whitespace between the parameter name and the "=", or between the "=" and the parameter value. */ char *param_name = concat (name, "=", NULL); char *cp; if ((cp = strstr (str, param_name))) { char *start, *end; size_t count = 1; /* Remove any leading spaces, before the parameter name. */ for (start = cp; start > str && isspace ((unsigned char) *(start-1)); --start) { continue; } /* Remove a leading semicolon. */ if (start > str && *(start-1) == ';') { --start; } end = cp + strlen (name) + 1; if (*end == '"') { /* Skip past the quoted value, and then the final quote. */ for (++end ; *end && *end != '"'; ++end) { continue; } ++end; } else { /* Skip past the value. */ for (++end ; *end && ! isspace ((unsigned char) *end); ++end) {} } /* Count how many characters need to be moved. Include trailing null, which is accounted for by the initialization of count to 1. */ for (cp = end; *cp; ++cp) { ++count; } (void) memmove (start, end, count); } free (param_name); return str; } /* * Fix Content-Transfer-Encoding of composite,, e.g., message or multipart, part. * According to RFC 2045 Sec. 6.4, it must be 7bit, 8bit, or binary. Set it to * 8 bit. */ static int fix_composite_cte (CT ct, int *message_mods) { int status = OK; if (ct->c_type == CT_MESSAGE || ct->c_type == CT_MULTIPART) { if (ct->c_encoding != CE_7BIT && ct->c_encoding != CE_8BIT && ct->c_encoding != CE_BINARY) { HF hf; for (hf = ct->c_first_hf; hf; hf = hf->next) { char *name = hf->name; for (; *name && isspace ((unsigned char) *name); ++name) { continue; } if (! strncasecmp (name, ENCODING_FIELD, strlen (ENCODING_FIELD))) { char *prefix = "Nmh-REPLACED-INVALID-"; HF h; NEW(h); h->name = mh_xstrdup (hf->name); h->hf_encoding = hf->hf_encoding; h->next = hf->next; hf->next = h; /* Retain old header but prefix its name. */ free (hf->name); hf->name = concat (prefix, h->name, NULL); ++*message_mods; if (verbosw) { char *encoding = cpytrim (hf->value); report (NULL, ct->c_partno, ct->c_file, "replace Content-Transfer-Encoding of %s " "with 8 bit", encoding); free (encoding); } h->value = mh_xstrdup (" 8bit\n"); /* Don't need to warn for multiple C-T-E header fields, parse_mime() already does that. But if there are any, fix them all as necessary. */ hf = h; } } set_ce (ct, CE_8BIT); } if (ct->c_type == CT_MULTIPART) { struct multipart *m; struct part *part; m = (struct multipart *) ct->c_ctparams; for (part = m->mp_parts; part; part = part->mp_next) { if (fix_composite_cte (part->mp_part, message_mods) != OK) { status = NOTOK; break; } } } } return status; } /* * Set content encoding. */ static int set_ce (CT ct, int encoding) { const char *ce = ce_str (encoding); const struct str2init *ctinit = get_ce_method (ce); if (ctinit) { char *cte = concat (" ", ce, "\n", NULL); int found_cte = 0; HF hf; /* Decoded contents might be in ct->c_cefile.ce_file, if the caller is decode_text_parts (). Save because we'll overwrite below. */ struct cefile decoded_content_info = ct->c_cefile; ct->c_encoding = encoding; ct->c_ctinitfnx = ctinit->si_init; /* This will assign ct->c_cefile with an all-0 struct, which is what we want. */ (*ctinit->si_init) (ct); /* After returning, the caller should set ct->c_cefile.ce_file to the name of the file containing the contents. */ if (ct->c_ceclosefnx) { (*ct->c_ceclosefnx) (ct); } /* Restore the cefile. */ ct->c_cefile = decoded_content_info; /* Update/add Content-Transfer-Encoding header field. */ for (hf = ct->c_first_hf; hf; hf = hf->next) { if (! strcasecmp (ENCODING_FIELD, hf->name)) { found_cte = 1; free (hf->value); hf->value = cte; } } if (! found_cte) { add_header (ct, mh_xstrdup (ENCODING_FIELD), cte); } /* Update c_celine. It's used only by mhlist -debug. */ free (ct->c_celine); ct->c_celine = mh_xstrdup (cte); return OK; } return NOTOK; } /* * Make sure each text part has a corresponding text/plain part. */ static int ensure_text_plain (CT *ct, CT parent, int *message_mods, int replacetextplain) { int status = OK; switch ((*ct)->c_type) { case CT_TEXT: { /* Nothing to do for text/plain. */ if ((*ct)->c_subtype == TEXT_PLAIN) { return OK; } if (parent && parent->c_type == CT_MULTIPART && parent->c_subtype == MULTI_ALTERNATE) { int new_subpart_number = 1; int has_text_plain = find_textplain_sibling (parent, replacetextplain, &new_subpart_number); if (! has_text_plain) { /* Parent is a multipart/alternative. Insert a new text/plain subpart. */ const int inserted = insert_new_text_plain_part (*ct, new_subpart_number, parent); if (inserted) { ++*message_mods; if (verbosw) { report (NULL, parent->c_partno, parent->c_file, "insert text/plain part"); } } else { status = NOTOK; } } } else if (parent && parent->c_type == CT_MULTIPART && parent->c_subtype == MULTI_RELATED) { char *type_subtype = concat ((*ct)->c_ctinfo.ci_type, "/", (*ct)->c_ctinfo.ci_subtype, NULL); const char *parent_type = get_param (parent->c_ctinfo.ci_first_pm, "type", '?', 1); int new_subpart_number = 1; int has_text_plain = 0; /* Have to do string comparison on the subtype because we don't enumerate all of them in c_subtype values. parent_type will be NULL if the multipart/related part doesn't have a type parameter. The type parameter must be specified according to RFC 2387 Sec. 3.1 but not all messages comply. */ if (parent_type && strcasecmp (type_subtype, parent_type) == 0) { /* The type of this part matches the root type of the parent multipart/related. Look to see if there's text/plain sibling. */ has_text_plain = find_textplain_sibling (parent, replacetextplain, &new_subpart_number); } free (type_subtype); if (! has_text_plain) { struct multipart *mp = (struct multipart *) parent->c_ctparams; struct part *part; int siblings = 0; for (part = mp->mp_parts; part; part = part->mp_next) { if (*ct != part->mp_part) { ++siblings; } } if (siblings) { /* Parent is a multipart/related. Insert a new text/plain subpart in a new multipart/alternative. */ if (insert_into_new_mp_alt (ct, message_mods)) { /* Not an error if text/plain couldn't be added. */ } } else { /* There are no siblings, so insert a new text/plain subpart, and change the parent type from multipart/related to multipart/alternative. */ const int inserted = insert_new_text_plain_part (*ct, new_subpart_number, parent); if (inserted) { HF hf; parent->c_subtype = MULTI_ALTERNATE; free (parent->c_ctinfo.ci_subtype); parent->c_ctinfo.ci_subtype = mh_xstrdup("alternative"); if (! replace_substring (&parent->c_ctline, "/related", "/alternative")) { inform("did not find multipart/related in %s", parent->c_ctline); } /* Update Content-Type header field. */ for (hf = parent->c_first_hf; hf; hf = hf->next) { if (! strcasecmp (TYPE_FIELD, hf->name)) { if (replace_substring (&hf->value, "/related", "/alternative")) { ++*message_mods; if (verbosw) { report (NULL, parent->c_partno, parent->c_file, "insert text/plain part"); } /* Remove, e.g., type="text/html" from multipart/alternative. */ remove_parameter (hf->value, "type"); break; } inform("did not find multipart/" "related in header %s", hf->value); } } } else { /* Not an error if text/plain couldn't be inserted. */ } } } } else { if (insert_into_new_mp_alt (ct, message_mods)) { status = NOTOK; } } break; } case CT_MULTIPART: { struct multipart *mp = (struct multipart *) (*ct)->c_ctparams; struct part *part; for (part = mp->mp_parts; status == OK && part; part = part->mp_next) { if ((*ct)->c_type == CT_MULTIPART) { status = ensure_text_plain (&part->mp_part, *ct, message_mods, replacetextplain); } } break; } case CT_MESSAGE: if ((*ct)->c_subtype == MESSAGE_EXTERNAL) { struct exbody *e = (struct exbody *) (*ct)->c_ctparams; status = ensure_text_plain (&e->eb_content, *ct, message_mods, replacetextplain); } break; } return status; } /* * See if there is a sibling text/plain, and return its subpart number. */ static int find_textplain_sibling (CT parent, int replacetextplain, int *new_subpart_number) { struct multipart *mp = (struct multipart *) parent->c_ctparams; struct part *part, *prev; int has_text_plain = 0; for (prev = part = mp->mp_parts; part; part = part->mp_next) { ++*new_subpart_number; if (part->mp_part->c_type == CT_TEXT && part->mp_part->c_subtype == TEXT_PLAIN) { if (replacetextplain) { struct part *old_part; if (part == mp->mp_parts) { old_part = mp->mp_parts; mp->mp_parts = part->mp_next; } else { old_part = prev->mp_next; prev->mp_next = part->mp_next; } if (verbosw) { report (NULL, parent->c_partno, parent->c_file, "remove text/plain part %s", old_part->mp_part->c_partno); } free_content (old_part->mp_part); free (old_part); } else { has_text_plain = 1; } break; } prev = part; } return has_text_plain; } /* * Insert a new text/plain part. */ static int insert_new_text_plain_part (CT ct, int new_subpart_number, CT parent) { struct multipart *mp = (struct multipart *) parent->c_ctparams; struct part *new_part; NEW(new_part); if ((new_part->mp_part = build_text_plain_part (ct))) { char buffer[16]; snprintf (buffer, sizeof buffer, "%d", new_subpart_number); new_part->mp_next = mp->mp_parts; mp->mp_parts = new_part; new_part->mp_part->c_partno = concat (parent->c_partno ? parent->c_partno : "1", ".", buffer, NULL); return 1; } free_content (new_part->mp_part); free (new_part); return 0; } /* * Create a text/plain part to go along with non-plain sibling part. */ static CT build_text_plain_part (CT encoded_part) { CT tp_part = divide_part (encoded_part); char *tmp_plain_file = NULL; if (decode_part (tp_part) == OK) { /* Now, tp_part->c_cefile.ce_file is the name of the tmp file that contains the decoded contents. And the decoding function, such as openQuoted, will have set ...->ce_unlink to 1 so that it will be unlinked by free_content (). */ char *tempfile; /* This m_mktemp2() call closes the temp file. */ if ((tempfile = m_mktemp2 (NULL, invo_name, NULL, NULL)) == NULL) { inform("unable to create temporary file in %s", get_temp_dir()); } else { tmp_plain_file = mh_xstrdup (tempfile); if (reformat_part (tp_part, tmp_plain_file, tp_part->c_ctinfo.ci_type, tp_part->c_ctinfo.ci_subtype, tp_part->c_type) == OK) { return tp_part; } } } free_content (tp_part); if (tmp_plain_file) { (void) m_unlink (tmp_plain_file); } free (tmp_plain_file); return NULL; } /* * Slip new text/plain part into a new multipart/alternative. */ static int insert_into_new_mp_alt (CT *ct, int *message_mods) { CT tp_part = build_text_plain_part (*ct); int status = OK; if (tp_part) { CT mp_alt = build_multipart_alt (*ct, tp_part, CT_MULTIPART, MULTI_ALTERNATE); if (mp_alt) { struct multipart *mp = (struct multipart *) mp_alt->c_ctparams; if (mp && mp->mp_parts) { mp->mp_parts->mp_part = tp_part; /* Make the new multipart/alternative the parent. */ *ct = mp_alt; ++*message_mods; if (verbosw) { report (NULL, (*ct)->c_partno, (*ct)->c_file, "insert text/plain part"); } } else { free_content (tp_part); free_content (mp_alt); status = NOTOK; } } else { status = NOTOK; } } else { /* Not an error if text/plain couldn't be built. */ } return status; } /* * Clone a MIME part. */ static CT divide_part (CT ct) { CT new_part; NEW0(new_part); /* Just copy over what is needed for decoding. c_vrsn and c_celine aren't necessary. */ new_part->c_file = mh_xstrdup (ct->c_file); new_part->c_begin = ct->c_begin; new_part->c_end = ct->c_end; copy_ctinfo (&new_part->c_ctinfo, &ct->c_ctinfo); new_part->c_type = ct->c_type; new_part->c_cefile = ct->c_cefile; new_part->c_encoding = ct->c_encoding; new_part->c_ctinitfnx = ct->c_ctinitfnx; new_part->c_ceopenfnx = ct->c_ceopenfnx; new_part->c_ceclosefnx = ct->c_ceclosefnx; new_part->c_cesizefnx = ct->c_cesizefnx; /* c_ctline is used by reformat__part(), so it can preserve anything after the type/subtype. */ new_part->c_ctline = mh_xstrdup (ct->c_ctline); return new_part; } /* * Copy the content info from one part to another. */ static void copy_ctinfo (CI dest, CI src) { PM s_pm, d_pm; dest->ci_type = src->ci_type ? mh_xstrdup (src->ci_type) : NULL; dest->ci_subtype = src->ci_subtype ? mh_xstrdup (src->ci_subtype) : NULL; for (s_pm = src->ci_first_pm; s_pm; s_pm = s_pm->pm_next) { d_pm = add_param(&dest->ci_first_pm, &dest->ci_last_pm, s_pm->pm_name, s_pm->pm_value, 0); if (s_pm->pm_charset) { d_pm->pm_charset = mh_xstrdup(s_pm->pm_charset); } if (s_pm->pm_lang) { d_pm->pm_lang = mh_xstrdup(s_pm->pm_lang); } } dest->ci_comment = src->ci_comment ? mh_xstrdup (src->ci_comment) : NULL; dest->ci_magic = src->ci_magic ? mh_xstrdup (src->ci_magic) : NULL; } /* * Decode content. */ static int decode_part (CT ct) { char *tmp_decoded; int status; FILE *file; char *tempfile; if ((tempfile = m_mktemp2 (NULL, invo_name, NULL, &file)) == NULL) { adios (NULL, "unable to create temporary file in %s", get_temp_dir()); } tmp_decoded = mh_xstrdup (tempfile); /* The following call will load ct->c_cefile.ce_file with the tmp filename of the decoded content. tmp_decoded will contain the encoded output, get rid of that. */ status = output_message_fp (ct, file, tmp_decoded); (void) m_unlink (tmp_decoded); free (tmp_decoded); if (fclose (file)) { inform("unable to close temporary file %s, continuing...", tempfile); } return status; } /* * Reformat content as plain text. * Some of the arguments aren't really needed now, but maybe will * be in the future for other than text types. */ static int reformat_part (CT ct, char *file, char *type, char *subtype, int c_type) { int output_subtype, output_encoding; const char *reason = NULL; char *cp, *cf; int status; /* Hacky: this redirects the output from whatever command is used to show the part to a file. So, the user can't have any output redirection in that command. Could show_multi() in mhshowsbr.c avoid this? */ /* Check for invo_name-format-type/subtype. */ if ((cf = context_find_by_type ("format", type, subtype)) == NULL) { if (verbosw) { inform("Don't know how to convert %s, there is no " "%s-format-%s/%s profile entry", ct->c_file, invo_name, type, subtype); } return NOTOK; } if (strchr (cf, '>')) { inform("'>' prohibited in \"%s\",\nplease fix your " "%s-format-%s/%s profile entry", cf, invo_name, type, FENDNULL(subtype)); return NOTOK; } cp = concat (cf, " >", file, NULL); status = show_content_aux (ct, 0, cp, NULL, NULL); free (cp); /* Unlink decoded content tmp file and free its filename to avoid leaks. The file stream should already have been closed. */ if (ct->c_cefile.ce_unlink) { (void) m_unlink (ct->c_cefile.ce_file); free (ct->c_cefile.ce_file); ct->c_cefile.ce_file = NULL; ct->c_cefile.ce_unlink = 0; } if (c_type == CT_TEXT) { output_subtype = TEXT_PLAIN; } else { /* Set subtype to 0, which is always an UNKNOWN subtype. */ output_subtype = 0; } output_encoding = content_encoding (ct, &reason); if (status == OK && set_ct_type (ct, c_type, output_subtype, output_encoding) == OK) { ct->c_cefile.ce_file = file; ct->c_cefile.ce_unlink = 1; } else { ct->c_cefile.ce_unlink = 0; status = NOTOK; } return status; } /* * Fill in a multipart/alternative part. */ static CT build_multipart_alt (CT first_alt, CT new_part, int type, int subtype) { char *boundary_prefix = "----=_nmh-multipart"; char *boundary = concat (boundary_prefix, first_alt->c_partno, NULL); char *boundary_indicator = "; boundary="; char *typename, *subtypename, *name; CT ct; struct part *p; struct multipart *m; const struct str2init *ctinit; NEW0(ct); /* Set up the multipart/alternative part. These fields of *ct were initialized to 0 by mh_xcalloc(): c_fp, c_unlink, c_begin, c_end, c_vrsn, c_ctline, c_celine, c_id, c_descr, c_dispo, c_partno, c_ctinfo.ci_comment, c_ctinfo.ci_magic, c_cefile, c_encoding, c_digested, c_digest[16], c_ctexbody, c_ctinitfnx, c_ceopenfnx, c_ceclosefnx, c_cesizefnx, c_umask, c_rfc934, c_showproc, c_termproc, c_storeproc, c_storage, c_folder */ ct->c_file = mh_xstrdup (first_alt->c_file); ct->c_type = type; ct->c_subtype = subtype; ctinit = get_ct_init (ct->c_type); typename = ct_type_str (type); subtypename = ct_subtype_str (type, subtype); { int serial = 0; int found_boundary = 1; while (found_boundary && serial < 1000000) { found_boundary = 0; /* Ensure that the boundary doesn't appear in the decoded content. */ if (new_part->c_cefile.ce_file) { if ((found_boundary = boundary_in_content (&new_part->c_cefile.ce_fp, new_part->c_cefile.ce_file, boundary)) == NOTOK) { free_content (ct); return NULL; } } /* Ensure that the boundary doesn't appear in the encoded content. */ if (! found_boundary && new_part->c_file) { if ((found_boundary = boundary_in_content (&new_part->c_fp, new_part->c_file, boundary)) == NOTOK) { free_content (ct); return NULL; } } if (found_boundary) { /* Try a slightly different boundary. */ char buffer2[16]; free (boundary); ++serial; snprintf (buffer2, sizeof buffer2, "%d", serial); boundary = concat (boundary_prefix, FENDNULL(first_alt->c_partno), "-", buffer2, NULL); } } if (found_boundary) { inform("giving up trying to find a unique boundary"); free_content (ct); return NULL; } } name = concat (" ", typename, "/", subtypename, boundary_indicator, "\"", boundary, "\"", NULL); /* Load c_first_hf and c_last_hf. */ transfer_noncontent_headers (first_alt, ct); add_header (ct, mh_xstrdup (TYPE_FIELD), concat (name, "\n", NULL)); free (name); /* Load c_partno. */ if (first_alt->c_partno) { ct->c_partno = mh_xstrdup (first_alt->c_partno); free (first_alt->c_partno); first_alt->c_partno = concat (ct->c_partno, ".1", NULL); new_part->c_partno = concat (ct->c_partno, ".2", NULL); } else { first_alt->c_partno = mh_xstrdup ("1"); new_part->c_partno = mh_xstrdup ("2"); } if (ctinit) { ct->c_ctinfo.ci_type = mh_xstrdup (typename); ct->c_ctinfo.ci_subtype = mh_xstrdup (subtypename); } add_param(&ct->c_ctinfo.ci_first_pm, &ct->c_ctinfo.ci_last_pm, "boundary", boundary, 0); NEW(p); NEW(p->mp_next); p->mp_next->mp_next = NULL; p->mp_next->mp_part = first_alt; NEW0(m); m->mp_start = concat (boundary, "\n", NULL); m->mp_stop = concat (boundary, "--\n", NULL); m->mp_parts = p; ct->c_ctparams = m; free (boundary); return ct; } /* * Check that the boundary does not appear in the content. */ static int boundary_in_content (FILE **fp, char *file, const char *boundary) { char buffer[NMH_BUFSIZ]; size_t bytes_read; int found_boundary = 0; /* free_content() will close *fp if we fopen it here. */ if (! *fp && (*fp = fopen (file, "r")) == NULL) { advise (file, "unable to open %s for reading", file); return NOTOK; } fseeko (*fp, 0L, SEEK_SET); while ((bytes_read = fread (buffer, 1, sizeof buffer, *fp)) > 0) { if (find_str (buffer, bytes_read, boundary)) { found_boundary = 1; break; } } return found_boundary; } /* * Remove all non-Content headers. */ static void transfer_noncontent_headers (CT old, CT new) { HF hp, hp_prev; hp_prev = hp = old->c_first_hf; while (hp) { HF next = hp->next; if (strncasecmp (XXX_FIELD_PRF, hp->name, strlen (XXX_FIELD_PRF))) { if (hp == old->c_last_hf) { if (hp == old->c_first_hf) { old->c_last_hf = old->c_first_hf = NULL; } else { hp_prev->next = NULL; old->c_last_hf = hp_prev; } } else { if (hp == old->c_first_hf) { old->c_first_hf = next; } else { hp_prev->next = next; } } /* Put node hp in the new CT. */ if (new->c_first_hf == NULL) { new->c_first_hf = hp; } else { new->c_last_hf->next = hp; } new->c_last_hf = hp; } else { /* A Content- header, leave in old. */ hp_prev = hp; } hp = next; } } /* * Set content type. */ static int set_ct_type (CT ct, int type, int subtype, int encoding) { char *typename = ct_type_str (type); char *subtypename = ct_subtype_str (type, subtype); /* E.g, " text/plain" */ char *type_subtypename = concat (" ", typename, "/", subtypename, NULL); /* E.g, " text/plain\n" */ char *name_plus_nl = concat (type_subtypename, "\n", NULL); int found_content_type = 0; HF hf; const char *cp = NULL; char *ctline; int status; /* Update/add Content-Type header field. */ for (hf = ct->c_first_hf; hf; hf = hf->next) { if (! strcasecmp (TYPE_FIELD, hf->name)) { found_content_type = 1; free (hf->value); hf->value = (cp = strchr (ct->c_ctline, ';')) ? concat (type_subtypename, cp, "\n", NULL) : mh_xstrdup (name_plus_nl); } } if (! found_content_type) { add_header (ct, mh_xstrdup (TYPE_FIELD), (cp = strchr (ct->c_ctline, ';')) ? concat (type_subtypename, cp, "\n", NULL) : mh_xstrdup (name_plus_nl)); } /* Some of these might not be used, but set them anyway. */ ctline = cp ? concat (type_subtypename, cp, NULL) : concat (type_subtypename, NULL); free (ct->c_ctline); ct->c_ctline = ctline; /* Leave other ctinfo members as they were. */ free (ct->c_ctinfo.ci_type); ct->c_ctinfo.ci_type = mh_xstrdup (typename); free (ct->c_ctinfo.ci_subtype); ct->c_ctinfo.ci_subtype = mh_xstrdup (subtypename); ct->c_type = type; ct->c_subtype = subtype; free (name_plus_nl); free (type_subtypename); status = set_ce (ct, encoding); return status; } /* * It's not necessary to update the charset parameter of a Content-Type * header for a text part. According to RFC 2045 Sec. 6.4, the body * (content) was originally in the specified charset, "and will be in * that character set again after decoding." */ static int decode_text_parts (CT ct, int encoding, const char *decodetypes, int *message_mods) { int status = OK; int lf_line_endings = 0; switch (ct->c_type) { case CT_MULTIPART: { struct multipart *m = (struct multipart *) ct->c_ctparams; struct part *part; /* Should check to see if the body for this part is encoded? For now, it gets passed along as-is by InitMultiPart(). */ for (part = m->mp_parts; status == OK && part; part = part->mp_next) { status = decode_text_parts (part->mp_part, encoding, decodetypes, message_mods); } break; } case CT_MESSAGE: if (ct->c_subtype == MESSAGE_EXTERNAL) { struct exbody *e = (struct exbody *) ct->c_ctparams; status = decode_text_parts (e->eb_content, encoding, decodetypes, message_mods); } break; default: if (! should_decode(decodetypes, ct->c_ctinfo.ci_type, ct->c_ctinfo.ci_subtype)) { break; } lf_line_endings = ct->c_ctparams && ((struct text *) ct->c_ctparams)->lf_line_endings; switch (ct->c_encoding) { case CE_BASE64: case CE_QUOTED: { int ct_encoding; if (decode_part (ct) == OK && ct->c_cefile.ce_file) { const char *reason = NULL; if ((ct_encoding = content_encoding (ct, &reason)) == CE_BINARY && encoding != CE_BINARY) { /* The decoding isn't acceptable so discard it. Leave status as OK to allow other transformations. */ if (verbosw) { report (NULL, ct->c_partno, ct->c_file, "will not decode%s because it is binary (%s)", ct->c_partno ? "" : (FENDNULL(ct->c_ctline)), reason); } (void) m_unlink (ct->c_cefile.ce_file); free (ct->c_cefile.ce_file); ct->c_cefile.ce_file = NULL; } else if (ct->c_encoding == CE_QUOTED && ct_encoding == CE_8BIT && encoding == CE_7BIT) { /* The decoding isn't acceptable so discard it. Leave status as OK to allow other transformations. */ if (verbosw) { report (NULL, ct->c_partno, ct->c_file, "will not decode%s because it is 8bit", ct->c_partno ? "" : (FENDNULL(ct->c_ctline))); } (void) m_unlink (ct->c_cefile.ce_file); free (ct->c_cefile.ce_file); ct->c_cefile.ce_file = NULL; } else { int enc; if (ct_encoding == CE_BINARY) { enc = CE_BINARY; } else if (ct_encoding == CE_8BIT && encoding == CE_7BIT) { enc = CE_QUOTED; } else { enc = ct_encoding; } if (set_ce (ct, enc) == OK) { ++*message_mods; if (verbosw) { report (NULL, ct->c_partno, ct->c_file, "decode%s", FENDNULL(ct->c_ctline)); } if (lf_line_endings) { strip_crs (ct, message_mods); } } else { status = NOTOK; } } } else { status = NOTOK; } break; } case CE_8BIT: case CE_7BIT: if (lf_line_endings) { strip_crs (ct, message_mods); } break; default: break; } break; } return status; } /* * Determine if the part with type[/subtype] should be decoded, according to * decodetypes (which came from the -decodetypes switch). */ static int should_decode(const char *decodetypes, const char *type, const char *subtype) { /* Quick search for matching type[/subtype] in decodetypes: bracket decodetypes with commas, then search for ,type, and ,type/subtype, in it. */ int found_match = 0; char *delimited_decodetypes = concat(",", decodetypes, ",", NULL); char *delimited_type = concat(",", type, ",", NULL); if (nmh_strcasestr(delimited_decodetypes, delimited_type)) { found_match = 1; } else if (subtype != NULL) { char *delimited_type_subtype = concat(",", type, "/", subtype, ",", NULL); if (nmh_strcasestr(delimited_decodetypes, delimited_type_subtype)) { found_match = 1; } free(delimited_type_subtype); } free(delimited_type); free(delimited_decodetypes); return found_match; } /* * See if the decoded content is 7bit, 8bit, or binary. It's binary * if it has any NUL characters, a CR not followed by a LF, or lines * greater than 998 characters in length. If binary, reason is set * to a string explaining why. */ static int content_encoding (CT ct, const char **reason) { CE ce = &ct->c_cefile; int encoding = CE_7BIT; if (ce->ce_file) { size_t line_len = 0; char buffer[NMH_BUFSIZ]; size_t inbytes; if (! ce->ce_fp && (ce->ce_fp = fopen (ce->ce_file, "r")) == NULL) { advise (ce->ce_file, "unable to open for reading"); return CE_UNKNOWN; } fseeko (ce->ce_fp, 0L, SEEK_SET); while (encoding != CE_BINARY && (inbytes = fread (buffer, 1, sizeof buffer, ce->ce_fp)) > 0) { char *cp; size_t i; int last_char_was_cr = 0; for (i = 0, cp = buffer; i < inbytes; ++i, ++cp) { if (*cp == '\0' || ++line_len > 998 || (*cp != '\n' && last_char_was_cr)) { encoding = CE_BINARY; if (*cp == '\0') { *reason = "null character"; } else if (line_len > 998) { *reason = "line length > 998"; } else if (*cp != '\n' && last_char_was_cr) { *reason = "CR not followed by LF"; } else { /* Should not reach this. */ *reason = ""; } break; } if (*cp == '\n') { line_len = 0; } else if (! isascii ((unsigned char) *cp)) { encoding = CE_8BIT; } last_char_was_cr = *cp == '\r'; } } fclose (ce->ce_fp); ce->ce_fp = NULL; } /* else should never happen */ return encoding; } /* * Strip carriage returns from content. */ static int strip_crs (CT ct, int *message_mods) { char *charset = content_charset (ct); int status = OK; /* Only strip carriage returns if content is ASCII or another charset that has the same readily recognizable CR followed by a LF. We can include UTF-8 here because if the high-order bit of a UTF-8 byte is 0, then it must be a single-byte ASCII character. */ if (! strcasecmp (charset, "US-ASCII") || ! strcasecmp (charset, "UTF-8") || ! strncasecmp (charset, "ISO-8859-", 9) || ! strncasecmp (charset, "WINDOWS-12", 10)) { char **file = NULL; FILE **fp = NULL; size_t begin; size_t end; int has_crs = 0; int opened_input_file = 0; if (ct->c_cefile.ce_file) { file = &ct->c_cefile.ce_file; fp = &ct->c_cefile.ce_fp; begin = end = 0; } else if (ct->c_file) { file = &ct->c_file; fp = &ct->c_fp; begin = (size_t) ct->c_begin; end = (size_t) ct->c_end; } /* else don't know where the content is */ if (file && *file && fp) { if (! *fp) { if ((*fp = fopen (*file, "r")) == NULL) { advise (*file, "unable to open for reading"); status = NOTOK; } else { opened_input_file = 1; } } } if (fp && *fp) { char buffer[NMH_BUFSIZ]; size_t bytes_read; size_t bytes_to_read = end > 0 && end > begin ? end - begin : sizeof buffer; fseeko (*fp, begin, SEEK_SET); while ((bytes_read = fread (buffer, 1, min (bytes_to_read, sizeof buffer), *fp)) > 0) { /* Look for CR followed by a LF. This is supposed to be text so there should be LF's. If not, don't modify the content. */ char *cp; size_t i; int last_char_was_cr = 0; if (end > 0) { bytes_to_read -= bytes_read; } for (i = 0, cp = buffer; i < bytes_read; ++i, ++cp) { if (*cp == '\n' && last_char_was_cr) { has_crs = 1; break; } last_char_was_cr = *cp == '\r'; } } if (has_crs) { int fd; char *stripped_content_file; char *tempfile = m_mktemp2 (NULL, invo_name, &fd, NULL); if (tempfile == NULL) { adios (NULL, "unable to create temporary file in %s", get_temp_dir()); } stripped_content_file = mh_xstrdup (tempfile); /* Strip each CR before a LF from the content. */ fseeko (*fp, begin, SEEK_SET); while ((bytes_read = fread (buffer, 1, sizeof buffer, *fp)) > 0) { char *cp; size_t i; int last_char_was_cr = 0; for (i = 0, cp = buffer; i < bytes_read; ++i, ++cp) { if (*cp == '\r') { last_char_was_cr = 1; } else if (last_char_was_cr) { if (*cp != '\n') { if (write (fd, "\r", 1) < 0) { advise (tempfile, "CR write"); } } if (write (fd, cp, 1) < 0) { advise (tempfile, "write"); } last_char_was_cr = 0; } else { if (write (fd, cp, 1) < 0) { advise (tempfile, "write"); } last_char_was_cr = 0; } } } if (close (fd)) { inform("unable to write temporary file %s, continuing...", stripped_content_file); (void) m_unlink (stripped_content_file); status = NOTOK; } else { /* Replace the decoded file with the converted one. */ if (ct->c_cefile.ce_file && ct->c_cefile.ce_unlink) (void) m_unlink (ct->c_cefile.ce_file); mh_xfree(ct->c_cefile.ce_file); ct->c_cefile.ce_file = stripped_content_file; ct->c_cefile.ce_unlink = 1; ++*message_mods; if (verbosw) { report (NULL, ct->c_partno, begin == 0 && end == 0 ? "" : *file, "stripped CRs"); } } } if (opened_input_file) { fclose (*fp); *fp = NULL; } } } free (charset); return status; } /* * Add/update, if necessary, the message C-T-E, based on the least restrictive * of the part C-T-E's. */ static void update_cte (CT ct) { const int least_restrictive_enc = least_restrictive_encoding (ct); if (least_restrictive_enc != CE_UNKNOWN && least_restrictive_enc != CE_7BIT) { char *cte = concat (" ", ce_str (least_restrictive_enc), "\n", NULL); HF hf; int found_cte = 0; /* Update/add Content-Transfer-Encoding header field. */ for (hf = ct->c_first_hf; hf; hf = hf->next) { if (! strcasecmp (ENCODING_FIELD, hf->name)) { found_cte = 1; free (hf->value); hf->value = cte; } } if (! found_cte) { add_header (ct, mh_xstrdup (ENCODING_FIELD), cte); } } } /* * Find the least restrictive encoding (7bit, 8bit, binary) of the parts * within a message. */ static int least_restrictive_encoding (CT ct) { int encoding = CE_UNKNOWN; switch (ct->c_type) { case CT_MULTIPART: { struct multipart *m = (struct multipart *) ct->c_ctparams; struct part *part; for (part = m->mp_parts; part; part = part->mp_next) { const int part_encoding = least_restrictive_encoding (part->mp_part); if (less_restrictive (encoding, part_encoding)) { encoding = part_encoding; } } break; } case CT_MESSAGE: if (ct->c_subtype == MESSAGE_EXTERNAL) { struct exbody *e = (struct exbody *) ct->c_ctparams; const int part_encoding = least_restrictive_encoding (e->eb_content); if (less_restrictive (encoding, part_encoding)) { encoding = part_encoding; } } break; default: { if (less_restrictive (encoding, ct->c_encoding)) { encoding = ct->c_encoding; } }} return encoding; } /* * Return whether the second encoding is less restrictive than the first, where * "less restrictive" is in the sense used by RFC 2045 Secs. 6.1 and 6.4. So, * CE_BINARY is less restrictive than CE_8BIT and * CE_8BIT is less restrictive than CE_7BIT. */ static int less_restrictive (int encoding, int second_encoding) { switch (second_encoding) { case CE_BINARY: return encoding != CE_BINARY; case CE_8BIT: return encoding != CE_BINARY && encoding != CE_8BIT; case CE_7BIT: return encoding != CE_BINARY && encoding != CE_8BIT && encoding != CE_7BIT; default : return 0; } } /* * Convert character set of each part. */ static int convert_charsets (CT ct, char *dest_charset, int *message_mods) { int status = OK; switch (ct->c_type) { case CT_TEXT: if (ct->c_subtype == TEXT_PLAIN) { status = convert_charset (ct, dest_charset, message_mods); if (status == OK) { if (verbosw) { char *ct_charset = content_charset (ct); report (NULL, ct->c_partno, ct->c_file, "convert %s to %s", ct_charset, dest_charset); free (ct_charset); } } else { char *ct_charset = content_charset (ct); report ("iconv", ct->c_partno, ct->c_file, "failed to convert %s to %s", ct_charset, dest_charset); free (ct_charset); } } break; case CT_MULTIPART: { struct multipart *m = (struct multipart *) ct->c_ctparams; struct part *part; /* Should check to see if the body for this part is encoded? For now, it gets passed along as-is by InitMultiPart(). */ for (part = m->mp_parts; status == OK && part; part = part->mp_next) { status = convert_charsets (part->mp_part, dest_charset, message_mods); } break; } case CT_MESSAGE: if (ct->c_subtype == MESSAGE_EXTERNAL) { struct exbody *e = (struct exbody *) ct->c_ctparams; status = convert_charsets (e->eb_content, dest_charset, message_mods); } break; default: break; } return status; } /* * Fix various problems that aren't handled elsewhere. These * are fixed unconditionally: there are no switches to disable * them. Currently, "problems" are these: * 1) remove extraneous semicolon at the end of a header parameter list * 2) replace RFC 2047 encoding with RFC 2231 encoding of name and * filename parameters in Content-Type and Content-Disposition * headers, respectively. */ static int fix_always (CT ct, int *message_mods) { int status = OK; switch (ct->c_type) { case CT_MULTIPART: { struct multipart *m = (struct multipart *) ct->c_ctparams; struct part *part; for (part = m->mp_parts; status == OK && part; part = part->mp_next) { status = fix_always (part->mp_part, message_mods); } break; } case CT_MESSAGE: if (ct->c_subtype == MESSAGE_EXTERNAL) { struct exbody *e = (struct exbody *) ct->c_ctparams; status = fix_always (e->eb_content, message_mods); } break; default: { HF hf; if (ct->c_first_hf) { fix_filename_encoding (ct); } for (hf = ct->c_first_hf; hf; hf = hf->next) { size_t len = strlen (hf->value); if (strcasecmp (hf->name, TYPE_FIELD) != 0 && strcasecmp (hf->name, DISPO_FIELD) != 0) { /* Only do this for Content-Type and Content-Disposition fields because those are the only headers that parse_mime() warns about. */ continue; } /* whitespace following a trailing ';' will be nuked as well */ if (hf->value[len - 1] == '\n') { while (isspace((unsigned char)(hf->value[len - 2]))) { if (len-- == 0) { break; } } } if (hf->value[len - 2] == ';') { /* Remove trailing ';' from parameter value. */ hf->value[len - 2] = '\n'; hf->value[len - 1] = '\0'; /* Also, if Content-Type parameter, remove trailing ';' from ct->c_ctline. This probably isn't necessary but can't hurt. */ if (strcasecmp(hf->name, TYPE_FIELD) == 0 && ct->c_ctline) { size_t l = strlen(ct->c_ctline) - 1; while (isspace((unsigned char)(ct->c_ctline[l])) || ct->c_ctline[l] == ';') { ct->c_ctline[l--] = '\0'; if (l == 0) { break; } } } ++*message_mods; if (verbosw) { report (NULL, ct->c_partno, ct->c_file, "remove trailing ; from %s parameter value", hf->name); } } } }} return status; } /* * Factor out common code for loops in fix_filename_encoding(). */ static int fix_filename_param (char *name, char *value, PM *first_pm, PM *last_pm) { int fixed = 0; if (has_prefix(value, "=?") && has_suffix(value, "?=")) { /* Looks like an RFC 2047 encoded parameter. */ char decoded[PATH_MAX + 1]; if (decode_rfc2047 (value, decoded, sizeof decoded)) { /* Encode using RFC 2231. */ replace_param (first_pm, last_pm, name, decoded, 0); fixed = 1; } else { inform("failed to decode %s parameter %s", name, value); } } return fixed; } /* * Replace RFC 2047 encoding with RFC 2231 encoding of name and * filename parameters in Content-Type and Content-Disposition * headers, respectively. */ static int fix_filename_encoding (CT ct) { PM pm; HF hf; int fixed = 0; for (pm = ct->c_ctinfo.ci_first_pm; pm; pm = pm->pm_next) { if (pm->pm_name && pm->pm_value && strcasecmp (pm->pm_name, "name") == 0) { fixed = fix_filename_param (pm->pm_name, pm->pm_value, &ct->c_ctinfo.ci_first_pm, &ct->c_ctinfo.ci_last_pm); } } for (pm = ct->c_dispo_first; pm; pm = pm->pm_next) { if (pm->pm_name && pm->pm_value && strcasecmp (pm->pm_name, "filename") == 0) { fixed = fix_filename_param (pm->pm_name, pm->pm_value, &ct->c_dispo_first, &ct->c_dispo_last); } } /* Fix hf values to correspond. */ for (hf = ct->c_first_hf; fixed && hf; hf = hf->next) { enum { OTHER, TYPE_HEADER, DISPO_HEADER } field = OTHER; if (strcasecmp (hf->name, TYPE_FIELD) == 0) { field = TYPE_HEADER; } else if (strcasecmp (hf->name, DISPO_FIELD) == 0) { field = DISPO_HEADER; } if (field != OTHER) { const char *const semicolon_loc = strchr (hf->value, ';'); if (semicolon_loc) { const size_t len = strlen (hf->name) + 1 + semicolon_loc - hf->value; const char *const params = output_params (len, field == TYPE_HEADER ? ct->c_ctinfo.ci_first_pm : ct->c_dispo_first, NULL, 0); const char *const new_params = concat (params, "\n", NULL); replace_substring (&hf->value, semicolon_loc, new_params); free((void *)new_params); /* Cast away const. Sigh. */ free((void *)params); } else { inform("did not find semicolon in %s:%s\n", hf->name, hf->value); } } } return OK; } /* * Output content in input file to output file. */ static int write_content (CT ct, const char *input_filename, char *outfile, FILE *outfp, int modify_inplace, int message_mods) { int status = OK; if (modify_inplace) { if (message_mods > 0) { if ((status = output_message_fp (ct, outfp, outfile)) == OK) { char *infile = input_filename ? mh_xstrdup (input_filename) : mh_xstrdup (ct->c_file ? ct->c_file : "-"); if (remove_file (infile) == OK) { if (rename (outfile, infile)) { /* Rename didn't work, possibly because of an attempt to rename across filesystems. Try brute force copy. */ int old = open (outfile, O_RDONLY); int new = open (infile, O_WRONLY | O_CREAT, m_gmprot ()); int i = -1; if (old != -1 && new != -1) { char buffer[NMH_BUFSIZ]; while ((i = read (old, buffer, sizeof buffer)) > 0) { if (write (new, buffer, i) != i) { i = -1; break; } } } if (new != -1) { close (new); } if (old != -1) { close (old); } (void) m_unlink (outfile); if (i < 0) { /* The -file argument processing used path() to expand filename to absolute path. */ int file = ct->c_file && ct->c_file[0] == '/'; inform("unable to rename %s %s to %s, continuing...", file ? "file" : "message", outfile, infile); status = NOTOK; } } } else { inform("unable to remove input file %s, " "not modifying it, continuing...", infile); (void) m_unlink (outfile); status = NOTOK; } free (infile); } else { status = NOTOK; } } else { /* No modifications and didn't need the tmp outfile. */ (void) m_unlink (outfile); } } else { /* Output is going to some file. Produce it whether or not there were modifications. */ status = output_message_fp (ct, outfp, outfile); } flush_errors (); return status; } /* * parse_mime() does not set lf_line_endings in struct text, so use this * function to do it. It touches the parts the decodetypes identifies. */ static void set_text_ctparams(CT ct, char *decodetypes, int lf_line_endings) { switch (ct->c_type) { case CT_MULTIPART: { struct multipart *m = (struct multipart *) ct->c_ctparams; struct part *part; for (part = m->mp_parts; part; part = part->mp_next) { set_text_ctparams(part->mp_part, decodetypes, lf_line_endings); } break; } case CT_MESSAGE: if (ct->c_subtype == MESSAGE_EXTERNAL) { struct exbody *e = (struct exbody *) ct->c_ctparams; set_text_ctparams(e->eb_content, decodetypes, lf_line_endings); } break; default: if (should_decode(decodetypes, ct->c_ctinfo.ci_type, ct->c_ctinfo.ci_subtype)) { if (ct->c_ctparams == NULL) { ct->c_ctparams = mh_xcalloc(1, sizeof (struct text)); } ((struct text *) ct->c_ctparams)->lf_line_endings = lf_line_endings; } } } /* * If "rmmproc" is defined, call that to remove the file. Otherwise, * use the standard MH backup file. */ static int remove_file (const char *file) { if (rmmproc) { char *rmm_command = concat (rmmproc, " ", file, NULL); int status = system (rmm_command); free (rmm_command); return WIFEXITED (status) ? WEXITSTATUS (status) : NOTOK; } /* This is OK for a non-message file, it still uses the BACKUP_PREFIX form. The backup file will be in the same directory as file. */ return rename (file, m_backup (file)); } /* * Output formatted message to user. */ static void report (char *what, char *partno, char *filename, char *message, ...) { va_list args; char *fmt; if (verbosw) { va_start (args, message); fmt = concat (filename, partno ? " part " : ", ", FENDNULL(partno), partno ? ", " : "", message, NULL); advertise (what, NULL, fmt, args); free (fmt); va_end (args); } } static void pipeser (int i) { if (i == SIGQUIT) { fflush (stdout); fprintf (stderr, "\n"); fflush (stderr); } done (1); /* NOTREACHED */ } nmh-1.7.1-RC3/uip/mhfree.c000644 007761 000024 00000011434 13243042054 015171 0ustar00kenhstaff000000 000000 /* mhfree.c -- routines to free the data structures used to * -- represent MIME messages * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include "../sbr/m_mktemp.h" #include "mhfree.h" /* The list of top-level contents to display */ CT *cts = NULL; /* * static prototypes */ static void free_header (CT); static void free_text (CT); static void free_multi (CT); static void free_partial (CT); static void free_external (CT); static void free_pmlist (PM *); /* * Primary routine to free a MIME content structure */ void free_content (CT ct) { if (!ct) return; /* * free all the header fields */ free_header (ct); mh_xfree(ct->c_partno); mh_xfree(ct->c_vrsn); mh_xfree(ct->c_ctline); ct->c_partno = ct->c_vrsn = ct->c_ctline = NULL; free_ctinfo (ct); /* * some of the content types have extra * parts which need to be freed. */ switch (ct->c_type) { case CT_MULTIPART: free_multi (ct); break; case CT_MESSAGE: switch (ct->c_subtype) { case MESSAGE_PARTIAL: free_partial (ct); break; case MESSAGE_EXTERNAL: free_external (ct); break; } break; default: /* Assume that the ct is for text. mhfixmsg(1) uses it for decoding application content. */ free_text (ct); break; } mh_xfree(ct->c_showproc); mh_xfree(ct->c_termproc); mh_xfree(ct->c_storeproc); ct->c_showproc = ct->c_termproc = ct->c_storeproc = NULL; mh_xfree(ct->c_celine); ct->c_celine = NULL; /* free structures for content encodings */ free_encoding (ct, 1); mh_xfree(ct->c_id); mh_xfree(ct->c_descr); mh_xfree(ct->c_dispo); mh_xfree(ct->c_dispo_type); ct->c_id = ct->c_descr = ct->c_dispo = ct->c_dispo_type = NULL; free_pmlist (&ct->c_dispo_first); if (ct->c_file) { if (ct->c_unlink) (void) m_unlink (ct->c_file); free (ct->c_file); ct->c_file = NULL; } if (ct->c_fp) { fclose (ct->c_fp); ct->c_fp = NULL; } mh_xfree(ct->c_storage); mh_xfree(ct->c_folder); ct->c_storage = ct->c_folder = NULL; free (ct); } /* * Free the linked list of header fields * for this content. */ static void free_header (CT ct) { HF hp1, hp2; hp1 = ct->c_first_hf; while (hp1) { hp2 = hp1->next; free (hp1->name); free (hp1->value); free (hp1); hp1 = hp2; } ct->c_first_hf = NULL; ct->c_last_hf = NULL; } void free_ctinfo (CT ct) { CI ci; ci = &ct->c_ctinfo; mh_xfree(ci->ci_type); mh_xfree(ci->ci_subtype); ci->ci_type = ci->ci_subtype = NULL; free_pmlist(&ci->ci_first_pm); mh_xfree(ci->ci_comment); mh_xfree(ci->ci_magic); ci->ci_comment = ci->ci_magic = NULL; } static void free_text (CT ct) { struct text *t; if (!(t = (struct text *) ct->c_ctparams)) return; free(t); ct->c_ctparams = NULL; } static void free_multi (CT ct) { struct multipart *m; struct part *part, *next; if (!(m = (struct multipart *) ct->c_ctparams)) return; mh_xfree(m->mp_start); mh_xfree(m->mp_stop); free (m->mp_content_before); free (m->mp_content_after); for (part = m->mp_parts; part; part = next) { next = part->mp_next; free_content (part->mp_part); free(part); } m->mp_parts = NULL; free(m); ct->c_ctparams = NULL; } static void free_partial (CT ct) { struct partial *p; if (!(p = (struct partial *) ct->c_ctparams)) return; mh_xfree(p->pm_partid); free(p); ct->c_ctparams = NULL; } static void free_external (CT ct) { struct exbody *e; if (!(e = (struct exbody *) ct->c_ctparams)) return; free_content (e->eb_content); mh_xfree(e->eb_body); mh_xfree(e->eb_url); free(e); ct->c_ctparams = NULL; } static void free_pmlist (PM *p) { PM pm = *p, pm2; while (pm != NULL) { mh_xfree(pm->pm_name); mh_xfree(pm->pm_value); mh_xfree(pm->pm_charset); mh_xfree(pm->pm_lang); pm2 = pm->pm_next; free(pm); pm = pm2; } if (*p) *p = NULL; } /* * Free data structures related to encoding/decoding * Content-Transfer-Encodings. */ void free_encoding (CT ct, int toplevel) { CE ce = &ct->c_cefile; if (ce->ce_fp) { fclose (ce->ce_fp); ce->ce_fp = NULL; } if (ce->ce_file) { if (ce->ce_unlink) (void) m_unlink (ce->ce_file); free (ce->ce_file); ce->ce_file = NULL; } if (! toplevel) { ct->c_ceopenfnx = NULL; } } void NORETURN freects_done (int status) { CT *ctp; for (ctp = cts; ctp && *ctp; ctp++) free_content (*ctp); free (cts); exit (status); } nmh-1.7.1-RC3/uip/mhfree.h000644 007761 000024 00000000560 13205305706 015200 0ustar00kenhstaff000000 000000 /* mhfree.h -- routines to free MIME-message data structures. * * This code is Copyright (c) 2017, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ void free_content(CT ct); void free_ctinfo(CT); void free_encoding(CT, int); void freects_done(int) NORETURN; extern CT *cts; nmh-1.7.1-RC3/uip/mhical.c000644 007761 000024 00000063350 13243042054 015164 0ustar00kenhstaff000000 000000 /* mhical.c -- operate on an iCalendar request * * This code is Copyright (c) 2014, 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/icalendar.h" #include "sbr/icalparse.h" #include #include "h/addrsbr.h" #include "h/mts.h" #include "h/utils.h" #include typedef enum act { ACT_NONE, ACT_ACCEPT, ACE_DECLINE, ACT_TENTATIVE, ACT_DELEGATE, ACT_CANCEL } act; static void convert_to_reply (contentline *, act); static void convert_to_cancellation (contentline *); static void convert_common (contentline *, act); static void dump_unfolded (FILE *, contentline *); static void output (FILE *, contentline *, int); static void display (FILE *, contentline *, char *); static const char *identity (const contentline *); static char *format_params (char *, param_list *); static char *fold (char *, int); #define MHICAL_SWITCHES \ X("reply accept|decline|tentative", 0, REPLYSW) \ X("cancel", 0, CANCELSW) \ X("form formatfile", 0, FORMSW) \ X("format string", 5, FMTSW) \ X("infile", 0, INFILESW) \ X("outfile", 0, OUTFILESW) \ X("contenttype", 0, CONTENTTYPESW) \ X("nocontenttype", 0, NCONTENTTYPESW) \ X("unfold", 0, UNFOLDSW) \ X("debug", 0, DEBUGSW) \ X("version", 0, VERSIONSW) \ X("help", 0, HELPSW) \ #define X(sw, minchars, id) id, DEFINE_SWITCH_ENUM(MHICAL); #undef X #define X(sw, minchars, id) { sw, minchars, id }, DEFINE_SWITCH_ARRAY(MHICAL, switches); #undef X vevent vevents = { NULL, NULL, NULL}; int parser_status = 0; int main (int argc, char *argv[]) { /* RFC 5322 § 3.3 date-time format, including the optional day-of-week and not including the optional seconds. The zone is required by the RFC but not always output by this format, because RFC 5545 § 3.3.5 allows date-times not bound to any time zone. */ act action = ACT_NONE; char *infile = NULL, *outfile = NULL; FILE *inputfile = NULL, *outputfile = NULL; int contenttype = 0, unfold = 0; vevent *v, *nextvevent; char *form = "mhical.24hour", *format = NULL; char **argp, **arguments, *cp; icaldebug = 0; /* Global provided by bison (with name-prefix "ical"). */ if (nmh_init(argv[0], 2)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; /* * Parse arguments */ while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: { char buf[128]; snprintf (buf, sizeof buf, "%s [switches]", invo_name); print_help (buf, switches, 1); done (0); } case VERSIONSW: print_version(invo_name); done (0); case DEBUGSW: icaldebug = 1; continue; case REPLYSW: if (! (cp = *argp++) || (*cp == '-' && cp[1])) adios (NULL, "missing argument to %s", argp[-2]); if (! strcasecmp (cp, "accept")) { action = ACT_ACCEPT; } else if (! strcasecmp (cp, "decline")) { action = ACE_DECLINE; } else if (! strcasecmp (cp, "tentative")) { action = ACT_TENTATIVE; } else if (! strcasecmp (cp, "delegate")) { action = ACT_DELEGATE; } else { adios (NULL, "Unknown action: %s", cp); } continue; case CANCELSW: action = ACT_CANCEL; continue; case FORMSW: if (! (form = *argp++) || *form == '-') adios (NULL, "missing argument to %s", argp[-2]); format = NULL; continue; case FMTSW: if (! (format = *argp++) || *format == '-') adios (NULL, "missing argument to %s", argp[-2]); form = NULL; continue; case INFILESW: if (! (cp = *argp++) || (*cp == '-' && cp[1])) adios (NULL, "missing argument to %s", argp[-2]); infile = *cp == '-' ? mh_xstrdup(cp) : path (cp, TFILE); continue; case OUTFILESW: if (! (cp = *argp++) || (*cp == '-' && cp[1])) adios (NULL, "missing argument to %s", argp[-2]); outfile = *cp == '-' ? mh_xstrdup(cp) : path (cp, TFILE); continue; case CONTENTTYPESW: contenttype = 1; continue; case NCONTENTTYPESW: contenttype = 0; continue; case UNFOLDSW: unfold = 1; continue; } } } free (arguments); if (infile) { if ((inputfile = fopen (infile, "r"))) { icalset_inputfile (inputfile); } else { adios (infile, "error opening"); } } else { inputfile = stdin; } if (outfile) { if ((outputfile = fopen (outfile, "w"))) { icalset_outputfile (outputfile); } else { adios (outfile, "error opening"); } } else { outputfile = stdout; } vevents.last = &vevents; /* vevents is accessed by parser as global. */ icalparse (); for (v = &vevents; v; v = nextvevent) { if (! unfold && v != &vevents && v->contentlines && v->contentlines->name && strcasecmp (v->contentlines->name, "END") && v->contentlines->value && strcasecmp (v->contentlines->value, "VCALENDAR")) { /* Output blank line between vevents. Not before first vevent and not after last. */ putc ('\n', outputfile); } if (action == ACT_NONE) { if (unfold) { dump_unfolded (outputfile, v->contentlines); } else { char *nfs = new_fs (form, format, NULL); display (outputfile, v->contentlines, nfs); free_fs (); } } else { if (action == ACT_CANCEL) { convert_to_cancellation (v->contentlines); } else { convert_to_reply (v->contentlines, action); } output (outputfile, v->contentlines, contenttype); } free_contentlines (v->contentlines); nextvevent = v->next; if (v != &vevents) { free (v); } } if (infile) { if (fclose (inputfile) != 0) { advise (infile, "error closing"); } free (infile); } if (outfile) { if (fclose (outputfile) != 0) { advise (outfile, "error closing"); } free (outfile); } return parser_status; } /* * - Change METHOD from REQUEST to REPLY. * - Change PRODID. * - Remove all ATTENDEE lines for other users (based on ismymbox ()). * - For the user's ATTENDEE line: * - Remove ROLE and RSVP parameters. * - Change PARTSTAT value to indicate reply action, e.g., ACCEPTED, * DECLINED, or TENTATIVE. * - Insert action at beginning of SUMMARY value. * - Remove all X- lines. * - Update DTSTAMP with current timestamp. * - Remove all DESCRIPTION lines. * - Excise VALARM sections. */ static void convert_to_reply (contentline *clines, act action) { char *partstat = NULL; int found_my_attendee_line = 0; contentline *node; convert_common (clines, action); switch (action) { case ACT_ACCEPT: partstat = "ACCEPTED"; break; case ACE_DECLINE: partstat = "DECLINED"; break; case ACT_TENTATIVE: partstat = "TENTATIVE"; break; default: ; } /* Call find_contentline () with node as argument to find multiple matching contentlines. */ for (node = clines; (node = find_contentline (node, "ATTENDEE", 0)); node = node->next) { param_list *p; ismymbox (NULL); /* need to prime ismymbox() */ /* According to RFC 5545 § 3.3.3, an email address in the value must be a mailto URI. */ if (! strncasecmp (node->value, "mailto:", 7)) { char *addr = node->value + 7; struct mailname *mn; /* Skip any leading whitespace. */ for ( ; isspace ((unsigned char) *addr); ++addr) { continue; } addr = getname (addr); mn = getm (addr, NULL, 0, NULL, 0); /* Need to flush getname after use. */ while (getname ("")) { continue; } if (ismymbox (mn)) { found_my_attendee_line = 1; for (p = node->params; p && p->param_name; p = p->next) { value_list *v; for (v = p->values; v; v = v->next) { if (! strcasecmp (p->param_name, "ROLE") || ! strcasecmp (p->param_name, "RSVP")) { remove_value (v); } else if (! strcasecmp (p->param_name, "PARTSTAT")) { free (v->value); v->value = strdup (partstat); } } } } else { remove_contentline (node); } mnfree (mn); } } if (! found_my_attendee_line) { /* Generate and attach an ATTENDEE line for me. */ contentline *node; /* Add it after the ORGANIZER line, or if none, BEGIN:VEVENT line. */ if ((node = find_contentline (clines, "ORGANIZER", 0)) || (node = find_contentline (clines, "BEGIN", "VEVENT"))) { contentline *new_node = add_contentline (node, "ATTENDEE"); add_param_name (new_node, mh_xstrdup ("PARTSTAT")); add_param_value (new_node, mh_xstrdup (partstat)); add_param_name (new_node, mh_xstrdup ("CN")); add_param_value (new_node, mh_xstrdup (getfullname ())); new_node->value = concat ("MAILTO:", getlocalmbox (), NULL); } } /* Call find_contentline () with node as argument to find multiple matching contentlines. */ for (node = clines; (node = find_contentline (node, "DESCRIPTION", 0)); node = node->next) { /* ACCEPT, at least, replies don't seem to have DESCRIPTIONS. */ remove_contentline (node); } } /* * - Change METHOD from REQUEST to CANCEL. * - Change PRODID. * - Insert action at beginning of SUMMARY value. * - Remove all X- lines. * - Update DTSTAMP with current timestamp. * - Change STATUS from CONFIRMED to CANCELLED. * - Increment value of SEQUENCE. * - Excise VALARM sections. */ static void convert_to_cancellation (contentline *clines) { contentline *node; convert_common (clines, ACT_CANCEL); if ((node = find_contentline (clines, "STATUS", 0)) && ! strcasecmp (node->value, "CONFIRMED")) { free (node->value); node->value = mh_xstrdup ("CANCELLED"); } if ((node = find_contentline (clines, "SEQUENCE", 0))) { int sequence = atoi (node->value); char buf[32]; (void) snprintf (buf, sizeof buf, "%d", sequence + 1); free (node->value); node->value = mh_xstrdup (buf); } } static void convert_common (contentline *clines, act action) { contentline *node; int in_valarm; if ((node = find_contentline (clines, "METHOD", 0))) { free (node->value); node->value = mh_xstrdup (action == ACT_CANCEL ? "CANCEL" : "REPLY"); } if ((node = find_contentline (clines, "PRODID", 0))) { free (node->value); node->value = mh_xstrdup ("nmh mhical v0.1"); } if ((node = find_contentline (clines, "VERSION", 0))) { if (! node->value) { inform("Version property is missing value, assume 2.0, continuing..."); node->value = mh_xstrdup ("2.0"); } if (strcmp (node->value, "2.0")) { inform("supports the Version 2.0 specified by RFC 5545 " "but iCalendar object has Version %s, continuing...", node->value); node->value = mh_xstrdup ("2.0"); } } if ((node = find_contentline (clines, "SUMMARY", 0))) { char *insert = NULL; switch (action) { case ACT_ACCEPT: insert = "Accepted: "; break; case ACE_DECLINE: insert = "Declined: "; break; case ACT_TENTATIVE: insert = "Tentative: "; break; case ACT_DELEGATE: adios (NULL, "Delegate replies are not supported"); break; case ACT_CANCEL: insert = "Cancelled:"; break; default: ; } if (insert) { const size_t len = strlen (insert) + strlen (node->value) + 1; char *tmp = mh_xmalloc (len); (void) strncpy (tmp, insert, len); (void) strncat (tmp, node->value, len - strlen (insert) - 1); free (node->value); node->value = tmp; } else { /* Should never get here. */ adios (NULL, "Unknown action: %d", action); } } if ((node = find_contentline (clines, "DTSTAMP", 0))) { const time_t now = time (NULL); struct tm now_tm; if (gmtime_r (&now, &now_tm)) { /* 17 would be sufficient given that RFC 5545 § 3.3.4 supports only a 4 digit year. */ char buf[32]; if (strftime (buf, sizeof buf, "%Y%m%dT%H%M%SZ", &now_tm)) { free (node->value); node->value = mh_xstrdup (buf); } else { inform("strftime unable to format current time, continuing..."); } } else { inform("gmtime_r failed on current time, continuing..."); } } /* Excise X- lines and VALARM section(s). */ in_valarm = 0; for (node = clines; node; node = node->next) { /* node->name will be NULL if the line was deleted. */ if (! node->name) { continue; } if (in_valarm) { if (! strcasecmp ("END", node->name) && ! strcasecmp ("VALARM", node->value)) { in_valarm = 0; } remove_contentline (node); } else { if (! strcasecmp ("BEGIN", node->name) && ! strcasecmp ("VALARM", node->value)) { in_valarm = 1; remove_contentline (node); } else if (! strncasecmp ("X-", node->name, 2)) { remove_contentline (node); } } } } /* Echo the input, but with unfolded lines. */ static void dump_unfolded (FILE *file, contentline *clines) { contentline *node; for (node = clines; node; node = node->next) { fputs (node->input_line, file); } } static void output (FILE *file, contentline *clines, int contenttype) { contentline *node; if (contenttype) { /* Generate a Content-Type header to pass the method parameter to mhbuild. Per RFC 5545 Secs. 6 and 8.1, it must be UTF-8. But we don't attempt to do any conversion of the input. */ if ((node = find_contentline (clines, "METHOD", 0))) { fprintf (file, "Content-Type: text/calendar; method=\"%s\"; " "charset=\"UTF-8\"\n\n", node->value); } } for (node = clines; node; node = node->next) { if (node->name) { char *line = NULL; size_t len; line = mh_xstrdup (node->name); line = format_params (line, node->params); len = strlen (line); line = mh_xrealloc (line, len + 2); line[len] = ':'; line[len + 1] = '\0'; line = fold (add (node->value, line), clines->cr_before_lf == CR_BEFORE_LF); if (clines->cr_before_lf == LF_ONLY) { fprintf (file, "%s\n", line); } else { fprintf (file, "%s\r\n", line); } free (line); } } } /* * Display these fields of the iCalendar event: * - method * - organizer * - summary * - description, except for "\n\n" and in VALARM * - location * - dtstart in local timezone * - dtend in local timezone * - attendees (limited to number specified in initialization) */ static void display (FILE *file, contentline *clines, char *nfs) { tzdesc_t timezones = load_timezones (clines); int in_vtimezone; int in_valarm; contentline *node; struct format *fmt; int dat[5] = { 0, 0, 0, INT_MAX, 0 }; struct comp *c; charstring_t buffer = charstring_create (BUFSIZ); charstring_t attendees = charstring_create (BUFSIZ); const unsigned int max_attendees = 20; unsigned int num_attendees; /* Don't call on the END:VCALENDAR line. */ if (clines && clines->next) { (void) fmt_compile (nfs, &fmt, 1); } if ((c = fmt_findcomp ("method"))) { if ((node = find_contentline (clines, "METHOD", 0)) && node->value) { c->c_text = mh_xstrdup (node->value); } } if ((c = fmt_findcomp ("organizer"))) { if ((node = find_contentline (clines, "ORGANIZER", 0)) && node->value) { c->c_text = mh_xstrdup (identity (node)); } } if ((c = fmt_findcomp ("summary"))) { if ((node = find_contentline (clines, "SUMMARY", 0)) && node->value) { c->c_text = mh_xstrdup (node->value); } } /* Only display DESCRIPTION lines that are outside VALARM section(s). */ in_valarm = 0; if ((c = fmt_findcomp ("description"))) { for (node = clines; node; node = node->next) { /* node->name will be NULL if the line was deleted. */ if (node->name && node->value && ! in_valarm && ! strcasecmp ("DESCRIPTION", node->name) && strcasecmp (node->value, "\\n\\n")) { c->c_text = mh_xstrdup (node->value); } else if (in_valarm) { if (! strcasecmp ("END", node->name) && ! strcasecmp ("VALARM", node->value)) { in_valarm = 0; } } else { if (! strcasecmp ("BEGIN", node->name) && ! strcasecmp ("VALARM", node->value)) { in_valarm = 1; } } } } if ((c = fmt_findcomp ("location"))) { if ((node = find_contentline (clines, "LOCATION", 0)) && node->value) { c->c_text = mh_xstrdup (node->value); } } if ((c = fmt_findcomp ("dtstart"))) { /* Find DTSTART outsize of a VTIMEZONE section. */ in_vtimezone = 0; for (node = clines; node; node = node->next) { /* node->name will be NULL if the line was deleted. */ if (! node->name) { continue; } if (in_vtimezone) { if (! strcasecmp ("END", node->name) && ! strcasecmp ("VTIMEZONE", node->value)) { in_vtimezone = 0; } } else { if (! strcasecmp ("BEGIN", node->name) && ! strcasecmp ("VTIMEZONE", node->value)) { in_vtimezone = 1; } else if (! strcasecmp ("DTSTART", node->name)) { /* Got it: DTSTART outside of a VTIMEZONE section. */ char *datetime = format_datetime (timezones, node); c->c_text = datetime ? datetime : mh_xstrdup(node->value); } } } } if ((c = fmt_findcomp ("dtend"))) { if ((node = find_contentline (clines, "DTEND", 0)) && node->value) { char *datetime = format_datetime (timezones, node); c->c_text = datetime ? datetime : strdup(node->value); } else if ((node = find_contentline (clines, "DTSTART", 0)) && node->value) { /* There is no DTEND. If there's a DTSTART, use it. If it doesn't have a time, assume that the event is for the entire day and append 23:59:59 to it so that it signifies the end of the day. And assume local timezone. */ if (strchr(node->value, 'T')) { char * datetime = format_datetime (timezones, node); c->c_text = datetime ? datetime : strdup(node->value); } else { char *datetime; contentline node_copy; node_copy = *node; node_copy.value = concat(node_copy.value, "T235959", NULL); datetime = format_datetime (timezones, &node_copy); c->c_text = datetime ? datetime : strdup(node_copy.value); free(node_copy.value); } } } if ((c = fmt_findcomp ("attendees"))) { /* Call find_contentline () with node as argument to find multiple matching contentlines. */ charstring_append_cstring (attendees, "Attendees: "); for (node = clines, num_attendees = 0; (node = find_contentline (node, "ATTENDEE", 0)) && num_attendees++ < max_attendees; node = node->next) { const char *id = identity (node); if (num_attendees > 1) { charstring_append_cstring (attendees, ", "); } charstring_append_cstring (attendees, id); } if (num_attendees >= max_attendees) { unsigned int not_shown = 0; for ( ; (node = find_contentline (node, "ATTENDEE", 0)); node = node->next) { ++not_shown; } if (not_shown > 0) { char buf[32]; (void) snprintf (buf, sizeof buf, ", and %d more", not_shown); charstring_append_cstring (attendees, buf); } } if (num_attendees > 0) { c->c_text = charstring_buffer_copy (attendees); } } /* Don't call on the END:VCALENDAR line. */ if (clines && clines->next) { (void) fmt_scan (fmt, buffer, INT_MAX, dat, NULL); fputs (charstring_buffer (buffer), file); fmt_free (fmt, 1); } charstring_free (attendees); charstring_free (buffer); free_timezones (timezones); } static const char * identity (const contentline *node) { /* According to RFC 5545 § 3.3.3, an email address in the value must be a mailto URI. */ if (! strncasecmp (node->value, "mailto:", 7)) { char *addr; param_list *p; for (p = node->params; p && p->param_name; p = p->next) { value_list *v; for (v = p->values; v; v = v->next) { if (! strcasecmp (p->param_name, "CN")) { return v->value; } } } /* Did not find a CN parameter, so output the address. */ addr = node->value + 7; /* Skip any leading whitespace. */ for ( ; isspace ((unsigned char) *addr); ++addr) { continue; } return addr; } return "unknown"; } static char * format_params (char *line, param_list *p) { for ( ; p && p->param_name; p = p->next) { value_list *v; size_t num_values = 0; for (v = p->values; v; v = v->next) { if (v->value) { ++num_values; } } if (num_values) { size_t len = strlen (line); line = mh_xrealloc (line, len + 2); line[len] = ';'; line[len + 1] = '\0'; line = add (p->param_name, line); for (v = p->values; v; v = v->next) { len = strlen (line); line = mh_xrealloc (line, len + 2); line[len] = v == p->values ? '=' : ','; line[len + 1] = '\0'; line = add (v->value, line); } } } return line; } static char * fold (char *line, int uses_cr) { size_t remaining = strlen (line); size_t current_line_len = 0; charstring_t folded_line = charstring_create (2 * remaining); const char *cp = line; #ifdef MULTIBYTE_SUPPORT if (mbtowc (NULL, NULL, 0)) {} /* reset shift state */ #endif while (*cp && remaining > 0) { #ifdef MULTIBYTE_SUPPORT int char_len = mbtowc (NULL, cp, (size_t) MB_CUR_MAX < remaining ? (size_t) MB_CUR_MAX : remaining); if (char_len == -1) { char_len = 1; } #else const int char_len = 1; #endif charstring_push_back_chars (folded_line, cp, char_len, 1); remaining -= max(char_len, 1); /* remaining must be > 0 to pass the loop condition above, so if it's not > 1, it is == 1. */ if (++current_line_len >= 75) { if (remaining > 1 || (*(cp+1) != '\0' && *(cp+1) != '\r' && *(cp+1) != '\n')) { /* fold */ if (uses_cr) { charstring_push_back (folded_line, '\r'); } charstring_push_back (folded_line, '\n'); charstring_push_back (folded_line, ' '); current_line_len = 0; } } cp += max(char_len, 1); } free (line); line = charstring_buffer_copy (folded_line); charstring_free (folded_line); return line; } nmh-1.7.1-RC3/uip/mhl.c000644 007761 000024 00000000605 13243042054 014501 0ustar00kenhstaff000000 000000 /* mhl.c -- the nmh message listing program * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include int main (int argc, char **argv) { if (nmh_init(argv[0], 2)) { return 1; } done (mhl (argc, argv)); return 1; } nmh-1.7.1-RC3/uip/mhlist.c000644 007761 000024 00000017713 13243042054 015231 0ustar00kenhstaff000000 000000 /* mhlist.c -- list the contents of MIME messages * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #include #include #include #include #include "../sbr/m_maildir.h" #include "mhfree.h" #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("disposition", 0, DISPOSW) \ X("nodisposition", 0, NDISPOSW) \ X("file file", 0, FILESW) \ X("part number", 0, PARTSW) \ X("type content", 0, TYPESW) \ X("prefer content", 0, PREFERSW) \ X("noprefer", 0, NPREFERSW) \ X("rcache policy", 0, RCACHESW) \ X("wcache policy", 0, WCACHESW) \ X("changecur", 0, CHGSW) \ X("nochangecur", 0, NCHGSW) \ 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 /* mhmisc.c */ extern int npart; extern int ntype; extern char *parts[NPARTS + 1]; extern char *types[NTYPES + 1]; extern int userrs; /* mhparse.c */ extern char *preferred_types[]; extern char *preferred_subtypes[]; extern int npreferred; /* * This is currently needed to keep mhparse happy. * This needs to be changed. */ int debugsw = 0; #define quitser pipeser /* mhparse.c */ CT parse_mime (char *); /* mhmisc.c */ int part_ok (CT); int type_ok (CT, int); void flush_errors (void); /* * static prototypes */ static void pipeser (int); int main (int argc, char **argv) { int sizesw = 1, headsw = 1, chgflag = 1, verbosw = 0, dispo = 0; int msgnum, *icachesw; char *cp, *file = NULL, *folder = NULL; char *maildir, buf[100], **argp; char **arguments; struct msgs_array msgs = { 0, 0, NULL }; struct msgs *mp = NULL; CT ct, *ctp; if (nmh_init(argv[0], 1)) { return 1; } done=freects_done; arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; /* * Parse arguments */ while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [+folder] [msgs] [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case RCACHESW: icachesw = &rcachesw; goto do_cache; case WCACHESW: icachesw = &wcachesw; do_cache: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); switch (*icachesw = smatch (cp, cache_policy)) { case AMBIGSW: ambigsw (cp, cache_policy); done (1); case UNKWNSW: adios (NULL, "%s unknown", cp); default: break; } continue; case CHECKSW: checksw++; continue; case NCHECKSW: checksw = 0; continue; case HEADSW: headsw = 1; continue; case NHEADSW: headsw = 0; continue; case SIZESW: sizesw = 1; continue; case NSIZESW: sizesw = 0; continue; case PARTSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if (npart >= NPARTS) adios (NULL, "too many parts (starting with %s), %d max", cp, NPARTS); parts[npart++] = cp; continue; case TYPESW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if (ntype >= NTYPES) adios (NULL, "too many types (starting with %s), %d max", cp, NTYPES); types[ntype++] = cp; continue; case PREFERSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if (npreferred >= NPREFS) adios (NULL, "too many preferred types (starting with %s), %d max", cp, NPREFS); preferred_types[npreferred] = cp; cp = strchr(cp, '/'); if (cp) *cp++ = '\0'; preferred_subtypes[npreferred++] = cp; continue; case NPREFERSW: npreferred = 0; continue; case FILESW: if (!(cp = *argp++) || (*cp == '-' && cp[1])) adios (NULL, "missing argument to %s", argp[-2]); file = *cp == '-' ? cp : path (cp, TFILE); continue; case CHGSW: chgflag++; continue; case NCHGSW: chgflag = 0; continue; case VERBSW: verbosw = 1; continue; case NVERBSW: verbosw = 0; continue; case DISPOSW: dispo = 1; continue; case NDISPOSW: dispo = 0; continue; case DEBUGSW: debugsw = 1; continue; } } if (*cp == '+' || *cp == '@') { if (folder) adios (NULL, "only one folder at a time!"); else folder = pluspath (cp); } else app_msgarg(&msgs, cp); } /* null terminate the list of acceptable parts/types */ parts[npart] = NULL; types[ntype] = NULL; /* Check for public cache location */ if ((cache_public = context_find (nmhcache)) && *cache_public != '/') cache_public = NULL; /* Check for private cache location */ if (!(cache_private = context_find (nmhprivcache))) cache_private = ".cache"; cache_private = getcpy (m_maildir (cache_private)); if (!context_find ("path")) free (path ("./", TFOLDER)); if (file && msgs.size) adios (NULL, "cannot specify msg and file at same time!"); /* * check if message is coming from file */ if (file) { cts = mh_xcalloc(2, sizeof *cts); ctp = cts; if ((ct = parse_mime (file))) *ctp++ = ct; } else { /* * message(s) are coming from a folder */ if (!msgs.size) app_msgarg(&msgs, "cur"); if (!folder) folder = getfolder (1); maildir = m_maildir (folder); if (chdir (maildir) == NOTOK) adios (maildir, "unable to change directory to"); /* read folder and create message structure */ if (!(mp = folder_read (folder, 0))) adios (NULL, "unable to read folder %s", folder); /* check for empty folder */ if (mp->nummsg == 0) adios (NULL, "no messages in %s", folder); /* parse all the message ranges/sequences and set SELECTED */ for (msgnum = 0; msgnum < msgs.size; msgnum++) if (!m_convert (mp, msgs.msgs[msgnum])) done (1); seq_setprev (mp); /* set the previous-sequence */ cts = mh_xcalloc(mp->numsel + 1, sizeof *cts); ctp = cts; for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { if (is_selected(mp, msgnum)) { char *msgnam; msgnam = m_name (msgnum); if ((ct = parse_mime (msgnam))) *ctp++ = ct; } } } if (!*cts) done (1); userrs = 1; SIGNAL (SIGQUIT, quitser); SIGNAL (SIGPIPE, pipeser); /* * Get the associated umask for the relevant contents. */ for (ctp = cts; *ctp; ctp++) { struct stat st; ct = *ctp; if (type_ok (ct, 1) && !ct->c_umask) { if (stat (ct->c_file, &st) != NOTOK) ct->c_umask = ~(st.st_mode & 0777); else ct->c_umask = ~m_gmprot(); } } /* * List the message content */ list_all_messages (cts, headsw, sizesw, verbosw, debugsw, dispo); /* Now free all the structures for the content */ for (ctp = cts; *ctp; ctp++) free_content (*ctp); free(cts); cts = NULL; /* If reading from a folder, do some updating */ if (mp) { context_replace (pfolder, folder);/* update current folder */ if (chgflag) seq_setcur (mp, mp->hghsel); /* update current message */ seq_save (mp); /* synchronize sequences */ context_save (); /* save the context file */ } done (0); return 1; } static void pipeser (int i) { if (i == SIGQUIT) { fflush (stdout); fprintf (stderr, "\n"); fflush (stderr); } done (1); /* NOTREACHED */ } nmh-1.7.1-RC3/uip/mhlistsbr.c000644 007761 000024 00000025274 13243042054 015741 0ustar00kenhstaff000000 000000 /* mhlistsbr.c -- routines to list information about the * -- contents of MIME messages * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #include /* mhmisc.c */ int part_ok (CT); int type_ok (CT, int); void flush_errors (void); /* * static prototypes */ static void list_single_message (CT, int, int, int, int); static int list_debug (CT); static int list_multi (CT, int, int, int, int, int); static int list_partial (CT, int, int, int, int, int); static int list_external (CT, int, int, int, int, int); static int list_application (CT, int, int, int, int, int); static int list_encoding (CT); /* * various formats for -list option */ #define LSTFMT1 "%4s %-5s %-24s %5s %s\n" #define LSTFMT2a "%4d " #define LSTFMT2b "%-5s %-24.24s " #define LSTFMT2bv "%-5s %-24s " #define LSTFMT2c1 "%5lu" #define LSTFMT2c2 "%4lu%c" #define LSTFMT2c3 "huge " #define LSTFMT2c4 " " #define LSTFMT2d1 " %.36s" #define LSTFMT2d1v " %s" #define LSTFMT2d2 "\t %-65s\n" /* * Top level entry point to list group of messages */ void list_all_messages (CT *cts, int headers, int realsize, int verbose, int debug, int dispo) { CT ct, *ctp; if (headers) printf (LSTFMT1, "msg", "part", "type/subtype", "size", "description"); for (ctp = cts; *ctp; ctp++) { ct = *ctp; list_single_message (ct, realsize, verbose, debug, dispo); } flush_errors (); } /* * Entry point to list a single message */ static void list_single_message (CT ct, int realsize, int verbose, int debug, int dispo) { if (type_ok (ct, 1)) { umask (ct->c_umask); list_switch (ct, 1, realsize, verbose, debug, dispo); if (ct->c_fp) { fclose (ct->c_fp); ct->c_fp = NULL; } if (ct->c_ceclosefnx) (*ct->c_ceclosefnx) (ct); } } /* * Primary switching routine to list information about a content */ int list_switch (CT ct, int toplevel, int realsize, int verbose, int debug, int dispo) { switch (ct->c_type) { case CT_MULTIPART: return list_multi (ct, toplevel, realsize, verbose, debug, dispo); case CT_MESSAGE: switch (ct->c_subtype) { case MESSAGE_PARTIAL: return list_partial (ct, toplevel, realsize, verbose, debug, dispo); case MESSAGE_EXTERNAL: return list_external (ct, toplevel, realsize, verbose, debug, dispo); case MESSAGE_RFC822: default: return list_content (ct, toplevel, realsize, verbose, debug, dispo); } case CT_TEXT: case CT_AUDIO: case CT_IMAGE: case CT_VIDEO: return list_content (ct, toplevel, realsize, verbose, debug, dispo); case CT_APPLICATION: default: return list_application (ct, toplevel, realsize, verbose, debug, dispo); } return 0; /* NOT REACHED */ } /* * Method for listing information about a simple/generic content */ int list_content (CT ct, int toplevel, int realsize, int verbose, int debug, int dispo) { unsigned long size; char *cp, buffer[BUFSIZ]; CI ci = &ct->c_ctinfo; PM pm; if (toplevel > 0) printf (LSTFMT2a, atoi (r1bindex (FENDNULL(ct->c_file), '/'))); else printf(toplevel < 0 ? "part " : " "); snprintf (buffer, sizeof(buffer), "%s/%s", FENDNULL(ci->ci_type), FENDNULL(ci->ci_subtype)); if (verbose) printf (LSTFMT2bv, FENDNULL(ct->c_partno), buffer); else printf (LSTFMT2b, FENDNULL(ct->c_partno), buffer); if (ct->c_cesizefnx && realsize) size = (*ct->c_cesizefnx) (ct); else size = ct->c_end - ct->c_begin; /* find correct scale for size (Kilo/Mega/Giga/Tera) */ for (cp = " KMGT"; size > 9999; size /= 1000) if (!*++cp) break; /* print size of this body part */ switch (*cp) { case ' ': if (size > 0 || ct->c_encoding != CE_EXTERNAL) printf (LSTFMT2c1, size); else printf (LSTFMT2c4); break; default: printf (LSTFMT2c2, size, *cp); break; case '\0': printf (LSTFMT2c3); } /* print Content-Description */ if (ct->c_descr) { char *dp; dp = cpytrim (ct->c_descr); if (verbose) printf (LSTFMT2d1v, dp); else printf (LSTFMT2d1, dp); free (dp); } putchar('\n'); if (verbose) { CI ci = &ct->c_ctinfo; for (pm = ci->ci_first_pm; pm; pm = pm->pm_next) { printf ("\t %s=\"%s\"\n", pm->pm_name, get_param_value(pm, '?')); } /* * If verbose, print any RFC-822 comments in the * Content-Type line. */ if (ci->ci_comment) { char *dp; dp = cpytrim (ci->ci_comment); snprintf (buffer, sizeof(buffer), "(%s)", dp); free (dp); printf (LSTFMT2d2, buffer); } } if (dispo && ct->c_dispo_type) { printf ("\t disposition \"%s\"\n", ct->c_dispo_type); if (verbose) { for (pm = ct->c_dispo_first; pm; pm = pm->pm_next) { printf ("\t %s=\"%s\"\n", pm->pm_name, get_param_value(pm, '?')); } } } if (debug) list_debug (ct); return OK; } /* * Print debugging information about a content */ static int list_debug (CT ct) { CI ci = &ct->c_ctinfo; PM pm; fflush (stdout); fprintf (stderr, " partno \"%s\"\n", FENDNULL(ct->c_partno)); /* print MIME-Version line */ if (ct->c_vrsn) fprintf (stderr, " %s:%s\n", VRSN_FIELD, ct->c_vrsn); /* print Content-Type line */ if (ct->c_ctline) fprintf (stderr, " %s:%s\n", TYPE_FIELD, ct->c_ctline); /* print parsed elements of content type */ fprintf (stderr, " type \"%s\"\n", FENDNULL(ci->ci_type)); fprintf (stderr, " subtype \"%s\"\n", FENDNULL(ci->ci_subtype)); fprintf (stderr, " comment \"%s\"\n", FENDNULL(ci->ci_comment)); fprintf (stderr, " magic \"%s\"\n", FENDNULL(ci->ci_magic)); /* print parsed parameters attached to content type */ fprintf (stderr, " parameters\n"); for (pm = ci->ci_first_pm; pm; pm = pm->pm_next) fprintf (stderr, " %s=\"%s\"\n", pm->pm_name, get_param_value(pm, '?')); /* print internal flags for type/subtype */ fprintf (stderr, " type 0x%x subtype 0x%x params 0x%x\n", ct->c_type, ct->c_subtype, (unsigned int)(unsigned long) ct->c_ctparams); fprintf (stderr, " showproc \"%s\"\n", FENDNULL(ct->c_showproc)); fprintf (stderr, " termproc \"%s\"\n", FENDNULL(ct->c_termproc)); fprintf (stderr, " storeproc \"%s\"\n", FENDNULL(ct->c_storeproc)); /* print transfer encoding information */ if (ct->c_celine) fprintf (stderr, " %s:%s", ENCODING_FIELD, ct->c_celine); /* print internal flags for transfer encoding */ fprintf (stderr, " transfer encoding 0x%x params 0x%x\n", ct->c_encoding, (unsigned int)(unsigned long) &ct->c_cefile); /* print Content-ID */ if (ct->c_id) fprintf (stderr, " %s:%s", ID_FIELD, ct->c_id); /* print Content-Description */ if (ct->c_descr) fprintf (stderr, " %s:%s", DESCR_FIELD, ct->c_descr); /* print Content-Disposition */ if (ct->c_dispo) fprintf (stderr, " %s:%s", DISPO_FIELD, ct->c_dispo); fprintf(stderr, " disposition \"%s\"\n", FENDNULL(ct->c_dispo_type)); fprintf(stderr, " disposition parameters\n"); for (pm = ct->c_dispo_first; pm; pm = pm->pm_next) fprintf (stderr, " %s=\"%s\"\n", pm->pm_name, get_param_value(pm, '?')); fprintf (stderr, " read fp 0x%x file \"%s\" begin %ld end %ld\n", (unsigned int)(unsigned long) ct->c_fp, FENDNULL(ct->c_file), ct->c_begin, ct->c_end); /* print more information about transfer encoding */ list_encoding (ct); return OK; } /* * list content information for type "multipart" */ static int list_multi (CT ct, int toplevel, int realsize, int verbose, int debug, int dispo) { struct multipart *m = (struct multipart *) ct->c_ctparams; struct part *part; /* list the content for toplevel of this multipart */ list_content (ct, toplevel, realsize, verbose, debug, dispo); /* now list for all the subparts */ for (part = m->mp_parts; part; part = part->mp_next) { CT p = part->mp_part; if (part_ok (p) && type_ok (p, 1)) list_switch (p, 0, realsize, verbose, debug, dispo); } return OK; } /* * list content information for type "message/partial" */ static int list_partial (CT ct, int toplevel, int realsize, int verbose, int debug, int dispo) { struct partial *p = (struct partial *) ct->c_ctparams; list_content (ct, toplevel, realsize, verbose, debug, dispo); if (verbose) { printf ("\t [message %s, part %d", p->pm_partid, p->pm_partno); if (p->pm_maxno) printf (" of %d", p->pm_maxno); puts("]"); } return OK; } /* * list content information for type "message/external" */ static int list_external (CT ct, int toplevel, int realsize, int verbose, int debug, int dispo) { struct exbody *e = (struct exbody *) ct->c_ctparams; /* * First list the information for the * message/external content itself. */ list_content (ct, toplevel, realsize, verbose, debug, dispo); if (verbose) { if (e->eb_name) printf ("\t name=\"%s\"\n", e->eb_name); if (e->eb_dir) printf ("\t directory=\"%s\"\n", e->eb_dir); if (e->eb_site) printf ("\t site=\"%s\"\n", e->eb_site); if (e->eb_server) printf ("\t server=\"%s\"\n", e->eb_server); if (e->eb_subject) printf ("\t subject=\"%s\"\n", e->eb_subject); if (e->eb_url) printf ("\t url=\"%s\"\n", e->eb_url); /* This must be defined */ printf ("\t access-type=\"%s\"\n", e->eb_access); if (e->eb_mode) printf ("\t mode=\"%s\"\n", e->eb_mode); if (e->eb_permission) printf ("\t permission=\"%s\"\n", e->eb_permission); if (e->eb_flags == NOTOK) puts("\t [service unavailable]"); } /* * Now list the information for the external content * to which this content points. */ list_content (e->eb_content, 0, realsize, verbose, debug, dispo); return OK; } /* * list content information for type "application" * This no longer needs to be a separate function. It used to * produce some output with verbose enabled, but that has been * moved to list_content (). */ static int list_application (CT ct, int toplevel, int realsize, int verbose, int debug, int dispo) { list_content (ct, toplevel, realsize, verbose, debug, dispo); return OK; } /* * list information about the Content-Transfer-Encoding * used by a content. */ static int list_encoding (CT ct) { CE ce = &ct->c_cefile; fprintf (stderr, " decoded fp 0x%x file \"%s\"\n", (unsigned int)(unsigned long) ce->ce_fp, FENDNULL(ce->ce_file)); return OK; } nmh-1.7.1-RC3/uip/mhlogin.c000644 007761 000024 00000012232 13243042054 015355 0ustar00kenhstaff000000 000000 /* mhlogin.c -- login to external (OAuth) services * * This code is Copyright (c) 2014, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #include "../sbr/lock_file.h" #define MHLOGIN_SWITCHES \ X("user username", 0, USERSW) \ X("saslmech", 0, SASLMECHSW) \ X("authservice", 0, AUTHSERVICESW) \ X("browser", 0, BROWSERSW) \ X("snoop", 0, SNOOPSW) \ X("help", 0, HELPSW) \ X("version", 0, VERSIONSW) \ #define X(sw, minchars, id) id, DEFINE_SWITCH_ENUM(MHLOGIN); #undef X #define X(sw, minchars, id) { sw, minchars, id }, DEFINE_SWITCH_ARRAY(MHLOGIN, switches); #undef X #ifdef OAUTH_SUPPORT /* XXX copied from install-mh.c */ static char * geta (void) { static char line[BUFSIZ]; if (fgets(line, sizeof(line), stdin) == NULL) done (1); trim_suffix_c(line, '\n'); return line; } static int do_login(const char *svc, const char *user, const char *browser, int snoop) { char *fn, *code; mh_oauth_ctx *ctx; mh_oauth_cred *cred; FILE *cred_file; int failed_to_lock = 0; const char *url; if (svc == NULL) { adios(NULL, "missing -authservice switch"); } if (user == NULL) { adios(NULL, "missing -user switch"); } if (!mh_oauth_new(&ctx, svc)) { adios(NULL, mh_oauth_get_err_string(ctx)); } if (snoop) { mh_oauth_log_to(stderr, ctx); } fn = mh_xstrdup(mh_oauth_cred_fn(svc)); if ((url = mh_oauth_get_authorize_url(ctx)) == NULL) { adios(NULL, mh_oauth_get_err_string(ctx)); } if (browser) { char *command = concat(browser, " '", url, "'", NULL); int status = OK; printf("Follow the prompts in your browser to authorize nmh" " to access %s.\n", mh_oauth_svc_display_name(ctx)); sleep(1); status = system(command); free(command); if (status != OK) { adios ((char *) browser, "SYSTEM"); } } else { printf("Load the following URL in your browser and authorize nmh" " to access %s:\n\n%s\n\n", mh_oauth_svc_display_name(ctx), url); } printf("Enter the authorization code: "); fflush(stdout); code = geta(); while (!*code || ((cred = mh_oauth_authorize(code, ctx)) == NULL && mh_oauth_get_err_code(ctx) == MH_OAUTH_BAD_GRANT)) { printf(!*code ? "Empty code; try again? " : "Code rejected; try again? "); fflush(stdout); code = geta(); } if (cred == NULL) { inform("error exchanging code for OAuth2 token"); adios(NULL, mh_oauth_get_err_string(ctx)); } cred_file = lkfopendata(fn, "r+", &failed_to_lock); if (cred_file == NULL && errno == ENOENT) { cred_file = lkfopendata(fn, "w+", &failed_to_lock); } if (cred_file == NULL || failed_to_lock) { adios(fn, "oops"); } if (!mh_oauth_cred_save(cred_file, cred, user)) { adios(NULL, mh_oauth_get_err_string(ctx)); } if (lkfclosedata(cred_file, fn) != 0) { adios (fn, "oops"); } free(fn); mh_oauth_cred_free(cred); mh_oauth_free(ctx); return 0; } #endif int main(int argc, char **argv) { char *cp, **argp, **arguments; const char *user = NULL, *saslmech = NULL, *svc = NULL, *browser = NULL; int snoop = 0; if (nmh_init(argv[0], 1)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; while ((cp = *argp++)) { if (*cp == '-') { char help[BUFSIZ]; switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf(help, sizeof(help), "%s [switches]", invo_name); print_help (help, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case USERSW: if (!(user = *argp++) || *user == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case SASLMECHSW: if (!(saslmech = *argp++) || *saslmech == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case AUTHSERVICESW: if (!(svc = *argp++) || *svc == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case BROWSERSW: if (!(browser = *argp++) || *browser == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case SNOOPSW: snoop++; continue; } } adios(NULL, "extraneous arguments"); } if (saslmech && strcasecmp(saslmech, "xoauth2")) { /* xoauth is assumed */ adios(NULL, "only -saslmech xoauth2 is supported"); } free(arguments); #ifdef OAUTH_SUPPORT return do_login(svc, user, browser, snoop); #else NMH_UNUSED(svc); NMH_UNUSED(browser); NMH_UNUSED(snoop); adios(NULL, "not built with OAuth support"); return 1; #endif } nmh-1.7.1-RC3/uip/mhlsbr.c000644 007761 000024 00000135407 13243042054 015221 0ustar00kenhstaff000000 000000 /* mhlsbr.c -- main routines for nmh message lister * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #include "../sbr/m_popen.h" #include #include /* * MAJOR BUG: * for a component containing addresses, ADDRFMT, if COMPRESS is also * set, then addresses get split wrong (not at the spaces between commas). * To fix this correctly, putstr() should know about "atomic" strings that * must NOT be broken across lines. That's too difficult for right now * (it turns out that there are a number of degenerate cases), so in * oneline(), instead of * * (*onelp == '\n' && !onelp[1]) * * being a terminating condition, * * (*onelp == '\n' && (!onelp[1] || (flags & ADDRFMT))) * * is used instead. This cuts the line prematurely, and gives us a much * better chance of getting things right. */ #define ONECOMP 0 #define TWOCOMP 1 #define BODYCOMP 2 #define QUOTE '\\' #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 */ #define CENTER 0x000004 /* center line */ #define CLEARTEXT 0x000008 /* cleartext */ #define EXTRA 0x000010 /* an "extra" component */ #define HDROUTPUT 0x000020 /* already output */ #define CLEARSCR 0x000040 /* clear screen */ #define LEFTADJUST 0x000080 /* left justify multiple lines */ #define COMPRESS 0x000100 /* compress text */ #define ADDRFMT 0x000200 /* contains addresses */ #define BELL 0x000400 /* sound bell at EOP */ #define DATEFMT 0x000800 /* contains dates */ #define FORMAT 0x001000 /* parse address/date/RFC-2047 field */ #define INIT 0x002000 /* initialize component */ #define RTRIM 0x004000 /* trim trailing whitespace */ #define SPLIT 0x010000 /* split headers (don't concatenate) */ #define NONEWLINE 0x020000 /* don't write trailing newline */ #define NOWRAP 0x040000 /* Don't wrap lines ever */ #define FMTFILTER 0x080000 /* Filter through format filter */ #define INVISIBLE 0x100000 /* count byte in display columns? */ #define FORCE7BIT 0x200000 /* don't display 8-bit bytes */ #define LBITS "\020\01NOCOMPONENT\02UPPERCASE\03CENTER\04CLEARTEXT\05EXTRA\06HDROUTPUT\07CLEARSCR\010LEFTADJUST\011COMPRESS\012ADDRFMT\013BELL\014DATEFMT\015FORMAT\016INIT\017RTRIM\021SPLIT\022NONEWLINE\023NOWRAP\024FMTFILTER\025INVISIBLE\026FORCE7BIT" #define GFLAGS (NOCOMPONENT | UPPERCASE | CENTER | LEFTADJUST | COMPRESS | SPLIT | NOWRAP) /* * A format string to be used as a command-line argument to the body * format filter. */ struct arglist { struct format *a_fmt; char *a_nfs; struct arglist *a_next; }; /* * Linked list of command line arguments for the body format filter. This * USED to be in "struct mcomp", but the format API got cleaned up and even * though it reduced the code we had to do, it make things more complicated * for us. Specifically: * * - The interface to the hash table has been cleaned up, which means the * rooting around in the hash table is no longer necessary (yay!). But * this ALSO means that we have to make sure that we call our format * compilation routines before we process the message, because the * components need to be visible in the hash table so we can save them for * later. So we moved them out of "mcomp" and now compile them right before * header processing starts. * - We also use format strings to handle other components in the mhl * configuration (using "formatfield" and "decode"), but here life * gets complicated: they aren't dealt with in the normal way. Instead * of referring to a component like {from}, each component is processed * using the special {text} component. But these format strings need to be * compiled BEFORE we compile the format arguments; in the previous * implementation they were compiled and scanned as the headers were * read, and that would reset the hash table that we need to populate * the components used by the body format filter. So we are compiling * the formatfield component strings ahead of time and then scanning them * later. * * Okay, fine ... this was broken before. But you know what? Fixing this * the right way will make things easier down the road. * * One side-effect to this change: format strings are now compiled only once * for components specified with "formatfield", but they are compiled for * every message for format arguments. */ static struct arglist *arglist_head; static struct arglist *arglist_tail; static int filter_nargs = 0; /* * Flags/options for each component */ struct mcomp { char *c_name; /* component name */ char *c_text; /* component text */ char *c_ovtxt; /* text overflow indicator */ char *c_nfs; /* iff FORMAT */ struct format *c_fmt; /* .. */ struct comp *c_c_text; /* Ref to {text} in FORMAT */ struct comp *c_c_error; /* Ref to {error} */ int c_offset; /* left margin indentation */ int c_ovoff; /* overflow indentation */ int c_width; /* width of field */ int c_cwidth; /* width of component */ int c_length; /* length in lines */ unsigned long c_flags; struct mcomp *c_next; }; static struct mcomp *msghd = NULL; static struct mcomp *msgtl = NULL; static struct mcomp *fmthd = NULL; static struct mcomp *fmttl = NULL; static struct mcomp global = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, -1, 80, -1, 40, BELL, NULL }; static struct mcomp holder = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, NOCOMPONENT, NULL }; struct pair { char *p_name; unsigned long p_flags; }; static struct pair pairs[] = { { "Date", DATEFMT }, { "From", ADDRFMT }, { "Sender", ADDRFMT }, { "Reply-To", ADDRFMT }, { "To", ADDRFMT }, { "cc", ADDRFMT }, { "Bcc", ADDRFMT }, { "Resent-Date", DATEFMT }, { "Resent-From", ADDRFMT }, { "Resent-Sender", ADDRFMT }, { "Resent-Reply-To", ADDRFMT }, { "Resent-To", ADDRFMT }, { "Resent-cc", ADDRFMT }, { "Resent-Bcc", ADDRFMT }, { NULL, 0 } }; struct triple { char *t_name; unsigned long t_on; unsigned long t_off; }; static struct triple triples[] = { { "nocomponent", NOCOMPONENT, 0 }, { "uppercase", UPPERCASE, 0 }, { "nouppercase", 0, UPPERCASE }, { "center", CENTER, 0 }, { "nocenter", 0, CENTER }, { "clearscreen", CLEARSCR, 0 }, { "noclearscreen", 0, CLEARSCR }, { "noclear", 0, CLEARSCR }, { "leftadjust", LEFTADJUST, 0 }, { "noleftadjust", 0, LEFTADJUST }, { "compress", COMPRESS, 0 }, { "nocompress", 0, COMPRESS }, { "split", SPLIT, 0 }, { "nosplit", 0, SPLIT }, { "rtrim", RTRIM, 0 }, { "nortrim", 0, RTRIM }, { "addrfield", ADDRFMT, DATEFMT }, { "bell", BELL, 0 }, { "nobell", 0, BELL }, { "datefield", DATEFMT, ADDRFMT }, { "newline", 0, NONEWLINE }, { "nonewline", NONEWLINE, 0 }, { "wrap", 0, NOWRAP }, { "nowrap", NOWRAP, 0 }, { "format", FMTFILTER, 0 }, { "noformat", 0, FMTFILTER }, { NULL, 0, 0 } }; static char *addrcomps[] = { "from", "sender", "reply-to", "to", "cc", "bcc", "resent-from", "resent-sender", "resent-reply-to", "resent-to", "resent-cc", "resent-bcc", NULL }; static int bellflg = 0; static int clearflg = 0; static int dashstuff = 0; static int dobody = 1; static int forwflg = 0; static int forwall = 0; static int sleepsw = NOTOK; static char *digest = NULL; static int volume = 0; static int issue = 0; static int exitstat = 0; static int mhldebug = 0; static int filesize = 0; #define PITTY (-1) #define NOTTY 0 #define ISTTY 1 static int ontty = NOTTY; static int row; static unsigned int column; static int lm; static int llim; static int ovoff; static int term; static unsigned int wid; static char *ovtxt; static char *onelp; static char *parptr; static int num_ignores = 0; static char *ignores[MAXARGS]; static jmp_buf env; static jmp_buf mhlenv; static char delim3[] = /* from forw.c */ "\n----------------------------------------------------------------------\n\n"; static char delim4[] = "\n------------------------------\n\n"; static FILE *(*mhl_action)(char *); /* * prototypes */ static void mhl_format (char *, int, int); static int evalvar (struct mcomp *); static int ptoi (char *, int *); static int ptos (char *, char **); static char *parse (void); static void process (char *, char *, int, int); static void mhlfile (FILE *, char *, int, int); static int mcomp_flags (char *); static char *mcomp_add (unsigned long, char *, char *); static void mcomp_format (struct mcomp *, struct mcomp *); static struct mcomp *add_queue (struct mcomp **, struct mcomp **, char *, char *, int); static void free_queue (struct mcomp **, struct mcomp **); static void putcomp (struct mcomp *, struct mcomp *, int); static char *oneline (char *, unsigned long); static void putstr (char *, unsigned long); static void putch (char, unsigned long); static void intrser (int); static void pipeser (int); static void quitser (int); static void mhladios (char *, char *, ...); static void mhldone (int); 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 mhl (int argc, char **argv) { int length = 0, nomore = 0; unsigned int i, vecp = 0; int width = 0; char *cp, *folder = NULL, *form = NULL; char buf[BUFSIZ], *files[MAXARGS]; char **argp, **arguments; /* Need this if called from main() of show(1). */ invo_name = r1bindex (argv[0], '/'); arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; if ((cp = getenv ("MHLDEBUG")) && *cp) mhldebug++; while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, mhlswitches)) { case AMBIGSW: ambigsw (cp, mhlswitches); mhldone (1); /* FALLTHRU */ case UNKWNSW: mhladios (NULL, "-%s unknown\n", cp); /* FALLTHRU */ case HELPSW: snprintf (buf, sizeof(buf), "%s [switches] [files ...]", invo_name); print_help (buf, mhlswitches, 1); mhldone (0); /* FALLTHRU */ case VERSIONSW: print_version(invo_name); mhldone (0); /* FALLTHRU */ case BELLSW: bellflg = 1; continue; case NBELLSW: bellflg = -1; continue; case CLRSW: clearflg = 1; continue; case NCLRSW: clearflg = -1; continue; case FOLDSW: if (!(folder = *argp++) || *folder == '-') mhladios (NULL, "missing argument to %s", argp[-2]); continue; case FORMSW: if (!(form = *argp++) || *form == '-') mhladios (NULL, "missing argument to %s", argp[-2]); continue; case SLEEPSW: if (!(cp = *argp++) || *cp == '-') mhladios (NULL, "missing argument to %s", argp[-2]); else sleepsw = atoi (cp);/* ZERO ok! */ continue; case PROGSW: if (!(moreproc = *argp++) || *moreproc == '-') mhladios (NULL, "missing argument to %s", argp[-2]); continue; case NPROGSW: nomore++; continue; case FMTPROCSW: if (!(formatproc = *argp++) || *formatproc == '-') mhladios (NULL, "missing argument to %s", argp[-2]); continue; case NFMTPROCSW: formatproc = NULL; continue; case LENSW: if (!(cp = *argp++) || *cp == '-') mhladios (NULL, "missing argument to %s", argp[-2]); else if ((length = atoi (cp)) < 1) mhladios (NULL, "bad argument %s %s", argp[-2], cp); continue; case WIDTHSW: if (!(cp = *argp++) || *cp == '-') mhladios (NULL, "missing argument to %s", argp[-2]); else if ((width = atoi (cp)) < 1) mhladios (NULL, "bad argument %s %s", argp[-2], cp); continue; case DGSTSW: if (!(digest = *argp++) || *digest == '-') mhladios (NULL, "missing argument to %s", argp[-2]); continue; case ISSUESW: if (!(cp = *argp++) || *cp == '-') mhladios (NULL, "missing argument to %s", argp[-2]); else if ((issue = atoi (cp)) < 1) mhladios (NULL, "bad argument %s %s", argp[-2], cp); continue; case VOLUMSW: if (!(cp = *argp++) || *cp == '-') mhladios (NULL, "missing argument to %s", argp[-2]); else if ((volume = atoi (cp)) < 1) mhladios (NULL, "bad argument %s %s", argp[-2], cp); continue; case FORW2SW: forwall++; /* FALLTHRU */ case FORW1SW: forwflg++; clearflg = -1;/* XXX */ continue; case BITSTUFFSW: dashstuff = 1; /* ternary logic */ continue; case NBITSTUFFSW: dashstuff = -1; /* ternary logic */ continue; case NBODYSW: dobody = 0; continue; } } files[vecp++] = cp; } if (!folder) folder = getenv ("mhfolder"); if (isatty (fileno (stdout))) { if (!nomore && moreproc && *moreproc != '\0') { if (mhl_action) { SIGNAL (SIGINT, SIG_IGN); SIGNAL2 (SIGQUIT, quitser); } SIGNAL2 (SIGPIPE, pipeser); m_popen (moreproc, mhl_action != NULL); ontty = PITTY; } else { SIGNAL (SIGINT, SIG_IGN); SIGNAL2 (SIGQUIT, quitser); ontty = ISTTY; } } else { ontty = NOTTY; } mhl_format (form ? form : mhlformat, length, width); if (vecp == 0) { process (folder, NULL, 1, vecp = 1); } else { for (i = 0; i < vecp; i++) process (folder, files[i], i + 1, vecp); } if (forwall) { if (digest) { fputs(delim4, stdout); if (volume == 0) { snprintf (buf, sizeof(buf), "End of %s Digest\n", digest); } else { snprintf (buf, sizeof(buf), "End of %s Digest [Volume %d Issue %d]\n", digest, volume, issue); } i = strlen (buf); for (cp = buf + i; i > 1; i--) *cp++ = '*'; *cp++ = '\n'; *cp = 0; fputs(buf, stdout); } else printf ("\n------- End of Forwarded Message%s\n", PLURALS(vecp)); } fflush(stdout); if(ferror(stdout)){ mhladios("output", "error writing"); } if (clearflg > 0 && ontty == NOTTY) nmh_clear_screen (); if (ontty == PITTY) m_pclose (); return exitstat; } static void mhl_format (char *file, int length, int width) { int i; char *bp, **ip; char *ap, name[NAMESZ]; struct mcomp *c1; struct stat st; FILE *fp; static dev_t dev = 0; static ino_t ino = 0; static time_t mtime = 0; if (fmthd != NULL) { if (stat (etcpath (file), &st) != NOTOK && mtime == st.st_mtime && dev == st.st_dev && ino == st.st_ino) goto out; free_queue (&fmthd, &fmttl); } if ((fp = fopen (etcpath (file), "r")) == NULL) mhladios (file, "unable to open format file"); if (fstat (fileno (fp), &st) != NOTOK) { mtime = st.st_mtime; dev = st.st_dev; ino = st.st_ino; } global.c_ovtxt = global.c_nfs = NULL; global.c_fmt = NULL; global.c_offset = 0; global.c_ovoff = -1; if ((i = sc_width ()) > 5) global.c_width = i; global.c_cwidth = -1; if ((i = sc_length ()) > 5) global.c_length = i - 1; global.c_flags = BELL; /* BELL is default */ *(ip = ignores) = NULL; filter_nargs = 0; while (vfgets (fp, &ap) == OK) { bp = ap; if (*bp == ';') continue; trim_suffix_c(bp, '\n'); if (*bp == ':') { (void) add_queue (&fmthd, &fmttl, NULL, bp + 1, CLEARTEXT); continue; } parptr = bp; strncpy (name, parse(), sizeof(name)); switch (*parptr) { case '\0': case ',': case '=': /* * Split this list of fields to ignore, and copy * it to the end of the current "ignores" list. */ if (!strcasecmp (name, "ignores")) { char **tmparray, **p; int n = 0; /* split the fields */ tmparray = brkstring (mh_xstrdup(++parptr), ",", NULL); /* count number of fields split */ p = tmparray; while (*p++) n++; /* copy pointers to split fields to ignores array */ ip = copyip (tmparray, ip, MAXARGS - num_ignores); num_ignores += n; continue; } parptr = bp; while (*parptr) { if (evalvar (&global)) mhladios (NULL, "format file syntax error: %s", bp); if (*parptr) parptr++; } continue; case ':': c1 = add_queue (&fmthd, &fmttl, name, NULL, INIT); while (*parptr == ':' || *parptr == ',') { parptr++; if (evalvar (c1)) mhladios (NULL, "format file syntax error: %s", bp); } if (!c1->c_nfs && global.c_nfs) { if (c1->c_flags & DATEFMT) { if (global.c_flags & DATEFMT) { c1->c_nfs = mh_xstrdup(global.c_nfs); compile_formatfield(c1); } } else if (c1->c_flags & ADDRFMT) { if (global.c_flags & ADDRFMT) { c1->c_nfs = mh_xstrdup(global.c_nfs); compile_formatfield(c1); } } } continue; default: mhladios (NULL, "format file syntax error: %s", bp); } } fclose (fp); if (mhldebug) { for (c1 = fmthd; c1; c1 = c1->c_next) { char buffer[BUFSIZ]; fprintf (stderr, "c1: name=\"%s\" text=\"%s\" ovtxt=\"%s\"\n", c1->c_name, c1->c_text, c1->c_ovtxt); fprintf (stderr, "\tnfs=0x%x fmt=0x%x\n", (unsigned int)(unsigned long) c1->c_nfs, (unsigned int)(unsigned long) c1->c_fmt); fprintf (stderr, "\toffset=%d ovoff=%d width=%d cwidth=%d length=%d\n", c1->c_offset, c1->c_ovoff, c1->c_width, c1->c_cwidth, c1->c_length); fprintf (stderr, "\tflags=%s\n", snprintb (buffer, sizeof(buffer), (unsigned) c1->c_flags, LBITS)); } } out: if (clearflg == 1) { global.c_flags |= CLEARSCR; } else { if (clearflg == -1) global.c_flags &= ~CLEARSCR; } switch (bellflg) { /* command line may override format file */ case 1: global.c_flags |= BELL; break; case -1: global.c_flags &= ~BELL; break; } if (length) global.c_length = length; if (width) global.c_width = width; if (global.c_length < 5) global.c_length = 10000; if (global.c_width < 5) global.c_width = 10000; } static int evalvar (struct mcomp *c1) { char *cp, name[NAMESZ]; struct triple *ap; if (!*parptr) return 0; strncpy (name, parse(), sizeof(name)); if (!strcasecmp (name, "component")) { if (ptos (name, &c1->c_text)) return 1; c1->c_flags &= ~NOCOMPONENT; return 0; } if (!strcasecmp (name, "overflowtext")) return ptos (name, &c1->c_ovtxt); if (!strcasecmp (name, "formatfield")) { if (ptos (name, &cp)) return 1; c1->c_nfs = getcpy (new_fs (NULL, NULL, cp)); compile_formatfield(c1); c1->c_flags |= FORMAT; return 0; } if (!strcasecmp (name, "decode")) { c1->c_nfs = getcpy (new_fs (NULL, NULL, "%(decode{text})")); compile_formatfield(c1); c1->c_flags |= FORMAT; return 0; } if (!strcasecmp (name, "offset")) return ptoi (name, &c1->c_offset); if (!strcasecmp (name, "overflowoffset")) return ptoi (name, &c1->c_ovoff); if (!strcasecmp (name, "width")) return ptoi (name, &c1->c_width); if (!strcasecmp (name, "compwidth")) return ptoi (name, &c1->c_cwidth); if (!strcasecmp (name, "length")) return ptoi (name, &c1->c_length); if (!strcasecmp (name, "nodashstuffing")) return (dashstuff = -1); for (ap = triples; ap->t_name; ap++) if (!strcasecmp (ap->t_name, name)) { c1->c_flags |= ap->t_on; c1->c_flags &= ~ap->t_off; return 0; } if (!strcasecmp (name, "formatarg")) { struct arglist *args; if (ptos (name, &cp)) return 1; if (! c1->c_name || strcasecmp (c1->c_name, "body")) { inform("format filters are currently only supported on " "the \"body\" component"); return 1; } NEW0(args); if (arglist_tail) arglist_tail->a_next = args; arglist_tail = args; if (! arglist_head) arglist_head = args; args->a_nfs = getcpy (new_fs (NULL, NULL, cp)); filter_nargs++; return 0; } return 1; } static int ptoi (char *name, int *i) { char *cp; if (*parptr++ != '=' || !*(cp = parse ())) { inform("missing argument to variable %s", name); return 1; } *i = atoi (cp); return 0; } static int ptos (char *name, char **s) { char c, *cp; if (*parptr++ != '=') { inform("missing argument to variable %s", name); return 1; } if (*parptr != '"') { for (cp = parptr; *parptr && *parptr != ':' && *parptr != ','; parptr++) continue; } else { for (cp = ++parptr; *parptr && *parptr != '"'; parptr++) if (*parptr == QUOTE) if (!*++parptr) parptr--; } c = *parptr; *parptr = 0; *s = mh_xstrdup(cp); if ((*parptr = c) == '"') parptr++; return 0; } static char * parse (void) { int c; char *cp; static char result[NAMESZ]; for (cp = result; *parptr && (cp - result < NAMESZ); parptr++) { c = *parptr; if (!isalnum (c) && c != '.' && c != '-' && c != '_' && c !='[' && c != ']') break; *cp++ = c; } *cp = '\0'; return result; } /* * Process one file/message */ static void process (char *folder, char *fname, int ofilen, int ofilec) { /* static to prevent "might be clobbered" warning from gcc 4.9.2: */ static char *cp; static FILE *fp; struct mcomp *c1; struct stat st; struct arglist *ap; /* volatile to prevent "might be clobbered" warning from gcc: */ char *volatile fname2 = fname ? fname : "(stdin)"; cp = NULL; fp = NULL; switch (setjmp (env)) { case OK: if (fname) { fp = mhl_action ? (*mhl_action) (fname) : fopen (fname, "r"); if (fp == NULL) { advise (fname, "unable to open"); exitstat++; return; } } else { fp = stdin; } if (fstat(fileno(fp), &st) == 0) { filesize = st.st_size; } else { filesize = 0; } cp = folder ? concat (folder, ":", fname2, NULL) : mh_xstrdup(fname2); if (ontty != PITTY) SIGNAL (SIGINT, intrser); mhlfile (fp, cp, ofilen, ofilec); free (cp); for (ap = arglist_head; ap; ap = ap->a_next) { fmt_free(ap->a_fmt, 0); ap->a_fmt = NULL; } if (arglist_head) fmt_free(NULL, 1); /* FALLTHRU */ default: if (ontty != PITTY) SIGNAL (SIGINT, SIG_IGN); if (mhl_action == NULL && fp != stdin && fp != NULL) fclose (fp); mh_xfree(holder.c_text); holder.c_text = NULL; free_queue (&msghd, &msgtl); for (c1 = fmthd; c1; c1 = c1->c_next) c1->c_flags &= ~HDROUTPUT; break; } } static void mhlfile (FILE *fp, char *mname, int ofilen, int ofilec) { int state, bucket; struct mcomp *c1, *c2, *c3; char **ip, name[NAMESZ], buf[NMH_BUFSIZ]; m_getfld_state_t gstate = 0; compile_filterargs(); if (forwall) { if (digest) fputs(ofilen == 1 ? delim3 : delim4, stdout); else { printf ("\n-------"); if (ofilen == 1) printf (" Forwarded Message%s", PLURALS(ofilec)); else printf (" Message %d", ofilen); printf ("\n\n"); } } else { switch (ontty) { case PITTY: if (ofilec > 1) { if (ofilen > 1) { if ((global.c_flags & CLEARSCR)) nmh_clear_screen (); else printf ("\n\n\n"); } printf (">>> %s\n\n", mname); } break; case ISTTY: strncpy (buf, "\n", sizeof(buf)); if (ofilec > 1) { if (SOprintf ("Press to list \"%s\"...", mname)) { if (ofilen > 1) printf ("\n\n\n"); printf ("Press to list \"%s\"...", mname); } fflush (stdout); buf[0] = 0; if (read (fileno (stdout), buf, sizeof(buf)) < 0) { advise ("stdout", "read"); } } if (strchr(buf, '\n')) { if ((global.c_flags & CLEARSCR)) nmh_clear_screen (); } else putchar('\n'); break; default: if (ofilec > 1) { if (ofilen > 1) { printf ("\n\n\n"); if (clearflg > 0) nmh_clear_screen (); } printf (">>> %s\n\n", mname); } break; } } 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 (!strcasecmp (name, *ip)) { while (state == FLDPLUS) { bufsz = sizeof buf; state = m_getfld (&gstate, name, buf, &bufsz, fp); fmt_appendcomp(bucket, name, buf); } break; } if (*ip) continue; for (c2 = fmthd; c2; c2 = c2->c_next) if (!strcasecmp (FENDNULL(c2->c_name), name)) break; c1 = NULL; if (!((c3 = c2 ? c2 : &global)->c_flags & SPLIT)) for (c1 = msghd; c1; c1 = c1->c_next) if (!strcasecmp (FENDNULL(c1->c_name), FENDNULL(c3->c_name))) { c1->c_text = mcomp_add (c1->c_flags, buf, c1->c_text); break; } if (c1 == NULL) c1 = add_queue (&msghd, &msgtl, name, buf, 0); while (state == FLDPLUS) { 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 (c2 == NULL) c1->c_flags |= EXTRA; continue; case BODY: case FILEEOF: row = column = 0; for (c1 = fmthd; c1; c1 = c1->c_next) { if (c1->c_flags & CLEARTEXT) { putcomp (c1, c1, ONECOMP); continue; } if (!c1->c_name || !strcasecmp (c1->c_name, "messagename")) { holder.c_text = concat ("(Message ", mname, ")\n", NULL); putcomp (c1, &holder, ONECOMP); free (holder.c_text); holder.c_text = NULL; continue; } if (!c1->c_name || !strcasecmp (c1->c_name, "extras")) { for (c2 = msghd; c2; c2 = c2->c_next) if (c2->c_flags & EXTRA) putcomp (c1, c2, TWOCOMP); continue; } if (dobody && (!c1->c_name || !strcasecmp (c1->c_name, "body"))) { if (c1->c_flags & FMTFILTER && state == BODY && formatproc != NULL) { 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); bufsz = sizeof buf; state = m_getfld (&gstate, name, holder.c_text, &bufsz, fp); } free (holder.c_text); holder.c_text = NULL; } continue; } for (c2 = msghd; c2; c2 = c2->c_next) if (!strcasecmp (FENDNULL(c2->c_name), FENDNULL(c1->c_name))) { putcomp (c1, c2, ONECOMP); if (!(c1->c_flags & SPLIT)) break; } } m_getfld_state_destroy (&gstate); return; case LENERR: case FMTERR: inform("format error in message %s", mname); exitstat++; m_getfld_state_destroy (&gstate); return; default: mhladios (NULL, "getfld() returned %d", state); } } } static int mcomp_flags (char *name) { struct pair *ap; for (ap = pairs; ap->p_name; ap++) if (!strcasecmp (ap->p_name, name)) return (ap->p_flags); return 0; } static char * mcomp_add (unsigned long flags, char *s1, char *s2) { char *dp; if (!(flags & ADDRFMT)) return add (s1, s2); if (s2 && *(dp = s2 + strlen (s2) - 1) == '\n') *dp = 0; return add (s1, add (",\n", s2)); } struct pqpair { char *pq_text; char *pq_error; struct pqpair *pq_next; }; static void mcomp_format (struct mcomp *c1, struct mcomp *c2) { int dat[5]; char *ap, *cp; char error[BUFSIZ]; struct pqpair *p, *q; struct pqpair pq; struct mailname *mp; ap = c2->c_text; c2->c_text = NULL; dat[0] = 0; dat[1] = 0; dat[2] = filesize; dat[3] = BUFSIZ - 1; dat[4] = 0; if (!(c1->c_flags & ADDRFMT)) { charstring_t scanl = charstring_create (BUFSIZ); if (c1->c_c_text) c1->c_c_text->c_text = ap; if ((cp = strrchr(ap, '\n'))) /* drop ending newline */ if (!cp[1]) *cp = 0; fmt_scan (c1->c_fmt, scanl, BUFSIZ - 1, dat, NULL); /* Don't need to append a newline, dctime() already did */ c2->c_text = charstring_buffer_copy (scanl); charstring_free (scanl); /* ap is now owned by the component struct, so do NOT free it here */ return; } (q = &pq)->pq_next = NULL; while ((cp = getname (ap))) { NEW0(p); if ((mp = getm (cp, NULL, 0, error, sizeof(error))) == NULL) { p->pq_text = mh_xstrdup(cp); p->pq_error = mh_xstrdup(error); } else { p->pq_text = getcpy (mp->m_text); mnfree (mp); } q = (q->pq_next = p); } for (p = pq.pq_next; p; p = q) { charstring_t scanl = charstring_create (BUFSIZ); char *buffer; if (c1->c_c_text) { c1->c_c_text->c_text = p->pq_text; p->pq_text = NULL; } if (c1->c_c_error) { c1->c_c_error->c_text = p->pq_error; p->pq_error = NULL; } fmt_scan (c1->c_fmt, scanl, BUFSIZ - 1, dat, NULL); buffer = charstring_buffer_copy (scanl); if (*buffer) { if (c2->c_text) c2->c_text = add (",\n", c2->c_text); if (*(cp = buffer + strlen (buffer) - 1) == '\n') *cp = 0; c2->c_text = add (buffer, c2->c_text); } charstring_free (scanl); mh_xfree(p->pq_text); mh_xfree(p->pq_error); q = p->pq_next; free(p); } c2->c_text = add ("\n", c2->c_text); free (ap); } static struct mcomp * add_queue (struct mcomp **head, struct mcomp **tail, char *name, char *text, int flags) { struct mcomp *c1; NEW0(c1); c1->c_flags = flags & ~INIT; if ((c1->c_name = name ? mh_xstrdup(name) : NULL)) c1->c_flags |= mcomp_flags (c1->c_name); c1->c_text = text ? mh_xstrdup(text) : NULL; if (flags & INIT) { if (global.c_ovtxt) c1->c_ovtxt = mh_xstrdup(global.c_ovtxt); c1->c_offset = global.c_offset; c1->c_ovoff = global. c_ovoff; c1->c_width = c1->c_length = 0; c1->c_cwidth = global.c_cwidth; c1->c_flags |= global.c_flags & GFLAGS; } if (*head == NULL) *head = c1; if (*tail != NULL) (*tail)->c_next = c1; *tail = c1; return c1; } static void free_queue (struct mcomp **head, struct mcomp **tail) { struct mcomp *c1, *c2; for (c1 = *head; c1; c1 = c2) { c2 = c1->c_next; mh_xfree(c1->c_name); mh_xfree(c1->c_text); mh_xfree(c1->c_ovtxt); mh_xfree(c1->c_nfs); if (c1->c_fmt) fmt_free (c1->c_fmt, 0); free(c1); } *head = *tail = NULL; } static void putcomp (struct mcomp *c1, struct mcomp *c2, int flag) { char *text; /* c1's text, or the name as a fallback. */ char *trimmed_prefix; int count, cchdr; char *cp; const int utf8 = strcasecmp(get_charset(), "UTF-8") == 0; if (! utf8 && flag != BODYCOMP) { /* Don't print 8-bit bytes in header field values if not in a UTF-8 locale, as required by RFC 6532. */ c1->c_flags |= FORCE7BIT; } text = c1->c_text ? c1->c_text : c1->c_name; /* Create a copy with trailing whitespace trimmed, for use with * blank lines. */ trimmed_prefix = rtrim(add(text, NULL)); cchdr = 0; lm = 0; llim = c1->c_length ? c1->c_length : -1; wid = c1->c_width ? c1->c_width : global.c_width; ovoff = (c1->c_ovoff >= 0 ? c1->c_ovoff : global.c_ovoff) + c1->c_offset; if ((ovtxt = c1->c_ovtxt ? c1->c_ovtxt : global.c_ovtxt) == NULL) ovtxt = ""; if (wid < ovoff + strlen (ovtxt) + 5) mhladios (NULL, "component: %s width(%d) too small for overflow(%d)", c1->c_name, wid, ovoff + strlen (ovtxt) + 5); onelp = NULL; if (c1->c_flags & CLEARTEXT) { putstr (c1->c_flags & RTRIM ? rtrim (c1->c_text) : c1->c_text, c1->c_flags); putstr ("\n", c1->c_flags); return; } if (c1->c_nfs && (c1->c_flags & (ADDRFMT | DATEFMT | FORMAT))) mcomp_format (c1, c2); if (c1->c_flags & CENTER) { count = (c1->c_width ? c1->c_width : global.c_width) - c1->c_offset - strlen (c2->c_text); if (!(c1->c_flags & HDROUTPUT) && !(c1->c_flags & NOCOMPONENT)) count -= strlen(text) + 2; lm = c1->c_offset + (count / 2); } else { if (c1->c_offset) lm = c1->c_offset; } if (!(c1->c_flags & HDROUTPUT) && !(c1->c_flags & NOCOMPONENT)) { if (c1->c_flags & UPPERCASE) /* uppercase component also */ to_upper(text); putstr(text, c1->c_flags); if (flag != BODYCOMP) { putstr (": ", c1->c_flags); if (!(c1->c_flags & SPLIT)) c1->c_flags |= HDROUTPUT; cchdr++; if ((count = c1->c_cwidth - strlen(text) - 2) > 0) while (count--) putstr (" ", c1->c_flags); } else c1->c_flags |= HDROUTPUT; /* for BODYCOMP */ } if (flag == TWOCOMP && !(c2->c_flags & HDROUTPUT) && !(c2->c_flags & NOCOMPONENT)) { if (c1->c_flags & UPPERCASE) to_upper(c2->c_name); putstr (c2->c_name, c1->c_flags); putstr (": ", c1->c_flags); if (!(c1->c_flags & SPLIT)) c2->c_flags |= HDROUTPUT; cchdr++; if ((count = c1->c_cwidth - strlen (c2->c_name) - 2) > 0) while (count--) putstr (" ", c1->c_flags); } if (c1->c_flags & UPPERCASE) to_upper(c2->c_text); count = 0; if (cchdr) { if (flag == TWOCOMP) count = (c1->c_cwidth >= 0) ? c1->c_cwidth : (int) strlen (c2->c_name) + 2; else count = (c1->c_cwidth >= 0) ? (size_t) c1->c_cwidth : strlen(text) + 2; } count += c1->c_offset; if ((cp = oneline (c2->c_text, c1->c_flags))) /* Output line, trimming trailing whitespace if requested. */ putstr (c1->c_flags & RTRIM ? rtrim (cp) : cp, c1->c_flags); if (term == '\n') putstr ("\n", c1->c_flags); while ((cp = oneline (c2->c_text, c1->c_flags))) { lm = count; if (flag == BODYCOMP && !(c1->c_flags & NOCOMPONENT)) { /* Output component, trimming trailing whitespace if there is no text on the line. */ if (*cp) { putstr(text, c1->c_flags); } else { putstr (trimmed_prefix, c1->c_flags); } } if (*cp) { /* Output line, trimming trailing whitespace if requested. */ putstr (c1->c_flags & RTRIM ? rtrim (cp) : cp, c1->c_flags); } if (term == '\n') putstr ("\n", c1->c_flags); } if (flag == BODYCOMP && term == '\n') c1->c_flags &= ~HDROUTPUT; /* Buffer ended on a newline */ free (trimmed_prefix); } static char * oneline (char *stuff, unsigned long flags) { int spc; char *cp, *ret; if (onelp == NULL) onelp = stuff; if (*onelp == 0) return (onelp = NULL); ret = onelp; term = 0; if (flags & COMPRESS) { for (spc = 1, cp = ret; *onelp; onelp++) if (isspace ((unsigned char) *onelp)) { if (*onelp == '\n' && (!onelp[1] || (flags & ADDRFMT))) { term = '\n'; *onelp++ = 0; break; } if (!spc) { *cp++ = ' '; spc++; } } else { *cp++ = *onelp; spc = 0; } *cp = 0; } else { while (*onelp && *onelp != '\n') onelp++; if (*onelp == '\n') { term = '\n'; *onelp++ = 0; } if (flags & LEFTADJUST) while (*ret == ' ' || *ret == '\t') ret++; } if (*onelp == 0 && term == '\n' && (flags & NONEWLINE)) term = 0; return ret; } static void putstr (char *string, unsigned long flags) { /* To not count, for the purpose of counting columns, all of the bytes of a multibyte character. */ int char_len; if (!column && lm > 0) { while (lm > 0) if (lm >= 8) { putch ('\t', flags); lm -= 8; } else { putch (' ', flags); lm--; } } lm = 0; #ifdef MULTIBYTE_SUPPORT if (mbtowc (NULL, NULL, 0)) {} /* reset shift state */ char_len = 0; #else NMH_UNUSED (char_len); #endif while (*string) { flags &= ~INVISIBLE; #ifdef MULTIBYTE_SUPPORT /* mbtowc should never return 0, because *string is non-NULL. */ if (char_len <= 0) { /* Find number of bytes in next character. */ if ((char_len = mbtowc (NULL, string, (size_t) MB_CUR_MAX)) == -1) { char_len = 1; } } else { /* Multibyte character, after the first byte. */ flags |= INVISIBLE; } --char_len; #endif putch (*string++, flags); } } static void putch (char ch, unsigned long flags) { char buf[BUFSIZ]; if (llim == 0) return; switch (ch) { case '\n': if (llim > 0) llim--; column = 0; row++; if (ontty != ISTTY || row != global.c_length) break; if (global.c_flags & BELL) putchar ('\007'); fflush (stdout); buf[0] = 0; if (read (fileno (stdout), buf, sizeof(buf)) < 0) { advise ("stdout", "read"); } if (strchr(buf, '\n')) { if (global.c_flags & CLEARSCR) nmh_clear_screen (); row = 0; } else { putchar ('\n'); row = global.c_length / 3; } return; case '\t': column |= 07; column++; break; case '\b': column--; break; case '\r': column = 0; break; default: /* * If we are forwarding this message, and the first * column contains a dash, then add a dash and a space. */ if (column == 0 && forwflg && (dashstuff >= 0) && ch == '-') { putchar ('-'); putchar (' '); } /* * Increment the character count, unless * 1) In UTF-8 locale, this is other than the last byte of a multibyte character, or * 2) In C locale, will print a non-printable character. */ if ((flags & FORCE7BIT) == 0) { /* UTF-8 locale */ if ((flags & INVISIBLE) == 0) { /* If multibyte character, its first byte only. */ ++column; } } else { /* If not an ASCII character, the replace character will be displayed. Count it. */ if (! isascii((unsigned char) ch) || isprint((unsigned char) ch)) { ++column; } } break; } if (column >= wid && (flags & NOWRAP) == 0) { putch ('\n', flags); if (ovoff > 0) lm = ovoff; putstr (FENDNULL(ovtxt), flags); putch (ch, flags); return; } if (flags & FORCE7BIT && ! isascii((unsigned char) ch)) { putchar ('?'); } else { putchar (ch); } } static void intrser (int i) { NMH_UNUSED (i); discard (stdout); putchar ('\n'); longjmp (env, DONE); } static void pipeser (int i) { NMH_UNUSED (i); mhldone (NOTOK); } static void quitser (int i) { NMH_UNUSED (i); putchar ('\n'); fflush (stdout); mhldone (NOTOK); } static void mhladios (char *what, char *fmt, ...) { va_list ap; va_start(ap, fmt); advertise (what, NULL, fmt, ap); va_end(ap); mhldone (1); } static void mhldone (int status) { exitstat = status; if (mhl_action) longjmp (mhlenv, DONE); else done (exitstat); } /* * Compile a format string used by the formatfield option and save it * for later. * * We will want the {text} (and possibly {error}) components for later, * so look for them and save them if we find them. */ static void compile_formatfield(struct mcomp *c1) { fmt_compile(c1->c_nfs, &c1->c_fmt, 1); /* * As a note to myself and any other poor bastard who is looking through * this code in the future .... * * When the format hash table is reset later on (as it almost certainly * will be), there will still be references to these components in the * compiled format instructions. Thus these component references will * be free'd when the format instructions are free'd (by fmt_free()). * * So, in other words ... don't go free'ing them yourself! */ c1->c_c_text = fmt_findcomp("text"); c1->c_c_error = fmt_findcomp("error"); } /* * Compile all of the arguments for our format list. * * Iterate through the linked list of format strings and compile them. * Note that we reset the format hash table before we start, but we do NOT * reset it between calls to fmt_compile(). * */ static void compile_filterargs (void) { struct arglist *arg = arglist_head; struct comp *cptr; char **ap; fmt_free(NULL, 1); while (arg) { fmt_compile(arg->a_nfs, &arg->a_fmt, 0); arg = arg->a_next; } /* * Search through and mark any components that are address components */ for (ap = addrcomps; *ap; ap++) { cptr = fmt_findcomp (*ap); if (cptr) cptr->c_type |= CT_ADDR; } } /* * Filter the body of a message through a specified format program */ static void filterbody (struct mcomp *c1, char *buf, int bufsz, int state, FILE *fp, m_getfld_state_t gstate) { struct mcomp holder; char name[NAMESZ]; int fdinput[2], fdoutput[2], waitstat; ssize_t cc; pid_t writerpid, filterpid; /* * Create pipes so we can communicate with our filter process. */ if (pipe(fdinput) < 0) { adios(NULL, "Unable to create input pipe"); } if (pipe(fdoutput) < 0) { adios(NULL, "Unable to create output pipe"); } /* * Here's what we're doing to do. * * - Fork ourselves and start writing data to the write side of the * input pipe (fdinput[1]). * * - Fork and exec our filter program. We set the standard input of * our filter program to be the read side of our input pipe (fdinput[0]). * Standard output is set to the write side of our output pipe * (fdoutput[1]). * * - We read from the read side of the output pipe (fdoutput[0]). * * We're forking because that's the simplest way to prevent any deadlocks. * (without doing something like switching to non-blocking I/O and using * select or poll, and I'm not interested in doing that). */ switch (writerpid = fork()) { case 0: /* * Our child process - just write to the filter input (fdinput[1]). * Close all other descriptors that we don't need. */ close(fdinput[0]); close(fdoutput[0]); close(fdoutput[1]); /* * Call m_getfld() until we're no longer in the BODY state */ while (state == BODY) { int bufsz2 = bufsz; if (write(fdinput[1], buf, strlen(buf)) < 0) { advise ("pipe output", "write"); } state = m_getfld (&gstate, name, buf, &bufsz2, fp); } /* * We should be done; time to exit. */ close(fdinput[1]); /* * Make sure we call _exit(), otherwise we may flush out the stdio * buffers that we have duplicated from the parent. */ _exit(0); case -1: adios(NULL, "Unable to fork for filter writer process"); break; } /* * Fork and exec() our filter program, after redirecting standard in * and standard out appropriately. */ switch (filterpid = fork()) { char **args, *program; struct arglist *a; int i, dat[5], s, argp; case 0: /* * Configure an argument array for us */ args = argsplit(formatproc, &program, &argp); args[argp + filter_nargs] = NULL; dat[0] = 0; dat[1] = 0; dat[2] = 0; dat[3] = BUFSIZ; dat[4] = 0; /* * Pull out each argument and scan them. */ for (a = arglist_head, i = argp; a != NULL; a = a->a_next, i++) { charstring_t scanl = charstring_create (BUFSIZ); fmt_scan(a->a_fmt, scanl, BUFSIZ, dat, NULL); args[i] = charstring_buffer_copy (scanl); charstring_free (scanl); /* * fmt_scan likes to put a trailing newline at the end of the * format string. If we have one, get rid of it. */ s = strlen(args[i]); if (args[i][s - 1] == '\n') args[i][s - 1] = '\0'; if (mhldebug) fprintf(stderr, "filterarg: fmt=\"%s\", output=\"%s\"\n", a->a_nfs, args[i]); } if (dup2(fdinput[0], STDIN_FILENO) < 0) { adios("formatproc", "Unable to dup2() standard input"); } if (dup2(fdoutput[1], STDOUT_FILENO) < 0) { adios("formatproc", "Unable to dup2() standard output"); } /* * Close everything (especially the old input and output * descriptors, since they've been dup'd to stdin and stdout), * and exec the formatproc. */ close(fdinput[0]); close(fdinput[1]); close(fdoutput[0]); close(fdoutput[1]); execvp(formatproc, args); adios(formatproc, "Unable to execute filter"); break; case -1: adios(NULL, "Unable to fork format program"); } /* * Close everything except our reader (fdoutput[0]); */ close(fdinput[0]); close(fdinput[1]); close(fdoutput[1]); /* * As we read in this data, send it to putcomp */ holder.c_text = buf; while ((cc = read(fdoutput[0], buf, bufsz - 1)) > 0) { buf[cc] = '\0'; putcomp(c1, &holder, BODYCOMP); } if (cc < 0) { adios(NULL, "reading from formatproc"); } /* * See if we got any errors along the way. I'm a little leery of calling * waitpid() without WNOHANG, but it seems to be the most correct solution. */ if (waitpid(filterpid, &waitstat, 0) < 0) { if (errno != ECHILD) { adios("filterproc", "Unable to determine status"); } } else { if (! (WIFEXITED(waitstat) && WEXITSTATUS(waitstat) == 0)) { pidstatus(waitstat, stderr, "filterproc"); } } if (waitpid(writerpid, &waitstat, 0) < 0) { if (errno != ECHILD) { adios("writer process", "Unable to determine status"); done(1); } } else { if (! (WIFEXITED(waitstat) && WEXITSTATUS(waitstat) == 0)) { pidstatus(waitstat, stderr, "writer process"); done(1); } } close(fdoutput[0]); } nmh-1.7.1-RC3/uip/mhmail000755 007761 000024 00000024504 13243042054 014756 0ustar00kenhstaff000000 000000 #! /bin/sh # # mhmail -- simple mail program # # 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. # # Emulation of compiled mhmail(1), with these differences: # * Adds -send/-nosend, -headerfield, and -attach options. # * Adds optional -to switch for recipient addresses. # * Supports all post(8) (by default, without -profile) or send(1) # (with -profile) options. # * Optionally (with -profile) obeys the users profile, including # AliasFile and send entries. # * Instead of silently not sending an empty message, notifies user # "mhmail: empty message not sent, use -body '' to force." # * The compiled mhmail dropped a trailing newline from the -body argument. # * Drops support for undocumented -queue option. usage='Usage: mhmail [-t(o)] addrs ... [switches] switches are: -at(tach) file [-at(tach) file] ... -b(ody) text -c(c) addrs ... -f(rom) addr -hea(derfield) name:value [-hea(derfield) name:value] ... -su(bject) text -r(esent) -pr(ofile) -se(nd) -nose(nd) -v(ersion) -hel(p) and all post(8)/send(1) switches mhmail with no arguments is equivalent to inc' #### 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 } help() { printf '%s\n' "$usage" #### Print the nmh intro text. ${nmhbindir}/mhparam -help | sed -n -e '/^$/,$p' exit } #### Convenience function to allow concise code below. die() { [ $# -gt 0 ] && printf '%s\n' "$1" >&2 exit 1 } bindir=`finddir $0` nmhbindir=`cd "$bindir" && pwd` nmhlibexecdir=`$nmhbindir/mhparam libexecdir` case `printf 'OK\n' | tail -n 1 2>&1` in OK) tail='tail -n ' ;; *) tail='tail -' ;; esac #### Checks for missing mandatory arguments. checkforargs() { if [ $attacharg -eq 1 ]; then die 'mhmail: missing argument to -attach' elif [ $bodyarg -eq 1 ]; then die 'mhmail: missing argument to -body' elif [ $ccarg -eq 1 -a "$cclist"x = x ]; then die 'mhmail: missing argument to -cc' elif [ $fromarg -eq 1 ]; then die 'mhmail: missing argument to -from' elif [ $headerfieldarg -eq 1 ]; then die 'mhmail: missing argument to -headerfield' elif [ $subjectarg -eq 1 ]; then die 'mhmail: missing argument to -subject' elif [ $toarg -eq 1 ]; then die 'mhmail: missing argument to -to' fi } if [ $# -eq 0 ]; then #### Emulate mhmail for reading mail. exec "$nmhbindir"/inc fi #### Go through all the switches so we can build the draft. tolist= ## To: addresses toarg=0 ## whether currently handling -to attacharg=0 ## whether currently handling -attach attachind=Attach ## attachment indicator body= ## contents of the message body bodyarg=0 ## whether currently handling -body cclist= ## Cc: addresses ccarg=0 ## whether currently handling -cc from= ## From: contents fromarg=0 ## whether currently handling -from headerfieldlist= ## header fields to be added to draft headerfieldarg=0 ## whether currently handling -headerfield mhmailswitch=0 ## whether currently handling any mhmail switch subject= ## Subject: contents subjectarg=0 ## whether currently handling -subject resent=0 ## whether resending postsendargs= ## switches to pass on to post or send post_send_switch_arg=0 ## whether currently handling a post/send switch use_send=0 ## use post (default) or send (-profile) sendsw=1 ## to send (default) or not to send for arg in "$@"; do case $arg in #### Post and send won't accept -f -or -s because they'd be #### ambiguous, so no conflicts with them. And they don't have #### -b, -c, -r, -t. For the new switches that compiled mhmail #### didn't have: let -p indicate mhmail -profile, not send #### -port. -send masks the send(1) -send switch. -attach #### masks the send(1) -attach switch. -at|-att|-atta|-attac|-attach) mhmailswitch=1 attacharg=1 use_send=1 ;; -b|-bo|-bod|-body) mhmailswitch=1; bodyarg=1 ;; -c|-cc) mhmailswitch=1; ccarg=1 ;; -f|-fr|-fro|-from) mhmailswitch=1; fromarg=1 ;; -hea|-head|-heade|-header|-headerf|-headerfi|-headerfie|-headerfiel|\ -headerfield) mhmailswitch=1; headerfieldarg=1 ;; -hel|-help) help ;; -nose|-nosen|-nosend) mhmailswitch=1; sendsw=0 ;; -p|-pr|-pro|-prof|-profi|-profil|-profile) mhmailswitch=1; use_send=1 ;; -resend) die 'mhmail: did you mean -resent instead of -resend?' ;; -r|-re|-res|-rese|-resen|-resent) mhmailswitch=1; resent=1 ;; -se|-sen|-send) mhmailswitch=1; sendsw=1 ;; -su|-sub|-subj|-subje|-subjec|-subject) mhmailswitch=1; subjectarg=1 ;; -t|-to) toarg=1; ccarg=0 ;; -v|-ve|-ver|-vers|-versi|-versio|-version) #### Cheat instead of using autoconf and make to fill in the version. "$nmhbindir"/mhpath -v | sed 's/mhpath/mhmail/'; exit ;; -*) if [ $mhmailswitch -eq 1 ]; then checkforargs mhmailswitch=0 fi post_send_switch_arg=1 postsendargs="${postsendargs:+$postsendargs }$arg" ;; *) mhmailswitch=0 if [ $bodyarg -eq 1 ]; then body="$arg " bodyarg=0 #### Allow -body "" by using just a newline for the body. [ "$body"x = x ] && body=' ' elif [ $fromarg -eq 1 ]; then from="$arg" fromarg=0 elif [ $subjectarg -eq 1 ]; then subject="$arg" subjectarg=0 elif [ $attacharg -eq 1 ]; then headerfieldlist="${headerfieldlist:+$headerfieldlist}$attachind: $arg " attacharg=0 elif [ $headerfieldarg -eq 1 ]; then #### It's not strictly necessary to have one space after #### the : that separates the header field name from the #### body, but do it to avoid surprising someone. #### Solaris sed wants the trailing newline in its input. add=`printf '%s\n' "$arg" | sed -e 's/:/: /' -e 's/: /: /'` headerfieldlist="${headerfieldlist:+$headerfieldlist}$add " headerfieldarg=0 elif [ $post_send_switch_arg -eq 1 ]; then postsendargs="${postsendargs:+$postsendargs }$arg" elif [ $ccarg -eq 1 ]; then #### ccarg can only be reset to 0 by -to. cclist="${cclist:+$cclist, }$arg" else #### An address. tolist="${tolist:+$tolist, }$arg" toarg=0 fi ;; esac done #### Check for at least one address and -from. if [ "$tolist"x = x ]; then die 'Usage: mhmail [-t(o)] addrs ... [switches]' fi if [ "$from"x = x ]; then from=`${nmhlibexecdir}/ap -format '%(localmbox)' 0` fi #### Check for missing mandatory arguments. checkforargs #### Build header. [ $resent -eq 0 ] && prefix= || prefix='Resent-' header="${prefix}To: $tolist " [ "$cclist"x = x ] || header="$header${prefix}Cc: $cclist " [ "$subject"x = x ] || header="$header${prefix}Subject: $subject " [ "$from"x = x ] || header="$header${prefix}From: $from " if [ "$headerfieldlist" ]; then header="$header$headerfieldlist" fi #### Set up a file to supply as a draft to post/send. And set a trap #### to remove it. send moves the file to a backup and can create a #### .orig file, so it will remove them, too. umask 077 tmpdir="${MHTMPDIR:-${TMPDIR:-`$nmhbindir/mhpath +`}}" tmpfilename=`cd "$tmpdir" && "${nmhlibexecdir}/mkstemp" -p mhmail` [ $? -ne 0 ] && die "mhmail: failed to create temporary file in $tmpdir" tmpfile="$tmpdir/$tmpfilename" backup_char=`"$nmhbindir"/mhparam sbackup` tmpfilebackup="$tmpdir/${backup_char}${tmpfilename}*" tmpfileresent= message_file= if [ $resent -eq 0 ]; then #### Add blank line after header if not resending. header="$header " message_file="$tmpfile" else if [ $use_send -eq 0 ]; then postsendargs="${postsendargs:+$postsendargs }-dist" message_file="$tmpfile" else #### When resending with send, tmpfile will just contain the #### Resent- header fields. "$tmpfileresent" will contain #### the message that is being resent. tmpfileresent=`"${nmhlibexecdir}/mkstemp" -d "$tmpdir" -p mhmail-resent` [ $? -ne 0 ] && die "mhmail: failed to create temporary file in $tmpdir" mhdist=1; export mhdist mhaltmsg=$tmpfileresent; export mhaltmsg message_file="$tmpfileresent" printf '' >"$message_file" || exit 2 fi fi trap "rm -f '$tmpfile' $tmpfilebackup ${tmpfileresent:+'$tmpfileresent'}" 0 if [ "$body"x = x ]; then #### First put message header in the file. printf %s "$header" >"$tmpfile" || exit 2 tmpfile_size_before=`wc -c "$message_file"` #### Now grab the body from stdin. cat >> handles blank lines #### better than body=`cat`. cat >>"$message_file" || exit 2 tmpfile_size_after=`wc -c "$message_file"` #### Don't allow an empty body (from stdin). Use string #### comparison so we don't have to strip the filename, etc. if [ "$tmpfile_size_before" = "$tmpfile_size_after" ]; then die 'mhmail: empty message not sent, use -body '"''"' to force.' fi #### Add trailing newline to body if it doesn't have one. if [ `${tail}1 "$message_file" | wc -l` -ne 1 ]; then printf '\n' >>"$message_file" || exit 2 fi else #### Add trailing newline to body if it doesn't have one. [ `printf %s "$body" | ${tail}1 | wc -l` -ne 1 ] && body="$body " if [ "$tmpfileresent" ]; then #### Put just the new message header in the file. printf %s "$header" >"$tmpfile" || exit 2 #### and the body in the file to resend. printf %s "$body" >"$tmpfileresent" || exit 2 else #### Put message header and body in the file. printf %s "$header$body" >"$tmpfile" || exit 2 fi fi if [ $sendsw -eq 0 ]; then cat "$tmpfile" else if [ $use_send -eq 0 ]; then post_or_send=`$nmhbindir/mhparam postproc` else post_or_send="$nmhbindir/send" fi if "$post_or_send" $postsendargs "$tmpfile"; then exit else status=$? mv -f "$tmpfile" dead.letter printf 'Letter saved in dead.letter\n' >&2 exit $status fi fi nmh-1.7.1-RC3/uip/mhmisc.c000644 007761 000024 00000011343 13243042054 015202 0ustar00kenhstaff000000 000000 /* mhmisc.c -- misc routines to process MIME messages * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include "../sbr/makedir.h" extern int debugsw; /* * limit actions to specified parts or content types */ int npart = 0; int ntype = 0; char *parts[NPARTS + 1]; char *types[NTYPES + 1]; int userrs = 0; static char *errs = NULL; /* * prototypes */ int part_ok (CT); int part_exact(CT ct); int type_ok (CT, int); void content_error (char *, CT, char *, ...); void flush_errors (void); int part_ok (CT ct) { char **ap; int len; /* a part is "ok", i.e., should be processed, if: - there were no -part arguments - this part is a multipart */ if (npart == 0 || ct->c_type == CT_MULTIPART) { return 1; } /* or if: - this part is a an exact match for any -part option - this part is a sub-part of any -part option */ for (ap = parts; *ap; ap++) { len = strlen(*ap); if (!strncmp (*ap, ct->c_partno, len) && (!ct->c_partno[len] || ct->c_partno[len] == '.' )) { return 1; } } return 0; } int part_exact(CT ct) { char **ap; if (!ct->c_partno) return 0; for (ap = parts; *ap; ap++) { if (!strcmp (*ap, ct->c_partno)) { return 1; } } return 0; } int type_ok (CT ct, int sP) { char **ap; char buffer[BUFSIZ]; CI ci = &ct->c_ctinfo; if (ntype == 0 || (ct->c_type == CT_MULTIPART && (sP || ct->c_subtype))) return 1; snprintf (buffer, sizeof(buffer), "%s/%s", ci->ci_type, ci->ci_subtype); for (ap = types; *ap; ap++) if (!strcasecmp (*ap, ci->ci_type) || !strcasecmp (*ap, buffer)) return 1; return 0; } /* * Returns true if this content is marked as "inline". * * Technically we should check parent content to see if they have * disposition to use as a default, but we don't right now. Maybe * later .... */ int is_inline(CT ct) { /* * If there isn't any disposition at all, it's "inline". Obviously * if it's "inline", then it's inline. RFC 2183 says if it's an unknown * disposition, treat it as 'attachment'. */ if (! ct->c_dispo_type || strcasecmp(ct->c_dispo_type, "inline") == 0) return 1; return 0; } int make_intermediates (char *file) { char *cp; for (cp = file + 1; (cp = strchr(cp, '/')); cp++) { struct stat st; *cp = '\0'; if (stat (file, &st) == NOTOK) { int answer; char *ep; if (errno != ENOENT) { advise (file, "error on directory"); losing_directory: *cp = '/'; return NOTOK; } ep = concat ("Create directory \"", file, "\"? ", NULL); answer = read_yes_or_no_if_tty (ep); free (ep); if (!answer) goto losing_directory; if (!makedir (file)) { inform("unable to create directory %s", file); goto losing_directory; } } *cp = '/'; } return OK; } /* * Construct error message for content */ void content_error (char *what, CT ct, char *fmt, ...) { va_list arglist; int i, len, buflen; char *bp, buffer[BUFSIZ]; CI ci; bp = buffer; buflen = sizeof(buffer); if (userrs && invo_name && *invo_name) { snprintf (bp, buflen, "%s: ", invo_name); len = strlen (bp); bp += len; buflen -= len; } va_start (arglist, fmt); vsnprintf (bp, buflen, fmt, arglist); len = strlen (bp); bp += len; buflen -= len; ci = &ct->c_ctinfo; if (what) { char *s; if (*what) { snprintf (bp, buflen, " %s: ", what); len = strlen (bp); bp += len; buflen -= len; } if ((s = strerror (errno))) snprintf (bp, buflen, "%s", s); else snprintf (bp, buflen, "Error %d", errno); len = strlen (bp); bp += len; buflen -= len; } i = strlen (invo_name) + 2; /* Now add content type and subtype */ snprintf (bp, buflen, "\n%*.*s(content %s/%s", i, i, "", ci->ci_type, ci->ci_subtype); len = strlen (bp); bp += len; buflen -= len; /* Now add the message/part number */ if (ct->c_file) { snprintf (bp, buflen, " in message %s", ct->c_file); len = strlen (bp); bp += len; buflen -= len; if (ct->c_partno) { snprintf (bp, buflen, ", part %s", ct->c_partno); len = strlen (bp); bp += len; buflen -= len; } } snprintf (bp, buflen, ")"); len = strlen (bp); bp += len; buflen -= len; if (userrs) { *bp++ = '\n'; *bp = '\0'; buflen--; errs = add (buffer, errs); } else { inform("%s", buffer); } } void flush_errors (void) { if (errs) { fflush (stdout); fputs(errs, stderr); free (errs); errs = NULL; } } nmh-1.7.1-RC3/uip/mhn.c000644 007761 000024 00000027362 13243042054 014514 0ustar00kenhstaff000000 000000 /* mhn.c -- display, list, cache, or store the contents of MIME messages * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #include #include #include #include #include #include "../sbr/m_maildir.h" #include "mhfree.h" #include "mhshowsbr.h" #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("realsize", 0, SIZESW) \ X("norealsize", 0, NSIZESW) \ 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", 0, RFC934SW) \ X("norfc934mode", 0, 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 /* mhmisc.c */ extern int npart; extern int ntype; extern char *parts[NPARTS + 1]; extern char *types[NTYPES + 1]; extern int userrs; int debugsw = 0; int verbosw = 0; /* * variables for mhbuild (mhn -build) */ static int buildsw = 0; static int rfc934sw = 0; /* * what action to take? */ static int cachesw = 0; static int listsw = 0; static int showsw = 0; static int storesw = 0; #define quitser pipeser /* mhparse.c */ CT parse_mime (char *); /* mhmisc.c */ int part_ok (CT); int type_ok (CT, int); void flush_errors (void); /* * static prototypes */ static void pipeser (int); int main (int argc, char **argv) { int sizesw = 1, headsw = 1, autosw = 0; int msgnum, *icachesw; char *cp, *file = NULL, *folder = NULL; char *maildir, buf[100], **argp; char **arguments; char *cwd; struct msgs_array msgs = { 0, 0, NULL }; struct msgs *mp = NULL; CT ct, *ctp; FILE *fp; mhstoreinfo_t info; if (nmh_init(argv[0], 1)) { return 1; } done=freects_done; arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; /* * Parse arguments */ while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [+folder] [msgs] [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case AUTOSW: autosw++; continue; case NAUTOSW: autosw = 0; continue; case CACHESW: cachesw++; continue; case NCACHESW: cachesw = 0; continue; case RCACHESW: icachesw = &rcachesw; goto do_cache; case WCACHESW: icachesw = &wcachesw; do_cache: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); switch (*icachesw = smatch (cp, cache_policy)) { case AMBIGSW: ambigsw (cp, cache_policy); done (1); case UNKWNSW: adios (NULL, "%s unknown", cp); default: break; } continue; case CHECKSW: checksw++; continue; case NCHECKSW: checksw = 0; continue; case HEADSW: headsw = 1; continue; case NHEADSW: headsw = 0; continue; case LISTSW: listsw = 1; continue; case NLISTSW: listsw = 0; continue; case SHOWSW: showsw = 1; continue; case NSHOWSW: showsw = 0; continue; case SIZESW: sizesw = 1; continue; case NSIZESW: sizesw = 0; continue; case STORESW: storesw = 1; continue; case NSTORESW: storesw = 0; continue; case PARTSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if (npart >= NPARTS) adios (NULL, "too many parts (starting with %s), %d max", cp, NPARTS); parts[npart++] = cp; continue; case TYPESW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if (ntype >= NTYPES) adios (NULL, "too many types (starting with %s), %d max", cp, NTYPES); types[ntype++] = cp; continue; case FILESW: if (!(cp = *argp++) || (*cp == '-' && cp[1])) adios (NULL, "missing argument to %s", argp[-2]); file = *cp == '-' ? cp : path (cp, TFILE); continue; case FORMSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); mh_xfree(formsw); formsw = getcpy (etcpath (cp)); continue; /* * Switches for moreproc/mhlproc */ case PROGSW: if (!(progsw = *argp++) || *progsw == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case NPROGSW: nomore++; continue; case LENSW: case WIDTHSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; /* * Switches for mhbuild */ case BUILDSW: buildsw = 1; continue; case NBUILDSW: buildsw = 0; continue; case RFC934SW: rfc934sw = 1; continue; case NRFC934SW: rfc934sw = -1; continue; case VERBSW: verbosw = 1; continue; case NVERBSW: verbosw = 0; continue; case DEBUGSW: debugsw = 1; continue; } } if (*cp == '+' || *cp == '@') { if (folder) adios (NULL, "only one folder at a time!"); else folder = pluspath (cp); } else app_msgarg(&msgs, cp); } /* null terminate the list of acceptable parts/types */ parts[npart] = NULL; types[ntype] = NULL; /* * Check if we've specified an additional profile */ if ((cp = getenv ("MHN"))) { if ((fp = fopen (cp, "r"))) { readconfig ((struct node **) 0, fp, cp, 0); fclose (fp); } else { admonish ("", "unable to read $MHN profile (%s)", cp); } } /* * Read the standard profile setup */ if ((fp = fopen (cp = etcpath ("mhn.defaults"), "r"))) { readconfig ((struct node **) 0, fp, cp, 0); fclose (fp); } /* Check for public cache location */ if ((cache_public = context_find (nmhcache)) && *cache_public != '/') cache_public = NULL; /* Check for private cache location */ if (!(cache_private = context_find (nmhprivcache))) cache_private = ".cache"; cache_private = getcpy (m_maildir (cache_private)); /* * Cache the current directory before we do any chdirs()'s. */ cwd = mh_xstrdup(pwd()); if (!context_find ("path")) free (path ("./", TFOLDER)); /* * Process a mhn composition file (mhn -build) */ if (buildsw) { char *vec[MAXARGS]; int vecp; if (showsw || storesw || cachesw) adios (NULL, "cannot use -build with -show, -store, -cache"); if (msgs.size < 1) adios (NULL, "need to specify a %s composition file", invo_name); if (msgs.size > 1) adios (NULL, "only one %s composition file at a time", invo_name); vecp = 0; vec[vecp++] = "mhbuild"; if (rfc934sw == 1) vec[vecp++] = "-rfc934mode"; else if (rfc934sw == -1) vec[vecp++] = "-norfc934mode"; vec[vecp++] = msgs.msgs[0]; vec[vecp] = NULL; execvp ("mhbuild", vec); fprintf (stderr, "unable to exec "); _exit (-1); } /* * Process a mhn composition file (old MH style) */ if (msgs.size == 1 && !folder && !npart && !cachesw && !showsw && !storesw && !ntype && !file && (cp = getenv ("mhdraft")) && strcmp (cp, msgs.msgs[0]) == 0) { char *vec[MAXARGS]; int vecp; vecp = 0; vec[vecp++] = "mhbuild"; if (rfc934sw == 1) vec[vecp++] = "-rfc934mode"; else if (rfc934sw == -1) vec[vecp++] = "-norfc934mode"; vec[vecp++] = cp; vec[vecp] = NULL; execvp ("mhbuild", vec); fprintf (stderr, "unable to exec "); _exit (-1); } if (file && msgs.size) adios (NULL, "cannot specify msg and file at same time!"); /* * check if message is coming from file */ if (file) { cts = mh_xcalloc(2, sizeof *cts); ctp = cts; if ((ct = parse_mime (file))) *ctp++ = ct; } else { /* * message(s) are coming from a folder */ if (!msgs.size) app_msgarg(&msgs, "cur"); if (!folder) folder = getfolder (1); maildir = m_maildir (folder); if (chdir (maildir) == NOTOK) adios (maildir, "unable to change directory to"); /* read folder and create message structure */ if (!(mp = folder_read (folder, 1))) adios (NULL, "unable to read folder %s", folder); /* check for empty folder */ if (mp->nummsg == 0) adios (NULL, "no messages in %s", folder); /* parse all the message ranges/sequences and set SELECTED */ for (msgnum = 0; msgnum < msgs.size; msgnum++) if (!m_convert (mp, msgs.msgs[msgnum])) done (1); seq_setprev (mp); /* set the previous-sequence */ cts = mh_xcalloc(mp->numsel + 1, sizeof *cts); ctp = cts; for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { if (is_selected(mp, msgnum)) { char *msgnam; msgnam = m_name (msgnum); if ((ct = parse_mime (msgnam))) *ctp++ = ct; } } } if (!*cts) done (1); /* * You can't give more than one of these flags * at a time. */ if (showsw + listsw + storesw + cachesw > 1) adios (NULL, "can only use one of -show, -list, -store, -cache at same time"); /* If no action is specified, assume -show */ if (!listsw && !showsw && !storesw && !cachesw) showsw = 1; userrs = 1; SIGNAL (SIGQUIT, quitser); SIGNAL (SIGPIPE, pipeser); /* * Get the associated umask for the relevant contents. */ for (ctp = cts; *ctp; ctp++) { struct stat st; ct = *ctp; if (type_ok (ct, 1) && !ct->c_umask) { if (stat (ct->c_file, &st) != NOTOK) ct->c_umask = ~(st.st_mode & 0777); else ct->c_umask = ~m_gmprot(); } } /* * List the message content */ if (listsw) list_all_messages (cts, headsw, sizesw, verbosw, debugsw, 0); /* * Store the message content */ if (storesw) { info = mhstoreinfo_create (cts, cwd, "always", autosw, verbosw);; store_all_messages (info); mhstoreinfo_free (info); } /* If reading from a folder, do some updating */ if (mp) { context_replace (pfolder, folder);/* update current folder */ seq_setcur (mp, mp->hghsel); /* update current message */ seq_save (mp); /* synchronize sequences */ context_save (); /* save the context file */ } /* * Cache the message content */ if (cachesw) cache_all_messages (cts); /* * Show the message content */ if (showsw) show_all_messages (cts, 0, 0, 0); /* Now free all the structures for the content */ for (ctp = cts; *ctp; ctp++) free_content (*ctp); free (cts); cts = NULL; done (0); return 1; } static void pipeser (int i) { if (i == SIGQUIT) { fflush (stdout); fprintf (stderr, "\n"); fflush (stderr); } done (1); /* NOTREACHED */ } nmh-1.7.1-RC3/uip/mhoutsbr.c000644 007761 000024 00000017454 13243042054 015576 0ustar00kenhstaff000000 000000 /* mhoutsbr.c -- routines to output MIME messages * -- given a Content structure * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #include #include #include "mhoutsbr.h" /* * static prototypes */ static int output_content (CT, FILE *); static void output_headers (CT, FILE *); static int writeExternalBody (CT, FILE *); static int write8Bit (CT, FILE *); static int writeQuoted (CT, FILE *); static int writeBase64ct (CT, FILE *); /* * Main routine to output a MIME message contained * in a Content structure, to a file. Any necessary * transfer encoding is added. */ int output_message_fp (CT ct, FILE *fp, char *file) { if (output_content (ct, fp) == NOTOK) return NOTOK; if (fflush (fp)) { advise ((file?file:""), "error writing to"); return NOTOK; } return OK; } /* * Output a Content structure to a file. */ static int output_content (CT ct, FILE *out) { int result = 0; CI ci = &ct->c_ctinfo; char *boundary = "", *cp; if ((cp = get_param(ci->ci_first_pm, "boundary", '-', 0))) boundary = cp; /* * Output all header fields for this content */ output_headers (ct, out); /* * If this is the internal content structure for a * "message/external", then we are done with the * headers (since it has no body). */ if (ct->c_ctexbody) { if (*boundary != '\0') free(boundary); return OK; } /* * Now output the content bodies. */ switch (ct->c_type) { case CT_MULTIPART: { struct multipart *m; struct part *part; if (ct->c_rfc934) putc ('\n', out); m = (struct multipart *) ct->c_ctparams; if (m->mp_content_before) { fputs(m->mp_content_before, out); } for (part = m->mp_parts; part; part = part->mp_next) { CT p = part->mp_part; fprintf (out, "\n--%s\n", boundary); if (output_content (p, out) == NOTOK) { if (*boundary != '\0') free(boundary); return NOTOK; } } fprintf (out, "\n--%s--\n", boundary); if (m->mp_content_after) { fputs(m->mp_content_after, out); } } break; case CT_MESSAGE: putc ('\n', out); if (ct->c_subtype == MESSAGE_EXTERNAL) { struct exbody *e; e = (struct exbody *) ct->c_ctparams; if (output_content (e->eb_content, out) == NOTOK) return NOTOK; /* output phantom body for access-type "mail-server" */ if (e->eb_body) writeExternalBody (ct, out); } else { result = write8Bit (ct, out); } break; /* * Handle discrete types (text/application/audio/image/video) */ default: switch (ct->c_encoding) { case CE_7BIT: /* Special case: if this is a non-MIME message with no body, don't emit the newline that would appear between the headers and body. In that case, the call to write8Bit() shouldn't be needed, but is harmless. */ if (ct->c_ctinfo.ci_first_pm != NULL || ct->c_begin == 0 || ct->c_begin != ct->c_end) { putc ('\n', out); } result = write8Bit (ct, out); break; case CE_8BIT: putc ('\n', out); result = write8Bit (ct, out); break; case CE_QUOTED: putc ('\n', out); result = writeQuoted (ct, out); break; case CE_BASE64: putc ('\n', out); result = writeBase64ct (ct, out); break; case CE_BINARY: if (ct->c_type == CT_TEXT) { /* So that mhfixmsg can decode to binary text. */ putc ('\n', out); result = write8Bit (ct, out); } else { inform("can't handle binary transfer encoding in content"); result = NOTOK; } break; default: inform("unknown transfer encoding in content"); result = NOTOK; break; } break; } if (*boundary != '\0') free(boundary); return result; } /* * Output all the header fields for a content */ static void output_headers (CT ct, FILE *out) { HF hp; hp = ct->c_first_hf; while (hp) { fprintf (out, "%s:%s", hp->name, hp->value); hp = hp->next; } } /* * Write the phantom body for access-type "mail-server". */ static int writeExternalBody (CT ct, FILE *out) { char *cp, *dp; struct exbody *e = (struct exbody *) ct->c_ctparams; putc ('\n', out); for (cp = e->eb_body; *cp; cp++) { CT ct2 = e->eb_content; CI ci2 = &ct2->c_ctinfo; if (*cp == '\\') { switch (*++cp) { case 'I': if (ct2->c_id) { dp = trimcpy (ct2->c_id); fputs (dp, out); free (dp); } continue; case 'N': dp = get_param(ci2->ci_first_pm, "name", '_', 0); if (dp) { fputs (dp, out); free (dp); } continue; case 'T': fprintf (out, "%s/%s", ci2->ci_type, ci2->ci_subtype); dp = output_params(strlen(ci2->ci_type) + strlen(ci2->ci_subtype) + 1, ci2->ci_first_pm, NULL, 0); if (dp) { fputs (dp, out); free (dp); } continue; case 'n': putc ('\n', out); continue; case 't': putc ('\t', out); continue; case '\0': cp--; break; case '\\': case '"': break; default: putc ('\\', out); break; } } putc (*cp, out); } putc ('\n', out); return OK; } /* * Output a content without any transfer encoding */ static int write8Bit (CT ct, FILE *out) { int fd; size_t inbytes; char c, *file, buffer[BUFSIZ]; CE ce = &ct->c_cefile; file = NULL; if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK) return NOTOK; c = '\n'; while ((inbytes = fread (buffer, 1, sizeof buffer, ce->ce_fp)) > 0) { c = buffer[inbytes - 1]; if (fwrite (buffer, 1, inbytes, out) < inbytes) { advise ("write8Bit", "fwrite"); } } if (c != '\n') putc ('\n', out); (*ct->c_ceclosefnx) (ct); return OK; } /* * Output a content using quoted-printable */ static int writeQuoted (CT ct, FILE *out) { int fd; char *cp, *file; char c = '\0'; CE ce = &ct->c_cefile; int n = 0; char *bufp = NULL; size_t buflen; ssize_t gotlen; file = NULL; if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK) return NOTOK; while ((gotlen = getline(&bufp, &buflen, ce->ce_fp)) != -1) { cp = bufp + gotlen - 1; if ((c = *cp) == '\n') gotlen--; /* * if the line starts with "From ", encode the 'F' so it * doesn't falsely match an mbox delimiter. */ cp = bufp; if (gotlen >= 5 && has_prefix(cp, "From ")) { fprintf (out, "=%02X", 'F'); cp++; n += 3; } for (; cp < bufp + gotlen; cp++) { if (n > CPERLIN - 3) { fputs ("=\n", out); n = 0; } switch (*cp) { case ' ': case '\t': putc (*cp, out); n++; break; default: if (*cp < '!' || *cp > '~') goto three_print; putc (*cp, out); n++; break; case '=': three_print: fprintf (out, "=%02X", *cp & 0xff); n += 3; break; } } if (c == '\n') { if (cp > bufp && (*--cp == ' ' || *cp == '\t')) fputs ("=\n", out); putc ('\n', out); n = 0; } } if (c != '\n') putc ('\n', out); (*ct->c_ceclosefnx) (ct); free (bufp); return OK; } /* * Output a content using base64 */ static int writeBase64ct (CT ct, FILE *out) { int fd, result; char *file; CE ce = &ct->c_cefile; file = NULL; if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK) return NOTOK; result = writeBase64aux (ce->ce_fp, out, ct->c_type == CT_TEXT && ct->c_ctparams ? ((struct text *) ct->c_ctparams)->lf_line_endings == 0 : 0); (*ct->c_ceclosefnx) (ct); return result; } nmh-1.7.1-RC3/uip/mhoutsbr.h000644 007761 000024 00000000447 13205305706 015601 0ustar00kenhstaff000000 000000 /* mhoutsbr.h -- output MIME messages from a Content structure. * * This code is Copyright (c) 2017, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ int output_message_fp(CT ct, FILE *fp, char *file); nmh-1.7.1-RC3/uip/mhparam.c000644 007761 000024 00000013510 13243042054 015345 0ustar00kenhstaff000000 000000 /* mhparam.c -- print mh_profile values * * Originally contributed by * Jeffrey C Honig * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #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 extern char *mhbindir; extern char *mhlibexecdir; extern char *mhetcdir; extern char *mhdocdir; static char *sbackup = BACKUP_PREFIX; static char *datalocking = "fcntl"; static char *localmbox = ""; static int localmbox_primed = 0; extern char *spoollocking; static char *sasl = #ifdef CYRUS_SASL "cyrus_sasl"; #else ""; #endif static char *tls = #ifdef TLS_SUPPORT "tls"; #else ""; #endif static char *mimetypeproc = #ifdef MIMETYPEPROC MIMETYPEPROC; #else ""; #endif static char *mimeencodingproc = #ifdef MIMEENCODINGPROC MIMEENCODINGPROC; #else ""; #endif static char *iconv = #ifdef HAVE_ICONV "iconv"; #else ""; #endif static char *oauth = #ifdef OAUTH_SUPPORT "oauth"; #else ""; #endif struct proc { char *p_name; char **p_field; }; static struct proc procs [] = { { "context", &context }, { "mh-sequences", &mh_seq }, { "buildmimeproc", &buildmimeproc }, { "fileproc", &fileproc }, { "foldprot", &foldprot }, { "formatproc", &formatproc }, { "incproc", &incproc }, { "lproc", &lproc }, { "mailproc", &mailproc }, { "mhlproc", &mhlproc }, { "mimetypeproc", &mimetypeproc }, { "mimeencodingproc", &mimeencodingproc }, { "moreproc", &moreproc }, { "msgprot", &msgprot }, { "packproc", &packproc }, { "postproc", &postproc }, { "rmmproc", &rmmproc }, { "sendproc", &sendproc }, { "showmimeproc", &showmimeproc }, { "showproc", &showproc }, { "version", &version_num }, { "whatnowproc", &whatnowproc }, { "whomproc", &whomproc }, { "bindir", &mhbindir }, { "libexecdir", &mhlibexecdir }, { "libdir", &mhlibexecdir }, { "etcdir", &mhetcdir }, { "docdir", &mhdocdir }, { "localmbox", &localmbox }, { "sbackup", &sbackup }, { "datalocking", &datalocking }, { "spoollocking", &spoollocking }, { "iconv", &iconv }, { "oauth", &oauth }, { "sasl", &sasl }, { "tls", &tls }, { NULL, NULL }, }; /* * static prototypes */ static char *p_find(char *); int main(int argc, char **argv) { int i, compp = 0, missed = 0; int all = 0, debug = 0; int components = -1; char *cp, buf[BUFSIZ], **argp; char **arguments, *comps[MAXARGS]; if (nmh_init(argv[0], 2)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [profile-components] [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case COMPSW: components = 1; break; case NCOMPSW: components = 0; break; case ALLSW: all = 1; break; case DEBUGSW: debug = 1; break; } } else { comps[compp++] = cp; if (strcmp("localmbox", cp) == 0 && ! localmbox_primed) { localmbox = getlocalmbox(); localmbox_primed = 1; } } } if (all) { struct node *np; if (compp) inform("profile-components ignored with -all"); if (components >= 0) inform("-%scomponents ignored with -all", components ? "" : "no"); /* Print all entries in context/profile list. That does not include entries in mts.conf, such as spoollocking. */ for (np = m_defs; np; np = np->n_next) printf("%s: %s\n", np->n_name, np->n_field); } if (debug) { struct proc *ps; /* In case datalocking was set in profile. */ if ((cp = context_find("datalocking"))) { datalocking = cp; } /* In case spoollocking was set in mts.conf. */ mts_init(); /* Also set localmbox here */ if (! localmbox_primed) { localmbox = getlocalmbox(); localmbox_primed = 1; } /* * Print the current value of everything in * procs array. This will show their current * value (as determined after context is read). */ for (ps = procs; ps->p_name; ps++) printf ("%s: %s\n", ps->p_name, FENDNULL(*ps->p_field)); } if (! all) { if (components < 0) components = compp > 1; for (i = 0; i < compp; i++) { char *value; if (! strcmp ("spoollocking", comps[i])) { /* In case spoollocking was set in mts.conf. */ mts_init(); } value = context_find (comps[i]); if (!value) value = p_find (comps[i]); if (value) { if (components) printf("%s: ", comps[i]); puts(value); } else if (missed < 120) missed++; } } done (missed); return 1; } static char * p_find(char *str) { struct proc *ps; for (ps = procs; ps->p_name; ps++) if (!strcasecmp (ps->p_name, str)) return (*ps->p_field); return NULL; } nmh-1.7.1-RC3/uip/mhparse.c000644 007761 000024 00000301565 13243042054 015371 0ustar00kenhstaff000000 000000 /* mhparse.c -- routines to parse the contents of MIME messages * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #include #include #include #include "../sbr/m_mktemp.h" #include "mhfree.h" #ifdef HAVE_ICONV # include #endif /* HAVE_ICONV */ extern int debugsw; int checksw = 0; /* check Content-MD5 field */ /* * These are for mhfixmsg to: * 1) Instruct parser not to detect invalid Content-Transfer-Encoding * in a multipart. * 2) Suppress the warning about bogus multipart content, and report it. * 3) Suppress the warning about extraneous trailing ';' in header parameter * lists. */ int skip_mp_cte_check; int suppress_bogus_mp_content_warning; int bogus_mp_content; int suppress_extraneous_trailing_semicolon_warning; /* * By default, suppress warning about multiple MIME-Version header fields. */ int suppress_multiple_mime_version_warning = 1; /* list of preferred type/subtype pairs, for -prefer */ char *preferred_types[NPREFS], *preferred_subtypes[NPREFS]; int npreferred; /* * Structures for TEXT messages */ struct k2v SubText[] = { { "plain", TEXT_PLAIN }, { "richtext", TEXT_RICHTEXT }, /* defined in RFC 1341 */ { "enriched", TEXT_ENRICHED }, /* defined in RFC 1896 */ { NULL, TEXT_UNKNOWN } /* this one must be last! */ }; /* Charset[] removed -- yozo. Mon Oct 8 01:03:41 JST 2012 */ /* * Structures for MULTIPART messages */ struct k2v SubMultiPart[] = { { "mixed", MULTI_MIXED }, { "alternative", MULTI_ALTERNATE }, { "digest", MULTI_DIGEST }, { "parallel", MULTI_PARALLEL }, { "related", MULTI_RELATED }, { NULL, MULTI_UNKNOWN } /* this one must be last! */ }; /* * Structures for MESSAGE messages */ struct k2v SubMessage[] = { { "rfc822", MESSAGE_RFC822 }, { "partial", MESSAGE_PARTIAL }, { "external-body", MESSAGE_EXTERNAL }, { NULL, MESSAGE_UNKNOWN } /* this one must be last! */ }; /* * Structure for APPLICATION messages */ struct k2v SubApplication[] = { { "octet-stream", APPLICATION_OCTETS }, { "postscript", APPLICATION_POSTSCRIPT }, { NULL, APPLICATION_UNKNOWN } /* this one must be last! */ }; /* * Mapping of names of CTE types in mhbuild directives */ static struct k2v EncodingType[] = { { "8bit", CE_8BIT }, { "qp", CE_QUOTED }, { "q-p", CE_QUOTED }, { "quoted-printable", CE_QUOTED }, { "b64", CE_BASE64 }, { "base64", CE_BASE64 }, { NULL, 0 }, }; /* mhmisc.c */ int part_ok (CT); int type_ok (CT, int); void content_error (char *, CT, char *, ...); /* * static prototypes */ static CT get_content (FILE *, char *, int); static int get_comment (const char *, const char *, char **, char **); static int InitGeneric (CT); static int InitText (CT); static int InitMultiPart (CT); static void reverse_parts (CT); static void prefer_parts(CT ct); static int InitMessage (CT); static int InitApplication (CT); static int init_encoding (CT, OpenCEFunc); static unsigned long size_encoding (CT); static int InitBase64 (CT); static int openBase64 (CT, char **); static int InitQuoted (CT); static int openQuoted (CT, char **); static int Init7Bit (CT); static int openExternal (CT, CT, CE, char **, int *); static int InitFile (CT); static int openFile (CT, char **); static int InitFTP (CT); static int openFTP (CT, char **); static int InitMail (CT); static int openMail (CT, char **); static int readDigest (CT, char *); static int get_leftover_mp_content (CT, int); static int InitURL (CT); static int openURL (CT, char **); static int parse_header_attrs (const char *, const char *, char **, PM *, PM *, char **); static size_t param_len(PM, int, size_t, int *, int *, size_t *); static size_t normal_param(PM, char *, size_t, size_t, size_t); static int get_dispo (char *, CT, int); struct str2init str2cts[] = { { "application", CT_APPLICATION, InitApplication }, { "audio", CT_AUDIO, InitGeneric }, { "image", CT_IMAGE, InitGeneric }, { "message", CT_MESSAGE, InitMessage }, { "multipart", CT_MULTIPART, InitMultiPart }, { "text", CT_TEXT, InitText }, { "video", CT_VIDEO, InitGeneric }, { NULL, CT_EXTENSION, NULL }, /* these two must be last! */ { NULL, CT_UNKNOWN, NULL }, }; struct str2init str2ces[] = { { "base64", CE_BASE64, InitBase64 }, { "quoted-printable", CE_QUOTED, InitQuoted }, { "8bit", CE_8BIT, Init7Bit }, { "7bit", CE_7BIT, Init7Bit }, { "binary", CE_BINARY, Init7Bit }, { NULL, CE_EXTENSION, NULL }, /* these two must be last! */ { NULL, CE_UNKNOWN, NULL }, }; /* * NOTE WELL: si_key MUST NOT have value of NOTOK * * si_key is 1 if access method is anonymous. */ struct str2init str2methods[] = { { "afs", 1, InitFile }, { "anon-ftp", 1, InitFTP }, { "ftp", 0, InitFTP }, { "local-file", 0, InitFile }, { "mail-server", 0, InitMail }, { "url", 0, InitURL }, { NULL, 0, NULL } }; /* * Main entry point for parsing a MIME message or file. * It returns the Content structure for the top level * entity in the file. */ CT parse_mime (char *file) { int is_stdin; char buffer[BUFSIZ]; FILE *fp; CT ct; size_t n; struct stat statbuf; bogus_mp_content = 0; /* * Check if file is actually standard input */ if ((is_stdin = !(strcmp (file, "-")))) { char *tfile = m_mktemp2(NULL, invo_name, NULL, &fp); if (tfile == NULL) { advise("mhparse", "unable to create temporary file in %s", get_temp_dir()); return NULL; } file = mh_xstrdup(tfile); while ((n = fread(buffer, 1, sizeof(buffer), stdin)) > 0) { if (fwrite(buffer, 1, n, fp) != n) { (void) m_unlink (file); advise (file, "error copying to temporary file"); return NULL; } } fflush (fp); if (ferror (stdin)) { (void) m_unlink (file); advise ("stdin", "error reading"); return NULL; } if (ferror (fp)) { (void) m_unlink (file); advise (file, "error writing"); return NULL; } fseek (fp, 0L, SEEK_SET); } else if (stat (file, &statbuf) == NOTOK) { advise (file, "unable to stat"); return NULL; } else if (S_ISDIR(statbuf.st_mode)) { /* Don't try to parse a directory. */ inform("%s is a directory", file); return NULL; } else if ((fp = fopen (file, "r")) == NULL) { advise (file, "unable to read"); return NULL; } if (!(ct = get_content (fp, file, 1))) { if (is_stdin) (void) m_unlink (file); inform("unable to decode %s", file); return NULL; } if (is_stdin) ct->c_unlink = 1; /* temp file to remove */ ct->c_fp = NULL; if (ct->c_end == 0L) { fseek (fp, 0L, SEEK_END); ct->c_end = ftell (fp); } if (ct->c_ctinitfnx && (*ct->c_ctinitfnx) (ct) == NOTOK) { fclose (fp); free_content (ct); return NULL; } fclose (fp); return ct; } /* * Main routine for reading/parsing the headers * of a message content. * * toplevel = 1 # we are at the top level of the message * toplevel = 0 # we are inside message type or multipart type * # other than multipart/digest * toplevel = -1 # we are inside multipart/digest * NB: on failure we will fclose(in)! */ static CT get_content (FILE *in, char *file, int toplevel) { int compnum, state; char buf[NMH_BUFSIZ], name[NAMESZ]; char *np, *vp; CT ct; HF hp; m_getfld_state_t gstate = 0; /* allocate the content structure */ NEW0(ct); ct->c_fp = in; ct->c_file = add (file, NULL); ct->c_begin = ftell (ct->c_fp) + 1; /* * Parse the header fields for this * content into a linked list. */ 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: compnum++; /* get copies of the buffers */ np = mh_xstrdup(name); vp = mh_xstrdup(buf); /* if necessary, get rest of field */ while (state == FLDPLUS) { 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, to see if this isn't the last header field */ ct->c_begin = ftell (in) + 1; continue; case BODY: /* There are two cases. The unusual one is when there is no * blank line between the headers and the body. This is * indicated by the name of the header starting with `:'. * * For both cases, normal first, `1' is the desired c_begin * file position for the start of the body, and `2' is the * file position when buf is returned. * * f o o : b a r \n \n b o d y \n bufsz = 6 * 1 2 move -5 * f o o : b a r \n b o d y \n bufsz = 4 * 1 2 move -4 * * For the normal case, bufsz includes the * header-terminating `\n', even though it is not in buf, * but bufsz isn't affected when it's missing in the unusual * case. */ if (name[0] == ':') { ct->c_begin = ftell(in) - bufsz; } else { ct->c_begin = ftell (in) - (bufsz - 1); } break; case FILEEOF: ct->c_begin = ftell (in); break; case LENERR: case FMTERR: adios (NULL, "message format error in component #%d", compnum); default: adios (NULL, "getfld() returned %d", state); } /* break out of the loop */ break; } m_getfld_state_destroy (&gstate); /* * Read the content headers. We will parse the * MIME related header fields into their various * structures and set internal flags related to * content type/subtype, etc. */ hp = ct->c_first_hf; /* start at first header field */ while (hp) { /* Get MIME-Version field */ if (!strcasecmp (hp->name, VRSN_FIELD)) { int ucmp; char c, *cp, *dp; char *vrsn; vrsn = add (hp->value, NULL); /* Now, cleanup this field */ cp = vrsn; while (isspace ((unsigned char) *cp)) cp++; for (dp = strchr(cp, '\n'); dp; dp = strchr(dp, '\n')) *dp++ = ' '; for (dp = cp + strlen (cp) - 1; dp >= cp; dp--) if (!isspace ((unsigned char) *dp)) break; *++dp = '\0'; if (debugsw) fprintf (stderr, "%s: %s\n", VRSN_FIELD, cp); if (*cp == '(' && get_comment (ct->c_file, VRSN_FIELD, &cp, NULL) == NOTOK) goto out; for (dp = cp; istoken (*dp); dp++) continue; c = *dp; *dp = '\0'; ucmp = !strcasecmp (cp, VRSN_VALUE); *dp = c; if (!ucmp) { inform("message %s has unknown value for %s: field (%s), continuing...", ct->c_file, VRSN_FIELD, cp); } if (!ct->c_vrsn) { ct->c_vrsn = vrsn; } else { if (! suppress_multiple_mime_version_warning) inform("message %s has multiple %s: fields", ct->c_file, VRSN_FIELD); free(vrsn); } } else if (!strcasecmp (hp->name, TYPE_FIELD)) { /* Get Content-Type field */ struct str2init *s2i; CI ci = &ct->c_ctinfo; /* Check if we've already seen a Content-Type header */ if (ct->c_ctline) { inform("message %s has multiple %s: fields", ct->c_file, TYPE_FIELD); goto next_header; } /* Parse the Content-Type field */ if (get_ctinfo (hp->value, ct, 0) == NOTOK) goto out; /* * Set the Init function and the internal * flag for this content type. */ for (s2i = str2cts; s2i->si_key; s2i++) if (!strcasecmp (ci->ci_type, s2i->si_key)) break; if (!s2i->si_key && !uprf (ci->ci_type, "X-")) s2i++; ct->c_type = s2i->si_val; ct->c_ctinitfnx = s2i->si_init; } else if (!strcasecmp (hp->name, ENCODING_FIELD)) { /* Get Content-Transfer-Encoding field */ char c, *cp, *dp; struct str2init *s2i; /* * Check if we've already seen the * Content-Transfer-Encoding field */ if (ct->c_celine) { inform("message %s has multiple %s: fields", ct->c_file, ENCODING_FIELD); goto next_header; } /* get copy of this field */ ct->c_celine = cp = add (hp->value, NULL); while (isspace ((unsigned char) *cp)) cp++; for (dp = cp; istoken (*dp); dp++) continue; c = *dp; *dp = '\0'; /* * Find the internal flag and Init function * for this transfer encoding. */ for (s2i = str2ces; s2i->si_key; s2i++) if (!strcasecmp (cp, s2i->si_key)) break; if (!s2i->si_key && !uprf (cp, "X-")) s2i++; *dp = c; ct->c_encoding = s2i->si_val; /* Call the Init function for this encoding */ if (s2i->si_init && (*s2i->si_init) (ct) == NOTOK) goto out; } else if (!strcasecmp (hp->name, MD5_FIELD)) { /* Get Content-MD5 field */ char *cp, *dp, *ep; if (!checksw) goto next_header; if (ct->c_digested) { inform("message %s has multiple %s: fields", ct->c_file, MD5_FIELD); goto next_header; } ep = cp = add (hp->value, NULL); /* get a copy */ while (isspace ((unsigned char) *cp)) cp++; for (dp = strchr(cp, '\n'); dp; dp = strchr(dp, '\n')) *dp++ = ' '; for (dp = cp + strlen (cp) - 1; dp >= cp; dp--) if (!isspace ((unsigned char) *dp)) break; *++dp = '\0'; if (debugsw) fprintf (stderr, "%s: %s\n", MD5_FIELD, cp); if (*cp == '(' && get_comment (ct->c_file, MD5_FIELD, &cp, NULL) == NOTOK) { free (ep); goto out; } for (dp = cp; *dp && !isspace ((unsigned char) *dp); dp++) continue; *dp = '\0'; readDigest (ct, cp); free (ep); ct->c_digested++; } else if (!strcasecmp (hp->name, ID_FIELD)) { /* Get Content-ID field */ ct->c_id = add (hp->value, ct->c_id); } else if (!strcasecmp (hp->name, DESCR_FIELD)) { /* Get Content-Description field */ ct->c_descr = add (hp->value, ct->c_descr); } else if (!strcasecmp (hp->name, DISPO_FIELD)) { /* Get Content-Disposition field */ if (get_dispo(hp->value, ct, 0) == NOTOK) goto out; } next_header: hp = hp->next; /* next header field */ } /* * Check if we saw a Content-Type field. * If not, then assign a default value for * it, and the Init function. */ if (!ct->c_ctline) { /* * If we are inside a multipart/digest message, * so default type is message/rfc822 */ if (toplevel < 0) { if (get_ctinfo ("message/rfc822", ct, 0) == NOTOK) goto out; ct->c_type = CT_MESSAGE; ct->c_ctinitfnx = InitMessage; } else { /* * Else default type is text/plain */ if (get_ctinfo ("text/plain", ct, 0) == NOTOK) goto out; ct->c_type = CT_TEXT; ct->c_ctinitfnx = InitText; } } /* Use default Transfer-Encoding, if necessary */ if (!ct->c_celine) { ct->c_encoding = CE_7BIT; Init7Bit (ct); } return ct; out: free_content (ct); return NULL; } /* * small routine to add header field to list */ int add_header (CT ct, char *name, char *value) { HF hp; /* allocate header field structure */ NEW(hp); /* link data into header structure */ hp->name = name; hp->value = value; hp->next = NULL; /* link header structure into the list */ if (ct->c_first_hf == NULL) { ct->c_first_hf = hp; /* this is the first */ ct->c_last_hf = hp; } else { ct->c_last_hf->next = hp; /* add it to the end */ ct->c_last_hf = hp; } return 0; } /* * Parse Content-Type line and (if `magic' is non-zero) mhbuild composition * directives. Fills in the information of the CTinfo structure. */ int get_ctinfo (char *cp, CT ct, int magic) { char *dp; char c; CI ci; int status; ci = &ct->c_ctinfo; /* store copy of Content-Type line */ cp = ct->c_ctline = add (cp, NULL); while (isspace ((unsigned char) *cp)) /* trim leading spaces */ cp++; /* change newlines to spaces */ for (dp = strchr(cp, '\n'); dp; dp = strchr(dp, '\n')) *dp++ = ' '; /* trim trailing spaces */ for (dp = cp + strlen (cp) - 1; dp >= cp; dp--) if (!isspace ((unsigned char) *dp)) break; *++dp = '\0'; if (debugsw) fprintf (stderr, "%s: %s\n", TYPE_FIELD, cp); if (*cp == '(' && get_comment (ct->c_file, TYPE_FIELD, &cp, &ci->ci_comment) == NOTOK) return NOTOK; for (dp = cp; istoken (*dp); dp++) continue; c = *dp; *dp = '\0'; ci->ci_type = mh_xstrdup(cp); /* store content type */ *dp = c; cp = dp; if (!*ci->ci_type) { inform("invalid %s: field in message %s (empty type)", TYPE_FIELD, ct->c_file); return NOTOK; } to_lower(ci->ci_type); while (isspace ((unsigned char) *cp)) cp++; if (*cp == '(' && get_comment (ct->c_file, TYPE_FIELD, &cp, &ci->ci_comment) == NOTOK) return NOTOK; if (*cp != '/') { if (!magic) ci->ci_subtype = mh_xstrdup(""); goto magic_skip; } cp++; while (isspace ((unsigned char) *cp)) cp++; if (*cp == '(' && get_comment (ct->c_file, TYPE_FIELD, &cp, &ci->ci_comment) == NOTOK) return NOTOK; for (dp = cp; istoken (*dp); dp++) continue; c = *dp; *dp = '\0'; ci->ci_subtype = mh_xstrdup(cp); /* store the content subtype */ *dp = c; cp = dp; if (!*ci->ci_subtype) { inform("invalid %s: field in message %s (empty subtype for \"%s\")", TYPE_FIELD, ct->c_file, ci->ci_type); return NOTOK; } to_lower(ci->ci_subtype); magic_skip: while (isspace ((unsigned char) *cp)) cp++; if (*cp == '(' && get_comment (ct->c_file, TYPE_FIELD, &cp, &ci->ci_comment) == NOTOK) return NOTOK; if ((status = parse_header_attrs (ct->c_file, TYPE_FIELD, &cp, &ci->ci_first_pm, &ci->ci_last_pm, &ci->ci_comment)) != OK) { return status == NOTOK ? NOTOK : OK; } /* * Get any given in buffer */ if (magic && *cp == '<') { mh_xfree(ct->c_id); ct->c_id = NULL; if (!(dp = strchr(ct->c_id = ++cp, '>'))) { inform("invalid ID in message %s", ct->c_file); return NOTOK; } c = *dp; *dp = '\0'; if (*ct->c_id) ct->c_id = concat ("<", ct->c_id, ">\n", NULL); else ct->c_id = NULL; *dp++ = c; cp = dp; while (isspace ((unsigned char) *cp)) cp++; } /* * Get any [Content-Description] given in buffer. */ if (magic && *cp == '[') { ct->c_descr = ++cp; for (dp = cp + strlen (cp) - 1; dp >= cp; dp--) if (*dp == ']') break; if (dp < cp) { inform("invalid description in message %s", ct->c_file); ct->c_descr = NULL; return NOTOK; } c = *dp; *dp = '\0'; if (*ct->c_descr) ct->c_descr = concat (ct->c_descr, "\n", NULL); else ct->c_descr = NULL; *dp++ = c; cp = dp; while (isspace ((unsigned char) *cp)) cp++; } /* * Get any {Content-Disposition} given in buffer. */ if (magic && *cp == '{') { ++cp; for (dp = cp + strlen (cp) - 1; dp >= cp; dp--) if (*dp == '}') break; if (dp < cp) { inform("invalid disposition in message %s", ct->c_file); ct->c_dispo = NULL; return NOTOK; } c = *dp; *dp = '\0'; if (get_dispo(cp, ct, 1) != OK) return NOTOK; *dp++ = c; cp = dp; while (isspace ((unsigned char) *cp)) cp++; } /* * Get any extension directives (right now just the content transfer * encoding, but maybe others) that we care about. */ if (magic && *cp == '*') { /* * See if it's a CTE we match on */ struct k2v *kv; dp = ++cp; while (*cp != '\0' && ! isspace((unsigned char) *cp)) cp++; if (dp == cp) { inform("invalid null transfer encoding specification"); return NOTOK; } if (*cp != '\0') *cp++ = '\0'; ct->c_reqencoding = CE_UNKNOWN; for (kv = EncodingType; kv->kv_key; kv++) { if (strcasecmp(kv->kv_key, dp) == 0) { ct->c_reqencoding = kv->kv_value; break; } } if (ct->c_reqencoding == CE_UNKNOWN) { inform("invalid CTE specification: \"%s\"", dp); return NOTOK; } while (isspace ((unsigned char) *cp)) cp++; } /* * Check if anything is left over */ if (*cp) { if (magic) { ci->ci_magic = mh_xstrdup(cp); /* If there is a Content-Disposition header and it doesn't have a *filename=, extract it from the magic contents. The r1bindex call skips any leading directory components. */ if (ct->c_dispo_type && !get_param(ct->c_dispo_first, "filename", '_', 1)) { add_param(&ct->c_dispo_first, &ct->c_dispo_last, "filename", r1bindex(ci->ci_magic, '/'), 0); } } else inform("extraneous information in message %s's %s: field\n%*s(%s)", ct->c_file, TYPE_FIELD, strlen(invo_name) + 2, "", cp); } return OK; } /* * Parse out a Content-Disposition header. A lot of this is cribbed from * get_ctinfo(). */ static int get_dispo (char *cp, CT ct, int buildflag) { char *dp, *dispoheader; char c; int status; /* * Save the whole copy of the Content-Disposition header, unless we're * processing a mhbuild directive. A NULL c_dispo will be a flag to * mhbuild that the disposition header needs to be generated at that * time. */ dispoheader = cp = add(cp, NULL); while (isspace ((unsigned char) *cp)) /* trim leading spaces */ cp++; /* change newlines to spaces */ for (dp = strchr(cp, '\n'); dp; dp = strchr(dp, '\n')) *dp++ = ' '; /* trim trailing spaces */ for (dp = cp + strlen (cp) - 1; dp >= cp; dp--) if (!isspace ((unsigned char) *dp)) break; *++dp = '\0'; if (debugsw) fprintf (stderr, "%s: %s\n", DISPO_FIELD, cp); if (*cp == '(' && get_comment (ct->c_file, DISPO_FIELD, &cp, NULL) == NOTOK) { free(dispoheader); return NOTOK; } for (dp = cp; istoken (*dp); dp++) continue; c = *dp; *dp = '\0'; ct->c_dispo_type = mh_xstrdup(cp); /* store disposition type */ *dp = c; cp = dp; if (*cp == '(' && get_comment (ct->c_file, DISPO_FIELD, &cp, NULL) == NOTOK) return NOTOK; if ((status = parse_header_attrs (ct->c_file, DISPO_FIELD, &cp, &ct->c_dispo_first, &ct->c_dispo_last, NULL)) != OK) { if (status == NOTOK) { free(dispoheader); return NOTOK; } } else if (*cp) { inform("extraneous information in message %s's %s: field\n%*s(%s)", ct->c_file, DISPO_FIELD, strlen(invo_name) + 2, "", cp); } if (buildflag) free(dispoheader); else ct->c_dispo = dispoheader; return OK; } static int get_comment (const char *filename, const char *fieldname, char **ap, char **commentp) { int i; char *bp, *cp; char c, buffer[BUFSIZ], *dp; cp = *ap; bp = buffer; cp++; for (i = 0;;) { switch (c = *cp++) { case '\0': invalid: inform("invalid comment in message %s's %s: field", filename, fieldname); return NOTOK; case '\\': *bp++ = c; if ((c = *cp++) == '\0') goto invalid; *bp++ = c; continue; case '(': i++; /* FALLTHRU */ default: *bp++ = c; continue; case ')': if (--i < 0) break; *bp++ = c; continue; } break; } *bp = '\0'; if (commentp) { if ((dp = *commentp)) { *commentp = concat (dp, " ", buffer, NULL); free (dp); } else { *commentp = mh_xstrdup(buffer); } } while (isspace ((unsigned char) *cp)) cp++; *ap = cp; return OK; } /* * CONTENTS * * Handles content types audio, image, and video. * There's not much to do right here. */ static int InitGeneric (CT ct) { NMH_UNUSED (ct); return OK; /* not much to do here */ } /* * TEXT */ static int InitText (CT ct) { char buffer[BUFSIZ]; char *chset = NULL; char *cp; PM pm; struct text *t; CI ci = &ct->c_ctinfo; /* check for missing subtype */ if (!*ci->ci_subtype) ci->ci_subtype = add ("plain", ci->ci_subtype); /* match subtype */ ct->c_subtype = ct_str_subtype (CT_TEXT, ci->ci_subtype); /* allocate text character set structure */ NEW0(t); ct->c_ctparams = (void *) t; /* scan for charset parameter */ for (pm = ci->ci_first_pm; pm; pm = pm->pm_next) if (!strcasecmp (pm->pm_name, "charset")) break; /* check if content specified a character set */ if (pm) { chset = pm->pm_value; t->tx_charset = CHARSET_SPECIFIED; } else { t->tx_charset = CHARSET_UNSPECIFIED; } /* * If we can not handle character set natively, * then check profile for string to modify the * terminal or display method. * * termproc is for mhshow, though mhlist -debug prints it, too. */ if (chset != NULL && !check_charset (chset, strlen (chset))) { snprintf (buffer, sizeof(buffer), "%s-charset-%s", invo_name, chset); if ((cp = context_find (buffer))) ct->c_termproc = mh_xstrdup(cp); } return OK; } /* * MULTIPART */ static int InitMultiPart (CT ct) { int inout; long last, pos; char *cp, *dp; PM pm; char *bp; char *bufp = NULL; size_t buflen; ssize_t gotlen; struct multipart *m; struct part *part, **next; CI ci = &ct->c_ctinfo; CT p; FILE *fp; /* * The encoding for multipart messages must be either * 7bit, 8bit, or binary (per RFC 2045). */ if (! skip_mp_cte_check && 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 = mh_xstrdup(ct->c_celine ? ct->c_celine : "(null)"); bp = cte + strlen (cte) - 1; while (bp >= cte && isspace ((unsigned char) *bp)) *bp-- = '\0'; for (bp = cte; *bp && isblank ((unsigned char) *bp); ++bp) continue; inform("\"%s/%s\" type in message %s must be encoded in\n" "7bit, 8bit, or binary, per RFC 2045 (6.4). " "mhfixmsg -fixcte can fix it, or\n" "manually edit the file and change the \"%s\"\n" "Content-Transfer-Encoding to one of those. For now, continuing...", ci->ci_type, ci->ci_subtype, ct->c_file, bp); free (cte); return NOTOK; } /* match subtype */ ct->c_subtype = ct_str_subtype (CT_MULTIPART, ci->ci_subtype); /* * Check for "boundary" parameter, which is * required for multipart messages. */ bp = 0; for (pm = ci->ci_first_pm; pm; pm = pm->pm_next) { if (!strcasecmp (pm->pm_name, "boundary")) { bp = pm->pm_value; break; } } /* complain if boundary parameter is missing */ if (!pm) { inform("a \"boundary\" parameter is mandatory for \"%s/%s\" type in message %s's %s: field", ci->ci_type, ci->ci_subtype, ct->c_file, TYPE_FIELD); return NOTOK; } /* allocate primary structure for multipart info */ NEW0(m); ct->c_ctparams = (void *) m; /* check if boundary parameter contains only whitespace characters */ for (cp = bp; isspace ((unsigned char) *cp); cp++) continue; if (!*cp) { inform("invalid \"boundary\" parameter for \"%s/%s\" type in message %s's %s: field", ci->ci_type, ci->ci_subtype, ct->c_file, TYPE_FIELD); return NOTOK; } /* remove trailing whitespace from boundary parameter */ for (cp = bp, dp = cp + strlen (cp) - 1; dp > cp; dp--) if (!isspace ((unsigned char) *dp)) break; *++dp = '\0'; /* record boundary separators */ m->mp_start = concat (bp, "\n", NULL); m->mp_stop = concat (bp, "--\n", NULL); if (!ct->c_fp && (ct->c_fp = fopen (ct->c_file, "r")) == NULL) { advise (ct->c_file, "unable to open for reading"); return NOTOK; } fseek (fp = ct->c_fp, pos = ct->c_begin, SEEK_SET); last = ct->c_end; next = &m->mp_parts; part = NULL; inout = 1; while ((gotlen = getline(&bufp, &buflen, fp)) != -1) { if (pos > last) break; pos += gotlen; if (bufp[0] != '-' || bufp[1] != '-') continue; if (inout) { if (strcmp (bufp + 2, m->mp_start)) continue; next_part: NEW0(part); *next = part; next = &part->mp_next; if (!(p = get_content (fp, ct->c_file, ct->c_subtype == MULTI_DIGEST ? -1 : 0))) { free(bufp); ct->c_fp = NULL; return NOTOK; } p->c_fp = NULL; part->mp_part = p; pos = p->c_begin; fseek (fp, pos, SEEK_SET); inout = 0; } else { if (strcmp (bufp + 2, m->mp_start) == 0) { inout = 1; end_part: p = part->mp_part; p->c_end = ftell(fp) - (gotlen + 1); if (p->c_end < p->c_begin) p->c_begin = p->c_end; if (inout) goto next_part; goto last_part; } if (strcmp (bufp + 2, m->mp_stop) == 0) goto end_part; } } if (! suppress_bogus_mp_content_warning) { inform("bogus multipart content in message %s", ct->c_file); } bogus_mp_content = 1; if (!inout && part) { p = part->mp_part; p->c_end = ct->c_end; if (p->c_begin >= p->c_end) { for (next = &m->mp_parts; *next != part; next = &((*next)->mp_next)) continue; *next = NULL; free_content (p); free(part); } } last_part: /* reverse the order of the parts for multipart/alternative */ if (ct->c_subtype == MULTI_ALTERNATE) { reverse_parts (ct); prefer_parts (ct); } /* * label all subparts with part number, and * then initialize the content of the subpart. */ { int partnum; char *pp; char partnam[BUFSIZ]; if (ct->c_partno) { snprintf (partnam, sizeof(partnam), "%s.", ct->c_partno); pp = partnam + strlen (partnam); } else { pp = partnam; } for (part = m->mp_parts, partnum = 1; part; part = part->mp_next, partnum++) { p = part->mp_part; sprintf (pp, "%d", partnum); p->c_partno = mh_xstrdup(partnam); /* initialize the content of the subparts */ if (p->c_ctinitfnx && (*p->c_ctinitfnx) (p) == NOTOK) { free(bufp); fclose (ct->c_fp); ct->c_fp = NULL; return NOTOK; } } } get_leftover_mp_content (ct, 1); get_leftover_mp_content (ct, 0); free(bufp); fclose (ct->c_fp); ct->c_fp = NULL; return OK; } /* * reverse the order of the parts of a multipart/alternative, * presumably to put the "most favored" alternative first, for * ease of choosing/displaying it later on. from a mail message on * nmh-workers, from kenh: * "Stock" MH 6.8.5 did not have a reverse_parts() function, but I * see code in mhn that did the same thing... According to the RCS * logs, that code was around from the initial checkin of mhn.c by * John Romine in 1992, which is as far back as we have." */ static void reverse_parts (CT ct) { struct multipart *m = (struct multipart *) ct->c_ctparams; struct part *part; struct part *next; /* Reverse the order of its parts by walking the mp_parts list and pushing each node to the front. */ for (part = m->mp_parts, m->mp_parts = NULL; part; part = next) { next = part->mp_next; part->mp_next = m->mp_parts; m->mp_parts = part; } } static void move_preferred_part (CT ct, char *type, char *subtype) { struct multipart *m = (struct multipart *) ct->c_ctparams; struct part *part, *prev, *head, *nhead, *ntail; struct part h, n; CI ci; /* move the matching part(s) to the head of the list: walk the * list of parts, move matching parts to a new list (maintaining * their order), and finally, concatenate the old list onto the * new. */ head = &h; nhead = &n; head->mp_next = m->mp_parts; nhead->mp_next = NULL; ntail = nhead; prev = head; part = head->mp_next; while (part != NULL) { ci = &part->mp_part->c_ctinfo; if (!strcasecmp(ci->ci_type, type) && (!subtype || !strcasecmp(ci->ci_subtype, subtype))) { prev->mp_next = part->mp_next; part->mp_next = NULL; ntail->mp_next = part; ntail = part; part = prev->mp_next; } else { prev = part; part = prev->mp_next; } } ntail->mp_next = head->mp_next; m->mp_parts = nhead->mp_next; } /* * move parts that match the user's preferences (-prefer) to the head * of the line. process preferences in reverse so first one given * ends up first in line */ static void prefer_parts(CT ct) { int i; for (i = 0; i < npreferred; i++) move_preferred_part(ct, preferred_types[i], preferred_subtypes[i]); } /* parse_mime() arranges alternates in reverse (priority) order. This function can be used to reverse them back. This will put, for example, a text/plain part before a text/html part in a multipart/alternative part, for example, where it belongs. */ void reverse_alternative_parts (CT ct) { if (ct->c_type == CT_MULTIPART) { struct multipart *m = (struct multipart *) ct->c_ctparams; struct part *part; if (ct->c_subtype == MULTI_ALTERNATE) { reverse_parts (ct); } /* And call recursively on each part of a multipart. */ for (part = m->mp_parts; part; part = part->mp_next) { reverse_alternative_parts (part->mp_part); } } } /* * MESSAGE */ static int InitMessage (CT ct) { CI ci = &ct->c_ctinfo; if ((ct->c_encoding != CE_7BIT) && (ct->c_encoding != CE_8BIT)) { inform("\"%s/%s\" type in message %s should be encoded in " "7bit or 8bit, continuing...", ci->ci_type, ci->ci_subtype, ct->c_file); return NOTOK; } /* check for missing subtype */ if (!*ci->ci_subtype) ci->ci_subtype = add ("rfc822", ci->ci_subtype); /* match subtype */ ct->c_subtype = ct_str_subtype (CT_MESSAGE, ci->ci_subtype); switch (ct->c_subtype) { case MESSAGE_RFC822: break; case MESSAGE_PARTIAL: { PM pm; struct partial *p; NEW0(p); ct->c_ctparams = (void *) p; /* scan for parameters "id", "number", and "total" */ for (pm = ci->ci_first_pm; pm; pm = pm->pm_next) { if (!strcasecmp (pm->pm_name, "id")) { p->pm_partid = add (pm->pm_value, NULL); continue; } if (!strcasecmp (pm->pm_name, "number")) { if (sscanf (pm->pm_value, "%d", &p->pm_partno) != 1 || p->pm_partno < 1) { invalid_param: inform("invalid %s parameter for \"%s/%s\" type in message %s's %s field", pm->pm_name, ci->ci_type, ci->ci_subtype, ct->c_file, TYPE_FIELD); return NOTOK; } continue; } if (!strcasecmp (pm->pm_name, "total")) { if (sscanf (pm->pm_value, "%d", &p->pm_maxno) != 1 || p->pm_maxno < 1) goto invalid_param; continue; } } if (!p->pm_partid || !p->pm_partno || (p->pm_maxno && p->pm_partno > p->pm_maxno)) { inform("invalid parameters for \"%s/%s\" type in message %s's %s field", ci->ci_type, ci->ci_subtype, ct->c_file, TYPE_FIELD); return NOTOK; } } break; case MESSAGE_EXTERNAL: { int exresult; struct exbody *e; CT p; FILE *fp; NEW0(e); ct->c_ctparams = (void *) e; if (!ct->c_fp && (ct->c_fp = fopen (ct->c_file, "r")) == NULL) { advise (ct->c_file, "unable to open for reading"); return NOTOK; } fseek (fp = ct->c_fp, ct->c_begin, SEEK_SET); if (!(p = get_content (fp, ct->c_file, 0))) { ct->c_fp = NULL; return NOTOK; } e->eb_parent = ct; e->eb_content = p; p->c_ctexbody = e; p->c_ceopenfnx = NULL; if ((exresult = params_external (ct, 0)) != NOTOK && p->c_ceopenfnx == openMail) { int cc, size; char *bp; if ((size = ct->c_end - p->c_begin) <= 0) { if (!e->eb_subject) content_error (NULL, ct, "empty body for access-type=mail-server"); goto no_body; } e->eb_body = bp = mh_xmalloc ((unsigned) size); fseek (p->c_fp, p->c_begin, SEEK_SET); while (size > 0) switch (cc = fread (bp, sizeof(*bp), size, p->c_fp)) { case NOTOK: adios ("failed", "fread"); case OK: adios (NULL, "unexpected EOF from fread"); default: bp += cc, size -= cc; break; } *bp = 0; } no_body: p->c_fp = NULL; p->c_end = p->c_begin; fclose (ct->c_fp); ct->c_fp = NULL; if (exresult == NOTOK) return NOTOK; if (e->eb_flags == NOTOK) return OK; switch (p->c_type) { case CT_MULTIPART: break; case CT_MESSAGE: if (p->c_subtype != MESSAGE_RFC822) break; /* FALLTHRU */ default: e->eb_partno = ct->c_partno; if (p->c_ctinitfnx) (*p->c_ctinitfnx) (p); break; } } break; default: break; } return OK; } int params_external (CT ct, int composing) { PM pm; struct exbody *e = (struct exbody *) ct->c_ctparams; CI ci = &ct->c_ctinfo; ct->c_ceopenfnx = NULL; for (pm = ci->ci_first_pm; pm; pm = pm->pm_next) { if (!strcasecmp (pm->pm_name, "access-type")) { struct str2init *s2i; CT p = e->eb_content; for (s2i = str2methods; s2i->si_key; s2i++) if (!strcasecmp (pm->pm_value, s2i->si_key)) break; if (!s2i->si_key) { e->eb_access = pm->pm_value; e->eb_flags = NOTOK; p->c_encoding = CE_EXTERNAL; continue; } e->eb_access = s2i->si_key; e->eb_flags = s2i->si_val; p->c_encoding = CE_EXTERNAL; /* Call the Init function for this external type */ if ((*s2i->si_init)(p) == NOTOK) return NOTOK; continue; } if (!strcasecmp (pm->pm_name, "name")) { e->eb_name = pm->pm_value; continue; } if (!strcasecmp (pm->pm_name, "permission")) { e->eb_permission = pm->pm_value; continue; } if (!strcasecmp (pm->pm_name, "site")) { e->eb_site = pm->pm_value; continue; } if (!strcasecmp (pm->pm_name, "directory")) { e->eb_dir = pm->pm_value; continue; } if (!strcasecmp (pm->pm_name, "mode")) { e->eb_mode = pm->pm_value; continue; } if (!strcasecmp (pm->pm_name, "size")) { sscanf (pm->pm_value, "%lu", &e->eb_size); continue; } if (!strcasecmp (pm->pm_name, "server")) { e->eb_server = pm->pm_value; continue; } if (!strcasecmp (pm->pm_name, "subject")) { e->eb_subject = pm->pm_value; continue; } if (!strcasecmp (pm->pm_name, "url")) { /* * According to RFC 2017, we have to remove all whitespace from * the URL */ char *u, *p = pm->pm_value; e->eb_url = u = mh_xmalloc(strlen(pm->pm_value) + 1); for (; *p != '\0'; p++) { if (! isspace((unsigned char) *p)) *u++ = *p; } *u = '\0'; continue; } if (composing && !strcasecmp (pm->pm_name, "body")) { e->eb_body = getcpy (pm->pm_value); continue; } } if (!e->eb_access) { inform("invalid parameters for \"%s/%s\" type in message %s's %s field", ci->ci_type, ci->ci_subtype, ct->c_file, TYPE_FIELD); return NOTOK; } return OK; } /* * APPLICATION */ static int InitApplication (CT ct) { CI ci = &ct->c_ctinfo; /* match subtype */ ct->c_subtype = ct_str_subtype (CT_APPLICATION, ci->ci_subtype); return OK; } /* * TRANSFER ENCODINGS */ static int init_encoding (CT ct, OpenCEFunc openfnx) { ct->c_ceopenfnx = openfnx; ct->c_ceclosefnx = close_encoding; ct->c_cesizefnx = size_encoding; return OK; } void close_encoding (CT ct) { CE ce = &ct->c_cefile; if (ce->ce_fp) { fclose (ce->ce_fp); ce->ce_fp = NULL; } } static unsigned long size_encoding (CT ct) { int fd; unsigned long size; char *file; CE ce = &ct->c_cefile; struct stat st; if (ce->ce_fp && fstat (fileno (ce->ce_fp), &st) != NOTOK) return (long) st.st_size; if (ce->ce_file) { if (stat (ce->ce_file, &st) != NOTOK) return (long) st.st_size; return 0L; } if (ct->c_encoding == CE_EXTERNAL) return (ct->c_end - ct->c_begin); file = NULL; if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK) return (ct->c_end - ct->c_begin); if (fstat (fd, &st) != NOTOK) size = (long) st.st_size; else size = 0L; (*ct->c_ceclosefnx) (ct); return size; } /* * BASE64 */ static int InitBase64 (CT ct) { return init_encoding (ct, openBase64); } static int openBase64 (CT ct, char **file) { ssize_t cc, len; int fd, own_ct_fp = 0; char *cp, *buffer = NULL; /* sbeck -- handle suffixes */ CI ci; CE ce = &ct->c_cefile; unsigned char *decoded; size_t decoded_len; unsigned char digest[16]; if (ce->ce_fp) { fseek (ce->ce_fp, 0L, SEEK_SET); goto ready_to_go; } if (ce->ce_file) { if ((ce->ce_fp = fopen (ce->ce_file, "r")) == NULL) { content_error (ce->ce_file, ct, "unable to fopen for reading"); return NOTOK; } goto ready_to_go; } if (*file == NULL) { ce->ce_unlink = 1; } else { ce->ce_file = mh_xstrdup(*file); ce->ce_unlink = 0; } /* sbeck@cise.ufl.edu -- handle suffixes */ ci = &ct->c_ctinfo; if ((cp = context_find_by_type ("suffix", ci->ci_type, ci->ci_subtype))) { if (ce->ce_unlink) { /* Create temporary file with filename extension. */ if ((ce->ce_file = m_mktemps(invo_name, cp, NULL, NULL)) == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } } else { ce->ce_file = add (cp, ce->ce_file); } } else if (*file == NULL) { char *tempfile; if ((tempfile = m_mktemp2(NULL, invo_name, NULL, NULL)) == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } ce->ce_file = mh_xstrdup(tempfile); } if ((ce->ce_fp = fopen (ce->ce_file, "w+")) == NULL) { content_error (ce->ce_file, ct, "unable to fopen for reading/writing"); return NOTOK; } if ((len = ct->c_end - ct->c_begin) < 0) adios (NULL, "internal error(1)"); buffer = mh_xmalloc (len + 1); if (! ct->c_fp) { if ((ct->c_fp = fopen (ct->c_file, "r")) == NULL) { content_error (ct->c_file, ct, "unable to open for reading"); return NOTOK; } own_ct_fp = 1; } lseek (fd = fileno (ct->c_fp), (off_t) ct->c_begin, SEEK_SET); cp = buffer; while (len > 0) { switch (cc = read (fd, cp, len)) { case NOTOK: content_error (ct->c_file, ct, "error reading from"); goto clean_up; case OK: content_error (NULL, ct, "premature eof"); goto clean_up; default: if (cc > len) cc = len; len -= cc; cp += cc; } } /* decodeBase64() requires null-terminated input. */ *cp = '\0'; if (decodeBase64 (buffer, &decoded, &decoded_len, ct->c_type == CT_TEXT, ct->c_digested ? digest : NULL) == OK) { size_t i; unsigned char *decoded_p = decoded; for (i = 0; i < decoded_len; ++i) { putc (*decoded_p++, ce->ce_fp); } free(decoded); if (ferror (ce->ce_fp)) { content_error (ce->ce_file, ct, "error writing to"); goto clean_up; } if (ct->c_digested) { if (memcmp(digest, ct->c_digest, sizeof digest)) { content_error (NULL, ct, "content integrity suspect (digest mismatch) -- continuing"); } else { if (debugsw) { fprintf (stderr, "content integrity confirmed\n"); } } } } else { goto clean_up; } fseek (ct->c_fp, 0L, SEEK_SET); if (fflush (ce->ce_fp)) { content_error (ce->ce_file, ct, "error writing to"); goto clean_up; } fseek (ce->ce_fp, 0L, SEEK_SET); ready_to_go: *file = ce->ce_file; if (own_ct_fp) { fclose (ct->c_fp); ct->c_fp = NULL; } free (buffer); return fileno (ce->ce_fp); clean_up: if (own_ct_fp) { fclose (ct->c_fp); ct->c_fp = NULL; } free_encoding (ct, 0); free (buffer); return NOTOK; } /* * QUOTED PRINTABLE */ static char hex2nib[0x80] = { 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, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 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, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 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 }; static int InitQuoted (CT ct) { return init_encoding (ct, openQuoted); } static int openQuoted (CT ct, char **file) { int cc, digested, len, quoted, own_ct_fp = 0; char *cp, *ep; char *bufp = NULL; size_t buflen; ssize_t gotlen; unsigned char mask; CE ce = &ct->c_cefile; /* sbeck -- handle suffixes */ CI ci; MD5_CTX mdContext; if (ce->ce_fp) { fseek (ce->ce_fp, 0L, SEEK_SET); goto ready_to_go; } if (ce->ce_file) { if ((ce->ce_fp = fopen (ce->ce_file, "r")) == NULL) { content_error (ce->ce_file, ct, "unable to fopen for reading"); return NOTOK; } goto ready_to_go; } if (*file == NULL) { ce->ce_unlink = 1; } else { ce->ce_file = mh_xstrdup(*file); ce->ce_unlink = 0; } /* sbeck@cise.ufl.edu -- handle suffixes */ ci = &ct->c_ctinfo; if ((cp = context_find_by_type ("suffix", ci->ci_type, ci->ci_subtype))) { if (ce->ce_unlink) { /* Create temporary file with filename extension. */ if ((ce->ce_file = m_mktemps(invo_name, cp, NULL, NULL)) == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } } else { ce->ce_file = add (cp, ce->ce_file); } } else if (*file == NULL) { char *tempfile; if ((tempfile = m_mktemp2(NULL, invo_name, NULL, NULL)) == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } ce->ce_file = mh_xstrdup(tempfile); } if ((ce->ce_fp = fopen (ce->ce_file, "w+")) == NULL) { content_error (ce->ce_file, ct, "unable to fopen for reading/writing"); return NOTOK; } if ((len = ct->c_end - ct->c_begin) < 0) adios (NULL, "internal error(2)"); if (! ct->c_fp) { if ((ct->c_fp = fopen (ct->c_file, "r")) == NULL) { content_error (ct->c_file, ct, "unable to open for reading"); return NOTOK; } own_ct_fp = 1; } if ((digested = ct->c_digested)) MD5Init (&mdContext); quoted = 0; #ifdef lint mask = 0; #endif fseek (ct->c_fp, ct->c_begin, SEEK_SET); while (len > 0) { if ((gotlen = getline(&bufp, &buflen, ct->c_fp)) == -1) { content_error (NULL, ct, "premature eof"); goto clean_up; } if ((cc = gotlen) > len) cc = len; len -= cc; for (ep = (cp = bufp) + cc - 1; cp <= ep; ep--) if (!isspace ((unsigned char) *ep)) break; *++ep = '\n'; ep++; for (; cp < ep; cp++) { if (quoted > 0) { /* in an escape sequence */ if (quoted == 1) { /* at byte 1 of an escape sequence */ mask = hex2nib[((unsigned char) *cp) & 0x7f]; /* next is byte 2 */ quoted = 2; } else { /* at byte 2 of an escape sequence */ mask <<= 4; mask |= hex2nib[((unsigned char) *cp) & 0x7f]; putc (mask, ce->ce_fp); if (digested) MD5Update (&mdContext, &mask, 1); if (ferror (ce->ce_fp)) { content_error (ce->ce_file, ct, "error writing to"); goto clean_up; } /* finished escape sequence; next may be literal or a new * escape sequence */ quoted = 0; } /* on to next byte */ continue; } /* not in an escape sequence */ if (*cp == '=') { /* starting an escape sequence, or invalid '='? */ if (cp + 1 < ep && cp[1] == '\n') { /* "=\n" soft line break, eat the \n */ cp++; continue; } if (cp + 1 >= ep || cp + 2 >= ep) { /* We don't have 2 bytes left, so this is an invalid * escape sequence; just show the raw bytes (below). */ } else if (isxdigit ((unsigned char) cp[1]) && isxdigit ((unsigned char) cp[2])) { /* Next 2 bytes are hex digits, making this a valid escape * sequence; let's decode it (above). */ quoted = 1; continue; } /* One or both of the next 2 is out of range, making this * an invalid escape sequence; just show the raw bytes * (below). */ } /* Just show the raw byte. */ putc (*cp, ce->ce_fp); if (digested) { if (*cp == '\n') { MD5Update (&mdContext, (unsigned char *) "\r\n",2); } else { MD5Update (&mdContext, (unsigned char *) cp, 1); } } if (ferror (ce->ce_fp)) { content_error (ce->ce_file, ct, "error writing to"); goto clean_up; } } } if (quoted) { content_error (NULL, ct, "invalid QUOTED-PRINTABLE encoding -- end-of-content while still quoting"); goto clean_up; } fseek (ct->c_fp, 0L, SEEK_SET); if (fflush (ce->ce_fp)) { content_error (ce->ce_file, ct, "error writing to"); goto clean_up; } if (digested) { unsigned char digest[16]; MD5Final (digest, &mdContext); if (memcmp((char *) digest, (char *) ct->c_digest, sizeof digest)) content_error (NULL, ct, "content integrity suspect (digest mismatch) -- continuing"); else if (debugsw) fprintf (stderr, "content integrity confirmed\n"); } fseek (ce->ce_fp, 0L, SEEK_SET); ready_to_go: *file = ce->ce_file; if (own_ct_fp) { fclose (ct->c_fp); ct->c_fp = NULL; } free (bufp); return fileno (ce->ce_fp); clean_up: free_encoding (ct, 0); if (own_ct_fp) { fclose (ct->c_fp); ct->c_fp = NULL; } free (bufp); return NOTOK; } /* * 7BIT */ static int Init7Bit (CT ct) { if (init_encoding (ct, open7Bit) == NOTOK) return NOTOK; ct->c_cesizefnx = NULL; /* no need to decode for real size */ return OK; } int open7Bit (CT ct, char **file) { int cc, fd, len, own_ct_fp = 0; char buffer[BUFSIZ]; /* sbeck -- handle suffixes */ char *cp; CI ci; CE ce = &ct->c_cefile; if (ce->ce_fp) { fseek (ce->ce_fp, 0L, SEEK_SET); goto ready_to_go; } if (ce->ce_file) { if ((ce->ce_fp = fopen (ce->ce_file, "r")) == NULL) { content_error (ce->ce_file, ct, "unable to fopen for reading"); return NOTOK; } goto ready_to_go; } if (*file == NULL) { ce->ce_unlink = 1; } else { ce->ce_file = mh_xstrdup(*file); ce->ce_unlink = 0; } /* sbeck@cise.ufl.edu -- handle suffixes */ ci = &ct->c_ctinfo; if ((cp = context_find_by_type ("suffix", ci->ci_type, ci->ci_subtype))) { if (ce->ce_unlink) { /* Create temporary file with filename extension. */ if ((ce->ce_file = m_mktemps(invo_name, cp, NULL, NULL)) == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } } else { ce->ce_file = add (cp, ce->ce_file); } } else if (*file == NULL) { char *tempfile; if ((tempfile = m_mktemp2(NULL, invo_name, NULL, NULL)) == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } ce->ce_file = mh_xstrdup(tempfile); } if ((ce->ce_fp = fopen (ce->ce_file, "w+")) == NULL) { content_error (ce->ce_file, ct, "unable to fopen for reading/writing"); return NOTOK; } if (ct->c_type == CT_MULTIPART) { CI ci = &ct->c_ctinfo; char *buffer; len = 0; fprintf (ce->ce_fp, "%s: %s/%s", TYPE_FIELD, ci->ci_type, ci->ci_subtype); len += strlen (TYPE_FIELD) + 2 + strlen (ci->ci_type) + 1 + strlen (ci->ci_subtype); buffer = output_params(len, ci->ci_first_pm, &len, 0); if (buffer) { fputs (buffer, ce->ce_fp); free(buffer); } if (ci->ci_comment) { if (len + 1 + (cc = 2 + strlen (ci->ci_comment)) >= CPERLIN) { fputs ("\n\t", ce->ce_fp); len = 8; } else { putc (' ', ce->ce_fp); len++; } fprintf (ce->ce_fp, "(%s)", ci->ci_comment); len += cc; } fprintf (ce->ce_fp, "\n"); if (ct->c_id) fprintf (ce->ce_fp, "%s:%s", ID_FIELD, ct->c_id); if (ct->c_descr) fprintf (ce->ce_fp, "%s:%s", DESCR_FIELD, ct->c_descr); if (ct->c_dispo) fprintf (ce->ce_fp, "%s:%s", DISPO_FIELD, ct->c_dispo); fprintf (ce->ce_fp, "\n"); } if ((len = ct->c_end - ct->c_begin) < 0) adios (NULL, "internal error(3)"); if (! ct->c_fp) { if ((ct->c_fp = fopen (ct->c_file, "r")) == NULL) { content_error (ct->c_file, ct, "unable to open for reading"); return NOTOK; } own_ct_fp = 1; } lseek (fd = fileno (ct->c_fp), (off_t) ct->c_begin, SEEK_SET); while (len > 0) switch (cc = read (fd, buffer, sizeof(buffer) - 1)) { case NOTOK: content_error (ct->c_file, ct, "error reading from"); goto clean_up; case OK: content_error (NULL, ct, "premature eof"); goto clean_up; default: if (cc > len) cc = len; len -= cc; if ((int) fwrite (buffer, sizeof(*buffer), cc, ce->ce_fp) < cc) { advise ("open7Bit", "fwrite"); } if (ferror (ce->ce_fp)) { content_error (ce->ce_file, ct, "error writing to"); goto clean_up; } } fseek (ct->c_fp, 0L, SEEK_SET); if (fflush (ce->ce_fp)) { content_error (ce->ce_file, ct, "error writing to"); goto clean_up; } fseek (ce->ce_fp, 0L, SEEK_SET); ready_to_go: *file = ce->ce_file; if (own_ct_fp) { fclose (ct->c_fp); ct->c_fp = NULL; } return fileno (ce->ce_fp); clean_up: free_encoding (ct, 0); if (own_ct_fp) { fclose (ct->c_fp); ct->c_fp = NULL; } return NOTOK; } /* * External */ static int openExternal (CT ct, CT cb, CE ce, char **file, int *fd) { char cachefile[BUFSIZ]; if (ce->ce_fp) { fseek (ce->ce_fp, 0L, SEEK_SET); goto ready_already; } if (ce->ce_file) { if ((ce->ce_fp = fopen (ce->ce_file, "r")) == NULL) { content_error (ce->ce_file, ct, "unable to fopen for reading"); return NOTOK; } goto ready_already; } if (find_cache (ct, rcachesw, (int *) 0, cb->c_id, cachefile, sizeof(cachefile)) != NOTOK) { if ((ce->ce_fp = fopen (cachefile, "r"))) { ce->ce_file = mh_xstrdup(cachefile); ce->ce_unlink = 0; goto ready_already; } admonish (cachefile, "unable to fopen for reading"); } *fd = ce->ce_fp ? fileno (ce->ce_fp) : -1; return OK; ready_already: *file = ce->ce_file; *fd = fileno (ce->ce_fp); return DONE; } /* * File */ static int InitFile (CT ct) { return init_encoding (ct, openFile); } static int openFile (CT ct, char **file) { int fd, cachetype; char cachefile[BUFSIZ]; struct exbody *e = ct->c_ctexbody; CE ce = &ct->c_cefile; switch (openExternal (e->eb_parent, e->eb_content, ce, file, &fd)) { case NOTOK: return NOTOK; case OK: break; case DONE: return fd; } if (!e->eb_name) { content_error (NULL, ct, "missing name parameter"); return NOTOK; } ce->ce_file = mh_xstrdup(e->eb_name); ce->ce_unlink = 0; if ((ce->ce_fp = fopen (ce->ce_file, "r")) == NULL) { content_error (ce->ce_file, ct, "unable to fopen for reading"); return NOTOK; } if ((!e->eb_permission || strcasecmp (e->eb_permission, "read-write")) && find_cache (NULL, wcachesw, &cachetype, e->eb_content->c_id, cachefile, sizeof(cachefile)) != NOTOK) { int mask; FILE *fp; mask = umask (cachetype ? ~m_gmprot () : 0222); if ((fp = fopen (cachefile, "w"))) { int cc; char buffer[BUFSIZ]; FILE *gp = ce->ce_fp; fseek (gp, 0L, SEEK_SET); while ((cc = fread (buffer, sizeof(*buffer), sizeof(buffer), gp)) > 0) if ((int) fwrite (buffer, sizeof(*buffer), cc, fp) < cc) { advise ("openFile", "fwrite"); } fflush (fp); if (ferror (gp)) { admonish (ce->ce_file, "error reading"); (void) m_unlink (cachefile); } else if (ferror (fp)) { admonish (cachefile, "error writing"); (void) m_unlink (cachefile); } fclose (fp); } umask (mask); } fseek (ce->ce_fp, 0L, SEEK_SET); *file = ce->ce_file; return fileno (ce->ce_fp); } /* * FTP */ static int InitFTP (CT ct) { return init_encoding (ct, openFTP); } static int openFTP (CT ct, char **file) { int cachetype, caching, fd; int len, buflen; char *bp, *ftp, *user, *pass; char buffer[BUFSIZ], cachefile[BUFSIZ]; struct exbody *e; CE ce = &ct->c_cefile; static char *username = NULL; static char *password = NULL; e = ct->c_ctexbody; if ((ftp = context_find (nmhaccessftp)) && !*ftp) ftp = NULL; if (!ftp) return NOTOK; switch (openExternal (e->eb_parent, e->eb_content, ce, file, &fd)) { case NOTOK: return NOTOK; case OK: break; case DONE: return fd; } if (!e->eb_name || !e->eb_site) { content_error (NULL, ct, "missing %s parameter", e->eb_name ? "site": "name"); return NOTOK; } /* Get the buffer ready to go */ bp = buffer; buflen = sizeof(buffer); /* * Construct the query message for user */ snprintf (bp, buflen, "Retrieve %s", e->eb_name); len = strlen (bp); bp += len; buflen -= len; if (e->eb_partno) { snprintf (bp, buflen, " (content %s)", e->eb_partno); len = strlen (bp); bp += len; buflen -= len; } snprintf (bp, buflen, "\n using %sFTP from site %s", e->eb_flags ? "anonymous " : "", e->eb_site); len = strlen (bp); bp += len; buflen -= len; if (e->eb_size > 0) { snprintf (bp, buflen, " (%lu octets)", e->eb_size); len = strlen (bp); bp += len; buflen -= len; } snprintf (bp, buflen, "? "); /* * Now, check the answer */ if (!read_yes_or_no_if_tty (buffer)) return NOTOK; if (e->eb_flags) { user = "anonymous"; snprintf (buffer, sizeof(buffer), "%s@%s", getusername (), LocalName (1)); pass = buffer; } else { ruserpass (e->eb_site, &username, &password, 0); user = username; pass = password; } ce->ce_unlink = (*file == NULL); caching = 0; cachefile[0] = '\0'; if ((!e->eb_permission || strcasecmp (e->eb_permission, "read-write")) && find_cache (NULL, wcachesw, &cachetype, e->eb_content->c_id, cachefile, sizeof(cachefile)) != NOTOK) { if (*file == NULL) { ce->ce_unlink = 0; caching = 1; } } if (*file) ce->ce_file = mh_xstrdup(*file); else if (caching) ce->ce_file = mh_xstrdup(cachefile); else { char *tempfile; if ((tempfile = m_mktemp2(NULL, invo_name, NULL, NULL)) == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } ce->ce_file = mh_xstrdup(tempfile); } if ((ce->ce_fp = fopen (ce->ce_file, "w+")) == NULL) { content_error (ce->ce_file, ct, "unable to fopen for reading/writing"); return NOTOK; } { int child_id, i, vecp; char *vec[9]; vecp = 0; vec[vecp++] = r1bindex (ftp, '/'); vec[vecp++] = e->eb_site; vec[vecp++] = user; vec[vecp++] = pass; vec[vecp++] = e->eb_dir; vec[vecp++] = e->eb_name; vec[vecp++] = ce->ce_file, vec[vecp++] = e->eb_mode && !strcasecmp (e->eb_mode, "ascii") ? "ascii" : "binary"; vec[vecp] = NULL; fflush (stdout); for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++) sleep (5); switch (child_id) { case NOTOK: adios ("fork", "unable to"); /* NOTREACHED */ case OK: close (fileno (ce->ce_fp)); execvp (ftp, vec); fprintf (stderr, "unable to exec "); perror (ftp); _exit (-1); /* NOTREACHED */ default: if (pidXwait (child_id, NULL)) { username = password = NULL; ce->ce_unlink = 1; return NOTOK; } break; } } if (cachefile[0]) { if (caching) chmod (cachefile, cachetype ? m_gmprot () : 0444); else { int mask; FILE *fp; mask = umask (cachetype ? ~m_gmprot () : 0222); if ((fp = fopen (cachefile, "w"))) { int cc; FILE *gp = ce->ce_fp; fseek (gp, 0L, SEEK_SET); while ((cc= fread (buffer, sizeof(*buffer), sizeof(buffer), gp)) > 0) if ((int) fwrite (buffer, sizeof(*buffer), cc, fp) < cc) { advise ("openFTP", "fwrite"); } fflush (fp); if (ferror (gp)) { admonish (ce->ce_file, "error reading"); (void) m_unlink (cachefile); } else if (ferror (fp)) { admonish (cachefile, "error writing"); (void) m_unlink (cachefile); } fclose (fp); } umask (mask); } } fseek (ce->ce_fp, 0L, SEEK_SET); *file = ce->ce_file; return fileno (ce->ce_fp); } /* * Mail */ static int InitMail (CT ct) { return init_encoding (ct, openMail); } static int openMail (CT ct, char **file) { int child_id, fd, i, vecp; int len, buflen; char *bp, buffer[BUFSIZ], *vec[7]; struct exbody *e = ct->c_ctexbody; CE ce = &ct->c_cefile; switch (openExternal (e->eb_parent, e->eb_content, ce, file, &fd)) { case NOTOK: return NOTOK; case OK: break; case DONE: return fd; } if (!e->eb_server) { content_error (NULL, ct, "missing server parameter"); return NOTOK; } /* Get buffer ready to go */ bp = buffer; buflen = sizeof(buffer); /* Now, construct query message */ snprintf (bp, buflen, "Retrieve content"); len = strlen (bp); bp += len; buflen -= len; if (e->eb_partno) { snprintf (bp, buflen, " %s", e->eb_partno); len = strlen (bp); bp += len; buflen -= len; } snprintf (bp, buflen, " by asking %s\n\n%s\n? ", e->eb_server, e->eb_subject ? e->eb_subject : e->eb_body); /* Now, check answer */ if (!read_yes_or_no_if_tty (buffer)) return NOTOK; vecp = 0; vec[vecp++] = r1bindex (mailproc, '/'); vec[vecp++] = e->eb_server; vec[vecp++] = "-subject"; vec[vecp++] = e->eb_subject ? e->eb_subject : "mail-server request"; vec[vecp++] = "-body"; vec[vecp++] = e->eb_body; vec[vecp] = NULL; for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++) sleep (5); switch (child_id) { case NOTOK: advise ("fork", "unable to"); return NOTOK; case OK: execvp (mailproc, vec); fprintf (stderr, "unable to exec "); perror (mailproc); _exit (-1); /* NOTREACHED */ default: if (pidXwait (child_id, NULL) == OK) inform("request sent"); break; } if (*file == NULL) { char *tempfile; if ((tempfile = m_mktemp2(NULL, invo_name, NULL, NULL)) == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } ce->ce_file = mh_xstrdup(tempfile); ce->ce_unlink = 1; } else { ce->ce_file = mh_xstrdup(*file); ce->ce_unlink = 0; } if ((ce->ce_fp = fopen (ce->ce_file, "w+")) == NULL) { content_error (ce->ce_file, ct, "unable to fopen for reading/writing"); return NOTOK; } /* showproc is for mhshow and mhstore, though mhlist -debug * prints it, too. */ mh_xfree(ct->c_showproc); ct->c_showproc = mh_xstrdup("true"); fseek (ce->ce_fp, 0L, SEEK_SET); *file = ce->ce_file; return fileno (ce->ce_fp); } /* * URL */ static int InitURL (CT ct) { return init_encoding (ct, openURL); } static int openURL (CT ct, char **file) { struct exbody *e = ct->c_ctexbody; CE ce = &ct->c_cefile; char *urlprog, *program; char buffer[BUFSIZ], cachefile[BUFSIZ]; int fd, caching, cachetype; struct msgs_array args = { 0, 0, NULL}; pid_t child_id; if ((urlprog = context_find(nmhaccessurl)) && *urlprog == '\0') urlprog = NULL; if (! urlprog) { content_error(NULL, ct, "No entry for nmh-access-url in profile"); return NOTOK; } switch (openExternal(e->eb_parent, e->eb_content, ce, file, &fd)) { case NOTOK: return NOTOK; case OK: break; case DONE: return fd; } if (!e->eb_url) { content_error(NULL, ct, "missing url parameter"); return NOTOK; } ce->ce_unlink = (*file == NULL); caching = 0; cachefile[0] = '\0'; if (find_cache(NULL, wcachesw, &cachetype, e->eb_content->c_id, cachefile, sizeof(cachefile)) != NOTOK) { if (*file == NULL) { ce->ce_unlink = 0; caching = 1; } } if (*file) ce->ce_file = mh_xstrdup(*file); else if (caching) ce->ce_file = mh_xstrdup(cachefile); else { char *tempfile; if ((tempfile = m_mktemp2(NULL, invo_name, NULL, NULL)) == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } ce->ce_file = mh_xstrdup(tempfile); } if ((ce->ce_fp = fopen(ce->ce_file, "w+")) == NULL) { content_error(ce->ce_file, ct, "unable to fopen for read/writing"); return NOTOK; } switch (child_id = fork()) { case NOTOK: adios ("fork", "unable to"); /* NOTREACHED */ case OK: argsplit_msgarg(&args, urlprog, &program); app_msgarg(&args, e->eb_url); app_msgarg(&args, NULL); dup2(fileno(ce->ce_fp), 1); close(fileno(ce->ce_fp)); execvp(program, args.msgs); fprintf(stderr, "Unable to exec "); perror(program); _exit(-1); /* NOTREACHED */ default: if (pidXwait(child_id, NULL)) { ce->ce_unlink = 1; return NOTOK; } } if (cachefile[0]) { if (caching) chmod(cachefile, cachetype ? m_gmprot() : 0444); else { int mask; FILE *fp; mask = umask (cachetype ? ~m_gmprot() : 0222); if ((fp = fopen(cachefile, "w"))) { int cc; FILE *gp = ce->ce_fp; fseeko(gp, 0, SEEK_SET); while ((cc = fread(buffer, sizeof(*buffer), sizeof(buffer), gp)) > 0) if ((int) fwrite(buffer, sizeof(*buffer), cc, fp) < cc) { advise ("openURL", "fwrite"); } fflush(fp); if (ferror(gp)) { admonish(ce->ce_file, "error reading"); (void) m_unlink (cachefile); } } umask(mask); } } fseeko(ce->ce_fp, 0, SEEK_SET); *file = ce->ce_file; return fileno(ce->ce_fp); } /* * Stores MD5 digest (in cp, from Content-MD5 header) in ct->c_digest. It * has to be base64 decoded. */ static int readDigest (CT ct, char *cp) { unsigned char *digest; size_t len; if (decodeBase64 (cp, &digest, &len, 0, NULL) == OK) { const size_t maxlen = sizeof ct->c_digest; if (strlen ((char *) digest) <= maxlen) { memcpy (ct->c_digest, digest, maxlen); if (debugsw) { size_t i; fprintf (stderr, "MD5 digest="); for (i = 0; i < maxlen; ++i) { fprintf (stderr, "%02x", ct->c_digest[i] & 0xff); } fprintf (stderr, "\n"); } return OK; } if (debugsw) { fprintf (stderr, "invalid MD5 digest (got %d octets)\n", (int) strlen ((char *) digest)); } return NOTOK; } return NOTOK; } /* Multipart parts might have content before the first subpart and/or after the last subpart that hasn't been stored anywhere else, so do that. */ int get_leftover_mp_content (CT ct, int before /* or after */) { struct multipart *m = (struct multipart *) ct->c_ctparams; char *boundary; int found_boundary = 0; int max = BUFSIZ; char *bufp = NULL; size_t buflen; ssize_t gotlen; int read = 0; char *content = NULL; if (! m) return NOTOK; if (before) { if (! m->mp_parts || ! m->mp_parts->mp_part) return NOTOK; /* Isolate the beginning of this part to the beginning of the first subpart and save any content between them. */ fseeko (ct->c_fp, ct->c_begin, SEEK_SET); max = m->mp_parts->mp_part->c_begin - ct->c_begin; boundary = concat ("--", m->mp_start, NULL); } else { struct part *last_subpart = NULL; struct part *subpart; /* Go to the last subpart to get its end position. */ for (subpart = m->mp_parts; subpart; subpart = subpart->mp_next) { last_subpart = subpart; } if (last_subpart == NULL) return NOTOK; /* Isolate the end of the last subpart to the end of this part and save any content between them. */ fseeko (ct->c_fp, last_subpart->mp_part->c_end, SEEK_SET); max = ct->c_end - last_subpart->mp_part->c_end; boundary = concat ("--", m->mp_stop, NULL); } /* Back up by 1 to pick up the newline. */ while ((gotlen = getline(&bufp, &buflen, ct->c_fp)) != -1) { read += gotlen; /* Don't look beyond beginning of first subpart (before) or next part (after). */ if (read > max) bufp[read-max] = '\0'; if (before) { if (! strcmp (bufp, boundary)) { found_boundary = 1; } } else { if (! found_boundary && ! strcmp (bufp, boundary)) { found_boundary = 1; continue; } } if ((before && ! found_boundary) || (! before && found_boundary)) { if (content) { char *old_content = content; content = concat (content, bufp, NULL); free (old_content); } else { content = before ? concat ("\n", bufp, NULL) : concat (bufp, NULL); } } if (before) { if (found_boundary || read > max) break; } else { if (read > max) break; } } /* Skip the newline if that's all there is. */ if (content) { char *cp; /* Remove trailing newline, except at EOF. */ if ((before || ! feof (ct->c_fp)) && (cp = content + strlen (content)) > content && *--cp == '\n') { *cp = '\0'; } if (strlen (content) > 1) { if (before) { m->mp_content_before = content; } else { m->mp_content_after = content; } } else { free (content); } } free (boundary); free (bufp); return OK; } char * ct_type_str (int type) { switch (type) { case CT_APPLICATION: return "application"; case CT_AUDIO: return "audio"; case CT_IMAGE: return "image"; case CT_MESSAGE: return "message"; case CT_MULTIPART: return "multipart"; case CT_TEXT: return "text"; case CT_VIDEO: return "video"; case CT_EXTENSION: return "extension"; default: return "unknown_type"; } } char * ct_subtype_str (int type, int subtype) { switch (type) { case CT_APPLICATION: switch (subtype) { case APPLICATION_OCTETS: return "octets"; case APPLICATION_POSTSCRIPT: return "postscript"; default: return "unknown_app_subtype"; } case CT_MESSAGE: switch (subtype) { case MESSAGE_RFC822: return "rfc822"; case MESSAGE_PARTIAL: return "partial"; case MESSAGE_EXTERNAL: return "external"; default: return "unknown_msg_subtype"; } case CT_MULTIPART: switch (subtype) { case MULTI_MIXED: return "mixed"; case MULTI_ALTERNATE: return "alternative"; case MULTI_DIGEST: return "digest"; case MULTI_PARALLEL: return "parallel"; case MULTI_RELATED: return "related"; default: return "unknown_multipart_subtype"; } case CT_TEXT: switch (subtype) { case TEXT_PLAIN: return "plain"; case TEXT_RICHTEXT: return "richtext"; case TEXT_ENRICHED: return "enriched"; default: return "unknown_text_subtype"; } default: return "unknown_type"; } } int ct_str_type (const char *type) { struct str2init *s2i; for (s2i = str2cts; s2i->si_key; ++s2i) { if (! strcasecmp (type, s2i->si_key)) { break; } } if (! s2i->si_key && ! uprf (type, "X-")) { ++s2i; } return s2i->si_val; } int ct_str_subtype (int type, const char *subtype) { struct k2v *kv; switch (type) { case CT_APPLICATION: for (kv = SubApplication; kv->kv_key; ++kv) { if (! strcasecmp (subtype, kv->kv_key)) { break; } } return kv->kv_value; case CT_MESSAGE: for (kv = SubMessage; kv->kv_key; ++kv) { if (! strcasecmp (subtype, kv->kv_key)) { break; } } return kv->kv_value; case CT_MULTIPART: for (kv = SubMultiPart; kv->kv_key; ++kv) { if (! strcasecmp (subtype, kv->kv_key)) { break; } } return kv->kv_value; case CT_TEXT: for (kv = SubText; kv->kv_key; ++kv) { if (! strcasecmp (subtype, kv->kv_key)) { break; } } return kv->kv_value; default: return 0; } } /* Find the content type and InitFunc for the CT. */ const struct str2init * get_ct_init (int type) { const struct str2init *sp; for (sp = str2cts; sp->si_key; ++sp) { if (type == sp->si_val) { return sp; } } return NULL; } const char * ce_str (int encoding) { switch (encoding) { case CE_BASE64: return "base64"; case CE_QUOTED: return "quoted-printable"; case CE_8BIT: return "8bit"; case CE_7BIT: return "7bit"; case CE_BINARY: return "binary"; case CE_EXTENSION: return "extension"; case CE_EXTERNAL: return "external"; default: return "unknown"; } } /* Find the content type and InitFunc for the content encoding method. */ const struct str2init * get_ce_method (const char *method) { struct str2init *sp; for (sp = str2ces; sp->si_key; ++sp) { if (! strcasecmp (method, sp->si_key)) { return sp; } } return NULL; } /* * Parse a series of MIME attributes (or parameters) given a header as * input. * * Arguments include: * * filename - Name of input file (for error messages) * fieldname - Name of field being processed * headerp - Pointer to pointer of the beginning of the MIME attributes. * Updated to point to end of attributes when finished. * param_head - Pointer to head of parameter list * param_tail - Pointer to tail of parameter list * commentp - Pointer to header comment pointer (may be NULL) * * Returns OK if parsing was successful, NOTOK if parsing failed, and * DONE to indicate a benign error (minor parsing error, but the program * should continue). */ static int parse_header_attrs (const char *filename, const char *fieldname, char **header_attrp, PM *param_head, PM *param_tail, char **commentp) { char *cp = *header_attrp; PM pm; struct sectlist { char *value; int index; int len; struct sectlist *next; } *sp, *sp2; struct parmlist { char *name; char *charset; char *lang; struct sectlist *sechead; struct parmlist *next; } *pp, *pp2, *phead = NULL; while (*cp == ';') { char *dp, *vp, *up, *nameptr, *valptr, *charset = NULL, *lang = NULL; int encoded = 0, partial = 0, len = 0, index = 0; cp++; while (isspace ((unsigned char) *cp)) cp++; if (*cp == '(' && get_comment (filename, fieldname, &cp, commentp) == NOTOK) { return NOTOK; } if (*cp == 0) { if (! suppress_extraneous_trailing_semicolon_warning) { inform("extraneous trailing ';' in message %s's %s: " "parameter list", filename, fieldname); } return DONE; } /* down case the attribute name */ for (dp = cp; istoken ((unsigned char) *dp); dp++) *dp = tolower ((unsigned char) *dp); for (up = dp; isspace ((unsigned char) *dp);) dp++; if (dp == cp || *dp != '=') { inform("invalid parameter in message %s's %s: " "field\n%*sparameter %s (error detected at offset %d)", filename, fieldname, strlen(invo_name) + 2, "",cp, dp - cp); return NOTOK; } /* * To handle RFC 2231, we have to deal with the following extensions: * * name*=encoded-value * name*=part-N-of-a-parameter-value * name**=encoded-part-N-of-a-parameter-value * * So the rule is: * If there's a * right before the equal sign, it's encoded. * If there's a * and one or more digits, then it's section N. * * Remember we can have one or the other, or both. cp points to * beginning of name, up points past the last character in the * parameter name. */ for (vp = cp; vp < up; vp++) { if (*vp == '*' && vp < up - 1) { partial = 1; continue; } if (*vp == '*' && vp == up - 1) { encoded = 1; } else if (partial) { if (isdigit((unsigned char) *vp)) index = *vp - '0' + index * 10; else { inform("invalid parameter index in message %s's " "%s: field\n%*s(parameter %s)", filename, fieldname, strlen(invo_name) + 2, "", cp); return NOTOK; } } else { len++; } } /* * Break out the parameter name and value sections and allocate * memory for each. */ nameptr = mh_xmalloc(len + 1); strncpy(nameptr, cp, len); nameptr[len] = '\0'; for (dp++; isspace ((unsigned char) *dp);) dp++; if (encoded) { /* * Single quotes delimit the character set and language tag. * They are required on the first section (or a complete * parameter). */ if (index == 0) { vp = dp; while (*vp != '\'' && !isspace((unsigned char) *vp) && *vp != '\0') vp++; if (*vp == '\'') { if (vp != dp) { len = vp - dp; charset = mh_xmalloc(len + 1); strncpy(charset, dp, len); charset[len] = '\0'; } else { charset = NULL; } vp++; } else { inform("missing charset in message %s's %s: " "field\n%*s(parameter %s)", filename, fieldname, strlen(invo_name) + 2, "", nameptr); free(nameptr); return NOTOK; } dp = vp; while (*vp != '\'' && !isspace((unsigned char) *vp) && *vp != '\0') vp++; if (*vp == '\'') { if (vp != dp) { len = vp - dp; lang = mh_xmalloc(len + 1); strncpy(lang, dp, len); lang[len] = '\0'; } else { lang = NULL; } vp++; } else { inform("missing language tag in message %s's %s: " "field\n%*s(parameter %s)", filename, fieldname, strlen(invo_name) + 2, "", nameptr); free(nameptr); mh_xfree(charset); return NOTOK; } dp = vp; } /* * At this point vp should be pointing at the beginning * of the encoded value/section. Continue until we reach * the end or get whitespace. But first, calculate the * length so we can allocate the correct buffer size. */ for (vp = dp, len = 0; istoken(*vp); vp++) { if (*vp == '%') { if (*(vp + 1) == '\0' || !isxdigit((unsigned char) *(vp + 1)) || *(vp + 2) == '\0' || !isxdigit((unsigned char) *(vp + 2))) { inform("invalid encoded sequence in message " "%s's %s: field\n%*s(parameter %s)", filename, fieldname, strlen(invo_name) + 2, "", nameptr); free(nameptr); mh_xfree(charset); mh_xfree(lang); return NOTOK; } vp += 2; } len++; } up = valptr = mh_xmalloc(len + 1); for (vp = dp; istoken(*vp); vp++) { if (*vp == '%') { *up++ = decode_qp(*(vp + 1), *(vp + 2)); vp += 2; } else { *up++ = *vp; } } *up = '\0'; cp = vp; } else { /* * A "normal" string. If it's got a leading quote, then we * strip the quotes out. Otherwise go until we reach the end * or get whitespace. Note we scan it twice; once to get the * length, then the second time copies it into the destination * buffer. */ len = 0; if (*dp == '"') { for (cp = dp + 1;;) { switch (*cp++) { case '\0': bad_quote: inform("invalid quoted-string in message %s's %s: " "field\n%*s(parameter %s)", filename, fieldname, strlen(invo_name) + 2, "", nameptr); free(nameptr); mh_xfree(charset); mh_xfree(lang); return NOTOK; case '"': break; case '\\': if (*++cp == '\0') goto bad_quote; /* FALLTHRU */ default: len++; continue; } break; } } else { for (cp = dp; istoken (*cp); cp++) { len++; } } valptr = mh_xmalloc(len + 1); if (*dp == '"') { int i; for (cp = dp + 1, vp = valptr, i = 0; i < len; i++) { if (*cp == '\\') { cp++; } *vp++ = *cp++; } cp++; } else { strncpy(valptr, cp = dp, len); cp += len; } valptr[len] = '\0'; } /* * If 'partial' is set, we don't allocate a parameter now. We * put it on the parameter linked list to be reassembled later. * * "phead" points to a list of all parameters we need to reassemble. * Each parameter has a list of sections. We insert the sections in * order. */ if (partial) { for (pp = phead; pp != NULL; pp = pp->next) { if (strcasecmp(nameptr, pp->name) == 0) { free (nameptr); nameptr = pp->name; break; } } if (pp == NULL) { NEW0(pp); pp->name = nameptr; pp->next = phead; phead = pp; } /* * Insert this into the section linked list */ NEW0(sp); sp->value = valptr; sp->index = index; sp->len = len; if (pp->sechead == NULL || pp->sechead->index > index) { sp->next = pp->sechead; pp->sechead = sp; } else { for (sp2 = pp->sechead; sp2 != NULL; sp2 = sp2->next) { if (sp2->index == sp->index) { inform("duplicate index (%d) in message " "%s's %s: field\n%*s(parameter %s)", sp->index, filename, fieldname, strlen(invo_name) + 2, "", nameptr); return NOTOK; } if (sp2->index < sp->index && (sp2->next == NULL || sp2->next->index > sp->index)) { sp->next = sp2->next; sp2->next = sp; break; } } if (sp2 == NULL) { inform("Internal error: cannot insert partial " "param in message %s's %s: field\n%*s(parameter %s)", filename, fieldname, strlen(invo_name) + 2, "", nameptr); return NOTOK; } } /* * Save our charset and lang tags. */ if (index == 0 && encoded) { mh_xfree(pp->charset); pp->charset = charset; mh_xfree(pp->lang); pp->lang = lang; } } else { pm = add_param(param_head, param_tail, nameptr, valptr, 1); pm->pm_charset = charset; pm->pm_lang = lang; } while (isspace ((unsigned char) *cp)) cp++; if (*cp == '(' && get_comment (filename, fieldname, &cp, commentp) == NOTOK) { return NOTOK; } } /* * Now that we're done, reassemble all of the partial parameters. */ for (pp = phead; pp != NULL; ) { char *p, *q; size_t tlen = 0; int pindex = 0; for (sp = pp->sechead; sp != NULL; sp = sp->next) { if (sp->index != pindex++) { inform("missing section %d for parameter in " "message %s's %s: field\n%*s(parameter %s)", pindex - 1, filename, fieldname, strlen(invo_name) + 2, "", pp->name); return NOTOK; } tlen += sp->len; } p = q = mh_xmalloc(tlen + 1); for (sp = pp->sechead; sp != NULL; ) { memcpy(q, sp->value, sp->len); q += sp->len; free(sp->value); sp2 = sp->next; free(sp); sp = sp2; } p[tlen] = '\0'; pm = add_param(param_head, param_tail, pp->name, p, 1); pm->pm_charset = pp->charset; pm->pm_lang = pp->lang; pp2 = pp->next; free(pp); pp = pp2; } *header_attrp = cp; return OK; } /* * Return the charset for a particular content type. */ char * content_charset (CT ct) { char *ret_charset = NULL; ret_charset = get_param(ct->c_ctinfo.ci_first_pm, "charset", '?', 0); return ret_charset ? ret_charset : mh_xstrdup("US-ASCII"); } /* * Create a string based on a list of output parameters. Assume that this * parameter string will be appended to an existing header, so start out * with the separator (;). Perform RFC 2231 encoding when necessary. */ char * output_params(size_t initialwidth, PM params, int *offsetout, int external) { char *paramout = NULL; char line[CPERLIN * 2], *q; int curlen, index, cont, encode, i; size_t valoff, numchars; while (params != NULL) { encode = 0; index = 0; valoff = 0; q = line; if (external && strcasecmp(params->pm_name, "body") == 0) continue; if (strlen(params->pm_name) > CPERLIN) { inform("Parameter name \"%s\" is too long", params->pm_name); mh_xfree(paramout); return NULL; } curlen = param_len(params, index, valoff, &encode, &cont, &numchars); /* * Loop until we get a parameter that fits within a line. We * assume new lines start with a tab, so check our overflow based * on that. */ while (cont) { *q++ = ';'; *q++ = '\n'; *q++ = '\t'; /* * At this point we're definitely continuing the line, so * be sure to include the parameter name and section index. */ q += snprintf(q, sizeof(line) - (q - line), "%s*%d", params->pm_name, index); /* * Both of these functions do a NUL termination */ if (encode) i = encode_param(params, q, sizeof(line) - (q - line), numchars, valoff, index); else i = normal_param(params, q, sizeof(line) - (q - line), numchars, valoff); if (i == 0) { mh_xfree(paramout); return NULL; } valoff += numchars; index++; curlen = param_len(params, index, valoff, &encode, &cont, &numchars); q = line; /* * "line" starts with a ;\n\t, so that doesn't count against * the length. But add 8 since it starts with a tab; that's * how we end up with 5. */ initialwidth = strlen(line) + 5; /* * At this point the line should be built, so add it to our * current output buffer. */ paramout = add(line, paramout); } /* * If this won't fit on the line, start a new one. Save room in * case we need a semicolon on the end */ if (initialwidth + curlen > CPERLIN - 1) { *q++ = ';'; *q++ = '\n'; *q++ = '\t'; initialwidth = 8; } else { *q++ = ';'; *q++ = ' '; initialwidth += 2; } /* * At this point, we're either finishing a continued parameter, or * we're working on a new one. */ if (index > 0) { q += snprintf(q, sizeof(line) - (q - line), "%s*%d", params->pm_name, index); } else { strncpy(q, params->pm_name, sizeof(line) - (q - line)); q += strlen(q); } if (encode) i = encode_param(params, q, sizeof(line) - (q - line), strlen(params->pm_value + valoff), valoff, index); else i = normal_param(params, q, sizeof(line) - (q - line), strlen(params->pm_value + valoff), valoff); if (i == 0) { mh_xfree(paramout); return NULL; } paramout = add(line, paramout); initialwidth += strlen(line); params = params->pm_next; } if (offsetout) *offsetout = initialwidth; return paramout; } /* * Calculate the size of a parameter. * * Arguments include * * pm - The parameter being output * index - If continuing the parameter, the index of the section * we're on. * valueoff - The current offset into the parameter value that we're * working on (previous sections have consumed valueoff bytes). * encode - Set if we should perform encoding on this parameter section * (given that we're consuming bytesfit bytes). * cont - Set if the remaining data in value will not fit on a single * line and will need to be continued. * bytesfit - The number of bytes that we can consume from the parameter * value and still fit on a completely new line. The * calculation assumes the new line starts with a tab, * includes the parameter name and any encoding, and fits * within CPERLIN bytes. Will always be at least 1. */ static size_t param_len(PM pm, int index, size_t valueoff, int *encode, int *cont, size_t *bytesfit) { char *start = pm->pm_value + valueoff, *p, indexchar[32]; size_t len = 0, fit = 0; int fitlimit = 0, eightbit, maxfit; *encode = 0; /* * Add up the length. First, start with the parameter name. */ len = strlen(pm->pm_name); /* * Scan the parameter value and see if we need to do encoding for this * section. */ eightbit = contains8bit(start, NULL); /* * Determine if we need to encode this section. Encoding is necessary if: * * - There are any 8-bit characters at all and we're on the first * section. * - There are 8-bit characters within N bytes of our section start. * N is calculated based on the number of bytes it would take to * reach CPERLIN. Specifically: * 8 (starting tab) + * strlen(param name) + * 4 ('* for section marker, '=', opening/closing '"') * strlen (index) * is the number of bytes used by everything that isn't part of the * value. So that gets subtracted from CPERLIN. */ snprintf(indexchar, sizeof(indexchar), "%d", index); maxfit = CPERLIN - (12 + len + strlen(indexchar)); if ((eightbit && index == 0) || contains8bit(start, start + maxfit)) { *encode = 1; } len++; /* Add in equal sign */ if (*encode) { /* * We're using maxfit as a marker for how many characters we can * fit into the line. Bump it by two because we're not using quotes * when encoding. */ maxfit += 2; /* * If we don't have a charset or language tag in this parameter, * add them now. */ if (! pm->pm_charset) { pm->pm_charset = mh_xstrdup(write_charset_8bit()); if (strcasecmp(pm->pm_charset, "US-ASCII") == 0) adios(NULL, "8-bit characters in parameter \"%s\", but " "local character set is US-ASCII", pm->pm_name); } if (! pm->pm_lang) pm->pm_lang = mh_xstrdup(""); /* Default to a blank lang tag */ len++; /* For the encoding marker */ maxfit--; if (index == 0) { int enclen = strlen(pm->pm_charset) + strlen(pm->pm_lang) + 2; len += enclen; maxfit-= enclen; } else { /* * We know we definitely need to include an index. maxfit already * includes the section marker. */ len += strlen(indexchar); } for (p = start; *p != '\0'; p++) { if (isparamencode(*p)) { len += 3; maxfit -= 3; } else { len++; maxfit--; } /* * Just so there's no confusion: maxfit is counting OUTPUT * characters (post-encoding). fit is counting INPUT characters. */ if (! fitlimit && maxfit >= 0) fit++; else if (! fitlimit) fitlimit++; } } else { /* * Calculate the string length, but add room for quoting \ * and " if necessary. Also account for quotes at beginning * and end. */ for (p = start; *p != '\0'; p++) { switch (*p) { case '"': case '\\': len++; maxfit--; /* FALLTHRU */ default: len++; maxfit--; } if (! fitlimit && maxfit >= 0) fit++; else if (! fitlimit) fitlimit++; } len += 2; } if (fit < 1) fit = 1; *cont = fitlimit; *bytesfit = fit; return len; } /* * Output an encoded parameter string. */ size_t encode_param(PM pm, char *output, size_t len, size_t valuelen, size_t valueoff, int index) { size_t outlen = 0, n; char *endptr = output + len, *p; /* * First, output the marker for an encoded string. */ *output++ = '*'; *output++ = '='; outlen += 2; /* * If the index is 0, output the character set and language tag. * If theses were NULL, they should have already been filled in * by param_len(). */ if (index == 0) { n = snprintf(output, len - outlen, "%s'%s'", pm->pm_charset, pm->pm_lang); output += n; outlen += n; if (output > endptr) { inform("Internal error: parameter buffer overflow"); return 0; } } /* * Copy over the value, encoding if necessary */ p = pm->pm_value + valueoff; while (valuelen-- > 0) { if (isparamencode(*p)) { n = snprintf(output, len - outlen, "%%%02X", (unsigned char) *p++); output += n; outlen += n; } else { *output++ = *p++; outlen++; } if (output > endptr) { inform("Internal error: parameter buffer overflow"); return 0; } } *output = '\0'; return outlen; } /* * Output a "normal" parameter, without encoding. Be sure to escape * quotes and backslashes if necessary. */ static size_t normal_param(PM pm, char *output, size_t len, size_t valuelen, size_t valueoff) { size_t outlen = 0; char *endptr = output + len, *p; *output++ = '='; *output++ = '"'; outlen += 2; p = pm->pm_value + valueoff; while (valuelen-- > 0) { switch (*p) { case '\\': case '"': *output++ = '\\'; outlen++; /* FALLTHRU */ default: *output++ = *p++; outlen++; } if (output > endptr) { inform("Internal error: parameter buffer overflow"); return 0; } } if (output - 2 > endptr) { inform("Internal error: parameter buffer overflow"); return 0; } *output++ = '"'; *output++ = '\0'; return outlen + 1; } /* * Add a parameter to the parameter linked list */ PM add_param(PM *first, PM *last, char *name, char *value, int nocopy) { PM pm; NEW0(pm); pm->pm_name = nocopy ? name : getcpy(name); pm->pm_value = nocopy ? value : getcpy(value); if (*first) { (*last)->pm_next = pm; *last = pm; } else { *first = pm; *last = pm; } return pm; } /* * Either replace a current parameter with a new value, or add the parameter * to the parameter linked list. */ PM replace_param(PM *first, PM *last, char *name, char *value, int nocopy) { PM pm; for (pm = *first; pm != NULL; pm = pm->pm_next) { if (strcasecmp(name, pm->pm_name) == 0) { /* * If nocopy is set, it's assumed that we own both name * and value. We don't need name, so we discard it now. */ if (nocopy) free(name); free(pm->pm_value); pm->pm_value = nocopy ? value : getcpy(value); return pm; } } return add_param(first, last, name, value, nocopy); } /* * Retrieve a parameter value from a parameter linked list. If the parameter * value needs converted to the local character set, do that now. */ char * get_param(PM first, const char *name, char replace, int fetchonly) { while (first != NULL) { if (strcasecmp(name, first->pm_name) == 0) { if (fetchonly) return first->pm_value; return getcpy(get_param_value(first, replace)); } first = first->pm_next; } return NULL; } /* * Return a parameter value, converting to the local character set if * necessary */ char *get_param_value(PM pm, char replace) { static char buffer[4096]; /* I hope no parameters are larger */ size_t bufsize = sizeof(buffer); #ifdef HAVE_ICONV size_t inbytes; int utf8; iconv_t cd; ICONV_CONST char *p; #else /* HAVE_ICONV */ char *p; #endif /* HAVE_ICONV */ char *q; /* * If we don't have a character set indicated, it's assumed to be * US-ASCII. If it matches our character set, we don't need to convert * anything. */ if (!pm->pm_charset || check_charset(pm->pm_charset, strlen(pm->pm_charset))) { return pm->pm_value; } /* * In this case, we need to convert. If we have iconv support, use * that. Otherwise, go through and simply replace every non-ASCII * character with the substitution character. */ #ifdef HAVE_ICONV q = buffer; bufsize = sizeof(buffer); utf8 = strcasecmp(pm->pm_charset, "UTF-8") == 0; cd = iconv_open(get_charset(), pm->pm_charset); if (cd == (iconv_t) -1) { goto noiconv; } inbytes = strlen(pm->pm_value); p = pm->pm_value; while (inbytes) { if (iconv(cd, &p, &inbytes, &q, &bufsize) == (size_t)-1) { if (errno != EILSEQ) { iconv_close(cd); goto noiconv; } /* * Reset shift state, substitute our character, * try to restart conversion. */ iconv(cd, NULL, NULL, &q, &bufsize); if (bufsize == 0) { iconv_close(cd); goto noiconv; } *q++ = replace; bufsize--; if (bufsize == 0) { iconv_close(cd); goto noiconv; } if (utf8) { for (++p, --inbytes; inbytes > 0 && (((unsigned char) *p) & 0xc0) == 0x80; ++p, --inbytes) continue; } else { p++; inbytes--; } } } iconv_close(cd); if (bufsize == 0) q--; *q = '\0'; return buffer; noiconv: #endif /* HAVE_ICONV */ /* * Take everything non-ASCII and substitute the replacement character */ q = buffer; bufsize = sizeof(buffer); for (p = pm->pm_value; *p != '\0' && bufsize > 1; p++, q++, bufsize--) { if (isascii((unsigned char) *p) && isprint((unsigned char) *p)) *q = *p; else *q = replace; } *q = '\0'; return buffer; } nmh-1.7.1-RC3/uip/mhpath.c000644 007761 000024 00000006207 13243042054 015206 0ustar00kenhstaff000000 000000 /* mhpath.c -- print full pathnames of nmh messages and folders * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include "../sbr/m_maildir.h" #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) { int i; char *cp, *maildir, *folder = NULL; char **argp; char **arguments, buf[BUFSIZ]; struct msgs_array msgs = { 0, 0, NULL }; struct msgs *mp; if (nmh_init(argv[0], 2)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; /* * Parse arguments */ while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [+folder] [msgs] [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); } } if (*cp == '+' || *cp == '@') { if (folder) adios (NULL, "only one folder at a time!"); else folder = pluspath (cp); } else app_msgarg(&msgs, cp); } if (!context_find ("path")) free (path ("./", TFOLDER)); if (!folder) folder = getfolder (1); maildir = m_maildir (folder); /* If no messages are given, print folder pathname */ if (!msgs.size) { puts(maildir); done (0); } if (chdir (maildir) == NOTOK) adios (maildir, "unable to change directory to"); /* read folder and create message structure */ if (!(mp = folder_read (folder, 1))) adios (NULL, "unable to read folder %s", folder); /* * We need to make sure there is message status space * for all the message numbers from 1 to "new" since * mhpath can select empty slots. If we are adding * space at the end, we go ahead and add 10 slots. */ if (mp->hghmsg >= mp->hghoff) { if (!(mp = folder_realloc (mp, 1, mp->hghmsg + 10))) adios (NULL, "unable to allocate folder storage"); } else if (mp->lowoff > 1) { if (!(mp = folder_realloc (mp, 1, mp->hghoff))) adios (NULL, "unable to allocate folder storage"); } mp->msgflags |= ALLOW_NEW; /* allow the "new" sequence */ /* parse all the message ranges/sequences and set SELECTED */ for (i = 0; i < msgs.size; i++) if (!m_convert (mp, msgs.msgs[i])) done (1); seq_setprev (mp); /* set the previous-sequence */ /* print the path of all selected messages */ for (i = mp->lowsel; i <= mp->hghsel; i++) if (is_selected (mp, i)) printf ("%s/%s\n", mp->foldpath, m_name (i)); seq_save (mp); /* synchronize message sequences */ context_save (); /* save the context file */ folder_free (mp); /* free folder/message structure */ done (0); return 1; } nmh-1.7.1-RC3/uip/mhshow.c000644 007761 000024 00000024500 13243042054 015226 0ustar00kenhstaff000000 000000 /* mhshow.c -- display the contents of MIME messages * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #include #include #include #include #include #include "../sbr/m_maildir.h" #include "../sbr/m_popen.h" #include "mhfree.h" #include "mhshowsbr.h" #define MHSHOW_SWITCHES \ X("check", 0, CHECKSW) \ X("nocheck", 0, NCHECKSW) \ X("verbose", 0, VERBSW) \ X("noverbose", 0, NVERBSW) \ X("concat", 0, CONCATSW) \ X("noconcat", 0, NCONCATSW) \ X("textonly", 0, TEXTONLYSW) \ X("notextonly", 0, NTEXTONLYSW) \ X("inlineonly", 0, INLINESW) \ X("noinlineonly", 0, NINLINESW) \ X("file file", 0, FILESW) \ X("form formfile", 0, FORMSW) \ X("header", 0, HEADSW) \ X("noheader", 0, NHEADSW) \ X("headerform formfile", 0, HEADFORMSW) \ X("markform formfile", 0, MARKFORMSW) \ X("part number", 0, PARTSW) \ X("type content", 0, TYPESW) \ X("prefer content", 0, PREFERSW) \ X("noprefer", 0, NPREFERSW) \ 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 /* mhmisc.c */ extern int npart; extern int ntype; extern char *parts[NPARTS + 1]; extern char *types[NTYPES + 1]; extern int userrs; /* mhparse.c */ extern char *preferred_types[]; extern char *preferred_subtypes[]; extern int npreferred; int debugsw = 0; int verbosw = 0; #define quitser pipeser /* mhparse.c */ CT parse_mime (char *); /* mhmisc.c */ int part_ok (CT); int type_ok (CT, int); void flush_errors (void); /* * static prototypes */ static void pipeser (int); int main (int argc, char **argv) { int msgnum, *icachesw, concatsw = -1, textonly = -1, inlineonly = -1; char *cp, *file = NULL; char *maildir, buf[100], **argp; char **arguments; struct msgs_array msgs = { 0, 0, NULL }; struct msgs *mp = NULL; CT ct, *ctp; FILE *fp; if (nmh_init(argv[0], 1)) { return 1; } done=freects_done; arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; /* * Parse arguments */ while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [+folder] [msgs] [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case RCACHESW: icachesw = &rcachesw; goto do_cache; case WCACHESW: icachesw = &wcachesw; do_cache: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); switch (*icachesw = smatch (cp, cache_policy)) { case AMBIGSW: ambigsw (cp, cache_policy); done (1); case UNKWNSW: adios (NULL, "%s unknown", cp); default: break; } continue; case CHECKSW: checksw++; continue; case NCHECKSW: checksw = 0; continue; case CONCATSW: concatsw = 1; continue; case NCONCATSW: concatsw = 0; continue; case TEXTONLYSW: textonly = 1; continue; case NTEXTONLYSW: textonly = 0; continue; case INLINESW: inlineonly = 1; continue; case NINLINESW: inlineonly = 0; continue; case PARTSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if (npart >= NPARTS) adios (NULL, "too many parts (starting with %s), %d max", cp, NPARTS); parts[npart++] = cp; continue; case TYPESW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if (ntype >= NTYPES) adios (NULL, "too many types (starting with %s), %d max", cp, NTYPES); types[ntype++] = cp; continue; case PREFERSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if (npreferred >= NPREFS) adios (NULL, "too many preferred types (starting with %s), %d max", cp, NPREFS); preferred_types[npreferred] = cp; cp = strchr(cp, '/'); if (cp) *cp++ = '\0'; preferred_subtypes[npreferred++] = cp; continue; case NPREFERSW: npreferred = 0; continue; case FILESW: if (!(cp = *argp++) || (*cp == '-' && cp[1])) adios (NULL, "missing argument to %s", argp[-2]); file = *cp == '-' ? cp : path (cp, TFILE); continue; case FORMSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); mh_xfree(formsw); formsw = getcpy (etcpath (cp)); continue; case HEADSW: headersw = 1; continue; case NHEADSW: headersw = 0; continue; case HEADFORMSW: if (!(headerform = *argp++) || *headerform == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case MARKFORMSW: if (!(markerform = *argp++) || *markerform == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; /* * Switches for moreproc/mhlproc */ case PROGSW: if (!(progsw = *argp++) || *progsw == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case NPROGSW: nomore++; continue; case LENSW: case WIDTHSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case VERBSW: verbosw = 1; continue; case NVERBSW: verbosw = 0; continue; case DEBUGSW: debugsw = 1; continue; } } if (*cp == '+' || *cp == '@') { if (folder) adios (NULL, "only one folder at a time!"); else folder = pluspath (cp); } else app_msgarg(&msgs, cp); } /* null terminate the list of acceptable parts/types */ parts[npart] = NULL; types[ntype] = NULL; /* * If we had any specific parts or types specified, turn off text only * content. */ if (npart > 0 || ntype > 0) { if (textonly == -1) textonly = 0; if (inlineonly == -1) inlineonly = 0; } /* * Check if we've specified an additional profile */ if ((cp = getenv ("MHSHOW"))) { if ((fp = fopen (cp, "r"))) { readconfig ((struct node **) 0, fp, cp, 0); fclose (fp); } else { admonish ("", "unable to read $MHSHOW profile (%s)", cp); } } /* * Read the standard profile setup */ if ((fp = fopen (cp = etcpath ("mhn.defaults"), "r"))) { readconfig ((struct node **) 0, fp, cp, 0); fclose (fp); } /* Check for public cache location */ if ((cache_public = context_find (nmhcache)) && *cache_public != '/') cache_public = NULL; /* Check for private cache location */ if (!(cache_private = context_find (nmhprivcache))) cache_private = ".cache"; cache_private = getcpy (m_maildir (cache_private)); if (!context_find ("path")) free (path ("./", TFOLDER)); if (file && msgs.size) adios (NULL, "cannot specify msg and file at same time!"); /* * check if message is coming from file */ if (file) { cts = mh_xcalloc(2, sizeof *cts); ctp = cts; if ((ct = parse_mime (file))) *ctp++ = ct; headersw = 0; } else { /* * message(s) are coming from a folder */ if (!msgs.size) app_msgarg(&msgs, "cur"); if (!folder) folder = getfolder (1); maildir = m_maildir (folder); if (chdir (maildir) == NOTOK) adios (maildir, "unable to change directory to"); /* read folder and create message structure */ if (!(mp = folder_read (folder, 1))) adios (NULL, "unable to read folder %s", folder); /* check for empty folder */ if (mp->nummsg == 0) adios (NULL, "no messages in %s", folder); /* parse all the message ranges/sequences and set SELECTED */ for (msgnum = 0; msgnum < msgs.size; msgnum++) if (!m_convert (mp, msgs.msgs[msgnum])) done (1); /* * Set the SELECT_UNSEEN bit for all the SELECTED messages, * since we will use that as a tag to know which messages * to remove from the "unseen" sequence. */ for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) if (is_selected(mp, msgnum)) set_unseen (mp, msgnum); seq_setprev (mp); /* set the Previous-Sequence */ seq_setunseen (mp, 1); /* unset the Unseen-Sequence */ cts = mh_xcalloc(mp->numsel + 1, sizeof *cts); ctp = cts; /* * Parse all the SELECTED messages. */ for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { if (is_selected(mp, msgnum)) { char *msgnam; msgnam = m_name (msgnum); if ((ct = parse_mime (msgnam))) *ctp++ = ct; } } } if (!*cts) done (1); userrs = 1; SIGNAL (SIGQUIT, quitser); SIGNAL (SIGPIPE, pipeser); /* * Get the associated umask for the relevant contents. */ for (ctp = cts; *ctp; ctp++) { struct stat st; ct = *ctp; if (type_ok (ct, 1) && !ct->c_umask) { if (stat (ct->c_file, &st) != NOTOK) ct->c_umask = ~(st.st_mode & 0777); else ct->c_umask = ~m_gmprot(); } } /* If reading from a folder, do some updating */ if (mp) { context_replace (pfolder, folder);/* update current folder */ seq_setcur (mp, mp->hghsel); /* update current message */ seq_save (mp); /* synchronize sequences */ context_save (); /* save the context file */ } if (concatsw) m_popen(moreproc, 0); /* * Show the message content */ show_all_messages (cts, concatsw, textonly, inlineonly); /* Now free all the structures for the content */ for (ctp = cts; *ctp; ctp++) free_content (*ctp); free(cts); cts = NULL; if (concatsw) m_pclose(); done (0); return 1; } static void pipeser (int i) { if (i == SIGQUIT) { fflush (stdout); fprintf (stderr, "\n"); fflush (stderr); } done (1); /* NOTREACHED */ } nmh-1.7.1-RC3/uip/mhshowsbr.c000644 007761 000024 00000113425 13243042054 015742 0ustar00kenhstaff000000 000000 /* mhshowsbr.c -- routines to display the contents of MIME messages * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #include #include #include #include #include "mhshowsbr.h" #include "../sbr/m_mktemp.h" #ifdef HAVE_ICONV # include #endif /* ! HAVE_ICONV */ extern int debugsw; extern int npart; extern int ntype; int nolist = 0; char *progsw = NULL; /* flags for moreproc/header display */ int nomore = 0; char *formsw = NULL; /* for output markerss and headers */ char *folder = NULL; char *markerform; char *headerform; int headersw = -1; /* mhmisc.c */ int part_ok (CT); int part_exact (CT); int type_ok (CT, int); void content_error (char *, CT, char *, ...); void flush_errors (void); /* * static prototypes */ static void show_single_message (CT, char *, int, int, int, struct format *); static void DisplayMsgHeader (CT, char *, int); static int show_switch (CT, int, int, int, int, struct format *); static int show_content (CT, int, int, int, struct format *); static int show_content_aux2 (CT, int, char *, char *, int, int, int, struct format *); static int show_text (CT, int, int, struct format *); static int show_multi (CT, int, int, int, int, struct format *); static int show_multi_internal (CT, int, int, int, int, struct format *); static int show_multi_aux (CT, int, char *, struct format *); static int show_message_rfc822 (CT, int, struct format *); static int show_partial (CT, int); static int show_external (CT, int, int, int, int, struct format *); static int parse_display_string (CT, char *, int *, int *, char *, char *, size_t, int multipart); static int convert_content_charset (CT, char **); static struct format *compile_header(char *); static struct format *compile_marker(char *); static void output_header (CT, struct format *); static void output_marker (CT, struct format *, int); static void free_markercomps (void); static int pidcheck(int); /* * Components (and list of parameters/components) we care about for the * content marker display. */ static struct comp *folder_comp = NULL; static struct comp *part_comp = NULL; static struct comp *ctype_comp = NULL; static struct comp *description_comp = NULL; static struct comp *dispo_comp = NULL; struct param_comp_list { char *param; struct comp *comp; struct param_comp_list *next; }; static struct param_comp_list *ctype_pc_list = NULL; static struct param_comp_list *dispo_pc_list = NULL; /* * Top level entry point to show/display a group of messages */ void show_all_messages(CT *cts, int concat, int textonly, int inlineonly) { CT ct, *ctp; struct format *hfmt, *mfmt; /* * If form is not specified, then get default form * for showing headers of MIME messages. */ if (!formsw) formsw = getcpy (etcpath ("mhl.headers")); /* * Compile the content marker and header format lines */ mfmt = compile_marker(markerform); hfmt = compile_header(headerform); /* * If form is "mhl.null", suppress display of header. */ if (!strcmp (formsw, "mhl.null")) formsw = NULL; for (ctp = cts; *ctp; ctp++) { ct = *ctp; /* if top-level type is ok, then display message */ if (type_ok (ct, 1)) { if (headersw) output_header(ct, hfmt); show_single_message (ct, formsw, concat, textonly, inlineonly, mfmt); } } free_markercomps(); fmt_free(hfmt, 1); fmt_free(mfmt, 1); } /* * Entry point to show/display a single message */ static void show_single_message (CT ct, char *form, int concatsw, int textonly, int inlineonly, struct format *fmt) { sigset_t set, oset; int status = OK; /* Allow user executable bit so that temporary directories created by * the viewer (e.g., lynx) are going to be accessible */ umask (ct->c_umask & ~(0100)); /* * If you have a format file, then display * the message headers. */ if (form) DisplayMsgHeader(ct, form, concatsw); /* Show the body of the message */ show_switch (ct, 0, concatsw, textonly, inlineonly, fmt); if (ct->c_fp) { fclose (ct->c_fp); ct->c_fp = NULL; } if (ct->c_ceclosefnx) (*ct->c_ceclosefnx) (ct); /* block a few signals */ sigemptyset (&set); sigaddset (&set, SIGHUP); sigaddset (&set, SIGINT); sigaddset (&set, SIGQUIT); sigaddset (&set, SIGTERM); sigprocmask (SIG_BLOCK, &set, &oset); while (!concatsw && wait (&status) != NOTOK) { pidcheck (status); continue; } /* reset the signal mask */ sigprocmask (SIG_SETMASK, &oset, &set); flush_errors (); } /* * Use the mhlproc to show the header fields */ static void DisplayMsgHeader (CT ct, char *form, int concatsw) { pid_t child_id; int i, vecp; char **vec; char *file; vec = argsplit(mhlproc, &file, &vecp); vec[vecp++] = mh_xstrdup("-form"); vec[vecp++] = mh_xstrdup(form); vec[vecp++] = mh_xstrdup("-nobody"); vec[vecp++] = getcpy(ct->c_file); /* * If we've specified -(no)moreproc, * then just pass that along. */ if (nomore || concatsw) { vec[vecp++] = mh_xstrdup("-nomoreproc"); } else if (progsw) { vec[vecp++] = mh_xstrdup("-moreproc"); vec[vecp++] = mh_xstrdup(progsw); } vec[vecp] = NULL; fflush (stdout); for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++) sleep (5); switch (child_id) { case NOTOK: adios ("fork", "unable to"); /* NOTREACHED */ case OK: execvp (file, vec); fprintf (stderr, "unable to exec "); perror (mhlproc); _exit (-1); /* NOTREACHED */ default: pidcheck(pidwait(child_id, NOTOK)); break; } arglist_free(file, vec); } /* * Switching routine. Call the correct routine * based on content type. */ static int show_switch (CT ct, int alternate, int concatsw, int textonly, int inlineonly, struct format *fmt) { switch (ct->c_type) { case CT_MULTIPART: return show_multi (ct, alternate, concatsw, textonly, inlineonly, fmt); case CT_MESSAGE: switch (ct->c_subtype) { case MESSAGE_PARTIAL: return show_partial (ct, alternate); case MESSAGE_EXTERNAL: return show_external (ct, alternate, concatsw, textonly, inlineonly, fmt); case MESSAGE_RFC822: return show_message_rfc822 (ct, alternate, fmt); /* * Treat unknown message types as equivalent to * application/octet-stream for now */ default: return show_content (ct, alternate, textonly, inlineonly, fmt); } case CT_TEXT: return show_text (ct, alternate, concatsw, fmt); case CT_AUDIO: case CT_IMAGE: case CT_VIDEO: case CT_APPLICATION: default: return show_content (ct, alternate, textonly, inlineonly, fmt); } return 0; /* NOT REACHED */ } /* * Generic method for displaying content */ static int show_content (CT ct, int alternate, int textonly, int inlineonly, struct format *fmt) { char *cp; CI ci = &ct->c_ctinfo; /* * If we're here, we are not a text type. So we don't need to check * the content-type. */ if (textonly || (inlineonly && !is_inline(ct))) { output_marker(ct, fmt, 1); return OK; } /* Check for invo_name-show-type[/subtype] */ if ((cp = context_find_by_type ("show", ci->ci_type, ci->ci_subtype))) return show_content_aux (ct, alternate, cp, NULL, fmt); if ((cp = ct->c_showproc)) return show_content_aux (ct, alternate, cp, NULL, fmt); /* complain if we are not a part of a multipart/alternative */ if (!alternate) content_error (NULL, ct, "don't know how to display content"); return NOTOK; } /* * Parse the display string for displaying generic content */ int show_content_aux (CT ct, int alternate, char *cp, char *cracked, struct format *fmt) { int fd; int xstdin = 0, xlist = 0; char *file = NULL, buffer[NMH_BUFSIZ]; if (!ct->c_ceopenfnx) { if (!alternate) content_error (NULL, ct, "don't know how to decode content"); return NOTOK; } if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK) return NOTOK; if (ct->c_showproc && !strcmp (ct->c_showproc, "true")) return OK; if (! strcmp(invo_name, "mhshow") && ct->c_type == CT_TEXT && ct->c_subtype == TEXT_PLAIN) { /* This has to be done after calling c_ceopenfnx, so unfortunately the type checks are necessary without some code rearrangement. And to make this really ugly, only do it in mhshow, not mhfixmsg, mhn, or mhstore. */ if (convert_content_charset (ct, &file) == OK) { (*ct->c_ceclosefnx) (ct); if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK) return NOTOK; } else { char *charset = content_charset (ct); inform("unable to convert character set%s%s from %s, continuing...", ct->c_partno ? " of part " : "", FENDNULL(ct->c_partno), charset); free (charset); } } if (cracked) { strncpy (buffer, cp, sizeof(buffer)); goto got_command; } if (parse_display_string (ct, cp, &xstdin, &xlist, file, buffer, sizeof(buffer) - 1, 0)) { inform("Buffer overflow constructing show command, continuing..."); return NOTOK; } got_command: return show_content_aux2 (ct, alternate, cracked, buffer, fd, xlist, xstdin, fmt); } /* * Routine to actually display the content */ static int show_content_aux2 (CT ct, int alternate, char *cracked, char *buffer, int fd, int xlist, int xstdin, struct format *fmt) { pid_t child_id; int i, vecp; char **vec, *file; if (debugsw || cracked) { fflush (stdout); fprintf (stderr, "%s msg %s", cracked ? "storing" : "show", ct->c_file); if (ct->c_partno) fprintf (stderr, " part %s", ct->c_partno); if (cracked) fprintf (stderr, " using command (cd %s; %s)\n", cracked, buffer); else fprintf (stderr, " using command %s\n", buffer); } if (xlist && fmt) { output_marker(ct, fmt, 0); } /* * If the command is a zero-length string, just write the output on * stdout. */ if (buffer[0] == '\0') { char readbuf[BUFSIZ]; ssize_t cc; char lastchar = '\n'; if (fd == NOTOK) { inform("Cannot use NULL command to display content-type " "%s/%s", ct->c_ctinfo.ci_type, ct->c_ctinfo.ci_subtype); return NOTOK; } while ((cc = read(fd, readbuf, sizeof(readbuf))) > 0) { if ((ssize_t) fwrite(readbuf, sizeof(char), cc, stdout) < cc) { advise ("putline", "fwrite"); } lastchar = readbuf[cc - 1]; } if (cc < 0) { advise("read", "while reading text content"); return NOTOK; } /* * The MIME standards allow content to not have a trailing newline. * But because we are (presumably) sending this to stdout, include * a newline for text content if the final character was not a * newline. Only do this for mhshow. */ if (strcmp(invo_name, "mhshow") == 0 && ct->c_type == CT_TEXT && ct->c_subtype == TEXT_PLAIN && lastchar != '\n') { putchar('\n'); } fflush(stdout); return OK; } vec = argsplit(buffer, &file, &vecp); vec[vecp++] = NULL; fflush (stdout); for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++) sleep (5); switch (child_id) { case NOTOK: advise ("fork", "unable to"); (*ct->c_ceclosefnx) (ct); return NOTOK; case OK: if (cracked) { if (chdir (cracked) < 0) { advise (cracked, "chdir"); } } if (!xstdin) dup2 (fd, 0); close (fd); execvp (file, vec); fprintf (stderr, "unable to exec "); perror (buffer); _exit (-1); /* NOTREACHED */ default: { int status; char *display_prog = vecp > 2 && vec[2][0] != '\0' /* Copy the real display program name. This relies on the specific construction of vec[] by argsplit(). */ ? vec[2] : NULL; pidcheck ((status = pidXwait (child_id, display_prog))); arglist_free(file, vec); if (fd != NOTOK) (*ct->c_ceclosefnx) (ct); return (alternate ? OK : status); } } } /* * show content of type "text" */ static int show_text (CT ct, int alternate, int concatsw, struct format *fmt) { char *cp, buffer[BUFSIZ]; CI ci = &ct->c_ctinfo; /* Check for invo_name-show-type[/subtype] */ if ((cp = context_find_by_type ("show", ci->ci_type, ci->ci_subtype))) return show_content_aux (ct, alternate, cp, NULL, fmt); /* * Use default method if content is text/plain, or if * if it is not a text part of a multipart/alternative */ if (!alternate || ct->c_subtype == TEXT_PLAIN) { if (concatsw) { if (ct->c_termproc) snprintf(buffer, sizeof(buffer), "%%lcat"); else snprintf(buffer, sizeof(buffer), "%%l"); } else snprintf (buffer, sizeof(buffer), "%%l%s %%F", progsw ? progsw : moreproc && *moreproc ? moreproc : DEFAULT_PAGER); cp = (ct->c_showproc = mh_xstrdup(buffer)); return show_content_aux (ct, alternate, cp, NULL, fmt); } return NOTOK; } /* * show message body of type "multipart" */ static int show_multi (CT ct, int alternate, int concatsw, int textonly, int inlineonly, struct format *fmt) { char *cp; CI ci = &ct->c_ctinfo; /* Check for invo_name-show-type[/subtype] */ if ((cp = context_find_by_type ("show", ci->ci_type, ci->ci_subtype))) return show_multi_aux (ct, alternate, cp, fmt); if ((cp = ct->c_showproc)) { return show_multi_aux (ct, alternate, cp, fmt); } /* * Use default method to display this multipart content. Even * unknown types are displayable, since they're treated as mixed * per RFC 2046. */ return show_multi_internal (ct, alternate, concatsw, textonly, inlineonly, fmt); } /* * show message body of subtypes of multipart that * we understand directly (mixed, alternate, etc...) */ static int show_multi_internal (CT ct, int alternate, int concatsw, int textonly, int inlineonly, struct format *fmt) { int alternating, nowalternate, result; struct multipart *m = (struct multipart *) ct->c_ctparams; struct part *part; int request_matched; int display_success; int mult_alt_done; int ret; CT p; alternating = 0; nowalternate = alternate; if (ct->c_subtype == MULTI_ALTERNATE) { nowalternate = 1; alternating = 1; } /* * alternate -> we are a part inside a multipart/alternative * alternating -> we are a multipart/alternative */ result = NOTOK; request_matched = 0; display_success = 0; mult_alt_done = 0; for (part = m->mp_parts; part; part = part->mp_next) { p = part->mp_part; /* while looking for the right displayable alternative, we * use a looser search criterion than we do after finding it. * specifically, while still looking, part_ok() will match * "parent" parts (e.g. "-part 2" where 2 is a high-level * multipart). after finding it, we use part_exact() to only * choose a part that was requested explicitly. */ if ((part_exact(p) && type_ok(p, 1)) || (!mult_alt_done && part_ok (p) && type_ok (p, 1))) { int inneresult; inneresult = show_switch (p, nowalternate, concatsw, textonly, inlineonly, fmt); switch (inneresult) { case NOTOK: /* hard display error */ request_matched = 1; if (alternate && !alternating) { result = NOTOK; goto out; } continue; case DONE: /* found no match on content type */ continue; case OK: /* display successful */ request_matched = 1; display_success = 1; result = OK; /* if we got success on a sub-part of * multipart/alternative, we're done, unless * there's a chance an explicit part should be * matched later in the alternatives. */ if (alternating) { mult_alt_done = 1; } else if (alternate) { alternate = nowalternate = 0; } continue; } break; } } /* we're supposed to be displaying at least something from a * multipart/alternative. if we've had parts to consider, and * we've had no success, then we should complain. we shouldn't * complain if none of the parts matched any -part or -type option. */ if (alternating && request_matched && !display_success) { /* if we're ourselves an alternate. don't complain yet. */ if (!alternate) content_error (NULL, ct, "don't know how to display any of the contents"); result = NOTOK; } out: /* if no parts matched what was requested, there can't have been * any display errors. we report DONE rather than OK. */ ret = request_matched ? result : DONE; return ret; } /* * Parse display string for multipart content * and use external program to display it. */ static int show_multi_aux (CT ct, int alternate, char *cp, struct format *fmt) { /* xstdin is only used in the call to parse_display_string(): its value is ignored in the function. */ int xstdin = 0, xlist = 0; char *file = NULL, buffer[BUFSIZ]; struct multipart *m = (struct multipart *) ct->c_ctparams; struct part *part; CT p; for (part = m->mp_parts; part; part = part->mp_next) { p = part->mp_part; if (!p->c_ceopenfnx) { if (!alternate) content_error (NULL, p, "don't know how to decode content"); return NOTOK; } if (p->c_storage == NULL) { if ((*p->c_ceopenfnx) (p, &file) == NOTOK) return NOTOK; p->c_storage = add (file, NULL); if (p->c_showproc && !strcmp (p->c_showproc, "true")) return OK; (*p->c_ceclosefnx) (p); } } if (parse_display_string (ct, cp, &xstdin, &xlist, file, buffer, sizeof(buffer) - 1, 1)) { inform("Buffer overflow constructing show command, continuing..."); return NOTOK; } return show_content_aux2 (ct, alternate, NULL, buffer, NOTOK, xlist, 0, fmt); } /* * show content of type "message/rfc822" */ static int show_message_rfc822 (CT ct, int alternate, struct format *fmt) { char *cp; CI ci = &ct->c_ctinfo; /* Check for invo_name-show-type[/subtype] */ if ((cp = context_find_by_type ("show", ci->ci_type, ci->ci_subtype))) return show_content_aux (ct, alternate, cp, NULL, fmt); if ((cp = ct->c_showproc)) return show_content_aux (ct, alternate, cp, NULL, fmt); /* default method for message/rfc822 */ if (ct->c_subtype == MESSAGE_RFC822) { cp = (ct->c_showproc = mh_xstrdup("%pshow -file %F")); return show_content_aux (ct, alternate, cp, NULL, fmt); } /* complain if we are not a part of a multipart/alternative */ if (!alternate) content_error (NULL, ct, "don't know how to display content"); return NOTOK; } /* * Show content of type "message/partial". */ static int show_partial (CT ct, int alternate) { NMH_UNUSED (alternate); content_error (NULL, ct, "in order to display this message, you must reassemble it"); return NOTOK; } /* * Show content of type "message/external". * * THE ERROR CHECKING IN THIS ONE IS NOT DONE YET. */ static int show_external (CT ct, int alternate, int concatsw, int textonly, int inlineonly, struct format *fmt) { struct exbody *e = (struct exbody *) ct->c_ctparams; CT p = e->eb_content; if (!type_ok (p, 0)) return OK; return show_switch (p, alternate, concatsw, textonly, inlineonly, fmt); } static int parse_display_string (CT ct, char *cp, int *xstdin, int *xlist, char *file, char *buffer, size_t buflen, int multipart) { int len, quoted = 0; char *bp = buffer, *pp; CI ci = &ct->c_ctinfo; bp[0] = bp[buflen] = '\0'; for ( ; *cp && buflen > 0; cp++) { if (*cp == '%') { pp = bp; switch (*++cp) { case 'a': /* insert parameters from Content-Type field */ { PM pm; char *s = ""; for (pm = ci->ci_first_pm; pm; pm = pm->pm_next) { snprintf (bp, buflen, "%s%s=\"%s\"", s, pm->pm_name, get_param_value(pm, '?')); len = strlen (bp); bp += len; buflen -= len; s = " "; } } break; case 'd': /* insert content description */ if (ct->c_descr) { char *s; s = trimcpy (ct->c_descr); strncpy (bp, s, buflen); free (s); } break; case 'e': /* no longer implemented */ break; case 'F': /* %f, and stdin is terminal not content */ *xstdin = 1; /* FALLTHRU */ case 'f': if (multipart) { /* insert filename(s) containing content */ struct multipart *m = (struct multipart *) ct->c_ctparams; struct part *part; char *s = ""; CT p; for (part = m->mp_parts; part; part = part->mp_next) { p = part->mp_part; snprintf (bp, buflen, "%s%s", s, p->c_storage); len = strlen (bp); bp += len; buflen -= len; s = " "; } } else { /* insert filename containing content */ snprintf (bp, buflen, "%s", file); /* * Old comments below are left here for posterity. * This was/is tricky. */ /* since we've quoted the file argument, set things up * to look past it, to avoid problems with the quoting * logic below. (I know, I should figure out what's * broken with the quoting logic, but..) */ /* * Here's the email that submitted the patch with * the comment above: * https://www.mail-archive.com/nmh-workers@mhost.com/ * msg00288.html * I can't tell from that exactly what was broken, * beyond misquoting of the filename. The profile * had appearances of %F both with and without quotes. * The unquoted ones should have been quoted by the * code below. * The fix was to always quote the filename. But * that broke '%F' because it expanded to ''filename''. */ /* * Old comments above are left here for posterity. * The quoting below should work properly now. */ } break; case 'p': /* No longer supported */ /* FALLTHRU */ case 'l': /* display listing prior to displaying content */ *xlist = !nolist; break; case 's': /* insert subtype of content */ strncpy (bp, ci->ci_subtype, buflen); break; case '%': /* insert character % */ goto raw; case '{' : { const char *closing_brace = strchr(cp, '}'); if (closing_brace) { const size_t param_len = closing_brace - cp - 1; char *param = mh_xmalloc(param_len + 1); char *value; (void) strncpy(param, cp + 1, param_len); param[param_len] = '\0'; value = get_param(ci->ci_first_pm, param, '?', 0); free(param); cp += param_len + 1; /* Skip both braces, too. */ if (value) { /* %{param} is set in the Content-Type header. After the break below, quote it if necessary. */ (void) strncpy(bp, value, buflen); free(value); } else { /* %{param} not found, so skip it completely. cp was advanced above. */ continue; } } else { /* This will get confused if there are multiple %{}'s, but its real purpose is to avoid doing bad things above if a closing brace wasn't found. */ inform("no closing brace for display string escape %s, continuing...", cp); } break; } default: *bp++ = *--cp; *bp = '\0'; buflen--; continue; } len = strlen (bp); bp += len; buflen -= len; *bp = '\0'; /* Did we actually insert something? */ if (bp != pp) { /* Insert single quote if not inside quotes already */ if (!quoted && buflen) { len = strlen (pp); memmove (pp + 1, pp, len+1); *pp++ = '\''; buflen--; bp++; quoted = 1; } /* Escape existing quotes */ while ((pp = strchr (pp, '\'')) && buflen > 3) { len = strlen (pp++); if (quoted) { /* Quoted. Let this quote close that quoting. Insert an escaped quote to replace it and another quote to reopen quoting, which will be closed below. */ memmove (pp + 2, pp, len); *pp++ = '\\'; *pp++ = '\''; buflen -= 2; bp += 2; quoted = 0; } else { /* Not quoted. This should not be reached with the current code, but handle the condition in case the code changes. Just escape the quote. */ memmove (pp, pp-1, len+1); *(pp++-1) = '\\'; buflen--; bp++; } } /* If pp is still set, that means we ran out of space. */ if (pp) buflen = 0; /* Close quoting. */ if (quoted && buflen) { /* See if we need to close the quote by looking for an odd number of unescaped close quotes in the remainder of the display string. */ int found_quote = 0, escaped = 0; char *c; for (c = cp+1; *c; ++c) { if (*c == '\\') { escaped = ! escaped; } else { if (escaped) { escaped = 0; } else { if (*c == '\'') { found_quote = ! found_quote; } } } } if (! found_quote) { *bp++ = '\''; buflen--; quoted = 0; } } } } else { raw: *bp++ = *cp; buflen--; if (*cp == '\'') quoted = !quoted; } *bp = '\0'; } if (buflen <= 0 || (ct->c_termproc && buflen <= strlen(ct->c_termproc))) { /* content_error would provide a more useful error message * here, except that if we got overrun, it probably would * too. */ return NOTOK; } /* use charset string to modify display method */ if (ct->c_termproc) { char term[BUFSIZ]; strncpy (term, buffer, sizeof(term)); snprintf (buffer, buflen, ct->c_termproc, term); } return OK; } int convert_charset (CT ct, char *dest_charset, int *message_mods) { char *src_charset = content_charset (ct); int status = OK; if (strcasecmp (src_charset, dest_charset)) { #ifdef HAVE_ICONV iconv_t conv_desc = NULL; char *dest; int fd = -1; char **file = NULL; FILE **fp = NULL; size_t begin; size_t end; int opened_input_file = 0; char src_buffer[BUFSIZ]; size_t dest_buffer_size = BUFSIZ; char *dest_buffer = mh_xmalloc(dest_buffer_size); HF hf; char *tempfile; int fromutf8 = !strcasecmp(src_charset, "UTF-8"); if ((conv_desc = iconv_open (dest_charset, src_charset)) == (iconv_t) -1) { inform("Can't convert %s to %s", src_charset, dest_charset); free (src_charset); return NOTOK; } if ((tempfile = m_mktemp2 (NULL, invo_name, &fd, NULL)) == NULL) { adios (NULL, "unable to create temporary file in %s", get_temp_dir()); } dest = mh_xstrdup(tempfile); if (ct->c_cefile.ce_file) { file = &ct->c_cefile.ce_file; fp = &ct->c_cefile.ce_fp; begin = end = 0; } else if (ct->c_file) { file = &ct->c_file; fp = &ct->c_fp; begin = (size_t) ct->c_begin; end = (size_t) ct->c_end; } /* else no input file: shouldn't happen */ if (file && *file && fp) { if (! *fp) { if ((*fp = fopen (*file, "r")) == NULL) { advise (*file, "unable to open for reading"); status = NOTOK; } else { opened_input_file = 1; } } } if (fp && *fp) { size_t inbytes; size_t bytes_to_read = end > 0 && end > begin ? end - begin : sizeof src_buffer; fseeko (*fp, begin, SEEK_SET); while ((inbytes = fread (src_buffer, 1, min (bytes_to_read, sizeof src_buffer), *fp)) > 0) { ICONV_CONST char *ib = src_buffer; char *ob = dest_buffer; size_t outbytes = dest_buffer_size; size_t outbytes_before = outbytes; if (end > 0) bytes_to_read -= inbytes; iconv_start: if (iconv (conv_desc, &ib, &inbytes, &ob, &outbytes) == (size_t) -1) { if (errno == E2BIG) { /* * Bump up the buffer by at least a factor of 2 * over what we need. */ size_t bumpup = inbytes * 2, ob_off = ob - dest_buffer; dest_buffer_size += bumpup; dest_buffer = mh_xrealloc(dest_buffer, dest_buffer_size); ob = dest_buffer + ob_off; outbytes += bumpup; outbytes_before += bumpup; goto iconv_start; } if (errno == EINVAL) { /* middle of multi-byte sequence */ if (write (fd, dest_buffer, outbytes_before - outbytes) < 0) { advise (dest, "write"); } fseeko (*fp, -inbytes, SEEK_CUR); if (end > 0) bytes_to_read += inbytes; /* inform("convert_charset: EINVAL"); */ continue; } if (errno == EILSEQ) { /* invalid multi-byte sequence */ if (fromutf8) { for (++ib, --inbytes; inbytes > 0 && (((unsigned char) *ib) & 0xc0) == 0x80; ++ib, --inbytes) continue; } else { ib++; inbytes--; /* skip it */ } (*ob++) = '?'; outbytes --; /* inform("convert_charset: EILSEQ"); */ goto iconv_start; } inform("convert_charset: errno = %d", errno); status = NOTOK; break; } if (write (fd, dest_buffer, outbytes_before - outbytes) < 0) { advise (dest, "write"); } } if (opened_input_file) { fclose (*fp); *fp = NULL; } } iconv_close (conv_desc); close (fd); if (status == OK) { /* Replace the decoded file with the converted one. */ if (ct->c_cefile.ce_file) { if (ct->c_cefile.ce_unlink) { (void) m_unlink (ct->c_cefile.ce_file); } free (ct->c_cefile.ce_file); } ct->c_cefile.ce_file = dest; ct->c_cefile.ce_unlink = 1; ++*message_mods; /* Update ct->c_ctline. */ if (ct->c_ctline) { char *ctline = concat(" ", ct->c_ctinfo.ci_type, "/", ct->c_ctinfo.ci_subtype, NULL); char *outline; replace_param(&ct->c_ctinfo.ci_first_pm, &ct->c_ctinfo.ci_last_pm, "charset", dest_charset, 0); outline = output_params(strlen(TYPE_FIELD) + 1 + strlen(ctline), ct->c_ctinfo.ci_first_pm, NULL, 0); if (outline) { ctline = add(outline, ctline); free(outline); } free (ct->c_ctline); ct->c_ctline = ctline; } /* else no CT line, which is odd */ /* Update Content-Type header field. */ for (hf = ct->c_first_hf; hf; hf = hf->next) { if (! strcasecmp (TYPE_FIELD, hf->name)) { char *ctline = concat (ct->c_ctline, "\n", NULL); free (hf->value); hf->value = ctline; break; } } } else { (void) m_unlink (dest); } free(dest_buffer); #else /* ! HAVE_ICONV */ NMH_UNUSED (message_mods); inform("Can't convert %s to %s without iconv", src_charset, dest_charset); errno = ENOSYS; status = NOTOK; #endif /* ! HAVE_ICONV */ } free (src_charset); return status; } static int convert_content_charset (CT ct, char **file) { int status = OK; #ifdef HAVE_ICONV /* Using current locale, see if the content needs to be converted. */ /* content_charset() cannot return NULL. */ char *src_charset = content_charset (ct); if (! check_charset (src_charset, strlen (src_charset))) { int unused = 0; char *dest_charset = getcpy (get_charset ()); if (convert_charset (ct, dest_charset, &unused) == 0) { *file = ct->c_cefile.ce_file; } else { status = NOTOK; } free (dest_charset); } free (src_charset); #else /* ! HAVE_ICONV */ NMH_UNUSED (ct); NMH_UNUSED (file); #endif /* ! HAVE_ICONV */ return status; } /* * Compile our format string and save any parameters we care about. */ #define DEFAULT_HEADER "[ Message %{folder}%<{folder}:%>%(msg) ]" #define DEFAULT_MARKER "[ part %{part} - %{content-type} - " \ "%<{description}%{description}" \ "%?{cdispo-filename}%{cdispo-filename}" \ "%|%{ctype-name}%> " \ "%(kilo(size))B %<(unseen)\\(suppressed\\)%> ]" static struct format * compile_header(char *form) { struct format *fmt; char *fmtstring; struct comp *comp = NULL; unsigned int bucket; fmtstring = new_fs(form, NULL, DEFAULT_HEADER); (void) fmt_compile(fmtstring, &fmt, 1); free_fs(); while ((comp = fmt_nextcomp(comp, &bucket)) != NULL) { if (strcasecmp(comp->c_name, "folder") == 0) { folder_comp = comp; } } return fmt; } static struct format * compile_marker(char *form) { struct format *fmt; char *fmtstring; struct comp *comp = NULL; unsigned int bucket; struct param_comp_list *pc_entry; fmtstring = new_fs(form, NULL, DEFAULT_MARKER); (void) fmt_compile(fmtstring, &fmt, 1); free_fs(); /* * Things we care about: * * part - Part name (e.g., 1.1) * content-type - Content-Type * description - Content-Description * disposition - Content-Disposition (inline, attachment) * ctype- - Content-Type parameter * cdispo- - Content-Disposition parameter */ while ((comp = fmt_nextcomp(comp, &bucket)) != NULL) { if (strcasecmp(comp->c_name, "part") == 0) { part_comp = comp; } else if (strcasecmp(comp->c_name, "content-type") == 0) { ctype_comp = comp; } else if (strcasecmp(comp->c_name, "description") == 0) { description_comp = comp; } else if (strcasecmp(comp->c_name, "disposition") == 0) { dispo_comp = comp; } else if (strncasecmp(comp->c_name, "ctype-", 6) == 0 && strlen(comp->c_name) > 6) { NEW(pc_entry); pc_entry->param = mh_xstrdup(comp->c_name + 6); pc_entry->comp = comp; pc_entry->next = ctype_pc_list; ctype_pc_list = pc_entry; } else if (strncasecmp(comp->c_name, "cdispo-", 7) == 0 && strlen(comp->c_name) > 7) { NEW(pc_entry); pc_entry->param = mh_xstrdup(comp->c_name + 7); pc_entry->comp = comp; pc_entry->next = dispo_pc_list; dispo_pc_list = pc_entry; } } return fmt; } /* * Output on stdout an appropriate marker for this content, using mh-format */ static void output_header(CT ct, struct format *fmt) { charstring_t outbuf = charstring_create (BUFSIZ); int dat[5] = { 0 }; char *endp; int message = 0; if (folder_comp) folder_comp->c_text = getcpy(folder); if (ct->c_file && *ct->c_file) { message = strtol(ct->c_file, &endp, 10); if (*endp) message = 0; dat[0] = message; } /* it would be nice to populate dat[2], for %(size) here, * but it's not available. it might also be nice to know * if the message originally had any mime parts or not -- but * there's also no record of that. (except for MIME-version:) */ fmt_scan(fmt, outbuf, BUFSIZ, dat, NULL); fputs(charstring_buffer (outbuf), stdout); charstring_free (outbuf); fmt_freecomptext(); } static void output_marker(CT ct, struct format *fmt, int hidden) { charstring_t outbuf = charstring_create (BUFSIZ); struct param_comp_list *pcentry; int partsize; int message = 0; char *endp; int dat[5] = { 0 }; /* * Grab any items we care about. */ if (ctype_comp && ct->c_ctinfo.ci_type) { ctype_comp->c_text = concat(ct->c_ctinfo.ci_type, "/", ct->c_ctinfo.ci_subtype, NULL); } if (part_comp && ct->c_partno) { part_comp->c_text = mh_xstrdup(ct->c_partno); } if (description_comp && ct->c_descr) { description_comp->c_text = mh_xstrdup(ct->c_descr); } if (dispo_comp && ct->c_dispo_type) { dispo_comp->c_text = mh_xstrdup(ct->c_dispo_type); } for (pcentry = ctype_pc_list; pcentry != NULL; pcentry = pcentry->next) { pcentry->comp->c_text = get_param(ct->c_ctinfo.ci_first_pm, pcentry->param, '?', 0); } for (pcentry = dispo_pc_list; pcentry != NULL; pcentry = pcentry->next) { pcentry->comp->c_text = get_param(ct->c_dispo_first, pcentry->param, '?', 0); } if (ct->c_cesizefnx) partsize = (*ct->c_cesizefnx) (ct); else partsize = ct->c_end - ct->c_begin; if (ct->c_file && *ct->c_file) { message = strtol(ct->c_file, &endp, 10); if (*endp) message = 0; dat[0] = message; } dat[2] = partsize; /* make the part's hidden aspect available by overloading the * %(unseen) function. make the part's size available via %(size). * see comments in h/fmt_scan.h. */ dat[4] = hidden; fmt_scan(fmt, outbuf, BUFSIZ, dat, NULL); fputs(charstring_buffer (outbuf), stdout); charstring_free (outbuf); fmt_freecomptext(); } /* * Reset (and free) any of the saved marker text */ static void free_markercomps(void) { struct param_comp_list *pc_entry, *pc2; folder_comp = NULL; part_comp = NULL; ctype_comp = NULL; description_comp = NULL; dispo_comp = NULL; for (pc_entry = ctype_pc_list; pc_entry != NULL; ) { free(pc_entry->param); pc2 = pc_entry->next; free(pc_entry); pc_entry = pc2; } for (pc_entry = dispo_pc_list; pc_entry != NULL; ) { free(pc_entry->param); pc2 = pc_entry->next; free(pc_entry); pc_entry = pc2; } } /* * Exit if the display process returned with a nonzero exit code, or terminated * with a SIGQUIT signal. */ static int pidcheck (int status) { if ((status & 0xff00) == 0xff00 || (status & 0x007f) != SIGQUIT) return status; fflush (stdout); fflush (stderr); done (1); return 1; } nmh-1.7.1-RC3/uip/mhshowsbr.h000644 007761 000024 00000003756 13205305706 015760 0ustar00kenhstaff000000 000000 /* mhshowsbr.h -- display the contents of MIME messages. * * This code is Copyright (c) 2017, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ /* * Display MIME message(s) on standard out. * * Arguments are: * * cts - NULL terminated array of CT structures for messages * to display * concat - If true, concatenate all MIME parts. If false, show each * MIME part under a separate pager. * textonly - If true, only display "text" MIME parts * inlineonly - If true, only display MIME parts that are marked with * a disposition of "inline" (includes parts that lack a * Content-Disposition header). */ void show_all_messages(CT *cts, int concat, int textonly, int inlineonly); /* * Display (or store) a single MIME part using the specified command * * Arguments are: * * ct - The Content structure of the MIME part we wish to display * alternate - Set this to true if this is one part of a MIME * multipart/alternative part. Will suppress some errors and * will cause the function to return DONE instead of OK on * success. * cp - The command string to execute. Will be run through the * parser for %-escapes as described in mhshow(1). * cracked - If set, chdir() to this directory before executing the * command in "cp". Only used by mhstore(1). * fmt - A series of mh-format(5) instructions to execute if the * command string indicates a marker is desired. Can be NULL. * * Returns NOTOK if we could not display the part, DONE if alternate was * set and we could display the part, and OK if alternate was not set and * we could display the part. */ int show_content_aux(CT ct, int alternate, char *cp, char *cracked, struct format *fmt); int convert_charset(CT ct, char *dest_charset, int *message_mods); extern char *progsw; extern int nomore; extern char *formsw; extern char *folder; extern char *markerform; extern char *headerform; extern int headersw; nmh-1.7.1-RC3/uip/mhstore.c000644 007761 000024 00000021541 13243042054 015404 0ustar00kenhstaff000000 000000 /* mhstore.c -- store the contents of MIME messages * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #include #include #include #include #include "../sbr/m_maildir.h" #include "mhfree.h" #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("outfile outfile", 0, OUTFILESW) \ X("part number", 0, PARTSW) \ X("type content", 0, TYPESW) \ X("prefer content", 0, PREFERSW) \ X("noprefer", 0, NPREFERSW) \ 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 /* mhmisc.c */ extern int npart; extern int ntype; extern char *parts[NPARTS + 1]; extern char *types[NTYPES + 1]; extern int userrs; /* mhparse.c */ extern char *preferred_types[]; extern char *preferred_subtypes[]; extern int npreferred; #define quitser pipeser /* mhparse.c */ int debugsw = 0; CT parse_mime (char *); /* mhmisc.c */ int part_ok (CT); int type_ok (CT, int); void flush_errors (void); /* * static prototypes */ static void pipeser (int); int main (int argc, char **argv) { /* verbosw defaults to 1 for backward compatibility. */ int msgnum, *icachesw, autosw = 0, verbosw = 1; const char *clobbersw = "always"; char *cp, *file = NULL, *outfile = NULL, *folder = NULL; char *maildir, buf[100], **argp; char **arguments; char *cwd; struct msgs_array msgs = { 0, 0, NULL }; struct msgs *mp = NULL; CT ct, *ctp; FILE *fp; int files_not_clobbered; mhstoreinfo_t info; if (nmh_init(argv[0], 1)) { return 1; } done=freects_done; arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; /* * Parse arguments */ while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [+folder] [msgs] [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case AUTOSW: autosw++; continue; case NAUTOSW: autosw = 0; continue; case RCACHESW: icachesw = &rcachesw; goto do_cache; case WCACHESW: icachesw = &wcachesw; do_cache: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); switch (*icachesw = smatch (cp, cache_policy)) { case AMBIGSW: ambigsw (cp, cache_policy); done (1); case UNKWNSW: adios (NULL, "%s unknown", cp); default: break; } continue; case CHECKSW: checksw++; continue; case NCHECKSW: checksw = 0; continue; case PARTSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if (npart >= NPARTS) adios (NULL, "too many parts (starting with %s), %d max", cp, NPARTS); parts[npart++] = cp; continue; case TYPESW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if (ntype >= NTYPES) adios (NULL, "too many types (starting with %s), %d max", cp, NTYPES); types[ntype++] = cp; continue; case PREFERSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if (npreferred >= NPREFS) adios (NULL, "too many preferred types (starting with %s), %d max", cp, NPREFS); preferred_types[npreferred] = cp; cp = strchr(cp, '/'); if (cp) *cp++ = '\0'; preferred_subtypes[npreferred++] = cp; continue; case NPREFERSW: npreferred = 0; continue; case FILESW: if (!(cp = *argp++) || (*cp == '-' && cp[1])) adios (NULL, "missing argument to %s", argp[-2]); file = *cp == '-' ? cp : path (cp, TFILE); continue; case OUTFILESW: if (!(cp = *argp++) || (*cp == '-' && cp[1])) adios (NULL, "missing argument to %s", argp[-2]); outfile = *cp == '-' ? cp : path (cp, TFILE); continue; case VERBSW: verbosw = 1; continue; case NVERBSW: verbosw = 0; continue; case CLOBBERSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); clobbersw = cp; continue; case DEBUGSW: debugsw = 1; continue; } } if (*cp == '+' || *cp == '@') { if (folder) adios (NULL, "only one folder at a time!"); else folder = pluspath (cp); } else app_msgarg(&msgs, cp); } /* null terminate the list of acceptable parts/types */ parts[npart] = NULL; types[ntype] = NULL; /* * Check if we've specified an additional profile */ if ((cp = getenv ("MHSTORE"))) { if ((fp = fopen (cp, "r"))) { readconfig ((struct node **) 0, fp, cp, 0); fclose (fp); } else { admonish ("", "unable to read $MHSTORE profile (%s)", cp); } } /* * Read the standard profile setup */ if ((fp = fopen (cp = etcpath ("mhn.defaults"), "r"))) { readconfig ((struct node **) 0, fp, cp, 0); fclose (fp); } /* Check for public cache location */ if ((cache_public = context_find (nmhcache)) && *cache_public != '/') cache_public = NULL; /* Check for private cache location */ if (!(cache_private = context_find (nmhprivcache))) cache_private = ".cache"; cache_private = getcpy (m_maildir (cache_private)); /* * Cache the current directory before we do any chdirs()'s. */ cwd = mh_xstrdup(pwd()); if (!context_find ("path")) free (path ("./", TFOLDER)); if (file && msgs.size) adios (NULL, "cannot specify msg and file at same time!"); /* * check if message is coming from file */ if (file) { cts = mh_xcalloc(2, sizeof *cts); ctp = cts; if ((ct = parse_mime (file))) { *ctp++ = ct; if (outfile) { ct->c_storage = mh_xstrdup(outfile); } } } else { /* * message(s) are coming from a folder */ if (!msgs.size) app_msgarg(&msgs, "cur"); if (!folder) folder = getfolder (1); maildir = m_maildir (folder); if (chdir (maildir) == NOTOK) adios (maildir, "unable to change directory to"); /* read folder and create message structure */ if (!(mp = folder_read (folder, 1))) adios (NULL, "unable to read folder %s", folder); /* check for empty folder */ if (mp->nummsg == 0) adios (NULL, "no messages in %s", folder); /* parse all the message ranges/sequences and set SELECTED */ for (msgnum = 0; msgnum < msgs.size; msgnum++) if (!m_convert (mp, msgs.msgs[msgnum])) done (1); seq_setprev (mp); /* set the previous-sequence */ cts = mh_xcalloc(mp->numsel + 1, sizeof *cts); ctp = cts; for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { if (is_selected(mp, msgnum)) { char *msgnam; msgnam = m_name (msgnum); if ((ct = parse_mime (msgnam))) { *ctp++ = ct; if (outfile) { ct->c_storage = mh_xstrdup(outfile); } } } } } if (!*cts) done (1); userrs = 1; SIGNAL (SIGQUIT, quitser); SIGNAL (SIGPIPE, pipeser); /* * Get the associated umask for the relevant contents. */ for (ctp = cts; *ctp; ctp++) { struct stat st; ct = *ctp; if (type_ok (ct, 1) && !ct->c_umask) { if (stat (ct->c_file, &st) != NOTOK) ct->c_umask = ~(st.st_mode & 0777); else ct->c_umask = ~m_gmprot(); } } /* * Store the message content */ info = mhstoreinfo_create (cts, cwd, clobbersw, autosw, verbosw); store_all_messages (info); files_not_clobbered = mhstoreinfo_files_not_clobbered(info); mhstoreinfo_free(info); /* Now free all the structures for the content */ for (ctp = cts; *ctp; ctp++) free_content (*ctp); free (cts); cts = NULL; /* If reading from a folder, do some updating */ if (mp) { context_replace (pfolder, folder);/* update current folder */ seq_setcur (mp, mp->hghsel); /* update current message */ seq_save (mp); /* synchronize sequences */ context_save (); /* save the context file */ } done (files_not_clobbered); return 1; } static void pipeser (int i) { if (i == SIGQUIT) { fflush (stdout); fprintf (stderr, "\n"); fflush (stderr); } done (1); /* NOTREACHED */ } nmh-1.7.1-RC3/uip/mhstoresbr.c000644 007761 000024 00000077433 13243042054 016126 0ustar00kenhstaff000000 000000 /* mhstoresbr.c -- routines to save/store the contents of MIME messages * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #include #include #include #include "mhshowsbr.h" #include "../sbr/m_maildir.h" #include "../sbr/m_mktemp.h" enum clobber_policy_t { NMH_CLOBBER_ALWAYS = 0, NMH_CLOBBER_AUTO, NMH_CLOBBER_SUFFIX, NMH_CLOBBER_ASK, NMH_CLOBBER_NEVER }; static enum clobber_policy_t clobber_policy (const char *); struct mhstoreinfo { CT *cts; /* Top-level list of contents to store. */ char *cwd; /* cached current directory */ int autosw; /* -auto enabled */ int verbosw; /* -verbose enabled */ int files_not_clobbered; /* output flag indicating that store failed in order to not clobber an existing file */ /* The following must never be touched by a caller: they are for internal use by the mhstoresbr functions. */ char *dir; /* directory in which to store contents */ enum clobber_policy_t clobber_policy; /* -clobber selection */ }; static bool use_param_as_filename(const char *p); mhstoreinfo_t mhstoreinfo_create (CT *ct, char *pwd, const char *csw, int asw, int vsw) { mhstoreinfo_t info; NEW(info); info->cts = ct; info->cwd = pwd; info->autosw = asw; info->verbosw = vsw; info->files_not_clobbered = 0; info->dir = NULL; info->clobber_policy = clobber_policy (csw); return info; } void mhstoreinfo_free (mhstoreinfo_t info) { free (info->cwd); free (info->dir); free (info); } int mhstoreinfo_files_not_clobbered (const mhstoreinfo_t info) { return info->files_not_clobbered; } /* * Type for a compare function for qsort. This keeps * the compiler happy. */ typedef int (*qsort_comp) (const void *, const void *); /* mhmisc.c */ int part_ok (CT); int type_ok (CT, int); void flush_errors (void); /* * static prototypes */ static void store_single_message (CT, mhstoreinfo_t); static int store_switch (CT, mhstoreinfo_t); static int store_generic (CT, mhstoreinfo_t); static int store_application (CT, mhstoreinfo_t); static int store_multi (CT, mhstoreinfo_t); static int store_partial (CT, mhstoreinfo_t); static int store_external (CT, mhstoreinfo_t); static int ct_compar (CT *, CT *); static int store_content (CT, CT, mhstoreinfo_t); static int output_content_file (CT, int); static int output_content_folder (char *, char *); static int parse_format_string (CT, char *, char *, int, char *); static void get_storeproc (CT); static int copy_some_headers (FILE *, CT); static char *clobber_check (char *, mhstoreinfo_t); /* * Main entry point to store content * from a collection of messages. */ void store_all_messages (mhstoreinfo_t info) { CT ct, *ctp; char *cp; /* * Check for the directory in which to * store any contents. */ if ((cp = context_find (nmhstorage)) && *cp) info->dir = mh_xstrdup(cp); else info->dir = getcpy (info->cwd); for (ctp = info->cts; *ctp; ctp++) { ct = *ctp; store_single_message (ct, info); } flush_errors (); } /* * Entry point to store the content * in a (single) message */ static void store_single_message (CT ct, mhstoreinfo_t info) { if (type_ok (ct, 1)) { umask (ct->c_umask); store_switch (ct, info); if (ct->c_fp) { fclose (ct->c_fp); ct->c_fp = NULL; } if (ct->c_ceclosefnx) (*ct->c_ceclosefnx) (ct); } } /* * Switching routine to store different content types */ static int store_switch (CT ct, mhstoreinfo_t info) { switch (ct->c_type) { case CT_MULTIPART: return store_multi (ct, info); case CT_MESSAGE: switch (ct->c_subtype) { case MESSAGE_PARTIAL: return store_partial (ct, info); case MESSAGE_EXTERNAL: return store_external (ct, info); case MESSAGE_RFC822: default: return store_generic (ct, info); } case CT_APPLICATION: default: return store_application (ct, info); case CT_TEXT: case CT_AUDIO: case CT_IMAGE: case CT_VIDEO: return store_generic (ct, info); } return OK; /* NOT REACHED */ } /* * Generic routine to store a MIME content. * (audio, video, image, text, message/rfc822) */ static int store_generic (CT ct, mhstoreinfo_t info) { /* * Check if the content specifies a filename. * Don't bother with this for type "message" * (only "message/rfc822" will use store_generic). */ if (info->autosw && ct->c_type != CT_MESSAGE) get_storeproc (ct); return store_content (ct, NULL, info); } /* * Store content of type "application" */ static int store_application (CT ct, mhstoreinfo_t info) { CI ci = &ct->c_ctinfo; /* Check if the content specifies a filename */ if (info->autosw) get_storeproc (ct); /* * If storeproc is not defined, and the content is type * "application/octet-stream", we also check for various * attribute/value pairs which specify if this a tar file. */ if (!ct->c_storeproc && ct->c_subtype == APPLICATION_OCTETS) { int tarP = 0, zP = 0, gzP = 0; char *cp; if ((cp = get_param(ci->ci_first_pm, "type", ' ', 1))) { if (strcasecmp (cp, "tar") == 0) tarP = 1; } /* check for "conversions=compress" attribute */ if ((cp = get_param(ci->ci_first_pm, "conversions", ' ', 1)) || (cp = get_param(ci->ci_first_pm, "x-conversions", ' ', 1))) { if (strcasecmp (cp, "compress") == 0 || strcasecmp (cp, "x-compress") == 0) { zP = 1; } if (strcasecmp (cp, "gzip") == 0 || strcasecmp (cp, "x-gzip") == 0) { gzP = 1; } } if (tarP) { ct->c_showproc = add (zP ? "%euncompress | tar tvf -" : (gzP ? "%egzip -dc | tar tvf -" : "%etar tvf -"), NULL); if (!ct->c_storeproc) { if (info->autosw) { ct->c_storeproc = add (zP ? "| uncompress | tar xvpf -" : (gzP ? "| gzip -dc | tar xvpf -" : "| tar xvpf -"), NULL); ct->c_umask = 0022; } else { ct->c_storeproc= add (zP ? "%m%P.tar.Z" : (gzP ? "%m%P.tar.gz" : "%m%P.tar"), NULL); } } } } return store_content (ct, NULL, info); } /* * Store the content of a multipart message */ static int store_multi (CT ct, mhstoreinfo_t info) { int result; struct multipart *m = (struct multipart *) ct->c_ctparams; struct part *part; result = NOTOK; for (part = m->mp_parts; part; part = part->mp_next) { CT p = part->mp_part; if (part_ok (p) && type_ok (p, 1)) { if (ct->c_storage) { /* Support mhstore -outfile. The MIME parser doesn't load c_storage, so we know that p->c_storage is NULL here. */ p->c_storage = mh_xstrdup(ct->c_storage); } result = store_switch (p, info); if (result == OK && ct->c_subtype == MULTI_ALTERNATE) break; } } return result; } /* * Reassemble and store the contents of a collection * of messages of type "message/partial". */ static int store_partial (CT ct, mhstoreinfo_t info) { int cur, hi, i; CT p, *ctp, *ctq; CT *base; struct partial *pm, *qm; qm = (struct partial *) ct->c_ctparams; if (qm->pm_stored) return OK; hi = i = 0; for (ctp = info->cts; *ctp; ctp++) { p = *ctp; if (p->c_type == CT_MESSAGE && p->c_subtype == ct->c_subtype) { pm = (struct partial *) p->c_ctparams; if (!pm->pm_stored && strcmp (qm->pm_partid, pm->pm_partid) == 0) { pm->pm_marked = pm->pm_partno; if (pm->pm_maxno) hi = pm->pm_maxno; pm->pm_stored = 1; i++; } else pm->pm_marked = 0; } } if (hi == 0) { inform("missing (at least) last part of multipart message"); return NOTOK; } base = mh_xcalloc(i + 1, sizeof *base); ctq = base; for (ctp = info->cts; *ctp; ctp++) { p = *ctp; if (p->c_type == CT_MESSAGE && p->c_subtype == ct->c_subtype) { pm = (struct partial *) p->c_ctparams; if (pm->pm_marked) *ctq++ = p; } } *ctq = NULL; if (i > 1) qsort ((char *) base, i, sizeof(*base), (qsort_comp) ct_compar); cur = 1; for (ctq = base; *ctq; ctq++) { p = *ctq; pm = (struct partial *) p->c_ctparams; if (pm->pm_marked == cur) { cur++; continue; } if (pm->pm_marked == cur - 1) { inform("duplicate part %d of %d part multipart message, continuing...", pm->pm_marked, hi); continue; } missing_part: inform("missing %spart %d of %d part multipart message", cur != hi ? "(at least) " : "", cur, hi); goto losing; } if (hi != --cur) { cur = hi; goto missing_part; } /* * Now cycle through the sorted list of messages of type * "message/partial" and save/append them to a file. */ ctq = base; ct = *ctq++; if (store_content (ct, NULL, info) == NOTOK) { losing: free(base); return NOTOK; } for (; *ctq; ctq++) { p = *ctq; if (store_content (p, ct, info) == NOTOK) goto losing; } free(base); return OK; } /* * Store content from a message of type "message/external". */ static int store_external (CT ct, mhstoreinfo_t info) { int result = NOTOK; struct exbody *e = (struct exbody *) ct->c_ctparams; CT p = e->eb_content; if (!type_ok (p, 1)) return OK; /* * Check if the parameters for the external body * specified a filename. */ if (info->autosw) { char *cp; if ((cp = e->eb_name) && use_param_as_filename(cp)) { if (!ct->c_storeproc) ct->c_storeproc = mh_xstrdup(cp); if (!p->c_storeproc) p->c_storeproc = mh_xstrdup(cp); } } /* * Since we will let the Content structure for the * external body substitute for the current content, * we temporarily change its partno (number inside * multipart), so everything looks right. */ p->c_partno = ct->c_partno; /* we probably need to check if content is really there */ if (ct->c_storage) { /* Support mhstore -outfile. The MIME parser doesn't load c_storage, so we know that p->c_storage is NULL here. */ p->c_storage = mh_xstrdup(ct->c_storage); } result = store_switch (p, info); p->c_partno = NULL; return result; } /* * Compare the numbering from two different * message/partials (needed for sorting). */ static int ct_compar (CT *a, CT *b) { struct partial *am = (struct partial *) ((*a)->c_ctparams); struct partial *bm = (struct partial *) ((*b)->c_ctparams); return (am->pm_marked - bm->pm_marked); } /* * Store contents of a message or message part to * a folder, a file, the standard output, or pass * the contents to a command. * * If the current content to be saved is a followup part * to a collection of messages of type "message/partial", * then field "p" is a pointer to the Content structure * to the first message/partial in the group. */ static int store_content (CT ct, CT p, mhstoreinfo_t info) { int appending = 0, msgnum = 0; int is_partial = 0, first_partial = 0; int last_partial = 0; char *cp, buffer[BUFSIZ]; /* * Do special processing for messages of * type "message/partial". * * We first check if this content is of type * "message/partial". If it is, then we need to check * whether it is the first and/or last in the group. * * Then if "p" is a valid pointer, it points to the Content * structure of the first partial in the group. So we copy * the file name and/or folder name from that message. In * this case, we also note that we will be appending. */ if (ct->c_type == CT_MESSAGE && ct->c_subtype == MESSAGE_PARTIAL) { struct partial *pm = (struct partial *) ct->c_ctparams; /* Yep, it's a message/partial */ is_partial = 1; /* But is it the first and/or last in the collection? */ if (pm->pm_partno == 1) first_partial = 1; if (pm->pm_maxno && pm->pm_partno == pm->pm_maxno) last_partial = 1; /* * If "p" is a valid pointer, then it points to the * Content structure for the first message in the group. * So we just copy the filename or foldername information * from the previous iteration of this function. */ if (p) { appending = 1; if (! ct->c_storage) { ct->c_storage = add (p->c_storage, NULL); /* record the folder name */ if (p->c_folder) { ct->c_folder = mh_xstrdup(p->c_folder); } } goto got_filename; } } /* * Get storage formatting string. * * 1) If we have storeproc defined, then use that * 2) Else check for a mhn-store-/ entry * 3) Else check for a mhn-store- entry * 4) Else if content is "message", use "+" (current folder) * 5) Else use string "%m%P.%s". */ if ((cp = ct->c_storeproc) == NULL || *cp == '\0') { CI ci = &ct->c_ctinfo; cp = context_find_by_type ("store", ci->ci_type, ci->ci_subtype); if (cp == NULL) { cp = ct->c_type == CT_MESSAGE ? "+" : "%m%P.%s"; } } if (! ct->c_storage) { /* * Check the beginning of storage formatting string * to see if we are saving content to a folder. */ if (*cp == '+' || *cp == '@') { char *tmpfilenam, *folder; /* Store content in temporary file for now */ if ((tmpfilenam = m_mktemp(invo_name, NULL, NULL)) == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } ct->c_storage = mh_xstrdup(tmpfilenam); /* Get the folder name */ if (cp[1]) folder = pluspath (cp); else folder = getfolder (1); /* Check if folder exists */ create_folder(m_mailpath(folder), 0, exit); /* Record the folder name */ ct->c_folder = mh_xstrdup(folder); if (cp[1]) free (folder); goto got_filename; } /* * Parse and expand the storage formatting string * in `cp' into `buffer'. */ parse_format_string (ct, cp, buffer, sizeof(buffer), info->dir); /* * If formatting begins with '|' or '!', then pass * content to standard input of a command and return. */ if (buffer[0] == '|' || buffer[0] == '!') return show_content_aux (ct, 0, buffer + 1, info->dir, NULL); /* record the filename */ if ((ct->c_storage = clobber_check (mh_xstrdup(buffer), info)) == NULL) { return NOTOK; } } else { /* The output filename was explicitly specified, so use it. */ if ((ct->c_storage = clobber_check (ct->c_storage, info)) == NULL) { return NOTOK; } } got_filename: /* flush the output stream */ fflush (stdout); /* Now save or append the content to a file */ if (output_content_file (ct, appending) == NOTOK) return NOTOK; /* * If necessary, link the file into a folder and remove * the temporary file. If this message is a partial, * then only do this if it is the last one in the group. */ if (ct->c_folder && (!is_partial || last_partial)) { msgnum = output_content_folder (ct->c_folder, ct->c_storage); (void) m_unlink (ct->c_storage); if (msgnum == NOTOK) return NOTOK; } if (info->verbosw) { /* * Now print out the name/number of the message * that we are storing. */ if (is_partial) { if (first_partial) fprintf (stderr, "reassembling partials "); if (last_partial) fputs(ct->c_file, stderr); else fprintf (stderr, "%s,", ct->c_file); } else { fprintf (stderr, "storing message %s", ct->c_file); if (ct->c_partno) fprintf (stderr, " part %s", ct->c_partno); } /* * Unless we are in the "middle" of group of message/partials, * we now print the name of the file, folder, and/or message * to which we are storing the content. */ if (!is_partial || last_partial) { if (ct->c_folder) { fprintf (stderr, " to folder %s as message %d\n", ct->c_folder, msgnum); } else if (!strcmp(ct->c_storage, "-")) { fprintf (stderr, " to stdout\n"); } else { int cwdlen = strlen (info->cwd); fprintf (stderr, " as file %s\n", !has_prefix(ct->c_storage, info->cwd) || ct->c_storage[cwdlen] != '/' ? ct->c_storage : ct->c_storage + cwdlen + 1); } } } return OK; } /* * Output content to a file */ static int output_content_file (CT ct, int appending) { int filterstate; char *file, buffer[BUFSIZ]; long pos, last; FILE *fp; /* * If the pathname is absolute, make sure * all the relevant directories exist. */ if (strchr(ct->c_storage, '/') && make_intermediates (ct->c_storage) == NOTOK) return NOTOK; if (ct->c_encoding != CE_7BIT) { int cc, fd; if (!ct->c_ceopenfnx) { inform("don't know how to decode part %s of message %s", ct->c_partno, ct->c_file); return NOTOK; } file = appending || !strcmp (ct->c_storage, "-") ? NULL : ct->c_storage; if ((fd = (*ct->c_ceopenfnx) (ct, &file)) == NOTOK) return NOTOK; if (!strcmp (file, ct->c_storage)) { (*ct->c_ceclosefnx) (ct); return OK; } /* * Send to standard output */ if (!strcmp (ct->c_storage, "-")) { int gd; if ((gd = dup (fileno (stdout))) == NOTOK) { advise ("stdout", "unable to dup"); losing: (*ct->c_ceclosefnx) (ct); return NOTOK; } if ((fp = fdopen (gd, appending ? "a" : "w")) == NULL) { advise ("stdout", "unable to fdopen (%d, \"%s\") from", gd, appending ? "a" : "w"); close (gd); goto losing; } } else { /* * Open output file */ if ((fp = fopen (ct->c_storage, appending ? "a" : "w")) == NULL) { advise (ct->c_storage, "unable to fopen for %s", appending ? "appending" : "writing"); goto losing; } } /* * Filter the header fields of the initial enclosing * message/partial into the file. */ if (ct->c_type == CT_MESSAGE && ct->c_subtype == MESSAGE_PARTIAL) { struct partial *pm = (struct partial *) ct->c_ctparams; if (pm->pm_partno == 1) copy_some_headers (fp, ct); } for (;;) { switch (cc = read (fd, buffer, sizeof(buffer))) { case NOTOK: advise (file, "error reading content from"); break; case OK: break; default: if ((int) fwrite (buffer, sizeof(*buffer), cc, fp) < cc) { advise ("output_content_file", "fwrite"); } continue; } break; } (*ct->c_ceclosefnx) (ct); if (cc != NOTOK && fflush (fp)) advise (ct->c_storage, "error writing to"); fclose (fp); return (cc != NOTOK ? OK : NOTOK); } if (!ct->c_fp && (ct->c_fp = fopen (ct->c_file, "r")) == NULL) { advise (ct->c_file, "unable to open for reading"); return NOTOK; } pos = ct->c_begin; last = ct->c_end; fseek (ct->c_fp, pos, SEEK_SET); if (!strcmp (ct->c_storage, "-")) { int gd; if ((gd = dup (fileno (stdout))) == NOTOK) { advise ("stdout", "unable to dup"); return NOTOK; } if ((fp = fdopen (gd, appending ? "a" : "w")) == NULL) { advise ("stdout", "unable to fdopen (%d, \"%s\") from", gd, appending ? "a" : "w"); close (gd); return NOTOK; } } else { if ((fp = fopen (ct->c_storage, appending ? "a" : "w")) == NULL) { advise (ct->c_storage, "unable to fopen for %s", appending ? "appending" : "writing"); return NOTOK; } } /* * Copy a few of the header fields of the initial * enclosing message/partial into the file. */ filterstate = 0; if (ct->c_type == CT_MESSAGE && ct->c_subtype == MESSAGE_PARTIAL) { struct partial *pm = (struct partial *) ct->c_ctparams; if (pm->pm_partno == 1) { copy_some_headers (fp, ct); filterstate = 1; } } while (fgets (buffer, sizeof buffer, ct->c_fp)) { if ((pos += strlen (buffer)) > last) { int diff; diff = strlen (buffer) - (pos - last); if (diff >= 0) buffer[diff] = '\0'; } /* * If this is the first content of a group of * message/partial contents, then we only copy a few * of the header fields of the enclosed message. */ if (filterstate) { switch (buffer[0]) { case ' ': case '\t': if (filterstate < 0) buffer[0] = 0; break; case '\n': filterstate = 0; break; default: if (!uprf (buffer, XXX_FIELD_PRF) && !uprf (buffer, VRSN_FIELD) && !uprf (buffer, "Subject:") && !uprf (buffer, "Encrypted:") && !uprf (buffer, "Message-ID:")) { filterstate = -1; buffer[0] = 0; break; } filterstate = 1; break; } } fputs (buffer, fp); if (pos >= last) break; } if (fflush (fp)) advise (ct->c_storage, "error writing to"); fclose (fp); fclose (ct->c_fp); ct->c_fp = NULL; return OK; } /* * Add a file to a folder. * * Return the new message number of the file * when added to the folder. Return -1, if * there is an error. */ static int output_content_folder (char *folder, char *filename) { int msgnum; struct msgs *mp; /* Read the folder. */ if ((mp = folder_read (folder, 0))) { /* Link file into folder */ msgnum = folder_addmsg (&mp, filename, 0, 0, 0, 0, NULL); } else { inform("unable to read folder %s", folder); return NOTOK; } /* free folder structure */ folder_free (mp); /* * Return msgnum. We are relying on the fact that * msgnum will be -1, if folder_addmsg() had an error. */ return msgnum; } /* * Parse and expand the storage formatting string * pointed to by "cp" into "buffer". */ static int parse_format_string (CT ct, char *cp, char *buffer, int buflen, char *dir) { int len; char *bp; CI ci = &ct->c_ctinfo; /* * If storage string is "-", just copy it, and * return (send content to standard output). */ if (cp[0] == '-' && cp[1] == '\0') { strncpy (buffer, cp, buflen); return 0; } bp = buffer; bp[0] = '\0'; /* * If formatting string is a pathname that doesn't * begin with '/', then preface the path with the * appropriate directory. */ if (*cp != '/' && *cp != '|' && *cp != '!') { if (!strcmp(dir, "/")) dir = ""; /* Don't start with "//". */ snprintf (bp, buflen, "%s/", dir); len = strlen (bp); bp += len; buflen -= len; } for (; *cp; cp++) { /* We are processing a storage escape */ if (*cp == '%') { switch (*++cp) { case 'a': /* * Insert parameters from Content-Type. * This is only valid for '|' commands. */ if (buffer[0] != '|' && buffer[0] != '!') { *bp++ = *--cp; *bp = '\0'; buflen--; continue; } { PM pm; char *s = ""; for (pm = ci->ci_first_pm; pm; pm = pm->pm_next) { snprintf (bp, buflen, "%s%s=\"%s\"", s, pm->pm_name, get_param_value(pm, '?')); len = strlen (bp); bp += len; buflen -= len; s = " "; } } break; case 'm': /* insert message number */ snprintf (bp, buflen, "%s", r1bindex (ct->c_file, '/')); break; case 'P': /* insert part number with leading dot */ if (ct->c_partno) snprintf (bp, buflen, ".%s", ct->c_partno); break; case 'p': /* insert part number without leading dot */ if (ct->c_partno) strncpy (bp, ct->c_partno, buflen); break; case 't': /* insert content type */ strncpy (bp, ci->ci_type, buflen); break; case 's': /* insert content subtype */ strncpy (bp, ci->ci_subtype, buflen); break; case '%': /* insert the character % */ goto raw; default: *bp++ = *--cp; *bp = '\0'; buflen--; continue; } /* Advance bp and decrement buflen */ len = strlen (bp); bp += len; buflen -= len; } else { raw: *bp++ = *cp; *bp = '\0'; buflen--; } } return 0; } /* * Check if the content specifies a filename * in its MIME parameters. */ static void get_storeproc (CT ct) { char *cp; CI ci; /* * If the storeproc has already been defined, * we just return (for instance, if this content * is part of a "message/external". */ if (ct->c_storeproc) return; /* * If there's a Content-Disposition header and it has a filename, * use that (RFC-2183). */ if (ct->c_dispo) { if ((cp = get_param(ct->c_dispo_first, "filename", '_', 0)) && use_param_as_filename(cp)) { ct->c_storeproc = mh_xstrdup(cp); free(cp); return; } mh_xfree(cp); } /* * Check the attribute/value pairs, for the attribute "name". * If found, do a few sanity checks and copy the value into * the storeproc. */ ci = &ct->c_ctinfo; if ((cp = get_param(ci->ci_first_pm, "name", '_', 0)) && use_param_as_filename(cp)) { ct->c_storeproc = mh_xstrdup(cp); } mh_xfree(cp); } /* * Copy some of the header fields of the initial message/partial * message into the header of the reassembled message. */ static int copy_some_headers (FILE *out, CT ct) { HF hp; hp = ct->c_first_hf; /* start at first header field */ while (hp) { /* * A few of the header fields of the enclosing * messages are not copied. */ if (!uprf (hp->name, XXX_FIELD_PRF) && strcasecmp (hp->name, VRSN_FIELD) && strcasecmp (hp->name, "Subject") && strcasecmp (hp->name, "Encrypted") && strcasecmp (hp->name, "Message-ID")) fprintf (out, "%s:%s", hp->name, hp->value); hp = hp->next; /* next header field */ } return OK; } /******************************************************************************/ /* -clobber support */ static enum clobber_policy_t clobber_policy (const char *value) { if (value == NULL || ! strcasecmp (value, "always")) { return NMH_CLOBBER_ALWAYS; } if (! strcasecmp (value, "auto")) { return NMH_CLOBBER_AUTO; } if (! strcasecmp (value, "suffix")) { return NMH_CLOBBER_SUFFIX; } if (! strcasecmp (value, "ask")) { return NMH_CLOBBER_ASK; } if (! strcasecmp (value, "never")) { return NMH_CLOBBER_NEVER; } adios (NULL, "invalid argument, %s, to clobber", value); } static char * next_version (char *file, enum clobber_policy_t clobber_policy) { const size_t max_versions = 1000000; /* 8 = log max_versions + one for - or . + one for null terminator */ const size_t buflen = strlen (file) + 8; char *buffer = mh_xmalloc (buflen); size_t version; char *extension = NULL; if (clobber_policy == NMH_CLOBBER_AUTO && ((extension = strrchr (file, '.')) != NULL)) { *extension++ = '\0'; } for (version = 1; version < max_versions; ++version) { int fd; switch (clobber_policy) { case NMH_CLOBBER_AUTO: { snprintf (buffer, buflen, "%s-%ld%s%s", file, (long) version, extension == NULL ? "" : ".", extension == NULL ? "" : extension); break; } case NMH_CLOBBER_SUFFIX: snprintf (buffer, buflen, "%s.%ld", file, (long) version); break; default: /* Should never get here. */ inform("will not overwrite %s, invalid clobber policy", buffer); free (buffer); return NULL; } /* Actually (try to) create the file here to avoid a race condition on file naming + creation. This won't solve the problem with old NFS that doesn't support O_EXCL, though. Let the umask strip off permissions from 0666 as desired. That's what fopen () would do if it was creating the file. */ if ((fd = open (buffer, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) >= 0) { close (fd); break; } } free (file); if (version >= max_versions) { inform("will not overwrite %s, too many versions", buffer); free (buffer); buffer = NULL; } return buffer; } static char * clobber_check (char *original_file, mhstoreinfo_t info) { /* clobber policy return value * -------------- ------------ * -always original_file * -auto original_file-.extension * -suffix original_file. * -ask original_file, 0, or another filename/path * -never 0 */ char *file; char *cwd = NULL; int check_again; if (! strcmp (original_file, "-")) { return original_file; } if (info->clobber_policy == NMH_CLOBBER_ASK) { /* Save cwd for possible use in loop below. */ char *slash; cwd = mh_xstrdup(original_file); slash = strrchr (cwd, '/'); if (slash) { *slash = '\0'; } else { /* original_file isn't a full path, which should only happen if it is -. */ free (cwd); cwd = NULL; } } do { struct stat st; file = original_file; check_again = 0; switch (info->clobber_policy) { case NMH_CLOBBER_ALWAYS: break; case NMH_CLOBBER_SUFFIX: case NMH_CLOBBER_AUTO: if (stat (file, &st) == OK) { if ((file = next_version (original_file, info->clobber_policy)) == NULL) { ++info->files_not_clobbered; } } break; case NMH_CLOBBER_ASK: if (stat (file, &st) == OK) { enum answers { NMH_YES, NMH_NO, NMH_RENAME }; static struct swit answer[4] = { { "yes", 0, NMH_YES }, { "no", 0, NMH_NO }, { "rename", 0, NMH_RENAME }, { NULL, 0, 0 } }; char **ans; if (isatty (fileno (stdin))) { char *prompt = concat ("Overwrite \"", file, "\" [y/n/rename]? ", NULL); ans = read_switch_multiword (prompt, answer); free (prompt); } else { /* Overwrite, that's what nmh used to do. And warn. */ inform("-clobber ask but no tty, so overwrite %s", file); break; } switch ((enum answers) smatch (*ans, answer)) { case NMH_YES: break; case NMH_NO: free (file); file = NULL; ++info->files_not_clobbered; break; case NMH_RENAME: { char buf[PATH_MAX]; printf ("Enter filename or full path of the new file: "); if (fgets (buf, sizeof buf, stdin) == NULL || buf[0] == '\0') { file = NULL; ++info->files_not_clobbered; } else { trim_suffix_c(buf, '\n'); } free (file); if (buf[0] == '/') { /* Full path, use it. */ file = mh_xstrdup(buf); } else { /* Relative path. */ file = cwd ? concat (cwd, "/", buf, NULL) : mh_xstrdup(buf); } check_again = 1; break; } } } break; case NMH_CLOBBER_NEVER: if (stat (file, &st) == OK) { /* Keep count of files that would have been clobbered, and return that as process exit status. */ inform("will not overwrite %s with -clobber never", file); free (file); file = NULL; ++info->files_not_clobbered; } break; } original_file = file; } while (check_again); free (cwd); return file; } static bool use_param_as_filename(const char *p) { /* Preserve result of original test that considered an empty string * OK. */ return !*p || (!strchr("/.|!", *p) && !strchr(p, '%')); } /* -clobber support */ /******************************************************************************/ nmh-1.7.1-RC3/uip/mkstemp.c000644 007761 000024 00000015024 13243042054 015402 0ustar00kenhstaff000000 000000 /* mkstemp.c -- create a temporary file * * This code is Copyright (c) 2014 by the authors of nmh. * See the COPYRIGHT file in the root directory of the nmh * distribution for complete copyright information. */ /* define NMH to 0 to remove dependencies on nmh. */ #ifndef NMH # define NMH 1 #endif /* ! NMH */ #ifdef HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #include #include #include #include #include #include #if ! defined HAVE_MKSTEMPS # define HAVE_MKSTEMPS 0 #endif /* ! HAVE_MKSTEMPS */ char *build_template(const char *, const char *, const char *); void process_args(int, char **, const char **, const char **, const char **); /* * Use a template of the form: * [directory/][prefix]XXXXXX[suffix] * where some of those named components might be null. suffix is only * supported if HAVE_MKSTEMPS. */ int main(int argc, char *argv[]) { const char *directory = "", *prefix = "", *suffix = ""; size_t suffix_len; int fd; char *template; process_args(argc, argv, &directory, &prefix, &suffix); if ((template = build_template(directory, prefix, suffix)) == NULL) { return -1; } if ((suffix_len = strlen(suffix)) > 0) { # if HAVE_MKSTEMPS if ((fd = mkstemps(template, suffix_len)) < 0) { perror("mkstemps"); } # else /* ! HAVE_MKSTEMPS */ fd = 0; # endif /* ! HAVE_MKSTEMPS */ } else { if ((fd = mkstemp(template)) < 0) { perror("mkstemp"); } } if (fd >= 0) { (void) puts(template); (void) close(fd); } free(template); return fd >= 0 ? 0 : -1; } char * build_template(const char *directory, const char *prefix, const char *suffix) { const char pattern[] = "XXXXXX"; size_t len, directory_len, pathsep_len, prefix_len, suffix_len; char *template; directory_len = strlen(directory); if (directory_len > 0) { pathsep_len = 1; if (directory[directory_len - 1] == '/') { /* Will insert a '/' separately, so truncate the one provided in the directory name. */ --directory_len; } } else { pathsep_len = 0; } prefix_len = strlen(prefix); suffix_len = strlen(suffix); /* sizeof pattern includes its final NULL, so don't add another. */ len = directory_len + pathsep_len + prefix_len + sizeof pattern + suffix_len; if ((template = malloc(len))) { char *tp = template; (void) strncpy(tp, directory, directory_len); tp += directory_len; if (pathsep_len == 1) { *tp++ = '/'; } (void) strncpy(tp, prefix, prefix_len); tp += prefix_len; (void) strncpy(tp, pattern, sizeof pattern - 1); tp += sizeof pattern - 1; (void) strncpy(tp, suffix, suffix_len); /* tp += suffix_len; */ template[len-1] = '\0'; return template; } perror("malloc"); return NULL; } #if NMH #include #if HAVE_MKSTEMPS # define MHFIXMSG_SWITCHES \ X("directory", 0, DIRECTORYSW) \ X("prefix", 0, PREFIXSW) \ X("suffix", 0, SUFFIXSW) \ X("version", 0, VERSIONSW) \ X("help", 0, HELPSW) #else /* ! HAVE_MKSTEMPS */ # define MHFIXMSG_SWITCHES \ X("directory", 0, DIRECTORYSW) \ X("prefix", 0, PREFIXSW) \ X("version", 0, VERSIONSW) \ X("help", 0, HELPSW) #endif /* ! HAVE_MKSTEMPS */ #define X(sw, minchars, id) id, DEFINE_SWITCH_ENUM(MHFIXMSG); #undef X #define X(sw, minchars, id) { sw, minchars, id }, DEFINE_SWITCH_ARRAY(MHFIXMSG, switches); #undef X void process_args(int argc, char **argv, const char **directory, const char **prefix, const char **suffix) { char **argp, **arguments, *cp, buf[100]; # if ! HAVE_MKSTEMPS NMH_UNUSED(suffix); # endif /* ! HAVE_MKSTEMPS */ if (nmh_init(argv[0], 2)) { done(NOTOK); } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; /* * Parse arguments */ while ((cp = *argp++)) { if (*cp == '-') { switch (smatch(++cp, switches)) { case AMBIGSW: ambigsw(cp, switches); done(NOTOK); case UNKWNSW: inform("-%s unknown", cp); (void) snprintf(buf, sizeof buf, "%s [switches]", invo_name); print_help(buf, switches, 1); done(NOTOK); case HELPSW: (void) snprintf(buf, sizeof buf, "%s [switches]", invo_name); print_help(buf, switches, 1); done(OK); case VERSIONSW: print_version(invo_name); done(OK); case DIRECTORYSW: /* Allow the directory to start with '-'. */ if ((cp = *argp++) == NULL) { adios(NULL, "missing argument to %s", argp[-2]); } *directory = cp; continue; case PREFIXSW: /* Allow the prefix to start with '-'. */ if ((cp = *argp++) == NULL) { adios(NULL, "missing argument to %s", argp[-2]); } *prefix = cp; continue; # if HAVE_MKSTEMPS case SUFFIXSW: /* Allow the suffix to start with '-'. */ if ((cp = *argp++) == NULL) { adios(NULL, "missing argument to %s", argp[-2]); } *suffix = cp; continue; # endif /* HAVE_MKSTEMPS */ } } } } #else /* ! NMH */ void process_args(int argc, char **argv, const char **directory, const char **prefix, const char **suffix) { # if HAVE_MKSTEMPS const char usage[] = "usage: %s [-h] [-d directory] [-p prefix] [-s suffix]\n"; const char optstring[] = "d:hp:s:"; # else /* ! HAVE_MKSTEMPS */ const char usage[] = "usage: %s [-h] [-d directory] [-p prefix]\n"; const char optstring[] = "d:hp:"; # endif /* ! HAVE_MKSTEMPS */ int opt; while ((opt = getopt(argc, argv, optstring)) != -1) { switch (opt) { case 'd': *directory = optarg; break; case 'p': *prefix = optarg; break; case 's': *suffix = optarg; break; case 'h': (void) printf(usage, argv[0]); exit(0); default: (void) fprintf(stderr, usage, argv[0]); exit(-1); } } } #endif /* ! NMH */ nmh-1.7.1-RC3/uip/msgchk.c000644 007761 000024 00000022716 13243042054 015204 0ustar00kenhstaff000000 000000 /* msgchk.c -- check for mail * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #ifndef CYRUS_SASL # define SASLminc(a) (a) #else # define SASLminc(a) 0 #endif #ifndef TLS_SUPPORT # define TLSminc(a) (a) #else # define TLSminc(a) 0 #endif #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", 0, SNOOPSW) \ X("sasl", SASLminc(4), SASLSW) \ X("nosasl", SASLminc(6), NOSASLSW) \ X("saslmech", SASLminc(5), SASLMECHSW) \ X("authservice", SASLminc(0), AUTHSERVICESW) \ X("initialtls", TLSminc(-10), INITTLSSW) \ X("notls", TLSminc(-5), NOTLSSW) \ X("certverify", TLSminc(-10), CERTVERSW) \ X("nocertverify", TLSminc(-12), NOCERTVERSW) \ 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 * one for the NULL vector at the end). */ #define MAXVEC 51 #define NT_NONE 0x0 #ifdef NT_NONE #endif /* Use NT_NONE to prevent warning from gcc -Wunused-macros. */ #define NT_MAIL 0x1 #define NT_NMAI 0x2 #define NT_ALL (NT_MAIL | NT_NMAI) #define NONEOK 0x0 #define UUCPOLD 0x1 #define UUCPNEW 0x2 #define UUCPOK (UUCPOLD | UUCPNEW) #define MMDFOLD 0x4 #define MMDFNEW 0x8 #define MMDFOK (MMDFOLD | MMDFNEW) /* * static prototypes */ static int donote (char *, int); static int checkmail (char *, char *, int, int, int); static int remotemail (char *, char *, char *, char *, int, int, int, int, char *, int, const char *); int main (int argc, char **argv) { int datesw = 1, notifysw = NT_ALL; int status = 0, sasl = 0, tls = 0, noverify = 0; int snoop = 0, vecp = 0; char *cp, *host = NULL, *port = NULL, *user = NULL, *proxy = NULL; char buf[BUFSIZ], *saslmech = NULL, *auth_svc = NULL; char **argp, **arguments, *vec[MAXVEC]; struct passwd *pw; if (nmh_init(argv[0], 1)) { return 1; } mts_init (); arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [switches] [users ...]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case DATESW: datesw++; continue; case NDATESW: datesw = 0; continue; case NOTESW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); notifysw |= donote (cp, 1); continue; case NNOTESW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); notifysw &= ~donote (cp, 0); continue; case HOSTSW: if (!(host = *argp++) || *host == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case PORTSW: if (!(port = *argp++) || *port == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case USERSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if (vecp >= MAXVEC-1) adios (NULL, "you can only check %d users at a time", MAXVEC-1); else user = vec[vecp++] = cp; continue; case SNOOPSW: snoop++; continue; case SASLSW: sasl++; continue; case NOSASLSW: sasl = 0; continue; case SASLMECHSW: if (!(saslmech = *argp++) || *saslmech == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case INITTLSSW: tls++; continue; case NOTLSSW: tls = 0; continue; case CERTVERSW: noverify = 0; continue; case NOCERTVERSW: noverify++; continue; case AUTHSERVICESW: #ifdef OAUTH_SUPPORT if (!(auth_svc = *argp++) || *auth_svc == '-') adios (NULL, "missing argument to %s", argp[-2]); #else adios (NULL, "not built with OAuth support"); #endif continue; case PROXYSW: if (!(proxy = *argp++) || *proxy == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; } } if (vecp >= MAXVEC-1) adios (NULL, "you can only check %d users at a time", MAXVEC-1); else vec[vecp++] = cp; } /* * If -host is not specified by user */ if (!host || !*host) { /* * If "pophost" is specified in mts.conf, * use it as default value. */ if (pophost && *pophost) host = pophost; } if (!host || !*host) host = NULL; if (vecp != 0) vec[vecp] = NULL; if (host) { int tlsflag = 0; if (tls) tlsflag |= P_INITTLS; if (noverify) tlsflag |= P_NOVERIFY; if (vecp == 0) { status = remotemail (host, port, user, proxy, notifysw, 1, snoop, sasl, saslmech, tlsflag, auth_svc); } else { for (vecp = 0; vec[vecp]; vecp++) status += remotemail (host, port, vec[vecp], proxy, notifysw, 0, snoop, sasl, saslmech, tlsflag, auth_svc); } } else { if (user == NULL) user = getusername (); if (vecp == 0) { char *home; /* Not sure this check makes sense... */ if (!geteuid() || NULL == (home = getenv("HOME"))) { pw = getpwnam (user); if (pw == NULL) adios (NULL, "unable to get information about user"); home = pw->pw_dir; } status = checkmail (user, home, datesw, notifysw, 1); } else { for (vecp = 0; vec[vecp]; vecp++) { if ((pw = getpwnam (vec[vecp]))) status += checkmail (pw->pw_name, pw->pw_dir, datesw, notifysw, 0); else inform("no such user as %s", vec[vecp]); } } } /* host == NULL */ done (status); return 1; } #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 donote (char *cp, int ntflag) { switch (smatch (cp, ntswitches)) { case AMBIGSW: ambigsw (cp, ntswitches); done (1); case UNKWNSW: adios (NULL, "-%snotify %s unknown", ntflag ? "" : "no", cp); case NALLSW: return NT_ALL; case NMAISW: return NT_MAIL; case NNMAISW: return NT_NMAI; } return 0; /* Before 1999-07-15, garbage was returned if control got here. */ } static int checkmail (char *user, char *home, int datesw, int notifysw, int personal) { int mf, status; char buffer[BUFSIZ]; struct stat st; snprintf (buffer, sizeof(buffer), "%s/%s", mmdfldir[0] ? mmdfldir : home, mmdflfil[0] ? mmdflfil : user); if (datesw) { st.st_size = 0; st.st_atime = st.st_mtime = 0; } mf = (stat (buffer, &st) == NOTOK || st.st_size == 0) ? NONEOK : st.st_atime <= st.st_mtime ? MMDFNEW : MMDFOLD; if ((mf & UUCPOK) || (mf & MMDFOK)) { if (notifysw & NT_MAIL) { if (personal) printf ("You have "); else printf ("%s has ", user); if (mf & UUCPOK) printf ("%s old-style bell", mf & UUCPOLD ? "old" : "new"); if ((mf & UUCPOK) && (mf & MMDFOK)) printf (" and "); if (mf & MMDFOK) printf ("%s%s", mf & MMDFOLD ? "old" : "new", mf & UUCPOK ? " Internet" : ""); printf (" mail waiting"); } else { notifysw = 0; } status = 0; } else { if (notifysw & NT_NMAI) printf (personal ? "You don't %s%s" : "%s doesn't %s", personal ? "" : user, "have any mail waiting"); else notifysw = 0; status = 1; } if (notifysw) if (datesw && st.st_atime) printf ("; last read on %s", dtime (&st.st_atime, 1)); if (notifysw) putchar('\n'); return status; } extern char response[]; static int remotemail (char *host, char *port, char *user, char *proxy, int notifysw, int personal, int snoop, int sasl, char *saslmech, int tls, const char *auth_svc) { int nmsgs, nbytes, status; if (auth_svc == NULL) { if (saslmech && ! strcasecmp(saslmech, "xoauth2")) { adios (NULL, "must specify -authservice with -saslmech xoauth2"); } } else { if (user == NULL) { adios (NULL, "must specify -user with -saslmech xoauth2"); } } /* open the POP connection */ if (pop_init (host, port, user, proxy, snoop, sasl, saslmech, tls, auth_svc) == NOTOK || pop_stat (&nmsgs, &nbytes) == NOTOK /* check for messages */ || pop_quit () == NOTOK) { /* quit POP connection */ inform("%s", response); return 1; } if (nmsgs) { if (notifysw & NT_MAIL) { if (personal) printf ("You have "); else printf ("%s has ", user); printf ("%d message%s (%d bytes)", nmsgs, PLURALS(nmsgs), nbytes); } else notifysw = 0; status = 0; } else { if (notifysw & NT_NMAI) printf (personal ? "You don't %s%s" : "%s doesn't %s", personal ? "" : user, "have any mail waiting"); else notifysw = 0; status = 1; } if (notifysw) printf (" on %s\n", host); return status; } nmh-1.7.1-RC3/uip/new.c000644 007761 000024 00000034045 13243042054 014517 0ustar00kenhstaff000000 000000 /* new.c -- as new, list all folders with unseen messages * -- as fnext, move to next folder with unseen messages * -- as fprev, move to previous folder with unseen messages * -- as unseen, scan all unseen messages * This code is Copyright (c) 2008, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. * * Inspired by Luke Mewburn's new: http://www.mewburn.net/luke/src/new */ #include #include #include #include #include "../sbr/lock_file.h" #include "../sbr/m_maildir.h" #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 /* What to do, based on argv[0]. */ static enum { RM_NEW, RM_FNEXT, RM_FPREV, RM_UNSEEN } run_mode = RM_NEW; /* check_folders uses this to maintain state with both .folders list of * folders and with crawl_folders. */ struct list_state { struct node **first, **cur_node; size_t *maxlen; char *cur; char **sequences; struct node *node; }; /* Return the number of messages in a string list of message numbers. */ static int count_messages(char *field) { int total = 0; int j, k; char *cp, **ap; field = getcpy(field); /* copied from seq_read.c:seq_init */ for (ap = brkstring (field, " ", "\n"); *ap; ap++) { if ((cp = strchr(*ap, '-'))) *cp++ = '\0'; if ((j = m_atoi (*ap)) > 0) { k = cp ? m_atoi (cp) : j; total += k - j + 1; } } free(field); return total; } /* Return TRUE if the sequence 'name' is in 'sequences'. */ static boolean seq_in_list(char *name, char *sequences[]) { int i; for (i = 0; sequences[i] != NULL; i++) { if (strcmp(name, sequences[i]) == 0) { return TRUE; } } return FALSE; } /* Return the string list of message numbers from the sequences file, or NULL * if none. */ static char * get_msgnums(char *folder, char *sequences[]) { char *seqfile = NULL; FILE *fp; int state; char name[NAMESZ], field[NMH_BUFSIZ]; char *cp; char *msgnums = NULL, *this_msgnums, *old_msgnums; int failed_to_lock = 0; m_getfld_state_t gstate = 0; /* copied from seq_read.c:seq_public */ /* * If mh_seq == NULL or if *mh_seq == '\0' (the user has defined * the "mh-sequences" profile entry, but left it empty), * then just return, and do not initialize any public sequences. */ if (mh_seq == NULL || *mh_seq == '\0') return NULL; /* get filename of sequence file */ seqfile = concat(m_maildir(folder), "/", mh_seq, (void *)NULL); if (seqfile == NULL) return NULL; if ((fp = lkfopendata (seqfile, "r", & failed_to_lock)) == NULL) { if (failed_to_lock) { adios (seqfile, "failed to lock"); } else { free(seqfile); return NULL; } } /* Use m_getfld to scan sequence file */ for (;;) { int fieldsz = sizeof field; switch (state = m_getfld (&gstate, name, field, &fieldsz, fp)) { case FLD: case FLDPLUS: if (state == FLDPLUS) { cp = getcpy (field); while (state == FLDPLUS) { fieldsz = sizeof field; state = m_getfld (&gstate, name, field, &fieldsz, fp); cp = add (field, cp); } /* Here's where we differ from seq_public: if it's in a * sequence we want, save the list of messages. */ if (seq_in_list(name, sequences)) { this_msgnums = trimcpy(cp); if (msgnums == NULL) { msgnums = this_msgnums; } else { old_msgnums = msgnums; msgnums = concat(old_msgnums, " ", this_msgnums, (void *)NULL); free(old_msgnums); free(this_msgnums); } } free (cp); } else { /* and here */ if (seq_in_list(name, sequences)) { this_msgnums = trimcpy(field); if (msgnums == NULL) { msgnums = this_msgnums; } else { old_msgnums = msgnums; msgnums = concat(old_msgnums, " ", this_msgnums, (void *)NULL); free(old_msgnums); free(this_msgnums); } } } continue; case BODY: adios (NULL, "no blank lines are permitted in %s", seqfile); break; case FILEEOF: break; default: adios (NULL, "%s is poorly formatted", seqfile); } break; /* break from for loop */ } m_getfld_state_destroy (&gstate); lkfclosedata (fp, seqfile); free(seqfile); return msgnums; } /* Check `folder' (of length `len') for interesting messages, filling in the * list in `b'. */ static void check_folder(char *folder, size_t len, struct list_state *b) { char *msgnums = get_msgnums(folder, b->sequences); int is_cur = strcmp(folder, b->cur) == 0; if (is_cur || msgnums != NULL) { if (*b->first == NULL) { NEW(b->node); *b->first = b->node; } else { NEW(b->node->n_next); b->node = b->node->n_next; } b->node->n_name = folder; b->node->n_field = msgnums; if (*b->maxlen < len) { *b->maxlen = len; } } /* Save the node for the current folder, so we can fall back to it. */ if (is_cur) { *b->cur_node = b->node; } } static boolean crawl_callback(char *folder, void *baton) { check_folder(folder, strlen(folder), baton); return TRUE; } /* Scan folders, returning: * first -- list of nodes for all folders which have desired messages; * if the current folder is listed in .folders, it is also in * the list regardless of whether it has any desired messages * last -- last node in list * cur_node -- node of current folder, if listed in .folders * maxlen -- length of longest folder name * * `cur' points to the name of the current folder, `folders' points to the * name of a .folder (if NULL, crawl all folders), and `sequences' points to * the array of sequences for which to look. * * An empty list is returned as first=last=NULL. */ static void check_folders(struct node **first, struct node **last, struct node **cur_node, size_t *maxlen, char *cur, char *folders, char *sequences[]) { struct list_state b; FILE *fp; char *line; size_t len; *first = *last = *cur_node = NULL; *maxlen = 0; b.first = first; b.cur_node = cur_node; b.maxlen = maxlen; b.cur = cur; b.sequences = sequences; if (folders == NULL) { if (chdir(m_maildir("")) < 0) { advise (m_maildir(""), "chdir"); } crawl_folders(".", crawl_callback, &b); } else { fp = fopen(folders, "r"); if (fp == NULL) { adios(NULL, "failed to read %s", folders); } while (vfgets(fp, &line) == OK) { len = strlen(line) - 1; line[len] = '\0'; check_folder(mh_xstrdup(line), len, &b); } fclose(fp); } if (*first != NULL) { b.node->n_next = NULL; *last = b.node; } } /* Return a single string of the `sequences' joined by a space (' '). */ static char * join_sequences(char *sequences[]) { int i; size_t len = 0; char *result, *cp; for (i = 0; sequences[i] != NULL; i++) { len += strlen(sequences[i]) + 1; } result = mh_xmalloc(len + 1); for (i = 0, cp = result; sequences[i] != NULL; i++, cp += len + 1) { len = strlen(sequences[i]); memcpy(cp, sequences[i], len); cp[len] = ' '; } /* -1 to overwrite the last delimiter */ *--cp = '\0'; return result; } /* Return a struct node for the folder to change to. This is the next * (previous, if RM_FPREV mode) folder with desired messages, or the current * folder if no folders have desired. If RM_NEW or RM_UNSEEN mode, print the * output but don't change folders. * * n_name is the folder to change to, and n_field is the string list of * desired message numbers. */ static struct node * doit(char *cur, char *folders, char *sequences[]) { struct node *first, *cur_node, *node, *last, *prev; size_t folder_len; int count, total = 0; char *command = NULL, *sequences_s = NULL; if (cur == NULL || cur[0] == '\0') { cur = "inbox"; } check_folders(&first, &last, &cur_node, &folder_len, cur, folders, sequences); if (run_mode == RM_FNEXT || run_mode == RM_FPREV) { if (first == NULL) { /* No folders at all... */ return NULL; } if (first->n_next == NULL) { /* We have only one node; any desired messages in it? */ if (first->n_field == NULL) { return NULL; } return first; } if (cur_node == NULL) { /* Current folder is not listed in .folders, return first. */ return first; } } else if (run_mode == RM_UNSEEN) { sequences_s = join_sequences(sequences); } for (node = first, prev = NULL; node != NULL; prev = node, node = node->n_next) { if (run_mode == RM_FNEXT) { /* If we have a previous node and it is the current * folder, return this node. */ if (prev != NULL && strcmp(prev->n_name, cur) == 0) { return node; } } else if (run_mode == RM_FPREV) { if (strcmp(node->n_name, cur) == 0) { /* Found current folder in fprev mode; if we have a * previous node in the list, return it; else return * the last node. */ if (prev == NULL) { return last; } return prev; } } else if (run_mode == RM_UNSEEN) { int status; if (node->n_field == NULL) { continue; } printf("\n%d %s messages in %s", count_messages(node->n_field), sequences_s, node->n_name); if (strcmp(node->n_name, cur) == 0) { puts(" (*: current folder)"); } else { putchar('\n'); } fflush(stdout); /* TODO: Split enough of scan.c out so that we can call it here. */ command = concat("scan +", node->n_name, " ", sequences_s, (void *)NULL); status = system(command); if (! WIFEXITED (status)) { adios (command, "system"); } free(command); } else { if (node->n_field == NULL) { continue; } count = count_messages(node->n_field); total += count; printf("%-*s %6d.%c %s\n", (int) folder_len, node->n_name, count, (strcmp(node->n_name, cur) == 0 ? '*' : ' '), node->n_field); } } /* If we're fnext, we haven't checked the last node yet. If it's the * current folder, return the first node. */ if (run_mode == RM_FNEXT) { assert(last != NULL); if (strcmp(last->n_name, cur) == 0) { return first; } } if (run_mode == RM_NEW) { printf("%-*s %6d.\n", (int) folder_len, " total", total); } return cur_node; } int main(int argc, char **argv) { char **ap, *cp, **argp, **arguments; char help[BUFSIZ]; char *folders = NULL; svector_t sequences = svector_create (0); int i = 0; char *unseen; struct node *folder; if (nmh_init(argv[0], 1)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; /* * Parse arguments */ while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (help, sizeof(help), "%s [switches] [sequences]", invo_name); print_help (help, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case FOLDERSSW: if (!(folders = *argp++) || *folders == '-') adios(NULL, "missing argument to %s", argp[-2]); continue; case MODESW: if (!(invo_name = *argp++) || *invo_name == '-') adios(NULL, "missing argument to %s", argp[-2]); invo_name = r1bindex(invo_name, '/'); continue; } } /* have a sequence argument */ if (!seq_in_list(cp, svector_strs (sequences))) { svector_push_back (sequences, cp); ++i; } } if (strcmp(invo_name, "fnext") == 0) { run_mode = RM_FNEXT; } else if (strcmp(invo_name, "fprev") == 0) { run_mode = RM_FPREV; } else if (strcmp(invo_name, "unseen") == 0) { run_mode = RM_UNSEEN; } if (folders == NULL) { /* will flists */ } else { if (folders[0] != '/') { folders = m_maildir(folders); } } if (i == 0) { /* no sequence arguments; use unseen */ unseen = context_find(usequence); if (unseen == NULL || unseen[0] == '\0') { adios(NULL, "must specify sequences or set %s", usequence); } for (ap = brkstring(unseen, " ", "\n"); *ap; ap++) { svector_push_back (sequences, *ap); ++i; } } folder = doit(context_find(pfolder), folders, svector_strs (sequences)); if (folder == NULL) { done(0); return 1; } if (run_mode == RM_UNSEEN) { /* All the scan(1)s it runs change the current folder, so we * need to put it back. Unfortunately, context_replace lamely * ignores the new value you give it if it is the same one it * has in memory. So, we'll be lame, too. I'm not sure if i * should just change context_replace... */ context_replace(pfolder, "defeat_context_replace_optimization"); } /* update current folder */ context_replace(pfolder, folder->n_name); if (run_mode == RM_FNEXT || run_mode == RM_FPREV) { printf("%s %s\n", folder->n_name, folder->n_field); } context_save(); svector_free (sequences); done (0); return 1; } nmh-1.7.1-RC3/uip/packf.c000644 007761 000024 00000010411 13243042054 015001 0ustar00kenhstaff000000 000000 /* packf.c -- pack a nmh folder into a file * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include "../sbr/m_maildir.h" #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; static void mbxclose_done(int) NORETURN; char *file = NULL; int main (int argc, char **argv) { int fd, msgnum; char *cp, *maildir, *msgnam, *folder = NULL, buf[BUFSIZ]; char **argp, **arguments; struct msgs_array msgs = { 0, 0, NULL }; struct msgs *mp; struct stat st; if (nmh_init(argv[0], 1)) { return 1; } done=mbxclose_done; arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; /* * Parse arguments */ while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [+folder] [msgs] [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case FILESW: if (file) adios (NULL, "only one file at a time!"); if (!(file = *argp++) || *file == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case MBOXSW: mbx_style = MBOX_FORMAT; continue; case MMDFSW: mbx_style = MMDF_FORMAT; continue; } } if (*cp == '+' || *cp == '@') { if (folder) adios (NULL, "only one folder at a time!"); folder = pluspath (cp); } else app_msgarg(&msgs, cp); } if (!file) file = "./msgbox"; file = path (file, TFILE); /* * Check if file to be created (or appended to) * exists. If not, ask for confirmation. */ if (stat (file, &st) == NOTOK) { if (errno != ENOENT) adios (file, "error on file"); cp = concat ("Create file \"", file, "\"? ", NULL); if (!read_yes_or_no_if_tty (cp)) done (1); free (cp); } if (!context_find ("path")) free (path ("./", TFOLDER)); /* default is to pack whole folder */ if (!msgs.size) app_msgarg(&msgs, "all"); if (!folder) folder = getfolder (1); maildir = m_maildir (folder); if (chdir (maildir) == NOTOK) adios (maildir, "unable to change directory to "); /* read folder and create message structure */ if (!(mp = folder_read (folder, 1))) adios (NULL, "unable to read folder %s", folder); /* check for empty folder */ if (mp->nummsg == 0) adios (NULL, "no messages in %s", folder); /* parse all the message ranges/sequences and set SELECTED */ for (msgnum = 0; msgnum < msgs.size; msgnum++) if (!m_convert (mp, msgs.msgs[msgnum])) done (1); seq_setprev (mp); /* set the previous-sequence */ /* open and lock new maildrop file */ if ((md = mbx_open(file, mbx_style, getuid(), getgid(), m_gmprot())) == NOTOK) adios (file, "unable to open"); /* copy all the SELECTED messages to the file */ for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) if (is_selected(mp, msgnum)) { if ((fd = open (msgnam = m_name (msgnum), O_RDONLY)) == NOTOK) { admonish (msgnam, "unable to read message"); break; } if (mbx_copy (file, mbx_style, md, fd, NULL) == NOTOK) adios (file, "error writing to file"); close (fd); } /* close and unlock maildrop file */ mbx_close (file, md); context_replace (pfolder, folder); /* update current folder */ if (mp->hghsel != mp->curmsg) seq_setcur (mp, mp->lowsel); seq_save (mp); context_save (); /* save the context file */ folder_free (mp); /* free folder/message structure */ done (0); return 1; } static void NORETURN mbxclose_done (int status) { mbx_close (file, md); exit (status); } nmh-1.7.1-RC3/uip/pick.c000644 007761 000024 00000017430 13243042054 014653 0ustar00kenhstaff000000 000000 /* pick.c -- search for messages by content * * This code is Copyright (c) 2002, 2008, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include "../sbr/m_maildir.h" #define PICK_SWITCHES \ X("reverse", 0, REVSW) \ 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("debug", 0, DEBUGSW) \ 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; static void putzero_done (int) NORETURN; int main (int argc, char **argv) { int publicsw = -1, zerosw = 1, vecp = 0; size_t seqp = 0; int msgnum; char *maildir, *folder = NULL, buf[100]; char *cp, **argp, **arguments; svector_t seqs = svector_create (0); char *vec[MAXARGS]; struct msgs_array msgs = { 0, 0, NULL }; struct msgnum_array nums = { 0, 0, NULL }; struct msgs *mp, *mp2; FILE *fp; int debug = 0; int reverse = 0; int start, end, inc; if (nmh_init(argv[0], 1)) { return 1; } done=putzero_done; /* Deprecated. Use -debug instead. */ if ((cp = getenv ("MHPDEBUG")) && *cp) ++debug; arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; while ((cp = *argp++)) { if (*cp == '-') { if (*++cp == '-') { vec[vecp++] = --cp; goto pattern; } switch (smatch (cp, switches)) { case AMBIGSW: ambigsw (cp, switches); listsw = 0; /* HACK */ done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [+folder] [msgs] [switches]", invo_name); print_help (buf, switches, 1); listsw = 0; /* HACK */ done (0); case VERSIONSW: print_version(invo_name); listsw = 0; /* HACK */ done (0); case REVSW: reverse = 1; continue; case CCSW: case DATESW: case FROMSW: case SUBJSW: case TOSW: case DATFDSW: case AFTRSW: case BEFRSW: case SRCHSW: vec[vecp++] = --cp; pattern: if (!(cp = *argp++))/* allow -xyz arguments */ adios (NULL, "missing argument to %s", argp[-2]); vec[vecp++] = cp; continue; case OTHRSW: adios (NULL, "internal error!"); case ANDSW: case ORSW: case NOTSW: case LBRSW: case RBRSW: vec[vecp++] = --cp; continue; case SEQSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if (!seq_nameok (cp)) done (1); svector_push_back (seqs, cp); seqp++; continue; case NSEQSW: seqp = 0; continue; case PUBLSW: publicsw = 1; continue; case NPUBLSW: publicsw = 0; continue; case ZEROSW: zerosw++; continue; case NZEROSW: zerosw = 0; continue; case LISTSW: listsw = 1; continue; case NLISTSW: listsw = 0; continue; case DEBUGSW: ++debug; continue; } } if (*cp == '+' || *cp == '@') { if (folder) adios (NULL, "only one folder at a time!"); else folder = pluspath (cp); } else app_msgarg(&msgs, cp); } vec[vecp] = NULL; if (!context_find ("path")) free (path ("./", TFOLDER)); /* * If we didn't specify which messages to search, * then search the whole folder. */ if (!msgs.size) app_msgarg(&msgs, "all"); if (!folder) folder = getfolder (1); maildir = m_maildir (folder); if (chdir (maildir) == NOTOK) adios (maildir, "unable to change directory to"); /* read folder and create message structure */ if (!(mp = folder_read (folder, 0))) adios (NULL, "unable to read folder %s", folder); /* check for empty folder */ if (mp->nummsg == 0) adios (NULL, "no messages in %s", folder); /* parse all the message ranges/sequences and set SELECTED */ for (msgnum = 0; msgnum < msgs.size; msgnum++) if (!m_convert (mp, msgs.msgs[msgnum])) done (1); /* * If we aren't saving the results to a sequence, * we default to list the results. */ if (listsw == -1) listsw = !seqp; if (publicsw == 1 && is_readonly(mp)) adios (NULL, "folder %s is read-only, so -public not allowed", folder); if (!pcompile (vec, NULL)) done (1); /* If printing message numbers to standard out, force line buffering on. */ if (listsw) setvbuf (stdout, NULL, _IOLBF, 0); /* * Scan through all the SELECTED messages and check for a * match. If there is NOT a match, then add it to a list to * remove from the final sequence (it will make sense later) */ if (!reverse) { /* Overflow or underflow is fine. */ start = mp->lowsel; end = mp->hghsel + 1; inc = 1; } else { start = mp->hghsel; end = mp->lowsel - 1; inc = -1; } for (msgnum = start; msgnum != end; msgnum += inc) { if (is_selected (mp, msgnum)) { if ((fp = fopen (cp = m_name (msgnum), "r")) == NULL) admonish (cp, "unable to read message"); if (fp && pmatches (fp, msgnum, 0L, 0L, debug)) { if (listsw) puts(m_name (msgnum)); } else { app_msgnum(&nums, msgnum); } if (fp) fclose (fp); } } if (nums.size >= mp->numsel) adios (NULL, "no messages match specification"); /* * So, what's happening here? * * - Re-read the folder and sequences, but with locking. * - Recreate the original set of selected messages from the command line * - Set the previous sequence * - Remove any messages that did NOT result in hits from the selection * - Add to any new sequences */ if (!(mp2 = folder_read (folder, 1))) adios (NULL, "unable to reread folder %s", folder); for (msgnum = 0; msgnum < msgs.size; msgnum++) if (!m_convert (mp2, msgs.msgs[msgnum])) done (1); seq_setprev (mp2); /* set the previous-sequence */ /* * Nums contains a list of messages that we did NOT match. Remove * that from the selection. */ for (msgnum = 0; msgnum < nums.size; msgnum++) { unset_selected(mp2, nums.msgnums[msgnum]); mp2->numsel--; } /* * Add the matching messages to sequences */ if (seqp > 0) { for (seqp = 0; seqp < svector_size (seqs); seqp++) if (!seq_addsel (mp2, svector_at (seqs, seqp), publicsw, zerosw)) done (1); } /* * Print total matched if not printing each matched message number. */ if (!listsw) { printf ("%d hit%s\n", mp2->numsel, PLURALS(mp2->numsel)); } svector_free (seqs); context_replace (pfolder, folder); /* update current folder */ seq_save (mp2); /* synchronize message sequences */ context_save (); /* save the context file */ folder_free (mp); /* free folder/message structure */ folder_free (mp2); done (0); return 1; } static void NORETURN putzero_done (int status) { if (listsw && status && !isatty (fileno (stdout))) puts("0"); exit (status); } nmh-1.7.1-RC3/uip/picksbr.c000644 007761 000024 00000047024 13243042054 015364 0ustar00kenhstaff000000 000000 /* picksbr.c -- routines to help pick along... * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #ifdef HAVE_SYS_TIME_H # include #endif #include #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 */ /* * We really should be using re_comp() and re_exec() here. Unfortunately, * pick advertises that lowercase characters matches characters of both * cases. Since re_exec() doesn't exhibit this behavior, we are stuck * with this version. Furthermore, we need to be able to save and restore * the state of the pattern matcher in order to do things "efficiently". * * The matching power of this algorithm isn't as powerful as the re_xxx() * routines (no \(xxx\) and \n constructs). Such is life. */ #define CCHR 2 #define CDOT 4 #define CCL 6 #define NCCL 8 #define CDOL 10 #define CEOF 11 #define STAR 01 #define LBSIZE NMH_BUFSIZ #define ESIZE 1024 static char linebuf[LBSIZE + 1]; static char decoded_linebuf[LBSIZE + 1]; /* the magic array for case-independence */ static unsigned char cc[] = { 0000,0001,0002,0003,0004,0005,0006,0007, 0010,0011,0012,0013,0014,0015,0016,0017, 0020,0021,0022,0023,0024,0025,0026,0027, 0030,0031,0032,0033,0034,0035,0036,0037, 0040,0041,0042,0043,0044,0045,0046,0047, 0050,0051,0052,0053,0054,0055,0056,0057, 0060,0061,0062,0063,0064,0065,0066,0067, 0070,0071,0072,0073,0074,0075,0076,0077, 0100,0141,0142,0143,0144,0145,0146,0147, 0150,0151,0152,0153,0154,0155,0156,0157, 0160,0161,0162,0163,0164,0165,0166,0167, 0170,0171,0172,0133,0134,0135,0136,0137, 0140,0141,0142,0143,0144,0145,0146,0147, 0150,0151,0152,0153,0154,0155,0156,0157, 0160,0161,0162,0163,0164,0165,0166,0167, 0170,0171,0172,0173,0174,0175,0176,0177, 0200,0201,0202,0203,0204,0205,0206,0207, 0210,0211,0212,0213,0214,0215,0216,0217, 0220,0221,0222,0223,0224,0225,0226,0227, 0230,0231,0232,0233,0234,0235,0236,0237, 0240,0241,0242,0243,0244,0245,0246,0247, 0250,0251,0252,0253,0254,0255,0256,0257, 0260,0261,0262,0263,0264,0265,0266,0267, 0270,0271,0272,0273,0274,0275,0276,0277, 0300,0301,0302,0303,0304,0305,0306,0307, 0310,0311,0312,0313,0314,0315,0316,0317, 0320,0321,0322,0323,0324,0325,0326,0327, 0330,0331,0332,0333,0334,0335,0336,0337, 0340,0341,0342,0343,0344,0345,0346,0347, 0350,0351,0352,0353,0354,0355,0356,0357, 0360,0361,0362,0363,0364,0365,0366,0367, 0370,0371,0372,0373,0374,0375,0376,0377, }; /* * DEFINITIONS FOR NEXUS */ #define nxtarg() (*argp ? *argp++ : NULL) #define prvarg() argp-- #define pinform if (!talked++) inform struct nexus { int (*n_action)(); union { /* for {OR,AND,NOT}action */ struct { struct nexus *un_L_child; struct nexus *un_R_child; } st1; /* for GREPaction */ struct { int un_header; int un_circf; char un_expbuf[ESIZE]; char *un_patbuf; } st2; /* for TWSaction */ struct { char *un_datef; int un_after; struct tws un_tws; } st3; } un; }; #define n_L_child un.st1.un_L_child #define n_R_child un.st1.un_R_child #define n_header un.st2.un_header #define n_circf un.st2.un_circf #define n_expbuf un.st2.un_expbuf #define n_patbuf un.st2.un_patbuf #define n_datef un.st3.un_datef #define n_after un.st3.un_after #define n_tws un.st3.un_tws static int talked; static char *datesw; static char **argp; static struct nexus *head; /* * prototypes for date routines */ static struct tws *tws_parse(char *, int); static struct tws *tws_special(char *); /* * static prototypes */ static void PRaction(struct nexus *, int); static int gcompile(struct nexus *, char *); static int advance(char *, char *); static int cclass(unsigned char *, int, int); static int tcompile(char *, struct tws *, int); static struct nexus *parse(void); static struct nexus *nexp1(void); static struct nexus *nexp2(void); static struct nexus *nexp3(void); static struct nexus *newnexus(int (*)(struct nexus *n, FILE *fp, int msgnum, long start, long stop)); static int ORaction(struct nexus *n, FILE *fp, int msgnum, long start, long stop); static int ANDaction(struct nexus *n, FILE *fp, int msgnum, long start, long stop); static int NOTaction(struct nexus *n, FILE *fp, int msgnum, long start, long stop); static int GREPaction(struct nexus *n, FILE *fp, int msgnum, long start, long stop); static int TWSaction(struct nexus *n, FILE *fp, int msgnum, long start, long stop); int pcompile (char **vec, char *date) { argp = vec; if ((datesw = date) == NULL) datesw = "date"; talked = 0; if ((head = parse ()) == NULL) return !talked; if (*argp) { inform("%s unexpected", *argp); return 0; } return 1; } static struct nexus * parse (void) { char *cp; struct nexus *n, *o; if ((n = nexp1 ()) == NULL || (cp = nxtarg ()) == NULL) return n; if (*cp != '-') { pinform("%s unexpected", cp); return NULL; } if (*++cp == '-') goto header; switch (smatch (cp, parswit)) { case AMBIGSW: ambigsw (cp, parswit); talked++; return NULL; case UNKWNSW: fprintf (stderr, "-%s unknown\n", cp); talked++; return NULL; case PROR: o = newnexus (ORaction); o->n_L_child = n; if ((o->n_R_child = parse ())) return o; pinform("missing disjunctive"); free (o); return NULL; header: ; default: prvarg (); return n; } } static struct nexus * nexp1 (void) { char *cp; struct nexus *n, *o; if ((n = nexp2 ()) == NULL || (cp = nxtarg ()) == NULL) return n; if (*cp != '-') { pinform("%s unexpected", cp); free (n); return NULL; } if (*++cp == '-') goto header; switch (smatch (cp, parswit)) { case AMBIGSW: ambigsw (cp, parswit); talked++; free (n); return NULL; case UNKWNSW: fprintf (stderr, "-%s unknown\n", cp); talked++; free (n); return NULL; case PRAND: o = newnexus (ANDaction); o->n_L_child = n; if ((o->n_R_child = nexp1 ())) return o; pinform("missing conjunctive"); free (o); return NULL; header: ; default: prvarg (); return n; } } static struct nexus * nexp2 (void) { char *cp; struct nexus *n; if ((cp = nxtarg ()) == NULL) return NULL; if (*cp != '-') { prvarg (); return nexp3 (); } if (*++cp == '-') goto header; switch (smatch (cp, parswit)) { case AMBIGSW: ambigsw (cp, parswit); talked++; return NULL; case UNKWNSW: fprintf (stderr, "-%s unknown\n", cp); talked++; return NULL; case PRNOT: n = newnexus (NOTaction); if ((n->n_L_child = nexp3 ())) return n; pinform("missing negation"); free (n); return NULL; header: ; default: prvarg (); return nexp3 (); } } static struct nexus * nexp3 (void) { int i; char *cp, *dp; char buffer[BUFSIZ], temp[64]; struct nexus *n; if ((cp = nxtarg ()) == NULL) return NULL; if (*cp != '-') { pinform("%s unexpected", cp); return NULL; } if (*++cp == '-') { dp = ++cp; goto header; } switch (i = smatch (cp, parswit)) { case AMBIGSW: ambigsw (cp, parswit); talked++; return NULL; case UNKWNSW: fprintf (stderr, "-%s unknown\n", cp); talked++; return NULL; case PRLBR: if ((n = parse ()) == NULL) { pinform("missing group"); return NULL; } if ((cp = nxtarg ()) == NULL) { pinform("missing -rbrace"); return NULL; } if (*cp++ == '-' && smatch (cp, parswit) == PRRBR) return n; pinform("%s unexpected", --cp); return NULL; default: prvarg (); return NULL; case PRCC: case PRDATE: case PRFROM: case PRTO: case PRSUBJ: strncpy(temp, parswit[i].sw, sizeof(temp)); temp[sizeof(temp) - 1] = '\0'; dp = *brkstring (temp, " ", NULL); header: ; if (!(cp = nxtarg ())) {/* allow -xyz arguments */ pinform("missing argument to %s", argp[-2]); return NULL; } n = newnexus (GREPaction); n->n_header = 1; snprintf (buffer, sizeof(buffer), "^%s[ \t]*:.*%s", dp, cp); dp = buffer; goto pattern; case PRSRCH: n = newnexus (GREPaction); n->n_header = 0; if (!(cp = nxtarg ())) {/* allow -xyz arguments */ pinform("missing argument to %s", argp[-2]); free (n); return NULL; } dp = cp; pattern: ; if (!gcompile (n, dp)) { pinform("pattern error in %s %s", argp[-2], cp); free (n); return NULL; } n->n_patbuf = mh_xstrdup(dp); return n; case PROTHR: pinform("internal error!"); return NULL; case PRDATF: if (!(datesw = nxtarg ()) || *datesw == '-') { pinform("missing argument to %s", argp[-2]); return NULL; } return nexp3 (); case PRAFTR: case PRBEFR: if (!(cp = nxtarg ())) {/* allow -xyz arguments */ pinform("missing argument to %s", argp[-2]); return NULL; } n = newnexus (TWSaction); n->n_datef = datesw; if (!tcompile (cp, &n->n_tws, n->n_after = i == PRAFTR)) { pinform("unable to parse %s %s", argp[-2], cp); free (n); return NULL; } return n; } } static struct nexus * newnexus(int (*action)(struct nexus *n, FILE *fp, int msgnum, long start, long stop)) { struct nexus *p; NEW0(p); p->n_action = action; return p; } int pmatches (FILE *fp, int msgnum, long start, long stop, int debug) { if (!head) return 1; if (!talked++ && debug) PRaction (head, 0); return (*head->n_action)(head, fp, msgnum, start, stop); } static void PRaction (struct nexus *n, int level) { int i; for (i = 0; i < level; i++) fprintf (stderr, "| "); if (n->n_action == ORaction) { fprintf (stderr, "OR\n"); PRaction (n->n_L_child, level + 1); PRaction (n->n_R_child, level + 1); return; } if (n->n_action == ANDaction) { fprintf (stderr, "AND\n"); PRaction (n->n_L_child, level + 1); PRaction (n->n_R_child, level + 1); return; } if (n->n_action == NOTaction) { fprintf (stderr, "NOT\n"); PRaction (n->n_L_child, level + 1); return; } if (n->n_action == GREPaction) { fprintf (stderr, "PATTERN(%s) %s\n", n->n_header ? "header" : "body", n->n_patbuf); return; } if (n->n_action == TWSaction) { fprintf (stderr, "TEMPORAL(%s) %s: %s\n", n->n_after ? "after" : "before", n->n_datef, dasctime (&n->n_tws, TW_NULL)); return; } fprintf (stderr, "UNKNOWN(0x%x)\n", (unsigned int)(unsigned long) (*n->n_action)); } static int ORaction(struct nexus *n, FILE *fp, int msgnum, long start, long stop) { if ((*n->n_L_child->n_action)(n->n_L_child, fp, msgnum, start, stop)) return 1; return (*n->n_R_child->n_action)(n->n_R_child, fp, msgnum, start, stop); } static int ANDaction(struct nexus *n, FILE *fp, int msgnum, long start, long stop) { if (!(*n->n_L_child->n_action)(n->n_L_child, fp, msgnum, start, stop)) return 0; return (*n->n_R_child->n_action)(n->n_R_child, fp, msgnum, start, stop); } static int NOTaction(struct nexus *n, FILE *fp, int msgnum, long start, long stop) { return (!(*n->n_L_child->n_action)(n->n_L_child, fp, msgnum, start, stop)); } static int gcompile (struct nexus *n, char *astr) { int c; int cclcnt; unsigned char *ep, *dp, *sp, *lastep = 0; dp = (ep = (unsigned char *) n->n_expbuf) + sizeof n->n_expbuf; sp = (unsigned char *) astr; if (*sp == '^') { n->n_circf = 1; sp++; } else n->n_circf = 0; for (;;) { if (ep >= dp) goto cerror; if ((c = *sp++) != '*') lastep = ep; switch (c) { case '\0': *ep++ = CEOF; return 1; case '.': *ep++ = CDOT; continue; case '*': if (lastep == 0) goto defchar; *lastep |= STAR; continue; case '$': if (*sp != '\0') goto defchar; *ep++ = CDOL; continue; case '[': *ep++ = CCL; *ep++ = 0; cclcnt = 0; if ((c = *sp++) == '^') { c = *sp++; ep[-2] = NCCL; } if (c == '-') { *ep++ = c; cclcnt++; c = *sp++; } do { if (c == '-' && *sp != '\0' && *sp != ']') { for (c = ep[-1]+1; c < *sp; c++) { *ep++ = c; cclcnt++; if (c == '\0' || ep >= dp) goto cerror; } } else { *ep++ = c; cclcnt++; if (c == '\0' || ep >= dp) goto cerror; } } while ((c = *sp++) != ']'); if (cclcnt > 255) goto cerror; lastep[1] = cclcnt; continue; case '\\': if ((c = *sp++) == '\0') goto cerror; /* FALLTHRU */ defchar: default: *ep++ = CCHR; *ep++ = c; } } cerror: ; return 0; } static int GREPaction(struct nexus *n, FILE *fp, int msgnum, long start, long stop) { int c, body, lf; long pos = start; char *p1, *p2, *ebp, *cbp; char ibuf[BUFSIZ]; NMH_UNUSED (msgnum); fseek (fp, start, SEEK_SET); body = 0; ebp = cbp = ibuf; for (;;) { if (body && n->n_header) return 0; p1 = linebuf; p2 = cbp; lf = 0; for (;;) { if (p2 >= ebp) { if (fgets (ibuf, sizeof ibuf, fp) == NULL || (stop && pos >= stop)) { if (lf) break; return 0; } pos += (long) strlen (ibuf); p2 = ibuf; ebp = ibuf + strlen (ibuf); } c = *p2++; if (lf && c != '\n') { if (c != ' ' && c != '\t') { --p2; break; } lf = 0; } if (c == '\n') { if (body) break; if (lf) { body++; break; } lf++; /* Unfold by skipping the newline. */ c = 0; } if (c && p1 < &linebuf[LBSIZE - 1]) *p1++ = c; } *p1++ = 0; cbp = p2; p1 = linebuf; p2 = n->n_expbuf; /* Attempt to decode as a MIME header. If it's the last header, body will be 1 and lf will be at least 1. */ if ((body == 0 || lf > 0) && decode_rfc2047 (linebuf, decoded_linebuf, sizeof decoded_linebuf)) { p1 = decoded_linebuf; } if (n->n_circf) { if (advance (p1, p2)) return 1; continue; } if (*p2 == CCHR) { c = p2[1]; do { if (*p1 == c || cc[(unsigned char)*p1] == c) if (advance (p1, p2)) return 1; } while (*p1++); continue; } do { if (advance (p1, p2)) return 1; } while (*p1++); } } static int advance (char *alp, char *aep) { unsigned char *lp, *ep, *curlp; lp = (unsigned char *)alp; ep = (unsigned char *)aep; for (;;) switch (*ep++) { case CCHR: if (*ep++ == *lp++ || ep[-1] == cc[lp[-1]]) continue; return 0; case CDOT: if (*lp++) continue; return 0; case CDOL: if (*lp == 0) continue; return 0; case CEOF: return 1; case CCL: if (cclass (ep, *lp++, 1)) { ep += *ep + 1; continue; } return 0; case NCCL: if (cclass (ep, *lp++, 0)) { ep += *ep + 1; continue; } return 0; case CDOT | STAR: curlp = lp; while (*lp++) continue; goto star; case CCHR | STAR: curlp = lp; while (*lp++ == *ep || cc[lp[-1]] == *ep) continue; ep++; goto star; case CCL | STAR: case NCCL | STAR: curlp = lp; while (cclass (ep, *lp++, ep[-1] == (CCL | STAR))) continue; ep += *ep + 1; goto star; star: do { lp--; if (advance ((char *) lp, (char *) ep)) return (1); } while (lp > curlp); return 0; default: inform("advance() botch -- you lose big, continuing..."); return 0; } } static int cclass (unsigned char *aset, int ac, int af) { unsigned int n; unsigned char c, *set; set = aset; if ((c = ac) == 0) return (0); n = *set++; while (n--) if (*set++ == c || set[-1] == cc[c]) return (af); return (!af); } static int tcompile (char *ap, struct tws *tb, int isafter) { struct tws *tw; if ((tw = tws_parse (ap, isafter)) == NULL) return 0; *tb = *tw; return 1; } static struct tws * tws_parse (char *ap, int isafter) { char buffer[BUFSIZ]; struct tws *tw, *ts; if ((tw = tws_special (ap)) != NULL) { tw->tw_sec = tw->tw_min = isafter ? 59 : 0; tw->tw_hour = isafter ? 23 : 0; return tw; } if ((tw = dparsetime (ap)) != NULL) return tw; if ((ts = dlocaltimenow ()) == NULL) return NULL; snprintf (buffer, sizeof(buffer), "%s %s", ap, dtwszone (ts)); if ((tw = dparsetime (buffer)) != NULL) return tw; snprintf (buffer, sizeof(buffer), "%s %02d:%02d:%02d %s", ap, ts->tw_hour, ts->tw_min, ts->tw_sec, dtwszone (ts)); if ((tw = dparsetime (buffer)) != NULL) return tw; snprintf (buffer, sizeof(buffer), "%02d %s %04d %s", ts->tw_mday, tw_moty[ts->tw_mon], ts->tw_year, ap); if ((tw = dparsetime (buffer)) != NULL) return tw; snprintf (buffer, sizeof(buffer), "%02d %s %04d %s %s", ts->tw_mday, tw_moty[ts->tw_mon], ts->tw_year, ap, dtwszone (ts)); if ((tw = dparsetime (buffer)) != NULL) return tw; return NULL; } static struct tws * tws_special (char *ap) { int i; time_t clock; struct tws *tw; time (&clock); if (!strcasecmp (ap, "today")) return dlocaltime (&clock); if (!strcasecmp (ap, "yesterday")) { clock -= (long) (60 * 60 * 24); return dlocaltime (&clock); } if (!strcasecmp (ap, "tomorrow")) { clock += (long) (60 * 60 * 24); return dlocaltime (&clock); } for (i = 0; tw_ldotw[i]; i++) if (!strcasecmp (ap, tw_ldotw[i])) break; if (tw_ldotw[i]) { if ((tw = dlocaltime (&clock)) == NULL) return NULL; if ((i -= tw->tw_wday) > 0) i -= 7; } else { if (*ap != '-') return NULL; /* -ddd days ago */ i = atoi (ap); /* we should error check this */ } clock += (long) ((60 * 60 * 24) * i); return dlocaltime (&clock); } static int TWSaction(struct nexus *n, FILE *fp, int msgnum, long start, long stop) { int state; char *bp; char buf[NMH_BUFSIZ], name[NAMESZ]; struct tws *tw; m_getfld_state_t gstate = 0; NMH_UNUSED (stop); fseek (fp, start, SEEK_SET); for (bp = NULL;;) { int bufsz = sizeof buf; switch (state = m_getfld (&gstate, name, buf, &bufsz, fp)) { case FLD: case FLDPLUS: mh_xfree(bp); bp = mh_xstrdup(buf); while (state == FLDPLUS) { bufsz = sizeof buf; state = m_getfld (&gstate, name, buf, &bufsz, fp); bp = add (buf, bp); } if (!strcasecmp (name, n->n_datef)) break; continue; case BODY: case FILEEOF: case LENERR: case FMTERR: if (state == LENERR || state == FMTERR) inform("format error in message %d", msgnum); mh_xfree(bp); return 0; default: adios (NULL, "internal error -- you lose"); } break; } m_getfld_state_destroy (&gstate); if ((tw = dparsetime (bp)) == NULL) inform("unable to parse %s field in message %d, matching...", n->n_datef, msgnum), state = 1; else state = n->n_after ? (twsort (tw, &n->n_tws) > 0) : (twsort (tw, &n->n_tws) < 0); mh_xfree(bp); return state; } nmh-1.7.1-RC3/uip/popsbr.c000644 007761 000024 00000036352 13243042054 015236 0ustar00kenhstaff000000 000000 /* popsbr.c -- POP client subroutines * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #define TRM "." static int poprint = 0; char response[BUFSIZ]; static netsec_context *nsc = NULL; /* * static prototypes */ static int command(const char *, ...); static int multiline(void); static int traverse (int (*)(char *), const char *, ...); static int vcommand(const char *, va_list); static int pop_getline (char *, int, netsec_context *); static int pop_sasl_callback(enum sasl_message_type, unsigned const char *, unsigned int, unsigned char **, unsigned int *, char **); static int check_mech(char *server_mechs, size_t server_mechs_size) { int status, sasl_capability = 0; /* * First off, we're going to send the CAPA command to see if we can * even support the AUTH command, and if we do, then we'll get a * list of mechanisms the server supports. If we don't support * the CAPA command, then it's unlikely that we will support * SASL */ if (command("CAPA") == NOTOK) { snprintf(response, sizeof(response), "The POP CAPA command failed; POP server does not " "support SASL"); return NOTOK; } while ((status = multiline()) != DONE) switch (status) { case NOTOK: return NOTOK; break; case DONE: /* Shouldn't be possible, but just in case */ break; case OK: if (strncasecmp(response, "SASL ", 5) == 0) { /* * We've seen the SASL capability. Grab the mech list */ sasl_capability++; strncpy(server_mechs, response + 5, server_mechs_size); } break; } if (!sasl_capability) { snprintf(response, sizeof(response), "POP server does not support " "SASL"); return NOTOK; } return OK; } /* * Split string containing proxy command into an array of arguments * suitable for passing to exec. Returned array must be freed. Shouldn't * be possible to call this with host set to NULL. */ char ** parse_proxy(char *proxy, char *host) { char **pargv, **p; int pargc = 2; int hlen = strlen(host); int plen = 1; unsigned char *cur, *pro; char *c; /* skip any initial space */ for (pro = (unsigned char *) proxy; isspace(*pro); pro++) continue; /* calculate required size for argument array */ for (cur = pro; *cur; cur++) { if (isspace(*cur) && cur[1] && !isspace(cur[1])) plen++, pargc++; else if (*cur == '%' && cur[1] == 'h') { plen += hlen; cur++; } else if (!isspace(*cur)) plen++; } /* put together list of arguments */ p = pargv = mh_xmalloc(pargc * sizeof(char *)); c = *pargv = mh_xmalloc(plen * sizeof(char)); for (cur = pro; *cur; cur++) { if (isspace(*cur) && cur[1] && !isspace(cur[1])) { *c++ = '\0'; *++p = c; } else if (*cur == '%' && cur[1] == 'h') { strcpy (c, host); c += hlen; cur++; } else if (!isspace(*cur)) *c++ = *cur; } *c = '\0'; *++p = NULL; return pargv; } int pop_init (char *host, char *port, char *user, char *proxy, int snoop, int sasl, char *mech, int tls, const char *oauth_svc) { int fd1, fd2; char buffer[BUFSIZ]; char *errstr; nsc = netsec_init(); if (user) netsec_set_userid(nsc, user); netsec_set_hostname(nsc, host); if (oauth_svc != NULL) { if (netsec_set_oauth_service(nsc, oauth_svc) != OK) { snprintf(response, sizeof(response), "OAuth2 not supported"); return NOTOK; } } if (proxy && *proxy) { int pid; int inpipe[2]; /* for reading from the server */ int outpipe[2]; /* for sending to the server */ if (pipe(inpipe) < 0) { adios ("inpipe", "pipe"); } if (pipe(outpipe) < 0) { adios ("outpipe", "pipe"); } pid=fork(); if (pid==0) { char **argv; /* in child */ close(0); close(1); dup2(outpipe[0],0); /* connect read end of connection */ dup2(inpipe[1], 1); /* connect write end of connection */ if(inpipe[0]>1) close(inpipe[0]); if(inpipe[1]>1) close(inpipe[1]); if(outpipe[0]>1) close(outpipe[0]); if(outpipe[1]>1) close(outpipe[1]); /* run the proxy command */ argv=parse_proxy(proxy, host); execvp(argv[0],argv); perror(argv[0]); close(0); close(1); free(*argv); free(argv); exit(10); } /* okay in the parent we do some stuff */ close(inpipe[1]); /* child uses this */ close(outpipe[0]); /* child uses this */ /* we read on fd1 */ fd1=inpipe[0]; /* and write on fd2 */ fd2=outpipe[1]; } else { if ((fd1 = client (host, port ? port : "pop3", response, sizeof(response), snoop)) == NOTOK) { return NOTOK; } fd2 = fd1; } SIGNAL (SIGPIPE, SIG_IGN); netsec_set_fd(nsc, fd1, fd2); netsec_set_snoop(nsc, snoop); if (tls & P_INITTLS) { if (netsec_set_tls(nsc, 1, tls & P_NOVERIFY, &errstr) != OK) { snprintf(response, sizeof(response), "%s", errstr); free(errstr); return NOTOK; } if (netsec_negotiate_tls(nsc, &errstr) != OK) { snprintf(response, sizeof(response), "%s", errstr); free(errstr); return NOTOK; } } if (sasl) { if (netsec_set_sasl_params(nsc, "pop", mech, pop_sasl_callback, &errstr) != OK) { snprintf(response, sizeof(response), "%s", errstr); free(errstr); return NOTOK; } } switch (pop_getline (response, sizeof response, nsc)) { case OK: if (poprint) fprintf (stderr, "<--- %s\n", response); if (*response == '+') { nmh_creds_t creds; if (sasl) { char server_mechs[256]; if (check_mech(server_mechs, sizeof(server_mechs)) != OK) return NOTOK; if (netsec_negotiate_sasl(nsc, server_mechs, &errstr) != OK) { strncpy(response, errstr, sizeof(response)); response[sizeof(response) - 1] = '\0'; free(errstr); return NOTOK; } return OK; } if (!(creds = nmh_get_credentials(host, user))) return NOTOK; if (command ("USER %s", nmh_cred_get_user(creds)) != NOTOK) { if (command("PASS %s", nmh_cred_get_password(creds)) != NOTOK) { nmh_credentials_free(creds); return OK; } } nmh_credentials_free(creds); } strncpy (buffer, response, sizeof(buffer)); command ("QUIT"); strncpy (response, buffer, sizeof(response)); /* FALLTHRU */ case NOTOK: case DONE: if (poprint) fprintf (stderr, "%s\n", response); netsec_shutdown(nsc); nsc = NULL; return NOTOK; } return NOTOK; /* NOTREACHED */ } /* * Our SASL callback; we are given SASL tokens and then have to format * them according to the protocol requirements, and then process incoming * messages and feed them back into the SASL library. */ static int pop_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata, unsigned int indatalen, unsigned char **outdata, unsigned int *outdatalen, char **errstr) { int rc, snoopoffset; char *mech, *line; size_t len, b64len; switch (mtype) { case NETSEC_SASL_START: /* * Generate our AUTH message, but there is a wrinkle. * * Technically, according to RFC 5034, if your command INCLUDING * an initial response exceeds 255 octets (including CRLF), you * can't issue this all in one go, but have to just issue the * AUTH command, wait for a blank initial response, and then * send your data. */ mech = netsec_get_sasl_mechanism(nsc); if (indatalen) { char *b64data; b64data = mh_xmalloc(BASE64SIZE(indatalen)); writeBase64raw(indata, indatalen, (unsigned char *) b64data); b64len = strlen(b64data); /* Formula here is AUTH + SP + mech + SP + out + CR + LF */ len = b64len + 8 + strlen(mech); if (len > 255) { rc = netsec_printf(nsc, errstr, "AUTH %s\r\n", mech); if (rc) return NOTOK; if (netsec_flush(nsc, errstr) != OK) return NOTOK; line = netsec_readline(nsc, &len, errstr); if (! line) return NOTOK; /* * If the protocol is being followed correctly, should just * be a "+ ", nothing else. */ if (len != 2 || strcmp(line, "+ ") != 0) { netsec_err(errstr, "Did not get expected blank response " "for initial challenge response"); return NOTOK; } netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, NULL); rc = netsec_printf(nsc, errstr, "%s\r\n", b64data); netsec_set_snoop_callback(nsc, NULL, NULL); free(b64data); if (rc != OK) return NOTOK; if (netsec_flush(nsc, errstr) != OK) return NOTOK; } else { netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, &snoopoffset); snoopoffset = 6 + strlen(mech); rc = netsec_printf(nsc, errstr, "AUTH %s %s\r\n", mech, b64data); free(b64data); netsec_set_snoop_callback(nsc, NULL, NULL); if (rc != OK) return NOTOK; if (netsec_flush(nsc, errstr) != OK) return NOTOK; } } else { if (netsec_printf(nsc, errstr, "AUTH %s\r\n", mech) != OK) return NOTOK; if (netsec_flush(nsc, errstr) != OK) return NOTOK; } break; /* * We should get one line back, with our base64 data. Decode that * and feed it back into the SASL library. */ case NETSEC_SASL_READ: netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, &snoopoffset); snoopoffset = 2; line = netsec_readline(nsc, &len, errstr); netsec_set_snoop_callback(nsc, NULL, NULL); if (line == NULL) return NOTOK; if (len < 2 || (len == 2 && strcmp(line, "+ ") != 0)) { netsec_err(errstr, "Invalid format for SASL response"); return NOTOK; } if (len == 2) { *outdata = NULL; *outdatalen = 0; } else { rc = decodeBase64(line + 2, outdata, &len, 0, NULL); *outdatalen = len; if (rc != OK) { netsec_err(errstr, "Unable to decode base64 response"); return NOTOK; } } break; /* * Our encoding is pretty simple, so this is easy. */ case NETSEC_SASL_WRITE: if (indatalen == 0) { rc = netsec_printf(nsc, errstr, "\r\n"); } else { unsigned char *b64data; b64data = mh_xmalloc(BASE64SIZE(indatalen)); writeBase64raw(indata, indatalen, b64data); netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, NULL); rc = netsec_printf(nsc, errstr, "%s\r\n", b64data); netsec_set_snoop_callback(nsc, NULL, NULL); free(b64data); } if (rc != OK) return NOTOK; if (netsec_flush(nsc, errstr) != OK) return NOTOK; break; /* * Finish the protocol; we're looking for an +OK */ case NETSEC_SASL_FINISH: line = netsec_readline(nsc, &len, errstr); if (line == NULL) return NOTOK; if (!has_prefix(line, "+OK")) { netsec_err(errstr, "Authentication failed: %s", line); return NOTOK; } break; /* * Cancel the SASL exchange in the middle of the commands; for * POP, that's a single "*". * * It's unclear to me if I should be returning errors up; I finally * decided the answer should be "yes", and if the upper layer wants to * ignore them that's their choice. */ case NETSEC_SASL_CANCEL: rc = netsec_printf(nsc, errstr, "*\r\n"); if (rc == OK) rc = netsec_flush(nsc, errstr); if (rc != OK) return NOTOK; break; } return OK; } /* * Find out number of messages available * and their total size. */ int pop_stat (int *nmsgs, int *nbytes) { if (command ("STAT") == NOTOK) return NOTOK; *nmsgs = *nbytes = 0; sscanf (response, "+OK %d %d", nmsgs, nbytes); return OK; } int pop_retr (int msgno, int (*action)(char *)) { return traverse (action, "RETR %d", msgno); } static int traverse (int (*action)(char *), const char *fmt, ...) { int result, snoopstate; va_list ap; char buffer[sizeof(response)]; va_start(ap, fmt); result = vcommand (fmt, ap); va_end(ap); if (result == NOTOK) return NOTOK; strncpy (buffer, response, sizeof(buffer)); if ((snoopstate = netsec_get_snoop(nsc))) netsec_set_snoop(nsc, 0); for (;;) switch (multiline ()) { case NOTOK: netsec_set_snoop(nsc, snoopstate); return NOTOK; case DONE: strncpy (response, buffer, sizeof(response)); netsec_set_snoop(nsc, snoopstate); return OK; case OK: (*action) (response); break; } } int pop_dele (int msgno) { return command ("DELE %d", msgno); } int pop_quit (void) { int i; i = command ("QUIT"); pop_done (); return i; } int pop_done (void) { if (nsc) netsec_shutdown(nsc); return OK; } int command(const char *fmt, ...) { va_list ap; int result; va_start(ap, fmt); result = vcommand(fmt, ap); va_end(ap); return result; } static int vcommand (const char *fmt, va_list ap) { /* char *cp; */ char *errstr; if (netsec_vprintf(nsc, &errstr, fmt, ap) != OK) { strncpy(response, errstr, sizeof(response)); response[sizeof(response) - 1] = '\0'; free(errstr); return NOTOK; } if (netsec_printf(nsc, &errstr, "\r\n") != OK) { strncpy(response, errstr, sizeof(response)); response[sizeof(response) - 1] = '\0'; free(errstr); return NOTOK; } if (netsec_flush(nsc, &errstr) != OK) { strncpy(response, errstr, sizeof(response)); response[sizeof(response) - 1] = '\0'; free(errstr); return NOTOK; } switch (pop_getline (response, sizeof response, nsc)) { case OK: if (poprint) fprintf (stderr, "<--- %s\n", response); return (*response == '+' ? OK : NOTOK); case NOTOK: case DONE: if (poprint) fprintf (stderr, "%s\n", response); return NOTOK; } return NOTOK; /* NOTREACHED */ } int multiline (void) { char buffer[BUFSIZ + LEN(TRM)]; if (pop_getline (buffer, sizeof buffer, nsc) != OK) return NOTOK; if (has_prefix(buffer, TRM)) { if (buffer[LEN(TRM)] == 0) return DONE; strncpy (response, buffer + LEN(TRM), sizeof(response)); } else strncpy (response, buffer, sizeof(response)); return OK; } /* * This is now just a thin wrapper around netsec_readline(). */ static int pop_getline (char *s, int n, netsec_context *ns) { /* int c = -2; */ char *p; size_t len, destlen; /* int rc; */ char *errstr; p = netsec_readline(ns, &len, &errstr); if (p == NULL) { strncpy(response, errstr, sizeof(response)); response[sizeof(response) - 1] = '\0'; free(errstr); return NOTOK; } /* * If we had an error, it should have been returned already. Since * netsec_readline() strips off the CR-LF ending, just copy the existing * buffer into response now. * * We get a length back from netsec_readline, but the rest of the POP * code doesn't handle it; the assumptions are that everything from * the network can be represented as C strings. That should get fixed * someday. */ destlen = min(len, (size_t)(n - 1)); memcpy(s, p, destlen); s[destlen] = '\0'; return OK; } nmh-1.7.1-RC3/uip/post.c000644 007761 000024 00000144711 13243042054 014715 0ustar00kenhstaff000000 000000 /* post.c -- enter messages into the mail transport system * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #include #include #include #include #include "../sbr/m_mktemp.h" #include "../sbr/message_id.h" #ifdef HAVE_SYS_TIME_H # include #endif #include #include #ifndef CYRUS_SASL # define SASLminc(a) (a) #else /* CYRUS_SASL */ # define SASLminc(a) 0 #endif /* CYRUS_SASL */ #ifndef TLS_SUPPORT # define TLSminc(a) (a) #else /* TLS_SUPPORT */ # define TLSminc(a) 0 #endif /* TLS_SUPPORT */ #ifndef OAUTH_SUPPORT # define OAUTHminc(a) (a) #else /* OAUTH_SUPPORT */ # define OAUTHminc(a) 0 #endif /* OAUTH_SUPPORT */ #define FCCS 10 /* max number of fccs allowed */ /* In the following array of structures, the numeric second field of the structures (minchars) is apparently used like this: -# : Switch can be abbreviated to # characters; switch hidden in -help. 0 : Switch can't be abbreviated; switch shown in -help. # : Switch can be abbreviated to # characters; switch shown in -help. */ #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("sasl", SASLminc(4), SASLSW) \ X("nosasl", SASLminc(6), NOSASLSW) \ X("saslmech", SASLminc(5), SASLMECHSW) \ X("user", SASLminc(-4), USERSW) \ X("port server submission port name/number", 4, PORTSW) \ X("tls", TLSminc(-3), TLSSW) \ X("initialtls", TLSminc(-10), INITTLSSW) \ X("notls", TLSminc(-5), NTLSSW) \ X("certverify", TLSminc(-10), CERTVERSW) \ X("nocertverify", TLSminc(-12), NOCERTVERSW) \ X("fileproc", -4, FILEPROCSW) \ X("mhlproc", -3, MHLPROCSW) \ X("sendmail program", 0, MTSSM) \ X("mts smtp|sendmail/smtp|sendmail/pipe", 2, MTSSW) \ X("credentials legacy|file:filename", 0, CREDENTIALSSW) \ X("messageid localname|random", 2, MESSAGEIDSW) \ X("authservice auth-service-name", OAUTHminc(-11), AUTHSERVICESW) \ X("oauthcredfile credential-file", OAUTHminc(-7), OAUTHCREDFILESW) \ X("oauthclientid client-id", OAUTHminc(-12), OAUTHCLIDSW) \ X("oauthclientsecret client-secret", OAUTHminc(-12), OAUTHCLSECSW) \ X("oauthauthendpoint authentication-endpoint", OAUTHminc(-6), OAUTHAUTHENDSW) \ X("oauthredirect redirect-uri", OAUTHminc(-6), OAUTHREDIRSW) \ X("oauthtokenendpoint token-endpoint", OAUTHminc(-6), OAUTHTOKENDSW) \ X("oauthscope scope", OAUTHminc(-6), OAUTHSCOPESW) \ #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 /* * Mapping between command-line switches and profile entries, communicated * from 'send'. We use a service name of 'post' internally. */ static struct { const char *profname; int switchnum; const char *value; } oauthswitches[] = { { "oauth-%s-credential-file", OAUTHCREDFILESW, NULL }, { "oauth-%s-client_id", OAUTHCLIDSW, NULL }, { "oauth-%s-client_secret", OAUTHCLSECSW, NULL }, { "oauth-%s-auth_endpoint", OAUTHAUTHENDSW, NULL }, { "oauth-%s-redirect_uri", OAUTHREDIRSW, NULL }, { "oauth-%s-token_endpoint", OAUTHTOKENDSW, NULL }, { "oauth-%s-scope", OAUTHSCOPESW, NULL }, { NULL, 0, NULL } }; struct headers { char *value; unsigned int flags; unsigned int set; }; /* * flags for headers->flags */ #define HNOP 0x0000 /* just used to keep .set around */ #define HBAD 0x0001 /* bad header - don't let it through */ #define HADR 0x0002 /* header has an address field */ #define HSUB 0x0004 /* Subject: header */ #define HTRY 0x0008 /* try to send to addrs on header */ #define HBCC 0x0010 /* don't output this header, unless MTS_SENDMAIL_PIPE */ #define HMNG 0x0020 /* munge this header */ #define HNGR 0x0040 /* no groups allowed in this header */ #define HFCC 0x0080 /* FCC: type header */ #define HNIL 0x0100 /* okay for this header not to have addrs */ #define HIGN 0x0200 /* ignore this header */ #define HDCC 0x0400 /* another undocumented feature */ #define HONE 0x0800 /* Only (zero or) one address allowed */ #define HEFM 0x1000 /* Envelope-From: header */ #define HMIM 0x2000 /* MIME-Version: header */ #define HCTE 0x4000 /* Content-Transfer-Encoding: header */ /* * flags for headers->set */ #define MFRM 0x0001 /* we've seen a From: */ #define MDAT 0x0002 /* we've seen a Date: */ #define MRFM 0x0004 /* we've seen a Resent-From: */ #define MVIS 0x0008 /* we've seen sighted addrs */ #define MINV 0x0010 /* we've seen blind addrs */ #define MSND 0x0020 /* we've seen a Sender: */ #define MRSN 0x0040 /* We've seen a Resent-Sender: */ #define MEFM 0x0080 /* We've seen Envelope-From: */ #define MMIM 0x0100 /* We've seen Mime-Version: */ static struct headers NHeaders[] = { { "Return-Path", HBAD, 0 }, { "Received", HBAD, 0 }, { "Reply-To", HADR|HNGR, 0 }, { "From", HADR|HNGR, MFRM }, { "Sender", HADR|HNGR|HONE, MSND }, { "Date", HBAD, 0 }, { "Subject", HSUB, 0 }, { "To", HADR|HTRY, MVIS }, { "cc", HADR|HTRY, MVIS }, { "Bcc", HADR|HTRY|HBCC|HNIL, MINV }, { "Dcc", HADR|HTRY|HDCC|HNIL, MVIS }, /* sorta cc & bcc combined */ { "Message-ID", HBAD, 0 }, { "Fcc", HFCC, 0 }, { "Envelope-From", HADR|HONE|HEFM, MEFM }, { "MIME-Version", HMIM, MMIM }, { "Content-Transfer-Encoding", HCTE, 0 }, { NULL, 0, 0 } }; static struct headers RHeaders[] = { { "Resent-Reply-To", HADR|HNGR, 0 }, { "Resent-From", HADR|HNGR, MRFM }, { "Resent-Sender", HADR|HNGR, MRSN }, { "Resent-Date", HBAD, 0 }, { "Resent-Subject", HSUB, 0 }, { "Resent-To", HADR|HTRY, MVIS }, { "Resent-cc", HADR|HTRY, MVIS }, { "Resent-Bcc", HADR|HTRY|HBCC, MINV }, { "Resent-Message-ID", HBAD, 0 }, { "Resent-Fcc", HFCC, 0 }, { "Reply-To", HADR, 0 }, { "From", HADR|HNGR, MFRM }, { "Sender", HADR|HNGR, MSND }, { "Date", HNOP, MDAT }, { "To", HADR|HNIL, 0 }, { "cc", HADR|HNIL, 0 }, { "Bcc", HADR|HTRY|HBCC|HNIL, 0 }, { "Fcc", HIGN, 0 }, { "Envelope-From", HADR|HONE|HEFM, MEFM }, { "MIME-Version", HMIM, MMIM }, { "Content-Transfer-Encoding", HCTE, 0 }, { NULL, 0, 0 } }; static short fccind = 0; /* index into fccfold[] */ static short outputlinelen = OUTPUTLINELEN; static int pfd = NOTOK; /* fd to write annotation list to */ static int recipients = 0; /* how many people will get a copy */ static int unkadr = 0; /* how many of those were unknown */ static int badadr = 0; /* number of bad addrs */ static int badmsg = 0; /* message has bad semantics */ static int verbose = 0; /* spell it out */ static int format = 1; /* format addresses */ static int mime = 0; /* use MIME-style encapsulations for Bcc */ static int msgid = 0; /* add msgid */ static int debug = 0; /* debugging post */ static int watch = 0; /* watch the delivery process */ static int whomsw = 0; /* we are whom not post */ static int checksw = 0; /* whom -check */ static int linepos=0; /* putadr()'s position on the line */ static int nameoutput=0; /* putadr() has output header name */ static int sasl=0; /* Use SASL auth for SMTP */ static char *saslmech=NULL; /* Force use of particular SASL mech */ static char *user=NULL; /* Authenticate as this user */ static char *port="submission"; /* Name of server port for SMTP submission */ static int tlsflag=0; /* Flags to control TLS settings */ static int fromcount=0; /* Count of addresses on From: header */ static int seensender=0; /* Have we seen a Sender: header? */ static unsigned msgflags = 0; /* what we've seen */ #define NORMAL 0 #define RESENT 1 static int msgstate = NORMAL; static time_t tclock = 0; /* the time we started (more or less) */ static SIGNAL_HANDLER hstat, istat, qstat, tstat; static char tmpfil[BUFSIZ]; static char bccfil[BUFSIZ]; static char from[BUFSIZ]; /* my network address */ static char sender[BUFSIZ]; /* my Sender: header */ static char efrom[BUFSIZ]; /* my Envelope-From: header */ static char fullfrom[BUFSIZ]; /* full contents of From header */ static char *filter = NULL; /* the filter for BCC'ing */ static char *subject = NULL; /* the subject field for BCC'ing */ static char *fccfold[FCCS]; /* foldernames for FCC'ing */ enum encoding { UNKNOWN = 0, BINARY = 1, SEVENBIT = 7, EIGHTBIT = 8 }; static enum encoding cte = UNKNOWN; static struct headers *hdrtab; /* table for the message we're doing */ static struct mailname localaddrs; /* local addrs */ static struct mailname netaddrs; /* network addrs */ static struct mailname uuaddrs; /* uucp addrs */ static struct mailname tmpaddrs; /* temporary queue */ static int snoop = 0; static char *clientsw = NULL; static char *serversw = NULL; static char prefix[] = "----- =_aaaaaaaaaa"; static char *partno = NULL; /* * static prototypes */ static void putfmt (char *, char *, int *, FILE *); static void start_headers (void); static void finish_headers (FILE *); static int get_header (char *, struct headers *); static int putadr (char *, char *, struct mailname *, FILE *, unsigned int, char *, unsigned int); static void putgrp (char *, char *, FILE *, unsigned int); static int insert (struct mailname *); static void pl (void); static void anno (void); static int annoaux (struct mailname *); static void insert_fcc (struct headers *, char *); static void make_bcc_file (int); static void verify_all_addresses (int, int, char *, int, char *); static void chkadr (void); static void sigon (void); static void sigoff (void); static void p_refile (char *); static void fcc (char *, char *); static void die (char *, char *, ...); static void post (char *, int, int, int, char *, int, char *); static void do_text (char *file, int fd); static void do_an_address (struct mailname *, int); static void do_addresses (int, int); static int find_prefix (void); int main (int argc, char **argv) { int state, compnum, dashstuff = 0, swnum, oauth_flag = 0, tls = -1; int noverify = 0; int eai = 0; /* use Email Address Internationalization (EAI) (SMTPUTF8) */ char *cp, *msg = NULL, **argp, **arguments, *envelope; char buf[NMH_BUFSIZ], name[NAMESZ], *auth_svc = NULL; FILE *in, *out; m_getfld_state_t gstate = 0; if (nmh_init(argv[0], 0 /* use context_foil() */)) { return 1; } mts_init (); arguments = getarguments (invo_name, argc, argv, 0); argp = arguments; while ((cp = *argp++)) { if (*cp == '-') { switch ((swnum = smatch (++cp, switches))) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [switches] file", invo_name); print_help (buf, switches, 0); done (0); case VERSIONSW: print_version(invo_name); done (0); case LIBSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); /* create a minimal context */ if (context_foil (cp) == -1) done (1); continue; case ALIASW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if ((state = alias (cp)) != AK_OK) adios (NULL, "aliasing error in %s - %s", cp, akerror (state)); continue; case CHKSW: checksw++; continue; case NCHKSW: checksw = 0; continue; case DEBUGSW: debug++; continue; case DISTSW: msgstate = RESENT; continue; case FILTSW: if (!(filter = *argp++) || *filter == '-') adios (NULL, "missing argument to %s", argp[-2]); mime = 0; continue; case NFILTSW: filter = NULL; continue; case FRMTSW: format++; continue; case NFRMTSW: format = 0; continue; case BITSTUFFSW: dashstuff = 1; continue; case NBITSTUFFSW: dashstuff = -1; continue; case MIMESW: mime++; filter = NULL; continue; case NMIMESW: mime = 0; continue; case MSGDSW: msgid++; continue; case NMSGDSW: msgid = 0; continue; case VERBSW: verbose++; continue; case NVERBSW: verbose = 0; continue; case WATCSW: watch++; continue; case NWATCSW: watch = 0; continue; case WHOMSW: whomsw++; continue; case WIDTHSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if ((outputlinelen = atoi (cp)) < 10) adios (NULL, "impossible width %d", outputlinelen); continue; case ANNOSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if ((pfd = atoi (cp)) <= 2) adios (NULL, "bad argument %s %s", argp[-2], cp); continue; case CLIESW: if (!(clientsw = *argp++) || *clientsw == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case SERVSW: if (!(serversw = *argp++) || *serversw == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case SNOOPSW: snoop++; continue; case PARTSW: if (!(partno = *argp++) || *partno == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case SASLSW: sasl++; continue; case NOSASLSW: sasl = 0; continue; case SASLMECHSW: if (!(saslmech = *argp++) || *saslmech == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case AUTHSERVICESW: if (!(auth_svc = *argp++) || *auth_svc == '-') adios (NULL, "missing argument to %s", argp[-2]); oauth_flag++; continue; case OAUTHCREDFILESW: case OAUTHCLIDSW: case OAUTHCLSECSW: case OAUTHAUTHENDSW: case OAUTHREDIRSW: case OAUTHTOKENDSW: case OAUTHSCOPESW: { int i; if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); for (i = 0; oauthswitches[i].profname != NULL; i++) { if (oauthswitches[i].switchnum == swnum) { oauthswitches[i].value = cp; break; } } if (oauthswitches[i].profname == NULL) adios (NULL, "internal error: cannot map switch %s " "to profile entry", argp[-2]); oauth_flag++; continue; } case USERSW: if (!(user = *argp++) || *user == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case PORTSW: if (!(port = *argp++) || *port == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case TLSSW: tls = 1; continue; case INITTLSSW: tls = 2; continue; case NTLSSW: tls = 0; continue; case CERTVERSW: noverify = 0; continue; case NOCERTVERSW: noverify++; continue; case FILEPROCSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); fileproc = cp; continue; case MHLPROCSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); mhlproc = cp; continue; case MTSSM: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); sendmail = cp; continue; case MTSSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); save_mts_method (cp); continue; case CREDENTIALSSW: { if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); add_profile_entry ("credentials", cp); continue; } case MESSAGEIDSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if (save_message_id_style (cp) != 0) adios (NULL, "unsupported messageid \"%s\"", cp); continue; } } if (msg) adios (NULL, "only one message at a time!"); else msg = cp; } alias (AliasFile); if (!msg) adios (NULL, "usage: %s [switches] file", invo_name); if (outputlinelen < 10) adios (NULL, "impossible width %d", outputlinelen); if ((in = fopen (msg, "r")) == NULL) adios (msg, "unable to open"); start_headers (); if (debug) { verbose++; out = stdout; } else { if (whomsw) { if ((out = fopen ("/dev/null", "w")) == NULL) adios ("/dev/null", "unable to open"); } else { char *cp = m_mktemp2(NULL, invo_name, NULL, &out); if (cp == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } strncpy(tmpfil, cp, sizeof(tmpfil)); } } hdrtab = msgstate == NORMAL ? NHeaders : RHeaders; for (compnum = 1;;) { int bufsz = sizeof buf; switch (state = m_getfld (&gstate, name, buf, &bufsz, in)) { case FLD: case FLDPLUS: compnum++; cp = mh_xstrdup(buf); while (state == FLDPLUS) { bufsz = sizeof buf; state = m_getfld (&gstate, name, buf, &bufsz, in); cp = add (buf, cp); } putfmt (name, cp, &eai, out); free (cp); continue; case BODY: finish_headers (out); if (whomsw) break; fprintf (out, "\n%s", buf); while (state == BODY) { bufsz = sizeof buf; state = m_getfld (&gstate, name, buf, &bufsz, in); fputs (buf, out); } break; case FILEEOF: finish_headers (out); break; case LENERR: case FMTERR: adios (NULL, "message format error in component #%d", compnum); default: adios (NULL, "getfld() returned %d", state); } break; } m_getfld_state_destroy (&gstate); if (pfd != NOTOK) anno (); fclose (in); if (debug) { pl (); done (0); } else { fclose (out); } /* * Here's how we decide which address to use as the envelope-from * address for SMTP. * * - If we were given an Envelope-From header, use that. * - If we were given a Sender: address, use that. * - Otherwise, use the address on the From: line */ if (msgflags & MEFM) { envelope = efrom; } else if (seensender) { envelope = sender; } else { envelope = from; } if (tls == -1) { #ifdef TLS_SUPPORT /* * The user didn't specify any of the tls switches. Try to * help them by implying -initialtls if they're using port 465 * (smtps, until IANA revoked that registration in 1998). */ tls = ! strcmp (port, "465") || ! strcasecmp (port, "smtps") ? 2 : 0; #else /* ! TLS_SUPPORT */ tls = 0; #endif /* ! TLS_SUPPORT */ } if (tls == 1) tlsflag = S_STARTTLS; else if (tls == 2) tlsflag = S_INITTLS; else tlsflag = 0; if (noverify) tlsflag |= S_NOVERIFY; /* * If we were given any oauth flags, store the appropriate profile * entries and make sure an authservice was given (we have to do this * here because we aren't guaranteed the authservice will be given on * the command line before the other OAuth flags are given). */ if (oauth_flag) { int i; char sbuf[128]; if (auth_svc == NULL) { adios(NULL, "No authentication service given with -authservice"); } for (i = 0; oauthswitches[i].profname != NULL; i++) { if (oauthswitches[i].value != NULL) { snprintf(sbuf, sizeof(sbuf), oauthswitches[i].profname, auth_svc); sbuf[sizeof(sbuf) - 1] = '\0'; add_profile_entry(sbuf, oauthswitches[i].value); } } } /* If we are doing a "whom" check */ if (whomsw) { /* This won't work with MTS_SENDMAIL_PIPE. */ verify_all_addresses (1, eai, envelope, oauth_flag, auth_svc); done (0); } if (msgflags & MINV) { make_bcc_file (dashstuff); if (msgflags & MVIS) { if (sm_mts != MTS_SENDMAIL_PIPE) { /* It would be nice to have support to call verify_all_addresses with MTS_SENDMAIL_PIPE, but that might require running sendmail as root. Note that spost didn't verify addresses. */ verify_all_addresses (verbose, eai, envelope, oauth_flag, auth_svc); } post (tmpfil, 0, verbose, eai, envelope, oauth_flag, auth_svc); } post (bccfil, 1, verbose, eai, envelope, oauth_flag, auth_svc); (void) m_unlink (bccfil); } else { post (tmpfil, 0, isatty (1), eai, envelope, oauth_flag, auth_svc); } p_refile (tmpfil); (void) m_unlink (tmpfil); if (verbose) { if (partno) printf ("Partial Message #%s Processed\n", partno); else puts("Message Processed"); } done (0); return 1; } /* * DRAFT GENERATION */ static void putfmt (char *name, char *str, int *eai, FILE *out) { int count, grp, i, keep; char *cp, *pp, *qp; char namep[BUFSIZ], error[BUFSIZ]; char *savehdr = NULL; unsigned int savehdrlen = 0; struct mailname *mp = NULL, *np = NULL; struct headers *hdr; while (*str == ' ' || *str == '\t') str++; if (msgstate == NORMAL && uprf (name, "resent")) { inform("illegal header line -- %s:", name); badmsg++; return; } if (! *eai) { /* Check each header field value to see if it has any 8-bit characters. If it does, enable EAI support. */ if (contains8bit(str, NULL)) { if (verbose) { puts("EAI/SMTPUTF8 enabled"); } /* Enable SMTPUTF8. */ *eai = 1; /* Enable passing of utf-8 setting to getname()/getadrx(). */ enable_eai(); } } if ((i = get_header (name, hdrtab)) == NOTOK) { if (strncasecmp (name, "nmh-", 4)) { fprintf (out, "%s: %s", name, str); } else { /* Filter out all Nmh-* headers, because Norm asked. They should never have reached this point. Warn about any that are non-empty. */ if (strcmp (str, "\n")) { trim_suffix_c(str, '\n'); if (! whomsw) { inform("ignoring header line -- %s: %s", name, str); } } } return; } hdr = &hdrtab[i]; if (hdr->flags & HIGN) { return; } if (hdr->flags & HBAD) { inform("illegal header line -- %s:", name); badmsg++; return; } msgflags |= (hdr->set & ~(MVIS | MINV)); if (hdr->flags & HSUB) subject = subject ? add (str, add ("\t", subject)) : mh_xstrdup(str); if (hdr->flags & HFCC) { if ((cp = strrchr(str, '\n'))) *cp = 0; for (pp = str; (cp = strchr(pp, ',')); pp = cp) { *cp++ = 0; insert_fcc (hdr, pp); } insert_fcc (hdr, pp); return; } if (hdr->flags & HCTE) { if (strncasecmp (str, "7bit", 4) == 0) { cte = SEVENBIT; } else if (strncasecmp (str, "8bit", 4) == 0) { cte = EIGHTBIT; } else if (strncasecmp (str, "binary", 6) == 0) { cte = BINARY; } } if (!(hdr->flags & HADR)) { fprintf (out, "%s: %s", name, str); return; } /* * If this is a From:/Resent-From: header, save the full thing for * later in case we need it for use when constructing a Bcc draft message. * Because we want to capture the results of alias expansion, save * the output from putadr(). */ if ((msgstate == RESENT) ? (hdr->set & MRFM) : (hdr->set & MFRM)) { savehdr = fullfrom; savehdr[0] = '\0'; savehdrlen = sizeof(fullfrom); } tmpaddrs.m_next = NULL; for (count = 0; (cp = getname (str)); count++) { if ((mp = getm (cp, NULL, 0, error, sizeof(error)))) { if (tmpaddrs.m_next) np->m_next = mp; else tmpaddrs.m_next = mp; np = mp; } else { admonish(cp, "%s", error); if (hdr->flags & HTRY) badadr++; else badmsg++; } } if (count < 1) { if (hdr->flags & HNIL) fprintf (out, "%s: %s", name, str); else { /* * Sender (or Resent-Sender) can have only one address */ if ((msgstate == RESENT) ? (hdr->set & MRSN) : (hdr->set & MSND)) { inform("%s: field requires one address", name); badmsg++; } #ifdef notdef inform("%s: field requires at least one address", name); badmsg++; #endif /* notdef */ } return; } if (count > 1 && (hdr->flags & HONE)) { inform("%s: field only permits one address", name); badmsg++; return; } nameoutput = linepos = 0; snprintf (namep, sizeof(namep), "%s%s", (hdr->flags & HMNG) ? "Original-" : "", name); for (grp = 0, mp = tmpaddrs.m_next; mp; mp = np) if (mp->m_nohost) { /* also used to test (hdr->flags & HTRY) */ /* The address doesn't include a host, so it might be an alias. */ pp = akvalue (mp->m_mbox); /* do mh alias substitution */ qp = akvisible () ? mp->m_mbox : ""; np = mp; if (np->m_gname) putgrp (namep, np->m_gname, out, hdr->flags); while ((cp = getname (pp))) { if (!(mp = getm (cp, NULL, 0, error, sizeof(error)))) { admonish(cp, "%s", error); badadr++; continue; } /* * If it's a From: or Resent-From: header, save the address * for later possible use (as the envelope address for SMTP) */ if ((msgstate == RESENT) ? (hdr->set & MRFM) : (hdr->set & MFRM)) { strncpy(from, auxformat(mp, 0), sizeof(from) - 1); from[sizeof(from) - 1] = '\0'; fromcount = count; } /* * Also save the Sender: or Resent-Sender: header as well */ if ((msgstate == RESENT) ? (hdr->set & MRSN) : (hdr->set & MSND)) { strncpy(sender, auxformat(mp, 0), sizeof(sender) - 1); sender[sizeof(sender) - 1] = '\0'; seensender++; } /* * ALSO ... save Envelope-From */ if (hdr->set & MEFM) { strncpy(efrom, auxformat(mp, 0), sizeof(efrom) - 1); efrom[sizeof(efrom) - 1] = '\0'; } if (hdr->flags & HBCC) mp->m_bcc++; if (np->m_ingrp) mp->m_ingrp = np->m_ingrp; else if (mp->m_gname) putgrp (namep, mp->m_gname, out, hdr->flags); if (mp->m_ingrp) { if (sm_mts == MTS_SENDMAIL_PIPE) { /* Catch this before sendmail chokes with: "553 List:; syntax illegal for recipient addresses". If we wanted to, we could expand out blind aliases and put them in Bcc:, but then they'd have the Blind-Carbon-Copy indication. */ adios (NULL, "blind lists not compatible with" " sendmail/pipe"); } grp++; } if (putadr (namep, qp, mp, out, hdr->flags, savehdr, savehdrlen)) msgflags |= (hdr->set & (MVIS | MINV)); else mnfree (mp); } mp = np; np = np->m_next; mnfree (mp); } else { /* Address includes a host, so no alias substitution is needed. */ /* * If it's a From: or Resent-From header, save the address * for later possible use (as the envelope address for SMTP) */ if ((msgstate == RESENT) ? (hdr->set & MRFM) : (hdr->set & MFRM)) { strncpy(from, auxformat(mp, 0), sizeof(from) - 1); fromcount = count; } /* * Also save the Sender: header as well */ if ((msgstate == RESENT) ? (hdr->set & MRSN) : (hdr->set & MSND)) { strncpy(sender, auxformat(mp, 0), sizeof(sender) - 1); sender[sizeof(sender) - 1] = '\0'; seensender++; } /* * ALSO ... save Envelope-From */ if (hdr->set & MEFM) { strncpy(efrom, auxformat(mp, 0), sizeof(efrom) - 1); efrom[sizeof(efrom) - 1] = '\0'; } if (hdr->flags & HBCC) mp->m_bcc++; if (mp->m_gname) putgrp (namep, mp->m_gname, out, hdr->flags); if (mp->m_ingrp) grp++; keep = putadr (namep, "", mp, out, hdr->flags, savehdr, savehdrlen); np = mp->m_next; if (keep) { mp->m_next = NULL; msgflags |= (hdr->set & (MVIS | MINV)); } else mnfree (mp); } /* * If it was a From header, strip off any trailing newlines from * the alias-expanded From line. */ if ((msgstate == RESENT) ? (hdr->set & MRFM) : (hdr->set & MFRM)) { while (*fullfrom && fullfrom[strlen(fullfrom) - 1] == '\n') { fullfrom[strlen(fullfrom) - 1] = '\0'; } } if (grp > 0 && (hdr->flags & HNGR)) { inform("%s: field does not allow groups", name); badmsg++; } if (linepos) { putc ('\n', out); } } static void start_headers (void) { time (&tclock); /* * Probably not necessary, but just in case ... */ from[0] = '\0'; efrom[0] = '\0'; sender[0] = '\0'; fullfrom[0] = '\0'; } /* * Now that we've outputted the header fields in the draft * message, we will now output any remaining header fields * that we need to add/create. */ static void finish_headers (FILE *out) { switch (msgstate) { case NORMAL: if (!(msgflags & MFRM)) { /* * A From: header is now required in the draft. */ inform("message has no From: header"); inform("See default components files for examples"); badmsg++; break; } if (fromcount > 1 && (seensender == 0 && !(msgflags & MEFM))) { inform("A Sender: or Envelope-From: header is required " "with multiple\nFrom: addresses"); badmsg++; break; } if (whomsw) break; fprintf (out, "Date: %s\n", dtime (&tclock, 0)); if (msgid) fprintf (out, "Message-ID: %s\n", message_id (tclock, 0)); /* * If we have multiple From: addresses, make sure we have an * Sender: header. If we don't have one, then generate one * from Envelope-From: (which in this case, cannot be blank) */ if (fromcount > 1 && seensender == 0) { if (efrom[0] == '\0') { inform("Envelope-From cannot be blank when there " "is multiple From: addresses\nand no Sender: " "header"); badmsg++; } else { fprintf (out, "Sender: %s\n", efrom); } } if (!(msgflags & MVIS)) fprintf (out, "Bcc: Blind Distribution List: ;\n"); break; case RESENT: if (!(msgflags & MDAT)) { inform("message has no Date: header"); badmsg++; } if (!(msgflags & MFRM)) { inform("message has no From: header"); badmsg++; } if (!(msgflags & MRFM)) { inform("message has no Resent-From: header"); inform("See default components files for examples"); badmsg++; break; } if (fromcount > 1 && (seensender == 0 && !(msgflags & MEFM))) { inform("A Resent-Sender: or Envelope-From: header is " "required with multiple\nResent-From: addresses"); badmsg++; break; } if (whomsw) break; fprintf (out, "Resent-Date: %s\n", dtime (&tclock, 0)); if (msgid) fprintf (out, "Resent-Message-ID: %s\n", message_id (tclock, 0)); /* * If we have multiple Resent-From: addresses, make sure we have an * Resent-Sender: header. If we don't have one, then generate one * from Envelope-From (which in this case, cannot be blank) */ if (fromcount > 1 && seensender == 0) { if (efrom[0] == '\0') { inform("Envelope-From cannot be blank when there " "is multiple Resent-From: addresses and no " "Resent-Sender: header"); badmsg++; } else { fprintf (out, "Resent-Sender: %s\n", efrom); } } if (!(msgflags & MVIS)) fprintf (out, "Resent-Bcc: Blind Re-Distribution List: ;\n"); break; } if (badmsg) adios (NULL, "re-format message and try again"); if (!recipients) adios (NULL, "no addressees"); } static int get_header (char *header, struct headers *table) { struct headers *h; for (h = table; h->value; h++) if (!strcasecmp (FENDNULL(header), FENDNULL(h->value))) return (h - table); return NOTOK; } static int putadr (char *name, char *aka, struct mailname *mp, FILE *out, unsigned int flags, char *savehdr, unsigned int savehdrsize) { int len, saveappend = 0; unsigned int shlen; char *cp; char buffer[BUFSIZ]; if (mp->m_mbox == NULL || ((flags & HTRY) && !insert (mp))) return 0; if (sm_mts != MTS_SENDMAIL_PIPE && ((flags & (HBCC | HDCC | HEFM)) || mp->m_ingrp)) return 1; if (!nameoutput) { fprintf (out, "%s: ", name); linepos += (nameoutput = strlen (name) + 2); } if (savehdr) { shlen = strlen(savehdr); saveappend = 1; } if (*aka && mp->m_type != UUCPHOST && !mp->m_pers) mp->m_pers = mh_xstrdup(aka); if (format) { if (mp->m_gname) { snprintf (buffer, sizeof(buffer), "%s;", mp->m_gname); cp = buffer; } else { cp = adrformat (mp); } } else { cp = mp->m_text; } len = strlen (cp); if (linepos != nameoutput) { if (len + linepos + 2 > outputlinelen) { fprintf (out, ",\n%*s", linepos = nameoutput, ""); if (saveappend) { if (shlen + 2 + nameoutput + len >= savehdrsize) { saveappend = 0; } else { snprintf(savehdr + shlen, savehdrsize - shlen, ",\n%*s", linepos, ""); } } } else { fputs (", ", out); linepos += 2; if (saveappend) { if (shlen + 2 + len >= savehdrsize) { saveappend = 0; } else { strncat(savehdr, ", ", savehdrsize - shlen); } } } } fputs (cp, out); if (saveappend && shlen + len < savehdrsize) strncat(savehdr, cp, savehdrsize - shlen + len); linepos += len; return (flags & HTRY); } static void putgrp (char *name, char *group, FILE *out, unsigned int flags) { int len; char *cp; if (sm_mts != MTS_SENDMAIL_PIPE && (flags & HBCC)) return; if (!nameoutput) { fprintf (out, "%s: ", name); linepos += (nameoutput = strlen (name) + 2); } cp = concat (group, ";", NULL); len = strlen (cp); if (linepos > nameoutput) { if (len + linepos + 2 > outputlinelen) { fprintf (out, ",\n%*s", nameoutput, ""); linepos = nameoutput; } else { fputs (", ", out); linepos += 2; } } fputs (cp, out); linepos += len; } static int insert (struct mailname *np) { struct mailname *mp; if (np->m_mbox == NULL) return 0; for (mp = np->m_type == LOCALHOST ? &localaddrs : np->m_type == UUCPHOST ? &uuaddrs : &netaddrs; mp->m_next; mp = mp->m_next) if (!strcasecmp (FENDNULL(np->m_host), FENDNULL(mp->m_next->m_host)) && !strcasecmp (FENDNULL(np->m_mbox), FENDNULL(mp->m_next->m_mbox)) && np->m_bcc == mp->m_next->m_bcc) return 0; mp->m_next = np; recipients++; return 1; } static void pl (void) { int i; struct mailname *mp; printf ("-------\n\t-- Addresses --\nlocal:\t"); for (mp = localaddrs.m_next; mp; mp = mp->m_next) printf ("%s%s%s", mp->m_mbox, mp->m_bcc ? "[BCC]" : "", mp->m_next ? ",\n\t" : ""); printf ("\nnet:\t"); for (mp = netaddrs.m_next; mp; mp = mp->m_next) printf ("%s%s@%s%s%s", FENDNULL(mp->m_path), mp->m_mbox, mp->m_host, mp->m_bcc ? "[BCC]" : "", mp->m_next ? ",\n\t" : ""); printf ("\nuucp:\t"); for (mp = uuaddrs.m_next; mp; mp = mp->m_next) printf ("%s!%s%s%s", mp->m_host, mp->m_mbox, mp->m_bcc ? "[BCC]" : "", mp->m_next ? ",\n\t" : ""); printf ("\n\t-- Folder Copies --\nfcc:\t"); for (i = 0; i < fccind; i++) printf ("%s%s", fccfold[i], i + 1 < fccind ? ",\n\t" : ""); putchar('\n'); } static void anno (void) { struct mailname *mp; for (mp = localaddrs.m_next; mp; mp = mp->m_next) if (annoaux (mp) == NOTOK) goto oops; for (mp = netaddrs.m_next; mp; mp = mp->m_next) if (annoaux (mp) == NOTOK) goto oops; for (mp = uuaddrs.m_next; mp; mp = mp->m_next) if (annoaux (mp) == NOTOK) break; oops: ; close (pfd); pfd = NOTOK; } static int annoaux (struct mailname *mp) { int i; char buffer[BUFSIZ]; snprintf (buffer, sizeof(buffer), "%s\n", adrformat (mp)); i = strlen (buffer); return (write (pfd, buffer, i) == i ? OK : NOTOK); } static void insert_fcc (struct headers *hdr, char *pp) { char *cp; for (cp = pp; isspace ((unsigned char) *cp); cp++) continue; for (pp += strlen (pp) - 1; pp > cp && isspace ((unsigned char) *pp); pp--) continue; if (pp >= cp) *++pp = 0; if (*cp == 0) return; if (fccind >= FCCS) adios (NULL, "too many %ss", hdr->value); fccfold[fccind++] = mh_xstrdup(cp); } /* * BCC GENERATION */ static void make_bcc_file (int dashstuff) { int fd, i; pid_t child_id; char **vec; FILE *out; char *tfile = NULL, *program; if ((tfile = m_mktemp2(NULL, "bccs", NULL, &out)) == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } strncpy (bccfil, tfile, sizeof(bccfil)); fprintf (out, "From: %s\n", fullfrom); fprintf (out, "Date: %s\n", dtime (&tclock, 0)); if (msgid) fprintf (out, "Message-ID: %s\n", message_id (tclock, 0)); if (subject) fprintf (out, "Subject: %s", subject); fprintf (out, "BCC:\n"); /* * Use MIME encapsulation for Bcc messages */ if (mime) { char *cp; /* * Check if any lines in the message clash with the * prefix for the MIME multipart separator. If there * is a clash, increment one of the letters in the * prefix and check again. */ if ((cp = strchr(prefix, 'a')) == NULL) adios (NULL, "lost prefix start"); while (find_prefix () == NOTOK) { if (*cp < 'z') (*cp)++; else if (*++cp == 0) adios (NULL, "can't find a unique delimiter string"); else (*cp)++; } fprintf (out, "%s: %s\n%s: multipart/digest; boundary=\"", VRSN_FIELD, VRSN_VALUE, TYPE_FIELD); fprintf (out, "%s\"\n\n--%s\n\n", prefix, prefix); } else { fprintf (out, "\n------- Blind-Carbon-Copy\n\n"); } fflush (out); /* * Do mhl filtering of Bcc messages instead * of MIME encapsulation. */ if (filter != NULL) { for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++) sleep (5); switch (child_id) { case NOTOK: adios ("fork", "unable to"); case OK: dup2 (fileno (out), 1); vec = argsplit(mhlproc, &program, &i); vec[i++] = "-forward"; vec[i++] = "-form"; vec[i++] = filter; vec[i++] = tmpfil; /* was the flag -[no]dashstuffing specified? */ if (dashstuff > 0) vec[i++] = "-dashstuffing"; else if (dashstuff < 0) vec[i++] = "-nodashstuffing"; vec[i] = NULL; execvp (program, vec); fprintf (stderr, "unable to exec "); perror (mhlproc); _exit (-1); default: pidXwait (child_id, mhlproc); break; } } else { if ((fd = open (tmpfil, O_RDONLY)) == NOTOK) adios (tmpfil, "unable to re-open"); /* * If using MIME encapsulation, or if the -nodashstuffing * flag was given, then just copy message. Else do * RFC934 quoting (dashstuffing). */ if (mime || dashstuff < 0) cpydata (fd, fileno (out), tmpfil, bccfil); else cpydgst (fd, fileno (out), tmpfil, bccfil); close (fd); } fseek (out, 0L, SEEK_END); if (mime) fprintf (out, "\n--%s--\n", prefix); else fprintf (out, "\n------- End of Blind-Carbon-Copy\n"); fclose (out); } /* * Scan message to check if any lines clash with * the prefix of the MIME multipart separator. */ static int find_prefix (void) { int result = OK; char buffer[BUFSIZ]; FILE *in; if ((in = fopen (tmpfil, "r")) == NULL) adios (tmpfil, "unable to re-open"); while (fgets (buffer, sizeof buffer, in)) if (buffer[0] == '-' && buffer[1] == '-') { char *cp; for (cp = buffer + strlen (buffer) - 1; cp >= buffer; cp--) if (!isspace ((unsigned char) *cp)) break; *++cp = '\0'; if (strcmp (buffer + 2, prefix) == 0) { result = NOTOK; break; } } fclose (in); return result; } static void chkadr (void) { if (badadr && unkadr) die (NULL, "%d address%s unparsable, %d addressee%s undeliverable", badadr, PLURALS(badadr), unkadr, PLURALS(badadr)); if (badadr) die (NULL, "%d address%s unparsable", badadr, PLURALS(badadr)); if (unkadr) die (NULL, "%d addressee%s undeliverable", unkadr, PLURALS(unkadr)); } static void do_addresses (int bccque, int talk) { int retval; int state; struct mailname *lp; state = 0; for (lp = localaddrs.m_next; lp; lp = lp->m_next) if (lp->m_bcc ? bccque : !bccque) { if (talk && !state) puts(" -- Local Recipients --"); do_an_address (lp, talk); state++; } state = 0; for (lp = uuaddrs.m_next; lp; lp = lp->m_next) if (lp->m_bcc ? bccque : !bccque) { if (talk && !state) puts(" -- UUCP Recipients --"); do_an_address (lp, talk); state++; } state = 0; for (lp = netaddrs.m_next; lp; lp = lp->m_next) if (lp->m_bcc ? bccque : !bccque) { if (talk && !state) puts(" -- Network Recipients --"); do_an_address (lp, talk); state++; } chkadr (); if (rp_isbad (retval = sm_waend ())) die (NULL, "problem ending addresses; %s", rp_string (retval)); } /* * MTS-SPECIFIC INTERACTION */ /* * SENDMAIL/SMTP routines */ static void post (char *file, int bccque, int talk, int eai, char *envelope, int oauth_flag, char *auth_svc) { int retval, i; pid_t child_id; if (verbose) { if (msgflags & MINV) printf (" -- Posting for %s Recipients --\n", bccque ? "Blind" : "Sighted"); else puts(" -- Posting for All Recipients --"); } sigon (); if (sm_mts == MTS_SENDMAIL_PIPE) { char **argp, *program; int argc; for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++) sleep (5); switch (child_id) { case NOTOK: adios ("fork", "unable to"); case OK: if (freopen( file, "r", stdin) == NULL) { adios (file, "can't reopen for sendmail"); } argp = argsplit(sendmail, &program, &argc); argp[argc++] = "-t"; /* read msg for recipients */ argp[argc++] = "-i"; /* don't stop on "." */ if (whomsw) argp[argc++] = "-bv"; if (snoop) argp[argc++] = "-v"; argp[argc] = NULL; execv (program, argp); adios (sendmail, "can't exec"); default: pidXwait (child_id, NULL); break; } } else { const int fd = open (file, O_RDONLY); int eightbit = 0; if (fd == NOTOK) { die (file, "unable to re-open"); } if (msgflags & MMIM && cte != UNKNOWN) { /* MIME message with C-T-E header. (BINARYMIME isn't supported, use 8BITMIME instead for binary.) */ eightbit = cte != SEVENBIT; } else { if (scan_input (fd, &eightbit) == NOTOK) { close (fd); die (file, "problem reading from"); } } if (rp_isbad (retval = sm_init (clientsw, serversw, port, watch, verbose, snoop, sasl, saslmech, user, oauth_flag ? auth_svc : NULL, tlsflag)) || rp_isbad (retval = sm_winit (envelope, eai, eightbit))) { close (fd); die (NULL, "problem initializing server; %s", rp_string (retval)); } do_addresses (bccque, talk && verbose); do_text (file, fd); close (fd); fflush (stdout); sm_end (!(msgflags & MINV) || bccque ? OK : DONE); sigoff (); if (verbose) { if (msgflags & MINV) printf (" -- %s Recipient Copies Posted --\n", bccque ? "Blind" : "Sighted"); else puts(" -- Recipient Copies Posted --"); } fflush (stdout); } } /* Address Verification */ static void verify_all_addresses (int talk, int eai, char *envelope, int oauth_flag, char *auth_svc) { int retval; struct mailname *lp; sigon (); if (!whomsw || checksw) { /* Not sending message body, so don't need to use 8BITMIME. */ const int eightbit = 0; if (rp_isbad (retval = sm_init (clientsw, serversw, port, watch, verbose, snoop, sasl, saslmech, user, oauth_flag ? auth_svc : NULL, tlsflag)) || rp_isbad (retval = sm_winit (envelope, eai, eightbit))) { die (NULL, "problem initializing server; %s", rp_string (retval)); } } if (talk && !whomsw) puts(" -- Address Verification --"); if (talk && localaddrs.m_next) puts(" -- Local Recipients --"); for (lp = localaddrs.m_next; lp; lp = lp->m_next) do_an_address (lp, talk); if (talk && uuaddrs.m_next) puts(" -- UUCP Recipients --"); for (lp = uuaddrs.m_next; lp; lp = lp->m_next) do_an_address (lp, talk); if (talk && netaddrs.m_next) puts(" -- Network Recipients --"); for (lp = netaddrs.m_next; lp; lp = lp->m_next) do_an_address (lp, talk); chkadr (); if (talk && !whomsw) puts(" -- Address Verification Successful --"); if (!whomsw || checksw) sm_end (whomsw ? OK : DONE); fflush (stdout); sigoff (); } static void do_an_address (struct mailname *lp, int talk) { int retval; char *mbox, *host; char addr[BUFSIZ]; switch (lp->m_type) { case LOCALHOST: mbox = lp->m_mbox; host = lp->m_host; strncpy (addr, mbox, sizeof(addr)); break; case UUCPHOST: mbox = auxformat (lp, 0); host = NULL; snprintf (addr, sizeof(addr), "%s!%s", lp->m_host, lp->m_mbox); break; default: /* let SendMail decide if the host is bad */ mbox = lp->m_mbox; host = lp->m_host; snprintf (addr, sizeof(addr), "%s at %s", mbox, host); break; } if (talk) printf (" %s%s", addr, whomsw && lp->m_bcc ? "[BCC]" : ""); if (whomsw && !checksw) { putchar ('\n'); return; } if (talk) printf (": "); fflush (stdout); switch (retval = sm_wadr (mbox, host, lp->m_type != UUCPHOST ? lp->m_path : NULL)) { case RP_OK: if (talk) puts("address ok"); break; case RP_NO: case RP_USER: if (!talk) fprintf (stderr, " %s: ", addr); fprintf (talk ? stdout : stderr, "loses; %s\n", rp_string (retval)); unkadr++; break; default: if (!talk) fprintf (stderr, " %s: ", addr); die (NULL, "unexpected response; %s", rp_string (retval)); } fflush (stdout); } static void do_text (char *file, int fd) { int retval, state; char buf[BUFSIZ]; lseek(fd, 0, SEEK_SET); while ((state = read (fd, buf, sizeof(buf))) > 0) { if (rp_isbad (retval = sm_wtxt (buf, state))) die (NULL, "problem writing text; %s\n", rp_string (retval)); } if (state == NOTOK) die (file, "problem reading from"); switch (retval = sm_wtend ()) { case RP_OK: break; case RP_NO: case RP_NDEL: die (NULL, "posting failed; %s", rp_string (retval)); break; default: die (NULL, "unexpected response; %s", rp_string (retval)); } } /* * SIGNAL HANDLING */ static void sigser (int i) { NMH_UNUSED (i); (void) m_unlink (tmpfil); if (msgflags & MINV) (void) m_unlink (bccfil); if (!whomsw || checksw) sm_end (NOTOK); done (1); } static void sigon (void) { if (debug) return; hstat = SIGNAL2 (SIGHUP, sigser); istat = SIGNAL2 (SIGINT, sigser); qstat = SIGNAL2 (SIGQUIT, sigser); tstat = SIGNAL2 (SIGTERM, sigser); } static void sigoff (void) { if (debug) return; SIGNAL (SIGHUP, hstat); SIGNAL (SIGINT, istat); SIGNAL (SIGQUIT, qstat); SIGNAL (SIGTERM, tstat); } /* * FCC INTERACTION */ static void p_refile (char *file) { int i; if (fccind == 0) return; if (verbose) puts(" -- Filing Folder Copies --"); for (i = 0; i < fccind; i++) fcc (file, fccfold[i]); if (verbose) puts(" -- Folder Copies Filed --"); } /* * Call the `fileproc' to add the file to the folder. */ static void fcc (char *file, char *folder) { pid_t child_id; int i, status, argp; char fold[BUFSIZ]; char **arglist, *program; if (verbose) printf (" %sFcc %s: ", msgstate == RESENT ? "Resent-" : "", folder); fflush (stdout); for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++) sleep (5); switch (child_id) { case NOTOK: if (!verbose) fprintf (stderr, " %sFcc %s: ", msgstate == RESENT ? "Resent-" : "", folder); fprintf (verbose ? stdout : stderr, "no forks, so not ok\n"); break; case OK: /* see if we need to add `+' */ snprintf (fold, sizeof(fold), "%s%s", *folder == '+' || *folder == '@' ? "" : "+", folder); /* now exec the fileproc */ 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: if ((status = pidwait (child_id, OK))) { if (!verbose) fprintf (stderr, " %sFcc %s: ", msgstate == RESENT ? "Resent-" : "", folder); pidstatus (status, verbose ? stdout : stderr, fileproc); } else { if (verbose) puts("folder ok"); } } fflush (stdout); } /* * TERMINATION */ static void die (char *what, char *fmt, ...) { int err; va_list ap; err = errno; (void) m_unlink (tmpfil); if (msgflags & MINV) (void) m_unlink (bccfil); if (!whomsw || checksw) sm_end (NOTOK); va_start(ap, fmt); errno = err; advertise (what, NULL, fmt, ap); va_end(ap); done (1); } nmh-1.7.1-RC3/uip/prompter.c000644 007761 000024 00000020033 13243042054 015566 0ustar00kenhstaff000000 000000 /* prompter.c -- simple prompting editor front-end * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include "../sbr/m_mktemp.h" #include #include #define QUOTE '\\' #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; static int wtuser = 0; static int sigint = 0; static jmp_buf sigenv; /* * prototypes */ static int getln (char *, int); static int chrcnv (char *); static void chrdsp (char *, char); static void intrser (int); int main (int argc, char **argv) { int body = 1, prepend = 1, rapid = 0; int doteof = 0, fdi, fdo, i, state; char *cp, *drft = NULL, *erasep = NULL; char *killp = NULL, name[NAMESZ], field[NMH_BUFSIZ]; char buffer[BUFSIZ]; char **arguments, **argp; FILE *in, *out; char *tmpfil; m_getfld_state_t gstate = 0; if (nmh_init(argv[0], 2)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; while ((cp = *argp++)) if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buffer, sizeof(buffer), "%s [switches] file", invo_name); print_help (buffer, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case ERASESW: if (!(erasep = *argp++) || *erasep == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case KILLSW: if (!(killp = *argp++) || *killp == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case PREPSW: prepend++; continue; case NPREPSW: prepend = 0; continue; case RAPDSW: rapid++; continue; case NRAPDSW: rapid = 0; continue; case BODYSW: body++; continue; case NBODYSW: body = 0; continue; case DOTSW: doteof++; continue; case NDOTSW: doteof = 0; continue; } } else { if (!drft) drft = cp; } if (!drft) adios (NULL, "usage: %s [switches] file", invo_name); if ((in = fopen (drft, "r")) == NULL) adios (drft, "unable to open"); if ((tmpfil = m_mktemp2(NULL, invo_name, NULL, &out)) == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } /* * Are we changing the kill or erase character? */ if (killp || erasep) { cc_t save_erase, save_kill; /* get the current terminal attributes */ tcgetattr(0, &tio); /* save original kill, erase character for later */ save_kill = tio.c_cc[VKILL]; save_erase = tio.c_cc[VERASE]; /* set new kill, erase character in terminal structure */ tio.c_cc[VKILL] = killp ? chrcnv (killp) : save_kill; tio.c_cc[VERASE] = erasep ? chrcnv (erasep) : save_erase; /* set the new terminal attributes */ tcsetattr(0, TCSADRAIN, &tio); /* print out new kill erase characters */ chrdsp ("erase", tio.c_cc[VERASE]); chrdsp (", kill", tio.c_cc[VKILL]); chrdsp (", intr", tio.c_cc[VINTR]); putchar ('\n'); fflush (stdout); /* * We set the kill and erase character back to original * setup in terminal structure so we can easily * restore it upon exit. */ tio.c_cc[VKILL] = save_kill; tio.c_cc[VERASE] = save_erase; } sigint = 0; SIGNAL2 (SIGINT, intrser); /* * Loop through the lines of the draft skeleton. */ for (;;) { int fieldsz = sizeof field; switch (state = m_getfld (&gstate, name, field, &fieldsz, in)) { case FLD: case FLDPLUS: /* * Check if the value of field contains anything * other than space or tab. */ for (cp = field; *cp; cp++) if (*cp != ' ' && *cp != '\t') break; /* If so, just add header line to draft */ if (*cp++ != '\n' || *cp != 0) { printf ("%s:%s", name, field); fprintf (out, "%s:%s", name, field); while (state == FLDPLUS) { fieldsz = sizeof field; state = m_getfld (&gstate, name, field, &fieldsz, in); fputs(field, stdout); fputs(field, out); } } else { /* Else, get value of header field */ printf ("%s: ", name); fflush (stdout); i = getln (field, sizeof(field)); if (i == -1) { abort: if (killp || erasep) { tcsetattr(0, TCSADRAIN, &tio); } (void) m_unlink (tmpfil); done (1); } if (i != 0 || (field[0] != '\n' && field[0] != 0)) { fprintf (out, "%s:", name); do { if (field[0] != ' ' && field[0] != '\t') putc (' ', out); fputs(field, out); } while (i == 1 && (i = getln (field, sizeof(field))) >= 0); if (i == -1) goto abort; } } continue; case BODY: case FILEEOF: if (!body) break; fprintf (out, "--------\n"); if (field[0] == 0 || !prepend) puts("--------"); if (field[0]) { if (prepend && body) { printf ("\n--------Enter initial text\n\n"); fflush (stdout); for (;;) { getln (buffer, sizeof(buffer)); if (doteof && buffer[0] == '.' && buffer[1] == '\n') break; if (buffer[0] == 0) break; fputs(buffer, out); } } do { fputs(field, out); if (!rapid && !sigint) fputs(field, stdout); } while (state == BODY && (fieldsz = sizeof field, state = m_getfld (&gstate, name, field, &fieldsz, in))); if (prepend || !body) break; else printf ("\n--------Enter additional text\n\n"); } fflush (stdout); for (;;) { getln (field, sizeof(field)); if (doteof && field[0] == '.' && field[1] == '\n') break; if (field[0] == 0) break; fputs(field, out); } break; default: adios (NULL, "skeleton is poorly formatted"); } break; } m_getfld_state_destroy (&gstate); if (body) puts("--------"); fflush (stdout); fclose (in); fclose (out); SIGNAL (SIGINT, SIG_IGN); if (killp || erasep) { tcsetattr(0, TCSADRAIN, &tio); } if ((fdi = open (tmpfil, O_RDONLY)) == NOTOK) adios (tmpfil, "unable to re-open"); if ((fdo = creat (drft, m_gmprot ())) == NOTOK) adios (drft, "unable to write"); cpydata (fdi, fdo, tmpfil, drft); close (fdi); close (fdo); (void) m_unlink (tmpfil); context_save (); /* save the context file */ done (0); return 1; } static int getln (char *buffer, int n) { int c; char *cp; static int quoting = 0; *buffer = 0; switch (setjmp (sigenv)) { case OK: wtuser = 1; break; case DONE: wtuser = 0; return 0; default: wtuser = 0; return NOTOK; } cp = buffer; *cp = 0; for (;;) { switch (c = getchar ()) { case EOF: quoting = 0; clearerr (stdin); longjmp (sigenv, DONE); case '\n': if (quoting) { *(cp - 1) = c; quoting = 0; wtuser = 0; return 1; } *cp++ = c; *cp = 0; wtuser = 0; return 0; default: if (c == QUOTE) { quoting = 1; } else { quoting = 0; } if (cp < buffer + n) *cp++ = c; *cp = 0; } } } static void intrser (int i) { NMH_UNUSED (i); if (wtuser) longjmp (sigenv, NOTOK); sigint++; } static int chrcnv (char *cp) { return (*cp != QUOTE ? *cp : m_atoi (++cp)); } static void chrdsp (char *s, char c) { printf ("%s ", s); if (c < ' ' || c == 0177) printf ("^%c", c ^ 0100); else printf ("%c", c); } nmh-1.7.1-RC3/uip/rcvdist.c000644 007761 000024 00000017556 13243042054 015414 0ustar00kenhstaff000000 000000 /* rcvdist.c -- asynchronously redistribute messages * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #include "../sbr/m_mktemp.h" #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 #ifndef CYRUS_SASL # define SASLminc(a) (a) #else /* CYRUS_SASL */ # define SASLminc(a) 0 #endif /* CYRUS_SASL */ #ifndef OAUTH_SUPPORT # define OAUTHminc(a) (a) #else /* OAUTH_SUPPORT */ # define OAUTHminc(a) 0 #endif /* OAUTH_SUPPORT */ /* These are just the post(1) switches that take an argument. */ #define POST_SWITCHES \ X("alias aliasfile", 0, ALIASW) \ X("filter filterfile", 0, FILTSW) \ X("library directory", -7, LIBSW) /* interface from send, whom */ \ X("width columns", 0, WIDTHSW) \ X("idanno number", -6, ANNOSW) /* interface from send */ \ X("client host", -6, CLIESW) \ X("server host", 6, SERVSW) /* specify alternate SMTP server */ \ X("partno", -6, PARTSW) \ X("saslmech", SASLminc(5), SASLMECHSW) \ X("user", SASLminc(-4), USERSW) \ X("port server submission port name/number", 4, PORTSW) \ X("fileproc", -4, FILEPROCSW) \ X("mhlproc", -3, MHLPROCSW) \ X("sendmail program", 0, MTSSM) \ X("mts smtp|sendmail/smtp|sendmail/pipe", 2, MTSSW) \ X("credentials legacy|file:filename", 0, CREDENTIALSSW) \ X("messageid localname|random", 2, MESSAGEIDSW) \ X("authservice auth-service-name", OAUTHminc(-11), AUTHSERVICESW) \ X("oauthcredfile credential-file", OAUTHminc(-7), OAUTHCREDFILESW) \ X("oauthclientid client-id", OAUTHminc(-12), OAUTHCLIDSW) \ X("oauthclientsecret client-secret", OAUTHminc(-12), OAUTHCLSECSW) \ X("oauthauthendpoint authentication-endpoint", OAUTHminc(-6), OAUTHAUTHENDSW) \ X("oauthredirect redirect-uri", OAUTHminc(-6), OAUTHREDIRSW) \ X("oauthtokenendpoint token-endpoint", OAUTHminc(-6), OAUTHTOKENDSW) \ X("oauthscope scope", OAUTHminc(-6), OAUTHSCOPESW) \ #define X(sw, minchars, id) id, DEFINE_SWITCH_ENUM(POST); #undef X #define X(sw, minchars, id) { sw, minchars, id }, DEFINE_SWITCH_ARRAY(POST, post_switches_with_args); #undef X static char backup[BUFSIZ] = ""; static char drft[BUFSIZ] = ""; static char tmpfil[BUFSIZ] = ""; /* * prototypes */ static void rcvdistout (FILE *, char *, char *); static void unlink_done (int) NORETURN; int main (int argc, char **argv) { pid_t child_id; int i, vecp; char *addrs = NULL, *cp, *form = NULL, buf[BUFSIZ], *program; char **argp, **arguments, **vec; FILE *fp; char *tfile = NULL; if (nmh_init(argv[0], 2)) { return 1; } done=unlink_done; /* * Configure this now, since any unknown switches to rcvdist get * sent to postproc */ vec = argsplit(postproc, &program, &vecp); mts_init (); arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: { const int argno = smatch(cp, post_switches_with_args); vec[vecp++] = --cp; if (argno != AMBIGSW && argno != UNKWNSW) { /* It's a post switch that does take an argument. */ if (!(cp = *argp) || *cp == '-') { adios(NULL, "missing argument to %s", argp[-1]); } vec[vecp++] = cp; ++argp; } continue; } case HELPSW: snprintf (buf, sizeof(buf), "%s [switches] [switches for postproc] address ...", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case FORMSW: if (!(form = *argp++) || *form == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; } } addrs = addrs ? add (cp, add (", ", addrs)) : mh_xstrdup(cp); } if (addrs == NULL) adios (NULL, "usage: %s [switches] [switches for postproc] address ...", invo_name); umask (~m_gmprot ()); if ((tfile = m_mktemp2(NULL, invo_name, NULL, &fp)) == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } strncpy (tmpfil, tfile, sizeof(tmpfil)); cpydata (fileno (stdin), fileno (fp), "message", tmpfil); fseek (fp, 0L, SEEK_SET); if ((tfile = m_mktemp2(NULL, invo_name, NULL, NULL)) == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } strncpy (drft, tfile, sizeof(tmpfil)); rcvdistout (fp, form, addrs); fclose (fp); if (distout (drft, tmpfil, backup) == NOTOK) done (1); vec[vecp++] = "-dist"; if ((cp = context_find ("mhlproc"))) { vec[vecp++] = "-mhlproc"; vec[vecp++] = cp; } vec[vecp++] = drft; vec[vecp] = NULL; for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++) sleep (5); switch (child_id) { case NOTOK: inform("unable to fork, continuing..."); /* FALLTHRU */ case OK: execvp (program, vec); fprintf (stderr, "unable to exec "); perror (postproc); _exit (1); default: done (pidXwait(child_id, postproc)); } return 0; /* dead code to satisfy the compiler */ } /* very similar to routine in replsbr.c */ static int outputlinelen = OUTPUTLINELEN; static struct format *fmt; static int dat[5]; static char *addrcomps[] = { "from", "sender", "reply-to", "to", "cc", "bcc", "resent-from", "resent-sender", "resent-reply-to", "resent-to", "resent-cc", "resent-bcc", NULL }; static void rcvdistout (FILE *inb, char *form, char *addrs) { int char_read = 0, format_len, i, state; char **ap; char *cp, name[NAMESZ], tmpbuf[NMH_BUFSIZ]; charstring_t scanl; struct comp *cptr; FILE *out; m_getfld_state_t gstate = 0; if (!(out = fopen (drft, "w"))) adios (drft, "unable to create"); /* get new format string */ cp = new_fs (form ? form : rcvdistcomps, NULL, NULL); format_len = strlen (cp); fmt_compile (cp, &fmt, 1); for (ap = addrcomps; *ap; ap++) { cptr = fmt_findcomp (*ap); if (cptr) cptr->c_type |= CT_ADDR; } cptr = fmt_findcomp ("addresses"); if (cptr) cptr->c_text = addrs; for (;;) { int msg_count = sizeof tmpbuf; 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) { 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) { msg_count = sizeof tmpbuf; state = m_getfld (&gstate, name, tmpbuf, &msg_count, inb); } break; case LENERR: case FMTERR: case BODY: case FILEEOF: goto finished; default: adios (NULL, "m_getfld() returned %d", state); } } finished: ; m_getfld_state_destroy (&gstate); i = format_len + char_read + 256; scanl = charstring_create (i + 2); dat[0] = dat[1] = dat[2] = dat[4] = 0; dat[3] = outputlinelen; fmt_scan (fmt, scanl, i, dat, NULL); fputs (charstring_buffer (scanl), out); if (ferror (out)) adios (drft, "error writing"); fclose (out); charstring_free (scanl); fmt_free(fmt, 1); } static void NORETURN unlink_done (int status) { if (backup[0]) (void) m_unlink (backup); if (drft[0]) (void) m_unlink (drft); if (tmpfil[0]) (void) m_unlink (tmpfil); exit (status ? RCV_MBX : RCV_MOK); } nmh-1.7.1-RC3/uip/rcvpack.c000644 007761 000024 00000004163 13243042054 015355 0ustar00kenhstaff000000 000000 /* rcvpack.c -- append message to a file * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #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 */ static int mbx_style = MBOX_FORMAT; int main (int argc, char **argv) { int md; char *cp, *file = NULL, buf[BUFSIZ]; char **argp, **arguments; if (nmh_init(argv[0], 2)) { return 1; } mts_init (); arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; /* parse arguments */ while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [switches] file", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case MBOXSW: mbx_style = MBOX_FORMAT; continue; case MMDFSW: mbx_style = MMDF_FORMAT; continue; } } if (file) adios (NULL, "only one file at a time!"); else file = cp; } if (!file) adios (NULL, "%s [switches] file", invo_name); rewind (stdin); /* open and lock the file */ if ((md = mbx_open (file, mbx_style, getuid(), getgid(), m_gmprot())) == NOTOK) done (RCV_MBX); /* append the message */ if (mbx_copy (file, mbx_style, md, fileno(stdin), NULL) == NOTOK) { mbx_close (file, md); done (RCV_MBX); } /* close and unlock the file */ if (mbx_close (file, md) == NOTOK) done (RCV_MBX); done (RCV_MOK); return 1; } nmh-1.7.1-RC3/uip/rcvstore.c000644 007761 000024 00000012547 13243042054 015600 0ustar00kenhstaff000000 000000 /* rcvstore.c -- asynchronously add mail to a folder * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include "../sbr/m_maildir.h" #include "../sbr/m_mktemp.h" #include "../sbr/makedir.h" #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 /* * name of temporary file to store incoming message */ static char *tmpfilenam = NULL; static void unlink_done(int) NORETURN; int main (int argc, char **argv) { int publicsw = -1, zerosw = 0; int create = 1, unseensw = 1; int fd, msgnum; size_t seqp = 0; char *cp, *maildir, *folder = NULL, buf[BUFSIZ]; char **argp, **arguments; svector_t seqs = svector_create (0); struct msgs *mp; struct stat st; if (nmh_init(argv[0], 2)) { return 1; } done=unlink_done; mts_init (); arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; /* parse arguments */ while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [+folder] [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case SEQSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument name to %s", argp[-2]); svector_push_back (seqs, cp); seqp++; continue; case UNSEENSW: unseensw = 1; continue; case NUNSEENSW: unseensw = 0; continue; case PUBSW: publicsw = 1; continue; case NPUBSW: publicsw = 0; continue; case ZEROSW: zerosw++; continue; case NZEROSW: zerosw = 0; continue; case CRETSW: create++; continue; case NCRETSW: create = 0; continue; } } if (*cp == '+' || *cp == '@') { if (folder) adios (NULL, "only one folder at a time!"); else folder = pluspath (cp); } else { adios (NULL, "usage: %s [+folder] [switches]", invo_name); } } if (!context_find ("path")) free (path ("./", TFOLDER)); /* if no folder is given, use default folder */ if (!folder) folder = getfolder (0); maildir = m_maildir (folder); /* check if folder exists */ if (stat (maildir, &st) == NOTOK) { if (errno != ENOENT) adios (maildir, "error on folder"); if (!create) adios (NULL, "folder %s doesn't exist", maildir); if (!makedir (maildir)) adios (NULL, "unable to create folder %s", maildir); } if (chdir (maildir) == NOTOK) adios (maildir, "unable to change directory to"); /* ignore a few signals */ SIGNAL (SIGHUP, SIG_IGN); SIGNAL (SIGINT, SIG_IGN); SIGNAL (SIGQUIT, SIG_IGN); SIGNAL (SIGTERM, SIG_IGN); /* create a temporary file */ tmpfilenam = m_mktemp (invo_name, &fd, NULL); if (tmpfilenam == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } chmod (tmpfilenam, m_gmprot()); /* copy the message from stdin into temp file */ cpydata (fileno (stdin), fd, "standard input", tmpfilenam); if (fstat (fd, &st) == NOTOK) { (void) m_unlink (tmpfilenam); adios (tmpfilenam, "unable to fstat"); } if (close (fd) == NOTOK) adios (tmpfilenam, "error closing"); /* don't add file if it is empty */ if (st.st_size == 0) { (void) m_unlink (tmpfilenam); inform("empty file"); done (0); } /* * read folder and create message structure */ if (!(mp = folder_read (folder, 1))) adios (NULL, "unable to read folder %s", folder); /* * Link message into folder, and possibly add * to the Unseen-Sequence's. */ if ((msgnum = folder_addmsg (&mp, tmpfilenam, 0, unseensw, 0, 0, NULL)) == -1) done (1); /* * Add the message to any extra sequences * that have been specified. */ if (seqp) { /* The only reason that seqp was checked to be non-zero is in case a -nosequence switch is added. */ for (seqp = 0; seqp < svector_size (seqs); seqp++) { if (!seq_addmsg (mp, svector_at (seqs, seqp), msgnum, publicsw, zerosw)) done (1); } } svector_free (seqs); seq_setunseen (mp, 0); /* synchronize any Unseen-Sequence's */ seq_save (mp); /* synchronize and save message sequences */ folder_free (mp); /* free folder/message structure */ context_save (); /* save the global context file */ (void) m_unlink (tmpfilenam); /* remove temporary file */ tmpfilenam = NULL; done (0); return 1; } /* * Clean up and exit */ static void NORETURN unlink_done(int status) { if (tmpfilenam && *tmpfilenam) (void) m_unlink (tmpfilenam); exit (status); } nmh-1.7.1-RC3/uip/rcvtty.c000644 007761 000024 00000016371 13243042054 015263 0ustar00kenhstaff000000 000000 /* rcvtty.c -- a rcvmail program (a lot like rcvalert) handling IPC ttys * * 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. */ /* Changed to use getutent() and friends. Assumes that when getutent() exists, * a number of other things also exist. Please check. * Ruud de Rooij Sun, 28 May 2000 17:28:55 +0200 */ #include #include #include #include #include #include #include #include #include "../sbr/m_mktemp.h" #include #ifdef HAVE_GETUTXENT #include #endif /* HAVE_GETUTXENT */ #define SCANFMT \ "%2(hour{dtimenow}):%02(min{dtimenow}): %<(size)%5(size) %>%<{encrypted}E%>\ %<(mymbox{from})%<{to}To:%14(friendly{to})%>%>%<(zero)%17(friendly{from})%> \ %{subject}%<{body}<<%{body}>>%>" #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; static int newline = 1; static int biff = 0; static int width = -1; static char *form = NULL; static char *format = NULL; /* * external prototypes */ char *getusername(void); /* * static prototypes */ static void alrmser (int); static int message_fd (char **); static int header_fd (void); #if HAVE_GETUTXENT static void alert (char *, int); #endif /* HAVE_GETUTXENT */ int main (int argc, char **argv) { int md, vecp = 0; char *cp, *user, buf[BUFSIZ], tty[BUFSIZ]; char **argp, **arguments, *vec[MAXARGS]; struct utmpx *utp; if (nmh_init(argv[0], 2)) { return 1; } mts_init (); arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: vec[vecp++] = --cp; continue; case HELPSW: snprintf (buf, sizeof(buf), "%s [command ...]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case BIFFSW: biff = 1; continue; case FORMSW: if (!(form = *argp++) || *form == '-') adios (NULL, "missing argument to %s", argp[-2]); format = NULL; continue; case FMTSW: if (!(format = *argp++) || *format == '-') adios (NULL, "missing argument to %s", argp[-2]); form = NULL; continue; case WIDTHSW: if (!(cp = *argp++) || *cp == '-') adios(NULL, "missing argument to %s", argp[-2]); width = atoi(cp); continue; case NLSW: newline = 1; continue; case NNLSW: newline = 0; continue; case BELSW: bell = 1; continue; case NBELSW: bell = 0; continue; } } vec[vecp++] = cp; } vec[vecp] = 0; if ((md = vecp ? message_fd (vec) : header_fd ()) == NOTOK) exit (RCV_MBX); user = getusername(); #if HAVE_GETUTXENT setutxent(); while ((utp = getutxent()) != NULL) { if (utp->ut_type == USER_PROCESS && utp->ut_user[0] != 0 && utp->ut_line[0] != 0 && strncmp (user, utp->ut_user, sizeof(utp->ut_user)) == 0) { strncpy (tty, utp->ut_line, sizeof(utp->ut_line)); alert (tty, md); } } endutxent(); #else NMH_UNUSED (tty); NMH_UNUSED (utp); #endif /* HAVE_GETUTXENT */ exit (RCV_MOK); } static void alrmser (int i) { NMH_UNUSED (i); longjmp (myctx, 1); } static int message_fd (char **vec) { pid_t child_id; int bytes, seconds; int fd; char *tfile; struct stat st; if ((tfile = m_mktemp2(NULL, invo_name, &fd, NULL)) == NULL) { inform("unable to create temporary file in %s", get_temp_dir()); return NOTOK; } (void) m_unlink(tfile); /* Use fd, no longer need the file name. */ if ((child_id = fork()) == NOTOK) { /* fork error */ close (fd); return header_fd (); } if (child_id) { /* parent process */ if (!setjmp (myctx)) { SIGNAL (SIGALRM, alrmser); bytes = fstat(fileno (stdin), &st) != NOTOK ? (int) st.st_size : 100; /* amount of time to wait depends on message size */ if (bytes <= 100) { /* give at least 5 minutes */ seconds = 300; } else if (bytes >= 90000) { /* but 30 minutes should be long enough */ seconds = 1800; } else { seconds = (bytes / 60) + 300; } alarm ((unsigned int) seconds); pidwait(child_id, OK); alarm (0); if (fstat (fd, &st) != NOTOK && st.st_size > 0) return fd; } else { /* * Ruthlessly kill the child and anything * else in its process group. */ killpg(child_id, SIGKILL); } close (fd); return header_fd (); } /* child process */ rewind (stdin); if (dup2 (fd, 1) == NOTOK || dup2 (fd, 2) == NOTOK) _exit (-1); closefds (3); setpgid ((pid_t) 0, getpid ()); /* put in own process group */ if (execvp (vec[0], vec) == NOTOK) { _exit (-1); } return NOTOK; } static int header_fd (void) { int fd; char *nfs; char *tfile = NULL; charstring_t scanl = NULL; if ((tfile = m_mktemp2(NULL, invo_name, &fd, NULL)) == NULL) { inform("unable to create temporary file in %s", get_temp_dir()); return NOTOK; } (void) m_unlink(tfile); /* Use fd, no longer need the file name. */ rewind (stdin); /* get new format string */ nfs = new_fs (form, format, SCANFMT); scan (stdin, 0, 0, nfs, width, 0, 0, NULL, 0L, 0, &scanl); scan_finished (); if (newline) { if (write (fd, "\n\r", 2) < 0) { advise (tfile, "write LF/CR"); } } if (write (fd, charstring_buffer (scanl), charstring_bytes (scanl)) < 0) { advise (tfile, "write"); } charstring_free (scanl); if (bell) { if (write (fd, "\007", 1) < 0) { advise (tfile, "write BEL"); } } return fd; } #if HAVE_GETUTXENT static void alert (char *tty, int md) { int i, td, mask; char buffer[BUFSIZ], ttyspec[BUFSIZ]; struct stat st; snprintf (ttyspec, sizeof(ttyspec), "/dev/%s", tty); /* * The mask depends on whether we are checking for * write permission based on `biff' or `mesg'. */ mask = biff ? S_IEXEC : (S_IWRITE >> 3); if (stat (ttyspec, &st) == NOTOK || (st.st_mode & mask) == 0) return; if (!setjmp (myctx)) { SIGNAL (SIGALRM, alrmser); alarm (2); td = open (ttyspec, O_WRONLY); alarm (0); if (td == NOTOK) return; } else { alarm (0); return; } lseek(md, 0, SEEK_SET); while ((i = read (md, buffer, sizeof(buffer))) > 0) if (write (td, buffer, i) != i) break; close (td); } #endif /* HAVE_GETUTXENT */ nmh-1.7.1-RC3/uip/refile.c000644 007761 000024 00000025114 13243042054 015171 0ustar00kenhstaff000000 000000 /* refile.c -- move or link message(s) from a source folder * -- into one or more destination folders * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include "../sbr/m_maildir.h" #include "../sbr/m_mktemp.h" #include #define REFILE_SWITCHES \ X("draft", 0, DRAFTSW) \ X("link", 0, LINKSW) \ X("nolink", 0, NLINKSW) \ X("preserve", 0, PRESSW) \ X("nopreserve", 0, NPRESSW) \ X("retainsequences", 0, RETAINSEQSSW) \ X("noretainsequences", 0, NRETAINSEQSSW) \ 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]; struct st_fold { char *f_name; struct msgs *f_mp; }; /* * static prototypes */ static void opnfolds (struct msgs *, struct st_fold *, int); static void clsfolds (struct st_fold *, int); static void remove_files (int, char **); static int m_file (struct msgs *, char *, int, struct st_fold *, int, int, int); static void copy_seqs (struct msgs *, int, struct msgs *, int); int main (int argc, char **argv) { int linkf = 0, preserve = 0, retainseqs = 0, filep = 0; int foldp = 0, isdf = 0, unlink_msgs = 0; int i, msgnum; char *cp, *folder = NULL, buf[BUFSIZ]; char **argp, **arguments; char *filevec[NFOLDERS + 2]; char **files = &filevec[1]; /* leave room for remove_files:vec[0] */ struct st_fold folders[NFOLDERS + 1]; struct msgs_array msgs = { 0, 0, NULL }; struct msgs *mp; if (nmh_init(argv[0], 1)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; /* * Parse arguments */ while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown\n", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [msgs] [switches] +folder ...", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case LINKSW: linkf++; continue; case NLINKSW: linkf = 0; continue; case PRESSW: preserve++; continue; case NPRESSW: preserve = 0; continue; case RETAINSEQSSW: retainseqs = 1; continue; case NRETAINSEQSSW: retainseqs = 0; continue; case UNLINKSW: unlink_msgs++; continue; case NUNLINKSW: unlink_msgs = 0; continue; case SRCSW: if (folder) adios (NULL, "only one source folder at a time!"); if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); folder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp, *cp != '@' ? TFOLDER : TSUBCWF); continue; case DRAFTSW: if (filep > NFOLDERS) adios (NULL, "only %d files allowed!", NFOLDERS); isdf = 0; files[filep++] = getcpy (m_draft (NULL, NULL, 1, &isdf)); continue; case FILESW: if (filep > NFOLDERS) adios (NULL, "only %d files allowed!", NFOLDERS); if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); files[filep++] = path (cp, TFILE); continue; case RPROCSW: if (!(rmmproc = *argp++) || *rmmproc == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case NRPRCSW: rmmproc = NULL; continue; } } if (*cp == '+' || *cp == '@') { if (foldp > NFOLDERS) adios (NULL, "only %d folders allowed!", NFOLDERS); folders[foldp++].f_name = pluspath (cp); } else app_msgarg(&msgs, cp); } if (!context_find ("path")) free (path ("./", TFOLDER)); if (foldp == 0) adios (NULL, "no folder specified"); /* * We are refiling a file to the folders */ if (filep > 0) { if (folder || msgs.size) adios (NULL, "use -file or some messages, not both"); opnfolds (NULL, folders, foldp); for (i = 0; i < filep; i++) if (m_file (0, files[i], 0, folders, foldp, preserve, 0)) done (1); /* If -nolink, then "remove" files */ if (!linkf) remove_files (filep, filevec); done (0); } if (!msgs.size) app_msgarg(&msgs, "cur"); if (!folder) folder = getfolder (1); strncpy (maildir, m_maildir (folder), sizeof(maildir)); if (chdir (maildir) == NOTOK) adios (maildir, "unable to change directory to"); /* read source folder and create message structure */ if (!(mp = folder_read (folder, 1))) adios (NULL, "unable to read folder %s", folder); /* check for empty folder */ if (mp->nummsg == 0) adios (NULL, "no messages in %s", folder); /* parse the message range/sequence/name and set SELECTED */ for (msgnum = 0; msgnum < msgs.size; msgnum++) if (!m_convert (mp, msgs.msgs[msgnum])) done (1); seq_setprev (mp); /* set the previous-sequence */ /* create folder structures for each destination folder */ opnfolds (mp, folders, foldp); /* Link all the selected messages into destination folders. * * This causes the add hook to be run for messages that are * linked into another folder. The refile hook is run for * messages that are moved to another folder. */ for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { if (is_selected (mp, msgnum)) { cp = mh_xstrdup(m_name (msgnum)); if (m_file (mp, cp, retainseqs ? msgnum : 0, folders, foldp, preserve, !linkf)) done (1); free (cp); } } /* * Update this now, since folder_delmsgs() will save the context * but doesn't have access to the folder name. */ context_replace (pfolder, folder); /* update current folder */ /* * Adjust "cur" if necessary */ if (mp->hghsel != mp->curmsg && (mp->numsel != mp->nummsg || linkf)) seq_setcur (mp, mp->hghsel); /* * Close destination folders now; if we are using private sequences * we need to have all of our calls to seq_save() complete before we * call context_save(). */ clsfolds (folders, foldp); /* If -nolink, then "remove" messages from source folder. * * Note that folder_delmsgs does not call the delete hook * because the message has already been handled above. */ if (!linkf) { folder_delmsgs (mp, unlink_msgs, 1); } else { seq_save (mp); /* synchronize message sequences */ context_save (); /* save the context file */ } folder_free (mp); /* free folder structure */ done (0); return 1; } /* * Read all the destination folders and * create folder structures for all of them. */ static void opnfolds (struct msgs *src_folder, struct st_fold *folders, int nfolders) { char nmaildir[BUFSIZ]; struct st_fold *fp, *ep; struct msgs *mp; for (fp = folders, ep = folders + nfolders; fp < ep; fp++) { if (chdir (m_maildir ("")) < 0) { advise (m_maildir (""), "chdir"); } strncpy (nmaildir, m_maildir (fp->f_name), sizeof(nmaildir)); /* * Null src_folder indicates that we are refiling a file to * the folders, in which case we don't want to short-circuit * fp->f_mp to any "source folder". */ if (! src_folder || strcmp (src_folder->foldpath, nmaildir)) { create_folder (nmaildir, 0, done); if (chdir (nmaildir) == NOTOK) adios (nmaildir, "unable to change directory to"); if (!(mp = folder_read (fp->f_name, 1))) adios (NULL, "unable to read folder %s", fp->f_name); mp->curmsg = 0; fp->f_mp = mp; } else { /* Source and destination folders are the same. */ fp->f_mp = src_folder; } if (maildir[0] != '\0' && chdir (maildir) < 0) { advise (maildir, "chdir"); } } } /* * Set the Previous-Sequence and then synchronize the * sequence file, for each destination folder. */ static void clsfolds (struct st_fold *folders, int nfolders) { struct st_fold *fp, *ep; struct msgs *mp; for (fp = folders, ep = folders + nfolders; fp < ep; fp++) { mp = fp->f_mp; seq_setprev (mp); seq_save (mp); } } /* * If you have a "rmmproc" defined, we called that * to remove all the specified files. If "rmmproc" * is not defined, then just unlink the files. */ static void remove_files (int filep, char **files) { int i, vecp; char **vec, *program; /* If rmmproc is defined, we use that */ if (rmmproc) { vec = argsplit(rmmproc, &program, &vecp); files++; /* Yes, we need to do this */ for (i = 0; i < filep; i++) vec[vecp++] = files[i]; vec[vecp] = NULL; /* NULL terminate list */ fflush (stdout); execvp (program, vec); adios (rmmproc, "unable to exec"); } /* Else just unlink the files */ files++; /* advance past filevec[0] */ for (i = 0; i < filep; i++) { if (m_unlink (files[i]) == NOTOK) admonish (files[i], "unable to unlink"); } } /* * Link (or copy) the message into each of the destination folders. * If oldmsgnum is not 0, call copy_seqs(). */ static int m_file (struct msgs *mp, char *msgfile, int oldmsgnum, struct st_fold *folders, int nfolders, int preserve, int refile) { int msgnum; struct st_fold *fp, *ep; for (fp = folders, ep = folders + nfolders; fp < ep; fp++) { /* * With same source and destination folder, don't indicate that * the new message is selected so that 1) folder_delmsgs() doesn't * delete it later and 2) it is not reflected in mp->hghsel, and * therefore won't be assigned to be the current message. */ if ((msgnum = folder_addmsg (&fp->f_mp, msgfile, mp != fp->f_mp, 0, preserve, nfolders == 1 && refile, maildir)) == -1) return 1; if (oldmsgnum) copy_seqs (mp, oldmsgnum, fp->f_mp, msgnum); } return 0; } /* * Copy sequence information for a refiled message to its * new folder. Skip the cur sequence. */ static void copy_seqs (struct msgs *oldmp, int oldmsgnum, struct msgs *newmp, int newmsgnum) { char **seq; size_t seqnum; for (seq = svector_strs (oldmp->msgattrs), seqnum = 0; *seq && seqnum < svector_size (oldmp->msgattrs); ++seq, ++seqnum) { if (strcmp (current, *seq)) { assert ((int) seqnum == seq_getnum (oldmp, *seq)); if (in_sequence (oldmp, seqnum, oldmsgnum)) { seq_addmsg (newmp, *seq, newmsgnum, !is_seq_private (oldmp, seqnum), 0); } } } } nmh-1.7.1-RC3/uip/repl.c000644 007761 000024 00000031536 13243042054 014672 0ustar00kenhstaff000000 000000 /* repl.c -- reply to a message * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include "../sbr/m_maildir.h" #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 all|to|cc|me", 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("convertargs type argstring", 0, CONVERTARGSW) \ 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) \ 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, NOSW }, { "replace", 0, YESW }, { "list", 0, LISTDSW }, { "refile +folder", 0, REFILSW }, { NULL, 0, 0 } }; short ccto = -1; /* global for replsbr */ short cccc = -1; short ccme = -1; short querysw = 0; static short outputlinelen = OUTPUTLINELEN; static short groupreply = 0; /* Is this a group reply? */ static int mime = 0; /* include original as MIME part */ static char *form = NULL; /* form (components) file */ static char *filter = NULL; /* message filter file */ static char *fcc = NULL; /* folders to add to Fcc: header */ /* * prototypes */ static void docc (char *, int); static void add_convert_header (const char *, char *, char *, char *); int main (int argc, char **argv) { int i, isdf = 0; int anot = 0, inplace = 1; int nedit = 0, nwhat = 0; int atfile = 0; int fmtproc = -1; char *cp, *cwd, *dp, *maildir, *file = NULL; char *folder = NULL, *msg = NULL, *dfolder = NULL; char *dmsg = NULL, *ed = NULL, drft[BUFSIZ], buf[BUFSIZ]; char **argp, **arguments; svector_t convert_types = svector_create (10); svector_t convert_args = svector_create (10); size_t n; struct msgs *mp = NULL; struct stat st; FILE *in; int buildsw = 0; if (nmh_init(argv[0], 1)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s: [+folder] [msg] [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case GROUPSW: groupreply++; continue; case NGROUPSW: groupreply = 0; continue; case ANNOSW: anot++; continue; case NANNOSW: anot = 0; continue; case CCSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); docc (cp, 1); continue; case NCCSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); docc (cp, 0); continue; case EDITRSW: if (!(ed = *argp++) || *ed == '-') adios (NULL, "missing argument to %s", argp[-2]); nedit = 0; continue; case NEDITSW: nedit++; continue; case CONVERTARGSW: { char *type; size_t i; if (!(type = *argp++)) { adios (NULL, "missing type argument to %s", argp[-2]); } if (!(cp = *argp++)) { adios (NULL, "missing argstring argument to %s", argp[-3]); } for (i = 0; i < svector_size (convert_types); ++i) { if (! strcmp (svector_at (convert_types, i), type)) { /* Already saw this type, so just update its args. */ svector_strs (convert_args)[i] = cp; break; } } if (i == svector_size (convert_types)) { svector_push_back (convert_types, type); svector_push_back (convert_args, cp); } continue; } case WHATSW: if (!(whatnowproc = *argp++) || *whatnowproc == '-') adios (NULL, "missing argument to %s", argp[-2]); nwhat = 0; continue; case BILDSW: buildsw++; /* FALLTHRU */ case NWHATSW: nwhat++; continue; case FCCSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); dp = NULL; if (*cp == '@') cp = dp = path (cp + 1, TSUBCWF); if (fcc) fcc = add (", ", fcc); fcc = add (cp, fcc); mh_xfree(dp); continue; case FILESW: if (file) adios (NULL, "only one file at a time!"); if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); file = path (cp, TFILE); continue; case FILTSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); filter = getcpy (etcpath (cp)); mime = 0; continue; case FORMSW: if (!(form = *argp++) || *form == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case FRMTSW: filter = getcpy (etcpath (mhlreply)); mime = 0; continue; case NFRMTSW: filter = NULL; continue; case INPLSW: inplace++; continue; case NINPLSW: inplace = 0; continue; case MIMESW: mime++; filter = NULL; continue; case NMIMESW: mime = 0; continue; case QURYSW: querysw++; continue; case NQURYSW: querysw = 0; continue; case WIDTHSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if ((outputlinelen = atoi (cp)) < 10) adios (NULL, "impossible width %d", outputlinelen); continue; case DFOLDSW: if (dfolder) adios (NULL, "only one draft folder at a time!"); if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); dfolder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp, *cp != '@' ? TFOLDER : TSUBCWF); continue; case DMSGSW: if (dmsg) adios (NULL, "only one draft message at a time!"); if (!(dmsg = *argp++) || *dmsg == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case NDFLDSW: dfolder = NULL; isdf = NOTOK; continue; case ATFILESW: atfile++; continue; case NOATFILESW: atfile = 0; continue; case FMTPROCSW: if (!(formatproc = *argp++) || *formatproc == '-') adios (NULL, "missing argument to %s", argp[-2]); fmtproc = 1; continue; case NFMTPROCSW: fmtproc = 0; continue; } } if (*cp == '+' || *cp == '@') { if (folder) adios (NULL, "only one folder at a time!"); else folder = pluspath (cp); } else { if (msg) adios (NULL, "only one message at a time!"); else msg = cp; } } if (ccto == -1) ccto = groupreply; if (cccc == -1) cccc = groupreply; if (ccme == -1) ccme = groupreply; cwd = mh_xstrdup(pwd ()); if (!context_find ("path")) free (path ("./", TFOLDER)); if (file && (msg || folder)) adios (NULL, "can't mix files and folders/msgs"); try_it_again: strncpy (drft, buildsw ? m_maildir ("reply") : m_draft (dfolder, NULL, NOUSE, &isdf), sizeof(drft)); /* Check if a draft exists */ if (!buildsw && stat (drft, &st) != NOTOK) { printf ("Draft \"%s\" exists (%ld bytes).", drft, (long) st.st_size); for (i = LISTDSW; i != YESW;) { if (!(argp = read_switch_multiword ("\nDisposition? ", isdf ? aqrnl : aqrl))) done (1); switch (i = smatch (*argp, isdf ? aqrnl : aqrl)) { case NOSW: done (0); case NEWSW: dmsg = NULL; goto try_it_again; case YESW: break; case LISTDSW: showfile (++argp, drft); break; case REFILSW: if (refile (++argp, drft) == 0) i = YESW; break; default: inform("say what?"); break; } } } if (file) { /* * We are replying to a file. */ anot = 0; /* we don't want to annotate a file */ } else { /* * We are replying to a message. */ if (!msg) msg = "cur"; if (!folder) folder = getfolder (1); maildir = m_maildir (folder); if (chdir (maildir) == NOTOK) adios (maildir, "unable to change directory to"); /* read folder and create message structure */ if (!(mp = folder_read (folder, 1))) adios (NULL, "unable to read folder %s", folder); /* check for empty folder */ if (mp->nummsg == 0) adios (NULL, "no messages in %s", folder); /* parse the message range/sequence/name and set SELECTED */ if (!m_convert (mp, msg)) done (1); seq_setprev (mp); /* set the previous-sequence */ if (mp->numsel > 1) adios (NULL, "only one message at a time!"); context_replace (pfolder, folder); /* update current folder */ seq_setcur (mp, mp->lowsel); /* update current message */ seq_save (mp); /* synchronize sequences */ context_save (); /* save the context file */ } msg = file ? file : mh_xstrdup(m_name (mp->lowsel)); if ((in = fopen (msg, "r")) == NULL) adios (msg, "unable to open"); /* find form (components) file */ if (!form) { if (groupreply) form = etcpath (replgroupcomps); else form = etcpath (replcomps); } replout (in, msg, drft, mp, outputlinelen, mime, form, filter, fcc, fmtproc); fclose (in); { char *filename = file ? file : concat (mp->foldpath, "/", msg, NULL); for (n = 0; n < svector_size (convert_types); ++n) { add_convert_header (svector_at (convert_types, n), svector_at (convert_args, n), filename, drft); } if (! file) { free (filename); } } if (nwhat) done (0); what_now (ed, nedit, NOUSE, drft, msg, 0, mp, anot ? "Replied" : NULL, inplace, cwd, atfile); svector_free (convert_args); svector_free (convert_types); done (1); return 1; } void docc (char *cp, int ccflag) { switch (smatch (cp, ccswitches)) { case AMBIGSW: ambigsw (cp, ccswitches); done (1); case UNKWNSW: adios (NULL, "-%scc %s unknown", ccflag ? "" : "no", cp); case CTOSW: ccto = ccflag; break; case CCCSW: cccc = ccflag; break; case CMESW: ccme = ccflag; break; case CALSW: ccto = cccc = ccme = ccflag; break; } } /* * Add pseudoheaders that will pass the convert arguments to * mhbuild. They have the form: * MHBUILD_FILE_PSEUDOHEADER-text/calendar: /home/user/Mail/inbox/7 * MHBUILD_ARGS_PSEUDOHEADER-text/calendar: reply -accept * The ARGS pseudoheader is optional, but we always add it when * -convertargs is used. */ void add_convert_header (const char *convert_type, char *convert_arg, char *filename, char *drft) { char *field_name; field_name = concat (MHBUILD_FILE_PSEUDOHEADER, convert_type, NULL); annotate (drft, field_name, filename, 1, 0, -2, 1); free (field_name); field_name = concat (MHBUILD_ARGS_PSEUDOHEADER, convert_type, NULL); annotate (drft, field_name, convert_arg, 1, 0, -2, 1); free (field_name); } nmh-1.7.1-RC3/uip/replsbr.c000644 007761 000024 00000035527 13243042054 015405 0ustar00kenhstaff000000 000000 /* replsbr.c -- routines to help repl along... * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include /* L_SET */ extern short ccto; /* from repl.c */ extern short cccc; extern short ccme; extern short querysw; static int dftype=0; static char *badaddrs = NULL; static char *dfhost = NULL; static struct mailname mq; static int nodupcheck = 0; /* If set, no check for duplicates */ static char *addrcomps[] = { "from", "sender", "reply-to", "to", "cc", "bcc", "resent-from", "resent-sender", "resent-reply-to", "resent-to", "resent-cc", "resent-bcc", NULL }; /* * static prototypes */ static int insert (struct mailname *); static void replfilter (FILE *, FILE *, char *, int); static char *replformataddr(char *, char *); static char *replconcataddr(char *, char *); static char *fix_addresses (char *); void replout (FILE *inb, char *msg, char *drft, struct msgs *mp, int outputlinelen, int mime, char *form, char *filter, char *fcc, int fmtproc) { int state, i; struct comp *cptr; char tmpbuf[NMH_BUFSIZ]; struct format *fmt; char **ap; int char_read = 0, format_len, mask; char name[NAMESZ], *cp; charstring_t scanl; static int dat[5]; /* aux. data for format routine */ m_getfld_state_t gstate = 0; struct fmt_callbacks cb; FILE *out; NMH_UNUSED (msg); mask = umask(~m_gmprot()); if ((out = fopen (drft, "w")) == NULL) adios (drft, "unable to create"); umask(mask); /* get new format string */ cp = new_fs (form, NULL, NULL); format_len = strlen (cp); /* compile format string */ fmt_compile (cp, &fmt, 1); for (ap = addrcomps; *ap; ap++) { cptr = fmt_findcomp (*ap); if (cptr) cptr->c_type |= CT_ADDR; } /* * ignore any components killed by command line switches * * This prevents the component from being found via fmt_findcomp(), * which makes sure no text gets added to it when the message is processed. */ if (!ccto) { cptr = fmt_findcomp ("to"); if (cptr) cptr->c_name = mh_xstrdup(""); } if (!cccc) { cptr = fmt_findcomp("cc"); if (cptr) cptr->c_name = mh_xstrdup(""); } if (!ccme) ismymbox (NULL); /* * pick any interesting stuff out of msg "inb" */ for (;;) { int msg_count = sizeof tmpbuf; state = m_getfld (&gstate, name, tmpbuf, &msg_count, inb); switch (state) { case FLD: case FLDPLUS: /* * if we're interested in this component, save a pointer * to the component text, then start using our next free * buffer as the component temp buffer (buffer switching * saves an extra copy of the component text). */ i = fmt_addcomptext(name, tmpbuf); if (i != -1) { char_read += msg_count; while (state == FLDPLUS) { 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) { msg_count= sizeof tmpbuf; state = m_getfld (&gstate, name, tmpbuf, &msg_count, inb); } break; case LENERR: case FMTERR: case BODY: case FILEEOF: goto finished; default: adios (NULL, "m_getfld() returned %d", state); } } /* * format and output the header lines. */ finished: m_getfld_state_destroy (&gstate); /* set up the "fcc" pseudo-component */ cptr = fmt_findcomp ("fcc"); if (cptr) { mh_xfree(cptr->c_text); if (fcc) cptr->c_text = mh_xstrdup(fcc); else cptr->c_text = NULL; } cptr = fmt_findcomp ("user"); if (cptr) { mh_xfree(cptr->c_text); if ((cp = getenv("USER"))) cptr->c_text = mh_xstrdup(cp); else cptr = NULL; } /* * if there's a "Subject" component, strip any "Re:"s off it */ cptr = fmt_findcomp ("subject"); if (cptr && (cp = cptr->c_text)) { char *sp = cp; for (;;) { while (isspace((unsigned char) *cp)) cp++; if(uprf(cp, "re:")) cp += 3; else break; sp = cp; } if (sp != cptr->c_text) { cp = cptr->c_text; cptr->c_text = mh_xstrdup(sp); free (cp); } } i = format_len + char_read + 256; scanl = charstring_create (i + 2); dat[0] = 0; dat[1] = 0; dat[2] = 0; dat[3] = outputlinelen; dat[4] = 0; memset(&cb, 0, sizeof(cb)); cb.formataddr = replformataddr; cb.concataddr = replconcataddr; fmt_scan (fmt, scanl, i, dat, &cb); fputs (charstring_buffer (scanl), out); if (badaddrs) { fputs ("\nrepl: bad addresses:\n", out); fputs ( badaddrs, out); } /* * Check if we should filter the message * or add mhn directives */ if (filter) { fflush(out); if (ferror (out)) adios (drft, "error writing"); replfilter (inb, out, filter, fmtproc); } else if (mime && mp) { fprintf (out, "#forw [original message] +%s %s\n", mp->foldpath, m_name (mp->lowsel)); } fflush(out); if (ferror (out)) adios (drft, "error writing"); fclose (out); /* return dynamically allocated buffers */ charstring_free (scanl); fmt_free(fmt, 1); } static char *buf; /* our current working buffer */ static char *bufend; /* end of working buffer */ static char *last_dst; /* buf ptr at end of last call */ static unsigned int bufsiz=0; /* current size of buf */ #define BUFINCR 512 /* how much to expand buf when if fills */ #define CPY(s) { cp = (s); while ((*dst++ = *cp++)) ; --dst; } /* * check if there's enough room in buf for str. * add more mem if needed */ #define CHECKMEM(str) \ if ((len = strlen (str)) >= bufend - dst) {\ int i = dst - buf;\ int n = last_dst - buf;\ bufsiz += ((dst + len - bufend) / BUFINCR + 1) * BUFINCR;\ buf = mh_xrealloc (buf, bufsiz);\ dst = buf + i;\ last_dst = buf + n;\ bufend = buf + bufsiz;\ } /* * fmt_scan will call this routine if the user includes the function * "(formataddr {component})" in a format string. "orig" is the * original contents of the string register. "str" is the address * string to be formatted and concatenated onto orig. This routine * returns a pointer to the concatenated address string. * * We try to not do a lot of malloc/copy/free's (which is why we * don't call "getcpy") but still place no upper limit on the * length of the result string. */ static char * replformataddr (char *orig, char *str) { int len; char baddr[BUFSIZ], error[BUFSIZ]; int isgroup; char *dst; char *cp; char *sp; struct mailname *mp = NULL; char *fixed_str = fix_addresses (str); /* if we don't have a buffer yet, get one */ if (bufsiz == 0) { buf = mh_xmalloc (BUFINCR); last_dst = buf; /* XXX */ bufsiz = BUFINCR - 6; /* leave some slop */ bufend = buf + bufsiz; } /* * If "orig" points to our buffer we can just pick up where we * left off. Otherwise we have to copy orig into our buffer. */ if (orig == buf) dst = last_dst; else if (!orig || !*orig) { dst = buf; *dst = '\0'; } else { dst = last_dst; /* XXX */ CHECKMEM (orig); CPY (orig); } /* concatenate all the new addresses onto 'buf' */ for (isgroup = 0; (cp = getname (fixed_str)); ) { if ((mp = getm (cp, dfhost, dftype, error, sizeof(error))) == NULL) { snprintf (baddr, sizeof(baddr), "\t%s -- %s\n", cp, error); badaddrs = add (baddr, badaddrs); continue; } if (isgroup && (mp->m_gname || !mp->m_ingrp)) { *dst++ = ';'; isgroup = 0; } if (insert (mp)) { /* if we get here we're going to add an address */ if (dst != buf) { *dst++ = ','; *dst++ = ' '; } if (mp->m_gname) { CHECKMEM (mp->m_gname); CPY (mp->m_gname); isgroup++; } sp = adrformat (mp); CHECKMEM (sp); CPY (sp); } } free (fixed_str); if (isgroup) *dst++ = ';'; *dst = '\0'; last_dst = dst; return (buf); } /* * fmt_scan will call this routine if the user includes the function * "(concataddr {component})" in a format string. This behaves exactly * like formataddr, except that it does NOT suppress duplicate addresses * between calls. * * As an implementation detail: I thought about splitting out replformataddr() * into the generic part and duplicate-suppressing part, but the call to * insert() was buried deep within a couple of loops and I didn't see a * way to do it easily. So instead we simply set a special flag to stop * the duplicate check and call replformataddr(). */ static char * replconcataddr(char *orig, char *str) { char *cp; nodupcheck = 1; cp = replformataddr(orig, str); nodupcheck = 0; return cp; } static int insert (struct mailname *np) { char buffer[BUFSIZ]; struct mailname *mp; if (nodupcheck) return 1; if (np->m_mbox == NULL) return 0; for (mp = &mq; mp->m_next; mp = mp->m_next) { if (!strcasecmp (FENDNULL(np->m_host), FENDNULL(mp->m_next->m_host)) && !strcasecmp (FENDNULL(np->m_mbox), FENDNULL(mp->m_next->m_mbox))) return 0; } if (!ccme && ismymbox (np)) return 0; if (querysw) { snprintf (buffer, sizeof(buffer), "Reply to %s? ", adrformat (np)); if (!read_switch (buffer, anoyes)) return 0; } mp->m_next = np; return 1; } /* * Call the mhlproc * * This function expects that argument out has been fflushed by the caller. */ static void replfilter (FILE *in, FILE *out, char *filter, int fmtproc) { int pid; char *mhl; char *errstr; char **arglist; int argnum; if (filter == NULL) return; if (access (filter, R_OK) == NOTOK) adios (filter, "unable to read"); rewind (in); lseek(fileno(in), 0, SEEK_SET); arglist = argsplit(mhlproc, &mhl, &argnum); switch (pid = fork()) { case NOTOK: adios ("fork", "unable to"); case OK: dup2 (fileno (in), fileno (stdin)); dup2 (fileno (out), fileno (stdout)); closefds (3); /* * 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[argnum++] = "-form"; arglist[argnum++] = filter; arglist[argnum++] = "-noclear"; switch (fmtproc) { case 1: arglist[argnum++] = "-fmtproc"; arglist[argnum++] = formatproc; break; case 0: arglist[argnum++] = "-nofmtproc"; break; } arglist[argnum++] = NULL; execvp (mhl, arglist); errstr = strerror(errno); if (write(2, "unable to exec ", 15) < 0 || write(2, mhlproc, strlen(mhlproc)) < 0 || write(2, ": ", 2) < 0 || write(2, errstr, strlen(errstr)) < 0 || write(2, "\n", 1) < 0) { advise ("stderr", "write"); } _exit (-1); default: if (pidXwait (pid, mhl)) done (1); fseek (out, 0L, SEEK_END); break; } } static char * fix_addresses (char *str) { char *fixed_str = NULL; int fixed_address = 0; if (str) { /* * Attempt to parse each of the addresses in str. If any fail * and can be fixed with escape_local_part(), do that. This * is extra ugly because getm()'s state can only be reset by * call getname(), and getname() needs to be called repeatedly * until it returns NULL to reset its state. */ struct adr_node { char *adr; int escape_local_part; int fixed; struct adr_node *next; } *adrs = NULL; struct adr_node *np = adrs; char *cp; /* * First, put each of the addresses in a linked list. Note * invalid addresses that might be fixed by escaping the * local part. */ while ((cp = getname (str))) { struct adr_node *adr_nodep; char error[BUFSIZ]; struct mailname *mp; NEW(adr_nodep); adr_nodep->adr = mh_xstrdup (cp); adr_nodep->escape_local_part = 0; adr_nodep->fixed = 0; adr_nodep->next = NULL; /* With AD_NAME, errors are not reported to user. */ if ((mp = getm (cp, dfhost, dftype, error, sizeof(error))) == NULL) { const char *no_at_sign = "no at-sign after local-part"; adr_nodep->escape_local_part = has_prefix(error, no_at_sign); } else { mnfree (mp); } if (np) { np = np->next = adr_nodep; } else { np = adrs = adr_nodep; } } /* * Walk the list and try to fix broken addresses. */ for (np = adrs; np; np = np->next) { char *display_name = mh_xstrdup (np->adr); size_t len = strlen (display_name); if (np->escape_local_part) { char *local_part_end = strrchr (display_name, '<'); char *angle_addr = mh_xstrdup (local_part_end); struct mailname *mp; char *new_adr, *adr; *local_part_end = '\0'; /* Trim any trailing whitespace. */ while (local_part_end > display_name && isspace ((unsigned char) *--local_part_end)) { *local_part_end = '\0'; } escape_local_part (display_name, len); new_adr = concat (display_name, " ", angle_addr, NULL); adr = getname (new_adr); if (adr != NULL && (mp = getm (adr, dfhost, dftype, NULL, 0)) != NULL) { fixed_address = 1; mnfree (mp); } free (angle_addr); free (new_adr); free (np->adr); np->adr = mh_xstrdup (adr); /* Need to flush getname() */ while ((cp = getname (""))) continue; } /* else the np->adr is OK, so use it as-is. */ free (display_name); } /* * If any addresses were repaired, build new address string, * replacing broken addresses. */ for (np = adrs; np; ) { struct adr_node *next = np->next; if (fixed_address) { if (fixed_str) { char *new_str = concat (fixed_str, ", ", np->adr, NULL); free (fixed_str); fixed_str = new_str; } else { fixed_str = mh_xstrdup (np->adr); } } free (np->adr); free (np); np = next; } } if (fixed_address) { return fixed_str; } free (fixed_str); return str ? mh_xstrdup (str) : NULL; } nmh-1.7.1-RC3/uip/rmf.c000644 007761 000024 00000012550 13243042054 014507 0ustar00kenhstaff000000 000000 /* rmf.c -- remove a folder * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include "../sbr/m_maildir.h" #include "../sbr/m_mktemp.h" #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 */ static int rmf(char *); static void rma (char *); int main (int argc, char **argv) { int defolder = 0, interactive = -1; char *cp, *folder = NULL, newfolder[BUFSIZ]; char buf[BUFSIZ], **argp, **arguments; if (nmh_init(argv[0], 1)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [+folder] [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case INTRSW: interactive = 1; continue; case NINTRSW: interactive = 0; continue; } } if (*cp == '+' || *cp == '@') { if (folder) adios (NULL, "only one folder at a time!"); else folder = pluspath (cp); } else { adios (NULL, "usage: %s [+folder] [switches]", invo_name); } } if (!context_find ("path")) free (path ("./", TFOLDER)); if (!folder) { folder = getfolder (1); defolder++; } if (strcmp (m_mailpath (folder), pwd ()) == 0) adios (NULL, "sorry, you can't remove the current working directory"); if (interactive == -1) interactive = defolder; if (strchr (folder, '/') && (*folder != '/') && (*folder != '.')) { for (cp = stpcpy(newfolder, folder); cp > newfolder && *cp != '/'; cp--) continue; if (cp > newfolder) *cp = '\0'; else strncpy (newfolder, getfolder(0), sizeof(newfolder)); } else { strncpy (newfolder, getfolder(0), sizeof(newfolder)); } if (interactive) { cp = concat ("Remove folder \"", folder, "\"? ", NULL); if (!read_yes_or_no_if_tty (cp)) done (0); free (cp); } if (rmf (folder) == OK) { char *cfolder = context_find(pfolder); if (cfolder && strcmp (cfolder, newfolder)) { printf ("[+%s now current]\n", newfolder); context_replace (pfolder, newfolder); /* update current folder */ } } context_save (); /* save the context file */ done (0); return 1; } static int rmf (char *folder) { int i, others; char *maildir; char cur[BUFSIZ]; struct dirent *dp; DIR *dd; switch (i = chdir (maildir = m_maildir (folder))) { case OK: if (access (".", W_OK) != NOTOK && access ("..", W_OK) != NOTOK) break; /* FALLTHRU */ case NOTOK: snprintf (cur, sizeof(cur), "atr-%s-%s", current, m_mailpath (folder)); if (!context_del (cur)) { printf ("[+%s de-referenced]\n", folder); return OK; } inform("you have no profile entry for the %s folder +%s", i == NOTOK ? "unreadable" : "read-only", folder); return NOTOK; } if ((dd = opendir (".")) == NULL) adios (NULL, "unable to read folder +%s", folder); others = 0; /* * Run the external delete hook program. */ (void)ext_hook("del-hook", maildir, NULL); while ((dp = readdir (dd))) { switch (dp->d_name[0]) { case '.': if (strcmp (dp->d_name, ".") == 0 || strcmp (dp->d_name, "..") == 0) continue; break; case ',': break; default: if (m_atoi (dp->d_name)) break; if (strcmp (dp->d_name, LINK) == 0 || has_prefix(dp->d_name, BACKUP_PREFIX)) break; inform("file \"%s/%s\" not deleted, continuing...", folder, dp->d_name); others++; continue; } if (m_unlink (dp->d_name) == NOTOK) { admonish (dp->d_name, "unable to unlink %s:", folder); others++; } } closedir (dd); /* * Remove any relevant private sequences * or attributes from context file. */ rma (folder); if (chdir ("..") < 0) { advise ("..", "chdir"); } if (others == 0 && remdir (maildir)) return OK; inform("folder +%s not removed", folder); return NOTOK; } /* * Remove all the (private) sequence information for * this folder from the profile/context list. */ static void rma (char *folder) { int alen, j, plen; char *cp; struct node *np, *pp; alen = LEN("atr-"); plen = strlen (cp = m_mailpath (folder)) + 1; /* * Search context list for keys that look like * "atr-something-folderpath", and remove them. */ for (np = m_defs, pp = NULL; np; np = np->n_next) { if (ssequal ("atr-", np->n_name) && (j = strlen (np->n_name) - plen) > alen && *(np->n_name + j) == '-' && strcmp (cp, np->n_name + j + 1) == 0) { if (!np->n_context) inform("bug: context_del(key=\"%s\"), continuing...", np->n_name); if (pp) { pp->n_next = np->n_next; np = pp; } else { m_defs = np->n_next; } ctxflags |= CTXMOD; } else { pp = np; } } } nmh-1.7.1-RC3/uip/rmm.c000644 007761 000024 00000006172 13243042054 014521 0ustar00kenhstaff000000 000000 /* rmm.c -- remove a message(s) * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include "../sbr/m_maildir.h" #define RMM_SWITCHES \ X("unlink", 0, UNLINKSW) \ X("nounlink", 0, NUNLINKSW) \ 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(RMM); #undef X #define X(sw, minchars, id) { sw, minchars, id }, DEFINE_SWITCH_ARRAY(RMM, switches); #undef X int main (int argc, char **argv) { int msgnum, unlink_msgs = 0; char *cp, *maildir, *folder = NULL; char buf[BUFSIZ], **argp; char **arguments; struct msgs_array msgs = { 0, 0, NULL }; struct msgs *mp; if (nmh_init(argv[0], 1)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; /* parse arguments */ while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown\n", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [+folder] [msgs] [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case UNLINKSW: unlink_msgs++; continue; case NUNLINKSW: unlink_msgs = 0; continue; case RPROCSW: if (!(rmmproc = *argp++) || *rmmproc == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case NRPRCSW: rmmproc = NULL; continue; } } if (*cp == '+' || *cp == '@') { if (folder) adios (NULL, "only one folder at a time!"); else folder = pluspath (cp); } else app_msgarg(&msgs, cp); } if (!context_find ("path")) free (path ("./", TFOLDER)); if (!msgs.size) app_msgarg(&msgs, "cur"); if (!folder) folder = getfolder (1); maildir = m_maildir (folder); if (chdir (maildir) == NOTOK) adios (maildir, "unable to change directory to"); /* read folder and create message structure */ if (!(mp = folder_read (folder, 1))) adios (NULL, "unable to read folder %s", folder); /* check for empty folder */ if (mp->nummsg == 0) adios (NULL, "no messages in %s", folder); /* parse all the message ranges/sequences and set SELECTED */ for (msgnum = 0; msgnum < msgs.size; msgnum++) if (!m_convert (mp, msgs.msgs[msgnum])) done (1); seq_setprev (mp); /* set the previous-sequence */ /* * As part of the new world locking order, folder_delmsgs() now updates * the sequence and context for us. But since folder_delmsgs() doesn't * have access to the folder name, change the context now. */ context_replace (pfolder, folder); /* "remove" the SELECTED messages */ folder_delmsgs (mp, unlink_msgs, 0); folder_free (mp); /* free folder structure */ done (0); return 1; } nmh-1.7.1-RC3/uip/scan.c000644 007761 000024 00000015252 13243042054 014651 0ustar00kenhstaff000000 000000 /* scan.c -- display a one-line "scan" listing of folder or messages * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #include "../sbr/m_maildir.h" #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 int main (int argc, char **argv) { int clearflag = 0, hdrflag = 0, ontty; int width = -1, revflag = 0; int i, state, msgnum; ivector_t seqnum = ivector_create (0); int unseen, num_unseen_seq = 0; char *cp, *maildir, *file = NULL, *folder = NULL; char *form = NULL, *format = NULL, buf[BUFSIZ]; char **argp, *nfs, **arguments; struct msgs_array msgs = { 0, 0, NULL }; struct msgs *mp; charstring_t scanl = NULL; FILE *in; if (nmh_init(argv[0], 1)) { return 1; } mts_init (); arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; /* * Parse arguments */ while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [+folder] [msgs] [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case CLRSW: clearflag++; continue; case NCLRSW: clearflag = 0; continue; case FORMSW: if (!(form = *argp++) || *form == '-') adios (NULL, "missing argument to %s", argp[-2]); format = NULL; continue; case FMTSW: if (!(format = *argp++) || *format == '-') adios (NULL, "missing argument to %s", argp[-2]); form = NULL; continue; case HEADSW: hdrflag++; continue; case NHEADSW: hdrflag = 0; continue; case WIDTHSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); width = atoi (cp); continue; case REVSW: revflag++; continue; case NREVSW: revflag = 0; continue; case FILESW: if (!(cp = *argp++) || (cp[0] == '-' && cp[1])) adios (NULL, "missing argument to %s", argp[-2]); if (strcmp (file = cp, "-")) file = path (cp, TFILE); continue; } } if (*cp == '+' || *cp == '@') { if (folder) adios (NULL, "only one folder at a time!"); else folder = pluspath (cp); } else app_msgarg(&msgs, cp); } if (!context_find ("path")) free (path ("./", TFOLDER)); /* * Get new format string. Must be before chdir(). */ nfs = new_fs (form, format, FORMAT); /* * We are scanning a maildrop file */ if (file) { if (msgs.size) adios (NULL, "\"msgs\" not allowed with -file"); if (folder) adios (NULL, "\"+folder\" not allowed with -file"); /* check if "file" is really stdin */ if (strcmp (file, "-") == 0) { in = stdin; file = "stdin"; } else { if ((in = fopen (file, "r")) == NULL) adios (file, "unable to open"); } if (hdrflag) { printf ("FOLDER %s\t%s\n", file, dtimenow (1)); } scan_detect_mbox_style (in); for (msgnum = 1; ; ++msgnum) { state = scan (in, msgnum, -1, nfs, width, 0, 0, hdrflag ? file : NULL, 0L, 1, &scanl); if (scanl) charstring_clear(scanl); if (state != SCNMSG && state != SCNENC) break; } charstring_free (scanl); scan_finished (); fclose (in); done (0); } /* * We are scanning a folder */ if (!msgs.size) app_msgarg(&msgs, "all"); if (!folder) folder = getfolder (1); maildir = m_maildir (folder); if (chdir (maildir) == NOTOK) adios (maildir, "unable to change directory to"); /* read folder and create message structure */ if (!(mp = folder_read (folder, 1))) adios (NULL, "unable to read folder %s", folder); /* check for empty folder */ if (mp->nummsg == 0) adios (NULL, "no messages in %s", folder); /* parse all the message ranges/sequences and set SELECTED */ for (msgnum = 0; msgnum < msgs.size; msgnum++) if (!m_convert (mp, msgs.msgs[msgnum])) done(1); seq_setprev (mp); /* set the Previous-Sequence */ context_replace (pfolder, folder); /* update current folder */ seq_save (mp); /* synchronize message sequences */ context_save (); /* save the context file */ /* * Get the sequence number for each sequence * specified by Unseen-Sequence */ if ((cp = context_find (usequence)) && *cp) { char **ap, *dp; dp = mh_xstrdup(cp); ap = brkstring (dp, " ", "\n"); for (i = 0; ap && *ap; i++, ap++) ivector_push_back (seqnum, seq_getnum (mp, *ap)); num_unseen_seq = i; mh_xfree(dp); } ontty = isatty (fileno (stdout)); for (msgnum = revflag ? mp->hghsel : mp->lowsel; (revflag ? msgnum >= mp->lowsel : msgnum <= mp->hghsel); msgnum += (revflag ? -1 : 1)) { if (is_selected(mp, msgnum)) { if ((in = fopen (cp = m_name (msgnum), "r")) == NULL) { admonish (cp, "unable to open message"); continue; } if (hdrflag) { printf ("FOLDER %s\t%s\n", folder, dtimenow(1)); } /* * Check if message is in any sequence given * by Unseen-Sequence profile entry. */ unseen = 0; for (i = 0; i < num_unseen_seq; i++) { if (in_sequence(mp, ivector_at (seqnum, i), msgnum)) { unseen = 1; break; } } switch (state = scan (in, msgnum, 0, nfs, width, msgnum == mp->curmsg, unseen, folder, 0L, 1, &scanl)) { case SCNMSG: case SCNENC: case SCNERR: break; default: adios (NULL, "scan() botch (%d)", state); case SCNEOF: inform("message %d: empty", msgnum); break; } if (scanl) charstring_clear(scanl); scan_finished (); hdrflag = 0; fclose (in); if (ontty) fflush (stdout); } } charstring_free (scanl); ivector_free (seqnum); folder_free (mp); /* free folder/message structure */ if (clearflag) nmh_clear_screen (); done (0); return 1; } nmh-1.7.1-RC3/uip/scansbr.c000644 007761 000024 00000024031 13243042054 015353 0ustar00kenhstaff000000 000000 /* scansbr.c -- routines to help scan along... * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include static struct format *fmt; static struct comp *datecomp; /* pntr to "date" comp */ static struct comp *bodycomp; /* pntr to "body" pseudo-comp * * (if referenced) */ static int ncomps = 0; /* # of interesting components */ static char **compbuffers = 0; /* buffers for component text */ static struct comp **used_buf = 0; /* stack for comp that use buffers */ static int dat[5]; /* aux. data for format routine */ static m_getfld_state_t gstate; /* for accessor functions below */ #define DIEWRERR() adios (scnmsg, "write error on") #define PUTC(c) \ if (putc((c), scnout) == EOF) \ DIEWRERR(); #define FPUTS(buf) {\ if (fputs(buf,scnout) == EOF)\ DIEWRERR();\ } /* outnum determines how the input from inb is copied. If positive then * it is the number of the message to create, e.g. for inc(1), and all * of the email is copied into that message, with some tweaks. If 0, * e.g. `scan 42', then reading inb can dubiously stop after a whole * buffer of body, even though this might not be enough to fulfill the * scan format and width. Or if -1 then no copy is being created, but * all of inb must be read because the next message must be found, e.g. * `scan -file foo.mbox'. */ int scan (FILE *inb, int innum, int outnum, char *nfs, int width, int curflg, int unseen, char *folder, long size, int noisy, charstring_t *scanl) { int i, compnum, encrypted, state; char *cp, *tmpbuf, *startbody, **nxtbuf; char *saved_c_text = NULL; struct comp *cptr; struct comp **savecomp; char *scnmsg = NULL; FILE *scnout = NULL; char name[NAMESZ]; int bufsz; static int rlwidth, slwidth; /* first-time only initialization, which will always happen the way the code is now, with callers initializing *scanl to NULL. scanl used to be a global. */ if (! *scanl) { if (width == -1) { /* Default: width of the terminal, but at least WIDTH/2. */ if ((width = sc_width ()) < WIDTH/2) width = WIDTH/2; } else if (width == 0) { /* Unlimited width. */ width = INT_MAX; } dat[3] = slwidth = width; *scanl = charstring_create (min(width, NMH_BUFSIZ)); if (outnum) umask(~m_gmprot()); /* Compile format string */ ncomps = fmt_compile (nfs, &fmt, 1) + 2; bodycomp = fmt_findcomp("body"); datecomp = fmt_findcomp("date"); cptr = fmt_findcomp("folder"); if (cptr && folder) cptr->c_text = mh_xstrdup(folder); if (fmt_addcompentry("encrypted")) { ncomps++; } cptr = fmt_findcomp("dtimenow"); if (cptr) cptr->c_text = getcpy(dtimenow (0)); /* * In other programs I got rid of this complicated buffer switching, * but since scan reads lots of messages at once and this complicated * memory management, I decided to keep it; otherwise there was * the potential for a lot of malloc() and free()s, and I could * see the malloc() pool really getting fragmented. Maybe it * wouldn't be an issue in practice; perhaps this will get * revisited someday. * * So, some notes for what's going on: * * nxtbuf is an array of pointers that contains malloc()'d buffers * to hold our component text. used_buf is an array of struct comp * pointers that holds pointers to component structures we found while * processing a message. * * We read in the message with m_getfld(), using "tmpbuf" as our * input buffer. tmpbuf is set at the start of message processing * to the first buffer in our buffer pool (nxtbuf). * * Every time we find a component we care about, we set that component's * text buffer to the current value of tmpbuf, and then switch tmpbuf * to the next buffer in our pool. We also add that component to * our used_buf pool. * * When we're done, we go back and zero out all of the component * text buffer pointers that we saved in used_buf. * * Note that this means c_text memory is NOT owned by the fmt_module * and it's our responsibility to free it. */ nxtbuf = compbuffers = mh_xcalloc(ncomps, sizeof *nxtbuf); used_buf = mh_xcalloc(ncomps + 1, sizeof *used_buf); used_buf += ncomps+1; *--used_buf = 0; rlwidth = NMH_BUFSIZ; for (i = ncomps; i--; ) *nxtbuf++ = mh_xmalloc(rlwidth); } /* * each-message initialization */ nxtbuf = compbuffers; savecomp = used_buf; tmpbuf = *nxtbuf++; startbody = NULL; dat[0] = innum ? innum : outnum; dat[1] = curflg; dat[4] = unseen; /* * Get the first field. If the message is non-empty * and we're doing an "inc", open the output file. */ 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; } return SCNEOF; } if (outnum > 0) { scnmsg = m_name (outnum); if (*scnmsg == '?') /* msg num out of range */ return SCNNUM; if ((scnout = fopen (scnmsg, "w")) == NULL) adios (scnmsg, "unable to write"); } /* scan - main loop */ for (compnum = 1; ; bufsz = rlwidth, state = m_getfld (&gstate, name, tmpbuf, &bufsz, inb)) { switch (state) { case FLD: case FLDPLUS: compnum++; if (scnout) { FPUTS (name); PUTC(':'); FPUTS (tmpbuf); } /* * if we're interested in this component, save a pointer * to the component text, then start using our next free * buffer as the component temp buffer (buffer switching * saves an extra copy of the component text). */ if ((cptr = fmt_findcasecomp(name))) { if (! cptr->c_text) { cptr->c_text = tmpbuf; for (cp = tmpbuf + strlen (tmpbuf) - 1; cp >= tmpbuf; cp--) if (isspace ((unsigned char) *cp)) *cp = 0; else break; *--savecomp = cptr; tmpbuf = *nxtbuf++; } } while (state == FLDPLUS) { bufsz = rlwidth; state = m_getfld (&gstate, name, tmpbuf, &bufsz, inb); if (scnout) FPUTS (tmpbuf); } break; case BODY: /* * A slight hack ... if we have less than rlwidth characters * in the buffer, call m_getfld again. */ if ((i = strlen(tmpbuf)) < rlwidth) { bufsz = rlwidth - i; state = m_getfld (&gstate, name, tmpbuf + i, &bufsz, inb); } if (outnum == 0) { state = FILEEOF; /* stop now if scan cmd */ if (bodycomp && startbody == NULL) startbody = tmpbuf; goto finished; } if (scnout) { PUTC('\n'); FPUTS (tmpbuf); } /* * The previous code here used to call m_getfld() using * pointers to the underlying output stdio buffers to * avoid the extra copy. Tests by Markus Schnalke show * no noticeable performance loss on larger mailboxes * if we incur an extra copy, and messing around with * internal stdio buffers is becoming more and more * unportable as times go on. So from now on just deal * with the overhead of an extra copy. * * Subtle change - with the previous code tmpbuf wasn't * used, so we could reuse it for the {body} component. * Now since we're using tmpbuf as our read buffer we * need to save the beginning of the body for later. * See the above (and below) use of startbody. */ body:; if (bodycomp && startbody == NULL) { startbody = tmpbuf; tmpbuf = *nxtbuf++; } while (state == BODY) { bufsz = rlwidth; state = m_getfld (&gstate, name, tmpbuf, &bufsz, inb); if (scnout) FPUTS(tmpbuf); } goto finished; case LENERR: case FMTERR: if (innum) fprintf (stderr, "??Format error (message %d) in ", outnum ? outnum : innum); else fprintf (stderr, "??Format error in "); fprintf (stderr, "component %d\n", compnum); if (scnout) { FPUTS ("\n\nBAD MSG:\n"); FPUTS (name); PUTC('\n'); state = BODY; goto body; } goto finished; case FILEEOF: goto finished; default: adios (NULL, "getfld() returned %d", state); } } /* * format and output the scan line. */ finished: if (ferror(inb)) { advise("read", "unable to"); /* "read error" */ return SCNFAT; } /* Save and restore buffer so we don't trash our dynamic pool! */ if (bodycomp) { saved_c_text = bodycomp->c_text; bodycomp->c_text = startbody; } if (size) dat[2] = size; else if (scnout) { dat[2] = ftell(scnout); if (dat[2] == EOF) DIEWRERR(); } if ((datecomp && !datecomp->c_text) || (!size && !outnum)) { struct stat st; fstat (fileno(inb), &st); if (!size && !outnum) dat[2] = st.st_size; if (datecomp) { if (! datecomp->c_text) { if (datecomp->c_tws == NULL) NEW0(datecomp->c_tws); *datecomp->c_tws = *dlocaltime ((time_t *) &st.st_mtime); datecomp->c_flags |= CF_DATEFAB|CF_TRUE; } else { datecomp->c_flags &= ~CF_DATEFAB; } } } fmt_scan (fmt, *scanl, slwidth, dat, NULL); if (bodycomp) bodycomp->c_text = saved_c_text; if (noisy) fputs (charstring_buffer (*scanl), stdout); cptr = fmt_findcomp ("encrypted"); encrypted = cptr && cptr->c_text; /* return dynamically allocated buffers to pool */ while ((cptr = *savecomp++)) { cptr->c_text = NULL; } if (scnout && (ferror(scnout) || fclose (scnout) == EOF)) DIEWRERR(); return (state != FILEEOF ? SCNERR : encrypted ? SCNENC : SCNMSG); } /* The following two functions allow access to the global gstate above. */ void scan_finished(void) { m_getfld_state_destroy (&gstate); } void scan_detect_mbox_style (FILE *f) { m_unknown (&gstate, f); } nmh-1.7.1-RC3/uip/send.c000644 007761 000024 00000027066 13243042054 014664 0ustar00kenhstaff000000 000000 /* send.c -- send a composed message * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #ifdef OAUTH_SUPPORT # include #endif #include "../sbr/m_maildir.h" #include "../sbr/m_mktemp.h" #ifndef CYRUS_SASL # define SASLminc(a) (a) #else /* CYRUS_SASL */ # define SASLminc(a) 0 #endif /* CYRUS_SASL */ #ifndef TLS_SUPPORT # define TLSminc(a) (a) #else /* TLS_SUPPORT */ # define TLSminc(a) 0 #endif /* TLS_SUPPORT */ #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("client host", -6, CLIESW) \ X("server host", 6, SERVSW) \ X("snoop", 5, SNOOPSW) \ X("sasl", SASLminc(4), SASLSW) \ X("nosasl", SASLminc(6), NOSASLSW) \ X("saslmech mechanism", SASLminc(6), SASLMECHSW) \ X("authservice", SASLminc(0), AUTHSERVICESW) \ X("user username", SASLminc(-4), USERSW) \ X("port server-port-name/number", 4, PORTSW) \ X("tls", TLSminc(-3), TLSSW) \ X("initialtls", TLSminc(-10), INITTLSSW) \ X("notls", TLSminc(-5), NTLSSW) \ X("certverify", TLSminc(-10), CERTVERSW) \ X("nocertverify", TLSminc(-12), NOCERTVERSW) \ X("sendmail program", 0, MTSSM) \ 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; extern int inplace; extern int pushsw; extern int splitsw; extern int unique; extern int verbsw; extern char *altmsg; /* .. */ extern char *annotext; extern char *distfile; int main (int argc, char **argv) { int msgp = 0, distsw = 0, vecp; int isdf = 0, mime = 0; int msgnum, status; char *cp, *dfolder = NULL, *maildir = NULL; char buf[BUFSIZ], **ap, **argp, **arguments, *program; char *msgs[MAXARGS], **vec; const char *user = NULL, *saslmech = NULL; struct msgs *mp; struct stat st; int snoop = 0; char *auth_svc = NULL; if (nmh_init(argv[0], 1)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; vec = argsplit(postproc, &program, &vecp); vec[vecp++] = "-library"; vec[vecp++] = getcpy (m_maildir ("")); if ((cp = context_find ("fileproc"))) { vec[vecp++] = "-fileproc"; vec[vecp++] = cp; } if ((cp = context_find ("mhlproc"))) { vec[vecp++] = "-mhlproc"; vec[vecp++] = cp; } if ((cp = context_find ("credentials"))) { /* post doesn't read context so need to pass credentials. */ vec[vecp++] = "-credentials"; vec[vecp++] = cp; } while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown\n", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [file] [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case DRAFTSW: msgs[msgp++] = draft; continue; case DFOLDSW: if (dfolder) adios (NULL, "only one draft folder at a time!"); if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); dfolder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp, *cp != '@' ? TFOLDER : TSUBCWF); continue; case DMSGSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); msgs[msgp++] = cp; continue; case NDFLDSW: dfolder = NULL; isdf = NOTOK; continue; case PUSHSW: pushsw++; continue; case NPUSHSW: pushsw = 0; continue; case SPLITSW: if (!(cp = *argp++) || sscanf (cp, "%d", &splitsw) != 1) adios (NULL, "missing argument to %s", argp[-2]); continue; case UNIQSW: unique++; continue; case NUNIQSW: unique = 0; continue; case FORWSW: forwsw++; continue; case NFORWSW: forwsw = 0; continue; case VERBSW: verbsw++; vec[vecp++] = --cp; continue; case NVERBSW: verbsw = 0; vec[vecp++] = --cp; continue; case MIMESW: mime++; vec[vecp++] = --cp; continue; case NMIMESW: mime = 0; vec[vecp++] = --cp; continue; case SNOOPSW: snoop++; vec[vecp++] = --cp; continue; case DEBUGSW: debugsw++; /* FALLTHRU */ case NFILTSW: case FRMTSW: case NFRMTSW: case BITSTUFFSW: case NBITSTUFFSW: case MSGDSW: case NMSGDSW: case WATCSW: case NWATCSW: case SASLSW: case NOSASLSW: case TLSSW: case INITTLSSW: case NTLSSW: case CERTVERSW: case NOCERTVERSW: vec[vecp++] = --cp; continue; case USERSW: vec[vecp++] = --cp; if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); vec[vecp++] = cp; user = cp; continue; case AUTHSERVICESW: #ifdef OAUTH_SUPPORT if (!(auth_svc = *argp++) || *auth_svc == '-') adios (NULL, "missing argument to %s", argp[-2]); #else adios (NULL, "not built with OAuth support"); #endif continue; case SASLMECHSW: if (!(saslmech = *argp) || *saslmech == '-') adios (NULL, "missing argument to %s", argp[-1]); /* FALLTHRU */ case ALIASW: case FILTSW: case WIDTHSW: case CLIESW: case SERVSW: case PORTSW: case MTSSM: case MTSSW: case MESSAGEIDSW: vec[vecp++] = --cp; if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); vec[vecp++] = cp; continue; } } else { msgs[msgp++] = cp; } } /* * check for "Aliasfile:" profile entry */ if ((cp = context_find ("Aliasfile"))) { char *dp = NULL; for (ap = brkstring(dp = mh_xstrdup(cp), " ", "\n"); ap && *ap; ap++) { vec[vecp++] = "-alias"; vec[vecp++] = *ap; } } if (dfolder == NULL) { if (msgp == 0) { msgs[msgp++] = getcpy (m_draft (NULL, NULL, 1, &isdf)); if (stat (msgs[0], &st) == NOTOK) adios (msgs[0], "unable to stat draft file"); cp = concat ("Use \"", msgs[0], "\"? ", NULL); for (status = LISTDSW; status != YESW;) { if (!(argp = read_switch_multiword (cp, anyl))) done (1); switch (status = smatch (*argp, anyl)) { case NOSW: done (0); case YESW: break; case LISTDSW: showfile (++argp, msgs[0]); break; default: inform("say what?"); break; } } } else { for (msgnum = 0; msgnum < msgp; msgnum++) msgs[msgnum] = getcpy (m_maildir (msgs[msgnum])); } } else { if (!context_find ("path")) free (path ("./", TFOLDER)); if (!msgp) msgs[msgp++] = "cur"; maildir = m_maildir (dfolder); if (chdir (maildir) == NOTOK) adios (maildir, "unable to change directory to"); /* read folder and create message structure */ if (!(mp = folder_read (dfolder, 1))) adios (NULL, "unable to read folder %s", dfolder); /* check for empty folder */ if (mp->nummsg == 0) adios (NULL, "no messages in %s", dfolder); /* parse all the message ranges/sequences and set SELECTED */ for (msgnum = 0; msgnum < msgp; msgnum++) if (!m_convert (mp, msgs[msgnum])) done (1); seq_setprev (mp); /* set the previous-sequence */ for (msgp = 0, msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { if (is_selected (mp, msgnum)) { msgs[msgp++] = mh_xstrdup(m_name (msgnum)); unset_exists (mp, msgnum); } } mp->msgflags |= SEQMOD; seq_save (mp); } #ifdef WHATNOW go_to_it: #endif /* WHATNOW */ if ((cp = getenv ("SIGNATURE")) == NULL || *cp == 0) if ((cp = context_find ("signature")) && *cp) setenv("SIGNATURE", cp, 1); for (msgnum = 0; msgnum < msgp; msgnum++) if (stat (msgs[msgnum], &st) == NOTOK) adios (msgs[msgnum], "unable to stat draft file"); if ((annotext = getenv ("mhannotate")) == NULL || *annotext == 0) annotext = NULL; if (annotext && ((cp = getenv ("mhinplace")) != NULL && *cp != 0)) inplace = atoi (cp); if ((altmsg = getenv ("mhaltmsg")) == NULL || *altmsg == 0) altmsg = NULL; /* used by dist interface - see below */ if ((cp = getenv ("mhdist")) && *cp && (distsw = atoi (cp)) && altmsg) { vec[vecp++] = "-dist"; if ((cp = m_mktemp2(altmsg, invo_name, NULL, NULL)) == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } distfile = mh_xstrdup(cp); (void) m_unlink(distfile); if (link (altmsg, distfile) == NOTOK) { /* Cygwin with FAT32 filesystem produces EPERM. */ if (errno != EXDEV && errno != EPERM #ifdef EISREMOTE && errno != EISREMOTE #endif /* EISREMOTE */ ) adios (distfile, "unable to link %s to", altmsg); free (distfile); if ((cp = m_mktemp2(NULL, invo_name, NULL, NULL)) == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } distfile = mh_xstrdup(cp); { int in, out; struct stat st; if ((in = open (altmsg, O_RDONLY)) == NOTOK) adios (altmsg, "unable to open"); fstat(in, &st); if ((out = creat (distfile, (int) st.st_mode & 0777)) == NOTOK) adios (distfile, "unable to write"); cpydata (in, out, altmsg, distfile); close (in); close (out); } } } else { distfile = NULL; } #ifdef OAUTH_SUPPORT if (auth_svc == NULL) { if (saslmech && ! strcasecmp(saslmech, "xoauth2")) { adios (NULL, "must specify -authservice with -saslmech xoauth2"); } } else { if (user == NULL) { adios (NULL, "must specify -user with -saslmech xoauth2"); } } #else NMH_UNUSED(auth_svc); NMH_UNUSED(user); NMH_UNUSED(saslmech); #endif /* OAUTH_SUPPORT */ if (altmsg == NULL || stat (altmsg, &st) == NOTOK) { st.st_mtime = 0; st.st_dev = 0; st.st_ino = 0; } if (pushsw) push (); status = 0; closefds (3); for (msgnum = 0; msgnum < msgp; msgnum++) { switch (sendsbr (vec, vecp, program, msgs[msgnum], &st, 1, auth_svc)) { case DONE: done (++status); /* FALLTHRU */ case NOTOK: status++; /* FALLTHRU */ case OK: break; } } context_save (); /* save the context file */ done (status); return 1; } nmh-1.7.1-RC3/uip/sendsbr.c000644 007761 000024 00000063106 13243042054 015366 0ustar00kenhstaff000000 000000 /* sendsbr.c -- routines to help WhatNow/Send along * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_TIME_H # include #endif #include #ifdef OAUTH_SUPPORT #include #endif #include "../sbr/m_maildir.h" #include "../sbr/m_mktemp.h" #include "../sbr/message_id.h" #ifdef OAUTH_SUPPORT static int setup_oauth_params(char *[], int *, const char *, const char **); #endif /* OAUTH_SUPPORT */ int debugsw = 0; /* global */ int forwsw = 1; int inplace = 1; int pushsw = 0; int splitsw = -1; int unique = 0; int verbsw = 0; char *altmsg = NULL; /* .. */ char *annotext = NULL; char *distfile = NULL; static jmp_buf env; /* * static prototypes */ static void alert (char *, int); static int tmp_fd (void); static void anno (int, struct stat *); static void annoaux (int); static int splitmsg (char **, int, char *, char *, struct stat *, int); static int sendaux (char **, int, char *, char *, struct stat *); static void handle_sendfrom(char **, int *, char *, const char *); static int get_from_header_info(const char *, const char **, const char **, const char **); static const char *get_message_header_info(FILE *, char *); static void merge_profile_entry(const char *, const char *, char *[], int *); static void armed_done (int) NORETURN; /* * Entry point into (back-end) routines to send message. */ int sendsbr (char **vec, int vecp, char *program, char *draft, struct stat *st, int rename_drft, const char *auth_svc) { int status, i; pid_t child; char buffer[BUFSIZ], file[BUFSIZ]; struct stat sts; char **buildvec, *buildprogram; char *volatile drft = draft; /* nvecs is volatile to prevent warning from gcc about possible clobbering by longjmp. */ volatile int nvecs = vecp; int *nvecsp = (int *) &nvecs; /* * Run the mimebuildproc (which is by default mhbuild) on the message * with the addition of the "-auto" flag */ switch (child = fork()) { case NOTOK: adios("fork", "unable to"); break; case OK: buildvec = argsplit(buildmimeproc, &buildprogram, &i); buildvec[i++] = "-auto"; if (distfile) buildvec[i++] = "-dist"; buildvec[i++] = (char *) drft; buildvec[i] = NULL; execvp(buildprogram, buildvec); fprintf(stderr, "unable to exec "); perror(buildmimeproc); _exit(-1); break; default: if (pidXwait(child, buildmimeproc)) return NOTOK; break; } done=armed_done; switch (setjmp (env)) { case OK: /* * If given -push and -unique (which is undocumented), then * rename the draft file. I'm not quite sure why. */ if (pushsw && unique) { char *cp = m_mktemp2(drft, invo_name, NULL, NULL); if (cp == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } if (rename (drft, strncpy(file, cp, sizeof(file))) == NOTOK) adios (file, "unable to rename %s to", drft); drft = file; } /* * Add in any necessary profile entries for xoauth */ if (auth_svc) { #ifdef OAUTH_SUPPORT const char *errmsg; if (setup_oauth_params(vec, nvecsp, auth_svc, &errmsg) != OK) { adios(NULL, errmsg); } #else adios(NULL, "send built without OAUTH_SUPPORT, " "so auth_svc %s is not supported", auth_svc); #endif /* OAUTH_SUPPORT */ } /* * Rework the vec based on From: header in draft, as specified * by sendfrom-address entries in profile. */ if (context_find_prefix("sendfrom-")) { handle_sendfrom(vec, nvecsp, draft, auth_svc); } /* * Check if we need to split the message into * multiple messages of type "message/partial". */ if (splitsw >= 0 && !distfile && stat ((char *) drft, &sts) != NOTOK && sts.st_size >= CPERMSG) { status = splitmsg (vec, nvecs, program, drft, st, splitsw) ? NOTOK : OK; } else { status = sendaux (vec, nvecs, program, drft, st) ? NOTOK : OK; } /* rename the original draft */ if (rename_drft && status == OK && rename (drft, strncpy (buffer, m_backup (drft), sizeof(buffer))) == NOTOK) advise (buffer, "unable to rename %s to", drft); break; default: status = DONE; break; } done=exit; if (distfile) (void) m_unlink (distfile); return status; } /* * Split large message into several messages of * type "message/partial" and send them. */ static int splitmsg (char **vec, int vecp, char *program, char *drft, struct stat *st, int delay) { int compnum, nparts, partno, state, status; long pos, start; time_t clock; char *cp, *dp, buffer[NMH_BUFSIZ], msgid[BUFSIZ]; 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"); cp = dp = NULL; start = 0L; /* * Scan through the message and examine the various header fields, * as well as locate the beginning of the message body. */ 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: compnum++; /* * This header field is discarded. */ if (!strcasecmp (name, "Message-ID")) { while (state == FLDPLUS) { bufsz = sizeof buffer; state = m_getfld (&gstate, name, buffer, &bufsz, in); } } else if (uprf (name, XXX_FIELD_PRF) || !strcasecmp (name, VRSN_FIELD) || !strcasecmp (name, "Subject") || !strcasecmp (name, "Encrypted")) { /* * These header fields are copied to the enclosed * header of the first message in the collection * of message/partials. For the "Subject" header * field, we also record it, so that a modified * version of it, can be copied to the header * of each message/partial in the collection. */ if (!strcasecmp (name, "Subject")) { size_t sublen; strncpy (subject, buffer, BUFSIZ); sublen = strlen (subject); if (sublen > 0 && subject[sublen - 1] == '\n') subject[sublen - 1] = '\0'; } dp = add (concat (name, ":", buffer, NULL), dp); while (state == FLDPLUS) { bufsz = sizeof buffer; state = m_getfld (&gstate, name, buffer, &bufsz, in); dp = add (buffer, dp); } } else { /* * These header fields are copied to the header of * each message/partial in the collection. */ cp = add (concat (name, ":", buffer, NULL), cp); while (state == FLDPLUS) { bufsz = sizeof buffer; state = m_getfld (&gstate, name, buffer, &bufsz, in); cp = add (buffer, cp); } } start = ftell (in) + 1; continue; case BODY: case FILEEOF: break; case LENERR: case FMTERR: adios (NULL, "message format error in component #%d", compnum); default: adios (NULL, "getfld () returned %d", state); } break; } m_getfld_state_destroy (&gstate); if (cp == NULL) adios (NULL, "headers missing from draft"); nparts = 1; pos = start; while (fgets (buffer, sizeof buffer, in)) { long len; if ((pos += (len = strlen (buffer))) > CPERMSG) { nparts++; pos = len; } } /* Only one part, nothing to split */ if (nparts == 1) { free (cp); mh_xfree(dp); fclose (in); return sendaux (vec, vecp, program, drft, st); } if (!pushsw) { printf ("Sending as %d Partial Messages\n", nparts); fflush (stdout); } status = OK; vec[vecp++] = "-partno"; vec[vecp++] = partnum; if (delay == 0) vec[vecp++] = "-queued"; time (&clock); snprintf (msgid, sizeof(msgid), "%s", message_id (clock, 0)); fseek (in, start, SEEK_SET); for (partno = 1; partno <= nparts; partno++) { char tmpdrf[BUFSIZ]; FILE *out; char *cp = m_mktemp2(drft, invo_name, NULL, &out); if (cp == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } strncpy(tmpdrf, cp, sizeof(tmpdrf)); /* * Output the header fields */ fputs (cp, out); fprintf (out, "Subject: %s (part %d of %d)\n", subject, partno, nparts); fprintf (out, "%s: %s\n", VRSN_FIELD, VRSN_VALUE); fprintf (out, "%s: message/partial; id=\"%s\";\n", TYPE_FIELD, msgid); fprintf (out, "\tnumber=%d; total=%d\n", partno, nparts); fprintf (out, "%s: part %d of %d\n\n", DESCR_FIELD, partno, nparts); /* * If this is the first in the collection, output the * header fields we are encapsulating at the beginning * of the body of the first message. */ if (partno == 1) { if (dp) fputs (dp, out); fprintf (out, "Message-ID: %s\n", msgid); fprintf (out, "\n"); } pos = 0; for (;;) { long len; if (!fgets (buffer, sizeof buffer, in)) { if (partno == nparts) break; adios (NULL, "premature eof"); } if ((pos += (len = strlen (buffer))) > CPERMSG) { fseek (in, -len, SEEK_CUR); break; } fputs (buffer, out); } if (fflush (out)) adios (tmpdrf, "error writing to"); fclose (out); if (!pushsw && verbsw) { putchar('\n'); fflush (stdout); } /* Pause here, if a delay is specified */ if (delay > 0 && 1 < partno && partno <= nparts) { if (!pushsw) { printf ("pausing %d seconds before sending part %d...\n", delay, partno); fflush (stdout); } sleep ((unsigned int) delay); } snprintf (partnum, sizeof(partnum), "%d", partno); status = sendaux (vec, vecp, program, tmpdrf, st); (void) m_unlink (tmpdrf); if (status != OK) break; /* * This is so sendaux will only annotate * the altmsg the first time it is called. */ annotext = NULL; } free (cp); mh_xfree(dp); fclose (in); /* close the draft */ return status; } /* * Annotate original message, and * call `postproc' (which is passed down in "program") to send message. */ static int sendaux (char **vec, int vecp, char *program, char *drft, struct stat *st) { pid_t child_id; int i, status, fd, fd2; char backup[BUFSIZ], buf[BUFSIZ]; fd = pushsw ? tmp_fd () : NOTOK; fd2 = NOTOK; if (annotext) { if ((fd2 = tmp_fd ()) != NOTOK) { vec[vecp++] = "-idanno"; snprintf (buf, sizeof(buf), "%d", fd2); vec[vecp++] = buf; } else { inform("unable to create temporary file in %s for " "annotation list, continuing...", get_temp_dir()); } } vec[vecp++] = drft; if (distfile && distout (drft, distfile, backup) == NOTOK) done (1); vec[vecp] = NULL; for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++) sleep (5); switch (child_id) { case -1: /* oops -- fork error */ adios ("fork", "unable to"); break; /* NOT REACHED */ case 0: /* * child process -- send it * * If fd is OK, then we are pushing and fd points to temp * file, so capture anything on stdout and stderr there. */ if (fd != NOTOK) { dup2 (fd, fileno (stdout)); dup2 (fd, fileno (stderr)); close (fd); } execvp (program, vec); fprintf (stderr, "unable to exec "); perror (postproc); _exit (-1); default: /* * parent process -- wait for it */ if ((status = pidwait(child_id, NOTOK)) == OK) { if (annotext && fd2 != NOTOK) anno (fd2, st); } else { /* * If postproc failed, and we have good fd (which means * we pushed), then mail error message (and possibly the * draft) back to the user. */ if (fd != NOTOK) { alert (drft, fd); close (fd); } else { inform("message not delivered to anyone"); } if (annotext && fd2 != NOTOK) close (fd2); if (distfile) { (void) m_unlink (drft); if (rename (backup, drft) == NOTOK) advise (drft, "unable to rename %s to", backup); } } break; } return status; } /* * Mail error notification (and possibly a copy of the * message) back to the user, using the mailproc */ static void alert (char *file, int out) { pid_t child_id; int i, in, argp; char buf[BUFSIZ]; char *program; char **arglist; for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++) sleep (5); switch (child_id) { case NOTOK: /* oops -- fork error */ advise ("fork", "unable to"); /* FALLTHRU */ case OK: /* child process -- send it */ SIGNAL (SIGHUP, SIG_IGN); SIGNAL (SIGINT, SIG_IGN); SIGNAL (SIGQUIT, SIG_IGN); SIGNAL (SIGTERM, SIG_IGN); if (forwsw) { if ((in = open (file, O_RDONLY)) == NOTOK) { admonish (file, "unable to re-open"); } else { lseek(out, 0, SEEK_END); strncpy (buf, "\nMessage not delivered to anyone.\n", sizeof(buf)); if (write (out, buf, strlen (buf)) < 0) { advise (file, "write"); } strncpy (buf, "\n------- Unsent Draft\n\n", sizeof(buf)); if (write (out, buf, strlen (buf)) < 0) { advise (file, "write"); } cpydgst (in, out, file, "temporary file"); close (in); strncpy (buf, "\n------- End of Unsent Draft\n", sizeof(buf)); if (write (out, buf, strlen (buf)) < 0) { advise (file, "write"); } if (rename (file, strncpy (buf, m_backup (file), sizeof(buf))) == NOTOK) admonish (buf, "unable to rename %s to", file); } } lseek(out, 0, SEEK_SET); dup2 (out, fileno (stdin)); close (out); /* create subject for error notification */ snprintf (buf, sizeof(buf), "send failed on %s", forwsw ? "enclosed draft" : file); 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); default: /* no waiting... */ break; } } static int tmp_fd (void) { int fd; char *tfile; if ((tfile = m_mktemp2(NULL, invo_name, &fd, NULL)) == NULL) return NOTOK; if (debugsw) inform("temporary file %s selected", tfile); else if (m_unlink (tfile) == NOTOK) advise (tfile, "unable to remove"); return fd; } static void anno (int fd, struct stat *st) { pid_t child_id; sigset_t set, oset; static char *cwd = NULL; struct stat st2; if (altmsg && (stat (altmsg, &st2) == NOTOK || st->st_mtime != st2.st_mtime || st->st_dev != st2.st_dev || st->st_ino != st2.st_ino)) { if (debugsw) inform("$mhaltmsg mismatch, continuing..."); return; } child_id = debugsw ? NOTOK : fork (); switch (child_id) { case NOTOK: /* oops */ if (!debugsw) inform("unable to fork, so doing annotations by hand..."); if (cwd == NULL) cwd = mh_xstrdup(pwd ()); /* FALLTHRU */ case OK: /* block a few signals */ sigemptyset (&set); sigaddset (&set, SIGHUP); sigaddset (&set, SIGINT); sigaddset (&set, SIGQUIT); sigaddset (&set, SIGTERM); sigprocmask (SIG_BLOCK, &set, &oset); unregister_for_removal(0); annoaux (fd); if (child_id == OK) _exit (0); /* reset the signal mask */ sigprocmask (SIG_SETMASK, &oset, &set); if (chdir (cwd) < 0) { advise (cwd, "chdir"); } break; default: /* no waiting... */ close (fd); break; } } static void annoaux (int fd) { int fd2, fd3, msgnum; char *cp, *folder, *maildir; char buffer[BUFSIZ], **ap; FILE *fp; struct msgs *mp; if ((folder = getenv ("mhfolder")) == NULL || *folder == 0) { if (debugsw) inform("$mhfolder not set, continuing..."); return; } maildir = m_maildir (folder); if (chdir (maildir) == NOTOK) { if (debugsw) admonish (maildir, "unable to change directory to"); return; } if (!(mp = folder_read (folder, 0))) { if (debugsw) inform("unable to read folder %s, continuing...", folder); return; } /* check for empty folder */ if (mp->nummsg == 0) { if (debugsw) inform("no messages in %s, continuing...", folder); goto oops; } if ((cp = getenv ("mhmessages")) == NULL || *cp == 0) { if (debugsw) inform("$mhmessages not set, continuing..."); goto oops; } if (!debugsw /* MOBY HACK... */ && pushsw && (fd3 = open ("/dev/null", O_RDWR)) != NOTOK && (fd2 = dup (fileno (stderr))) != NOTOK) { dup2 (fd3, fileno (stderr)); close (fd3); } else fd2 = NOTOK; for (ap = brkstring (cp = mh_xstrdup(cp), " ", NULL); *ap; ap++) m_convert (mp, *ap); free (cp); if (fd2 != NOTOK) dup2 (fd2, fileno (stderr)); if (mp->numsel == 0) { if (debugsw) inform("no messages to annotate, continuing..."); goto oops; } lseek(fd, 0, SEEK_SET); if ((fp = fdopen (fd, "r")) == NULL) { if (debugsw) inform("unable to fdopen annotation list, continuing..."); goto oops; } cp = NULL; while (fgets (buffer, sizeof(buffer), fp) != NULL) cp = add (buffer, cp); fclose (fp); if (debugsw) inform("annotate%s with %s: \"%s\"", inplace ? " inplace" : "", annotext, cp); for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { if (is_selected(mp, msgnum)) { if (debugsw) inform("annotate message %d", msgnum); annotate (m_name (msgnum), annotext, cp, inplace, 1, -2, 0); } } free (cp); oops: folder_free (mp); /* free folder/message structure */ } static void handle_sendfrom(char **vec, int *vecp, char *draft, const char *auth_svc) { const char *addr, *host; const char *message; /* Extract address and host from From: header line in draft. */ if (get_from_header_info(draft, &addr, &host, &message) != OK) { adios(draft, message); } /* Merge in any address or host specific switches to post(1) from profile. */ merge_profile_entry(addr, host, vec, vecp); free((void *) host); free((void *) addr); vec[*vecp] = NULL; { char **vp; for (vp = vec; *vp; ++vp) { if (strcmp(*vp, "xoauth2") == 0) { #ifdef OAUTH_SUPPORT if (setup_oauth_params(vec, vecp, auth_svc, &message) != OK) { adios(NULL, message); } break; #else NMH_UNUSED(auth_svc); adios(NULL, "send built without OAUTH_SUPPORT, " "so -saslmech xoauth2 is not supported"); #endif /* OAUTH_SUPPORT */ } } } } #ifdef OAUTH_SUPPORT /* * For XOAUTH2, append profile entries so post can do the heavy lifting */ static int setup_oauth_params(char *vec[], int *vecp, const char *auth_svc, const char **message) { const char *saslmech = NULL, *user = NULL; mh_oauth_service_info svc; char errbuf[256]; int i; /* Make sure we have all the information we need. */ for (i = 1; i < *vecp; ++i) { /* Don't support abbreviated switches, to avoid collisions in the future if new ones are added. */ if (! strcmp(vec[i-1], "-saslmech")) { saslmech = vec[i]; } else if (! strcmp(vec[i-1], "-user")) { user = vec[i]; } else if (! strcmp(vec[i-1], "-authservice")) { auth_svc = vec[i]; } } if (auth_svc == NULL) { if (saslmech && ! strcasecmp(saslmech, "xoauth2")) { *message = "must specify -authservice with -saslmech xoauth2"; return NOTOK; } } else { if (user == NULL) { *message = "must specify -user with -saslmech xoauth2"; return NOTOK; } if (saslmech && ! strcasecmp(saslmech, "xoauth2")) { if (! mh_oauth_get_service_info(auth_svc, &svc, errbuf, sizeof(errbuf))) adios(NULL, "Unable to retrieve oauth profile entries: %s", errbuf); vec[(*vecp)++] = mh_xstrdup("-authservice"); vec[(*vecp)++] = mh_xstrdup(auth_svc); vec[(*vecp)++] = mh_xstrdup("-oauthcredfile"); vec[(*vecp)++] = mh_xstrdup(mh_oauth_cred_fn(auth_svc)); vec[(*vecp)++] = mh_xstrdup("-oauthclientid"); vec[(*vecp)++] = getcpy(svc.client_id); vec[(*vecp)++] = mh_xstrdup("-oauthclientsecret"); vec[(*vecp)++] = getcpy(svc.client_secret); vec[(*vecp)++] = mh_xstrdup("-oauthauthendpoint"); vec[(*vecp)++] = getcpy(svc.auth_endpoint); vec[(*vecp)++] = mh_xstrdup("-oauthredirect"); vec[(*vecp)++] = getcpy(svc.redirect_uri); vec[(*vecp)++] = mh_xstrdup("-oauthtokenendpoint"); vec[(*vecp)++] = getcpy(svc.token_endpoint); vec[(*vecp)++] = mh_xstrdup("-oauthscope"); vec[(*vecp)++] = getcpy(svc.scope); } } return 0; } #endif /* OAUTH_SUPPORT */ /* * Extract user and domain from From: header line in draft. */ static int get_from_header_info(const char *filename, const char **addr, const char **host, const char **message) { struct stat st; FILE *in; if (stat (filename, &st) == NOTOK) { *message = "unable to stat draft file"; return NOTOK; } if ((in = fopen (filename, "r")) != NULL) { /* There must be a non-blank Envelope-From or {Resent-}Sender or {Resent-}From header. */ char *addrformat = "%(addr{Envelope-From})"; char *hostformat = "%(host{Envelope-From})"; if ((*addr = get_message_header_info (in, addrformat)) == NULL || !**addr) { addrformat = distfile == NULL ? "%(addr{Sender})" : "%(addr{Resent-Sender})"; hostformat = distfile == NULL ? "%(host{Sender})" : "%(host{Resent-Sender})"; if ((*addr = get_message_header_info (in, addrformat)) == NULL) { addrformat = distfile == NULL ? "%(addr{From})" : "%(addr{Resent-From})"; hostformat = distfile == NULL ? "%(host{From})" : "%(host{Resent-From})"; if ((*addr = get_message_header_info (in, addrformat)) == NULL) { *message = "unable to find sender address in"; fclose(in); return NOTOK; } } } /* Use the hostformat that corresponds to the successful addrformat. */ if ((*host = get_message_header_info(in, hostformat)) == NULL) { *message = "unable to find sender host"; fclose(in); return NOTOK; } fclose(in); return OK; } *message = "unable to open"; return NOTOK; } /* * Get formatted information from header of a message. * Adapted from process_single_file() in uip/fmttest.c. */ static const char * get_message_header_info(FILE *in, char *format) { int dat[5]; struct format *fmt; struct stat st; int parsing_header; m_getfld_state_t gstate = 0; charstring_t buffer = charstring_create(0); char *retval; dat[0] = dat[1] = dat[4] = 0; dat[2] = fstat(fileno(in), &st) == 0 ? st.st_size : 0; dat[3] = INT_MAX; (void) fmt_compile(new_fs(NULL, NULL, format), &fmt, 1); free_fs(); /* * Read in the message and process the header. */ rewind (in); parsing_header = 1; do { char name[NAMESZ], rbuf[NMH_BUFSIZ]; int bufsz = sizeof rbuf; int state = m_getfld(&gstate, name, rbuf, &bufsz, in); switch (state) { case FLD: case FLDPLUS: { int bucket = fmt_addcomptext(name, rbuf); if (bucket != -1) { while (state == FLDPLUS) { bufsz = sizeof rbuf; state = m_getfld(&gstate, name, rbuf, &bufsz, in); fmt_appendcomp(bucket, name, rbuf); } } while (state == FLDPLUS) { bufsz = sizeof rbuf; state = m_getfld(&gstate, name, rbuf, &bufsz, in); } break; } default: parsing_header = 0; } } while (parsing_header); m_getfld_state_destroy(&gstate); fmt_scan(fmt, buffer, INT_MAX, dat, NULL); fmt_free(fmt, 1); /* Trim trailing newline, if any. */ retval = rtrim(charstring_buffer_copy((buffer))); charstring_free(buffer); if (*retval) return retval; free(retval); return NULL; } /* * Look in profile for entry corresponding to addr or host, and add its contents to vec. * * Could do some of this automatically, by looking for: * 1) access-$(mbox{from}) in oauth-svc file using mh_oauth_cred_load(), which isn't * static and doesn't have side effects; free the result with mh_oauth_cred_free()) * 2) machine $(mbox{from}) in creds * If no -server passed in from profile or commandline, could use smtp..com for gmail, * but that might not generalize for other svcs. */ static void merge_profile_entry(const char *addr, const char *host, char *vec[], int *vecp) { char *addr_entry = concat("sendfrom-", addr, NULL); char *profile_entry = context_find(addr_entry); free(addr_entry); if (profile_entry == NULL) { /* No entry for the user. Look for one for the host. */ char *host_entry = concat("sendfrom-", host, NULL); profile_entry = context_find(host_entry); free(host_entry); } /* Use argsplit() to do the real work of splitting the args in the profile entry. */ if (profile_entry && *profile_entry) { int profile_vecp; char *file; char **profile_vec = argsplit(profile_entry, &file, &profile_vecp); int i; for (i = 0; i < profile_vecp; ++i) { vec[(*vecp)++] = getcpy(profile_vec[i]); } arglist_free(file, profile_vec); } } static void NORETURN armed_done (int status) { longjmp (env, status ? status : NOTOK); } nmh-1.7.1-RC3/uip/show.c000644 007761 000024 00000030555 13243042054 014710 0ustar00kenhstaff000000 000000 /* show.c -- show/list messages * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include "../sbr/m_maildir.h" #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) \ /* \ * switches for mhlproc \ */ \ X("concat", 0, CONCATSW) \ X("noconcat", 0, NCONCATSW) \ /* \ * switches for mhshow \ */ \ X("part number", 0, PARTSW) \ X("type content", 0, TYPESW) \ X("prefer content", 0, PREFERSW) \ X("markform file", 0, MARKFORMSW) \ X("rcache policy", 0, RCACHESW) \ X("wcache policy", 0, WCACHESW) \ #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 */ static int is_nontext(char *); #define SHOW 0 #define NEXT 1 #define PREV 2 int main (int argc, char **argv) { int draftsw = 0, headersw = 1; int nshow = 0, checkmime = 1, mime = 0; int isdf = 0, mode = SHOW, msgnum; char *cp, *maildir, *file = NULL, *folder = NULL, *proc, *program; char buf[BUFSIZ], **argp, **arguments; struct msgs *mp = NULL; struct msgs_array msgs = { 0, 0, NULL }; struct msgs_array vec = { 0, 0, NULL }, non_mhl_vec = { 0, 0, NULL }; if (nmh_init(argv[0], 1)) { return 1; } if (!strcasecmp (invo_name, "next")) { mode = NEXT; } else if (!strcasecmp (invo_name, "prev")) { mode = PREV; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case HEADSW: headersw = 1; goto non_mhl_switches; case NHEADSW: headersw = 0; /* FALLTHRU */ case CONCATSW: case NCONCATSW: non_mhl_switches: /* mhl can't handle these, so keep them separate. */ app_msgarg(&non_mhl_vec, --cp); continue; case UNKWNSW: case NPROGSW: case NFMTPROCSW: app_msgarg(&vec, --cp); continue; case HELPSW: snprintf (buf, sizeof(buf), "%s [+folder] %s[switches] [switches for showproc]", invo_name, mode == SHOW ? "[msgs] ": ""); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case DRFTSW: if (file) adios (NULL, "only one file at a time!"); draftsw++; if (mode == SHOW) continue; usage: adios (NULL, "usage: %s [+folder] [switches] [switches for showproc]", invo_name); case FILESW: if (mode != SHOW) goto usage; if (draftsw || file) adios (NULL, "only one file at a time!"); if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); file = path (cp, TFILE); continue; case FORMSW: app_msgarg(&vec, --cp); if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); app_msgarg(&vec, getcpy (etcpath(cp))); continue; case PROGSW: case LENSW: case WIDTHSW: case FMTPROCSW: case PARTSW: case TYPESW: case PREFERSW: case MARKFORMSW: case RCACHESW: case WCACHESW: app_msgarg(&vec, --cp); if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); app_msgarg(&vec, cp); continue; case SHOWSW: if (!(showproc = *argp++) || *showproc == '-') adios (NULL, "missing argument to %s", argp[-2]); nshow = 0; continue; case NSHOWSW: nshow++; continue; case SHOWMIMESW: if (!(showmimeproc = *argp++) || *showmimeproc == '-') adios (NULL, "missing argument to %s", argp[-2]); nshow = 0; continue; case CHECKMIMESW: checkmime++; continue; case NOCHECKMIMESW: checkmime = 0; continue; } } if (*cp == '+' || *cp == '@') { if (folder) adios (NULL, "only one folder at a time!"); else folder = pluspath (cp); } else { if (mode != SHOW) goto usage; app_msgarg(&msgs, cp); } } if (!context_find ("path")) free (path ("./", TFOLDER)); if (draftsw || file) { if (msgs.size) adios (NULL, "only one file at a time!"); if (draftsw) app_msgarg(&vec, getcpy (m_draft (folder, NULL, 1, &isdf))); else app_msgarg(&vec, file); headersw = 0; goto go_to_it; } if (!msgs.size) { switch (mode) { case NEXT: app_msgarg(&msgs, "next"); break; case PREV: app_msgarg(&msgs, "prev"); break; default: app_msgarg(&msgs, "cur"); break; } } if (!folder) folder = getfolder (1); maildir = m_maildir (folder); if (chdir (maildir) == NOTOK) adios (maildir, "unable to change directory to"); /* read folder and create message structure */ if (!(mp = folder_read (folder, 1))) adios (NULL, "unable to read folder %s", folder); /* check for empty folder */ if (mp->nummsg == 0) adios (NULL, "no messages in %s", folder); /* parse all the message ranges/sequences and set SELECTED */ for (msgnum = 0; msgnum < msgs.size; msgnum++) if (!m_convert (mp, msgs.msgs[msgnum])) done (1); /* * Set the SELECT_UNSEEN bit for all the SELECTED messages, * since we will use that as a tag to know which messages * to remove from the "unseen" sequence. */ for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) if (is_selected(mp, msgnum)) set_unseen (mp, msgnum); seq_setprev (mp); /* set the Previous-Sequence */ seq_setunseen (mp, 1); /* unset the Unseen-Sequence */ for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) if (is_selected(mp, msgnum)) app_msgarg(&vec, mh_xstrdup(m_name (msgnum))); seq_setcur (mp, mp->hghsel); /* update current message */ seq_save (mp); /* synchronize sequences */ context_replace (pfolder, folder); /* update current folder */ context_save (); /* save the context file */ go_to_it: ; /* * Decide which "proc" to use */ if (nshow) { proc = catproc; } else { /* check if any messages are non-text MIME messages */ if (! mime && checkmime) { if (!draftsw && !file) { /* loop through selected messages and check for MIME */ for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) if (is_selected (mp, msgnum) && is_nontext (m_name (msgnum))) { mime = 1; break; } } else { /* check the file or draft for MIME */ if (is_nontext (vec.msgs[vec.size - 1])) mime = 1; } } /* Set the "proc" */ if (mime) proc = showmimeproc; else proc = showproc; } if (folder && !draftsw && !file) setenv("mhfolder", folder, 1); if (strcmp (r1bindex (proc, '/'), "cat") == 0) { if (headersw && vec.size == 1) printf ("(Message %s:%s)\n", folder, vec.msgs[0]); } else if (strcmp (r1bindex (proc, '/'), "mhl") == 0) { if (headersw && vec.size == 1) printf ("(Message %s:%s)\n", folder, vec.msgs[0]); /* If "mhl", then run it internally */ argsplit_insert(&vec, "mhl", &program); app_msgarg(&vec, NULL); mhl (vec.size, vec.msgs); done (0); } else { int i; char **mp; for (i = 0, mp = non_mhl_vec.msgs; i < non_mhl_vec.size; ++i, ++mp) { if (draftsw || file) { /* Insert the switch before the filename. */ app_msgarg(&vec, vec.msgs[vec.size - 1]); vec.msgs[vec.size - 2] = *mp; } else { app_msgarg(&vec, *mp); } } if (strcmp (r1bindex (proc, '/'), "mhn") == 0) { /* Add "-file" if showing file or draft, */ if (draftsw || file) { app_msgarg(&vec, vec.msgs[vec.size - 1]); vec.msgs[vec.size - 2] = "-file"; } /* and add -show for backward compatibility */ app_msgarg(&vec, "-show"); } else if (strcmp (r1bindex (proc, '/'), "mhshow") == 0) { /* If "mhshow", add "-file" if showing file or draft. */ if (draftsw || file) { app_msgarg(&vec, vec.msgs[vec.size - 1]); vec.msgs[vec.size - 2] = "-file"; } } else { if (headersw && vec.size == 1) printf ("(Message %s:%s)\n", folder, vec.msgs[0]); } } fflush (stdout); argsplit_insert(&vec, proc, &program); app_msgarg(&vec, NULL); execvp (program, vec.msgs); adios (proc, "unable to exec"); return 0; /* dead code to satisfy the compiler */ } /* * Check if a message or file contains any non-text parts */ static int is_nontext (char *msgnam) { int result, state; char *bp, *dp, *cp; char buf[NMH_BUFSIZ], name[NAMESZ]; FILE *fp; m_getfld_state_t gstate = 0; if ((fp = fopen (msgnam, "r")) == NULL) return 0; for (;;) { int bufsz = sizeof buf; switch (state = m_getfld (&gstate, name, buf, &bufsz, fp)) { case FLD: case FLDPLUS: /* * Check Content-Type field */ if (!strcasecmp (name, TYPE_FIELD)) { int passno; char c; cp = mh_xstrdup(buf); while (state == FLDPLUS) { bufsz = sizeof buf; state = m_getfld (&gstate, name, buf, &bufsz, fp); cp = add (buf, cp); } bp = cp; passno = 1; again: for (; isspace ((unsigned char) *bp); bp++) continue; if (*bp == '(') { int i; for (bp++, i = 0;;) { switch (*bp++) { case '\0': invalid: result = 0; goto out; case '\\': if (*bp++ == '\0') goto invalid; continue; case '(': i++; continue; default: continue; case ')': if (--i < 0) break; continue; } break; } } if (passno == 2) { if (*bp != '/') goto invalid; bp++; passno = 3; goto again; } for (dp = bp; istoken (*dp); dp++) continue; c = *dp; *dp = '\0'; if (!*bp) goto invalid; if (passno > 1) { if ((result = (strcasecmp (bp, "plain") != 0))) goto out; *dp = c; for (dp++; isspace ((unsigned char) *dp); dp++) continue; if (*dp) { if ((result = !uprf (dp, "charset"))) goto out; dp += LEN("charset"); while (isspace ((unsigned char) *dp)) dp++; if (*dp++ != '=') goto invalid; while (isspace ((unsigned char) *dp)) dp++; if (*dp == '"') { if ((bp = strchr(++dp, '"'))) *bp = '\0'; } else { for (bp = dp; *bp; bp++) if (!istoken (*bp)) { *bp = '\0'; break; } } } else { /* Default character set */ dp = "US-ASCII"; } /* Check the character set */ result = !check_charset (dp, strlen (dp)); } else { if (!(result = (strcasecmp (bp, "text") != 0))) { *dp = c; bp = dp; passno = 2; goto again; } } out: free (cp); if (result) { fclose (fp); m_getfld_state_destroy (&gstate); return result; } break; } /* * Check Content-Transfer-Encoding field */ if (!strcasecmp (name, ENCODING_FIELD)) { cp = mh_xstrdup(buf); while (state == FLDPLUS) { bufsz = sizeof buf; state = m_getfld (&gstate, name, buf, &bufsz, fp); cp = add (buf, cp); } for (bp = cp; isspace ((unsigned char) *bp); bp++) continue; for (dp = bp; istoken ((unsigned char) *dp); dp++) continue; *dp = '\0'; result = (strcasecmp (bp, "7bit") && strcasecmp (bp, "8bit") && strcasecmp (bp, "binary")); free (cp); if (result) { fclose (fp); m_getfld_state_destroy (&gstate); return result; } break; } /* * Just skip the rest of this header * field and go to next one. */ while (state == FLDPLUS) { bufsz = sizeof buf; state = m_getfld (&gstate, name, buf, &bufsz, fp); } break; /* * We've passed the message header, * so message is just text. */ default: fclose (fp); m_getfld_state_destroy (&gstate); return 0; } } } nmh-1.7.1-RC3/uip/slocal.c000644 007761 000024 00000101322 13243042054 015174 0ustar00kenhstaff000000 000000 /* slocal.c -- asynchronously filter and deliver new mail * * 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. */ /* * Under sendmail, users should add the line * * "| /usr/local/nmh/lib/slocal" * * to their $HOME/.forward file. * */ /* Changed to use getutent() and friends. Assumes that when getutent() exists, * a number of other things also exist. Please check. * Ruud de Rooij Sun, 28 May 2000 17:28:55 +0200 */ #include #include #include #include #include #include #include #include #include "../sbr/lock_file.h" #include "../sbr/m_mktemp.h" #include #include #include /* Hopefully, grp.h declares initgroups(). If we run into a platform where it doesn't, we could consider declaring it here as well. */ #include /* This define is needed for Berkeley db v2 and above to * make the header file expose the 'historical' ndbm APIs. * We define it unconditionally because this is simple and * harmless. */ #define DB_DBM_HSEARCH 1 #ifdef DB_DBM_HSEARCH #endif /* Use DB_DBM_HSEARCH to prevent warning from gcc -Wunused-macros. */ #ifdef NDBM_HEADER #include NDBM_HEADER #endif #ifdef HAVE_GETUTXENT #include #endif /* HAVE_GETUTXENT */ #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 */ static int utmped = 0; /* have we scanned umtp(x) file yet */ static int suppressdup = 0; /* are we suppressing duplicate messages? */ static int verbose = 0; static int debug = 0; static char *addr = NULL; static char *user = NULL; static char *info = NULL; static char *file = NULL; static char *sender = NULL; static char *envelope = NULL; /* envelope information ("From " line) */ static char *mbox = NULL; static char *home = NULL; static struct passwd *pw; /* passwd file entry */ static char ddate[BUFSIZ]; /* record the delivery date */ struct tws *now; static jmp_buf myctx; /* flags for pair->p_flags */ #define P_NIL 0x00 #define P_ADR 0x01 /* field is address */ #define P_HID 0x02 /* special (fake) field */ #define P_CHK 0x04 struct pair { char *p_name; char *p_value; char p_flags; }; #define NVEC 100 /* * Lookup table for matching fields and patterns * in messages. The rest of the table is added * when the message is parsed. */ static struct pair hdrs[NVEC + 1] = { { "source", NULL, P_HID }, { "addr", NULL, P_HID }, { "Return-Path", NULL, P_ADR }, { "Reply-To", NULL, P_ADR }, { "From", NULL, P_ADR }, { "Sender", NULL, P_ADR }, { "To", NULL, P_ADR }, { "cc", NULL, P_ADR }, { "Resent-Reply-To", NULL, P_ADR }, { "Resent-From", NULL, P_ADR }, { "Resent-Sender", NULL, P_ADR }, { "Resent-To", NULL, P_ADR }, { "Resent-cc", NULL, P_ADR }, { NULL, NULL, 0 } }; /* * The list of builtin variables to expand in a string * before it is executed by the "pipe" or "qpipe" action. */ static struct pair vars[] = { { "sender", NULL, P_NIL }, { "address", NULL, P_NIL }, { "size", NULL, P_NIL }, { "reply-to", NULL, P_CHK }, { "info", NULL, P_NIL }, { NULL, NULL, 0 } }; extern char **environ; /* * static prototypes */ static int localmail (int, char *); static int usr_delivery (int, char *, int); static int split (char *, char **); static int parse (int); static void expand (char *, char *, int); static void glob (int); static struct pair *lookup (struct pair *, char *); static int logged_in (void); static int timely (char *, char *); static int usr_file (int, char *, int); static int usr_pipe (int, char *, char *, char **, int); static int usr_folder (int, char *); static void alrmser (int); static void get_sender (char *, char **); static int copy_message (int, char *, int); static void verbose_printf (char *fmt, ...); static void adorn (char *, char *, ...); static void debug_printf (char *fmt, ...); static int suppress_duplicates (int, char *); static char *trim (char *); int main (int argc, char **argv) { int fd, status; FILE *fp; char *cp, *mdlvr = NULL, buf[BUFSIZ]; char mailbox[BUFSIZ], tmpfil[BUFSIZ]; char **argp, **arguments; if (nmh_init(argv[0], 0 /* use context_foil() */)) { return 1; } mts_init (); arguments = getarguments (invo_name, argc, argv, 0); argp = arguments; /* Parse arguments */ while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [switches]", invo_name); print_help (buf, switches, 0); done (0); case VERSIONSW: print_version(invo_name); done (0); case ADDRSW: if (!(addr = *argp++))/* allow -xyz arguments */ adios (NULL, "missing argument to %s", argp[-2]); continue; case INFOSW: if (!(info = *argp++))/* allow -xyz arguments */ adios (NULL, "missing argument to %s", argp[-2]); continue; case USERSW: if (!(user = *argp++))/* allow -xyz arguments */ adios (NULL, "missing argument to %s", argp[-2]); continue; case FILESW: if (!(file = *argp++) || *file == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case SENDERSW: if (!(sender = *argp++))/* allow -xyz arguments */ adios (NULL, "missing argument to %s", argp[-2]); continue; case MAILBOXSW: if (!(mbox = *argp++) || *mbox == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case HOMESW: if (!(home = *argp++) || *home == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case MAILSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); if (mdlvr) adios (NULL, "only one maildelivery file at a time!"); mdlvr = cp; continue; case VERBSW: verbose++; continue; case NVERBSW: verbose = 0; continue; case SUPPRESSDUP: suppressdup++; continue; case NSUPPRESSDUP: suppressdup = 0; continue; case DEBUGSW: debug++; continue; } } else { adios (NULL, "only switch arguments are supported"); } } if (addr == NULL) addr = getusername (); if (user == NULL) { user = getusername (); } if ((pw = getpwnam (user)) == NULL) adios (NULL, "no such local user as %s", user); if (chdir (pw->pw_dir) == -1) if (chdir ("/") < 0) { advise ("/", "chdir"); } umask (0077); if (geteuid() == 0) { if (setgid (pw->pw_gid) != 0) { adios ("setgid", "unable to set group to %ld", (long) pw->pw_gid); } initgroups (pw->pw_name, pw->pw_gid); if (setuid (pw->pw_uid) != 0) { adios ("setuid", "unable to set user to %ld", (long) pw->pw_uid); } } if (info == NULL) info = ""; setbuf (stdin, NULL); /* Record the delivery time */ if ((now = dlocaltimenow ()) == NULL) adios (NULL, "unable to ascertain local time"); snprintf (ddate, sizeof(ddate), "Delivery-Date: %s\n", dtimenow (0)); /* * Copy the message to a temporary file */ if (file) { int tempfd; /* getting message from file */ if ((tempfd = open (file, O_RDONLY)) == -1) adios (file, "unable to open"); if (debug) debug_printf ("retrieving message from file \"%s\"\n", file); if ((fd = copy_message (tempfd, tmpfil, 1)) == -1) adios(NULL, "unable to create temporary file in %s", get_temp_dir()); close (tempfd); } else { /* getting message from stdin */ if (debug) debug_printf ("retrieving message from stdin\n"); if ((fd = copy_message (fileno (stdin), tmpfil, 1)) == -1) adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } if (debug) debug_printf ("temporary file=\"%s\"\n", tmpfil); /* Delete the temp file now or a copy of every single message passed through slocal will be left in the /tmp directory until deleted manually! This unlink() used to be under an 'else' of the 'if (debug)' above, but since some people like to always run slocal with -debug and log the results, the /tmp directory would get choked over time. Of course, now that we always delete the temp file, the "temporary file=" message above is somewhat pointless -- someone watching debug output wouldn't have a chance to 'tail -f' or 'ln' the temp file before it's unlinked. The best thing would be to delay this unlink() until later if debug == 1, but I'll leave that for someone who cares about the temp-file-accessing functionality (they'll have to watch out for cases where we adios()). */ (void) m_unlink (tmpfil); if (!(fp = fdopen (fd, "r+"))) adios (NULL, "unable to access temporary file"); /* * If no sender given, extract it * from envelope information. */ if (sender == NULL) get_sender (envelope, &sender); if (mbox == NULL) { snprintf (mailbox, sizeof(mailbox), "%s/%s", mmdfldir[0] ? mmdfldir : pw->pw_dir, mmdflfil[0] ? mmdflfil : pw->pw_name); mbox = mailbox; } if (home == NULL) home = pw->pw_dir; if (debug) { debug_printf ("addr=\"%s\"\n", trim(addr)); debug_printf ("user=\"%s\"\n", trim(user)); debug_printf ("info=\"%s\"\n", trim(info)); debug_printf ("sender=\"%s\"\n", trim(sender)); debug_printf ("envelope=\"%s\"\n", envelope ? trim(envelope) : ""); debug_printf ("mbox=\"%s\"\n", trim(mbox)); debug_printf ("home=\"%s\"\n", trim(home)); debug_printf ("ddate=\"%s\"\n", trim(ddate)); debug_printf ("now=%02d:%02d\n\n", now->tw_hour, now->tw_min); } /* deliver the message */ status = localmail (fd, mdlvr); done (status != -1 ? RCV_MOK : RCV_MBX); return 1; } /* * Main routine for delivering message. */ static int localmail (int fd, char *mdlvr) { /* check if this message is a duplicate */ if (suppressdup && suppress_duplicates(fd, mdlvr ? mdlvr : ".maildelivery") == DONE) return 0; /* delivery according to personal Maildelivery file */ if (usr_delivery (fd, mdlvr ? mdlvr : ".maildelivery", 0) != -1) return 0; /* delivery according to global Maildelivery file */ if (usr_delivery (fd, maildelivery, 1) != -1) return 0; if (verbose) verbose_printf ("(delivering to standard mail spool)\n"); /* last resort - deliver to standard mail spool */ return usr_file (fd, mbox, MBOX_FORMAT); } #define matches(a,b) (stringdex (b, a) >= 0) /* * Parse the delivery file, and process incoming message. */ static int usr_delivery (int fd, char *delivery, int su) { int i, accept, status=1, won, vecp, next; char *field, *pattern, *action, *result, *string; char buffer[BUFSIZ], tmpbuf[BUFSIZ]; char *vec[NVEC]; struct stat st; struct pair *p; FILE *fp; /* open the delivery file */ if ((fp = fopen (delivery, "r")) == NULL) return -1; /* check if delivery file has bad ownership or permissions */ if (fstat (fileno (fp), &st) == -1 || (st.st_uid != 0 && (su || st.st_uid != pw->pw_uid)) || st.st_mode & (S_IWGRP|S_IWOTH)) { if (verbose) { verbose_printf ("WARNING: %s has bad ownership/modes (su=%d,uid=%d,owner=%d,mode=0%o)\n", delivery, su, (int) pw->pw_uid, (int) st.st_uid, (int) st.st_mode); } return -1; } won = 0; next = 1; /* read and process delivery file */ while (fgets (buffer, sizeof(buffer), fp)) { /* skip comments and empty lines */ if (*buffer == '#' || *buffer == '\n') continue; trim_suffix_c(buffer, '\n'); /* split buffer into fields */ vecp = split (buffer, vec); /* check for too few fields */ if (vecp < 5) { if (debug) debug_printf ("WARNING: entry with only %d fields, skipping.\n", vecp); continue; } if (debug) { for (i = 0; vec[i]; i++) debug_printf ("vec[%d]: \"%s\"\n", i, trim(vec[i])); } field = vec[0]; pattern = vec[1]; action = vec[2]; result = vec[3]; string = vec[4]; /* find out how to perform the action */ switch (result[0]) { case 'N': case 'n': /* * If previous condition failed, don't * do this - else fall through */ if (!next) continue; /* FALLTHRU */ case '?': /* * If already delivered, skip this action. Else * consider delivered if action is successful. */ if (won) continue; /* FALLTHRU */ case 'A': case 'a': /* * Take action, and consider delivered if * action is successful. */ accept = 1; break; case 'R': case 'r': default: /* * Take action, but don't consider delivered, even * if action is successful */ accept = 0; break; } if (vecp > 5) { if (!strcasecmp (vec[5], "select")) { if (logged_in () != -1) continue; if (vecp > 7 && timely (vec[6], vec[7]) == -1) continue; } } /* check if the field matches */ switch (*field) { case '*': /* always matches */ break; case 'd': /* * "default" matches only if the message hasn't * been delivered yet. */ if (!strcasecmp (field, "default")) { if (won) continue; break; } /* FALLTHRU */ default: /* parse message and build lookup table */ if (!parsed && parse (fd) == -1) { fclose (fp); return -1; } /* * find header field in lookup table, and * see if the pattern matches. */ if ((p = lookup (hdrs, field)) && (p->p_value != NULL) && matches (p->p_value, pattern)) { next = 1; } else { next = 0; continue; } break; } /* find out the action to perform */ switch (*action) { case 'q': /* deliver to quoted pipe */ if (strcasecmp (action, "qpipe")) continue; /* FALLTHRU */ case '^': expand (tmpbuf, string, fd); if (split (tmpbuf, vec) < 1) continue; status = usr_pipe (fd, tmpbuf, vec[0], vec, 0); break; case 'p': /* deliver to pipe */ if (strcasecmp (action, "pipe")) continue; /* FALLTHRU */ case '|': vec[2] = "sh"; vec[3] = "-c"; expand (tmpbuf, string, fd); vec[4] = tmpbuf; vec[5] = NULL; status = usr_pipe (fd, tmpbuf, "/bin/sh", vec + 2, 0); break; case 'f': /* mbox format */ if (!strcasecmp (action, "file")) { status = usr_file (fd, string, MBOX_FORMAT); break; } /* deliver to nmh folder */ else if (strcasecmp (action, "folder")) continue; /* FALLTHRU */ case '+': status = usr_folder (fd, string); break; case 'm': /* mmdf format */ if (!strcasecmp (action, "mmdf")) { status = usr_file (fd, string, MMDF_FORMAT); break; } /* mbox format */ else if (strcasecmp (action, "mbox")) continue; /* FALLTHRU */ case '>': /* mbox format */ status = usr_file (fd, string, MBOX_FORMAT); break; case 'd': /* ignore message */ if (strcasecmp (action, "destroy")) continue; status = 0; break; } if (status) next = 0; /* action failed, mark for 'N' result */ if (accept && status == 0) won++; } fclose (fp); return (won ? 0 : -1); } #define QUOTE '\\' /* * Split buffer into fields (delimited by whitespace or * comma's). Return the number of fields found. */ static int split (char *cp, char **vec) { int i; char *s; s = cp; /* split into a maximum of NVEC fields */ for (i = 0; i <= NVEC;) { vec[i] = NULL; /* zap any whitespace and comma's */ while (isspace ((unsigned char) *s) || *s == ',') *s++ = 0; /* end of buffer, time to leave */ if (*s == 0) break; /* get double quote text as a single field */ if (*s == '"') { for (vec[i++] = ++s; *s && *s != '"'; s++) { /* * Check for escaped double quote. We need * to shift the string to remove slash. */ if (*s == QUOTE) { if (*++s == '"') strcpy (s - 1, s); s--; } } if (*s == '"') /* zap trailing double quote */ *s++ = 0; continue; } if (*s == QUOTE && *++s != '"') s--; vec[i++] = s++; /* move forward to next field delimiter */ while (*s && !isspace ((unsigned char) *s) && *s != ',') s++; } vec[i] = NULL; return i; } /* * Parse the headers of a message, and build the * lookup table for matching fields and patterns. */ static int parse (int fd) { int i, state; int fd1; char *cp, *dp, *lp; char name[NAMESZ], field[NMH_BUFSIZ]; struct pair *p, *q; FILE *in; m_getfld_state_t gstate = 0; if (parsed++) return 0; /* get a new FILE pointer to message */ if ((fd1 = dup (fd)) == -1) return -1; if ((in = fdopen (fd1, "r")) == NULL) { close (fd1); return -1; } rewind (in); /* add special entries to lookup table */ if ((p = lookup (hdrs, "source"))) p->p_value = getcpy (sender); if ((p = lookup (hdrs, "addr"))) p->p_value = getcpy (addr); /* * Scan the headers of the message and build * a lookup table. */ for (i = 0;;) { int fieldsz = sizeof field; switch (state = m_getfld (&gstate, name, field, &fieldsz, in)) { case FLD: case FLDPLUS: lp = mh_xstrdup(field); while (state == FLDPLUS) { fieldsz = sizeof field; state = m_getfld (&gstate, name, field, &fieldsz, in); lp = add (field, lp); } for (p = hdrs; p->p_name; p++) { if (!strcasecmp (p->p_name, name)) { if (!(p->p_flags & P_HID)) { if ((cp = p->p_value)) { if (p->p_flags & P_ADR) { dp = cp + strlen (cp) - 1; if (*dp == '\n') *dp = 0; cp = add (",\n\t", cp); } else { cp = add ("\t", cp); } } p->p_value = add (lp, cp); } free (lp); break; } } if (p->p_name == NULL && i < NVEC) { p->p_name = mh_xstrdup(name); p->p_value = lp; p->p_flags = P_NIL; p++, i++; p->p_name = NULL; } continue; case BODY: case FILEEOF: break; case LENERR: case FMTERR: inform("format error in message"); break; default: inform("internal error in m_getfld"); fclose (in); return -1; } break; } m_getfld_state_destroy (&gstate); fclose (in); if ((p = lookup (vars, "reply-to"))) { if ((q = lookup (hdrs, "reply-to")) == NULL || q->p_value == NULL) q = lookup (hdrs, "from"); p->p_value = getcpy (q ? q->p_value : ""); p->p_flags &= ~P_CHK; if (debug) debug_printf ("vars[%d]: name=\"%s\" value=\"%s\"\n", p - vars, p->p_name, trim(p->p_value)); } if (debug) { for (p = hdrs; p->p_name; p++) debug_printf ("hdrs[%d]: name=\"%s\" value=\"%s\"\n", p - hdrs, p->p_name, p->p_value ? trim(p->p_value) : ""); } return 0; } #define LPAREN '(' #define RPAREN ')' /* * Expand any builtin variables such as $(sender), * $(address), etc., in a string. */ static void expand (char *s1, char *s2, int fd) { char c, *cp; struct pair *p; if (!globbed) glob (fd); while ((c = *s2++)) { if (c != '$' || *s2 != LPAREN) { *s1++ = c; } else { for (cp = ++s2; *s2 && *s2 != RPAREN; s2++) continue; if (*s2 != RPAREN) { s2 = --cp; continue; } *s2++ = 0; if ((p = lookup (vars, cp))) { if (!parsed && (p->p_flags & P_CHK)) parse (fd); strcpy (s1, p->p_value); s1 += strlen (s1); } } } *s1 = 0; } /* * Fill in the information missing from the "vars" * table, which is necessary to expand any builtin * variables in the string for a "pipe" or "qpipe" * action. */ static void glob (int fd) { char buffer[BUFSIZ]; struct stat st; struct pair *p; if (globbed++) return; if ((p = lookup (vars, "sender"))) p->p_value = getcpy (sender); if ((p = lookup (vars, "address"))) p->p_value = getcpy (addr); if ((p = lookup (vars, "size"))) { snprintf (buffer, sizeof(buffer), "%d", fstat (fd, &st) != -1 ? (int) st.st_size : 0); p->p_value = mh_xstrdup(buffer); } if ((p = lookup (vars, "info"))) p->p_value = getcpy (info); if (debug) { for (p = vars; p->p_name; p++) debug_printf ("vars[%d]: name=\"%s\" value=\"%s\"\n", p - vars, p->p_name, trim(p->p_value)); } } /* * Find a matching name in a lookup table. If found, * return the "pairs" entry, else return NULL. */ static struct pair * lookup (struct pair *pairs, char *key) { for (; pairs->p_name; pairs++) if (!strcasecmp (pairs->p_name, key)) return pairs; return NULL; } /* * Check utmp(x) file to see if user is currently * logged in. */ static int logged_in (void) { #if HAVE_GETUTXENT struct utmpx *utp; if (utmped) return utmped; setutxent(); while ((utp = getutxent()) != NULL) { if ( utp->ut_type == USER_PROCESS && utp->ut_user[0] != 0 && strncmp (user, utp->ut_user, sizeof(utp->ut_user)) == 0) { if (debug) continue; endutxent(); return (utmped = DONE); } } endutxent(); #endif /* HAVE_GETUTXENT */ return (utmped = NOTOK); } #define check(t,a,b) if (t < a || t > b) return -1 #define cmpar(h1,m1,h2,m2) if (h1 < h2 || (h1 == h2 && m1 < m2)) return 0 static int timely (char *t1, char *t2) { int t1hours, t1mins, t2hours, t2mins; if (sscanf (t1, "%d:%d", &t1hours, &t1mins) != 2) return -1; check (t1hours, 0, 23); check (t1mins, 0, 59); if (sscanf (t2, "%d:%d", &t2hours, &t2mins) != 2) return -1; check (t2hours, 0, 23); check (t2mins, 0, 59); cmpar (now->tw_hour, now->tw_min, t1hours, t1mins); cmpar (t2hours, t2mins, now->tw_hour, now->tw_min); return -1; } /* * Deliver message by appending to a file. */ static int usr_file (int fd, char *mailbox, int mbx_style) { int md; if (verbose) { verbose_printf("delivering to file \"%s\" (%s style)", mailbox, mbx_style == MBOX_FORMAT ? "mbox" : "mmdf"); } /* open and lock the file */ if ((md = mbx_open (mailbox, mbx_style, pw->pw_uid, pw->pw_gid, m_gmprot())) == -1) { if (verbose) adorn ("", "unable to open:"); return -1; } lseek(fd, 0, SEEK_SET); /* append message to file */ if (mbx_copy (mailbox, mbx_style, md, fd, NULL) == -1) { if (verbose) adorn ("", "error writing to:"); return -1; } /* close and unlock file */ if (mbx_close (mailbox, md) == NOTOK) { if (verbose) adorn ("", "error closing:"); return -1; } if (verbose) verbose_printf (", success.\n"); return 0; } /* * Deliver message to a nmh folder. */ static int usr_folder (int fd, char *string) { int status; char folder[BUFSIZ], *vec[3]; /* get folder name ready */ if (*string == '+') strncpy(folder, string, sizeof(folder)); else snprintf(folder, sizeof(folder), "+%s", string); if (verbose) verbose_printf ("delivering to folder \"%s\"", folder + 1); vec[0] = "rcvstore"; vec[1] = folder; vec[2] = NULL; /* use rcvstore to put message in folder */ status = usr_pipe (fd, "rcvstore", rcvstoreproc, vec, 1); return status; } /* * Deliver message to a process. */ static int usr_pipe (int fd_arg, char *cmd, char *pgm, char **vec, int suppress) { volatile int fd = fd_arg; pid_t child_id; int i, bytes, seconds, status; struct stat st; if (verbose && !suppress) verbose_printf ("delivering to pipe \"%s\"", cmd); lseek(fd, 0, SEEK_SET); for (i = 0; (child_id = fork()) == -1 && i < 5; i++) sleep (5); switch (child_id) { case -1: /* fork error */ if (verbose) adorn ("fork", "unable to"); return -1; case 0: /* child process */ if (fd != 0) dup2 (fd, 0); if (freopen ("/dev/null", "w", stdout) == NULL) { advise ("stdout", "freopen"); } if (freopen ("/dev/null", "w", stderr) == NULL) { advise ("stderr", "freopen"); } if (fd != 3) dup2 (fd, 3); closefds (4); #ifdef TIOCNOTTY if ((fd = open ("/dev/tty", O_RDWR)) != -1) { ioctl (fd, TIOCNOTTY, NULL); close (fd); } #endif /* TIOCNOTTY */ setpgid ((pid_t) 0, getpid ()); /* put in own process group */ *environ = NULL; setenv("USER", pw->pw_name, 1); setenv("HOME", pw->pw_dir, 1); setenv("SHELL", pw->pw_shell, 1); execvp (pgm, vec); _exit (-1); default: /* parent process */ if (! setjmp (myctx)) { SIGNAL (SIGALRM, alrmser); bytes = fstat (fd, &st) != -1 ? (int) st.st_size : 100; /* amount of time to wait depends on message size */ if (bytes <= 100) { /* give at least 5 minutes */ seconds = 300; } else if (bytes >= 90000) { /* a half hour is long enough */ seconds = 1800; } else { seconds = (bytes / 60) + 300; } alarm ((unsigned int) seconds); status = pidwait (child_id, 0); alarm (0); if (verbose) { if (status == 0) verbose_printf (", success.\n"); else if ((status & 0xff00) == 0xff00) verbose_printf (", system error\n"); else pidstatus (status, stdout, ", failed"); } return (status == 0 ? 0 : -1); } /* * Ruthlessly kill the child and anything * else in its process group. */ killpg(child_id, SIGKILL); if (verbose) verbose_printf (", timed-out; terminated\n"); return -1; } } static void alrmser (int i) { NMH_UNUSED (i); longjmp (myctx, DONE); } /* * Get the `sender' from the envelope * information ("From " line). */ static void get_sender (char *envelope, char **sender) { int i; char *cp; char buffer[BUFSIZ]; if (envelope == NULL) { *sender = mh_xstrdup(""); return; } i = LEN("From "); strncpy (buffer, envelope + i, sizeof(buffer)); if ((cp = strchr(buffer, '\n'))) { *cp = 0; cp -= 24; if (cp < buffer) cp = buffer; } else { cp = buffer; } *cp = 0; for (cp = buffer + strlen (buffer) - 1; cp >= buffer; cp--) if (isspace ((unsigned char) *cp)) *cp = 0; else break; *sender = mh_xstrdup(buffer); } /* * Copy message into a temporary file. * While copying, it will do some header processing * including the extraction of the envelope information. */ static int copy_message (int qd, char *tmpfil, int fold) { int i, first = 1, fd1, fd2; char buffer[BUFSIZ]; FILE *qfp, *ffp; char *tfile = NULL; tfile = m_mktemp2(NULL, invo_name, &fd1, NULL); if (tfile == NULL) return -1; strncpy (tmpfil, tfile, BUFSIZ); if (!fold) { while ((i = read (qd, buffer, sizeof(buffer))) > 0) if (write (fd1, buffer, i) != i) { you_lose: close (fd1); (void) m_unlink (tmpfil); return -1; } if (i == -1) goto you_lose; lseek(fd1, 0, SEEK_SET); return fd1; } /* dup the fd for incoming message */ if ((fd2 = dup (qd)) == -1) { close (fd1); return -1; } /* now create a FILE pointer for it */ if ((qfp = fdopen (fd2, "r")) == NULL) { close (fd1); close (fd2); return -1; } /* dup the fd for temporary file */ if ((fd2 = dup (fd1)) == -1) { close (fd1); fclose (qfp); return -1; } /* now create a FILE pointer for it */ if ((ffp = fdopen (fd2, "r+")) == NULL) { close (fd1); close (fd2); fclose (qfp); return -1; } /* * copy message into temporary file * and massage the headers. Save * a copy of the "From " line for later. */ while (fgets (buffer, sizeof(buffer), qfp)) { if (first) { first = 0; if (has_prefix(buffer, "From ")) { /* get copy of envelope information ("From " line) */ envelope = mh_xstrdup(buffer); /* Put the delivery date in message */ fputs (ddate, ffp); if (ferror (ffp)) goto fputs_error; continue; } } fputs (buffer, ffp); if (ferror (ffp)) goto fputs_error; } fclose (ffp); if (ferror (qfp)) { close (fd1); fclose (qfp); return -1; } fclose (qfp); lseek(fd1, 0, SEEK_SET); return fd1; fputs_error: close (fd1); fclose (ffp); fclose (qfp); return -1; } /* * Trim strings for pretty printing of debugging output */ static char * trim (char *cp) { char buffer[BUFSIZ*4]; char *bp, *sp; if (cp == NULL) return NULL; /* copy string into temp buffer */ strncpy (buffer, cp, sizeof(buffer)); bp = buffer; /* skip over leading whitespace */ while (isspace((unsigned char) *bp)) bp++; /* start at the end and zap trailing whitespace */ for (sp = bp + strlen(bp) - 1; sp >= bp; sp--) { if (isspace((unsigned char) *sp)) *sp = 0; else break; } /* replace remaining whitespace with spaces */ for (sp = bp; *sp; sp++) if (isspace((unsigned char) *sp)) *sp = ' '; /* now return a copy */ return mh_xstrdup(bp); } /* * Function for printing `verbose' messages. */ static void verbose_printf (char *fmt, ...) { va_list ap; va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); fflush (stdout); /* now flush output */ } /* * Function for printing `verbose' delivery * error messages. */ static void adorn (char *what, char *fmt, ...) { va_list ap; int eindex; char *s; eindex = errno; /* save the errno */ printf(", "); va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); if (what) { if (*what) printf(" %s: ", what); if ((s = strerror (eindex))) fputs(s, stdout); else printf("Error %d", eindex); } putchar('\n'); fflush (stdout); } /* * Function for printing `debug' messages. */ static void debug_printf (char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf (stderr, fmt, ap); va_end(ap); } /* * Check ndbm/db file(s) to see if the Message-Id of this * message matches the Message-Id of a previous message, * so we can discard it. If it doesn't match, we add the * Message-Id of this message to the ndbm/db file. */ static int suppress_duplicates (int fd, char *file) { int fd1, lockfd, state, result; char *cp, buf[NMH_BUFSIZ], name[NAMESZ]; datum key, value; DBM *db; FILE *in; m_getfld_state_t gstate = 0; if ((fd1 = dup (fd)) == -1) return -1; if (!(in = fdopen (fd1, "r"))) { close (fd1); return -1; } rewind (in); for (;;) { int failed_to_lock = 0; int bufsz = sizeof buf; state = m_getfld (&gstate, name, buf, &bufsz, in); switch (state) { case FLD: case FLDPLUS: /* Search for the message ID */ if (strcasecmp (name, "Message-ID")) { while (state == FLDPLUS) { bufsz = sizeof buf; state = m_getfld (&gstate, name, buf, &bufsz, in); } continue; } cp = mh_xstrdup(buf); while (state == FLDPLUS) { bufsz = sizeof buf; state = m_getfld (&gstate, name, buf, &bufsz, in); cp = add (buf, cp); } key.dptr = trimcpy (cp); key.dsize = strlen (key.dptr) + 1; free (cp); cp = key.dptr; if (!(db = dbm_open (file, O_RDWR | O_CREAT, 0600))) { advise (file, "unable to perform dbm_open on"); free (cp); fclose (in); return -1; } /* * Since it is difficult to portable lock a ndbm file, * we will open and lock the Maildelivery file instead. * This will fail if your Maildelivery file doesn't * exist. */ if ((lockfd = lkopendata(file, O_RDWR, 0, &failed_to_lock)) == -1) { advise (file, "unable to perform file locking on"); free (cp); fclose (in); return -1; } value = dbm_fetch (db, key); if (value.dptr) { if (verbose) verbose_printf ("Message-ID: %s\n already received on %s", cp, value.dptr); result = DONE; } else { value.dptr = ddate + sizeof("Delivery-Date:"); value.dsize = strlen(value.dptr) + 1; if (dbm_store (db, key, value, DBM_INSERT)) advise (file, "possibly corrupt file"); result = 0; } dbm_close (db); lkclosedata(lockfd, file); free (cp); fclose (in); return result; case BODY: case FILEEOF: break; case LENERR: case FMTERR: default: break; } break; } m_getfld_state_destroy (&gstate); fclose (in); return 0; } nmh-1.7.1-RC3/uip/sortm.c000644 007761 000024 00000034267 13243042054 015100 0ustar00kenhstaff000000 000000 /* sortm.c -- sort messages in a folder by date/time * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include "../sbr/m_maildir.h" #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; time_t s_clock; char *s_subj; }; static struct smsg *smsgs; int nmsgs; char *subjsort = (char *) 0; /* sort on subject if != 0 */ time_t datelimit = 0; int submajor = 0; /* if true, sort on subject-major */ int verbose; int allmsgs = 1; int check_failed = 0; /* This keeps compiler happy on calls to qsort */ typedef int (*qsort_comp) (const void *, const void *); /* * static prototypes */ static int read_hdrs (struct msgs *, char *); static int get_fields (char *, int, struct smsg *); static int dsort (struct smsg **, struct smsg **); static int subsort (struct smsg **, struct smsg **); static int txtsort (struct smsg **, struct smsg **); static void rename_chain (struct msgs *, struct smsg **, int, int); static void rename_msgs (struct msgs *, struct smsg **); int main (int argc, char **argv) { int i, msgnum; char *cp, *maildir, *datesw = NULL; char *folder = NULL, buf[BUFSIZ], **argp; char **arguments; struct msgs_array msgs = { 0, 0, NULL }; struct msgs *mp; struct smsg **dlist; int checksw = 0; if (nmh_init(argv[0], 1)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; /* * Parse arguments */ while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf(buf, sizeof(buf), "%s [+folder] [msgs] [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case DATESW: if (datesw) adios (NULL, "only one date field at a time"); if (!(datesw = *argp++) || *datesw == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case TEXTSW: if (subjsort) adios (NULL, "only one text field at a time"); if (!(subjsort = *argp++) || *subjsort == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case SUBJSW: subjsort = "subject"; continue; case NSUBJSW: subjsort = NULL; continue; case LIMSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); while (*cp == '0') cp++; /* skip any leading zeros */ if (!*cp) { /* hit end of string */ submajor++; /* sort subject-major */ continue; } if (!isdigit((unsigned char) *cp) || !(datelimit = atoi(cp))) adios (NULL, "impossible limit %s", cp); datelimit *= 60*60*24; continue; case NLIMSW: submajor = 0; /* use date-major, but */ datelimit = 0; /* use no limit */ continue; case VERBSW: verbose++; continue; case NVERBSW: verbose = 0; continue; case ALLMSGS: allmsgs = 1; continue; case NALLMSGS: allmsgs = 0; continue; case CHECKSW: checksw = 1; continue; case NCHECKSW: checksw = 0; continue; } } if (*cp == '+' || *cp == '@') { if (folder) adios (NULL, "only one folder at a time!"); else folder = pluspath (cp); } else app_msgarg(&msgs, cp); } if (!context_find ("path")) free (path ("./", TFOLDER)); if (!msgs.size) { if (allmsgs) { app_msgarg(&msgs, "all"); } else { adios (NULL, "must specify messages to sort with -noall"); } } if (!datesw) datesw = "date"; if (!folder) folder = getfolder (1); maildir = m_maildir (folder); if (chdir (maildir) == NOTOK) adios (maildir, "unable to change directory to"); /* read folder and create message structure */ if (!(mp = folder_read (folder, 1))) adios (NULL, "unable to read folder %s", folder); /* check for empty folder */ if (mp->nummsg == 0) adios (NULL, "no messages in %s", folder); /* parse all the message ranges/sequences and set SELECTED */ for (msgnum = 0; msgnum < msgs.size; msgnum++) if (!m_convert (mp, msgs.msgs[msgnum])) done (1); seq_setprev (mp); /* set the previous sequence */ if ((nmsgs = read_hdrs (mp, datesw)) <= 0) adios (NULL, "no messages to sort"); if (checksw && check_failed) { adios (NULL, "errors found, no messages sorted"); } /* * sort a list of pointers to our "messages to be sorted". */ dlist = (struct smsg **) mh_xmalloc ((nmsgs+1) * sizeof(*dlist)); for (i = 0; i < nmsgs; i++) dlist[i] = &smsgs[i]; dlist[nmsgs] = 0; if (verbose) { /* announce what we're doing */ if (subjsort) if (submajor) printf ("sorting by %s\n", subjsort); else printf ("sorting by %s-major %s-minor\n", subjsort, datesw); else printf ("sorting by datefield %s\n", datesw); } /* first sort by date, or by subject-major, date-minor */ qsort ((char *) dlist, nmsgs, sizeof(*dlist), (qsort_comp) (submajor && subjsort ? txtsort : dsort)); /* * if we're sorting on subject, we need another list * in subject order, then a merge pass to collate the * two sorts. */ if (!submajor && subjsort) { /* already date sorted */ struct smsg **slist, **flist; struct smsg ***il, **fp, **dp; slist = (struct smsg **) mh_xmalloc ((nmsgs+1) * sizeof(*slist)); memcpy((char *)slist, (char *)dlist, (nmsgs+1)*sizeof(*slist)); qsort((char *)slist, nmsgs, sizeof(*slist), (qsort_comp) subsort); /* * make an inversion list so we can quickly find * the collection of messages with the same subj * given a message number. */ il = mh_xcalloc(mp->hghsel + 1, sizeof *il); for (i = 0; i < nmsgs; i++) il[slist[i]->s_msg] = &slist[i]; /* * make up the final list, chronological but with * all the same subjects grouped together. */ flist = (struct smsg **) mh_xmalloc ((nmsgs+1) * sizeof(*flist)); fp = flist; for (dp = dlist; *dp;) { struct smsg **s = il[(*dp++)->s_msg]; /* see if we already did this guy */ if (! s) continue; *fp++ = *s++; /* * take the next message(s) if there is one, * its subject isn't null and its subject * is the same as this one and it's not too * far away in time. */ while (*s && (*s)->s_subj[0] && strcmp((*s)->s_subj, s[-1]->s_subj) == 0 && (datelimit == 0 || (*s)->s_clock - s[-1]->s_clock <= datelimit)) { il[(*s)->s_msg] = 0; *fp++ = *s++; } } *fp = 0; free (il); free (slist); free (dlist); dlist = flist; } /* * At this point, dlist is a sorted array of pointers to smsg structures, * each of which contains a message number. */ rename_msgs (mp, dlist); context_replace (pfolder, folder); /* update current folder */ seq_save (mp); /* synchronize message sequences */ context_save (); /* save the context file */ folder_free (mp); /* free folder/message structure */ done (0); return 1; } static int read_hdrs (struct msgs *mp, char *datesw) { int msgnum; struct smsg *s; smsgs = mh_xcalloc(mp->hghsel - mp->lowsel + 2, sizeof *smsgs); s = smsgs; for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { if (is_selected(mp, msgnum)) { if (get_fields (datesw, msgnum, s)) { s->s_msg = msgnum; s++; } } } s->s_msg = 0; return(s - smsgs); } /* * Parse the message and get the data or subject field, * if needed. */ static int get_fields (char *datesw, int msg, struct smsg *smsg) { int state; int compnum; char *msgnam, buf[NMH_BUFSIZ], nam[NAMESZ]; struct tws *tw; char *datecomp = NULL, *subjcomp = NULL; 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;;) { int bufsz = sizeof buf; switch (state = m_getfld (&gstate, nam, buf, &bufsz, in)) { case FLD: case FLDPLUS: compnum++; if (!strcasecmp (nam, datesw)) { datecomp = add (buf, datecomp); while (state == FLDPLUS) { bufsz = sizeof buf; state = m_getfld (&gstate, nam, buf, &bufsz, in); datecomp = add (buf, datecomp); } if (!subjsort || subjcomp) break; } else if (subjsort && !strcasecmp (nam, subjsort)) { subjcomp = add (buf, subjcomp); while (state == FLDPLUS) { 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) { bufsz = sizeof buf; state = m_getfld (&gstate, nam, buf, &bufsz, in); } } continue; case BODY: case FILEEOF: break; case LENERR: case FMTERR: if (state == LENERR || state == FMTERR) { inform("format error in message %d (header #%d), continuing...", msg, compnum); check_failed = 1; } mh_xfree(datecomp); mh_xfree(subjcomp); fclose (in); return (0); default: adios (NULL, "internal error -- you lose"); } break; } m_getfld_state_destroy (&gstate); /* * If no date component, then use the modification * time of the file as its date */ if (!datecomp || (tw = dparsetime (datecomp)) == NULL) { struct stat st; inform("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; } else { smsg->s_clock = dmktime (tw); } if (subjsort) { if (subjcomp) { /* * try to make the subject "canonical": delete * leading "re:", everything but letters & smash * letters to lower case. */ char *cp, *cp2, c; cp = subjcomp; cp2 = subjcomp; if (strcmp (subjsort, "subject") == 0) { while ((c = *cp)) { if (! isspace((unsigned char) c)) { if(!uprf(cp, "re:")) break; cp += 2; } cp++; } } while ((c = *cp++)) { if (isascii((unsigned char) c) && isalnum((unsigned char) c)) *cp2++ = tolower((unsigned char)c); } *cp2 = '\0'; } else subjcomp = ""; smsg->s_subj = subjcomp; } fclose (in); mh_xfree(datecomp); return (1); } /* * sort on dates. */ static int dsort (struct smsg **a, struct smsg **b) { if ((*a)->s_clock < (*b)->s_clock) return (-1); if ((*a)->s_clock > (*b)->s_clock) return (1); if ((*a)->s_msg < (*b)->s_msg) return (-1); return (1); } /* * sort on subjects. */ static int subsort (struct smsg **a, struct smsg **b) { int i; if ((i = strcmp ((*a)->s_subj, (*b)->s_subj))) return (i); return (dsort (a, b)); } static int txtsort (struct smsg **a, struct smsg **b) { int i; if ((i = strcmp ((*a)->s_subj, (*b)->s_subj))) return (i); if ((*a)->s_msg < (*b)->s_msg) return (-1); return (1); } static void rename_chain (struct msgs *mp, struct smsg **mlist, int msg, int endmsg) { int nxt, old, new; char *newname, oldname[BUFSIZ]; char newbuf[PATH_MAX + 1]; for (;;) { nxt = mlist[msg] - smsgs; /* mlist[msg] is a ptr into smsgs */ mlist[msg] = NULL; old = smsgs[nxt].s_msg; new = smsgs[msg].s_msg; strncpy (oldname, m_name (old), sizeof(oldname)); newname = m_name (new); if (verbose) printf ("message %d becomes message %d\n", old, new); (void)snprintf(oldname, sizeof (oldname), "%s/%d", mp->foldpath, old); (void)snprintf(newbuf, sizeof (newbuf), "%s/%d", mp->foldpath, new); ext_hook("ref-hook", oldname, newbuf); if (rename (oldname, newname) == NOTOK) adios (newname, "unable to rename %s to", oldname); copy_msg_flags (mp, new, old); if (mp->curmsg == old) seq_setcur (mp, new); if (nxt == endmsg) break; msg = nxt; } /* if (nxt != endmsg); */ /* rename_chain (mp, mlist, nxt, endmsg); */ } static void rename_msgs (struct msgs *mp, struct smsg **mlist) { int i, j, old, new; bvector_t tmpset = bvector_create (); char f1[BUFSIZ], tmpfil[BUFSIZ]; char newbuf[PATH_MAX + 1]; struct smsg *sp; strncpy (tmpfil, m_name (mp->hghmsg + 1), sizeof(tmpfil)); for (i = 0; i < nmsgs; i++) { if (! (sp = mlist[i])) continue; /* did this one */ j = sp - smsgs; if (j == i) continue; /* this one doesn't move */ /* * the guy that was msg j is about to become msg i. * rename 'j' to make a hole, then recursively rename * guys to fill up the hole. */ old = smsgs[j].s_msg; new = smsgs[i].s_msg; strncpy (f1, m_name (old), sizeof(f1)); if (verbose) printf ("renaming message chain from %d to %d\n", old, new); /* * Run the external hook to refile the old message as the * temporary message number that is off of the end of the * messages in the folder. */ (void)snprintf(f1, sizeof (f1), "%s/%d", mp->foldpath, old); (void)snprintf(newbuf, sizeof (newbuf), "%s/%d", mp->foldpath, mp->hghmsg + 1); ext_hook("ref-hook", f1, newbuf); if (rename (f1, tmpfil) == NOTOK) adios (tmpfil, "unable to rename %s to ", f1); get_msg_flags (mp, tmpset, old); rename_chain (mp, mlist, j, i); /* * Run the external hook to refile the temporary message number * to the real place. */ (void)snprintf(f1, sizeof (f1), "%s/%d", mp->foldpath, new); ext_hook("ref-hook", newbuf, f1); if (rename (tmpfil, m_name(new)) == NOTOK) adios (m_name(new), "unable to rename %s to", tmpfil); set_msg_flags (mp, tmpset, new); mp->msgflags |= SEQMOD; } bvector_free (tmpset); } nmh-1.7.1-RC3/uip/spost.in000644 007761 000024 00000000610 13205305706 015255 0ustar00kenhstaff000000 000000 #! /bin/sh # # spost -- delivers a message to local sendmail using its -t option # # 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. # # Emulates old spost(8) using post(8). prefix='@prefix@' exec_prefix="@exec_prefix@" exec "@libexecdir@/nmh/post" -mts sendmail/pipe "$@" nmh-1.7.1-RC3/uip/viamail.c000644 007761 000024 00000012216 13243042054 015344 0ustar00kenhstaff000000 000000 /* viamail.c -- send multiple files in a MIME message * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #include #include #include "../sbr/m_mktemp.h" #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; /* * static prototypes */ static int via_mail (char *, char *, char *, char *, char *, int, char *); int main (int argc, char **argv) { int delay = 0; char *f1 = NULL, *f2 = NULL, *f3 = NULL; char *f4 = NULL, *f5 = NULL, *f7 = NULL; char *cp, buf[BUFSIZ]; char **argp, **arguments; if (nmh_init(argv[0], 2)) { return 1; } arguments = getarguments (invo_name, argc, argv, 0); argp = arguments; while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [switches]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case TOSW: if (!(f1 = *argp++)) adios (NULL, "missing argument to %s", argp[-2]); continue; case SUBJECTSW: if (!(f2 = *argp++)) adios (NULL, "missing argument to %s", argp[-2]); continue; case PARAMSW: if (!(f3 = *argp++)) adios (NULL, "missing argument to %s", argp[-2]); continue; case DESCRIPTSW: if (!(f4 = *argp++)) adios (NULL, "missing argument to %s", argp[-2]); continue; case COMMENTSW: if (!(f5 = *argp++)) adios (NULL, "missing argument to %s", argp[-2]); continue; case DELAYSW: if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); /* * If there is an error, just reset the delay parameter * to -1. We will set a default delay later. */ if (sscanf (cp, "%d", &delay) != 1) delay = -1; continue; case FROMSW: if (!(f7 = *argp++)) adios (NULL, "missing argument to %s", argp[-2]); continue; case VERBSW: verbsw = 1; continue; case NVERBSW: verbsw = 0; continue; case DEBUGSW: debugsw = 1; continue; } } } if (!f1) adios (NULL, "missing -viamail \"mailpath\" switch"); via_mail (f1, f2, f3, f4, f5, delay, f7); return 0; /* dead code to satisfy the compiler */ } /* * VIAMAIL */ static int via_mail (char *mailsw, char *subjsw, char *parmsw, char *descsw, char *cmntsw, int delay, char *fromsw) { int status, vecp; char tmpfil[BUFSIZ], *program; char **vec; struct stat st; FILE *fp; char *tfile = NULL; char *cp; umask (~m_gmprot ()); if ((tfile = m_mktemp2(NULL, invo_name, NULL, &fp)) == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } strncpy (tmpfil, tfile, sizeof(tmpfil)); if (!strchr(mailsw, '@')) mailsw = concat (mailsw, "@", LocalName (0), NULL); fprintf (fp, "To: %s\n", mailsw); if (subjsw) fprintf (fp, "Subject: %s\n", subjsw); if (fromsw) { if (!strchr(fromsw, '@')) fromsw = concat (fromsw, "@", LocalName (0), NULL); fprintf (fp, "From: %s\n", fromsw); } fprintf (fp, "%s: %s\n", VRSN_FIELD, VRSN_VALUE); fprintf (fp, "%s: application/octet-stream", TYPE_FIELD); if (parmsw) fprintf (fp, "; %s", parmsw); if (cmntsw) fprintf (fp, "\n\t(%s)", cmntsw); if (descsw) fprintf (fp, "\n%s: %s", DESCR_FIELD, descsw); fprintf (fp, "\n%s: %s\n\n", ENCODING_FIELD, "base64"); if (fflush (fp)) adios (tmpfil, "error writing to"); writeBase64aux (stdin, fp, 0); if (fflush (fp)) adios (tmpfil, "error writing to"); if (fstat (fileno (fp), &st) == NOTOK) adios ("failed", "fstat of %s", tmpfil); if (delay < 0) splitsw = 10; else splitsw = delay; status = 0; vec = argsplit(postproc, &program, &vecp); if (verbsw) vec[vecp++] = "-verbose"; if ((cp = context_find ("credentials"))) { /* post doesn't read context so need to pass credentials. */ vec[vecp++] = "-credentials"; vec[vecp++] = cp; } switch (sendsbr (vec, vecp, program, tmpfil, &st, 0, NULL)) { case DONE: case NOTOK: status++; break; case OK: break; } fclose (fp); if (m_unlink (tmpfil) == -1) advise (tmpfil, "unable to remove temp file %s", tmpfil); done (status); return 1; } nmh-1.7.1-RC3/uip/whatnow.c000644 007761 000024 00000000567 13243042054 015417 0ustar00kenhstaff000000 000000 /* whatnow.c -- the nmh `WhatNow' shell * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include int main (int argc, char **argv) { if (nmh_init(argv[0], 2)) { return 1; } return WhatNow (argc, argv); } nmh-1.7.1-RC3/uip/whatnowproc.c000644 007761 000024 00000006062 13243042054 016277 0ustar00kenhstaff000000 000000 /* whatnowproc.c -- exec the "whatnowproc" * * 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 /* * This routine is used by comp, repl, forw, and dist to exec * the "whatnowproc". It first sets up all the environment * variables that the "whatnowproc" will need to check, and * then execs the command. As an optimization, if the * "whatnowproc" is the nmh command "whatnow" (typical case), * it will call this routine directly without exec'ing it. */ int what_now (char *ed, int nedit, int use, char *file, char *altmsg, int dist, struct msgs *mp, char *text, int inplace, char *cwd, int atfile) { int found, k, msgnum, vecp; int len, buflen; char *bp; char buffer[BUFSIZ], *vec[MAXARGS]; vecp = 0; vec[vecp++] = r1bindex (whatnowproc, '/'); vec[vecp] = NULL; setenv("mhdraft", file, 1); if (mp) setenv("mhfolder", mp->foldpath, 1); else unsetenv("mhfolder"); if (altmsg) { if (mp == NULL || *altmsg == '/' || cwd == NULL) setenv("mhaltmsg", altmsg, 1); else { snprintf (buffer, sizeof(buffer), "%s/%s", mp->foldpath, altmsg); setenv("mhaltmsg", buffer, 1); } } else { unsetenv("mhaltmsg"); } if ((bp = getenv ("mhaltmsg")))/* XXX */ setenv("editalt", bp, 1); snprintf (buffer, sizeof(buffer), "%d", dist); setenv("mhdist", buffer, 1); if (nedit) { unsetenv("mheditor"); } else { if (!ed) ed = get_default_editor(); setenv("mheditor", ed, 1); } snprintf (buffer, sizeof(buffer), "%d", use); setenv("mhuse", buffer, 1); snprintf (buffer, sizeof(buffer), "%d", atfile); setenv("mhatfile", buffer, 1); unsetenv("mhmessages"); unsetenv("mhannotate"); unsetenv("mhinplace"); if (text && mp && !is_readonly(mp)) { found = 0; bp = buffer; buflen = sizeof(buffer); for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg; msgnum++) { if (is_selected(mp, msgnum)) { snprintf (bp, buflen, "%s%s", found ? " " : "", m_name (msgnum)); len = strlen (bp); bp += len; buflen -= len; for (k = msgnum + 1; k <= mp->hghmsg && is_selected(mp, k); k++) continue; if (--k > msgnum) { snprintf (bp, buflen, "-%s", m_name (k)); len = strlen (bp); bp += len; buflen -= len; } msgnum = k + 1; found++; } } if (found) { setenv("mhmessages", buffer, 1); setenv("mhannotate", text, 1); snprintf (buffer, sizeof(buffer), "%d", inplace); setenv("mhinplace", buffer, 1); } } context_save (); /* save the context file */ fflush (stdout); if (cwd) { if (chdir (cwd) < 0) { advise (cwd, "chdir"); } } /* * If the "whatnowproc" is the nmh command "whatnow", * we run it internally, rather than exec'ing it. */ if (strcmp (vec[0], "whatnow") == 0) { WhatNow (vecp, vec); done (0); } execvp (whatnowproc, vec); fprintf (stderr, "unable to exec "); perror (whatnowproc); return 0; } nmh-1.7.1-RC3/uip/whatnowsbr.c000644 007761 000024 00000077446 13243042054 016140 0ustar00kenhstaff000000 000000 /* whatnowsbr.c -- the WhatNow shell * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. * * Several options have been added to ease the inclusion of attachments * using the header field name mechanism added to anno and send. The * -attach option is used to specify the header field name for attachments. * * Several commands have been added at the whatnow prompt: * * cd [ directory ] This option works just like the shell's * cd command and lets the user change the * directory from which attachments are * taken so that long path names are not * needed with every file. * * ls [ ls-options ] This option works just like the normal * ls command and exists to allow the user * to verify file names in the directory. * * pwd This option works just like the normal * pwd command and exists to allow the user * to verify the directory. * * attach [-v] files This option attaches the named files to * the draft. -v displays the mhbuild * directive that send(1) will use. * * alist [-ln] This option lists the attachments on the * draft. -l gets long listings, -n gets * numbered listings. * * detach files This option removes attachments from the * detach -n numbers draft. This can be done by file name or * by attachment number. */ #include #include #include #include #ifdef OAUTH_SUPPORT # include #endif #include "../sbr/m_maildir.h" #include "../sbr/m_mktemp.h" #include "../sbr/mime_type.h" #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) \ #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 */ #define PROMPT_SWITCHES \ X("edit [ ]", 0, EDITSW) \ X("refile [] +folder", 0, REFILEOPT) \ X("mime []", 0, BUILDMIMESW) \ X("display []", 0, DISPSW) \ X("list []", 0, LISTSW) \ X("send []", 0, SENDSW) \ X("push []", 0, PUSHSW) \ X("whom []", 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 [-v]", 0, ATTACHCMDSW) \ X("detach [-n]", 0, 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? "; /* * static prototypes */ static int editfile (char **, char **, char *, int, struct msgs *, char *, char *, int, int); static int sendfile (char **, char *, int); static void sendit (char *, char **, char *, int); static int buildfile (char **, char *); static int whomfile (char **, char *); static int removefile (char *); static int checkmimeheader (char *); static void writelscmd(char *, int, char *, char **); static void writesomecmd(char *buf, int bufsz, char *cmd, char *trailcmd, char **argp); static FILE* popen_in_dir(const char *dir, const char *cmd, const char *type); static int system_in_dir(const char *dir, const char *cmd); static int copyf (char *, char *); int WhatNow (int argc, char **argv) { int isdf = 0, nedit = 0, use = 0, atfile = 1; char *cp, *dfolder = NULL, *dmsg = NULL; char *ed = NULL, *drft = NULL, *msgnam = NULL; char buf[BUFSIZ], prompt[BUFSIZ]; char **argp, **arguments; struct stat st; char cwd[PATH_MAX + 1]; /* current working directory */ char file[PATH_MAX + 1]; /* file name buffer */ char shell[PATH_MAX + 1]; /* shell response buffer */ FILE *f; /* read pointer for bgnd proc */ char *l; /* set on -l to alist command */ int n; /* set on -n to alist command */ /* Need this if called from what_now(). */ invo_name = r1bindex (argv[0], '/'); arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; /* * Get the initial current working directory. */ if (getcwd(cwd, sizeof (cwd)) == NULL) { adios("getcwd", "could not get working directory"); } while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, whatnowswitches)) { case AMBIGSW: ambigsw (cp, whatnowswitches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [switches] [file]", invo_name); print_help (buf, whatnowswitches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case DFOLDSW: if (dfolder) adios (NULL, "only one draft folder at a time!"); if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); dfolder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp, *cp != '@' ? TFOLDER : TSUBCWF); continue; case DMSGSW: if (dmsg) adios (NULL, "only one draft message at a time!"); if (!(dmsg = *argp++) || *dmsg == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case NDFLDSW: dfolder = NULL; isdf = NOTOK; continue; case EDITRSW: if (!(ed = *argp++) || *ed == '-') adios (NULL, "missing argument to %s", argp[-2]); nedit = 0; continue; case NEDITSW: nedit++; continue; case PRMPTSW: if (!(myprompt = *argp++) || *myprompt == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; } } if (drft) adios (NULL, "only one draft at a time!"); else drft = cp; } if ((drft == NULL && (drft = getenv ("mhdraft")) == NULL) || *drft == 0) drft = getcpy (m_draft (dfolder, dmsg, 1, &isdf)); msgnam = (cp = getenv ("mhaltmsg")) && *cp ? mh_xstrdup(cp) : NULL; if ((cp = getenv ("mhatfile")) && *cp) atfile = atoi(cp); if ((cp = getenv ("mhuse")) && *cp) use = atoi (cp); if (ed == NULL && ((ed = getenv ("mheditor")) == NULL || *ed == 0)) { ed = NULL; nedit++; } /* start editing the draft, unless -noedit was given */ if (!nedit && editfile (&ed, NULL, drft, use, NULL, msgnam, NULL, 1, atfile) < 0) done (1); snprintf (prompt, sizeof(prompt), myprompt, invo_name); for (;;) { #ifdef READLINE_SUPPORT if (!(argp = read_switch_multiword_via_readline (prompt, aleqs))) { #else /* ! READLINE_SUPPORT */ if (!(argp = read_switch_multiword (prompt, aleqs))) { #endif /* READLINE_SUPPORT */ (void) m_unlink (LINK); done (1); } switch (smatch (*argp, aleqs)) { case DISPSW: /* display the message being replied to, or distributed */ if (msgnam) showfile (++argp, msgnam); else inform("no alternate message to display"); break; case BUILDMIMESW: /* Translate MIME composition file */ buildfile (++argp, drft); break; case EDITSW: /* Call an editor on the draft file */ if (*++argp) ed = *argp++; if (editfile (&ed, argp, drft, NOUSE, NULL, msgnam, NULL, 1, atfile) == NOTOK) done (1); break; case LISTSW: /* display the draft file */ showfile (++argp, drft); break; case WHOMSW: /* Check to whom the draft would be sent */ whomfile (++argp, drft); break; case QUITSW: /* Quit, and possibly delete the draft */ if (*++argp && (*argp[0] == 'd' || ((*argp)[0] == '-' && (*argp)[1] == 'd'))) { removefile (drft); } else { if (stat (drft, &st) != NOTOK) inform("draft left on %s", drft); } done (1); case DELETESW: /* Delete draft and exit */ removefile (drft); done (1); case PUSHSW: /* Send draft in background */ if (sendfile (++argp, drft, 1)) done (1); break; case SENDSW: /* Send draft */ sendfile (++argp, drft, 0); break; case REFILEOPT: /* Refile the draft */ if (refile (++argp, drft) == 0) done (0); break; case CDCMDSW: /* Change the working directory for attachments * * Run the directory through the user's shell so that * we can take advantage of any syntax that the user * is accustomed to. Read back the absolute path. */ if (*(argp+1) == NULL) { strcpy(buf, "$SHELL -c \"cd&&pwd\""); } else { writesomecmd(buf, BUFSIZ, "cd", "pwd", argp); } if ((f = popen_in_dir(cwd, buf, "r")) != NULL) { if (fgets(cwd, sizeof (cwd), f) == NULL) { advise (buf, "fgets"); } trim_suffix_c(cwd, '\n'); pclose(f); } else { advise("popen", "could not get directory"); } break; case PWDCMDSW: /* Print the working directory for attachments */ puts(cwd); break; case LSCMDSW: /* List files in the current attachment working directory * * Use the user's shell so that we can take advantage of any * syntax that the user is accustomed to. */ writelscmd(buf, sizeof(buf), "", argp); (void)system_in_dir(cwd, buf); break; case ALISTCMDSW: /* * List attachments on current draft. Options are: * * -l long listing (full path names) * -n numbers listing */ if (checkmimeheader(drft)) break; l = NULL; n = 0; while (*++argp != NULL) { if (strcmp(*argp, "-l") == 0) l = "/"; else if (strcmp(*argp, "-n") == 0) n = 1; else if (strcmp(*argp, "-ln") == 0 || strcmp(*argp, "-nl") == 0) { l = "/"; n = 1; } else { n = -1; break; } } if (n == -1) inform("usage is alist [-ln]."); else annolist(drft, ATTACH_FIELD, l, n); break; case ATTACHCMDSW: { /* * Attach files to current draft. */ int verbose = 0; char **ap; if (checkmimeheader(drft)) break; for (ap = argp+1; *ap; ++ap) { if (strcmp(*ap, "-v") == 0) { ++argp; verbose = 1; } else if (*ap[0] != '-') { break; } } if (*(argp+1) == NULL) { inform("attach command requires file argument(s)."); break; } /* * Build a command line that causes the user's shell to list the file name * arguments. This handles and wildcard expansion, tilde expansion, etc. */ writelscmd(buf, sizeof(buf), "-d --", argp); /* * Read back the response from the shell, which contains a number of lines * with one file name per line. Remove off the newline. Determine whether * we have an absolute or relative path name. Prepend the current working * directory to relative path names. Add the attachment annotation to the * draft. */ if ((f = popen_in_dir(cwd, buf, "r")) != NULL) { while (fgets(shell, sizeof (shell), f) != NULL) { char *ctype; trim_suffix_c(shell, '\n'); if (*shell == '/') { strncpy(file, shell, sizeof(file)); file[sizeof(file) - 1] = '\0'; } else { snprintf(file, sizeof(file), "%s/%s", cwd, shell); } annotate(drft, ATTACH_FIELD, file, 1, 0, -2, 1); if (verbose) { ctype = mime_type(file); printf ("Attaching %s as a %s\n", file, ctype); free (ctype); } } pclose(f); } else { advise("popen", "could not get file from shell"); } break; } case DETACHCMDSW: /* * Detach files from current draft. */ /* * Scan the arguments for a -n. Mixed file names and numbers aren't allowed, * so this catches a -n anywhere in the argument list. */ if (checkmimeheader(drft)) break; for (n = 0, arguments = argp + 1; *arguments != NULL; arguments++) { if (strcmp(*arguments, "-n") == 0) { n = 1; break; } } /* * A -n was found so interpret the arguments as attachment numbers. * Decrement any remaining argument number that is greater than the one * just processed after processing each one so that the numbering stays * correct. */ if (n == 1) { for (arguments = argp + 1; *arguments != NULL; arguments++) { if (strcmp(*arguments, "-n") == 0) continue; if (**arguments != '\0') { n = atoi(*arguments); annotate(drft, ATTACH_FIELD, NULL, 1, 0, n, 1); for (argp = arguments + 1; *argp != NULL; argp++) { if (atoi(*argp) > n) { if (atoi(*argp) == 1) *argp = ""; else (void)sprintf(*argp, "%d", atoi(*argp) - 1); } } } } } /* * The arguments are interpreted as file names. Run them through the * user's shell for wildcard expansion and other goodies. Do this from * the current working directory if the argument is not an absolute path * name (does not begin with a /). * * We feed all the file names to the shell at once, otherwise you can't * provide a file name with a space in it. */ writelscmd(buf, sizeof(buf), "-d --", argp); if ((f = popen_in_dir(cwd, buf, "r")) != NULL) { while (fgets(shell, sizeof (shell), f) != NULL) { trim_suffix_c(shell, '\n'); annotate(drft, ATTACH_FIELD, shell, 1, 0, 0, 1); } pclose(f); } else { advise("popen", "could not get file from shell"); } break; default: /* Unknown command */ inform("say what?"); break; } } /*NOTREACHED*/ } /* Build a command line of the form $SHELL -c "cd 'cwd'; cmd argp ... ; trailcmd". */ static void writesomecmd(char *buf, int bufsz, char *cmd, char *trailcmd, char **argp) { char *cp; /* Note that we do not quote -- the argp from the user * is assumed to be quoted as they desire. (We can't treat * it as pure literal as that would prevent them using ~, * wildcards, etc.) The buffer produced by this function * should be given to popen_in_dir() or system_in_dir() so * that the current working directory is set correctly. */ int ln = snprintf(buf, bufsz, "$SHELL -c \"%s", cmd); /* NB that some snprintf() return -1 on overflow rather than the * new C99 mandated 'number of chars that would have been written' */ /* length checks here and inside the loop allow for the * trailing "&&", trailcmd, '"' and NUL */ int trailln = strlen(trailcmd) + 4; if (ln < 0 || ln + trailln > bufsz) adios(NULL, "arguments too long"); cp = buf + ln; while (*argp && *++argp) { ln = strlen(*argp); /* +1 for leading space */ if (ln + trailln + 1 > bufsz - (cp-buf)) adios(NULL, "arguments too long"); *cp++ = ' '; memcpy(cp, *argp, ln+1); cp += ln; } if (*trailcmd) { *cp++ = '&'; *cp++ = '&'; strcpy(cp, trailcmd); cp += trailln - 4; } *cp++ = '"'; *cp = 0; } /* * Build a command line that causes the user's shell to list the file name * arguments. This handles and wildcard expansion, tilde expansion, etc. */ static void writelscmd(char *buf, int bufsz, char *lsoptions, char **argp) { char *lscmd = concat ("ls ", lsoptions, NULL); writesomecmd(buf, bufsz, lscmd, "", argp); free (lscmd); } /* Like system(), but run the command in directory dir. * This assumes the program is single-threaded! */ static int system_in_dir(const char *dir, const char *cmd) { char olddir[BUFSIZ]; int r; /* ensure that $SHELL exists, as the cmd was written relying on a non-blank $SHELL... */ setenv("SHELL","/bin/sh",0); /* don't overwrite */ if (getcwd(olddir, sizeof(olddir)) == 0) adios("getcwd", "could not get working directory"); if (chdir(dir) != 0) adios("chdir", "could not change working directory"); r = system(cmd); if (chdir(olddir) != 0) adios("chdir", "could not change working directory"); return r; } /* ditto for popen() */ static FILE* popen_in_dir(const char *dir, const char *cmd, const char *type) { char olddir[BUFSIZ]; FILE *f; /* ensure that $SHELL exists, as the cmd was written relying on a non-blank $SHELL... */ setenv("SHELL","/bin/sh",0); /* don't overwrite */ if (getcwd(olddir, sizeof(olddir)) == 0) adios("getcwd", "could not get working directory"); if (chdir(dir) != 0) adios("chdir", "could not change working directory"); f = popen(cmd, type); if (chdir(olddir) != 0) adios("chdir", "could not change working directory"); return f; } /* * EDIT */ static int reedit = 0; /* have we been here before? */ static char *edsave = NULL; /* the editor we used previously */ static int editfile (char **ed, char **arg, char *file, int use, struct msgs *mp, char *altmsg, char *cwd, int save_editor, int atfile) { int pid, status, vecp; char altpath[BUFSIZ], linkpath[BUFSIZ]; char *cp, *prog, **vec; struct stat st; int slinked = 0; /* Was there a previous edit session? */ if (reedit && (*ed || edsave)) { if (!*ed) { /* no explicit editor */ *ed = edsave; /* so use the previous one */ if ((cp = r1bindex (*ed, '/')) == NULL) cp = *ed; /* unless we've specified it via "editor-next" */ cp = concat (cp, "-next", NULL); if ((cp = context_find (cp)) != NULL) *ed = cp; } } else { /* set initial editor */ if (*ed == NULL) *ed = get_default_editor(); } if (altmsg) { if (mp == NULL || *altmsg == '/' || cwd == NULL) strncpy (altpath, altmsg, sizeof(altpath)); else snprintf (altpath, sizeof(altpath), "%s/%s", mp->foldpath, altmsg); if (cwd == NULL) strncpy (linkpath, LINK, sizeof(linkpath)); else snprintf (linkpath, sizeof(linkpath), "%s/%s", cwd, LINK); if (atfile) { (void) m_unlink (linkpath); if (link (altpath, linkpath) == NOTOK) { if (symlink (altpath, linkpath) < 0) { adios (linkpath, "symlink"); } slinked = 1; } else { slinked = 0; } } } context_save (); /* save the context file */ fflush (stdout); switch (pid = fork()) { case NOTOK: advise ("fork", "unable to"); status = NOTOK; break; case OK: if (cwd) { if (chdir (cwd) < 0) { advise (cwd, "chdir"); } } if (altmsg) { if (mp) setenv("mhfolder", mp->foldpath, 1); setenv("editalt", altpath, 1); } vec = argsplit(*ed, &prog, &vecp); if (arg) while (*arg) vec[vecp++] = *arg++; vec[vecp++] = file; vec[vecp] = NULL; execvp (prog, vec); fprintf (stderr, "unable to exec "); perror (*ed); _exit (-1); default: if ((status = pidwait (pid, NOTOK))) { if (((status & 0xff00) != 0xff00) && (!reedit || (status & 0x00ff))) { if (!use && (status & 0xff00) && (rename (file, cp = m_backup (file)) != NOTOK)) { inform("problems with edit--draft left in %s", cp); } else { inform("problems with edit--%s preserved", file); } } status = -2; /* maybe "reedit ? -2 : -1"? */ break; } reedit++; if (altmsg && mp && !is_readonly(mp) && (slinked ? lstat (linkpath, &st) != NOTOK && S_ISREG(st.st_mode) && copyf (linkpath, altpath) == NOTOK : stat (linkpath, &st) != NOTOK && st.st_nlink == 1 && (m_unlink (altpath) == NOTOK || link (linkpath, altpath) == NOTOK))) advise (linkpath, "unable to update %s from", altmsg); } /* normally, we remember which editor we used */ if (save_editor) edsave = getcpy (*ed); *ed = NULL; if (altmsg && atfile) (void) m_unlink (linkpath); return status; } static int copyf (char *ifile, char *ofile) { int i, in, out; char buffer[BUFSIZ]; if ((in = open (ifile, O_RDONLY)) == NOTOK) return NOTOK; if ((out = open (ofile, O_WRONLY | O_TRUNC)) == NOTOK) { admonish (ofile, "unable to open and truncate"); close (in); return NOTOK; } while ((i = read (in, buffer, sizeof(buffer))) > OK) if (write (out, buffer, i) != i) { advise (ofile, "may have damaged"); i = NOTOK; break; } close (in); close (out); return i; } /* * SEND */ static int sendfile (char **arg, char *file, int pushsw) { pid_t child_id; int i, vecp; char *cp, *sp, **vec, *program; /* * If the sendproc is the nmh command `send', then we call * those routines directly rather than exec'ing the command. */ if (strcmp (sp = r1bindex (sendproc, '/'), "send") == 0) { cp = invo_name; sendit (invo_name = sp, arg, file, pushsw); invo_name = cp; return 1; } context_save (); /* save the context file */ fflush (stdout); for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++) sleep (5); switch (child_id) { case NOTOK: inform("unable to fork, so sending directly..."); /* FALLTHRU */ case OK: vec = argsplit(sendproc, &program, &vecp); if (pushsw) vec[vecp++] = "-push"; if (arg) while (*arg) vec[vecp++] = *arg++; vec[vecp++] = file; vec[vecp] = NULL; execvp (program, vec); fprintf (stderr, "unable to exec "); perror (sendproc); _exit (-1); default: if (pidwait(child_id, OK) == 0) done (0); return 1; } } /* * Translate MIME composition file (call buildmimeproc) */ static int buildfile (char **argp, char *file) { int i; char **args, *ed; ed = buildmimeproc; /* allocate space for arguments */ i = 0; if (argp) { while (argp[i]) i++; } args = (char **) mh_xmalloc((i + 2) * sizeof(char *)); /* * For backward compatibility, we need to add -build * if we are using mhn as buildmimeproc */ i = 0; if (strcmp (r1bindex (ed, '/'), "mhn") == 0) args[i++] = "-build"; /* copy any other arguments */ while (argp && *argp) args[i++] = *argp++; args[i] = NULL; i = editfile (&ed, args, file, NOUSE, NULL, NULL, NULL, 0, 0); free (args); return (i ? NOTOK : OK); } #ifndef CYRUS_SASL # define SASLminc(a) (a) #else /* CYRUS_SASL */ # define SASLminc(a) 0 #endif /* CYRUS_SASL */ #ifndef TLS_SUPPORT # define TLSminc(a) (a) #else /* TLS_SUPPORT */ # define TLSminc(a) 0 #endif /* TLS_SUPPORT */ #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("client host", -6, CLIESW) \ X("server host", 6, SERVSW) \ X("snoop", -5, SNOOPSW) \ X("draftfolder +folder", 0, SDRFSW) \ X("draftmessage msg", 0, SDRMSW) \ X("nodraftfolder", 0, SNDRFSW) \ X("sasl", SASLminc(4), SASLSW) \ X("nosasl", SASLminc(6), NOSASLSW) \ X("saslmech", SASLminc(5), SASLMECHSW) \ X("authservice", SASLminc(0), AUTHSERVICESW) \ X("user username", SASLminc(4), USERSW) \ X("port server-port-name/number", 4, PORTSW) \ X("tls", TLSminc(-3), TLSSW) \ X("initialtls", TLSminc(-10), INITTLSSW) \ X("notls", TLSminc(-5), NTLSSW) \ X("certverify", TLSminc(-10), CERTVERSW) \ X("nocertverify", TLSminc(-12), NOCERTVERSW) \ X("sendmail program", 0, MTSSM) \ 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 */ extern int forwsw; extern int inplace; extern int pushsw; extern int splitsw; extern int unique; extern int verbsw; extern char *altmsg; /* .. */ extern char *annotext; extern char *distfile; static void sendit (char *sp, char **arg, char *file, int pushed) { int vecp, n = 1; char *cp, buf[BUFSIZ], **argp, *program; char **arguments, *savearg[MAXARGS], **vec; const char *user = NULL, *saslmech = NULL; char *auth_svc = NULL; int snoop = 0; struct stat st; #ifndef lint int distsw = 0; #endif /* * Make sure these are defined. In particular, we need * savearg[1] to be NULL, in case "arg" is NULL below. It * doesn't matter what is the value of savearg[0], but we * set it to NULL, to help catch "off-by-one" errors. */ savearg[0] = NULL; savearg[1] = NULL; /* * Temporarily copy arg to savearg, since the brkstring() call in * getarguments() will wipe it out before it is merged in. * Also, we skip the first element of savearg, since getarguments() * skips it. Then we count the number of arguments * copied. The value of "n" will be one greater than * this in order to simulate the standard argc/argv. */ if (arg) { char **bp; copyip (arg, savearg+1, MAXARGS-1); bp = savearg+1; while (*bp++) n++; } /* * Merge any arguments from command line (now in savearg) * and arguments from profile. */ arguments = getarguments (sp, n, savearg, 1); argp = arguments; debugsw = 0; forwsw = 1; inplace = 1; unique = 0; altmsg = NULL; annotext = NULL; distfile = NULL; /* * Get our initial arguments for postproc now */ vec = argsplit(postproc, &program, &vecp); vec[vecp++] = "-library"; vec[vecp++] = getcpy (m_maildir ("")); if ((cp = context_find ("fileproc"))) { vec[vecp++] = "-fileproc"; vec[vecp++] = cp; } if ((cp = context_find ("mhlproc"))) { vec[vecp++] = "-mhlproc"; vec[vecp++] = cp; } if ((cp = context_find ("credentials"))) { /* post doesn't read context so need to pass credentials. */ vec[vecp++] = "-credentials"; vec[vecp++] = cp; } while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, sendswitches)) { case AMBIGSW: ambigsw (cp, sendswitches); return; case UNKWNSW: inform("-%s unknown\n", cp); return; case SHELPSW: snprintf (buf, sizeof(buf), "%s [switches]", sp); print_help (buf, sendswitches, 1); return; case SVERSIONSW: print_version (invo_name); return; case SPSHSW: pushed++; continue; case NSPSHSW: pushed = 0; continue; case SPLITSW: if (!(cp = *argp++) || sscanf (cp, "%d", &splitsw) != 1) { inform("missing argument to %s", argp[-2]); return; } continue; case UNIQSW: unique++; continue; case NUNIQSW: unique = 0; continue; case FORWSW: forwsw++; continue; case NFORWSW: forwsw = 0; continue; case VERBSW: verbsw++; vec[vecp++] = --cp; continue; case NVERBSW: verbsw = 0; vec[vecp++] = --cp; continue; case DEBUGSW: debugsw++; /* FALLTHRU */ case NFILTSW: case FRMTSW: case NFRMTSW: case BITSTUFFSW: case NBITSTUFFSW: case MIMESW: case NMIMESW: case MSGDSW: case NMSGDSW: case WATCSW: case NWATCSW: case SASLSW: case NOSASLSW: case TLSSW: case INITTLSSW: case NTLSSW: case CERTVERSW: case NOCERTVERSW: vec[vecp++] = --cp; continue; case SNOOPSW: snoop++; vec[vecp++] = --cp; continue; case AUTHSERVICESW: #ifdef OAUTH_SUPPORT if (!(auth_svc = *argp++) || *auth_svc == '-') adios (NULL, "missing argument to %s", argp[-2]); #else NMH_UNUSED (user); NMH_UNUSED (auth_svc); adios (NULL, "not built with OAuth support"); #endif continue; case SASLMECHSW: saslmech = *argp; /* FALLTHRU */ case ALIASW: case FILTSW: case WIDTHSW: case CLIESW: case SERVSW: case USERSW: case PORTSW: case MTSSM: case MTSSW: case MESSAGEIDSW: vec[vecp++] = --cp; if (!(cp = *argp++) || *cp == '-') { inform("missing argument to %s", argp[-2]); return; } vec[vecp++] = cp; user = cp; continue; case SDRFSW: case SDRMSW: if (!(cp = *argp++) || *cp == '-') { inform("missing argument to %s", argp[-2]); return; } continue; case SNDRFSW: continue; } } inform("usage: %s [switches]", sp); return; } /* allow Aliasfile: profile entry */ if ((cp = context_find ("Aliasfile"))) { char **ap, *dp; dp = mh_xstrdup(cp); for (ap = brkstring (dp, " ", "\n"); ap && *ap; ap++) { vec[vecp++] = "-alias"; vec[vecp++] = *ap; } } if ((cp = getenv ("SIGNATURE")) == NULL || *cp == 0) if ((cp = context_find ("signature")) && *cp) setenv("SIGNATURE", cp, 1); if ((annotext = getenv ("mhannotate")) == NULL || *annotext == 0) annotext = NULL; if ((altmsg = getenv ("mhaltmsg")) == NULL || *altmsg == 0) altmsg = NULL; if (annotext && ((cp = getenv ("mhinplace")) != NULL && *cp != 0)) inplace = atoi (cp); if ((cp = getenv ("mhdist")) && *cp #ifndef lint && (distsw = atoi (cp)) #endif /* not lint */ && altmsg) { vec[vecp++] = "-dist"; if ((cp = m_mktemp2(altmsg, invo_name, NULL, NULL)) == NULL) { adios(NULL, "unable to create temporary file in %s", get_temp_dir()); } distfile = mh_xstrdup(cp); (void) m_unlink(distfile); if (link (altmsg, distfile) == NOTOK) adios (distfile, "unable to link %s to", altmsg); } else { distfile = NULL; } #ifdef OAUTH_SUPPORT if (auth_svc == NULL) { if (saslmech && ! strcasecmp(saslmech, "xoauth2")) { adios (NULL, "must specify -authservice with -saslmech xoauth2"); } } else { if (user == NULL) { adios (NULL, "must specify -user with -saslmech xoauth2"); } } #else NMH_UNUSED(saslmech); #endif /* OAUTH_SUPPORT */ if (altmsg == NULL || stat (altmsg, &st) == NOTOK) { st.st_mtime = 0; st.st_dev = 0; st.st_ino = 0; } if ((pushsw = pushed)) push (); closefds (3); if (sendsbr (vec, vecp, program, file, &st, 1, auth_svc) == OK) done (0); } /* * WHOM */ static int whomfile (char **arg, char *file) { pid_t pid; int vecp; char **vec, *program; context_save (); /* save the context file */ fflush (stdout); switch (pid = fork()) { case NOTOK: advise ("fork", "unable to"); return 1; case OK: vec = argsplit(whomproc, &program, &vecp); if (arg) while (*arg) vec[vecp++] = *arg++; vec[vecp++] = file; vec[vecp] = NULL; execvp (program, vec); fprintf (stderr, "unable to exec "); perror (whomproc); _exit (-1); /* NOTREACHED */ default: return (pidwait (pid, NOTOK) & 0377 ? 1 : 0); } } /* * Remove the draft file */ static int removefile (char *drft) { if (m_unlink (drft) == NOTOK) adios (drft, "unable to unlink"); return OK; } /* * Return 1 if we already have a MIME-Version header, 0 otherwise. */ static int checkmimeheader (char *drft) { FILE *f; m_getfld_state_t gstate = 0; char buf[NMH_BUFSIZ], name[NAMESZ]; int state, retval = 0; if ((f = fopen(drft, "r")) == NULL) { admonish(drft, "unable to read draft"); return (0); } for (;;) { int bufsz = sizeof(buf); switch (state = m_getfld(&gstate, name, buf, &bufsz, f)) { case FLD: case FLDPLUS: if (strcasecmp(name, VRSN_FIELD) == 0) { inform("Cannot use attach commands with already-" "formatted MIME message \"%s\"", drft); retval = 1; break; } continue; default: break; } break; } m_getfld_state_destroy(&gstate); fclose(f); return retval; } nmh-1.7.1-RC3/uip/whom.c000644 007761 000024 00000012221 13243042054 014670 0ustar00kenhstaff000000 000000 /* whom.c -- report to whom a message would be sent * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include "../sbr/m_maildir.h" #include "../sbr/m_mktemp.h" #ifndef CYRUS_SASL # define SASLminc(a) (a) #else /* CYRUS_SASL */ # define SASLminc(a) 0 #endif /* CYRUS_SASL */ #ifndef TLS_SUPPORT # define TLSminc(a) (a) #else /* TLS_SUPPORT */ # define TLSminc(a) 0 #endif /* TLS_SUPPORT */ #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", 0, SERVSW) \ X("snoop", 0, 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("initialtls", TLSminc(-10), INITTLSSW) \ 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 main (int argc, char **argv) { pid_t child_id = OK; int i, status, isdf = 0; int distsw = 0, vecp = 0; char *cp, *dfolder = NULL, *dmsg = NULL; char *msg = NULL, **ap, **argp, backup[BUFSIZ]; char buf[BUFSIZ], **arguments, *vec[MAXARGS]; if (nmh_init(argv[0], 2)) { return 1; } arguments = getarguments (invo_name, argc, argv, 1); argp = arguments; vec[vecp++] = invo_name; vec[vecp++] = "-whom"; vec[vecp++] = "-library"; vec[vecp++] = getcpy (m_maildir ("")); if ((cp = context_find ("credentials"))) { /* post doesn't read context so need to pass credentials. */ vec[vecp++] = "-credentials"; vec[vecp++] = cp; } /* Don't need to feed fileproc or mhlproc to post because it doesn't use them when used for whom. */ while ((cp = *argp++)) { if (*cp == '-') { switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: adios (NULL, "-%s unknown", cp); case HELPSW: snprintf (buf, sizeof(buf), "%s [switches] [file]", invo_name); print_help (buf, switches, 1); done (0); case VERSIONSW: print_version(invo_name); done (0); case CHKSW: case NOCHKSW: case SNOOPSW: case SASLSW: case TLSSW: case INITTLSSW: case NTLSSW: vec[vecp++] = --cp; continue; case DRAFTSW: msg = draft; continue; case DFOLDSW: if (dfolder) adios (NULL, "only one draft folder at a time!"); if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); dfolder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp, *cp != '@' ? TFOLDER : TSUBCWF); continue; case DMSGSW: if (dmsg) adios (NULL, "only one draft message at a time!"); if (!(dmsg = *argp++) || *dmsg == '-') adios (NULL, "missing argument to %s", argp[-2]); continue; case NDFLDSW: dfolder = NULL; isdf = NOTOK; continue; case ALIASW: case CLIESW: case SERVSW: case USERSW: case PORTSW: case SASLMECHSW: case MTSSW: vec[vecp++] = --cp; if (!(cp = *argp++) || *cp == '-') adios (NULL, "missing argument to %s", argp[-2]); vec[vecp++] = cp; continue; } } if (msg) adios (NULL, "only one draft at a time!"); else vec[vecp++] = msg = cp; } /* allow Aliasfile: profile entry */ if ((cp = context_find ("Aliasfile"))) { char *dp = NULL; for (ap = brkstring(dp = mh_xstrdup(cp), " ", "\n"); ap && *ap; ap++) { vec[vecp++] = "-alias"; vec[vecp++] = *ap; } } if (msg == NULL) { cp = getcpy (m_draft (dfolder, dmsg, 1, &isdf)); msg = vec[vecp++] = cp; } if ((cp = getenv ("mhdist")) && *cp && (distsw = atoi (cp)) && (cp = getenv ("mhaltmsg")) && *cp) { if (distout (msg, cp, backup) == NOTOK) done (1); vec[vecp++] = "-dist"; distsw++; } vec[vecp] = NULL; closefds (3); if (distsw) { for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++) sleep (5); } switch (distsw ? child_id : OK) { case NOTOK: inform("unable to fork, so checking directly..."); /* FALLTHRU */ case OK: execvp (postproc, vec); fprintf (stderr, "unable to exec "); perror (postproc); _exit (-1); default: SIGNAL (SIGHUP, SIG_IGN); SIGNAL (SIGINT, SIG_IGN); SIGNAL (SIGQUIT, SIG_IGN); SIGNAL (SIGTERM, SIG_IGN); status = pidwait(child_id, OK); (void) m_unlink (msg); if (rename (backup, msg) == NOTOK) adios (msg, "unable to rename %s to", backup); done (status); } return 0; /* dead code to satisfy the compiler */ } nmh-1.7.1-RC3/thirdparty/jsmn/000755 007761 000024 00000000000 13243043704 016123 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/thirdparty/jsmn/jsmn.c000644 007761 000024 00000017024 13205305706 017243 0ustar00kenhstaff000000 000000 #include #include "jsmn.h" /** * Allocates a fresh unused token from the token pull. */ static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, jsmntok_t *tokens, size_t num_tokens) { jsmntok_t *tok; if (parser->toknext >= num_tokens) { return NULL; } tok = &tokens[parser->toknext++]; tok->start = tok->end = -1; tok->size = 0; #ifdef JSMN_PARENT_LINKS tok->parent = -1; #endif return tok; } /** * Fills token type and boundaries. */ static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, int start, int end) { token->type = type; token->start = start; token->end = end; token->size = 0; } /** * Fills next available token with JSON primitive. */ static jsmnerr_t jsmn_parse_primitive(jsmn_parser *parser, const char *js, size_t len, jsmntok_t *tokens, size_t num_tokens) { jsmntok_t *token; int start; start = parser->pos; for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { switch (js[parser->pos]) { #ifndef JSMN_STRICT /* In strict mode primitive must be followed by "," or "}" or "]" */ case ':': #endif case '\t' : case '\r' : case '\n' : case ' ' : case ',' : case ']' : case '}' : goto found; } if (js[parser->pos] < 32 || js[parser->pos] >= 127) { parser->pos = start; return JSMN_ERROR_INVAL; } } #ifdef JSMN_STRICT /* In strict mode primitive must be followed by a comma/object/array */ parser->pos = start; return JSMN_ERROR_PART; #endif found: if (tokens == NULL) { parser->pos--; return 0; } token = jsmn_alloc_token(parser, tokens, num_tokens); if (token == NULL) { parser->pos = start; return JSMN_ERROR_NOMEM; } jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); #ifdef JSMN_PARENT_LINKS token->parent = parser->toksuper; #endif parser->pos--; return 0; } /** * Filsl next token with JSON string. */ static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js, size_t len, jsmntok_t *tokens, size_t num_tokens) { jsmntok_t *token; int start = parser->pos; parser->pos++; /* Skip starting quote */ for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { char c = js[parser->pos]; /* Quote: end of string */ if (c == '\"') { if (tokens == NULL) { return 0; } token = jsmn_alloc_token(parser, tokens, num_tokens); if (token == NULL) { parser->pos = start; return JSMN_ERROR_NOMEM; } jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos); #ifdef JSMN_PARENT_LINKS token->parent = parser->toksuper; #endif return 0; } /* Backslash: Quoted symbol expected */ if (c == '\\' && parser->pos + 1 < len) { int i; parser->pos++; switch (js[parser->pos]) { /* Allowed escaped symbols */ case '\"': case '/' : case '\\' : case 'b' : case 'f' : case 'r' : case 'n' : case 't' : break; /* Allows escaped symbol \uXXXX */ case 'u': parser->pos++; for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) { /* If it isn't a hex character we have an error */ if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ parser->pos = start; return JSMN_ERROR_INVAL; } parser->pos++; } parser->pos--; break; /* Unexpected symbol */ default: parser->pos = start; return JSMN_ERROR_INVAL; } } } parser->pos = start; return JSMN_ERROR_PART; } /** * Parse JSON string and fill tokens. */ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len, jsmntok_t *tokens, unsigned int num_tokens) { jsmnerr_t r; int i; jsmntok_t *token; int count = 0; for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { char c; jsmntype_t type; c = js[parser->pos]; switch (c) { case '{': case '[': count++; if (tokens == NULL) { break; } token = jsmn_alloc_token(parser, tokens, num_tokens); if (token == NULL) return JSMN_ERROR_NOMEM; if (parser->toksuper != -1) { tokens[parser->toksuper].size++; #ifdef JSMN_PARENT_LINKS token->parent = parser->toksuper; #endif } token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); token->start = parser->pos; parser->toksuper = parser->toknext - 1; break; case '}': case ']': if (tokens == NULL) break; type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); #ifdef JSMN_PARENT_LINKS if (parser->toknext < 1) { return JSMN_ERROR_INVAL; } token = &tokens[parser->toknext - 1]; for (;;) { if (token->start != -1 && token->end == -1) { if (token->type != type) { return JSMN_ERROR_INVAL; } token->end = parser->pos + 1; parser->toksuper = token->parent; break; } if (token->parent == -1) { break; } token = &tokens[token->parent]; } #else for (i = parser->toknext - 1; i >= 0; i--) { token = &tokens[i]; if (token->start != -1 && token->end == -1) { if (token->type != type) { return JSMN_ERROR_INVAL; } parser->toksuper = -1; token->end = parser->pos + 1; break; } } /* Error if unmatched closing bracket */ if (i == -1) return JSMN_ERROR_INVAL; for (; i >= 0; i--) { token = &tokens[i]; if (token->start != -1 && token->end == -1) { parser->toksuper = i; break; } } #endif break; case '\"': r = jsmn_parse_string(parser, js, len, tokens, num_tokens); if (r < 0) return r; count++; if (parser->toksuper != -1 && tokens != NULL) tokens[parser->toksuper].size++; break; case '\t' : case '\r' : case '\n' : case ' ': break; case ':': parser->toksuper = parser->toknext - 1; break; case ',': if (tokens != NULL && tokens[parser->toksuper].type != JSMN_ARRAY && tokens[parser->toksuper].type != JSMN_OBJECT) { #ifdef JSMN_PARENT_LINKS parser->toksuper = tokens[parser->toksuper].parent; #else for (i = parser->toknext - 1; i >= 0; i--) { if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { if (tokens[i].start != -1 && tokens[i].end == -1) { parser->toksuper = i; break; } } } #endif } break; #ifdef JSMN_STRICT /* In strict mode primitives are: numbers and booleans */ case '-': case '0': case '1' : case '2': case '3' : case '4': case '5': case '6': case '7' : case '8': case '9': case 't': case 'f': case 'n' : /* And they must not be keys of the object */ if (tokens != NULL) { jsmntok_t *t = &tokens[parser->toksuper]; if (t->type == JSMN_OBJECT || (t->type == JSMN_STRING && t->size != 0)) { return JSMN_ERROR_INVAL; } } #else /* In non-strict mode every unquoted value is a primitive */ default: #endif r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); if (r < 0) return r; count++; if (parser->toksuper != -1 && tokens != NULL) tokens[parser->toksuper].size++; break; #ifdef JSMN_STRICT /* Unexpected char in strict mode */ default: return JSMN_ERROR_INVAL; #endif } } for (i = parser->toknext - 1; i >= 0; i--) { /* Unmatched opened object or array */ if (tokens[i].start != -1 && tokens[i].end == -1) { return JSMN_ERROR_PART; } } return count; } /** * Creates a new parser based over a given buffer with an array of tokens * available. */ void jsmn_init(jsmn_parser *parser) { parser->pos = 0; parser->toknext = 0; parser->toksuper = -1; } nmh-1.7.1-RC3/thirdparty/jsmn/jsmn.h000644 007761 000024 00000003160 13205305706 017244 0ustar00kenhstaff000000 000000 #ifndef __JSMN_H_ #define __JSMN_H_ #include #ifdef __cplusplus extern "C" { #endif /** * JSON type identifier. Basic types are: * o Object * o Array * o String * o Other primitive: number, boolean (true/false) or null */ typedef enum { JSMN_PRIMITIVE = 0, JSMN_OBJECT = 1, JSMN_ARRAY = 2, JSMN_STRING = 3 } jsmntype_t; typedef enum { /* Not enough tokens were provided */ JSMN_ERROR_NOMEM = -1, /* Invalid character inside JSON string */ JSMN_ERROR_INVAL = -2, /* The string is not a full JSON packet, more bytes expected */ JSMN_ERROR_PART = -3 } jsmnerr_t; /** * JSON token description. * @param type type (object, array, string etc.) * @param start start position in JSON data string * @param end end position in JSON data string */ typedef struct { jsmntype_t type; int start; int end; int size; #ifdef JSMN_PARENT_LINKS int parent; #endif } jsmntok_t; /** * JSON parser. Contains an array of token blocks available. Also stores * the string being parsed now and current position in that string */ typedef struct { unsigned int pos; /* offset in the JSON string */ unsigned int toknext; /* next token to allocate */ int toksuper; /* superior token node, e.g parent object or array */ } jsmn_parser; /** * Create JSON parser over an array of tokens */ void jsmn_init(jsmn_parser *parser); /** * Run JSON parser. It parses a JSON data string into and array of tokens, each describing * a single JSON object. */ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len, jsmntok_t *tokens, unsigned int num_tokens); #ifdef __cplusplus } #endif #endif /* __JSMN_H_ */ nmh-1.7.1-RC3/test/ali/000755 007761 000024 00000000000 13243043704 014506 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/anno/000755 007761 000024 00000000000 13243043704 014674 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/bad-input/000755 007761 000024 00000000000 13243043704 015624 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/burst/000755 007761 000024 00000000000 13243043704 015100 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/cleanup000755 007761 000024 00000000662 13205305704 015321 0ustar00kenhstaff000000 000000 #!/bin/sh # # This exists so "make check" will always clean up the "inst" directory # after a run, even if tests fail. That way if you fix a problem and do # another "make check", you will get new binaries to test against. # 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" rm -rf "${MH_TEST_DIR}"/.w3m rm -rf "${MH_INST_DIR}" nmh-1.7.1-RC3/test/common.sh.in000644 007761 000024 00000034021 13243042053 016166 0ustar00kenhstaff000000 000000 # Common helper routines for test shell scripts -- to be sourced by them # @configure_input@ #### The following variables are set by "make check". Ensure #### that they are set here so that individual tests can be run #### outside of make. Requires that MH_OBJ_DIR be set on entry. #### Use the result of cd and pwd -P so that the result will agree #### with what getcwd(3) returns. test -d "$MH_OBJ_DIR/test/testdir" || mkdir -p "$MH_OBJ_DIR/test/testdir" test -z "$MH_TEST_DIR" && MH_TEST_DIR=`cd "$MH_OBJ_DIR/test/testdir" && pwd -P` export MH_TEST_DIR test -z "$MH_INST_DIR" && MH_INST_DIR="${MH_TEST_DIR}/inst" test -z "$MH_VERSION" && MH_VERSION="@VERSION@" test -z "$prefix" && prefix=@prefix@ test -z "$datarootdir" && datarootdir=@datarootdir@ test -z "$exec_prefix" && exec_prefix=@exec_prefix@ test -z "$bindir" && bindir="@bindir@" test -z "$mandir" && mandir="@mandir@" test -z "$nmhetcdir" && nmhetcdir="@sysconfdir@/nmh" #### The following doesn't support running the distcheck version of #### test-mhparam standalone, but only via make distcheck. test -z "$nmhetcdirinst" && nmhetcdirinst="@nmhetcdirinst@$nmhetcdir" test -z "$nmhlibexecdir" && nmhlibexecdir="@libexecdir@/nmh" test -z "$supported_locks" && supported_locks="@supported_locks@" test -z "$default_locking" && default_locking="@default_locking@" test -z "$MULTIBYTE_ENABLED" && MULTIBYTE_ENABLED="@MULTIBYTE_ENABLED@" test -z "$ICONV_ENABLED" && ICONV_ENABLED="@ICONV_ENABLED@" test -z "$OAUTH_SUPPORT" && OAUTH_SUPPORT="@OAUTH_SUPPORT@" test -z "$CURL_USER_AGENT" && CURL_USER_AGENT="@CURL_USER_AGENT@" #### Make sure that HOME is set to avoid run-time warning from w3m about #### not being able to create config directory. HOME="$MH_TEST_DIR" export HOME unset MAILDROP MHBUILD MHCONTEXT MHMTSUSERCONF MHN MHSHOW MHSTORE unset MHLDEBUG MHPDEBUG MHWDEBUG PAGER XOAUTH SMTPUTF8 #### Set LC_ALL in individual tests as needed. Unset these so #### that we don't depend on user's settings in other tests. unset LANG LC_ALL LC_CTYPE # Don't have libcurl(3) use the environment's proxy for tests' # connections to 127.0.0.1. unset http_proxy ALL_PROXY all_proxy #### Use a test dir for tmp files when MHTMPDIR applies. MHTMPDIR="$MH_TEST_DIR"/Mail export MHTMPDIR #### If you're reading this .... you can set MH_TEST_NOCLEANUP to prevent #### the test suite from cleaning up the results of a test run, if you need #### to do manual debugging on a test. output_md5() { #### Output just the checksum. If the filename needs to appear on #### the same line, the caller needs to add it. This avoids #### differences due to a leading '*' binary file indicator, for #### text files, on some platforms (Cygwin). @MD5SUM@ $* | @MD5FMT@ | awk '{print $1}' } #### Use built-in $((...)) in test suite if shell supports it. #### Borrowed from configure's as_fn_arith. The result is placed #### in global arith_val. #### Detected at run-time instead of by configure to allow testing #### with different shells. if (eval "test \$(( 1 + 1 )) = 2" 2>/dev/null); then eval 'arith_eval () { arith_val=$(( $* )); }' else arith_eval () { arith_val=`expr "$@" || test $? -eq 1`; } fi test_skip () { why="$1" echo "$0: skipped: $why" exit 77 } # portable implementation of 'which' utility findprog() { PROG="$1" #### Don't need to save current IFS because this function is run in #### a subshell. IFS=: for D in $PATH; do if [ -z "$D" ]; then D=. fi if [ -f "$D/$PROG" -a -x "$D/$PROG" ]; then printf '%s\n' "$D/$PROG" break fi done } require_prog () { if [ -z "`findprog $1`" ]; then test_skip "missing $1" fi } # Skip test if none of the offered locales are supported. # As side effect, use the first locale that is found. Note that # some platforms allow, by way of example, en_US.UTF-8 to be used # even though en_US.UTF8 is listed by locale -a. But by setting # LC_ALL here, we don't rely on that. require_locale () { for locale in "$@"; do if locale -a | grep -i "$locale" >/dev/null; then LC_ALL="$locale"; export LC_ALL return fi done test_skip "no suitable locale available" } # Some stuff for doing silly progress indicators if [ -t 1 ] ; then progress_update () { THIS="$1" FIRST="$2" LAST="$3" arith_eval $LAST - $FIRST; RANGE=$arith_val arith_eval $THIS - $FIRST; PROG=$arith_val # this automatically rounds to nearest integer arith_eval 100 \* $PROG / $RANGE; PERC=$arith_val # note \r so next update will overwrite printf '%3d%%\r' $PERC } progress_done () { printf '100%%\n' } else # don't emit anything if stdout is not connected to a tty. progress_update () { : } progress_done () { : } fi check_for_hard_links () { set +e printf '' > "${MH_TEST_DIR}/$$-1" xdir_links_supported=0 if link "${MH_TEST_DIR}/$$-1" "${MH_TEST_DIR}/$$-2" 2>/dev/null; then hard_links_supported=1 mkdir "${MH_TEST_DIR}/xlinkdir" if link "${MH_TEST_DIR}/$$-1" "${MH_TEST_DIR}/xlinkdir/$$-2" 2>/dev/null; then xdir_links_supported=1 fi else hard_links_supported=0 fi rm -f "${MH_TEST_DIR}/$$-1" "${MH_TEST_DIR}/$$-2" rm -rf "${MH_TEST_DIR}/xlinkdir" set -e } #### Filter that squeezes blank lines, partially emulating GNU cat -s, #### but sufficient for our purpose. #### From http://www-rohan.sdsu.edu/doc/sed.html, compiled by Eric Pement. squeeze_lines() { sed '/^$/N;/\n$/D' } #### Filter that removes blank lines and leading space that lynx inserts. #### but sufficient for our purpose. squeeze_whitespace() { sed '/^$/D; s/^ *//;' } #### Filter that converts non-breakable space U+00A0 to an ASCII space. prepare_space() { sed 's/'"`printf '\\302\\240'`"'/ /g' } #### check() requires two arguments, each the name of a file to be #### diff'ed. #### If the contents are same, the second file is removed. If different, #### global variable "failed" is incremented. #### Optional arguments: #### 'keep first' -- first file is removed unless this is present. #### 'ignore space' -- spacing differences will not be considered #### significant, emulating GNU diff -w. It is assumed that the #### first file has already been run through prepare_space. #### ':' -- will print '' in the failure message, #### to make it easier to tell which of multiple tests has failed. check() { first=$1; shift second=$1; shift keepfirst= ignorespace= label=test while [ $# -gt 0 ]; do case $1 in 'keep first') keepfirst=1 ;; 'ignore space') ignorespace=1 ;; ':') shift; label=\'"$*"\'; break ;; *) echo "$0: invalid check() argument \"$1\" in test suite" >&2 ;; esac shift done success= if [ "$ignorespace" ]; then #### POSIX diff should support -b. prepare_space <"$second" | diff -b "$first" - >/dev/null && success=1 else cmp -s "$first" "$second" && success=1 fi if [ "$success" ]; then [ "$keepfirst" ] || rm -f "$first" rm -f "$second" else echo #### POSIX diff should support -c. diff -c "$first" "$second" || true echo echo "$0: $label failed, outputs are in $first and $second." failed=`expr ${failed:-0} + 1` #### Set return status of the function. [ $failed -eq 0 ] fi } #### Shortcut to enable use of valgrind: set NMH_VALGRIND environment #### variable (to anything) so run_* will use valgrind. if [ "${NMH_VALGRIND}" -a -z "${NMH_TEST_PREFIX}" ]; then #### Need absolute path to valgrind.supp in case the test does a cd. NMH_TEST_PREFIX="valgrind --quiet --error-exitcode=1 \ --suppressions=`cd ${srcdir} && pwd`/test/valgrind.supp" fi #### Run test under another program by setting NMH_TEST_PREFIX #### environment variable to, e.g., 'valgrind --quiet'. run_prog() { case $1 in #### Don't run valgrind on shell built-in. eval\ *) "$@" ;; *) ${NMH_TEST_PREFIX} "$@" ;; esac } #### run_test() requires two arguments, the first is a program and #### arguments, the second is its expected one-line output string. #### If the actual output does not match that string: #### an error message is printed and global variable "failed" is incremented; #### if there is an optional third argument, it is used in the error message. run_test() { set +e case $1 in #### Don't run valgrind on shell built-in. eval\ *) actual_output=`$1 2>&1` ;; *) actual_output=`${NMH_TEST_PREFIX} $1 2>&1` ;; esac set -e if test x"$actual_output" != x"$2"; then echo "$0: ${3:-\"$1\"} expected:" 1>&2 echo " '$2'" 1>&2 echo "but instead got:" 1>&2 echo " '$actual_output'" 1>&2 failed=`expr ${failed:-0} + 1` fi } #### check_exit() runs the command in $2..., capturing stdout and #### stderr, and then tests its exit status with the test(1) condition #### in $1. If that fails, the captured stdout and stderr are #### displayed, and $failed incremented. check_exit() { c="$1"; shift t="$MH_TEST_DIR/.check_exit" r=0 $NMH_TEST_PREFIX "$@" >"$t.1" 2>"$t.2" || r=$? if test $r $c; then rm "$t.1" "$t.2" else echo "$0: check_exit: $r $c failed: $*" >&2 echo " stdout:" >&2 sed 's/^/ /' "$t.1" >&2 echo " stderr:" >&2 sed 's/^/ /' "$t.2" >&2 failed=`expr ${failed:-0} + 1` fi } #### Function invoked by trap on exit. cleanup() { #### Save exit status to use as status for this program. status=$? #### Clean up test mail space. #### cd to $MH_TEST_DIR before trying to remove its Mail #### subdirectory. rm on Solaris won't remove it if it's in the #### path of the current working directory. test -z "$MH_TEST_NOCLEANUP" && (cd "$MH_TEST_DIR"; rm -rf "$MH_TEST_DIR"/Mail) #### Report test name if set, which indicates failure. #### Relies on set -e to invoke the trap which calls #### this function on failure. #### To use: #### 1) Set test name before running the test, use start_test(). #### 2) Unset upon successful completion, use finish_test(). if test -n "$nmh_tests_testname"; then echo "first named test failure: $nmh_tests_testname" fi #### Exit with non-zero status if failure. Failure is defined as either #### non-empty nmh_tests_testname or non-zero exit status on entry to the #### function. if test -n "$nmh_tests_testname" -o $status -ne 0; then test $status -ne 0 && exit $status || exit 1 test $status -ne 0 && exit 0 || exit 0 fi } #### Function to set the test name, and whatever the future brings. start_test() { #### run_test disables exit on non-zero status, but does increment #### failed. Don't overwrite nmh_tests_testname if there was a #### failure; remember the first test that failed. [ ${failed:-0} -eq 0 ] && nmh_tests_testname="$1" } #### Corresponding function to indicate that the test has finished. It need #### not be called after each test, just the last one in a file. finish_test() { #### run_test disables exit on non-zero status, but does increment #### failed. Don't unset nmh_tests_testname if there was a failure. [ ${failed:-0} -eq 0 ] && unset nmh_tests_testname } setup_test () { set -e MH="${MH_TEST_DIR}/Mail/.mh_profile" MHMTSCONF="${MH_INST_DIR}${nmhetcdir}/mts.conf" MH_LIBEXEC_DIR="${MH_INST_DIR}${nmhlibexecdir}" export MH MHMTSCONF MH_LIBEXEC_DIR # # Only install once # if [ -d "${MH_INST_DIR}${bindir}" ]; then : else (cd "${MH_OBJ_DIR}" && make DESTDIR="${MH_INST_DIR}" SETGID_MAIL= install) || exit 1 #### Don't test with sendmail because it would really send the #### mail. If configured to use sendmail, change to smtp instead #### so that we use fakesmtp. #### And set up the maildrop in the test directory so tests don't #### use the user's real maildrop. #### test-slocal needs to look at the original mts.conf, so save it. mv -f "${MHMTSCONF}" "${MHMTSCONF}.old" sed -e 's/mts: *.*/mts: smtp/' \ -e "s%mmdfldir: *.*%mmdfldir: ${MH_TEST_DIR}/Mail%" \ -e 's%mmdflfil: *.*%mmdflfil: maildrop%' \ "${MHMTSCONF}.old" >"${MHMTSCONF}" fi #### On Solaris, must set PATH after the install! PATH="${MH_INST_DIR}${bindir}:${PATH}" export PATH # clean old test data on exit trap cleanup 0 # setup test data mkdir -p "$MH_TEST_DIR/Mail" || exit 1 cat > "$MH" < /dev/null #### Suppress warnings about a new version. #### mhparam version includes the nmh- prefix, so be consistent with that. printf 'Version: nmh-%s\n' "${MH_VERSION}" >> "${MH_TEST_DIR}"/Mail/context # create 10 basic messages for i in 1 2 3 4 5 6 7 8 9 10; do cat > $MH_TEST_DIR/Mail/inbox/$i < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: $i@test.nmh Subject: Testing message $i This is message number $i EOF done } nmh-1.7.1-RC3/test/comp/000755 007761 000024 00000000000 13243043704 014677 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/dist/000755 007761 000024 00000000000 13243043704 014704 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/fakehttp.c000644 007761 000024 00000006645 13243042053 015722 0ustar00kenhstaff000000 000000 /* fakehttp - A fake HTTP server used by the nmh test suite * * This code is Copyright (c) 2014, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #include #include #define LINESIZE 1024 #define PIDFN "/tmp/fakehttp.pid" int serve(const char *, const char *); void putcrlf(int, char *); static void strip_cr(char *buf, ssize_t *len) { ssize_t src, dst; for (src = dst = 0; src < *len; src++) { buf[dst] = buf[src]; if (buf[src] != '\r') { dst++; } } *len -= src - dst; } static void save_req(int conn, FILE *req) { char buf[BUFSIZ]; ssize_t r; int e; /* used to save errno */ int started = 0; /* whether the request has started coming in */ if (fcntl(conn, F_SETFL, O_NONBLOCK) < 0) { fprintf(stderr, "Unable to make socket non-blocking: %s\n", strerror(errno)); exit(1); } for (;;) { r = read(conn, buf, sizeof buf); if (!started) { /* First keep trying until some data is ready; for testing, don't * bother with using select to wait for input. */ if (r < 0) { e = errno; if (e == EAGAIN || e == EWOULDBLOCK) { continue; /* keep waiting */ } fclose(req); fprintf(stderr, "Unable to read socket: %s\n", strerror(e)); exit(1); } /* Request is here. Fall through to the fwrite below and keep * reading. */ started = 1; } if (r < 0) { e = errno; putc('\n', req); /* req body usually has no newline */ fclose(req); if (e != EAGAIN && e != EWOULDBLOCK) { fprintf(stderr, "Unable to read socket: %s\n", strerror(e)); exit(1); } /* For testing, we can get away without understand the HTTP request * and just treating the would-block case as meaning the request is * all done. */ return; } strip_cr(buf, &r); fwrite(buf, 1, r, req); } } static void send_res(int conn, FILE *res) { size_t size; ssize_t len; char *res_line = NULL; while ((len = getline(&res_line, &size, res)) > 0) { res_line[len - 1] = '\0'; putcrlf(conn, res_line); } free(res_line); if (!feof(res)) { fprintf(stderr, "read response failed: %s\n", strerror(errno)); exit(1); } } int main(int argc, char *argv[]) { struct st; int conn; FILE *req, *res; if (argc != 4) { fprintf(stderr, "Usage: %s output-filename port response\n", argv[0]); exit(1); } if (!(req = fopen(argv[1], "w"))) { fprintf(stderr, "Unable to open output file \"%s\": %s\n", argv[1], strerror(errno)); exit(1); } if (!(res = fopen(argv[3], "r"))) { fprintf(stderr, "Unable to open response \"%s\": %s\n", argv[3], strerror(errno)); exit(1); } conn = serve(PIDFN, argv[2]); save_req(conn, req); send_res(conn, res); close(conn); return 0; } nmh-1.7.1-RC3/test/fakepop.c000644 007761 000024 00000015512 13240376505 015543 0ustar00kenhstaff000000 000000 /* fakepop - A fake POP server used by the nmh test suite * * 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 #include #include #include #include #include #include #define PIDFILE "/tmp/fakepop.pid" #define LINESIZE 1024 #define BUFALLOC 4096 #define CHECKUSER() if (!user) { \ putcrlf(s, "-ERR Aren't you forgetting " \ "something? Like the USER command?"); \ continue; \ } #define CHECKAUTH() if (!auth) { \ putcrlf(s, "-ERR Um, hello? Forget to " \ "log in?"); \ continue; \ } void putcrlf(int, char *); int serve(const char *, const char *); static void putpopbulk(int, char *); static int getpop(int, char *, ssize_t); static char *readmessage(FILE *); int main(int argc, char *argv[]) { FILE **mfiles; char line[LINESIZE]; int rc, s, user = 0, auth = 0, i, j; int numfiles; size_t *octets; const char *xoauth; if (argc < 5) { fprintf(stderr, "Usage: %s port username " "password mail-file [mail-file ...]\n", argv[0]); exit(1); } if (strcmp(argv[2], "XOAUTH") == 0) { xoauth = argv[3]; } else { xoauth = NULL; } numfiles = argc - 4; mfiles = malloc(sizeof(FILE *) * numfiles); if (! mfiles) { fprintf(stderr, "Unable to allocate %d bytes for file " "array\n", (int) (sizeof(FILE *) * numfiles)); exit(1); } octets = malloc(sizeof(*octets) * numfiles); if (! octets) { fprintf(stderr, "Unable to allocate %d bytes for size " "array\n", (int) (sizeof(FILE *) * numfiles)); exit(1); } for (i = 4, j = 0; i < argc; i++, j++) { if (!(mfiles[j] = fopen(argv[i], "r"))) { fprintf(stderr, "Unable to open message file \"%s\"" ": %s\n", argv[i], strerror(errno)); exit(1); } /* * POP wants the size of the maildrop in bytes, but * with \r\n line endings. Calculate that. */ octets[j] = 0; while (fgets(line, sizeof(line), mfiles[j])) { octets[j] += strlen(line); if (strrchr(line, '\n')) octets[j]++; } rewind(mfiles[j]); } s = serve(PIDFILE, argv[1]); /* * Pretend to be a POP server */ putcrlf(s, "+OK Not really a POP server, but we play one on TV"); for (;;) { char linebuf[LINESIZE]; rc = getpop(s, linebuf, sizeof(linebuf)); if (rc <= 0) break; /* Error or EOF */ if (strcasecmp(linebuf, "CAPA") == 0) { putpopbulk(s, "+OK We have no capabilities, really\r\n" "FAKE-CAPABILITY\r\n"); if (xoauth != NULL) { putcrlf(s, "SASL XOAUTH2"); } putcrlf(s, "."); } else if (strncasecmp(linebuf, "USER ", 5) == 0) { if (strcmp(linebuf + 5, argv[2]) == 0) { putcrlf(s, "+OK Niiiice!"); user = 1; } else { putcrlf(s, "-ERR Don't play me, bro!"); } } else if (strncasecmp(linebuf, "PASS ", 5) == 0) { CHECKUSER(); if (strcmp(linebuf + 5, argv[3]) == 0) { putcrlf(s, "+OK Aren't you a sight " "for sore eyes!"); auth = 1; } else { putcrlf(s, "-ERR C'mon!"); } } else if (xoauth != NULL && strncasecmp(linebuf, "AUTH XOAUTH2", 12) == 0) { if (strstr(linebuf, xoauth) == NULL) { putcrlf(s, "+ base64-json-err"); rc = getpop(s, linebuf, sizeof(linebuf)); if (rc != 0) break; /* Error or EOF */ putcrlf(s, "-ERR [AUTH] Invalid credentials."); continue; } putcrlf(s, "+OK Welcome."); auth = 1; } else if (strcasecmp(linebuf, "STAT") == 0) { size_t total = 0; CHECKAUTH(); for (i = 0, j = 0; i < numfiles; i++) { if (mfiles[i]) { total += octets[i]; j++; } } snprintf(linebuf, sizeof(linebuf), "+OK %d %d", i, (int) total); putcrlf(s, linebuf); } else if (strncasecmp(linebuf, "RETR ", 5) == 0) { CHECKAUTH(); rc = sscanf(linebuf + 5, "%d", &i); if (rc != 1) { putcrlf(s, "-ERR Whaaaa...?"); continue; } if (i < 1 || i > numfiles) { putcrlf(s, "-ERR That message number is " "out of range, jerkface!"); continue; } if (mfiles[i - 1] == NULL) { putcrlf(s, "-ERR Sorry, don't have it anymore"); } else { char *buf = readmessage(mfiles[i - 1]); putcrlf(s, "+OK Here you go ..."); putpopbulk(s, buf); free(buf); } } else if (strncasecmp(linebuf, "DELE ", 5) == 0) { CHECKAUTH(); rc = sscanf(linebuf + 5, "%d", &i); if (rc != 1) { putcrlf(s, "-ERR Whaaaa...?"); continue; } if (i < 1 || i > numfiles) { putcrlf(s, "-ERR That message number is " "out of range, jerkface!"); continue; } if (mfiles[i - 1] == NULL) { putcrlf(s, "-ERR Um, didn't you tell me " "to delete it already?"); } else { fclose(mfiles[i - 1]); mfiles[i - 1] = NULL; putcrlf(s, "+OK Alright man, I got rid of it"); } } else if (strcasecmp(linebuf, "QUIT") == 0) { putcrlf(s, "+OK See ya, wouldn't want to be ya!"); close(s); break; } else { putcrlf(s, "-ERR Um, what?"); } } exit(0); } /* * Put one big buffer to the POP server. Should have already had the line * endings set up and dot-stuffed if necessary. */ static void putpopbulk(int socket, char *data) { ssize_t datalen = strlen(data); if (write(socket, data, datalen) < 0) { perror ("write"); } } /* * Get one line from the POP server. We don't do any buffering here. */ static int getpop(int socket, char *data, ssize_t len) { int cc; int offset = 0; for (;;) { cc = read(socket, data + offset, len - offset); if (cc < 0) { fprintf(stderr, "Read failed: %s\n", strerror(errno)); exit(1); } if (cc == 0) { return 0; } offset += cc; if (offset >= len) { fprintf(stderr, "Input buffer overflow " "(%d bytes)\n", (int) len); exit(1); } if (data[offset - 1] == '\n' && data[offset - 2] == '\r') { data[offset - 2] = '\0'; return offset - 2; } } } #define HAVEROOM(buf, size, used, new) do { \ if (used + new > size - 1) { \ buf = realloc(buf, size += BUFALLOC); \ } \ } while (0) /* * Read a file and return it as one malloc()'d buffer. Convert \n to \r\n * and dot-stuff if necessary. */ static char * readmessage(FILE *file) { char *buffer = malloc(BUFALLOC); ssize_t bufsize = BUFALLOC, used = 0; char linebuf[LINESIZE]; int i; buffer[0] = '\0'; while (fgets(linebuf, sizeof(linebuf), file)) { if (strcmp(linebuf, ".\n") == 0) { HAVEROOM(buffer, bufsize, used, 4); strcat(buffer, "..\r\n"); } else { i = strlen(linebuf); if (i && linebuf[i - 1] == '\n') { HAVEROOM(buffer, bufsize, used, i + 1); linebuf[i - 1] = '\0'; strcat(buffer, linebuf); strcat(buffer, "\r\n"); } else { HAVEROOM(buffer, bufsize, used, i); strcat(buffer, linebuf); } } } /* * Put a terminating dot at the end */ HAVEROOM(buffer, bufsize, used, 3); strcat(buffer, ".\r\n"); rewind(file); return buffer; } nmh-1.7.1-RC3/test/fakesendmail000755 007761 000024 00000002621 13205305704 016312 0ustar00kenhstaff000000 000000 #! /bin/sh ## # fakesendmail - A fake sendmail program used by the nmh test suite # to test the sendmail/smtp and sendmail/pipe mts # methods. # # This code is Copyright (c) 2012, by the authors of nmh. See the # COPYRIGHT file in the root or documentation directory of the nmh # distribution for complete copyright information. ## if [ "$MH_TEST_DIR"x = x ]; then printf '%s is intended for use only by the nmh test suite\n' "$0" exit 1 fi #### Puts message on stdin in a drop that the test knows about. deliver="$MH_LIBEXEC_DIR/rcvpack $MH_TEST_DIR/Mail/fakesendmail.mbox" found_dasht=0 for arg in "$@"; do [ "$arg" = -t ] && found_dasht=1 done if [ $found_dasht -eq 0 ]; then # sendmail/smtp msg= datamode=0 printf '%s\n' "220 If it can't be done in Bourne shell it's not worth doing" while read line; do #### Strip off carriage returns, they confuse the pattern matching. line=`printf %s "$line" | tr -d '\r'` case "$line" in DATA) printf '354 do tell\n'; datamode=1 ;; .) printf '250 done\n'; datamode=0; printf %s "$msg" | $deliver; msg= ;; QUIT) printf '221 byenow\n'; break ;; *) [ $datamode -eq 1 ] && msg="${msg}${line} " || printf '250 OK\n' esac done else # sendmail/pipe #### This will delete any lines in the message body that start with Bcc:! sed -e '/^[Bb][Cc][Cc]:/d' | $deliver fi nmh-1.7.1-RC3/test/fakesmtp.c000644 007761 000024 00000007436 13243042053 015725 0ustar00kenhstaff000000 000000 /* fakesmtp - A fake SMTP server used by the nmh test suite * * 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 #include #include #include #include #include #include #include #define PIDFILE "/tmp/fakesmtp.pid" #define LINESIZE 1024 enum { /* Processing top-level SMTP commands (e.g. EHLO, DATA). */ SMTP_TOP, /* Processing payload of a DATA command. */ SMTP_DATA, /* Looking for the blank line required by XOAUTH2 after 334 response. */ SMTP_XOAUTH_ERR }; void putcrlf(int, char *); int serve(const char *, const char *); static int getsmtp(int, char *); int main(int argc, char *argv[]) { int rc, conn, smtp_state; FILE *f; const char *xoauth = getenv("XOAUTH"); const char *smtputf8 = getenv("SMTPUTF8"); if (argc != 3) { fprintf(stderr, "Usage: %s output-filename port\n", argv[0]); exit(1); } if (!(f = fopen(argv[1], "w"))) { fprintf(stderr, "Unable to open output file \"%s\": %s\n", argv[1], strerror(errno)); exit(1); } conn = serve(PIDFILE, argv[2]); /* * Pretend to be an SMTP server. */ putcrlf(conn, "220 Not really an ESMTP server"); smtp_state = SMTP_TOP; for (;;) { char line[LINESIZE]; rc = getsmtp(conn, line); if (rc == -1) break; /* EOF */ fprintf(f, "%s\n", line); switch (smtp_state) { case SMTP_DATA: if (strcmp(line, ".") == 0) { smtp_state = SMTP_TOP; putcrlf(conn, "250 Thanks for the info!"); } continue; case SMTP_XOAUTH_ERR: smtp_state = SMTP_TOP; putcrlf(conn, "535 Not no way, not no how!"); continue; } /* * Most commands we ignore and send the same response to. */ if (strcmp(line, "QUIT") == 0) { fclose(f); f = NULL; putcrlf(conn, "221 Later alligator!"); close(conn); break; } if (strcmp(line, "DATA") == 0) { putcrlf(conn, "354 Go ahead"); smtp_state = SMTP_DATA; continue; } if (strncmp(line, "EHLO", 4) == 0) { putcrlf(conn, "250-ready"); if (smtputf8 != NULL) { putcrlf(conn, "250-8BITMIME"); putcrlf(conn, "250-SMTPUTF8"); } if (xoauth != NULL) { putcrlf(conn, "250-AUTH XOAUTH2"); } putcrlf(conn, "250 I'll buy that for a dollar!"); continue; } if (xoauth != NULL) { /* XOAUTH2 support enabled; handle AUTH (and EHLO above). */ if (strncmp(line, "AUTH", 4) == 0) { if (strncmp(line, "AUTH XOAUTH2", 12) == 0 && strstr(line, xoauth) != NULL) { putcrlf(conn, "235 OK come in"); continue; } putcrlf(conn, "334 base64-json-err"); smtp_state = SMTP_XOAUTH_ERR; continue; } } putcrlf(conn, "250 I'll buy that for a dollar!"); } if (f) fclose(f); exit(0); } /* * Read a line (up to the \r\n) */ static int getsmtp(int socket, char *data) { int cc; static unsigned int bytesinbuf = 0; static char buffer[LINESIZE * 2], *p; for (;;) { /* * Find our \r\n */ if (bytesinbuf > 0 && (p = strchr(buffer, '\r')) && *(p + 1) == '\n') { *p = '\0'; strncpy(data, buffer, LINESIZE); data[LINESIZE - 1] = '\0'; cc = strlen(buffer); /* * Shuffle leftover bytes back to the beginning */ bytesinbuf -= cc + 2; /* Don't forget \r\n */ if (bytesinbuf > 0) { memmove(buffer, buffer + cc + 2, bytesinbuf); } return cc; } if (bytesinbuf >= sizeof(buffer)) { fprintf(stderr, "Buffer overflow in getsmtp()!\n"); exit(1); } memset(buffer + bytesinbuf, 0, sizeof(buffer) - bytesinbuf); cc = read(socket, buffer + bytesinbuf, sizeof(buffer) - bytesinbuf); if (cc < 0) { fprintf(stderr, "Read failed: %s\n", strerror(errno)); exit(1); } if (cc == 0) return -1; bytesinbuf += cc; } } nmh-1.7.1-RC3/test/folder/000755 007761 000024 00000000000 13243043704 015214 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/format/000755 007761 000024 00000000000 13243043704 015231 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/forw/000755 007761 000024 00000000000 13243043704 014716 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/getcanon.c000644 007761 000024 00000002650 13243042053 015702 0ustar00kenhstaff000000 000000 /* getcanon.c - Print the canonical name of a host, default to localhost. * * 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 /* for getaddrinfo */ #include #include #include /* for gethostname */ #include /* for _POSIX_HOST_NAME_MAX */ #include /* for memset */ #include #include int main(int argc, char *argv[]) { char buf[_POSIX_HOST_NAME_MAX + 1]; const char *hostname = buf; struct addrinfo hints, *res; int status = 0; /* Borrowed the important code below from LocalName() in sbr/mts.c. */ if (argc < 2) { /* First get our local name. */ status = gethostname(buf, sizeof buf); } else if (argc == 2) { hostname = argv[1]; } else if (argc > 2) { fprintf(stderr, "usage: %s [hostname]\n", argv[0]); return 1; } if (status == 0) { /* Now fully qualify the hostname. */ memset(&hints, 0, sizeof hints); hints.ai_flags = AI_CANONNAME; hints.ai_family = AF_UNSPEC; if ((status = getaddrinfo(hostname, NULL, &hints, &res)) == 0) { printf("%s\n", res->ai_canonname); freeaddrinfo(res); } else { printf("%s\n", hostname); } } else { fprintf(stderr, "gethostname() failed: %s\n", strerror(errno)); } return status; } nmh-1.7.1-RC3/test/getcwidth.c000644 007761 000024 00000006743 13243042053 016075 0ustar00kenhstaff000000 000000 /* getcwidth - Get the OS's idea of the width of Unicode codepoints * * 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 #include #include #include #ifdef HAVE_CONFIG_H #include #endif #ifdef MULTIBYTE_SUPPORT #include #include #endif #ifdef MULTIBYTE_SUPPORT static void usage(char *); static void dumpwidth(void); static void getwidth(const char *); #endif /* MULTIBYTE_SUPPORT */ int main(int argc, char *argv[]) { #ifndef MULTIBYTE_SUPPORT (void) argc; (void) argv; fprintf(stderr, "Nmh was not configured with multibyte support\n"); exit(1); #else /* MULTIBYTE_SUPPORT */ wchar_t c; int i; if (! setlocale(LC_ALL, "")) { fprintf(stderr, "setlocale failed, check your LC_ALL, " "LC_CTYPE, and LANG environment variables\n"); } if (argc < 2) usage(argv[0]); if (strcmp(argv[1], "--dump") == 0) { if (argc == 2) { dumpwidth(); exit(0); } else { fprintf(stderr, "--dump cannot be combined with " "other arguments\n"); exit(1); } } /* * Process each argument. If it begins with "U+", then try to * convert it to a Unicode codepoint. Otherwise, take each * string and get the total width */ for (i = 1; i < argc; i++) { if (strncmp(argv[i], "U+", 2) == 0) { /* * We're making a big assumption here that * wchar_t represents a Unicode codepoint. * That technically isn't valid unless the * C compiler defines __STDC_ISO_10646__, but * we're going to assume now that it works. */ errno = 0; c = strtoul(argv[i] + 2, NULL, 16); if (errno) { fprintf(stderr, "Codepoint %s invalid\n", argv[i]); continue; } printf("%d\n", wcwidth(c)); } else { getwidth(argv[i]); } } exit(0); } static void usage(char *argv0) { fprintf(stderr, "Usage: %s [--dump]\n", argv0); fprintf(stderr, " %s U+XXXX [...]\n", argv0); fprintf(stderr, " %s utf-8-sequence [...]\n", argv0); fprintf(stderr, "Returns the column width of a Unicode codepoint " "or UTF-8 character sequence\n"); fprintf(stderr, "\t--dump\tDump complete width table\n"); exit(1); } static void getwidth(const char *string) { wchar_t c; int charlen, charleft = strlen(string); int length = 0; /* * In theory we should be able to use wcswidth(), but since we're * testing out how the format libraries behave we'll do it a character * at a time. */ if (mbtowc(NULL, NULL, 0)) {} while (charleft > 0) { int clen; charlen = mbtowc(&c, string, charleft); if (charlen == 0) break; if (charlen < 0) { fprintf(stderr, "Unable to convert string \"%s\"\n", string); return; } if ((clen = wcwidth(c)) < 0) { fprintf(stderr, "U+%04lX non-printable\n", (unsigned long int) c); return; } length += clen; string += charlen; charleft -= charlen; } printf("%d\n", length); } static void dumpwidth(void) { wchar_t wc, low; int width, lastwidth; for (wc = 0, low = 1, lastwidth = wcwidth(1); wc < 0xffff; wc++) { width = wcwidth(wc+1); if (width != lastwidth) { printf("%04lX - %04lX = %d\n", (unsigned long int) low, (unsigned long int) (wc), lastwidth); low = wc+1; } lastwidth = width; } width = wcwidth(wc); if (width == lastwidth) printf("%04lX - %04lX = %d\n", (unsigned long int) low, (unsigned long int) (wc), width); #endif /* MULTIBYTE_SUPPORT */ } nmh-1.7.1-RC3/test/getfullname.c000644 007761 000024 00000002306 13243042053 016405 0ustar00kenhstaff000000 000000 /* getfullname.c - Extract a user's name out of the GECOS field in * the password file. * * 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 #include #include #include #include #include extern void escape_display_name (char *, size_t); int main(int argc, char *argv[]) { struct passwd *pwd; char buf[BUFSIZ], *p; if (argc < 2) { pwd = getpwuid(getuid()); if (! pwd) { fprintf(stderr, "Unable to retrieve user info for " "userid %ld\n", (long) getuid()); exit(1); } strncpy(buf, pwd->pw_gecos, sizeof(buf)); buf[sizeof(buf) - 1] = '\0'; } else if (argc == 2) { strncpy(buf, argv[1], sizeof(buf)); } else if (argc > 2) { fprintf (stderr, "usage: %s [name]\n", argv[0]); return 1; } /* * Perform the same processing that getuserinfo() does. */ /* * Stop at the first comma. */ if ((p = strchr(buf, ','))) *p = '\0'; /* * Quote the entire string if it has a special character in it. */ escape_display_name (buf, sizeof(buf)); printf("%s\n", buf); exit(0); } nmh-1.7.1-RC3/test/inc/000755 007761 000024 00000000000 13243043705 014513 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/install-mh/000755 007761 000024 00000000000 13243043705 016012 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/locking/000755 007761 000024 00000000000 13243043705 015370 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/manpages/000755 007761 000024 00000000000 13243043705 015535 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/mhbuild/000755 007761 000024 00000000000 13243043705 015366 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/mhfixmsg/000755 007761 000024 00000000000 13243043705 015564 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/mhical/000755 007761 000024 00000000000 13243043705 015177 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/mhl/000755 007761 000024 00000000000 13243043705 014522 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/mhlist/000755 007761 000024 00000000000 13243043705 015242 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/mhmail/000755 007761 000024 00000000000 13243043705 015211 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/mhparam/000755 007761 000024 00000000000 13243043705 015367 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/mhpath/000755 007761 000024 00000000000 13243043705 015223 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/mhshow/000755 007761 000024 00000000000 13243043705 015247 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/mhstore/000755 007761 000024 00000000000 13243043705 015423 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/mkstemp/000755 007761 000024 00000000000 13243043705 015422 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/new/000755 007761 000024 00000000000 13243043705 014533 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/oauth/000755 007761 000024 00000000000 13243043705 015062 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/pick/000755 007761 000024 00000000000 13243043705 014670 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/post/000755 007761 000024 00000000000 13243043705 014727 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/prompter/000755 007761 000024 00000000000 13243043705 015612 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/rcv/000755 007761 000024 00000000000 13243043705 014534 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/README000644 007761 000024 00000006741 13205305704 014630 0ustar00kenhstaff000000 000000 nmh unit test suite. The purpose of these tests is to verify the functionality of the nmh commands. The goal of the suite is to create an environment where testing nmh commands is easy and useful. Each test is a shell script, and is launched via the 'sh' command. The script should run the test and report the result by one of: * for a test pass: exit with status 0 * where a test has been skipped (perhaps because it depends on an external program which can't be found): print "Test $0 SKIP (reason)" and exit with status 77 * for a test fail: exit with some status other than 0 or 120 The Suite is a re-worked version of the original test suite; it now is designed to work with Automake. To run these tests you can do "make check" via the top-level Makefile. This is also done automatically via "make distcheck". WARNING: The test suite installs nmh and runs the tests on that test installation. If you run tests individually, they will not remove that test installation or check to see if it remains up to date with your nmh workspace. You can run test/clean after a test to remove the test installation. "make check" will do that, so it is best to use it. If you wish to write a new test script, here are the steps: - Make sure your test script sources $MH_OBJ_DIR/test/common.sh and calls the setup_test shell function (the other scripts have examples of this). - Your path will be set up to find the locations of the test nmh binaries. - Add your script to the TESTS variable in the toplevel Makefile.am. By convention, test script names start with "test-", though that is not a requirement. - If you need additional files for your tests, be sure to add them to the EXTRA_DIST variable in Makefile.am. Note that you should insure that you access these files relative to the $srcdir environment variable. - Verify that the test works with both "make check" and "make distcheck". Please use only Bourne shell and bare-bones POSIX program constructs in the test scripts. In particular: - Use `` instead of $(). - Wrap shell variables with "" if they could possibly contain whitespace or special characters that would affect syntax. - Use the arith_eval() function in common.sh instead of $(()) or expr. It detects at run time if $(()) is available. - Use grep >/dev/null instead of grep -q. - Don't use egrep, grep -E, fgrep, grep -F, or other non-portable grep functionality. The built-in case statement supports alternation (|). - Don't use ! to negate conditions. Instead, use something like: || or if ; then :; else fi - Separate variable assignment from export (don't assign in export statements). - Use sed >tmpfile and mv instead of sed -i. - Avoid depending on the exact format of output from system (non-nmh) programs. - Use octal instead of hex (\x) bytes in printf(1) formats, because hex is not supported by POSIX printf. The Heirloom Bourne Shell, http://heirloom.sourceforge.net/sh.html, catches many non-portable shell constructs, such as $(), $(()), !, and assignment in export statements. checkbashisms, available at http://sourceforge.net/projects/checkbaskisms/, might help some catch problems. Though it misses all of the troublesome constructs, except for assignment in an export statement, listed above. The "Portable Shell" section of the Autoconf info manual has a wealth of tips for avoiding portability problems in shell scripts. It might be available by entering: info autoconf portable. nmh-1.7.1-RC3/test/refile/000755 007761 000024 00000000000 13243043705 015210 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/repl/000755 007761 000024 00000000000 13243043705 014704 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/runpty.c000644 007761 000024 00000010064 13243042053 015443 0ustar00kenhstaff000000 000000 /* runpty.c - Run a process under a pseudo-tty * * This code is Copyright (c) 2017, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #include #include #include #include #include #define COMMAND_TIMEOUT 30 int main(int argc, char *argv[]) { int master_in, master_out, slave, cc, status; time_t starttime, now; const char *slavename; pid_t child; unsigned char readbuf[1024]; FILE *output; if (argc < 3) { fprintf(stderr, "Usage: %s output-filename command [arguments ...]\n", argv[0]); exit(1); } if ((master_in = posix_openpt(O_RDWR | O_NOCTTY)) < 0) { fprintf(stderr, "Unable to open master pseudo-tty: %s\n", strerror(errno)); exit(1); } if ((master_out = posix_openpt(O_RDWR | O_NOCTTY)) < 0) { fprintf(stderr, "Unable to open master pseudo-tty: %s\n", strerror(errno)); exit(1); } if (grantpt(master_in) < 0) { fprintf(stderr, "Unable to grant permissions to master pty: %s\n", strerror(errno)); exit(1); } if (grantpt(master_out) < 0) { fprintf(stderr, "Unable to grant permissions to master pty: %s\n", strerror(errno)); exit(1); } if (unlockpt(master_in) < 0) { fprintf(stderr, "Unable to unlock master pty: %s\n", strerror(errno)); exit(1); } if (unlockpt(master_out) < 0) { fprintf(stderr, "Unable to unlock master pty: %s\n", strerror(errno)); exit(1); } child = fork(); /* * Start the child process if we are in the child; open the two * slave pseudo-ttys and close the masters after we are done with them. */ if (child == 0) { if (!(slavename = ptsname(master_in))) { fprintf(stderr, "Unable to determine name of slave pty: %s\n", strerror(errno)); exit(1); } if ((slave = open(slavename, O_RDWR)) < 0) { fprintf(stderr, "Unable to open slave pty \"%s\": %s\n", slavename, strerror(errno)); exit(1); } dup2(slave, STDIN_FILENO); close(slave); close(master_in); if (!(slavename = ptsname(master_out))) { fprintf(stderr, "Unable to determine name of slave pty: %s\n", strerror(errno)); exit(1); } if ((slave = open(slavename, O_RDWR | O_NOCTTY)) < 0) { fprintf(stderr, "Unable to open slave pty \"%s\": %s\n", slavename, strerror(errno)); exit(1); } dup2(slave, STDOUT_FILENO); dup2(slave, STDERR_FILENO); close(slave); close(master_out); execvp(argv[2], argv + 2); fprintf(stderr, "execvp(%s) failed: %s\n", argv[2], strerror(errno)); exit(1); } else if (child < 0) { fprintf(stderr, "fork() failed: %s\n", strerror(errno)); exit(1); } if (!(output = fopen(argv[1], "w"))) { fprintf(stderr, "Unable to open \"%s\" for output: %s\n", argv[1], strerror(errno)); exit(1); } starttime = time(NULL); for (;;) { fd_set readfds; struct timeval tv; FD_ZERO(&readfds); FD_SET(master_out, &readfds); /* * After we get our first bit of data, close the master pty * connected to standard input on our slave; that will generate * an EOF. */ tv.tv_sec = starttime + COMMAND_TIMEOUT - time(NULL); if (tv.tv_sec < 0) tv.tv_sec = 0; tv.tv_usec = 0; cc = select(master_out + 1, &readfds, NULL, NULL, &tv); if (cc < 0) { fprintf(stderr, "select() failed: %s\n", strerror(errno)); exit(1); } if (cc > 0 && FD_ISSET(master_out, &readfds)) { cc = read(master_out, readbuf, sizeof(readbuf)); if (cc <= 0) break; fwrite(readbuf, 1, cc, output); if (master_in != -1) { close(master_in); master_in = -1; } } now = time(NULL); if (now >= starttime + COMMAND_TIMEOUT) { fprintf(stderr, "Command execution timed out: %ld to %ld: %d\n", starttime, now, cc); break; } } if (master_in != -1) close(master_in); close(master_out); fclose(output); waitpid(child, &status, 0); exit(0); } nmh-1.7.1-RC3/test/scan/000755 007761 000024 00000000000 13243043705 014666 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/send/000755 007761 000024 00000000000 13243043705 014673 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/sequences/000755 007761 000024 00000000000 13243043705 015735 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/server.c000644 007761 000024 00000011372 13240376505 015424 0ustar00kenhstaff000000 000000 /* server.c - Utilities for fake servers used by the nmh test suite * * This code is Copyright (c) 2014, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #include #include #include #include #include #include #include static const char *PIDFN = NULL; static void killpidfile(void); static void handleterm(int); #ifndef EPROTOTYPE #define EPROTOTYPE 0 #endif static int try_bind(int socket, const struct sockaddr *address, socklen_t len) { int i, status; for (i = 0; i < 5; i++) { if ((status = bind(socket, address, len)) == 0) { return 0; } sleep(1); } return status; } int serve(const char *pidfn, const char *port) { struct addrinfo hints, *res; int rc, l, conn, on; FILE *pid; pid_t child; fd_set readfd; struct stat st; struct timeval tv; PIDFN = pidfn; /* * If there is a pid file already around, kill the previously running * fakesmtp process. Hopefully this will reduce the race conditions * that crop up when running the test suite. */ if (stat(pidfn, &st) == 0) { long oldpid; if (!(pid = fopen(pidfn, "r"))) { fprintf(stderr, "Cannot open %s (%s), continuing ...\n", pidfn, strerror(errno)); } else { rc = fscanf(pid, "%ld", &oldpid); fclose(pid); if (rc != 1) { fprintf(stderr, "Unable to parse pid in %s," " continuing ...\n", pidfn); } else { kill((pid_t) oldpid, SIGTERM); } } unlink(pidfn); } memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_PASSIVE; rc = getaddrinfo("127.0.0.1", port, &hints, &res); if (rc) { fprintf(stderr, "Unable to resolve localhost/%s: %s\n", port, gai_strerror(rc)); exit(1); } l = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (l == -1) { fprintf(stderr, "Unable to create listening socket: %s\n", strerror(errno)); exit(1); } on = 1; if (setsockopt(l, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { fprintf(stderr, "Unable to set SO_REUSEADDR: %s\n", strerror(errno)); exit(1); } if (try_bind(l, res->ai_addr, res->ai_addrlen) == -1) { fprintf(stderr, "Unable to bind socket: %s\n", strerror(errno)); exit(1); } freeaddrinfo(res); if (listen(l, 1) == -1) { fprintf(stderr, "Unable to listen on socket: %s\n", strerror(errno)); exit(1); } /* * Now we fork() and print out the process ID of our child * for scripts to use. Once we do that, then exit. */ child = fork(); switch (child) { case -1: fprintf(stderr, "Unable to fork child: %s\n", strerror(errno)); exit(1); break; case 0: /* * Close stdin & stdout, otherwise people can * think we're still doing stuff. For now leave stderr * open. */ fclose(stdin); fclose(stdout); break; default: /* XXX why? it's never used... */ printf("%ld\n", (long) child); exit(0); } /* * Now that our socket & files are set up, wait 30 seconds for * a connection. If there isn't one, then exit. */ if (!(pid = fopen(pidfn, "w"))) { fprintf(stderr, "Cannot open %s: %s\n", pidfn, strerror(errno)); exit(1); } fprintf(pid, "%ld\n", (long) getpid()); fclose(pid); signal(SIGTERM, handleterm); atexit(killpidfile); FD_ZERO(&readfd); FD_SET(l, &readfd); tv.tv_sec = 30; tv.tv_usec = 0; rc = select(l + 1, &readfd, NULL, NULL, &tv); if (rc < 0) { fprintf(stderr, "select() failed: %s\n", strerror(errno)); exit(1); } /* * I think if we get a timeout, we should just exit quietly. */ if (rc == 0) { exit(1); } /* * Alright, got a connection! Accept it. */ if ((conn = accept(l, NULL, NULL)) == -1) { fprintf(stderr, "Unable to accept connection: %s\n", strerror(errno)); exit(1); } close(l); return conn; } /* * Write a line (adding \r\n) to the client on the other end */ void putcrlf(int socket, char *data) { struct iovec iov[2]; iov[0].iov_base = data; iov[0].iov_len = strlen(data); iov[1].iov_base = "\r\n"; iov[1].iov_len = 2; /* ECONNRESET just means the client already closed its end */ /* MacOS X can also return EPROTOTYPE (!) here sometimes */ /* XXX is it useful to log errors here at all? */ if (writev(socket, iov, 2) < 0 && errno != ECONNRESET && errno != EPROTOTYPE) { perror ("server writev"); } } /* * Handle a SIGTERM */ static void handleterm(int signal) { (void) signal; killpidfile(); fflush(NULL); _exit(1); } /* * Get rid of our pid file */ static void killpidfile(void) { if (PIDFN != NULL) { unlink(PIDFN); } } nmh-1.7.1-RC3/test/show/000755 007761 000024 00000000000 13243043705 014722 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/slocal/000755 007761 000024 00000000000 13243043705 015217 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/valgrind.supp000644 007761 000024 00000004054 13243042053 016457 0ustar00kenhstaff000000 000000 { Invalid free in valgrind/vgpreload_memcheck-amd64-linux.so Memcheck:Free fun:free fun:__libc_freeres fun:_vgnU_freeres fun:__run_exit_handlers fun:exit } { Syscall param sendmsg(msg.msg_name) points to uninitialised byte(s) Memcheck:Param sendmsg(msg.msg_name) fun:*sendmsg* fun:readline } { Syscall param msgsnd(msgp->mtext) points to uninitialised byte(s) [under fakeroot] Memcheck:Param msgsnd(msgp->mtext) ... obj:*libfakeroot*.so } { Syscall param stat(file_name) points to uninitialised byte(s) [under fakeroot] Memcheck:Param stat(file_name) ... obj:*libfakeroot*.so } { Syscall param socketcall.connect(serv_addr.sa_data) points to uninitialised byte(s) (MacOS X) Memcheck:Param socketcall.connect(serv_addr.sa_data) fun:connect ... fun:sa_dst_lookup fun:sa_dst_compare_internal fun:_qsort fun:_gai_sort_list fun:si_addrinfo fun:getaddrinfo } { gdbm 1.13-1 writes uninitialised bytes from malloc'd area to file Memcheck:Param write(buf) fun:__write_nocancel fun:_gdbm_full_write fun:gdbm_fd_open fun:dbm_open fun:suppress_duplicates fun:localmail fun:main } { dyld libraryLocator on MacOS 10.11.6 (El Capitan) Memcheck:Cond fun:bcmp ... fun:_ZN4dyldL14libraryLocator* } { dyld libraryLocator on MacOS 10.11.6 (El Capitan) Memcheck:Value8 fun:bcmp ... fun:_ZN4dyldL14libraryLocator* } { dyld ImageLoader on MacOS 10.11.6 (El Capitan) Memcheck:Cond fun:_ZN16ImageLoaderMachO18validateFirstPagesEPK21linkedit_data_commandiPKhmxRKN11ImageLoader11LinkContextE ... fun:_ZN4dyldL14libraryLocator* } { Mach msg uninitialized bytes (MacOS X) Memcheck:Param mach_msg("rcv_name") fun:mach_msg_trap ... fun:_os_trace* } { Mach msg->desc.port uninitialized bytes (MacOS X) Memcheck:Param msg->desc.port.name fun:mach_msg_trap ... fun:_os_trace* } { Invalid read of size 16 (MacOS X) Memcheck:Addr16 fun:_platform_memchr$VARIANT$Base fun:fgets fun:mts_read_conf_file } nmh-1.7.1-RC3/test/whatnow/000755 007761 000024 00000000000 13243043705 015431 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/whom/000755 007761 000024 00000000000 13243043705 014714 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/test/whom/test-whom000755 007761 000024 00000005573 13240377167 016614 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test whom # ###################################################### # Not tested: # -check, -client, -server, -port, -user, -sasl, -saslmech, -snoop, -tls, -notls 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 check_exit '-eq 1' whom - expected=$MH_TEST_DIR/$$.expected actual=$MH_TEST_DIR/$$.actual cd $MH_TEST_DIR cat >$MH_TEST_DIR/Mail/draft <<'EOF' From: Test1 To: Some User Subject: Testing message 1 -------- This is a draft message. EOF # check -help # Only look at first 10 lines because the rest depend on # whether sasl support was configured in. cat >$expected <&1 | head -10 >$actual check $expected $actual # check -version case `whom -v` in whom\ --*) ;; * ) echo "$0: whom -v generated unexpected output" 1>&2 failed=`expr ${failed:-0} + 1`;; esac # check with no options run_test 'whom' ' -- Network Recipients -- user at example.com' # check -nocheck run_test 'whom -check -nocheck' ' -- Network Recipients -- user at example.com' # check with file specified run_test "whom $MH_TEST_DIR/Mail/draft" ' -- Network Recipients -- user at example.com' # check -draftmessage run_test "whom -draftm draft" ' -- Network Recipients -- user at example.com' # check -draftfolder with -draftmessage folder +drafts -create >/dev/null folder +inbox -fast >/dev/null cp $MH_TEST_DIR/Mail/draft $MH_TEST_DIR/Mail/drafts/1 run_test "whom -draftfolder +drafts -draftm 1" \ ' -- Network Recipients -- user at example.com' # check -draftfolder with current draftmessage folder +drafts 1 >/dev/null run_test "whom -draftfolder +drafts" \ ' -- Network Recipients -- user at example.com' # check -nodraftfolder run_test 'whom -draftfolder +nonexistent -nodraftfolder' \ ' -- Network Recipients -- user at example.com' # check -draft, though I'm not sure that it's useful. Note that it # must appear after the file argument when run standalone. run_test "whom $MH_TEST_DIR/Mail/drafts/1 -draft" \ ' -- Network Recipients -- user at example.com' # check -alias rm -f $MH_TEST_DIR/Mail/draft cat >$MH_TEST_DIR/Mail/draft <<'EOF' From: Test1 To: u Subject: Testing message 1 -------- This is a draft message. EOF cat >$MH_TEST_DIR/Mail/nmhaliases <<'EOF' u: user1@example.com EOF run_test 'whom -alias nmhaliases' ' -- Network Recipients -- user1 at example.com' # check -alias with nonexistent aliasfile run_test 'whom -alias nonexistent' \ "whom: aliasing error in nonexistent - unable to read 'nonexistent'" exit $failed nmh-1.7.1-RC3/test/whatnow/test-attach-detach000755 007761 000024 00000004764 12437351011 021035 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test that whatnow's "ls" copes with directory names # which have spaces in them (see bug #23319) # ###################################################### 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 # Set TERM to get consistent output. TERM=dumb; export TERM cd "$MH_TEST_DIR" testname="baz's boz" testname_quoted="baz\'s\ boz" touch "$testname" # whatnow's attach stuff needs a draft to work on cp "$MH_TEST_DIR/Mail/inbox/1" "$MH_TEST_DIR/Mail/draft" expectederr=$MH_TEST_DIR/$$.expectederr actualerr=$MH_TEST_DIR/$$.actualerr expected=$MH_TEST_DIR/$$.expected actual=$MH_TEST_DIR/$$.actual rm -f $expected $expectederr $actual $actualerr touch $expected $expectederr $actual $actualerr # # Sigh. Different readline versions change echoing behavior, so we need # to deal. # set +e whatnowtest=`echo cd | whatnow -prompt ''` set -e case ${whatnowtest} in cd) cat >"$expected" <"$expected" <>$actualerr >>$actual echo "alist" | \ run_prog whatnow -noedit -prompt '' 2>>$actualerr >>$actual echo "detach $testname_quoted" | \ run_prog whatnow -noedit -prompt '' 2>>$actualerr >>$actual echo "alist" | \ run_prog whatnow -noedit -prompt '' 2>>$actualerr >>$actual set -e check "$expectederr" "$actualerr" check "$expected" "$actual" if [ "$readline" = 0 ]; then cat >"$expected" <"$expected" <&1 | \ sed -e 's/; charset=us-ascii//' >"$actual" check "$expected" "$actual" test ${failed:-0} -eq 0 && rm "$testname" exit $failed nmh-1.7.1-RC3/test/whatnow/test-cd000755 007761 000024 00000003366 13205305706 016732 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test that whatnow's "cd" copes with directory names # which have spaces and quotes in them (see bug #23319) # ###################################################### 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 # Set TERM to get consistent output. TERM=dumb; export TERM SPDIR="$MH_TEST_DIR/foo's bar" rm -rf "$SPDIR" mkdir "$SPDIR" (cd "$SPDIR" && touch baz boz) expectederr=$MH_TEST_DIR/$$.expectederr actualerr=$MH_TEST_DIR/$$.actualerr expected=$MH_TEST_DIR/$$.expected actual=$MH_TEST_DIR/$$.actual # # Handle different output depending on readline version # set +e whatnowtest=`echo cd | whatnow -prompt ''` set -e case ${whatnowtest} in cd) cat > "$expected" </dev/null` || COLUMNS=8192 export COLUMNS ;; "") cat > "$expected" < $expectederr < "$actualerr" > "$actual" || true check "$expectederr" "$actualerr" check "$expected" "$actual" test ${failed:-0} -eq 0 && rm -r "$SPDIR" exit $failed nmh-1.7.1-RC3/test/whatnow/test-ls000755 007761 000024 00000003323 12437351011 016747 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test that whatnow's "ls" copes with directory names # which have spaces and quotes in them (see bug #23319) # ###################################################### 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 # Set TERM to get consistent output. TERM=dumb; export TERM SPDIR="$MH_TEST_DIR/foo's bar" rm -rf "$SPDIR" mkdir "$SPDIR" cd "$SPDIR" touch baz boz expectederr=$MH_TEST_DIR/$$.expectederr actualerr=$MH_TEST_DIR/$$.actualerr expected=$MH_TEST_DIR/$$.expected actual=$MH_TEST_DIR/$$.actual # # Handle different output depending on readline version # set +e whatnowtest=`echo cd | whatnow -prompt ''` set -e case ${whatnowtest} in cd) cat > "$expected" < "$expected" < $expectederr < "$actualerr" | \ sort > "$actual" check "$expectederr" "$actualerr" 'keep first' check "$expected" "$actual" 'keep first' # Check with SHELL unset. This won't reveal any problems if # /bin/sh sets SHELL, which bash does. unset SHELL echo 'ls' | run_prog whatnow -noedit -prompt '' 2> "$actualerr" | \ sort > "$actual" check "$expectederr" "$actualerr" check "$expected" "$actual" # On some platforms, need to be out of $SPDIR in order to remove it. cd "$MH_TEST_DIR" test ${failed:-0} -eq 0 && rm -r "$SPDIR" exit $failed nmh-1.7.1-RC3/test/slocal/test-slocal000755 007761 000024 00000014713 13240377167 017416 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test slocal # ###################################################### 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 # Use proper program, maybe not the first one on PATH. slocal="$MH_LIBEXEC_DIR"/slocal check_exit '-eq 1' $slocal - expected="$MH_TEST_DIR"/$$.expected actual="$MH_TEST_DIR"/$$.actual actual2="$MH_TEST_DIR"/$$.actual2 md="$MH_TEST_DIR"/Mail/maildelivery # check -help cat >"$expected" <&1 | sed '/^$/,$d' >"$actual" check "$expected" "$actual" # check -version case `$slocal -vers` in slocal\ --*) ;; * ) printf '%s: slocal -vers generated unexpected output\n' "$0" >&2 failed=`expr ${failed:-0} + 1`;; esac # check unknown switch run_test "$slocal -nonexistent" 'slocal: -nonexistent unknown' # check non-switch argument run_test "$slocal nonexistent" 'slocal: only switch arguments are supported' # If no mail spool, explicitly specify the mailbox. if grep 'mmdfldir:.*/dev/null' ${MHMTSCONF}.old >/dev/null; then mbox="-mailbox ${MH_TEST_DIR}/Mail/mbox" else mbox= fi #### Need to specify full path to tee on Cygwin. [ -x /usr/bin/tee ] && tee=/usr/bin/tee || tee=tee # check basic operation # Can't use rcvstore because slocal wipes out the environment. # So, it would put the message in the user's inbox, not the # test inbox. slocal also freopens stdout and stderr to # /dev/null, so we can't view them to verify simulated delivery. cat >"$md" <"$actual2" 2>&1 run_test "grep ^retrieving $actual2" 'retrieving message from stdin' # check -verbose run_prog $slocal -verbose -maildelivery "$md" $mbox \ <"$MH_TEST_DIR"/Mail/inbox/1 >"$actual2" 2>&1 run_test "grep ^delivering $actual2" "delivering to pipe \"$tee\", success." # check -noverbose run_prog $slocal -verbose -noverbose -maildelivery "$md" $mbox \ <"$MH_TEST_DIR"/Mail/inbox/1 >"$actual2" 2>&1 run_test "grep ^delivering $actual2" '' rm -f "$actual2" # check match of From cat >"$md" <"$md" <"$md" <"$md" <"$md" <"$md" <"$md" <"$md" <"$md" <"$md" <"$md" < $msgfile < $expected <>> inbox:1 Date: Fri, 29 Sep 2006 00:00:00 To: Some User From: Test1 Subject: Testing message 1 This is message number 1 >>> inbox:2 Date: Fri, 29 Sep 2006 00:00:00 To: Some User From: Test2 Subject: Testing message 2 This is message number 2 EOF show +inbox 1 2 > $actual || exit 1 check "$expected" "$actual" : show two non-mime # Test showing one MIME message shows message number. # Format is different; why? cat > $expected < $actual || exit 1 check "$expected" "$actual" : show one MIME # Test showing multiple MIME messages shows message numbers. # Currently fails. cat > $expected < From: Test1 Subject: Testing message 1 [ part - text/plain - 25B ] This is message number 1 [ Message inbox:11 ] Date: Thu, 19 May 2011 00:00:00 To: recipient@example.com From: sender@example.com MIME-Version: 1.0 Content-class: urn:content-classes:message [ part 1.1 - text/plain - 29B ] This is the text/plain part. EOF show +inbox 1 $msgnum > $actual || exit 1 check "$expected" "$actual" : show multiple mime exit $failed nmh-1.7.1-RC3/test/sequences/test-flist000755 007761 000024 00000005243 13205305706 017765 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test flist # ###################################################### 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 check_exit '-eq 1' flist - check_exit '-eq 1' flist -xyzzy check_exit '-eq 0' flist -help check_exit '-eq 0' flist -version check_exit '-eq 1' flist -sequence check_exit '-eq 1' flist -all -noall -showzero -noshowzero \ -recurse -norecurse -total - x=tendixzehn l=$x$x$x$x$x c=$l$l check_exit '-eq 1' flist `echo $c | sed 's/./& /g'` 101 - run_test 'mark 1 3 5 7 9 +inbox -sequence odd' '' run_test 'mark -s odd -list' 'odd: 1 3 5 7 9' run_test 'mark +inbox -sequence unseen all' '' run_test 'mark +inbox -sequence unseen -list' 'unseen: 1-10' folder -create +other > /dev/null for i in 2 5 7 12; do cp -p "$MH_TEST_DIR/Mail/inbox/1" "$MH_TEST_DIR/Mail/other/$i" done run_test 'mark +other -sequence unseen all' '' run_test 'mark +other -sequence unseen -list' 'unseen: 2 5 7 12' # Make sure that inbox is current folder. folder -f +inbox > /dev/null # Test flists. run_test 'flists -seq odd' 'inbox+ has 5 in sequence odd; out of 10 other has 0 in sequence odd; out of 4' run_test 'flists -seq unseen' \ 'inbox+ has 10 in sequence unseen; out of 10 other has 4 in sequence unseen; out of 4' # Test flist on individual folders, starting with the current folder. run_test 'flist -sequence unseen' \ 'inbox+ has 10 in sequence unseen; out of 10' run_test 'flist +other -sequence unseen' \ 'other+ has 4 in sequence unseen; out of 4' # Test multiple folders and sequences. run_test 'flist +inbox +other -seq unseen -seq odd' \ 'inbox has 10 in sequence unseen; out of 10 inbox has 5 in sequence odd ; out of 10 other+ has 4 in sequence unseen; out of 4 other+ has 0 in sequence odd ; out of 4' # Test Flist-Order with -noalpha. echo 'Flist-Order: o* i*' >> "$MH" run_test 'flists -seq unseen -seq odd -noalpha' \ 'other+ has 4 in sequence unseen; out of 4 other+ has 0 in sequence odd ; out of 4 inbox has 10 in sequence unseen; out of 10 inbox has 5 in sequence odd ; out of 10' # Test nonexistent folder. run_test 'flist +nonexistent -seq unseen' '' # Test nonexistent sequence. run_test 'flist +inbox -seq nonexistent' \ 'inbox+ has 0 in sequence nonexistent; out of 10' # Test -fast. folder -f +inbox > /dev/null run_test 'flist -sequence unseen -fast' 'inbox' run_test 'flist +other -sequence unseen -fast' 'other' # Test -fast and -alpha. run_test 'flists -seq unseen -fast -alpha' 'inbox other' exit $failed nmh-1.7.1-RC3/test/sequences/test-mark000755 007761 000024 00000007703 13205305706 017601 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test mark # ###################################################### 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 check_exit '-eq 1' mark - # Test sequence creation. run_test 'mark 1 3 5 7 +inbox -sequence odd' '' run_test 'mark 2 4 6 8 10 +inbox -sequence even' '' run_test 'mark +inbox -seq odd -seq even -list' \ 'odd: 1 3 5 7 even: 2 4 6 8 10' # Test add. run_test 'mark 9 -sequence odd -add -nozero' '' run_test 'mark -seq odd -list' 'odd: 1 3 5 7 9' # Test delete. run_test 'mark 9 -sequence odd -delete' '' run_test 'mark -seq odd -list' 'odd: 1 3 5 7' # Test that -nozero is default run_test 'mark 9 -sequence odd -add' '' run_test 'mark -seq odd -list' 'odd: 1 3 5 7 9' # Test -zero run_test 'mark 10 -s even -add -zero' '' run_test 'mark -s even -list' 'even: 10' # Test add prior to last message; run_test 'mark 8 -s even -add' '' run_test 'mark -s even -list' 'even: 8 10' # Test list. run_test 'mark -s odd -list' 'odd: 1 3 5 7 9' # Try to mark message that doesn't exist. run_test 'mark 12' "mark: message 12 doesn't exist" # Try to mark nonexistent folder. run_test 'mark +nonexistent' \ "mark: unable to change directory to `mhpath +`/nonexistent: \ No such file or directory" # Test message ranges # Set current message for following tests. folder +inbox 5 >/dev/null run_test 'mark -s foo -zero cur' '' run_test 'mark -s foo -list' 'foo: 5' run_test 'mark -s foo -zero 5:-3' '' run_test 'mark -s foo -list' 'foo: 3-5' run_test 'mark -s foo -zero 5:2' '' run_test 'mark -s foo -list' 'foo: 5-6' run_test 'mark -s foo -zero 5=1' '' run_test 'mark -s foo -list' 'foo: 5' run_test 'mark -s foo -zero 5=-2' '' run_test 'mark -s foo -list' 'foo: 4' run_test 'mark -s foo -zero 5=7' 'mark: no such message' run_test 'mark -s onesix -zero 1 2 3 4 5 6' run_test 'mark -s onesix -list' 'onesix: 1-6' run_test 'mark -s foo -zero onesix:2' run_test 'mark -s foo -list' 'foo: 1-2' run_test 'mark -s foo -zero onesix=3' run_test 'mark -s foo -list' 'foo: 3' run_test 'mark -s foo -zero onesix:-3' run_test 'mark -s foo -list' 'foo: 4-6' run_test 'mark -s foo -zero onesix=-3' run_test 'mark -s foo -list' 'foo: 4' run_test 'mark -s foo -zero onesix:8' run_test 'mark -s foo -list' 'foo: 1-6' run_test 'mark -s foo -zero onesix=11' 'mark: no onesix=11 message' run_test 'mark -s foo -delete all' '' run_test 'mark -s onesix -delete all' '' # Test private sequence creation. # Set current message for following tests. folder +inbox 1 >/dev/null run_test 'mark 1 -sequence privateseq -add -nopublic' '' run_test 'mark -list' 'cur: 1 odd: 1 3 5 7 9 even: 8 10 privateseq (private): 1' # Test add to private sequence. run_test 'mark 2 -sequence privateseq -add -nopublic' '' run_test 'mark -list' 'cur: 1 odd: 1 3 5 7 9 even: 8 10 privateseq (private): 1-2' # Test private sequence list. run_test 'mark -sequence privateseq -list' 'privateseq (private): 1-2' # Test private sequence list with -public, which is apparently ignored. run_test 'mark -sequence privateseq -list -public' 'privateseq (private): 1-2' # Test mark on empty folder. folder -create +other >/dev/null run_test 'mark +other -sequence unseen all' 'mark: no messages in other' # Test removal of indication of cur message. mark +inbox -sequence cur -delete all run_test 'pick -nolist cur' 'pick: no cur message' # Check large number of sequences. for i in 1 2 3 4 5; do for j in 0 1 2 3 4 5 6 7 8 9; do run_prog mark $i -seq seq$i${j}0 -seq seq$i${j}1 -seq seq$i${j}2 \ -seq seq$i${j}3 -seq seq$i${j}4 -seq seq$i${j}5 \ -seq seq$i${j}6 -seq seq$i${j}7 -seq seq$i${j}8 \ -seq seq$i${j}9 run_test "pick seq$i${j}0 seq$i${j}1 seq$i${j}2 seq$i${j}3 seq$i${j}4 \ seq$i${j}5 seq$i${j}6 seq$i${j}7 seq$i${j}8 seq$i${j}9" $i done done exit $failed nmh-1.7.1-RC3/test/sequences/test-out-of-range000755 007761 000024 00000001356 12437351011 021144 0ustar00kenhstaff000000 000000 #!/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 < $MH_TEST_DIR/Mail/inbox/.mh_sequences <> "$MH" < "${MH_TEST_DIR}/Mail/draft" < To: Somebody Else Subject: Test This is a test. EOF cat > "${testname}.expected" < RCPT TO: DATA From: Mr Nobody To: Somebody Else Subject: Test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is a test. . QUIT EOF cat > "${testname}.post-expected" < EHLO nosuchhost.example.com <= 250-ready <= 250 I'll buy that for a dollar! => MAIL FROM: <= 250 I'll buy that for a dollar! => RCPT TO: <= 250 I'll buy that for a dollar! => DATA <= 354 Go ahead => . <= 250 Thanks for the info! => QUIT <= 221 Later alligator! EOF test_post "${testname}.actual" "${testname}.expected" \ 2> ${testname}.post check "${testname}.post-expected" "${testname}.post" finish_test exit ${failed:-0} nmh-1.7.1-RC3/test/scan/test-header-parsing000755 007761 000024 00000001642 13205305706 020465 0ustar00kenhstaff000000 000000 #!/bin/sh # Test short headers and short bodies. # One-character long headers used to sometimes be missed; see commit # 41a82a7ecba04be5b27b3ffc813e2f34d2786a38. 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 mail="$MH_TEST_DIR/$$.mail" expected="$MH_TEST_DIR/$$.expected" actual="$MH_TEST_DIR/$$.actual" format="$MH_TEST_DIR/$$.format" for a in a: a:1 aa: aa:1; do for b in b: b:1 bb: bb:1; do for c in c: c:1 cc: cc:1; do printf '%s\n%s\n%s\n' $a $b $c >"$mail" sed 's/.*://' "$mail" >"$expected" sed 's/:.*/}/; s/^/%{/' "$mail" >"$format" run_prog scan -form "$format" -file "$mail" >"$actual" || exit 1 check "$expected" "$actual" rm -f "$mail" "$format" done done done exit $failed nmh-1.7.1-RC3/test/scan/test-scan000755 007761 000024 00000004761 13205305706 016525 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test a simple scan. # ###################################################### 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 check_exit '-eq 1' scan - expected="$MH_TEST_DIR/$$.expected" actual="$MH_TEST_DIR/$$.actual" # check -width start_test '-width' cat >"$expected" <> 2 09/29 Test2 Testing message 2<> 3 09/29 Test3 Testing message 3<> 4 09/29 Test4 Testing message 4<> 5 09/29 Test5 Testing message 5<> 6 09/29 Test6 Testing message 6<> 7 09/29 Test7 Testing message 7<> 8 09/29 Test8 Testing message 8<> 9 09/29 Test9 Testing message 9<> 10 09/29 Test10 Testing message 10<> EOF run_prog scan +inbox -width 80 >"$actual" || exit 1 check "$expected" "$actual" # check highlighting start_test 'highlighting' cat >"$expected" <> 2 09/29 Test2 Testing message 2<> 3 09/29 Test3 Testing message 3<> 4 09/29 Test4 Testing message 4<>  5+ 09/29 Test5 Testing message 5<> 6 09/29 Test6 Testing message 6<> 7 09/29 Test7 Testing message 7<> 8 09/29 Test8 Testing message 8<> 9 09/29 Test9 Testing message 9<>  10 09/29 Test10 Testing message 10<> EOF printf 'Unseen-Sequence: unseen\n' >> $MH mark -sequence cur 5 mark -sequence unseen 10 run_prog scan -form scan.highlighted -width 80 >"$actual" || exit 1 check "$expected" "$actual" # check null input start_test 'null input' run_test 'scan -format "" -file /dev/null' '' finish_test exit $failed nmh-1.7.1-RC3/test/scan/test-scan-multibyte000755 007761 000024 00000012276 13205305706 020541 0ustar00kenhstaff000000 000000 #!/bin/sh ############################################################ # # Test scan to see if multibyte support (UTF-8 locale) works # # Other tests will get the normal ASCII case, so all we care # about here is UTF-8 encoded headers (RFC 2047). # # Note that this file should be edited via a UTF-8 aware # editor, since UTF-8 characters are in it. # ############################################################ 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 if test "${MULTIBYTE_ENABLED}" -ne 1; then test_skip "configure did not detect multibyte support" fi require_locale en_US.UTF-8 en_US.UTF8 en_US.utf-8 en_US.utf8 # # 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. # # True Spın̈al Tap fans will note that David st Hubbins was born in Squatney, # London, England, and thus having his name language-tagged with "cy" is almost # certainly incorrect. But in his own words: "Here lies David st Hubbins, # and why not?". # # The second "* in the To line is just to exercise the parser a bit. # cat > "${MH_TEST_DIR}/Mail/inbox/11" < To: Sir Denis =?utf-8*?q?Eton=E2=80=93Hogg? Date: Friday, 2 Mar 1984 00:00:00 Subject: =?utf-8?q?Sp=C4=B1n=CC=88al_Tap_=E2=86=92_Tap_into_America!?= Things are looking great! EOF width=`${MH_OBJ_DIR}/test/getcwidth "→n̈"` if test $? -ne 0; then echo "getcwidth failed to run" exit 1 fi expected="$MH_TEST_DIR/$$.expected" actual="$MH_TEST_DIR/$$.actual" start_test 'RFC 2047 headers' if test "$width" -eq 3; then cat > "$expected" < "$expected" < $actual || exit 1 check "$expected" "$actual" # # Check decoding with an invalid multibyte sequence. We skip this test # if we don't have iconv support, since it requires converting from one # character set to another. Be sure we created the test file, though, because # it's required for the test right after it. # start_test 'invalid multibyte sequence' cat >`mhpath new` < To: Some User 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 single-byte character sets, but it (U+2019) is valid UTF-8. EOF if test "$ICONV_ENABLED" -eq 1; then cat >"$expected" <"$actual" check "$expected" "$actual" fi # # Find out the width of our Unicode apostrophe (U+2019). Some implementations # say it has a width of 2, but that seems totally bizarre to me. # width=`${MH_OBJ_DIR}/test/getcwidth U+2019` if test $? -ne 0; then echo "getcwidth failed to run" exit 1 fi # check scan width with a valid multibyte sequence start_test 'scan width with a valid multibyte sequence' if test "$width" -eq 1; then cat >"$expected" <"$expected" <"$actual" check "$expected" "$actual" if test "$ICONV_ENABLED" -eq 1; then start_test 'encoded single quote' cat >"$expected" <"${MH_TEST_DIR}/Mail/inbox/13" < Subject: =?iso-8859-1?B?kgo=?= Date: Mon, 13 Jan 2014 14:18:33 -0600 The Subject: is an encoded single quote, 0x92. cpstripped() didn't properly count it when decoding, which could be seen with: scan -format '%(decode{subject})%{body}' The scan listing was two characters too long. EOF run_prog scan -width 80 last >"$actual" check "$expected" "$actual" fi start_test 'insufficient room for multicolumn character' #### This multibyte character requires 2 columns for display, but #### only 1 is availble. cpstripped() used to get this wrong. cat >"$expected" <`mhpath new` <"$actual" check "$expected" "$actual" finish_test exit $failed nmh-1.7.1-RC3/test/repl/test-convert000755 007761 000024 00000020556 13205305705 017276 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test repl -convertarg # ###################################################### set -e if test -z "${MH_OBJ_DIR}"; then srcdir=`dirname $0`/../.. MH_OBJ_DIR=`cd $srcdir && pwd`; export MH_OBJ_DIR fi . "${srcdir}/test/post/test-post-common.sh" expected="$MH_TEST_DIR/test-convert$$.expected" actual=`mhpath +`/draft printf 'Local-Mailbox: recipient@example.com\n' >>"$MH" #### Make sure that this works with 7-bit encoding. LC_ALL=C; export LC_ALL # check -convertarg with multiple parts and additional text in draft start_test '-convertarg with multiple parts and additional text in draft' cat >"$expected" <<'EOF' From: recipient@example.com To: sender@example.com cc: Fcc: +outbox Subject: Re: test Comments: In-reply-to sender@example.com message dated "Thu, 11 Dec 2014 08:19:02 -0600." MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" > This is part 1. > This is part 2. EOF cat >`mhpath new` <<'EOF' From: sender@example.com To: recipient@example.com Subject: test Date: Thu, 11 Dec 2014 08:19:02 -0600 Content-Type: multipart/mixed; boundary="_001_" MIME-Version: 1.0 --_001_ Content-Type: text/plain This is part 1. --_001_ Content-Type: text/plain This is part 2. --_001_ Content-Type: text/enriched This should not appear in the reply because the content type isn't matched. --_001_-- EOF repl -noformat -convertarg text/plain '' -nowhatnowproc last mhbuild "$actual" check "$actual" "$expected" # check that text is quoted-printable encoded due to long text line # This tests the setting of reply_ct->c_reqencoding and # (*text_plain_ct)->c_reqencoding in expand_pseudoheader(). start_test "encode text as quoted-printable due to long text line" cat >"$expected" <<'EOF' From: recipient@example.com To: sender@example.com cc: Fcc: +outbox Subject: Re: test Comments: In-reply-to sender@example.com message dated "Thu, 11 Dec 2014 08:19:02 -0600." MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: quoted-printable sender@example.com writes: > This is a very, very, very, very, very, very, very, very, very, very, ve= ry, long line. EOF cat >`mhpath new` <<'EOF' From: sender@example.com To: recipient@example.com Subject: test Date: Thu, 11 Dec 2014 08:19:02 -0600 Content-Type: multipart/mixed; boundary="_001_" MIME-Version: 1.0 --_001_ Content-Type: text/plain This is a very, very, very, very, very, very, very, very, very, very, very, long line. --_001_-- EOF #### Just prefix the text with "> ". cp "${MH}" "${MH}.new" cat >>"${MH}.new" < \1/; s/^$/>/;' <%F EOF repl -filter mhl.replywithoutbody -convertarg text/plain '' \ -nowhatnowproc last MH="${MH}.new" mhbuild "$actual" rm "${MH}.new" check "$actual" "$expected" #### Make sure that this works with 8-bit encoding. finish_test require_locale en_US.UTF-8 en_US.UTF8 en_US.utf-8 en_US.utf8 # check -convertarg with multiple parts, 7 bit start_test '-convertarg with multiple parts, 7 bit' cat >"$expected" <<'EOF' From: recipient@example.com To: sender@example.com cc: Fcc: +outbox Subject: Re: test Comments: In-reply-to sender@example.com message dated "Thu, 11 Dec 2014 08:19:02 -0600." MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" sender@example.com writes: > This is part 1. > This is part 2. EOF cat >`mhpath new` <<'EOF' From: sender@example.com To: recipient@example.com Subject: test Date: Thu, 11 Dec 2014 08:19:02 -0600 Content-Type: multipart/mixed; boundary="_001_" MIME-Version: 1.0 --_001_ Content-Type: text/plain This is part 1. --_001_ Content-Type: text/plain; charset="UTF-8" This is part 2. --_001_-- EOF repl -filter mhl.replywithoutbody -convertarg text/plain '' -nowhatnowproc last mhbuild "$actual" check "$actual" "$expected" # check -convertarg with multiple parts, 8 bit start_test '-convertarg with multiple parts, 8 bit' cat >"$expected" <<'EOF' From: recipient@example.com To: sender@example.com cc: Fcc: +outbox Subject: Re: test Comments: In-reply-to sender@example.com message dated "Thu, 11 Dec 2014 08:19:02 -0600." MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8bit sender@example.com writes: > This is part 1. > This is §2, with a non-ASCII character. EOF cat >`mhpath new` <<'EOF' From: sender@example.com To: recipient@example.com Subject: test Date: Thu, 11 Dec 2014 08:19:02 -0600 Content-Type: multipart/mixed; boundary="_001_" MIME-Version: 1.0 --_001_ Content-Type: text/plain This is part 1. --_001_ Content-Type: text/plain; charset="UTF-8" This is §2, with a non-ASCII character. --_001_-- EOF repl -filter mhl.replywithoutbody -convertarg text/plain '' -nowhatnowproc last mhbuild "$actual" check "$actual" "$expected" # check message with text part in multipart/related start_test 'check message with text part in multipart/related' cat >"$expected" <<'EOF' From: recipient@example.com To: sender@example.com cc: Fcc: +outbox Subject: Re: test with text part in multipart/related Comments: In-reply-to sender@example.com message dated "." MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" sender@example.com writes: > This is a test. EOF cat >`mhpath new` <<'EOF' From: sender@example.com To: recipient@example.com Subject: test with text part in multipart/related Content-Type: multipart/alternative; boundary="_001_" MIME-Version: 1.0 --_001_ Content-Type: multipart/related; type="text/plain"; boundary="_002_" --_002_ Content-Type: text/plain; charset="UTF-8" This is a test. --_002_-- --_001_-- EOF repl -filter mhl.replywithoutbody -convertarg text/plain '' -nowhatnowproc last mhbuild "$actual" check "$actual" "$expected" # check reply to calendar request start_test 'check reply to calendar request' cat >"$expected" <<'EOF' From: recipient@example.com To: sender@example.com cc: Fcc: +outbox Subject: Re: test iCalendar reply Comments: In-reply-to sender@example.com message dated "." MIME-Version: 1.0 Content-Type: text/calendar; method="REPLY"; charset="UTF-8" BEGIN:VCALENDAR METHOD:REPLY PRODID:nmh mhical v0.1 VERSION:2.0 BEGIN:VTIMEZONE TZID:Eastern Standard Time BEGIN:STANDARD DTSTART:16010101T020000 TZOFFSETFROM:-0400 TZOFFSETTO:-0500 RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11 END:STANDARD BEGIN:DAYLIGHT DTSTART:16010101T020000 TZOFFSETFROM:-0500 TZOFFSETTO:-0400 RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=2SU;BYMONTH=3 END:DAYLIGHT END:VTIMEZONE BEGIN:VEVENT ORGANIZER;CN=Requester:MAILTO:requester@example.com ATTENDEE;PARTSTAT=ACCEPTED;CN=Recip:MAILTO:recipient@example.com SUMMARY;LANGUAGE=en-US:Accepted: test request DTSTART;TZID=Eastern Standard Time:20150105T090000 DTEND;TZID=Eastern Standard Time:20150105T093000 UID:0123456789 CLASS:PUBLIC PRIORITY:5 TRANSP:OPAQUE STATUS:CONFIRMED SEQUENCE:0 LOCATION;LANGUAGE=en-US: END:VEVENT END:VCALENDAR EOF cat >`mhpath new` <<'EOF' From: sender@example.com To: recipient@example.com Subject: test iCalendar reply Content-Type: text/calendar; charset="UTF-8" MIME-Version: 1.0 BEGIN:VCALENDAR METHOD:REQUEST PRODID:test-convert VERSION:2.0 BEGIN:VTIMEZONE TZID:Eastern Standard Time BEGIN:STANDARD DTSTART:16010101T020000 TZOFFSETFROM:-0400 TZOFFSETTO:-0500 RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11 END:STANDARD BEGIN:DAYLIGHT DTSTART:16010101T020000 TZOFFSETFROM:-0500 TZOFFSETTO:-0400 RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=2SU;BYMONTH=3 END:DAYLIGHT END:VTIMEZONE BEGIN:VEVENT ORGANIZER;CN=Requester:MAILTO:requester@example.com ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Requestee1 :MAILTO:requestee1@example.com ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Requestee2 :MAILTO:requestee2@example.com ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Requestee3 :MAILTO:requestee3@example.com SUMMARY;LANGUAGE=en-US:test request DTSTART;TZID=Eastern Standard Time:20150105T090000 DTEND;TZID=Eastern Standard Time:20150105T093000 UID:0123456789 CLASS:PUBLIC PRIORITY:5 DTSTAMP:20150101T171600Z TRANSP:OPAQUE STATUS:CONFIRMED SEQUENCE:0 LOCATION;LANGUAGE=en-US: BEGIN:VALARM ACTION:DISPLAY DESCRIPTION:REMINDER TRIGGER;RELATED=START:-PT15M END:VALARM END:VEVENT END:VCALENDAR EOF actual="$MH_TEST_DIR/test-convert$$.actual" repl -noformat \ -convertargs text/calendar '-reply accept -contenttype' -nowhatnowproc last SIGNATURE=Recip mhbuild - <`mhpath +`/draft | egrep -v '^DTSTAMP:' >"$actual" check "$actual" "$expected" finish_test exit $failed nmh-1.7.1-RC3/test/repl/test-if-str000755 007761 000024 00000002226 12437351011 017011 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test that an '%<(function)...' if-construct correctly # tests whether 'str' is empty if the function returns # a string, and tests 'value' if the function returns # an integer. # ###################################################### 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 # create test replgroupcomps form=$MH_TEST_DIR/$$.replgroupcomps cat > $form <\n\ X-NUMBER: %(num)%(lit)%<(num 3) yes%| no%>\n\ X-NOSTRING: %(num 3)%(lit x)%<(lit) found%| missing%>\n\ X-NONUMBER: %(num 3)%(lit x)%<(num) yes%| no%>\n\ -------- EOF expected=$MH_TEST_DIR/$$.expected actual=$MH_TEST_DIR/Mail/draft cat > $expected < This is message number 1 EOF run_prog repl -editor true -format -form $form -group -nocc me \ -nowhatnowproc 1 || exit 1 check "$expected" "$actual" test ${failed:-0} -eq 0 && rm "$form" exit $failed nmh-1.7.1-RC3/test/repl/test-multicomp000755 007761 000024 00000002720 12437351011 017615 0ustar00kenhstaff000000 000000 #!/bin/sh # # See if we handle multiple components of the same name correctly. # 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 # create test replcomps form="$MH_TEST_DIR/$$.replcomps" cat > "$form" < %(lit)%(formataddr %<{reply-to}%?{from}%>)\ %<(nonnull)%(void(width))%(putaddr To: )\n%>\ %(lit)%(formataddr{cc})\ %<(nonnull)%(void(width))%(putaddr cc: )\n%>\ %<{subject}Subject: Re: %{subject}\n%>\ -------- EOF cat > "${MH_TEST_DIR}/Mail/inbox/11" < To: Nowhere User cc: Mister User One Subject: This is a subject cc: Mister User Two Subject: that got continued on another line Date: 28 Sep 2006 03:04:05 -0400 This is a new test message EOF expected="$MH_TEST_DIR/$$.expected" actual="$MH_TEST_DIR/Mail/draft" cat > "$expected" < To: Test1 cc: Mister User One , Mister User Two Subject: Re: This is a subject that got continued on another line -------- Test1 writes: > This is a new test message EOF run_prog repl -editor true -cc cc -format -form $form -width 72 \ -nowhatnowproc 11 || exit 1 check "$expected" "$actual" test ${failed:-0} -eq 0 && rm "$form" exit $failed nmh-1.7.1-RC3/test/repl/test-repl000755 007761 000024 00000012611 13240377167 016563 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test repl # ###################################################### # This is not a comprehensive test of repl, but some day it will be :-) # Please add to it. 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 check_exit '-eq 1' repl - expected=$MH_TEST_DIR/$$.expected actual=$MH_TEST_DIR/Mail/draft # check -help start_test -help cat >$expected <&1 | sed '/^$/,$d' >"$actual" check "$expected" "$actual" # check -version start_test -version case `repl -v` in repl\ --*) ;; * ) printf '%s: repl -v generated unexpected output\n' "$0" >&2 failed=`expr ${failed:-0} + 1`;; esac # check unknown switch start_test 'unknown switch' run_test "repl -nonexistent" 'repl: -nonexistent unknown' # check with no switches start_test 'with no switches' run_test "repl" 'repl: no cur message' printf 'Local-Mailbox: mymailbox@localhost\n' >> "$MH" # check -cc me start_test '-cc me' cat >$expected < cc: mymailbox@localhost Fcc: +outbox Subject: Re: Testing message 1 In-reply-to: 1@test.nmh References: 1@test.nmh Comments: In-reply-to Test1 message dated "Fri, 29 Sep 2006 00:00:00." -------- EOF run_prog repl -cc me -editor true -nowhatnowproc 1 check $expected $actual # check -nocc me start_test '-nocc me' cat >$expected < cc: Fcc: +outbox Subject: Re: Testing message 1 In-reply-to: 1@test.nmh References: 1@test.nmh Comments: In-reply-to Test1 message dated "Fri, 29 Sep 2006 00:00:00." -------- EOF run_prog repl -cc me -nocc me -editor true -nowhatnowproc 1 check $expected $actual # check -cc me with Local- and Alternate-Mailbox addtions, Bug #36635 start_test '-cc me with Local- and Alternate-Mailbox addtions, Bug #36635' # -nocc me doesn't account for Alternate-Mailboxes. printf 'Alternate-Mailboxes: user@example.com\n' >> "$MH" cat >$expected < cc: mymailbox@localhost Fcc: +outbox Subject: Re: Testing message 1 In-reply-to: 1@test.nmh References: 1@test.nmh Comments: In-reply-to Test1 message dated "Fri, 29 Sep 2006 00:00:00." -------- EOF run_prog repl -cc me -editor true -nowhatnowproc 1 check $expected $actual # check -nocc me with Local- and Alternate-Mailbox addtions, Bug #36635 start_test '-nocc me with Local- and Alternate-Mailbox addtions, Bug #36635' # -nocc me doesn't account for Alternate-Mailboxes. cat >$expected < cc: Fcc: +outbox Subject: Re: Testing message 1 In-reply-to: 1@test.nmh References: 1@test.nmh Comments: In-reply-to Test1 message dated "Fri, 29 Sep 2006 00:00:00." -------- EOF run_prog repl -cc me -nocc me -editor true -nowhatnowproc 1 check $expected $actual # check quoting of local part of invalid address, Bug #26780 start_test 'quoting of local part of invalid address, Bug #26780' cat >`mhpath new` < To: before_auser@example.com, A. User , after_user@example.com Date: Fri, 29 Sep 2006 00:00:11 Message-Id: 11@test.nmh Subject: Testing message 11 This is message number 11 EOF cat >$expected < cc: before_auser@example.com, "A. User" , after_user@example.com Fcc: +outbox Subject: Re: Testing message 11 In-reply-to: 11@test.nmh References: 11@test.nmh Comments: In-reply-to Test11 message dated "Fri, 29 Sep 2006 00:00:11." -------- EOF run_prog repl -cc to -editor true -nowhatnowproc 11 check $expected $actual # check that Fcc: header isn't propagated start_test "Fcc: header isn't propagated" form="${MH_TEST_DIR}/$$.components" cat > $form <<'EOF' From: sender@example.com %<{from}%(void(width))%(putaddr To: )%> Fcc:%<{fcc} %{fcc}%> Subject: %<{subject}Re: %(void{subject})%(trim)%(putstr)%> -------- EOF cat > $expected < `mhpath new`< $expected < "$form" < %(lit)%(formataddr %<{reply-to}%?{from}%>)\ %<(nonnull)%(void(width))%(putaddr To: )\n%>\ %<{subject}Subject: Re: %{subject}\n%>\ -------- EOF expected="$MH_TEST_DIR/$$.expected" actual="$MH_TEST_DIR/Mail/draft" cat > "$expected" < To: Test1 Subject: Re: Testing message 1 -------- Test1 writes: > This is message number 1 EOF run_prog repl -editor true -format -form $form -nowhatnowproc 1 || exit 1 check "$expected" "$actual" test ${failed:-0} -eq 0 && rm "$form" exit $failed nmh-1.7.1-RC3/test/refile/test-refile000755 007761 000024 00000014770 13240377015 017373 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test refile # ###################################################### 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 check_exit '-eq 1' refile - expected=$MH_TEST_DIR/$$.expected actual=$MH_TEST_DIR/$$.actual cd $MH_TEST_DIR run_prog folder -create +other -fast >/dev/null run_prog folder -create +another -fast >/dev/null # check with no options and no current message run_test 'refile' 'refile: no folder specified' # check with current message run_prog folder +inbox 4 >/dev/null run_test 'refile +other' '' run_test 'folders -noheader' \ 'another has no messages. inbox+ has 9 messages (1-10); cur=4. other has 1 message (1- 1). TOTAL = 10 messages in 3 folders.' # check with specified message run_prog folder +inbox 5 >/dev/null run_test 'refile 5 +other' '' run_test 'folders -noheader' \ 'another has no messages. inbox+ has 8 messages (1-10); cur=5. other has 2 messages (1- 2). TOTAL = 10 messages in 3 folders.' # check multiple messages run_test 'refile 6 7 +other' '' run_test 'folders -noheader' \ 'another has no messages. inbox+ has 6 messages (1-10); cur=7. other has 4 messages (1- 4). TOTAL = 10 messages in 3 folders.' # check multiple folders run_test 'refile 8 +other +another' '' run_test 'folders -noheader' \ 'another has 1 message (1- 1). inbox+ has 5 messages (1-10); cur=8. other has 5 messages (1- 5). TOTAL = 11 messages in 3 folders.' # check message number greater than highest run_test 'refile 11 +other' "refile: message 11 doesn't exist" run_prog folder -f +another >/dev/null # check -src run_test 'refile 9 -src +inbox +other' '' run_test 'folders -noheader' \ 'another has 1 message (1- 1). inbox+ has 4 messages (1-10); cur=9. other has 6 messages (1- 6). TOTAL = 11 messages in 3 folders.' # check -file run_test "refile -file $MH_TEST_DIR/Mail/inbox/10 +other" '' run_test 'folders -noheader' \ 'another has 1 message (1-1). inbox+ has 3 messages (1-3). other has 7 messages (1-7). TOTAL = 11 messages in 3 folders.' # check -file -, which isn't supported run_test "refile -file - +other <$MH_TEST_DIR/Mail/inbox/9" \ 'refile: missing argument to -file' run_test 'folders -noheader' \ 'another has 1 message (1-1). inbox+ has 3 messages (1-3). other has 7 messages (1-7). TOTAL = 11 messages in 3 folders.' run_test "refile -src +other all +inbox" run_test 'folders -noheader' \ 'another has 1 message (1- 1). inbox has 10 messages (1-10); cur=9. other+ has no messages. TOTAL = 11 messages in 3 folders.' # check -draft mv $MH_TEST_DIR/Mail/another/1 $MH_TEST_DIR/Mail/draft rmdir $MH_TEST_DIR/Mail/another run_test 'refile -draft +other' '' run_test 'folders -noheader' \ 'inbox has 10 messages (1-10); cur=9. other+ has 1 message (1- 1). TOTAL = 11 messages in 2 folders.' check_for_hard_links if [ $xdir_links_supported -eq 1 ]; then # check -link run_test 'refile 7 -src +inbox +other -link' '' run_test 'folders -noheader' \ 'inbox+ has 10 messages (1-10); cur=7. other has 2 messages (1- 2). TOTAL = 12 messages in 2 folders.' # inbox/7 and other/2 are linked. Modify one and verify # that the other changes as well. echo '' >>$MH_TEST_DIR/Mail/other/2 run_test "cmp $MH_TEST_DIR/Mail/inbox/7 $MH_TEST_DIR/Mail/other/2" '' else # Hard links are not supported. Skip the -link test but emulate # what it would have done using a copy instead of a link. cp -p Mail/inbox/7 Mail/other/2 folder -f +inbox 7 >/dev/null fi # check -nolink run_test 'refile 7 +other -link -nolink' '' run_test 'folders -noheader' \ 'inbox+ has 9 messages (1-10); cur=7. other has 3 messages (1- 3). TOTAL = 12 messages in 2 folders.' # inbox/7 should no longer exist because it was moved, not linked. run_test 'scan +inbox 7' "scan: message 7 doesn't exist" # check -preserve run_test 'refile 10 +other -preserve' '' run_test 'folders -noheader' \ 'inbox+ has 8 messages (1- 9). other has 4 messages (1-10). TOTAL = 12 messages in 2 folders.' run_test 'scan +other last -format %(msg):%(decode{subject})' \ '10:Testing message 10' # check -nopreserve run_test 'refile 9 -src +inbox +other -preserve -nopreserve' '' run_test 'folders -noheader' \ 'inbox+ has 7 messages (1- 8). other has 5 messages (1-11). TOTAL = 12 messages in 2 folders.' run_test 'scan +other last -format %(msg):%(decode{subject})' \ '11:Testing message 9' sbackup="`mhparam sbackup`" # check -unlink run_test 'refile 3 -src +inbox +other -unlink' '' run_test 'folders -noheader' \ 'inbox+ has 6 messages (1- 8); cur=3. other has 6 messages (1-12). TOTAL = 12 messages in 2 folders.' if test -f "$MH_TEST_DIR/Mail/inbox/${sbackup}3"; then echo "$0: refile -unlink failed" 1>&2 failed=`expr ${failed:-0} + 1` fi # check -nounlink run_test 'refile 2 +other -unlink -nounlink' '' run_test 'folders -noheader' \ 'inbox+ has 5 messages (1- 8); cur=2. other has 7 messages (1-13). TOTAL = 12 messages in 2 folders.' if test -f "$MH_TEST_DIR/Mail/inbox/${sbackup}2"; then : else echo "$0: refile -nounlink failed" 1>&2 failed=`expr ${failed:-0} + 1` fi # test folder creation when stdin is not a tty refile first +newfolder $expected <&1 | sed '/^$/,$d' >"$actual" check "$expected" "$actual" # check -version start_test -version case `$rcvdist -v` in rcvdist\ --*) ;; * ) printf '%s: rcvdist -v generated unexpected output\n' "$0" >&2 failed=`expr ${failed:-0} + 1`;; esac # check unknown switch start_test 'unknown switch' run_test "$rcvdist -nonexistent" \ 'rcvdist: usage: rcvdist [switches] [switches for postproc] address ...' # check with no switches start_test 'no switches' run_test "$rcvdist" \ 'rcvdist: usage: rcvdist [switches] [switches for postproc] address ...' #### Use fakesmtp for this first test. # check post switch with argument start_test 'post switch with argument' cat > "${MH_TEST_DIR}/Mail/draft" < To: Somebody Else Subject: Test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: Sun, 14 Jan 2018 12:00:00 -0500 This is a test. EOF cat > "${testname}.expected" < RCPT TO: DATA From: Mr Nobody To: Somebody Else Subject: Test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: Resent-To: somebody@example.com Resent-From: Somebody Else Resent-Date: This is a test. . QUIT EOF cat > "$MH_TEST_DIR/Mail/rcvdistcomps" <<'EOF' %(lit)%(formataddr{addresses})\ %<(nonnull)%(void(width))%(putaddr Resent-To:)%> %(lit)%(formataddr{to})\ %<(nonnull)%(void(width))%(putaddr Resent-From:)\n%> EOF # Set this for the EHLO command echo "clientname: nosuchhost.example.com" >> ${MHMTSCONF} # $1: message draft file # $2: output filename for fakesmtp, i.e., the sent message test_post () { pid=`"${MH_OBJ_DIR}/test/fakesmtp" "$2" $localport` run_prog $rcvdist -form "$MH_TEST_DIR/Mail/rcvdistcomps" -server 127.0.0.1 -port $localport somebody@example.com <$1 sed -e 's/^Date:.*/Date:/' -e 's/^Resent-Date:.*/Resent-Date:/' "$2" > "$2".nodate rm -f "$2" check "$2".nodate "$3" } test_post "${MH_TEST_DIR}/Mail/draft" "${testname}.fakesmtp" "${testname}.expected" #### Use sendmail/pipe below to override default mts. mts_fakesendmail="${MHMTSCONF}-fakesendmail" sed -e 's/^mts:.*/mts: sendmail\/pipe/' "${MHMTSCONF}" > "$mts_fakesendmail" printf 'sendmail: %s/test/fakesendmail\n' "$srcdir" >>"$mts_fakesendmail" MHMTSCONF="$mts_fakesendmail" # arguments: rcvdist switches test_rcvdist () { run_prog $rcvdist "$@" # fakesendmail drops the message and any cc's into this mbox. mbox="${MH_TEST_DIR}"/Mail/fakesendmail.mbox inc -silent -file "$mbox" rm -f "$mbox" # It's hard to calculate the exact Date: header post is going to # use, so we'll just use sed to remove the actual date so we can # easily compare it against our "correct" output. sed -e 's/^Resent-Date:.*/Resent-Date:/' `mhpath last` > "$actual" check "$expected" "$actual" } # check with address start_test 'with address' cat > "$expected" < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 1@test.nmh Subject: Testing message 1 Resent-To: recipient@example.com Resent-From: Some User Resent-Date: This is message number 1 EOF test_rcvdist recipient@example.com < "$MH_TEST_DIR/Mail/inbox/1" # check -form start_test -form cat > "$expected" < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 2@test.nmh Subject: Testing message 2 Resent-To: recipient@example.com Resent-From: Some User Resent-Date: This is message number 2 EOF test_rcvdist -form "$MH_TEST_DIR/Mail/rcvdistcomps" recipient@example.com \ < "$MH_TEST_DIR/Mail/inbox/2" finish_test exit ${failed:-0} nmh-1.7.1-RC3/test/rcv/test-rcvpack000755 007761 000024 00000004606 13240377167 017107 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test rcvpack # ###################################################### 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 # Use proper program, likely not the first one on PATH. rcvpack="${MH_LIBEXEC_DIR}/rcvpack" check_exit '-eq 1' $rcvpack - expected="$MH_TEST_DIR/$$.expected" actual="$MH_TEST_DIR/$$.actual" # check -help cat >"$expected" <&1 | sed '/^$/,$d' >"$actual" check "$expected" "$actual" # check -version case `$rcvpack -v` in rcvpack\ --*) ;; * ) printf '%s: rcvpack -v generated unexpected output\n' "$0" >&2 failed=`expr ${failed:-0} + 1`;; esac # check unknown switch run_test "$rcvpack -nonexistent" 'rcvpack: -nonexistent unknown' # check with no switches run_test "$rcvpack" 'rcvpack: rcvpack [switches] file' # check mbox creation run_prog $rcvpack <${MH_TEST_DIR}/Mail/inbox/1 ${MH_TEST_DIR}/Mail/mbox inc -file ${MH_TEST_DIR}/Mail/mbox -silent check "${MH_TEST_DIR}/Mail/inbox/1" "${MH_TEST_DIR}/Mail/inbox/11" 'keep first' # check -mbox run_prog $rcvpack -mmdf -mbox ${MH_TEST_DIR}/Mail/mbox2 \ <${MH_TEST_DIR}/Mail/inbox/1 # Filter out "From " lines because their timestamps can differ by a second. grep -v '^From ' "${MH_TEST_DIR}/Mail/mbox" >"${MH_TEST_DIR}/Mail/mbox-filt" grep -v '^From ' "${MH_TEST_DIR}/Mail/mbox2" >"${MH_TEST_DIR}/Mail/mbox2-filt" check "${MH_TEST_DIR}/Mail/mbox-filt" "${MH_TEST_DIR}/Mail/mbox2-filt" # check append to existing mbox file run_prog $rcvpack <${MH_TEST_DIR}/Mail/inbox/2 ${MH_TEST_DIR}/Mail/mbox inc -file ${MH_TEST_DIR}/Mail/mbox -silent check "${MH_TEST_DIR}/Mail/inbox/2" "${MH_TEST_DIR}/Mail/inbox/12" 'keep first' # check -mmdf run_prog $rcvpack -mmdf <${MH_TEST_DIR}/Mail/inbox/3 ${MH_TEST_DIR}/Mail/mmdf inc -file ${MH_TEST_DIR}/Mail/mmdf -silent check "${MH_TEST_DIR}/Mail/inbox/3" "${MH_TEST_DIR}/Mail/inbox/12" 'keep first' # check append to existing mmdf file run_prog $rcvpack -mmdf <${MH_TEST_DIR}/Mail/inbox/4 ${MH_TEST_DIR}/Mail/mmdf inc -file ${MH_TEST_DIR}/Mail/mmdf -silent check "${MH_TEST_DIR}/Mail/inbox/4" "${MH_TEST_DIR}/Mail/inbox/13" 'keep first' exit ${failed:-0} nmh-1.7.1-RC3/test/rcv/test-rcvstore000755 007761 000024 00000015424 13243042053 017307 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test rcvstore # ###################################################### 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 # Use proper program, likely not the first one on PATH. rcvstore="${MH_LIBEXEC_DIR}/rcvstore" check_exit '-eq 1' $rcvstore - expected=$MH_TEST_DIR/$$.expected expected_err=$MH_TEST_DIR/$$.expected_err actual=$MH_TEST_DIR/$$.actual actual_err=$MH_TEST_DIR/$$.actual_err # check -help cat >$expected <&1 | sed '/^$/,$d' >"$actual" check "$expected" "$actual" # check -version case `$rcvstore -v` in rcvstore\ --*) ;; * ) printf '%s: rcvstore -v generated unexpected output\n' "$0" >&2 failed=`expr ${failed:-0} + 1`;; esac # check unknown switch run_test "$rcvstore -nonexistent" 'rcvstore: -nonexistent unknown' # check with no switches and zero-length input message cat >$expected <$actual 2>&1 check $expected $actual # check with no switches cat >$expected <$actual 2>&1 check $expected $actual 'keep first' check "${MH_TEST_DIR}/Mail/inbox/1" "${MH_TEST_DIR}/Mail/inbox/11" 'keep first' # check + of existing folder run_prog $rcvstore +inbox <${MH_TEST_DIR}/Mail/inbox/1 >$actual 2>&1 check $expected $actual 'keep first' check "${MH_TEST_DIR}/Mail/inbox/1" "${MH_TEST_DIR}/Mail/inbox/11" 'keep first' # check + of new folder run_prog $rcvstore +newfolder <${MH_TEST_DIR}/Mail/inbox/1 >$actual 2>&1 check $expected $actual 'keep first' check "${MH_TEST_DIR}/Mail/inbox/1" "${MH_TEST_DIR}/Mail/newfolder/1" \ 'keep first' rmdir "${MH_TEST_DIR}/Mail/newfolder" # check -nocreate cat >$expected_err <$actual \ 2>$actual_err set -e check $expected $actual 'keep first' check $expected_err $actual_err # check -create run_prog $rcvstore +newfolder -nocreate -create <${MH_TEST_DIR}/Mail/inbox/1 \ >$actual 2>&1 check $expected $actual 'keep first' check "${MH_TEST_DIR}/Mail/inbox/1" "${MH_TEST_DIR}/Mail/newfolder/1" \ 'keep first' rmdir "${MH_TEST_DIR}/Mail/newfolder" # check addition to unseen sequence printf 'Unseen-Sequence: unseen\n' >> $MH run_prog $rcvstore <${MH_TEST_DIR}/Mail/inbox/1 >$actual 2>&1 check $expected $actual 'keep first' run_test 'mark -sequence unseen -list' 'unseen: 11' check "${MH_TEST_DIR}/Mail/inbox/1" "${MH_TEST_DIR}/Mail/inbox/11" 'keep first' #### Need to clear the unseen sequence. touch "${MH_TEST_DIR}/Mail/inbox/11" rmm 11 # check -nounseen run_prog $rcvstore -nounseen <${MH_TEST_DIR}/Mail/inbox/1 >$actual 2>&1 check $expected $actual 'keep first' run_test 'mark -sequence unseen -list' 'unseen: ' check "${MH_TEST_DIR}/Mail/inbox/1" "${MH_TEST_DIR}/Mail/inbox/11" 'keep first' # check -unseen run_prog $rcvstore -nounseen -unseen <${MH_TEST_DIR}/Mail/inbox/1 >$actual 2>&1 check $expected $actual 'keep first' run_test 'mark -sequence unseen -list' 'unseen: 11' check "${MH_TEST_DIR}/Mail/inbox/1" "${MH_TEST_DIR}/Mail/inbox/11" 'keep first' # check -sequence run_prog $rcvstore -sequence newseq <${MH_TEST_DIR}/Mail/inbox/1 >$actual 2>&1 check $expected $actual 'keep first' run_test 'mark -sequence newseq -list' 'newseq: 11' check "${MH_TEST_DIR}/Mail/inbox/1" "${MH_TEST_DIR}/Mail/inbox/11" 'keep first' # check that default is -nozero mark -sequence newseq all run_prog $rcvstore -sequence newseq <${MH_TEST_DIR}/Mail/inbox/1 >$actual 2>&1 check $expected $actual 'keep first' run_test 'mark -sequence newseq -list' 'newseq: 1-11' check "${MH_TEST_DIR}/Mail/inbox/1" "${MH_TEST_DIR}/Mail/inbox/11" 'keep first' # check -zero mark -sequence newseq all run_prog $rcvstore -sequence newseq -zero \ <${MH_TEST_DIR}/Mail/inbox/1 >$actual 2>&1 check $expected $actual 'keep first' run_test 'mark -sequence newseq -list' 'newseq: 11' check "${MH_TEST_DIR}/Mail/inbox/1" "${MH_TEST_DIR}/Mail/inbox/11" 'keep first' # check -nozero mark -sequence newseq all run_prog $rcvstore -seq newseq -zero -nozero \ <${MH_TEST_DIR}/Mail/inbox/1 >$actual 2>&1 check $expected $actual 'keep first' run_test 'mark -sequence newseq -list' 'newseq: 1-11' check "${MH_TEST_DIR}/Mail/inbox/1" "${MH_TEST_DIR}/Mail/inbox/11" 'keep first' # check that default is -public run_prog $rcvstore -sequence pubseq <${MH_TEST_DIR}/Mail/inbox/1 >$actual 2>&1 check $expected $actual 'keep first' run_test 'mark -sequence pubseq -list' 'pubseq: 11' check "${MH_TEST_DIR}/Mail/inbox/1" "${MH_TEST_DIR}/Mail/inbox/11" 'keep first' # check -nopublic run_prog $rcvstore -sequence privseq -nopublic \ <${MH_TEST_DIR}/Mail/inbox/1 >$actual 2>&1 check $expected $actual 'keep first' run_test 'mark -sequence privseq -nopublic -list' 'privseq (private): 11' check "${MH_TEST_DIR}/Mail/inbox/1" "${MH_TEST_DIR}/Mail/inbox/11" 'keep first' # check -public run_prog $rcvstore -sequence pubseq -nopublic -public \ <${MH_TEST_DIR}/Mail/inbox/1 >$actual 2>&1 check $expected $actual 'keep first' run_test 'mark -sequence pubseq -public -list' 'pubseq: 11' check "${MH_TEST_DIR}/Mail/inbox/1" "${MH_TEST_DIR}/Mail/inbox/11" 'keep first' #### Windows FAT filesystems don't support file permissions that #### disallow read access, and chmod doesn't fail. If a test above #### has failed, report that failure. Otherwise, report that we're #### skipping the remainer of the test if chmod can't remove read #### permission. printf '\n' >${MH_TEST_DIR}/Mail/test-read-perms chmod 600 ${MH_TEST_DIR}/Mail/test-read-perms if [ "`find ${MH_TEST_DIR}/Mail/test-read-perms -perm 600`"x = ''x ]; then if [ ${failed:-0} -eq 0 ]; then echo "$Test $0 SKIP (cannot remove read permission on plain files)" exit 77 else exit $failed fi else rm -f ${MH_TEST_DIR}/Mail/test-read-perms fi # check default Msg-Protect msgprot=`mhparam msgprot` run_prog $rcvstore <${MH_TEST_DIR}/Mail/inbox/1 >$actual 2>&1 check $expected $actual 'keep first' run_test "find ${MH_TEST_DIR}/Mail/inbox/11 -perm $msgprot" \ "${MH_TEST_DIR}/Mail/inbox/11" check "${MH_TEST_DIR}/Mail/inbox/1" "${MH_TEST_DIR}/Mail/inbox/11" 'keep first' # check Msg-Protect profile entry msgprot=640 printf 'Msg-Protect: %s\n' "$msgprot" >>$MH run_prog $rcvstore <${MH_TEST_DIR}/Mail/inbox/1 >$actual 2>&1 check $expected $actual run_test "find ${MH_TEST_DIR}/Mail/inbox/11 -perm $msgprot" \ "${MH_TEST_DIR}/Mail/inbox/11" check "${MH_TEST_DIR}/Mail/inbox/1" "${MH_TEST_DIR}/Mail/inbox/11" exit ${failed:-0} nmh-1.7.1-RC3/test/rcv/test-rcvtty000755 007761 000024 00000002626 13240377167 017011 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test rcvtty # ###################################################### 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 # Use proper program, likely not the first one on PATH. rcvtty="${MH_LIBEXEC_DIR}/rcvtty" check_exit '-eq 1' $rcvtty - expected="$MH_TEST_DIR/$$.expected" actual="$MH_TEST_DIR/$$.actual" # check -help cat >"$expected" <&1 | sed '/^$/,$d' >"$actual" check "$expected" "$actual" # check -version case `$rcvtty -v` in rcvtty\ --*) ;; * ) printf '%s: rcvtty -v generated unexpected output\n' "$0" >&2 failed=`expr ${failed:-0} + 1`;; esac # check normal operation. Use -biff to avoid sending notification to # each of the user's terminals. So this command shouldn't do # anything. It will write the notification(s) if the user actually # has actually enabled biff notification, or has set the exec bit of # any of their ttys. cat >"$expected" <"$actual" 2>&1 check "$expected" "$actual" exit ${failed:-0} nmh-1.7.1-RC3/test/prompter/test-prompter000755 007761 000024 00000012105 13240377167 020375 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test prompter # ###################################################### 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 check_exit '-eq 1' prompter - expected=$MH_TEST_DIR/$$.expected expected_err=$MH_TEST_DIR/$$.expected_err actual=$MH_TEST_DIR/$$.actual actual_err=$MH_TEST_DIR/$$.actual_err # check -help cat >$expected <&1 | sed '/^$/,$d' >"$actual" check "$expected" "$actual" # check -version case `prompter -v` in prompter\ --*) ;; * ) printf '%s: prompter -v generated unexpected output\n' "$0" >&2 failed=`expr ${failed:-0} + 1`;; esac # check unknown switch run_test 'prompter -nonexistent' 'prompter: -nonexistent unknown' # check with no switches run_test 'prompter' 'prompter: usage: prompter [switches] file' # check with file cat >$expected <$MH_TEST_DIR/prompter-file </dev/null check "$expected" "$MH_TEST_DIR/prompter-file" 'keep first' # check -doteof cat >$MH_TEST_DIR/prompter-file </dev/null check "$expected" "$MH_TEST_DIR/prompter-file" 'keep first' # check -nodoteof cat >$MH_TEST_DIR/prompter-file </dev/null check "$expected" "$MH_TEST_DIR/prompter-file" 'keep first' # check -noprepend cat >$MH_TEST_DIR/prompter-file <>"$expected" printf 'recipient@example.com\ncc@example.com\n+outbox\nappendage\n' | \ run_prog prompter -noprepend $MH_TEST_DIR/prompter-file >/dev/null check "$expected" "$MH_TEST_DIR/prompter-file" # check -prepend cat >$MH_TEST_DIR/prompter-file <$expected </dev/null check "$MH_TEST_DIR/prompter-file" "$expected" 'keep first' # check -rapid cat >$expected <"$actual" $expected <"$actual" $expected <"$actual" check "$expected" "$actual" # check -body. It's undocumented but the default, so make sure that # it reverses the effect of -nobody. cat >$expected <"$actual" \ $expected </dev/null check "$expected" "$MH_TEST_DIR/prompter-file" exit ${failed:-0} nmh-1.7.1-RC3/test/post/test-messageid000755 007761 000024 00000007433 13205305705 017601 0ustar00kenhstaff000000 000000 #!/bin/sh # # Test post -messageid # 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 testname="${MH_TEST_DIR}/$$" cat > "${MH_TEST_DIR}/Mail/draft" < To: Somebody Else Subject: Test This is a test EOF cat > "${testname}.expected" < RCPT TO: DATA From: Mr Nobody To: Somebody Else Subject: Test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is a test . QUIT EOF # check invalid -messageid selection run_test "send -draft -messageid invalid" \ "post: unsupported messageid \"invalid\" send: message not delivered to anyone" #### Rely on sendmail/pipe below to override default mts. mts_fakesendmail="${MHMTSCONF}-fakesendmail" cp "${MHMTSCONF}" "$mts_fakesendmail" printf 'sendmail: %s/test/fakesendmail\n' "$srcdir" >>"$mts_fakesendmail" MHMTSCONF="$mts_fakesendmail" # $1: -messageid switch selection # arguments: expected output(s) test_messageid () { msgid_style="$1" run_prog send -draft -mts sendmail/pipe -msgid -messageid "$msgid_style" shift # fakesendmail drops the message and any cc's into this mbox. mbox="${MH_TEST_DIR}"/Mail/fakesendmail.mbox inc -silent -file "$mbox" rm -f "$mbox" n=1 for expected in "$@"; do cur=`mhpath cur` # Verify that Message-ID is of the right form. We'll see how # portable these grep regular expressions are. case $msgid_style in localname) # e.g., Message-ID: <5348.1342884222@localhost.localdomain> id='^Message-ID: <[0-9]\{1,\}\.[0-9]\{1,\}@' ;; random) # e.g., Message-ID: <5364-1342884222.165897@ldYM.FXwU.bBqK> id='^Message-ID: <[0-9]\{1,\}-[0-9]\{1,\}\.[0-9]\{6,6\}@[-_0-9A-Za-z]\{4,4\}\.[-_0-9A-Za-z]\{4,4\}\.[-_0-9A-Za-z]\{4,4\}' ;; *) printf '%s: unexpected messageid: %s\n' "$0" "$msgid_style"; exit 1 ;; esac if grep "$id" "$cur" >/dev/null; then : else mv "$cur" "${testname}.actual" printf '%s: unexpected %s Message-ID format, see %s\n' "$0" \ "$msgid_style" "${testname}.actual" exit 1 fi # # It's hard to calculate the exact Date: header post is going to # use, so we'll just use sed to remove the actual date so we can easily # compare it against our "correct" output. And same for # Message-ID. # sed -e 's/^Date:.*/Date:/' \ -e 's/^Message-ID:.*/Message-ID:/' \ "$cur" > "${testname}.actual$n" check "${testname}.actual$n" "$expected" if [ "$cur" != "`mhpath last`" ]; then folder next >/dev/null arith_eval $n + 1; n=$arith_val fi done } # check -messageid localname (the default) cat > "${MH_TEST_DIR}/Mail/draft" < To: Somebody Else Subject: Test This is a test . EOF cat > "${testname}.expected" < To: Somebody Else Subject: Test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: Message-ID: This is a test . EOF test_messageid localname "${testname}.expected" # check -messageid random cat > "${MH_TEST_DIR}/Mail/draft" < To: Somebody Else Subject: Test This is a test . EOF cat > "${testname}.expected" < To: Somebody Else Subject: Test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: Message-ID: This is a test . EOF test_messageid random "${testname}.expected" rm -f ${MHMTSCONF} exit ${failed:-0} nmh-1.7.1-RC3/test/post/test-mts000755 007761 000024 00000007454 13205305705 016446 0ustar00kenhstaff000000 000000 #!/bin/sh # # Test the sendmail/smtp and sendmail/pipe transport methods # via the -mts option. # set -e if test -z "${MH_OBJ_DIR}"; then srcdir=`dirname "$0"`/../.. MH_OBJ_DIR=`cd "$srcdir" && pwd`; export MH_OBJ_DIR fi . "${srcdir}/test/post/test-post-common.sh" cat > "${MH_TEST_DIR}/Mail/draft" < To: Somebody Else Subject: Test This is a test EOF cat > "${testname}.expected" < RCPT TO: DATA From: Mr Nobody To: Somebody Else Subject: Test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is a test . QUIT EOF # check invalid -mts selection run_test "send -draft -mts invalid" \ "post: unsupported mts selection \"invalid\" send: message not delivered to anyone" test_post "${testname}.actual" "${testname}.expected" "-mts smtp" #### Rely on sendmail/smtp or sendmail/pipe below to override default mts. mts_fakesendmail="${MHMTSCONF}-fakesendmail" cp "${MHMTSCONF}" "$mts_fakesendmail" printf 'sendmail: %s/test/fakesendmail\n' "$srcdir" >>"$mts_fakesendmail" MHMTSCONF="$mts_fakesendmail" # $1: -mts switch selection # remaining arguments: expected output(s) test_sendmail () { run_prog send -draft -mts "$1" shift # fakesendmail drops the message and any cc's into this mbox. mbox="${MH_TEST_DIR}"/Mail/fakesendmail.mbox inc -silent -file "$mbox" rm -f "$mbox" n=1 for expected in "$@"; do # # It's hard to calculate the exact Date: header post is going to # use, so we'll just use sed to remove the actual date so we can easily # compare it against our "correct" output. # sed -e 's/^Date:.*/Date:/' "`mhpath cur`" > "${testname}.actual$n" check "${testname}.actual$n" "$expected" if [ "`mhpath cur`" != "`mhpath last`" ]; then folder next >/dev/null arith_eval $n + 1; n=$arith_val fi done } # check -mts sendmail/smtp cat > "${MH_TEST_DIR}/Mail/draft" < To: Somebody Else Subject: Test This is a test . EOF cat > "${testname}.expected" < To: Somebody Else Subject: Test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is a test .. EOF test_sendmail sendmail/smtp "${testname}.expected" # check -mts sendmail/pipe # Dots are not stuffed because sendmail/pipe causes sendmail to be # invoked with -i. cat > "${MH_TEST_DIR}/Mail/draft" < To: Somebody Else Subject: Test This is a test . EOF cat > "${testname}.expected" < To: Somebody Else Subject: Test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is a test . EOF test_sendmail sendmail/pipe "${testname}.expected" # check Bcc cat > "${MH_TEST_DIR}/Mail/draft" < To: Somebody Else Bcc: Silent Partner Subject: Test This is a test . EOF cat > "${testname}.expected1" < To: Somebody Else Subject: Test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is a test . EOF cat > "${testname}.expected2" < Date: Subject: Test ------- Blind-Carbon-Copy From: Mr Nobody To: Somebody Else Subject: Test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is a test . ------- End of Blind-Carbon-Copy EOF test_sendmail sendmail/pipe "${testname}.expected1" "${testname}.expected2" rm -f ${MHMTSCONF} exit ${failed:-0} nmh-1.7.1-RC3/test/post/test-post-aliases000755 007761 000024 00000012236 13205305705 020241 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test aliases all the way through post # ###################################################### set -e if test -z "${MH_OBJ_DIR}"; then srcdir=`dirname "$0"`/../.. MH_OBJ_DIR=`cd "$srcdir" && pwd`; export MH_OBJ_DIR fi . "${srcdir}/test/post/test-post-common.sh" # Note that the last address in the blind list does not end with a # semicolon. cat >"${MH_TEST_DIR}/Mail/aliases" < EOF #### Rely on sendmail/smtp or sendmail/pipe below to override default mts. mts_fakesendmail="${MHMTSCONF}-fakesendmail" cp "${MHMTSCONF}" "$mts_fakesendmail" printf 'sendmail: %s/test/fakesendmail\n' "$srcdir" >>"$mts_fakesendmail" MHMTSCONF="$mts_fakesendmail" # $1: -mts switch selection # $2: expected output test_alias () { if [ "$1" = 'sendmail/smtp' ]; then run_prog send -draft -alias "${MH_TEST_DIR}/Mail/aliases" -mts sendmail/smtp # fakesendmail drops the message and any cc's into this mbox. mbox="${MH_TEST_DIR}"/Mail/fakesendmail.mbox inc -silent -file "$mbox" rm -f "$mbox" # It's hard to calculate the exact Date: header post is going to # use, so we'll just use sed to remove the actual date so we can easily # compare it against our "correct" output. sed -e 's/^Date:.*/Date:/' "`mhpath cur`" >"${testname}.actual" check "${testname}.actual" "$2" if [ "`mhpath cur`" != "`mhpath last`" ]; then folder next >/dev/null arith_eval $n + 1; n=$arith_val fi elif [ "$1" = 'sendmail/pipe' ]; then set +e run_prog send -draft -alias "${MH_TEST_DIR}/Mail/aliases" \ -mts sendmail/pipe >"${testname}.actual" 2>&1 if [ $? -eq 0 ]; then printf '%s: sendmail/pipe should have failed but didn'"'"'t\n' "$0" else set -e check "${testname}.actual" "$2" fi else printf '%s: invalid -mts switch selection\n' "$0" exit 1 fi } # check blind list cat >"${MH_TEST_DIR}/Mail/draft" < To: blind_list Subject: blind list test This is test of a blind list. EOF cp -p "${MH_TEST_DIR}/Mail/draft" "${MH_TEST_DIR}/Mail/draft2" cat >"${testname}.expected" < To: Blind List: ; Subject: blind list test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is test of a blind list. EOF test_alias sendmail/smtp "${testname}.expected" # Make sure the addresses were expanded correctly. mv "${MH_TEST_DIR}/Mail/draft2" "${MH_TEST_DIR}/Mail/draft" cat > "${testname}.expected" < RCPT TO: RCPT TO: RCPT TO: DATA From: Mr Nobody To: Blind List: ; Subject: blind list test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is test of a blind list. . QUIT EOF test_post "${testname}.actual" "${testname}.expected" \ "-alias ${MH_TEST_DIR}/Mail/aliases" # check named list (alias followed by ;) cat >"${MH_TEST_DIR}/Mail/draft" < To: named.list Subject: named list test This is test of a named list. EOF cat >"${testname}.expected" < To: "named.list" , "named.list" Subject: named list test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is test of a named list. EOF test_alias sendmail/smtp "${testname}.expected" # check blind list with -mts sendmail/pipe, which should fail cat >"${MH_TEST_DIR}/Mail/draft" < To: blind_list Subject: blind list test This is test of a blind list. EOF cat >"${testname}.expected" <"${MH_TEST_DIR}/Mail/draft" <"${testname}.expected" < RCPT TO: RCPT TO: RSET MAIL FROM: RCPT TO: DATA From: Mister Four To: one@example.com Subject: from bcc expansion test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is test of from line expansion for a bcc. . RSET MAIL FROM: RCPT TO: DATA From: Mister Four Date: Subject: from bcc expansion test BCC: ------- Blind-Carbon-Copy From: Mister Four To: one@example.com Subject: from bcc expansion test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is test of from line expansion for a bcc. ------- End of Blind-Carbon-Copy . QUIT EOF test_post "${testname}.actual" "${testname}.expected" \ "-alias ${MH_TEST_DIR}/Mail/aliases" exit ${failed:-0} nmh-1.7.1-RC3/test/post/test-post-basic000755 007761 000024 00000010773 13205305705 017705 0ustar00kenhstaff000000 000000 #!/bin/sh # # Test the basic behavior of post # set -e if test -z "${MH_OBJ_DIR}"; then srcdir=`dirname "$0"`/../.. MH_OBJ_DIR=`cd "$srcdir" && pwd`; export MH_OBJ_DIR fi . "${srcdir}/test/post/test-post-common.sh" check_exit '-eq 1' "$MH_LIBEXEC_DIR/post" - # # Basic test - Simple message, single user, single recipient. Note that # we test dot-stuffing here as well. # start_test 'simple message' cat > "${MH_TEST_DIR}/Mail/draft" < To: Somebody Else Subject: Test This is a test . EOF cat > "${testname}.expected" < RCPT TO: DATA From: Mr Nobody To: Somebody Else Subject: Test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is a test .. . QUIT EOF test_post "${testname}.actual" "${testname}.expected" # # Make sure a draft without a From: is rejected # start_test 'reject draft without a From:' cat > "${MH_TEST_DIR}/Mail/draft" < Subject: Blank Test This is a blank test EOF run_test "send -draft -server 127.0.0.1 -port $localport" \ "post: message has no From: header post: See default components files for examples post: re-format message and try again send: message not delivered to anyone" # # Make sure that empty Nmh-* header lines are ignored, and that post # warns about non-empty ones. # start_test 'ignore Nmh-* header lines' cat > "${MH_TEST_DIR}/Mail/draft" < To: Somebody Else Nmh-Attachment: Nmh-Unused: suppress this line Subject: Test This is a test . EOF cat > "${testname}.expected" < RCPT TO: DATA From: Mr Nobody To: Somebody Else Subject: Test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is a test .. . QUIT EOF cat > "${testname}.expected_send_output" <${testname}.send_output 2>&1 check "${testname}.send_output" "${testname}.expected_send_output" # # 8-bit without 8BITMIME support # start_test '8-bit without 8BITMIME support' cat > "${MH_TEST_DIR}/Mail/draft" < To: Somebody Else Subject: Test MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit This is a test . EOF cat > "${testname}.expected" < "${testname}.err.expected" <"${testname}.err" set +e check "${testname}.err" "${testname}.err.expected" # # 8-bit with 8BITMIME support # start_test '8-bit with 8BITMIME support' # Cheat: SMTPUTF8 enables 8BITMIME in fakestmp SMTPUTF8=1; export SMTPUTF8 cat > "${testname}.expected" < BODY=8BITMIME RCPT TO: DATA From: Mr Nobody To: Somebody Else Subject: Test MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit Date: This is a test .. . QUIT EOF test_post "${testname}.actual" "${testname}.expected" # # 8-bit with 8BITMIME support, inferred from content # start_test '8-bit, inferred, with 8BITMIME support' cat > "${MH_TEST_DIR}/Mail/draft" < To: Somebody Else Subject: Test MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" This is a test, with a non-ascii character: § . EOF cat > "${testname}.expected" < BODY=8BITMIME RCPT TO: DATA From: Mr Nobody To: Somebody Else Subject: Test MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Date: This is a test, with a non-ascii character: § .. . QUIT EOF test_post "${testname}.actual" "${testname}.expected" finish_test exit ${failed:-0} nmh-1.7.1-RC3/test/post/test-post-bcc000755 007761 000024 00000004115 12437351011 017341 0ustar00kenhstaff000000 000000 #!/bin/sh # # Test the behavior of post with multiple recipients and the use of Bcc: # set -e if test -z "${MH_OBJ_DIR}"; then srcdir=`dirname "$0"`/../.. MH_OBJ_DIR=`cd "$srcdir" && pwd`; export MH_OBJ_DIR fi . "${srcdir}/test/post/test-post-common.sh" # # Bcc test. # # It's worth pointing out here what's going on the SMTP protocol. # # If there are both sighted and unsighted addresses in the address list, # post calls verify_all_addresses() which results in ALL recipient # addresses being attempted, then the SMTP connection is reset, then # both the sighted and unsigned messages are sent (in different SMTP # transactions). Apparantly post has always done it this way. # cat > "${MH_TEST_DIR}/Mail/draft" < To: Somebody One , Somebody Two Subject: Test Bcc Bcc: Somebody Three , Somebody Four This is test of Bcc recipients. EOF cat > "${testname}.expected" < RCPT TO: RCPT TO: RCPT TO: RCPT TO: RSET MAIL FROM: RCPT TO: RCPT TO: DATA From: Mr Nobody To: Somebody One , Somebody Two Subject: Test Bcc MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is test of Bcc recipients. . RSET MAIL FROM: RCPT TO: RCPT TO: DATA From: Mr Nobody Date: Subject: Test Bcc BCC: ------- Blind-Carbon-Copy From: Mr Nobody To: Somebody One , Somebody Two Subject: Test Bcc MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is test of Bcc recipients. ------- End of Blind-Carbon-Copy . QUIT EOF test_post "${testname}.actual" "${testname}.expected" exit ${failed:-0} nmh-1.7.1-RC3/test/post/test-post-common.sh000755 007761 000024 00000001634 13205305705 020521 0ustar00kenhstaff000000 000000 #!/bin/sh # # Common routines for the post tests # set -e . "${MH_OBJ_DIR}/test/common.sh" setup_test arith_eval 64000 + $$ % 1000 localport=$arith_val testname="${MH_TEST_DIR}/$$" # # Set this for the EHLO command # echo "clientname: nosuchhost.example.com" >> ${MHMTSCONF} # # One "post" test run. Ok, yeah, we're using "send", but that's just # because it's easier. # $1: output filename for fakesmtp, i.e., the sent message # $2: expected output # $3: optional switches for send test_post () { pid=`"${MH_OBJ_DIR}/test/fakesmtp" "$1" $localport` run_prog send -draft -server 127.0.0.1 -port $localport $3 # # It's hard to calculate the exact Date: header post is going to # use, so we'll just use sed to remove the actual date so we can easily # compare it against our "correct" output. # sed -e 's/^Date:.*/Date:/' "$1" > "$1".nodate rm -f "$1" check "$1".nodate "$2" } nmh-1.7.1-RC3/test/post/test-post-dcc000755 007761 000024 00000002031 12437351011 017336 0ustar00kenhstaff000000 000000 #!/bin/sh # # Test the behavior of post with multiple recipients (& dcc) # set -e if test -z "${MH_OBJ_DIR}"; then srcdir=`dirname "$0"`/../.. MH_OBJ_DIR=`cd "$srcdir" && pwd`; export MH_OBJ_DIR fi . "${srcdir}/test/post/test-post-common.sh" # # Dcc test # cat > "${MH_TEST_DIR}/Mail/draft" < To: Somebody One , Somebody Two Subject: Test Dcc Dcc: Somebody Three This is test of Dcc recipients. EOF cat > "${testname}.expected" < RCPT TO: RCPT TO: RCPT TO: DATA From: Mr Nobody To: Somebody One , Somebody Two Subject: Test Dcc MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is test of Dcc recipients. . QUIT EOF test_post "${testname}.actual" "${testname}.expected" exit ${failed:-0} nmh-1.7.1-RC3/test/post/test-post-envelope000755 007761 000024 00000010624 12437351011 020431 0ustar00kenhstaff000000 000000 #!/bin/sh # # Test the setting of the envelope-from address for SMTP # # Note here we use multiple From: addresses for some tests so we pick up # some cases skipped in other tests. # set -e if test -z "${MH_OBJ_DIR}"; then srcdir=`dirname "$0"`/../.. MH_OBJ_DIR=`cd "$srcdir" && pwd`; export MH_OBJ_DIR fi . "${srcdir}/test/post/test-post-common.sh" # # Sender # cat > "${MH_TEST_DIR}/Mail/draft" <, Mr Nobody Two Sender: Mr Nobody Three To: Somebody Else Subject: Sender test This is a test of the Sender header. EOF cat > "${testname}.0.expected" < RCPT TO: DATA From: Mr Nobody One , Mr Nobody Two Sender: Mr Nobody Three To: Somebody Else Subject: Sender test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is a test of the Sender header. . QUIT EOF test_post "${testname}.0.actual" "${testname}.0.expected" # # Check to see if Envelope-From overrides Sender # cat > "${MH_TEST_DIR}/Mail/draft" <, Mr Nobody Two Sender: Mr Nobody Three Envelope-From: Mr Nobody Four To: Somebody Else Subject: Envelope-From test This is a test of the Envelope-From header. EOF cat > "${testname}.1.expected" < RCPT TO: DATA From: Mr Nobody One , Mr Nobody Two Sender: Mr Nobody Three To: Somebody Else Subject: Envelope-From test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is a test of the Envelope-From header. . QUIT EOF test_post "${testname}.1.actual" "${testname}.1.expected" # # See if Envelope-From will generate a Sender: header with multiple From: # addresses # cat > "${MH_TEST_DIR}/Mail/draft" <, Mr Nobody Two Envelope-From: Mr Nobody Four To: Somebody Else Subject: Envelope-From and Sender test This is a test of the Envelope-From and Sender headers. EOF cat > "${testname}.2.expected" < RCPT TO: DATA From: Mr Nobody One , Mr Nobody Two To: Somebody Else Subject: Envelope-From and Sender test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: Sender: nobody4@example.com This is a test of the Envelope-From and Sender headers. . QUIT EOF test_post "${testname}.2.actual" "${testname}.2.expected" # # And make sure we do NOT get a Sender with only one From: # cat > "${MH_TEST_DIR}/Mail/draft" < Envelope-From: Mr Nobody Five To: Somebody Else Subject: Solo Envelope-From test This is a solo test of the Envelope-From header. EOF cat > "${testname}.3.expected" < RCPT TO: DATA From: Mr Nobody One To: Somebody Else Subject: Solo Envelope-From test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is a solo test of the Envelope-From header. . QUIT EOF test_post "${testname}.3.actual" "${testname}.3.expected" # # Make sure blank Envelope-From does what we expect it to # cat > "${MH_TEST_DIR}/Mail/draft" < Envelope-From: To: Somebody Else Subject: Blank Envelope-From test This is a blank test of the Envelope-From header. EOF cat > "${testname}.4.expected" < RCPT TO: DATA From: Mr Nobody One To: Somebody Else Subject: Blank Envelope-From test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is a blank test of the Envelope-From header. . QUIT EOF test_post "${testname}.4.actual" "${testname}.4.expected" exit ${failed:-0} nmh-1.7.1-RC3/test/post/test-post-fcc000755 007761 000024 00000002407 12437351011 017347 0ustar00kenhstaff000000 000000 #!/bin/sh # # Test the Fcc: feature of post # set -e if test -z "${MH_OBJ_DIR}"; then srcdir=`dirname "$0"`/../.. MH_OBJ_DIR=`cd "$srcdir" && pwd`; export MH_OBJ_DIR fi . "${srcdir}/test/post/test-post-common.sh" # # Basic test - Simple message, single user, single recipient. Note that # we test dot-stuffing here as well. # cat > "${MH_TEST_DIR}/Mail/draft" < To: Somebody Else Subject: Fcc test Fcc: +inbox This is a fcc test EOF cat > "${testname}.expected" < RCPT TO: DATA From: Mr Nobody To: Somebody Else Subject: Fcc test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is a fcc test . QUIT EOF test_post "${testname}.actual" "${testname}.expected" cat > "${testname}.msg.expected" < To: Somebody Else Subject: Fcc test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is a fcc test EOF msgname=`mhpath +inbox 11` sed -e 's/^Date:.*/Date:/' "${msgname}" > "${msgname}".nodate check "${testname}.msg.expected" "${msgname}".nodate exit ${failed:-0} nmh-1.7.1-RC3/test/post/test-post-group000755 007761 000024 00000001632 12437351011 017747 0ustar00kenhstaff000000 000000 #!/bin/sh # # Test the behavior of post when using group addresses # set -e if test -z "${MH_OBJ_DIR}"; then srcdir=`dirname "$0"`/../.. MH_OBJ_DIR=`cd "$srcdir" && pwd`; export MH_OBJ_DIR fi . "${srcdir}/test/post/test-post-common.sh" # # Group test # cat > "${MH_TEST_DIR}/Mail/draft" < To: our-group: Somebody One Somebody Two ; Subject: Group test This is test of group recipients. EOF cat > "${testname}.expected" < RCPT TO: RCPT TO: DATA From: Mr Nobody To: our-group: ; Subject: Group test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is test of group recipients. . QUIT EOF test_post "${testname}.actual" "${testname}.expected" exit ${failed:-0} nmh-1.7.1-RC3/test/post/test-post-multifrom000755 007761 000024 00000002442 11732520432 020633 0ustar00kenhstaff000000 000000 #!/bin/sh # # Test the behavior of post with multiple from addresses # set -e if test -z "${MH_OBJ_DIR}"; then srcdir=`dirname "$0"`/../.. MH_OBJ_DIR=`cd "$srcdir" && pwd`; export MH_OBJ_DIR fi . "${srcdir}/test/post/test-post-common.sh" # # This SHOULD error # cat > "${MH_TEST_DIR}/Mail/draft" <, Mr Nobody Two To: Somebody Else Subject: Test multi-from This is a test of multi-from. EOF # # Since this should fail, don't run fakesmtp # run_test "send -draft -server 127.0.0.1 -port $localport" \ "post: A Sender: or Envelope-From: header is required with multiple From: addresses post: re-format message and try again send: message not delivered to anyone" # # This should also error # cat > "${MH_TEST_DIR}/Mail/draft" <, Mr Nobody Two To: Somebody Else Subject: Test multi-from Envelope-From: This is a test of multi-from with blank Envelope-From. EOF run_test "send -draft -server 127.0.0.1 -port $localport" \ "post: Envelope-From cannot be blank when there is multiple From: addresses and no Sender: header post: re-format message and try again send: message not delivered to anyone" exit ${failed:-0} nmh-1.7.1-RC3/test/post/test-post-multiple000755 007761 000024 00000001751 12437351011 020450 0ustar00kenhstaff000000 000000 #!/bin/sh # # Test the behavior of post with multiple recipients # set -e if test -z "${MH_OBJ_DIR}"; then srcdir=`dirname "$0"`/../.. MH_OBJ_DIR=`cd "$srcdir" && pwd`; export MH_OBJ_DIR fi . "${srcdir}/test/post/test-post-common.sh" # # Multiple recipients test # cat > "${MH_TEST_DIR}/Mail/draft" < To: Somebody One , Somebody Two Subject: Test multiple This is test of multiple recipients. EOF cat > "${testname}.expected" < RCPT TO: RCPT TO: DATA From: Mr Nobody To: Somebody One , Somebody Two Subject: Test multiple MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is test of multiple recipients. . QUIT EOF test_post "${testname}.actual" "${testname}.expected" exit ${failed:-0} nmh-1.7.1-RC3/test/post/test-rfc6531000755 007761 000024 00000006126 13240377015 016731 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test SMTPUTF8 (RFC 6531) support. # ###################################################### set -e if test -z "${MH_OBJ_DIR}"; then srcdir=`dirname $0`/../.. MH_OBJ_DIR=`cd $srcdir && pwd`; export MH_OBJ_DIR fi . "${srcdir}/test/post/test-post-common.sh" setup_test mhl="${MH_LIBEXEC_DIR}/mhl" SMTPUTF8=1; export SMTPUTF8 #### Make sure that html-to-text conversion is what we expect. require_locale en_US.UTF-8 en_US.UTF8 en_US.utf-8 en_US.utf8 #### Enable EAI in mhbuild, via the profile. sed "s%^\(mhbuild: .*\)%\1 -headerencoding utf-8%" "$MH" >"$MH.new" mv -f "$MH.new" "$MH" # check SMTPUTF8 basic start_test 'SMTPUTF8 basic' cat > "${testname}.expected" < BODY=8BITMIME SMTPUTF8 RCPT TO: DATA From: senderø@example.com To: recipientæ@example.com Subject: Blåbærsyltetøy MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8bit Date: Blåbærsyltetøy er veldig godt. Jeg liker blåbærsyltetøy. Jøran. Text source: Arnt Gulbrandsen and Jiankang Yao, "Email Address Internationalization", Computing Edge 1:6, June 2015, http://www.computer.org/cms/computing-edge/ce-jun15-final.pdf, p. 50. . QUIT EOF cat > "${MH_TEST_DIR}/Mail/draft" < "${testname}.expected" < BODY=8BITMIME SMTPUTF8 RCPT TO: DATA From: senderø@example.com To: recipientæ@example.com Subject: Blåbærsyltetøy MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8bit Date: This is a test. . QUIT EOF cat > "${MH_TEST_DIR}/Mail/draft" < "${testname}.expected" < "${testname}.expected.err" <"${testname}.err" set -e check "${testname}.err" "${testname}.expected.err" finish_test exit $failed nmh-1.7.1-RC3/test/post/test-sendfiles000755 007761 000024 00000014477 13240377167 017634 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test sendfiles # ###################################################### 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 localmbox=`$MH_LIBEXEC_DIR/ap -format "%(localmbox)" 0` #### Use this script itself for the test file. testfiledir="$srcdir/test/post" testfile=`basename $0` (cd "$MH_TEST_DIR" && mkdir -p tmp) #### Copy fakesendmail and the testfile because we cd to the #### test directory, because tar doesn't like absolute paths. cp "$srcdir/test/fakesendmail" "$testfiledir/$testfile" "$MH_TEST_DIR" #### Use sendmail/pipe below to override default mts. mts_fakesendmail="$MHMTSCONF-fakesendmail" sed -e 's/^mts:.*/mts: sendmail\/pipe/' "$MHMTSCONF" > "$mts_fakesendmail" printf 'sendmail: %s/fakesendmail\n' "$MH_TEST_DIR" >>"$mts_fakesendmail" MHMTSCONF="$mts_fakesendmail" # $1: uncompress command # $2: argument style: # new: -to recipient -subject subject # old: recipient subject # remaining arguments: sendfiles switches test_sendfiles () { uncompress="$1"; shift argstyle="$1"; shift if [ "$argstyle" = 'new' ]; then (cd "$MH_TEST_DIR" && run_prog sendfiles "$@" -to recipient@example.com \ -subject "sendfiles test" "$testfile" >/dev/null 2>&1) elif [ "$argstyle" = 'old' ]; then (cd "$MH_TEST_DIR" && run_prog sendfiles "$@" recipient@example.com "sendfiles test" \ "$testfile" >/dev/null 2>&1) fi # fakesendmail drops the message and any cc's into this mbox. mbox="$MH_TEST_DIR"/Mail/fakesendmail.mbox inc -silent -file "$mbox" rm -f "$mbox" mhlist -verbose last | sed -e 's/ *$//' -e 's/\(octet-stream\).*$/\1/' \ >"$actual" (cd $MH_TEST_DIR/tmp && contents=`mhstore -noauto last 2>&1 | \ sed -e 's/storing message.*as file //'` && $uncompress <"$contents" | tar xpf - && rm -f "$contents") rmm last check "$testfiledir/$testfile" "$MH_TEST_DIR/tmp/$testfile" \ 'keep first' [ -f "$expected" ] && check "$expected" "$actual" || rm -f "$actual" } # check -help cat >"$expected" < -[delay] (expressed in seconds) -version -help Can use PERSON environment variable instead of -from switch. EOF #### Skip nmh intro text. run_prog sendfiles -help 2>&1 | sed '/^$/,$d' >"$actual" check "$expected" "$actual" # check -version case `sendfiles -v` in sendfiles\ --*) ;; * ) printf '%s: sendfiles -v generated unexpected output\n' "$0" >&2 failed=`expr ${failed:-0} + 1`;; esac # check unknown switch run_test 'sendfiles -nonexistent' "Usage: sendfiles [switches] -to recipient \ -subject subject file1 [file2 ...] or sendfiles [switches] recipient subject file1 [file2 ...] switches are: -compress [bzip2 | compress | gzip | lzma | none] -from -[delay] (expressed in seconds) -version -help Can use PERSON environment variable instead of -from switch." # check unknown compression method run_test 'sendfiles -compress unknown to subject file' \ 'sendfiles: unknown compression method "unknown"'" Usage: sendfiles [switches] -to recipient \ -subject subject file1 [file2 ...] or sendfiles [switches] recipient subject file1 [file2 ...] switches are: -compress [bzip2 | compress | gzip | lzma | none] -from -[delay] (expressed in seconds) -version -help Can use PERSON environment variable instead of -from switch." # Check basic operation, using specified compression method. # Don't check the mhlist output, by not creating an $expected file, # because it will vary with compression method and compressed file # size. [ "`findprog bzip2`" ] && test_sendfiles 'bzip2 -cd' new -compress bzip2 [ "`findprog compress`" ] && test_sendfiles 'uncompress -c' new \ -compress compress [ "`findprog gzip`" ] && test_sendfiles 'gzip -cd' new -compress gzip [ "`findprog gzip`" ] && test_sendfiles 'gzip -cd' new -gzip [ "`findprog lzma`" ] && test_sendfiles 'lzma -cd' new -compress lzma # check with no compression cat >"$expected" <"$expected" <"$expected" <"$expected" <' # check PERSON environment variable cat >"$expected" <"$expected" <"$expected" </' \ -e 's/^\(Date:.*\)2006\( 00:00:\)00/\12008\200\ Delivery-Date: \12009\241/' \ $MH_TEST_DIR/Mail/inbox/10 >$MH_TEST_DIR/Mail/inbox/11 # Test message specification. run_test 'pick first last' '1 11' # Test -and. run_test 'pick -subject message.3 -and -from Test3' '3' run_test 'pick -subject message.3 -and -from Test4' \ 'pick: no messages match specification 0' # Test -or. run_test 'pick -subject message.3 -or -from Test3' '3' run_test 'pick -subject message.3 -or -from Test4' '3 4' # Test -not. run_test 'pick -not -subject message.8 last:5' '7 9 10 11' # Test -reverse. run_test 'pick -reverse -not -subject message.8 last:5' '11 10 9 7' # Test -lbrace, -rbrace. run_test 'pick -subject message.12 -and -subject message.3 -or -from Test4' '4' run_test 'pick -subject message.12 -and -lbrace -subject message.3 -rbrace' \ 'pick: no messages match specification 0' # -and takes precedence over -or. run_test 'pick -subject message.12 -or -subject message.3 -and -from Test3' '3' run_test 'pick -subject message.12 -or -subject message.3 -and -from Test4' \ 'pick: no messages match specification 0' # -not takes precedence over -and. run_test 'pick -not -subject message.12 -and -subject message.3' '3' run_test 'pick -not -lbrace -subject NoMatch -and -subject message.3 -rbrace' \ '1 2 3 4 5 6 7 8 9 10 11' # Test -debug. run_prog pick -debug -not -lbrace -subject NoMatch -and -subject message.3 \ -rbrace >/dev/null 2>"$actual" cat >"$expected" <"$actual" 2>/dev/null` \ >/dev/null cat >"$expected" </dev/tty) 2>/dev/null; then # Produce no standard output if no messages match and standard # output is a tty. To test that even when run with stdout # detached, write directly to /dev/tty. Can't capture the # output so hopefully the user will notice it. run_prog pick -subject message.3 -and -from Test4 >/dev/tty 2>/dev/null fi # Also, check that the exit status is 1. run_prog pick -subject message.3 -and -from Test4 >/dev/null 2>&1 run_test "echo $?" '1' set -e # Test -cc. run_test 'pick -cc another' '11' # Test -date. run_test 'pick -date 29.Sep.2008' '11' # Test -from. run_test 'pick -from test7' '7' # Test -search. run_test 'pick -search This.is.message.number.[456]' '4 5 6' # Test -subject. run_test 'pick -subject message.2' '2' # Test -to. run_test 'pick -to some -nolist' '11 hits' run_test 'pick -to user@example.com -nolist' '11 hits' # Test -after. run_prog pick -after '28 Sep 2008 00:00:00' >"$actual" 2>&1 cat >"$expected" <"$actual" 2>/dev/null set -e cat >"$expected" <"$actual" 2>&1 cat >"$expected" <"$actual" 2>&1 cat >"$expected" <"$actual" 2>/dev/null set -e cat >"$expected" <"$actual" 2>/dev/null set -e cat >"$expected" <"$actual" 2>&1 cat >"$expected" < /dev/null run_test 'pick -date 29.Sep.2008 -sequence privateseq -nopublic' '1 hit' run_test 'mark -list' 'cur: 1 even: 2 4 6 8 10 privateseq (private): 11' # Test add to private sequence. run_test 'pick first -sequence privateseq -nozero -nopublic' '1 hit' run_test 'mark -list' 'cur: 1 even: 2 4 6 8 10 privateseq (private): 1 11' # Test sequence creation, with -list. run_test 'pick 5 7 -sequence odd -list' '5 7' run_test 'mark -s odd -list' 'odd: 5 7' # Test sequence creation, with default of -zero. run_test 'pick 1 3 -sequence odd' '2 hits' run_test 'mark -s odd -list' 'odd: 1 3' # Test sequence creation, with -nozero. run_test 'pick 5 7 9 -sequence odd -nozero' '3 hits' run_test 'mark -s odd -list' 'odd: 1 3 5 7 9' # Test sequence creation, with explicit folder, -public, and -zero. run_test 'pick +inbox 5 7 9 11 -public -sequence odd' '4 hits' run_test 'mark -s odd -list' 'odd: 5 7 9 11' # Test -nolist. run_test 'pick all -nolist' '11 hits' # Test unfolding of multi-line header fields: it should only # remove embedded newlines. cat >"$MH_TEST_DIR/Mail/inbox/12" < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 12@test.nmh Subject: multi-line header field This is message number 12 EOF echo 12 >"$expected" run_prog pick -subject 'multi-line header field' 12 >"$actual" 2>&1 check "$expected" "$actual" # Test MIME-encoded header. cat >"$MH_TEST_DIR/Mail/inbox/13" < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 13@test.nmh Subject: =?us-ascii?q?=66=6f=6f?= =?utf-8?q?=62=61=72?= This is message number 13, with MIME-encoded Subject "foobar". EOF echo 13 >"$expected" set +e require_locale en_US.UTF-8 en_US.UTF8 en_US.utf-8 en_US.utf8 # Don't use run_prog here because it loses the environment setting. pick -subject foobar 13 >"$actual" 2>&1 set -e check "$expected" "$actual" # Test -nosequence. run_test 'pick +inbox 5 7 9 11 -sequence test -nosequence' '5 7 9 11' run_test 'mark -list -sequence test' 'test: ' exit $failed nmh-1.7.1-RC3/test/pick/test-stderr000755 007761 000024 00000001453 13205305705 017100 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test that errors are not written to stdout. # ###################################################### 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_err=$MH_TEST_DIR/$$.expected_err expected_out=$MH_TEST_DIR/$$.expected_out actual_err=$MH_TEST_DIR/$$.actual_err actual_out=$MH_TEST_DIR/$$.actual_out # Error message should go to stderr. cat > $expected_err < $expected_out run_prog pick -a > $actual_out 2> $actual_err || true check "$expected_err" "$actual_err" check "$expected_out" "$actual_out" nmh-1.7.1-RC3/test/oauth/common.sh000644 007761 000024 00000011360 13205305705 016706 0ustar00kenhstaff000000 000000 # Common routines for OAuth tests . "${MH_OBJ_DIR}/test/common.sh" setup_test if [ "${OAUTH_SUPPORT}" -eq 0 ]; then test_skip 'no oauth support' fi testname="${MH_TEST_DIR}/$$" arith_eval 64001 + $$ % 1000 http_port=${arith_val} arith_eval ${http_port} + 1 pop_port=${arith_val} arith_eval ${pop_port} + 1 smtp_port=${arith_val} cat >> ${MH} < "${pop_message}" < To: Some Other User Subject: Hello Date: Sun, 17 Dec 2006 12:13:14 -0500 Hey man EOM } setup_draft() { cat > "${MH_TEST_DIR}/Mail/draft" < To: Somebody Else Subject: Test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" This is a test EOF } start_fakehttp() { "${MH_OBJ_DIR}/test/fakehttp" "${testname}.http-req" ${http_port} \ "${testname}.http-res" > /dev/null } start_pop() { "${MH_OBJ_DIR}/test/fakepop" "${pop_port}" "$1" "$2" "${pop_message}" \ > /dev/null } start_pop_xoauth() { start_pop XOAUTH \ 'dXNlcj1ub2JvZHlAZXhhbXBsZS5jb20BYXV0aD1CZWFyZXIgdGVzdC1hY2Nlc3MBAQ==' } start_fakesmtp() { "${MH_OBJ_DIR}/test/fakesmtp" "${testname}.smtp-req" ${smtp_port} \ > /dev/null } clean_fakesmtp() { rm "${testname}.smtp-req" } fake_creds() { cat > "${MHTMPDIR}/oauth-test" } fake_http_response() { echo "HTTP/1.1 $1" > "${testname}.http-res" cat >> "${testname}.http-res" } clean_fakehttp() { rm -f "${testname}.http-res" } fake_json_response() { (echo 'Content-Type: application/json'; echo; cat) | fake_http_response '200 OK' } # The format of the POST request is mostly dependent on curl, and could possibly # change with newer or older curl versions, or by configuration. curl 7.39.0 # makes POST requests like this on FreeBSD 10 and Ubuntu 14.04. If you find # this failing, you'll need to make this a smarter comparison. Note that it is # sorted, so that it doesn't depend on the JSON being in a specific order. expect_http_post() { sort > "${testname}.expected-http-req" < "${MHTMPDIR}/$$.expected-creds" } test_inc() { run_test "inc -host 127.0.0.1 -port ${pop_port} -sasl -saslmech xoauth2 -authservice test -user nobody@example.com -width 80" "$@" } test_inc_success() { test_inc 'Incorporating new mail into inbox... 11+ 12/17 No Such User Hello<>' check "${pop_message}" "`mhpath +inbox 11`" 'keep first' } test_send_no_servers() { run_test "send -draft -server 127.0.0.1 -port ${smtp_port} -sasl -saslmech xoauth2 -authservice test -user nobody@example.com" "$@" } test_send_only_fakesmtp() { start_fakesmtp test_send_no_servers "$@" } test_send() { start_fakehttp test_send_only_fakesmtp "$@" sort -o "${testname}.http-req.sorted" "${testname}.http-req" rm "${testname}.http-req" check "${testname}.http-req.sorted" "${testname}.expected-http-req" } check_http_req() { sort -o "${testname}.http-req.sorted" "${testname}.http-req" rm "${testname}.http-req" check "${testname}.http-req.sorted" "${testname}.expected-http-req" } check_creds_private() { f="${MHTMPDIR}/oauth-test" if ls -dl "$f" | grep '^-rw-------' > /dev/null 2>&1; then : else echo "$f permissions not private" failed=`expr ${failed:-0} + 1` fi } check_creds() { # It's hard to calculate the exact expiration time mhlogin is going to use, # so we'll just use sed to remove the actual time so we can easily compare # it against our "correct" output. f="${MHTMPDIR}/oauth-test" sed 's/^\(expire.*:\).*/\1/' "$f" > "$f".notime check "$f".notime "${MHTMPDIR}/$$.expected-creds" rm "$f" } nmh-1.7.1-RC3/test/oauth/test-inc000755 007761 000024 00000003572 13205305705 016544 0ustar00kenhstaff000000 000000 #!/bin/sh # # Test the XOAUTH2 support in inc # if test -z "${MH_OBJ_DIR}"; then srcdir=`dirname "$0"`/../.. MH_OBJ_DIR=`cd "${srcdir}" && pwd`; export MH_OBJ_DIR fi . "${srcdir}/test/oauth/common.sh" check_exit '-eq 1' inc - setup_pop # # success cases # # TEST start_test 'access token ready, pop server accepts message' fake_creds < "${MHTMPDIR}/$$.expected-creds" cat /dev/null > "${MHTMPDIR}/oauth-test" chmod 600 "${MHTMPDIR}/oauth-test" } test_mhlogin() { start_fakehttp run_test 'eval echo code | mhlogin -saslmech xoauth2 -authservice test -user nobody@example.com' \ "Load the following URL in your browser and authorize nmh to access test: http://127.0.0.1:${http_port}/oauth/auth?response_type=code&client_id=test-id&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&scope=test-scope Enter the authorization code: $1" check_http_req check_creds_private check_creds } test_mhlogin_invalid_response() { test_mhlogin 'mhlogin: error exchanging code for OAuth2 token mhlogin: invalid response' } # # success cases # # TEST start_test 'mhlogin receives access and expiration' expect_http_post_code fake_json_response < ${MHTMPDIR}/$$.browser" 2>&1 1>/dev/null | \ sed 's/\( endpoint:\) .*/\1/' > "${MHTMPDIR}/$$.mhlogin.err" cat > "${MHTMPDIR}/$$.mhlogin.err.expected" < "${MHTMPDIR}/$$.browser.expected" < "${testname}.expected-send-output" < "${testname}.send-output" 2>&1 || true # Clear out an error message we get from libcurl on some systems (seen at least # 3 different versions of this error message, on FreeBSD 10.1, Ubuntu 12.04, and # Ubuntu 14.04). f="${testname}.send-output" sed 's/\(post: error making HTTP request to OAuth2 authorization endpoint:\).*/\1 [details]/' "$f" > "$f".clean check "$f".clean "${testname}.expected-send-output" rm "$f" # TEST start_test 'refresh gets bogus 200 response from http server' expect_http_post_refresh fake_http_response '200 OK' <doh! EOF test_send 'post: error refreshing OAuth2 token post: invalid response send: message not delivered to anyone' # TEST start_test 'refresh gets 500 response from http server' expect_http_post_refresh fake_http_response '500 Server Error' <doh! EOF test_send 'post: error refreshing OAuth2 token post: invalid response send: message not delivered to anyone' # TEST start_test 'refresh gets proper error from http' expect_http_post_refresh fake_http_response '400 Bad Request' <> "${testname}.http-res" test_send 'post: error refreshing OAuth2 token post: refusing to process response body larger than 8192 bytes send: message not delivered to anyone' # TEST start_test 'smtp server rejects token' XOAUTH='not-that-one' fake_creds <> "$MH" < "${testname}.expected" < RCPT TO: DATA From: Mr Nobody To: Somebody Else Subject: Test MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: This is a test . QUIT EOF start_fakesmtp run_test "send -draft" sed 's/^Date:.*/Date:/' "${testname}.smtp-req" > "${testname}.smtp-req".clean check "${testname}.smtp-req".clean "${testname}.expected" clean_fakesmtp clean_fakehttp finish_test exit ${failed:-0} nmh-1.7.1-RC3/test/oauth/test-share000755 007761 000024 00000006013 13205305705 017066 0ustar00kenhstaff000000 000000 #!/bin/sh # # Test that inc, msgchck, and send share tokens. # if test -z "${MH_OBJ_DIR}"; then srcdir=`dirname "$0"`/../.. MH_OBJ_DIR=`cd "${srcdir}" && pwd`; export MH_OBJ_DIR fi . "${srcdir}/test/oauth/common.sh" setup_pop export XOAUTH XOAUTH='dXNlcj1ub2JvZHlAZXhhbXBsZS5jb20BYXV0aD1CZWFyZXIgdGVzdC1hY2Nlc3MBAQ==' # TEST start_test 'mhlogin then all run with no refresh' expect_http_post_code fake_json_response < $folders < $expected < $actual 2>&1 || true check $expected $actual # test with no desired messages start_test 'test with no desired messages' cat > $expected < $actual 2>&1 check $expected $actual 'keep first' run_prog new -folders $folders aseq > $actual 2>&1 check $expected $actual # test fnext/fprev with no desired messages start_test 'test fnext/fprev with no desired messages' cat /dev/null > $expected run_prog fnext aseq > $actual 2>&1 check $expected $actual 'keep first' run_prog fprev aseq > $actual 2>&1 check $expected $actual # add 1 desired message in each folder echo 'aseq: 1' > $MH_TEST_DIR/Mail/inbox/.mh_sequences echo 'aseq: 1' > $MH_TEST_DIR/Mail/foo1/.mh_sequences echo 'aseq: 1' > $MH_TEST_DIR/Mail/foo2/.mh_sequences # test with all folders start_test 'test with all folders' cat > $expected < $actual 2>&1 check $expected $actual # test with .folders start_test 'test with .folders' cat > $expected < $actual 2>&1 check $expected $actual # add 2 desired messages to another sequence in each folder echo 'bseq: 3-4' >> $MH_TEST_DIR/Mail/inbox/.mh_sequences echo 'bseq: 3-4' >> $MH_TEST_DIR/Mail/foo1/.mh_sequences echo 'bseq: 3-4' >> $MH_TEST_DIR/Mail/foo2/.mh_sequences # test listing aseq and bseq start_test 'test listing aseq and bseq' cat > $expected < $actual 2>&1 check $expected $actual 'keep first' # set aseq bseq as unseen echo 'Unseen-Sequence: aseq bseq' >> $MH run_prog new > $actual 2>&1 check $expected $actual # test unseen start_test 'test unseen' cat > $expected <> 3 09/29 Test3 Testing message 3<> 4 09/29 Test4 Testing message 4<> 3 aseq bseq messages in foo2 1 09/29 Test1 Testing message 1<> 3 09/29 Test3 Testing message 3<> 4 09/29 Test4 Testing message 4<> 3 aseq bseq messages in inbox (*: current folder) 1 09/29 Test1 Testing message 1<> 3 09/29 Test3 Testing message 3<> 4 09/29 Test4 Testing message 4<> EOF run_prog unseen > $actual 2>&1 check $expected $actual # test fnext with the current folder not in the list start_test 'test fnext with the current folder not in the list' echo 'Current-Folder: foo1' > $MH_TEST_DIR/Mail/context echo 'inbox 1 3-4' > $expected run_prog fnext -folders $folders > $actual 2>&1 check $expected $actual # test fprev with the current folder not in the list start_test 'test fprev with the current folder not in the list' echo 'Current-Folder: foo1' > $MH_TEST_DIR/Mail/context echo 'inbox 1 3-4' > $expected run_prog fprev -folders $folders > $actual 2>&1 check $expected $actual # test fnext with current folder in the middle of the list start_test 'test fnext with current folder in the middle of the list' echo 'Current-Folder: foo2' > $MH_TEST_DIR/Mail/context echo 'inbox 1 3-4' > $expected run_prog fnext > $actual 2>&1 check $expected $actual # test fprev with current folder in the middle of the list start_test 'test fprev with current folder in the middle of the list' echo 'Current-Folder: foo2' > $MH_TEST_DIR/Mail/context echo 'foo1 1 3-4' > $expected run_prog fprev > $actual 2>&1 check $expected $actual # test fprev with current folder at the beginning of the list start_test 'test fprev with current folder at the beginning of the list' echo 'Current-Folder: foo1' > $MH_TEST_DIR/Mail/context echo 'inbox 1 3-4' > $expected run_prog fprev > $actual 2>&1 check $expected $actual # test fnext with current folder at the end of the list start_test 'test fnext with current folder at the end of the list' echo 'Current-Folder: inbox' > $MH_TEST_DIR/Mail/context echo 'foo1 1 3-4' > $expected run_prog fnext > $actual 2>&1 check $expected $actual # test fnext with no current folder start_test 'test fnext with no current folder' rm $MH_TEST_DIR/Mail/context echo 'foo1 1 3-4' > $expected run_prog fnext > $actual 2>&1 check $expected $actual # test fnext with only one folder in the list start_test 'test fnext with only one folder in the list' cat > $folders < $expected run_prog fnext -folders $folders > $actual 2>&1 check $expected $actual finish_test exit $failed nmh-1.7.1-RC3/test/mkstemp/test-mkstemp000755 007761 000024 00000004425 13243042053 020005 0ustar00kenhstaff000000 000000 #!/bin/sh ################################## # # Test creation of temporary file. # ################################## 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 mkstemp="${MH_LIBEXEC_DIR}/mkstemp" check_exit '-eq 255' $mkstemp - $mkstemp -help | grep suffix >/dev/null && has_mkstemps=1 || has_mkstemps=0 cd "$MHTMPDIR" # check -help if [ $has_mkstemps -eq 1 ]; then cat >$expected <<-'EOF' Usage: mkstemp [switches] switches are: -directory -prefix -suffix -version -help EOF else cat >$expected <<-'EOF' Usage: mkstemp [switches] switches are: -directory -prefix -version -help EOF fi #### Skip nmh intro text. run_prog $mkstemp -h 2>&1 | sed '/^$/,$d' >"$actual" check "$expected" "$actual" # check -version # Verified same behavior as compiled mhmail. case `$mkstemp -v` in mkstemp\ --*) ;; * ) printf '%s: mkstemp -v generated unexpected output\n' "$0" >&2 failed=`expr ${failed:-0} + 1`;; esac # check with no switches tmpfile=`$mkstemp` if [ -f "$tmpfile" ]; then rm "$tmpfile" else failed=1 fi # check -directory tmpfile=`$mkstemp -directory "$MHTMPDIR"` [ -f "$tmpfile" ] && rm "$tmpfile" || failed=`expr ${failed:-0} + 1` # Rely on exit status of grep to detect failure and terminate due to set -e: check_tmpfile=`echo $tmpfile | grep "^$MHTMPDIR/......$" >/dev/null` run_test 'eval echo $check_tmpfile' '' # check -prefix tmpfile=`$mkstemp -prefix mkstemptest` [ -f "$tmpfile" ] && rm "$tmpfile" || failed=`expr ${failed:-0} + 1` # Rely on exit status of grep to detect failure and terminate due to set -e: check_tmpfile=`echo $tmpfile | grep '^mkstemptest......$' >/dev/null` run_test 'eval echo $check_tmpfile' '' if [ $has_mkstemps -eq 1 ]; then # check -suffix tmpfile=`$mkstemp -suffix .txt` [ -f "$tmpfile" ] && rm "$tmpfile" || failed=`expr ${failed:-0} + 1` # Rely on exit status of grep to detect failure and terminate due to set -e: check_tmpfile=`echo $tmpfile | grep '^......\.txt$' >/dev/null` run_test 'eval echo $check_tmpfile' '' fi exit $failed nmh-1.7.1-RC3/test/mhstore/test-mhstore000755 007761 000024 00000027466 13243042053 020021 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test mhstore # ###################################################### 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 check_exit '-eq 1' mhstore - expected="$MH_TEST_DIR/test-mhstore$$.expected" expected2="$MH_TEST_DIR/test-mhstore$$.expected2" expected_err="$MH_TEST_DIR/test-mhmail$$.expected_err" actual="$MH_TEST_DIR/test-mhstore$$.actual" actual_err="$MH_TEST_DIR/test-mhmail$$.actual_err" cd "$MH_TEST_DIR" # check with no options and no current message start_test 'with no options and no current message' run_test 'mhstore' 'mhstore: no cur message' # check with no options and current message start_test 'with no options and current message' folder +inbox 5 >/dev/null cat >"$expected" <<'EOF' This is message number 5 EOF run_test 'mhstore' 'storing message 5 as file 5.txt' check "$expected" 5.txt 'keep first' # check with folder and current message start_test 'with folder and current message' run_test 'mhstore +inbox' 'storing message 5 as file 5.txt' check "$expected" 5.txt 'keep first' # check with specified message start_test 'with specified message' run_test 'mhstore 5' 'storing message 5 as file 5.txt' check "$expected" 5.txt 'keep first' # check -file start_test '-file' run_test "mhstore -file $MH_TEST_DIR/Mail/inbox/5" \ "storing message $MH_TEST_DIR/Mail/inbox/5 as file 5.txt" check "$expected" 5.txt 'keep first' # check -file - start_test '-file -' stored_contents=`run_prog mhstore -file - < $MH_TEST_DIR/Mail/inbox/5 2>&1 | \ sed 's/.*as file //'` check "$expected" "$stored_contents" 'keep first' # check -outfile and -noverbose start_test '-outfile and -noverbose' run_prog mhstore 5 -noverbose -outfile "$actual" >"$actual_err" 2>&1 printf '' >"$expected_err" check "$expected" "$actual" 'keep first' check "$expected_err" "$actual_err" # check -outfile - start_test '-outfile -' printf '%s\n' 'storing message 5 to stdout' >>"$expected" run_prog mhstore 5 -outfile - >"$actual" 2>&1 check "$expected" "$actual" # check message number greater than highest start_test 'message number greater than highest' run_test 'mhstore 11' "mhstore: message 11 doesn't exist" # check multiple messages start_test 'multiple messages' run_test 'mhstore 4 6' 'storing message 4 as file 4.txt storing message 6 as file 6.txt' cat >"$expected" <<'EOF' This is message number 4 EOF check "$expected" 4.txt cat >"$expected" <<'EOF' This is message number 6 EOF check "$expected" 6.txt # Write message with a text/plain subpart. msgfile=`mhpath new` cat >"$msgfile" <<'EOF' To: recipient@example.com From: sender@example.com Subject: mhlist test MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" ------- =_aaaaaaaaaa0 Content-Type: multipart/related; type="multipart/alternative"; boundary="subpart__1.1" --subpart__1.1 Content-Type: text/plain; charset="iso-8859-1" Content-Disposition: attachment; filename="test1.txt" This is the first text/plain part, in a subpart. --subpart__1.1-- ------- =_aaaaaaaaaa0 Content-Type: text/plain; charset="iso-8859-1" Content-Disposition: attachment; filename="test2.txt" Content-MD5: kq+Hnc2SD/eKwAnkFBDuEA== Content-Transfer-Encoding: quoted-printable This is the second text/plain part. ------- =_aaaaaaaaaa0 Content-Type: text/plain; charset="iso-8859-1" Content-Disposition: attachment; filename="test3.txt" This is the third text/plain part. ------- =_aaaaaaaaaa0 Content-Type: text/plain; charset="iso-8859-1"; name="test4.txt" Content-Disposition: attachment; filename="test4.txt" Content-MD5: cMI1lB/LZ4jgVl3EbhdyWA== Content-Transfer-Encoding: base64 VGhpcyBpcyB0aGUgZm91cnRoIHRleHQvcGxhaW4gcGFydC4NClRoaXMgdGVzdCBoYXMgbXVsdGlw bGUgbGluZXMuDQo= ------- =_aaaaaaaaaa0-- EOF # check -part start_test '-part' cat >"$expected" <<'EOF' This is the third text/plain part. EOF run_test 'mhstore last -part 3' 'storing message 11 part 3 as file 11.3.txt' check "$expected" 11.3.txt # check -part of a subpart start_test '-part of a subpart' cat >"$expected" <<'EOF' This is the first text/plain part, in a subpart. EOF run_test 'mhstore last -part 1.1' \ 'storing message 11 part 1.1 as file 11.1.1.txt' check "$expected" 11.1.1.txt 'keep first' # check -type start_test '-type' run_test 'mhstore last -type text/plain' \ 'storing message 11 part 1.1 as file 11.1.1.txt storing message 11 part 2 as file 11.2.txt storing message 11 part 3 as file 11.3.txt storing message 11 part 4 as file 11.4.txt' check "$expected" 11.1.1.txt cat >"$expected" <<'EOF' This is the second text/plain part. EOF check "$expected" 11.2.txt cat >"$expected" <<'EOF' This is the third text/plain part. EOF check "$expected" 11.3.txt cat >"$expected" <<'EOF' This is the fourth text/plain part. This test has multiple lines. EOF check "$expected" 11.4.txt # check -auto start_test '-auto' cat >"$expected" <<'EOF' This is the fourth text/plain part. This test has multiple lines. EOF run_test 'mhstore last -part 4 -auto' \ 'storing message 11 part 4 as file test4.txt' check "$expected" test4.txt 'keep first' # check -noauto, the default start_test '-noauto, the default' run_test 'mhstore last -part 4 -auto -noauto' \ 'storing message 11 part 4 as file 11.4.txt' check "$expected" 11.4.txt 'keep first' # check -verbose, the default start_test '-verbose, the default' run_test 'mhstore last -part 4 -noverbose -verbose' \ 'storing message 11 part 4 as file 11.4.txt' check "$expected" 11.4.txt 'keep first' # check -noverbose start_test '-noverbose' run_test 'mhstore last -part 4 -noverbose' '' check "$expected" 11.4.txt # check that -auto obeys Content-Disposition header start_test 'that -auto obeys Content-Disposition header' cat >"$expected" <<'EOF' This is the first text/plain part, in a subpart. EOF run_test 'mhstore last -part 1.1 -auto' \ 'storing message 11 part 1.1 as file test1.txt' check "$expected" test1.txt # check -check start_test '-check' cat >"$expected" <<'EOF' This is the second text/plain part. EOF run_test 'mhstore last -part 2 -check' \ 'storing message 11 part 2 as file 11.2.txt' check "$expected" 11.2.txt 'keep first' # check with -check on base64 encoded part start_test 'with -check on base64 encoded part' cat >"$expected2" <<'EOF' This is the fourth text/plain part. This test has multiple lines. EOF run_test 'mhstore last -part 4 -check' \ 'storing message 11 part 4 as file 11.4.txt' check "$expected2" 11.4.txt # check -check with bad MD5 checksum start_test '-check with bad MD5 checksum' sed 's/\(Content-MD5: \)kq+Hnc/\1BADBAD/' "$msgfile" >"$MH_TEST_DIR/$$.tmp" mv -f "$MH_TEST_DIR/$$.tmp" "$msgfile" run_test 'mhstore last -part 2 -check' \ 'storing message 11 part 2 as file 11.2.txt mhstore: content integrity suspect (digest mismatch) -- continuing (content text/plain in message 11, part 2)' check "$expected" 11.2.txt 'keep first' # check -nocheck, the default start_test '-nocheck, the default' run_test 'mhstore last -part 2 -check -nocheck' \ 'storing message 11 part 2 as file 11.2.txt' check "$expected" 11.2.txt 'keep first' # check -outfile - with -file start_test '-outfile - with -file' run_prog mhstore -noverbose -file `mhpath 11` -part 2 -outfile - >"$actual" 2>&1 check "$expected" "$actual" # check reassembly of message/partial messages (RFC 1521, 7.3.2) start_test 'reassembly of message/partial messages (RFC 1521, 7.3.2)' msgfile=`mhpath new` cat >"$msgfile" <<'EOF' To: recipient@example.com From: sender@example.com Subject: mhlist test MIME-Version: 1.0 Content-Type: message/partial; id="test-mhstore message/partial test"; number=1 Content-Type: text/plain; charset="iso-8859-1" This is part one of three. EOF msgfile=`mhpath new` cat >"$msgfile" <<'EOF' To: recipient@example.com From: sender@example.com Subject: mhlist test MIME-Version: 1.0 Content-Type: message/partial; id="test-mhstore message/partial test"; number=2 This is part two of three. EOF msgfile=`mhpath new` cat >"$msgfile" <<'EOF' To: recipient@example.com From: sender@example.com Subject: mhlist test MIME-Version: 1.0 Content-Type: message/partial; id="test-mhstore message/partial test"; number=3; total=3 This is part three of three. EOF run_test 'mhstore last:3' \ 'reassembling partials 12,13,14 to folder inbox as message 15' cat >"$expected" <<'EOF' This is part one of three. This is part two of three. This is part three of three. EOF run_test 'mhstore last' 'storing message 15 as file 15.txt' check "$expected" 15.txt # cd into Mail directory because it gets cleaned up by the exit trap. cd Mail # check -clobber always start_test '-clobber always' folder +inbox 7 >/dev/null touch 7.txt cat >"$expected" <<'EOF' This is message number 7 EOF run_test 'mhstore' 'storing message 7 as file 7.txt' check "$expected" 7.txt 'keep first' run_test 'mhstore -clobber ask -clobber always' \ 'storing message 7 as file 7.txt' check "$expected" 7.txt 'keep first' # check -clobber auto start_test '-clobber auto' touch 7.txt run_test 'mhstore -clobber auto' 'storing message 7 as file 7-1.txt' check "$expected" 7-1.txt 'keep first' touch 7-1.txt run_test 'mhstore -clobber auto' 'storing message 7 as file 7-2.txt' check "$expected" 7-2.txt 'keep first' # check -clobber suffix start_test '-clobber suffix' run_test 'mhstore -clobber suffix' 'storing message 7 as file 7.txt.1' check "$expected" 7.txt.1 'keep first' touch 7.txt.1 run_test 'mhstore -clobber suffix' 'storing message 7 as file 7.txt.2' check "$expected" 7.txt.2 'keep first' # Don't check -clobber ask because it requires connection to a # terminal, and this test won't always be run with one. # check -clobber never. Its exit status is the number of files not overwritten. start_test '-clobber never. Its exit status is the number of files not overwritten.' run_test 'mhstore -clobber never' \ "mhstore: will not overwrite $MH_TEST_DIR/Mail/7.txt with -clobber never" set +e mhstore -clobber never >/dev/null 2>&1 run_test "echo $?" 1 set -e cd .. # check with short relative nmh-storage profile component start_test 'with short relative nmh-storage profile component' storagedir=s dir="$MH_TEST_DIR/Mail/inbox/$storagedir" mkdir "$dir" printf '%s\n' "nmh-storage: $storagedir" >>"$MH" cat >"$expected" <<'EOF' This is the fourth text/plain part. This test has multiple lines. EOF run_test 'mhstore 11 -part 4' \ "storing message 11 part 4 as file $storagedir/11.4.txt" check "$expected" "$dir/11.4.txt" 'keep first' rmdir "$dir" sed '$d' "$MH" >"$MH.new" mv "$MH.new" "$MH" # check with relative nmh-storage profile component start_test 'with relative nmh-storage profile component' storagedir=storagedir dir="$MH_TEST_DIR/Mail/inbox/$storagedir" mkdir "$dir" printf '%s\n' "nmh-storage: $storagedir" >>"$MH" run_test 'mhstore 11 -part 4' \ "storing message 11 part 4 as file $storagedir/11.4.txt" check "$expected" "$dir/11.4.txt" 'keep first' # check with relative nmh-storage profile component and -auto start_test 'with relative nmh-storage profile component and -auto' run_test 'mhstore 11 -part 4 -auto' \ "storing message 11 part 4 as file $storagedir/test4.txt" check "$expected" "$dir/test4.txt" 'keep first' # check with absolute nmh-storage profile component start_test 'with absolute nmh-storage profile component' absstoragedir="$MH_TEST_DIR/$storagedir" mkdir "$absstoragedir" sed "s%\(nmh-storage: \)storagedir%\1$absstoragedir%" "$MH" >"$MH.new" mv -f "$MH.new" "$MH" run_test 'mhstore 11 -part 4' \ "storing message 11 part 4 as file $storagedir/11.4.txt" check "$expected" "$absstoragedir/11.4.txt" 'keep first' # check with absolute nmh-storage profile component and -auto start_test 'with absolute nmh-storage profile component and -auto' run_test 'mhstore 11 -part 4 -auto' \ "storing message 11 part 4 as file $storagedir/test4.txt" check "$expected" "$absstoragedir/test4.txt" rmdir "$absstoragedir" finish_test exit $failed nmh-1.7.1-RC3/test/mhshow/test-binary000755 007761 000024 00000001732 13205305705 017440 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test MIME parser on binary input # ###################################################### 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 actual="$MH_TEST_DIR/test-binary$$.actual" expected="$MH_TEST_DIR/test-binary$$.expected" printf '%s\000%s' >"${expected}" \ "[ Message inbox:11 ] To: recipient@example.edu From: sender@example.edu Subject: test binary content MIME-Version: 1.0 [ part - text/plain - 23B ] Here's a null byte: " ". " printf '%s\000%s' >`mhpath new` \ "From: sender@example.edu To: recipient@example.edu Subject: test binary content MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: binary Here's a null byte: " ". " run_prog mhshow last >"${actual}" 2>&1 check "${expected}" "${actual}" finish_test exit $failed nmh-1.7.1-RC3/test/mhshow/test-charset000755 007761 000024 00000010252 13243042057 017602 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test charset conversion functionality # ###################################################### 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 check_exit '-eq 1' mhshow - require_locale en_US.UTF-8 en_US.UTF8 en_US.utf-8 en_US.utf8 iconv_elides_question_marks=0 if test "$ICONV_ENABLED" -eq 0; then text_size=10 else text_size=11 #### The GNU iconv library normalises charset names by eliding '?', along #### with some other characters. The iconv libraries used on FreeBSD/NetBSD #### and Mac OS X don't. printf x | iconv -f '?UTF-8' -t UTF-8 >/dev/null 2>&1 && iconv_elides_question_marks=1 fi expected=$MH_TEST_DIR/$$.expected actual=$MH_TEST_DIR/$$.actual echo 'mhshow-charset-windows-1252: echo "This is a test"' >> "$MH" # Write message with bogus quoted-printable data. start_test 'Write message with bogus quoted-printable data' msgfile=`mhpath new` msgnum=`basename $msgfile` cat > $msgfile < $expected < $actual 2>&1 check "$expected" "$actual" 'keep first' : bogus quoted-printable data start_test 'locale profile component' #### Used LC_ALL above, now use locale profile component instead. printf "locale: $LC_ALL\n" >> "${MH}" unset LC_ALL run_prog mhshow $msgnum > $actual 2>&1 check "$expected" "$actual" : locale profile component #### All of the remaining tests rely on iconv.a if test "$ICONV_ENABLED" -eq 0; then finish_test exit $failed fi #### RFC 2231 defines the extended value syntax: #### extended-initial-value := [charset] "'" [language] "'" #### extended-other-values #### used below, where language is blank. start_test 'Encoded parameter value' msgfile=`mhpath new` msgnum=`basename $msgfile` #### Use a charset to exercise the iconv code, if it's available, #### in get_param_value(). The Content-Type charset is UTF-8, encoded #### to exercise iconv. cat > $msgfile < $expected < $actual 2>&1 check "$expected" "$actual" : encoded parameter value #### mhshow replaces the invalid character in the charset parameter value with #### a '?'. So, a charset name of "?us-ascii" is fed to iconv. If #### $iconv_elides_question_marks, iconv will normalize that to "us-ascii". #### Otherwise, we expect iconv to fail. start_test 'replacement character in parameter value' cat > $msgfile <<'EOF' Subject: invalid parameter value charset MIME-Version: 1.0 Content-Type: text/plain; charset*=invalid''%0Dus-ascii EOF cat > $expected < $actual 2>&1 if [ $iconv_elides_question_marks -eq 1 ]; then check "$expected" "$actual" else if grep "Can't convert .*us-ascii to UTF-8" "$actual" >/dev/null; then rm -f "$expected" "$actual" else failed=1 fi fi finish_test exit $failed nmh-1.7.1-RC3/test/mhshow/test-cte-binary000755 007761 000024 00000002266 13205305705 020214 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test Content-Transfer-Encoding: binary (Debian #136976). # ###################################################### 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 # Write message with Content-Transfer-Encoding: binary text. msgfile=`mhpath new` msgnum=`basename $msgfile` cat > $msgfile < Date: Tue, 05 Mar 2002 18:20:35 +0000 This is a test; this is the body. EOF # check it cat > $expected < $actual 2>&1 check "$expected" "$actual" : C-T-E binary text exit $failed nmh-1.7.1-RC3/test/mhshow/test-msg-buffer-boundaries000755 007761 000024 00000064260 13205305705 022347 0ustar00kenhstaff000000 000000 #!/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" <"$expected" <"$actual" 2>&1 check "$expected" "$actual" : check number 1 # 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" <"$expected" <"$actual" 2>&1 check "$expected" "$actual" : check number 2 # 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" <"$expected" <"$actual" 2>&1 check "$expected" "$actual" : check number 3 exit $failed nmh-1.7.1-RC3/test/mhshow/test-qp000755 007761 000024 00000002547 13205305705 016601 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test quoted-printable decoding. # ###################################################### 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 # Write message with bogus quoted-printable data. msgfile=`mhpath new` msgnum=`basename $msgfile` cat > $msgfile < $expected < $actual 2>&1 check "$expected" "$actual" : bogus quoted-printable data exit $failed nmh-1.7.1-RC3/test/mhshow/test-subpart000755 007761 000024 00000012523 13240377167 017646 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test show of one part, fixed by # 31cba404636730df219dd009ca5893ccc56d46af # ###################################################### 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 mhn_defaults="$MH_INST_DIR${nmhetcdir}/mhn.defaults" if grep mhfixmsg-format-text/html "${mhn_defaults}" >/dev/null; then can_reformat_texthtml=1 if grep 'mhfixmsg-format-text/html.*w3m' "${mhn_defaults}" \ >/dev/null; then #### w3m uses $HOME/.w3m/, and creates it if it doesn't exist. To #### support testing with non-writeable $HOME, and to not leave #### relics from this test if it is writeable but doesn't already #### have a .w3m, and to not depend on whatever is in that if it #### does already exist, overwrite $HOME if using w3m. HOME="$MHTMPDIR"; export HOME fi else echo "$0: skipping html checks because no text browser was found" can_reformat_texthtml=0 fi # Write message with a text/plain subpart. msgfile=`mhpath new` msgnum=`basename $msgfile` cat > $msgfile < $expected < $actual 2>&1 check "$expected" "$actual" : part 1.1 # tests of -part/-type/-prefer cat > $msgfile < Subject: mhshow -part/-type/-prefer test Date: Thu, 29 Jan 2015 18:12:21 +0000 (GMT) Content-Type: multipart/mixed; boundary="BoundaryMixed" --BoundaryMixed Content-type: multipart/alternative; boundary="BoundaryAlternative1" --BoundaryAlternative1 Content-type: text/plain; charset=US-ASCII; format=flowed Content-transfer-encoding: 8bit This is the body text/plain part. --BoundaryAlternative1 Content-type: multipart/related; boundary="BoundaryAlternative2"; type="text/html" --BoundaryAlternative2 Content-type: text/html; CHARSET=US-ASCII Content-transfer-encoding: quoted-printable
This is the text/html body part.
--BoundaryAlternative2-- --BoundaryAlternative1-- --BoundaryMixed Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ This is the final text/plain signature part. --BoundaryMixed-- EOF # Write the expected output. if [ $can_reformat_texthtml -eq 1 ]; then cat > $expected <&1 | squeeze_whitespace >$actual check "$expected" "$actual" : part 1.1.1 fi # Write the expected output. cat > $expected < $actual 2>&1 check "$expected" "$actual" : part 1.2 # Write the expected output. cat > $expected < $actual 2>&1 check "$expected" "$actual" : part conflicting text/plain, part 1 switches # Write the expected output. cat > $expected < $actual 2>&1 check "$expected" "$actual" : part 2 # Write the expected output. cat > $expected < $actual 2>&1 check "$expected" "$actual" : type text/plain # Write the expected output. cat > $expected < $actual 2>&1 check "$expected" "$actual" : prefer text/plain finish_test exit $failed nmh-1.7.1-RC3/test/mhshow/test-textcharset000755 007761 000024 00000132014 13240377167 020522 0ustar00kenhstaff000000 000000 #!/bin/sh ########################################################## # # Test display of text/plain parts with charset conversion # ########################################################## 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 if test "$ICONV_ENABLED" -eq 0; then test_skip 'test-textcharset requires that nmh have been built with iconv' fi require_locale en_US.UTF-8 en_US.UTF8 en_US.utf-8 en_US.utf8 expected="$MH_TEST_DIR"/$$.expected actual="$MH_TEST_DIR"/$$.actual # check charset conversion msgfile=`mhpath new` msgnum=`basename $msgfile` cat >"$msgfile" <<'EOF' From: foo@example.edu To: bar@example.edu Subject: test display with charset conversion MIME-Version: 1.0 Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: quoted-printable Date: Sun, 18 Dec 2005 00:52:39 +0100 4 =F7 2 =3D 2 EOF cat >"$expected" <"$actual" 2>&1 check "$expected" "$actual" : check charset conversion cat >>"$MH" <<'EOF' mhshow-show-text/plain: echo %{charset} EOF # check expansion of %{charset} by itself msgfile=`mhpath new` msgnum=`basename $msgfile` cat >"$msgfile" <<'EOF' From: foo@example.edu To: bar@example.edu Subject: test display with %{charset} expansion MIME-Version: 1.0 Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: quoted-printable Date: Sun, 18 Dec 2005 00:52:39 +0100 4 =F7 2 =3D 2 EOF cat >"$expected" <"$actual" 2>&1 check "$expected" "$actual" : check %{charset} by itself # check expansion of empty %{charset} by itself msgfile=`mhpath new` omsgnum=$msgnum msgnum=`basename $msgfile` cat >"$msgfile" <<'EOF' From: foo@example.edu To: bar@example.edu Subject: test display with empty %{charset} expansion MIME-Version: 1.0 Content-Type: text/plain Content-Transfer-Encoding: quoted-printable Date: Sun, 18 Dec 2005 00:52:39 +0100 4 =F7 2 =3D 2 EOF cat >"$expected" <"$actual" 2>&1 check "$expected" "$actual" : check empty %{charset} by itself grep -v 'mhshow-show-text/plain:' "$MH" >"$MH.new" mv -f "$MH.new" "$MH" cat >>"$MH" <<'EOF' mhshow-show-text/plain: charset=%{charset}; echo ${charset:+-I $charset} EOF # check expansion of embedded %{charset} with no text following cat >"$expected" <"$actual" 2>&1 # NB: "mhshow prev" !!! check "$expected" "$actual" : check embedded %{charset} with no text # check expansion of empty embedded %{charset} with no text following cat >"$expected" <"$actual" 2>&1 check "$expected" "$actual" : check empty embedded %{charset} with no text following sed -e 's%\(mhshow-show-text/plain:.*\)%\1 file%' "$MH" >"$MH.new" mv -f "$MH.new" "$MH" # check expansion of embedded %{charset} with text following cat >"$expected" <"$actual" 2>&1 # NB: "mhshow prev" !!! check "$expected" "$actual" : check embedded %{charset} with text following # check expansion of empty embedded %{charset} with text following cat >"$expected" <"$actual" 2>&1 check "$expected" "$actual" : check empty embedded %{charset} with text following sed -e 's/charset/method/g' "$MH" >"$MH.new" mv -f "$MH.new" "$MH" # check parameter value quoting msgfile=`mhpath new` msgnum=`basename $msgfile` cat >"$msgfile" <<'EOF' From: foo@example.edu To: bar@example.edu Subject: test C-T parameter expansion quoting MIME-Version: 1.0 Content-Type: text/plain; method=$QUOTEME' Content-Transfer-Encoding: quoted-printable Date: Sun, 18 Dec 2005 00:52:39 +0100 4 =F7 2 =3D 2 EOF cat >"$expected" <>"$expected" <<'EOF' Date: Sun, 18 Dec 2005 00:52:39 +0100 To: bar@example.edu From: foo@example.edu Subject: test C-T parameter expansion quoting MIME-Version: 1.0 -I $QUOTEME' file EOF run_prog mhshow last >"$actual" 2>&1 check "$expected" "$actual" : check parameter value quoting sed -e 's/method/unknown/g' "$MH" >"$MH.new" mv -f "$MH.new" "$MH" # check that unknown parameter is not expanded msgfile=`mhpath new` msgnum=`basename $msgfile` cat >"$msgfile" <<'EOF' From: foo@example.edu To: bar@example.edu Subject: test display with unknown C-T parameter expansion MIME-Version: 1.0 Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: quoted-printable Date: Sun, 18 Dec 2005 00:52:39 +0100 4 =F7 2 =3D 2 EOF cat >"$expected" <"$actual" 2>&1 check "$expected" "$actual" : check unknown parameter is not expanded grep -v '^mhshow-show-text/plain: ' "$MH" >>"$MH.new" mv -f "$MH.new" "$MH" cat >>"$MH" <"$msgfile" <<'EOF' From: foo@example.edu To: bar@example.edu Subject: check parameter value quoting with text following MIME-Version: 1.0 Content-Type: text/plain Date: Sun, 18 Dec 2005 00:52:39 +0100 This is a test. EOF cat >"$expected" <"$actual" 2>&1 check "$expected" "$actual" : parameter value quoting with text following # check malicious parameter value quoting msgfile=`mhpath new` msgnum=`basename $msgfile` cat >"$msgfile" <<'EOF' Subject: shows difficulty of quoting with /bin/sh -c MIME-Version: 1.0 Content-Type: text/html; charset="oops'; echo should not see this!" EOF cat >"$expected" <&1 | squeeze_whitespace >"$actual" check "$expected" "$actual" : malicious parameter value quoting # # test a large file that needs to be converted to UTF-8 # grep -v '^mhshow-show-text/plain: ' "$MH" >>"$MH.new" mv -f "$MH.new" "$MH" msgfile=`mhpath new` msgnum=`basename $msgfile` cat >"$msgfile" <<'EOF' From: foo@example.edu To: bar@example.edu Subject: check charset conversion of a large file MIME-Version: 1.0 Content-Type: text/plain; charset="windows-1252" Content-Transfer-Encoding: quoted-printable Date: Sun, 18 Dec 2005 00:52:39 +0100 1. The Earthquake The train from 'Frisco was very late. It should have arrived at Hugson's Siding at midnight, but it was already five o'clock and the gray dawn was breaking in the east when the little train slowly rumbled up to the open shed that served for the station-house. As it came to a stop the conductor called out in a loud voice: =93Hugson's Siding!=94 At once a little girl rose from her seat and walked to the door of the car, carrying a wicker suit-case in one hand and a round bird-cage covered up with newspapers in the other, while a parasol was tucked under her arm. The conductor helped her off the car and then the engineer started his train again, so that it puffed and groaned and moved slowly away up the track. The reason he was so late was because all through the night there were times when the solid earth shook and trembled under him, and the engineer was afraid that at any moment the rails might spread apart and an accident happen to his passengers. So he moved the cars slowly and with caution. The little girl stood still to watch until the train had disappeared around a curve; then she turned to see where she was. The shed at Hugson's Siding was bare save for an old wooden bench, and did not look very inviting. As she peered through the soft gray light not a house of any sort was visible near the station, nor was any person in sight; but after a while the child discovered a horse and buggy standing near a group of trees a short distance away. She walked toward it and found the horse tied to a tree and standing motionless, with its head hanging down almost to the ground. It was a big horse, tall and bony, with long legs and large knees and feet. She could count his ribs easily where they showed through the skin of his body, and his head was long and seemed altogether too big for him, as if it did not fit. His tail was short and scraggly, and his harness had been broken in many places and fastened together again with cords and bits of wire. The buggy seemed almost new, for it had a shiny top and side curtains. Getting around in front, so that she could look inside, the girl saw a boy curled up on the seat, fast asleep. She set down the bird-cage and poked the boy with her parasol. Presently he woke up, rose to a sitting position and rubbed his eyes briskly. =93Hello!=94 he said, seeing her, =93are you Dorothy Gale?=94 =93Yes,=94 she answered, looking gravely at his tousled hair and blinking gray eyes. =93Have you come to take me to Hugson's Ranch?=94 =93Of course,=94 he answered. =93Train in?=94 =93I couldn't be here if it wasn't,=94 she said. He laughed at that, and his laugh was merry and frank. Jumping out of the buggy he put Dorothy's suit-case under the seat and her bird-cage on the floor in front. =93Canary-birds?=94 he asked. =93Oh no; it's just Eureka, my kitten. I thought that was the best way to carry her.=94 The boy nodded. =93Eureka's a funny name for a cat,=94 he remarked. =93I named my kitten that because I found it,=94 she explained. =93Uncle Henry says 'Eureka' means 'I have found it.'=94 =93All right; hop in.=94 She climbed into the buggy and he followed her. Then the boy picked up the reins, shook them, and said =93Gid-dap!=94 The horse did not stir. Dorothy thought he just wiggled one of his drooping ears, but that was all. =93Gid-dap!=94 called the boy, again. The horse stood still. =93Perhaps,=94 said Dorothy, =93if you untied him, he would go.=94 The boy laughed cheerfully and jumped out. =93Guess I'm half asleep yet,=94 he said, untying the horse. =93But Jim knows his business all right--don't you, Jim?=94 patting the long nose of the animal. Then he got into the buggy again and took the reins, and the horse at once backed away from the tree, turned slowly around, and began to trot down the sandy road which was just visible in the dim light. =93Thought that train would never come,=94 observed the boy. =93I've wait= ed at that station for five hours.=94 =93We had a lot of earthquakes,=94 said Dorothy. =93Didn't you feel the ground shake?=94 =93Yes; but we're used to such things in California,=94 he replied. =93Th= ey don't scare us much.=94 =93The conductor said it was the worst quake he ever knew.=94 =93Did he? Then it must have happened while I was asleep,=94 he said thoughtfully. =93How is Uncle Henry?=94 she enquired, after a pause during which the horse continued to trot with long, regular strides. =93He's pretty well. He and Uncle Hugson have been having a fine visit.=94 =93Is Mr. Hugson your uncle?=94 she asked. =93Yes. Uncle Bill Hugson married your Uncle Henry's wife's sister; so we must be second cousins,=94 said the boy, in an amused tone. =93I work for Uncle Bill on his ranch, and he pays me six dollars a month and my board.=94 =93Isn't that a great deal?=94 she asked, doubtfully. =93Why, it's a great deal for Uncle Hugson, but not for me. I'm a splendid worker. I work as well as I sleep,=94 he added, with a laugh. =93What is your name?=94 said Dorothy, thinking she liked the boy's manner and the cheery tone of his voice. =93Not a very pretty one,=94 he answered, as if a little ashamed. =93My whole name is Zebediah; but folks just call me 'Zeb.' You've been to Australia, haven't you?=94 =93Yes; with Uncle Henry,=94 she answered. =93We got to San Francisco a w= eek ago, and Uncle Henry went right on to Hugson's Ranch for a visit while I stayed a few days in the city with some friends we had met.=94 =93How long will you be with us?=94 he asked. =93Only a day. Tomorrow Uncle Henry and I must start back for Kansas. We've been away for a long time, you know, and so we're anxious to get home again.=94 The boy flicked the big, boney horse with his whip and looked thoughtful. Then he started to say something to his little companion, but before he could speak the buggy began to sway dangerously from side to side and the earth seemed to rise up before them. Next minute there was a roar and a sharp crash, and at her side Dorothy saw the ground open in a wide crack and then come together again. =93Goodness!=94 she cried, grasping the iron rail of the seat. =93What wa= s that?=94 =93That was an awful big quake,=94 replied Zeb, with a white face. =93It almost got us that time, Dorothy.=94 The horse had stopped short, and stood firm as a rock. Zeb shook the reins and urged him to go, but Jim was stubborn. Then the boy cracked his whip and touched the animal's flanks with it, and after a low moan of protest Jim stepped slowly along the road. Neither the boy nor the girl spoke again for some minutes. There was a breath of danger in the very air, and every few moments the earth would shake violently. Jim's ears were standing erect upon his head and every muscle of his big body was tense as he trotted toward home. He was not going very fast, but on his flanks specks of foam began to appear and at times he would tremble like a leaf. The sky had grown darker again and the wind made queer sobbing sounds as it swept over the valley. Suddenly there was a rending, tearing sound, and the earth split into another great crack just beneath the spot where the horse was standing. With a wild neigh of terror the animal fell bodily into the pit, drawing the buggy and its occupants after him. Dorothy grabbed fast hold of the buggy top and the boy did the same. The sudden rush into space confused them so that they could not think. Blackness engulfed them on every side, and in breathless silence they waited for the fall to end and crush them against jagged rocks or for the earth to close in on them again and bury them forever in its dreadful depths. The horrible sensation of falling, the darkness and the terrifying noises, proved more than Dorothy could endure and for a few moments the little girl lost consciousness. Zeb, being a boy, did not faint, but he was badly frightened, and clung to the buggy seat with a tight grip, expecting every moment would be his last. 2. The Glass City When Dorothy recovered her senses they were still falling, but not so fast. The top of the buggy caught the air like a parachute or an umbrella filled with wind, and held them back so that they floated downward with a gentle motion that was not so very disagreeable to bear. The worst thing was their terror of reaching the bottom of this great crack in the earth, and the natural fear that sudden death was about to overtake them at any moment. Crash after crash echoed far above their heads, as the earth came together where it had split, and stones and chunks of clay rattled around them on every side. These they could not see, but they could feel them pelting the buggy top, and Jim screamed almost like a human being when a stone overtook him and struck his boney body. They did not really hurt the poor horse, because everything was falling together; only the stones and rubbish fell faster than the horse and buggy, which were held back by the pressure of the air, so that the terrified animal was actually more frightened than he was injured. How long this state of things continued Dorothy could not even guess, she was so greatly bewildered. But bye and bye, as she stared ahead into the black chasm with a beating heart, she began to dimly see the form of the horse Jim--his head up in the air, his ears erect and his long legs sprawling in every direction as he tumbled through space. Also, turning her head, she found that she could see the boy beside her, who had until now remained as still and silent as she herself. Dorothy sighed and commenced to breathe easier. She began to realize that death was not in store for her, after all, but that she had merely started upon another adventure, which promised to be just as queer and unusual as were those she had before encountered. With this thought in mind the girl took heart and leaned her head over the side of the buggy to see where the strange light was coming from. Far below her she found six great glowing balls suspended in the air. The central and largest one was white, and reminded her of the sun. Around it were arranged, like the five points of a star, the other five brilliant balls; one being rose colored, one violet, one yellow, one blue and one orange. This splendid group of colored suns sent rays darting in every direction, and as the horse and buggy--with Dorothy and Zeb--sank steadily downward and came nearer to the lights, the rays began to take on all the delicate tintings of a rainbow, growing more and more distinct every moment until all the space was brilliantly illuminated. Dorothy was too dazed to say much, but she watched one of Jim's big ears turn to violet and the other to rose, and wondered that his tail should be yellow and his body striped with blue and orange like the stripes of a zebra. Then she looked at Zeb, whose face was blue and whose hair was pink, and gave a little laugh that sounded a bit nervous. =93Isn't it funny?=94 she said. The boy was startled and his eyes were big. Dorothy had a green streak through the center of her face where the blue and yellow lights came together, and her appearance seemed to add to his fright. =93I--I don't s-s-see any-thing funny--'bout it!=94 he stammered. Just then the buggy tipped slowly over upon its side, the body of the horse tipping also. But they continued to fall, all together, and the boy and girl had no difficulty in remaining upon the seat, just as they were before. Then they turned bottom side up, and continued to roll slowly over until they were right side up again. During this time Jim struggled frantically, all his legs kicking the air; but on finding himself in his former position the horse said, in a relieved tone of voice: =93Well, that's better!=94 Dorothy and Zeb looked at one another in wonder. =93Can your horse talk?=94 she asked. =93Never knew him to, before,=94 replied the boy. =93Those were the first words I ever said,=94 called out the horse, who ha= d overheard them, =93and I can't explain why I happened to speak then. This is a nice scrape you've got me into, isn't it?=94 =93As for that, we are in the same scrape ourselves,=94 answered Dorothy, cheerfully. =93But never mind; something will happen pretty soon.=94 =93Of course,=94 growled the horse, =93and then we shall be sorry it happened.=94 Zeb gave a shiver. All this was so terrible and unreal that he could not understand it at all, and so had good reason to be afraid. Swiftly they drew near to the flaming colored suns, and passed close beside them. The light was then so bright that it dazzled their eyes, and they covered their faces with their hands to escape being blinded. There was no heat in the colored suns, however, and after they had passed below them the top of the buggy shut out many of the piercing rays so that the boy and girl could open their eyes again. =93We've got to come to the bottom some time,=94 remarked Zeb, with a deep sigh. =93We can't keep falling forever, you know.=94 =93Of course not,=94 said Dorothy. =93We are somewhere in the middle of t= he earth, and the chances are we'll reach the other side of it before long. But it's a big hollow, isn't it?=94 =93Awful big!=94 answered the boy. =93We're coming to something now,=94 announced the horse. At this they both put their heads over the side of the buggy and looked down. Yes; there was land below them; and not so very far away, either. But they were floating very, very slowly--so slowly that it could no longer be called a fall--and the children had ample time to take heart and look about them. They saw a landscape with mountains and plains, lakes and rivers, very like those upon the earth's surface; but all the scene was splendidly colored by the variegated lights from the six suns. Here and there were groups of houses that seemed made of clear glass, because they sparkled so brightly. =93I'm sure we are in no danger,=94 said Dorothy, in a sober voice. =93We are falling so slowly that we can't be dashed to pieces when we land, and this country that we are coming to seems quite pretty.=94 =93We'll never get home again, though!=94 declared Zeb, with a groan. =93Oh, I'm not so sure of that,=94 replied the girl. =93But don't let us worry over such things, Zeb; we can't help ourselves just now, you know, and I've always been told it's foolish to borrow trouble.=94 The boy became silent, having no reply to so sensible a speech, and soon both were fully occupied in staring at the strange scenes spread out below them. They seemed to be falling right into the middle of a big city which had many tall buildings with glass domes and sharp-pointed spires. These spires were like great spear-points, and if they tumbled upon one of them they were likely to suffer serious injury. Jim the horse had seen these spires, also, and his ears stood straight up with fear, while Dorothy and Zeb held their breaths in suspense. But no; they floated gently down upon a broad, flat roof, and came to a stop at last. When Jim felt something firm under his feet the poor beast's legs trembled so much that he could hardly stand; but Zeb at once leaped out of the buggy to the roof, and he was so awkward and hasty that he kicked over Dorothy's bird-cage, which rolled out upon the roof so that the bottom came off. At once a pink kitten crept out of the upset cage, sat down upon the glass roof, and yawned and blinked its round eyes. =93Oh,=94 said Dorothy. =93There's Eureka.=94 =93First time I ever saw a pink cat,=94 said Zeb. =93Eureka isn't pink; she's white. It's this queer light that gives her that color.=94 =93Where's my milk?=94 asked the kitten, looking up into Dorothy's face. =93I'm 'most starved to death.=94 =93Oh, Eureka! Can you talk?=94 =93Talk! Am I talking? Good gracious, I believe I am. Isn't it funny?=94 asked the kitten. =93It's all wrong,=94 said Zeb, gravely. =93Animals ought not to talk. B= ut even old Jim has been saying things since we had our accident.=94 =93I can't see that it's wrong,=94 remarked Jim, in his gruff tones. =93A= t least, it isn't as wrong as some other things. What's going to become of us now?=94 =93I don't know,=94 answered the boy, looking around him curiously. The houses of the city were all made of glass, so clear and transparent that one could look through the walls as easily as through a window. Dorothy saw, underneath the roof on which she stood, several rooms used for rest chambers, and even thought she could make out a number of queer forms huddled into the corners of these rooms. The roof beside them had a great hole smashed through it, and pieces of glass were lying scattered in every direction. A nearby steeple had been broken off short and the fragments lay heaped beside it. Other buildings were cracked in places or had corners chipped off from them; but they must have been very beautiful before these accidents had happened to mar their perfection. The rainbow tints from the colored suns fell upon the glass city softly and gave to the buildings many delicate, shifting hues which were very pretty to see. But not a sound had broken the stillness since the strangers had arrived, except that of their own voices. They began to wonder if there were no people to inhabit this magnificent city of the inner world. Suddenly a man appeared through a hole in the roof next to the one they were on and stepped into plain view. He was not a very large man, but was well formed and had a beautiful face--calm and serene as the face of a fine portrait. His clothing fitted his form snugly and was gorgeously colored in brilliant shades of green, which varied as the sunbeams touched them but was not wholly influenced by the solar rays. The man had taken a step or two across the glass roof before he noticed the presence of the strangers; but then he stopped abruptly. There was no expression of either fear or surprise upon his tranquil face, yet he must have been both astonished and afraid; for after his eyes had rested upon the ungainly form of the horse for a moment he walked rapidly to the furthest edge of the roof, his head turned back over his shoulder to gaze at the strange animal. =93Look out!=94 cried Dorothy, who noticed that the beautiful man did not look where he was going; =93be careful, or you'll fall off!=94 But he paid no attention to her warning. He reached the edge of the tall roof, stepped one foot out into the air, and walked into space as calmly as if he were on firm ground. The girl, greatly astonished, ran to lean over the edge of the roof, and saw the man walking rapidly through the air toward the ground. Soon he reached the street and disappeared through a glass doorway into one of the glass buildings. =93How strange!=94 she exclaimed, drawing a long breath. EOF cat >"$expected" <"$actual" 2>&1 check "$expected" "$actual" : large file conversion to UTF-8 exit $failed nmh-1.7.1-RC3/test/mhpath/test-mhpath000755 007761 000024 00000006375 13240377167 017433 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test mhpath # ###################################################### 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 check_exit '-eq 1' mhpath - expected=$MH_TEST_DIR/$$.expected actual=$MH_TEST_DIR/$$.actual # check -help cat > $expected <&1 | sed '/^$/,$d' >"$actual" check "$expected" "$actual" # check -version case `mhpath -v` in mhpath\ --*) ;; * ) echo "$0: mhpath -v generated unexpected output" 1>&2 failed=`expr ${failed:-0} + 1`;; esac # check + run_test "mhpath +" "$MH_TEST_DIR/Mail" # check with no options folder -fast +inbox > /dev/null run_test "mhpath" "$MH_TEST_DIR/Mail/inbox" # check +inbox run_test "mhpath +inbox" "$MH_TEST_DIR/Mail/inbox" # check all cat > $expected < $actual 2>&1 check $expected $actual # check message number greater than highest run_test "mhpath 11" "mhpath: message 11 out of range 1-10" run_test "mhpath 10 11" "mhpath: message 11 out of range 1-10" # check range with message number greater than highest cat > $expected < $actual 2>&1 check $expected $actual # check new run_test "mhpath new" "$MH_TEST_DIR/Mail/inbox/11" # check multiple msgs, including new cat > $expected < $actual 2>&1 check $expected $actual # check invalid message list using names run_test "mhpath last-new" "mhpath: bad message list last-new" # check cur folder +inbox 5 > /dev/null run_test "mhpath cur" "$MH_TEST_DIR/Mail/inbox/5" # check prev run_test "mhpath prev" "$MH_TEST_DIR/Mail/inbox/4" # check next run_test "mhpath next" "$MH_TEST_DIR/Mail/inbox/6" # check invalid message list using numbers rmm 1-2 run_test "mhpath 1-2" "mhpath: no messages in range 1-2" # check ignoring of out-of-range message numbers in ranges run_test "mhpath 1-3" "$MH_TEST_DIR/Mail/inbox/3" run_test "mhpath first-3" "$MH_TEST_DIR/Mail/inbox/3" run_test "mhpath 10-11" "$MH_TEST_DIR/Mail/inbox/10" run_test "mhpath last-11" "$MH_TEST_DIR/Mail/inbox/10" # check reference to existing messages cat > $expected < $actual 2>&1 check $expected $actual # check reference to non-existent messages cat > $expected < $actual 2>&1 check $expected $actual exit $failed nmh-1.7.1-RC3/test/mhparam/test-mhparam000755 007761 000024 00000012211 13243042053 017707 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test mhparam # ###################################################### 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 check_exit '-eq 1' mhparam - check_exit '-eq 0' mhparam localmbox expected=$MH_TEST_DIR/$$.expected expected_err=$MH_TEST_DIR/$$.expected_err actual=$MH_TEST_DIR/$$.actual actual_err=$MH_TEST_DIR/$$.actual_err # check -help start_test "-help" cat >$expected <&1 | sed '/^$/,$d' >"$actual" check "$expected" "$actual" # check -version start_test "-version" case `mhparam -v` in mhparam\ --*) ;; * ) echo "$0: mhparam -v generated unexpected output" 1>&2 failed=`expr ${failed:-0} + 1`;; esac # check unknown option start_test "unknown option" run_test 'mhparam -nonexistent' 'mhparam: -nonexistent unknown' # check -all start_test "-all" cp "$MH" $expected # -all adds current folder and Version echo 'Current-Folder: '`folder -f` >>$expected echo "Version: nmh-$MH_VERSION" >>$expected run_prog mhparam -all >$actual check $expected $actual 'keep first' # check -all with a component start_test "-all with a component" echo 'mhparam: profile-components ignored with -all' >$expected_err run_prog mhparam -all path >$actual 2>$actual_err check $expected $actual 'keep first' check $expected_err $actual_err # check -all with -components start_test "-all with -components" echo 'mhparam: -components ignored with -all' >$expected_err run_prog mhparam -all -components >$actual 2>$actual_err check $expected $actual check $expected_err $actual_err # check one component start_test "one component" run_test 'mhparam path' "$MH_TEST_DIR/Mail" # check more than one component, which enables -component start_test "more than one component, which enables -component" echo 'AliasFile: aliases' >>"$MH" run_test 'mhparam path AliasFile' "path: $MH_TEST_DIR/Mail AliasFile: aliases" # check each component in procs array in uip/mhparam.c start_test "each component in procs array in uip/mhparam.c" # The tests don't override these, so they're default or configured values. # Note that cat is hardcoded here because the testsuite uses it for moreproc. cat >$expected <$actual 2>&1 check $expected $actual #### This exits with non-zero status, so let run_test squash that: run_test 'mhparam formatproc rmmproc' '' #### Test sbackup separately because it's only passed as a -D compile option. case `mhparam sbackup` in ,|\#) ;; * ) echo mhparam sbackup failed failed=`expr ${failed:-0} + 1` ;; esac # check -component start_test "-component" run_test 'mhparam -component Path' "Path: $MH_TEST_DIR/Mail" # check -component, note that component name of argument is echoed exactly start_test "-component, note that component name of argument is echoed exactly" run_test 'mhparam -component path' "path: $MH_TEST_DIR/Mail" run_test 'mhparam -component PATH' "PATH: $MH_TEST_DIR/Mail" # check -nocomponent start_test "-nocomponent" run_test 'mhparam -component -nocomponent path' "$MH_TEST_DIR/Mail" run_test 'mhparam -nocomponent path AliasFile' "$MH_TEST_DIR/Mail aliases" # check nonexistent component start_test "nonexistent component" run_test 'mhparam nonexistent' '' # check that return status counts nonexistent components start_test "return status counts nonexistent components" set +e mhparam path context nonexistent1 nonexistent2 nonexistent3 >/dev/null run_test "echo $?" 3 set -e # And clips their numbers to avoid a misleading exit value. start_test "clips their numbers to avoid a misleading exit value" while read use want; do r=0 #### Heirloom shell can't handle the backquote expression as the #### argument: with set -e, it exits immediately. textlines=`yes nonexistent | sed ${use}q` mhparam $textlines || r=$? run_test "echo $r" $want done <<\E 119 119 120 120 121 120 E # mhparam -debug start_test "-debug" # Some of its output depends on configure options, so don't bother to # check for correctness here. mhparam -debug >/dev/null # check with text file that does not end with newline start_test "with text file that does not end with newline" printf 'Editor: emacs' >>"$MH" run_test 'mhparam -nocomponent editor' 'emacs' finish_test exit $failed nmh-1.7.1-RC3/test/mhmail/attachment.txt000644 007761 000024 00000000276 12437351011 020103 0ustar00kenhstaff000000 000000 The future disappears into memory, With only a moment between, Forever dwells in that moment, hope is what remains to be seen Forever dwells in that moment, hope is what remains to be seen. nmh-1.7.1-RC3/test/mhmail/test-mhmail000755 007761 000024 00000043531 13240377167 017402 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test mhmail # ###################################################### set -e if test -z "${MH_OBJ_DIR}"; then srcdir=`dirname $0`/../.. MH_OBJ_DIR=`cd $srcdir && pwd`; export MH_OBJ_DIR fi . "${srcdir}/test/post/test-post-common.sh" # Find MIME type string, using configured procs if available. MIMETYPEPROC=`mhparam mimetypeproc` MIMEENCODINGPROC=`mhparam mimeencodingproc` content_type_string() { if test -z "$MIMETYPEPROC" -o -z "$MIMEENCODINGPROC"; then #### This should be the order of name and charset. echo "text/plain; name=\"`basename $1`\"; charset=\"us-ascii\"" else #### Excise any leading filename followed by : and whitespace. printf '%s; charset="%s"; name="%s"' \ `$MIMETYPEPROC $1 | sed -e 's/.*: *//'` \ `$MIMEENCODINGPROC $1 | sed -e 's/.*: *//'` `basename $1` fi } # Customize test_post () for use with mhmail. # $1 is expected output file, provided by caller # $2 is mhmail switches, except for -body # $3 of -b signifies use -body switch, | signifies provide body on stdin # $4 contains the message body. test_mhmail () { pid=`"${MH_OBJ_DIR}/test/fakesmtp" "$actual" $localport` if [ $3 = '|' ]; then printf '%s' "$4" | mhmail recipient@example.com $2 \ -server 127.0.0.1 -port $localport else mhmail recipient@example.com $2 -body "$4" \ -server 127.0.0.1 -port $localport fi # # It's hard to calculate the exact Date: header post is going to # use, so we'll just use sed to remove the actual date so we can easily # compare it against our "correct" output. And same for # Message-ID. # sed -e 's/^Date:.*/Date:/' \ -e 's/^Resent-Date:.*/Resent-Date:/' \ -e 's/^Message-ID:.*/Message-ID:/' "$actual" > "$actual".nodate rm -f "$actual" check "$actual".nodate "$1" } expected=$MH_TEST_DIR/test-mhmail$$.expected expected_err=$MH_TEST_DIR/test-mhmail$$.expected_err actual=$MH_TEST_DIR/test-mhmail$$.actual actual_err=$MH_TEST_DIR/test-mhmail$$.actual_err # check -help # Verified behavior consistent with compiled sendmail. cat >$expected <&1 | sed '/^$/,$d' >"$actual" check "$expected" "$actual" # check -version # Verified same behavior as compiled mhmail. case `mhmail -v` in mhmail\ --*) ;; * ) printf '%s: mhmail -v generated unexpected output\n' "$0" >&2 failed=`expr ${failed:-0} + 1`;; esac # check for missing argument to switches that require them for switch in attach body cc from headerfield subject to; do run_test "mhmail recipient -$switch" \ "mhmail: missing argument to -$switch" done for switch in attach body cc from headerfield subject to; do run_test "mhmail recipient -$switch -nosend" \ "mhmail: missing argument to -$switch" done for switch in attach body cc from headerfield subject to; do run_test "mhmail recipient -$switch -server 127.0.0.1" \ "mhmail: missing argument to -$switch" done # check with no switches # That will just run inc, which we don't want to do anything, # so tell inc to just display its version. # Verified same behavior as compiled mhmail. printf 'inc: -version\n' >> $MH case `mhmail` in inc\ --*) ;; * ) echo "$0: mhmail generated unexpected output" >&2 failed=`expr ${failed:-0} + 1`;; esac # check -nosend # Not supported by compiled mhmail. mhmail -nosend recipient@example.com -from sender1@localhost \ -server 127.0.0.1 -port $localport -body '' >"$actual" 2>"$actual_err" cat > "$expected" < "$expected_err" < "$expected" < RCPT TO: DATA To: recipient@example.com From: sender2@localhost Date: message . QUIT EOF test_mhmail "$expected" "-from sender2@localhost -nosend -send" '|' message [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check -from # Verified same behavior as compiled mhmail. cat > "$expected" < RCPT TO: DATA To: recipient@example.com From: sender3@localhost Date: message . QUIT EOF test_mhmail "$expected" "-from sender3@localhost" '|' message [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check -from and -body # Verified same behavior as compiled mhmail. cat > "$expected" < RCPT TO: DATA To: recipient@example.com From: sender4@localhost Date: body . QUIT EOF test_mhmail "$expected" "-from sender4@localhost" -b body [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check -from and -cc # Verified same behavior as compiled mhmail. cat > "$expected" < RCPT TO: RCPT TO: DATA To: recipient@example.com Cc: recipient2@example.com From: sender5@localhost Date: message . QUIT EOF test_mhmail "$expected" \ "-from sender5@localhost -cc recipient2@example.com" '|' message [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check -from and multiple -cc addresses # Verified same behavior as compiled mhmail. cat > "$expected" < RCPT TO: RCPT TO: RCPT TO: RCPT TO: DATA To: recipient@example.com Cc: recipient2@example.com, recipient3@example.com, recipient4@example.com From: sender6@localhost Date: message . QUIT EOF test_mhmail "$expected" \ '-from sender6@localhost -cc recipient2@example.com '\ 'recipient3@example.com recipient4@example.com' '|' message [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check -from and -subject # Verified same behavior as compiled mhmail. cat > "$expected" < RCPT TO: DATA To: recipient@example.com Subject: Test From: sender7@localhost Date: message . QUIT EOF test_mhmail "$expected" '-from sender7@localhost -subject Test' '|' message [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check -from and -profile # Show that -profile causes mhmail to 1) read the profile and # 2) use send(1) by added a send switch to the profile and # verifying that it gets used. # Not supported by compiled mhmail. printf 'send: -msgid\n' >> $MH cat > "$expected" < RCPT TO: DATA To: recipient@example.com From: sender8@localhost MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Date: Message-ID: message . QUIT EOF test_mhmail "$expected" '-from sender8@localhost -profile' '|' message [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check repeated -from and -subject switches # Verified same behavior as compiled mhmail. cat > "$expected" < RCPT TO: DATA To: recipient@example.com Subject: Subject2 From: sender9@localhost Date: message . QUIT EOF test_mhmail "$expected" '-from sender9@localhost -from sender9@localhost '\ '-subject Subject1 -subject Subject2' -b message [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check repeated -body switches # Verified same behavior as compiled mhmail. cat > "$expected" < RCPT TO: DATA To: recipient@example.com From: sender10@localhost Date: body2 . QUIT EOF test_mhmail "$expected" "-from sender10@localhost -body body1" -b body2 [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check multiple -cc switches # Verified same behavior as compiled mhmail. cat > "$expected" < RCPT TO: RCPT TO: RCPT TO: DATA To: recipient@example.com Cc: cc1@example.com, cc2@example.com From: sender11@localhost Date: message . QUIT EOF test_mhmail "$expected" \ '-from sender11@localhost -cc cc1@example.com -cc cc2@example.com' -b message [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check separated -cc arguments # Verified same behavior as compiled mhmail. cat > "$expected" < RCPT TO: RCPT TO: RCPT TO: DATA To: recipient@example.com Cc: cc1@example.com, cc2@example.com Subject: Test From: sender12@localhost Date: message . QUIT EOF test_mhmail "$expected" \ '-from sender12@localhost -cc cc1@example.com -subject '\ 'Test cc2@example.com' -b message [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check -cc switch followed by -to switch # Verified same behavior as compiled mhmail. cat > "$expected" < RCPT TO: RCPT TO: RCPT TO: DATA To: recipient@example.com, recipient2@example.com Cc: cc1@example.com Subject: Test From: sender13@localhost Date: message . QUIT EOF test_mhmail "$expected" \ "-from sender13@localhost -cc cc1@example.com -subject Test \ -to recipient2@example.com" \ -b message [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check with no newline on stdin # Shows different behavior than compiled mhmail, which was silent in this case. cat > "$expected" < "$expected_err" <"$actual" 2>"$actual_err" set -e check "$expected" "$actual" check "$expected_err" "$actual_err" [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check with one newline on stdin # Verified same behavior as compiled mhmail. cat > "$expected" < RCPT TO: DATA To: recipient@example.com From: sender14@localhost Date: . QUIT EOF test_mhmail "$expected" '-from sender14@localhost' '|' ' ' [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check with multiple newlines on stdin # Verified same behavior as compiled mhmail. cat > "$expected" < RCPT TO: DATA To: recipient@example.com From: sender15@localhost Date: . QUIT EOF test_mhmail "$expected" '-from sender15@localhost' '|' ' ' [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check with text and no trailing newline on stdin # Verified same behavior as compiled mhmail. cat > "$expected" < RCPT TO: DATA To: recipient@example.com From: sender16@localhost Date: no newline in input . QUIT EOF test_mhmail "$expected" '-from sender16@localhost' '|' 'no newline in input' [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check with text and multiple trailing blank lines on stdin # Verified same behavior as compiled mhmail. cat > "$expected" < RCPT TO: DATA To: recipient@example.com From: sender17@localhost Date: here's some text . QUIT EOF test_mhmail "$expected" '-from sender17@localhost' '|' "here's some text " [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check with no newline to -body # Verified same behavior as compiled mhmail. cat > "$expected" < RCPT TO: DATA To: recipient@example.com From: sender18@localhost Date: . QUIT EOF test_mhmail "$expected" '-from sender18@localhost' -b '' [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check with one newline to -body # Shows different behavior than compiled mhmail, which suppressed the newline. cat > "$expected" < RCPT TO: DATA To: recipient@example.com From: sender19@localhost Date: . QUIT EOF test_mhmail "$expected" '-from sender19@localhost' -b ' ' [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check with multiple newlines to -body # Shows different behavior than compiled mhmail, which suppressed one # of the newlines. cat > "$expected" < RCPT TO: DATA To: recipient@example.com From: sender20@localhost Date: . QUIT EOF test_mhmail "$expected" '-from sender20@localhost' -b ' ' [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check with text and no trailing newline to -body # Verified same behavior as compiled mhmail. cat > "$expected" < RCPT TO: DATA To: recipient@example.com From: sender21@localhost Date: no newline in input . QUIT EOF test_mhmail "$expected" '-from sender21@localhost' -b 'no newline in input' [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check with text and multiple trailing blank lines to -body # Shows different behavior than compiled mhmail, which suppressed one # of the newlines. cat > "$expected" < RCPT TO: DATA To: recipient@example.com From: sender22@localhost Date: here's some text . QUIT EOF test_mhmail "$expected" '-from sender22@localhost' -b "here's some text " [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check -resent # Verified same behavior as compiled mhmail. cat > "$expected" < RCPT TO: DATA Resent-To: recipient@example.com Resent-From: orig_recipient@example.com To: recipient@example.com From: sender23@localhost Date: Resent-Date: please resend this message, 1 . QUIT EOF test_mhmail "$expected" '-from orig_recipient@example.com -resent' \ -b 'To: recipient@example.com From: sender23@localhost Date: Sat Jun 16 18:35:15 -0500 please resend this message, 1' [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check -resent -profile, using stdin # Not supported by compiled mhmail. cat > "$expected" < RCPT TO: DATA To: recipient@example.com From: sender24@localhost Date: Resent-To: recipient@example.com Resent-From: orig_recipient@example.com Resent-Date: please resend this message, 2 . QUIT EOF test_mhmail "$expected" \ '-from orig_recipient@example.com -resent -profile -nomsgid' \ '|' 'To: recipient@example.com From: sender24@localhost Date: Sat Jun 16 18:35:15 -0500 please resend this message, 2' [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check -resent -profile, using -b # Not supported by compiled mhmail. cat > "$expected" < RCPT TO: DATA To: recipient@example.com From: sender25@localhost Date: Resent-To: recipient@example.com Resent-From: orig_recipient@example.com Resent-Date: please resend this message, 3 . QUIT EOF test_mhmail "$expected" \ '-from orig_recipient@example.com -resent -profile -nomsgid' \ -b 'To: recipient@example.com From: sender25@localhost Date: Sat Jun 16 18:35:15 -0500 please resend this message, 3' [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check -headerfield. # Not supported by compiled mhmail. cat > "$expected" < RCPT TO: DATA To: recipient@example.com From: sender26@example.com User-Agent: nmh Date: with added header field . QUIT EOF test_mhmail "$expected" \ '-from sender26@example.com -headerfield User-Agent:nmh' \ -b 'with added header field' [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check multiple -headerfields. # Not supported by compiled mhmail. cat > "$expected" < RCPT TO: DATA To: recipient@example.com From: sender27@example.com MIME-Version: 1.0 Content-Type: text/plain;charset=utf-8 Content-Transfer-Encoding: 7bit Date: with added header fields . QUIT EOF test_mhmail "$expected" \ "-from sender27@example.com -headerfield MIME-Version:1.0 \ -headerfield Content-Type:text/plain;charset=utf-8 \ -headerfield Content-Transfer-Encoding:7bit" \ -b 'with added header fields' [ ${failed:-0} -eq 0 ] || exit ${failed:-0} # check -attach # Not supported by compiled mhmail. cat > "$expected" < RCPT TO: DATA To: recipient@example.com From: sender28@example.com MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" Date: Message-ID: ------- =_aaaaaaaaaa0 Content-Type: text/plain; charset="us-ascii" See how easy it is to add an attachment! ------- =_aaaaaaaaaa0 Content-Type: `content_type_string ${srcdir}/test/mhmail/attachment.txt` Content-Description: attachment.txt Content-Disposition: attachment; filename="attachment.txt" The future disappears into memory, With only a moment between, Forever dwells in that moment, hope is what remains to be seen Forever dwells in that moment, hope is what remains to be seen. ------- =_aaaaaaaaaa0-- . QUIT EOF test_mhmail "$expected" \ "-from sender28@example.com -attach ${srcdir}/test/mhmail/attachment.txt" \ -b 'See how easy it is to add an attachment!' [ ${failed:-0} -eq 0 ] || exit ${failed:-0} exit ${failed:-0} nmh-1.7.1-RC3/test/mhlist/test-ext-params000755 007761 000024 00000013102 13243042053 020216 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test mhlist with extended parameters (RFC 2231) # ###################################################### 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 require_locale en_US.UTF-8 en_US.UTF8 en_US.utf-8 en_US.utf8 expected=$MH_TEST_DIR/$$.expected actual=$MH_TEST_DIR/$$.actual # # Write a message with some extended parameters # msgfile=`mhpath new` cat > $msgfile < $msgfile < $msgfile < /dev/null cat > $expected < $actual 2>&1 check $expected $actual 'keep first' start_test '-noheaders' run_test 'mhlist 5 -noheaders' ' 5 text/plain 25' start_test '-headers' run_prog mhlist -noheaders -headers > $actual 2>&1 check $expected $actual 'keep first' start_test 'with folder and current message' run_prog mhlist +inbox > $actual 2>&1 check $expected $actual 'keep first' start_test 'with specified message' run_prog mhlist 5 > $actual 2>&1 check $expected $actual 'keep first' start_test '-file' run_prog mhlist -file "$MH_TEST_DIR/Mail/inbox/5" > $actual 2>&1 check $expected $actual start_test '-file -' cat > $expected < $actual 2>&1 check $expected $actual start_test 'message with no blank line separating the headers from the body.' # Shouldn't make a difference to the size of the body part. # Bug meant no-blank-line case was one bigger by including the `\n' # ending the last header. f=$MH_TEST_DIR/$$.blank cat >$f-yes <<\E foo: bar body1 body2 E sed '/^$/d' $f-yes >$f-no run_prog mhlist -file $f-yes >$actual-yes run_prog mhlist -file $f-no >$actual-no check $actual-yes $actual-no rm $f-yes $f-no start_test 'message number greater than highest' run_test 'mhlist 11' "mhlist: message 11 doesn't exist" start_test 'multiple messages' cat > $expected < $actual 2>&1 check $expected $actual # Write message with a text/plain subpart. msgfile=`mhpath new` cat > $msgfile < $MH_TEST_DIR/$$.tmp mv -f $MH_TEST_DIR/$$.tmp $msgfile run_test 'mhlist last -part 2 -noheader -check' \ ' 11 multipart/mixed 936 1 multipart/related 180 2 text/plain 36 mhlist: content integrity suspect (digest mismatch) -- continuing (content text/plain in message 11, part 2)' start_test '-nocheck, the default' run_test 'mhlist last -part 2 -noheader -check -nocheck' \ ' 11 multipart/mixed 936 1 multipart/related 180 2 text/plain 36' # # Set the cur sequence to 1 to test default behavior of changecur after # this test. # mark 1 -sequence cur -add -zero start_test '-verbose' run_test 'mhlist 11 -verbose -noheader' \ ' 11 multipart/mixed 936 boundary="----- =_aaaaaaaaaa0" 1 multipart/related 180 type="multipart/alternative" boundary="subpart__1.1" 1.1 text/plain 49 charset="iso-8859-1" 2 text/plain 36 charset="iso-8859-1" 3 text/plain 35 charset="iso-8859-1" name="test3" 4 text/plain 36 charset="iso-8859-1"' # start_test 'default changecur behavior' # run_test 'mark -sequence cur -list' 'cur: 11' # # Now test -nochangecur # mhlist -nochangecur 1 >/dev/null run_test 'mark -sequence cur -list' 'cur: 11' start_test 'MIME parser and m_getfld' cat > $expected < $msgfile < $actual 2>&1 check $expected $actual ## now check mhlist output msgfile=`mhpath new` msgnum=`basename $msgfile` cat > $msgfile < Subject: mhlist test Date: Thu, 29 Jan 2015 18:12:21 +0000 (GMT) Content-Type: multipart/mixed; boundary="BoundaryMixed" --BoundaryMixed Content-type: multipart/alternative; boundary="BoundaryAlternative1" --BoundaryAlternative1 Content-type: text/enriched; CHARSET=US-ASCII Content-transfer-encoding: 7bit This is supposedly enriched. --BoundaryAlternative1 Content-type: text/plain; charset=ISO-8859-1; format=flowed Content-transfer-encoding: 8bit This is the body text/plain part. --BoundaryAlternative1 Content-type: text/html; CHARSET=US-ASCII Content-transfer-encoding: 7bit
This is the text/html body part.
--BoundaryAlternative1-- --BoundaryMixed Content-type: multipart/alternative; boundary="BoundaryAlternative2" --BoundaryAlternative2 Content-type: audio/wav Content-transfer-encoding: 8bit pretend wav audio --BoundaryAlternative2 Content-type: audio/mp3 Content-transfer-encoding: 8bit pretend mp3 audio --BoundaryAlternative2 Content-type: audio/basic Content-transfer-encoding: 8bit pretend basic audio --BoundaryAlternative2-- --BoundaryMixed-- EOF # Write the expected output. cat > $expected < $actual 2>&1 check "$expected" "$actual" # Write the expected output. cat > $expected < $actual 2>&1 check "$expected" "$actual" # Write the expected output. cat > $expected < $actual 2>&1 check "$expected" "$actual" # Write the expected output. cat > $expected < $actual 2>&1 check "$expected" "$actual" # Write the expected output. cat > $expected < $actual 2>&1 check "$expected" "$actual" finish_test exit $failed nmh-1.7.1-RC3/test/mhl/test-mhl-flags000755 007761 000024 00000004736 13205305705 017310 0ustar00kenhstaff000000 000000 #!/bin/sh # # Test of various (well, start with one) function escapes. 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 mhl="${MH_LIBEXEC_DIR}/mhl" MHLDEBUG=foo check_exit '-eq 1' "$mhl" - unset MHLDEBUG check_exit '-eq 1' "$mhl" -xyzzy check_exit '-eq 0' "$mhl" -help check_exit '-eq 0' "$mhl" -version check_exit '-eq 1' "$mhl" -bell -nobell -clear - check_exit '-eq 1' "$mhl" -folder check_exit '-eq 1' "$mhl" -folder + - check_exit '-eq 1' "$mhl" -form check_exit '-eq 1' "$mhl" -sleep check_exit '-eq 1' "$mhl" -sleep 42 - check_exit '-eq 1' "$mhl" -moreproc foo -moreproc check_exit '-eq 1' "$mhl" -nofmtproc -fmtproc foo -fmtproc check_exit '-eq 1' "$mhl" -length 42 -length check_exit '-eq 1' "$mhl" -length 0 check_exit '-eq 1' "$mhl" -width check_exit '-eq 1' "$mhl" -digest foo -width 0 check_exit '-eq 1' "$mhl" -issue 42 -digest check_exit '-eq 1' "$mhl" -issue check_exit '-eq 1' "$mhl" -volume 42 -issue 0 check_exit '-eq 1' "$mhl" -volume check_exit '-eq 1' "$mhl" -forwall -volume 0 check_exit '-eq 0' "$mhl" -dashstuffing -nodashstuffing \ -forwall `mhpath new` <"$expected" < There are two blank lines below. And there is a trailing space: > And another trailing space: > > EOF cat >"$MH_TEST_DIR/test.format" <"$actual" check "$expected" "$actual" # check rtrim cat >"$expected" < There are two blank lines below. And there is a trailing space: > And another trailing space: > > EOF cat >"$MH_TEST_DIR/test.format" <"$actual" check "$expected" "$actual" rm -f "$MH_TEST_DIR/test.format" exit $failed nmh-1.7.1-RC3/test/mhl/test-rfc6532000755 007761 000024 00000005266 13205305705 016527 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test compatibility with RFC 6532, Internationalized # Email Headers # ###################################################### 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 mhl="${MH_LIBEXEC_DIR}/mhl" #### Make sure that html-to-text conversion is what we expect. require_locale en_US.UTF-8 en_US.UTF8 en_US.utf-8 en_US.utf8 start_test 'UTF-8 headers' #### The -- position the multibyte characters to check edge #### cases in the 'UTF-8 headers with narrow width' test below. cat >`mhpath new` <"$MH_TEST_DIR/test.format" <"$expected" <&1 | sed '/^$/,$d' >"$actual" check "$expected" "$actual" # check -version start_test "-version" case `mhical -version` in mhical\ --*) ;; *) printf '%s: mhical -version generated unexpected output\n' "$0" >&2 failed=`expr ${failed:-0} + 1`;; esac # check display with timezone that only has standard time start_test "display with timezone that only has standard time" cat >"$expected" <<'EOF' Summary: Santa Watch Description: See Santa here first! At: Wed, 24 Dec 2014 12:00 +0000 To: Fri, 25 Dec 2015 11:59 EOF cat >"$MH_TEST_DIR/test1.ics" <<'EOF' BEGIN:VCALENDAR VERSION:2.0 PRODID:test-mhical BEGIN:VTIMEZONE TZID:MHT-12 BEGIN:STANDARD DTSTART:16010101T020000 TZOFFSETFROM:+1200 TZOFFSETTO:+1200 END:STANDARD END:VTIMEZONE BEGIN:VEVENT DTSTAMP:20141224T140426Z DTSTART;TZID=MHT-12:20141225T000000 DTEND;TZID=MHT-12:20151225T235959 SUMMARY:Santa Watch DESCRIPTION: See Santa here first! END:VEVENT END:VCALENDAR EOF TZ=UTC mhical <"$MH_TEST_DIR/test1.ics" >"$MH_TEST_DIR/test1.txt" check "$expected" "$MH_TEST_DIR/test1.txt" # check display with 24 hour time format and -outfile start_test "display with 24 hour time format and -outfile" cat >"$expected" <<'EOF' Summary: 4 pm meeting At: Mon, 05 Jan 2015 16:00 To: Mon, 05 Jan 2015 16:30 EOF cat >"$MH_TEST_DIR/test1.ics" <<'EOF' BEGIN:VCALENDAR VERSION:2.0 PRODID:test-mhical BEGIN:VEVENT DTSTAMP:20150101T162400Z DTSTART:20150105T160000 DTEND:20150105T163000 SUMMARY:4 pm meeting END:VEVENT END:VCALENDAR EOF mhical -outfile "$MH_TEST_DIR/test1.txt" <"$MH_TEST_DIR/test1.ics" check "$expected" "$MH_TEST_DIR/test1.txt" # check display with 12 hour time format and -infile start_test "display with 12 hour time format and -infile" cat >"$expected" <<'EOF' Summary: 4 pm meeting At: Mon, 05 Jan 2015 4:00 PM To: Mon, 05 Jan 2015 4:30 PM EOF cat >"$MH_TEST_DIR/test1.ics" <<'EOF' BEGIN:VCALENDAR VERSION:2.0 PRODID:test-mhical BEGIN:VEVENT DTSTAMP:20150101T162800Z DTSTART:20150105T160000 DTEND:20150105T163000 SUMMARY:4 pm meeting END:VEVENT END:VCALENDAR EOF mhical -form mhical.12hour -infile "$MH_TEST_DIR/test1.ics" \ >"$MH_TEST_DIR/test1.txt" check "$expected" "$MH_TEST_DIR/test1.txt" # check display with DST start_test "display with DST" cat >"$expected" <<'EOF' Method: REQUEST Organizer: Requester Summary: Big Meeting Location: The Office At: Mon, 05 Jan 2015 08:00 -0500 To: Mon, 05 Jan 2015 09:00 Attendees: Requestee EOF cat >"$MH_TEST_DIR/test1.ics" <<'EOF' BEGIN:VCALENDAR METHOD:REQUEST PRODID:Microsoft Exchange Server 2010 VERSION:2.0 BEGIN:VTIMEZONE TZID:Eastern Standard Time BEGIN:STANDARD DTSTART:16010101T020000 TZOFFSETFROM:-0400 TZOFFSETTO:-0500 RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11 END:STANDARD BEGIN:DAYLIGHT DTSTART:16010101T020000 TZOFFSETFROM:-0500 TZOFFSETTO:-0400 RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=2SU;BYMONTH=3 END:DAYLIGHT END:VTIMEZONE BEGIN:VEVENT ORGANIZER;CN=Requester:MAILTO:requester@example.com ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=FALSE;CN=Requestee :MAILTO:requestee@example.com DESCRIPTION;LANGUAGE=en-US:\n\n SUMMARY;LANGUAGE=en-US:Big Meeting DTSTART;TZID=Eastern Standard Time:20150105T080000 DTEND;TZID=Eastern Standard Time:20150105T090000 UID:0123456789 CLASS:PUBLIC PRIORITY:5 DTSTAMP:20141231T235959Z TRANSP:OPAQUE STATUS:CONFIRMED SEQUENCE:0 LOCATION;LANGUAGE=en-US:The Office X-MICROSOFT-CDO-APPT-SEQUENCE:0 X-MICROSOFT-CDO-OWNERAPPTID:-0123456789 X-MICROSOFT-CDO-BUSYSTATUS:TENTATIVE X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY X-MICROSOFT-CDO-ALLDAYEVENT:FALSE X-MICROSOFT-CDO-IMPORTANCE:1 X-MICROSOFT-CDO-INSTTYPE:0 X-MICROSOFT-DISALLOW-COUNTER:FALSE BEGIN:VALARM ACTION:DISPLAY DESCRIPTION:REMINDER TRIGGER;RELATED=START:-PT15M END:VALARM END:VEVENT END:VCALENDAR EOF TZ=EST mhical <"$MH_TEST_DIR/test1.ics" >"$MH_TEST_DIR/test1.txt" check "$expected" "$MH_TEST_DIR/test1.txt" # check timezone boundary at transition to daylight saving time start_test "timezone boundary at transition to daylight saving time" # The default mhical display format doesn't show the timezone for the # To: time, but it is different than that of the At: time. cat >"$expected" <<'EOF' Summary: EST to EDT At: Sun, 09 Mar 2014 01:59 -0500 To: Sun, 09 Mar 2014 03:30 EOF cat >"$MH_TEST_DIR/test1.ics" <<'EOF' BEGIN:VCALENDAR VERSION:2.0 PRODID:test-mhical BEGIN:VTIMEZONE TZID:Eastern Standard Time BEGIN:STANDARD DTSTART:16010101T020000 TZOFFSETFROM:-0400 TZOFFSETTO:-0500 RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11 END:STANDARD BEGIN:DAYLIGHT DTSTART:16010101T020000 TZOFFSETFROM:-0500 TZOFFSETTO:-0400 RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=2SU;BYMONTH=3 END:DAYLIGHT END:VTIMEZONE BEGIN:VEVENT DTSTAMP:20150101T000000Z DTSTART;TZID=Eastern Standard Time:20140309T015959 DTEND;TZID=Eastern Standard Time:20140309T023000 Summary: EST to EDT END:VEVENT END:VCALENDAR EOF TZ=EST5EDT mhical <"$MH_TEST_DIR/test1.ics" >"$MH_TEST_DIR/test1.txt" check "$expected" "$MH_TEST_DIR/test1.txt" # check -format, and that timezone is correct in end time start_test "-format, and that timezone is correct in end time" cat >"$expected" <<'EOF' Sun, 09 Mar 2014 03:30:00 -0400 EOF TZ=EST5EDT mhical -format '%(pretty{dtend})' \ -infile "$MH_TEST_DIR/test1.ics" -outfile "$MH_TEST_DIR/test1.txt" check "$expected" "$MH_TEST_DIR/test1.txt" # check timezone boundary at transition from daylight saving time start_test "timezone boundary at transition from daylight saving time" cat >"$expected" <<'EOF' Summary: EDT to EST At: Sun, 02 Nov 2014 01:59 -0400 To: Sun, 02 Nov 2014 02:00 EOF cat >"$MH_TEST_DIR/test1.ics" <<'EOF' BEGIN:VCALENDAR VERSION:2.0 PRODID:test-mhical BEGIN:VTIMEZONE TZID:Eastern Standard Time BEGIN:STANDARD DTSTART:16010101T020000 TZOFFSETFROM:-0400 TZOFFSETTO:-0500 RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11 END:STANDARD BEGIN:DAYLIGHT DTSTART:16010101T020000 TZOFFSETFROM:-0500 TZOFFSETTO:-0400 RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=2SU;BYMONTH=3 END:DAYLIGHT END:VTIMEZONE BEGIN:VEVENT DTSTAMP:20150101T000000Z DTSTART;TZID=Eastern Standard Time:20141102T015959 DTEND;TZID=Eastern Standard Time:20141102T020000 Summary: EDT to EST END:VEVENT END:VCALENDAR EOF TZ=EST5EDT mhical <"$MH_TEST_DIR/test1.ics" >"$MH_TEST_DIR/test1.txt" check "$expected" "$MH_TEST_DIR/test1.txt" # check -format, and that timezone is correct in end time start_test "-format, and that timezone is correct in end time" cat >"$expected" <<'EOF' Sun, 02 Nov 2014 02:00:00 -0500 EOF TZ=EST5EDT mhical -format '%(pretty{dtend})' \ -infile "$MH_TEST_DIR/test1.ics" -outfile "$MH_TEST_DIR/test1.txt" check "$expected" "$MH_TEST_DIR/test1.txt" printf 'Local-Mailbox: Requestee2 \n' >> "$MH" # check accept of request start_test "accept of request" cat >"$expected" <<'EOF' BEGIN:VCALENDAR METHOD:REPLY PRODID:nmh mhical v0.1 VERSION:2.0 BEGIN:VTIMEZONE TZID:Eastern Standard Time BEGIN:STANDARD DTSTART:16010101T020000 TZOFFSETFROM:-0400 TZOFFSETTO:-0500 RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11 END:STANDARD BEGIN:DAYLIGHT DTSTART:16010101T020000 TZOFFSETFROM:-0500 TZOFFSETTO:-0400 RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=2SU;BYMONTH=3 END:DAYLIGHT END:VTIMEZONE BEGIN:VEVENT ORGANIZER;CN=Requester:MAILTO:requester@example.com ATTENDEE;PARTSTAT=ACCEPTED;CN=Requestee2:MAILTO:requestee2@example.com SUMMARY;LANGUAGE=en-US:Accepted: test request DTSTART;TZID=Eastern Standard Time:20150105T090000 DTEND;TZID=Eastern Standard Time:20150105T093000 UID:0123456789 CLASS:PUBLIC PRIORITY:5 TRANSP:OPAQUE STATUS:CONFIRMED SEQUENCE:0 LOCATION;LANGUAGE=en-US: END:VEVENT END:VCALENDAR EOF cat >"$MH_TEST_DIR/test1.ics" <<'EOF' BEGIN:VCALENDAR METHOD:REQUEST PRODID:test-mhical VERSION:2.0 BEGIN:VTIMEZONE TZID:Eastern Standard Time BEGIN:STANDARD DTSTART:16010101T020000 TZOFFSETFROM:-0400 TZOFFSETTO:-0500 RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11 END:STANDARD BEGIN:DAYLIGHT DTSTART:16010101T020000 TZOFFSETFROM:-0500 TZOFFSETTO:-0400 RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=2SU;BYMONTH=3 END:DAYLIGHT END:VTIMEZONE BEGIN:VEVENT ORGANIZER;CN=Requester:MAILTO:requester@example.com ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Requestee1 :MAILTO:requestee1@example.com ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Requestee2 :MAILTO:requestee2@example.com ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Requestee3 :MAILTO:requestee3@example.com SUMMARY;LANGUAGE=en-US:test request DTSTART;TZID=Eastern Standard Time:20150105T090000 DTEND;TZID=Eastern Standard Time:20150105T093000 UID:0123456789 CLASS:PUBLIC PRIORITY:5 DTSTAMP:20150101T171600Z TRANSP:OPAQUE STATUS:CONFIRMED SEQUENCE:0 LOCATION;LANGUAGE=en-US: BEGIN:VALARM ACTION:DISPLAY DESCRIPTION:REMINDER TRIGGER;RELATED=START:-PT15M END:VALARM END:VEVENT END:VCALENDAR EOF mhical -reply accept <"$MH_TEST_DIR/test1.ics" | egrep -v '^DTSTAMP:' \ >"$MH_TEST_DIR/test1.txt" check "$expected" "$MH_TEST_DIR/test1.txt" # check accept of multiple vevent requests in single vcalendar start_test "accept of multiple vevent requests in single vcalendar" cat >"$expected" <<'EOF' BEGIN:VCALENDAR METHOD:REPLY PRODID:nmh mhical v0.1 VERSION:2.0 BEGIN:VTIMEZONE TZID:Eastern Standard Time BEGIN:STANDARD DTSTART:16010101T020000 TZOFFSETFROM:-0400 TZOFFSETTO:-0500 RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11 END:STANDARD BEGIN:DAYLIGHT DTSTART:16010101T020000 TZOFFSETFROM:-0500 TZOFFSETTO:-0400 RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=2SU;BYMONTH=3 END:DAYLIGHT END:VTIMEZONE BEGIN:VEVENT ORGANIZER;CN=Requester:MAILTO:requester@example.com ATTENDEE;PARTSTAT=ACCEPTED;CN=Requestee2:MAILTO:requestee2@example.com SUMMARY;LANGUAGE=en-US:Accepted: test request DTSTART;TZID=Eastern Standard Time:20150105T090000 DTEND;TZID=Eastern Standard Time:20150105T093000 UID:0123456790 CLASS:PUBLIC PRIORITY:5 TRANSP:OPAQUE STATUS:CONFIRMED SEQUENCE:0 LOCATION;LANGUAGE=en-US: END:VEVENT BEGIN:VEVENT ORGANIZER;CN=Requester:MAILTO:requester@example.com ATTENDEE;PARTSTAT=ACCEPTED;CN=Requestee2:MAILTO:requestee2@example.com SUMMARY;LANGUAGE=en-US:Accepted: test request DTSTART;TZID=Eastern Standard Time:20150105T130000 DTEND;TZID=Eastern Standard Time:20150105T134500 UID:0123456791 CLASS:PUBLIC PRIORITY:5 TRANSP:OPAQUE STATUS:CONFIRMED SEQUENCE:0 LOCATION;LANGUAGE=en-US: END:VEVENT END:VCALENDAR EOF cat >"$MH_TEST_DIR/test1.ics" <<'EOF' BEGIN:VCALENDAR METHOD:REQUEST PRODID:test-mhical VERSION:2.0 BEGIN:VTIMEZONE TZID:Eastern Standard Time BEGIN:STANDARD DTSTART:16010101T020000 TZOFFSETFROM:-0400 TZOFFSETTO:-0500 RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=11 END:STANDARD BEGIN:DAYLIGHT DTSTART:16010101T020000 TZOFFSETFROM:-0500 TZOFFSETTO:-0400 RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=2SU;BYMONTH=3 END:DAYLIGHT END:VTIMEZONE BEGIN:VEVENT ORGANIZER;CN=Requester:MAILTO:requester@example.com ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Requestee1 :MAILTO:requestee1@example.com ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Requestee2 :MAILTO:requestee2@example.com ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Requestee3 :MAILTO:requestee3@example.com SUMMARY;LANGUAGE=en-US:test request DTSTART;TZID=Eastern Standard Time:20150105T090000 DTEND;TZID=Eastern Standard Time:20150105T093000 UID:0123456790 CLASS:PUBLIC PRIORITY:5 DTSTAMP:20150101T171600Z TRANSP:OPAQUE STATUS:CONFIRMED SEQUENCE:0 LOCATION;LANGUAGE=en-US: BEGIN:VALARM ACTION:DISPLAY DESCRIPTION:REMINDER TRIGGER;RELATED=START:-PT15M END:VALARM END:VEVENT BEGIN:VEVENT ORGANIZER;CN=Requester:MAILTO:requester@example.com ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Requestee2 :MAILTO:requestee2@example.com ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Requestee3 :MAILTO:requestee3@example.com SUMMARY;LANGUAGE=en-US:test request DTSTART;TZID=Eastern Standard Time:20150105T130000 DTEND;TZID=Eastern Standard Time:20150105T134500 UID:0123456791 CLASS:PUBLIC PRIORITY:5 DTSTAMP:20150101T171600Z TRANSP:OPAQUE STATUS:CONFIRMED SEQUENCE:0 LOCATION;LANGUAGE=en-US: BEGIN:VALARM ACTION:DISPLAY DESCRIPTION:REMINDER TRIGGER;RELATED=START:-PT15M END:VALARM END:VEVENT END:VCALENDAR EOF mhical -reply accept <"$MH_TEST_DIR/test1.ics" | egrep -v '^DTSTAMP:' \ >"$MH_TEST_DIR/test1.txt" check "$expected" "$MH_TEST_DIR/test1.txt" # check decline of request start_test "decline of request" cat >"$expected" <<'EOF' BEGIN:VCALENDAR METHOD:REPLY PRODID:nmh mhical v0.1 VERSION:2.0 BEGIN:VEVENT ORGANIZER;CN=Requester:MAILTO:requester@example.com ATTENDEE;PARTSTAT=DECLINED;CN=Requestee2:MAILTO:requestee2@example.com SUMMARY;LANGUAGE=en-US:Declined: test request DTSTART:20150105T090000 DTEND:20150105T093000 UID:0123456789 CLASS:PUBLIC PRIORITY:5 TRANSP:OPAQUE STATUS:CONFIRMED SEQUENCE:0 LOCATION;LANGUAGE=en-US: END:VEVENT END:VCALENDAR EOF cat >"$MH_TEST_DIR/test1.ics" <<'EOF' BEGIN:VCALENDAR METHOD:REQUEST PRODID:test-mhical VERSION:2.0 BEGIN:VEVENT ORGANIZER;CN=Requester:MAILTO:requester@example.com ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Requestee1 :MAILTO:requestee1@example.com ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Requestee2 :MAILTO:requestee2@example.com ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Requestee3 :MAILTO:requestee3@example.com SUMMARY;LANGUAGE=en-US:test request DTSTART:20150105T090000 DTEND:20150105T093000 UID:0123456789 CLASS:PUBLIC PRIORITY:5 DTSTAMP:20150101T171600Z TRANSP:OPAQUE STATUS:CONFIRMED SEQUENCE:0 LOCATION;LANGUAGE=en-US: BEGIN:VALARM ACTION:DISPLAY DESCRIPTION:REMINDER TRIGGER;RELATED=START:-PT15M END:VALARM END:VEVENT END:VCALENDAR EOF mhical -reply decline <"$MH_TEST_DIR/test1.ics" | egrep -v '^DTSTAMP:' \ >"$MH_TEST_DIR/test1.txt" check "$expected" "$MH_TEST_DIR/test1.txt" # check response of tentative to request, and -nocontenttype start_test "response of tentative to request, and -nocontenttype" cat >"$expected" <<'EOF' BEGIN:VCALENDAR METHOD:REPLY PRODID:nmh mhical v0.1 VERSION:2.0 BEGIN:VEVENT ORGANIZER;CN=Requester:MAILTO:requester@example.com ATTENDEE;PARTSTAT=TENTATIVE;CN=Requestee2:MAILTO:requestee2@example.com SUMMARY;LANGUAGE=en-US:Tentative: test request DTSTART:20150105T090000 DTEND:20150105T093000 UID:0123456789 CLASS:PUBLIC PRIORITY:5 TRANSP:OPAQUE STATUS:CONFIRMED SEQUENCE:0 LOCATION;LANGUAGE=en-US: END:VEVENT END:VCALENDAR EOF cat >"$MH_TEST_DIR/test1.ics" <<'EOF' BEGIN:VCALENDAR METHOD:REQUEST PRODID:test-mhical VERSION:2.0 BEGIN:VEVENT ORGANIZER;CN=Requester:MAILTO:requester@example.com ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Requestee1 :MAILTO:requestee1@example.com ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Requestee2 :MAILTO:requestee2@example.com ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Requestee3 :MAILTO:requestee3@example.com SUMMARY;LANGUAGE=en-US:test request DTSTART:20150105T090000 DTEND:20150105T093000 UID:0123456789 CLASS:PUBLIC PRIORITY:5 DTSTAMP:20150101T171600Z TRANSP:OPAQUE STATUS:CONFIRMED SEQUENCE:0 LOCATION;LANGUAGE=en-US: BEGIN:VALARM ACTION:DISPLAY DESCRIPTION:REMINDER TRIGGER;RELATED=START:-PT15M END:VALARM END:VEVENT END:VCALENDAR EOF mhical -reply tentative -contenttype -nocontenttype \ -infile "$MH_TEST_DIR/test1.ics" | egrep -v '^DTSTAMP:' \ >"$MH_TEST_DIR/test1.txt" check "$expected" "$MH_TEST_DIR/test1.txt" # check cancel request, and -contenttype start_test "cancel request, and -contenttype" cat >"$expected" <<'EOF' Content-Type: text/calendar; method="CANCEL"; charset="UTF-8" BEGIN:VCALENDAR METHOD:CANCEL PRODID:nmh mhical v0.1 VERSION:2.0 BEGIN:VEVENT ORGANIZER;CN=Requestee2:MAILTO:requestee2@example.com ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Requestee1 :MAILTO:requestee1@example.com ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Requestee3 :MAILTO:requestee3@example.com SUMMARY;LANGUAGE=en-US:Cancelled:test request DTSTART:20150105T090000 DTEND:20150105T093000 UID:0123456789 CLASS:PUBLIC PRIORITY:5 TRANSP:OPAQUE STATUS:CANCELLED SEQUENCE:1 LOCATION;LANGUAGE=en-US: END:VEVENT END:VCALENDAR EOF cat >"$MH_TEST_DIR/test1.ics" <<'EOF' BEGIN:VCALENDAR METHOD:REQUEST PRODID:test-mhical VERSION:2.0 BEGIN:VEVENT ORGANIZER;CN=Requestee2:MAILTO:requestee2@example.com ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Requestee1 :MAILTO:requestee1@example.com ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE;CN=Requestee3 :MAILTO:requestee3@example.com SUMMARY;LANGUAGE=en-US:test request DTSTART:20150105T090000 DTEND:20150105T093000 UID:0123456789 CLASS:PUBLIC PRIORITY:5 DTSTAMP:20150101T171600Z TRANSP:OPAQUE STATUS:CONFIRMED SEQUENCE:0 LOCATION;LANGUAGE=en-US: BEGIN:VALARM ACTION:DISPLAY DESCRIPTION:REMINDER TRIGGER;RELATED=START:-PT15M END:VALARM END:VEVENT END:VCALENDAR EOF mhical -cancel -contenttype <"$MH_TEST_DIR/test1.ics" | egrep -v '^DTSTAMP:' \ >"$MH_TEST_DIR/test1.txt" check "$expected" "$MH_TEST_DIR/test1.txt" # Check TZID name wrapped with quotes, this used to cause a segfault. start_test "TZID name wrapped with quotes, this used to cause a segfault." cat >"$expected" <<'EOF' Method: REQUEST Summary: Quoted timezone ID At: Wed, 01 Jan 2014 00:00 To: Wed, 01 Jan 2014 01:00 EOF cat >"$MH_TEST_DIR/test1.ics" <<'EOF' BEGIN:VCALENDAR PRODID:Zimbra-Calendar-Provider VERSION:2.0 METHOD:REQUEST SUMMARY:Quoted timezone ID BEGIN:VTIMEZONE TZID:Etc/GMT BEGIN:STANDARD DTSTART:19710101T000000 TZOFFSETTO:-0000 TZOFFSETFROM:-0000 TZNAME:GMT END:STANDARD END:VTIMEZONE BEGIN:VEVENT DTSTART:20140101T000000 DTEND;TZID="Etc/GMT":20140101T010000 SEQUENCE:0 END:VEVENT END:VCALENDAR EOF TZ=UTC mhical <"$MH_TEST_DIR/test1.ics" >"$MH_TEST_DIR/test1.txt" check "$expected" "$MH_TEST_DIR/test1.txt" # Check start datetime without a time, and missing end datetime. start_test "start datetime without a time, and missing end datetime." cat >"$expected" <<'EOF' Method: PUBLISH Summary: Test datetime without time At: Wed, 30 Dec 2015 00:00 To: Wed, 30 Dec 2015 23:59 EOF cat >"$MH_TEST_DIR/test1.ics" <<'EOF' BEGIN:VCALENDAR VERSION:2.0 PRODID:icalendar-ruby CALSCALE:GREGORIAN METHOD:PUBLISH BEGIN:VEVENT DTSTAMP:20151208T204350Z UID:0123456789 DTSTART;VALUE=DATE:20151230 CLASS:PRIVATE SUMMARY:Test datetime without time BEGIN:VALARM ACTION:DISPLAY DESCRIPTION:REMINDER TRIGGER;RELATED=START:-PT15M END:VALARM END:VEVENT END:VCALENDAR EOF TZ=UTC mhical <"$MH_TEST_DIR/test1.ics" >"$MH_TEST_DIR/test1.txt" check "$expected" "$MH_TEST_DIR/test1.txt" rm -f "$MH_TEST_DIR/test1.ics" # check missing final newline start_test "missing final newline" cat >"$expected" <<'EOF' Summary: test Description: this file does not end with a newline At: Sun, 14 May 2017 13:00 +0000 To: Sun, 14 May 2017 14:00 EOF printf %s \ "BEGIN:VCALENDAR VERSION:2.0 PRODID:RevenueWell BEGIN:VEVENT DTSTAMP:20170514T122300Z DTSTART:20170514T130000Z DTEND:20170514T140000Z SUMMARY:test DESCRIPTION:this file does not end with a newline END:VEVENT END:VCALENDAR" | TZ=UTC mhical >"$actual" check "$expected" "$actual" # check invalid line folding start_test "invalid line folding" cat >"$expected" <<'EOF' Summary: test Description: this file does not end with a newline At: Sun, 14 May 2017 13:00 +0000 To: Sun, 14 May 2017 14:00 EOF cat >"$expected_err" <<'EOF' mhical: syntax error, unexpected ICAL_COMMA, expecting ICAL_COLON after " this line is not folded" EOF set +e printf %s \ "BEGIN:VCALENDAR VERSION:2.0 PRODID:-//TDP v3.0//EN BEGIN:VEVENT DTSTAMP:20170514T122300Z DTSTART:20170514T130000Z DTEND:20170514T140000Z SUMMARY:test DESCRIPTION:this file does not end with a newline and this line is not folded, END:VEVENT END:VCALENDAR" | TZ=UTC mhical >"$actual" 2>"$actual_err" set -e check "$expected" "$actual" check "$expected_err" "$actual_err" # check null input start_test "null input" check_exit '-eq 0' mhical /dev/null; then can_reformat_texthtml=1 if grep 'mhfixmsg-format-text/html.*w3m' "${mhn_defaults}" \ >/dev/null; then #### w3m uses $HOME/.w3m/, and creates it if it doesn't exist. To #### support testing with non-writeable $HOME, and to not leave #### relics from this test if it is writeable but doesn't already #### have a .w3m, and to not depend on whatever is in that if it #### does already exist, overwrite $HOME if using w3m. HOME="$MHTMPDIR"; export HOME fi else echo "$0: skipping -reformat check because no text browser was found" can_reformat_texthtml=0 fi # check -help start_test "-help" cat >"$expected" <&1 | sed '/^$/,$d' >"$actual" check "$expected" "$actual" # check -version start_test "-version" case `mhfixmsg -version` in mhfixmsg\ --*) ;; *) printf '%s: mhfixmsg -version generated unexpected output\n' "$0" >&2 failed=`expr ${failed:-0} + 1`;; esac # check that non-MIME messages aren't modified # check -outfile start_test "non-MIME messages aren't modified, and -outfile" run_test 'mhfixmsg first -outfile '"$actual" '' check "`mhpath first`" "$actual" 'keep first' # check that non-MIME messages with no bodies aren't modified # check -outfile start_test "non-MIME messages with no bodies aren't modified, and -outfile" cat >"`mhpath new`" < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: @test.nmh Subject: message with no body EOF run_test 'mhfixmsg last -outfile '"$actual" '' check "`mhpath last`" "$actual" # check -nofixcte start_test "-nofixcte" cat >"`mhpath new`" <"$expected" </dev/null run_test 'mhfixmsg' '' check "$expected" "$MH_TEST_DIR"/Mail/inbox/11 'keep first' cp "$MH_TEST_DIR"/Mail/inbox/11.original "$MH_TEST_DIR"/Mail/inbox/11 check "$MH_TEST_DIR/Mail/inbox/${sbackup}11" "$MH_TEST_DIR"/Mail/inbox/11.original # check backup with -file start_test "backup with -file" cp "$MH_TEST_DIR"/Mail/inbox/11 "$MH_TEST_DIR"/Mail/inbox/11.original folder last >/dev/null run_test 'mhfixmsg -file '"$MH_TEST_DIR"/Mail/inbox/11 '' check "$MH_TEST_DIR"/Mail/inbox/11 "$expected" 'keep first' check "$MH_TEST_DIR/Mail/inbox/${sbackup}11" "$MH_TEST_DIR"/Mail/inbox/11.original # check -file with directory start_test "-file with directory" run_test 'mhfixmsg -file /tmp' 'mhfixmsg: /tmp is a directory mhfixmsg: unable to parse message from file /tmp' # check -reformat (enabled by default): addition of text/plain part # to solitary text/html part start_test "-reformat (enabled by default): addition of text/plain part" prepare_space >"$expected" <
Need to go! Need ... to ... go!
------=_nmh-multipart-- EOF cat >"`mhpath new`" <
Need to go! Need ... to ... go!
EOF if [ $can_reformat_texthtml -eq 1 ]; then printf '%s\n' "mhfixmsg: 12, insert text/plain part mhfixmsg: 12 part 1, decode text/html; charset=\"Windows-1252\"" \ >"$expected.err" #### lynx inserts multiple blank lines, so squeeze them. run_prog mhfixmsg last -outfile - -verbose 2>"$actual.err" | \ squeeze_lines >"$actual" check "$expected" "$actual" 'ignore space' check "$expected.err" "$actual.err" else rm -f "$expected" fi # check implicit -file with absolute pathname start_test "implicit -file with absolute pathname" run_test "mhfixmsg `mhpath last` -outfile /dev/null" '' # check handling of boundary string that appears in message body start_test "handling of boundary string that appears in message body" prepare_space >"$expected" < ------=_nmh-multipart
------=_nmh-multipart-1
------=_nmh-multipart-2
------=_nmh-multipart-3-- EOF cat >"`mhpath last`" < ------=3D_nmh-multipart
------=3D_nmh-multipart-1
------=3D_nmh-multipart-2
EOF if [ $can_reformat_texthtml -eq 1 ]; then printf '%s\n' "mhfixmsg: 12, insert text/plain part mhfixmsg: 12 part 1, decode text/html; charset=\"Windows-1252\"" \ >"$expected.err" #### lynx inserts multiple blank lines, so squeeze them. run_prog mhfixmsg last -outfile - -verbose 2>"$actual.err" | \ squeeze_lines >"$actual" check "$expected" "$actual" 'ignore space' check "$expected.err" "$actual.err" else rm -f "$expected" fi # check -nodecode start_test "-nodecode" prepare_space >"$expected" <
Need to go! Need ... to ... go!
------=_nmh-multipart-- EOF cat >"$MH_TEST_DIR"/Mail/inbox/12 <
Need to go! Need ... to ... go!
EOF if [ $can_reformat_texthtml -eq 1 ]; then printf '%s\n' 'mhfixmsg: 12, insert text/plain part' >"$expected.err" #### lynx inserts multiple blank lines, so squeeze them. run_prog mhfixmsg last -nodecode -outfile - -verbose 2>"$actual.err" | \ squeeze_lines >"$actual" check "$expected" "$actual" 'ignore space' check "$expected.err" "$actual.err" else rm -f "$expected" fi # check -decodetext (enabled by default) start_test "-decodetext (enabled by default)" cat >"$expected" <"`mhpath new`" <$expected <"`mhpath new`" <"`mhpath new`" <998 characters) text start_test "for successful decode of a different part with attempted -decodetext" cat >$expected <"`mhpath new`" <998 characters) text start_test "for successful decode of a different part with -decodetext of binary" cat >$expected <long lineThis line is greater than 998 characters in length, so this part should not be decoded. This line is greater than 998 characters in length, so this part should not be decoded. This line is greater than 998 characters in length, so this part should not be decoded. This line is greater than 998 characters in length, so this part should not be decoded. This line is greater than 998 characters in length, so this part should not be decoded. This line is greater than 998 characters in length, so this part should not be decoded. This line is greater than 998 characters in length, so this part should not be decoded. This line is greater than 998 characters in length, so this part should not be decoded. This line is greater than 998 characters in length, so this part should not be decoded. This line is greater than 998 characters in length, so this part should not be decoded. This line is greater than 998 characters in length, so this part should not be decoded. ------- =_aaaaaaaaaa0-- EOF run_prog mhfixmsg -noreformat -decodetext binary last check "`mhpath last`" "$expected" # check -decodetext of binary (containing ASCII NUL) text start_test "-decodetext of binary (containing ASCII NUL) text" printf "%s\275\262=\274\000%s" "To: recipient@example.com From: sender@example.com Subject: mhfixmsg binary decode test MIME-Version: 1.0 Content-Type: multipart/mixed; boundary=\"----- =_aaaaaaaaaa0\" Content-Transfer-Encoding: binary ------- =_aaaaaaaaaa0 Content-Type: text/plain; charset=\"UTF-8\"; name=\"nul+square.txt\" Content-Transfer-Encoding: binary " " ------- =_aaaaaaaaaa0-- " >"$expected" mhfixmsg last -decodetext binary -outfile "$actual" check "$expected" "$actual" # check that -reformat succeeds when decode of binary text fails start_test "-reformat succeeds when decode of binary text fails" prepare_space >"$expected" <<'EOF' MIME-Version: 1.0 Date: Thu, 11 Apr 2013 02:47:08 -0700 To: From: Subject: body requires binary encoding Content-Type: multipart/alternative; boundary="----=_nmh-multipart" ------=_nmh-multipart Content-Type: text/plain; charset="ISO-8859-1" Content-Transfer-Encoding: 7bit Mile $0.00 Time $78.71 State Tax $5.90 Vehicle License Fee $1.84 State Txn Tax $6.00 ------=_nmh-multipart Content-Type: text/html; charset="ISO-8859-1" Content-Transfer-Encoding: quoted-printable EOF cat >"`mhpath new`" <<'EOF' MIME-Version: 1.0 Content-Type: text/html; charset="ISO-8859-1" Content-Transfer-Encoding: quoted-printable Date: Thu, 11 Apr 2013 02:47:08 -0700 To: From: Subject: body requires binary encoding   EOF if [ $can_reformat_texthtml -eq 1 ]; then #### lynx inserts multiple blank lines, so squeeze them. #### Truncate to avoid comparing the html portion because it can #### get reformatted. run_prog mhfixmsg last -outfile - | squeeze_lines | head -22 >"$actual" check "$expected" "$actual" 'ignore space' else cp -p "$MH_TEST_DIR/Mail/inbox/15" "$MH_TEST_DIR/Mail/inbox/15.backup" rm -f "$expected" fi # check -textcharset # Also checks preservation of attributes after one (charset) that is # modified. start_test "-textcharset" cat >"$expected" <"`mhpath new`" <&1 check "$expected" "$actual" else echo "$0: skipping -textcharset check because nmh was built without iconv" rm -f "$expected" fi # check -nofixboundary start_test "-nofixboundary" cat >"$expected" <"`mhpath new`" < To: Subject: mhfixmsg bad boundary test This is a multi-part message in MIME format. ------=_NextPart_000_1781A1A_01CC1147.81EBA8D4 Content-Type: text/plain The boundaries of this part don't match the header boundary. ------=_NextPart_000_1781A1A_01CC1147.81EBA8D4-- EOF cp -p "`mhpath last`" "`mhpath new`" run_test 'mhfixmsg last -nofixboundary' '' check "$MH_TEST_DIR"/Mail/inbox/18 "$MH_TEST_DIR"/Mail/inbox/19 'keep first' # check that message is not output when fed through stdin (without -outfile) start_test "message is not output when fed through stdin" run_prog mhfixmsg -file - -verbose <`mhpath last` >"$actual" 2>"$actual.err" check "$expected" "$actual" if grep "mhfixmsg: $MH_TEST_DIR/Mail/.*, fix multipart boundary" \ "$actual.err" >/dev/null; then rm -f "$actual.err" else echo "$0: test failed, output is in $actual.err." failed=`expr ${failed:-0} + 1` fi # check fixup of erroneous boundary in multipart (-fixboundary, # enabled by default) # check -verbose start_test "fixup of erroneous boundary in multipart (-fixboundary, enabled by default)" cat >"$expected" < To: Subject: mhfixmsg bad boundary test This is a multi-part message in MIME format. ------=_NextPart_000_1781A1A_01CC1147.81EBA8D4 Content-Type: text/plain The boundaries of this part don't match the header boundary. ------=_NextPart_000_1781A1A_01CC1147.81EBA8D4-- EOF run_test 'mhfixmsg last -outfile '"$actual"' -verbose' \ "mhfixmsg: 18, fix multipart boundary" check "$expected" "$actual" # check that message is not modified when -fixboundary fails start_test "message is not modified when -fixboundary fails" cat >"`mhpath new`" < To: Subject: mhfixmsg bad boundary test This is a multi-part message in MIME format. ------=_ NextPart_000_1781A1A_01CC1147.81EBA8D4 Content-Type: text/plain The boundary below doesn't match the header boundary. ------=_ NextPart_000_1781A1A_01CC1147.81EBA8D4-- EOF cp -p "`mhpath last`" "$expected" run_test "mhfixmsg last -outfile $actual" '' check "$expected" "$actual" # check that text/plain part is not added to text/html in multipart/related # when it shouldn't be start_test "text/plain part is not added to text/html in multipart/related when it shouldn't be" cat >"`mhpath new`" < HTML Content This is the real content. ------=_Part_90310_101292502.1 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Your email client does not support HTML messages ------=_Part_90310_101292502.1-- EOF cp -p "`mhpath last`" "$expected" if [ $can_reformat_texthtml -eq 1 ]; then #### lynx inserts multiple blank lines, so squeeze them. run_prog mhfixmsg last -outfile - | squeeze_lines >"$actual" check "$expected" "$actual" 'ignore space' else rm -f "$expected" fi # check that text/plain part is added to text/html in multipart/related # when it should be start_test "text/plain part is added to text/html in multipart/related when it should be" cat >"$expected" < HTML Content This is the real content. ------=_Part_90310_101292502.1-- EOF cat >"`mhpath new`" < HTML Content This is the real content. ------=_Part_90310_101292502.1-- EOF if [ $can_reformat_texthtml -eq 1 ]; then #### lynx inserts multiple blank lines, so squeeze them. run_prog mhfixmsg last -outfile - | squeeze_lines >"$actual" check "$expected" "$actual" 'ignore space' else rm -f "$expected" fi # check handling of rfc822 message type # also, checks -fixboundary start_test "handling of rfc822 message type" cat >"$expected" < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: @test.nmh Subject: message with message/rfc822 attachment MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" and some garbage before the attachment ------- =_aaaaaaaaaa0 Content-Type: message/rfc822; name="1552"; charset="us-ascii" Content-Description: 1552 Content-Disposition: attachment; filename="1552" From: Test To: Date: Thu, 28 Sep 2006 00:00:00 Message-Id: @test.nmh Subject: message/rfc822 attachment This is an RFC-822 message. ------- =_aaaaaaaaaa0-- and some garbage at the end EOF cat >"`mhpath new`" < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: @test.nmh Subject: message with message/rfc822 attachment MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =badboundary" and some garbage before the attachment ------- =_aaaaaaaaaa0 Content-Type: message/rfc822; name="1552"; charset="us-ascii" Content-Description: 1552 Content-Disposition: attachment; filename="1552" From: Test To: Date: Thu, 28 Sep 2006 00:00:00 Message-Id: @test.nmh Subject: message/rfc822 attachment This is an RFC-822 message. ------- =_aaaaaaaaaa0-- and some garbage at the end EOF run_test 'mhfixmsg last -outfile '"$actual" '' check "$expected" "$actual" # check not stripping of CRs from ASCII text context (default) start_test "not stripping of CRs from ASCII text context (default)" cat >"$expected" <"`mhpath new`" <<'EOF' MIME-Version: 1.0 From: sender@example.com To: recipient@example.com Subject: message with CR's Date: Mon, 29 Apr 2013 11:51:45 -0400 There are two CR-LF pairs at the end of this sentence. EOF run_prog mhfixmsg last -outfile "$actual" check "$expected" "$actual" # check stripping of CRs from ASCII text context start_test "stripping of CRs from ASCII text context" cat >"$expected" <"`mhpath new`" <<'EOF' MIME-Version: 1.0 From: sender@example.com To: recipient@example.com Subject: message with CR's Date: Mon, 29 Apr 2013 11:51:45 -0400 There were two CR-LF pairs at the end of this sentence. EOF run_prog mhfixmsg last -outfile "$actual" -nocrlflinebreaks check "$expected" "$actual" # check -replacetextplain start_test "-replacetextplain" prepare_space >"$expected" < eticket Yes, the text/plain part really was empty. ------=_Part_876302-- EOF cat >"`mhpath new`" <<'EOF' To: recipient@example.com From: sender@example.com Subject: mhfixmsg replacement of bad text/plain part test MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_Part_876302" ------=_Part_876302 Content-Type: text/plain; charset="iso-8859-15" Content-Transfer-Encoding: 7bit Content-Disposition: inline ------=_Part_876302 Content-Type: text/html; charset="UTF-8" Content-Disposition: inline eticket Yes, the text/plain part really was empty. ------=_Part_876302-- EOF if [ $can_reformat_texthtml -eq 1 ]; then #### lynx inserts multiple blank lines, so squeeze them. run_prog mhfixmsg last -replacetextplain -outfile - | \ squeeze_lines > "$actual" check "$expected" "$actual" 'ignore space' else rm -f "$expected" fi # check -noreplacetextplain start_test "-noreplacetextplain" cat >"$expected" < eticket Yes, the text/plain part really was empty. ------=_Part_876302-- EOF run_prog mhfixmsg last -replacetextplain -noreplacetextplain -outfile "$actual" check "$expected" "$actual" # check removal of extraneous trailing semicolon from header parameter list start_test "removal of extraneous trailing semicolon from header parameter list" cat >"$expected" <"`mhpath new`" <"$MH_TEST_DIR/Mail/rmmproc" <<'EOF' mv "$1" "$1.backup" EOF chmod a+x "${MH_TEST_DIR}/Mail/rmmproc" echo "rmmproc: ${MH_TEST_DIR}/Mail/rmmproc" >>"$MH" cp "${MH_TEST_DIR}/Mail/inbox/16" "${MH_TEST_DIR}/Mail/inbox/16.original" run_test 'mhfixmsg 16' '' check "${MH_TEST_DIR}/Mail/inbox/16.backup" \ "${MH_TEST_DIR}/Mail/inbox/16.original" # check -normmproc start_test "-normmproc" cp "${MH_TEST_DIR}/Mail/inbox/21" "${MH_TEST_DIR}/Mail/inbox/22" run_test 'mhfixmsg 21 -normmproc' check "${MH_TEST_DIR}/Mail/inbox/22" \ "${MH_TEST_DIR}/Mail/inbox/${sbackup}21" 'keep first' fi # check -rmmproc start_test "-rmmproc" run_test 'mhfixmsg 21 -rmmproc true' if test -f '${MH_TEST_DIR}/Mail/inbox/22.backup'; then echo check of mhfixmsg -rmmproc FAILED, should not have created backup file failed=`expr ${failed:-0} + 1` fi # check -fixtype start_test "-fixtype" cat >"$expected" <"`mhpath new`" <$expected < This was the text/html part. ------- =_aaaaaaaaaa0-- EOF cat >"`mhpath new`" <$expected <"`mhpath new`" <$expected <"`mhpath new`" <$expected <"`mhpath new`" <"$expected.err" <"`mhpath new`" <"$actual.err" set -e #### Expected output is identical to the input message. check "`mhpath last`" "$actual" 'keep first' check "$expected.err" "$actual.err" # check that input is passed through to output when there's a parse error # (the charset string is missing its closing quote) with -outfile, and # input from stdin. Don't check err output, because it contains the name # of a tmp file. It's similar to that of the previous check. start_test "input is passed through to output when there's a parse error" set +e run_prog mhfixmsg -file - -outfile - <`mhpath last` >"$actual" 2>/dev/null set -e #### Expected output is identical to the input message. check "`mhpath last`" "$actual" 'keep first' start_test "pass through message with relative folder path with parse error" #### Factor out leading portion of current folder path and make it relative. pwd=`pwd -P` set +e run_prog mhfixmsg +./`mhpath | sed "s%^$pwd/%%"` last -out - >"$actual" 2>/dev/null set -e folder -f +inbox >/dev/null #### Expected output is identical to the input message. check "`mhpath last`" "$actual" start_test "fix RFC 2047 encoded header parameters" #### Also, add C-T-E:8bit to the message headers. cat >"$expected" <"`mhpath new`" <"$actual" 2>/dev/null check "$expected" "$actual" # make sure there are no tmp files left over find "$MH_TEST_DIR/Mail" -name '*mhfix*' -print \ >"$actual" cat >"$expected" < "$draft" < cc: Fcc: +outbox Nmh-Attach: ${srcdir}/test/mhbuild/tiny.jpg ------ EOF run_prog mhbuild "$draft" cat > "$expected" < cc: Fcc: +outbox MIME-Version: 1.0 Content-Type: image/jpeg; name="tiny.jpg" Content-Description: tiny.jpg Content-Disposition: attachment; filename="tiny.jpg" Content-Transfer-Encoding: base64 /9g= EOF check "$draft" "$expected" # # Check out more common case, one (or more) attachments # along with message text. # cat > "$draft" < cc: Fcc: +outbox Nmh-Attach: ${srcdir}/test/mhbuild/tiny.jpg Nmh-Attach: ${srcdir}/test/mhbuild/nulls ------ This is a test EOF run_prog mhbuild "$draft" cat > "$expected" < cc: Fcc: +outbox MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" ------- =_aaaaaaaaaa0 Content-Type: text/plain; charset="us-ascii" This is a test ------- =_aaaaaaaaaa0 Content-Type: image/jpeg; name="tiny.jpg" Content-Description: tiny.jpg Content-Disposition: attachment; filename="tiny.jpg" Content-Transfer-Encoding: base64 /9g= ------- =_aaaaaaaaaa0 Content-Type: application/octet-stream; name="nulls" Content-Description: nulls Content-Disposition: attachment; filename="nulls" Content-Transfer-Encoding: base64 AAAAAAAAAAAAAAAAAAAA ------- =_aaaaaaaaaa0-- EOF check "$draft" "$expected" # # An empty Attach header # cat > "$draft" < cc: Fcc: +outbox Nmh-Attach: ------ This is a test of an empty attach header. EOF run_prog mhbuild "$draft" cat > "$expected" < cc: Fcc: +outbox MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" This is a test of an empty attach header. EOF check "$draft" "$expected" # # Check a completely empty message # cat > "$draft" < cc: Fcc: +outbox Subject: Test of an empty body EOF run_prog mhbuild "$draft" cat > "$expected" < cc: Fcc: +outbox Subject: Test of an empty body MIME-Version: 1.0 Content-Type: text/plain EOF # # Check an md5'd attachment # cat > "$draft" < cc: Fcc: +outbox Subject: Test of digested part #text/plain; name="textplain" [ - ] ${srcdir}/test/mhbuild/textplain EOF mhbuild -check "$draft" cat > "$expected" < cc: Fcc: +outbox Subject: Test of digested part MIME-Version: 1.0 Content-Type: text/plain; name="textplain"; charset="us-ascii" Content-Description: - Content-MD5: x3hNJn10cGowZv+ILUkycw== Content-Transfer-Encoding: quoted-printable This is a text/plain part. EOF check "$draft" "$expected" # # Make sure we fail if we run into a MIME-Version header # cat > "$draft" < cc: Fcc: +outbox Subject: Test of an already-MIMEified message MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" This is a preformatted MIME content test. EOF set +e run_test 'eval mhbuild "$draft"' "mhbuild: draft shouldn't contain MIME-Version: field" set -e # # Run it again using -auto # run_prog mhbuild -auto "$draft" cat > "$expected" < cc: Fcc: +outbox Subject: Test of an already-MIMEified message MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" This is a preformatted MIME content test. EOF check "$draft" "$expected" # # Make sure -dist does nothing but encode headers # cat > "$draft" < cc: Fcc: +outbox Subject: An empty dist test EOF run_prog mhbuild -dist "$draft" cat > "$expected" < cc: Fcc: +outbox Subject: An empty dist test EOF check "$draft" "$expected" # # Two parts, one attachment; make sure mixing of multiparts at different # levels works. This also tests Attach: instead of Nmh-Attach:. # cat > "$draft" < cc: Fcc: +outbox Subject: A more complete multipart test Attach: ${srcdir}/test/mhbuild/tiny.jpg -------- #begin alternative # This is some HTML tëxt. #end EOF run_prog mhbuild "$draft" cat > "$expected" < cc: Fcc: +outbox Subject: A more complete multipart test MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" Content-Transfer-Encoding: 8bit ------- =_aaaaaaaaaa0 Content-Type: multipart/alternative; boundary="----- =_aaaaaaaaaa1" Content-Transfer-Encoding: 8bit ------- =_aaaaaaaaaa1 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8bit This is some tëxt. ------- =_aaaaaaaaaa1 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: 8bit This is some HTML tëxt. ------- =_aaaaaaaaaa1-- ------- =_aaaaaaaaaa0 Content-Type: image/jpeg; name="tiny.jpg" Content-Description: tiny.jpg Content-Disposition: attachment; filename="tiny.jpg" Content-Transfer-Encoding: base64 /9g= ------- =_aaaaaaaaaa0-- EOF check "$draft" "$expected" # # One attachment, text/plain containing some binary characters, # include NUL bytes. # cat > "$draft" < cc: Fcc: +outbox Subject: Testing some binary chars -------- This is some tëxt. #text/plain; name="somebinary" [ - ] {attachment} ${srcdir}/test/mhbuild/somebinary EOF run_prog mhbuild "$draft" cat > "$expected" < cc: Fcc: +outbox Subject: Testing some binary chars MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" Content-Transfer-Encoding: 8bit ------- =_aaaaaaaaaa0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8bit This is some tëxt. ------- =_aaaaaaaaaa0 Content-Type: text/plain; name="somebinary"; charset="us-ascii" Content-Description: - Content-Disposition: attachment; filename="somebinary" Content-Transfer-Encoding: quoted-printable =46rom here on, this is only = a test, though it contains =13ome =00odd=00 bytes. ------- =_aaaaaaaaaa0-- EOF check "$draft" "$expected" # check that blank line is inserted between header and content cat > "$MH_TEST_DIR/Mail/oneline" < "$draft" < cc: Fcc: +outbox Subject: test blank line between header and content -------- #text/plain {inline} $MH_TEST_DIR/Mail/oneline #application/octet-stream {inline} $MH_TEST_DIR/Mail/oneline EOF run_prog mhbuild "$draft" cat > "$expected" < cc: Fcc: +outbox Subject: test blank line between header and content MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" ------- =_aaaaaaaaaa0 Content-Type: text/plain; charset="us-ascii" Content-Disposition: inline; filename="oneline" There needs to be a blank line before this content line. ------- =_aaaaaaaaaa0 Content-Type: application/octet-stream Content-Disposition: inline; filename="oneline" There needs to be a blank line before this content line. ------- =_aaaaaaaaaa0-- EOF check "$draft" "$expected" [ ${failed:=0} -eq 0 ] && rm -f ${backup} exit ${failed:-0} nmh-1.7.1-RC3/test/mhbuild/test-cte000755 007761 000024 00000031542 13205305705 017050 0ustar00kenhstaff000000 000000 #!/bin/sh ######################################################### # # Test the use of explicit Content-Transfer-Encoding tags # ######################################################### 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 set -e require_locale en_US.UTF-8 en_US.UTF8 en_US.utf-8 en_US.utf8 draft="$MH_TEST_DIR/$$.draft" backup="${MH_TEST_DIR}/`mhparam sbackup`$$.draft.orig" expected="$MH_TEST_DIR/$$.expected" # # Force some text to be quoted-printable # cat > "$draft" < cc: Fcc: +outbox ------ # "$expected" < cc: Fcc: +outbox MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable This is a test of a message with a sh=C3=B8rt line. EOF run_prog mhbuild "$draft" check "$draft" "$expected" # # Force some text to be base64, to test out the encoder. Try at different # line lengths to check out the padding on the routines to convert LF to # CR LF. The current implementation reads in using a 3 byte buffer, so make # sure we catch all of those cases. # cat > "$draft" < cc: Fcc: +outbox ------ # "$expected" < cc: Fcc: +outbox MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: base64 VGhpcyBpcyBhIHRlc3Qgb2YgYSBtZXNzYWdlIHdpdGggYSBzaMO4cnQgbGluZS4NCg== EOF run_prog mhbuild "$draft" check "$draft" "$expected" cat > "$draft" < cc: Fcc: +outbox ------ # "$expected" < cc: Fcc: +outbox MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: base64 VGhpcyBpcyBhIHRlc3Qgb2YgYSBtw6tzc2FnZSB3aXRoIGEgc2jDuHJ0IGxpbmUuDQo= EOF run_prog mhbuild "$draft" check "$draft" "$expected" cat > "$draft" < cc: Fcc: +outbox ------ # "$expected" < cc: Fcc: +outbox MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: base64 VGhpcyBpcyBhIHRlc3Qgb2YgYSBtw6tzc8OkZ2Ugd2l0aCBhIHNow7hydCBsaW5lLg0K EOF run_prog mhbuild "$draft" check "$draft" "$expected" cat > "$draft" < cc: Fcc: +outbox ------ # "$expected" < cc: Fcc: +outbox MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: base64 VGhpcyBpcyBhIHRlc3Qgb2YgYSBtZXNzYWdlIHdpdGggYSBzaMO4cnQgbGluZS4NClRoaXMgaXMg YSBzZWNvbmQgbGluZS4NCg== EOF run_prog mhbuild "$draft" check "$draft" "$expected" cat > "$draft" < cc: Fcc: +outbox ------ # "$expected" < cc: Fcc: +outbox MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: base64 VGhpcyBpcyBhIHRlc3Qgb2YgYSBtw6tzc2FnZSB3aXRoIGEgc2jDuHJ0IGxpbmUuDQpUaGlzIGlz IGEgc2Vjb25kIGxpbmUuDQo= EOF run_prog mhbuild "$draft" check "$draft" "$expected" cat > "$draft" < cc: Fcc: +outbox ------ # "$expected" < cc: Fcc: +outbox MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: base64 VGhpcyBpcyBhIHRlc3Qgb2YgYSBtw6tzc8OkZ2Ugd2l0aCBhIHNow7hydCBsaW5lLg0KVGhpcyBp cyBhIHNlY29uZCBsaW5lLg0K EOF run_prog mhbuild "$draft" check "$draft" "$expected" cat > "$draft" < cc: Fcc: +outbox ------ # "$expected" < cc: Fcc: +outbox MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: base64 VGhpcyBpcyBhIHRlc3Qgb2YgYSBtw6tzc8OkZ2Ugd2l0aCBhIHNow7hydCBsaW5lLg0KDQoNClRo aXMgaXMgYSBzZWNvbmQgbGluZS4NCg0KDQoNCg0K EOF run_prog mhbuild "$draft" check "$draft" "$expected" # # Test out some "long" text. By default it should end up as quoted-printable. # But if we request 8bit we should error out if the line is greater than # 998. # cat > "$draft" < cc: Fcc: +outbox ------ This is a test of a messege with a long line. This line needs to be longer than 998 to test out the encoding rules. Will that work? That's a good question; I don't know if it will or not. I am the very model of a modern Major-General, I've information vegetable, animal, and mineral, I know the kings of England, and I quote the fights historical From Marathon to Waterloo, in order categorical, I'm very well acquainted, too, with matters mathematical, I understand equations, both the simple and quadratical, About binomial theorem I'm teeming with a lot o' news, With many cheerful facts about the square of the hypotenuse. I'm very good at integral and differential calculus; I know the scientific names of beings animalculous: In short, in matters vegetable, animal, and mineral, I am the very model of a modern Major-General. I know our mythic history, King Arthur's and Sir Caradoc's; I answer hard acrostics, I've a pretty taste for paradox, I quote in elegiacs all the crimes of Heliogabalus, In conics I can floor peculiarities parabolous; I can tell undoubted Raphaels from Gerard Dows and Zoffanies, I know the croaking chorus from The Frogs of Aristophanes! Then I can hum a fugue of which I've heard the music's din afore, And whistle all the airs from that infernal nonsense Pinafore. This is a second line. EOF cat > "$expected" < cc: Fcc: +outbox MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable This is a test of a messege with a long line. This line needs to be longe= r than 998 to test out the encoding rules. Will that work? That's a good= question; I don't know if it will or not. I am the very model of a moder= n Major-General, I've information vegetable, animal, and mineral, I know t= he kings of England, and I quote the fights historical From Marathon to Wa= terloo, in order categorical, I'm very well acquainted, too, with matters = mathematical, I understand equations, both the simple and quadratical, Abo= ut binomial theorem I'm teeming with a lot o' news, With many cheerful fac= ts about the square of the hypotenuse. I'm very good at integral and diffe= rential calculus; I know the scientific names of beings animalculous: In s= hort, in matters vegetable, animal, and mineral, I am the very model of a = modern Major-General. I know our mythic history, King Arthur's and Sir Car= adoc's; I answer hard acrostics, I've a pretty taste for paradox, I quote = in elegiacs all the crimes of Heliogabalus, In conics I can floor peculiar= ities parabolous; I can tell undoubted Raphaels from Gerard Dows and Zoffa= nies, I know the croaking chorus from The Frogs of Aristophanes! Then I c= an hum a fugue of which I've heard the music's din afore, And whistle all = the airs from that infernal nonsense Pinafore. = This is a second line. EOF run_prog mhbuild "$draft" check "$draft" "$expected" cat > "$draft" < cc: Fcc: +outbox ------ This is a test of a messege with a long line. This line needs to be longer than 998 to test out the encoding rules. Will that work? That's a good question; I don't know if it will or not. I am the very model of a modern Major-General, I've information vegetable, animal, and mineral, I know the kings of England, and I quote the fights historical From Marathon to Waterloo, in order categorical, I'm very well acquainted, too, with matters mathematical, I understand equations, both the simple and quadratical, About binomial theorem I'm teeming with a lot o' news, With many cheerful facts about the square of the hypotenuse. I'm very good at integral and differential calculus; I know the scientific names of beings animalculous: In short, in matters vegetable, animal, and mineral, I am the very model of a modern Major-General. I know our mythic history, King Arthur's and Sir Caradoc's; I answer hard acrostics, I've a pretty taste for paradox, I quote in elegiacs all the crimes of Heliogabalus, In conics I can floor peculiarities parabolous; I can tell undoubted Raphaels from Gerard Dows and Zoffanies, I know the croaking chorus from The Frogs of Aristophanes! Then I can hum a fugue of which I've heard the music's din afore, And whistle all the airs from that infernal nonsense Pinafore. This is a secönd line. EOF cat > "$expected" < cc: Fcc: +outbox MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable This is a test of a messege with a long line. This line needs to be longe= r than 998 to test out the encoding rules. Will that work? That's a good= question; I don't know if it will or not. I am the very model of a moder= n Major-General, I've information vegetable, animal, and mineral, I know t= he kings of England, and I quote the fights historical From Marathon to Wa= terloo, in order categorical, I'm very well acquainted, too, with matters = mathematical, I understand equations, both the simple and quadratical, Abo= ut binomial theorem I'm teeming with a lot o' news, With many cheerful fac= ts about the square of the hypotenuse. I'm very good at integral and diffe= rential calculus; I know the scientific names of beings animalculous: In s= hort, in matters vegetable, animal, and mineral, I am the very model of a = modern Major-General. I know our mythic history, King Arthur's and Sir Car= adoc's; I answer hard acrostics, I've a pretty taste for paradox, I quote = in elegiacs all the crimes of Heliogabalus, In conics I can floor peculiar= ities parabolous; I can tell undoubted Raphaels from Gerard Dows and Zoffa= nies, I know the croaking chorus from The Frogs of Aristophanes! Then I c= an hum a fugue of which I've heard the music's din afore, And whistle all = the airs from that infernal nonsense Pinafore. = This is a sec=C3=B6nd line. EOF run_prog mhbuild "$draft" check "$draft" "$expected" cat > "$draft" < cc: Fcc: +outbox ------ #&1' 'mhbuild: Line in content exceeds maximum line limit (998)' set -e # # Check to make sure -maxunencoded does what we want. # cat > "$draft" < cc: Fcc: +outbox ------ This is the test of a lønger line than the usual limit. Assuming we set the maxunencded parameter properly, this should end up as 8bit? EOF cat > "$expected" < cc: Fcc: +outbox MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8bit This is the test of a lønger line than the usual limit. Assuming we set the maxunencded parameter properly, this should end up as 8bit? EOF run_prog mhbuild -maxunencoded 200 "$draft" check "$draft" "$expected" [ ${failed:=0} -eq 0 ] && rm -f ${backup} exit ${failed:-0} nmh-1.7.1-RC3/test/mhbuild/test-ext-params000755 007761 000024 00000012417 13205305705 020356 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test the creation of RFC 2231 encoded parameters # ###################################################### 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 require_locale en_US.UTF-8 en_US.UTF8 en_US.utf-8 en_US.utf8 draft="$MH_TEST_DIR/$$.draft" backup="${MH_TEST_DIR}/`mhparam sbackup`$$.draft.orig" expected="$MH_TEST_DIR/$$.expected" # # Try out a draft with some 8-bit encoded parameters # cat > "$draft" < cc: Fcc: +outbox ------ This is a test message #image/jpeg {attachment; filename="tïny.jpg"} ${srcdir}/test/mhbuild/tiny.jpg EOF run_prog mhbuild "$draft" cat > "$expected" < cc: Fcc: +outbox MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" ------- =_aaaaaaaaaa0 Content-Type: text/plain; charset="us-ascii" This is a test message ------- =_aaaaaaaaaa0 Content-Type: image/jpeg Content-Disposition: attachment; filename*=UTF-8''t%C3%AFny.jpg Content-Transfer-Encoding: base64 /9g= ------- =_aaaaaaaaaa0-- EOF check "$draft" "$expected" # # Try out a draft with some long parameters # cat > "$draft" < cc: Fcc: +outbox ------ This is a test message #image/jpeg {attachment; filename="This is an example of a rather long filename that is longer than would fit on a normal line.jpg"} \ ${srcdir}/test/mhbuild/tiny.jpg EOF run_prog mhbuild "$draft" cat > "$expected" < cc: Fcc: +outbox MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" ------- =_aaaaaaaaaa0 Content-Type: text/plain; charset="us-ascii" This is a test message ------- =_aaaaaaaaaa0 Content-Type: image/jpeg Content-Disposition: attachment; filename*0="This is an example of a rather long filename that is lo"; filename*1="nger than would fit on a normal line.jpg" Content-Transfer-Encoding: base64 /9g= ------- =_aaaaaaaaaa0-- EOF check "$draft" "$expected" # # Try out attach with a filename with 8-bit characters # cp "${srcdir}/test/mhbuild/tiny.jpg" "$MH_TEST_DIR/tïny.jpg" cat > "$draft" < cc: Fcc: +outbox Attach: $MH_TEST_DIR/tïny.jpg ------ This is a test message EOF run_prog mhbuild "$draft" cat > "$expected" < cc: Fcc: +outbox MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" ------- =_aaaaaaaaaa0 Content-Type: text/plain; charset="us-ascii" This is a test message ------- =_aaaaaaaaaa0 Content-Type: image/jpeg; name*=UTF-8''t%C3%AFny.jpg Content-Description: =?UTF-8?B?dMOvbnkuanBn?= Content-Disposition: attachment; filename*=UTF-8''t%C3%AFny.jpg Content-Transfer-Encoding: base64 /9g= ------- =_aaaaaaaaaa0-- EOF check "$draft" "$expected" # # Alternate version; specify a disposion, but not an explicit filename # cat > "$draft" < cc: Fcc: +outbox ------ This is a test message #image/jpeg {attachment} $MH_TEST_DIR/tïny.jpg EOF run_prog mhbuild "$draft" cat > "$expected" < cc: Fcc: +outbox MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" ------- =_aaaaaaaaaa0 Content-Type: text/plain; charset="us-ascii" This is a test message ------- =_aaaaaaaaaa0 Content-Type: image/jpeg Content-Disposition: attachment; filename*=UTF-8''t%C3%AFny.jpg Content-Transfer-Encoding: base64 /9g= ------- =_aaaaaaaaaa0-- EOF check "$draft" "$expected" # # Test to make sure things fail if we try to put 8-bit characters when the # locale is US-ASCII # cat > "$draft" < cc: Fcc: +outbox ------ This is a test message #image/jpeg {attachment} $MH_TEST_DIR/tïny.jpg EOF old_locale="$LC_ALL" LC_ALL=C; export LC_ALL set +e run_test 'eval mhbuild "$draft" 2>&1' 'mhbuild: 8-bit characters in parameter "filename", but local character set is US-ASCII' set -e LC_ALL="$old_locale"; export LC_ALL rm -f "$MH_TEST_DIR/tïny.jpg" # # Test out message/external-body decoding # cat > "$draft" < cc: Fcc: +outbox ------ This is a test message #@application/octet-stream [Test of a long URL] {attachment; \ filename=test.tar.gz} access-type=url; url="http://www.example.com/this/is/an/example/of/a/very/long/url/that-should-be-wrapped/name.tar.gz" EOF run_prog mhbuild "$draft" cat > "$expected" < cc: Fcc: +outbox MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" ------- =_aaaaaaaaaa0 Content-Type: text/plain; charset="us-ascii" This is a test message ------- =_aaaaaaaaaa0 Content-Type: message/external-body; access-type="url"; url*0="http://www.example.com/this/is/an/example/of/a/very/long/url"; url*1="/that-should-be-wrapped/name.tar.gz" Content-Type: application/octet-stream Content-ID: Content-Description: Test of a long URL Content-Disposition: attachment; filename="test.tar.gz" ------- =_aaaaaaaaaa0-- EOF sed -e 's/^Content-ID:.*/Content-ID:/' "$draft" > "${draft}.nocontentid" rm "$draft" check "${draft}.nocontentid" "$expected" [ ${failed:=0} -eq 0 ] && rm -f ${backup} exit ${failed:-0} nmh-1.7.1-RC3/test/mhbuild/test-forw000755 007761 000024 00000004237 13240377015 017255 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test forwarding messages (including RFC-934 mode). # ###################################################### 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 check_exit '-eq 1' forw - # Make a draft file forwarding two messages. mkdraft() { cat > $draft < $expected < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 1@test.nmh Subject: Testing message 1 This is message number 1 ------- =_aaaaaaaaaa0 Content-Type: message/rfc822 From: Test2 To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 2@test.nmh Subject: Testing message 2 This is message number 2 ------- =_aaaaaaaaaa0-- EOF mkdraft run_prog mhbuild $draft check $expected $draft test ${failed:-0} -eq 0 && rm "$draftorig" # check mhbuild -rfc934 cat > $expected < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 1@test.nmh Subject: Testing message 1 This is message number 1 ------- =_aaaaaaaaaa0 From: Test2 To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 2@test.nmh Subject: Testing message 2 This is message number 2 ------- =_aaaaaaaaaa0-- EOF mkdraft run_prog mhbuild -rfc934 $draft check $expected $draft test ${failed:-0} -eq 0 && rm "$draftorig" exit $failed nmh-1.7.1-RC3/test/mhbuild/test-header-encode000755 007761 000024 00000034223 13205305705 020757 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test encoding headers according to RFC 2047 # ###################################################### 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 check_exit '-eq 1' mhbuild -h testname="${MH_TEST_DIR}/$$" backupname="${MH_TEST_DIR}/`mhparam sbackup`$$" # # We're going to hardcode UTF-8 for this test. # require_locale en_US.UTF-8 en_US.UTF8 en_US.utf-8 en_US.utf8 # # Basic test of encoding a short subject # cat > "${testname}.basic.actual" < To: Somebody Subject: This is ä test This is a test EOF cat > "${testname}.basic.expected" < To: Somebody Subject: =?UTF-8?Q?This_is_=C3=A4_test?= MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" This is a test EOF run_prog mhbuild "${testname}.basic.actual" check "${testname}.basic.actual" "${testname}.basic.expected" 'keep first' # # Make sure we can undo the encoding # run_test 'eval fmttest -outsize max -format "%(decode{subject})" -message -file "${testname}.basic.actual"' 'This is ä test' rm -f "${testname}.basic.actual" # # Basic test of encoding a short subject, but with base64 # cat > "${testname}.basic.actual" < To: Somebody Subject: This is ä test This is a test EOF cat > "${testname}.basic.expected" < To: Somebody Subject: =?UTF-8?B?VGhpcyBpcyDDpCB0ZXN0?= MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" This is a test EOF run_prog mhbuild -headerencoding base64 "${testname}.basic.actual" check "${testname}.basic.actual" "${testname}.basic.expected" 'keep first' run_test 'eval fmttest -outsize max -format "%(decode{subject})" -message -file "${testname}.basic.actual"' 'This is ä test' rm -f "${testname}.basic.actual" "${backupname}.basic.actual.orig" # # Have a subject that will pick base64 as the shorter encoding # cat > "${testname}.autopick.actual" < To: Somebody Subject: This is ä tëst© This is a test EOF cat > "${testname}.autopick.expected" < To: Somebody Subject: =?UTF-8?B?VGhpcyBpcyDDpCB0w6tzdMKp?= MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" This is a test EOF run_prog mhbuild "${testname}.autopick.actual" check "${testname}.autopick.actual" "${testname}.autopick.expected" 'keep first' run_test 'eval fmttest -outsize max -format "%(decode{subject})" -message -file "${testname}.autopick.actual"' 'This is ä tëst©' rm -f "${testname}.autopick.actual" "${backupname}.autopick.actual.orig" # # Tests using longer subject lines. # cat > "${testname}.longsubject1.actual" < To: Somebody Subject: This is ä tëst of a rather long sübject line; will it overflow the line length? I sure hope thät ='s and _'s are encoded properly. Will they be? This is a test of a very long subject line. EOF cat > "${testname}.longsubject1.expected" < To: Somebody Subject: =?UTF-8?Q?This_is_=C3=A4_t=C3=ABst_of_a_rather_long_s=C3=BCbject_?= =?UTF-8?Q?line;_will_it_overflow_the_line_length=3F__I_sure_hope_?= =?UTF-8?Q?th=C3=A4t_=3D's_and_=5F's_are_encoded_properly.__Will_t?= =?UTF-8?Q?hey_be=3F?= MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" This is a test of a very long subject line. EOF run_prog mhbuild "${testname}.longsubject1.actual" check "${testname}.longsubject1.actual" "${testname}.longsubject1.expected" 'keep first' run_test 'eval fmttest -outsize max -format "%(putlit(decode(trim{subject})))" -message -file "${testname}.longsubject1.actual"' "This is ä tëst of a rather long sübject line; will it overflow the line length? I sure hope thät ='s and _'s are encoded properly. Will they be?" rm -f "${testname}.longsubject1.actual" "${backupname}.longsubject1.actual.orig" # # Test a longer line with base64 encoding # cat > "${testname}.longsubject2.actual" < To: Somebody Subject: This is ä tëst øf ä räthër løng sübjëct line; will it øvërfløw the line length? I sure hope thät ='s and "'s are encoded properly. Will they be? This is a test of a very long subject line using base64. EOF cat > "${testname}.longsubject2.expected" < To: Somebody Subject: =?UTF-8?B?VGhpcyBpcyDDpCB0w6tzdCDDuGYgw6QgcsOkdGjDq3IgbMO4bmcg?= =?UTF-8?B?c8O8YmrDq2N0IGxpbmU7IHdpbGwgaXQgw7h2w6tyZmzDuHcgdGhl?= =?UTF-8?B?IGxpbmUgbGVuZ3RoPyAgSSBzdXJlIGhvcGUgdGjDpHQgPSdzIGFu?= =?UTF-8?B?ZCAiJ3MgYXJlIGVuY29kZWQgcHJvcGVybHkuICBXaWxsIHRoZXkg?= =?UTF-8?B?YmU/?= MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" This is a test of a very long subject line using base64. EOF run_prog mhbuild "${testname}.longsubject2.actual" check "${testname}.longsubject2.actual" "${testname}.longsubject2.expected" 'keep first' run_test 'eval fmttest -outsize max -format "%(putlit(decode(trim{subject})))" -message -file "${testname}.longsubject2.actual"' "This is ä tëst øf ä räthër løng sübjëct line; will it øvërfløw the line length? I sure hope thät ='s and \"'s are encoded properly. Will they be?" rm -f "${testname}.longsubject2.actual" "${backupname}.longsubject2.actual.orig" # # Another long test, but make sure multibyte characters are not split across # RFC-2047 tokens (prohibited by the standard). Test both quoted-printable # and base64 # cat > "${testname}.longsubject3.actual" < To: Somebody Subject: This is a test of a big UTF-8 multibyte character (😉); will this work properly, or will it get truncated? 😨! Hopefully not This is another long test. EOF cat > "${testname}.longsubject3.expected" < To: Somebody Subject: =?UTF-8?Q?This_is_a_test_of_a_big_UTF-8_multibyte_character_(?= =?UTF-8?Q?=F0=9F=98=89);_will_this_work_properly,_or_will_it_get_?= =?UTF-8?Q?truncated=3F_=F0=9F=98=A8!_Hopefully_not?= MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" This is another long test. EOF run_prog mhbuild "${testname}.longsubject3.actual" check "${testname}.longsubject3.actual" "${testname}.longsubject3.expected" 'keep first' run_test 'eval fmttest -outsize max -format "%(putlit(decode(trim{subject})))" -message -file "${testname}.longsubject3.actual"' "This is a test of a big UTF-8 multibyte character (😉); will this work properly, or will it get truncated? 😨! Hopefully not" rm -f "${testname}.longsubject3.actual" "${backupname}.longsubject3.actual.orig" cat > "${testname}.longsubject4.actual" < To: Somebody Subject: This is ä tëst øf Ã¥ big ÜTF-8 (😉) mültibyte character; will this wørk prøperly, ør will it get trµná´¬ted? 😨! Hopefully nøt This is another long test. EOF cat > "${testname}.longsubject4.expected" < To: Somebody Subject: =?UTF-8?B?VGhpcyBpcyDDpCB0w6tzdCDDuGYgw6UgYmlnIMOcVEYtOCAo?= =?UTF-8?B?8J+YiSkgbcO8bHRpYnl0ZSBjaGFyYWN0ZXI7IHdpbGwgdGhpcyB3?= =?UTF-8?B?w7hyayBwcsO4cGVybHksIMO4ciB3aWxsIGl0IGdldCB0csK1bg==?= =?UTF-8?B?4bSsdGVkPyDwn5ioISBIb3BlZnVsbHkgbsO4dA==?= MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" This is another long test. EOF run_prog mhbuild "${testname}.longsubject4.actual" check "${testname}.longsubject4.actual" "${testname}.longsubject4.expected" 'keep first' run_test 'eval fmttest -outsize max -format "%(putlit(decode(trim{subject})))" -message -file "${testname}.longsubject4.actual"' "This is ä tëst øf Ã¥ big ÜTF-8 (😉) mültibyte character; will this wørk prøperly, ør will it get trµná´¬ted? 😨! Hopefully nøt" rm -f "${testname}.longsubject4.actual" "${backupname}.longsubject4.actual.orig" # # Test out some basic email address encoding # cat > "${testname}.basicemail1.actual" < To: Somebody Subject: Impørtant stuff This is important information EOF cat > "${testname}.basicemail1.expected" < To: Somebody Subject: =?UTF-8?Q?Imp=C3=B8rtant_stuff?= MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" This is important information EOF run_prog mhbuild "${testname}.basicemail1.actual" check "${testname}.basicemail1.actual" "${testname}.basicemail1.expected" 'keep first' run_test 'eval fmttest -outsize max -format "%(decode{from})" -message -file "${testname}.basicemail1.actual"' "Mr Foo Bär " run_test 'eval fmttest -outsize max -format "%(decode(friendly{from}))" -message -file "${testname}.basicemail1.actual"' "Mr Foo Bär" rm -f "${testname}.basicemail1.actual" "${backupname}.basicemail1.actual.orig" cat > "${testname}.basicemail2.actual" < Subject: Impørtant stuff This is important information EOF cat > "${testname}.basicemail2.expected" < Subject: =?UTF-8?Q?Imp=C3=B8rtant_stuff?= MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" This is important information EOF run_prog mhbuild "${testname}.basicemail2.actual" check "${testname}.basicemail2.actual" "${testname}.basicemail2.expected" 'keep first' run_test 'eval fmttest -outsize max -format "%(decode{from})" -message -file "${testname}.basicemail2.actual"' "foobar@example.com (Mr Foo Bär)" run_test 'eval fmttest -outsize max -format "%(decode(friendly{from}))" -message -file "${testname}.basicemail2.actual"' "Mr Foo Bär" rm -f "${testname}.basicemail2.actual" "${backupname}.basicemail2.actual.orig" # # Make sure the base64 encoder is tested as well # cat > "${testname}.basicemail3.actual" < To: Somebody Subject: Impørtant stuff This is important information EOF cat > "${testname}.basicemail3.expected" < To: Somebody Subject: =?UTF-8?Q?Imp=C3=B8rtant_stuff?= MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" This is important information EOF run_prog mhbuild "${testname}.basicemail3.actual" check "${testname}.basicemail3.actual" "${testname}.basicemail3.expected" 'keep first' run_test 'eval fmttest -outsize max -format "%(decode{from})" -message -file "${testname}.basicemail3.actual"' "Mr Føø Bär " run_test 'eval fmttest -outsize max -format "%(decode(friendly{from}))" -message -file "${testname}.basicemail3.actual"' "Mr Føø Bär" rm -f "${testname}.basicemail3.actual" "${backupname}.basicemail3.actual.orig" cat > "${testname}.basicemail4.actual" < Subject: Impørtant stuff This is important information EOF cat > "${testname}.basicemail4.expected" < Subject: =?UTF-8?Q?Imp=C3=B8rtant_stuff?= MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" This is important information EOF run_prog mhbuild "${testname}.basicemail4.actual" check "${testname}.basicemail4.actual" "${testname}.basicemail4.expected" 'keep first' run_test 'eval fmttest -outsize max -format "%(decode{from})" -message -file "${testname}.basicemail4.actual"' "foobar@example.com (Mr Føø Bär)" run_test 'eval fmttest -outsize max -format "%(decode(friendly{from}))" -message -file "${testname}.basicemail4.actual"' "Mr Føø Bär" rm -f "${testname}.basicemail4.actual" "${backupname}.basicemail4.actual.orig" # # A more complicated header; it includes groups, addresses that require # quoted-printable and base64, and unencoded email. # cat > "${testname}.complexemail1.actual" < To: "Mr F. One" , "Mr F. Twø" , foo list: Føø Thrëë , Foo Four , Foo Fivë ; Føø Sîx , "Mr F. Seven" cc: "The Distingµishëd F. Sëvën" Subject: Very long list This is a lot of people on this email! EOF cat > "${testname}.complexemail1.expected" < To: "Mr F. One" , =?UTF-8?Q?Mr_F=2E_Tw=C3=B8?= , foo list: =?UTF-8?Q?F=C3=B8=C3=B8_Thr=C3=AB=C3=AB?= , Foo Four , =?UTF-8?Q?Foo_Fiv=C3=AB?= ;, =?UTF-8?Q?F=C3=B8=C3=B8_S=C3=AEx?= , "Mr F. Seven" cc: =?UTF-8?B?VGhlIERpc3RpbmfCtWlzaMOrZCBGLiBTw6t2w6tu?= Subject: Very long list MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" This is a lot of people on this email! EOF run_prog mhbuild "${testname}.complexemail1.actual" check "${testname}.complexemail1.actual" "${testname}.complexemail1.expected" 'keep first' run_test 'eval fmttest -outsize max -format "%(decode{to})" -message -file "${testname}.complexemail1.actual"' "\"Mr F. One\" , Mr F. Twø , foo list: Føø Thrëë , Foo Four , Foo Fivë ;, Føø Sîx , \"Mr F. Seven\" " run_test 'eval fmttest -outsize max -format "%(decode{cc})" -message -file "${testname}.complexemail1.actual"' "The Distingµishëd F. Sëvën " rm -f "${testname}.complexemail1.actual" "${backupname}.complexemail1.actual.orig" exit ${failed:-0} nmh-1.7.1-RC3/test/mhbuild/test-mhbuild000755 007761 000024 00000001605 13205305705 017716 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Basic mhbuild tests. # ###################################################### 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/test-mhbuild$$.expected" start_test "-nodirectives" cat >"$expected" <<'EOF' Subject: test -nodirectives MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" #define line begins with # and ends with backslash-newline \ all characters should be preserved EOF cat >"`mhpath new`" <<'EOF' Subject: test -nodirectives -------- #define line begins with # and ends with backslash-newline \ all characters should be preserved EOF run_test "mhbuild -nodirectives `mhpath last`" check "`mhpath last`" "$expected" finish_test exit $failed nmh-1.7.1-RC3/test/mhbuild/test-utf8-body000755 007761 000024 00000013034 13243042053 020106 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test UTF-8 body along with an attachment # ###################################################### 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 testname="${MH_TEST_DIR}/$$" expected="$MH_TEST_DIR/$$.expected" actual="$MH_TEST_DIR/$$.actual" require_locale en_US.UTF-8 en_US.UTF8 en_US.utf-8 en_US.utf8 #### Rely on sendmail/pipe below to override default mts. mts_fakesendmail="${MHMTSCONF}-fakesendmail" cp "${MHMTSCONF}" "$mts_fakesendmail" printf 'sendmail: %s/test/fakesendmail\n' "$srcdir" >>"$mts_fakesendmail" MHMTSCONF="$mts_fakesendmail" # argument: expected output test_attachment () { run_prog send -draft -mts sendmail/pipe # fakesendmail drops the message and any cc's into this mbox. mbox="${MH_TEST_DIR}"/Mail/fakesendmail.mbox inc -silent -file "$mbox" rm -f "$mbox" # # It's hard to calculate the exact Date: header post is going to # use, so we'll just use sed to remove the actual date so we can easily # compare it against our "correct" output. And same for charset, # because mime_type() can rely on file(1) --mime-encoding. # sed -e 's/^Date:.*/Date:/' -e 's/; charset="[^;]*//' \ "`mhpath cur`" > "${testname}.actual" check "${testname}.actual" "$1" } # check that 7-bit body isn't encoded start_test "7-bit body isn't encoded" cat > "${MH_TEST_DIR}/attachment.txt" < "${MH_TEST_DIR}/Mail/draft" < To: Somebody Subject: Test Nmh-Attach: $MH_TEST_DIR/attachment.txt This is a test. EOF cat > "${testname}.expected" < To: Somebody Subject: Test MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" Date: ------- =_aaaaaaaaaa0 Content-Type: text/plain This is a test. ------- =_aaaaaaaaaa0 Content-Type: text/plain; name="attachment.txt" Content-Description: attachment.txt Content-Disposition: attachment; filename="attachment.txt" this is an attachment ------- =_aaaaaaaaaa0-- EOF test_attachment "${testname}.expected" # check that 8-bit body is encoded as quoted-printable text/plain, # even with an attachment start_test '8-bit body is encoded as quoted-printable text/plain' cat > "${MH_TEST_DIR}/Mail/draft" < To: Somebody Subject: Test Nmh-Attach: $MH_TEST_DIR/attachment.txt ¡Ay, caramba! EOF cat > "${testname}.expected" < To: Somebody Subject: Test MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" Content-Transfer-Encoding: 8bit Date: ------- =_aaaaaaaaaa0 Content-Type: text/plain Content-Transfer-Encoding: 8bit ¡Ay, caramba! ------- =_aaaaaaaaaa0 Content-Type: text/plain; name="attachment.txt" Content-Description: attachment.txt Content-Disposition: attachment; filename="attachment.txt" this is an attachment ------- =_aaaaaaaaaa0-- EOF test_attachment "${testname}.expected" # check that 8-bit attachment gets C-T-E start_test '8-bit attachment gets C-T-E' rm -f "${MH_TEST_DIR}/attachment.txt" cat > "${MH_TEST_DIR}/attachment.txt" < "${MH_TEST_DIR}/Mail/draft" < To: Somebody Subject: Test Nmh-Attach: $MH_TEST_DIR/attachment.txt EOF cat > "${testname}.expected" < To: Somebody Subject: Test MIME-Version: 1.0 Content-Type: text/plain; name="attachment.txt" Content-Description: attachment.txt Content-Disposition: attachment; filename="attachment.txt" Content-Transfer-Encoding: 8bit Date: 8-bit attachment, ¡Ay, caramba! EOF test_attachment "${testname}.expected" # check 8-bit body but make sure that the locale is set to C, which # should cause mhbuild to fail start_test '8-bit body with C locale' cat > "${MH_TEST_DIR}/Mail/draft" < To: Somebody Subject: Test Nmh-Attach: $MH_TEST_DIR/attachment.txt ¡Ay, caramba! EOF LC_ALL="C"; export LC_ALL set +e run_prog send -draft -mts sendmail/pipe > "$actual" 2>&1 set -e cat > "$expected" <> "${MH}" cat > "${testname}.expected" < To: Somebody Subject: Test MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" Content-Transfer-Encoding: 8bit Date: ------- =_aaaaaaaaaa0 Content-Type: text/plain Content-Transfer-Encoding: 8bit ¡Ay, caramba! ------- =_aaaaaaaaaa0 Content-Type: text/plain; name="attachment.txt" Content-Description: attachment.txt Content-Disposition: attachment; filename="attachment.txt" Content-Transfer-Encoding: 8bit 8-bit attachment, ¡Ay, caramba! ------- =_aaaaaaaaaa0-- EOF test_attachment "${testname}.expected" rm -f ${MHMTSCONF} "${MH_TEST_DIR}/attachment.txt" finish_test 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: nmh-1.7.1-RC3/test/mhbuild/textplain000644 007761 000024 00000000033 13205103207 017305 0ustar00kenhstaff000000 000000 This is a text/plain part. nmh-1.7.1-RC3/test/mhbuild/tiny.jpg000644 007761 000024 00000000002 12437351011 017037 0ustar00kenhstaff000000 000000 ÿØnmh-1.7.1-RC3/test/manpages/test-manpages000755 007761 000024 00000002645 13243042053 020235 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test that the manpages don't have any syntax errors # as detected by groff. # ###################################################### 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 require_prog groff cd ${MH_INST_DIR}${mandir} || exit 1 # groff will exit with zero status even if warnings # were emitted, so we have to jump through hoops to # find out if any were emitted. expected=$MH_TEST_DIR/$$.expected actual=$MH_TEST_DIR/$$.actual # There aren't any expected warnings at the moment but # this mechanism does let us add them if necessary later. rm -f "$expected" "$actual" touch "$expected" "$actual" warnings="-ww" #### If the prefix is too long, groff will report that it can't break #### the `aliasfiles' line in ali.1. length=`echo $prefix | awk '{print length($0)}'` [ $length -gt 32 ] && warnings="${warnings} -Wbreak" #### OpenBSD's mandoc spits out a lot of "unbalance .el request" warnings; #### -Wel suppresses them. groff -Tutf8 -mandoc -ww man1/ali.1 >/dev/null 2>>"$actual" if grep warning "$actual" >/dev/null; then warnings="$warnings -Wel" fi rm -f "$actual" touch "$actual" for manpage in man?/*.?; do groff -Tutf8 -mandoc $warnings "$manpage" >/dev/null 2>>"$actual" done check "$expected" "$actual" exit $failed nmh-1.7.1-RC3/test/locking/test-datalocking000755 007761 000024 00000001567 12437351011 020560 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test the locking of nmh metadata # ###################################################### 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 # # Set things up so we have a "cur" sequence # show +inbox 1 -nocheckmime -showproc cat > /dev/null # # mark read & writes sequences files, so use it to exercise the locking code # for each locking algorithm # for locktype in $supported_locks do mv -f ${MH} ${MH}.old sed -e '/^datalocking:/d' < ${MH}.old > ${MH} rm -f ${MH}.old echo "datalocking: $locktype" >> ${MH} run_prog mark 2 4 6 -sequence test -add run_test 'mark -list' 'cur: 1 test: 2 4 6' run_prog mark all -sequence test -delete done exit ${failed:-0} nmh-1.7.1-RC3/test/locking/test-spoollocking000755 007761 000024 00000002320 13205305705 020772 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test the locking of nmh spool file # ###################################################### 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 testmessage="$MH_TEST_DIR/testmessage" cat > "$testmessage" < To: Some Other User Subject: Hello, how are you? Date: Sun, 17 Dec 2006 12:13:14 -0500 This is a test; will it work? EOM # # invoke "inc" for each locking algorithm # mv -f ${MHMTSCONF} ${MHMTSCONF}.backup for locktype in $supported_locks do sed -e '/^spoollocking:/d' < ${MHMTSCONF}.backup > ${MHMTSCONF} echo "spoollocking: $locktype" >> ${MHMTSCONF} run_test "inc -notruncate -width 80 -file $testmessage" \ "Incorporating new mail into inbox... 11+ 12/17 No Such User Hello, how are you?</dev/null if [ -f $MH_TEST_DIR/Mail/context -a -f "$MH" ]; then run_prog install-mh -check else failed=`expr ${failed:-0} + 1` fi # Remove the nmh installation so that install-mh -auto can install. # And set HOME to that it installs in the test directory: # install-mh -auto does a chdir($HOME). rm -rf $MH_TEST_DIR/Mail HOME=$MH_TEST_DIR install-mh -auto >/dev/null if [ -f $MH_TEST_DIR/Mail/context -a -f "$MH" ]; then run_prog install-mh -check else failed=`expr ${failed:-0} + 1` fi exit $failed nmh-1.7.1-RC3/test/install-mh/test-version-check000755 007761 000024 00000007603 13205305705 021462 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test display of new version welcome message. This # doesn't really belong in install-mh. # ###################################################### 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 actual="${MH_TEST_DIR}/test-version-check$$.actual" context="${MH_TEST_DIR}"/Mail/context version="Version: nmh-${MH_VERSION}" cmd="${MH_TEST_DIR}/Mail/cmd" runpty="${MH_OBJ_DIR}/test/runpty" #### Run a command but don't wait for user input. We switched from script(1) #### to our own utility, runpty. Check that it makes the command look like #### it's connected to a terminal below. run_without_input() { #### Create a command to use as a shell for script. cat >"${cmd}" </dev/null || test_skip "runpty doesn't simulate tty" # Removing Version will trigger the welcome message. (setup_test # inserted it so that other tests wouldn't show it.) grep -v Version "${context}" > "${context}.NEW" mv -f "${context}.NEW" "${context}" start_test 'mhparam skips the welcome message' run_without_input mhparam path grep 'Welcome to nmh version ' "${actual}" >/dev/null && false # Make sure that version wasn't added to context. grep "^${version}$" "${MH_TEST_DIR}/Mail/context" >/dev/null && false rm "${actual}" start_test 'Welcome: disable in profile skips the welcome message' cp "${MH}" "${MH}-welcome" printf 'Welcome: disable\n' >> "${MH}-welcome" # Run the function in subshell instead of augmenting the environment # for a single command, so that the environment does not retain the # MH setting. That can happen when run under distcheck, depending # on the user's shell. (MH="${MH}-welcome"; run_without_input pick last) rm "${MH}-welcome" grep 'Welcome to nmh version ' "${actual}" >/dev/null && false # Make sure that version wasn't added to context. grep "^${version}$" "${MH_TEST_DIR}/Mail/context" >/dev/null && false rm "${actual}" start_test 'with welcome message' run_without_input pick last grep 'Welcome to nmh version ' "${actual}" >/dev/null # Make sure that version was added to context. grep "^${version}$" "${MH_TEST_DIR}/Mail/context" >/dev/null rm "${actual}" start_test 'without welcome message' # After running the previous test, this one should not have # the welcome message. run_without_input pick last grep 'Welcome to nmh version ' "${actual}" >/dev/null && false # Make sure that version is still in context. grep "^${version}$" "${MH_TEST_DIR}/Mail/context" >/dev/null rm "${actual}" start_test 'with MHCONTEXT, welcome only if older' MHCONTEXT="${MH_TEST_DIR}/Mail/context2"; export MHCONTEXT printf 'Version: nmh-1.5\n' >"${MHCONTEXT}" run_without_input pick last grep 'Welcome to nmh version ' "${actual}" >/dev/null # And make sure that version did get updated in context. grep "^${version}$" "${MHCONTEXT}" >/dev/null rm "${actual}" start_test "with MHCONTEXT doesn't welcome if newer" printf 'Version: nmh-10000.0\n' >"${MHCONTEXT}" run_without_input pick last grep 'Welcome to nmh version ' "${actual}" >/dev/null && false # And make sure that version didn't get updated in context. grep '^Version: nmh-10000.0$' "${MHCONTEXT}" >/dev/null rm "${actual}" start_test 'with MHCONTEXT but no version, no welcome and update' printf '' >"${MHCONTEXT}" run_without_input pick last grep 'Welcome to nmh version ' "${actual}" >/dev/null && false # And make sure that version did get updated in context. grep "^${version}$" "${MHCONTEXT}" >/dev/null rm "${actual}" finish_test exit ${failed} nmh-1.7.1-RC3/test/inc/deb359167.mbox000644 007761 000024 00000006374 11732520432 016643 0ustar00kenhstaff000000 000000 From KKKKKKK@KKKKKK.KKKKKKKK.KKK.KK KKK KKK 00 00:00:00 0000 KKKKKKKK: KKKK [000.00.000.000] ([000.00.000.000] KKKK=000.00.000.000) KK KKKKKK.KKKKKKKK.KKK.KK (KKKKKK KKKK 0.00 #0) KKKK KKKK (KKKKKK-KKKK KKKKKKK@KKKKK.KKK) KK 0KKK0K-0000KK-00 KKK KKKKKKKK@KKKKKKKKKKK.KKK.KK; KKK, 00 KKK 0000 00:00:00 +0000 K-KKKKK-KKKKKKK: (KKKKKK.KKKKKKKK.KKK.KK) KKKKKKK KKK: 000.00.000.000: KKKKK KKKKKK KKK KKK KKKKKK KKK 000.000.00.000.KK-KKKK.KKKK: KK KKKK KKKKKK K-KKKKK-KKKKKKK: (KKKKKK.KKKKKKKK.KKK.KK) KKKK KKKK KK KKKKKKKK-KKKKKKKKKKK (KKK-KKK.KKKKKKKK.KKK: KKKK://KKK.KKKKKKKK.KKK/KKKKK/KK?KK=000.00.000.000) K-KKKKK-KKKKKKK: (KKKKKK.KKKKKKKK.KKK.KK) KKKKKKK KKKK-KKKK: [00.00.0.00.] 000 KKKKK, KK KKKKKKK KKKK KK KKKK KKKK. (#0.0.0) KKKKKKKK: KKKK [000.00.000.000] ([000.00.000.000]) KK KKKKKK.KKKKKKKK.KKK.KK (KKKKK K0.0.0) KKKK KKKK KK KKKKK-00000-0000000-0; 00 KKK 0000 00:00:00 +0000 (KKK) KKKKKKK-KK: KKKK: KKKKKK K. KKKKKK KK: KKKKKKKK@KKKKKKKKKKK.KKK.KK KKKKKKK: KKK KKKKKKK - KKK KKKKK! KKKK: KKK, 00 KKK 0000 00:00:00 +0000 KKKK-KKKKKKK: 0.0 KKKKKKK-KKKK: KKKKKKKKK/KKKKKKKKKKK; KKKKKKKK="----=_KKKKKKKK_000_0000_0K0000KK.00K000K0" K-KKKKKKKK: 0 K-KKKKKK-KKKKKKKK: KKKKKK K-KKKKKK: KKKKKKKKK KKKKKKK KKKKKKK K0.00.0000.0000 K-KKKKKKK: KKKKKKKK KK KKKKKKKKK KKKKKKK K0.00.0000.0000 K-KKK-KKKKKKK: (KKK-KKK.KKKKKKKK.KKK) KKKK://KKK.KKKKKKKK.KKK/KKKKK/KK?KK=000.00.000.000 K-KKK-KKKKKKK: (KKK.KKKKKKK.KKK) KKKKKKK - KKK KKKK://KKK.KKKKKKK.KKK/KKKKKK.KKK?KK=000.00.000.000 KKKK KK K KKKKK-KKKK KKKKKKK KK KKKK KKKKKK. ------=_KKKKKKKK_000_0000_0K0000KK.00K000K0 KKKKKKK-KKKK: KKKK/KKKKK; KKKKKKK="KKK-0000-0" KKKKKKK-KKKKKKKK-KKKKKKKK: 0KKK KKKK KKKKKK KK KKKKK KKKKKKK - KKKKK KKKKKK KK K.K.K. KKKKKKK - KKKKKKK KK K KKKK KKK KKKK KKKKKKKKKK KKK KKKKKKK KKKKK, KKKKK KKKKKKKK, KKKKK KKKKKKK, KKKKKKK, KKKKKK KKKKKK .. KKK 00 KKKKK KKKK KKKKKK KKKKKKKKKKKKK. KKKK://000.KKK-KKK-KKKKKKK.KKK KKK KKKKKKK KKK KKK KKKK $000.00 - $000.00! ________________________________ KK KKKKKK KKKK KKKK KKKKKKKKKKK, KK KKKK ------=_KKKKKKKK_000_0000_0K0000KK.00K000K0 KKKKKKK-KKKK: KKKK/KKKK; KKKKKKK="KKK-0000-0" KKKKKKK-KKKKKKKK-KKKKKKKK: KKKKKK-KKKKKKKKK = KKKK KKKKKK KK KKKKK KKKKKKK - KKKKK KKKKKK KK K.K.K. KKKKKKK - KKKKKKK KK K KKKK KKK KKKK KKKKKKKKKK KKK KKKKKKK KKKKK, KKKKK KKKKKKKK, KKKKK KKKKKKK, KKKKKKK, KKKKKK KKKKKK .. KKK 00 KKKKK KKKK KKKKKK KKKKKKKKKKKKK. KKKK://000.KKK-KKK-KKKKKKK.KKK KKK KKKKKKK KKK KKK KKKK $000.00 - $000.00! ________________________________ KK KKKKKK KKKK KKKK KKKKKKKKKKK, KK KKKK ------=_KKKKKKKK_000_0000_0K0000KK.00K000K0-- nmh-1.7.1-RC3/test/inc/filler.txt000644 007761 000024 00000041411 11732520432 016530 0ustar00kenhstaff000000 000000 CHAPTER I. MR. SHERLOCK HOLMES. IN the year 1878 I took my degree of Doctor of Medicine of the University of London, and proceeded to Netley to go through the course prescribed for surgeons in the army. Having completed my studies there, I was duly attached to the Fifth Northumberland Fusiliers as Assistant Surgeon. The regiment was stationed in India at the time, and before I could join it, the second Afghan war had broken out. On landing at Bombay, I learned that my corps had advanced through the passes, and was already deep in the enemy's country. I followed, however, with many other officers who were in the same situation as myself, and succeeded in reaching Candahar in safety, where I found my regiment, and at once entered upon my new duties. The campaign brought honours and promotion to many, but for me it had nothing but misfortune and disaster. I was removed from my brigade and attached to the Berkshires, with whom I served at the fatal battle of Maiwand. There I was struck on the shoulder by a Jezail bullet, which shattered the bone and grazed the subclavian artery. I should have fallen into the hands of the murderous Ghazis had it not been for the devotion and courage shown by Murray, my orderly, who threw me across a pack-horse, and succeeded in bringing me safely to the British lines. Worn with pain, and weak from the prolonged hardships which I had undergone, I was removed, with a great train of wounded sufferers, to the base hospital at Peshawar. Here I rallied, and had already improved so far as to be able to walk about the wards, and even to bask a little upon the verandah, when I was struck down by enteric fever, that curse of our Indian possessions. For months my life was despaired of, and when at last I came to myself and became convalescent, I was so weak and emaciated that a medical board determined that not a day should be lost in sending me back to England. I was dispatched, accordingly, in the troopship "Orontes," and landed a month later on Portsmouth jetty, with my health irretrievably ruined, but with permission from a paternal government to spend the next nine months in attempting to improve it. I had neither kith nor kin in England, and was therefore as free as air--or as free as an income of eleven shillings and sixpence a day will permit a man to be. Under such circumstances, I naturally gravitated to London, that great cesspool into which all the loungers and idlers of the Empire are irresistibly drained. There I stayed for some time at a private hotel in the Strand, leading a comfortless, meaningless existence, and spending such money as I had, considerably more freely than I ought. So alarming did the state of my finances become, that I soon realized that I must either leave the metropolis and rusticate somewhere in the country, or that I must make a complete alteration in my style of living. Choosing the latter alternative, I began by making up my mind to leave the hotel, and to take up my quarters in some less pretentious and less expensive domicile. On the very day that I had come to this conclusion, I was standing at the Criterion Bar, when some one tapped me on the shoulder, and turning round I recognized young Stamford, who had been a dresser under me at Barts. The sight of a friendly face in the great wilderness of London is a pleasant thing indeed to a lonely man. In old days Stamford had never been a particular crony of mine, but now I hailed him with enthusiasm, and he, in his turn, appeared to be delighted to see me. In the exuberance of my joy, I asked him to lunch with me at the Holborn, and we started off together in a hansom. "Whatever have you been doing with yourself, Watson?" he asked in undisguised wonder, as we rattled through the crowded London streets. "You are as thin as a lath and as brown as a nut." I gave him a short sketch of my adventures, and had hardly concluded it by the time that we reached our destination. "Poor devil!" he said, commiseratingly, after he had listened to my misfortunes. "What are you up to now?" "Looking for lodgings." [3] I answered. "Trying to solve the problem as to whether it is possible to get comfortable rooms at a reasonable price." "That's a strange thing," remarked my companion; "you are the second man to-day that has used that expression to me." "And who was the first?" I asked. "A fellow who is working at the chemical laboratory up at the hospital. He was bemoaning himself this morning because he could not get someone to go halves with him in some nice rooms which he had found, and which were too much for his purse." "By Jove!" I cried, "if he really wants someone to share the rooms and the expense, I am the very man for him. I should prefer having a partner to being alone." Young Stamford looked rather strangely at me over his wine-glass. "You don't know Sherlock Holmes yet," he said; "perhaps you would not care for him as a constant companion." "Why, what is there against him?" "Oh, I didn't say there was anything against him. He is a little queer in his ideas--an enthusiast in some branches of science. As far as I know he is a decent fellow enough." "A medical student, I suppose?" said I. "No--I have no idea what he intends to go in for. I believe he is well up in anatomy, and he is a first-class chemist; but, as far as I know, he has never taken out any systematic medical classes. His studies are very desultory and eccentric, but he has amassed a lot of out-of-the way knowledge which would astonish his professors." "Did you never ask him what he was going in for?" I asked. "No; he is not a man that it is easy to draw out, though he can be communicative enough when the fancy seizes him." "I should like to meet him," I said. "If I am to lodge with anyone, I should prefer a man of studious and quiet habits. I am not strong enough yet to stand much noise or excitement. I had enough of both in Afghanistan to last me for the remainder of my natural existence. How could I meet this friend of yours?" "He is sure to be at the laboratory," returned my companion. "He either avoids the place for weeks, or else he works there from morning to night. If you like, we shall drive round together after luncheon." "Certainly," I answered, and the conversation drifted away into other channels. As we made our way to the hospital after leaving the Holborn, Stamford gave me a few more particulars about the gentleman whom I proposed to take as a fellow-lodger. "You mustn't blame me if you don't get on with him," he said; "I know nothing more of him than I have learned from meeting him occasionally in the laboratory. You proposed this arrangement, so you must not hold me responsible." "If we don't get on it will be easy to part company," I answered. "It seems to me, Stamford," I added, looking hard at my companion, "that you have some reason for washing your hands of the matter. Is this fellow's temper so formidable, or what is it? Don't be mealy-mouthed about it." "It is not easy to express the inexpressible," he answered with a laugh. "Holmes is a little too scientific for my tastes--it approaches to cold-bloodedness. I could imagine his giving a friend a little pinch of the latest vegetable alkaloid, not out of malevolence, you understand, but simply out of a spirit of inquiry in order to have an accurate idea of the effects. To do him justice, I think that he would take it himself with the same readiness. He appears to have a passion for definite and exact knowledge." "Very right too." "Yes, but it may be pushed to excess. When it comes to beating the subjects in the dissecting-rooms with a stick, it is certainly taking rather a bizarre shape." "Beating the subjects!" "Yes, to verify how far bruises may be produced after death. I saw him at it with my own eyes." "And yet you say he is not a medical student?" "No. Heaven knows what the objects of his studies are. But here we are, and you must form your own impressions about him." As he spoke, we turned down a narrow lane and passed through a small side-door, which opened into a wing of the great hospital. It was familiar ground to me, and I needed no guiding as we ascended the bleak stone staircase and made our way down the long corridor with its vista of whitewashed wall and dun-coloured doors. Near the further end a low arched passage branched away from it and led to the chemical laboratory. This was a lofty chamber, lined and littered with countless bottles. Broad, low tables were scattered about, which bristled with retorts, test-tubes, and little Bunsen lamps, with their blue flickering flames. There was only one student in the room, who was bending over a distant table absorbed in his work. At the sound of our steps he glanced round and sprang to his feet with a cry of pleasure. "I've found it! I've found it," he shouted to my companion, running towards us with a test-tube in his hand. "I have found a re-agent which is precipitated by hoemoglobin, [4] and by nothing else." Had he discovered a gold mine, greater delight could not have shone upon his features. "Dr. Watson, Mr. Sherlock Holmes," said Stamford, introducing us. "How are you?" he said cordially, gripping my hand with a strength for which I should hardly have given him credit. "You have been in Afghanistan, I perceive." "How on earth did you know that?" I asked in astonishment. "Never mind," said he, chuckling to himself. "The question now is about hoemoglobin. No doubt you see the significance of this discovery of mine?" "It is interesting, chemically, no doubt," I answered, "but practically----" "Why, man, it is the most practical medico-legal discovery for years. Don't you see that it gives us an infallible test for blood stains. Come over here now!" He seized me by the coat-sleeve in his eagerness, and drew me over to the table at which he had been working. "Let us have some fresh blood," he said, digging a long bodkin into his finger, and drawing off the resulting drop of blood in a chemical pipette. "Now, I add this small quantity of blood to a litre of water. You perceive that the resulting mixture has the appearance of pure water. The proportion of blood cannot be more than one in a million. I have no doubt, however, that we shall be able to obtain the characteristic reaction." As he spoke, he threw into the vessel a few white crystals, and then added some drops of a transparent fluid. In an instant the contents assumed a dull mahogany colour, and a brownish dust was precipitated to the bottom of the glass jar. "Ha! ha!" he cried, clapping his hands, and looking as delighted as a child with a new toy. "What do you think of that?" "It seems to be a very delicate test," I remarked. "Beautiful! beautiful! The old Guiacum test was very clumsy and uncertain. So is the microscopic examination for blood corpuscles. The latter is valueless if the stains are a few hours old. Now, this appears to act as well whether the blood is old or new. Had this test been invented, there are hundreds of men now walking the earth who would long ago have paid the penalty of their crimes." "Indeed!" I murmured. "Criminal cases are continually hinging upon that one point. A man is suspected of a crime months perhaps after it has been committed. His linen or clothes are examined, and brownish stains discovered upon them. Are they blood stains, or mud stains, or rust stains, or fruit stains, or what are they? That is a question which has puzzled many an expert, and why? Because there was no reliable test. Now we have the Sherlock Holmes' test, and there will no longer be any difficulty." His eyes fairly glittered as he spoke, and he put his hand over his heart and bowed as if to some applauding crowd conjured up by his imagination. "You are to be congratulated," I remarked, considerably surprised at his enthusiasm. "There was the case of Von Bischoff at Frankfort last year. He would certainly have been hung had this test been in existence. Then there was Mason of Bradford, and the notorious Muller, and Lefevre of Montpellier, and Samson of new Orleans. I could name a score of cases in which it would have been decisive." "You seem to be a walking calendar of crime," said Stamford with a laugh. "You might start a paper on those lines. Call it the 'Police News of the Past.'" "Very interesting reading it might be made, too," remarked Sherlock Holmes, sticking a small piece of plaster over the prick on his finger. "I have to be careful," he continued, turning to me with a smile, "for I dabble with poisons a good deal." He held out his hand as he spoke, and I noticed that it was all mottled over with similar pieces of plaster, and discoloured with strong acids. "We came here on business," said Stamford, sitting down on a high three-legged stool, and pushing another one in my direction with his foot. "My friend here wants to take diggings, and as you were complaining that you could get no one to go halves with you, I thought that I had better bring you together." Sherlock Holmes seemed delighted at the idea of sharing his rooms with me. "I have my eye on a suite in Baker Street," he said, "which would suit us down to the ground. You don't mind the smell of strong tobacco, I hope?" "I always smoke 'ship's' myself," I answered. "That's good enough. I generally have chemicals about, and occasionally do experiments. Would that annoy you?" "By no means." "Let me see--what are my other shortcomings. I get in the dumps at times, and don't open my mouth for days on end. You must not think I am sulky when I do that. Just let me alone, and I'll soon be right. What have you to confess now? It's just as well for two fellows to know the worst of one another before they begin to live together." I laughed at this cross-examination. "I keep a bull pup," I said, "and I object to rows because my nerves are shaken, and I get up at all sorts of ungodly hours, and I am extremely lazy. I have another set of vices when I'm well, but those are the principal ones at present." "Do you include violin-playing in your category of rows?" he asked, anxiously. "It depends on the player," I answered. "A well-played violin is a treat for the gods--a badly-played one----" "Oh, that's all right," he cried, with a merry laugh. "I think we may consider the thing as settled--that is, if the rooms are agreeable to you." "When shall we see them?" "Call for me here at noon to-morrow, and we'll go together and settle everything," he answered. "All right--noon exactly," said I, shaking his hand. We left him working among his chemicals, and we walked together towards my hotel. "By the way," I asked suddenly, stopping and turning upon Stamford, "how the deuce did he know that I had come from Afghanistan?" My companion smiled an enigmatical smile. "That's just his little peculiarity," he said. "A good many people have wanted to know how he finds things out." "Oh! a mystery is it?" I cried, rubbing my hands. "This is very piquant. I am much obliged to you for bringing us together. 'The proper study of mankind is man,' you know." "You must study him, then," Stamford said, as he bade me good-bye. "You'll find him a knotty problem, though. I'll wager he learns more about you than you about him. Good-bye." "Good-bye," I answered, and strolled on to my hotel, considerably interested in my new acquaintance. CHAPTER II. THE SCIENCE OF DEDUCTION. WE met next day as he had arranged, and inspected the rooms at No. 221B, Baker Street, of which he had spoken at our meeting. They consisted of a couple of comfortable bed-rooms and a single large airy sitting-room, cheerfully furnished, and illuminated by two broad windows. So desirable in every way were the apartments, and so moderate did the terms seem when divided between us, that the bargain was concluded upon the spot, and we at once entered into possession. That very evening I moved my things round from the hotel, and on the following morning Sherlock Holmes followed me with several boxes and portmanteaus. For a day or two we were busily employed in unpacking and laying out our property to the best advantage. That done, we gradually began to settle down and to accommodate ourselves to our new surroundings. Holmes was certainly not a difficult man to live with. He was quiet in his ways, and his habits were regular. It was rare for him to be up after ten at night, and he had invariably breakfasted and gone out before I rose in the morning. Sometimes he spent his day at the chemical laboratory, sometimes in the dissecting-rooms, and occasionally in long walks, which appeared to take him into the lowest portions of the City. Nothing could exceed his energy when the working fit was upon him; but now and again a reaction would seize him, and for days on end he would lie upon the sofa in the sitting-room, hardly uttering a word or moving a muscle from morning to night. On these occasions I have noticed such a dreamy, vacant expression in his eyes, that I might have suspected him of being addicted to the use of some narcotic, had not the temperance and cleanliness of his whole life forbidden such a notion. nmh-1.7.1-RC3/test/inc/fromline.txt000644 007761 000024 00000000063 11732520432 017064 0ustar00kenhstaff000000 000000 From pm215@archaic.org.uk Fri Dec 26 15:03:52 2008 nmh-1.7.1-RC3/test/inc/md5sums000644 007761 000024 00000000214 12076271023 016027 0ustar00kenhstaff000000 000000 4112b1460e11bd94d30944dd464a6662 filler.txt 023aad60eab43f06cf525869a833beb4 fromline.txt 4fda7f16b29d757413cb928d6ffc5aa5 msgheader.txt nmh-1.7.1-RC3/test/inc/msgheader.txt000644 007761 000024 00000000171 11732520432 017210 0ustar00kenhstaff000000 000000 From: Test To: Some User Date: Fri, 29 Sep 2006 00:00:00 Subject: Testing message nmh-1.7.1-RC3/test/inc/test-deb359167000755 007761 000024 00000001715 13205305704 016651 0ustar00kenhstaff000000 000000 #!/bin/sh # Test a variant of a mailbox which caused debian bug 359167. 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 # valgrind throws a strange error on FreeBSD >= 10; skip the test # for now while we try to track down the underlying cause. if [ `uname -s` = 'FreeBSD' ]; then case `uname -r` in 1?.*) test_skip 'valgrind fails on FreeBSD >= 10' ;; esac fi require_prog valgrind THISDIR="$srcdir/test/inc" TESTMBOX="$THISDIR/deb359167.mbox" if [ "`output_md5 "$TESTMBOX"`" != "e6ac458b8cccba2b2fd866fb505aeb5e" ]; then echo "Test mailbox has been corrupted" exit 1 fi # # valgrind refuses to run on a setuid/setgid program, so chmod inc so it # isn't (just in case) # chmod 755 ${MH_INST_DIR}${bindir}/inc valgrind --error-exitcode=1 --quiet --suppressions="${srcdir}/test/valgrind.supp" inc -silent -file "$TESTMBOX" nmh-1.7.1-RC3/test/inc/test-eom-align000755 007761 000024 00000011465 13243042053 017270 0ustar00kenhstaff000000 000000 #!/bin/sh # Test all combinations of alignment of the end-of-message delimiter # with the end of a stdio buffer 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 THISDIR="$srcdir/test/inc" if [ -z "$VALGRIND_ME" ]; then VALGRIND= else require_prog valgrind # Lack of quotes here is important VALGRIND="valgrind --quiet --error-exitcode=1" echo "Running tests under valgrind: takes ages!" fi # First check that all our various pieces of text are # intact. (Since we're dealing in exact byte alignment # minor corruptions such as line ending changes could # render the tests useless.) (cd "$THISDIR" && \ for i in *.txt; do echo `output_md5 $i`' '"$i" >> "$MH_TEST_DIR/inctest.md5sums" done) check "$THISDIR/md5sums" "$MH_TEST_DIR/inctest.md5sums" 'keep first' FILLER="$THISDIR/filler.txt" FROMLINE="$THISDIR/fromline.txt" HDR="$THISDIR/msgheader.txt" if grep From "$FILLER" >/dev/null; then echo "Somebody's messed with $FILLER -- it must not contain" echo "anything that might look like a message delimiter!" exit 1 fi # a sort of worst-case guess for the buffer size; # obviously a buffer boundary for this will be a boundary # for any smaller power of two size. # If you need to increase this you'll need to make filler.txt # bigger as well. STDIO_BUFSZ=16384 FROMLINESZ=`wc -c < "$FROMLINE"` HDRSZ=`wc -c < "$HDR"` # makembox_A mboxname sz # Assemble a mailbox into file mboxname, with two messages, such # that the first is exactly sz bytes long (including its header # and its initial 'From' line and the newline which terminates it # but not the newline which mbox format demands after each message) # We also leave the body of message one in mboxname.body # (the body of message two is always $FILLER in its entirety) makembox_A () { MBOX="$1" SZ=$2 arith_eval $SZ - $HDRSZ - $FROMLINESZ - 1; WANTSZ=$arith_val dd if="$FILLER" of="$MBOX.body" bs="$WANTSZ" count=1 2>/dev/null echo >> "$MBOX.body" cat "$FROMLINE" "$HDR" "$MBOX.body" > "$MBOX" echo >> "$MBOX" cat "$FROMLINE" "$HDR" "$FILLER" >> "$MBOX" echo >> "$MBOX" } # make_mbox_B mboxname sz # Test B makes a mailbox with one message of sz bytes long, # which ends in a partial mbox delimiter (ie part of the string # \n\nFrom '). To both do this and be a valid mbox this means # it has to end with two newlines (one of which is in the message # body and one of which is the mbox format mandated one) makembox_B () { MBOX="$1" SZ=$2 arith_eval $SZ - $HDRSZ - $FROMLINESZ - 1; WANTSZ=$arith_val dd if="$FILLER" of="$MBOX.body" bs="$WANTSZ" count=1 2>/dev/null echo >> "$MBOX.body" cat "$FROMLINE" "$HDR" "$MBOX.body" > "$MBOX" echo >> "$MBOX" } # do_one_test_A sz # Do a single test with message one's body of size sz. do_one_test_A () { SZ=$1 printf '%5s A\r' $SZ makembox_A "$MH_TEST_DIR/eom-align.mbox" $SZ $VALGRIND inc -silent -file "$MH_TEST_DIR/eom-align.mbox" # We know the messages should be 11 and 12 in inbox # Now get the bodies back out. body1="$MH_TEST_DIR/eom-align.inbox.body1" body2="$MH_TEST_DIR/eom-align.inbox.body2" sed -e '1,/^$/d' "$MH_TEST_DIR/Mail/inbox/11" > "$body1" sed -e '1,/^$/d' "$MH_TEST_DIR/Mail/inbox/12" > "$body2" check "$MH_TEST_DIR/eom-align.mbox.body" "$body1" 'keep first' check "$FILLER" "$body2" 'keep first' rmm 11 12 } # do_one_test_B sz # Do a test type B do_one_test_B () { SZ=$1 printf '%5s B\r' $SZ makembox_B "$MH_TEST_DIR/eom-align.mbox" $SZ $VALGRIND inc -silent -file "$MH_TEST_DIR/eom-align.mbox" # We know the message should be 11 in the inbox body1="$MH_TEST_DIR/eom-align.inbox.body1" sed -e '1,/^$/d' "$MH_TEST_DIR/Mail/inbox/11" > "$body1" check "$MH_TEST_DIR/eom-align.mbox.body" "$body1" 'keep first' rmm 11 } # Cover a decent range around the stdio buffer size to make sure we catch # any corner cases whether they relate to total message size equal to # buffer size or to body size equal to buffer size. arith_eval $STDIO_BUFSZ - 16; START=$arith_val arith_eval $STDIO_BUFSZ + $HDRSZ + $FROMLINESZ + 32; FINISH=$arith_val [ -t 1 ] && echo \ "Testing inc of files with various alignments of eom marker with buffer size..." #### Trouble spots for the particular input, with BUFSZ of 8192: for sz in 3146 3147 7241 7242 7243 11338 11339 15433 15434 15435; do do_one_test_A $sz done # Also 155, 174, 175, but they're too small for makembox_B to handle. for sz in 684 4074 4097 4148 4610 4611 5121 5122 6654 6655 8170 \ 8193 8244 8364 12266 12289 12340 16362 16385 16436; do do_one_test_B $sz done i="$START" while test $i -le $FINISH; do do_one_test_A $i do_one_test_B $i i=`expr $i + 1` done printf '\n' test ${failed:-0} -eq 0 && \ rm "$MH_TEST_DIR/eom-align.mbox" "$MH_TEST_DIR/eom-align.mbox.body" exit $failed nmh-1.7.1-RC3/test/inc/test-inc-scanout000755 007761 000024 00000062056 13205305705 017651 0ustar00kenhstaff000000 000000 #!/bin/sh # # Check to see if the scan output is correct if we have a message # right on the stdio buffer boundary # 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 thisdir="$srcdir/test/inc" expected="$MH_TEST_DIR/$$.expected" actual="$MH_TEST_DIR/$$.actual" cat > "${MH_TEST_DIR}/test.mbox" < To: Another Nobody Date: Thu, 1 Mar 2012 01:02:03 -0500 Subject: Who is on first? Abbott: Every dollar of it. And why not, the man's entitled to it. Costello: Who is? Abbott: Yes. Costello: So who gets it? Abbott: Why shouldn't he? Sometimes his wife comes down and collects it. Costello: Who's wife? Abbott: Yes. After all, the man earns it. Costello: Who does? Abbott: Absolutely. Costello: Well, all I'm trying to find out is what's the guy's name on first base? Abbott: Oh, no, no. What is on second base. Costello: I'm not asking you who's on second. Abbott: Who's on first! EOF cat > "${MH_TEST_DIR}/test.mbox.2" < To: Another Nobody Date: Thu, 1 Mar 2012 01:02:03 -0500 Subject: Who is on first? Abbott: Every dollar of it. And why not, the man's entitled to it. Costello: Who is? Abbott: Yes. Costello: So who gets it? Abbott: Why shouldn't he? Sometimes his wife comes down and collects it. Costello: Who's wife? Abbott: Yes. After all, the man earns it. Costello: Who does? Abbott: Absolutely. Costello: Well, all I'm trying to find out is what's the guy's name on first base? Abbott: Oh, no, no. What is on second base. Costello: I'm not asking you who's on second. Abbott: Who's on first! EOF run_test "inc -file ${MH_TEST_DIR}/test.mbox -width 120 -truncate" \ "Incorporating new mail into inbox... 11+ 03/01 Mr Nobody Who is on first?<"$MH_TEST_DIR/mess" < To: Some Other User 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` <"$MH_TEST_DIR/mess" < To: Some Other User 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 inc of message with header field body with more than 511 characters cat >"$expected" < To: Some Other User Subject: FLDPLUS test Date: Wed, 16 Jan 2013 20:33:58 -0600 EOF cat >"$MH_TEST_DIR/mess" < To: Some Other User Subject: FLDPLUS test Date: Wed, 16 Jan 2013 20:33:58 -0600 EOF run_prog inc -file "$MH_TEST_DIR/mess" >/dev/null check "$expected" `mhpath last` || rmm last 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<> 2 09/29 Test2 Testing message 2<> 3 09/29 Test3 Testing message 3<> 4 09/29 Test4 Testing message 4<> 5 09/29 Test5 Testing message 5<> 6 09/29 Test6 Testing message 6<> 7 09/29 Test7 Testing message 7<> 8 09/29 Test8 Testing message 8<> 9 09/29 Test9 Testing message 9<> 10 09/29 Test10 Testing message 10<> 11 03/01 Mr Nobody Who is on first?<> 14 09/29 Test2 Testing message 2<> 15 09/29 Test3 Testing message 3<> 16 09/29 Test4 Testing message 4<> 17 09/29 Test5 Testing message 5<> 18 09/29 Test6 Testing message 6<> 19 09/29 Test7 Testing message 7<> 20 09/29 Test8 Testing message 8<> 21 09/29 Test9 Testing message 9<> 22 09/29 Test10 Testing message 10<> 23 03/01 Mr Nobody Who is on first?<>"$MH_TEST_DIR/msgbox" <>' rm -f "$MH_TEST_DIR/msgbox" # check inc (m_getfld, actually) of very, very, very short message cat >>"$MH_TEST_DIR/msgbox" <>' rm -f "$MH_TEST_DIR/msgbox" # check inc (m_getfld, actually) of very, very short message cat >>"$MH_TEST_DIR/msgbox" <>' rm -f "$MH_TEST_DIR/msgbox" # check inc (m_getfld, actually) of very short message cat >>"$MH_TEST_DIR/msgbox" <>' rm -f "$MH_TEST_DIR/msgbox" # check inc (m_getfld, actually) of short message cat >>"$MH_TEST_DIR/msgbox" <>' rm -f "$MH_TEST_DIR/msgbox" exit ${failed:-0} nmh-1.7.1-RC3/test/inc/test-msgchk000755 007761 000024 00000006424 13240377167 016711 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test msgchk # Only tests checking of local maildrop, does not # test checking of POP server. # ###################################################### 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 check_exit '-eq 1' msgchk - expected=$MH_TEST_DIR/$$.expected expected_err=$MH_TEST_DIR/$$.expected_err actual=$MH_TEST_DIR/$$.actual actual_err=$MH_TEST_DIR/$$.actual_err # check -help # Only look at first 9 lines because the rest depend on # whether sasl support was configured in. cat >"$expected" <&1 | head -9 >"$actual" check "$expected" "$actual" # check -version case `msgchk -v` in msgchk\ --*) ;; * ) printf '%s: msgchk -v generated unexpected output\n' "$0" >&2 failed=`expr ${failed:-0} + 1`;; esac # check unknown switch run_test "msgchk -nonexistent" 'msgchk: -nonexistent unknown' # check with no arguments and no mail waiting run_test 'msgchk' "You don't have any mail waiting" # Use maildrop specified in mts.conf, i.e., # ${MH_TEST_DIR}/Mail/maildrop, which should not yet exist. "${MH_LIBEXEC_DIR}"/rcvpack <"${MH_TEST_DIR}"/Mail/inbox/1 \ "${MH_TEST_DIR}"/Mail/maildrop # check with no arguments and mail waiting cat >"$expected" <"$actual" check "$expected" "$actual" # check -date cat >"$expected" <"$actual" check "$expected" "$actual" # check -nodate run_test 'msgchk -nodate' 'You have new mail waiting' # check -notify mail, when there is mail run_test 'msgchk -notify mail -nodate' 'You have new mail waiting' # check -notify nomail, when there is mail run_test 'msgchk -notify nomail -nodate' 'You have new mail waiting' # check -notify all, when there is mail run_test 'msgchk -notify nomail -notify all -nodate' 'You have new mail waiting' # check -nonotify mail, when there is mail run_test 'msgchk -nonotify mail -nodate' '' # check -nonotify nomail, when there is mail run_test 'msgchk -nonotify nomail -nodate' 'You have new mail waiting' # check -nonotify all, when there is mail run_test 'msgchk -nonotify nomail -nonotify all -nodate' '' run_prog inc -silent # check -notify mail, when there is no mail run_test 'msgchk -notify mail -nodate' "You don't have any mail waiting" # check -notify nomail, when there is no mail run_test 'msgchk -notify nomail -nodate' "You don't have any mail waiting" # check -notify all, when there is no mail run_test 'msgchk -notify nomail -nonotify all -nodate' '' # check -nonotify mail, when there is no mail run_test 'msgchk -nonotify mail -nodate' "You don't have any mail waiting" # check -nonotify nomail, when there is no mail run_test 'msgchk -nonotify nomail -nodate' '' # check -nonotify all, when there is no mail run_test 'msgchk -nonotify nomail -nonotify all -nodate' '' exit ${failed:-0} nmh-1.7.1-RC3/test/inc/test-pop000755 007761 000024 00000007111 13205305705 016213 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test POP support in inc # Only tests checking of local maildrop, does not # test checking of POP server. # ###################################################### 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 # # Some extra stuff we need for POP support # TESTUSER=testuser TESTPASS=testuserpass arith_eval 64001 + $$ % 1000 testport=$arith_val HOME="${MH_TEST_DIR}"; export HOME 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 actual=$MH_TEST_DIR/$$.actual actual_err=$MH_TEST_DIR/$$.actual_err testmessage=$MH_TEST_DIR/testmessage cat > "$testmessage" < To: Some Other User Subject: Hello Date: Sun, 17 Dec 2006 12:13:14 -0500 Hey man, how's it going? . Hope you're doing better. EOM cat > "${testmessage}.2" < To: Some Other User Subject: Anything new? Date: Monday, 18 Dec 2006 14:13:14 -0500 What's been happening at your place? EOM cat > "${testmessage}.3" < To: Some Other User Subject: Brutal Date: Tuesday, 19 Dec 2006 4:15:16 -0500 Dude, nmh is totally brutal. EOM # Check netrc's permissions test pid=`"${MH_OBJ_DIR}/test/fakepop" "$testport" '' '' "$testmessage"` chmod g=w,o=x $netrc run_test "inc -user ${TESTUSER} -host 127.0.0.1 -port $testport" \ "inc: group or other permissions, 0100621, forbidden: $netrc inc: Remove password or correct file permissions." chmod go= $netrc pid=`"${MH_OBJ_DIR}/test/fakepop" "$testport" \ "$TESTUSER" "$TESTPASS" "$testmessage"` run_test "inc -user ${TESTUSER} -host 127.0.0.1 -port $testport -width 80" \ "Incorporating new mail into inbox... 11+ 12/17 No Such User Hello<>" check "$testmessage" `mhpath +inbox 11` 'keep first' check "${testmessage}.2" `mhpath +inbox 12` check "${testmessage}.3" `mhpath +inbox 13` rm -f "$netrc" # check credentials: file # Redirect stdin so that inc doesn't wait on the user if it can't # read the netrc file, even though that shouldn't happen. TESTUSER=differenuser TESTPASS=differentpass netrc="${HOME}/.mhnetrc" echo "default login ${TESTUSER} password ${TESTPASS}" > "$netrc" chmod 600 "$netrc" echo "credentials: file:${netrc}" >>$MH pid=`"${MH_OBJ_DIR}/test/fakepop" "$testport" \ "$TESTUSER" "$TESTPASS" "$testmessage"` run_test "inc -user ${TESTUSER} -host 127.0.0.1 -port $testport -width 65" \ "Incorporating new mail into inbox... 11+ 12/17 No Such User Hello< "$expected" <> "$expected" cat >> "$expected" <> "$expected" < "$expected" <> "$expected" cat >> "$expected" <> "$expected" < $form < -------- EOF expected="${MH_TEST_DIR}/$$.expected" actual="${MH_TEST_DIR}/Mail/draft" from="Mr Test User " to1="User One " to2="User Two " cc1="CC User One " cc2="CC User Two " cc3="CC User Three " cc4="CC User Four " fcc1="+nosuchmailbox" fcc2="+nosuchmailbox2" subject="Totally bogus subject" cat > "$expected" <> "$expected" cat >> "$expected" </dev/null 2>&1; then standout_code=smso bold_code=bold reset_code=sgr0 foreground_code=setaf elif tput -Txterm-color me >/dev/null 2>&1; then standout_code=so bold_code=md reset_code=me foreground_code=AF else test_skip "unable to use terminfo or termcap capabilities" fi tput -Txterm-color ${reset_code} >/dev/null 2>&1 || test_skip "missing terminfo entry for xterm-color" tput -Tvt100 ${reset_code} > /dev/null 2>&1 || test_skip "missing terminfo entry for vt100" # # Set up things so messages 7-10 are unseen, and message 6 is cur # echo "Unseen-Sequence: unseen" >> "$MH" mark +inbox 7-10 -seq unseen -add mark 6 -seq cur -add -zero # # Right now, in scan.curses cur is marked with standout for monochrome, red # for color, and unseen is marked with with bold/green for unseen. # TERM=vt100; export TERM standout=`tput ${standout_code}` bold=`tput ${bold_code}` reset=`tput ${reset_code}` cat > "$expected" <>${reset} 2 09/29 Test2 Testing message 2<>${reset} 3 09/29 Test3 Testing message 3<>${reset} 4 09/29 Test4 Testing message 4<>${reset} 5 09/29 Test5 Testing message 5<>${reset} ${standout} 6+ 09/29 Test6 Testing message 6<>${reset} ${bold} 7 09/29 Test7 Testing message 7<>${reset} ${bold} 8 09/29 Test8 Testing message 8<>${reset} ${bold} 9 09/29 Test9 Testing message 9<>${reset} ${bold} 10 09/29 Test10 Testing message 10<>${reset} EOF run_prog scan -width 80 -form scan.curses > "$actual" check "$expected" "$actual" # # xterm-color should cause %(hascolor) to return true, so we should execute # all of the color-based scan output. According to the terminfo # documentation the color red should be 1, where green is 2. But the # format code will fall back to the older setf capability if setaf isn't # supported, which has a different color numbering scheme; we should # test for that at some point. # TERM=xterm-color; export TERM red=`tput ${foreground_code} 1` green=`tput ${foreground_code} 2` reset=`tput ${reset_code}` cat > "$expected" <>${reset} 2 09/29 Test2 Testing message 2<>${reset} 3 09/29 Test3 Testing message 3<>${reset} 4 09/29 Test4 Testing message 4<>${reset} 5 09/29 Test5 Testing message 5<>${reset} ${red} 6+ 09/29 Test6 Testing message 6<>${reset} ${green} 7 09/29 Test7 Testing message 7<>${reset} ${green} 8 09/29 Test8 Testing message 8<>${reset} ${green} 9 09/29 Test9 Testing message 9<>${reset} ${green} 10 09/29 Test10 Testing message 10<>${reset} EOF run_prog scan -width 80 -form scan.curses > "$actual" check "$expected" "$actual" exit $failed nmh-1.7.1-RC3/test/format/test-dp000755 007761 000024 00000004755 13240377167 016564 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test dp # ###################################################### 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 # Use proper program, likely not the first one on PATH. dp="${MH_LIBEXEC_DIR}/dp" check_exit '-eq 1' $dp - check_exit '-eq 1' $dp -format foo -form check_exit '-eq 1' $dp -form foo -format check_exit '-eq 1' $dp -width x=tendixzehn l=$x$x$x$x$x c=$l$l check_exit '-eq 1' $dp `echo $c | sed 's/./ &/g'` 101 COLUMNS=1 check_exit '-eq 0' $dp foo check_exit '-eq 0' $dp -width 0 foo expected="$MH_TEST_DIR/$$.expected" expected_err="$MH_TEST_DIR/$$.expected_err" actual="$MH_TEST_DIR/$$.actual" actual_err="$MH_TEST_DIR/$$.actual_err" # check -help cat >"$expected" <&1 | sed '/^$/,$d' >"$actual" check "$expected" "$actual" # check -version case `$dp -v` in dp\ --*) ;; * ) printf '%s: dp -v generated unexpected output\n' "$0" >&2 failed=`expr ${failed:-0} + 1`;; esac # check unknown switch run_test "$dp -nonexistent" 'dp: -nonexistent unknown' # check with no switches run_test "$dp" 'dp: usage: dp [switches] dates ...' # check with one valid date cat >"$expected" < "$actual" 2>&1 check "$expected" "$actual" # check with two valid dates cat >"$expected" < "$actual" 2>&1 check "$expected" "$actual" # check with invalid date cat >"$expected" <"$expected_err" < "$actual" 2> "$actual_err" check "$expected" "$actual" check "$expected_err" "$actual_err" # check -form form="${MH_TEST_DIR}/Mail/dp-form" cat >"$form" <<'EOF' %(day{text}) EOF cat >"$expected" <$actual 2>&1 check $expected $actual rm -f "$form" # check -format cat >"$expected" <$actual 2>&1 check $expected $actual # check -width cat >"$expected" < "$actual" 2>&1 check "$expected" "$actual" exit ${failed:-0} nmh-1.7.1-RC3/test/format/test-fmtdump000755 007761 000024 00000011745 13240377167 017632 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test fmtdump # ###################################################### 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 # Use proper program, likely not the first one on PATH. fmtdump="${MH_LIBEXEC_DIR}/fmtdump" check_exit '-eq 1' "$fmtdump" - check_exit '-eq 1' "$fmtdump" -form check_exit '-eq 1' "$fmtdump" -format check_exit '-eq 1' "$fmtdump" foo bar check_exit '-eq 0' "$fmtdump" -format ' %4{} %(eq) %(getenv) %(decodecomp{}) %(trim{}) %(putaddr) %(putlit) %(zputlit) %(compval{}) %(num) %(plus) %(minus) %(multiply) %(divide) %(modulo) %(charleft) %(kilo) %(kibi) %(month{}) %(tzone{}) %(day{}) %(weekday{}) %(tws{}) %(pretty{}) %(sec{}) %(min{}) %(hour{}) %(year{}) %(yday{}) %(wday{}) %(clock{}) %(rclock{}) %(sday{}) %(dst{}) %(szone{}) %(date2local{}) %(date2gmt{}) ' check_exit '-eq 0' "$fmtdump" -format ' %(addr{}) %(pers{}) %(mbox{}) %(host{}) %(path{}) %(gname{}) %(note{}) %(proper{}) %(type{}) %(ingrp{}) %(nohost{}) %(formataddr) %(concataddr) %(getmymbox{}) %(getmyaddr{}) %<(null)%> %<(gt)%> %<(match)%> %<(amatch)%> %(null) %(nonnull) %(ne) %(gt) %(match) %(amatch) ' check_exit '-eq 0' "$fmtdump" -format "`printf '\302\010\014\015\011\177'`" expected=$MH_TEST_DIR/$$.expected expected_err=$MH_TEST_DIR/$$.expected_err actual=$MH_TEST_DIR/$$.actual actual_err=$MH_TEST_DIR/$$.actual_err # check -help cat >$expected <&1 | sed '/^$/,$d' >"$actual" check "$expected" "$actual" # check -version case `$fmtdump -v` in fmtdump\ --*) ;; * ) printf '%s: fmtdump -v generated unexpected output\n' "$0" >&2 failed=`expr ${failed:-0} + 1`;; esac # check unknown switch run_test "$fmtdump -nonexistent" 'fmtdump: -nonexistent unknown' # check with no switches cat >$expected < LV_MON, c_name "date", c_type NUMF, width 2, fill '0' CHAR '/' PARSEDATE, c_name "date", c_type LV_MDAY, c_name "date", c_type NUMF, width 2, fill '0' LS_COMP, comp "date", c_type IF_S continue else goto L6 CHAR ' ' GOTO L7 L6: CHAR '*' L7: MYMBOX, c_name "from", c_type LV_COMPFLAG, comp "from", c_type IF_V_NE 0 continue else goto L8 LS_COMP, comp "to", c_type IF_S continue else goto L8 LIT "To:" PARSEADDR, c_name "to", c_type LS_FRIENDLY, c_name "to", c_type LS_DECODE STRF, width 14, fill ' ' L8: IF_V_EQ 0 continue else goto L9 PARSEADDR, c_name "from", c_type LS_FRIENDLY, c_name "from", c_type LS_DECODE STRF, width 17, fill ' ' L9: LIT " " LS_COMP, comp "subject" LS_DECODE STR LS_COMP, comp "body" IF_S continue else goto L10 LIT "<<" COMP, comp "body" LIT ">>" L10: CHAR '\n' DONE EOF run_prog $fmtdump >$actual 2>&1 check $expected $actual # check -form cat >$expected < LV_MON, c_name "date", c_type NUMF, width 2, fill '0' CHAR '/' PARSEDATE, c_name "date", c_type LV_MDAY, c_name "date", c_type NUMF, width 2, fill '0' LS_COMP, comp "date", c_type IF_S continue else goto L6 CHAR ' ' GOTO L7 L6: CHAR '*' L7: MYMBOX, c_name "from", c_type LV_COMPFLAG, comp "from", c_type IF_V_NE 0 continue else goto L8 LS_COMP, comp "to", c_type IF_S continue else goto L8 LIT "To:" PARSEADDR, c_name "to", c_type LS_FRIENDLY, c_name "to", c_type LS_DECODE LS_UNQUOTE STRF, width 14, fill ' ' L8: IF_V_EQ 0 continue else goto L9 PARSEADDR, c_name "from", c_type LS_FRIENDLY, c_name "from", c_type LS_DECODE LS_UNQUOTE STRF, width 17, fill ' ' L9: LIT " " LS_COMP, comp "subject" LS_DECODE STR LS_COMP, comp "body" IF_S continue else goto L10 LIT "<<" COMP, comp "body" LIT ">>" L10: CHAR '\n' DONE EOF run_prog $fmtdump -form "$MH_INST_DIR${nmhetcdir}/scan.default" >$actual 2>&1 check $expected $actual # check -format cat >$expected <' >$actual 2>&1 check $expected $actual exit ${failed:-0} nmh-1.7.1-RC3/test/format/test-fmttest000755 007761 000024 00000022533 13240377015 017631 0ustar00kenhstaff000000 000000 #! /bin/sh # Tests for fmttest(1). 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 # fmttest(1) doesn't accept `--' to mark the end of option processing. # This is a bug. It also considers a string of `-3' to be an unknown # option `3'; `-- -3' can't be used. One workaround is to give a # string of `3' and use `%(void(minus 0))' in the format string to # negate it, but this contains a space and makes parsing the here file # tedious. Instead, pass the test value as the component `t', with a # dummy string `unused' to satisfy the requirement of at least one thing # to format. t="$MH_TEST_DIR/$$" want_out="$t.want.1" want_err="$t.want.2" got_out="$t.got.1" got_err="$t.got.2" ok=true while read -r fmt val size out; do if test "$fmt" = '#'; then continue; fi if test -n "$out"; then printf -- "$out\n"; fi >$want_out >$want_err r=0 fmttest -raw -format "$fmt" -outsize "$size" \ --t "`printf -- $val`" unused >$got_out 2>$got_err || r=$? label="of \"$fmt\", size \"$size\", with \"$val\"" if test $r -ne 0; then echo "$0: exit status $label is not 0: $r" ok=false fi check $want_out $got_out : "output $label" || ok=false check $want_err $got_err : "errors $label" || ok=false $ok || break done <<\E # The `^' and `$' aren't used here as regexp meta-characters, but as # bracketing characters around the escape that mnemonically stand for # `before' and `after'. If parenthesis or similar are used then they # trigger annoying behaviour in some editors. # # Test cpstripped() with FT_COMP. # %{t} foo max foo %{t} foo 0 %{t} foo 1 f %{t} foo 2 fo %{t} foo 3 foo %{t} foo 4 foo ^%{t} foo max ^foo ^%{t} foo 0 ^%{t} foo 1 ^ ^%{t} foo 2 ^f ^%{t} foo 3 ^fo ^%{t} foo 4 ^foo ^%{t} foo 5 ^foo %{t}$ foo max foo$ %{t}$ foo 0 %{t}$ foo 1 f %{t}$ foo 2 fo %{t}$ foo 3 foo %{t}$ foo 4 foo$ %{t}$ foo 5 foo$ ^%{t}$ foo max ^foo$ ^%{t}$ foo 0 ^%{t}$ foo 1 ^ ^%{t}$ foo 2 ^f ^%{t}$ foo 3 ^fo ^%{t}$ foo 4 ^foo ^%{t}$ foo 5 ^foo$ ^%{t}$ foo 6 ^foo$ # # zputlit only outputs if there's room for following content. # This suggests a zputlit to cancel the effect of an earlier zputlit may # not appear. ^%(zputlit{t})%{t}$ foo max ^foofoo$ ^%(zputlit{t})%{t}$ foo 5 ^foofoo$ ^%(zputlit{t})%{t}$ foo 4 ^foofoo ^%(zputlit{t})%{t}$ foo 3 ^foofo ^%(zputlit{t})%{t}$ foo 2 ^foof ^%(zputlit{t})%{t}$ foo 1 ^ ^%(zputlit{t})%{t}$ foo 0 # # Test leading whitespace is stripped, and intervening compressed. %{t} \40foo 3 foo %{t} \t\40foo 3 foo %{t} \t\40f\n\vo\n\no 3 f o %{t} \t\40f\n\vo\n\no 4 f o\40 %{t} \t\40f\n\vo\n\no 5 f o o # # Test cptrimmed() with FT_COMPF. %5{t} dum max dum \40 %5{t} dumb max dumb\40 %5{t} dumbw max dumbw %5{t} dumbwa max dumbw %5{t} dumbwai max dumbw %5{t} dumbwai 6 dumbw %5{t} dumbwai 5 dumbw %5{t} dumbwai 4 dumb ^%5{t} dum max ^dum \40 ^%5{t} dumb max ^dumb\40 ^%5{t} dumbw max ^dumbw ^%5{t} dumbwa max ^dumbw ^%5{t} dumbwai max ^dumbw ^%5{t} dumbwai 6 ^dumbw ^%5{t} dumbwai 5 ^dumb ^%5{t} dumbwai 4 ^dum %5{t}$ dum max dum $ %5{t}$ dumb max dumb $ %5{t}$ dumbw max dumbw$ %5{t}$ dumbwa max dumbw$ %5{t}$ dumbwai max dumbw$ %5{t}$ dumbwai 7 dumbw$ %5{t}$ dumbwai 6 dumbw$ %5{t}$ dumbwai 5 dumbw %5{t}$ dumbwai 4 dumb ^%5{t}$ dum max ^dum $ ^%5{t}$ dumb max ^dumb $ ^%5{t}$ dumbw max ^dumbw$ ^%5{t}$ dumbwa max ^dumbw$ ^%5{t}$ dumbwai max ^dumbw$ ^%5{t}$ dumbwai 8 ^dumbw$ ^%5{t}$ dumbwai 7 ^dumbw$ ^%5{t}$ dumbwai 6 ^dumbw ^%5{t}$ dumbwai 5 ^dumb # %-5{t} dum max \40 dum %-5{t} dumb max \40dumb %-5{t} dumbw max dumbw %-5{t} dumbwa max dumbw %-5{t} dumbwai max dumbw %-5{t} dumbwai 6 dumbw %-5{t} dumbwai 5 dumbw %-5{t} dumbwai 4 dumb ^%-5{t} dum max ^ dum ^%-5{t} dumb max ^ dumb ^%-5{t} dumbw max ^dumbw ^%-5{t} dumbwa max ^dumbw ^%-5{t} dumbwai max ^dumbw ^%-5{t} dumbwai 7 ^dumbw ^%-5{t} dumbwai 6 ^dumbw ^%-5{t} dumbwai 5 ^dumb %-5{t}$ dum max \40 dum$ %-5{t}$ dumb max \40dumb$ %-5{t}$ dumbw max dumbw$ %-5{t}$ dumbwa max dumbw$ %-5{t}$ dumbwai max dumbw$ %-5{t}$ dumbwai 7 dumbw$ %-5{t}$ dumbwai 6 dumbw$ %-5{t}$ dumbwai 5 dumbw %-5{t}$ dumbwai 4 dumb ^%-5{t}$ dum max ^ dum$ ^%-5{t}$ dumb max ^ dumb$ ^%-5{t}$ dumbw max ^dumbw$ ^%-5{t}$ dumbwa max ^dumbw$ ^%-5{t}$ dumbwai max ^dumbw$ ^%-5{t}$ dumbwai 8 ^dumbw$ ^%-5{t}$ dumbwai 7 ^dumbw$ ^%-5{t}$ dumbwai 6 ^dumbw ^%-5{t}$ dumbwai 5 ^dumb # # Test cpnumber(). # %(void(compval{t}))%0(putnumf) 3 max %(void(compval{t}))%1(putnumf) 3 max 3 %(void(compval{t}))%2(putnumf) 3 max \0403 %(void(compval{t}))%3(putnumf) 3 max \040 3 %(void(compval{t}))%00(putnumf) 3 max %(void(compval{t}))%01(putnumf) 3 max 3 %(void(compval{t}))%02(putnumf) 3 max 03 %(void(compval{t}))%03(putnumf) 3 max 003 %(void(compval{t}))%-0(putnumf) 3 max %(void(compval{t}))%-1(putnumf) 3 max 3 %(void(compval{t}))%-2(putnumf) 3 max 3\40 %(void(compval{t}))%-3(putnumf) 3 max 3 \40 %(void(compval{t}))%-00(putnumf) 3 max %(void(compval{t}))%-01(putnumf) 3 max 3 %(void(compval{t}))%-02(putnumf) 3 max 3\40 %(void(compval{t}))%-03(putnumf) 3 max 3 \40 # %(void(compval{t}))%0(putnumf) -3 max %(void(compval{t}))%1(putnumf) -3 max %(void(compval{t}))%2(putnumf) -3 max -3 %(void(compval{t}))%3(putnumf) -3 max \040-3 %(void(compval{t}))%4(putnumf) -3 max \040 -3 %(void(compval{t}))%00(putnumf) -3 max %(void(compval{t}))%01(putnumf) -3 max %(void(compval{t}))%02(putnumf) -3 max -3 %(void(compval{t}))%03(putnumf) -3 max -03 %(void(compval{t}))%04(putnumf) -3 max -003 %(void(compval{t}))%-0(putnumf) -3 max %(void(compval{t}))%-1(putnumf) -3 max %(void(compval{t}))%-2(putnumf) -3 max -3 %(void(compval{t}))%-3(putnumf) -3 max -3\40 %(void(compval{t}))%-4(putnumf) -3 max -3 \40 %(void(compval{t}))%-00(putnumf) -3 max %(void(compval{t}))%-01(putnumf) -3 max %(void(compval{t}))%-02(putnumf) -3 max -3 %(void(compval{t}))%-03(putnumf) -3 max -3\40 %(void(compval{t}))%-04(putnumf) -3 max -3 \40 # %(void(compval{t}))%0(putnumf) 42 max %(void(compval{t}))%1(putnumf) 42 max ? %(void(compval{t}))%2(putnumf) 42 max 42 %(void(compval{t}))%3(putnumf) 42 max \04042 %(void(compval{t}))%00(putnumf) 42 max %(void(compval{t}))%01(putnumf) 42 max ? %(void(compval{t}))%02(putnumf) 42 max 42 %(void(compval{t}))%03(putnumf) 42 max 042 %(void(compval{t}))%-0(putnumf) 42 max %(void(compval{t}))%-1(putnumf) 42 max ? %(void(compval{t}))%-2(putnumf) 42 max 42 %(void(compval{t}))%-3(putnumf) 42 max 42\40 %(void(compval{t}))%-00(putnumf) 42 max %(void(compval{t}))%-01(putnumf) 42 max ? %(void(compval{t}))%-02(putnumf) 42 max 42 %(void(compval{t}))%-03(putnumf) 42 max 42\40 # %(void(compval{t}))%0(putnumf) -42 max %(void(compval{t}))%1(putnumf) -42 max %(void(compval{t}))%2(putnumf) -42 max -? %(void(compval{t}))%3(putnumf) -42 max -42 %(void(compval{t}))%4(putnumf) -42 max \40-42 %(void(compval{t}))%00(putnumf) -42 max %(void(compval{t}))%01(putnumf) -42 max %(void(compval{t}))%02(putnumf) -42 max -? %(void(compval{t}))%03(putnumf) -42 max -42 %(void(compval{t}))%04(putnumf) -42 max -042 %(void(compval{t}))%-0(putnumf) -42 max %(void(compval{t}))%-1(putnumf) -42 max %(void(compval{t}))%-2(putnumf) -42 max -? %(void(compval{t}))%-3(putnumf) -42 max -42 %(void(compval{t}))%-4(putnumf) -42 max -42\40 %(void(compval{t}))%-00(putnumf) -42 max %(void(compval{t}))%-01(putnumf) -42 max %(void(compval{t}))%-02(putnumf) -42 max -? %(void(compval{t}))%-03(putnumf) -42 max -42 %(void(compval{t}))%-04(putnumf) -42 max -42\40 # %(void(compval{t}))%5(putnumf) 13579 0 %(void(compval{t}))%5(putnumf) 13579 1 %(void(compval{t}))%5(putnumf) 13579 2 %(void(compval{t}))%5(putnumf) 13579 3 %(void(compval{t}))%5(putnumf) 13579 4 %(void(compval{t}))%5(putnumf) 13579 5 13579 %(void(compval{t}))%5(putnumf) 13579 6 13579 %(void(compval{t}))%6(putnumf) 13579 5 %(void(compval{t}))%6(putnumf) 13579 6 \04013579 %(void(compval{t}))^%5(putnumf) 13579 0 %(void(compval{t}))^%5(putnumf) 13579 1 ^ %(void(compval{t}))^%5(putnumf) 13579 2 ^ %(void(compval{t}))^%5(putnumf) 13579 3 ^ %(void(compval{t}))^%5(putnumf) 13579 4 ^ %(void(compval{t}))^%5(putnumf) 13579 5 ^ %(void(compval{t}))^%5(putnumf) 13579 6 ^13579 %(void(compval{t}))^%5(putnumf) 13579 7 ^13579 %(void(compval{t}))^%6(putnumf) 13579 6 ^ %(void(compval{t}))^%6(putnumf) 13579 7 ^ 13579 %(void(compval{t}))^%6(putnumf) 13579 8 ^ 13579 %(void(compval{t}))%5(putnumf)$ 13579 0 # FIXME: If output won't fit, stop; the `$' is wrong. %(void(compval{t}))%5(putnumf)$ 13579 1 $ %(void(compval{t}))%5(putnumf)$ 13579 2 $ %(void(compval{t}))%5(putnumf)$ 13579 3 $ %(void(compval{t}))%5(putnumf)$ 13579 4 $ %(void(compval{t}))%5(putnumf)$ 13579 5 13579 %(void(compval{t}))%5(putnumf)$ 13579 6 13579$ %(void(compval{t}))%5(putnumf)$ 13579 7 13579$ %(void(compval{t}))%6(putnumf)$ 13579 5 $ %(void(compval{t}))%6(putnumf)$ 13579 6 \04013579 %(void(compval{t}))%6(putnumf)$ 13579 7 \04013579$ %(void(compval{t}))%6(putnumf)$ 13579 8 \04013579$ %(void(compval{t}))^%5(putnumf)$ 13579 0 %(void(compval{t}))^%5(putnumf)$ 13579 1 ^ # FIXME: If output won't fit, stop; the `$' is wrong. %(void(compval{t}))^%5(putnumf)$ 13579 2 ^$ %(void(compval{t}))^%5(putnumf)$ 13579 3 ^$ %(void(compval{t}))^%5(putnumf)$ 13579 4 ^$ %(void(compval{t}))^%5(putnumf)$ 13579 5 ^$ %(void(compval{t}))^%5(putnumf)$ 13579 6 ^13579 %(void(compval{t}))^%5(putnumf)$ 13579 7 ^13579$ %(void(compval{t}))^%5(putnumf)$ 13579 8 ^13579$ %(void(compval{t}))^%6(putnumf)$ 13579 7 ^\04013579 %(void(compval{t}))^%6(putnumf)$ 13579 8 ^\04013579$ %(void(compval{t}))^%6(putnumf)$ 13579 9 ^\04013579$ E $ok finish_test nmh-1.7.1-RC3/test/format/test-functions000755 007761 000024 00000002244 13205305704 020145 0ustar00kenhstaff000000 000000 #!/bin/sh # # Test of various (well, start with one) function escapes. 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/test-functions$$.expected" actual="$MH_TEST_DIR/test-functions$$.actual" # check sday when day of week is specified printf '1\n' >"$expected" fmttest -raw -format '%(sday{text})' 'Fri Sep 12 20:02 2014' >"$actual" check "$expected" "$actual" # check sday when day of week is not specified printf '0\n' >"$expected" fmttest -raw -format '%(sday{text})' 'Sep 12 20:02 2014' >"$actual" check "$expected" "$actual" # check negative number, without padding printf '%s\n' ' -42' >"$expected" fmttest -raw -format '%4(minus -42)' 0 >"$actual" check "$expected" "$actual" # check negative number, with padding # Output was "0-42" with nmh 1.6 and earlier. printf '%s\n' -042 >"$expected" fmttest -raw -format '%04(minus -42)' 0 >"$actual" check "$expected" "$actual" # check multiply printf '%s\n' 42 >"$expected" fmttest -raw -format '%(void(num 7))%(multiply 6)' 0 >"$actual" check "$expected" "$actual" exit $failed nmh-1.7.1-RC3/test/format/test-localmbox000755 007761 000024 00000001364 13205305704 020117 0ustar00kenhstaff000000 000000 #!/bin/sh # # Test that we can retrieve the local mailbox name from the profile via # component functions # 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 testname="Some User " #### Remove existing Local-Mailbox: profile component, if any. Then #### add one. grep -v 'Local-Mailbox: ' ${MH} > ${MH}.new mv -f ${MH}.new ${MH} echo "Local-Mailbox: ${testname}" >> ${MH} # We can use "ap" to get the output of format commands testoutput=`run_prog ${MH_LIBEXEC_DIR}/ap -format "%(localmbox)" ignore` if [ x"${testname}" != x"${testoutput}" ]; then echo "Expected ${testname}, got ${testoutput}" exit 1 fi exit 0 nmh-1.7.1-RC3/test/format/test-myhost000755 007761 000024 00000001333 13243042053 017453 0ustar00kenhstaff000000 000000 #!/bin/sh # # Test that the %(myhost) function returns the local hostname and # the localname entry out of the mts configuration file. # 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 set +e host=`${MH_OBJ_DIR}/test/getcanon` set -e run_test "${MH_LIBEXEC_DIR}/ap -format %(myhost) ignore" "$host" \ "local hostname test" cp ${MHMTSCONF} ${MH_TEST_DIR}/Mail/mts.conf || exit 1 MHMTSCONF="${MH_TEST_DIR}/Mail/mts.conf" echo "localname: some.random.name" >> ${MHMTSCONF} run_test "${MH_LIBEXEC_DIR}/ap -format %(myhost) ignore" "some.random.name" \ "mts.conf localname test" exit $failed nmh-1.7.1-RC3/test/format/test-mymbox000755 007761 000024 00000006003 13205305704 017445 0ustar00kenhstaff000000 000000 #!/bin/sh # # Test that the %(mymbox) function correctly determines whether or not # a particular email address is "mine" or not # 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 #### Use ap to get the username. That will either be what's in the #### Local-Mailbox profile component, which we don't use in the test #### suite, or the user's login name. ap will escape (quote) it if #### needed. user=`run_prog ${MH_LIBEXEC_DIR}/ap -format '%(me)' 0` set +e host=`${MH_OBJ_DIR}/test/getcanon` set -e output=`run_prog ${MH_LIBEXEC_DIR}/ap -format '%(mymbox{text})' "${user}"` run_test "echo $output" 1 "Basic user test" output=`run_prog ${MH_LIBEXEC_DIR}/ap -format '%(mymbox{text})' "${user}@${host}"` run_test "echo $output" 1 "Basic user@host test" run_test "${MH_LIBEXEC_DIR}/ap -format %(mymbox{text}) nosuchuser@nosuchhost.blah" \ 0 "Basic non-matching test" myname="Random User " #### Remove existing Local-Mailbox: profile component, if any. Then #### add one. grep -v 'Local-Mailbox: ' "$MH" > "$MH".new mv -f "$MH".new "$MH" echo "Local-Mailbox: ${myname}" >> "$MH" run_test "echo \ `run_prog ${MH_LIBEXEC_DIR}/ap -format '%(mymbox{text})' "${myname}"`" \ 1 "Local-Mailbox test" output=`run_prog ${MH_LIBEXEC_DIR}/ap -format '%(mymbox{text})' "${user}@${host}"` run_test "echo $output" 0 "Local-mailbox overriding user@host test" # Add an Alternate-Mailbox. This caused ismymbox() to lose the # Local-Mailbox, Bug #36635: -nocc me doesn't account for # Alternate-Mailboxes. printf 'Alternate-Mailboxes: user@example.com\n' >> $MH run_test "echo \ `run_prog ${MH_LIBEXEC_DIR}/ap -format '%(mymbox{text})' "${myname}"`" \ 1 "Local-Mailbox with Alternate-Mailbox test" # check getmymbox, without match run_test 'fmttest -message -format %(getmymbox{from}) first' '' # check getmyaddr, without match run_test 'fmttest -message -format %(getmyaddr{from}) first' '' grep -v 'Alternate-Mailboxes: ' "$MH" > "$MH".new mv -f "$MH".new "$MH" cat >>"$MH" <' # check getmyaddr, with match run_test 'fmttest -message -format %(getmyaddr{from}) first' \ 'test1@example.com' # check getmymbox and getmyaddr, with match of other than first address in # component cat >`mhpath new` <<'EOF' From: Test11 Cc: Test0 , Test3 , Test1 , Test2 To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 11@test.nmh Subject: Testing message 11 This is message number 11 EOF run_test 'fmttest -message -format %(getmymbox{cc}) last' \ 'Test1 ' run_test 'fmttest -message -format %(getmyaddr{cc}) last' \ 'test1@example.com' exit $failed nmh-1.7.1-RC3/test/format/test-myname000755 007761 000024 00000004463 13205305704 017430 0ustar00kenhstaff000000 000000 #!/bin/sh # # Test that we can retrieve the local username via the passwd file, # the Signature profile entry, and via SIGNATURE environment variable. # 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 unset SIGNATURE fullname=`${MH_OBJ_DIR}/test/getfullname` run_test "${MH_LIBEXEC_DIR}/ap -format %(myname) ignore" \ "$fullname" "GECOS field test" echo "Signature: Some Random Name 1" >> ${MH} run_test "${MH_LIBEXEC_DIR}/ap -format %(myname) ignore" \ "Some Random Name 1" "MH Profile Signature test" SIGNATURE="Some Random Name 2" export SIGNATURE run_test "${MH_LIBEXEC_DIR}/ap -format %(myname) ignore" \ "${SIGNATURE}" "SIGNATURE Environment test" #### Test escaping of display names. escape="${MH_OBJ_DIR}/test/getfullname" run_test "$escape "'user' 'user' 'no escape' run_test "$escape "'first.last' '"first.last"' 'escape' run_test "$escape "'"first.last"' '"first.last"' 'already escaped' run_test "$escape "'first.last"' '"first.last"' 'missing initial "' run_test "$escape "'"first.last' '"first.last"' 'missing final "' run_test "$escape "'embedded"quote' '"embedded\"quote"' 'embedded quote' run_test "$escape "'server\name,#' '"server\name"' 'Windows form' run_test "$escape "'"' '"\""' 'special "' run_test "$escape "'(' '"("' 'special (' run_test "$escape "')' '")"' 'special )' #### We stop at the first comma so this one gets eliminated: run_test "$escape "',' '' 'special ,' run_test "$escape "'.' '"."' 'special .' run_test "$escape "':' '":"' 'special :' run_test "$escape "';' '";"' 'special ;' run_test "$escape "'<' '"<"' 'special <' run_test "$escape "'>' '">"' 'special >' run_test "$escape "'@' '"@"' 'special @' run_test "$escape "'[' '"["' 'special [' run_test "$escape "'\\' '"\\"' 'special \\' run_test "$escape "']' '"]"' 'special ]' exit $failed nmh-1.7.1-RC3/test/format/test-nullstr000755 007761 000024 00000001346 12437351011 017640 0ustar00kenhstaff000000 000000 #!/bin/sh # # Test that a NULL str register doesn't cause the string handling format # escapes to fail. # 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 # # %{null} is arbitrary; it could be any component that does not exist. # run_test "fmttest -raw -format Test%(putstr{null}) dummy" "Test" \ "Test of %(putstr)" run_test "fmttest -raw -format Test%10(putstrf{null}) dummy" "Test " \ "Test of %(putstrf)" run_test "fmttest -raw -format Test%(putlit{null}) dummy" "Test" \ "Test of %(putlit)" run_test "fmttest -raw -format Test%(zputlit{null}) dummy" "Test" \ "Test of %(zputlit)" exit $failed nmh-1.7.1-RC3/test/format/test-rightjustify000755 007761 000024 00000001405 13205305704 020666 0ustar00kenhstaff000000 000000 #!/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 for prefix in '' '>' '2>'; do actual=`run_prog ${MH_LIBEXEC_DIR}/ap -format "$prefix%-20(friendly{text})<'` expected="$prefix No Such User<&2 echo " $expected" 1>&2 echo "but instead got:" 1>&2 echo " $actual" 1>&2 failed=`expr ${failed:-0} + 1` fi done exit $failed nmh-1.7.1-RC3/test/format/test-unquote000755 007761 000024 00000001317 12437351011 017633 0ustar00kenhstaff000000 000000 #!/bin/sh # # Test that the unquote function works properly. # 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 # # Test various unquoting scenarios # run_test 'eval fmttest -raw -format "%(unquote{text})" "Mr. Foo Bar"' \ 'Mr. Foo Bar' run_test 'eval fmttest -raw -format "%(unquote{text})" "Mr. \"Foo\" Bar"' \ 'Mr. Foo Bar' # # Note here: the string we wanted passed on the command line is: # # "Mr. \"Foo\" Bar" # # The extra \ are necessary to get it past the shell # run_test 'eval fmttest -raw -format "%(unquote{text})" "Mr. \\\"Foo\\\" Bar"' \ 'Mr. "Foo" Bar' exit ${failed:-0} nmh-1.7.1-RC3/test/folder/test-coverage000755 007761 000024 00000002152 13205305704 017711 0ustar00kenhstaff000000 000000 #!/bin/sh # Tests for folder(1)'s coverage. 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 check_exit '-eq 1' folder - check_exit '-eq 1' folder -xyzzy check_exit '-eq 0' folder -help check_exit '-eq 0' folder -version check_exit '-eq 1' folder -all -noall -fast -nofast -header -noheader \ -pack -nopack -verbose -noverbose -recurse -norecurse \ -total -nototal -print -noprint -list -nolist -push -pop - check_exit '-eq 1' folder + @ check_exit '-eq 1' folder 42 314 check_exit '-eq 1' folder -push check_exit '-eq 0' folder -push + check_exit '-eq 0' folder -push + check_exit '-eq 0' folder -push + check_exit '-eq 0' folder -push check_exit '-eq 1' folder -pop +foo check_exit '-eq 0' folder -pop check_exit '-eq 0' folder -pop check_exit '-eq 0' folder -pop check_exit '-eq 1' folder -pop check_exit '-eq 1' folder -push +missing check_exit '-eq 1' folder -nocreate +missing check_exit '-eq 0' folder -all 1 check_exit '-eq 0' folder -all -fast + check_exit '-eq 0' folder -pack finish_test nmh-1.7.1-RC3/test/folder/test-create000755 007761 000024 00000001100 12437351011 017347 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test the creation and removal of a folder. # ###################################################### 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 run_prog folder -create +testfolder > /dev/null if [ -d "$MH_TEST_DIR/Mail/testfolder" ]; then : else exit 1 fi run_prog rmf +testfolder > /dev/null if [ -d "$MH_TEST_DIR/Mail/testfolder" ]; then # Test failed exit 1 fi nmh-1.7.1-RC3/test/folder/test-nocreate000755 007761 000024 00000001055 13205305704 017717 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test -nocreate. # ###################################################### 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 set +e run_test 'folder -nocreate +testfolder 2>&1' \ 'folder: folder testfolder does not exist' set -e if [ -d "$MH_TEST_DIR/Mail/testfolder" ]; then printf %s "folder should not have been created" exit 1 fi exit ${failed:-0} nmh-1.7.1-RC3/test/folder/test-packf000755 007761 000024 00000006273 13240377167 017225 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test packf # ###################################################### 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 check_exit '-eq 1' packf - expected="$MH_TEST_DIR/$$.expected" actual="$MH_TEST_DIR/$$.actual" # check -help cat >"$expected" <&1 | sed '/^$/,$d' >"$actual" check "$expected" "$actual" # check -version case `packf -v` in packf\ --*) ;; * ) printf '%s: packf -v generated unexpected output\n' "$0" >&2 failed=`expr ${failed:-0} + 1`;; esac # check unknown switch run_test "packf -nonexistent" 'packf: -nonexistent unknown' cd "${MH_TEST_DIR}" || exit 1 printf 'y\n' >Mail/yes # check with no switches run_prog packf /dev/null rm -f msgbox for i in `pick +inbox`; do diff "`mhpath +inbox $i`" "`mhpath +inbox2 $i`" done run_test "printf $i" '10' rmm +inbox2 -unlink `pick +inbox2` # check +folder run_prog packf +inbox /dev/null rm -f msgbox for i in `pick +inbox`; do diff "`mhpath +inbox $i`" "`mhpath +inbox2 $i`" done run_test "printf $i" '10' rmm +inbox2 -unlink `pick +inbox2` # check msgs run_prog packf +inbox 1 2 3 /dev/null rm -f msgbox for i in `pick +inbox2`; do diff "`mhpath +inbox $i`" "`mhpath +inbox2 $i`" done run_test "printf $i" '3' rmm +inbox2 -unlink `pick +inbox2` # check -file run_prog packf +inbox -file msgbox2 /dev/null for i in `pick +inbox2`; do diff "`mhpath +inbox $i`" "`mhpath +inbox2 $i`" done run_test "printf $i" '10' rmm +inbox2 -unlink `pick +inbox2` # check append to existing mbox file run_prog packf +inbox -file msgbox2 /dev/null rm -f msgbox2 for i in `pick +inbox2`; do if [ $i -le 10 ]; then diff "`mhpath +inbox $i`" "`mhpath +inbox2 $i`" else arith_eval $i - 10 diff "`mhpath +inbox $arith_val`" "`mhpath +inbox2 $i`" fi done run_test "printf $i" '20' rmm +inbox2 -unlink `pick +inbox2` # check -mbox run_prog packf +inbox -mbox /dev/null rm -f msgbox for i in `pick +inbox2`; do diff "`mhpath +inbox $i`" "`mhpath +inbox2 $i`" done run_test "printf $i" '10' rmm +inbox2 -unlink `pick +inbox2` # check -mmdf run_prog packf +inbox -mmdf /dev/null rm -f msgbox for i in `pick +inbox2`; do diff "`mhpath +inbox $i`" "`mhpath +inbox2 $i`" done run_test "printf $i" '10' rmm +inbox2 -unlink `pick +inbox2` # check append to existing mmdf file run_prog packf +inbox -mmdf /dev/null rm -f msgbox for i in `pick +inbox2`; do if [ $i -le 10 ]; then diff "`mhpath +inbox $i`" "`mhpath +inbox2 $i`" else arith_eval $i - 10 diff "`mhpath +inbox $arith_val`" "`mhpath +inbox2 $i`" fi done run_test "printf $i" '10' rmm +inbox2 -unlink `pick +inbox2` exit ${failed:-0} nmh-1.7.1-RC3/test/folder/test-recurse000755 007761 000024 00000001242 12437351011 017563 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test of the -recuse option # ###################################################### 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 run_prog folder -create +testfolder > /dev/null run_prog folder -create +testfolder/folder1 > /dev/null run_prog folder -create +testfolder/folder2 > /dev/null run_test 'folder -recurse +testfolder' 'testfolder+ has no messages ; (others). testfolder/folder1 has no messages. testfolder/folder2 has no messages.' exit $failed nmh-1.7.1-RC3/test/folder/test-sortm000755 007761 000024 00000051214 13240377167 017300 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test sortm # ###################################################### 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 check_exit '-eq 1' sortm - expected=$MH_TEST_DIR/$$.expected actual=$MH_TEST_DIR/$$.actual cd $MH_TEST_DIR # check -help cat >"$expected" <&1 | sed '/^$/,$d' >"$actual" check "$expected" "$actual" # check -version case `sortm -version` in sortm\ --*) ;; * ) echo "$0: sortm -v generated unexpected output" 1>&2 failed=`expr ${failed:-0} + 1`;; esac cat >$MH_TEST_DIR/Mail/inbox/11 < To: Some User Date: Fri, 29 Sep 2006 00:00:01 Alt-Date: Thu, 1 Sep 2005 00:00:00 Subject: Re: common subject This is message number 11 EOF cat >$MH_TEST_DIR/Mail/inbox/12 < To: Some User Date: Thu, 28 Sep 2006 23:59:59 Alt-Date: Sat, 30 Sep 2006 00:00:00 Subject: common subject This is message number 12 EOF # check with no options cat >"$expected" <> 2 09/29 Test1 Testing message 1<> 3 09/29 Test2 Testing message 2<> 4 09/29 Test3 Testing message 3<> 5 09/29 Test4 Testing message 4<> 6 09/29 Test5 Testing message 5<> 7 09/29 Test6 Testing message 6<> 8 09/29 Test7 Testing message 7<> 9 09/29 Test8 Testing message 8<> 10 09/29 Test9 Testing message 9<> 11 09/29 Test10 Testing message 10<> 12 09/29 Test11 Re: common subject<> EOF run_prog sortm scan -width 80 >"$actual" check "$expected" "$actual" # check +folder cat >"$expected" <> 2+ 09/29 Test1 Testing message 1<> 3 09/29 Test2 Testing message 2<> 4 09/29 Test3 Testing message 3<> 5 09/29 Test4 Testing message 4<> 6 09/29 Test5 Testing message 5<> 7 09/29 Test6 Testing message 6<> 8 09/29 Test7 Testing message 7<> 9 09/29 Test8 Testing message 8<> 10 09/29 Test9 Testing message 9<> 11 09/29 Test10 Testing message 10<> 12 09/29 Test11 Re: common subject<> EOF refile first +inbox; folder -pack >/dev/null run_prog sortm +inbox scan -width 80 >"$actual" check "$expected" "$actual" # check -verbose cat >"$expected" <> 2+ 09/29 Test1 Testing message 1<> 3 09/29 Test2 Testing message 2<> 4 09/29 Test3 Testing message 3<> 5 09/29 Test4 Testing message 4<> 6 09/29 Test5 Testing message 5<> 7 09/29 Test6 Testing message 6<> 8 09/29 Test7 Testing message 7<> 9 09/29 Test8 Testing message 8<> 10 09/29 Test9 Testing message 9<> 11 09/29 Test10 Testing message 10<> 12 09/29 Test11 Re: common subject<> EOF refile first +inbox; folder -pack >/dev/null run_prog sortm -verbose >"$actual" scan -width 80 >>"$actual" check "$expected" "$actual" # check -noverbose cat >"$expected" <> 2+ 09/29 Test1 Testing message 1<> 3 09/29 Test2 Testing message 2<> 4 09/29 Test3 Testing message 3<> 5 09/29 Test4 Testing message 4<> 6 09/29 Test5 Testing message 5<> 7 09/29 Test6 Testing message 6<> 8 09/29 Test7 Testing message 7<> 9 09/29 Test8 Testing message 8<> 10 09/29 Test9 Testing message 9<> 11 09/29 Test10 Testing message 10<> 12 09/29 Test11 Re: common subject<> EOF refile first +inbox; folder -pack >/dev/null run_prog sortm -verbose -noverbose >"$actual" scan -width 80 >>"$actual" check "$expected" "$actual" # check msgs cat >"$expected" <> 2 09/29 Test2 Testing message 2<> 3 09/29 Test3 Testing message 3<> 4 09/29 Test4 Testing message 4<> 5 09/29 Test5 Testing message 5<> 6 09/29 Test6 Testing message 6<> 7 09/29 Test7 Testing message 7<> 8 09/29 Test8 Testing message 8<> 9 09/29 Test9 Testing message 9<> 10 09/29 Test10 Testing message 10<> 11 09/29 Test11 Re: common subject<> 12+ 09/29 Test1 Testing message 1<> EOF refile first +inbox; folder -pack >/dev/null run_prog sortm first last scan -width 80 >"$actual" check "$expected" "$actual" # check -datefield cat >"$expected" <> 2 09/29 Test2 Testing message 2<> 3 09/29 Test3 Testing message 3<> 4 09/29 Test4 Testing message 4<> 5 09/29 Test5 Testing message 5<> 6 09/29 Test6 Testing message 6<> 7 09/29 Test7 Testing message 7<> 8 09/29 Test8 Testing message 8<> 9 09/29 Test9 Testing message 9<> 10 09/29 Test10 Testing message 10<> 11 09/28 Test12 common subject<> 12+ 09/29 Test1 Testing message 1<> EOF run_prog sortm -datefield Alt-Date 1 11 scan -width 80 >"$actual" check "$expected" "$actual" # check -textfield subject (datefield major, subjects grouped) cat >"$expected" <> 2 09/29 Test11 Re: common subject<> 3 09/29 Test2 Testing message 2<> 4 09/29 Test3 Testing message 3<> 5 09/29 Test4 Testing message 4<> 6 09/29 Test5 Testing message 5<> 7 09/29 Test6 Testing message 6<> 8 09/29 Test7 Testing message 7<> 9 09/29 Test8 Testing message 8<> 10 09/29 Test9 Testing message 9<> 11 09/29 Test10 Testing message 10<> 12+ 09/29 Test1 Testing message 1<> EOF run_prog sortm -textfield subject scan -width 80 >"$actual" check "$expected" "$actual" # check -nolimit cat >"$expected" <> 2 09/29 Test11 Re: common subject<> 3 09/29 Test2 Testing message 2<> 4 09/29 Test3 Testing message 3<> 5 09/29 Test4 Testing message 4<> 6 09/29 Test5 Testing message 5<> 7 09/29 Test6 Testing message 6<> 8 09/29 Test7 Testing message 7<> 9 09/29 Test8 Testing message 8<> 10 09/29 Test9 Testing message 9<> 11 09/29 Test10 Testing message 10<> 12+ 09/29 Test1 Testing message 1<> EOF run_prog sortm -textfield subject -limit 0 -nolimit scan -width 80 >"$actual" check "$expected" "$actual" # check -textfield subject -limit 0 (subject sort) cat >"$expected" <> 2 09/28 Test12 common subject<> 3 09/29 Test1 Testing message 1<> 4 09/29 Test10 Testing message 10<> 5 09/29 Test2 Testing message 2<> 6 09/29 Test3 Testing message 3<> 7 09/29 Test4 Testing message 4<> 8 09/29 Test5 Testing message 5<> 9 09/29 Test6 Testing message 6<> 10 09/29 Test7 Testing message 7<> 11 09/29 Test8 Testing message 8<> 12+ 09/29 Test9 Testing message 9<> EOF refile 2-7 +inbox; refile 1 +inbox; folder -pack last >/dev/null run_prog sortm -textfield subject -limit 0 scan -width 80 >"$actual" check "$expected" "$actual" # check -textfield -limit 0 (text sort) cat >"$expected" <> 2 09/29 Test11 Re: common subject<> 3 09/28 Test12 common subject<> 4 09/29 Test1 Testing message 1<> 5 09/29 Test2 Testing message 2<> 6 09/29 Test3 Testing message 3<> 7 09/29 Test4 Testing message 4<> 8 09/29 Test5 Testing message 5<> 9 09/29 Test6 Testing message 6<> 10 09/29 Test7 Testing message 7<> 11 09/29 Test8 Testing message 8<> 12+ 09/29 Test9 Testing message 9<> EOF refile 2-7 +inbox; refile 1 +inbox; folder -pack last >/dev/null run_prog sortm -textfield from -limit 0 scan -width 80 >"$actual" check "$expected" "$actual" # check -textfield with finite -limit that doesn't cover message 13 cat >$MH_TEST_DIR/Mail/inbox/13 < To: Some User Date: Tue, 31 Oct 2006 23:59:59 Subject: Re: common subject This is message number 13 EOF cat >"$expected" <> 2 09/29 Test11 Re: common subject<> 3 09/29 Test5 Testing message 5<> 4 09/29 Test6 Testing message 6<> 5 09/29 Test7 Testing message 7<> 6 09/29 Test8 Testing message 8<> 7 09/29 Test9 Testing message 9<> 8 09/29 Test1 Testing message 1<> 9 09/29 Test2 Testing message 2<> 10 09/29 Test3 Testing message 3<> 11 09/29 Test4 Testing message 4<> 12+ 09/29 Test10 Testing message 10<> 13 10/31 Test13 Re: common subject<> EOF refile 2-7 +inbox; refile 1 +inbox; folder -pack last >/dev/null run_prog sortm -textfield subject -limit 10 scan -width 80 >"$actual" check "$expected" "$actual" # check -textfield with finite -limit that does cover message 13 cat >"$expected" <> 2 09/29 Test11 Re: common subject<> 3 10/31 Test13 Re: common subject<> 4 09/29 Test1 Testing message 1<> 5 09/29 Test2 Testing message 2<> 6 09/29 Test3 Testing message 3<> 7 09/29 Test4 Testing message 4<> 8 09/29 Test10 Testing message 10<> 9 09/29 Test5 Testing message 5<> 10 09/29 Test6 Testing message 6<> 11 09/29 Test7 Testing message 7<> 12 09/29 Test8 Testing message 8<> 13+ 09/29 Test9 Testing message 9<> EOF refile 2-7 +inbox; refile 1 +inbox; folder -pack last >/dev/null run_prog sortm -textfield subject -limit 60 scan -width 80 >"$actual" check "$expected" "$actual" # check -notextfield cat >"$expected" <> 2 09/29 Test10 Testing message 10<> 3 09/29 Test5 Testing message 5<> 4 09/29 Test6 Testing message 6<> 5 09/29 Test7 Testing message 7<> 6 09/29 Test8 Testing message 8<> 7 09/29 Test9 Testing message 9<> 8 09/29 Test1 Testing message 1<> 9 09/29 Test2 Testing message 2<> 10 09/29 Test3 Testing message 3<> 11 09/29 Test4 Testing message 4<> 12 09/29 Test11 Re: common subject<> 13+ 10/31 Test13 Re: common subject<> EOF refile 2-7 +inbox; refile 1 +inbox; folder -pack last >/dev/null run_prog sortm -textfield subject -limit 60 -notextfield scan -width 80 >"$actual" check "$expected" "$actual" # check -noall run_test 'sortm -noall' 'sortm: must specify messages to sort with -noall' # check -all cat >"$expected" <> 2+ 09/29 Test10 Testing message 10<> 3 09/29 Test5 Testing message 5<> 4 09/29 Test6 Testing message 6<> 5 09/29 Test7 Testing message 7<> 6 09/29 Test8 Testing message 8<> 7 09/29 Test9 Testing message 9<> 8 09/29 Test1 Testing message 1<> 9 09/29 Test2 Testing message 2<> 10 09/29 Test3 Testing message 3<> 11 09/29 Test4 Testing message 4<> 12 09/29 Test11 Re: common subject<> 13 10/31 Test13 Re: common subject<> EOF refile first +inbox; folder -pack >/dev/null run_prog sortm -noall -all scan -width 80 >"$actual" check "$expected" "$actual" # check -check cat >"$expected" < $MH_TEST_DIR/Mail/inbox/14 set +e run_prog sortm -check >"$actual" 2>&1 set -e check "$expected" "$actual" cat >"$expected" <> 2+ 09/29 Test10 Testing message 10<> 3 09/29 Test5 Testing message 5<> 4 09/29 Test6 Testing message 6<> 5 09/29 Test7 Testing message 7<> 6 09/29 Test8 Testing message 8<> 7 09/29 Test9 Testing message 9<> 8 09/29 Test1 Testing message 1<> 9 09/29 Test2 Testing message 2<> 10 09/29 Test3 Testing message 3<> 11 09/29 Test4 Testing message 4<> 12 09/29 Test11 Re: common subject<> 13 10/31 Test13 Re: common subject<> 14 01/00 Test9 Testing message 9<> EOF scan -width 80 >"$actual" check "$expected" "$actual" # check -nocheck cat >"$expected" <> 2+ 09/29 Test10 Testing message 10<> 3 09/29 Test5 Testing message 5<> 4 09/29 Test6 Testing message 6<> 5 09/29 Test7 Testing message 7<> 6 09/29 Test8 Testing message 8<> 7 09/29 Test9 Testing message 9<> 8 09/29 Test1 Testing message 1<> 9 09/29 Test2 Testing message 2<> 10 09/29 Test3 Testing message 3<> 11 09/29 Test4 Testing message 4<> 12 09/29 Test11 Re: common subject<> 13 10/31 Test13 Re: common subject<> 14 01/00 Test9 Testing message 9<> 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, will use file \ modification time" scan -width 80 >"$actual" check "$expected" "$actual" exit ${failed:-0} nmh-1.7.1-RC3/test/folder/test-total000755 007761 000024 00000000665 12437351011 017246 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test the -total switch # ###################################################### 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 output=`run_prog folder -total +inbox` if test x"$output" != x'TOTAL = 10 messages in 1 folder.' ; then exit 1 fi nmh-1.7.1-RC3/test/dist/test-dist000755 007761 000024 00000025034 13240377167 016570 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test dist # ###################################################### 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 check_exit '-eq 1' dist - check_exit '-eq 1' dist -editor check_exit '-eq 1' dist -editor foo -editor check_exit '-eq 1' dist -nowhatnowproc -whatnowproc foo -whatnowproc check_exit '-eq 1' dist -file check_exit '-eq 1' dist -file foo -file bar check_exit '-eq 1' dist -form check_exit '-eq 1' dist -draftfolder check_exit '-eq 1' dist -draftfolder foo -draftfolder bar check_exit '-eq 1' dist -draftmessage check_exit '-eq 1' dist -draftmessage 42 -draftmessage 314 check_exit '-eq 1' dist -from check_exit '-eq 1' dist -to check_exit '-eq 1' dist -cc check_exit '-eq 1' dist -fcc check_exit '-eq 1' dist -width check_exit '-eq 1' dist -width 42 -width 0 check_exit '-eq 1' dist -atfile -noatfile - check_exit '-eq 1' dist + @ check_exit '-eq 1' dist 42 314 check_exit '-eq 1' dist -file foo 42 expected=$MH_TEST_DIR/$$.expected expected_err=$MH_TEST_DIR/$$.expected_err actual=$MH_TEST_DIR/$$.actual actual_err=$MH_TEST_DIR/$$.actual_err localmbox=`${MH_LIBEXEC_DIR}/ap -format "%(localmbox)" 0 | sed 's/^<\(.*\)>$/\1/'` #### Use sendmail/pipe below to override default mts. mts_fakesendmail="${MHMTSCONF}-fakesendmail" sed -e 's/^mts:.*/mts: sendmail\/pipe/' "${MHMTSCONF}" > "$mts_fakesendmail" printf 'sendmail: %s/test/fakesendmail\n' "$srcdir" >>"$mts_fakesendmail" MHMTSCONF="$mts_fakesendmail" # arguments: dist switches test_dist () { printf 'send\n' | run_prog dist "$@" >/dev/null # fakesendmail drops the message and any cc's into this mbox. mbox="${MH_TEST_DIR}"/Mail/fakesendmail.mbox inc -silent -file "$mbox" rm -f "$mbox" # It's hard to calculate the exact Date: header post is going to # use, so we'll just use sed to remove the actual date so we can # easily compare it against our "correct" output. sed -e 's/^Resent-Date:.*/Resent-Date:/' `mhpath last` > "$actual" check "$expected" "$actual" } # check -help cat >"$expected" <&1 | sed '/^$/,$d' >"$actual" check "$expected" "$actual" # check -version case `dist -v` in dist\ --*) ;; * ) printf '%s: dist -v generated unexpected output\n' "$0" >&2 failed=`expr ${failed:-0} + 1`;; esac # check unknown switch run_test "dist -nonexistent" 'dist: -nonexistent unknown' folder +outbox -create -fast >/dev/null folder +inbox -fast 1 >/dev/null # For most tests, use -nowhatnow and just check that the draft # looks correct. # check basic dist operation, including -noedit and -to cat >"$expected" < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 1@test.nmh Subject: Testing message 1 Resent-From: ${localmbox} Resent-To: somebody@example.com Resent-Date: This is message number 1 EOF test_dist -noedit -to somebody@example.com # check +folder and msg folder +outbox -fast >/dev/null cat >"$expected" < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 1@test.nmh Subject: Testing message 1 Resent-From: ${localmbox} Resent-To: somebody@example.com Resent-Date: This is message number 1 EOF test_dist +inbox 1 -noedit -to somebody@example.com # check -form cat >"${MH_TEST_DIR}/Mail/distform" <<'EOF' Resent-From: me@example.com Resent-To: you@example.com EOF cat >"$expected" < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 1@test.nmh Subject: Testing message 1 Resent-From: me@example.com Resent-To: you@example.com Resent-Date: This is message number 1 EOF test_dist 1 -noedit -form "${MH_TEST_DIR}"/Mail/distform rm "${MH_TEST_DIR}"/Mail/distform # check -annotate cat >"$expected" < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 2@test.nmh Subject: Testing message 2 Resent-From: ${localmbox} Resent-To: somebody@example.com Resent-Date: This is message number 2 EOF test_dist 2 -noedit -to somebody@example.com -annotate cat >"$expected" < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 2@test.nmh Subject: Testing message 2 This is message number 2 EOF # The annotation is done by a separate process, so we need to wait for # it to complete. i=1 until grep '^Resent:' "${MH_TEST_DIR}"/Mail/inbox/2 >/dev/null; do sleep 2 arith_eval $i + 1 i=$arith_val if [ $i -gt 60 ]; then printf '%s: -annotate failed, will not wait any longer\n' "$0" break fi done # Strip date from line of this form: # Resent: Sat, 06 Oct 2012 08:24:08 -0500 sed -e 's/^Resent:.*:.*/Resent:/' "${MH_TEST_DIR}"/Mail/inbox/2 >"$actual" check "$expected" "$actual" # check -noannotate cat >"$expected" < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 1@test.nmh Subject: Testing message 1 Resent-From: ${localmbox} Resent-To: somebody@example.com Resent-Date: This is message number 1 EOF test_dist 1 -noedit -to somebody@example.com -annotate -noannotate cat >"$expected" < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 1@test.nmh Subject: Testing message 1 This is message number 1 EOF check "${MH_TEST_DIR}"/Mail/inbox/1 "$expected" 'keep first' check_for_hard_links if [ $hard_links_supported -eq 1 ]; then # check -noinplace # Hard link the message and verify that the new one doesn't get annotated. cp "${MH_TEST_DIR}/Mail/inbox/8" "${MH_TEST_DIR}/Mail/inbox/8.copy" ln "${MH_TEST_DIR}/Mail/inbox/8" "${MH_TEST_DIR}/Mail/inbox/8.link" cat >"$expected" < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 8@test.nmh Subject: Testing message 8 Resent-From: ${localmbox} Resent-To: somebody@example.com Resent-Date: This is message number 8 EOF test_dist 8 -noedit -to somebody@example.com -annotate -noinplace mv -f "${MH_TEST_DIR}/Mail/inbox/8.copy" "${MH_TEST_DIR}/Mail/inbox/8" check "${MH_TEST_DIR}/Mail/inbox/8" "${MH_TEST_DIR}/Mail/inbox/8.link" \ 'keep first' # check -inplace # Hard link the message and verify that the new one does get annotated. ln "${MH_TEST_DIR}/Mail/inbox/9" "${MH_TEST_DIR}/Mail/inbox/9.link" cat >"$expected" < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 9@test.nmh Subject: Testing message 9 Resent-From: ${localmbox} Resent-To: somebody@example.com Resent-Date: This is message number 9 EOF test_dist 9 -noedit -to somebody@example.com -annotate -noinplace -inplace check "${MH_TEST_DIR}/Mail/inbox/9" "${MH_TEST_DIR}/Mail/inbox/9.link" fi # check -draftfolder cat >"$expected" < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 3@test.nmh Subject: Testing message 3 Resent-From: ${localmbox} Resent-To: somebody@example.com Resent-Date: This is message number 3 EOF test_dist 3 -noedit -to somebody@example.com -draftfolder drafts # check -draftmsg cat >"$expected" < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 3@test.nmh Subject: Testing message 3 Resent-From: ${localmbox} Resent-To: somebody@example.com Resent-Date: This is message number 3 EOF touch $MH_TEST_DIR/Mail/drafts/3 test_dist 3 -noedit -to somebody@example.com -draftfolder drafts -draftmessage 2 # check -nodraftfolder cat >"$expected" < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 3@test.nmh Subject: Testing message 3 Resent-From: ${localmbox} Resent-To: somebody@example.com Resent-Date: This is message number 3 EOF test_dist 3 -noedit -to somebody@example.com -draftfolder nonexistent \ -nodraftfolder if test -d "${MH_TEST_DIR}/Mail/nonexistent"; then echo "$0: -nodraftfolder test failed." failed=`expr ${failed:-0} + 1` fi # check -from cat >"$expected" < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 1@test.nmh Subject: Testing message 1 Resent-From: me@example.com Resent-To: somebody@example.com Resent-Date: This is message number 1 EOF test_dist 1 -noedit -to somebody@example.com -from me@example.com # check -cc cat >"$expected" < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 1@test.nmh Subject: Testing message 1 Resent-From: ${localmbox} Resent-To: somebody@example.com Resent-cc: cc@example.com Resent-Date: This is message number 1 EOF test_dist 1 -noedit -to somebody@example.com -cc cc@example.com # check -fcc cat >"$expected" < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 1@test.nmh Subject: Testing message 1 Resent-From: ${localmbox} Resent-To: somebody@example.com Resent-Date: This is message number 1 EOF test_dist 1 -noedit -to somebody@example.com -fcc outbox run_test 'scan +outbox -width 6' ' 1 ' cat >"$expected" < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 1@test.nmh Subject: Testing message 1 Resent-From: ${localmbox} Resent-To: somebody@example.com Resent-Date: This is message number 1 EOF test_dist +inbox 1 -noedit -to somebody@example.com -fcc +outbox run_test 'scan +outbox -width 6 2' ' 2 ' # # Check that dist encodes headers using RFC-2047 properly # require_locale en_US.UTF-8 en_US.UTF8 en_US.utf-8 en_US.utf8 cat >"$expected" < To: Some User Date: Fri, 29 Sep 2006 00:00:00 Message-Id: 1@test.nmh Subject: Testing message 1 Resent-From: =?UTF-8?Q?Mr_F=C3=B8o_Bar?= Resent-To: =?UTF-8?Q?Mr_Nobod=C3=BF?= Resent-Date: This is message number 1 EOF test_dist +inbox 1 -noedit -from 'Mr Føo Bar ' \ -to 'Mr Nobodÿ ' -fcc +outbox exit ${failed:-0} nmh-1.7.1-RC3/test/comp/test-comp-format000755 007761 000024 00000006353 13205305704 020034 0ustar00kenhstaff000000 000000 #!/bin/sh # # Tests to see if the -from, -to, -cc, -fcc, and -subject switches to # "comp" work 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 check_exit '-eq 1' comp - check_exit '-eq 1' comp -xyzzy check_exit '-eq 0' comp -help check_exit '-eq 0' comp -version check_exit '-eq 1' comp -build -noedit -editor check_exit '-eq 1' comp -whatnowproc check_exit '-eq 1' comp -whatnowproc '' - check_exit '-eq 1' comp -use -nouse -form check_exit '-eq 1' comp -file check_exit '-eq 1' comp -file foo -file check_exit '-eq 1' comp -nodraftfolder -draftfolder check_exit '-eq 1' comp -draftfolder foo -draftfolder check_exit '-eq 1' comp -draftmessage check_exit '-eq 1' comp -draftmessage foo -draftmessage check_exit '-eq 1' comp -to check_exit '-eq 1' comp -cc check_exit '-eq 1' comp -from check_exit '-eq 1' comp -fcc check_exit '-eq 1' comp -fcc @ - check_exit '-eq 1' comp -width check_exit '-eq 1' comp -width 0 check_exit '-eq 1' comp -subject check_exit '-eq 1' comp + @ check_exit '-eq 1' comp 42 314 check_exit '-eq 1' comp -form foo 42 check_exit '-eq 1' comp + check_exit '-eq 1' comp 42 # # Create a test template file (we create one here just in case the master # one changes) # form="${MH_TEST_DIR}/$$.components" cat > $form < $expected < $form <%(void(width))%(putaddr From: ) %<{to}%(void(width))%(putaddr To: )%|To:%> %<{cc}%(void(width))%(putaddr cc: )%|cc:%> Subject:%<{subject} %(putstr)%> -------- EOF #### There won't be an Fcc: header because there isn't one in the components. cat > $expected < "${MH_TEST_DIR}/Mail/inbox/11" < To: Test Recipient Date: Friday, 29 Sep 2006 00:00:00 Subject: Test digest ------- Message one From: Mister Burster To: Nobody 1 Date: Thursday, 28 Sep 2006 00:01:00 Subject: Message one This is message one ------- Message two From: Mister Burster To: Nobody 2 Date: Thursday, 28 Sep 2006 00:02:00 Subject: Message two This is message two For real. ------- End of all messages EOF run_prog burst 11 || exit run_test 'scan -width 80 11-last' "\ 11 09/29 Test Burst Messag Test digest<<------- Message one From: Mister Bur 12+ 09/28 Mister Burster Message one<> 13 09/28 Mister Burster Message two<>" # # Create another test message that stresses the boundary checker a bit # cat > "${MH_TEST_DIR}/Mail/inbox/14" < To: Test Recipient Date: Friday, 29 Sep 2006 00:00:00 Subject: Test digest This is a preamble ------- Message one From: Mister Burster To: Nobody 1 Date: Thursday, 28 Sep 2006 00:01:00 Subject: Message one - -This is message one ------- Message two From: Mister Burster To: Nobody 2 Date: Thursday, 28 Sep 2006 00:02:00 Subject: Message two This is message two - For real. ------- Message three From: Mister Burster To: Nobody 3 Date: Thursday, 28 Sep 2006 00:03:00 Subject: Message three Will this one work? ------ Message three End of all messages EOF run_prog burst 14 || exit run_test 'scan -width 80 14-last' "\ 14 09/29 Test Burst Messag Test digest<> 16 09/28 Mister Burster Message two<> 17 09/28 Mister Burster Message three<>" # # Check to see if each message is what we expect # run_test 'show -noheader -noshow 15' \ "From: Mister Burster To: Nobody 1 Date: Thursday, 28 Sep 2006 00:01:00 Subject: Message one -This is message one" run_test 'show -noheader -noshow 16' \ "From: Mister Burster To: Nobody 2 Date: Thursday, 28 Sep 2006 00:02:00 Subject: Message two This is message two For real." # # Backticks used by run_test can consume blank lines at the end of the # command output, so use check for this one. # expected="${MH_TEST_DIR}/$$.expected" cat > "${expected}" < To: Nobody 3 Date: Thursday, 28 Sep 2006 00:03:00 Subject: Message three Will this one work? EOF check "${expected}" `mhpath 17` exit $failed nmh-1.7.1-RC3/test/burst/test-burst-mime000755 007761 000024 00000006404 13205305704 020072 0ustar00kenhstaff000000 000000 #!/bin/sh # # Tests to see if bursting MIME messages works correctly. # 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 # # Create a one-part test message that we can burst # cat > "${MH_TEST_DIR}/Mail/inbox/11" < To: Test Recipient Date: Friday, 29 Sep 2006 00:00:00 Subject: Test MIME digest MIME-Version: 1.0 Content-type: message/rfc822 From: Mister Burster To: Nobody 1 Date: Thursday, 28 Sep 2006 00:01:00 Subject: Message one - - This line should not be unstuffed EOF run_prog burst 11 run_test 'scan -width 80 11-last' "\ 11 09/29 Test Burst Messag Test MIME digest< "${MH_TEST_DIR}/Mail/inbox/14" < To: Test Recipient Date: Friday, 29 Sep 2006 00:00:00 Subject: Test digest MIME-Version: 1.0 Content-Type: multipart/digest; boundary="----- =_aaaaaaaaaa0" This is a preamble ------- =_aaaaaaaaaa0 Content-Type: message/rfc822 From: Mister Burster To: Nobody 1 Date: Thursday, 28 Sep 2006 00:01:00 Subject: Message one - -This is message one ------- =_aaaaaaaaaa0 From: Mister Burster To: Nobody 2 Date: Thursday, 28 Sep 2006 00:02:00 Subject: Message two This is message two - For real. ------- =_aaaaaaaaaa0 From: Mister Burster To: Nobody 3 Date: Thursday, 28 Sep 2006 00:03:00 Subject: Message three Will this one work? ------- =_aaaaaaaaaa0-- EOF run_prog burst 14 || exit run_test 'scan -width 80 14-last' "\ 14 09/29 Test Burst Messag Test digest<> 16 09/28 Mister Burster Message two<> 17 09/28 Mister Burster Message three<>" # # Check to see if each message is what we expect # run_test 'show -noheader -noshow 15' \ "From: Mister Burster To: Nobody 1 Date: Thursday, 28 Sep 2006 00:01:00 Subject: Message one - -This is message one" run_test 'show -noheader -noshow 16' \ "From: Mister Burster To: Nobody 2 Date: Thursday, 28 Sep 2006 00:02:00 Subject: Message two This is message two - For real." # # The CR/LF that appears right before the boundary line is considered part # of the boundary line, so this has the practical effect of "eating" a # blank line if it's before the boundary (RFC 2046. 5.1.1). So make sure # a double blank line results in only one blank line at the end of a message. # expected="${MH_TEST_DIR}/$$.expected" cat > "${expected}" < To: Nobody 3 Date: Thursday, 28 Sep 2006 00:03:00 Subject: Message three Will this one work? EOF check "${expected}" `mhpath 17` exit $failed nmh-1.7.1-RC3/test/bad-input/test-header000755 007761 000024 00000010376 13205305704 017765 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # 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 fi . "$MH_OBJ_DIR/test/common.sh" setup_test 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="$MH_TEST_DIR/Mail/inbox/11" cat >"$msgfile" <"$expected" < "$actual" 2>&1 check "$expected" "$actual" : scan with bogus header field # check show (mhl) start_test show cat >"$expected" < "$actual" 2>&1 check "$expected" "$actual" : "show (mhl) with bogus header field" # check mhshow start_test mhshow cat >"$expected" < "$actual" 2>&1 check "$expected" "$actual" : mhshow with bogus header field # check m_getfld() handling of empty header field start_test '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" <"$expected_err" <"$actual" 2>"$actual_err" check "$expected" "$actual" : m_getfld, empty header output check "$expected_err" "$actual_err" : m_getfld, empty header error # check m_getfld() handling of excessively long header field name start_test 'm_getfld() handling of excessively long header field name' msgfile="$MH_TEST_DIR/Mail/inbox/13" cat >"$msgfile" <"$expected" <"$actual" 2>"$actual_err" check "$expected" "$actual" : m_getfld with excessively long header field name # 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" finish_test exit $failed nmh-1.7.1-RC3/test/anno/test-anno000755 007761 000024 00000016714 13240377167 016555 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test anno # ###################################################### 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 check_exit '-eq 1' anno - check_exit '-eq 1' anno -comp check_exit '-eq 1' anno -comp foo -comp bar check_exit '-eq 1' anno -text check_exit '-eq 1' anno -text foo -text bar check_exit '-eq 1' anno -number 0 check_exit '-eq 1' anno -number -number check_exit '-eq 1' anno + @ check_exit '-eq 1' anno -draft 42 check_exit '-eq 1' anno -draft -list "$expected" <&1 | sed '/^$/,$d' >"$actual" check "$expected" "$actual" # check -version case `anno -v` in anno\ --*) ;; * ) printf '%s: anno -v generated unexpected output\n' "$0" >&2 failed=`expr ${failed:-0} + 1`;; esac # check unknown switch run_test "anno -nonexistent" 'anno: -nonexistent unknown' cat "${MH_TEST_DIR}/Mail/inbox/1" >"${MH_TEST_DIR}/Mail/inbox/11" # check with no switches printf 'Nmh-test:\n' >"$expected" cat "${MH_TEST_DIR}/Mail/inbox/1" >>"$expected" folder -fast 1 >/dev/null printf 'Nmh-test' | run_prog anno >/dev/null sed -e 's/^Nmh-test:.*/Nmh-test:/' "${MH_TEST_DIR}/Mail/inbox/1" >"$actual" check "$expected" "$actual" 'keep first' cp -f "${MH_TEST_DIR}/Mail/inbox/11" "${MH_TEST_DIR}/Mail/inbox/1" # check -component run_prog anno -component Nmh-test sed -e 's/^Nmh-test:.*/Nmh-test:/' "${MH_TEST_DIR}/Mail/inbox/1" >"$actual" check "$expected" "$actual" 'keep first' cp -f "${MH_TEST_DIR}/Mail/inbox/11" "${MH_TEST_DIR}/Mail/inbox/1" # check +folder run_prog anno -component Nmh-test +inbox sed -e 's/^Nmh-test:.*/Nmh-test:/' "${MH_TEST_DIR}/Mail/inbox/1" >"$actual" check "$expected" "$actual" 'keep first' cp -f "${MH_TEST_DIR}/Mail/inbox/11" "${MH_TEST_DIR}/Mail/inbox/1" # check msg folder -fast 2 >/dev/null run_prog anno 1 -component Nmh-test sed -e 's/^Nmh-test:.*/Nmh-test:/' "${MH_TEST_DIR}/Mail/inbox/1" >"$actual" check "$expected" "$actual" 'keep first' cp -f "${MH_TEST_DIR}/Mail/inbox/11" "${MH_TEST_DIR}/Mail/inbox/1" check_for_hard_links if [ $hard_links_supported -eq 1 ]; then # check -noinplace # Hard link the message and verify that the new one doesn't get annotated. cp "${MH_TEST_DIR}/Mail/inbox/8" "${MH_TEST_DIR}/Mail/inbox/8.copy" ln "${MH_TEST_DIR}/Mail/inbox/8" "${MH_TEST_DIR}/Mail/inbox/8.link" run_prog anno 8 -component Nmh-test -noinplace mv -f "${MH_TEST_DIR}/Mail/inbox/8.copy" "${MH_TEST_DIR}/Mail/inbox/8" check "${MH_TEST_DIR}/Mail/inbox/8" "${MH_TEST_DIR}/Mail/inbox/8.link" \ 'keep first' # check -inplace # Hard link the message and verify that the new one does get annotated. ln "${MH_TEST_DIR}/Mail/inbox/8" "${MH_TEST_DIR}/Mail/inbox/8.link" run_prog anno 8 -component Nmh-test -noinplace -inplace check "${MH_TEST_DIR}/Mail/inbox/8" "${MH_TEST_DIR}/Mail/inbox/8.link" fi # check -nodate. Without -text, it doesn't change the message. cp -f "${MH_TEST_DIR}/Mail/inbox/11" "$expected-nodate" run_prog anno 1 -component Nmh-test -nodate cp -f "${MH_TEST_DIR}/Mail/inbox/1" "$actual" check "$expected-nodate" "$actual" cp -f "${MH_TEST_DIR}/Mail/inbox/11" "${MH_TEST_DIR}/Mail/inbox/1" # check -date run_prog anno 1 -component Nmh-test -nodate -date sed -e 's/^Nmh-test:.*/Nmh-test:/' "${MH_TEST_DIR}/Mail/inbox/1" >"$actual" check "$expected" "$actual" 'keep first' cp -f "${MH_TEST_DIR}/Mail/inbox/11" "${MH_TEST_DIR}/Mail/inbox/1" # check -draft. cp -f "${MH_TEST_DIR}/Mail/inbox/1" "${MH_TEST_DIR}/Mail/draft" run_prog anno -draft -component Nmh-test sed -e 's/^Nmh-test:.*/Nmh-test:/' "${MH_TEST_DIR}/Mail/draft" >"$actual" check "$expected" "$actual" rm "${MH_TEST_DIR}/Mail/draft" # check -append sed -e 's/\(Subject: Testing message 1\)/\1\ Nmh-test:/' <"${MH_TEST_DIR}/Mail/inbox/1" >"$expected" run_prog anno 1 -component Nmh-test -append sed -e 's/^Nmh-test:.*/Nmh-test:/' "${MH_TEST_DIR}/Mail/inbox/1" >"$actual" check "$expected" "$actual" cp -f "${MH_TEST_DIR}/Mail/inbox/11" "${MH_TEST_DIR}/Mail/inbox/1" # check -list printf 'Nmh-test: test of anno -list\n' >"$expected" cat "${MH_TEST_DIR}/Mail/inbox/1" >>"$expected" run_prog anno 1 -component Nmh-test -nodate -text 'test of anno -list' run_test 'anno 1 -component Nmh-test -list' 'test of anno -list' # check -text check "$expected" "${MH_TEST_DIR}/Mail/inbox/1" cp -f "${MH_TEST_DIR}/Mail/inbox/11" "${MH_TEST_DIR}/Mail/inbox/1" # check -list -number printf 'Nmh-test: test of anno -list -number\n' >"$expected" cat "${MH_TEST_DIR}/Mail/inbox/1" >>"$expected" run_prog anno 1 -component Nmh-test -nodate -text 'test of anno -list -number' run_test 'anno 1 -component Nmh-test -list -number' \ '1 test of anno -list -number' check "$expected" "${MH_TEST_DIR}/Mail/inbox/1" cp -f "${MH_TEST_DIR}/Mail/inbox/11" "${MH_TEST_DIR}/Mail/inbox/1" # check -delete cp "${MH_TEST_DIR}/Mail/inbox/1" "$expected" run_prog anno 1 -component Nmh-test run_prog anno 1 -component Nmh-test -delete sed -e 's/^Nmh-test:.*/Nmh-test:/' "${MH_TEST_DIR}/Mail/inbox/1" >"$actual" check "$expected" "$actual" cp -f "${MH_TEST_DIR}/Mail/inbox/11" "${MH_TEST_DIR}/Mail/inbox/1" # check -delete -number printf 'Nmh-test: 1\nNmh-test: 3\n' >"$expected" cat "${MH_TEST_DIR}/Mail/inbox/1" >>"$expected" run_prog anno 1 -component Nmh-test -nodate -text 3 run_prog anno 1 -component Nmh-test -nodate -text 2 run_prog anno 1 -component Nmh-test -nodate -text 1 run_prog anno 1 -component Nmh-test -delete -number 2 cp -f "${MH_TEST_DIR}/Mail/inbox/1" "$actual" check "$expected" "$actual" cp -f "${MH_TEST_DIR}/Mail/inbox/11" "${MH_TEST_DIR}/Mail/inbox/1" # check -delete -all cp "${MH_TEST_DIR}/Mail/inbox/1" "$expected" run_prog anno 1 -component Nmh-test -nodate -text 3 run_prog anno 1 -component Nmh-test -nodate -text 2 run_prog anno 1 -component Nmh-test -nodate -text 1 run_prog anno 1 -component Nmh-test -delete -number all cp -f "${MH_TEST_DIR}/Mail/inbox/1" "$actual" check "$expected" "$actual" cp -f "${MH_TEST_DIR}/Mail/inbox/11" "${MH_TEST_DIR}/Mail/inbox/1" # check -preserve touch -t '201210010000.00' "${MH_TEST_DIR}/Mail/inbox/1" ls -l "${MH_TEST_DIR}/Mail/inbox/1" >"$actual-ls1" run_prog anno 1 -component Nmh-test -preserve run_prog anno 1 -component Nmh-test -preserve -delete ls -l "${MH_TEST_DIR}/Mail/inbox/1" >"$actual-ls2" check "$actual-ls1" "$actual-ls2" cp -f "${MH_TEST_DIR}/Mail/inbox/11" "${MH_TEST_DIR}/Mail/inbox/1" # check -nopreserve touch -t '2012100100.00' "${MH_TEST_DIR}/Mail/inbox/1" ls -l "${MH_TEST_DIR}/Mail/inbox/1" >"$actual-ls1" run_prog anno 1 -component Nmh-test -preserve -nopreserve run_prog anno 1 -component Nmh-test -preserve -nopreserve -delete ls -l "${MH_TEST_DIR}/Mail/inbox/1" >"$actual-ls2" set +e diff "$actual-ls1" "$actual-ls2" >/dev/null run_test 'printf 1' "$?" set -e rm "$actual-ls1" "$actual-ls2" exit ${failed:-0} nmh-1.7.1-RC3/test/ali/test-ali000755 007761 000024 00000006727 13240377167 016204 0ustar00kenhstaff000000 000000 #!/bin/sh ###################################################### # # Test ali # ###################################################### # Not tested: # -normalize, -nonormalize 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 check_exit '-eq 1' ali - check_exit '-eq 1' ali -noalias -alias check_exit '-eq 1' ali -user check_exit '-eq 1' ali -user '' check_exit '-eq 1' ali -user 'foo bar' check_exit '-eq 0' ali -user foo,bar expected=$MH_TEST_DIR/$$.expected expected_err=$MH_TEST_DIR/$$.expected_err actual=$MH_TEST_DIR/$$.actual actual_err=$MH_TEST_DIR/$$.actual_err # check -help cat >$expected <&1 | sed '/^$/,$d' >"$actual" check "$expected" "$actual" # check -version case `ali -v` in ali\ --*) ;; * ) echo "$0: ali -v generated unexpected output" 1>&2 failed=`expr ${failed:-0} + 1`;; esac # check unknown option run_test 'ali -nonexistent' 'ali: -nonexistent unknown' # check with no arguments and no AliasFile profile component run_test 'ali' '' # check with nonexistent alias file run_test 'ali -alias nonexistent' \ "ali: aliasing error in nonexistent - unable to read 'nonexistent'" cat >"${MH_TEST_DIR}/Mail/aliases" <"${MH_TEST_DIR}/Mail/aliases" <"${MH_TEST_DIR}/Mail/aliases" < nmh_files %clean rm -rf $RPM_BUILD_ROOT $RPM_BUILD_DIR/%buildsubdir %files -f nmh_files %defattr(-,root,root,-) %config(noreplace) %_sysconfdir/* nmh-1.7.1-RC3/sbr/addrsbr.c000644 007761 000024 00000024401 13243042053 015332 0ustar00kenhstaff000000 000000 /* addrsbr.c -- parse addresses 822-style * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include /* High level parsing of addresses: The routines in sbr/mf.c parse the syntactic representations of addresses. The routines in sbr/addrsbr.c associate semantics with those addresses. The comments below are left in for historical purposes; DUMB and REALLYDUMB are now the default in the code. If #ifdef DUMB is in effect, a full 822-style parser is called for syntax recognition. This breaks each address into its components. Note however that no semantics are assumed about the parts or their totality. This means that implicit hostnames aren't made explicit, and explicit hostnames aren't expanded to their "official" representations. If DUMB is not in effect, then this module does some high-level thinking about what the addresses are. 1. for MMDF systems: string%@ -> string 2. for non-MMDF systems: string@host. -> host!string 3. for any system, an address interpreted relative to the local host: string@ -> string For cases (1) and (3) above, the leftmost host is extracted. If it's not present, the local host is used. If the tests above fail, the address is considered to be a real 822-style address. If an explicit host is not present, then MH checks for a bang to indicate an explicit UUCP-style address. If so, this is noted. If not, the host is defaulted, typically to the local host. The lack of an explicit host is also noted. If an explicit 822-style host is present, then MH checks to see if it can expand this to the official name for the host. If the hostname is unknown, the address is so typed. To summarize, when we're all done, here's what MH knows about the address: DUMB - type: local, uucp, or network host: not locally defaulted, not explicitly expanded everything else other - type: local, uucp, network, unknown everything else */ static int ingrp = 0; static char *pers = NULL; static char *mbox = NULL; static char *host = NULL; static char *route = NULL; static char *grp = NULL; static char *note = NULL; static char err[BUFSIZ]; static char adr[BUFSIZ]; static int eai = 0; void enable_eai(void) { eai = 1; } char * getname (const char *addrs) { struct adrx *ap; pers = mbox = host = route = grp = note = NULL; err[0] = '\0'; if ((ap = getadrx (FENDNULL(addrs), eai)) == NULL) { return NULL; } strncpy (adr, ap->text, sizeof(adr)); pers = ap->pers; mbox = ap->mbox; host = ap->host; route = ap->path; grp = ap->grp; ingrp = ap->ingrp; note = ap->note; if (ap->err && *ap->err) strncpy (err, ap->err, sizeof(err)); return adr; } struct mailname * getm (char *str, char *dfhost, int dftype, char *eresult, size_t eresultsize) { char *pp; struct mailname *mp; if (err[0]) { if (eresult) { strncpy (eresult, err, eresultsize); eresult[eresultsize - 1] = '\0'; } return NULL; } if (pers == NULL && mbox == NULL && host == NULL && route == NULL && grp == NULL) { if (eresult) { strncpy (eresult, "null address", eresultsize); eresult[eresultsize - 1] = '\0'; } return NULL; } if (mbox == NULL && grp == NULL) { if (eresult) { strncpy (eresult, "no mailbox in address", eresultsize); eresult[eresultsize - 1] = '\0'; } return NULL; } if (dfhost == NULL) { dfhost = LocalName (0); dftype = LOCALHOST; } NEW0(mp); mp->m_next = NULL; mp->m_text = getcpy (str); if (pers) mp->m_pers = mh_xstrdup(pers); if (mbox == NULL) { mp->m_type = BADHOST; mp->m_nohost = 1; mp->m_ingrp = ingrp; mp->m_gname = getcpy (grp); if (note) mp->m_note = mh_xstrdup(note); return mp; } if (host) { mp->m_mbox = getcpy (mbox); mp->m_host = mh_xstrdup(host); mp->m_type = strcasecmp (LocalName(0), mp->m_host) ? NETHOST : LOCALHOST; } else { if ((pp = strchr(mbox, '!'))) { *pp++ = '\0'; mp->m_mbox = mh_xstrdup(pp); mp->m_host = getcpy (mbox); mp->m_type = UUCPHOST; } else { mp->m_nohost = 1; mp->m_mbox = getcpy (mbox); if (route == NULL && dftype == LOCALHOST) { mp->m_host = NULL; mp->m_type = dftype; } else { mp->m_host = route ? NULL : getcpy (dfhost); mp->m_type = route ? NETHOST : dftype; } } } /* For alternate mailboxes, m_type gets overwritten in ismymbox () to support wild-card matching. */ if (route) mp->m_path = mh_xstrdup(route); mp->m_ingrp = ingrp; if (grp) mp->m_gname = mh_xstrdup(grp); if (note) mp->m_note = mh_xstrdup(note); return mp; } void mnfree (struct mailname *mp) { if (!mp) return; mh_xfree(mp->m_text); mh_xfree(mp->m_pers); mh_xfree(mp->m_mbox); mh_xfree(mp->m_host); mh_xfree(mp->m_path); mh_xfree(mp->m_gname); mh_xfree(mp->m_note); free(mp); } char * auxformat (struct mailname *mp, int extras) { static char addr[BUFSIZ]; static char buffer[BUFSIZ]; if (mp->m_nohost) strncpy (addr, FENDNULL(mp->m_mbox), sizeof(addr)); else if (mp->m_type != UUCPHOST) { if (mp->m_host) snprintf (addr, sizeof(addr), "%s%s@%s", FENDNULL(mp->m_path), FENDNULL(mp->m_mbox), mp->m_host); else snprintf (addr, sizeof(addr), "%s%s", FENDNULL(mp->m_path), FENDNULL(mp->m_mbox)); } else snprintf (addr, sizeof(addr), "%s!%s", mp->m_host, mp->m_mbox); if (!extras) return addr; if (mp->m_pers || mp->m_path) { if (mp->m_note) snprintf (buffer, sizeof(buffer), "%s %s <%s>", legal_person (mp->m_pers ? mp->m_pers : mp->m_mbox), mp->m_note, addr); else snprintf (buffer, sizeof(buffer), "%s <%s>", legal_person (mp->m_pers ? mp->m_pers : mp->m_mbox), addr); } else if (mp->m_note) snprintf (buffer, sizeof(buffer), "%s %s", addr, mp->m_note); else strncpy (buffer, addr, sizeof(buffer)); return buffer; } #define W_NIL 0x0000 #define W_MBEG 0x0001 #define W_MEND 0x0002 #define W_MBOX (W_MBEG | W_MEND) #define W_HBEG 0x0004 #define W_HEND 0x0008 #define W_HOST (W_HBEG | W_HEND) #define WBITS "\020\01MBEG\02MEND\03HBEG\04HEND" /* * Check if this is my address */ int ismymbox (struct mailname *np) { int oops; int len, i; char *cp; char *pp; char buffer[BUFSIZ]; struct mailname *mp; static char *am = NULL; static struct mailname mq; static int localmailbox = 0; /* * If this is the first call, initialize * list of alternate mailboxes. */ if (am == NULL) { mq.m_next = NULL; mq.m_mbox = getusername (); if ((am = context_find ("local-mailbox"))) { localmailbox++; if ((cp = getname(am)) == NULL) { inform("Unable to find address in local-mailbox, continuing..."); return 0; } if ((mq.m_next = getm (cp, NULL, 0, NULL, 0)) == NULL) { inform("invalid entry in local-mailbox: %s, continuing...", cp); return 0; } /* Sigh, it turns out that the address parser gets messed up * if you don't call getname() until it returns NULL. */ while (getname(am) != NULL) ; } if ((am = context_find ("alternate-mailboxes")) == NULL) am = getusername(); else { mp = mq.m_next ? mq.m_next : &mq; oops = 0; while ((cp = getname (am))) { if ((mp->m_next = getm (cp, NULL, 0, NULL, 0)) == NULL) { inform("illegal address: %s, continuing...", cp); oops++; } else { mp = mp->m_next; mp->m_type = W_NIL; if (*mp->m_mbox == '*') { mp->m_type |= W_MBEG; mp->m_mbox++; } if (*(cp = mp->m_mbox + strlen (mp->m_mbox) - 1) == '*') { mp->m_type |= W_MEND; *cp = '\0'; } if (mp->m_host) { if (*mp->m_host == '*') { mp->m_type |= W_HBEG; mp->m_host++; } if (*(cp = mp->m_host + strlen (mp->m_host) - 1) == '*') { mp->m_type |= W_HEND; *cp = '\0'; } } } } if (oops) inform("please fix the %s: entry in your %s file", "alternate-mailboxes", mh_profile); } if ((cp = getenv ("MHWDEBUG")) && *cp) { for (mp = &mq; mp; mp = mp->m_next) { fprintf (stderr, "Local- or Alternate-Mailbox: text=\"%s\" " "mbox=\"%s\" host=\"%s\" %s\n", FENDNULL(mp->m_text), mp->m_mbox, FENDNULL(mp->m_host), snprintb (buffer, sizeof(buffer), (unsigned) mp->m_type, WBITS)); } } } if (np == NULL) /* XXX */ return 0; /* * Don't perform this "local" test if we have a Local-Mailbox set */ if (! localmailbox) switch (np->m_type) { case NETHOST: len = strlen (cp = LocalName (0)); if (!uprf (np->m_host, cp) || np->m_host[len] != '.') break; goto local_test; case UUCPHOST: if (strcasecmp (np->m_host, SystemName())) break; /* FALLTHRU */ case LOCALHOST: local_test: ; if (!strcasecmp (np->m_mbox, mq.m_mbox)) return 1; break; default: break; } /* * Now scan through list of alternate * mailboxes, and check for a match. */ for (mp = &mq; mp->m_next;) { mp = mp->m_next; if (!np->m_mbox) continue; if ((len = strlen (cp = np->m_mbox)) < (i = strlen (pp = mp->m_mbox))) continue; switch (mp->m_type & W_MBOX) { case W_NIL: if (strcasecmp (cp, pp)) continue; break; case W_MBEG: if (strcasecmp (cp + len - i, pp)) continue; break; case W_MEND: if (!uprf (cp, pp)) continue; break; case W_MBEG | W_MEND: if (stringdex (pp, cp) < 0) continue; break; } if (mp->m_nohost) return 1; if (np->m_host == NULL || mp->m_host == NULL) continue; if ((len = strlen (cp = np->m_host)) < (i = strlen (pp = mp->m_host))) continue; switch (mp->m_type & W_HOST) { case W_NIL: if (strcasecmp (cp, pp)) continue; break; case W_HBEG: if (strcasecmp (cp + len - i, pp)) continue; break; case W_HEND: if (!uprf (cp, pp)) continue; break; case W_HBEG | W_HEND: if (stringdex (pp, cp) < 0) continue; break; } return 1; } return 0; } nmh-1.7.1-RC3/sbr/ambigsw.c000644 007761 000024 00000000602 13243042053 015337 0ustar00kenhstaff000000 000000 /* ambigsw.c -- report an ambiguous switch * * 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 void ambigsw (const char *arg, const struct swit *swp) { inform("-%s ambiguous. It matches", arg); print_sw (arg, swp, "-", stderr); } nmh-1.7.1-RC3/sbr/arglist.c000644 007761 000024 00000013003 13243042053 015352 0ustar00kenhstaff000000 000000 /* 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 #include /* * 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 + 5))); /* * The simple case - no spaces or shell metacharacters */ if (!space && !metachar) { argvarray[0] = getcpy(r1bindex(command, '/')); argvarray[1] = NULL; *file = mh_xstrdup(command); if (argp) *argp = 1; return argvarray; } /* * Spaces, but no shell metacharacters; space-split into separate * arguments */ if (space && !metachar) { char **split; p = mh_xstrdup(command); split = brkstring(p, " \t", NULL); if (split[0] == NULL) { adios(NULL, "Invalid blank command found"); } argvarray[0] = mh_xstrdup(r1bindex(split[0], '/')); for (i = 1; split[i] != NULL; i++) { if (i > MAXARGS) { adios(NULL, "Command exceeded argument limit"); } argvarray[i] = mh_xstrdup(split[i]); } argvarray[i] = NULL; *file = mh_xstrdup(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 = mh_xstrdup("/bin/sh"); argvarray[0] = mh_xstrdup("sh"); argvarray[1] = mh_xstrdup("-c"); argvarray[2] = mh_xstrdup(command); argvarray[2] = add(" \"$@\"", argvarray[2]); argvarray[3] = mh_xstrdup("/bin/sh"); argvarray[4] = NULL; if (argp) *argp = 4; return argvarray; } /* * Free our argument array */ void arglist_free(char *command, char **argvarray) { int i; mh_xfree(command); if (argvarray != NULL) { for (i = 0; argvarray[i] != NULL; i++) free(argvarray[i]); free(argvarray); } } /* * Similar in functionality to argsplit, but is designed to deal with * a msgs_array. */ void argsplit_msgarg(struct msgs_array *msgs, char *command, char **program) { int argp, i; char **vec; vec = argsplit(command, program, &argp); /* * As usual, there is lousy memory management in nmh. Nothing ever * free's the msgs_array, and a lot of the arguments are allocated * from static memory. I could have app_msgarg() allocate new * memory for each pointer, but for now I decided to stick with * the existing interface; maybe that will be revisited later. * So we'll just copy over our pointers and free the pointer list * (not the actual pointers themselves). Note that we don't * include a trailing NULL, since we are expecting the application * to take care of that. */ for (i = 0; i < argp; i++) { app_msgarg(msgs, vec[i]); } free(vec); } /* * Insert a arglist vector into the beginning of an struct msgs array * * Uses by some programs (e.g., show) who want to decide which proc * to use after the argument vector has been constructed */ #ifndef MAXMSGS #define MAXMSGS 256 #endif void argsplit_insert(struct msgs_array *msgs, char *command, char **program) { int argp, i; char **vec; vec = argsplit(command, program, &argp); /* * Okay, we want to shuffle all of our arguments down so we have room * for argp number of arguments. This means we need to know about * msgs_array internals. If that changes, we need to change this * code here. */ if (msgs->size + argp >= msgs->max) { msgs->max += max(MAXMSGS, argp); msgs->msgs = mh_xrealloc(msgs->msgs, msgs->max * sizeof(*msgs->msgs)); } for (i = msgs->size - 1; i >= 0; i--) msgs->msgs[i + argp] = msgs->msgs[i]; msgs->size += argp; /* * Now fill in the arguments at the beginning of the vector. */ for (i = 0; i < argp; i++) msgs->msgs[i] = vec[i]; free(vec); } nmh-1.7.1-RC3/sbr/atooi.c000644 007761 000024 00000000613 13243042053 015023 0ustar00kenhstaff000000 000000 /* atooi.c -- octal version of atoi() * * 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 int atooi(char *cp) { int i, base; i = 0; base = 8; while (*cp >= '0' && *cp <= '7') { i *= base; i += *cp++ - '0'; } return i; } nmh-1.7.1-RC3/sbr/base64.c000644 007761 000024 00000022325 13243042053 015000 0ustar00kenhstaff000000 000000 /* base64.c -- routines for converting to base64 * * 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 #include #include #include static const char nib2b64[0x40+1] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int writeBase64aux (FILE *in, FILE *out, int crlf) { unsigned int cc, n; unsigned char inbuf[3]; int skipnl = 0; n = BPERLIN; while ((cc = fread (inbuf, sizeof(*inbuf), sizeof(inbuf), in)) > 0) { unsigned long bits; char *bp; char outbuf[4]; if (cc < sizeof(inbuf)) { inbuf[2] = 0; if (cc < sizeof(inbuf) - 1) inbuf[1] = 0; } /* * Convert a LF to a CRLF if desired. That means we need to push * data back into the input stream. */ if (crlf) { unsigned int i; for (i = 0; i < cc; i++) { if (inbuf[i] == '\n' && !skipnl) { inbuf[i] = '\r'; /* * If it's the last character in the buffer, we can just * substitute a \r and push a \n back. Otherwise shuffle * everything down and push the last character back. */ if (i == cc - 1) { /* * If we're at the end of the input, there might be * more room in inbuf; if so, add it there. Otherwise * push it back to the input. */ if (cc < sizeof(inbuf)) inbuf[cc++] = '\n'; else ungetc('\n', in); skipnl = 1; } else { /* This only works as long as sizeof(inbuf) == 3 */ ungetc(inbuf[cc - 1], in); if (cc == 3 && i == 0) inbuf[2] = inbuf[1]; inbuf[++i] = '\n'; } } else { skipnl = 0; } } } bits = (inbuf[0] & 0xff) << 16; bits |= (inbuf[1] & 0xff) << 8; bits |= inbuf[2] & 0xff; for (bp = outbuf + sizeof(outbuf); bp > outbuf; bits >>= 6) *--bp = nib2b64[bits & 0x3f]; if (cc < sizeof(inbuf)) { outbuf[3] = '='; if (cc < sizeof inbuf - 1) outbuf[2] = '='; } if (fwrite (outbuf, sizeof(*outbuf), sizeof(outbuf), out) < sizeof outbuf) { advise ("writeBase64aux", "fwrite"); } if (cc < sizeof(inbuf)) { putc ('\n', out); return OK; } if (--n <= 0) { n = BPERLIN; putc ('\n', out); } } if (n != BPERLIN) putc ('\n', out); return OK; } /* Caller is responsible for ensuring that the out array is long enough. Given length is that of in, out should be have at least this capacity: 4 * [length/3] + length/57 + 2 But double the length will certainly be sufficient. */ int writeBase64 (const unsigned char *in, size_t length, unsigned char *out) { unsigned int n = BPERLIN; while (1) { unsigned long bits; unsigned char *bp; unsigned int cc; for (cc = 0; length > 0 && cc < 3; ++cc, --length) /* empty */ ; if (cc == 0) break; bits = (in[0] & 0xff) << 16; if (cc > 1) { bits |= (in[1] & 0xff) << 8; if (cc > 2) { bits |= in[2] & 0xff; } } for (bp = out + 4; bp > out; bits >>= 6) *--bp = nib2b64[bits & 0x3f]; if (cc < 3) { out[3] = '='; if (cc < 2) out[2] = '='; out += 4; n = 0; break; } in += 3; out += 4; if (--n <= 0) { n = BPERLIN; *out++ = '\n'; } } if (n != BPERLIN) *out++ = '\n'; *out = '\0'; return OK; } /* * Essentially a duplicate of writeBase64, but without line wrapping or * newline termination (note: string IS NUL terminated) */ int writeBase64raw (const unsigned char *in, size_t length, unsigned char *out) { while (1) { unsigned long bits; unsigned char *bp; unsigned int cc; for (cc = 0; length > 0 && cc < 3; ++cc, --length) /* empty */ ; if (cc == 0) break; bits = (in[0] & 0xff) << 16; if (cc > 1) { bits |= (in[1] & 0xff) << 8; if (cc > 2) { bits |= in[2] & 0xff; } } for (bp = out + 4; bp > out; bits >>= 6) *--bp = nib2b64[bits & 0x3f]; if (cc < 3) { out[3] = '='; if (cc < 2) out[2] = '='; out += 4; break; } in += 3; out += 4; } *out = '\0'; return OK; } static const unsigned char b642nib[0x80] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff }; /* * Decode a base64 string. The result, decoded, must be freed by the caller. * See description of arguments with declaration in h/prototypes.h. */ int decodeBase64 (const char *encoded, unsigned char **decoded, size_t *len, int skip_crs, unsigned char *digest) { const char *cp = encoded; int self_delimiting = 0; int bitno, skip; uint32_t bits; /* Size the decoded string very conservatively. */ charstring_t decoded_c = charstring_create (strlen (encoded)); MD5_CTX mdContext; if (digest) MD5Init (&mdContext); bitno = 18; bits = 0L; skip = 0; for (; *cp; ++cp) { switch (*cp) { unsigned char value; default: if (isspace ((unsigned char) *cp)) { break; } if (skip || (((unsigned char) *cp) & 0x80) || (value = b642nib[((unsigned char) *cp) & 0x7f]) > 0x3f) { inform("invalid BASE64 encoding in %s", cp); charstring_free (decoded_c); *decoded = NULL; return NOTOK; } bits |= value << bitno; test_end: if ((bitno -= 6) < 0) { char b = (char) ((bits >> 16) & 0xff); if (! skip_crs || b != '\r') { charstring_push_back (decoded_c, b); } if (digest) MD5Update (&mdContext, (unsigned char *) &b, 1); if (skip < 2) { b = (bits >> 8) & 0xff; if (! skip_crs || b != '\r') { charstring_push_back (decoded_c, b); } if (digest) MD5Update (&mdContext, (unsigned char *) &b, 1); if (skip < 1) { b = bits & 0xff; if (! skip_crs || b != '\r') { charstring_push_back (decoded_c, b); } if (digest) MD5Update (&mdContext, (unsigned char *) &b, 1); } } bitno = 18; bits = 0L; skip = 0; } break; case '=': if (++skip <= 3) goto test_end; self_delimiting = 1; break; } } if (! self_delimiting && bitno != 18) { int i; /* Show some context for the error. */ for (i = 0; i < 20 && cp > encoded; ++i, --cp) {} inform("premature ending (bitno %d) near %s", bitno, cp ? cp : encoded); charstring_free (decoded_c); *decoded = NULL; return NOTOK; } *decoded = (unsigned char *) charstring_buffer_copy (decoded_c); *len = charstring_bytes (decoded_c); charstring_free (decoded_c); if (digest) { MD5Final (digest, &mdContext); } return OK; } /* * Prepare an unsigned char array for display by replacing non-printable * ASCII bytes with their hex representation. Assumes ASCII input. output * is allocated by the function and must be freed by the caller. */ void hexify (const unsigned char *input, size_t len, char **output) { /* Start with a charstring capacity that's arbitrarily larger than len. */ const charstring_t tmp = charstring_create (2 * len); const unsigned char *cp = input; size_t i; for (i = 0; i < len; ++i, ++cp) { if (isascii(*cp) && isprint(*cp)) { charstring_push_back (tmp, (const char) *cp); } else { char s[16]; const int num = snprintf(s, sizeof s, "[0x%02x]", *cp); if (num <= 0 || (unsigned int) num >= sizeof s) { inform("hexify failed to write nonprintable character, needed %d bytes", num + 1); } else { charstring_append_cstring (tmp, s); } } } *output = charstring_buffer_copy (tmp); charstring_free (tmp); } nmh-1.7.1-RC3/sbr/brkstring.c000644 007761 000024 00000003275 13243042053 015724 0ustar00kenhstaff000000 000000 /* brkstring.c -- (destructively) split a string into * -- an array of substrings * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include /* allocate this number of pointers at a time */ #define NUMBROKEN 256 static char **broken = NULL; /* array of substring start addresses */ static int len = 0; /* current size of "broken" */ /* * static prototypes */ static int brkany (char, char *); char ** brkstring (char *str, char *brksep, char *brkterm) { int i; char c, *s; /* allocate initial space for pointers on first call */ if (!broken) { len = NUMBROKEN; broken = (char **) mh_xmalloc ((size_t) (len * sizeof(*broken))); } /* * scan string, replacing separators with zeroes * and enter start addresses in "broken". */ s = str; for (i = 0;; i++) { /* enlarge pointer array, if necessary */ if (i >= len) { len += NUMBROKEN; broken = mh_xrealloc (broken, (size_t) (len * sizeof(*broken))); } while (brkany (c = *s, brksep)) *s++ = '\0'; /* * we are either at the end of the string, or the * terminator found has been found, so finish up. */ if (!c || brkany (c, brkterm)) { *s = '\0'; broken[i] = NULL; break; } /* set next start addr */ broken[i] = s; while ((c = *++s) && !brkany (c, brksep) && !brkany (c, brkterm)) ; /* empty body */ } return broken; } /* * If the character is in the string, * return 1, else return 0. */ static int brkany (char c, char *str) { return str && c && strchr(str, c); } nmh-1.7.1-RC3/sbr/charstring.c000644 007761 000024 00000011127 13243042053 016056 0ustar00kenhstaff000000 000000 /* charstring.c -- dynamically-sized char array that can report size * in both characters and bytes * * This code is Copyright (c) 2014, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #ifdef MULTIBYTE_SUPPORT # define NMH_MAX_CHARWIDTH MB_CUR_MAX #else # define NMH_MAX_CHARWIDTH 1 #endif #define CHARSTRING_DEFAULT_SIZE 64 struct charstring { char *buffer; /* the char array, not always null-terminated */ size_t max; /* current size of the char array, in bytes */ char *cur; /* size in bytes = cur - buffer, without trailing null */ size_t chars; /* size in characters */ }; static void charstring_reserve (charstring_t s, size_t need) { const size_t cur = s->cur - s->buffer; while (need >= s->max - cur) { /* Insufficient capacity, so double it. */ s->buffer = mh_xrealloc (s->buffer, s->max *= 2); s->cur = s->buffer + cur; } } /* * max is in characters */ charstring_t charstring_create (size_t max) { charstring_t s; NEW(s); s->max = NMH_MAX_CHARWIDTH * (max ? max : CHARSTRING_DEFAULT_SIZE); s->cur = s->buffer = mh_xmalloc (s->max); s->chars = 0; return s; } charstring_t charstring_copy (const charstring_t src) { const size_t num = src->cur - src->buffer; charstring_t s; NEW(s); s->max = src->max; s->buffer = mh_xmalloc (s->max); memcpy (s->buffer, src->buffer, num); s->cur = s->buffer + num; s->chars = src->chars; return s; } /* * OK to call charstring_free with a NULL argument. */ void charstring_free (charstring_t s) { if (s) { free (s->buffer); free (s); } } void charstring_push_back (charstring_t s, const char c) { charstring_reserve (s, s->cur - s->buffer + 1); *s->cur++ = c; ++s->chars; } /* * num is the number of bytes in c, width is the display width * occupied by the character(s). */ void charstring_push_back_chars (charstring_t s, const char c[], size_t num, size_t width) { size_t i; charstring_reserve (s, s->cur - s->buffer + num); for (i = 0; i < num; ++i) { *s->cur++ = *c++; } s->chars += width; } void charstring_append (charstring_t dest, const charstring_t src) { const size_t num = src->cur - src->buffer; if (num > 0) { charstring_reserve (dest, dest->cur - dest->buffer + num); memcpy (dest->cur, src->buffer, num); dest->cur += num; dest->chars += src->chars; } } void charstring_append_cstring (charstring_t dest, const char src[]) { const size_t num = strlen (src); if (num > 0) { charstring_reserve (dest, dest->cur - dest->buffer + num); memcpy (dest->cur, src, num); /* Exclude src's trailing newline. */ dest->cur += num; dest->chars += num; } } void charstring_clear (charstring_t s) { s->cur = s->buffer; s->chars = 0; } /* * Don't store return value of charstring_buffer() and use later after * intervening push_back's; use charstring_buffer_copy() instead. */ const char * charstring_buffer (const charstring_t s) { charstring_reserve (s, s->cur - s->buffer + 1); /* This is the only place that we null-terminate the buffer. */ *s->cur = '\0'; /* Don't increment cur so that more can be appended later, and so that charstring_bytes() behaves as strlen() by not counting the null. */ return s->buffer; } char * charstring_buffer_copy (const charstring_t s) { char *copy = mh_xmalloc (s->cur - s->buffer + 1); /* Use charstring_buffer() to null terminate the buffer. */ memcpy (copy, charstring_buffer (s), s->cur - s->buffer + 1); return copy; } size_t charstring_bytes (const charstring_t s) { return s->cur - s->buffer; } size_t charstring_chars (const charstring_t s) { return s->chars; } int charstring_last_char_len (const charstring_t s) { int len = 0; #ifdef MULTIBYTE_SUPPORT const char *sp = charstring_buffer (s); size_t remaining = charstring_bytes (s); if (mbtowc (NULL, NULL, 0)) {} /* reset shift state */ while (*sp && remaining > 0) { wchar_t wide_char; len = mbtowc (&wide_char, sp, (size_t) MB_CUR_MAX < remaining ? (size_t) MB_CUR_MAX : remaining); sp += max(len, 1); remaining -= max(len, 1); } #else /* ! MULTIBYTE_SUPPORT */ if (charstring_bytes (s) > 0) { len = 1; } #endif /* ! MULTIBYTE_SUPPORT */ return len; } nmh-1.7.1-RC3/sbr/check_charset.c000644 007761 000024 00000011676 13243042053 016511 0ustar00kenhstaff000000 000000 /* check_charset.c -- routines for character sets * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include static const char *norm_charmap(char *name); /* * Get the current character set */ char * get_charset(void) { return (char *)norm_charmap(nl_langinfo(CODESET)); } /* * Check if we can display a given character set natively. * We are passed the length of the initial part of the * string to check, since we want to allow the name of the * character set to be a substring of a larger string. */ int check_charset (char *str, int len) { static char *mm_charset = NULL; static char *alt_charset = NULL; static int mm_len; static int alt_len; /* Cache the name of our default character set */ if (!mm_charset) { if (!(mm_charset = get_charset ())) mm_charset = "US-ASCII"; mm_len = strlen (mm_charset); /* US-ASCII is a subset of the ISO-8859-X and UTF-8 character sets */ if (!strncasecmp("ISO-8859-", mm_charset, 9) || !strcasecmp("UTF-8", mm_charset)) { alt_charset = "US-ASCII"; alt_len = strlen (alt_charset); } } /* Check if character set is OK */ if ((len == mm_len) && !strncasecmp(str, mm_charset, mm_len)) return 1; if (alt_charset && (len == alt_len) && !strncasecmp(str, alt_charset, alt_len)) return 1; return 0; } /* * Return the name of the character set we are * using for 8bit text. */ char * write_charset_8bit (void) { static char *mm_charset = NULL; /* * Cache the name of the character set to * use for 8bit text. */ if (!mm_charset && !(mm_charset = get_charset ())) mm_charset = "x-unknown"; return mm_charset; } /* The Single Unix Specification function nl_langinfo(CODESET) * returns the name of the encoding used by the currently selected * locale: * * http://www.opengroup.org/onlinepubs/7908799/xsh/langinfo.h.html * * Unfortunately the encoding names are not yet standardized. * This function knows about the encoding names used on many * different systems and converts them where possible into * the corresponding MIME charset name registered in * * http://www.iana.org/assignments/character-sets * * Please extend it as needed and suggest improvements to the author. * * Markus.Kuhn@cl.cam.ac.uk -- 2002-03-11 * Permission to use, copy, modify, and distribute this software * for any purpose and without fee is hereby granted. The author * disclaims all warranties with regard to this software. * * Latest version: * * http://www.cl.cam.ac.uk/~mgk25/ucs/norm_charmap.c */ static const char *norm_charmap(char *name) { static const char *correct[] = { "UTF-8", "US-ASCII", NULL }, **cor; static struct { const char *alias; const char *name; } *ali, aliases[] = { /* Names for US-ASCII. */ { "ANSI_X3.4-1968", "US-ASCII" }, /* LC_ALL=C. */ { "ASCII", "US-ASCII" }, { "646", "US-ASCII" }, { "ISO646", "US-ASCII" }, { "ISO_646.IRV", "US-ASCII" }, /* Case differs. */ { "BIG5", "Big5" }, { "BIG5HKSCS", "Big5HKSCS" }, /* Names for ISO-8859-11. */ { "TIS-620", "ISO-8859-11" }, { "TIS620.2533", "ISO-8859-11" }, { NULL, NULL } }; static struct { const char *substr; const char *name; } *sub, substrs[] = { { "8859-1", "ISO-8859-1" }, { "8859-2", "ISO-8859-2" }, { "8859-3", "ISO-8859-3" }, { "8859-4", "ISO-8859-4" }, { "8859-5", "ISO-8859-5" }, { "8859-6", "ISO-8859-6" }, { "8859-7", "ISO-8859-7" }, { "8859-8", "ISO-8859-8" }, { "8859-9", "ISO-8859-9" }, { "8859-10", "ISO-8859-10" }, { "8859-11", "ISO-8859-11" }, /* 12, Latin/Devanagari, not completed. */ { "8859-13", "ISO-8859-13" }, { "8859-14", "ISO-8859-14" }, { "8859-15", "ISO-8859-15" }, { "8859-16", "ISO-8859-16" }, { "CP1200", "WINDOWS-1200" }, { "CP1201", "WINDOWS-1201" }, { "CP1250", "WINDOWS-1250" }, { "CP1251", "WINDOWS-1251" }, { "CP1252", "WINDOWS-1252" }, { "CP1253", "WINDOWS-1253" }, { "CP1254", "WINDOWS-1254" }, { "CP1255", "WINDOWS-1255" }, { "CP1256", "WINDOWS-1256" }, { "CP1257", "WINDOWS-1257" }, { "CP1258", "WINDOWS-1258" }, { NULL, NULL } }; if (!name) return name; /* Avoid lots of tests for common correct names. */ for (cor = correct; *cor; cor++) if (!strcmp(name, *cor)) return name; for (ali = aliases; ali->alias; ali++) if (!strcmp(name, ali->alias)) return ali->name; for (sub = substrs; sub->substr; sub++) if (strstr(name, sub->substr)) return sub->name; return name; } nmh-1.7.1-RC3/sbr/client.c000644 007761 000024 00000004600 13243042053 015166 0ustar00kenhstaff000000 000000 /* client.c -- connect to a server * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #include #include int client (char *server, char *service, char *response, int len_response, int debug) { int sd, rc; struct addrinfo hints, *res, *ai; if (!server || *server == '\0') { snprintf(response, len_response, "Internal error: NULL server name " "passed to client()"); return NOTOK; } memset(&hints, 0, sizeof(hints)); #ifdef AI_ADDRCONFIG hints.ai_flags = AI_ADDRCONFIG; #endif hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if (debug) { fprintf(stderr, "Trying to connect to \"%s\" ...\n", server); } rc = getaddrinfo(server, service, &hints, &res); if (rc) { snprintf(response, len_response, "Lookup of \"%s\" failed: %s", server, gai_strerror(rc)); return NOTOK; } for (ai = res; ai != NULL; ai = ai->ai_next) { if (debug) { char address[NI_MAXHOST]; char port[NI_MAXSERV]; rc = getnameinfo(ai->ai_addr, ai->ai_addrlen, address, sizeof(address), port, sizeof port, NI_NUMERICHOST | NI_NUMERICSERV); fprintf(stderr, "Connecting to %s:%s...\n", rc ? "unknown" : address, rc ? "--" : port); } sd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sd < 0) { if (debug) fprintf(stderr, "socket() failed: %s\n", strerror(errno)); rc = errno; continue; } if (connect(sd, ai->ai_addr, ai->ai_addrlen) == 0) { freeaddrinfo(res); return sd; } rc = errno; if (debug) { fprintf(stderr, "Connection failed: %s\n", strerror(errno)); } close(sd); } /* * Improve error handling a bit. If we were given multiple IP addresses * then return the old "no servers available" error, but point the user * to -snoop (hopefully that's universal). Otherwise report a specific * error. */ if (res->ai_next) snprintf(response, len_response, "no servers available (use -snoop " "for details"); else snprintf(response, len_response, "Connection to \"%s\" failed: %s", server, strerror(errno)); freeaddrinfo(res); return NOTOK; } nmh-1.7.1-RC3/sbr/closefds.c000644 007761 000024 00000000501 13243042053 015506 0ustar00kenhstaff000000 000000 /* closefds.c -- close-up fd's * * 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 void closefds(int i) { int nbits = OPEN_MAX; for (; i < nbits; i++) close (i); } nmh-1.7.1-RC3/sbr/concat.c000644 007761 000024 00000001740 13243042053 015161 0ustar00kenhstaff000000 000000 /* concat.c -- concatenate a variable number (minimum of 1) * of strings in managed memory * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include /* concat returns a non-NULL malloc'd pointer to the catenation of the * argument strings less their NUL terminators other than the last. The * arguments are terminated by a NULL. * * Example: concat("abc", "def", "", "g", NULL) returns "abcdefg". */ char * concat (const char *s1, ...) { char *cp, *dp, *sp; size_t len; va_list list; len = strlen (s1) + 1; va_start(list, s1); while ((cp = va_arg(list, char *))) len += strlen (cp); va_end(list); dp = sp = mh_xmalloc(len); sp = stpcpy(sp, s1); va_start(list, s1); while ((cp = va_arg (list, char *))) sp = stpcpy(sp, cp); va_end(list); return dp; } nmh-1.7.1-RC3/sbr/context_del.c000644 007761 000024 00000001562 13243042053 016224 0ustar00kenhstaff000000 000000 /* context_del.c -- delete an entry from the context/profile list * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include /* * Delete a key/value pair from the context/profile list. * Return 0 if key is found, else return 1. */ int context_del (char *key) { struct node *np, *pp; for (np = m_defs, pp = NULL; np; pp = np, np = np->n_next) { if (!strcasecmp (FENDNULL(np->n_name), FENDNULL(key))) { if (!np->n_context) inform("bug: context_del(key=\"%s\"), continuing...", np->n_name); if (pp) pp->n_next = np->n_next; else m_defs = np->n_next; free (np->n_name); mh_xfree(np->n_field); free(np); ctxflags |= CTXMOD; return 0; } } return 1; } nmh-1.7.1-RC3/sbr/context_find.c000644 007761 000024 00000003155 13243042053 016400 0ustar00kenhstaff000000 000000 /* context_find.c -- find an entry in the context/profile list * * 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 char * context_find (const char *str) { struct node *np; for (np = m_defs; np; np = np->n_next) if (!strcasecmp (FENDNULL(np->n_name), FENDNULL(str))) return (np->n_field); return NULL; } /* * Helper function to search first, if subtype is non-NULL, for * invoname-string-type/subtype and then, if not yet found, * invoname-string-type. If entry is found but is empty, it is * treated as not found. */ char * context_find_by_type (const char *string, const char *type, const char *subtype) { char *value = NULL; if (subtype) { char *cp; cp = concat (invo_name, "-", string, "-", type, "/", subtype, NULL); if ((value = context_find (cp)) != NULL && *value == '\0') value = NULL; free (cp); } if (value == NULL) { char *cp; cp = concat (invo_name, "-", string, "-", type, NULL); if ((value = context_find (cp)) != NULL && *value == '\0') value = NULL; free (cp); } return value; } /* * Helper function to search profile an entry with name beginning with prefix. * The search is case insensitive. */ int context_find_prefix (const char *prefix) { struct node *np; for (np = m_defs; np; np = np->n_next) { if (np->n_name && ! strncasecmp (np->n_name, prefix, strlen(prefix))) { return 1; } } return 0; } nmh-1.7.1-RC3/sbr/context_foil.c000644 007761 000024 00000003404 13243042053 016406 0ustar00kenhstaff000000 000000 /* context_foil.c -- foil search of profile and context * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include /* * Foil search of users .mh_profile * If error, return -1, else return 0 */ int context_foil (char *path) { struct node *np; /* In fact, nobody examines defpath in code paths where * it's been set by us -- the uses in the source tree are: * 1 sbr/context_read.c uses it only after setting it itself * 2 uip/install_mh.c uses it only after setting it itself * 3 uip/mark.c prints it if given the -debug switch * A worthwhile piece of code cleanup would be to make 1 and * 2 use a local variable and just delete 3. * * Similarly, context and ctxpath are not really used * outside the context_* routines. It might be worth combining * them into one file so the variables can be made static. */ /* We set context to NULL to indicate that no context file * is to be read. (Using /dev/null doesn't work because we * would try to lock it, which causes timeouts with some * locking methods.) */ defpath = context = NULL; /* * If path is given, create a minimal profile/context list */ if (path) { NEW(np); m_defs = np; if (!(np->n_name = strdup ("Path"))) { inform("strdup failed"); return -1; } if (!(np->n_field = strdup (path))) { inform("strdup failed"); return -1; } np->n_context = 0; np->n_next = NULL; if (mypath == NULL && (mypath = getenv ("HOME")) != NULL) if (!(mypath = strdup (mypath))) { inform("strdup failed"); return -1; } } return 0; } nmh-1.7.1-RC3/sbr/context_read.c000644 007761 000024 00000011057 13243042053 016373 0ustar00kenhstaff000000 000000 /* context_read.c -- find and read profile and context files * * 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. * * This function must be called early on in any nmh utility, and * may only be called once. It does the following: * * o Sets the global variable "mypath" to the home directory path. * * o Sets the global variable "defpath" to the absolute path of * the profile file. * * o Reads in the profile file. Bails out if it can't. * * o Makes sure that the mail directory exists, prompting for * creation if it doesn't. * * o Reads the context file either as set by the MHCONTEXT * environment variable or by the profile. */ #include /* mh internals */ #include "lock_file.h" #include "m_maildir.h" #include "makedir.h" #include /* structure for getpwuid() results */ void context_read (void) { char buf[BUFSIZ]; /* path name buffer */ char *cp; /* miscellaneous pointer */ char *nd; /* nmh directory pointer */ struct stat st; /* stat() results */ struct passwd *pw; /* getpwuid() results */ FILE *ib; /* profile and context file pointer */ int failed_to_lock = 0; /* * If this routine _is_ called again (despite the warnings in the * comments above), return immediately. */ if ( m_defs != 0 ) return; /* * Find user's home directory. Try the HOME environment variable first, * the home directory field in the password file if that's not found. */ if ((mypath = getenv("HOME")) == NULL) { if ((pw = getpwuid(getuid())) == NULL || *pw->pw_dir == '\0') adios(NULL, "cannot determine your home directory"); else mypath = pw->pw_dir; } /* * Find and read user's profile. Check for the existence of an MH environment * variable first with non-empty contents. Convert any relative path name * found there to an absolute one. Look for the profile in the user's home * directory if the MH environment variable isn't set. */ if ((cp = getenv("MH")) && *cp != '\0') { defpath = path(cp, TFILE); /* defpath is an absolute path; make sure that always MH is, too. */ setenv("MH", defpath, 1); if (stat(defpath, &st) != -1 && (st.st_mode & S_IFREG) == 0) adios(NULL, "`%s' specified by your MH environment variable is not a normal file", cp); if ((ib = fopen(defpath, "r")) == NULL) adios(NULL, "unable to read the `%s' profile specified by your MH environment variable", defpath); } else { defpath = concat(mypath, "/", mh_profile, NULL); if ((ib = fopen(defpath, "r")) == NULL) adios(NULL, "Doesn't look like nmh is installed. Run install-mh to do so."); cp = mh_profile; } readconfig (&m_defs, ib, cp, 0); fclose (ib); /* * Find the user's nmh directory, which is specified by the "path" profile component. * Convert a relative path name to an absolute one rooted in the home directory. */ if ((cp = context_find ("path")) == NULL) adios(NULL, "Your %s file does not contain a path entry.", defpath); if (*cp == '\0') adios(NULL, "Your `%s' profile file does not contain a valid path entry.", defpath); if (*cp != '/') (void)snprintf (nd = buf, sizeof(buf), "%s/%s", mypath, cp); else nd = cp; if (stat(nd, &st) == -1) { if (errno != ENOENT) adios (nd, "error opening"); cp = concat ("Your MH-directory \"", nd, "\" doesn't exist; Create it? ", NULL); if (!read_yes_or_no_if_tty(cp)) adios (NULL, "unable to access MH-directory \"%s\"", nd); free (cp); if (!makedir (nd)) adios (NULL, "unable to create %s", nd); } else if ((st.st_mode & S_IFDIR) == 0) adios (NULL, "`%s' is not a directory", nd); /* * Open and read user's context file. The name of the context file comes from the * profile unless overridden by the MHCONTEXT environment variable. */ if ((cp = getenv ("MHCONTEXT")) == NULL || *cp == '\0') cp = context; /* context is NULL if context_foil() was called to disable use of context * We also support users setting explicitly setting MHCONTEXT to /dev/null. * (if this wasn't special-cased then the locking would be liable to fail) */ if (!cp || (strcmp(cp,"/dev/null") == 0)) { ctxpath = NULL; return; } ctxpath = getcpy (m_maildir (cp)); if ((ib = lkfopendata (ctxpath, "r", &failed_to_lock))) { readconfig ((struct node **) 0, ib, cp, 1); lkfclosedata (ib, ctxpath); } } nmh-1.7.1-RC3/sbr/context_replace.c000644 007761 000024 00000002552 13243042053 017073 0ustar00kenhstaff000000 000000 /* context_replace.c -- add/replace an entry in the context/profile list * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include void context_replace (char *key, char *value) { struct node *np; /* * If list is empty, allocate head of profile/context list. */ if (!m_defs) { NEW(np); m_defs = np; np->n_name = getcpy (key); np->n_field = getcpy (value); np->n_context = 1; np->n_next = NULL; ctxflags |= CTXMOD; return; } /* * Search list of context/profile entries for * this key, and replace its value if found. */ for (np = m_defs;; np = np->n_next) { if (!strcasecmp (FENDNULL(np->n_name), FENDNULL(key))) { if (strcmp (value, np->n_field)) { if (!np->n_context) inform("bug: context_replace(key=\"%s\",value=\"%s\"), continuing...", key, value); mh_xfree(np->n_field); np->n_field = mh_xstrdup(value); ctxflags |= CTXMOD; } return; } if (!np->n_next) break; } /* * Else add this new entry at the end */ NEW(np->n_next); np = np->n_next; np->n_name = getcpy (key); np->n_field = getcpy (value); np->n_context = 1; np->n_next = NULL; ctxflags |= CTXMOD; } nmh-1.7.1-RC3/sbr/context_save.c000644 007761 000024 00000002607 13243042053 016417 0ustar00kenhstaff000000 000000 /* context_save.c -- write out the updated context file * * 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. */ /* * This function used to support setuid/setgid programs by writing * the file as the user. But that code, m_chkids(), was removed * because there no longer are setuid/setgid programs in nmh. */ #include #include #include "lock_file.h" void context_save (void) { struct node *np; FILE *out; sigset_t set, oset; int failed_to_lock = 0; /* No context in use -- silently ignore any changes! */ if (!ctxpath) return; if (!(ctxflags & CTXMOD)) return; ctxflags &= ~CTXMOD; /* block a few signals */ sigemptyset (&set); sigaddset (&set, SIGHUP); sigaddset (&set, SIGINT); sigaddset (&set, SIGQUIT); sigaddset (&set, SIGTERM); sigprocmask (SIG_BLOCK, &set, &oset); if (!(out = lkfopendata (ctxpath, "w", &failed_to_lock))) { if (failed_to_lock) { adios (ctxpath, "failed to lock"); } else { adios (ctxpath, "unable to write"); } } for (np = m_defs; np; np = np->n_next) if (np->n_context) fprintf (out, "%s: %s\n", np->n_name, np->n_field); lkfclosedata (out, ctxpath); sigprocmask (SIG_SETMASK, &oset, &set); /* reset the signal mask */ } nmh-1.7.1-RC3/sbr/copyip.c000644 007761 000024 00000000602 13243042053 015211 0ustar00kenhstaff000000 000000 /* copyip.c -- copy a string array and return pointer to end * * 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 char ** copyip (char **p, char **q, int len_q) { while (*p && --len_q > 0) *q++ = *p++; *q = NULL; return q; } nmh-1.7.1-RC3/sbr/cpydata.c000644 007761 000024 00000001037 13243042053 015336 0ustar00kenhstaff000000 000000 /* cpydata.c -- copy all data from one fd to another * * 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 void cpydata (int in, int out, const char *ifile, const char *ofile) { int i; char buffer[BUFSIZ]; while ((i = read(in, buffer, sizeof(buffer))) > 0) { if (write(out, buffer, i) != i) adios(ofile, "error writing"); } if (i == -1) adios(ifile, "error reading"); } nmh-1.7.1-RC3/sbr/cpydgst.c000644 007761 000024 00000002656 13243042053 015376 0ustar00kenhstaff000000 000000 /* cpydgst.c -- copy from one fd to another in encapsulating mode * -- (do dashstuffing of input data). * * 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 /* * We want to perform the substitution * * \n(-.*)\n --> \n- \1\n * * This is equivalent to the sed substitution * * sed -e 's%^-%- -%' < ifile > ofile * * but the routine below is faster than the pipe, fork, and exec. */ #define S1 0 #define S2 1 #define output(c) if (bp >= dp) {flush(); *bp++ = c;} else *bp++ = c #define flush() if ((j = bp - outbuf) && write (out, outbuf, j) != j) \ adios (ofile, "error writing"); \ else \ bp = outbuf void cpydgst (int in, int out, char *ifile, char *ofile) { int i, j, state; char *cp, *ep; char *bp, *dp; char buffer[BUFSIZ], outbuf[BUFSIZ]; dp = (bp = outbuf) + sizeof outbuf; for (state = S1; (i = read (in, buffer, sizeof buffer)) > 0;) for (ep = (cp = buffer) + i; cp < ep; cp++) { if (*cp == '\0') continue; switch (state) { case S1: if (*cp == '-') { output ('-'); output (' '); } state = S2; /* FALLTHRU */ case S2: output (*cp); if (*cp == '\n') state = S1; break; } } if (i == -1) adios (ifile, "error reading"); flush(); } nmh-1.7.1-RC3/sbr/crawl_folders.c000644 007761 000024 00000006744 13243042053 016551 0ustar00kenhstaff000000 000000 /* crawl_folders.c -- crawl folder hierarchy * * This code is Copyright (c) 2008, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include struct crawl_context { int max; /* how many folders we currently can hold in * the array `folders', increased by * CRAWL_NUMFOLDERS at a time */ char **folders; /* the array of folders */ int start; int foldp; }; /* * Add the folder name into the * list in a sorted fashion. */ static void add_folder (char *fold, struct crawl_context *crawl) { int i, j; /* if necessary, reallocate the space for folder names */ if (crawl->foldp >= crawl->max) { crawl->max += CRAWL_NUMFOLDERS; crawl->folders = mh_xrealloc (crawl->folders, crawl->max * sizeof(char *)); } for (i = crawl->start; i < crawl->foldp; i++) if (strcmp (fold, crawl->folders[i]) < 0) { for (j = crawl->foldp - 1; j >= i; j--) crawl->folders[j + 1] = crawl->folders[j]; crawl->foldp++; crawl->folders[i] = fold; return; } crawl->folders[crawl->foldp++] = fold; } static void add_children (char *name, struct crawl_context *crawl) { char *prefix, *child; struct stat st; struct dirent *dp; DIR * dd; int child_is_folder; if (!(dd = opendir (name))) { admonish (name, "unable to read directory "); return; } if (strcmp (name, ".") == 0) { prefix = mh_xstrdup(""); } else { prefix = concat (name, "/", (void *)NULL); } while ((dp = readdir (dd))) { /* If the system supports it, try to skip processing of children we * know are not directories or symlinks. */ child_is_folder = -1; #if defined(HAVE_STRUCT_DIRENT_D_TYPE) if (dp->d_type == DT_DIR) { child_is_folder = 1; } else if (dp->d_type != DT_LNK && dp->d_type != DT_UNKNOWN) { continue; } #endif if (!strcmp (dp->d_name, ".") || !strcmp (dp->d_name, "..")) { continue; } child = concat (prefix, dp->d_name, (void *)NULL); /* If we have no d_type or d_type is DT_LNK or DT_UNKNOWN, stat the * child to see what it is. */ if (child_is_folder == -1) { child_is_folder = (stat (child, &st) != -1 && S_ISDIR(st.st_mode)); } if (child_is_folder) { /* add_folder saves child in the list, don't free it */ add_folder (child, crawl); } else { free (child); } } closedir (dd); free(prefix); } static void crawl_folders_body (struct crawl_context *crawl, char *dir, crawl_callback_t *callback, void *baton) { int i; int os = crawl->start; int of = crawl->foldp; crawl->start = crawl->foldp; add_children (dir, crawl); for (i = crawl->start; i < crawl->foldp; i++) { char *fold = crawl->folders[i]; int crawl_children = 1; if (callback != NULL) { crawl_children = callback (fold, baton); } if (crawl_children) { crawl_folders_body (crawl, fold, callback, baton); } } crawl->start = os; crawl->foldp = of; } void crawl_folders (char *dir, crawl_callback_t *callback, void *baton) { struct crawl_context *crawl; NEW(crawl); crawl->max = CRAWL_NUMFOLDERS; crawl->start = crawl->foldp = 0; crawl->folders = mh_xmalloc (crawl->max * sizeof(*crawl->folders)); crawl_folders_body (crawl, dir, callback, baton); /* Note that we "leak" the folder names, on the assumption that the caller * is using them. */ free (crawl->folders); free (crawl); } nmh-1.7.1-RC3/sbr/credentials.c000644 007761 000024 00000007234 13243042053 016213 0ustar00kenhstaff000000 000000 /* credentials.c -- wrap configurable access to .netrc or similar files. * * 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 #include #include #include "m_maildir.h" struct nmh_creds { char *host; /* Hostname corresponding to credentials */ char *user; /* Username corresponding to credentials */ char *pass; /* (Optional) password used by credentials */ }; void init_credentials_file(void) { if (credentials_file == NULL) { char *cred_style = context_find ("credentials"); if (cred_style == NULL || ! strcmp (cred_style, "legacy")) { char *hdir = getenv ("HOME"); credentials_file = concat (hdir ? hdir : ".", "/.netrc", NULL); } else if (! strncasecmp (cred_style, "file:", 5) || ! strncasecmp (cred_style, "file-nopermcheck:", 17)) { struct stat st; char *filename = strchr(cred_style, ':') + 1; while (*filename && isspace ((unsigned char) *filename)) ++filename; if (*filename == '/') { credentials_file = filename; } else { credentials_file = m_maildir (filename); if (stat (credentials_file, &st) != OK) { credentials_file = concat (mypath ? mypath : ".", "/", filename, NULL); if (stat (credentials_file, &st) != OK) { inform("unable to find credentials file %s, continuing...", filename); } } } if (! strncasecmp (cred_style, "file-nopermcheck:", 17)) credentials_no_perm_check = 1; } } } nmh_creds_t nmh_get_credentials (const char *host, const char *user) { nmh_creds_t creds; char *cred_style = context_find ("credentials"); init_credentials_file (); creds = mh_xmalloc(sizeof(*creds)); creds->host = mh_xstrdup(host); creds->user = NULL; creds->pass = NULL; if (cred_style == NULL || ! strcmp (cred_style, "legacy")) { creds->user = user == NULL ? mh_xstrdup(getusername ()) : mh_xstrdup(user); } else if (! strncasecmp (cred_style, "file:", 5) || ! strncasecmp (cred_style, "file-nopermcheck:", 17)) { /* * Determine user using the first of: * 1) -user switch * 2) matching host entry with login in a credentials file * such as ~/.netrc * 3) interactively request from user (as long as the * credentials file didn't have a "default" token) */ creds->user = user == NULL ? NULL : mh_xstrdup(user); } else { inform("unknown credentials style %s, continuing...", cred_style); return NULL; } ruserpass(creds->host, &creds->user, &creds->pass, RUSERPASS_NO_PROMPT_USER | RUSERPASS_NO_PROMPT_PASSWORD); return creds; } /* * Retrieve the username */ const char * nmh_cred_get_user(nmh_creds_t creds) { if (! creds->user) { ruserpass(creds->host, &creds->user, &creds->pass, RUSERPASS_NO_PROMPT_PASSWORD); } return creds->user; } /* * Retrieve the password */ const char * nmh_cred_get_password(nmh_creds_t creds) { if (! creds->pass) { ruserpass(creds->host, &creds->user, &creds->pass, 0); } return creds->pass; } /* * Free our credentials */ void nmh_credentials_free(nmh_creds_t creds) { mh_xfree(creds->host); mh_xfree(creds->user); if (creds->pass) { memset(creds->pass, 0, strlen(creds->pass)); free(creds->pass); } free(creds); } nmh-1.7.1-RC3/sbr/ctype-checked.c000644 007761 000024 00000003647 13243042053 016432 0ustar00kenhstaff000000 000000 /* ctype-checked.c -- checks char isn't used as the value for each of * the ctype functions * * This code is Copyright (c) 2016, by the authors of nmh. * See the COPYRIGHT file in the root directory of the nmh * distribution for complete copyright information. */ #include #ifndef NDEBUG #include #if EOF != -1 #error "Please report this to nmh's authors." #endif #include /* ctype_identity returns its index less one allowing [EOF, 255] to be * used as indexes to ctype_identity + 1. */ int ctype_identity[257] = { -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 }; #else /* Need to put a symbol in the .c file with NDEBUG so the compilation * unit isn't empty. */ void ctype_checked(void); #endif nmh-1.7.1-RC3/sbr/ctype-checked.h000644 007761 000024 00000003237 13205305704 016435 0ustar00kenhstaff000000 000000 /* ctype-checked.h -- ctype.h with compiler checks. * * This code is Copyright (c) 2016, by the authors of nmh. * See the COPYRIGHT file in the root directory of the nmh * distribution for complete copyright information. */ #ifndef CTYPE_CHECKED_H #define CTYPE_CHECKED_H #include extern int ctype_identity[257]; #define CTYPE_CHECK(f, c) ((f)((ctype_identity + 1)[c])) #ifdef isalnum #undef isalnum #endif #define isalnum(c) CTYPE_CHECK(isalnum, c) #ifdef isalpha #undef isalpha #endif #define isalpha(c) CTYPE_CHECK(isalpha, c) #ifdef iscntrl #undef iscntrl #endif #define iscntrl(c) CTYPE_CHECK(iscntrl, c) #ifdef isdigit #undef isdigit #endif #define isdigit(c) CTYPE_CHECK(isdigit, c) #ifdef isgraph #undef isgraph #endif #define isgraph(c) CTYPE_CHECK(isgraph, c) #ifdef islower #undef islower #endif #define islower(c) CTYPE_CHECK(islower, c) #ifdef isprint #undef isprint #endif #define isprint(c) CTYPE_CHECK(isprint, c) #ifdef ispunct #undef ispunct #endif #define ispunct(c) CTYPE_CHECK(ispunct, c) #ifdef isspace #undef isspace #endif #define isspace(c) CTYPE_CHECK(isspace, c) #ifdef isupper #undef isupper #endif #define isupper(c) CTYPE_CHECK(isupper, c) #ifdef isxdigit #undef isxdigit #endif #define isxdigit(c) CTYPE_CHECK(isxdigit, c) #ifdef tolower #undef tolower #endif #define tolower(c) CTYPE_CHECK(tolower, c) #ifdef toupper #undef toupper #endif #define toupper(c) CTYPE_CHECK(toupper, c) #ifdef isascii #undef isascii #endif #define isascii(c) CTYPE_CHECK(isascii, c) #ifdef toascii #undef toascii #endif #define toascii(c) CTYPE_CHECK(toascii, c) #ifdef isblank #undef isblank #endif #define isblank(c) CTYPE_CHECK(isblank, c) #endif nmh-1.7.1-RC3/sbr/datetime.c000644 007761 000024 00000042441 13243042053 015511 0ustar00kenhstaff000000 000000 /* datetime.c -- functions for manipulating RFC 5545 date-time values * * This code is Copyright (c) 2014, 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/icalendar.h" #include #include "h/tws.h" #include "h/utils.h" #include "unquote.h" /* * This doesn't try to support all of the myriad date-time formats * allowed by RFC 5545. It is only used for viewing date-times, * so that shouldn't be a problem: if a particular format can't * be handled by this code, just present it to the user in its * original form. * * And, this assumes a valid iCalendar input file. E.g, it * doesn't check that each BEGIN has a matching END and vice * versa. That should be done in the parser, though it currently * isn't. */ typedef struct tzparams { /* Pointers to values in parse tree. * TZOFFSETFROM is used to calculate the absolute time at which * the transition to a given observance takes place. * TZOFFSETTO is the timezone offset from UTC. Both are in HHmm * format. */ char *offsetfrom, *offsetto; const char *dtstart; const char *rrule; /* This is only used to make sure that timezone applies. And not always, because if the timezone DTSTART is before the epoch, we don't try to compare to it. */ time_t start_dt; /* in seconds since epoch */ } tzparams; struct tzdesc { char *tzid; /* The following are translations of the pieces of RRULE and DTSTART into seconds from beginning of year. */ tzparams standard_params; tzparams daylight_params; struct tzdesc *next; }; /* * Parse a datetime of the form YYYYMMDDThhmmss and a string * representation of the timezone in units of [+-]hhmm and load the * struct tws. */ static int parse_datetime (const char *datetime, const char *zone, int dst, struct tws *tws) { char utc_indicator; int form_1 = 0; int items_matched; memset(tws, 0, sizeof *tws); items_matched = sscanf (datetime, "%4d%2d%2dT%2d%2d%2d%c", &tws->tw_year, &tws->tw_mon, &tws->tw_mday, &tws->tw_hour, &tws->tw_min, &tws->tw_sec, &utc_indicator); tws->tw_flags = TW_NULL; if (items_matched == 7) { /* The 'Z' must be capital according to RFC 5545 Sec. 3.3.5. */ if (utc_indicator != 'Z') { inform("%s has invalid timezone indicator of 0x%x", datetime, utc_indicator); return NOTOK; } } else if (zone == NULL) { form_1 = 1; } /* items_matched of 3 is for, e.g., 20151230. Assume that means the entire day. The time fields of the tws struct were initialized to 0 by the memset() above. */ if (items_matched >= 6 || items_matched == 3) { int offset = atoi (zone ? zone : "0"); /* struct tws defines tw_mon over [0, 11]. */ --tws->tw_mon; /* Fill out rest of tws, i.e., its tw_wday and tw_flags. */ set_dotw (tws); /* set_dotw() sets TW_SIMP. Replace that with TW_SEXP so that dasctime() outputs the dotw before the date instead of after. */ tws->tw_flags &= ~TW_SDAY; tws->tw_flags |= TW_SEXP; /* For the call to dmktime(): - don't need tw_yday - tw_clock must be 0 on entry, and is set by dmktime() - the only flag in tw_flags used is TW_DST */ tws->tw_yday = tws->tw_clock = 0; tws->tw_zone = 60 * (offset / 100) + offset % 100; if (dst) { tws->tw_zone -= 60; /* per dlocaltime() */ tws->tw_flags |= TW_DST; } /* dmktime() just sets tws->tw_clock. */ (void) dmktime (tws); if (! form_1) { /* Set TW_SZEXP so that dasctime outputs timezone, except with local time (Form #1). */ tws->tw_flags |= TW_SZEXP; /* Convert UTC time to time in local timezone. However, don't try for years before 1970 because dlocatime() doesn't handle them well. dlocaltime() will succeed if tws->tw_clock is nonzero. */ if (tws->tw_year >= 1970 && tws->tw_clock > 0) { const int was_dst = tws->tw_flags & TW_DST; *tws = *dlocaltime (&tws->tw_clock); if (was_dst && ! (tws->tw_flags & TW_DST)) { /* dlocaltime() changed the DST flag from 1 to 0, which means the time is in the hour (assumed to be one hour) that is lost in the transition to DST. So per RFC 5545 Sec. 3.3.5, "the DATE-TIME value is interpreted using the UTC offset before the gap in local times." In other words, add an hour to it. No adjustment is necessary for the transition from DST to standard time, because dasctime() shows the first occurrence of the time. */ tws->tw_clock += 3600; *tws = *dlocaltime (&tws->tw_clock); } } } return OK; } return NOTOK; } tzdesc_t load_timezones (const contentline *clines) { tzdesc_t timezones = NULL, timezone = NULL; int in_vtimezone, in_standard, in_daylight; tzparams *params = NULL; const contentline *node; /* Interpret each VTIMEZONE section. */ in_vtimezone = in_standard = in_daylight = 0; for (node = clines; node; node = node->next) { /* node->name will be NULL if the line was "deleted". */ if (! node->name) { continue; } if (in_daylight || in_standard) { if (! strcasecmp ("END", node->name) && ((in_standard && ! strcasecmp ("STANDARD", node->value)) || (in_daylight && ! strcasecmp ("DAYLIGHT", node->value)))) { struct tws tws; if (in_standard) { in_standard = 0; } else if (in_daylight) { in_daylight = 0; } if (parse_datetime (params->dtstart, params->offsetfrom, in_daylight, &tws) == OK) { if (tws.tw_year >= 1970) { /* dmktime() falls apart for, e.g., the year 1601. */ params->start_dt = tws.tw_clock; } } else { inform("failed to parse start time %s for %s", params->dtstart, in_standard ? "standard" : "daylight"); return NULL; } params = NULL; } else if (! strcasecmp ("DTSTART", node->name)) { /* Save DTSTART for use after getting TZOFFSETFROM. */ params->dtstart = node->value; } else if (! strcasecmp ("TZOFFSETFROM", node->name)) { params->offsetfrom = node->value; } else if (! strcasecmp ("TZOFFSETTO", node->name)) { params->offsetto = node->value; } else if (! strcasecmp ("RRULE", node->name)) { params->rrule = node->value; } } else if (in_vtimezone) { if (! strcasecmp ("END", node->name) && ! strcasecmp ("VTIMEZONE", node->value)) { in_vtimezone = 0; } else if (! strcasecmp ("BEGIN", node->name) && ! strcasecmp ("STANDARD", node->value)) { in_standard = 1; params = &timezone->standard_params; } else if (! strcasecmp ("BEGIN", node->name) && ! strcasecmp ("DAYLIGHT", node->value)) { in_daylight = 1; params = &timezone->daylight_params; } else if (! strcasecmp ("TZID", node->name)) { /* See comment below in format_datetime() about removing any enclosing quotes from a timezone identifier. */ char *buf = mh_xmalloc(strlen(node->value) + 1); unquote_string(node->value, buf); timezone->tzid = buf; } } else { if (! strcasecmp ("BEGIN", node->name) && ! strcasecmp ("VTIMEZONE", node->value)) { in_vtimezone = 1; NEW0(timezone); if (timezones) { tzdesc_t t; for (t = timezones; t && t->next; t = t->next) { continue; } /* The loop terminated at, not after, the last timezones node. */ t->next = timezone; } else { timezones = timezone; } } } } return timezones; } void free_timezones (tzdesc_t timezone) { tzdesc_t next; for ( ; timezone; timezone = next) { free (timezone->tzid); next = timezone->next; free (timezone); } } /* * Convert time to local timezone, accounting for daylight saving time: * - Detect which type of datetime the node contains: * Form #1: DATE WITH LOCAL TIME * Form #2: DATE WITH UTC TIME * Form #3: DATE WITH LOCAL TIME AND TIME ZONE REFERENCE * - Convert value to local time in seconds since epoch. * - If there's a DST in the timezone, convert its start and end * date-times to local time in seconds, also. Then determine * if the value is between them, and therefore DST. Otherwise, it's * not. * - Format the time value. */ /* * Given a recurrence rule and year, calculate its time in seconds * from 01 January UTC of the year. */ time_t rrule_clock (const char *rrule, const char *starttime, const char *zone, unsigned int year) { time_t clock = 0; if (nmh_strcasestr (rrule, "FREQ=YEARLY;INTERVAL=1") || (nmh_strcasestr (rrule, "FREQ=YEARLY") && nmh_strcasestr(rrule, "INTERVAL") == NULL)) { struct tws *tws; const char *cp; int wday = -1, month = -1; int specific_day = 1; /* BYDAY integer (prefix) */ char buf[32]; int day; if ((cp = nmh_strcasestr (rrule, "BYDAY="))) { cp += 6; /* BYDAY integers must be ASCII. */ if (*cp == '+') { ++cp; } /* +n specific day; don't support '-' */ else if (*cp == '-') { goto fail; } if (isdigit ((unsigned char) *cp)) { specific_day = *cp++ - 0x30; } if (! strncasecmp (cp, "SU", 2)) { wday = 0; } else if (! strncasecmp (cp, "MO", 2)) { wday = 1; } else if (! strncasecmp (cp, "TU", 2)) { wday = 2; } else if (! strncasecmp (cp, "WE", 2)) { wday = 3; } else if (! strncasecmp (cp, "TH", 2)) { wday = 4; } else if (! strncasecmp (cp, "FR", 2)) { wday = 5; } else if (! strncasecmp (cp, "SA", 2)) { wday = 6; } } if ((cp = nmh_strcasestr (rrule, "BYMONTH="))) { month = atoi (cp + 8); } for (day = 1; day <= 7; ++day) { /* E.g, 11-01-2014 02:00:00-0400 */ snprintf (buf, sizeof buf, "%02d-%02d-%04u %.2s:%.2s:%.2s%s", month, day + 7 * (specific_day-1), year, starttime, starttime + 2, starttime + 4, zone ? zone : "0000"); if ((tws = dparsetime (buf))) { if (! (tws->tw_flags & (TW_SEXP|TW_SIMP))) { set_dotw (tws); } if (tws->tw_wday == wday) { /* Found the day specified in the RRULE. */ break; } } } if (day <= 7) { clock = tws->tw_clock; } } fail: if (clock == 0) { inform("Unsupported RRULE format: %s, assume local timezone, continuing...", rrule); } return clock; } char * format_datetime (tzdesc_t timezones, const contentline *node) { param_list *p; char *dt_timezone = NULL; int dst = 0; struct tws tws[2]; /* [standard, daylight] */ tzdesc_t tz; char *tp_std, *tp_dst, *tp_dt; /* Extract the timezone, if specified (RFC 5545 Sec. 3.3.5 Form #3). */ for (p = node->params; p && p->param_name; p = p->next) { if (! strcasecmp (p->param_name, "TZID") && p->values) { /* Remove any enclosing quotes from the timezone identifier. I don't believe that it's legal for it to be quoted, according to RFC 5545 § 3.2.19: tzidparam = "TZID" "=" [tzidprefix] paramtext tzidprefix = "/" where paramtext includes SAFE-CHAR, which specifically excludes DQUOTE. But we'll be generous and strip quotes. */ char *buf = mh_xmalloc(strlen(p->values->value) + 1); unquote_string(p->values->value, buf); dt_timezone = buf; break; } } if (! dt_timezone) { /* Form #1: DATE WITH LOCAL TIME, i.e., no time zone, or Form #2: DATE WITH UTC TIME */ if (parse_datetime (node->value, NULL, 0, &tws[0]) == OK) { return strdup (dasctime (&tws[0], 0)); } inform("unable to parse datetime %s", node->value); return NULL; } /* * must be * Form #3: DATE WITH LOCAL TIME AND TIME ZONE REFERENCE */ /* Find the corresponding tzdesc. */ for (tz = timezones; dt_timezone && tz; tz = tz->next) { /* Property parameter values are case insensitive (RFC 5545 Sec. 2) and time zone identifiers are property parameters (RFC 5545 Sec. 3.8.2.4), though it would seem odd to use different case in the same file for identifiers that are supposed to be the same. */ if (tz->tzid && ! strcasecmp (dt_timezone, tz->tzid)) { break; } } if (tz) { free(dt_timezone); } else { inform("did not find VTIMEZONE section for %s", dt_timezone); free(dt_timezone); return NULL; } /* Determine if it's Daylight Saving. */ tp_std = strchr (tz->standard_params.dtstart, 'T'); tp_dt = strchr (node->value, 'T'); if (tz->daylight_params.dtstart) { tp_dst = strchr (tz->daylight_params.dtstart, 'T'); } else { /* No DAYLIGHT section. */ tp_dst = NULL; dst = 0; } if (tp_std && tp_dt) { time_t transition[2] = { 0, 0 }; /* [standard, daylight] */ time_t dt[2]; /* [standard, daylight] */ unsigned int year; char buf[5]; /* Datetime is form YYYYMMDDThhmmss. Extract year. */ memcpy (buf, node->value, sizeof buf - 1); buf[sizeof buf - 1] = '\0'; year = atoi (buf); if (tz->standard_params.rrule) { /* +1 to skip the T before the time */ transition[0] = rrule_clock (tz->standard_params.rrule, tp_std + 1, tz->standard_params.offsetfrom, year); } if (tp_dst && tz->daylight_params.rrule) { /* +1 to skip the T before the time */ transition[1] = rrule_clock (tz->daylight_params.rrule, tp_dst + 1, tz->daylight_params.offsetfrom, year); } if (transition[0] < transition[1]) { inform("format_datetime() requires that daylight " "saving time transition precede standard time " "transition"); return NULL; } if (parse_datetime (node->value, tz->standard_params.offsetto, 0, &tws[0]) == OK) { dt[0] = tws[0].tw_clock; } else { inform("unable to parse datetime %s", node->value); return NULL; } if (tp_dst) { if (dt[0] < transition[1]) { dst = 0; } else { if (parse_datetime (node->value, tz->daylight_params.offsetto, 1, &tws[1]) == OK) { dt[1] = tws[1].tw_clock; } else { inform("unable to parse datetime %s", node->value); return NULL; } dst = dt[1] <= transition[0]; } } if (dst) { if (tz->daylight_params.start_dt > 0 && dt[dst] < tz->daylight_params.start_dt) { inform("date-time of %s is before VTIMEZONE start " "of %s", node->value, tz->daylight_params.dtstart); return NULL; } } else { if (tz->standard_params.start_dt > 0 && dt[dst] < tz->standard_params.start_dt) { inform("date-time of %s is before VTIMEZONE start " "of %s", node->value, tz->standard_params.dtstart); return NULL; } } } else { if (! tp_std) { inform("unsupported date-time format: %s", tz->standard_params.dtstart); return NULL; } if (! tp_dt) { inform("unsupported date-time format: %s", node->value); return NULL; } } return strdup (dasctime (&tws[dst], 0)); } nmh-1.7.1-RC3/sbr/discard.c000644 007761 000024 00000000535 13243042053 015324 0ustar00kenhstaff000000 000000 /* discard.c -- discard output on a file pointer * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include void discard (FILE *io) { if (io) tcflush (fileno(io), TCOFLUSH); } nmh-1.7.1-RC3/sbr/done.c000644 007761 000024 00000000415 13243042053 014635 0ustar00kenhstaff000000 000000 /* done.c -- terminate the program * * 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 void (*done) (int) NORETURN = exit; nmh-1.7.1-RC3/sbr/dtime.c000644 007761 000024 00000020600 13243042053 015010 0ustar00kenhstaff000000 000000 /* dtime.c -- time/date routines * * 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 /* for snprintf() */ #include #include #include #include #if !defined(HAVE_STRUCT_TM_TM_GMTOFF) extern long timezone; #endif /* * The number of days in the year, accounting for leap years */ #define dysize(y) \ (((y) % 4) ? 365 : (((y) % 100) ? 366 : (((y) % 400) ? 365 : 366))) char *tw_moty[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL }; char *tw_dotw[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL }; char *tw_ldotw[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", NULL }; static int dmsize[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; /* * Get current time (adjusted for local time * zone and daylight savings time) expressed * as nmh "broken-down" time structure. */ struct tws * dlocaltimenow (void) { time_t clock; time (&clock); return dlocaltime (&clock); } /* * Take clock value and return pointer to nmh time structure * containing "broken-down" time. The time is adjusted for * local time zone and daylight savings time. */ struct tws * dlocaltime (time_t *clock) { static struct tws tw; struct tm *tm; if (!clock) return NULL; tm = localtime (clock); tw.tw_sec = tm->tm_sec; tw.tw_min = tm->tm_min; tw.tw_hour = tm->tm_hour; tw.tw_mday = tm->tm_mday; tw.tw_mon = tm->tm_mon; /* * tm_year is always "year - 1900". * So we correct for this. */ tw.tw_year = tm->tm_year + 1900; tw.tw_wday = tm->tm_wday; tw.tw_yday = tm->tm_yday; tw.tw_flags = TW_NULL; if (tm->tm_isdst) tw.tw_flags |= TW_DST; #ifdef HAVE_STRUCT_TM_TM_GMTOFF tw.tw_zone = tm->tm_gmtoff / 60; if (tm->tm_isdst) /* if DST is in effect */ tw.tw_zone -= 60; /* reset to normal offset */ #else { static bool deja_vu; if (!deja_vu) { deja_vu = true; tzset(); } } tw.tw_zone = -(timezone / 60); #endif tw.tw_flags &= ~TW_SDAY; tw.tw_flags |= TW_SEXP; tw.tw_flags |= TW_SZEXP; tw.tw_clock = *clock; return (&tw); } /* * Take clock value and return pointer to nmh time * structure containing "broken-down" time. Time is * expressed in UTC (Coordinated Universal Time). */ struct tws * dgmtime (time_t *clock) { static struct tws tw; struct tm *tm; if (!clock) return NULL; tm = gmtime (clock); tw.tw_sec = tm->tm_sec; tw.tw_min = tm->tm_min; tw.tw_hour = tm->tm_hour; tw.tw_mday = tm->tm_mday; tw.tw_mon = tm->tm_mon; /* * tm_year is always "year - 1900" * So we correct for this. */ tw.tw_year = tm->tm_year + 1900; tw.tw_wday = tm->tm_wday; tw.tw_yday = tm->tm_yday; tw.tw_flags = TW_NULL; if (tm->tm_isdst) tw.tw_flags |= TW_DST; tw.tw_zone = 0; tw.tw_flags &= ~TW_SDAY; tw.tw_flags |= TW_SEXP; tw.tw_flags |= TW_SZEXP; tw.tw_clock = *clock; return (&tw); } /* * Using a nmh "broken-down" time structure, * produce a 26-byte date/time string, such as * * Tue Jan 14 17:49:03 1992\n\0 */ char * dctime (struct tws *tw) { static char buffer[26]; if (!tw) return NULL; snprintf (buffer, sizeof(buffer), "%.3s %.3s %02d %02d:%02d:%02d %s\n", tw_dotw[tw->tw_wday], tw_moty[tw->tw_mon], tw->tw_mday, tw->tw_hour, tw->tw_min, tw->tw_sec, m_strn(tw->tw_year < 100 ? tw->tw_year + 1900 : tw->tw_year, 4)); return buffer; } /* * Produce a date/time string of the form * * Mon, 16 Jun 1992 15:30:48 -700 (or) * Mon, 16 Jun 1992 15:30:48 EDT * * for the current time, as specified by RFC 822. * The first form is required by RFC 1123. */ char * dtimenow (int alpha_timezone) { time_t clock; time (&clock); return dtime (&clock, alpha_timezone); } /* * Using a local calendar time value, produce * a date/time string of the form * * Mon, 16 Jun 1992 15:30:48 -700 (or) * Mon, 16 Jun 1992 15:30:48 EDT * * as specified by RFC 822. The first form is required * by RFC 1123 for outgoing messages. */ char * dtime (time_t *clock, int alpha_timezone) { if (alpha_timezone) /* use alpha-numeric timezones */ return dasctime (dlocaltime (clock), TW_NULL); /* use numeric timezones */ return dasctime (dlocaltime (clock), TW_ZONE); } /* * Using a nmh "broken-down" time structure, produce * a date/time string of the form * * Mon, 16 Jun 1992 15:30:48 -0700 * * as specified by RFC 822 and RFC 1123. */ char * dasctime (struct tws *tw, int flags) { char buffer[80]; static char result[80]; int twf; if (!tw) return NULL; /* Display timezone if known */ if (tw->tw_flags & TW_SZEXP) snprintf(result, sizeof(result), " %s", dtimezone(tw->tw_zone, tw->tw_flags | flags)); else result[0] = '\0'; snprintf(buffer, sizeof(buffer), "%02d %s %0*d %02d:%02d:%02d%s", tw->tw_mday, tw_moty[tw->tw_mon], tw->tw_year < 100 ? 2 : 4, tw->tw_year, tw->tw_hour, tw->tw_min, tw->tw_sec, result); if ((twf = tw->tw_flags & TW_SDAY)) { if (twf == TW_SEXP) snprintf(result, sizeof(result), "%s, %s", tw_dotw[tw->tw_wday], buffer); else snprintf(result, sizeof(result), "%s (%s)", buffer, tw_dotw[tw->tw_wday]); } else strncpy(result, buffer, sizeof(result)); return result; } /* * Get the timezone for given offset. * This used to return a three-letter abbreviation for some offset * values. But not many. Until there's a good way to do that, * return the string representation of the numeric offset. */ char *dtimezone(int offset, int flags) { static char buffer[sizeof "+3579139459"]; /* 2,147,483,648 / 60 = 35,791,394 */ bool pos; unsigned os, hours, mins; pos = offset >= 0; os = pos ? offset : ~offset + 1; /* abs(3) undefined on INT_MIN. */ hours = os / 60; mins = os % 60; if (flags & TW_DST) /* Shift towards +infinity. */ hours += pos ? 1 : -1; snprintf(buffer, sizeof(buffer), "%c%02u%02u", pos ? '+' : '-', hours, mins); return buffer; } /* * Convert nmh time structure for local "broken-down" * time to calendar time (clock value). This routine * is based on the gtime() routine written by Steven Shafer * at CMU. It was forwarded to MTR by Jay Lepreau at Utah-CS. */ time_t dmktime (struct tws *tw) { int i, sec, min, hour, mday, mon, year; time_t result; if (tw->tw_clock != 0) return tw->tw_clock; if ((sec = tw->tw_sec) < 0 || sec > 61 || (min = tw->tw_min) < 0 || min > 59 || (hour = tw->tw_hour) < 0 || hour > 23 || (mday = tw->tw_mday) < 1 || mday > 31 || (mon = tw->tw_mon + 1) < 1 || mon > 12) return (tw->tw_clock = (time_t) -1); year = tw->tw_year; result = 0; if (year < 1970) year += 1900; if (year < 1970) year += 100; for (i = 1970; i < year; i++) result += dysize (i); if (dysize (year) == 366 && mon >= 3) result++; while (--mon) result += dmsize[mon - 1]; result += mday - 1; result = 24 * result + hour; result = 60 * result + min; result = 60 * result + sec; result -= 60 * tw->tw_zone; if (tw->tw_flags & TW_DST) result -= 60 * 60; return (tw->tw_clock = result); } /* * Simple calculation of day of the week. Algorithm * used is Zeller's congruence. We assume that * if tw->tw_year < 100, then the century = 19. */ void set_dotw (struct tws *tw) { int month, day, year, century; month = tw->tw_mon - 1; day = tw->tw_mday; year = tw->tw_year % 100; century = tw->tw_year < 100 ? 19 : tw->tw_year / 100; if (month <= 0) { month += 12; if (--year < 0) { year += 100; century--; } } tw->tw_wday = ((26 * month - 2) / 10 + day + year + year / 4 - 3 * century / 4 + 1) % 7; if (tw->tw_wday < 0) tw->tw_wday += 7; tw->tw_flags &= ~TW_SDAY; tw->tw_flags |= TW_SIMP; } /* * Compare two nmh time structures */ int twsort (struct tws *tw1, struct tws *tw2) { time_t c1, c2; if (tw1->tw_clock == 0) dmktime (tw1); if (tw2->tw_clock == 0) dmktime (tw2); return ((c1 = tw1->tw_clock) > (c2 = tw2->tw_clock) ? 1 : c1 == c2 ? 0 : -1); } nmh-1.7.1-RC3/sbr/dtimep.c000644 007761 000024 00000233012 13243042112 015167 0ustar00kenhstaff000000 000000 #line 3 "sbr/dtimep.c" #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 6 #define YY_FLEX_SUBMINOR_VERSION 0 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ #include #include #include #include /* end standard C headers. */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #endif /* ! C99 */ #endif /* ! FLEXINT_H */ #ifdef __cplusplus /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ /* C99 requires __STDC__ to be defined as 1. */ #if defined (__STDC__) #define YY_USE_CONST #endif /* defined (__STDC__) */ #endif /* ! __cplusplus */ #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN (yy_start) = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START (((yy_start) - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE yyrestart(yyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k. * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. * Ditto for the __ia64__ case accordingly. */ #define YY_BUF_SIZE 32768 #else #define YY_BUF_SIZE 16384 #endif /* __ia64__ */ #endif /* The state buf must be large enough to hold one state per character in the main buffer. */ #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef size_t yy_size_t; #endif extern yy_size_t yyleng; extern FILE *yyin, *yyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 #define YY_LESS_LINENO(n) #define YY_LINENO_REWIND_TO(ptr) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = (yy_hold_char); \ YY_RESTORE_YY_MORE_OFFSET \ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, (yytext_ptr) ) #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ yy_size_t yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ /* Stack of input buffers. */ static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ : NULL) /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] /* yy_hold_char holds the character lost when yytext is formed. */ static char yy_hold_char; static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */ yy_size_t yyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; static int yy_init = 0; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow yywrap()'s to do buffer switches * instead of setting up a fresh yyin. A bit of a hack ... */ static int yy_did_buffer_switch_on_eof; void yyrestart (FILE *input_file ); void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); void yy_delete_buffer (YY_BUFFER_STATE b ); void yy_flush_buffer (YY_BUFFER_STATE b ); void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); void yypop_buffer_state (void ); static void yyensure_buffer_stack (void ); static void yy_load_buffer_state (void ); static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); #define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ); void *yyalloc (yy_size_t ); void *yyrealloc (void *,yy_size_t ); void yyfree (void * ); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer(yyin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer(yyin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* Begin user sect3 */ typedef unsigned char YY_CHAR; FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; typedef int yy_state_type; extern int yylineno; int yylineno = 1; extern char *yytext; #ifdef yytext_ptr #undef yytext_ptr #endif #define yytext_ptr yytext static yy_state_type yy_get_previous_state (void ); static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); static int yy_get_next_buffer (void ); #if defined(__GNUC__) && __GNUC__ >= 3 __attribute__((__noreturn__)) #endif static void yy_fatal_error (yyconst char msg[] ); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ yyleng = (size_t) (yy_cp - yy_bp); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; #define YY_NUM_RULES 30 #define YY_END_OF_BUFFER 31 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info { flex_int32_t yy_verify; flex_int32_t yy_nxt; }; static yyconst flex_int16_t yy_accept[571] = { 0, 0, 0, 31, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 25, 19, 18, 17, 16, 15, 28, 27, 21, 20, 24, 23, 22, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 5, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 6, 6, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 6, 0, 0, 0, 0, 0, 0, 6, 6, 0, 2, 4, 1, 1, 0, 6, 0, 0, 0, 1, 0, 0, 1, 2, 4, 0 } ; static yyconst YY_CHAR yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 4, 4, 1, 5, 6, 7, 1, 8, 9, 10, 9, 9, 9, 9, 9, 9, 9, 9, 11, 1, 1, 1, 1, 1, 1, 12, 1, 13, 14, 15, 16, 17, 18, 1, 19, 1, 1, 20, 21, 22, 23, 1, 1, 24, 25, 26, 1, 27, 1, 1, 1, 28, 1, 29, 1, 1, 1, 30, 31, 32, 33, 34, 16, 35, 36, 37, 19, 1, 38, 39, 40, 41, 42, 1, 43, 44, 45, 46, 47, 27, 1, 48, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst YY_CHAR yy_meta[49] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst flex_uint16_t yy_base[571] = { 0, 0, 0, 907, 908, 37, 52, 55, 78, 24, 872, 25, 44, 48, 864, 872, 61, 46, 869, 81, 70, 82, 84, 882, 85, 86, 877, 87, 875, 69, 70, 72, 860, 79, 82, 854, 84, 852, 109, 111, 127, 115, 125, 853, 860, 862, 862, 855, 851, 13, 87, 850, 842, 843, 842, 844, 845, 838, 849, 849, 851, 838, 854, 853, 852, 851, 850, 849, 848, 847, 846, 845, 844, 843, 842, 841, 908, 820, 819, 818, 817, 816, 815, 814, 813, 812, 811, 810, 809, 808, 807, 127, 135, 92, 817, 816, 51, 819, 807, 815, 812, 145, 138, 140, 129, 148, 156, 154, 157, 159, 162, 843, 163, 168, 170, 171, 174, 176, 177, 178, 186, 815, 814, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 908, 188, 194, 799, 806, 808, 808, 798, 147, 147, 790, 791, 793, 197, 205, 206, 796, 789, 793, 785, 225, 828, 799, 798, 825, 824, 789, 794, 784, 791, 778, 786, 789, 774, 784, 782, 787, 786, 908, 908, 199, 172, 197, 208, 179, 212, 219, 222, 811, 227, 221, 226, 223, 233, 266, 810, 766, 779, 779, 268, 206, 774, 773, 210, 776, 764, 772, 769, 754, 758, 798, 751, 767, 763, 763, 756, 746, 760, 762, 747, 770, 769, 271, 750, 743, 747, 739, 754, 781, 780, 745, 741, 748, 744, 277, 280, 282, 775, 257, 774, 741, 731, 291, 771, 729, 736, 738, 738, 728, 245, 251, 720, 721, 723, 294, 716, 295, 729, 719, 731, 729, 296, 729, 710, 724, 717, 716, 299, 307, 752, 708, 721, 721, 707, 747, 717, 713, 707, 316, 310, 327, 313, 318, 702, 696, 292, 709, 708, 258, 711, 699, 707, 704, 304, 228, 312, 331, 293, 338, 341, 340, 735, 342, 343, 345, 693, 733, 686, 699, 684, 346, 701, 701, 700, 347, 349, 726, 693, 683, 677, 690, 680, 691, 344, 719, 358, 360, 718, 717, 675, 682, 684, 684, 674, 323, 330, 666, 667, 669, 378, 672, 665, 669, 661, 676, 703, 702, 667, 663, 670, 666, 697, 375, 655, 377, 649, 908, 908, 383, 385, 387, 653, 647, 651, 691, 658, 680, 389, 398, 688, 392, 401, 369, 363, 348, 389, 402, 403, 406, 413, 687, 410, 411, 414, 418, 686, 642, 655, 655, 641, 681, 651, 647, 641, 677, 415, 420, 676, 675, 674, 673, 631, 424, 630, 631, 389, 221, 637, 444, 445, 632, 625, 629, 621, 636, 663, 662, 627, 623, 630, 626, 447, 657, 456, 656, 623, 613, 607, 620, 610, 621, 640, 429, 648, 638, 611, 607, 601, 605, 598, 609, 609, 451, 454, 639, 595, 608, 608, 594, 634, 604, 600, 594, 456, 459, 469, 589, 583, 587, 627, 594, 463, 465, 594, 593, 579, 591, 580, 578, 581, 474, 478, 618, 585, 575, 569, 582, 572, 583, 480, 483, 492, 486, 490, 611, 610, 609, 567, 598, 495, 578, 577, 563, 575, 560, 570, 568, 504, 498, 507, 558, 552, 556, 596, 563, 509, 594, 511, 513, 522, 524, 533, 593, 527, 908, 546, 545, 559, 543, 557, 559, 544, 535, 585, 584, 583, 525, 482, 538, 475, 527, 531, 908, 908, 485, 908, 482, 462, 464, 474, 541, 451, 430, 543, 552, 546, 908, 388, 378, 908, 220, 548, 550, 554, 556, 558, 908, 908, 190, 111, 64, 560, 562, 54, 908, 564, 566, 568, 570, 572, 574, 908, 908, 908, 908 } ; static yyconst flex_int16_t yy_def[571] = { 0, 570, 1, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 0 } ; static yyconst flex_uint16_t yy_nxt[957] = { 0, 4, 5, 5, 5, 6, 4, 7, 4, 8, 8, 4, 9, 4, 10, 4, 11, 4, 4, 12, 13, 14, 15, 4, 16, 17, 4, 18, 19, 4, 9, 4, 4, 10, 4, 4, 4, 4, 4, 13, 14, 15, 4, 4, 16, 17, 4, 4, 4, 20, 21, 108, 22, 109, 23, 24, 540, 25, 26, 46, 27, 38, 38, 28, 39, 39, 43, 29, 47, 30, 44, 31, 32, 33, 48, 562, 34, 35, 50, 36, 40, 143, 57, 37, 62, 41, 41, 42, 42, 51, 49, 54, 58, 60, 63, 55, 64, 144, 66, 69, 71, 74, 77, 79, 61, 81, 65, 56, 67, 70, 72, 75, 84, 78, 80, 86, 82, 89, 91, 91, 92, 92, 561, 85, 101, 101, 87, 40, 90, 40, 110, 151, 41, 41, 139, 111, 137, 137, 140, 93, 151, 94, 151, 95, 138, 138, 96, 97, 98, 99, 151, 100, 149, 149, 150, 150, 151, 93, 156, 151, 94, 151, 157, 154, 151, 156, 97, 98, 99, 157, 151, 100, 151, 156, 218, 152, 151, 157, 156, 156, 156, 218, 157, 157, 157, 181, 153, 182, 156, 158, 183, 155, 157, 161, 162, 184, 163, 174, 174, 218, 159, 218, 164, 175, 175, 160, 188, 189, 151, 168, 218, 165, 149, 149, 218, 190, 190, 166, 220, 167, 169, 218, 170, 218, 218, 223, 171, 156, 218, 218, 335, 221, 230, 230, 195, 195, 219, 196, 560, 197, 244, 198, 231, 231, 199, 200, 201, 202, 240, 203, 554, 222, 241, 225, 226, 196, 245, 435, 197, 232, 224, 227, 228, 233, 200, 201, 202, 436, 232, 203, 238, 229, 233, 218, 337, 234, 234, 239, 239, 274, 263, 264, 274, 294, 232, 295, 275, 275, 329, 276, 276, 277, 278, 238, 296, 335, 156, 156, 156, 297, 157, 157, 157, 281, 330, 282, 335, 283, 310, 310, 284, 285, 286, 287, 335, 288, 311, 311, 274, 320, 320, 281, 321, 321, 282, 319, 319, 322, 322, 274, 285, 286, 287, 335, 325, 288, 320, 320, 326, 340, 335, 336, 335, 335, 335, 335, 338, 335, 156, 354, 405, 354, 157, 362, 362, 363, 355, 355, 356, 356, 364, 373, 364, 374, 365, 405, 365, 366, 366, 367, 367, 405, 343, 375, 339, 342, 344, 156, 376, 156, 335, 157, 408, 157, 345, 354, 341, 380, 380, 354, 346, 405, 392, 392, 393, 393, 393, 393, 398, 398, 364, 404, 404, 364, 405, 405, 406, 365, 405, 407, 404, 404, 405, 405, 399, 405, 405, 156, 400, 433, 417, 157, 401, 402, 418, 403, 553, 419, 419, 427, 427, 428, 409, 430, 430, 434, 552, 400, 457, 457, 412, 539, 401, 402, 414, 413, 364, 405, 410, 417, 365, 411, 415, 405, 438, 439, 449, 450, 417, 416, 466, 466, 418, 467, 467, 475, 475, 476, 477, 477, 476, 451, 484, 484, 485, 485, 493, 501, 478, 479, 493, 502, 501, 494, 494, 536, 502, 495, 495, 503, 503, 476, 504, 504, 501, 506, 506, 546, 502, 507, 507, 505, 505, 476, 510, 510, 493, 519, 519, 493, 545, 501, 544, 518, 518, 543, 519, 519, 524, 524, 525, 525, 526, 526, 501, 537, 501, 405, 502, 540, 502, 525, 525, 503, 503, 501, 527, 527, 541, 502, 542, 542, 505, 505, 535, 535, 536, 538, 538, 539, 547, 547, 548, 548, 540, 551, 551, 555, 555, 556, 556, 549, 550, 557, 557, 558, 558, 559, 559, 563, 563, 564, 564, 565, 565, 566, 566, 567, 567, 567, 567, 568, 568, 569, 569, 405, 405, 493, 534, 533, 532, 531, 530, 529, 528, 335, 501, 523, 405, 522, 521, 520, 517, 516, 515, 514, 513, 512, 511, 509, 508, 335, 335, 335, 500, 499, 498, 376, 497, 496, 405, 492, 491, 490, 489, 488, 487, 486, 483, 335, 482, 481, 480, 474, 473, 472, 405, 471, 470, 469, 468, 405, 465, 464, 463, 462, 461, 460, 459, 458, 218, 428, 456, 455, 454, 297, 453, 452, 335, 451, 448, 447, 446, 445, 405, 405, 444, 443, 442, 441, 440, 437, 432, 431, 429, 218, 218, 218, 354, 151, 426, 425, 424, 335, 423, 422, 421, 420, 335, 405, 364, 363, 397, 218, 396, 395, 394, 391, 390, 151, 389, 388, 387, 386, 335, 335, 385, 384, 383, 382, 381, 379, 378, 377, 372, 371, 370, 369, 368, 151, 151, 274, 361, 360, 359, 184, 358, 357, 218, 353, 352, 351, 350, 349, 348, 151, 347, 335, 334, 333, 332, 331, 328, 327, 324, 323, 318, 317, 316, 218, 315, 314, 313, 312, 218, 309, 308, 307, 306, 305, 304, 303, 302, 301, 111, 300, 299, 298, 293, 292, 291, 290, 289, 238, 280, 279, 151, 232, 273, 272, 271, 270, 218, 218, 269, 268, 267, 266, 265, 262, 261, 260, 259, 258, 257, 256, 255, 254, 253, 252, 151, 251, 250, 249, 248, 247, 246, 243, 242, 237, 236, 235, 151, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 151, 151, 205, 204, 156, 194, 193, 192, 191, 187, 186, 185, 180, 179, 178, 177, 176, 173, 172, 151, 148, 147, 146, 145, 142, 141, 136, 135, 134, 133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123, 136, 135, 134, 133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 107, 106, 105, 104, 103, 102, 76, 88, 83, 76, 73, 68, 59, 53, 52, 45, 570, 3, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570 } ; static yyconst flex_int16_t yy_chk[957] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 5, 49, 5, 49, 5, 5, 559, 5, 5, 11, 5, 6, 6, 5, 7, 7, 9, 5, 11, 5, 9, 5, 5, 5, 12, 556, 5, 5, 13, 5, 8, 96, 17, 5, 20, 8, 8, 8, 8, 13, 12, 16, 17, 19, 20, 16, 21, 96, 22, 24, 25, 27, 29, 30, 19, 31, 21, 16, 22, 24, 25, 27, 33, 29, 30, 34, 31, 36, 38, 38, 39, 39, 555, 33, 41, 41, 34, 42, 36, 40, 50, 104, 42, 42, 93, 50, 91, 91, 93, 40, 102, 40, 103, 40, 92, 92, 40, 40, 40, 40, 105, 40, 101, 101, 101, 101, 107, 40, 106, 108, 40, 109, 106, 104, 110, 112, 40, 40, 40, 112, 113, 40, 114, 115, 177, 102, 116, 115, 117, 118, 119, 180, 117, 118, 119, 144, 103, 144, 120, 106, 145, 105, 120, 109, 110, 145, 112, 137, 137, 178, 107, 176, 113, 138, 138, 108, 149, 149, 151, 117, 179, 114, 150, 150, 181, 151, 151, 115, 177, 116, 118, 182, 119, 186, 183, 180, 120, 156, 187, 185, 290, 178, 188, 188, 156, 156, 176, 156, 554, 156, 199, 156, 189, 189, 156, 156, 156, 156, 196, 156, 546, 179, 196, 182, 183, 156, 199, 402, 156, 234, 181, 185, 186, 234, 156, 156, 156, 402, 190, 156, 195, 187, 190, 218, 290, 190, 190, 195, 195, 230, 218, 218, 231, 245, 232, 245, 230, 230, 284, 231, 231, 232, 232, 238, 246, 293, 250, 252, 257, 246, 250, 252, 257, 238, 284, 238, 289, 238, 263, 263, 238, 238, 238, 238, 291, 238, 264, 264, 274, 275, 275, 238, 277, 277, 238, 274, 274, 278, 278, 276, 238, 238, 238, 292, 281, 238, 276, 276, 281, 293, 294, 289, 296, 295, 298, 299, 291, 300, 306, 310, 370, 311, 306, 319, 319, 319, 310, 310, 311, 311, 321, 330, 322, 330, 321, 369, 322, 321, 321, 322, 322, 368, 296, 331, 292, 295, 298, 348, 331, 350, 335, 348, 370, 350, 299, 354, 294, 335, 335, 356, 300, 371, 354, 354, 355, 355, 356, 356, 363, 363, 364, 366, 366, 367, 372, 373, 368, 367, 374, 369, 367, 367, 377, 378, 364, 375, 379, 391, 364, 401, 380, 391, 364, 364, 380, 364, 544, 380, 380, 392, 392, 392, 371, 398, 398, 401, 543, 364, 428, 428, 374, 538, 364, 364, 377, 375, 404, 405, 372, 417, 404, 373, 378, 537, 405, 405, 417, 417, 419, 379, 438, 438, 419, 439, 439, 449, 449, 449, 450, 450, 450, 451, 457, 457, 458, 458, 466, 525, 451, 451, 467, 525, 475, 466, 466, 535, 475, 467, 467, 475, 475, 475, 476, 476, 477, 478, 478, 534, 477, 479, 479, 477, 477, 477, 485, 485, 493, 494, 494, 495, 533, 501, 532, 493, 493, 530, 495, 495, 501, 501, 503, 503, 504, 504, 505, 523, 506, 522, 505, 526, 506, 505, 505, 506, 506, 507, 509, 509, 526, 507, 527, 527, 507, 507, 518, 518, 518, 524, 524, 524, 536, 536, 539, 539, 540, 541, 541, 547, 547, 548, 548, 540, 540, 549, 549, 550, 550, 551, 551, 557, 557, 558, 558, 561, 561, 562, 562, 563, 563, 564, 564, 565, 565, 566, 566, 521, 520, 519, 517, 516, 515, 514, 513, 512, 511, 508, 502, 500, 499, 498, 497, 496, 492, 491, 490, 489, 488, 487, 486, 484, 483, 482, 481, 480, 474, 473, 472, 471, 470, 469, 468, 465, 464, 463, 462, 461, 460, 459, 456, 455, 454, 453, 452, 448, 447, 446, 445, 444, 443, 442, 441, 440, 437, 436, 435, 434, 433, 432, 431, 430, 429, 427, 426, 425, 424, 423, 422, 421, 420, 418, 416, 415, 414, 413, 412, 411, 410, 409, 408, 407, 406, 403, 400, 399, 397, 396, 395, 394, 393, 390, 389, 388, 387, 386, 385, 384, 383, 382, 381, 376, 365, 362, 361, 360, 359, 358, 357, 351, 349, 347, 346, 345, 344, 343, 342, 341, 340, 339, 338, 337, 336, 334, 333, 332, 329, 328, 327, 326, 325, 324, 323, 320, 318, 317, 316, 315, 314, 313, 312, 309, 308, 307, 305, 304, 303, 302, 301, 297, 288, 287, 286, 285, 283, 282, 280, 279, 273, 272, 271, 270, 269, 268, 267, 266, 265, 262, 261, 260, 259, 258, 256, 255, 254, 253, 251, 249, 248, 247, 244, 243, 242, 241, 240, 239, 237, 236, 235, 233, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 198, 197, 194, 193, 192, 191, 184, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 155, 154, 153, 152, 148, 147, 146, 143, 142, 141, 140, 139, 122, 121, 111, 100, 99, 98, 97, 95, 94, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 48, 47, 46, 45, 44, 43, 37, 35, 32, 28, 26, 23, 18, 15, 14, 10, 3, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570, 570 } ; static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; extern int yy_flex_debug; int yy_flex_debug = 0; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *yytext; #line 1 "sbr/dtimep.l" /* dtimep.l -- parse dates and times. * * This exceeds the default table capacities for some old versions * of lex (and the minimum defaults as specified by POSIX). The following * choices meet or exceed the lex defaults for older SunOS4.x, Solaris, * HPUX, and AIX. */ #line 13 "sbr/dtimep.l" #include #include /* Since we're looking at a string at a time, don't worry about * wrapping to the next buffer. */ #if YY_FLEX_MAJOR_VERSION == 2 && \ YY_FLEX_MINOR_VERSION == 6 && \ YY_FLEX_SUBMINOR_VERSION == 3 /* https://github.com/westes/flex/issues/162 */ #undef yywrap #endif #define yywrap() 1 #define YY_SKIP_YYWRAP #define YY_NO_INPUT /* This is the tricky thing that makes this function cool. We * replace the traditional int yylex(void) declaration with our * dparsetime() declaration, essentially piggy-backing off the * utility of the yylex() function and adding what we need to make * the parsing function useful to us. */ #define YY_DECL struct tws *dparsetime(char *lexstr) /* yyterminate() is called after the input string is matched to * completion (actually, when the lexer reaches an EOF). The only * thing that really needs to be in this macro function is the * return call, which must be substituted inline into dparsetime. */ #define yyterminate() (void)yy_delete_buffer(lexhandle); \ if(!(tw.tw_flags & TW_SUCC)) { \ return (struct tws *)NULL; \ } \ if(tw.tw_year < 1970) \ tw.tw_year += 1900; \ if(tw.tw_year < 1970) \ tw.tw_year += 100; \ return(&tw) /* * Table to convert month names to numeric month. We use the * fact that the low order 5 bits of the sum of the 2nd & 3rd * characters of the name is a hash with no collisions for the 12 * valid month names. (The mask to 5 bits maps any combination of * upper and lower case into the same hash value). */ static int month_map[] = { 0, 6, /* 1 - Jul */ 3, /* 2 - Apr */ 5, /* 3 - Jun */ 0, 10, /* 5 - Nov */ 0, 1, /* 7 - Feb */ 11, /* 8 - Dec */ 0, 0, 0, 0, 0, 0, 0, /*15 - Jan */ 0, 0, 0, 2, /*19 - Mar */ 0, 8, /*21 - Sep */ 0, 9, /*23 - Oct */ 0, 0, 4, /*26 - May */ 0, 7 /*28 - Aug */ }; /* * Lookup table for day-of-week using the same hash trick as for above name-of- * month table, but using the first and second character, not second and third. * * Compute index into table using: (day_name[0] & 7) + (day_name[1] & 4) */ static int day_map[] = { 0, 0, 0, 6, /* 3 - Sat */ 4, /* 4 - Thu */ 0, 5, /* 6 - Fri */ 0, /* 7 - Sun */ 2, /* 8 - Tue */ 1 /* 9 - Mon */, 0, 3 /*11 - Wed */ }; /* The SET* macros will parse for the appropriate field, and leave the * cp pointer at the first character after the desired field. Be * careful with variable-length fields or alpha-num mixes. * The SKIP* macros skip over characters of a particular class and * leave cp at the position of the first character that doesn't match * that class. Correspondingly, SKIPTO* skips until it reaches a * character of a particular class. */ #define INIT() { cp = yytext;} #define SETWDAY() { tw.tw_wday= day_map[(cp[0] & 7) + (cp[1] & 4)]; \ tw.tw_flags &= ~TW_SDAY; tw.tw_flags |= TW_SEXP; \ SKIPA(); } #define SETMON() { cp++; \ tw.tw_mon = month_map[(((unsigned char) cp[0]) + ((unsigned char) cp[1])) & 0x1f]; \ SKIPA(); } #define SETMON_NUM() { tw.tw_mon = atoi(cp)-1; \ SKIPD(); } #define SETYEAR() { tw.tw_year = atoi(cp); \ SKIPD(); } #define SETDAY() { tw.tw_mday = atoi(cp); \ tw.tw_flags |= TW_SUCC; \ SKIPD(); } #define SETTIME() { tw.tw_hour = atoi(cp); \ cp += 2; \ SKIPTOD(); \ tw.tw_min = atoi(cp); \ cp += 2; \ if(*cp == ':') { \ tw.tw_sec = atoi(++cp); SKIPD(); } } #define SETZONE(x) { tw.tw_zone = ((x)/100)*60+(x)%100; \ tw.tw_flags |= TW_SZEXP; \ SKIPD(); } #define SETDST() { tw.tw_flags |= TW_DST; } #define SKIPD() { while ( isdigit((unsigned char) *cp++) ) ; \ --cp; } #define SKIPTOD() { while ( !isdigit((unsigned char) *cp++) ) ; \ --cp; } #define SKIPA() { while ( isalpha((unsigned char) *cp++) ) ; \ --cp; } #define SKIPTOA() { while ( !isalpha((unsigned char) *cp++) ) ; \ --cp; } #define SKIPSP() { while ( isspace((unsigned char) *cp++) ) ; \ --cp; } #define SKIPTOSP() { while ( !isspace((unsigned char) *cp++) ) ; \ --cp; } # ifdef HAVE_SYS_TIME_H # include # endif #include static void zonehack (struct tws *tw) { struct tm *tm; if (dmktime (tw) == (time_t) -1) return; tm = localtime (&tw->tw_clock); if (tm->tm_isdst) { tw->tw_flags |= TW_DST; tw->tw_zone -= 60; } } /* The year can either be 2 digits, or 4. However, after Y2K, we found that some MUA were reporting the year 100, hence the middle term here. yyterminate() resolves the actual issues with 2-digit years. */ #line 1041 "sbr/dtimep.c" #define INITIAL 0 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ #include #endif #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * #endif static int yy_init_globals (void ); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ int yylex_destroy (void ); int yyget_debug (void ); void yyset_debug (int debug_flag ); YY_EXTRA_TYPE yyget_extra (void ); void yyset_extra (YY_EXTRA_TYPE user_defined ); FILE *yyget_in (void ); void yyset_in (FILE * _in_str ); FILE *yyget_out (void ); void yyset_out (FILE * _out_str ); yy_size_t yyget_leng (void ); char *yyget_text (void ); int yyget_lineno (void ); void yyset_lineno (int _line_number ); /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int yywrap (void ); #else extern int yywrap (void ); #endif #endif #ifndef YY_NO_UNPUT static void yyunput (int c,char *buf_ptr ); #endif #ifndef yytext_ptr static void yy_flex_strncpy (char *,yyconst char *,int ); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * ); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void ); #else static int input (void ); #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k */ #define YY_READ_BUF_SIZE 16384 #else #define YY_READ_BUF_SIZE 8192 #endif /* __ia64__ */ #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ size_t n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else \ { \ errno=0; \ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ { \ if( errno != EINTR) \ { \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ break; \ } \ errno=0; \ clearerr(yyin); \ } \ }\ \ #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif /* end tables serialization structures and prototypes */ /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 extern int yylex (void); #define YY_DECL int yylex (void) #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK /*LINTED*/break; #endif #define YY_RULE_SETUP \ YY_USER_ACTION /** The main scanner function which does all the work. */ YY_DECL { yy_state_type yy_current_state; char *yy_cp, *yy_bp; int yy_act; if ( !(yy_init) ) { (yy_init) = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! (yy_start) ) (yy_start) = 1; /* first start state */ if ( ! yyin ) yyin = stdin; if ( ! yyout ) yyout = stdout; if ( ! YY_CURRENT_BUFFER ) { yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin,YY_BUF_SIZE ); } yy_load_buffer_state( ); } { #line 224 "sbr/dtimep.l" /* This section begins the definition of dparsetime(). Put here any local variable definitions and initializations */ YY_BUFFER_STATE lexhandle; char *cp; static struct tws tw; memset(&tw,0,sizeof(struct tws)); lexhandle = yy_scan_string(lexstr); #line 1275 "sbr/dtimep.c" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { yy_cp = (yy_c_buf_p); /* Support of yytext. */ *yy_cp = (yy_hold_char); /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = (yy_start); yy_match: do { YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 571 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } while ( yy_base[yy_current_state] != 908 ); yy_find_action: yy_act = yy_accept[yy_current_state]; if ( yy_act == 0 ) { /* have to back up */ yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); yy_act = yy_accept[yy_current_state]; } YY_DO_BEFORE_ACTION; do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = (yy_hold_char); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); goto yy_find_action; case 1: YY_RULE_SETUP #line 239 "sbr/dtimep.l" { INIT(); SETWDAY(); SKIPTOA(); SETMON(); SKIPTOD(); SETDAY(); SKIPTOD(); SETTIME(); SKIPTOD(); SETYEAR(); } YY_BREAK case 2: YY_RULE_SETUP #line 252 "sbr/dtimep.l" { INIT(); SETWDAY(); SKIPTOD(); SETDAY(); SKIPTOA(); SETMON(); SKIPTOD(); SETYEAR(); SKIPTOD(); SETTIME(); } YY_BREAK case 3: YY_RULE_SETUP #line 264 "sbr/dtimep.l" { INIT(); SETDAY(); SKIPTOA(); SETMON(); SKIPTOD(); SETYEAR(); SKIPTOD(); SETTIME(); } YY_BREAK case 4: YY_RULE_SETUP #line 274 "sbr/dtimep.l" { INIT(); SETWDAY(); SKIPTOA(); SETMON(); SKIPTOD(); SETDAY(); SKIPTOD(); SETYEAR(); SKIPTOD(); SETTIME(); } YY_BREAK case 5: YY_RULE_SETUP #line 286 "sbr/dtimep.l" { INIT(); SETWDAY(); SKIPTOA(); SETMON(); SKIPTOD(); SETDAY(); SKIPTOD(); SETYEAR(); } YY_BREAK case 6: YY_RULE_SETUP #line 296 "sbr/dtimep.l" { INIT(); SETMON(); SKIPTOD(); SETDAY(); SKIPTOD(); SETYEAR(); SKIPTOA(); SETWDAY(); } YY_BREAK case 7: YY_RULE_SETUP #line 306 "sbr/dtimep.l" { INIT(); SETMON(); SKIPTOD(); SETDAY(); SKIPTOD(); SETYEAR(); } YY_BREAK case 8: YY_RULE_SETUP #line 314 "sbr/dtimep.l" { INIT(); /* MM/DD/YY */ SETMON_NUM(); SKIPTOD(); SETDAY(); SKIPTOD(); SETYEAR(); SKIPTOD(); SETTIME(); } YY_BREAK case 9: YY_RULE_SETUP #line 325 "sbr/dtimep.l" { INIT(); /* MM/DD/YY */ SETMON_NUM(); SKIPTOD(); SETDAY(); SKIPTOD(); SETYEAR(); } YY_BREAK case 10: YY_RULE_SETUP #line 335 "sbr/dtimep.l" YY_BREAK case 11: YY_RULE_SETUP #line 336 "sbr/dtimep.l" tw.tw_hour += 12; YY_BREAK case 12: YY_RULE_SETUP #line 338 "sbr/dtimep.l" { INIT(); SKIPTOD(); SETZONE(atoi(cp)); zonehack (&tw); yyterminate(); } YY_BREAK case 13: YY_RULE_SETUP #line 345 "sbr/dtimep.l" { INIT(); SKIPTOD(); SETZONE(-atoi(cp)); zonehack (&tw); yyterminate(); } YY_BREAK case 14: /* rule 14 can match eol */ YY_RULE_SETUP #line 353 "sbr/dtimep.l" INIT(); SETZONE(0); yyterminate(); YY_BREAK case 15: /* rule 15 can match eol */ YY_RULE_SETUP #line 354 "sbr/dtimep.l" INIT(); SETZONE(0); yyterminate(); YY_BREAK case 16: /* rule 16 can match eol */ YY_RULE_SETUP #line 355 "sbr/dtimep.l" INIT(); SETZONE(-500); yyterminate(); YY_BREAK case 17: /* rule 17 can match eol */ YY_RULE_SETUP #line 356 "sbr/dtimep.l" { INIT(); SETDST(); SETZONE(-500); yyterminate(); } YY_BREAK case 18: /* rule 18 can match eol */ YY_RULE_SETUP #line 358 "sbr/dtimep.l" INIT(); SETZONE(-600); yyterminate(); YY_BREAK case 19: /* rule 19 can match eol */ YY_RULE_SETUP #line 359 "sbr/dtimep.l" { INIT(); SETDST(); SETZONE(-600); yyterminate(); } YY_BREAK case 20: /* rule 20 can match eol */ YY_RULE_SETUP #line 361 "sbr/dtimep.l" INIT(); SETZONE(-700); yyterminate(); YY_BREAK case 21: /* rule 21 can match eol */ YY_RULE_SETUP #line 362 "sbr/dtimep.l" { INIT(); SETDST(); SETZONE(-700); yyterminate(); } YY_BREAK case 22: /* rule 22 can match eol */ YY_RULE_SETUP #line 364 "sbr/dtimep.l" INIT(); SETZONE(-800); yyterminate(); YY_BREAK case 23: /* rule 23 can match eol */ YY_RULE_SETUP #line 365 "sbr/dtimep.l" { INIT(); SETDST(); SETZONE(-800); yyterminate(); } YY_BREAK case 24: /* rule 24 can match eol */ YY_RULE_SETUP #line 367 "sbr/dtimep.l" INIT(); SETZONE(-330); yyterminate(); YY_BREAK case 25: /* rule 25 can match eol */ YY_RULE_SETUP #line 368 "sbr/dtimep.l" INIT(); SETZONE(-400); yyterminate(); YY_BREAK case 26: /* rule 26 can match eol */ YY_RULE_SETUP #line 369 "sbr/dtimep.l" { INIT(); SETDST(); SETZONE(-400); yyterminate(); } YY_BREAK case 27: /* rule 27 can match eol */ YY_RULE_SETUP #line 371 "sbr/dtimep.l" INIT(); SETZONE(-1000); yyterminate(); YY_BREAK case 28: /* rule 28 can match eol */ YY_RULE_SETUP #line 372 "sbr/dtimep.l" { INIT(); SETDST(); SETZONE(-1000); yyterminate(); } YY_BREAK case 29: /* rule 29 can match eol */ YY_RULE_SETUP #line 374 "sbr/dtimep.l" YY_BREAK case 30: YY_RULE_SETUP #line 376 "sbr/dtimep.l" ECHO; YY_BREAK #line 1602 "sbr/dtimep.c" case YY_STATE_EOF(INITIAL): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = (yy_hold_char); YY_RESTORE_YY_MORE_OFFSET if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) { /* This was really a NUL. */ yy_state_type yy_next_state; (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = (yytext_ptr) + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++(yy_c_buf_p); yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = (yy_c_buf_p); goto yy_find_action; } } else switch ( yy_get_next_buffer( ) ) { case EOB_ACT_END_OF_FILE: { (yy_did_buffer_switch_on_eof) = 0; if ( yywrap( ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * yytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: (yy_c_buf_p) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of user's declarations */ } /* end of yylex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer (void) { char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; char *source = (yytext_ptr); yy_size_t number_to_move, i; int ret_val; if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (yy_size_t) ((yy_c_buf_p) - (yytext_ptr)) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; else { yy_size_t num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; int yy_c_buf_p_offset = (int) ((yy_c_buf_p) - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { yy_size_t new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = 0; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), (yy_n_chars), (size_t) num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } if ( (yy_n_chars) == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; yyrestart(yyin ); } else { ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); } (yy_n_chars) += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state (void) { yy_state_type yy_current_state; char *yy_cp; yy_current_state = (yy_start); for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) { YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 571 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) { int yy_is_jam; char *yy_cp = (yy_c_buf_p); YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 571 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 570); return yy_is_jam ? 0 : yy_current_state; } #ifndef YY_NO_UNPUT static void yyunput (int c, char * yy_bp ) { char *yy_cp; yy_cp = (yy_c_buf_p); /* undo effects of setting up yytext */ *yy_cp = (yy_hold_char); if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ yy_size_t number_to_move = (yy_n_chars) + 2; char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; char *source = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; (yytext_ptr) = yy_bp; (yy_hold_char) = *yy_cp; (yy_c_buf_p) = yy_cp; } #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void) #else static int input (void) #endif { int c; *(yy_c_buf_p) = (yy_hold_char); if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) /* This was really a NUL. */ *(yy_c_buf_p) = '\0'; else { /* need more input */ yy_size_t offset = (yy_c_buf_p) - (yytext_ptr); ++(yy_c_buf_p); switch ( yy_get_next_buffer( ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ yyrestart(yyin ); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( yywrap( ) ) return EOF; if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + offset; break; } } } c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ *(yy_c_buf_p) = '\0'; /* preserve yytext */ (yy_hold_char) = *++(yy_c_buf_p); return c; } #endif /* ifndef YY_NO_INPUT */ /** Immediately switch to a different input stream. * @param input_file A readable stream. * * @note This function does not reset the start condition to @c INITIAL . */ void yyrestart (FILE * input_file ) { if ( ! YY_CURRENT_BUFFER ){ yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin,YY_BUF_SIZE ); } yy_init_buffer(YY_CURRENT_BUFFER,input_file ); yy_load_buffer_state( ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * */ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) { /* TODO. We should be able to replace this entire function body * with * yypop_buffer_state(); * yypush_buffer_state(new_buffer); */ yyensure_buffer_stack (); if ( YY_CURRENT_BUFFER == new_buffer ) return; if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } YY_CURRENT_BUFFER_LVALUE = new_buffer; yy_load_buffer_state( ); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ (yy_did_buffer_switch_on_eof) = 1; } static void yy_load_buffer_state (void) { (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; (yy_hold_char) = *(yy_c_buf_p); } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. * * @return the allocated buffer state. */ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_buf_size = (yy_size_t)size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; yy_init_buffer(b,file ); return b; } /** Destroy the buffer. * @param b a buffer created with yy_create_buffer() * */ void yy_delete_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) yyfree((void *) b->yy_ch_buf ); yyfree((void *) b ); } /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a yyrestart() or at EOF. */ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) { int oerrno = errno; yy_flush_buffer(b ); b->yy_input_file = file; b->yy_fill_buffer = 1; /* If b is the current buffer, then yy_init_buffer was _probably_ * called from yyrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ b->yy_bs_lineno = 1; b->yy_bs_column = 0; } b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * */ void yy_flush_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) yy_load_buffer_state( ); } /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * */ void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) { if (new_buffer == NULL) return; yyensure_buffer_stack(); /* This block is copied from yy_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) (yy_buffer_stack_top)++; YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from yy_switch_to_buffer. */ yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * */ void yypop_buffer_state (void) { if (!YY_CURRENT_BUFFER) return; yy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; if ((yy_buffer_stack_top) > 0) --(yy_buffer_stack_top); if (YY_CURRENT_BUFFER) { yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } } /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ static void yyensure_buffer_stack (void) { yy_size_t num_to_alloc; if (!(yy_buffer_stack)) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; // After all that talk, this was set to 1 anyways... (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc (num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; (yy_buffer_stack_top) = 0; return; } if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ /* Increase the buffer to prepare for a possible push. */ yy_size_t grow_size = 8 /* arbitrary grow size */; num_to_alloc = (yy_buffer_stack_max) + grow_size; (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc ((yy_buffer_stack), num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); /* zero only the new slots.*/ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; } } /** Setup the input buffer state to scan directly from a user-specified character buffer. * @param base the character buffer * @param size the size in bytes of the character buffer * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = 0; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; yy_switch_to_buffer(b ); return b; } /** Setup the input buffer state to scan a string. The next call to yylex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * yy_scan_bytes() instead. */ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) { return yy_scan_bytes(yystr,strlen(yystr) ); } /** Setup the input buffer state to scan the given bytes. The next call to yylex() will * scan from a @e copy of @a bytes. * @param yybytes the byte buffer to scan * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len ) { YY_BUFFER_STATE b; char *buf; yy_size_t n; yy_size_t i; /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; buf = (char *) yyalloc(n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; b = yy_scan_buffer(buf,n ); if ( ! b ) YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif static void yy_fatal_error (yyconst char* msg ) { (void) fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ yytext[yyleng] = (yy_hold_char); \ (yy_c_buf_p) = yytext + yyless_macro_arg; \ (yy_hold_char) = *(yy_c_buf_p); \ *(yy_c_buf_p) = '\0'; \ yyleng = yyless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ /** Get the current line number. * */ int yyget_lineno (void) { return yylineno; } /** Get the input stream. * */ FILE *yyget_in (void) { return yyin; } /** Get the output stream. * */ FILE *yyget_out (void) { return yyout; } /** Get the length of the current token. * */ yy_size_t yyget_leng (void) { return yyleng; } /** Get the current token. * */ char *yyget_text (void) { return yytext; } /** Set the current line number. * @param _line_number line number * */ void yyset_lineno (int _line_number ) { yylineno = _line_number; } /** Set the input stream. This does not discard the current * input buffer. * @param _in_str A readable stream. * * @see yy_switch_to_buffer */ void yyset_in (FILE * _in_str ) { yyin = _in_str ; } void yyset_out (FILE * _out_str ) { yyout = _out_str ; } int yyget_debug (void) { return yy_flex_debug; } void yyset_debug (int _bdebug ) { yy_flex_debug = _bdebug ; } static int yy_init_globals (void) { /* Initialization is the same as for the non-reentrant scanner. * This function is called from yylex_destroy(), so don't allocate here. */ (yy_buffer_stack) = 0; (yy_buffer_stack_top) = 0; (yy_buffer_stack_max) = 0; (yy_c_buf_p) = (char *) 0; (yy_init) = 0; (yy_start) = 0; /* Defined in main.c */ #ifdef YY_STDINIT yyin = stdin; yyout = stdout; #else yyin = (FILE *) 0; yyout = (FILE *) 0; #endif /* For future reference: Set errno on error, since we are called by * yylex_init() */ return 0; } /* yylex_destroy is for both reentrant and non-reentrant scanners. */ int yylex_destroy (void) { /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ yy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; yypop_buffer_state(); } /* Destroy the stack itself. */ yyfree((yy_buffer_stack) ); (yy_buffer_stack) = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time * yylex() is called, initialization will occur. */ yy_init_globals( ); return 0; } /* * Internal utility routines. */ #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) { int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s ) { int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif void *yyalloc (yy_size_t size ) { return (void *) malloc( size ); } void *yyrealloc (void * ptr, yy_size_t size ) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } void yyfree (void * ptr ) { free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ } #define YYTABLES_NAME "yytables" #line 376 "sbr/dtimep.l" /* This is a portable way to squash a warning about the yyunput() * function being static but never used. It costs us a tiny amount * of extra code in the binary but the other options are: * "%option nounput" which is flex-specific * makefile hackery just to compile dtimep.c with different flags */ void dtimep_yyunput(int c) { unput(c); } nmh-1.7.1-RC3/sbr/dtimep.l000644 007761 000024 00000025322 13243042053 015207 0ustar00kenhstaff000000 000000 /* dtimep.l -- parse dates and times. * * This exceeds the default table capacities for some old versions * of lex (and the minimum defaults as specified by POSIX). The following * choices meet or exceed the lex defaults for older SunOS4.x, Solaris, * HPUX, and AIX. */ %e4000 %p7000 %n2500 %a5000 %{ #include #include /* Since we're looking at a string at a time, don't worry about * wrapping to the next buffer. */ #if YY_FLEX_MAJOR_VERSION == 2 && \ YY_FLEX_MINOR_VERSION == 6 && \ YY_FLEX_SUBMINOR_VERSION == 3 /* https://github.com/westes/flex/issues/162 */ #undef yywrap #endif #define yywrap() 1 #define YY_SKIP_YYWRAP #define YY_NO_INPUT /* This is the tricky thing that makes this function cool. We * replace the traditional int yylex(void) declaration with our * dparsetime() declaration, essentially piggy-backing off the * utility of the yylex() function and adding what we need to make * the parsing function useful to us. */ #define YY_DECL struct tws *dparsetime(char *lexstr) /* yyterminate() is called after the input string is matched to * completion (actually, when the lexer reaches an EOF). The only * thing that really needs to be in this macro function is the * return call, which must be substituted inline into dparsetime. */ #define yyterminate() (void)yy_delete_buffer(lexhandle); \ if(!(tw.tw_flags & TW_SUCC)) { \ return (struct tws *)NULL; \ } \ if(tw.tw_year < 1970) \ tw.tw_year += 1900; \ if(tw.tw_year < 1970) \ tw.tw_year += 100; \ return(&tw) /* * Table to convert month names to numeric month. We use the * fact that the low order 5 bits of the sum of the 2nd & 3rd * characters of the name is a hash with no collisions for the 12 * valid month names. (The mask to 5 bits maps any combination of * upper and lower case into the same hash value). */ static int month_map[] = { 0, 6, /* 1 - Jul */ 3, /* 2 - Apr */ 5, /* 3 - Jun */ 0, 10, /* 5 - Nov */ 0, 1, /* 7 - Feb */ 11, /* 8 - Dec */ 0, 0, 0, 0, 0, 0, 0, /*15 - Jan */ 0, 0, 0, 2, /*19 - Mar */ 0, 8, /*21 - Sep */ 0, 9, /*23 - Oct */ 0, 0, 4, /*26 - May */ 0, 7 /*28 - Aug */ }; /* * Lookup table for day-of-week using the same hash trick as for above name-of- * month table, but using the first and second character, not second and third. * * Compute index into table using: (day_name[0] & 7) + (day_name[1] & 4) */ static int day_map[] = { 0, 0, 0, 6, /* 3 - Sat */ 4, /* 4 - Thu */ 0, 5, /* 6 - Fri */ 0, /* 7 - Sun */ 2, /* 8 - Tue */ 1 /* 9 - Mon */, 0, 3 /*11 - Wed */ }; /* The SET* macros will parse for the appropriate field, and leave the * cp pointer at the first character after the desired field. Be * careful with variable-length fields or alpha-num mixes. * The SKIP* macros skip over characters of a particular class and * leave cp at the position of the first character that doesn't match * that class. Correspondingly, SKIPTO* skips until it reaches a * character of a particular class. */ #define INIT() { cp = yytext;} #define SETWDAY() { tw.tw_wday= day_map[(cp[0] & 7) + (cp[1] & 4)]; \ tw.tw_flags &= ~TW_SDAY; tw.tw_flags |= TW_SEXP; \ SKIPA(); } #define SETMON() { cp++; \ tw.tw_mon = month_map[(((unsigned char) cp[0]) + ((unsigned char) cp[1])) & 0x1f]; \ SKIPA(); } #define SETMON_NUM() { tw.tw_mon = atoi(cp)-1; \ SKIPD(); } #define SETYEAR() { tw.tw_year = atoi(cp); \ SKIPD(); } #define SETDAY() { tw.tw_mday = atoi(cp); \ tw.tw_flags |= TW_SUCC; \ SKIPD(); } #define SETTIME() { tw.tw_hour = atoi(cp); \ cp += 2; \ SKIPTOD(); \ tw.tw_min = atoi(cp); \ cp += 2; \ if(*cp == ':') { \ tw.tw_sec = atoi(++cp); SKIPD(); } } #define SETZONE(x) { tw.tw_zone = ((x)/100)*60+(x)%100; \ tw.tw_flags |= TW_SZEXP; \ SKIPD(); } #define SETDST() { tw.tw_flags |= TW_DST; } #define SKIPD() { while ( isdigit((unsigned char) *cp++) ) ; \ --cp; } #define SKIPTOD() { while ( !isdigit((unsigned char) *cp++) ) ; \ --cp; } #define SKIPA() { while ( isalpha((unsigned char) *cp++) ) ; \ --cp; } #define SKIPTOA() { while ( !isalpha((unsigned char) *cp++) ) ; \ --cp; } #define SKIPSP() { while ( isspace((unsigned char) *cp++) ) ; \ --cp; } #define SKIPTOSP() { while ( !isspace((unsigned char) *cp++) ) ; \ --cp; } # ifdef HAVE_SYS_TIME_H # include # endif #include static void zonehack (struct tws *tw) { struct tm *tm; if (dmktime (tw) == (time_t) -1) return; tm = localtime (&tw->tw_clock); if (tm->tm_isdst) { tw->tw_flags |= TW_DST; tw->tw_zone -= 60; } } %} sun [Ss]un(day)? mon [Mm]on(day)? tue [Tt]ue(sday)? wed [Ww]ed(nesday)? thu [Tt]hu(rsday)? fri [Ff]ri(day)? sat [Ss]at(urday)? DAY {sun}|{mon}|{tue}|{wed}|{thu}|{fri}|{sat} jan [Jj]an(uary)? feb [Ff]eb(ruary)? mar [Mm]ar(ch)? apr [Aa]pr(il)? may [Mm]ay jun [Jj]une? jul [Jj]uly? aug [Aa]ug(ust)? sep [Ss]ep(tember)? oct [Oo]ct(ober)? nov [Nn]ov(ember)? dec [Dd]ec(ember)? MONTH {jan}|{feb}|{mar}|{apr}|{may}|{jun}|{jul}|{aug}|{sep}|{oct}|{nov}|{dec} TIME {D}:{d}{d}(:{d}{d})? /* The year can either be 2 digits, or 4. However, after Y2K, we found that some MUA were reporting the year 100, hence the middle term here. yyterminate() resolves the actual issues with 2-digit years. */ YEAR ({d}{d})|(1{d}{d})|({d}{4}) w [ \t]* W [ \t]+ D [0-9]?[0-9] d [0-9] nl [ \t\n()] %% %{ /* This section begins the definition of dparsetime(). Put here any local variable definitions and initializations */ YY_BUFFER_STATE lexhandle; char *cp; static struct tws tw; memset(&tw,0,sizeof(struct tws)); lexhandle = yy_scan_string(lexstr); %} {DAY}","?{W}{MONTH}{W}{D}{W}{TIME}{W}{YEAR} { INIT(); SETWDAY(); SKIPTOA(); SETMON(); SKIPTOD(); SETDAY(); SKIPTOD(); SETTIME(); SKIPTOD(); SETYEAR(); } {DAY}","?{W}{D}{W}{MONTH}{W}{YEAR}{W}{TIME} { INIT(); SETWDAY(); SKIPTOD(); SETDAY(); SKIPTOA(); SETMON(); SKIPTOD(); SETYEAR(); SKIPTOD(); SETTIME(); } {D}{W}{MONTH}{W}{YEAR}{W}{TIME} { INIT(); SETDAY(); SKIPTOA(); SETMON(); SKIPTOD(); SETYEAR(); SKIPTOD(); SETTIME(); } {DAY}","?{W}{MONTH}{W}{D}","?{W}{YEAR}","?{W}{TIME} { INIT(); SETWDAY(); SKIPTOA(); SETMON(); SKIPTOD(); SETDAY(); SKIPTOD(); SETYEAR(); SKIPTOD(); SETTIME(); } {DAY}","?{W}{MONTH}{W}{D}","?{W}{YEAR} { INIT(); SETWDAY(); SKIPTOA(); SETMON(); SKIPTOD(); SETDAY(); SKIPTOD(); SETYEAR(); } {MONTH}{W}{D}","?{W}{YEAR}","?{W}{DAY} { INIT(); SETMON(); SKIPTOD(); SETDAY(); SKIPTOD(); SETYEAR(); SKIPTOA(); SETWDAY(); } {MONTH}{W}{D}","?{W}{YEAR} { INIT(); SETMON(); SKIPTOD(); SETDAY(); SKIPTOD(); SETYEAR(); } {D}("-"|"/"){D}("-"|"/"){YEAR}{W}{TIME} { INIT(); /* MM/DD/YY */ SETMON_NUM(); SKIPTOD(); SETDAY(); SKIPTOD(); SETYEAR(); SKIPTOD(); SETTIME(); } {D}("-"|"/"){D}("-"|"/"){YEAR} { INIT(); /* MM/DD/YY */ SETMON_NUM(); SKIPTOD(); SETDAY(); SKIPTOD(); SETYEAR(); } "[Aa][Mm]" "[Pp][Mm]" tw.tw_hour += 12; "+"{D}{d}{d} { INIT(); SKIPTOD(); SETZONE(atoi(cp)); zonehack (&tw); yyterminate(); } "-"{D}{d}{d} { INIT(); SKIPTOD(); SETZONE(-atoi(cp)); zonehack (&tw); yyterminate(); } {nl}("ut"|"UT") INIT(); SETZONE(0); yyterminate(); {nl}("gmt"|"GMT") INIT(); SETZONE(0); yyterminate(); {nl}("est"|"EST") INIT(); SETZONE(-500); yyterminate(); {nl}("edt"|"EDT") { INIT(); SETDST(); SETZONE(-500); yyterminate(); } {nl}("cst"|"CST") INIT(); SETZONE(-600); yyterminate(); {nl}("cdt"|"CDT") { INIT(); SETDST(); SETZONE(-600); yyterminate(); } {nl}("mst"|"MST") INIT(); SETZONE(-700); yyterminate(); {nl}("mdt"|"MDT") { INIT(); SETDST(); SETZONE(-700); yyterminate(); } {nl}("pst"|"PST") INIT(); SETZONE(-800); yyterminate(); {nl}("pdt"|"PDT") { INIT(); SETDST(); SETZONE(-800); yyterminate(); } {nl}("nst"|"NST") INIT(); SETZONE(-330); yyterminate(); {nl}("ast"|"AST") INIT(); SETZONE(-400); yyterminate(); {nl}("adt"|"ADT") { INIT(); SETDST(); SETZONE(-400); yyterminate(); } {nl}("hst"|"HST") INIT(); SETZONE(-1000); yyterminate(); {nl}("hdt"|"HDT") { INIT(); SETDST(); SETZONE(-1000); yyterminate(); } .|\n %% /* This is a portable way to squash a warning about the yyunput() * function being static but never used. It costs us a tiny amount * of extra code in the binary but the other options are: * "%option nounput" which is flex-specific * makefile hackery just to compile dtimep.c with different flags */ void dtimep_yyunput(int c) { unput(c); } nmh-1.7.1-RC3/sbr/encode_rfc2047.c000644 007761 000024 00000052434 13243042053 016324 0ustar00kenhstaff000000 000000 /* encode_rfc2047.c -- encode message headers using RFC 2047 encoding. * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include "unquote.h" /* * List of headers that contain addresses and as a result require special * handling */ static char *address_headers[] = { "To", "From", "cc", "Bcc", "Reply-To", "Sender", "Resent-To", "Resent-From", "Resent-cc", "Resent-Bcc", "Resent-Reply-To", "Resent-Sender", NULL, }; /* * Macros we use for parsing headers */ #define is_fws(c) (c == '\t' || c == ' ' || c == '\n') #define qphrasevalid(c) ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || \ (c >= 'a' && c <= 'z') || \ c == '!' || c == '*' || c == '+' || c == '-' || \ c == '/' || c == '=' || c == '_') #define qpspecial(c) (c < ' ' || c == '=' || c == '?' || c == '_') #define base64len(n) ((((n) + 2) / 3 ) * 4) /* String len to base64 len */ #define strbase64(n) ((n) / 4 * 3) /* Chars that fit in base64 */ #define ENCODELINELIMIT 76 static void unfold_header(char **, int); static int field_encode_address(const char *, char **, int, const char *); static int field_encode_quoted(const char *, char **, const char *, int, int, int); static int field_encode_base64(const char *, char **, const char *); static int scanstring(const char *, int *, int *, int *); static int utf8len(const char *); static int pref_encoding(int, int, int); /* * Encode a message header using RFC 2047 encoding. We make the assumption * that all characters < 128 are ASCII and as a consequence don't need any * encoding. */ int encode_rfc2047(const char *name, char **value, int encoding, const char *charset) { int i, asciicount = 0, eightbitcount = 0, qpspecialcount = 0; char *p; /* * First, check to see if we even need to encode the header */ for (p = *value; *p != '\0'; p++) { if (isascii((unsigned char) *p)) { asciicount++; if (qpspecial((unsigned char) *p)) qpspecialcount++; } else eightbitcount++; } if (eightbitcount == 0) return 0; /* * Some rules from RFC 2047: * * - Encoded words cannot be more than 75 characters long * - Multiple "long" encoded words must be on new lines. * * Also, we're not permitted to encode email addresses, so * we need to actually _parse_ email addresses and only encode * the right bits. */ /* * If charset was NULL, then get the value from the locale. But * we reject it if it returns US-ASCII */ if (charset == NULL) charset = write_charset_8bit(); if (strcasecmp(charset, "US-ASCII") == 0) { inform("Cannot use US-ASCII with 8 bit characters in header"); return 1; } /* * If we have an address header, then we need to parse the addresses * and only encode the names or comments. Otherwise, handle it normally. */ for (i = 0; address_headers[i]; i++) { if (strcasecmp(name, address_headers[i]) == 0) return field_encode_address(name, value, encoding, charset); } /* * On the encoding we choose, and the specifics of encoding: * * - If a specified encoding is passed in, we use that. * - Otherwise, pick which encoding is shorter. * * We don't quite handle continuation right here, but it should be * pretty close. */ if (encoding == CE_UNKNOWN) encoding = pref_encoding(asciicount, qpspecialcount, eightbitcount); unfold_header(value, asciicount + eightbitcount); switch (encoding) { case CE_BASE64: return field_encode_base64(name, value, charset); case CE_QUOTED: return field_encode_quoted(name, value, charset, asciicount, eightbitcount + qpspecialcount, 0); default: inform("Internal error: unknown RFC-2047 encoding type"); return 1; } } /* * Encode our specified header (or field) using quoted-printable */ static int field_encode_quoted(const char *name, char **value, const char *charset, int ascii, int encoded, int phraserules) { int prefixlen = name ? strlen(name) + 2: 0, outlen = 0, column, newline = 1; int charsetlen = strlen(charset), utf8; char *output = NULL, *p, *q = NULL; /* * Right now we just encode the whole thing. Maybe later on we'll * only encode things on a per-atom basis. */ p = *value; column = prefixlen + 2; /* Header name plus ": " */ utf8 = strcasecmp(charset, "UTF-8") == 0; while (*p != '\0') { /* * Start a new line, if it's time */ if (newline) { /* * If it's the start of the header, we don't need to pad it * * The length of the output string is ... * =?charset?Q?...?= so that's 7+strlen(charset) + 2 for \n NUL * * plus 1 for every ASCII character and 3 for every eight bit * or special character (eight bit characters are written as =XX). * */ int tokenlen; outlen += 9 + charsetlen + ascii + 3 * encoded; /* * If output is set, then we're continuing the header. Otherwise * do the initial allocation. */ if (output) { int curlen = q - output, i; outlen += prefixlen + 1; /* Header plus \n ": " */ output = mh_xrealloc(output, outlen); q = output + curlen; *q++ = '?'; *q++ = '='; *q++ = '\n'; for (i = 0; i < prefixlen; i++) *q++ = ' '; } else { /* * A bit of a hack here; the header can contain multiple * spaces (probably at least one) until we get to the * actual text. Copy until we get to a non-space. */ output = mh_xmalloc(outlen); q = output; while (is_fws(*p)) *q++ = *p++; } tokenlen = snprintf(q, outlen - (q - output), "=?%s?Q?", charset); q += tokenlen; column = prefixlen + tokenlen; newline = 0; } /* * Process each character, encoding if necessary * * Note that we have a different set of rules if we're processing * RFC 5322 'phrase' (something you'd see in an address header). */ column++; if (*p == ' ') { *q++ = '_'; ascii--; } else if (isascii((unsigned char) *p) && (phraserules ? qphrasevalid((unsigned char) *p) : !qpspecial((unsigned char) *p))) { *q++ = *p; ascii--; } else { snprintf(q, outlen - (q - output), "=%02X", (unsigned char) *p); q += 3; column += 2; /* column already incremented by 1 above */ encoded--; } p++; /* * We're not allowed more than ENCODELINELIMIT characters per line, * so reserve some room for the final ?=. * * If prefixlen == 0, we haven't been passed in a header name, so * don't ever wrap the field (we're likely doing an address). */ if (prefixlen == 0) continue; if (column >= ENCODELINELIMIT - 2) { newline = 1; } else if (utf8) { /* * Okay, this is a bit weird, but to explain a bit more ... * * RFC 2047 prohibits the splitting of multibyte characters * across encoded words. Right now we only handle the case * of UTF-8, the most common multibyte encoding. * * p is now pointing at the next input character. If we're * using UTF-8 _and_ we'd go over ENCODELINELIMIT given the * length of the complete character, then trigger a newline * now. Note that we check the length * 3 since we have to * allow for the encoded output. */ if (column + (utf8len(p) * 3) > ENCODELINELIMIT - 2) { newline = 1; } } } if (q == NULL) { /* This should never happen, but just in case. Found by clang static analyzer. */ inform("null output encoding for %s, continuing...", *value); return 1; } *q++ = '?'; *q++ = '='; if (prefixlen) *q++ = '\n'; *q = '\0'; free(*value); *value = output; return 0; } /* * Encode our specified header (or field) using base64. * * This is a little easier since every character gets encoded, we can * calculate the line wrap up front. */ static int field_encode_base64(const char *name, char **value, const char *charset) { int prefixlen = name ? strlen(name) + 2 : 0, charsetlen = strlen(charset); int outlen = 0, numencode, curlen; char *output = NULL, *p = *value, *q = NULL, *linestart = NULL; /* * Skip over any leading white space. */ while (*p == ' ' || *p == '\t') p++; /* * If we had a zero-length prefix, then just encode the whole field * as-is, without line wrapping. Note that in addition to the encoding * * The added length we need is =? + charset + ?B? ... ?= * * That's 7 + strlen(charset) + 2 (for \n NUL). */ while (prefixlen && ((base64len(strlen(p)) + 7 + charsetlen + prefixlen) > ENCODELINELIMIT)) { /* * Our very first time, don't pad the line in the front * * Note ENCODELINELIMIT is + 2 because of \n \0 */ if (! output) { outlen += ENCODELINELIMIT + 2; output = q = mh_xmalloc(outlen); linestart = q - prefixlen; /* Yes, this is intentional */ } else { int curstart = linestart - output; curlen = q - output; outlen += ENCODELINELIMIT + 2; output = mh_xrealloc(output, outlen); q = output + curlen; linestart = output + curstart; } /* * We should have enough space now, so prepend the encoding markers * and character set information. The leading space is intentional. */ q += snprintf(q, outlen - (q - output), " =?%s?B?", charset); /* * Find out how much room we have left on the line and see how * many characters we can stuff in. The start of our line * is marked by "linestart", so use that to figure out how * many characters are left out of ENCODELINELIMIT. Reserve * 2 characters for the end markers and calculate how many * characters we can fit into that space given the base64 * encoding expansion. */ numencode = strbase64(ENCODELINELIMIT - (q - linestart) - 2); if (numencode <= 0) { inform("Internal error: tried to encode %d characters " "in base64", numencode); return 1; } /* * RFC 2047 prohibits spanning multibyte characters across tokens. * Right now we only check for UTF-8. * * So note the key here ... we want to make sure the character BEYOND * our last character is not a continuation byte. If it's the start * of a new multibyte character or a single-byte character, that's ok. */ if (strcasecmp(charset, "UTF-8") == 0) { /* * p points to the start of our current buffer, so p + numencode * is one past the last character to encode */ while (numencode > 0 && ((*(p + numencode) & 0xc0) == 0x80)) numencode--; if (numencode == 0) { inform("Internal error: could not find start of " "UTF-8 character when base64 encoding header"); return 1; } } if (writeBase64raw((unsigned char *) p, numencode, (unsigned char *) q) != OK) { inform("Internal error: base64 encoding of header failed"); return 1; } p += numencode; q += base64len(numencode); /* * This will point us at the beginning of the new line (trust me). */ linestart = q + 3; /* * What's going on here? Well, we know we're continuing to the next * line, so we want to add continuation padding. We also add the * trailing marker for the RFC 2047 token at this time as well. * This uses a trick of snprintf(); we tell it to print a zero-length * string, but pad it out to prefixlen - 1 characters; that ends * up always printing out the requested number of spaces. We use * prefixlen - 1 because we always add a space on the starting * token marker; this makes things work out correctly for the first * line, which should have a space between the ':' and the start * of the token. * * It's okay if you don't follow all of that. */ q += snprintf(q, outlen - (q - output), "?=\n%*s", prefixlen - 1, ""); } /* * We're here if there is either no prefix, or we can fit it in less * than ENCODELINELIMIT characters. Encode the whole thing. */ outlen += prefixlen + 9 + charsetlen + base64len(strlen(p)); curlen = q - output; output = mh_xrealloc(output, outlen); q = output + curlen; q += snprintf(q, outlen - (q - output), "%s=?%s?B?", prefixlen ? " " : "", charset); if (writeBase64raw((unsigned char *) p, strlen(p), (unsigned char *) q) != OK) { inform("Internal error: base64 encoding of header failed"); return 1; } strcat(q, "?="); if (prefixlen) strcat(q, "\n"); free(*value); *value = output; return 0; } /* * Calculate the length of a UTF-8 character. * * If it's not a UTF-8 character (or we're in the middle of a multibyte * character) then simply return 0. */ static int utf8len(const char *p) { int len = 1; if (*p == '\0') return 0; if (isascii((unsigned char) *p) || (((unsigned char) *p) & 0xc0) == 0x80) return 0; p++; while ((((unsigned char) *p++) & 0xc0) == 0x80) len++; return len; } /* * "Unfold" a header, making it a single line (without continuation) * * We cheat a bit here; we never make the string longer, so using the * original length here is fine. */ static void unfold_header(char **value, int len) { char *str = mh_xmalloc(len + 1); char *p = str, *q = *value; while (*q != '\0') { if (*q == '\n') { /* * When we get a newline, skip to the next non-whitespace * character and add a space to replace all of the whitespace * * This has the side effect of stripping off the final newline * for the header; we put it back in the encoding routine. */ while (is_fws(*q)) q++; if (*q == '\0') break; *p++ = ' '; } else { *p++ = *q++; } } *p = '\0'; free(*value); *value = str; } /* * Decode a header containing addresses. This means we have to parse * each address and only encode the display-name or comment field. */ static int field_encode_address(const char *name, char **value, int encoding, const char *charset) { int prefixlen = strlen(name) + 2, column = prefixlen, groupflag; int asciichars, specialchars, eightbitchars, reformat = 0, errflag = 0; size_t len; char *mp, *cp = NULL, *output = NULL; char *tmpbuf = NULL; size_t tmpbufsize = 0; struct mailname *mn; char errbuf[BUFSIZ]; /* * Because these are addresses, we need to handle them individually. * * Break them down and process them one by one. This means we have to * rewrite the whole header, but that's unavoidable. */ /* * The output headers always have to start with a space first; this * is just the way the API works right now. */ output = add(" ", output); for (groupflag = 0; (mp = getname(*value)); ) { if ((mn = getm(mp, NULL, 0, errbuf, sizeof(errbuf))) == NULL) { inform("%s: %s", errbuf, mp); errflag++; continue; } reformat = 0; /* * We only care if the phrase (m_pers) or any trailing comment * (m_note) have 8-bit characters. If doing q-p, we also need * to encode anything marked as qspecial(). Unquote it first * so the specialchars count is right. */ if (! mn->m_pers) goto check_note; if ((len = strlen(mn->m_pers)) + 1 > tmpbufsize) { tmpbuf = mh_xrealloc(tmpbuf, tmpbufsize = len + 1); } unquote_string(mn->m_pers, tmpbuf); if (scanstring(tmpbuf, &asciichars, &eightbitchars, &specialchars)) { /* * If we have 8-bit characters, encode it. */ if (encoding == CE_UNKNOWN) encoding = pref_encoding(asciichars, specialchars, eightbitchars); /* * This is okay, because the output of unquote_string will be either * equal or shorter than the original. */ strcpy(mn->m_pers, tmpbuf); switch (encoding) { case CE_BASE64: if (field_encode_base64(NULL, &mn->m_pers, charset)) { errflag++; goto out; } break; case CE_QUOTED: if (field_encode_quoted(NULL, &mn->m_pers, charset, asciichars, eightbitchars + specialchars, 1)) { errflag++; goto out; } break; default: inform("Internal error: unknown RFC-2047 encoding type"); errflag++; goto out; } reformat++; } check_note: /* * The "note" field is generally a comment at the end of the address, * at least as how it's implemented here. Notes are always surrounded * by parenthesis (since they're comments). Strip them out and * then put them back when we format the final field, but they do * not get encoded. */ if (! mn->m_note) goto do_reformat; if ((len = strlen(mn->m_note)) + 1 > tmpbufsize) { tmpbuf = mh_xrealloc(tmpbuf, tmpbufsize = len + 1); } if (mn->m_note[0] != '(' || mn->m_note[len - 1] != ')') { inform("Internal error: Invalid note field \"%s\"", mn->m_note); errflag++; goto out; } strncpy(tmpbuf, mn->m_note + 1, len - 1); tmpbuf[len - 2] = '\0'; if (scanstring(tmpbuf, &asciichars, &eightbitchars, &specialchars)) { /* * If we have 8-bit characters, encode it. */ if (encoding == CE_UNKNOWN) encoding = pref_encoding(asciichars, specialchars, eightbitchars); switch (encoding) { case CE_BASE64: if (field_encode_base64(NULL, &tmpbuf, charset)) { errflag++; goto out; } break; case CE_QUOTED: if (field_encode_quoted(NULL, &tmpbuf, charset, asciichars, eightbitchars + specialchars, 1)) { errflag++; goto out; } break; default: inform("Internal error: unknown RFC-2047 encoding type"); errflag++; goto out; } reformat++; /* * Make sure the size of tmpbuf is correct (it always gets * reallocated in the above functions). */ tmpbufsize = strlen(tmpbuf) + 1; /* * Put the note field back surrounded by parenthesis. */ mn->m_note = mh_xrealloc(mn->m_note, tmpbufsize + 2); snprintf(mn->m_note, tmpbufsize + 2, "(%s)", tmpbuf); } do_reformat: /* * So, some explanation is in order. * * We know we need to rewrite at least one address in the header, * otherwise we wouldn't be here. If we had to reformat this * particular address, then run it through adrformat(). Otherwise * we can use m_text directly. */ /* * If we were in a group but are no longer, make sure we add a * semicolon (which needs to be FIRST, as it needs to be at the end * of the last address). */ if (groupflag && ! mn->m_ingrp) { output = add(";", output); column++; } groupflag = mn->m_ingrp; if (mn->m_gname) { cp = mh_xstrdup(mn->m_gname); } if (reformat) { cp = add(adrformat(mn), cp); } else { cp = add(mn->m_text, cp); } len = strlen(cp); /* * If we're not at the beginning of the line, add a command and * either a space or a newline. */ if (column != prefixlen) { if (len + column + 2 > OUTPUTLINELEN) { if ((size_t) (prefixlen + 3) < tmpbufsize) tmpbuf = mh_xrealloc(tmpbuf, tmpbufsize = prefixlen + 3); snprintf(tmpbuf, tmpbufsize, ",\n%*s", column = prefixlen, ""); output = add(tmpbuf, output); } else { output = add(", ", output); column += 2; } } /* * Finally add the address */ output = add(cp, output); column += len; free(cp); cp = NULL; } /* * Just in case we're at the end of a list */ if (groupflag) { output = add(";", output); } output = add("\n", output); free(*value); *value = output; output = NULL; out: mh_xfree(tmpbuf); mh_xfree(output); return errflag > 0; } /* * Scan a string, check for characters that need to be encoded */ static int scanstring(const char *string, int *asciilen, int *eightbitchars, int *specialchars) { *asciilen = 0; *eightbitchars = 0; *specialchars = 0; for (; *string != '\0'; string++) { if ((isascii((unsigned char) *string))) { (*asciilen)++; /* * So, a space is not a valid phrase character, but we're counting * an exception here, because in q-p a space can be directly * encoded as an underscore. */ if (!qphrasevalid((unsigned char) *string) && *string != ' ') (*specialchars)++; } else { (*eightbitchars)++; } } return *eightbitchars > 0; } /* * This function is to be used to decide which encoding algorithm we should * use if one is not given. Basically, we pick whichever one is the shorter * of the two. * * Arguments are: * * ascii - Number of ASCII characters in to-be-encoded string. * specials - Number of ASCII characters in to-be-encoded string that * still require encoding under quoted-printable. Note that * these are included in the "ascii" total. * eightbit - Eight-bit characters in the to-be-encoded string. * * Returns one of CE_BASE64 or CE_QUOTED. */ static int pref_encoding(int ascii, int specials, int eightbits) { /* * The length of the q-p encoding is: * * ascii - specials + (specials + eightbits) * 3. * * The length of the base64 encoding is: * * base64len(ascii + eightbits) (See macro for details) */ return base64len(ascii + eightbits) < (ascii - specials + (specials + eightbits) * 3) ? CE_BASE64 : CE_QUOTED; } nmh-1.7.1-RC3/sbr/error.c000644 007761 000024 00000006717 13243042053 015054 0ustar00kenhstaff000000 000000 /* error.c -- main error handling routines * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include /* inform calls advertise() with no what and no tail. * Thus the simple "[invo_name: ]fmt\n" results. */ void inform(char *fmt, ...) { va_list ap; va_start(ap, fmt); advertise(NULL, NULL, fmt, ap); va_end(ap); } /* advise calls advertise() with no tail to print fmt, and perhaps what, * to stderr. * Thus "[invo_name: ]fmt[[ what]: errno]\n" results. */ void advise (const char *what, const char *fmt, ...) { va_list ap; va_start(ap, fmt); advertise (what, NULL, fmt, ap); va_end(ap); } /* adios is the same as advise(), but then "ends" the program. * It calls advertise() with no tail to print fmt, and perhaps what, to * stderr, and exits the program with an error status. * Thus "[invo_name: ]fmt[[ what]: errno]\n" results. * The route to exit is via the done function pointer and may not be * straightforward, e.g. longjmp(3), but it must not return to adios(). * If it does then it's a bug and adios() will abort(3) as callers do * not expect execution to continue. */ void NORETURN adios (const char *what, const char *fmt, ...) { va_list ap; va_start(ap, fmt); advertise (what, NULL, fmt, ap); va_end(ap); done (1); abort(); } /* admonish calls advertise() with a tail indicating the program * continues. * Thus "[invo_name: ]fmt[[ what]: errno], continuing...\n" results. */ void admonish (char *what, char *fmt, ...) { va_list ap; va_start(ap, fmt); advertise (what, "continuing...", fmt, ap); va_end(ap); } /* advertise prints fmt and ap to stderr after flushing stdout. * If invo_name isn't NULL or empty then "invo_name: " precedes fmt. * If what isn't NULL or empty then " what" is appended. * If what isn't NULL then ": errno" is appended. * If tail isn't NULL or empty then ", tail" is appended. * A "\n" finishes the output to stderr. * In summary: "[invo_name: ]fmt[[ what]: errno][, tail]\n". */ void advertise (const char *what, char *tail, const char *fmt, va_list ap) { int eindex = errno; char buffer[NMH_BUFSIZ], *err; struct iovec iob[10], *iov; size_t niov; iov = iob; #define APPEND_IOV(p, len) \ iov->iov_base = (p); \ iov->iov_len = (len); \ iov++ #define ADD_LITERAL(s) APPEND_IOV((s), LEN(s)) #define ADD_VAR(s) APPEND_IOV((s), strlen(s)) if (invo_name && *invo_name) { ADD_VAR(invo_name); ADD_LITERAL(": "); } vsnprintf (buffer, sizeof(buffer), fmt, ap); ADD_VAR(buffer); if (what) { if (*what) { ADD_LITERAL(" "); ADD_VAR((void *)what); } ADD_LITERAL(": "); err = strerror(eindex); ADD_VAR(err); } if (tail && *tail) { ADD_LITERAL(", "); ADD_VAR(tail); } ADD_LITERAL("\n"); #undef ADD_LITERAL #undef ADD_VAR niov = iov - iob; assert(niov <= DIM(iob)); fflush (stdout); fflush (stderr); if (writev(fileno(stderr), iob, niov) == -1) { snprintf(buffer, sizeof buffer, "%s: write stderr failed: %d\n", invo_name && *invo_name ? invo_name : "nmh", errno); if (write(2, buffer, strlen(buffer)) == -1) { /* Ignore. if-statement needed to shut up compiler. */ } } } nmh-1.7.1-RC3/sbr/escape_addresses.c000644 007761 000024 00000005405 13243042053 017211 0ustar00kenhstaff000000 000000 /* escape_addresses.c -- Escape address components, hopefully per RFC 5322. * * 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 #include static void escape_component (char *name, size_t namesize, char *chars); void escape_display_name (char *name, size_t namesize) { char *specials = "\"(),.:;<>@[\\]"; escape_component (name, namesize, specials); } void escape_local_part (char *name, size_t namesize) { /* wsp (whitespace) is horizontal tab or space, according to RFC 5234. */ char *specials_less_dot_plus_wsp = " \"(),:;<>@[\\]"; escape_component (name, namesize, specials_less_dot_plus_wsp); } /* Escape an address component, hopefully per RFC 5322. Assumes one-byte characters. The char array pointed to by the name argument is modified in place. Its size is specified by the namesize argument. The need_escape argument is a string of characters that require that name be escaped. */ void escape_component (char *name, size_t namesize, char *chars_to_escape) { /* If name contains any chars_to_escape: 1) enclose it in "" 2) escape any embedded " */ if (strpbrk(name, chars_to_escape)) { char *destp, *srcp; /* Maximum space requirement would be if each character had to be escaped, plus enclosing double quotes, plus NUL terminator. E.g., 2 characters, "", would require 7, "\"\""0, where that 0 is '\0'. */ char *tmp = mh_xmalloc (2*strlen(name) + 3); for (destp = tmp, srcp = name; *srcp; ++srcp) { if (srcp == name) { /* Insert initial double quote, if needed. */ if (*srcp != '"') { *destp++ = '"'; } } else { /* Escape embedded, unescaped double quote. */ if (*srcp == '"' && *(srcp+1) != '\0' && *(srcp-1) != '\\') { *destp++ = '\\'; } } *destp++ = *srcp; /* End of name. */ if (*(srcp+1) == '\0') { /* Insert final double quote, if needed. */ if (*srcp != '"') { *destp++ = '"'; } *destp++ = '\0'; } } if (strcmp (tmp, "\"")) { size_t len = destp - tmp; assert ((ssize_t) strlen(tmp) + 1 == destp - tmp); strncpy (name, tmp, min(len, namesize)); } else { /* Handle just " as special case here instead of above. */ strncpy (name, "\"\\\"\"", namesize); } name[namesize - 1] = '\0'; free (tmp); } } nmh-1.7.1-RC3/sbr/ext_hook.c000644 007761 000024 00000003353 13243042053 015534 0ustar00kenhstaff000000 000000 /* Run a program that hooks into some other system. The first argument is * name of the hook to use, the second is the full path name of a mail message. * The third argument is also the full path name of a mail message, or a NULL * pointer if it isn't needed. Look in the context for an error message if * something goes wrong; there is a built-in message in case one isn't specified. * Only produce the error message once. */ #include int ext_hook(char *hook_name, char *message_file_name_1, char *message_file_name_2) { char *hook; /* hook program from context */ pid_t pid; /* ID of child process */ int status; /* exit or other child process status */ char **vec; /* argument vector for child process */ int vecp; /* Vector index */ char *program; /* Name of program to execute */ static int did_message = 0; /* set if we've already output a message */ if ((hook = context_find(hook_name)) == NULL) return (OK); switch (pid = fork()) { case -1: status = NOTOK; inform("external database may be out-of-date."); break; case 0: vec = argsplit(hook, &program, &vecp); vec[vecp++] = message_file_name_1; vec[vecp++] = message_file_name_2; vec[vecp++] = NULL; execvp(program, vec); advise(program, "Unable to execute"); _exit(-1); /* NOTREACHED */ default: status = pidwait(pid, -1); break; } if (status != OK) { if (did_message == 0) { char *msghook; if ((msghook = context_find("msg-hook")) != NULL) inform(msghook); else { char errbuf[BUFSIZ]; snprintf(errbuf, sizeof(errbuf), "external hook \"%s\"", hook); pidstatus(status, stderr, errbuf); } did_message = 1; } return (NOTOK); } else return (OK); } nmh-1.7.1-RC3/sbr/fdcompare.c000644 007761 000024 00000001415 13243042053 015651 0ustar00kenhstaff000000 000000 /* fdcompare.c -- are two files identical? * * 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 int fdcompare (int fd1, int fd2) { int i, n1, n2, resp; char *c1, *c2; char b1[BUFSIZ], b2[BUFSIZ]; resp = 1; while ((n1 = read (fd1, b1, sizeof(b1))) >= 0 && (n2 = read (fd2, b2, sizeof(b2))) >= 0 && n1 == n2) { c1 = b1; c2 = b2; for (i = n1 < (int) sizeof(b1) ? n1 : (int) sizeof(b1); i--;) if (*c1++ != *c2++) { resp = 0; goto leave; } if (n1 < (int) sizeof(b1)) goto leave; } resp = 0; leave: ; lseek(fd1, 0, SEEK_SET); lseek(fd2, 0, SEEK_SET); return resp; } nmh-1.7.1-RC3/sbr/fmt_addr.c000644 007761 000024 00000005745 13243042053 015503 0ustar00kenhstaff000000 000000 /* fmt_addr.c -- format an address field (from fmt_scan) * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include static char *buf; /* our current working buffer */ static char *bufend; /* end of working buffer */ static char *last_dst; /* buf ptr at end of last call */ static unsigned int bufsiz; /* current size of buf */ #define BUFINCR 512 /* how much to expand buf when if fills */ #define CPY(s) { cp = (s); while ((*dst++ = *cp++)) ; --dst; } /* check if there's enough room in buf for str. add more mem if needed */ #define CHECKMEM(str) \ if ((len = strlen (str)) >= bufend - dst) {\ int i = dst - buf;\ int n = last_dst - buf;\ bufsiz += ((dst + len - bufend) / BUFINCR + 1) * BUFINCR;\ buf = mh_xrealloc (buf, bufsiz);\ dst = buf + i;\ last_dst = buf + n;\ bufend = buf + bufsiz;\ } /* fmt_scan will call this routine if the user includes the function * "(formataddr {component})" in a format string. "orig" is the * original contents of the string register. "str" is the address * string to be formatted and concatenated onto orig. This routine * returns a pointer to the concatenated address string. * * We try to not do a lot of malloc/copy/free's (which is why we * don't call "getcpy") but still place no upper limit on the * length of the result string. * * This routine is placed in a separate library so it can be * overridden by particular programs (e.g., "replsbr"). */ char * formataddr (char *orig, char *str) { int len; int isgroup; char *dst; char *cp; char *sp; struct mailname *mp = NULL; /* if we don't have a buffer yet, get one */ if (bufsiz == 0) { buf = mh_xmalloc (BUFINCR); last_dst = buf; /* XXX */ bufsiz = BUFINCR - 6; /* leave some slop */ bufend = buf + bufsiz; } /* * If "orig" points to our buffer we can just pick up where we * left off. Otherwise we have to copy orig into our buffer. */ if (orig == buf) dst = last_dst; else if (!orig || !*orig) { dst = buf; *dst = '\0'; } else { dst = last_dst; /* XXX */ CHECKMEM (orig); CPY (orig); } /* concatenate all the new addresses onto 'buf' */ for (isgroup = 0; (cp = getname (str)); ) { if ((mp = getm (cp, NULL, 0, NULL, 0)) == NULL) continue; if (isgroup && (mp->m_gname || !mp->m_ingrp)) { *dst++ = ';'; isgroup = 0; } /* if we get here we're going to add an address */ if (dst != buf) { *dst++ = ','; *dst++ = ' '; } if (mp->m_gname) { CHECKMEM (mp->m_gname); CPY (mp->m_gname); isgroup++; } sp = adrformat (mp); CHECKMEM (sp); CPY (sp); mnfree (mp); } if (isgroup) *dst++ = ';'; *dst = '\0'; last_dst = dst; return (buf); } char *concataddr (char *orig, char *str) { return formataddr(orig, str); } nmh-1.7.1-RC3/sbr/fmt_compile.c000644 007761 000024 00000075214 13243042053 016217 0ustar00kenhstaff000000 000000 /* fmt_compile.c -- "compile" format strings for fmt_scan * * 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. * * This code compiles the format strings (documented in mh-format(5)) into * an internal form to be later processed by fmt_scan.c. * * What happens here is that the format strings are parsed and an array * of struct format structures are returned. Each format structure is * a single operation interpreted by the the routines in fmt_scan.c. * * There is a NOT a one-to-one correspondence between format strings and * format instructions; some functions have side effects that can result * in multiple instructions being generated. The exact list of instructions * generated by a format string can be seem with the nmh fmttest utility. * * A list of format instructions can be found in fmt_compile.h. * * If you wish to add a new function, you will need to do the following * things: * * - Add a new instruction to the list of instructions in fmt_compile.h. * Note that test instructions (starting with FT_IF_S_NULL) have special * handling, so if you are NOT writing a test function then you need * to insert it into the list before that _and_ bump all of the * following instruction numbers. * * - Add the function name to the functable[] array below, and write any * special code that your function may require in terms of parsing * (it very well may not need anything). * * - Add the code in fmt_scan.c to handle your new function. * * - Add code to fmttest.c to display your new function. * * - Document the new function in the mh-format(5) man page. * */ #include #include #include #include #include #include #include #ifdef HAVE_SYS_TIME_H # include #endif #include /* * hash table for deciding if a component is "interesting" */ static struct comp *wantcomp[128]; static struct format *formatvec; /* array to hold formats */ static struct format *next_fp; /* next free format slot */ static struct format *fp; /* current format slot */ static struct comp *cm; /* most recent comp ref */ static struct ftable *ftbl; /* most recent func ref */ static int ncomp; static int infunction; /* function nesting cnt */ extern struct mailname fmt_mnull; /* ftable->type (argument type) */ #define TF_COMP 0 /* component expected */ #define TF_NUM 1 /* number expected */ #define TF_STR 2 /* string expected */ #define TF_EXPR 3 /* component or func. expected */ #define TF_NONE 4 /* no argument */ #define TF_MYBOX 5 /* special - get current user's mbox */ #define TF_NOW 6 /* special - get current unix time */ #define TF_EXPR_SV 7 /* like expr but save current str reg */ #define TF_NOP 8 /* like expr but no result */ #define TF_MYNAME 9 /* special - get current name of user */ #define TF_MYHOST 10 /* special - get "local" hostname */ #define TF_LMBOX 11 /* special - get full local mailbox */ #define TF_BOLD 12 /* special - enter terminal bold mode */ #define TF_UNDERLN 13 /* special - enter underline mode */ #define TF_STNDOUT 14 /* special - enter underline mode */ #define TF_RESET 15 /* special - reset terminal modes */ #define TF_HASCLR 16 /* special - terminal have color? */ #define TF_FGCOLR 17 /* special - foreground term color */ #define TF_BGCOLR 18 /* special - background term color */ /* ftable->flags */ /* NB that TFL_PUTS is also used to decide whether the test * in a "%<(function)..." should be a string or numeric one. */ #define TFL_PUTS 1 /* implicit putstr if top level */ #define TFL_PUTN 2 /* implicit putnum if top level */ /* * The functable array maps between the text names of format functions and * the format instructions interpreted by the engine in fmt_scan.c. * * The elements of this structure are as follows: * * name - The name of the function as seen in the format string. This is * what maps a particular function name into a format instruction. * type - The type of argument this function expects. Those types are * listed above (with the TF_ prefix). This affects what gets * placed in the format instruction (the f_un union). Also, * instructions that require special handling are distinguished * here (TF_MYMBOX is one example). * f_type - The instruction corresponding to this function (from the list * in fmt_compile.h). * extra - Used by some functions to provide extra data to the compiler. * Uses include: * - Providing an alternate instruction to combine a load * and test operation (see do_if()). * - Passed in f_value in the format instruction to provide * extra information for the engine (see FT_LV_DAT handling * in fmt_scan.c). * - Provide a hint as to preprocessing that is required for * this instruction (see do_name()). * flags - See the definitions for TFL_PUTS & TFL_PUTN above. */ struct ftable { char *name; /* function name */ char type; /* argument type */ char f_type; /* fmt type */ char extra; /* arg. type dependent extra info */ char flags; }; static struct ftable functable[] = { { "nonzero", TF_EXPR, FT_V_NE, FT_IF_V_NE, 0 }, { "zero", TF_EXPR, FT_V_EQ, FT_IF_V_EQ, 0 }, { "eq", TF_NUM, FT_V_EQ, FT_IF_V_EQ, 0 }, { "ne", TF_NUM, FT_V_NE, FT_IF_V_NE, 0 }, { "gt", TF_NUM, FT_V_GT, FT_IF_V_GT, 0 }, { "null", TF_EXPR, FT_S_NULL, FT_IF_S_NULL, 0 }, { "nonnull", TF_EXPR, FT_S_NONNULL, FT_IF_S, 0 }, { "match", TF_STR, FT_V_MATCH, FT_IF_MATCH, 0 }, { "amatch", TF_STR, FT_V_AMATCH, FT_IF_AMATCH, 0 }, { "putstr", TF_EXPR, FT_STR, 0, 0 }, { "putstrf", TF_EXPR, FT_STRF, 0, 0 }, { "putnum", TF_EXPR, FT_NUM, 0, 0 }, { "putnumf", TF_EXPR, FT_NUMF, 0, 0 }, { "putaddr", TF_STR, FT_PUTADDR, 0, 0 }, { "putlit", TF_EXPR, FT_STRLIT, 0, 0 }, { "zputlit", TF_EXPR, FT_STRLITZ, 0, 0 }, { "void", TF_NOP, 0, 0, 0 }, { "comp", TF_COMP, FT_LS_COMP, 0, TFL_PUTS }, { "lit", TF_STR, FT_LS_LIT, 0, TFL_PUTS }, { "getenv", TF_STR, FT_LS_GETENV, 0, TFL_PUTS }, { "profile", TF_STR, FT_LS_CFIND, 0, TFL_PUTS }, { "decodecomp", TF_COMP, FT_LS_DECODECOMP, 0, TFL_PUTS }, { "decode", TF_EXPR, FT_LS_DECODE, 0, TFL_PUTS }, { "trim", TF_EXPR, FT_LS_TRIM, 0, 0 }, { "kilo", TF_EXPR, FT_LS_KILO, 0, TFL_PUTS }, { "kibi", TF_EXPR, FT_LS_KIBI, 0, TFL_PUTS }, { "compval", TF_COMP, FT_LV_COMP, 0, TFL_PUTN }, { "compflag", TF_COMP, FT_LV_COMPFLAG, 0, TFL_PUTN }, { "num", TF_NUM, FT_LV_LIT, 0, TFL_PUTN }, { "msg", TF_NONE, FT_LV_DAT, 0, TFL_PUTN }, { "cur", TF_NONE, FT_LV_DAT, 1, TFL_PUTN }, { "size", TF_NONE, FT_LV_DAT, 2, TFL_PUTN }, { "width", TF_NONE, FT_LV_DAT, 3, TFL_PUTN }, { "unseen", TF_NONE, FT_LV_DAT, 4, TFL_PUTN }, { "dat", TF_NUM, FT_LV_DAT, 0, TFL_PUTN }, { "strlen", TF_NONE, FT_LV_STRLEN, 0, TFL_PUTN }, { "me", TF_MYBOX, FT_LS_LIT, 0, TFL_PUTS }, { "myname", TF_MYNAME, FT_LS_LIT, 0, TFL_PUTS }, { "myhost", TF_MYHOST, FT_LS_LIT, 0, TFL_PUTS }, { "localmbox", TF_LMBOX, FT_LS_LIT, 0, TFL_PUTS }, { "plus", TF_NUM, FT_LV_PLUS_L, 0, TFL_PUTN }, { "minus", TF_NUM, FT_LV_MINUS_L, 0, TFL_PUTN }, { "multiply", TF_NUM, FT_LV_MULTIPLY_L, 0, TFL_PUTN }, { "divide", TF_NUM, FT_LV_DIVIDE_L, 0, TFL_PUTN }, { "modulo", TF_NUM, FT_LV_MODULO_L, 0, TFL_PUTN }, { "charleft", TF_NONE, FT_LV_CHAR_LEFT, 0, TFL_PUTN }, { "timenow", TF_NOW, FT_LV_LIT, 0, TFL_PUTN }, { "month", TF_COMP, FT_LS_MONTH, FT_PARSEDATE, TFL_PUTS }, { "lmonth", TF_COMP, FT_LS_LMONTH, FT_PARSEDATE, TFL_PUTS }, { "tzone", TF_COMP, FT_LS_ZONE, FT_PARSEDATE, TFL_PUTS }, { "day", TF_COMP, FT_LS_DAY, FT_PARSEDATE, TFL_PUTS }, { "weekday", TF_COMP, FT_LS_WEEKDAY, FT_PARSEDATE, TFL_PUTS }, { "tws", TF_COMP, FT_LS_822DATE, FT_PARSEDATE, TFL_PUTS }, { "sec", TF_COMP, FT_LV_SEC, FT_PARSEDATE, TFL_PUTN }, { "min", TF_COMP, FT_LV_MIN, FT_PARSEDATE, TFL_PUTN }, { "hour", TF_COMP, FT_LV_HOUR, FT_PARSEDATE, TFL_PUTN }, { "mday", TF_COMP, FT_LV_MDAY, FT_PARSEDATE, TFL_PUTN }, { "mon", TF_COMP, FT_LV_MON, FT_PARSEDATE, TFL_PUTN }, { "year", TF_COMP, FT_LV_YEAR, FT_PARSEDATE, TFL_PUTN }, { "yday", TF_COMP, FT_LV_YDAY, FT_PARSEDATE, TFL_PUTN }, { "wday", TF_COMP, FT_LV_WDAY, FT_PARSEDATE, TFL_PUTN }, { "zone", TF_COMP, FT_LV_ZONE, FT_PARSEDATE, TFL_PUTN }, { "clock", TF_COMP, FT_LV_CLOCK, FT_PARSEDATE, TFL_PUTN }, { "rclock", TF_COMP, FT_LV_RCLOCK, FT_PARSEDATE, TFL_PUTN }, { "sday", TF_COMP, FT_LV_DAYF, FT_PARSEDATE, TFL_PUTN }, { "szone", TF_COMP, FT_LV_ZONEF, FT_PARSEDATE, TFL_PUTN }, { "dst", TF_COMP, FT_LV_DST, FT_PARSEDATE, TFL_PUTN }, { "pretty", TF_COMP, FT_LS_PRETTY, FT_PARSEDATE, TFL_PUTS }, { "nodate", TF_COMP, FT_LV_COMPFLAG, FT_PARSEDATE, TFL_PUTN }, { "date2local", TF_COMP, FT_LOCALDATE, FT_PARSEDATE, 0 }, { "date2gmt", TF_COMP, FT_GMTDATE, FT_PARSEDATE, 0 }, { "pers", TF_COMP, FT_LS_PERS, FT_PARSEADDR, TFL_PUTS }, { "mbox", TF_COMP, FT_LS_MBOX, FT_PARSEADDR, TFL_PUTS }, { "host", TF_COMP, FT_LS_HOST, FT_PARSEADDR, TFL_PUTS }, { "path", TF_COMP, FT_LS_PATH, FT_PARSEADDR, TFL_PUTS }, { "gname", TF_COMP, FT_LS_GNAME, FT_PARSEADDR, TFL_PUTS }, { "note", TF_COMP, FT_LS_NOTE, FT_PARSEADDR, TFL_PUTS }, { "addr", TF_COMP, FT_LS_ADDR, FT_PARSEADDR, TFL_PUTS }, { "proper", TF_COMP, FT_LS_822ADDR, FT_PARSEADDR, TFL_PUTS }, { "type", TF_COMP, FT_LV_HOSTTYPE, FT_PARSEADDR, TFL_PUTN }, { "ingrp", TF_COMP, FT_LV_INGRPF, FT_PARSEADDR, TFL_PUTN }, { "nohost", TF_COMP, FT_LV_NOHOSTF, FT_PARSEADDR, TFL_PUTN }, { "formataddr", TF_EXPR_SV,FT_FORMATADDR, FT_FORMATADDR, 0 }, { "concataddr", TF_EXPR_SV,FT_CONCATADDR, FT_FORMATADDR, 0 }, { "friendly", TF_COMP, FT_LS_FRIENDLY, FT_PARSEADDR, TFL_PUTS }, { "mymbox", TF_COMP, FT_LV_COMPFLAG, FT_MYMBOX, TFL_PUTN }, { "getmymbox", TF_COMP, FT_STR, FT_GETMYMBOX, 0 }, { "getmyaddr", TF_COMP, FT_LS_ADDR, FT_GETMYADDR, TFL_PUTS }, { "unquote", TF_EXPR, FT_LS_UNQUOTE, 0, TFL_PUTS }, { "bold", TF_BOLD, FT_LS_LIT, 0, TFL_PUTS }, { "underline", TF_UNDERLN,FT_LS_LIT, 0, TFL_PUTS }, { "standout", TF_STNDOUT,FT_LS_LIT, 0, TFL_PUTS }, { "resetterm", TF_RESET, FT_LS_LIT, 0, TFL_PUTS }, { "hascolor", TF_HASCLR, FT_LV_LIT, 0, 0 }, { "fgcolor", TF_FGCOLR, FT_LS_LIT, 0, TFL_PUTS }, { "bgcolor", TF_BGCOLR, FT_LS_LIT, 0, TFL_PUTS }, { NULL, 0, 0, 0, 0 } }; /* * A mapping of color names to terminfo color numbers. * * There are two sets of terminal-setting codes: 'setaf/setab' (ANSI) and * 'setf/setb'. Different terminals support different capabilities, so * we provide a mapping for both. I'm not crazy about putting numbers * directly in here, but it seems these are well defined by terminfo * so it should be okay. */ struct colormap { char *colorname; /* Name of color */ int ansinum; /* The ANSI escape color number */ int nonansinum; /* The non-ANSI escape color number */ }; static struct colormap colortable[] = { { "black", 0, 0 }, { "red", 1, 4 }, { "green", 2, 2 }, { "yellow", 3, 6 }, { "blue", 4, 1 }, { "magenta", 5, 5 }, { "cyan", 6, 3 }, { "white", 7, 7 }, { NULL, 0, 0 } }; /* Hash function for component name. Deliberately avoids a function * call. Is case independent. Covers interval [0, 126] so never uses * the last element of wantcomp[]. This function is "pretty good". */ #define CHASH(nm) ( \ (( \ ((nm)[0]) - ((nm)[0] ? ((nm)[1]) : 0) \ ) & 0x1f) + \ ((nm[1]) ? (((nm)[2]) & 0x5f) : 0) \ ) /* * Find a component in the hash table. */ #define FINDCOMP(comp,name) \ for (comp = wantcomp[CHASH(name)]; \ comp && strcmp(comp->c_name,name); \ comp = comp->c_next) \ ; /* Add new component to the hash table */ #define NEWCOMP(cm,name) do { \ NEW0(cm);\ cm->c_name = mh_xstrdup(name);\ cm->c_refcount++;\ ncomp++;\ i = CHASH(name);\ cm->c_next = wantcomp[i];\ wantcomp[i] = cm; \ } while (0) #define NEW_FP(type,fill,wid) do {\ fp=next_fp++; fp->f_type=(type); fp->f_fill=(fill); fp->f_width=(wid); \ } while (0) /* Add (possibly new) component to the hash table */ #define ADDC(name) do { \ FINDCOMP(cm, name);\ if (!cm) {\ NEWCOMP(cm,name);\ }\ fp->f_comp = cm; \ fp->f_flags |= FF_COMPREF; \ cm->c_refcount++; \ } while (0) #define LV(type, value) do { NEW_FP(type,0,0); fp->f_value = (value); } while (0) #define LS(type, str) do { NEW_FP(type,0,0); fp->f_text = getcpy(str); fp->f_flags |= FF_STRALLOC; } while (0) #define PUTCOMP(comp) do { NEW_FP(FT_COMP,0,0); ADDC(comp); } while (0) #define PUTLIT(str) do { NEW_FP(FT_LIT,0,0); fp->f_text = getcpy(str); fp->f_flags |= FF_STRALLOC; } while (0) #define PUTC(c) do { NEW_FP(FT_CHAR,0,0); fp->f_char = (c); } while (0) static char *format_string; static char *usr_fstring; /* for CERROR */ #define CERROR(str) compile_error (str, cp) /* * static prototypes */ static struct ftable *lookup(char *); static void compile_error(char *, char *); static char *compile (char *); static char *do_spec(char *); static char *do_name(char *, int); static char *do_func(char *); static char *do_expr (char *, int); static char *do_loop(char *); static char *do_if(char *); static void free_component(struct comp *); static void free_comptable(void); /* * Lookup a function name in the functable */ static struct ftable * lookup(char *name) { struct ftable *t = functable; char *nm; char c = *name; while ((nm = t->name)) { if (*nm == c && strcmp (nm, name) == 0) return (ftbl = t); t++; } return (struct ftable *) 0; } static void compile_error(char *str, char *cp) { int i, errpos, errctx; errpos = cp - format_string; errctx = min(errpos, 20); usr_fstring[errpos] = '\0'; for (i = errpos-errctx; i < errpos; i++) { if (iscntrl((unsigned char) usr_fstring[i])) usr_fstring[i] = '_'; } inform("\"%s\": format compile error - %s", &usr_fstring[errpos-errctx], str); adios (NULL, "%*s", errctx+1, "^"); } /* * Compile format string "fstring" into format list "fmt". * Return the number of header components found in the format * string. */ int fmt_compile(char *fstring, struct format **fmt, int reset_comptable) { char *cp; size_t i; static int comptable_initialized = 0; format_string = mh_xstrdup(fstring); usr_fstring = fstring; if (reset_comptable || !comptable_initialized) { free_comptable(); comptable_initialized = 1; } /* it takes at least 4 char to generate one format so we * allocate a worst-case format array using 1/4 the length * of the format string. We actually need twice this much * to handle both pre-processing (e.g., address parsing) and * normal processing. */ i = strlen(fstring)/2 + 1; if (i==1) i++; next_fp = formatvec = mh_xcalloc(i, sizeof *next_fp); infunction = 0; cp = compile(format_string); if (*cp) { CERROR("extra '%>', '%|' or '%?'"); } LV(FT_DONE, 0); /* really done */ *fmt = formatvec; free(format_string); return (ncomp); } static char * compile (char *sp) { char *cp = sp; int c; for (;;) { sp = cp; while ((c = *cp) && c != '%') cp++; *cp = 0; switch (cp-sp) { case 0: break; case 1: PUTC(*sp); break; default: PUTLIT(sp); break; } if (c == 0) return (cp); switch (c = *++cp) { case '%': PUTC (*cp); cp++; break; case '|': case '>': case '?': case ']': return (cp); case '<': cp = do_if(++cp); break; case '[': /* ] */ cp = do_loop(++cp); break; case ';': /* comment line */ cp++; while ((c = *cp++) && c != '\n') continue; break; default: cp = do_spec(cp); break; } } } /* * Process functions & components (handle field width here as well */ static char * do_spec(char *sp) { char *cp = sp; int c; #ifndef lint int ljust = 0; #endif /* not lint */ int wid = 0; char fill = ' '; c = *cp++; if (c == '-') { ljust++; c = *cp++; } if (c == '0') { fill = c; c = *cp++; } while (isdigit(c)) { wid = wid*10 + (c - '0'); c = *cp++; } if (c == '{') { cp = do_name(cp, 0); if (! infunction) fp->f_type = wid? FT_COMPF : FT_COMP; } else if (c == '(') { cp = do_func(cp); if (! infunction) { if (ftbl->flags & TFL_PUTS) { LV( wid? FT_STRF : FT_STR, ftbl->extra); } else if (ftbl->flags & TFL_PUTN) { LV( wid? FT_NUMF : FT_NUM, ftbl->extra); } } } else { CERROR("component or function name expected"); } if (ljust) wid = -wid; fp->f_width = wid; fp->f_fill = fill; return (cp); } /* * Process a component name. Normally this involves generating an FT_COMP * instruction for the specified component. If preprocess is set, then we * do some extra processing. */ static char * do_name(char *sp, int preprocess) { char *cp = sp; int c; int i; static int primed = 0; while (isalnum(c = *cp++) || c == '-' || c == '_') ; if (c != '}') { CERROR("'}' expected"); } cp[-1] = '\0'; PUTCOMP(sp); switch (preprocess) { case FT_PARSEDATE: if (cm->c_type & CT_ADDR) { CERROR("component used as both date and address"); } if (cm->c_tws) { memset (cm->c_tws, 0, sizeof *cm->c_tws); } else { NEW0(cm->c_tws); } fp->f_type = preprocess; PUTCOMP(sp); cm->c_type |= CT_DATE; break; case FT_MYMBOX: case FT_GETMYMBOX: case FT_GETMYADDR: if (!primed) { ismymbox ((struct mailname *) 0); primed++; } /* FALLTHRU */ case FT_PARSEADDR: if (cm->c_type & CT_DATE) { CERROR("component used as both date and address"); } cm->c_mn = &fmt_mnull; fp->f_type = preprocess; PUTCOMP(sp); cm->c_type |= CT_ADDR; break; case FT_FORMATADDR: if (cm->c_type & CT_DATE) { CERROR("component used as both date and address"); } cm->c_type |= CT_ADDR; break; } return (cp); } /* * Generate one or more instructions corresponding to the named function. * The different type of function arguments are handled here. */ static char * do_func(char *sp) { char *cp = sp; int c; struct ftable *t; int n; int mflag; /* minus sign in NUM */ infunction++; while (isalnum(c = *cp++)) ; if (c != '(' && c != '{' && c != ' ' && c != ')') { CERROR("'(', '{', ' ' or ')' expected"); } cp[-1] = '\0'; if ((t = lookup (sp)) == 0) { CERROR("unknown function"); } if (isspace(c)) c = *cp++; switch (t->type) { case TF_COMP: if (c != '{') { CERROR("component name expected"); } cp = do_name(cp, t->extra); fp->f_type = t->f_type; c = *cp++; break; case TF_NUM: if ((mflag = (c == '-'))) c = *cp++; n = 0; while (isdigit(c)) { n = n*10 + (c - '0'); c = *cp++; } if (mflag) n = (-n); LV(t->f_type,n); break; case TF_STR: sp = cp - 1; while (c && c != ')') c = *cp++; cp[-1] = '\0'; LS(t->f_type,sp); break; case TF_NONE: LV(t->f_type,t->extra); break; case TF_MYBOX: LS(t->f_type, getusername()); break; case TF_MYNAME: LS(t->f_type, getfullname()); break; case TF_MYHOST: LS(t->f_type, LocalName(0)); break; case TF_LMBOX: LS(t->f_type, getlocalmbox()); break; case TF_BOLD: LS(t->f_type, get_term_stringcap("bold")); break; case TF_UNDERLN: LS(t->f_type, get_term_stringcap("smul")); break; case TF_STNDOUT: LS(t->f_type, get_term_stringcap("smso")); break; case TF_RESET: LS(t->f_type, get_term_stringcap("sgr0")); break; case TF_HASCLR: LV(t->f_type, get_term_numcap("colors") > 1); break; case TF_FGCOLR: case TF_BGCOLR: { struct colormap *cmap = colortable; char *code; sp = cp - 1; while (c && c != ')') c = *cp++; cp[-1] = '\0'; while (cmap->colorname != NULL) { if (strcasecmp(sp, cmap->colorname) == 0) break; cmap++; } if (cmap->colorname == NULL) { CERROR("Unknown color name"); break; } code = get_term_stringparm(t->type == TF_FGCOLR ? "setaf" : "setab", cmap->ansinum, 0); /* * If this doesn't have anything, try falling back to setf/setb */ if (! code) code = get_term_stringparm(t->type == TF_FGCOLR ? "setf" : "setb", cmap->nonansinum, 0); LS(t->f_type, code); break; } case TF_NOW: LV(t->f_type, time((time_t *) 0)); break; case TF_EXPR_SV: LV(FT_SAVESTR, 0); /* FALLTHRU */ case TF_EXPR: *--cp = c; cp = do_expr(cp, t->extra); LV(t->f_type, 0); c = *cp++; ftbl = t; break; case TF_NOP: *--cp = c; cp = do_expr(cp, t->extra); c = *cp++; ftbl = t; break; } if (c != ')') { CERROR("')' expected"); } --infunction; return (cp); } /* * Handle an expression as an argument. Basically we call one of do_name(), * do_func(), or do_if() */ static char * do_expr (char *sp, int preprocess) { char *cp = sp; int c; if ((c = *cp++) == '{') { cp = do_name (cp, preprocess); fp->f_type = FT_LS_COMP; } else if (c == '(') { cp = do_func (cp); } else if (c == ')') { return (--cp); } else if (c == '%' && *cp == '<') { cp = do_if (cp+1); } else { CERROR ("'(', '{', '%<' or ')' expected"); } return (cp); } /* * I am guessing this was for some kind of loop statement, which would have * looked like %[ .... %]. It looks like the way this would have worked * is that the format engine would have seen that FT_DONE had a 1 in the * f_un.f_un_value and then decided whether or not to continue the loop. * There is no support for this in the format engine, so right now if * you try using it you will reach the FT_DONE and simply stop. I'm leaving * this here in case someone wants to continue the work. * * Okay, got some more information on this from John L. Romine! From an * email he sent to the nmh-workers mailing list on December 2, 2010, he * explains it so: * * In this case (scan, formatsbr) it has to do with an extension to * the mh-format syntax to allow for looping. * * The scan format is processed once for each message. Those #ifdef * JLR changes allowed for the top part of the format file to be * processed once, then a second, looping part to be processed * once per message. As I recall, there were new mh-format escape * sequences to delimit the loop. This would have allowed for things * like per-format column headings in the scan output. * * Since existing format files didn't include the scan listing * header (it was hard-coded in scan.c) it would not have been * backward-compatible. All existing format files (including any * local ones) would have needed to be changed to include the format * codes for a header. The practice at the time was not to introduce * incompatible changes in a minor release, and I never managed to * put out a newer major release. * * I can see how this would work, and I suspect part of the motivation was * because the format compiler routines (at the time) couldn't really be * called multiple times on the same message because the memory management * was so lousy. That's been reworked and things are now a lot cleaner, * so I suspect if we're going to allow a format string to be used for the * scan header it might be simpler to have a separate format string just * for the header. But I'll leave this code in for now just in case we * decide that we want some kind of looping support. */ static char * do_loop(char *sp) { char *cp = sp; struct format *floop; floop = next_fp; cp = compile (cp); if (*cp++ != ']') CERROR ("']' expected"); LV(FT_DONE, 1); /* not yet done */ LV(FT_GOTO, 0); fp->f_skip = floop - fp; /* skip backwards */ return cp; } /* * Handle an if-elsif-endif statement. Note here that the branching * is handled by the f_skip member of the struct format (which is really * just f_width overloaded). This number controls how far to move forward * (or back) in the format instruction array. */ static char * do_if(char *sp) { char *cp = sp; struct format *fexpr, *fif = (struct format *)NULL; int c = '<'; for (;;) { if (c == '<') { /* doing an IF */ if ((c = *cp++) == '{') /*}*/{ cp = do_name(cp, 0); fp->f_type = FT_LS_COMP; LV (FT_IF_S, 0); } else if (c == '(') { cp = do_func(cp); /* see if we can merge the load and the "if" */ if (ftbl->f_type >= IF_FUNCS) fp->f_type = ftbl->extra; else { /* Put out a string test or a value test depending * on what this function's return type is. */ if (ftbl->flags & TFL_PUTS) { LV (FT_IF_S, 0); } else { LV (FT_IF_V_NE, 0); } } } else { CERROR("'(' or '{' expected"); /*}*/ } } fexpr = fp; /* loc of [ELS]IF */ cp = compile (cp); /* compile IF TRUE stmts */ if (fif) fif->f_skip = next_fp - fif; if ((c = *cp++) == '|') { /* the last ELSE */ LV(FT_GOTO, 0); fif = fp; /* loc of GOTO */ fexpr->f_skip = next_fp - fexpr; fexpr = (struct format *)NULL;/* no extra ENDIF */ cp = compile (cp); /* compile ELSE stmts */ fif->f_skip = next_fp - fif; c = *cp++; } else if (c == '?') { /* another ELSIF */ LV(FT_GOTO, 0); fif = fp; /* loc of GOTO */ fexpr->f_skip = next_fp - fexpr; c = '<'; /* impersonate an IF */ continue; } break; } if (c != '>') { CERROR("'>' expected."); } if (fexpr) /* IF ... [ELSIF ...] ENDIF */ fexpr->f_skip = next_fp - fexpr; return (cp); } /* * Free a set of format instructions. * * What we do here is: * * - Iterate through the list of format instructions, freeing any references * to allocated memory in each instruction. * - Free component references. * - If requested, reset the component hash table; that will also free any * references to components stored there. * */ void fmt_free(struct format *fmt, int reset_comptable) { struct format *fp = fmt; if (fp) { while (! (fp->f_type == FT_DONE && fp->f_value == 0)) { if (fp->f_flags & FF_STRALLOC) free(fp->f_text); if (fp->f_flags & FF_COMPREF) free_component(fp->f_comp); fp++; } free(fmt); } if (reset_comptable) free_comptable(); } /* * Free just the text strings from all of the component hash table entries */ void fmt_freecomptext(void) { unsigned int i; struct comp *cm; for (i = 0; i < DIM(wantcomp); i++) for (cm = wantcomp[i]; cm; cm = cm->c_next) { mh_xfree(cm->c_text); cm->c_text = NULL; } } /* * Find a component in our hash table. This is just a public interface to * the FINDCOMP macro, so we don't have to expose our hash table. */ struct comp * fmt_findcomp(char *component) { struct comp *cm; FINDCOMP(cm, component); return cm; } /* * Like fmt_findcomp, but case-insensitive. */ struct comp * fmt_findcasecomp(char *component) { struct comp *cm; for (cm = wantcomp[CHASH(component)]; cm; cm = cm->c_next) if (strcasecmp(component, FENDNULL(cm->c_name)) == 0) break; return cm; } /* * Add an entry to the component hash table * * Returns true if the component was added, 0 if it already existed. * */ int fmt_addcompentry(char *component) { struct comp *cm; int i; FINDCOMP(cm, component); if (cm) return 0; NEWCOMP(cm, component); /* * ncomp is really meant for fmt_compile() and this function is * meant to be used outside of it. So decrement it just to be safe * (internal callers should be using NEWCOMP()). */ ncomp--; return 1; } /* * Add a string to a component hash table entry. * * Note the special handling for components marked with CT_ADDR. The comments * in fmt_scan.h explain this in more detail. */ int fmt_addcomptext(char *component, char *text) { int i, found = 0, bucket = CHASH(component); struct comp *cptr = wantcomp[bucket]; char *cp; while (cptr) { if (strcasecmp(component, FENDNULL(cptr->c_name)) == 0) { found++; if (! cptr->c_text) { cptr->c_text = getcpy(text); } else { i = strlen(cp = cptr->c_text) - 1; if (cp[i] == '\n') { if (cptr->c_type & CT_ADDR) { cp[i] = '\0'; cp = add(",\n\t", cp); } else { cp = add("\t", cp); } } cptr->c_text = add(text, cp); } } cptr = cptr->c_next; } return found ? bucket : -1; } /* * Append text to a component we've already found. See notes in fmt_scan.h * for more information. */ void fmt_appendcomp(int bucket, char *component, char *text) { struct comp *cptr; if (bucket != -1) { for (cptr = wantcomp[bucket]; cptr; cptr = cptr->c_next) if (strcasecmp(component, FENDNULL(cptr->c_name)) == 0) cptr->c_text = add(text, cptr->c_text); } } /* * Iterate over our component hash table */ struct comp * fmt_nextcomp(struct comp *comp, unsigned int *bucket) { if (comp == NULL) *bucket = 0; else comp = comp->c_next; while (comp == NULL && *bucket < DIM(wantcomp)) { comp = wantcomp[(*bucket)++]; } return comp; } /* * Free and reset our component hash table */ static void free_comptable(void) { unsigned int i; struct comp *cm, *cm2; for (i = 0; i < DIM(wantcomp); i++) { cm = wantcomp[i]; while (cm != NULL) { cm2 = cm->c_next; free_component(cm); cm = cm2; } wantcomp[i] = 0; } ncomp = 0; } /* * Decrement the reference count of a component structure. If it reaches * zero, free it */ static void free_component(struct comp *cm) { if (--cm->c_refcount <= 0) { /* Shouldn't ever be NULL, but just in case ... */ mh_xfree(cm->c_name); mh_xfree(cm->c_text); if (cm->c_type & CT_DATE) free(cm->c_tws); if (cm->c_type & CT_ADDR && cm->c_mn && cm->c_mn != &fmt_mnull) mnfree(cm->c_mn); free(cm); } } nmh-1.7.1-RC3/sbr/fmt_new.c000644 007761 000024 00000003273 13243042053 015354 0ustar00kenhstaff000000 000000 /* fmt_new.c -- read format file/string and normalize * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #define QUOTE '\\' static char *formats = 0; /* * static prototypes */ static void normalize (char *); /* * Get new format string */ char * new_fs (char *form, char *format, char *default_fs) { struct stat st; FILE *fp; mh_xfree(formats); if (form) { if ((fp = fopen (etcpath (form), "r")) == NULL) adios (form, "unable to open format file"); if (fstat (fileno (fp), &st) == -1) adios (form, "unable to stat format file"); formats = mh_xmalloc ((size_t) st.st_size + 1); if (read (fileno(fp), formats, (int) st.st_size) != st.st_size) adios (form, "error reading format file"); formats[st.st_size] = '\0'; fclose (fp); } else { formats = getcpy (format ? format : default_fs); } normalize (formats); /* expand escapes */ return formats; } void free_fs(void) { free (formats); formats = 0; } /* * Expand escapes in format strings */ static void normalize (char *cp) { char *dp; for (dp = cp; *cp; cp++) { if (*cp != QUOTE) { *dp++ = *cp; } else { switch (*++cp) { case 'b': *dp++ = '\b'; break; case 'f': *dp++ = '\f'; break; case 'n': *dp++ = '\n'; break; case 'r': *dp++ = '\r'; break; case 't': *dp++ = '\t'; break; case '\n': break; case 0: cp--; /* FALLTHRU */ default: *dp++ = *cp; break; } } } *dp = '\0'; } nmh-1.7.1-RC3/sbr/fmt_rfc2047.c000644 007761 000024 00000023672 13243042053 015657 0ustar00kenhstaff000000 000000 /* fmt_rfc2047.c -- decode RFC-2047 header format * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #ifdef HAVE_ICONV # include #endif static signed char hexindex[] = { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 }; static signed char index_64[128] = { -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 }; #define char64(c) (((unsigned char) (c) > 127) ? -1 : index_64[(unsigned char) (c)]) /* * Decode two quoted-pair characters */ int decode_qp (unsigned char byte1, unsigned char byte2) { if (hexindex[byte1] == -1 || hexindex[byte2] == -1) return -1; return (hexindex[byte1] << 4 | hexindex[byte2]); } /* Check if character is linear whitespace */ #define is_lws(c) ((c) == ' ' || (c) == '\t' || (c) == '\n') /* * Decode the string as a RFC-2047 header field */ /* Add character to the destination buffer, and bomb out if it fills up */ #define ADDCHR(C) do { *q++ = (C); dstlen--; if (!dstlen) goto buffull; } while (0) int decode_rfc2047 (char *str, char *dst, size_t dstlen) { char *p, *q, *pp; char *startofmime, *endofmime, *endofcharset; int c, quoted_printable; int encoding_found = 0; /* did we decode anything? */ int between_encodings = 0; /* are we between two encodings? */ int equals_pending = 0; /* is there a '=' pending? */ int whitespace = 0; /* how much whitespace between encodings? */ #ifdef HAVE_ICONV int use_iconv = 0; /* are we converting encoding with iconv? */ iconv_t cd = NULL; int fromutf8 = 0; char *saveq, *convbuf = NULL; size_t savedstlen; #endif if (!str) return 0; /* * Do a quick and dirty check for the '=' character. * This should quickly eliminate many cases. */ if (!strchr (str, '=')) return 0; for (p = str, q = dst; *p; p++) { /* reset iconv */ #ifdef HAVE_ICONV if (use_iconv) { iconv_close(cd); use_iconv = 0; } #endif /* * If we had an '=' character pending from * last iteration, then add it first. */ if (equals_pending) { ADDCHR('='); equals_pending = 0; between_encodings = 0; /* we have added non-whitespace text */ } if (*p != '=') { /* count linear whitespace while between encodings */ if (between_encodings && is_lws(*p)) whitespace++; else between_encodings = 0; /* we have added non-whitespace text */ ADDCHR(*p); continue; } equals_pending = 1; /* we have a '=' pending */ /* Check for initial =? */ if (*p == '=' && p[1] == '?' && p[2]) { startofmime = p + 2; /* Scan ahead for the next '?' character */ for (pp = startofmime; *pp && *pp != '?'; pp++) ; if (!*pp) continue; /* * RFC 2231 specifies that language information can appear * in a charset specification like so: * * =?us-ascii*en?Q?Foo?= * * Right now we don't use language information, so ignore it. */ for (endofcharset = startofmime; *endofcharset != '*' && endofcharset < pp; endofcharset++) ; /* Check if character set can be handled natively */ if (!check_charset(startofmime, endofcharset - startofmime)) { #ifdef HAVE_ICONV /* .. it can't. We'll use iconv then. */ *endofcharset = '\0'; cd = iconv_open(get_charset(), startofmime); fromutf8 = !strcasecmp(startofmime, "UTF-8"); *pp = '?'; if (cd == (iconv_t)-1) continue; use_iconv = 1; #else continue; #endif } startofmime = pp + 1; /* Check for valid encoding type */ if (*startofmime != 'B' && *startofmime != 'b' && *startofmime != 'Q' && *startofmime != 'q') continue; /* Is encoding quoted printable or base64? */ quoted_printable = (*startofmime == 'Q' || *startofmime == 'q'); startofmime++; /* Check for next '?' character */ if (*startofmime != '?') continue; startofmime++; /* * Scan ahead for the ending ?= * * While doing this, we will also check if encoded * word has any embedded linear whitespace. */ endofmime = NULL; for (pp = startofmime; *pp && *(pp+1); pp++) { if (is_lws(*pp)) break; if (*pp == '?' && pp[1] == '=') { endofmime = pp; break; } } if (is_lws(*pp) || endofmime == NULL) continue; /* * We've found an encoded word, so we can drop * the '=' that was pending */ equals_pending = 0; /* * If we are between two encoded words separated only by * linear whitespace, then we ignore the whitespace. * We will roll back the buffer the number of whitespace * characters we've seen since last encoded word. */ if (between_encodings) { q -= whitespace; dstlen += whitespace; } #ifdef HAVE_ICONV /* * empty encoded text. This ensures that we don't * malloc 0 bytes but skip on to the end */ if (endofmime == startofmime && use_iconv) { use_iconv = 0; iconv_close(cd); } if (use_iconv) { saveq = q; savedstlen = dstlen; q = convbuf = (char *) mh_xmalloc(endofmime - startofmime); } /* ADDCHR2 is for adding characters when q is or might be convbuf: * in this case on buffer-full we want to run iconv before returning. * I apologise for the dreadful name. */ #define ADDCHR2(C) do { *q++ = (C); dstlen--; if (!dstlen) goto iconvbuffull; } while (0) #else #define ADDCHR2(C) ADDCHR(C) #endif /* Now decode the text */ if (quoted_printable) { for (pp = startofmime; pp < endofmime; pp++) { if (*pp == '=') { c = decode_qp (pp[1], pp[2]); if (c == -1) continue; if (c != 0) *q++ = c; pp += 2; } else if (*pp == '_') { ADDCHR2(' '); } else { ADDCHR2(*pp); } } } else { /* base64 */ int c1, c2, c3, c4; c1 = c2 = c3 = c4 = -1; pp = startofmime; while (pp < endofmime) { /* 6 + 2 bits */ while ((pp < endofmime) && ((c1 = char64(*pp)) == -1)) { pp++; } if (pp < endofmime) { pp++; } while ((pp < endofmime) && ((c2 = char64(*pp)) == -1)) { pp++; } if (pp < endofmime && c1 != -1 && c2 != -1) { ADDCHR2((c1 << 2) | (c2 >> 4)); pp++; } /* 4 + 4 bits */ while ((pp < endofmime) && ((c3 = char64(*pp)) == -1)) { pp++; } if (pp < endofmime && c2 != -1 && c3 != -1) { ADDCHR2(((c2 & 0xF) << 4) | (c3 >> 2)); pp++; } /* 2 + 6 bits */ while ((pp < endofmime) && ((c4 = char64(*pp)) == -1)) { pp++; } if (pp < endofmime && c3 != -1 && c4 != -1) { ADDCHR2(((c3 & 0x3) << 6) | (c4)); pp++; } } } #ifdef HAVE_ICONV iconvbuffull: /* NB that the string at convbuf is not necessarily NUL terminated here: * q points to the first byte after the valid part. */ /* Convert to native character set */ if (use_iconv) { size_t inbytes = q - convbuf; ICONV_CONST char *start = convbuf; while (inbytes) { if (iconv(cd, &start, &inbytes, &saveq, &savedstlen) == (size_t)-1) { if (errno != EILSEQ) break; /* character couldn't be converted. we output a `?' * and try to carry on which won't work if * either encoding was stateful */ iconv (cd, 0, 0, &saveq, &savedstlen); if (!savedstlen) break; *saveq++ = '?'; savedstlen--; if (!savedstlen) break; /* skip to next input character */ if (fromutf8) { for (++start, --inbytes; start < q && (*start & 192) == 128; ++start, --inbytes) continue; } else start++, inbytes--; if (start >= q) break; } } q = saveq; /* Stop now if (1) we hit the end of the buffer trying to do * MIME decoding and have just iconv-converted a partial string * or (2) our iconv-conversion hit the end of the buffer. */ if (!dstlen || !savedstlen) goto buffull; dstlen = savedstlen; free(convbuf); } #endif /* * Now that we are done decoding this particular * encoded word, advance string to trailing '='. */ p = endofmime + 1; encoding_found = 1; /* we found (at least 1) encoded word */ between_encodings = 1; /* we have just decoded something */ whitespace = 0; /* re-initialize amount of whitespace */ } } #ifdef HAVE_ICONV if (use_iconv) iconv_close(cd); #endif /* If an equals was pending at end of string, add it now. */ if (equals_pending) ADDCHR('='); *q = '\0'; return encoding_found; buffull: /* q is currently just off the end of the buffer, so rewind to NUL terminate */ q--; *q = '\0'; return encoding_found; } nmh-1.7.1-RC3/sbr/fmt_scan.c000644 007761 000024 00000073032 13243042053 015507 0ustar00kenhstaff000000 000000 /* fmt_scan.c -- format string interpretation * * 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. * * This is the engine that processes the format instructions created by * fmt_compile (found in fmt_compile.c). */ #include #include #include #include #include #include #include "unquote.h" #ifdef HAVE_SYS_TIME_H # include #endif #include #ifdef MULTIBYTE_SUPPORT # include # include #endif struct mailname fmt_mnull = { NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, NULL, NULL }; /* * static prototypes */ static int match (char *, char *); static char *get_x400_friendly (char *, char *, int); static int get_x400_comp (char *, char *, char *, int); /* * test if string "sub" appears anywhere in * string "str" (case insensitive). */ static int match (char *str, char *sub) { int c1, c2; char *s1, *s2; while ((c1 = *sub)) { c1 = tolower((unsigned char)c1); while ((c2 = *str++) && c1 != tolower((unsigned char)c2)) ; if (! c2) return 0; s1 = sub + 1; s2 = str; while ((c1 = *s1++) && tolower((unsigned char)c1) == tolower((unsigned char)(c2 = *s2++))) ; if (! c1) return 1; } return 1; } /* cpnumber formats num as a signed decimal, * appending it to dest if the result doesn't exceed max. * The absolute value of width is the minimum width to produce. * A smaller string is padded; * on the left if width is positive, else the right. * Left-padding uses fill. It is either ' ' or '0'. * Right-padding is always with space. */ void cpnumber(charstring_t dest, int num, int width, char fill, size_t max) { if (width == 0 || width == INT_MIN) { return; } bool padright = width < 0; if (padright) { width = -width; /* Can't overflow after above check. */ } size_t w = width; if (w > max) { return; /* The padded result can't fit. */ } if (num < 0 && w == 1) { return; /* No room for `-' and a digit or `?'. */ } char *s = m_str(num); size_t len = strlen(s); if (len == w) { charstring_append_cstring(dest, s); return; } bool neg = *s == '-'; if (len < w) { if (padright) { charstring_append_cstring(dest, s); while (len++ < w) { charstring_push_back(dest, ' '); } return; } if (neg && fill == '0') { charstring_push_back(dest, *s++); } while (len++ < w) { charstring_push_back(dest, fill); } charstring_append_cstring(dest, s); return; } /* Transform 1234567 -> 1234?67 and -1234567 -> 1234-?7. */ char *news = s + len - w; if (neg) { *news = '-'; } news[neg] = '?'; charstring_append_cstring(dest, news); } /* * copy string from str to dest padding with the fill character to a * size of wid characters. if wid is negative, the string is right * aligned no more than max characters are copied */ void cptrimmed(charstring_t dest, char *str, int wid, char fill, size_t max) { int remaining; /* remaining output width available */ int rjust; struct charstring *trimmed; size_t end; /* number of input bytes remaining in str */ #ifdef MULTIBYTE_SUPPORT int char_len; /* bytes in current character */ int w; wchar_t wide_char; char *altstr = NULL; #endif char *sp; /* current position in source string */ int prevCtrl = 1; /* get alignment */ rjust = 0; if ((remaining = wid) < 0) { remaining = -remaining; rjust++; } if (remaining > (int) max) { remaining = max; } trimmed = rjust ? charstring_create(remaining) : dest; if ((sp = str)) { #ifdef MULTIBYTE_SUPPORT if (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); /* * See the relevant comments in cpstripped() to explain what's * going on here; we want to handle the case where we get * characters that mbtowc() cannot handle */ if (char_len < 0) { altstr = "?"; char_len = mbtowc(&wide_char, altstr, 1); } if (char_len <= 0) { break; } w = wcwidth(wide_char); /* If w > remaining, w must be positive. */ if (w > remaining) { break; } end -= char_len; if (iswcntrl(wide_char) || iswspace(wide_char)) { sp += char_len; #else int c; end--; /* isnctrl(), etc., take an int argument. Cygwin's ctype.h intentionally warns if they are passed a char. */ c = (unsigned char) *sp; if (iscntrl(c) || isspace(c)) { sp++; #endif if (!prevCtrl) { charstring_push_back (trimmed, ' '); remaining--; } prevCtrl = 1; continue; } prevCtrl = 0; #ifdef MULTIBYTE_SUPPORT if (w >= 0 && remaining >= w) { charstring_push_back_chars (trimmed, altstr ? altstr : sp, char_len, w); remaining -= w; altstr = NULL; } sp += char_len; #else charstring_push_back (trimmed, *sp++); remaining--; #endif } } while (remaining-- > 0) { charstring_push_back(dest, fill); } if (rjust) { charstring_append(dest, trimmed); charstring_free(trimmed); } } #ifdef MULTIBYTE_SUPPORT static void cpstripped (charstring_t dest, size_t max, char *str) { static bool deja_vu; static char *oddchar; static size_t oddlen; static char *spacechar; static size_t spacelen; char *end; bool squash; char *src; int srclen; wchar_t rune; int w; if (!deja_vu) { size_t two; deja_vu = true; two = MB_CUR_MAX * 2; /* Varies at run-time. */ oddchar = mh_xmalloc(two); oddlen = wcstombs(oddchar, L"?", two); assert(oddlen > 0); assert(wcwidth(L' ') == 1); /* Need to pad in ones. */ spacechar = mh_xmalloc(two); spacelen = wcstombs(spacechar, L" ", two); assert(spacelen > 0); } if (!str) return; /* It's unclear why no padding in this case. */ end = str + strlen(str); if (mbtowc(NULL, NULL, 0)) {} /* Reset shift state. */ squash = true; /* Trim `space' or `cntrl' from the start. */ while (max) { if (!*str) return; /* It's unclear why no padding in this case. */ srclen = mbtowc(&rune, str, end - str); if (srclen == -1) { /* Invalid rune, or not enough bytes to finish it. */ rune = L'?'; src = oddchar; srclen = oddlen; str++; /* Skip one byte. */ } else { src = str; str += srclen; } if (iswspace(rune) || iswcntrl(rune)) { if (squash) continue; /* Amidst a run of these. */ rune = L' '; src = spacechar; srclen = spacelen; squash = true; } else squash = false; w = wcwidth(rune); if (w == -1) { rune = L'?'; w = wcwidth(rune); assert(w != -1); src = oddchar; srclen = oddlen; } if ((size_t)w > max) { /* No room for rune; pad. */ while (max--) charstring_push_back_chars(dest, spacechar, spacelen, 1); return; } charstring_push_back_chars(dest, src, srclen, w); max -= w; } } #endif #ifndef MULTIBYTE_SUPPORT static void cpstripped (charstring_t dest, size_t max, char *str) { bool squash; int c; if (!str) return; squash = true; /* Strip leading cases. */ while (max--) { c = (unsigned char)*str++; if (!c) return; if (isspace(c) || iscntrl(c)) { if (squash) continue; c = ' '; squash = true; } else squash = false; charstring_push_back(dest, (char)c); } } #endif static char *lmonth[] = { "January", "February","March", "April", "May", "June", "July", "August", "September","October", "November","December" }; static char * get_x400_friendly (char *mbox, char *buffer, int buffer_len) { char given[BUFSIZ], surname[BUFSIZ]; if (mbox == NULL) return NULL; if (*mbox == '"') mbox++; if (*mbox != '/') return NULL; if (get_x400_comp (mbox, "/PN=", buffer, buffer_len)) { for (mbox = buffer; (mbox = strchr(mbox, '.')); ) *mbox++ = ' '; return buffer; } if (!get_x400_comp (mbox, "/S=", surname, sizeof(surname))) return NULL; if (get_x400_comp (mbox, "/G=", given, sizeof(given))) snprintf (buffer, buffer_len, "%s %s", given, surname); else snprintf (buffer, buffer_len, "%s", surname); return buffer; } static int get_x400_comp (char *mbox, char *key, char *buffer, int buffer_len) { int idx; char *cp; if ((idx = stringdex (key, mbox)) < 0 || !(cp = strchr(mbox += idx + strlen (key), '/'))) return 0; snprintf (buffer, buffer_len, "%*.*s", (int)(cp - mbox), (int)(cp - mbox), mbox); return 1; } struct format * fmt_scan (struct format *format, charstring_t scanlp, int width, int *dat, struct fmt_callbacks *callbacks) { char *sp; char *savestr, *str; char buffer[NMH_BUFSIZ], buffer2[NMH_BUFSIZ]; int i, c, rjust; int value; time_t t; size_t max; struct format *fmt; struct comp *comp; struct tws *tws; struct mailname *mn; /* * max is the same as width, but unsigned so comparisons * with charstring_chars() won't raise compile warnings. */ max = width; savestr = str = NULL; value = 0; for (fmt = format; fmt->f_type != FT_DONE; fmt++) switch (fmt->f_type) { case FT_PARSEADDR: case FT_PARSEDATE: fmt->f_comp->c_flags &= ~CF_PARSED; break; case FT_COMP: case FT_COMPF: case FT_LS_COMP: case FT_LS_DECODECOMP: /* * Trim these components of any newlines. * * But don't trim the "body" and "text" components. */ comp = fmt->f_comp; 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) comp->c_text[i - 1] = '\0'; comp->c_flags |= CF_TRIMMED; } break; } fmt = format; for ( ; charstring_chars (scanlp) < max; ) { switch (fmt->f_type) { case FT_COMP: cpstripped (scanlp, max - charstring_chars (scanlp), fmt->f_comp->c_text); break; case FT_COMPF: cptrimmed (scanlp, fmt->f_comp->c_text, fmt->f_width, fmt->f_fill, max - charstring_chars (scanlp)); break; case FT_LIT: sp = fmt->f_text; while ((c = *sp++) && charstring_chars (scanlp) < max) { charstring_push_back (scanlp, c); } break; case FT_LITF: sp = fmt->f_text; rjust = 0; i = fmt->f_width; if (i < 0) { i = -i; rjust++; /* XXX should do something with this */ } while ((c = *sp++) && --i >= 0 && charstring_chars (scanlp) < max) { charstring_push_back (scanlp, c); } while (--i >= 0 && charstring_chars (scanlp) < max) { charstring_push_back (scanlp, fmt->f_fill); } break; case FT_STR: cpstripped (scanlp, max - charstring_chars (scanlp), str); break; case FT_STRF: cptrimmed (scanlp, str, fmt->f_width, fmt->f_fill, max - charstring_chars (scanlp)); break; case FT_STRLIT: if (str) { sp = str; while ((c = *sp++) && charstring_chars (scanlp) < max) { charstring_push_back (scanlp, c); } } break; case FT_STRLITZ: if (str) charstring_push_back_chars (scanlp, str, strlen (str), 0); break; case FT_STRFW: adios (NULL, "internal error (FT_STRFW)"); case FT_NUM: { int num = value; unsigned int wid; for (wid = num <= 0; num; ++wid, num /= 10) {} cpnumber (scanlp, value, wid, ' ', max - charstring_chars (scanlp)); break; } case FT_LS_KILO: case FT_LS_KIBI: { char *unitcp; unsigned int whole, tenths; unsigned int scale = 0; unsigned int val = (unsigned int)value; char *kibisuff = NULL; switch (fmt->f_type) { case FT_LS_KILO: scale = 1000; kibisuff = ""; break; case FT_LS_KIBI: scale = 1024; kibisuff = "i"; break; } if (val < scale) { snprintf(buffer, sizeof(buffer), "%u", val); } else { /* To prevent divide by 0, found by clang static analyzer. */ if (scale == 0) { scale = 1; } /* find correct scale for size (Kilo/Mega/Giga/Tera) */ for (unitcp = "KMGT"; val > (scale * scale); val /= scale) { if (!*++unitcp) break; } if (!*unitcp) { strcpy(buffer, "huge"); } else { /* val is scale times too big. we want tenths */ val *= 10; /* round up */ val += (scale - 1); val /= scale; whole = val / 10; tenths = val - (whole * 10); if (tenths) { snprintf(buffer, sizeof(buffer), "%u.%u%c%s", whole, tenths, *unitcp, kibisuff); } else { snprintf(buffer, sizeof(buffer), "%u%c%s", whole, *unitcp, kibisuff); } } } str = buffer; } break; case FT_NUMF: cpnumber (scanlp, value, fmt->f_width, fmt->f_fill, max - charstring_chars (scanlp)); break; case FT_CHAR: charstring_push_back (scanlp, fmt->f_char); break; case FT_DONE: if (callbacks && callbacks->trace_func) callbacks->trace_func(callbacks->trace_context, fmt, value, str, charstring_buffer (scanlp)); goto finished; case FT_IF_S: if (!(value = (str && *str))) { if (callbacks && callbacks->trace_func) callbacks->trace_func(callbacks->trace_context, fmt, value, str, charstring_buffer (scanlp)); fmt += fmt->f_skip; continue; } break; case FT_IF_S_NULL: if (!(value = (str == NULL || *str == 0))) { if (callbacks && callbacks->trace_func) callbacks->trace_func(callbacks->trace_context, fmt, value, str, charstring_buffer (scanlp)); fmt += fmt->f_skip; continue; } break; case FT_IF_V_EQ: if (value != fmt->f_value) { if (callbacks && callbacks->trace_func) callbacks->trace_func(callbacks->trace_context, fmt, value, str, charstring_buffer (scanlp)); fmt += fmt->f_skip; continue; } break; case FT_IF_V_NE: if (value == fmt->f_value) { if (callbacks && callbacks->trace_func) callbacks->trace_func(callbacks->trace_context, fmt, value, str, charstring_buffer (scanlp)); fmt += fmt->f_skip; continue; } break; case FT_IF_V_GT: if (value <= fmt->f_value) { if (callbacks && callbacks->trace_func) callbacks->trace_func(callbacks->trace_context, fmt, value, str, charstring_buffer (scanlp)); fmt += fmt->f_skip; continue; } break; case FT_IF_MATCH: if (!(value = (str && match (str, fmt->f_text)))) { if (callbacks && callbacks->trace_func) callbacks->trace_func(callbacks->trace_context, fmt, value, str, charstring_buffer (scanlp)); fmt += fmt->f_skip; continue; } break; case FT_V_MATCH: if (str) value = match (str, fmt->f_text); else value = 0; break; case FT_IF_AMATCH: if (!(value = (str && uprf (str, fmt->f_text)))) { if (callbacks && callbacks->trace_func) callbacks->trace_func(callbacks->trace_context, fmt, value, str, charstring_buffer (scanlp)); fmt += fmt->f_skip; continue; } break; case FT_V_AMATCH: value = uprf (str, fmt->f_text); break; case FT_S_NONNULL: value = (str != NULL && *str != 0); break; case FT_S_NULL: value = (str == NULL || *str == 0); break; case FT_V_EQ: value = (fmt->f_value == value); break; case FT_V_NE: value = (fmt->f_value != value); break; case FT_V_GT: value = (fmt->f_value > value); break; case FT_GOTO: if (callbacks && callbacks->trace_func) callbacks->trace_func(callbacks->trace_context, fmt, value, str, charstring_buffer (scanlp)); fmt += fmt->f_skip; continue; case FT_NOP: break; case FT_LS_COMP: str = fmt->f_comp->c_text; break; case FT_LS_LIT: str = fmt->f_text; break; case FT_LS_GETENV: if (!(str = getenv (fmt->f_text))) str = ""; break; case FT_LS_CFIND: if (!(str = context_find (fmt->f_text))) str = ""; break; case FT_LS_DECODECOMP: if (decode_rfc2047(fmt->f_comp->c_text, buffer2, sizeof(buffer2))) str = buffer2; else str = fmt->f_comp->c_text; break; case FT_LS_DECODE: if (str && decode_rfc2047(str, buffer2, sizeof(buffer2))) str = buffer2; break; case FT_LS_TRIM: if (str) { char *xp; if (str != buffer) strncpy(buffer, str, sizeof(buffer)); buffer[sizeof(buffer)-1] = '\0'; str = buffer; while (isspace((unsigned char) *str)) str++; rjust = 0; if ((i = fmt->f_width) < 0) { i = -i; rjust++; } if (!rjust && i > 0 && (int) strlen(str) > i) str[i] = '\0'; xp = str; xp += strlen(str) - 1; while (xp > str && isspace((unsigned char) *xp)) *xp-- = '\0'; if (rjust && i > 0 && (int) strlen(str) > i) str += strlen(str) - i; } break; case FT_LV_COMPFLAG: value = (fmt->f_comp->c_flags & CF_TRUE) != 0; break; case FT_LV_COMP: value = (comp = fmt->f_comp)->c_text ? atoi(comp->c_text) : 0; break; case FT_LV_LIT: value = fmt->f_value; break; case FT_LV_DAT: value = dat[fmt->f_value]; break; case FT_LV_STRLEN: if (str != NULL) value = strlen(str); else value = 0; break; case FT_LV_CHAR_LEFT: value = max - charstring_bytes (scanlp); break; case FT_LV_PLUS_L: value += fmt->f_value; break; case FT_LV_MINUS_L: value = fmt->f_value - value; break; case FT_LV_MULTIPLY_L: value *= fmt->f_value; break; case FT_LV_DIVIDE_L: if (fmt->f_value) value /= fmt->f_value; else value = 0; break; case FT_LV_MODULO_L: if (fmt->f_value) value %= fmt->f_value; else value = 0; break; case FT_SAVESTR: savestr = str; break; case FT_LV_SEC: value = fmt->f_comp->c_tws->tw_sec; break; case FT_LV_MIN: value = fmt->f_comp->c_tws->tw_min; break; case FT_LV_HOUR: value = fmt->f_comp->c_tws->tw_hour; break; case FT_LV_MDAY: value = fmt->f_comp->c_tws->tw_mday; break; case FT_LV_MON: value = fmt->f_comp->c_tws->tw_mon + 1; break; case FT_LS_MONTH: str = tw_moty[fmt->f_comp->c_tws->tw_mon]; break; case FT_LS_LMONTH: str = lmonth[fmt->f_comp->c_tws->tw_mon]; break; case FT_LS_ZONE: str = dtwszone (fmt->f_comp->c_tws); break; case FT_LV_YEAR: value = fmt->f_comp->c_tws->tw_year; break; case FT_LV_WDAY: if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP))) set_dotw (tws); value = tws->tw_wday; break; case FT_LS_DAY: if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP))) set_dotw (tws); str = tw_dotw[tws->tw_wday]; break; case FT_LS_WEEKDAY: if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP))) set_dotw (tws); str = tw_ldotw[tws->tw_wday]; break; case FT_LV_YDAY: value = fmt->f_comp->c_tws->tw_yday; break; case FT_LV_ZONE: value = fmt->f_comp->c_tws->tw_zone; break; case FT_LV_CLOCK: if ((value = fmt->f_comp->c_tws->tw_clock) == 0) value = dmktime(fmt->f_comp->c_tws); break; case FT_LV_RCLOCK: if ((value = fmt->f_comp->c_tws->tw_clock) == 0) value = dmktime(fmt->f_comp->c_tws); value = time((time_t *) 0) - value; break; case FT_LV_DAYF: if (!(((tws = fmt->f_comp->c_tws)->tw_flags) & (TW_SEXP|TW_SIMP))) set_dotw (tws); switch (fmt->f_comp->c_tws->tw_flags & TW_SDAY) { case TW_SEXP: value = 1; break; case TW_SIMP: value = 0; break; default: value = -1; break; } break; case FT_LV_ZONEF: if (fmt->f_comp->c_tws->tw_flags & TW_SZEXP) value = 1; else value = -1; break; case FT_LV_DST: value = fmt->f_comp->c_tws->tw_flags & TW_DST ? 1 : 0; break; case FT_LS_822DATE: str = dasctime (fmt->f_comp->c_tws , TW_ZONE); break; case FT_LS_PRETTY: str = dasctime (fmt->f_comp->c_tws, TW_NULL); break; case FT_LS_PERS: str = fmt->f_comp->c_mn->m_pers; break; case FT_LS_MBOX: str = fmt->f_comp->c_mn->m_mbox; break; case FT_LS_HOST: str = fmt->f_comp->c_mn->m_host; break; case FT_LS_PATH: str = fmt->f_comp->c_mn->m_path; break; case FT_LS_GNAME: str = fmt->f_comp->c_mn->m_gname; break; case FT_LS_NOTE: str = fmt->f_comp->c_mn->m_note; break; case FT_LS_822ADDR: str = adrformat( fmt->f_comp->c_mn ); break; case FT_LV_HOSTTYPE: value = fmt->f_comp->c_mn->m_type; break; case FT_LV_INGRPF: value = fmt->f_comp->c_mn->m_ingrp; break; case FT_LV_NOHOSTF: value = fmt->f_comp->c_mn->m_nohost; break; case FT_LS_ADDR: case FT_LS_FRIENDLY: if ((mn = fmt->f_comp->c_mn) == &fmt_mnull) { str = fmt->f_comp->c_text; break; } if (fmt->f_type == FT_LS_ADDR) goto unfriendly; if ((str = mn->m_pers) == NULL) { if ((str = mn->m_note)) { if (str != buffer) strncpy (buffer, str, sizeof(buffer)); buffer[sizeof(buffer)-1] = '\0'; str = buffer; if (*str == '(') str++; sp = str + strlen(str) - 1; if (*sp == ')') { *sp-- = '\0'; while (sp >= str) if (*sp == ' ') *sp-- = '\0'; else break; } } else if (!(str = get_x400_friendly (mn->m_mbox, buffer, sizeof(buffer)))) { unfriendly: switch (mn->m_type) { case LOCALHOST: str = mn->m_mbox; break; case UUCPHOST: snprintf (buffer, sizeof(buffer), "%s!%s", mn->m_host, mn->m_mbox); str = buffer; break; default: if (mn->m_mbox) { snprintf (buffer, sizeof(buffer), "%s@%s", mn->m_mbox, mn->m_host); str= buffer; } else str = mn->m_text; break; } } } break; /* UNQUOTEs RFC-2822 quoted-string and quoted-pair */ case FT_LS_UNQUOTE: if (str) { if (str != buffer) strncpy(buffer, str, sizeof(buffer)); /* strncpy doesn't NUL-terminate if it fills the buffer */ buffer[sizeof(buffer)-1] = '\0'; unquote_string(buffer, buffer2); str = buffer2; } break; case FT_LOCALDATE: comp = fmt->f_comp; if ((t = comp->c_tws->tw_clock) == 0) t = dmktime(comp->c_tws); tws = dlocaltime(&t); *comp->c_tws = *tws; break; case FT_GMTDATE: comp = fmt->f_comp; if ((t = comp->c_tws->tw_clock) == 0) t = dmktime(comp->c_tws); tws = dgmtime(&t); *comp->c_tws = *tws; break; case FT_PARSEDATE: comp = fmt->f_comp; if (comp->c_flags & CF_PARSED) break; if ((sp = comp->c_text) && (tws = dparsetime(sp))) { *comp->c_tws = *tws; comp->c_flags &= ~CF_TRUE; } else if ((comp->c_flags & CF_DATEFAB) == 0) { memset (comp->c_tws, 0, sizeof *comp->c_tws); comp->c_flags = CF_TRUE; } comp->c_flags |= CF_PARSED; break; case FT_FORMATADDR: /* hook for custom address list formatting (see replsbr.c) */ if (callbacks && callbacks->formataddr) str = callbacks->formataddr (savestr, str); else str = formataddr (savestr, str); break; case FT_CONCATADDR: /* The same as formataddr, but doesn't do duplicate suppression */ if (callbacks && callbacks->concataddr) str = callbacks->concataddr (savestr, str); else str = concataddr (savestr, str); break; case FT_PUTADDR: /* output the str register as an address component, * splitting it into multiple lines if necessary. The * value reg. contains the max line length. The lit. * field may contain a string to prepend to the result * (e.g., "To: ") */ { char *lp, *lastb; int indent, wid, len; lp = str; wid = value; len = str ? strlen (str) : 0; sp = fmt->f_text; indent = strlen (sp); wid -= indent; if (wid <= 0) { adios(NULL, "putaddr -- num register (%d) must be greater " "than label width (%d)", value, indent); } while ((c = *sp++) && charstring_chars (scanlp) < max) { charstring_push_back (scanlp, c); } while (len > wid) { /* try to break at a comma; failing that, break at a * space. */ lastb = 0; sp = lp + wid; while (sp > lp && (c = (unsigned char) *--sp) != ',') { if (! lastb && isspace(c)) lastb = sp - 1; } if (sp == lp) { if (! (sp = lastb)) { sp = lp + wid - 1; while (*sp && *sp != ',' && !isspace((unsigned char) *sp)) sp++; if (*sp != ',') sp--; } } len -= sp - lp + 1; while (lp <= sp && charstring_chars (scanlp) < max) { charstring_push_back (scanlp, *lp++); } while (isspace((unsigned char) *lp)) lp++, len--; if (*lp) { if (charstring_chars (scanlp) < max) { charstring_push_back (scanlp, '\n'); } for (i=indent; charstring_chars (scanlp) < max && i > 0; i--) charstring_push_back (scanlp, ' '); } } cpstripped (scanlp, max - charstring_chars (scanlp), lp); } break; case FT_PARSEADDR: comp = fmt->f_comp; if (comp->c_flags & CF_PARSED) break; if (comp->c_mn != &fmt_mnull) mnfree (comp->c_mn); if ((sp = comp->c_text) && (sp = getname(sp)) && (mn = getm (sp, NULL, 0, NULL, 0))) { comp->c_mn = mn; while (getname("")) ; comp->c_flags |= CF_PARSED; } else { while (getname("")) /* XXX */ ; comp->c_mn = &fmt_mnull; } break; case FT_MYMBOX: case FT_GETMYMBOX: case FT_GETMYADDR: /* * if there's no component, we say true. Otherwise we * say "true" only if we can parse the address and it * matches one of our addresses. */ comp = fmt->f_comp; if (comp->c_mn != &fmt_mnull) mnfree (comp->c_mn); if ((sp = comp->c_text) && (sp = getname(sp)) && (mn = getm (sp, NULL, 0, NULL, 0))) { comp->c_mn = mn; if (ismymbox(mn)) { comp->c_flags |= CF_TRUE; /* Set str for use with FT_GETMYMBOX. With FT_GETMYADDR, comp->c_mn will be run through FT_LS_ADDR, which will strip off any pers name. */ str = mn->m_text; } else { comp->c_flags &= ~CF_TRUE; } while ((sp = getname(sp))) if ((comp->c_flags & CF_TRUE) == 0 && (mn = getm (sp, NULL, 0, NULL, 0))) if (ismymbox(mn)) { comp->c_flags |= CF_TRUE; /* Set str and comp->c_text for use with FT_GETMYMBOX. With FT_GETMYADDR, comp->c_mn will be run through FT_LS_ADDR, which will strip off any pers name. */ /* NB: We remove the call to free() here because it interferes with the buffer management in scansbr.c. Revisit this when we clean up memory handling */ /* free (comp->c_text); */ comp->c_text = str = strdup (mn->m_text); comp->c_mn = mn; } comp->c_flags |= CF_PARSED; } else { while (getname("")) /* XXX */ ; if (comp->c_text == 0) comp->c_flags |= CF_TRUE; else { comp->c_flags &= ~CF_TRUE; } comp->c_mn = &fmt_mnull; } if ((comp->c_flags & CF_TRUE) == 0 && (fmt->f_type == FT_GETMYMBOX || fmt->f_type == FT_GETMYADDR)) { /* Fool FT_LS_ADDR into not producing an address. */ comp->c_mn = &fmt_mnull; comp->c_text = NULL; } break; } /* * Call our tracing callback function, if one was supplied */ if (callbacks && callbacks->trace_func) callbacks->trace_func(callbacks->trace_context, fmt, value, str, charstring_buffer (scanlp)); fmt++; } /* Emit any trailing sequences of zero display length. */ while (fmt->f_type != FT_DONE) { if (fmt->f_type == FT_LS_LIT) { str = fmt->f_text; if (callbacks && callbacks->trace_func) callbacks->trace_func(callbacks->trace_context, fmt, value, str, charstring_buffer (scanlp)); } else if (fmt->f_type == FT_STRLITZ) { /* Don't want to emit part of an escape sequence. So if there isn't enough room in the buffer for the entire string, skip it completely. Need room for null terminator, and maybe trailing newline (added below). */ if (str) { for (sp = str; *sp; ++sp) { charstring_push_back (scanlp, *sp); } } if (callbacks && callbacks->trace_func) callbacks->trace_func(callbacks->trace_context, fmt, value, str, charstring_buffer (scanlp)); } fmt++; } finished: if (charstring_bytes (scanlp) > 0) { /* * Append a newline if the last character wasn't. */ #ifdef MULTIBYTE_SUPPORT /* * It's a little tricky because the last byte might be part of * a multibyte character, in which case we assume that wasn't * a newline. */ size_t last_char_len = charstring_last_char_len (scanlp); #else /* ! MULTIBYTE_SUPPORT */ size_t last_char_len = 1; #endif /* ! MULTIBYTE_SUPPORT */ if (last_char_len > 1 || charstring_buffer (scanlp)[charstring_bytes (scanlp) - 1] != '\n') { charstring_push_back (scanlp, '\n'); } } return (NULL); } nmh-1.7.1-RC3/sbr/folder_addmsg.c000644 007761 000024 00000013044 13243042053 016504 0ustar00kenhstaff000000 000000 /* folder_addmsg.c -- Link message into folder * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include /* * Link message into a folder. Return the new number * of the message. If an error occurs, return -1. */ int folder_addmsg (struct msgs **mpp, char *msgfile, int selected, int unseen, int preserve, int deleting, char *from_dir) { int infd, outfd, linkerr, msgnum; char *nmsg, newmsg[BUFSIZ]; char oldmsg[BUFSIZ]; struct msgs *mp; struct stat st1, st2; mp = *mpp; /* should we preserve the numbering of the message? */ if (preserve && (msgnum = m_atoi (msgfile)) > 0) { ; } else if (mp->nummsg == 0) { /* check if we are adding to empty folder */ msgnum = 1; } else { /* else use highest message number + 1 */ msgnum = mp->hghmsg + 1; } /* * We might need to make several attempts * in order to add the message to the folder. */ for (;; msgnum++) { /* * See if we need more space. If we need space at the * end, then we allocate space for an addition 100 messages. * If we need space at the beginning of the range, then just * extend message status range to cover this message number. */ if (msgnum > mp->hghoff) { if (!(mp = folder_realloc (mp, mp->lowoff, msgnum + 100))) { inform("unable to allocate folder storage"); return -1; } *mpp = mp; } else if (msgnum < mp->lowoff) { if (!(mp = folder_realloc (mp, msgnum, mp->hghoff))) { inform("unable to allocate folder storage"); return -1; } *mpp = mp; } /* * If a message is already in that slot, * then loop to next available slot. */ if (does_exist (mp, msgnum)) continue; /* setup the bit flags for this message */ clear_msg_flags (mp, msgnum); set_exists (mp, msgnum); /* should we set the SELECT_UNSEEN bit? */ if (unseen) { set_unseen (mp, msgnum); } /* should we set the SELECTED bit? */ if (selected) { set_selected (mp, msgnum); /* check if highest or lowest selected */ if (mp->numsel == 0) { mp->lowsel = msgnum; mp->hghsel = msgnum; } else { if (msgnum < mp->lowsel) mp->lowsel = msgnum; if (msgnum > mp->hghsel) mp->hghsel = msgnum; } /* increment number selected */ mp->numsel++; } /* * check if this is highest or lowest message */ if (mp->nummsg == 0) { mp->lowmsg = msgnum; mp->hghmsg = msgnum; } else { if (msgnum < mp->lowmsg) mp->lowmsg = msgnum; if (msgnum > mp->hghmsg) mp->hghmsg = msgnum; } /* increment message count */ mp->nummsg++; nmsg = m_name (msgnum); snprintf (newmsg, sizeof(newmsg), "%s/%s", mp->foldpath, nmsg); /* * Now try to link message into folder. * Then run the external hook on the message if one was specified in the context. * Run the refile hook if we're moving the message from one place to another. * We have to construct the from path name for this because it's not there. * Run the add hook if the message is getting copied or linked somewhere else. */ if (link (msgfile, newmsg) != -1) { if (deleting) { (void)snprintf(oldmsg, sizeof (oldmsg), "%s/%s", from_dir, msgfile); (void)ext_hook("ref-hook", oldmsg, newmsg); } else (void)ext_hook("add-hook", newmsg, NULL); return msgnum; } linkerr = errno; #ifdef EISREMOTE if (linkerr == EISREMOTE) linkerr = EXDEV; #endif /* EISREMOTE */ /* * Check if the file in our desired location is the same * as the source file. If so, then just leave it alone * and return. Otherwise, we will continue the main loop * and try again at another slot (hghmsg+1). */ if (linkerr == EEXIST) { if (stat (msgfile, &st2) == 0 && stat (newmsg, &st1) == 0 && st2.st_ino == st1.st_ino) { return msgnum; } continue; } /* * If link failed because we are trying to link * across devices, then check if there is a message * already in the desired location. If so, then return * error, else just copy the message. * Cygwin with FAT32 filesystem produces EPERM. */ if (linkerr == EXDEV || linkerr == EPERM) { if (stat (newmsg, &st1) == 0) { inform("message %s:%s already exists", mp->foldpath, newmsg); return -1; } if ((infd = open (msgfile, O_RDONLY)) == -1) { advise (msgfile, "unable to open message %s", msgfile); return -1; } fstat (infd, &st1); if ((outfd = creat (newmsg, (int) st1.st_mode & 0777)) == -1) { advise (newmsg, "unable to create"); close (infd); return -1; } cpydata (infd, outfd, msgfile, newmsg); close (infd); close (outfd); if (deleting) { (void)snprintf(oldmsg, sizeof (oldmsg), "%s/%s", from_dir, msgfile); (void)ext_hook("ref-hook", oldmsg, newmsg); } else (void)ext_hook("add-hook", newmsg, NULL); return msgnum; } /* * Else, some other type of link error, * so just return error. */ advise (newmsg, "error linking %s to", msgfile); return -1; } } nmh-1.7.1-RC3/sbr/folder_delmsgs.c000644 007761 000024 00000007147 13243042053 016712 0ustar00kenhstaff000000 000000 /* folder_delmsgs.c -- "remove" SELECTED messages from a folder * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include "m_mktemp.h" /* * 1) If we are using an external rmmproc, then exec it. * 2) Else if unlink_msgs is non-zero, then unlink the * SELECTED messages. * 3) Else rename SELECTED messages by prefixing name * with a standard prefix. * * If there is an error, return -1, else return 0. */ int folder_delmsgs (struct msgs *mp, int unlink_msgs, int nohook) { pid_t pid; int msgnum, vecp, retval = 0; char buf[100], *dp, **vec, *prog; char msgpath[BUFSIZ]; /* * If "rmmproc" is defined, exec it to remove messages. */ if (rmmproc) { /* Unset the EXISTS flag for each message to be removed */ for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { if (is_selected (mp, msgnum)) unset_exists (mp, msgnum); } /* Mark that the sequence information has changed */ mp->msgflags |= SEQMOD; /* * Write out the sequence and context files; this will release * any locks before the rmmproc is called. */ seq_save (mp); context_save (); 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 = mh_xrealloc(vec, (mp->numsel + vecp + 1) * sizeof *vec); for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { if (is_selected (mp, msgnum) && !(vec[vecp++] = strdup (m_name (msgnum)))) adios (NULL, "strdup failed"); } vec[vecp] = NULL; fflush (stdout); switch (pid = fork()) { case -1: advise ("fork", "unable to"); return -1; case 0: execvp (prog, vec); fprintf (stderr, "unable to exec "); perror (rmmproc); _exit (-1); default: arglist_free(prog, vec); return (pidwait (pid, -1)); } } /* * Either unlink or rename the SELECTED messages */ for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { if (is_selected (mp, msgnum)) { /* unselect message */ unset_selected (mp, msgnum); mp->numsel--; /* * Run the external hook on the message if one was specified in the context. * All we have is the message number; we have changed to the directory * containing the message. So, we need to extract that directory to form * the complete path. Note that the caller knows the directory, but has * no way of passing that to us. */ if (!nohook) { (void)snprintf(msgpath, sizeof (msgpath), "%s/%d", mp->foldpath, msgnum); (void)ext_hook("del-hook", msgpath, NULL); } dp = m_name (msgnum); if (unlink_msgs) { /* just unlink the messages */ if (m_unlink (dp) == -1) { admonish (dp, "unable to unlink"); retval = -1; continue; } } else { /* or rename messages with standard prefix */ strncpy (buf, m_backup (dp), sizeof(buf)); if (rename (dp, buf) == -1) { admonish (buf, "unable to rename %s to", dp); retval = -1; continue; } } /* If removal was successful, decrement message count */ unset_exists (mp, msgnum); mp->nummsg--; } } /* Sanity check */ if (mp->numsel != 0) adios (NULL, "oops, mp->numsel should be 0"); /* Mark that the sequence information has changed */ mp->msgflags |= SEQMOD; /* * Write out sequence and context files */ seq_save (mp); context_save (); return retval; } nmh-1.7.1-RC3/sbr/folder_free.c000644 007761 000024 00000001654 13243042053 016172 0ustar00kenhstaff000000 000000 /* folder_free.c -- free a folder/message structure * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include "lock_file.h" void folder_free (struct msgs *mp) { size_t i; struct bvector *v; if (!mp) return; mh_xfree(mp->foldpath); /* free the sequence names */ for (i = 0; i < svector_size (mp->msgattrs); i++) free (svector_at (mp->msgattrs, i)); svector_free (mp->msgattrs); for (i = 0, v = mp->msgstats; i < mp->num_msgstats; ++i, ++v) { bvector_fini(v); } free (mp->msgstats); /* Close/free the sequence file if it is open */ if (mp->seqhandle) lkfclosedata (mp->seqhandle, mp->seqname); mh_xfree(mp->seqname); bvector_free (mp->attrstats); free (mp); /* free main folder structure */ } nmh-1.7.1-RC3/sbr/folder_pack.c000644 007761 000024 00000004544 13243042053 016170 0ustar00kenhstaff000000 000000 /* folder_pack.c -- pack (renumber) the messages in a folder * -- into a contiguous range from 1 to n. * * 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 /* * Pack the message in a folder. * Return -1 if error, else return 0. */ int folder_pack (struct msgs **mpp, int verbose) { int hole, msgnum, newcurrent = 0; char newmsg[BUFSIZ], oldmsg[BUFSIZ]; struct msgs *mp; mp = *mpp; /* * Just return if folder is empty. */ if (mp->nummsg == 0) return 0; /* * Make sure we have message status space allocated * for all numbers from 1 to current high message. */ if (mp->lowoff > 1) { if ((mp = folder_realloc (mp, 1, mp->hghmsg))) *mpp = mp; else { inform("unable to allocate folder storage"); return -1; } } for (msgnum = mp->lowmsg, hole = 1; msgnum <= mp->hghmsg; msgnum++) { if (does_exist (mp, msgnum)) { if (msgnum != hole) { strncpy (newmsg, m_name (hole), sizeof(newmsg)); strncpy (oldmsg, m_name (msgnum), sizeof(oldmsg)); if (verbose) printf ("message %s becomes %s\n", oldmsg, newmsg); /* * Invoke the external refile hook for each message being renamed. * This is done before the file is renamed so that the old message * file is around for the hook. */ (void)snprintf(oldmsg, sizeof (oldmsg), "%s/%d", mp->foldpath, msgnum); (void)snprintf(newmsg, sizeof (newmsg), "%s/%d", mp->foldpath, hole); ext_hook("ref-hook", oldmsg, newmsg); /* move the message file */ if (rename (oldmsg, newmsg) == -1) { advise (newmsg, "unable to rename %s to", oldmsg); return -1; } /* check if this is the current message */ if (msgnum == mp->curmsg) newcurrent = hole; /* copy the attribute flags for this message */ copy_msg_flags (mp, hole, msgnum); if (msgnum == mp->lowsel) mp->lowsel = hole; if (msgnum == mp->hghsel) mp->hghsel = hole; /* mark that sequence information has been modified */ mp->msgflags |= SEQMOD; } hole++; } } /* record the new number for the high/low message */ mp->lowmsg = 1; mp->hghmsg = hole - 1; /* update the "cur" sequence */ if (newcurrent != 0) seq_setcur (mp, newcurrent); return 0; } nmh-1.7.1-RC3/sbr/folder_read.c000644 007761 000024 00000010227 13243042053 016160 0ustar00kenhstaff000000 000000 /* folder_read.c -- initialize folder structure and read folder * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include "m_maildir.h" /* We allocate the `mi' array 1024 elements at a time */ #define NUMMSGS 1024 /* * 1) Create the folder/message structure * 2) Read the directory (folder) and temporarily * record the numbers of the messages we have seen. * 3) Then allocate the array for message attributes and * set the initial flags for all messages we've seen. * 4) Read and initialize the sequence information. */ struct msgs * folder_read (char *name, int lockflag) { int msgnum, len, *mi; struct msgs *mp; struct dirent *dp; DIR *dd; struct bvector *v; size_t i; name = m_mailpath (name); if (!(dd = opendir (name))) { free (name); return NULL; } /* Allocate the main structure for folder information */ NEW(mp); clear_folder_flags (mp); mp->foldpath = name; mp->lowmsg = 0; mp->hghmsg = 0; mp->curmsg = 0; mp->lowsel = 0; mp->hghsel = 0; mp->numsel = 0; mp->nummsg = 0; mp->seqhandle = NULL; mp->seqname = NULL; if (access (name, W_OK) == -1) set_readonly (mp); /* * Allocate a temporary place to record the * name of the messages in this folder. */ len = NUMMSGS; mi = (int *) mh_xmalloc ((size_t) (len * sizeof(*mi))); while ((dp = readdir (dd))) { if ((msgnum = m_atoi (dp->d_name)) && msgnum > 0) { /* * Check if we need to allocate more * temporary elements for message names. */ if (mp->nummsg >= len) { len += NUMMSGS; mi = (int *) mh_xrealloc (mi, (size_t) (len * sizeof(*mi))); } /* Check if this is the first message we've seen */ if (mp->nummsg == 0) { mp->lowmsg = msgnum; mp->hghmsg = msgnum; } else { /* Check if this is it the highest or lowest we've seen? */ if (msgnum < mp->lowmsg) mp->lowmsg = msgnum; if (msgnum > mp->hghmsg) mp->hghmsg = msgnum; } /* * Now increment count, and record message * number in a temporary place for now. */ mi[mp->nummsg++] = msgnum; } else { switch (dp->d_name[0]) { case '.': case ',': continue; default: /* skip any files beginning with backup prefix */ if (has_prefix(dp->d_name, BACKUP_PREFIX)) continue; /* skip the LINK file */ if (!strcmp (dp->d_name, LINK)) continue; /* indicate that there are other files in folder */ set_other_files (mp); continue; } } } closedir (dd); mp->lowoff = max (mp->lowmsg, 1); /* Go ahead and allocate space for 100 additional messages. */ mp->hghoff = mp->hghmsg + 100; /* for testing, allocate minimal necessary space */ /* mp->hghoff = max (mp->hghmsg, 1); */ /* * If for some reason hghoff < lowoff (like we got an integer overflow) * the complain about this now. */ if (mp->hghoff < mp->lowoff) { adios(NULL, "Internal failure: high message limit < low message " "limit; possible overflow?"); } /* * Allocate space for status of each message. */ mp->num_msgstats = MSGSTATNUM (mp->lowoff, mp->hghoff); mp->msgstats = mh_xmalloc (MSGSTATSIZE(mp)); for (i = 0, v = mp->msgstats; i < mp->num_msgstats; ++i, ++v) { bvector_init(v); } mp->msgattrs = svector_create (0); /* * Scan through the array of messages we've seen and * setup the initial flags for those messages in the * newly allocated mp->msgstats area. */ for (msgnum = 0; msgnum < mp->nummsg; msgnum++) set_exists (mp, mi[msgnum]); free (mi); /* We don't need this anymore */ /* * Read and initialize the sequence information. */ if (seq_read (mp, lockflag) == NOTOK) { char seqfile[PATH_MAX]; /* Failed to lock sequence file. */ snprintf (seqfile, sizeof(seqfile), "%s/%s", mp->foldpath, mh_seq); advise (seqfile, "failed to lock"); return NULL; } return mp; } nmh-1.7.1-RC3/sbr/folder_realloc.c000644 007761 000024 00000003325 13243042053 016667 0ustar00kenhstaff000000 000000 /* folder_realloc.c -- realloc a folder/msgs structure * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include /* * Reallocate some of the space in the folder * structure (currently just message status array). * * Return pointer to new folder structure. * If error, return NULL. */ struct msgs * folder_realloc (struct msgs *mp, int lo, int hi) { struct bvector *tmpstats, *t; size_t i; int msgnum; /* sanity checks */ if (lo < 1) adios (NULL, "BUG: called folder_realloc with lo (%d) < 1", lo); if (hi < 1) adios (NULL, "BUG: called folder_realloc with hi (%d) < 1", hi); if (mp->nummsg > 0 && lo > mp->lowmsg) adios (NULL, "BUG: called folder_realloc with lo (%d) > mp->lowmsg (%d)", lo, mp->lowmsg); if (mp->nummsg > 0 && hi < mp->hghmsg) adios (NULL, "BUG: called folder_realloc with hi (%d) < mp->hghmsg (%d)", hi, mp->hghmsg); /* Check if we really need to reallocate anything */ if (lo == mp->lowoff && hi == mp->hghoff) return mp; /* first allocate the new message status space */ mp->num_msgstats = MSGSTATNUM (lo, hi); tmpstats = mh_xmalloc (MSGSTATSIZE(mp)); for (i = 0, t = tmpstats; i < mp->num_msgstats; ++i, ++t) { bvector_init(t); } /* then copy messages status array with shift */ if (mp->nummsg > 0) { for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg; msgnum++) bvector_copy (tmpstats + msgnum - lo, msgstat (mp, msgnum)); } free(mp->msgstats); mp->msgstats = tmpstats; mp->lowoff = lo; mp->hghoff = hi; return mp; } nmh-1.7.1-RC3/sbr/getarguments.c000644 007761 000024 00000002161 13243042053 016415 0ustar00kenhstaff000000 000000 /* getarguments.c -- Get the argument vector ready to go. * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include char ** getarguments (char *invo_name, int argc, char **argv, int check_context) { char *cp = NULL, **ap = NULL, **bp = NULL, **arguments = NULL; int n = 0; /* * Check if profile/context specifies any arguments */ if (check_context && (cp = context_find (invo_name))) { cp = mh_xstrdup(cp); /* make copy */ ap = brkstring (cp, " ", "\n"); /* split string */ /* Count number of arguments split */ bp = ap; while (*bp++) n++; } arguments = (char **) mh_xmalloc ((argc + n) * sizeof(*arguments)); bp = arguments; /* Copy any arguments from profile/context */ if (ap != NULL && n > 0) { while (*ap) *bp++ = *ap++; } /* Copy arguments from command line */ argv++; while (*argv) *bp++ = *argv++; /* Now NULL terminate the array */ *bp = NULL; return arguments; } nmh-1.7.1-RC3/sbr/getcpy.c000644 007761 000024 00000001137 13243042053 015205 0ustar00kenhstaff000000 000000 /* getcpy.c -- copy a string in managed memory * * THIS IS OBSOLETE. NEED TO REPLACE ALL OCCURRENCES * OF GETCPY WITH STRDUP. BUT THIS WILL REQUIRE * CHANGING PARTS OF THE CODE TO DEAL WITH NULL VALUES. * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include /* Return malloc'd copy of str, or of "" if NULL, exit on failure. */ char *getcpy(const char *str) { if (str) return mh_xstrdup(str); return mh_xcalloc(1, 1); } nmh-1.7.1-RC3/sbr/geteditor.c000644 007761 000024 00000001112 13243042053 015671 0ustar00kenhstaff000000 000000 /* 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 #include 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); } nmh-1.7.1-RC3/sbr/getfolder.c000644 007761 000024 00000001265 13243042053 015667 0ustar00kenhstaff000000 000000 /* getfolder.c -- get the current or default folder * * 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 char * getfolder(int wantcurrent) { char *folder; /* * If wantcurrent == 1, then try the current folder first */ if (wantcurrent && (folder = context_find (pfolder)) && *folder != '\0') return folder; /* * Else try the Inbox profile entry */ if ((folder = context_find (inbox)) && *folder != '\0') return folder; /* * Else return compile time default. */ return defaultfolder; } nmh-1.7.1-RC3/sbr/getline.c000644 007761 000024 00000003762 13243042053 015347 0ustar00kenhstaff000000 000000 /* getline.c -- replacement getline() implementation * * This code is Copyright (c) 2016, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include /* Largest possible size of buffer that allows SSIZE_MAX to be returned * to indicate SSIZE_MAX - 1 characters read before the '\n'. The * additional 1 is for the terminating NUL. */ #define MAX_AVAIL ((size_t)SSIZE_MAX + 1) /* Ideal increase in size of line buffer. */ #define GROWTH 128 ssize_t getline(char **lineptr, size_t *n, FILE *stream) { char *l; size_t avail; size_t used; int c; bool last; if (!lineptr || !n) { errno = EINVAL; return -1; } l = *lineptr; if (l) avail = *n <= MAX_AVAIL ? *n : MAX_AVAIL; else avail = *n = 0; /* POSIX allows *lineptr = NULL, *n = 42. */ used = 0; last = false; for (;;) { c = getc(stream); if (c == EOF) { if (ferror(stream) || /* errno set by stdlib. */ !used) /* EOF with nothing read. */ return -1; /* Line will be returned without a \n terminator. */ append_nul: c = '\0'; last = true; } if (used == avail) { size_t want; char *new; if (avail == MAX_AVAIL) { errno = EOVERFLOW; return -1; } want = avail + GROWTH; if (want > MAX_AVAIL) want = MAX_AVAIL; new = realloc(l, want); if (!new) return -1; /* errno set by stdlib. */ l = *lineptr = new; avail = *n = want; } l[used++] = c; if (last) return used - 1; /* Don't include NUL. */ if (c == '\n') goto append_nul; /* Final half loop. */ } } nmh-1.7.1-RC3/sbr/getpass.c000644 007761 000024 00000006310 13243042053 015356 0ustar00kenhstaff000000 000000 /* getpass.c -- read a password without echo. * * Portions of this code are Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include /* We don't use MAX_PASS here because the maximum password length on a remote POP daemon will have nothing to do with the length on our OS. 256 is arbitrary but hopefully big enough to accommodate everyone. */ #define MAX_PASSWORD_LEN 256 #ifndef TCSANOW #define TCSANOW 0 #endif char * nmh_getpass(const char *prompt) { struct termios oterm, term; int ch; char *p; FILE *fout, *fin; static char buf[MAX_PASSWORD_LEN + 1]; int istty = isatty(fileno(stdin)); /* Find if stdin is connect to a terminal. If so, read directly from * the terminal, and turn off echo. Otherwise read from stdin. */ if (!istty || !(fout = fin = fopen("/dev/tty", "w+"))) { fout = stderr; fin = stdin; } else /* Reading directly from terminal here */ { (void)tcgetattr(fileno(fin), &oterm); term = oterm; /* Save original info */ term.c_lflag &= ~ECHO; (void)fputs(prompt, fout); rewind(fout); /* implied flush */ (void)tcsetattr(fileno(fin), TCSANOW, &term); } for (p = buf; (ch = getc(fin)) != EOF && ch != '\n' && p < buf + MAX_PASSWORD_LEN;) *p++ = ch; *p = '\0'; if (istty) { (void)tcsetattr(fileno(fin), TCSANOW, &oterm); rewind(fout); (void)fputc('\n', fout); (void)fclose(fin); } return buf; } nmh-1.7.1-RC3/sbr/icalendar.c000644 007761 000024 00000172717 13243042114 015647 0ustar00kenhstaff000000 000000 #line 2 "sbr/icalendar.c" #line 4 "sbr/icalendar.c" #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ #define yy_create_buffer ical_create_buffer #define yy_delete_buffer ical_delete_buffer #define yy_flex_debug ical_flex_debug #define yy_init_buffer ical_init_buffer #define yy_flush_buffer ical_flush_buffer #define yy_load_buffer_state ical_load_buffer_state #define yy_switch_to_buffer ical_switch_to_buffer #define yyin icalin #define yyleng icalleng #define yylex icallex #define yylineno icallineno #define yyout icalout #define yyrestart icalrestart #define yytext icaltext #define yywrap icalwrap #define yyalloc icalalloc #define yyrealloc icalrealloc #define yyfree icalfree #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 6 #define YY_FLEX_SUBMINOR_VERSION 0 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ #include #include #include #include /* end standard C headers. */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #endif /* ! C99 */ #endif /* ! FLEXINT_H */ #ifdef __cplusplus /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ /* C99 requires __STDC__ to be defined as 1. */ #if defined (__STDC__) #define YY_USE_CONST #endif /* defined (__STDC__) */ #endif /* ! __cplusplus */ #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN (yy_start) = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START (((yy_start) - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE icalrestart(icalin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k. * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. * Ditto for the __ia64__ case accordingly. */ #define YY_BUF_SIZE 32768 #else #define YY_BUF_SIZE 16384 #endif /* __ia64__ */ #endif /* The state buf must be large enough to hold one state per character in the main buffer. */ #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef size_t yy_size_t; #endif extern yy_size_t icalleng; extern FILE *icalin, *icalout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 #define YY_LESS_LINENO(n) #define YY_LINENO_REWIND_TO(ptr) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up icaltext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = (yy_hold_char); \ YY_RESTORE_YY_MORE_OFFSET \ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up icaltext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, (yytext_ptr) ) #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ yy_size_t yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via icalrestart()), so that the user can continue scanning by * just pointing icalin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ /* Stack of input buffers. */ static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ : NULL) /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] /* yy_hold_char holds the character lost when icaltext is formed. */ static char yy_hold_char; static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */ yy_size_t icalleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; static int yy_init = 0; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow icalwrap()'s to do buffer switches * instead of setting up a fresh icalin. A bit of a hack ... */ static int yy_did_buffer_switch_on_eof; void icalrestart (FILE *input_file ); void ical_switch_to_buffer (YY_BUFFER_STATE new_buffer ); YY_BUFFER_STATE ical_create_buffer (FILE *file,int size ); void ical_delete_buffer (YY_BUFFER_STATE b ); void ical_flush_buffer (YY_BUFFER_STATE b ); void icalpush_buffer_state (YY_BUFFER_STATE new_buffer ); void icalpop_buffer_state (void ); static void icalensure_buffer_stack (void ); static void ical_load_buffer_state (void ); static void ical_init_buffer (YY_BUFFER_STATE b,FILE *file ); #define YY_FLUSH_BUFFER ical_flush_buffer(YY_CURRENT_BUFFER ) YY_BUFFER_STATE ical_scan_buffer (char *base,yy_size_t size ); YY_BUFFER_STATE ical_scan_string (yyconst char *yy_str ); YY_BUFFER_STATE ical_scan_bytes (yyconst char *bytes,yy_size_t len ); void *icalalloc (yy_size_t ); void *icalrealloc (void *,yy_size_t ); void icalfree (void * ); #define yy_new_buffer ical_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ icalensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ ical_create_buffer(icalin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ icalensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ ical_create_buffer(icalin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* Begin user sect3 */ #define icalwrap() (/*CONSTCOND*/1) #define YY_SKIP_YYWRAP typedef unsigned char YY_CHAR; FILE *icalin = (FILE *) 0, *icalout = (FILE *) 0; typedef int yy_state_type; extern int icallineno; int icallineno = 1; extern char *icaltext; #ifdef yytext_ptr #undef yytext_ptr #endif #define yytext_ptr icaltext static yy_state_type yy_get_previous_state (void ); static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); static int yy_get_next_buffer (void ); #if defined(__GNUC__) && __GNUC__ >= 3 __attribute__((__noreturn__)) #endif static void yy_fatal_error (yyconst char msg[] ); /* Done after the current pattern has been matched and before the * corresponding action - sets up icaltext. */ #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ icalleng = (size_t) (yy_cp - yy_bp); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; #define YY_NUM_RULES 17 #define YY_END_OF_BUFFER 18 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info { flex_int32_t yy_verify; flex_int32_t yy_nxt; }; static yyconst flex_int16_t yy_accept[125] = { 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, 0, 0, 12, 12, 12, 12, 18, 16, 1, 16, 3, 3, 17, 13, 4, 7, 6, 15, 16, 16, 14, 16, 9, 9, 10, 12, 17, 16, 16, 16, 1, 0, 0, 0, 3, 3, 6, 0, 0, 0, 5, 15, 0, 6, 14, 0, 0, 0, 9, 9, 12, 0, 0, 0, 11, 0, 0, 0, 12, 0, 12, 0, 3, 3, 5, 0, 6, 0, 9, 9, 11, 0, 0, 0, 12, 2, 3, 5, 6, 8, 9, 11, 0, 11, 0, 0, 12, 3, 5, 6, 9, 11, 0, 0, 12, 3, 3, 5, 6, 9, 9, 11, 0, 0, 12, 5, 11, 0, 0, 5, 11, 0, 0, 0 } ; static yyconst YY_CHAR yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 8, 9, 6, 6, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 12, 6, 13, 6, 6, 6, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 14, 14, 6, 6, 6, 6, 6, 6, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 6, 6, 6, 6, 1, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst YY_CHAR yy_meta[17] = { 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 } ; static yyconst flex_uint16_t yy_base[131] = { 0, 0, 13, 26, 0, 38, 54, 2, 4, 68, 0, 8, 17, 83, 0, 0, 0, 136, 406, 9, 132, 97, 125, 406, 406, 406, 406, 110, 125, 130, 109, 15, 121, 128, 114, 406, 142, 157, 119, 160, 105, 21, 117, 175, 116, 0, 178, 191, 28, 115, 101, 205, 0, 113, 99, 32, 107, 220, 106, 0, 223, 0, 0, 105, 89, 237, 251, 266, 101, 406, 87, 86, 269, 275, 281, 294, 65, 64, 308, 314, 320, 0, 63, 333, 60, 59, 0, 340, 58, 57, 0, 346, 56, 359, 406, 53, 52, 51, 373, 50, 49, 386, 48, 47, 46, 45, 0, 0, 44, 43, 0, 0, 40, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 406, 401, 403, 38, 31, 24, 0 } ; static yyconst flex_int16_t yy_def[131] = { 0, 125, 125, 125, 3, 126, 126, 125, 125, 125, 9, 125, 125, 124, 13, 13, 13, 124, 124, 124, 124, 124, 21, 124, 124, 124, 124, 127, 124, 124, 124, 124, 124, 124, 33, 124, 124, 124, 124, 128, 124, 124, 124, 124, 124, 21, 124, 127, 28, 124, 124, 129, 28, 124, 47, 124, 124, 124, 124, 33, 124, 36, 37, 124, 124, 124, 128, 124, 124, 124, 124, 36, 124, 46, 46, 129, 124, 47, 124, 60, 60, 65, 124, 130, 66, 36, 72, 46, 75, 47, 78, 60, 65, 130, 124, 124, 66, 36, 124, 75, 47, 124, 65, 93, 66, 36, 73, 98, 75, 47, 79, 101, 65, 93, 66, 36, 75, 65, 93, 66, 75, 65, 93, 93, 0, 124, 124, 124, 124, 124, 124 } ; static yyconst flex_uint16_t yy_nxt[423] = { 0, 124, 93, 19, 20, 31, 32, 31, 32, 21, 21, 23, 41, 42, 21, 22, 19, 20, 55, 56, 23, 35, 21, 21, 41, 42, 75, 21, 22, 23, 35, 48, 49, 66, 24, 55, 56, 25, 26, 18, 47, 28, 29, 123, 123, 121, 120, 119, 122, 121, 120, 115, 119, 118, 30, 18, 117, 28, 29, 109, 116, 115, 114, 113, 112, 109, 108, 105, 104, 103, 30, 23, 102, 100, 99, 97, 96, 33, 33, 92, 89, 88, 33, 34, 18, 36, 37, 38, 36, 36, 39, 18, 36, 36, 18, 18, 36, 36, 36, 40, 43, 44, 85, 84, 67, 71, 45, 45, 62, 57, 55, 45, 45, 48, 49, 77, 52, 54, 48, 43, 41, 71, 62, 60, 55, 54, 50, 51, 52, 53, 51, 57, 58, 52, 46, 41, 124, 59, 59, 124, 124, 124, 59, 59, 61, 62, 63, 61, 61, 124, 124, 61, 61, 124, 124, 61, 61, 61, 64, 65, 62, 63, 65, 67, 68, 124, 124, 69, 124, 124, 124, 124, 124, 124, 124, 124, 70, 72, 43, 44, 72, 43, 44, 124, 124, 124, 124, 73, 74, 124, 124, 124, 74, 74, 48, 49, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 50, 48, 49, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 76, 78, 57, 58, 78, 57, 58, 124, 124, 124, 124, 79, 80, 124, 124, 124, 80, 80, 81, 62, 63, 81, 81, 124, 124, 81, 81, 124, 124, 81, 81, 81, 82, 67, 68, 124, 124, 69, 124, 124, 124, 124, 124, 124, 124, 124, 70, 83, 67, 68, 83, 43, 44, 124, 124, 124, 124, 86, 86, 124, 124, 124, 86, 86, 73, 124, 124, 124, 73, 73, 87, 124, 124, 124, 87, 87, 48, 49, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 76, 57, 58, 124, 124, 124, 124, 90, 90, 124, 124, 124, 90, 90, 79, 124, 124, 124, 79, 79, 91, 124, 124, 124, 91, 91, 67, 68, 124, 124, 94, 124, 124, 124, 124, 124, 124, 124, 124, 95, 98, 124, 124, 124, 98, 98, 101, 124, 124, 124, 101, 101, 124, 124, 124, 124, 94, 124, 124, 124, 124, 124, 124, 124, 124, 95, 43, 44, 124, 124, 124, 124, 106, 107, 124, 124, 124, 107, 107, 57, 58, 124, 124, 124, 124, 110, 111, 124, 124, 124, 111, 111, 18, 18, 27, 27, 17, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124 } ; static yyconst flex_int16_t yy_chk[423] = { 0, 0, 130, 1, 1, 7, 7, 8, 8, 1, 1, 11, 19, 19, 1, 1, 2, 2, 31, 31, 12, 11, 2, 2, 41, 41, 129, 2, 2, 3, 12, 48, 48, 128, 3, 55, 55, 3, 3, 5, 127, 5, 5, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113, 5, 6, 112, 6, 6, 109, 108, 105, 104, 103, 102, 100, 99, 97, 96, 95, 6, 9, 92, 89, 88, 85, 84, 9, 9, 82, 77, 76, 9, 9, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 21, 21, 71, 70, 68, 64, 21, 21, 63, 58, 56, 21, 21, 27, 27, 54, 53, 50, 49, 44, 42, 40, 38, 34, 32, 30, 27, 28, 28, 28, 28, 33, 33, 29, 22, 20, 17, 33, 33, 0, 0, 0, 33, 33, 36, 36, 36, 36, 36, 0, 0, 36, 36, 0, 0, 36, 36, 36, 36, 37, 37, 37, 37, 39, 39, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 39, 43, 43, 43, 43, 46, 46, 0, 0, 0, 0, 46, 46, 0, 0, 0, 46, 46, 47, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 51, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 57, 57, 57, 57, 60, 60, 0, 0, 0, 0, 60, 60, 0, 0, 0, 60, 60, 65, 65, 65, 65, 65, 0, 0, 65, 65, 0, 0, 65, 65, 65, 65, 66, 66, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 66, 67, 67, 67, 67, 72, 72, 0, 0, 0, 0, 72, 72, 0, 0, 0, 72, 72, 73, 0, 0, 0, 73, 73, 74, 0, 0, 0, 74, 74, 75, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 75, 78, 78, 0, 0, 0, 0, 78, 78, 0, 0, 0, 78, 78, 79, 0, 0, 0, 79, 79, 80, 0, 0, 0, 80, 80, 83, 83, 0, 0, 83, 0, 0, 0, 0, 0, 0, 0, 0, 83, 87, 0, 0, 0, 87, 87, 91, 0, 0, 0, 91, 91, 93, 93, 0, 0, 93, 0, 0, 0, 0, 0, 0, 0, 0, 93, 98, 98, 0, 0, 0, 0, 98, 98, 0, 0, 0, 98, 98, 101, 101, 0, 0, 0, 0, 101, 101, 0, 0, 0, 101, 101, 125, 125, 126, 126, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124 } ; static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; extern int ical_flex_debug; int ical_flex_debug = 0; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *icaltext; #line 1 "sbr/icalendar.l" /* icalendar.l -- icalendar (RFC 5545) scanner * * This code is Copyright (c) 2014, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ /* See porting notes at end of this file. */ #line 11 "sbr/icalendar.l" #include "h/mh.h" #include "h/icalendar.h" #include "sbr/icalparse.h" static char *unfold (char *, size_t *); static void destroy_icallex(void); /* * These flex options aren't used: * 8bit not needed * case-insensitive not needed * align not used because this isn't performance critical */ #define YY_NO_INPUT 1 /* * From RFC 5545 § 3.1. */ /* The following is a short-cut definition that admits more that the UNICODE characters permitted by RFC 5545. */ /* The following excludes HTAB, unlike {CTL}. */ /* Solaris lex requires that the , be escaped. */ /* * From RFC 5545 § 2.1. */ /* * From RFC 5545 § 3.3.11. */ /* * Core rules (definitions) from RFC 5234 Appendix B.1. */ /* Variance from RFC 5234: the {CR} is required in CRLF, but it is optional below to support Unix filesystem convention. */ /* * Our definitions. */ #line 664 "sbr/icalendar.c" #define INITIAL 0 #define s_name 1 #define s_colon 2 #define s_value 3 #define s_semicolon 4 #define s_param_name 5 #define s_equal 6 #define s_comma 7 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ #include #endif #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * #endif static int yy_init_globals (void ); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ int icallex_destroy (void ); int icalget_debug (void ); void icalset_debug (int debug_flag ); YY_EXTRA_TYPE icalget_extra (void ); void icalset_extra (YY_EXTRA_TYPE user_defined ); FILE *icalget_in (void ); void icalset_in (FILE * _in_str ); FILE *icalget_out (void ); void icalset_out (FILE * _out_str ); yy_size_t icalget_leng (void ); char *icalget_text (void ); int icalget_lineno (void ); void icalset_lineno (int _line_number ); /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int icalwrap (void ); #else extern int icalwrap (void ); #endif #endif #ifndef YY_NO_UNPUT static void yyunput (int c,char *buf_ptr ); #endif #ifndef yytext_ptr static void yy_flex_strncpy (char *,yyconst char *,int ); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * ); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void ); #else static int input (void ); #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #ifdef __ia64__ /* On IA-64, the buffer size is 16k, not 8k */ #define YY_READ_BUF_SIZE 16384 #else #define YY_READ_BUF_SIZE 8192 #endif /* __ia64__ */ #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO do { if (fwrite( icaltext, icalleng, 1, icalout )) {} } while (0) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ size_t n; \ for ( n = 0; n < max_size && \ (c = getc( icalin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( icalin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else \ { \ errno=0; \ while ( (result = fread(buf, 1, max_size, icalin))==0 && ferror(icalin)) \ { \ if( errno != EINTR) \ { \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ break; \ } \ errno=0; \ clearerr(icalin); \ } \ }\ \ #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif /* end tables serialization structures and prototypes */ /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 extern int icallex (void); #define YY_DECL int icallex (void) #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after icaltext and icalleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK /*LINTED*/break; #endif #define YY_RULE_SETUP \ YY_USER_ACTION /** The main scanner function which does all the work. */ YY_DECL { yy_state_type yy_current_state; char *yy_cp, *yy_bp; int yy_act; if ( !(yy_init) ) { (yy_init) = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! (yy_start) ) (yy_start) = 1; /* first start state */ if ( ! icalin ) icalin = stdin; if ( ! icalout ) icalout = stdout; if ( ! YY_CURRENT_BUFFER ) { icalensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = ical_create_buffer(icalin,YY_BUF_SIZE ); } ical_load_buffer_state( ); } { #line 100 "sbr/icalendar.l" #line 892 "sbr/icalendar.c" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { yy_cp = (yy_c_buf_p); /* Support of icaltext. */ *yy_cp = (yy_hold_char); /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = (yy_start); yy_match: do { YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 125 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } while ( yy_current_state != 124 ); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); yy_find_action: yy_act = yy_accept[yy_current_state]; YY_DO_BEFORE_ACTION; do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = (yy_hold_char); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); goto yy_find_action; case 1: /* rule 1 can match eol */ YY_RULE_SETUP #line 103 "sbr/icalendar.l" { /* Eat any leading newlines. */ } YY_BREAK case 2: /* rule 2 can match eol */ YY_RULE_SETUP #line 108 "sbr/icalendar.l" { /* flex 2.5.4 defines icalleng as an int instead of a size_t, so copy it. */ size_t len = icalleng; unfold (icaltext, &len); icalleng = len; icallval = strdup (icaltext); /* yy_push_state (s_name); * s_name */ BEGIN (s_name); /* s_name */ return ICAL_NAME; } YY_BREAK case 3: YY_RULE_SETUP #line 122 "sbr/icalendar.l" { icallval = strdup (icaltext); /* yy_push_state (s_name); * s_name */ BEGIN (s_name); /* s_name */ return ICAL_NAME; } YY_BREAK case 4: YY_RULE_SETUP #line 130 "sbr/icalendar.l" { /* Don't need to strdup a single character. */ icallval = icaltext; /* yy_pop_state (); * INITIAL */ /* yy_push_state (s_colon); * s_colon */ BEGIN (s_colon); /* s_colon */ return ICAL_COLON; } YY_BREAK case 5: /* rule 5 can match eol */ YY_RULE_SETUP #line 140 "sbr/icalendar.l" { /* flex 2.5.4 defines icalleng as an int instead of a size_t, so copy it. */ size_t len = icalleng; unfold (icaltext, &len); icalleng = len; icallval = strdup (icaltext); /* yy_pop_state (); * INITIAL */ /* yy_push_state (s_value); * s_value */ BEGIN (s_value); /* s_value */ return ICAL_VALUE; } YY_BREAK case 6: YY_RULE_SETUP #line 155 "sbr/icalendar.l" { icallval = strdup (icaltext); /* yy_pop_state (); * INITIAL */ /* yy_push_state (s_value); * s_value */ BEGIN (s_value); /* s_value */ return ICAL_VALUE; } YY_BREAK case 7: YY_RULE_SETUP #line 164 "sbr/icalendar.l" { /* Don't need to strdup a single character. */ icallval = icaltext; /* yy_push_state (s_semicolon); * s_name, s_semicolon */ BEGIN (s_semicolon); /* s_name, s_semicolon */ return ICAL_SEMICOLON; } YY_BREAK case 8: /* rule 8 can match eol */ YY_RULE_SETUP #line 173 "sbr/icalendar.l" { /* flex 2.5.4 defines icalleng as an int instead of a size_t, so copy it. */ size_t len = icalleng; unfold (icaltext, &len); icalleng = len; icallval = strdup (icaltext); /* yy_pop_state (); * s_name */ /* yy_push_state (s_param_name); * s_name, s_param_name */ BEGIN (s_param_name); /* s_name, s_param_name */ return ICAL_PARAM_NAME; } YY_BREAK case 9: YY_RULE_SETUP #line 188 "sbr/icalendar.l" { icallval = strdup (icaltext); /* yy_pop_state (); * s_name */ /* yy_push_state (s_param_name); * s_name, s_param_name */ BEGIN (s_param_name); /* s_name, s_param_name */ return ICAL_PARAM_NAME; } YY_BREAK case 10: YY_RULE_SETUP #line 197 "sbr/icalendar.l" { /* Don't need to strdup a single character. */ icallval = icaltext; /* yy_pop_state (); * s_name */ /* yy_push_state (s_equal); * s_name, s_equal */ BEGIN (s_equal); /* s_name, s_equal */ return ICAL_EQUAL; } YY_BREAK case 11: /* rule 11 can match eol */ YY_RULE_SETUP #line 207 "sbr/icalendar.l" { /* flex 2.5.4 defines icalleng as an int instead of a size_t, so copy it. */ size_t len = icalleng; unfold (icaltext, &len); icalleng = len; icallval = strdup (icaltext); /* yy_pop_state (); * s_name */ BEGIN (s_name); /* s_name */ return ICAL_PARAM_VALUE; } YY_BREAK case 12: YY_RULE_SETUP #line 221 "sbr/icalendar.l" { icallval = strdup (icaltext); /* yy_pop_state (); * s_name */ BEGIN (s_name); /* s_name */ return ICAL_PARAM_VALUE; } YY_BREAK case 13: YY_RULE_SETUP #line 229 "sbr/icalendar.l" { /* Don't need to strdup a single character. */ icallval = icaltext; /* yy_push_state (s_comma); * s_name, s_comma */ BEGIN (s_comma); /* s_name, s_comma */ return ICAL_COMMA; } YY_BREAK case 14: /* rule 14 can match eol */ YY_RULE_SETUP #line 238 "sbr/icalendar.l" { /* Use start condition to ensure that all newlines are where expected. */ icallval = icaltext; /* yy_pop_state (); * INITIAL */ BEGIN (INITIAL); /* INITIAL */ return ICAL_CRLF; } YY_BREAK case 15: /* rule 15 can match eol */ YY_RULE_SETUP #line 247 "sbr/icalendar.l" { /* Null value. */ icallval = strdup (""); /* yy_pop_state (); * INITIAL */ /* yy_push_state (s_value); * s_value */ BEGIN (s_value); /* s_value */ /* Push the newline back so it can be handled in the proper state. */ unput ('\n'); return ICAL_VALUE; } YY_BREAK case 16: YY_RULE_SETUP #line 258 "sbr/icalendar.l" { /* By default, flex will just pass unmatched text. Catch it instead. */ contentline *clines = vevents.last->contentlines; contentline *cline; if (clines && (cline = clines->last)) { if (cline->unexpected == NULL) { cline->unexpected = charstring_create (0); } charstring_append_cstring (cline->unexpected, icaltext); } } YY_BREAK case YY_STATE_EOF(INITIAL): #line 272 "sbr/icalendar.l" { /* See next rule for when start state is not INITIAL. */ destroy_icallex (); yyterminate (); } YY_BREAK case YY_STATE_EOF(s_name): case YY_STATE_EOF(s_colon): case YY_STATE_EOF(s_value): case YY_STATE_EOF(s_semicolon): case YY_STATE_EOF(s_param_name): case YY_STATE_EOF(s_equal): case YY_STATE_EOF(s_comma): #line 278 "sbr/icalendar.l" { /* Missing a final newline after a token. The input does not conform to RFC 5545 § 3.1, which requires that each contentline end with a CRLF. (Assume that the token is at the end of a contentline.) Be liberal in what we accept by faking a newline here, and setting the start state to terminate on the next call. */ BEGIN (INITIAL); return ICAL_CRLF; } YY_BREAK case 17: YY_RULE_SETUP #line 288 "sbr/icalendar.l" ECHO; YY_BREAK #line 1200 "sbr/icalendar.c" case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = (yy_hold_char); YY_RESTORE_YY_MORE_OFFSET if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed icalin at a new source and called * icallex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_CURRENT_BUFFER_LVALUE->yy_input_file = icalin; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) { /* This was really a NUL. */ yy_state_type yy_next_state; (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = (yytext_ptr) + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++(yy_c_buf_p); yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); goto yy_find_action; } } else switch ( yy_get_next_buffer( ) ) { case EOB_ACT_END_OF_FILE: { (yy_did_buffer_switch_on_eof) = 0; if ( icalwrap( ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * icaltext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: (yy_c_buf_p) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of user's declarations */ } /* end of icallex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer (void) { char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; char *source = (yytext_ptr); yy_size_t number_to_move, i; int ret_val; if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (yy_size_t) ((yy_c_buf_p) - (yytext_ptr)) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; else { yy_size_t num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; int yy_c_buf_p_offset = (int) ((yy_c_buf_p) - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { yy_size_t new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ icalrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = 0; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), (yy_n_chars), (size_t) num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } if ( (yy_n_chars) == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; icalrestart(icalin ); } else { ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) icalrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); } (yy_n_chars) += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state (void) { yy_state_type yy_current_state; char *yy_cp; yy_current_state = (yy_start); for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) { YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 125 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) { int yy_is_jam; char *yy_cp = (yy_c_buf_p); YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 125 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 124); return yy_is_jam ? 0 : yy_current_state; } #ifndef YY_NO_UNPUT static void yyunput (int c, char * yy_bp ) { char *yy_cp; yy_cp = (yy_c_buf_p); /* undo effects of setting up icaltext */ *yy_cp = (yy_hold_char); if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ yy_size_t number_to_move = (yy_n_chars) + 2; char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; char *source = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; (yytext_ptr) = yy_bp; (yy_hold_char) = *yy_cp; (yy_c_buf_p) = yy_cp; } #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void) #else static int input (void) #endif { int c; *(yy_c_buf_p) = (yy_hold_char); if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) /* This was really a NUL. */ *(yy_c_buf_p) = '\0'; else { /* need more input */ yy_size_t offset = (yy_c_buf_p) - (yytext_ptr); ++(yy_c_buf_p); switch ( yy_get_next_buffer( ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ icalrestart(icalin ); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( icalwrap( ) ) return EOF; if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + offset; break; } } } c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ *(yy_c_buf_p) = '\0'; /* preserve icaltext */ (yy_hold_char) = *++(yy_c_buf_p); return c; } #endif /* ifndef YY_NO_INPUT */ /** Immediately switch to a different input stream. * @param input_file A readable stream. * * @note This function does not reset the start condition to @c INITIAL . */ void icalrestart (FILE * input_file ) { if ( ! YY_CURRENT_BUFFER ){ icalensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = ical_create_buffer(icalin,YY_BUF_SIZE ); } ical_init_buffer(YY_CURRENT_BUFFER,input_file ); ical_load_buffer_state( ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * */ void ical_switch_to_buffer (YY_BUFFER_STATE new_buffer ) { /* TODO. We should be able to replace this entire function body * with * icalpop_buffer_state(); * icalpush_buffer_state(new_buffer); */ icalensure_buffer_stack (); if ( YY_CURRENT_BUFFER == new_buffer ) return; if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } YY_CURRENT_BUFFER_LVALUE = new_buffer; ical_load_buffer_state( ); /* We don't actually know whether we did this switch during * EOF (icalwrap()) processing, but the only time this flag * is looked at is after icalwrap() is called, so it's safe * to go ahead and always set it. */ (yy_did_buffer_switch_on_eof) = 1; } static void ical_load_buffer_state (void) { (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; icalin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; (yy_hold_char) = *(yy_c_buf_p); } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. * * @return the allocated buffer state. */ YY_BUFFER_STATE ical_create_buffer (FILE * file, int size ) { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) icalalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in ical_create_buffer()" ); b->yy_buf_size = (yy_size_t)size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) icalalloc(b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in ical_create_buffer()" ); b->yy_is_our_buffer = 1; ical_init_buffer(b,file ); return b; } /** Destroy the buffer. * @param b a buffer created with ical_create_buffer() * */ void ical_delete_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) icalfree((void *) b->yy_ch_buf ); icalfree((void *) b ); } /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a icalrestart() or at EOF. */ static void ical_init_buffer (YY_BUFFER_STATE b, FILE * file ) { int oerrno = errno; ical_flush_buffer(b ); b->yy_input_file = file; b->yy_fill_buffer = 1; /* If b is the current buffer, then ical_init_buffer was _probably_ * called from icalrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ b->yy_bs_lineno = 1; b->yy_bs_column = 0; } b->yy_is_interactive = 0; errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * */ void ical_flush_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) ical_load_buffer_state( ); } /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * */ void icalpush_buffer_state (YY_BUFFER_STATE new_buffer ) { if (new_buffer == NULL) return; icalensure_buffer_stack(); /* This block is copied from ical_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) (yy_buffer_stack_top)++; YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from ical_switch_to_buffer. */ ical_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * */ void icalpop_buffer_state (void) { if (!YY_CURRENT_BUFFER) return; ical_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; if ((yy_buffer_stack_top) > 0) --(yy_buffer_stack_top); if (YY_CURRENT_BUFFER) { ical_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } } /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ static void icalensure_buffer_stack (void) { yy_size_t num_to_alloc; if (!(yy_buffer_stack)) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; // After all that talk, this was set to 1 anyways... (yy_buffer_stack) = (struct yy_buffer_state**)icalalloc (num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in icalensure_buffer_stack()" ); memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; (yy_buffer_stack_top) = 0; return; } if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ /* Increase the buffer to prepare for a possible push. */ yy_size_t grow_size = 8 /* arbitrary grow size */; num_to_alloc = (yy_buffer_stack_max) + grow_size; (yy_buffer_stack) = (struct yy_buffer_state**)icalrealloc ((yy_buffer_stack), num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in icalensure_buffer_stack()" ); /* zero only the new slots.*/ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; } } /** Setup the input buffer state to scan directly from a user-specified character buffer. * @param base the character buffer * @param size the size in bytes of the character buffer * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE ical_scan_buffer (char * base, yy_size_t size ) { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; b = (YY_BUFFER_STATE) icalalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in ical_scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = 0; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; ical_switch_to_buffer(b ); return b; } /** Setup the input buffer state to scan a string. The next call to icallex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * ical_scan_bytes() instead. */ YY_BUFFER_STATE ical_scan_string (yyconst char * yystr ) { return ical_scan_bytes(yystr,strlen(yystr) ); } /** Setup the input buffer state to scan the given bytes. The next call to icallex() will * scan from a @e copy of @a bytes. * @param yybytes the byte buffer to scan * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE ical_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len ) { YY_BUFFER_STATE b; char *buf; yy_size_t n; yy_size_t i; /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; buf = (char *) icalalloc(n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in ical_scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; b = ical_scan_buffer(buf,n ); if ( ! b ) YY_FATAL_ERROR( "bad buffer in ical_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif static void yy_fatal_error (yyconst char* msg ) { (void) fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up icaltext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ icaltext[icalleng] = (yy_hold_char); \ (yy_c_buf_p) = icaltext + yyless_macro_arg; \ (yy_hold_char) = *(yy_c_buf_p); \ *(yy_c_buf_p) = '\0'; \ icalleng = yyless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ /** Get the current line number. * */ int icalget_lineno (void) { return icallineno; } /** Get the input stream. * */ FILE *icalget_in (void) { return icalin; } /** Get the output stream. * */ FILE *icalget_out (void) { return icalout; } /** Get the length of the current token. * */ yy_size_t icalget_leng (void) { return icalleng; } /** Get the current token. * */ char *icalget_text (void) { return icaltext; } /** Set the current line number. * @param _line_number line number * */ void icalset_lineno (int _line_number ) { icallineno = _line_number; } /** Set the input stream. This does not discard the current * input buffer. * @param _in_str A readable stream. * * @see ical_switch_to_buffer */ void icalset_in (FILE * _in_str ) { icalin = _in_str ; } void icalset_out (FILE * _out_str ) { icalout = _out_str ; } int icalget_debug (void) { return ical_flex_debug; } void icalset_debug (int _bdebug ) { ical_flex_debug = _bdebug ; } static int yy_init_globals (void) { /* Initialization is the same as for the non-reentrant scanner. * This function is called from icallex_destroy(), so don't allocate here. */ (yy_buffer_stack) = 0; (yy_buffer_stack_top) = 0; (yy_buffer_stack_max) = 0; (yy_c_buf_p) = (char *) 0; (yy_init) = 0; (yy_start) = 0; /* Defined in main.c */ #ifdef YY_STDINIT icalin = stdin; icalout = stdout; #else icalin = (FILE *) 0; icalout = (FILE *) 0; #endif /* For future reference: Set errno on error, since we are called by * icallex_init() */ return 0; } /* icallex_destroy is for both reentrant and non-reentrant scanners. */ int icallex_destroy (void) { /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ ical_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; icalpop_buffer_state(); } /* Destroy the stack itself. */ icalfree((yy_buffer_stack) ); (yy_buffer_stack) = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time * icallex() is called, initialization will occur. */ yy_init_globals( ); return 0; } /* * Internal utility routines. */ #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) { int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s ) { int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif void *icalalloc (yy_size_t size ) { return (void *) malloc( size ); } void *icalrealloc (void * ptr, yy_size_t size ) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } void icalfree (void * ptr ) { free( (char *) ptr ); /* see icalrealloc() for (char *) cast */ } #define YYTABLES_NAME "yytables" #line 288 "sbr/icalendar.l" static char * unfold (char *text, size_t *leng) { /* It's legal to shorten text and modify leng (because we don't use yymore()). */ char *cp; /* First squash any CR-LF-WSP sequences. */ while ((cp = strstr (text, "\r\n ")) || (cp = strstr (text, "\r\n\t"))) { /* Subtract any characters prior to fold sequence and 3 for the fold sequence, and add 1 for the terminating null. */ (void) memmove (cp, cp + 3, *leng - (cp - text) - 3 + 1); *leng -= 3; } /* Then squash any LF-WSP sequences. */ while ((cp = strstr (text, "\n ")) || (cp = strstr (text, "\n\t"))) { /* Subtract any characters prior to fold sequence and 2 for the fold sequence, and add 1 for the terminating null. */ (void) memmove (cp, cp + 2, *leng - (cp - text) - 2 + 1); *leng -= 2; } return text; } /* * To clean up memory, call the function provided by modern * versions of flex. Older versions don't have it, and of * course this won't do anything if the scanner was built * with something other than flex. */ static void destroy_icallex(void) { #if defined FLEX_SCANNER && defined YY_FLEX_SUBMINOR_VERSION /* Hack: rely on fact that the the YY_FLEX_SUBMINOR_VERSION #define was added to flex (flex.skl v. 2.163) after #icallex_destroy() was added. */ icallex_destroy (); #endif /* FLEX_SCANNER && YY_CURRENT_BUFFER_LVALUE */ } /* * See comment in h/icalendar.h about having to provide these * because flex 2.5.4 doesn't. */ void icalset_inputfile (FILE *file) { icalin = file; } void icalset_outputfile (FILE *file) { icalout = file; } /* * Porting notes * ------------- * POSIX lex only supports an entry point name of icallex(). nmh * programs can contain multiple scanners (see sbr/dtimep.l), so * nmh requires the use of flex to build them. * In addition, if there is a need to port this to Solaris lex: * - Use the lex -e or -w option. * - Comment out all of the %options. * - Comment out the <> rule. * - The start condition and pattern must be on the same line. * - Comments must be inside rules, not just before them. * - Don't use start condition stack. In the code, above BEGIN's are * used instead, and the contents of an imaginary start condition * stack are shown after each. The stack operations are also shown * in comments. */ nmh-1.7.1-RC3/sbr/icalendar.l000644 007761 000024 00000024640 13243042053 015651 0ustar00kenhstaff000000 000000 /* icalendar.l -- icalendar (RFC 5545) scanner * * This code is Copyright (c) 2014, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ /* See porting notes at end of this file. */ %{ #include "h/mh.h" #include "h/icalendar.h" #include "sbr/icalparse.h" static char *unfold (char *, size_t *); static void destroy_icallex(void); %} /* * These flex options aren't used: * 8bit not needed * case-insensitive not needed * align not used because this isn't performance critical */ %option outfile="lex.yy.c" prefix="ical" %option perf-report warn %option never-interactive noinput noyywrap /* * From RFC 5545 § 3.1. */ name {iana-token}|{x-name} iana-token ({ALPHA}|{DIGIT}|-)+ x-name X-({vendorid}-)?({ALPHA}|{DIGIT}|-)+ vendorid ({ALPHA}|{DIGIT}){3,} param-name {iana-token}|{x-name} param-value {paramtext}|{quoted-string} paramtext {SAFE-CHAR}* value {VALUE-CHAR}* quoted-string {DQUOTE}{QSAFE-CHAR}*{DQUOTE} QSAFE-CHAR {WSP}|[\x21\x23-\x7E]|{NON-US-ASCII} SAFE-CHAR {WSP}|[\x21\x23-\x2B\x2D-\x39\x3C-\x7E]|{NON-US-ASCII} VALUE-CHAR {WSP}|[\x21-\x7E]|{NON-US-ASCII} /* The following is a short-cut definition that admits more that the UNICODE characters permitted by RFC 5545. */ NON-US-ASCII [\x80-\xF8]{2,4} /* The following excludes HTAB, unlike {CTL}. */ CONTROL [\x00-\x08\x0A-\x1F\x7F] EQUAL = /* Solaris lex requires that the , be escaped. */ COMMA \, /* * From RFC 5545 § 2.1. */ COLON : SEMICOLON ; /* * From RFC 5545 § 3.3.11. */ text ({TSAFE-CHAR}|:|{DQUOTE}|{ESCAPED-CHAR})* ESCAPED-CHAR \\\\|\\;|\\,|\\N|\\n TSAFE-CHAR {WSP}|[\x21\x23-\x2B\x2D-\x39\x3C-\x5B\x5D-\x7E]|{NON-US-ASCII| /* * Core rules (definitions) from RFC 5234 Appendix B.1. */ ALPHA [\x41-\x5A\x61-\x7A] BIT [01] CHAR [\x01-\x7F] CR \x0D /* Variance from RFC 5234: the {CR} is required in CRLF, but it is optional below to support Unix filesystem convention. */ CRLF ({CR}?{LF})+ CTL [\x00-\x1F\x7F] DIGIT [\x30-\x39] DQUOTE \x22 HEXDIG {DIGIT}|[A-F] HTAB \x09 LF \x0A LWSP ({WSP}|({CRLF}{WSP}))* OCTET [\x00-\xFF] SP \x20 VCHAR [\x21-\x7E] WSP {SP}|{HTAB} /* * Our definitions. */ fold {CRLF}{WSP} folded-name {name}({fold}+{iana-token})+ folded-param-name {param-name}({fold}+{iana-token})+ folded-quoted-string {DQUOTE}{QSAFE-CHAR}*{fold}+{QSAFE-CHAR}*{DQUOTE} folded-param-value {paramtext}({fold}{paramtext}*)+|{folded-quoted-string} folded-value {VALUE-CHAR}*({fold}{VALUE-CHAR}*)+ %s s_name s_colon s_value s_semicolon s_param_name s_equal s_comma %% {CRLF} { /* Eat any leading newlines. */ } {folded-name} { /* flex 2.5.4 defines icalleng as an int instead of a size_t, so copy it. */ size_t len = icalleng; unfold (icaltext, &len); icalleng = len; icallval = strdup (icaltext); /* yy_push_state (s_name); * s_name */ BEGIN (s_name); /* s_name */ return ICAL_NAME; } {name} { icallval = strdup (icaltext); /* yy_push_state (s_name); * s_name */ BEGIN (s_name); /* s_name */ return ICAL_NAME; } {COLON} { /* Don't need to strdup a single character. */ icallval = icaltext; /* yy_pop_state (); * INITIAL */ /* yy_push_state (s_colon); * s_colon */ BEGIN (s_colon); /* s_colon */ return ICAL_COLON; } {folded-value} { /* flex 2.5.4 defines icalleng as an int instead of a size_t, so copy it. */ size_t len = icalleng; unfold (icaltext, &len); icalleng = len; icallval = strdup (icaltext); /* yy_pop_state (); * INITIAL */ /* yy_push_state (s_value); * s_value */ BEGIN (s_value); /* s_value */ return ICAL_VALUE; } {value} { icallval = strdup (icaltext); /* yy_pop_state (); * INITIAL */ /* yy_push_state (s_value); * s_value */ BEGIN (s_value); /* s_value */ return ICAL_VALUE; } {SEMICOLON} { /* Don't need to strdup a single character. */ icallval = icaltext; /* yy_push_state (s_semicolon); * s_name, s_semicolon */ BEGIN (s_semicolon); /* s_name, s_semicolon */ return ICAL_SEMICOLON; } {folded-param-name} { /* flex 2.5.4 defines icalleng as an int instead of a size_t, so copy it. */ size_t len = icalleng; unfold (icaltext, &len); icalleng = len; icallval = strdup (icaltext); /* yy_pop_state (); * s_name */ /* yy_push_state (s_param_name); * s_name, s_param_name */ BEGIN (s_param_name); /* s_name, s_param_name */ return ICAL_PARAM_NAME; } {param-name} { icallval = strdup (icaltext); /* yy_pop_state (); * s_name */ /* yy_push_state (s_param_name); * s_name, s_param_name */ BEGIN (s_param_name); /* s_name, s_param_name */ return ICAL_PARAM_NAME; } {EQUAL} { /* Don't need to strdup a single character. */ icallval = icaltext; /* yy_pop_state (); * s_name */ /* yy_push_state (s_equal); * s_name, s_equal */ BEGIN (s_equal); /* s_name, s_equal */ return ICAL_EQUAL; } {folded-param-value} { /* flex 2.5.4 defines icalleng as an int instead of a size_t, so copy it. */ size_t len = icalleng; unfold (icaltext, &len); icalleng = len; icallval = strdup (icaltext); /* yy_pop_state (); * s_name */ BEGIN (s_name); /* s_name */ return ICAL_PARAM_VALUE; } {param-value} { icallval = strdup (icaltext); /* yy_pop_state (); * s_name */ BEGIN (s_name); /* s_name */ return ICAL_PARAM_VALUE; } {COMMA} { /* Don't need to strdup a single character. */ icallval = icaltext; /* yy_push_state (s_comma); * s_name, s_comma */ BEGIN (s_comma); /* s_name, s_comma */ return ICAL_COMMA; } {CRLF} { /* Use start condition to ensure that all newlines are where expected. */ icallval = icaltext; /* yy_pop_state (); * INITIAL */ BEGIN (INITIAL); /* INITIAL */ return ICAL_CRLF; } {CRLF} { /* Null value. */ icallval = strdup (""); /* yy_pop_state (); * INITIAL */ /* yy_push_state (s_value); * s_value */ BEGIN (s_value); /* s_value */ /* Push the newline back so it can be handled in the proper state. */ unput ('\n'); return ICAL_VALUE; } . { /* By default, flex will just pass unmatched text. Catch it instead. */ contentline *clines = vevents.last->contentlines; contentline *cline; if (clines && (cline = clines->last)) { if (cline->unexpected == NULL) { cline->unexpected = charstring_create (0); } charstring_append_cstring (cline->unexpected, icaltext); } } <> { /* See next rule for when start state is not INITIAL. */ destroy_icallex (); yyterminate (); } <> { /* Missing a final newline after a token. The input does not conform to RFC 5545 § 3.1, which requires that each contentline end with a CRLF. (Assume that the token is at the end of a contentline.) Be liberal in what we accept by faking a newline here, and setting the start state to terminate on the next call. */ BEGIN (INITIAL); return ICAL_CRLF; } %% static char * unfold (char *text, size_t *leng) { /* It's legal to shorten text and modify leng (because we don't use yymore()). */ char *cp; /* First squash any CR-LF-WSP sequences. */ while ((cp = strstr (text, "\r\n ")) || (cp = strstr (text, "\r\n\t"))) { /* Subtract any characters prior to fold sequence and 3 for the fold sequence, and add 1 for the terminating null. */ (void) memmove (cp, cp + 3, *leng - (cp - text) - 3 + 1); *leng -= 3; } /* Then squash any LF-WSP sequences. */ while ((cp = strstr (text, "\n ")) || (cp = strstr (text, "\n\t"))) { /* Subtract any characters prior to fold sequence and 2 for the fold sequence, and add 1 for the terminating null. */ (void) memmove (cp, cp + 2, *leng - (cp - text) - 2 + 1); *leng -= 2; } return text; } /* * To clean up memory, call the function provided by modern * versions of flex. Older versions don't have it, and of * course this won't do anything if the scanner was built * with something other than flex. */ static void destroy_icallex(void) { #if defined FLEX_SCANNER && defined YY_FLEX_SUBMINOR_VERSION /* Hack: rely on fact that the the YY_FLEX_SUBMINOR_VERSION #define was added to flex (flex.skl v. 2.163) after #yylex_destroy() was added. */ icallex_destroy (); #endif /* FLEX_SCANNER && YY_CURRENT_BUFFER_LVALUE */ } /* * See comment in h/icalendar.h about having to provide these * because flex 2.5.4 doesn't. */ void icalset_inputfile (FILE *file) { yyin = file; } void icalset_outputfile (FILE *file) { yyout = file; } /* * Porting notes * ------------- * POSIX lex only supports an entry point name of yylex(). nmh * programs can contain multiple scanners (see sbr/dtimep.l), so * nmh requires the use of flex to build them. * In addition, if there is a need to port this to Solaris lex: * - Use the lex -e or -w option. * - Comment out all of the %options. * - Comment out the <> rule. * - The start condition and pattern must be on the same line. * - Comments must be inside rules, not just before them. * - Don't use start condition stack. In the code, above BEGIN's are * used instead, and the contents of an imaginary start condition * stack are shown after each. The stack operations are also shown * in comments. */ nmh-1.7.1-RC3/sbr/icalparse.c000644 007761 000024 00000155430 13243042113 015660 0ustar00kenhstaff000000 000000 /* A Bison parser, made by GNU Bison 3.0.4. */ /* Bison implementation for Yacc-like parsers in C Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ #define YYBISON_VERSION "3.0.4" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 0 /* Push parsers. */ #define YYPUSH 0 /* Pull parsers. */ #define YYPULL 1 /* Copy the first part of user declarations. */ #line 8 "sbr/icalparse.y" /* yacc.c:339 */ /* * Use these yy* #defines, instead of the -p command line * option, to allow multiple parsers in a program. yyval * is generated by Solaris yacc and is of type YYSTYPE. * All other yy* symbols are data of a built-in type and * are initialized by yyparse(), so they can be shared * between different parsers. */ #define yydebug icaldebug #define yyerror icalerror #define yylex icallex #define yylval icallval #define yyval icalval #define yyparse icalparse #define YYDEBUG 1 #define YYERROR_DEBUG #define YYERROR_VERBOSE #define YY_NO_LEAKS /* * To quiet compile warnings with Solaris yacc: #ifdef sun # define lint 1 # undef YYDEBUG #endif */ #include "h/mh.h" #include "h/icalendar.h" #include "h/utils.h" static char *append (contentline *, const char *, const size_t); static void new_content_line (contentline **); static void new_vevent (vevent *); static void free_param_names (param_list *); static void free_param_values (value_list *); static int icalerror (const char *); #line 106 "sbr/icalparse.c" /* yacc.c:339 */ # ifndef YY_NULLPTR # if defined __cplusplus && 201103L <= __cplusplus # define YY_NULLPTR nullptr # else # define YY_NULLPTR 0 # endif # endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 0 #endif /* In a future release of Bison, this section will be replaced by #include "y.tab.h". */ #ifndef YY_YY_SBR_ICALPARSE_H_INCLUDED # define YY_YY_SBR_ICALPARSE_H_INCLUDED /* Debug traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif #if YYDEBUG extern int yydebug; #endif /* Token type. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE enum yytokentype { ICAL_NAME = 258, ICAL_COLON = 259, ICAL_VALUE = 260, ICAL_CRLF = 261, ICAL_SEMICOLON = 262, ICAL_PARAM_NAME = 263, ICAL_EQUAL = 264, ICAL_PARAM_VALUE = 265, ICAL_COMMA = 266 }; #endif /* Tokens. */ #define ICAL_NAME 258 #define ICAL_COLON 259 #define ICAL_VALUE 260 #define ICAL_CRLF 261 #define ICAL_SEMICOLON 262 #define ICAL_PARAM_NAME 263 #define ICAL_EQUAL 264 #define ICAL_PARAM_VALUE 265 #define ICAL_COMMA 266 /* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef int YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define YYSTYPE_IS_DECLARED 1 #endif extern YYSTYPE yylval; int yyparse (void); #endif /* !YY_YY_SBR_ICALPARSE_H_INCLUDED */ /* Copy the second part of user declarations. */ #line 179 "sbr/icalparse.c" /* yacc.c:358 */ #ifdef short # undef short #endif #ifdef YYTYPE_UINT8 typedef YYTYPE_UINT8 yytype_uint8; #else typedef unsigned char yytype_uint8; #endif #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; #else typedef signed char yytype_int8; #endif #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else typedef unsigned short int yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else typedef short int yytype_int16; #endif #ifndef YYSIZE_T # ifdef __SIZE_TYPE__ # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t # elif ! defined YYSIZE_T # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else # define YYSIZE_T unsigned int # endif #endif #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(Msgid) dgettext ("bison-runtime", Msgid) # endif # endif # ifndef YY_ # define YY_(Msgid) Msgid # endif #endif #ifndef YY_ATTRIBUTE # if (defined __GNUC__ \ && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C # define YY_ATTRIBUTE(Spec) __attribute__(Spec) # else # define YY_ATTRIBUTE(Spec) /* empty */ # endif #endif #ifndef YY_ATTRIBUTE_PURE # define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) #endif #ifndef YY_ATTRIBUTE_UNUSED # define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) #endif #if !defined _Noreturn \ && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) # if defined _MSC_VER && 1200 <= _MSC_VER # define _Noreturn __declspec (noreturn) # else # define _Noreturn YY_ATTRIBUTE ((__noreturn__)) # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(E) ((void) (E)) #else # define YYUSE(E) /* empty */ #endif #if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ /* Suppress an incorrect diagnostic about yylval being uninitialized. */ # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ _Pragma ("GCC diagnostic push") \ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") # define YY_IGNORE_MAYBE_UNINITIALIZED_END \ _Pragma ("GCC diagnostic pop") #else # define YY_INITIAL_VALUE(Value) Value #endif #ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN # define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN # define YY_IGNORE_MAYBE_UNINITIALIZED_END #endif #ifndef YY_INITIAL_VALUE # define YY_INITIAL_VALUE(Value) /* Nothing. */ #endif #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # elif defined __BUILTIN_VA_ARG_INCR # include /* INFRINGES ON USER NAME SPACE */ # elif defined _AIX # define YYSTACK_ALLOC __alloca # elif defined _MSC_VER # include /* INFRINGES ON USER NAME SPACE */ # define alloca _alloca # else # define YYSTACK_ALLOC alloca # if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS # include /* INFRINGES ON USER NAME SPACE */ /* Use EXIT_SUCCESS as a witness for stdlib.h. */ # ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 # endif # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's 'empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif # else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif # if (defined __cplusplus && ! defined EXIT_SUCCESS \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ # ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc # if ! defined malloc && ! defined EXIT_SUCCESS void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free # if ! defined free && ! defined EXIT_SUCCESS void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif #endif /* ! defined yyoverflow || YYERROR_VERBOSE */ #if (! defined yyoverflow \ && (! defined __cplusplus \ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { yytype_int16 yyss_alloc; YYSTYPE yyvs_alloc; }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) # define YYCOPY_NEEDED 1 /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack_alloc, Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ Stack = &yyptr->Stack_alloc; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (0) #endif #if defined YYCOPY_NEEDED && YYCOPY_NEEDED /* Copy COUNT objects from SRC to DST. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(Dst, Src, Count) \ __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) # else # define YYCOPY(Dst, Src, Count) \ do \ { \ YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (Dst)[yyi] = (Src)[yyi]; \ } \ while (0) # endif # endif #endif /* !YYCOPY_NEEDED */ /* YYFINAL -- State number of the termination state. */ #define YYFINAL 6 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 31 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 12 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 17 /* YYNRULES -- Number of rules. */ #define YYNRULES 21 /* YYNSTATES -- Number of states. */ #define YYNSTATES 34 /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned by yylex, with out-of-bounds checking. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 266 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM as returned by yylex, without out-of-bounds checking. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; #if YYDEBUG /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { 0, 59, 59, 60, 64, 68, 70, 64, 89, 93, 95, 89, 107, 107, 110, 110, 116, 119, 116, 124, 128, 128 }; #endif #if YYDEBUG || YYERROR_VERBOSE || 0 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "ICAL_NAME", "ICAL_COLON", "ICAL_VALUE", "ICAL_CRLF", "ICAL_SEMICOLON", "ICAL_PARAM_NAME", "ICAL_EQUAL", "ICAL_PARAM_VALUE", "ICAL_COMMA", "$accept", "contentline_list", "contentline", "$@1", "$@2", "$@3", "$@4", "$@5", "$@6", "param_list", "$@7", "$@8", "param", "$@9", "$@10", "param_value_list", "$@11", YY_NULLPTR }; #endif # ifdef YYPRINT /* YYTOKNUM[NUM] -- (External) token number corresponding to the (internal) symbol number NUM (which must be that of a token). */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266 }; # endif #define YYPACT_NINF -5 #define yypact_value_is_default(Yystate) \ (!!((Yystate) == (-5))) #define YYTABLE_NINF -9 #define yytable_value_is_error(Yytable_value) \ 0 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ static const yytype_int8 yypact[] = { -1, -2, 0, -5, 2, 1, -5, -5, -5, -5, -3, 4, 3, -5, -5, -5, -5, -5, 5, 3, 6, 7, -5, -5, -5, -5, 8, 9, -5, -5, -4, -5, 10, -5 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. Performed when YYTABLE does not specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { 0, 4, 0, 2, 0, 0, 1, 3, 5, 12, 0, 0, 0, 9, 14, 6, 16, 13, 0, 0, 0, 0, 10, 15, 7, 17, 0, 0, 11, 19, 18, 20, 0, 21 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { -5, -5, 11, -5, -5, -5, -5, -5, -5, -5, -5, -5, 12, -5, -5, -5, -5 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { -1, 2, 3, 4, 11, 20, 5, 18, 26, 10, 12, 19, 17, 21, 27, 30, 32 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule whose number is the opposite. If YYTABLE_NINF, syntax error. */ static const yytype_int8 yytable[] = { 6, 13, 1, 1, 14, -8, 8, 31, 9, 15, 22, 16, 24, 7, 28, 0, 25, 0, 0, 29, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23 }; static const yytype_int8 yycheck[] = { 0, 4, 3, 3, 7, 7, 4, 11, 7, 5, 5, 8, 6, 2, 6, -1, 9, -1, -1, 10, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 19 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 3, 13, 14, 15, 18, 0, 14, 4, 7, 21, 16, 22, 4, 7, 5, 8, 24, 19, 23, 17, 25, 5, 24, 6, 9, 20, 26, 6, 10, 27, 11, 28, 10 }; /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { 0, 12, 13, 13, 15, 16, 17, 14, 18, 19, 20, 14, 22, 21, 23, 21, 25, 26, 24, 27, 28, 27 }; /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 1, 2, 0, 0, 0, 7, 0, 0, 0, 8, 0, 3, 0, 4, 0, 0, 5, 1, 0, 4 }; #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY) \ { \ yychar = (Token); \ yylval = (Value); \ YYPOPSTACK (yylen); \ yystate = *yyssp; \ goto yybackup; \ } \ else \ { \ yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (0) /* Error token number */ #define YYTERROR 1 #define YYERRCODE 256 /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (0) /* This macro is provided for backward compatibility. */ #ifndef YY_LOCATION_PRINT # define YY_LOCATION_PRINT(File, Loc) ((void) 0) #endif # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ Type, Value); \ YYFPRINTF (stderr, "\n"); \ } \ } while (0) /*----------------------------------------. | Print this symbol's value on YYOUTPUT. | `----------------------------------------*/ static void yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) { FILE *yyo = yyoutput; YYUSE (yyo); if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # endif YYUSE (yytype); } /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ static void yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) { YYFPRINTF (yyoutput, "%s %s (", yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); yy_symbol_value_print (yyoutput, yytype, yyvaluep); YYFPRINTF (yyoutput, ")"); } /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ static void yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) { YYFPRINTF (stderr, "Stack now"); for (; yybottom <= yytop; yybottom++) { int yybot = *yybottom; YYFPRINTF (stderr, " %d", yybot); } YYFPRINTF (stderr, "\n"); } # define YY_STACK_PRINT(Bottom, Top) \ do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ } while (0) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ static void yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule) { unsigned long int yylno = yyrline[yyrule]; int yynrhs = yyr2[yyrule]; int yyi; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yystos[yyssp[yyi + 1 - yynrhs]], &(yyvsp[(yyi + 1) - (yynrhs)]) ); YYFPRINTF (stderr, "\n"); } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (yyssp, yyvsp, Rule); \ } while (0) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #if YYERROR_VERBOSE # ifndef yystrlen # if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ static YYSIZE_T yystrlen (const char *yystr) { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) continue; return yylen; } # endif # endif # ifndef yystpcpy # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ static char * yystpcpy (char *yydest, const char *yysrc) { char *yyd = yydest; const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif # ifndef yytnamerr /* Copy to YYRES the contents of YYSTR after stripping away unnecessary quotes and backslashes, so that it's suitable for yyerror. The heuristic is that double-quoting is unnecessary unless the string contains an apostrophe, a comma, or backslash (other than backslash-backslash). YYSTR is taken from yytname. If YYRES is null, do not copy; instead, return the length of what the result would have been. */ static YYSIZE_T yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { YYSIZE_T yyn = 0; char const *yyp = yystr; for (;;) switch (*++yyp) { case '\'': case ',': goto do_not_strip_quotes; case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; /* Fall through. */ default: if (yyres) yyres[yyn] = *yyp; yyn++; break; case '"': if (yyres) yyres[yyn] = '\0'; return yyn; } do_not_strip_quotes: ; } if (! yyres) return yystrlen (yystr); return yystpcpy (yyres, yystr) - yyres; } # endif /* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message about the unexpected token YYTOKEN for the state stack whose top is YYSSP. Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is not large enough to hold the message. In that case, also set *YYMSG_ALLOC to the required number of bytes. Return 2 if the required number of bytes is too large to store. */ static int yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, yytype_int16 *yyssp, int yytoken) { YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); YYSIZE_T yysize = yysize0; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; /* Internationalized format string. */ const char *yyformat = YY_NULLPTR; /* Arguments of yyformat. */ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; /* Number of reported tokens (one for the "unexpected", one per "expected"). */ int yycount = 0; /* There are many possibilities here to consider: - If this state is a consistent state with a default action, then the only way this function was invoked is if the default action is an error action. In that case, don't check for expected tokens because there are none. - The only way there can be no lookahead present (in yychar) is if this state is a consistent state with a default action. Thus, detecting the absence of a lookahead is sufficient to determine that there is no unexpected or expected token to report. In that case, just report a simple "syntax error". - Don't assume there isn't a lookahead just because this state is a consistent state with a default action. There might have been a previous inconsistent state, consistent state with a non-default action, or user semantic action that manipulated yychar. - Of course, the expected token list depends on states to have correct lookahead information, and it depends on the parser not to perform extra reductions after fetching a lookahead from the scanner and before detecting a syntax error. Thus, state merging (from LALR or IELR) and default reductions corrupt the expected token list. However, the list is correct for canonical LR with one exception: it will still contain any token that will not be accepted due to an error action in a later state. */ if (yytoken != YYEMPTY) { int yyn = yypact[*yyssp]; yyarg[yycount++] = yytname[yytoken]; if (!yypact_value_is_default (yyn)) { /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. In other words, skip the first -YYN actions for this state because they are default actions. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn + 1; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yyx; for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR && !yytable_value_is_error (yytable[yyx + yyn])) { if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) { yycount = 1; yysize = yysize0; break; } yyarg[yycount++] = yytname[yyx]; { YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) return 2; yysize = yysize1; } } } } switch (yycount) { # define YYCASE_(N, S) \ case N: \ yyformat = S; \ break YYCASE_(0, YY_("syntax error")); YYCASE_(1, YY_("syntax error, unexpected %s")); YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); # undef YYCASE_ } { YYSIZE_T yysize1 = yysize + yystrlen (yyformat); if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) return 2; yysize = yysize1; } if (*yymsg_alloc < yysize) { *yymsg_alloc = 2 * yysize; if (! (yysize <= *yymsg_alloc && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; return 1; } /* Avoid sprintf, as that infringes on the user's name space. Don't have undefined behavior even if the translation produced a string with the wrong number of "%s"s. */ { char *yyp = *yymsg; int yyi = 0; while ((*yyp = *yyformat) != '\0') if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) { yyp += yytnamerr (yyp, yyarg[yyi++]); yyformat += 2; } else { yyp++; yyformat++; } } return 0; } #endif /* YYERROR_VERBOSE */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) { YYUSE (yyvaluep); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN YYUSE (yytype); YY_IGNORE_MAYBE_UNINITIALIZED_END } /* The lookahead symbol. */ int yychar; /* The semantic value of the lookahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; /*----------. | yyparse. | `----------*/ int yyparse (void) { int yystate; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* The stacks and their tools: 'yyss': related to states. 'yyvs': related to semantic values. Refer to the stacks through separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ yytype_int16 yyssa[YYINITDEPTH]; yytype_int16 *yyss; yytype_int16 *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs; YYSTYPE *yyvsp; YYSIZE_T yystacksize; int yyn; int yyresult; /* Lookahead token as an internal (translated) token number. */ int yytoken = 0; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; char *yymsg = yymsgbuf; YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; yyssp = yyss = yyssa; yyvsp = yyvs = yyvsa; yystacksize = YYINITDEPTH; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { yytype_int16 *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); if (yystate == YYFINAL) YYACCEPT; goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yypact_value_is_default (yyn)) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = yylex (); } if (yychar <= YYEOF) { yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yytoken = YYTRANSLATE (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yytable_value_is_error (yyn)) goto yyerrlab; yyn = -yyn; goto yyreduce; } /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the shifted token. */ yychar = YYEMPTY; yystate = yyn; YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; YY_IGNORE_MAYBE_UNINITIALIZED_END goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: '$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; YY_REDUCE_PRINT (yyn); switch (yyn) { case 4: #line 64 "sbr/icalparse.y" /* yacc.c:1646 */ { new_content_line (&vevents.last->contentlines); append (vevents.last->contentlines->last, (yyvsp[0]), strlen ((yyvsp[0]))); vevents.last->contentlines->last->name = (yyvsp[0]); } #line 1276 "sbr/icalparse.c" /* yacc.c:1646 */ break; case 5: #line 68 "sbr/icalparse.y" /* yacc.c:1646 */ { append (vevents.last->contentlines->last, (yyvsp[0]), strlen ((yyvsp[0]))); } #line 1284 "sbr/icalparse.c" /* yacc.c:1646 */ break; case 6: #line 70 "sbr/icalparse.y" /* yacc.c:1646 */ { append (vevents.last->contentlines->last, (yyvsp[0]), strlen ((yyvsp[0]))); vevents.last->contentlines->last->value = (yyvsp[0]); } #line 1293 "sbr/icalparse.c" /* yacc.c:1646 */ break; case 7: #line 73 "sbr/icalparse.y" /* yacc.c:1646 */ { append (vevents.last->contentlines->last, (yyvsp[0]), strlen ((yyvsp[0]))); if (vevents.last->contentlines->cr_before_lf == CR_UNSET) { vevents.last->contentlines->cr_before_lf = (yyvsp[0])[0] == '\r' ? CR_BEFORE_LF : LF_ONLY; } /* END:VEVENT doesn't have a param_list so we don't need to check for it below. */ if (vevents.last->contentlines->last->name && vevents.last->contentlines->last->value && ! strcasecmp (vevents.last->contentlines->last->name, "END") && ! strcasecmp (vevents.last->contentlines->last->value, "VEVENT")) { new_vevent (&vevents); } } #line 1314 "sbr/icalparse.c" /* yacc.c:1646 */ break; case 8: #line 89 "sbr/icalparse.y" /* yacc.c:1646 */ { new_content_line (&vevents.last->contentlines); append (vevents.last->contentlines->last, (yyvsp[0]), strlen ((yyvsp[0]))); vevents.last->contentlines->last->name = (yyvsp[0]); } #line 1324 "sbr/icalparse.c" /* yacc.c:1646 */ break; case 9: #line 93 "sbr/icalparse.y" /* yacc.c:1646 */ { append (vevents.last->contentlines->last, (yyvsp[0]), strlen ((yyvsp[0]))); } #line 1332 "sbr/icalparse.c" /* yacc.c:1646 */ break; case 10: #line 95 "sbr/icalparse.y" /* yacc.c:1646 */ { append (vevents.last->contentlines->last, (yyvsp[0]), strlen ((yyvsp[0]))); vevents.last->contentlines->last->value = (yyvsp[0]); } #line 1341 "sbr/icalparse.c" /* yacc.c:1646 */ break; case 11: #line 98 "sbr/icalparse.y" /* yacc.c:1646 */ { append (vevents.last->contentlines->last, (yyvsp[0]), strlen ((yyvsp[0]))); if (vevents.last->contentlines->cr_before_lf == CR_UNSET) { vevents.last->contentlines->cr_before_lf = (yyvsp[0])[0] == '\r' ? CR_BEFORE_LF : LF_ONLY; } } #line 1353 "sbr/icalparse.c" /* yacc.c:1646 */ break; case 12: #line 107 "sbr/icalparse.y" /* yacc.c:1646 */ { append (vevents.last->contentlines->last, (yyvsp[0]), strlen ((yyvsp[0]))); } #line 1361 "sbr/icalparse.c" /* yacc.c:1646 */ break; case 14: #line 110 "sbr/icalparse.y" /* yacc.c:1646 */ { append (vevents.last->contentlines->last, (yyvsp[0]), strlen ((yyvsp[0]))); } #line 1369 "sbr/icalparse.c" /* yacc.c:1646 */ break; case 16: #line 116 "sbr/icalparse.y" /* yacc.c:1646 */ { append (vevents.last->contentlines->last, (yyvsp[0]), strlen ((yyvsp[0]))); add_param_name (vevents.last->contentlines->last, (yyvsp[0])); } #line 1378 "sbr/icalparse.c" /* yacc.c:1646 */ break; case 17: #line 119 "sbr/icalparse.y" /* yacc.c:1646 */ { append (vevents.last->contentlines->last, (yyvsp[0]), strlen ((yyvsp[0]))); } #line 1386 "sbr/icalparse.c" /* yacc.c:1646 */ break; case 19: #line 124 "sbr/icalparse.y" /* yacc.c:1646 */ { append (vevents.last->contentlines->last, (yyvsp[0]), strlen ((yyvsp[0]))); add_param_value (vevents.last->contentlines->last, (yyvsp[0])); } #line 1395 "sbr/icalparse.c" /* yacc.c:1646 */ break; case 20: #line 128 "sbr/icalparse.y" /* yacc.c:1646 */ { append (vevents.last->contentlines->last, (yyvsp[0]), strlen ((yyvsp[0]))); } #line 1403 "sbr/icalparse.c" /* yacc.c:1646 */ break; case 21: #line 130 "sbr/icalparse.y" /* yacc.c:1646 */ { append (vevents.last->contentlines->last, (yyvsp[0]), strlen ((yyvsp[0]))); add_param_value (vevents.last->contentlines->last, (yyvsp[0])); } #line 1412 "sbr/icalparse.c" /* yacc.c:1646 */ break; #line 1416 "sbr/icalparse.c" /* yacc.c:1646 */ default: break; } /* User semantic actions sometimes alter yychar, and that requires that yytoken be updated with the new translation. We take the approach of translating immediately before every use of yytoken. One alternative is translating here after every semantic action, but that translation would be missed if the semantic action invokes YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an incorrect destructor might then be invoked immediately. In the case of YYERROR or YYBACKUP, subsequent parser actions might lead to an incorrect destructor call or verbose syntax error message before the lookahead is translated. */ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; /* Now 'shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; /*--------------------------------------. | yyerrlab -- here on detecting error. | `--------------------------------------*/ yyerrlab: /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if ! YYERROR_VERBOSE yyerror (YY_("syntax error")); #else # define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ yyssp, yytoken) { char const *yymsgp = YY_("syntax error"); int yysyntax_error_status; yysyntax_error_status = YYSYNTAX_ERROR; if (yysyntax_error_status == 0) yymsgp = yymsg; else if (yysyntax_error_status == 1) { if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); if (!yymsg) { yymsg = yymsgbuf; yymsg_alloc = sizeof yymsgbuf; yysyntax_error_status = 2; } else { yysyntax_error_status = YYSYNTAX_ERROR; yymsgp = yymsg; } } yyerror (yymsgp); if (yysyntax_error_status == 2) goto yyexhaustedlab; } # undef YYSYNTAX_ERROR #endif } if (yyerrstatus == 3) { /* If just tried and failed to reuse lookahead token after an error, discard it. */ if (yychar <= YYEOF) { /* Return failure if at end of input. */ if (yychar == YYEOF) YYABORT; } else { yydestruct ("Error: discarding", yytoken, &yylval); yychar = YYEMPTY; } } /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (/*CONSTCOND*/ 0) goto yyerrorlab; /* Do not reclaim the symbols of the rule whose action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); yystate = *yyssp; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; if (!yypact_value_is_default (yyn)) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) { yyn = yytable[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) YYABORT; yydestruct ("Error: popping", yystos[yystate], yyvsp); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; YY_IGNORE_MAYBE_UNINITIALIZED_END /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; #if !defined yyoverflow || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: yyerror (YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: if (yychar != YYEMPTY) { /* Make sure we have latest lookahead translation. See comments at user semantic actions for why this is necessary. */ yytoken = YYTRANSLATE (yychar); yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval); } /* Do not reclaim the symbols of the rule whose action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", yystos[*yyssp], yyvsp); YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif #if YYERROR_VERBOSE if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); #endif return yyresult; } #line 135 "sbr/icalparse.y" /* yacc.c:1906 */ /* * Remove the contentline node (by setting its name to NULL). */ void remove_contentline (contentline *node) { free (node->name); node->name = NULL; } contentline * add_contentline (contentline *node, const char *name) { contentline *new_node; NEW0(new_node); new_node->name = mh_xstrdup (name); new_node->next = node->next; node->next = new_node; return new_node; } /* * Remove the value from a value_list. */ void remove_value (value_list *node) { free (node->value); node->value = NULL; } /* * Find the contentline with the specified name, and optionally, * the specified value and/or parameter name. */ contentline * find_contentline (contentline *contentlines, const char *name, const char *val) { contentline *node; for (node = contentlines; node; node = node->next) { /* node->name will be NULL if the line was "deleted". */ if (node->name && ! strcasecmp (name, node->name)) { if (val && node->value) { if (! strcasecmp (val, node->value)) { return node; } } else { return node; } } } return NULL; } static char * append (contentline *cline, const char *src, const size_t src_len) { if (src_len > 0) { const size_t len = cline->input_line_len + src_len; while (len >= cline->input_line_size) { cline->input_line_size = cline->input_line_size == 0 ? NMH_BUFSIZ : 2 * cline->input_line_size; cline->input_line = mh_xrealloc (cline->input_line, cline->input_line_size); } memcpy (cline->input_line + cline->input_line_len, src, src_len); cline->input_line[len] = '\0'; cline->input_line_len = len; } return cline->input_line; } static void new_content_line (contentline **cline) { contentline *new_node; NEW0(new_node); if (*cline) { /* Append the new node to the end of the list. */ (*cline)->last->next = new_node; } else { /* First line: save the root node in *cline. */ *cline = new_node; } /* Only maintain the pointer to the last node in the root node. */ (*cline)->last = new_node; } static void new_vevent (vevent *event) { vevent *new_node, *node; NEW0(new_node); /* Append the new node to the end of the list. */ for (node = event; node->next; node = node->next) { continue; } event->last = node->next = new_node; } void add_param_name (contentline *cline, char *name) { param_list *new_node; param_list *p; NEW0(new_node); new_node->param_name = name; if (cline->params) { for (p = cline->params; p->next; p = p->next) { continue; } /* The loop terminated at, not after, the last node. */ p->next = new_node; } else { cline->params = new_node; } } /* * Add a value to the last parameter seen. */ void add_param_value (contentline *cline, char *value) { value_list *new_node; param_list *p; value_list *v; NEW0(new_node); new_node->value = value; if (cline->params) { for (p = cline->params; p->next; p = p->next) { continue; } /* The loop terminated at, not after, the last param_list node. */ if (p->values) { for (v = p->values; v->next; v = v->next) { continue; } /* The loop terminated at, not after, the last value_list node. */ v->next = new_node; } else { p->values = new_node; } } else { /* Never should get here because a param value is always preceded by a param name. */ free (new_node); } } void free_contentlines (contentline *root) { contentline *i, *next; for (i = root; i; i = next) { free (i->name); if (i->params) { free_param_names (i->params); } free (i->value); free (i->input_line); charstring_free (i->unexpected); next = i->next; free (i); } } static void free_param_names (param_list *p) { param_list *next; for ( ; p; p = next) { free (p->param_name); free_param_values (p->values); next = p->next; free (p); } } static void free_param_values (value_list *v) { value_list *next; for ( ; v; v = next) { free (v->value); next = v->next; free (v); } } static int icalerror (const char *error) { contentline *c; charstring_t context = NULL; /* Find last chunk of unexpected text. */ for (c = vevents.last->contentlines; c; c = c->next) { if (c->unexpected) { context = c->unexpected; } } if (! strcmp ("syntax error, unexpected $end, expecting ICAL_NAME", error)) { /* Empty input: produce no output. */ } else { if (context) { inform ("%s after \"%s\"", error, charstring_buffer (context)); } else { inform ("%s", error); } parser_status = -1; return -1; } return 0; /* The return value isn't used anyway. */ } /* * In case YYDEBUG is disabled above; mhical refers to icaldebug. */ #if ! defined YYDEBUG || ! YYDEBUG int icaldebug; #endif /* ! YYDEBUG */ nmh-1.7.1-RC3/sbr/icalparse.h000644 007761 000024 00000004675 12717113566 015711 0ustar00kenhstaff000000 000000 /* A Bison parser, made by GNU Bison 3.0.4. */ /* Bison interface for Yacc-like parsers in C Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ #ifndef YY_YY_SBR_ICALPARSE_H_INCLUDED # define YY_YY_SBR_ICALPARSE_H_INCLUDED /* Debug traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif #if YYDEBUG extern int yydebug; #endif /* Token type. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE enum yytokentype { ICAL_NAME = 258, ICAL_COLON = 259, ICAL_VALUE = 260, ICAL_CRLF = 261, ICAL_SEMICOLON = 262, ICAL_PARAM_NAME = 263, ICAL_EQUAL = 264, ICAL_PARAM_VALUE = 265, ICAL_COMMA = 266 }; #endif /* Tokens. */ #define ICAL_NAME 258 #define ICAL_COLON 259 #define ICAL_VALUE 260 #define ICAL_CRLF 261 #define ICAL_SEMICOLON 262 #define ICAL_PARAM_NAME 263 #define ICAL_EQUAL 264 #define ICAL_PARAM_VALUE 265 #define ICAL_COMMA 266 /* Value type. */ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef int YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define YYSTYPE_IS_DECLARED 1 #endif extern YYSTYPE yylval; int yyparse (void); #endif /* !YY_YY_SBR_ICALPARSE_H_INCLUDED */ nmh-1.7.1-RC3/sbr/icalparse.y000644 007761 000024 00000023625 13243042053 015711 0ustar00kenhstaff000000 000000 /* icalparse.y -- icalendar (RFC 5545) parser * * This code is Copyright (c) 2014, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ %{ /* * Use these yy* #defines, instead of the -p command line * option, to allow multiple parsers in a program. yyval * is generated by Solaris yacc and is of type YYSTYPE. * All other yy* symbols are data of a built-in type and * are initialized by yyparse(), so they can be shared * between different parsers. */ #define yydebug icaldebug #define yyerror icalerror #define yylex icallex #define yylval icallval #define yyval icalval #define yyparse icalparse #define YYDEBUG 1 #define YYERROR_DEBUG #define YYERROR_VERBOSE #define YY_NO_LEAKS /* * To quiet compile warnings with Solaris yacc: #ifdef sun # define lint 1 # undef YYDEBUG #endif */ #include "h/mh.h" #include "h/icalendar.h" #include "h/utils.h" static char *append (contentline *, const char *, const size_t); static void new_content_line (contentline **); static void new_vevent (vevent *); static void free_param_names (param_list *); static void free_param_values (value_list *); static int icalerror (const char *); %} %token ICAL_NAME ICAL_COLON ICAL_VALUE ICAL_CRLF ICAL_SEMICOLON %token ICAL_PARAM_NAME ICAL_EQUAL ICAL_PARAM_VALUE ICAL_COMMA %start contentline_list %% /* Instead of rigorous definition, cheat based on fact that every icalbody line looks like a contentline. And we don't need to parse values. */ contentline_list : contentline | contentline_list contentline /* contentline = name *(";" param ) ":" value CRLF */ contentline : ICAL_NAME { new_content_line (&vevents.last->contentlines); append (vevents.last->contentlines->last, $1, strlen ($1)); vevents.last->contentlines->last->name = $1; } ICAL_COLON { append (vevents.last->contentlines->last, $3, strlen ($3)); } ICAL_VALUE { append (vevents.last->contentlines->last, $5, strlen ($5)); vevents.last->contentlines->last->value = $5; } ICAL_CRLF { append (vevents.last->contentlines->last, $7, strlen ($7)); if (vevents.last->contentlines->cr_before_lf == CR_UNSET) { vevents.last->contentlines->cr_before_lf = $7[0] == '\r' ? CR_BEFORE_LF : LF_ONLY; } /* END:VEVENT doesn't have a param_list so we don't need to check for it below. */ if (vevents.last->contentlines->last->name && vevents.last->contentlines->last->value && ! strcasecmp (vevents.last->contentlines->last->name, "END") && ! strcasecmp (vevents.last->contentlines->last->value, "VEVENT")) { new_vevent (&vevents); } } | ICAL_NAME { new_content_line (&vevents.last->contentlines); append (vevents.last->contentlines->last, $1, strlen ($1)); vevents.last->contentlines->last->name = $1; } param_list ICAL_COLON { append (vevents.last->contentlines->last, $4, strlen ($4)); } ICAL_VALUE { append (vevents.last->contentlines->last, $6, strlen ($6)); vevents.last->contentlines->last->value = $6; } ICAL_CRLF { append (vevents.last->contentlines->last, $8, strlen ($8)); if (vevents.last->contentlines->cr_before_lf == CR_UNSET) { vevents.last->contentlines->cr_before_lf = $8[0] == '\r' ? CR_BEFORE_LF : LF_ONLY; } } param_list : ICAL_SEMICOLON { append (vevents.last->contentlines->last, $1, strlen ($1)); } param | param_list ICAL_SEMICOLON { append (vevents.last->contentlines->last, $2, strlen ($2)); } param /* param = param-name "=" param-value *("," param-value) */ param : ICAL_PARAM_NAME { append (vevents.last->contentlines->last, $1, strlen ($1)); add_param_name (vevents.last->contentlines->last, $1); } ICAL_EQUAL { append (vevents.last->contentlines->last, $3, strlen ($3)); } param_value_list param_value_list : ICAL_PARAM_VALUE { append (vevents.last->contentlines->last, $1, strlen ($1)); add_param_value (vevents.last->contentlines->last, $1); } | param_value_list ICAL_COMMA { append (vevents.last->contentlines->last, $2, strlen ($2)); } ICAL_PARAM_VALUE { append (vevents.last->contentlines->last, $4, strlen ($4)); add_param_value (vevents.last->contentlines->last, $4); } %% /* * Remove the contentline node (by setting its name to NULL). */ void remove_contentline (contentline *node) { free (node->name); node->name = NULL; } contentline * add_contentline (contentline *node, const char *name) { contentline *new_node; NEW0(new_node); new_node->name = mh_xstrdup (name); new_node->next = node->next; node->next = new_node; return new_node; } /* * Remove the value from a value_list. */ void remove_value (value_list *node) { free (node->value); node->value = NULL; } /* * Find the contentline with the specified name, and optionally, * the specified value and/or parameter name. */ contentline * find_contentline (contentline *contentlines, const char *name, const char *val) { contentline *node; for (node = contentlines; node; node = node->next) { /* node->name will be NULL if the line was "deleted". */ if (node->name && ! strcasecmp (name, node->name)) { if (val && node->value) { if (! strcasecmp (val, node->value)) { return node; } } else { return node; } } } return NULL; } static char * append (contentline *cline, const char *src, const size_t src_len) { if (src_len > 0) { const size_t len = cline->input_line_len + src_len; while (len >= cline->input_line_size) { cline->input_line_size = cline->input_line_size == 0 ? NMH_BUFSIZ : 2 * cline->input_line_size; cline->input_line = mh_xrealloc (cline->input_line, cline->input_line_size); } memcpy (cline->input_line + cline->input_line_len, src, src_len); cline->input_line[len] = '\0'; cline->input_line_len = len; } return cline->input_line; } static void new_content_line (contentline **cline) { contentline *new_node; NEW0(new_node); if (*cline) { /* Append the new node to the end of the list. */ (*cline)->last->next = new_node; } else { /* First line: save the root node in *cline. */ *cline = new_node; } /* Only maintain the pointer to the last node in the root node. */ (*cline)->last = new_node; } static void new_vevent (vevent *event) { vevent *new_node, *node; NEW0(new_node); /* Append the new node to the end of the list. */ for (node = event; node->next; node = node->next) { continue; } event->last = node->next = new_node; } void add_param_name (contentline *cline, char *name) { param_list *new_node; param_list *p; NEW0(new_node); new_node->param_name = name; if (cline->params) { for (p = cline->params; p->next; p = p->next) { continue; } /* The loop terminated at, not after, the last node. */ p->next = new_node; } else { cline->params = new_node; } } /* * Add a value to the last parameter seen. */ void add_param_value (contentline *cline, char *value) { value_list *new_node; param_list *p; value_list *v; NEW0(new_node); new_node->value = value; if (cline->params) { for (p = cline->params; p->next; p = p->next) { continue; } /* The loop terminated at, not after, the last param_list node. */ if (p->values) { for (v = p->values; v->next; v = v->next) { continue; } /* The loop terminated at, not after, the last value_list node. */ v->next = new_node; } else { p->values = new_node; } } else { /* Never should get here because a param value is always preceded by a param name. */ free (new_node); } } void free_contentlines (contentline *root) { contentline *i, *next; for (i = root; i; i = next) { free (i->name); if (i->params) { free_param_names (i->params); } free (i->value); free (i->input_line); charstring_free (i->unexpected); next = i->next; free (i); } } static void free_param_names (param_list *p) { param_list *next; for ( ; p; p = next) { free (p->param_name); free_param_values (p->values); next = p->next; free (p); } } static void free_param_values (value_list *v) { value_list *next; for ( ; v; v = next) { free (v->value); next = v->next; free (v); } } static int icalerror (const char *error) { contentline *c; charstring_t context = NULL; /* Find last chunk of unexpected text. */ for (c = vevents.last->contentlines; c; c = c->next) { if (c->unexpected) { context = c->unexpected; } } if (! strcmp ("syntax error, unexpected $end, expecting ICAL_NAME", error)) { /* Empty input: produce no output. */ } else { if (context) { inform ("%s after \"%s\"", error, charstring_buffer (context)); } else { inform ("%s", error); } parser_status = -1; return -1; } return 0; /* The return value isn't used anyway. */ } /* * In case YYDEBUG is disabled above; mhical refers to icaldebug. */ #if ! defined YYDEBUG || ! YYDEBUG int icaldebug; #endif /* ! YYDEBUG */ nmh-1.7.1-RC3/sbr/lock_file.c000644 007761 000024 00000036455 13243042053 015654 0ustar00kenhstaff000000 000000 /* lock_file.c -- routines to lock/unlock files * * 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. */ /* Modified by Ruud de Rooij to support Miquel van Smoorenburg's liblockfile * * Since liblockfile locking shares most of its code with dot locking, it * is enabled by defining both DOT_LOCKING and HAVE_LIBLOCKFILE. * * Ruud de Rooij Sun, 28 Mar 1999 15:34:03 +0200 */ #include #include #include #include #include "lock_file.h" #include "m_mktemp.h" #ifdef HAVE_SYS_TIME_H # include #endif #include #include #ifdef HAVE_FLOCK # include #endif #if defined(HAVE_LIBLOCKFILE) # include #endif #ifdef LOCKDIR char *lockdir = LOCKDIR; #endif /* struct for getting name of lock file to create */ struct lockinfo { char curlock[BUFSIZ]; #if !defined(HAVE_LIBLOCKFILE) char tmplock[BUFSIZ]; #endif }; /* * Number of tries to retry locking */ #define LOCK_RETRIES 60 /* * Amount of time to wait before * updating ctime of lock file. */ #define NSECS 20 #if !defined(HAVE_LIBLOCKFILE) /* * How old does a lock file need to be * before we remove it. */ #define RSECS 180 #endif /* HAVE_LIBLOCKFILE */ /* struct for recording and updating locks */ struct lock { int l_fd; char *l_lock; struct lock *l_next; }; enum locktype { FCNTL_LOCKING, FLOCK_LOCKING, LOCKF_LOCKING, DOT_LOCKING }; /* Our saved lock types. */ static enum locktype datalocktype, spoollocktype; /* top of list containing all open locks */ static struct lock *l_top = NULL; static int lkopen(const char *, int, mode_t, enum locktype, int *); static int str2accbits(const char *); static int lkopen_fcntl (const char *, int, mode_t, int *); #ifdef HAVE_LOCKF static int lkopen_lockf (const char *, int, mode_t, int *); #endif /* HAVE_LOCKF */ #ifdef HAVE_FLOCK static int lkopen_flock (const char *, int, mode_t, int *); #endif /* HAVE_FLOCK */ static enum locktype init_locktype(const char *); static int lkopen_dot (const char *, int, mode_t, int *); static void lkclose_dot (int, const char *); static void lockname (const char *, struct lockinfo *, int); static void timerON (char *, int); static void timerOFF (int); static void alrmser (int); #if !defined(HAVE_LIBLOCKFILE) static int lockit (struct lockinfo *); #endif /* * Base functions: determine the data type used to lock files and * call the underlying function. */ int lkopendata(const char *file, int access, mode_t mode, int *failed_to_lock) { static bool deja_vu; if (!deja_vu) { char *dl; deja_vu = true; if ((dl = context_find("datalocking"))) { datalocktype = init_locktype(dl); } else { /* We default to fcntl locking for data files */ datalocktype = FCNTL_LOCKING; } } return lkopen(file, access, mode, datalocktype, failed_to_lock); } /* * Locking using the spool locking algorithm */ int lkopenspool(const char *file, int access, mode_t mode, int *failed_to_lock) { static bool deja_vu; if (!deja_vu) { deja_vu = true; spoollocktype = init_locktype(spoollocking); } return lkopen(file, access, mode, spoollocktype, failed_to_lock); } /* * Versions of lkopen that return a FILE * */ FILE * lkfopendata(const char *file, const char *mode, int *failed_to_lock) { FILE *fp; int oflags = str2accbits(mode); int fd; if (oflags == -1) { errno = EINVAL; return NULL; } if ((fd = lkopendata(file, oflags, 0666, failed_to_lock)) == -1) return NULL; if ((fp = fdopen (fd, mode)) == NULL) { close (fd); return NULL; } return fp; } FILE * lkfopenspool(const char *file, const char *mode) { FILE *fp; int oflags = str2accbits(mode); int failed_to_lock = 0; int fd; if (oflags == -1) { errno = EINVAL; return NULL; } if ((fd = lkopenspool(file, oflags, 0666, &failed_to_lock)) == -1) return NULL; if ((fp = fdopen (fd, mode)) == NULL) { close (fd); return NULL; } return fp; } /* * Corresponding close functions. * * A note here: All of the kernel locking functions terminate the lock * when the descriptor is closed, so why write the code to explicitly * unlock the file? We only need to do this in the dot-locking case. */ int lkclosedata(int fd, const char *name) { int rc = close(fd); if (datalocktype == DOT_LOCKING) lkclose_dot(fd, name); return rc; } int lkfclosedata(FILE *f, const char *name) { int fd, rc; if (f == NULL) return 0; fd = fileno(f); rc = fclose(f); if (datalocktype == DOT_LOCKING) lkclose_dot(fd, name); return rc; } int lkclosespool(int fd, const char *name) { int rc = close(fd); if (spoollocktype == DOT_LOCKING) lkclose_dot(fd, name); return rc; } int lkfclosespool(FILE *f, const char *name) { int fd, rc; if (f == NULL) return 0; fd = fileno(f); rc = fclose(f); if (spoollocktype == DOT_LOCKING) lkclose_dot(fd, name); return rc; } /* * Convert fopen() mode argument to open() bits */ static int str2accbits(const char *mode) { if (strcmp (mode, "r") == 0) return O_RDONLY; if (strcmp (mode, "r+") == 0) return O_RDWR; if (strcmp (mode, "w") == 0) return O_WRONLY | O_CREAT | O_TRUNC; if (strcmp (mode, "w+") == 0) return O_RDWR | O_CREAT | O_TRUNC; if (strcmp (mode, "a") == 0) return O_WRONLY | O_CREAT | O_APPEND; if (strcmp (mode, "a+") == 0) return O_RDWR | O_CREAT | O_APPEND; errno = EINVAL; return -1; } /* * Internal routine to switch between different locking types. */ static int lkopen (const char *file, int access, mode_t mode, enum locktype ltype, int *failed_to_lock) { switch (ltype) { case FCNTL_LOCKING: return lkopen_fcntl(file, access, mode, failed_to_lock); case DOT_LOCKING: return lkopen_dot(file, access, mode, failed_to_lock); #ifdef HAVE_FLOCK case FLOCK_LOCKING: return lkopen_flock(file, access, mode, failed_to_lock); #endif /* HAVE_FLOCK */ #ifdef HAVE_LOCKF case LOCKF_LOCKING: return lkopen_lockf(file, access, mode, failed_to_lock); #endif /* HAVE_FLOCK */ default: adios(NULL, "Internal locking error: unsupported lock type used!"); } return -1; } /* * Routine to clean up the dot locking file */ static void lkclose_dot (int fd, const char *file) { struct lockinfo lkinfo; lockname (file, &lkinfo, 0); /* get name of lock file */ #if !defined(HAVE_LIBLOCKFILE) (void) m_unlink (lkinfo.curlock); /* remove lock file */ #else lockfile_remove(lkinfo.curlock); #endif /* HAVE_LIBLOCKFILE */ timerOFF (fd); /* turn off lock timer */ } /* * Open and lock a file, using fcntl locking */ static int lkopen_fcntl(const char *file, int access, mode_t mode, int *failed_to_lock) { int fd, i, saved_errno; struct flock flk; /* * The assumption here is that if you open the file for writing, you * need an exclusive lock. */ for (i = 0; i < LOCK_RETRIES; i++) { if ((fd = open(file, access, mode)) == -1) return -1; flk.l_start = 0; flk.l_len = 0; flk.l_type = (access & O_ACCMODE) == O_RDONLY ? F_RDLCK : F_WRLCK; flk.l_whence = SEEK_SET; if (fcntl(fd, F_SETLK, &flk) != -1) return fd; saved_errno = errno; close(fd); sleep(1); } *failed_to_lock = 1; errno = saved_errno; return -1; } #ifdef HAVE_FLOCK /* * Open and lock a file, using flock locking */ static int lkopen_flock(const char *file, int access, mode_t mode, int *failed_to_lock) { int fd, i, saved_errno, locktype; /* * The assumption here is that if you open the file for writing, you * need an exclusive lock. */ locktype = (((access & O_ACCMODE) == O_RDONLY) ? LOCK_SH : LOCK_EX) | LOCK_NB; for (i = 0; i < LOCK_RETRIES; i++) { if ((fd = open(file, access, mode)) == -1) return -1; if (flock(fd, locktype) != -1) return fd; saved_errno = errno; close(fd); sleep(1); } *failed_to_lock = 1; errno = saved_errno; return -1; } #endif /* HAVE_FLOCK */ /* * Open and lock a file, using lockf locking */ static int lkopen_lockf(const char *file, int access, mode_t mode, int *failed_to_lock) { int fd, i, saved_errno, saved_access; /* * Two notes: * * Because lockf locks start from the current offset, mask off O_APPEND * and seek to the end of the file later if it was requested. * * lockf locks require write access to the file, so always add it * even if it wasn't requested. */ saved_access = access; access &= ~O_APPEND; if ((access & O_ACCMODE) == O_RDONLY) { access &= ~O_RDONLY; access |= O_RDWR; } for (i = 0; i < LOCK_RETRIES; i++) { if ((fd = open(file, access, mode)) == -1) return -1; if (lockf(fd, F_TLOCK, 0) != -1) { /* * Seek to end if requested */ if (saved_access & O_APPEND) { lseek(fd, 0, SEEK_END); } return fd; } saved_errno = errno; close(fd); sleep(1); } *failed_to_lock = 1; errno = saved_errno; return -1; } /* * open and lock a file, using dot locking */ static int lkopen_dot (const char *file, int access, mode_t mode, int *failed_to_lock) { int fd; struct lockinfo lkinfo; /* open the file */ if ((fd = open (file, access, mode)) == -1) return -1; /* * Get the name of the eventual lock file, as well * as a name for a temporary lock file. */ lockname (file, &lkinfo, 1); #if !defined(HAVE_LIBLOCKFILE) { int i; for (i = 0; i < LOCK_RETRIES; ++i) { struct stat st; /* attempt to create lock file */ if (lockit (&lkinfo) == 0) { /* if successful, turn on timer and return */ timerON (lkinfo.curlock, fd); return fd; } /* * Abort locking, if we fail to lock after 5 attempts * and are never able to stat the lock file. Or, if * we can stat the lockfile but exceed LOCK_RETRIES * seconds waiting for it (by falling out of the loop). */ if (stat (lkinfo.curlock, &st) == -1) { if (i++ > 5) break; sleep (1); } else { time_t curtime; time (&curtime); /* check for stale lockfile, else sleep */ if (curtime > st.st_ctime + RSECS) (void) m_unlink (lkinfo.curlock); else sleep (1); } lockname (file, &lkinfo, 1); } *failed_to_lock = 1; return -1; } #else if (lockfile_create(lkinfo.curlock, 5, 0) == L_SUCCESS) { timerON(lkinfo.curlock, fd); return fd; } close(fd); *failed_to_lock = 1; return -1; #endif /* HAVE_LIBLOCKFILE */ } #if !defined(HAVE_LIBLOCKFILE) /* * Routine that actually tries to create * the lock file. */ static int lockit (struct lockinfo *li) { int fd; char *curlock, *tmpfile; #if 0 char buffer[128]; #endif curlock = li->curlock; if ((tmpfile = m_mktemp(li->tmplock, &fd, NULL)) == NULL) { inform("unable to create temporary file in %s", li->tmplock); return -1; } #if 0 /* write our process id into lock file */ snprintf (buffer, sizeof(buffer), "nmh lock: pid %d\n", (int) getpid()); write(fd, buffer, strlen(buffer) + 1); #endif close (fd); /* * Now try to create the real lock file * by linking to the temporary file. */ fd = link(tmpfile, curlock); (void) m_unlink(tmpfile); return (fd == -1 ? -1 : 0); } #endif /* HAVE_LIBLOCKFILE */ /* * Get name of lock file, and temporary lock file */ static void lockname (const char *file, struct lockinfo *li, int isnewlock) { int bplen, tmplen; char *bp; const char *cp; #if 0 struct stat st; #endif if ((cp = strrchr (file, '/')) == NULL || *++cp == 0) cp = file; bp = li->curlock; bplen = 0; #ifdef LOCKDIR snprintf (bp, sizeof(li->curlock), "%s/", lockdir); tmplen = strlen (bp); bp += tmplen; bplen += tmplen; #else if (cp != file) { snprintf (bp, sizeof(li->curlock), "%.*s", (int)(cp - file), file); tmplen = strlen (bp); bp += tmplen; bplen += tmplen; } #endif #if 0 /* * mmdf style dot locking. Currently not supported. * If we start supporting mmdf style dot locking, * we will need to change the return value of lockname */ if (stat (file, &st) == -1) return -1; snprintf (bp, sizeof(li->curlock) - bplen, "LCK%05d.%05d", st.st_dev, st.st_ino); #endif snprintf (bp, sizeof(li->curlock) - bplen, "%s.lock", cp); #if defined(HAVE_LIBLOCKFILE) NMH_UNUSED(isnewlock); #else /* * If this is for a new lock, create a name for * the temporary lock file for lockit() */ if (isnewlock) { if ((cp = strrchr (li->curlock, '/')) == NULL || *++cp == 0) strncpy (li->tmplock, ",LCK.XXXXXX", sizeof(li->tmplock)); else snprintf (li->tmplock, sizeof(li->tmplock), "%.*s,LCK.XXXXXX", (int)(cp - li->curlock), li->curlock); } #endif } /* * Add new lockfile to the list of open lockfiles * and start the lock file timer. */ static void timerON (char *curlock, int fd) { struct lock *lp; NEW(lp); lp->l_lock = mh_xstrdup(curlock); lp->l_fd = fd; lp->l_next = l_top; if (!l_top) { /* perhaps SIGT{STP,TIN,TOU} ? */ SIGNAL (SIGALRM, alrmser); alarm (NSECS); } l_top = lp; } /* * Search through the list of lockfiles for the * current lockfile, and remove it from the list. */ static void timerOFF (int fd) { struct lock *pp, *lp; alarm(0); if (l_top) { for (pp = lp = l_top; lp; pp = lp, lp = lp->l_next) { if (lp->l_fd == fd) break; } if (lp) { if (lp == l_top) l_top = lp->l_next; else pp->l_next = lp->l_next; free (lp->l_lock); free (lp); } } /* if there are locks left, restart timer */ if (l_top) alarm (NSECS); } /* * If timer goes off, we update the ctime of all open * lockfiles, so another command doesn't remove them. */ static void alrmser (int sig) { char *lockfile; struct lock *lp; NMH_UNUSED (sig); /* update the ctime of all the lock files */ for (lp = l_top; lp; lp = lp->l_next) { lockfile = lp->l_lock; #if !defined(HAVE_LIBLOCKFILE) { int j; if (*lockfile && (j = creat (lockfile, 0600)) != -1) close (j); } #else lockfile_touch(lockfile); #endif } /* restart the alarm */ alarm (NSECS); } /* * Return a locking algorithm based on the string name */ static enum locktype init_locktype(const char *lockname) { if (strcasecmp(lockname, "fcntl") == 0) { return FCNTL_LOCKING; } if (strcasecmp(lockname, "lockf") == 0) { #ifdef HAVE_LOCKF return LOCKF_LOCKING; #else /* ! HAVE_LOCKF */ adios(NULL, "lockf not supported on this system"); #endif /* HAVE_LOCKF */ } if (strcasecmp(lockname, "flock") == 0) { #ifdef HAVE_FLOCK return FLOCK_LOCKING; #else /* ! HAVE_FLOCK */ adios(NULL, "flock not supported on this system"); #endif /* HAVE_FLOCK */ } if (strcasecmp(lockname, "dot") == 0) { return DOT_LOCKING; } adios(NULL, "Unknown lock type: \"%s\"", lockname); /* NOTREACHED */ return 0; } nmh-1.7.1-RC3/sbr/lock_file.h000644 007761 000024 00000002376 13205305704 015657 0ustar00kenhstaff000000 000000 /* lock_file.h -- lock and unlock files. * * This code is Copyright (c) 2017, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ /* * Lock open/close routines. * * The lk[f]opendata() functions are designed to open "data" files (anything * not a mail spool file) using the locking mechanism configured for data * files. The lk[f]openspool() functions are for opening the mail spool * file, which will use the locking algorithm configured for the mail * spool. * * Files opened for reading are locked with a read lock (if possible by * the underlying lock mechanism), files opened for writing are locked * using an exclusive lock. The int * argument is used to indicate failure * to acquire a lock. */ int lkopendata(const char *file, int access, mode_t mode, int *failed_to_lock); int lkopenspool(const char *file, int access, mode_t mode, int *failed_to_lock); FILE *lkfopendata(const char *file, const char *mode, int *failed_to_lock); FILE *lkfopenspool(const char *file, const char *mode); int lkclosedata(int fd, const char *name); int lkfclosedata(FILE *f, const char *name); int lkclosespool(int fd, const char *name); int lkfclosespool(FILE *f, const char *name); nmh-1.7.1-RC3/sbr/m_atoi.c000644 007761 000024 00000001127 13243042053 015161 0ustar00kenhstaff000000 000000 /* m_atoi.c -- Parse a string representation of a message number, and * -- return the numeric value of the message. If the string * -- contains any non-digit characters, then return 0. * * 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 int m_atoi (char *str) { int i; char *cp; for (i = 0, cp = str; *cp; cp++) { if (!isdigit((unsigned char) *cp)) return 0; i *= 10; i += (*cp - '0'); } return i; } nmh-1.7.1-RC3/sbr/m_backup.c000644 007761 000024 00000001155 13243042053 015473 0ustar00kenhstaff000000 000000 /* m_backup.c -- construct a backup file * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include "m_mktemp.h" char * m_backup (const char *file) { const char *cp; static char buffer[BUFSIZ]; if ((cp = r1bindex((char *) file, '/')) == file) snprintf(buffer, sizeof(buffer), "%s%s", BACKUP_PREFIX, cp); else snprintf(buffer, sizeof(buffer), "%.*s%s%s", (int)(cp - file), file, BACKUP_PREFIX, cp); (void) m_unlink(buffer); return buffer; } nmh-1.7.1-RC3/sbr/m_convert.c000644 007761 000024 00000024632 13243042053 015713 0ustar00kenhstaff000000 000000 /* m_convert.c -- parse a message range or sequence and set SELECTED * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include /* * error codes for sequence * and message range processing */ #define BADMSG (-2) #define BADRNG (-3) #define BADNEW (-4) #define BADNUM (-5) #define BADLST (-6) #define FIRST 1 #define LAST 2 #define getnew(mp) (mp->hghmsg + 1) static int convdir; /* convert direction */ static char *delimp; /* * static prototypes */ static int m_conv (struct msgs *, char *, int); static int attr (struct msgs *, char *); int m_convert (struct msgs *mp, char *name) { int first, last, found, count, is_range, err; char *bp, *cp; /* check if user defined sequence */ err = attr (mp, cp = name); if (err == -1) return 0; if (err < 0) goto badmsg; if (err > 0) return 1; /* * else err == 0, so continue */ found = 0; is_range = 1; /* * Check for special "new" sequence, which * is valid only if ALLOW_NEW is set. */ if ((mp->msgflags & ALLOW_NEW) && !strcmp (cp, "new")) { if ((err = first = getnew (mp)) <= 0) goto badmsg; goto single; } if (!strcmp (cp, "all")) cp = "first-last"; if ((err = first = m_conv (mp, cp, FIRST)) <= 0) goto badmsg; cp = delimp; if (*cp != '\0' && *cp != '-' && *cp != ':' && *cp != '=') { badelim: inform("illegal argument delimiter: `%c'(0%o)", *delimp, *delimp); return 0; } if (*cp == '-') { cp++; if ((err = last = m_conv (mp, cp, LAST)) <= 0) { badmsg: switch (err) { case BADMSG: inform("no %s message", cp); break; case BADNUM: inform("message %s doesn't exist", cp); break; case BADRNG: inform("message %s out of range 1-%d", cp, mp->hghmsg); break; case BADLST: badlist: inform("bad message list %s", name); break; case BADNEW: inform("folder full, no %s message", name); break; default: inform("no messages match specification"); } return 0; } if (last < first) goto badlist; if (*delimp) goto badelim; if (first > mp->hghmsg || last < mp->lowmsg) { rangerr: inform("no messages in range %s", name); return 0; } /* tighten the range to search */ if (last > mp->hghmsg) last = mp->hghmsg; if (first < mp->lowmsg) first = mp->lowmsg; } else if (*cp == ':' || *cp == '=') { if (*cp == '=') is_range = 0; cp++; if (*cp == '-') { /* foo:-3 or foo=-3 */ convdir = -1; cp++; } else if (*cp == '+') { /* foo:+3 or foo=+3 is same as foo:3 or foo=3 */ convdir = 1; cp++; } if ((count = atoi (bp = cp)) == 0) goto badlist; while (isdigit ((unsigned char) *bp)) bp++; if (*bp) goto badelim; if ((convdir > 0 && first > mp->hghmsg) || (convdir < 0 && first < mp->lowmsg)) goto rangerr; /* tighten the range to search */ if (first < mp->lowmsg) first = mp->lowmsg; if (first > mp->hghmsg) first = mp->hghmsg; for (last = first; last >= mp->lowmsg && last <= mp->hghmsg; last += convdir) if (does_exist (mp, last)) if (--count <= 0) break; if (is_range) { /* a range includes any messages that exist */ if (last < mp->lowmsg) last = mp->lowmsg; if (last > mp->hghmsg) last = mp->hghmsg; if (last < first) { count = last; last = first; first = count; } } else { /* looking for the nth message. if not enough, fail. */ if (last < mp->lowmsg || last > mp->hghmsg) { inform("no such message"); return 0; } first = last; } } else { single: /* * Single Message * * If ALLOW_NEW is set, then allow selecting of an * empty slot. If ALLOW_NEW is not set, then we * 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, min(first, mp->lowoff), max(first, mp->hghoff)); set_select_empty (mp, first); } else { if (first > mp->hghmsg || first < mp->lowmsg || !(does_exist (mp, first))) { if (!strcmp (name, "cur") || !strcmp (name, ".")) inform("no %s message", name); else inform("message %d doesn't exist", first); return 0; } } last = first; /* range of 1 */ } /* * Cycle through the range and select the messages * that exist. If ALLOW_NEW is set, then we also check * if we are selecting an empty slot. */ for (; first <= last; first++) { if (does_exist (mp, first) || ((mp->msgflags & ALLOW_NEW) && is_select_empty (mp, first))) { if (!is_selected (mp, first)) { set_selected (mp, first); mp->numsel++; if (mp->lowsel == 0 || first < mp->lowsel) mp->lowsel = first; if (first > mp->hghsel) mp->hghsel = first; } found++; } } if (!found) goto rangerr; return 1; } /* * Convert the various message names to * their numeric values. * * n (integer) * prev * next * first * last * cur * . (same as cur) */ static int m_conv (struct msgs *mp, char *str, int call) { int i; char *cp, *bp; char buf[16]; convdir = 1; cp = bp = str; if (isdigit ((unsigned char) *cp)) { while (isdigit ((unsigned char) *bp)) bp++; delimp = bp; i = atoi (cp); if (i <= mp->hghmsg) return i; if (*delimp || call == LAST) return mp->hghmsg + 1; if (mp->msgflags & ALLOW_NEW) return BADRNG; return BADNUM; } /* doesn't enforce lower case */ for (bp = buf; (isalpha((unsigned char) *cp) || *cp == '.') && (bp - buf < (int) sizeof(buf) - 1); ) { *bp++ = *cp++; } *bp++ = '\0'; delimp = cp; if (!strcmp (buf, "first")) return (mp->hghmsg || !(mp->msgflags & ALLOW_NEW) ? mp->lowmsg : BADMSG); if (!strcmp (buf, "last")) { convdir = -1; return (mp->hghmsg || !(mp->msgflags & ALLOW_NEW) ? mp->hghmsg : BADMSG); } if (!strcmp (buf, "cur") || !strcmp (buf, ".")) return (mp->curmsg > 0 ? mp->curmsg : BADMSG); if (!strcmp (buf, "prev")) { convdir = -1; for (i = (mp->curmsg <= mp->hghmsg) ? mp->curmsg - 1 : mp->hghmsg; i >= mp->lowmsg; i--) { if (does_exist (mp, i)) return i; } return BADMSG; } if (!strcmp (buf, "next")) { for (i = (mp->curmsg >= mp->lowmsg) ? mp->curmsg + 1 : mp->lowmsg; i <= mp->hghmsg; i++) { if (does_exist (mp, i)) return i; } return BADMSG; } return BADLST; } /* * Handle user defined sequences. * They can take the following forms: * * seq * seq:prev * seq:next * seq:first * seq:last * seq:+n * seq:-n * seq:n */ static int attr (struct msgs *mp, char *cp) { char *dp; char *bp = NULL; char *ep; char op; int i, j; int found, inverted = 0, count = 0, /* range given? else use entire sequence */ just_one = 0, /* want entire sequence or range */ first = 0, start = 0; /* hack for "cur-name", "cur-n", etc. */ if (!strcmp (cp, "cur")) return 0; if (has_prefix(cp, "cur")) { if (cp[3] == ':' || cp[3] == '=') return 0; } /* Check for sequence negation */ if ((dp = context_find (nsequence)) && *dp != '\0' && ssequal (dp, cp)) { inverted = 1; cp += strlen (dp); } convdir = 1; /* convert direction */ for (dp = cp; *dp && isalnum((unsigned char) *dp); dp++) continue; if (*dp == ':') { bp = dp++; count = 1; /* * seq:prev (or) * seq:next (or) * seq:first (or) * seq:last */ if (isalpha ((unsigned char) *dp)) { if (!strcmp (dp, "prev")) { convdir = -1; first = (mp->curmsg > 0) && (mp->curmsg <= mp->hghmsg) ? mp->curmsg - 1 : mp->hghmsg; start = first; } else if (!strcmp (dp, "next")) { convdir = 1; first = (mp->curmsg >= mp->lowmsg) ? mp->curmsg + 1 : mp->lowmsg; start = first; } else if (!strcmp (dp, "first")) { convdir = 1; start = mp->lowmsg; } else if (!strcmp (dp, "last")) { convdir = -1; start = mp->hghmsg; } else { return BADLST; } } else { /* * seq:n (or) * seq:+n (or) * seq:-n */ if (*dp == '+') { /* foo:+3 is same as foo:3 */ dp++; convdir = 1; start = mp->lowmsg; } else if (*dp == '-' || *dp == ':') { /* foo:-3 or foo::3 */ dp++; convdir = -1; start = mp->hghmsg; } count = strtol(dp,&ep,10); if (count == 0 || *ep) /* 0 illegal */ return BADLST; } op = *bp; *bp = '\0'; /* temporarily terminate sequence name */ } else if (*dp == '=') { bp = dp++; if (*dp == '+') { /* foo=+3 is same as foo=3 */ dp++; convdir = 1; start = mp->lowmsg; } else if (*dp == '-') { /* foo=-3 */ dp++; convdir = -1; start = mp->hghmsg; } count = strtol(dp,&ep,10); /* 0 illegal */ if (count == 0 || *ep) return BADLST; just_one = 1; op = *bp; *bp = '\0'; /* temporarily terminate sequence name */ } i = seq_getnum (mp, cp); /* get index of sequence */ if (bp) *bp = op; /* restore sequence name */ if (i == -1) return 0; found = 0; /* count the number we select for this argument */ if (!start) start = mp->lowmsg; for (j = start; j >= mp->lowmsg && j <= mp->hghmsg; j += convdir) { if (does_exist (mp, j) && inverted ? !in_sequence (mp, i, j) : in_sequence (mp, i, j)) { found++; /* we want all that we find, or just the last in the +/_ case */ if (!just_one || found >= count) { if (!is_selected (mp, j)) { set_selected (mp, j); mp->numsel++; if (mp->lowsel == 0 || j < mp->lowsel) mp->lowsel = j; if (j > mp->hghsel) mp->hghsel = j; } } /* * If we have any sort of limit, then break out * once we've found enough. */ if (count && found >= count) break; } } if (mp->numsel > 0) return mp->numsel; if (first || just_one) return BADMSG; inform("sequence %s %s", cp, inverted ? "full" : "empty"); return -1; } nmh-1.7.1-RC3/sbr/m_draft.c000644 007761 000024 00000004531 13243042053 015327 0ustar00kenhstaff000000 000000 /* m_draft.c -- construct the name of a draft message * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include "m_maildir.h" char * m_draft (char *folder, char *msg, int use, int *isdf) { char *cp; struct msgs *mp; static char buffer[BUFSIZ]; if (*isdf == -1 || folder == NULL || *folder == '\0') { if (*isdf == -1 || (cp = context_find ("Draft-Folder")) == NULL) { *isdf = 0; return m_maildir (msg && *msg ? msg : draft); } folder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp, *cp != '@' ? TFOLDER : TSUBCWF); } *isdf = 1; if (chdir (m_maildir ("")) < 0) { advise (m_maildir (""), "chdir"); } strncpy (buffer, m_maildir (folder), sizeof(buffer)); create_folder (buffer, 0, done); if (chdir (buffer) == -1) adios (buffer, "unable to change directory to"); if (!(mp = folder_read (folder, 1))) adios (NULL, "unable to read folder %s", folder); /* * Make sure we have enough message status space for all * the message numbers from 1 to "new", since we might * select an empty slot. If we add more space at the * end, go ahead and add 10 additional slots. */ if (mp->hghmsg >= mp->hghoff) { if (!(mp = folder_realloc (mp, 1, mp->hghmsg + 10))) adios (NULL, "unable to allocate folder storage"); } else if (mp->lowoff > 1) { if (!(mp = folder_realloc (mp, 1, mp->hghoff))) adios (NULL, "unable to allocate folder storage"); } mp->msgflags |= ALLOW_NEW; /* allow the "new" sequence */ /* * If we have been give a valid message name, then use that. * Else, if we are given the "use" option, then use the * current message. Else, use special sequence "new". */ if (!m_convert (mp, msg && *msg ? msg : use ? "cur" : "new")) done (1); seq_setprev (mp); if (mp->numsel > 1) adios (NULL, "only one message draft at a time!"); snprintf (buffer, sizeof(buffer), "%s/%s", mp->foldpath, m_name (mp->lowsel)); cp = buffer; seq_setcur (mp, mp->lowsel);/* set current message for folder */ seq_save (mp); /* synchronize message sequences */ folder_free (mp); /* free folder/message structure */ return cp; } nmh-1.7.1-RC3/sbr/m_getfld.c000644 007761 000024 00000074544 13243042053 015507 0ustar00kenhstaff000000 000000 /* m_getfld.c -- read/parse a message * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include /* 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 and scan when reading from a maildrop file. 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: char **pat_map char *fdelim char *delimend int fdelimlen char *edelim int edelimlen char *msg_delim int msg_style 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 newline. Unfortunately, MMDF will convert this delimiter *inside* a message to a CTRL-B followed by three CTRL-A:s and a newline. This caused the old version of m_getfld() to declare eom prematurely. The fix was a lot slower than c == '\001' && peekc (iob) == '\001' but it worked, and to increase generality, MBOX style maildrops could be parsed as well. Unfortunately the speed issue finally caught up with us since this routine is at the very heart of MH. To speed things up considerably, the routine Eom() was made an auxiliary function called by the macro eom(). Unless we are bursting a maildrop, the eom() macro returns FALSE saying we aren't at the end of the message. The next thing to do is to read the mts.conf file and initialize delimiter[] and delimlen accordingly... After mhl was made a built-in in msh, m_getfld() worked just fine (using m_unknown() at startup). Until one day: a message which was the result of a bursting was shown. Then, since the burst boundaries aren't CTRL-A:s, m_getfld() would blinding plunge on past the boundary. Very sad. The solution: introduce m_eomsbr(). This hook gets called after the end of each line (since testing for eom involves an fseek()). This worked fine, until one day: a message with no body portion arrived. Then the while (eom (c = Getc (iob), iob)) continue; loop caused m_getfld() to return FMTERR. So, that logic was changed to check for (*eom_action) and act accordingly. This worked fine, until one day: someone didn't use four CTRL:A's as their delimiters. So, the bullet got bit and we read mts.h and continue to struggle on. It's not that bad though, since the only time the code gets executed is when inc (or msh) calls it, and both of these have already called mts_init(). ------------------------ (Written by Van Jacobson for the mh6 m_getfld, January, 1986): This routine was accounting for 60% of the cpu time used by most mh programs. I spent a bit of time tuning and it now accounts for <10% of the time used. Like any heavily tuned routine, it's a bit complex and you want to be sure you understand everything that it's doing before you start hacking on it. Let me try to emphasize that: every line in this atrocity depends on every other line, sometimes in subtle ways. You should understand it all, in detail, before trying to change any part. If you do change it, test the result thoroughly (I use a hand-constructed test file that exercises all the ways a header name, header body, header continuation, header-body separator, body line and body eom can align themselves with respect to a buffer boundary). "Minor" bugs in this routine result in garbaged or lost mail. If you hack on this and slow it down, I, my children and my children's children will curse you. This routine gets used on three different types of files: normal, single msg files, "packed" unix or mmdf mailboxs (when used by inc) and packed, directoried bulletin board files (when used by msh). The biggest impact of different file types is in "eom" testing. The code has been carefully organized to test for eom at appropriate times and at no other times (since the check is quite expensive). I have tried to arrange things so that the eom check need only be done on entry to this routine. Since an eom can only occur after a newline, this is easy to manage for header fields. For the msg body, we try to efficiently search the input buffer to see if contains the eom delimiter. If it does, we take up to the delimiter, otherwise we take everything in the buffer. (The change to the body eom/copy processing produced the most noticeable performance difference, particularly for "inc" and "show".) There are three qualitatively different things this routine busts out of a message: field names, field text and msg bodies. Field names are typically short (~8 char) and the loop that extracts them might terminate on a colon, newline or max width. I considered using a Vax "scanc" to locate the end of the field followed by a "memmove" but the routine call overhead on a Vax is too large for this to work on short names. If Berkeley ever makes "inline" part of the C optimiser (so things like "scanc" turn into inline instructions) a change here would be worthwhile. Field text is typically 60 - 100 characters so there's (barely) a win in doing a routine call to something that does a "locc" followed by a "bmove". About 30% of the fields have continuations (usually the 822 "received:" lines) and each continuation generates another routine call. "Inline" would be a big win here, as well. Messages, as of this writing, seem to come in two flavors: small (~1K) and long (>2K). Most messages have 400 - 600 bytes of headers so message bodies average at least a few hundred characters. Assuming your system uses reasonably sized stdio buffers (1K or more), this routine should be able to remove the body in large (>500 byte) chunks. The makes the cost of a call to "memmove" small but there is a premium on checking for the eom in packed maildrops. The eom pattern is always a simple string so we can construct an efficient pattern matcher for it (e.g., a Vax "matchc" instruction). Some thought went into recognizing the start of an eom that has been split across two buffers. This routine wants to deal with large chunks of data so, rather than "getc" into a local buffer, it uses stdio's buffer. If you try to use it on a non-buffered file, you'll get what you deserve. This routine "knows" that struct FILEs have a _ptr and a _cnt to describe the current state of the buffer and 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 should complain to the vendor. As a consequence of the sticky EOF, this routine will never return any kind of EOF status when there is data in "name" or "buf"). */ /* * static prototypes */ static int m_Eom (m_getfld_state_t); #define eom(c,s) (s->msg_style != MS_DEFAULT && \ ((c) == *s->msg_delim && m_Eom(s))) /* * Maildrop styles */ #define MS_DEFAULT 0 /* default (one msg per file) */ #define MS_UNKNOWN 1 /* type not known yet */ #define MS_MBOX 2 /* Unix-style "from" lines */ #define MS_MMDF 3 /* string MMDF_DELIM */ /* 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 8192. */ #define MSG_INPUT_SIZE NMH_BUFSIZ #define MAX_DELIMITER_SIZE 5 struct m_getfld_state { char msg_buf[2 * MSG_INPUT_SIZE + MAX_DELIMITER_SIZE]; char *readpos; 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(). bytes_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; 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; char *fdelim; char *delimend; int fdelimlen; char *edelim; int edelimlen; int state; int track_filepos; }; static void m_getfld_state_init (m_getfld_state_t *gstate, FILE *iob) { m_getfld_state_t s; NEW(s); *gstate = s; 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->state = FLD; s->track_filepos = 0; } /* 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->pat_map); } free (s); *gstate = 0; } } /* 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() 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(). 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. */ static void enter_getfld (m_getfld_state_t *gstate, FILE *iob) { m_getfld_state_t s; off_t pos; off_t pos_movement; 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) return; pos = ftello(iob); if (pos == 0 && s->last_internal_pos == 0) return; if (s->last_internal_pos == 0) { s->total_bytes_read = pos; return; } 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, if at least edelimlen have been read, so that we can back up to them in m_Eom(). */ ssize_t retain = s->end - s->msg_buf < s->edelimlen ? 0 : s->edelimlen; size_t num_read; if (retain > 0) { if (retain < s->end - s->readpos) retain = s->end - s->readpos; assert (retain <= s->readpos - s->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; } /* The return values of the following functions are a bit subtle. They can return 0x00 - 0xff as a valid character, but EOF is typically 0xffffffff. */ static int Getc (m_getfld_state_t s) { if ((s->end - s->readpos < 1 && read_more (s) == 0) || s->readpos >= s->end) return EOF; s->bytes_read++; return (unsigned char)*s->readpos++; } static int Peek (m_getfld_state_t s) { if (s->end - s->readpos < 1 && read_more (s) == 0) { return EOF; } return s->readpos < s->end ? (unsigned char) *s->readpos : EOF; } static int Ungetc (int c, m_getfld_state_t s) { if (s->readpos == s->msg_buf) { return EOF; } --s->bytes_read; return *--s->readpos = (unsigned char) c; } int m_getfld (m_getfld_state_t *gstate, char name[NAMESZ], char *buf, int *bufsz, FILE *iob) { m_getfld_state_t s; char *cp; int max, n, c; enter_getfld (gstate, iob); s = *gstate; if ((c = Getc(s)) == EOF) { *bufsz = *buf = 0; leave_getfld (s); return s->state = FILEEOF; } if (eom (c, s)) { /* flush null messages */ while ((c = Getc(s)) != EOF && eom (c, s)) ; if (c != EOF) Ungetc(c, s); *bufsz = *buf = 0; leave_getfld (s); return s->state = FILEEOF; } switch (s->state) { case FLD: if (c == '\n' || c == '-') { /* we hit the header/body separator */ while (c != '\n' && (c = Getc(s)) != EOF) ; if (c == EOF || (c = Getc(s)) == EOF || eom (c, s)) { /* flush null messages */ while ((c = Getc(s)) != EOF && eom (c, s)) ; if (c != EOF) Ungetc(c, s); *bufsz = *buf = 0; leave_getfld (s); return s->state = FILEEOF; } 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. */ cp = name; 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; } /* 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; inform("eof encountered in field \"%s\"", name); leave_getfld (s); return s->state = FMTERR; } } /* 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; inform("eol encountered in field \"%s\"", name); s->state = FMTERR; break; } memcpy (buf, name, n - 1); buf[n - 1] = '\n'; buf[n] = '\0'; /* Indicate this wasn't a header field using a character that can't appear in a header field. */ name[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; } 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; inform("field name \"%s\" exceeds %d bytes", name, NAMESZ - 2); s->state = LENERR; break; } /* Trim any trailing spaces from the end of name. */ while (isspace ((unsigned char) *--cp) && cp >= name) continue; *++cp = 0; /* readpos points to the first character of the field body. */ /* FALLTHRU */ case FLDPLUS: { /* * 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. */ int finished; cp = buf; max = *bufsz-1; n = 0; for (finished = 0; ! finished; ) { while (c != '\n' && c != EOF && n++ < max) { if ((c = Getc (s)) != EOF) *cp++ = c; } if (c != EOF) c = Peek (s); if (max < n) { /* The dest buffer is full. Need to back the read pointer up by one because when m_getfld() is reentered, it will read a character. Then we'll jump right to the FLDPLUS handling code, which will not store that character, but instead move on to the next one. */ if (s->readpos > s->msg_buf) { --s->readpos; --s->bytes_read; } 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; } body: case BODY: { /* * get the message body up to bufsz characters or the * end of the message. */ char *bp; name[0] = '\0'; max = *bufsz-1; /* Back up and store the current position. */ bp = --s->readpos; c = min(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 * probably be a Boyer-Moore matcher for non-vaxen, * particularly since we have the alignment table * all built for the end-of-buffer test (next). * But our vax timings indicate that the "matchc" * instruction is 50% faster than a carefully coded * B.M. matcher for most strings. (So much for elegant * algorithms vs. brute force.) Since I (currently) * run MH on a vax, we use the matchc instruction. --vj */ char *ep; if ((ep = memmem(bp, c, s->fdelim, s->fdelimlen))) c = ep - bp + 1; else { /* * There's no delim in the buffer but there may be * a partial one at the end. If so, we want to leave * it so the "eom" check on the next call picks it up. * Use a modified Boyer-Moore matcher to make this * check relatively cheap. The first "if" figures * out what position in the pattern matches the last * character in the buffer. The inner "while" matches * the pattern against the buffer, backwards starting * at that position. Note that unless the buffer * ends with one of the characters in the pattern * (excluding the first and last), we do only one test. */ char *sp; ep = bp + c - 1; if ((sp = s->pat_map[(unsigned char) *ep])) { do { /* This if() is true unless (a) the buffer is too * small to contain this delimiter prefix, or * (b) it contains exactly enough chars for the * delimiter prefix. * For case (a) obviously we aren't going to match. * For case (b), if the buffer really contained exactly * a delim prefix, then the m_eom call at entry * should have found it. Thus it's not a delim * and we know we won't get a match. */ 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 * contains a NUL in exactly the wrong place (this * would cause us to run off the front of fdelim). */ while (*--ep == *--cp) if (cp < s->fdelim) break; 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 */ c = (ep - bp) + 2; break; } } /* try matching one less char of delim string */ ep = bp + c - 1; } while (--sp > s->fdelim); } } } memcpy( buf, bp, c ); /* 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", s->state); } *cp = 0; leave_getfld (s); return s->state; } void m_unknown(m_getfld_state_t *gstate, FILE *iob) { m_getfld_state_t s; int c; char text[MAX_DELIMITER_SIZE]; char from[] = "From "; char *cp; char *delimstr; unsigned int i; enter_getfld (gstate, iob); s = *gstate; /* * Figure out what the message delimiter string is for this * maildrop. (This used to be part of m_Eom but I didn't like * the idea of an "if" statement that could only succeed on the * first call to m_Eom getting executed on each call, i.e., at * every newline in the message). * * If the first line of the maildrop is a Unix "From " line, we * say the style is MBOX and eat the rest of the line. Otherwise * we say the style is MMDF and look for the delimiter string * specified when nmh was built (or from the mts.conf file). */ s->msg_style = MS_UNKNOWN; for (i = 0, cp = text; i < sizeof text; ++i, ++cp) { if ((c = Getc (s)) == EOF) { *cp = '\0'; break; } *cp = c; } if (i == sizeof from-1 && strncmp (text, "From ", sizeof from-1) == 0) { s->msg_style = MS_MBOX; delimstr = "\nFrom "; while ((c = Getc(s)) != EOF && c != '\n') ; } else { /* not a Unix style maildrop */ s->readpos -= s->bytes_read; s->bytes_read = 0; delimstr = MMDF_DELIM; s->msg_style = MS_MMDF; } c = strlen (delimstr); s->fdelim = mh_xmalloc (c + 3); /* \0, \n, delimstr, \0 */ *s->fdelim++ = '\0'; *s->fdelim = '\n'; s->fdelimlen = c + 1; s->msg_delim = s->fdelim+1; strcpy (s->msg_delim, delimstr); s->edelim = s->msg_delim+1; s->edelimlen = c - 1; s->delimend = s->msg_delim + s->edelimlen; if (s->edelimlen <= 1) adios (NULL, "maildrop delimiter must be at least 2 bytes"); /* Now malloc'd memory at s->fdelim-1 is referenced several times, * containing a copy of the string constant from delimstr. * * "\nFrom \0" 7 "\001\001\001\001\n\0" 6 * | | * delimstr c=6 delimstr c=5 * * "\0\n\nFrom \0" 9 "\0\n\001\001\001\001\n\0" 8 * | || | | | | | * | || s->delimend | | | s->delimend * | || | | | * | |s->edelim s->edelimlen=5 | | s->edelim s->edelimlen=4 * | | | | * | s->msg_delim | s->msg_delim * | | * s->fdelim s->fdelimlen=7 s->fdelim s->fdelimlen=6 */ /* * build a Boyer-Moore end-position map for the matcher in m_getfld. * N.B. - we don't match just the first char (since it's the newline * separator) or the last char (since the matchc would have found it * if it was a real delim). */ s->pat_map = (char **) mh_xcalloc (256, sizeof(char *)); for (cp = s->fdelim + 1; cp < s->delimend; cp++ ) s->pat_map[(unsigned char)*cp] = cp; if (s->msg_style == MS_MMDF) { /* flush extra msg hdrs */ while ((c = Getc(s)) != EOF && eom (c, s)) ; if (c != EOF) Ungetc(c, s); } leave_getfld (s); } /* * test for msg delimiter string */ static int m_Eom (m_getfld_state_t s) { int i; char text[MAX_DELIMITER_SIZE]; char *cp; int adjust = 1; for (i = 0, cp = text; i < s->edelimlen; ++i, ++cp) { int c2; if ((c2 = Getc (s)) == EOF) { *cp = '\0'; break; } *cp = c2; } 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 delimiter - delete it. */ return 1; } if (i <= 2 && s->msg_style == MS_MBOX && i != s->edelimlen && ! strncmp(text, s->fdelim, i)) { /* If all or part of fdelim appeared at the end of the file, back up even more so that the bytes are included in the message. */ adjust = 2; } /* 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 - adjust; s->bytes_read = adjust; return 0; } if (s->msg_style == MS_MBOX) { int c; while ((c = Getc(s)) != EOF && c != '\n') ; } return 1; } nmh-1.7.1-RC3/sbr/m_gmprot.c000644 007761 000024 00000000552 13243042053 015536 0ustar00kenhstaff000000 000000 /* m_gmprot.c -- return the msg-protect value * * 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 int m_gmprot (void) { char *cp; return atooi ((cp = context_find ("msg-protect")) && *cp ? cp : msgprot); } nmh-1.7.1-RC3/sbr/m_maildir.c000644 007761 000024 00000003417 13243042053 015652 0ustar00kenhstaff000000 000000 /* m_maildir.c -- get the path for the mail directory * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include "m_maildir.h" #define CWD "./" #define DOT "." #define DOTDOT ".." #define PWD "../" static char mailfold[BUFSIZ]; /* * static prototypes */ static char *exmaildir (char *); char * m_maildir (char *folder) { char *cp, *ep; if ((cp = exmaildir (folder)) && (ep = cp + strlen (cp) - 1) > cp && *ep == '/') *ep = '\0'; return cp; } char * m_mailpath (char *folder) { char *cp; char maildir[BUFSIZ]; if (*folder != '/' && !has_prefix(folder, CWD) && strcmp (folder, DOT) && strcmp (folder, DOTDOT) && !has_prefix(folder, PWD)) { strncpy (maildir, mailfold, sizeof(maildir)); /* preserve... */ cp = getcpy (m_maildir (folder)); strncpy (mailfold, maildir, sizeof(mailfold)); } else { cp = path (folder, TFOLDER); } return cp; } static char * exmaildir (char *folder) { char *cp, *pp; /* use current folder if none is specified */ if (folder == NULL) folder = getfolder(1); if (!(*folder != '/' && !has_prefix(folder, CWD) && strcmp (folder, DOT) && strcmp (folder, DOTDOT) && !has_prefix(folder, PWD))) { strncpy (mailfold, folder, sizeof(mailfold)); return mailfold; } cp = mailfold; if ((pp = context_find ("path")) && *pp) { if (*pp != '/') { snprintf(cp, sizeof mailfold, "%s/", mypath); cp += strlen (cp); } cp = stpcpy(cp, pp); } else { cp = stpcpy(cp, path("./", TFOLDER)); } if (cp[-1] != '/') *cp++ = '/'; strcpy (cp, folder); return mailfold; } nmh-1.7.1-RC3/sbr/m_maildir.h000644 007761 000024 00000000451 13205305704 015655 0ustar00kenhstaff000000 000000 /* m_maildir.h -- get the path for the mail directory. * * This code is Copyright (c) 2017, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ char *m_maildir(char *folder); char *m_mailpath(char *folder); nmh-1.7.1-RC3/sbr/m_mktemp.c000644 007761 000024 00000024467 13243042053 015536 0ustar00kenhstaff000000 000000 /* m_mktemp.c -- Construct a temporary file. * * This code is Copyright (c) 2010, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include "m_maildir.h" #include "m_mktemp.h" static void register_for_removal(const char *); /* Create a temporary file. If pfx_in is null, the temporary file * will be created in the temporary directory (more on that later). * If pfx_in is not null, then the temporary file location will be * defined by the value pfx_in. * * The file created will be at the pathname specified appended with * 6 random (we hope :) characters. * * The return value will be the pathname to the file created. * * CAUTION: The return pointer references static data. If * you need to modify, or save, the return string, make a copy of it * first. * * When pfx_in is null, the temporary directory is determined as * follows, in order: * * MHTMPDIR envvar * TMPDIR envvar * User's mail directory. * * NOTE: One will probably use m_mktemp2() instead of this function. * For example, if you want to create a temp file in the defined * temporary directory, but with a custom basename prefix, do * something like the following: * * char *tmp_pathname = m_mktemp2(NULL, "mypre", ...); */ char * m_mktemp ( const char *pfx_in, /* Pathname prefix for temporary file. */ int *fd_ret, /* (return,optional) File descriptor to temp file. */ FILE **fp_ret /* (return,optional) FILE pointer to temp file. */ ) { static char tmpfil[BUFSIZ]; int fd = -1; int keep_open = 0; mode_t oldmode = umask(077); if (pfx_in == NULL) { snprintf(tmpfil, sizeof(tmpfil), "%s/nmhXXXXXX", get_temp_dir()); } else { snprintf(tmpfil, sizeof(tmpfil), "%sXXXXXX", pfx_in); } fd = mkstemp(tmpfil); if (fd < 0) { umask(oldmode); return NULL; } register_for_removal(tmpfil); if (fd_ret != NULL) { *fd_ret = fd; keep_open = 1; } if (fp_ret != NULL) { FILE *fp = fdopen(fd, "w+"); if (fp == NULL) { int olderr = errno; (void) m_unlink(tmpfil); close(fd); errno = olderr; umask(oldmode); return NULL; } *fp_ret = fp; keep_open = 1; } if (!keep_open) { close(fd); } umask(oldmode); return tmpfil; } /* This version allows one to specify the directory the temp file should * by created based on a given pathname. Although m_mktemp() technically * supports this, this version is when the directory is defined by * a separate variable from the prefix, eliminating the caller from having * to do string manipulation to generate the desired pathname prefix. * * The pfx_in parameter specifies a basename prefix for the file. If dir_in * is NULL, then the defined temporary directory (see comments to m_mktemp() * above) is used to create the temp file. */ char * m_mktemp2 ( const char *dir_in, /* Directory to place temp file. */ const char *pfx_in, /* Basename prefix for temp file. */ int *fd_ret, /* (return,optional) File descriptor to temp file. */ FILE **fp_ret /* (return,optional) FILE pointer to temp file. */ ) { static char buffer[BUFSIZ]; char *cp; int n; if (dir_in == NULL) { if (pfx_in == NULL) { return m_mktemp(NULL, fd_ret, fp_ret); } snprintf(buffer, sizeof(buffer), "%s/%s", get_temp_dir(), pfx_in); return m_mktemp(buffer, fd_ret, fp_ret); } if ((cp = r1bindex ((char *)dir_in, '/')) == dir_in) { /* No directory component */ return m_mktemp(pfx_in, fd_ret, fp_ret); } n = (int)(cp-dir_in); /* Length of dir component */ snprintf(buffer, sizeof(buffer), "%.*s%s", n, dir_in, pfx_in); return m_mktemp(buffer, fd_ret, fp_ret); } /* * This version supports a suffix for the temp filename. * It has two other differences from m_mktemp() and m_mktemp2(): * 1) It does not support specification of a directory for the temp * file. Instead it always uses get_temp_dir(). * 2) It returns a dynamically allocated string. The caller is * responsible for freeing the allocated memory. */ char * m_mktemps( const char *pfx_in, /* Basename prefix for temp file. */ const char *suffix, /* Suffix, including any '.', for temp file. */ int *fd_ret, /* (return,optional) File descriptor to temp file. */ FILE **fp_ret /* (return,optional) FILE pointer to temp file. */ ) { char *tmpfil; int fd = -1; int keep_open = 0; mode_t oldmode = umask(077); if (suffix == NULL) { if ((tmpfil = m_mktemp2(NULL, pfx_in, fd_ret, fp_ret))) { return mh_xstrdup(tmpfil); } return NULL; } #if HAVE_MKSTEMPS if (pfx_in == NULL) { tmpfil = concat(get_temp_dir(), "/nmhXXXXXX", suffix, NULL); } else { tmpfil = concat(get_temp_dir(), "/", pfx_in, "XXXXXX", suffix, NULL); } fd = mkstemps(tmpfil, (int) strlen(suffix)); #else /* ! HAVE_MKSTEMPS */ /* NetBSD, Solaris 10 */ if (pfx_in == NULL) { tmpfil = concat(get_temp_dir(), "/nmhXXXXXX", NULL); } else { tmpfil = concat(get_temp_dir(), "/", pfx_in, "XXXXXX", NULL); } fd = mkstemp(tmpfil); { char *oldfilename = tmpfil; tmpfil = concat(oldfilename, suffix, NULL); if (rename(oldfilename, tmpfil) != 0) { (void) unlink(oldfilename); free(oldfilename); free(tmpfil); return NULL; } free(oldfilename); } #endif /* ! HAVE_MKSTEMPS */ if (fd < 0) { umask(oldmode); free(tmpfil); return NULL; } register_for_removal(tmpfil); if (fd_ret != NULL) { *fd_ret = fd; keep_open = 1; } if (fp_ret != NULL) { FILE *fp = fdopen(fd, "w+"); if (fp == NULL) { int olderr = errno; (void) m_unlink(tmpfil); close(fd); errno = olderr; umask(oldmode); free(tmpfil); return NULL; } *fp_ret = fp; keep_open = 1; } if (!keep_open) { close(fd); } umask(oldmode); return tmpfil; } char * get_temp_dir(void) { /* Ignore envvars if we are setuid */ if ((getuid()==geteuid()) && (getgid()==getegid())) { char *tmpdir = NULL; tmpdir = getenv("MHTMPDIR"); if (tmpdir != NULL && *tmpdir != '\0') return tmpdir; tmpdir = getenv("TMPDIR"); if (tmpdir != NULL && *tmpdir != '\0') return tmpdir; } return m_maildir(""); } /* * Array of files (full pathnames) to remove on process exit. * Instead of removing slots from the array, just set to NULL * to indicate that the file should no longer be removed. */ static svector_t exit_filelist = NULL; /* * Register a file for removal at program termination. */ static void register_for_removal(const char *pathname) { if (exit_filelist == NULL) exit_filelist = svector_create(20); (void) svector_push_back(exit_filelist, add(pathname, NULL)); } /* * Unregister all files that were registered to be removed at program * termination. When called with remove_files of 0, this function is * intended for use by one of the programs after a fork(3) without a * subsequent call to one of the exec(3) functions or _exit(3). When * called with non-0 remove_files argument, it is intended for use by * an atexit() function. * * Right after a fork() and before calling exec() or _exit(), if the * child catches one of the appropriate signals, it will remove * all the registered temporary files. Some of those may be needed by * the parent. Some nmh programs ignore or block some of the signals * in the child right after fork(). For the other programs, rather * than complicate things by preventing that, just take the chance * that it might happen. It is harmless to attempt to unlink a * temporary file twice, assuming another one wasn't created too * quickly created with the same name. */ void unregister_for_removal(int remove_files) { if (exit_filelist) { size_t i; for (i = 0; i < svector_size(exit_filelist); ++i) { char *filename = svector_at(exit_filelist, i); if (filename) { if (remove_files) (void) unlink(filename); free(filename); } } svector_free(exit_filelist); exit_filelist = NULL; } } /* * If the file was registered for removal, deregister it. In * any case, unlink it. */ int m_unlink(const char *pathname) { if (exit_filelist) { char **slot = svector_find(exit_filelist, pathname); if (slot && *slot) { free(*slot); *slot = NULL; } } return unlink(pathname); /* errno should be set to ENOENT if file was not found */ } /* * Remove all registered temporary files. */ void remove_registered_files_atexit(void) { unregister_for_removal(1); } /* * Remove all registered temporary files. Suitable for use as a * signal handler. If the signal is one of the usual process * termination signals, calls exit(). Otherwise, disables itself * by restoring the default action and then re-raises the signal, * in case the use was expecting a core dump. */ void remove_registered_files(int sig) { struct sigaction act; /* * Ignore this signal for the duration. And we either exit() or * disable this signal handler below, so don't restore this handler. */ act.sa_handler = SIG_IGN; (void) sigemptyset(&act.sa_mask); act.sa_flags = 0; (void) sigaction(sig, &act, 0); if (sig == SIGHUP || sig == SIGINT || sig == SIGQUIT || sig == SIGTERM) { /* * We don't need to call remove_registered_files_atexit() if * it was registered with atexit(), but let's not assume that. * It's harmless to call it twice. */ remove_registered_files_atexit(); exit(1); } else { remove_registered_files_atexit(); act.sa_handler = SIG_DFL; (void) sigemptyset(&act.sa_mask); act.sa_flags = 0; (void) sigaction(sig, &act, 0); (void) raise(sig); } } nmh-1.7.1-RC3/sbr/m_mktemp.h000644 007761 000024 00000001221 13205305704 015525 0ustar00kenhstaff000000 000000 /* m_mktemp.h -- Construct a temporary file. * * This code is Copyright (c) 2017, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ char *m_mktemp(const char *pfx_in, int *fd_ret, FILE **fp_ret); char *m_mktemp2(const char *dir_in, const char *pfx_in, int *fd_ret, FILE **fp_ret); char *m_mktemps(const char *pfx_in, const char *suffix, int *fd_ret, FILE **fp_ret); char *get_temp_dir(void); void unregister_for_removal(int remove_files); int m_unlink(const char *pathname); void remove_registered_files_atexit(void); void remove_registered_files(int sig); nmh-1.7.1-RC3/sbr/m_name.c000644 007761 000024 00000000713 13243042053 015145 0ustar00kenhstaff000000 000000 /* m_name.c -- return a message number as a string * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #define STR(s) #s #define SIZE(n) (sizeof STR(n)) /* Includes NUL. */ char * m_name (int num) { if (num <= 0) return "?"; return m_strn(num, SIZE(INT_MAX)); } nmh-1.7.1-RC3/sbr/m_popen.c000644 007761 000024 00000003236 13243042053 015351 0ustar00kenhstaff000000 000000 /* m_popen.c -- Interface for a popen() call that redirects the current * process standard output to the popen()d process. * * This code is Copyright (c) 2014, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include "m_popen.h" static int m_pid = NOTOK; /* Process we're waiting for */ static int sd = NOTOK; /* Original standard output */ /* * Fork a process and redirect our standard output to that process */ void m_popen (char *name, int savestdout) { int pd[2]; char *file; char **arglist; if (savestdout && (sd = dup (fileno (stdout))) == NOTOK) adios ("standard output", "unable to dup()"); if (pipe (pd) == NOTOK) adios ("pipe", "unable to"); switch (m_pid = fork()) { case NOTOK: adios ("fork", "unable to"); case OK: SIGNAL (SIGINT, SIG_DFL); SIGNAL (SIGQUIT, SIG_DFL); close (pd[1]); if (pd[0] != fileno (stdin)) { dup2 (pd[0], fileno (stdin)); close (pd[0]); } arglist = argsplit(name, &file, NULL); execvp (file, arglist); fprintf (stderr, "unable to exec "); perror (name); _exit (-1); default: close (pd[0]); if (pd[1] != fileno (stdout)) { dup2 (pd[1], fileno (stdout)); close (pd[1]); } } } void m_pclose (void) { if (m_pid == NOTOK) return; if (sd != NOTOK) { fflush (stdout); if (dup2 (sd, fileno (stdout)) == NOTOK) adios ("standard output", "unable to dup2()"); clearerr (stdout); close (sd); sd = NOTOK; } else fclose (stdout); pidwait (m_pid, OK); m_pid = NOTOK; } nmh-1.7.1-RC3/sbr/m_popen.h000644 007761 000024 00000001163 13205305704 015356 0ustar00kenhstaff000000 000000 /* m_popen.h -- redirect standard output to a popen(3)'d process. * * This code is Copyright (c) 2017, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ /* * Create a subprocess and redirect our standard output to it. * * Arguments are: * * name - Name of process to create * savestdout - If true, will save the current stdout file descriptor and * m_pclose() will close it at the appropriate time. */ void m_popen(char *name, int savestdout); /* * Wait for the last process opened by m_popen(). */ void m_pclose(void); nmh-1.7.1-RC3/sbr/m_rand.c000644 007761 000024 00000002704 13243042053 015153 0ustar00kenhstaff000000 000000 /* m_rand.c -- provides pseudorandom bytes * * 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 /* for abs(), srand(), rand(), arc4random() */ #include /* for fopen(), fread(), fclose() */ #include /* for getpid() */ #include /* for time() */ #include #include "m_rand.h" #if !HAVE_ARC4RANDOM static int seeded = 0; #endif int m_rand (unsigned char *buf, size_t n) { #if !HAVE_ARC4RANDOM if (! seeded) { FILE *devurandom; unsigned int seed; if ((devurandom = fopen ("/dev/urandom", "r"))) { if (fread (&seed, sizeof (seed), 1, devurandom) == 1) seeded = 1; fclose (devurandom); } if (! seeded) { /* This seed calculation is from Helmut G. Katzgraber, "Random Numbers in Scientific Computing: An Introduction", arXiv:1005.4117v1 [physics.comp-ph], 22 May 2010, p. 19. time() and getpid() shouldn't fail on POSIX platforms. */ seed = abs ((int) ((time (0) * 181 * ((getpid ()-83) * 359)) % 104729)); seeded = 1; } srand (seed); } while (n > 0) { int rnd = rand (); unsigned char *rndp = (unsigned char *) &rnd; unsigned int i; for (i = 0; i < sizeof rnd && n > 0; ++i, --n) { *buf++ = *rndp++; } } #else arc4random_buf(buf, n); #endif return 0; } nmh-1.7.1-RC3/sbr/m_rand.h000644 007761 000024 00000000410 13205305704 015153 0ustar00kenhstaff000000 000000 /* m_rand.h -- provide pseudorandom bytes. * * This code is Copyright (c) 2017, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ int m_rand(unsigned char *buf, size_t n); nmh-1.7.1-RC3/sbr/makedir.c000644 007761 000024 00000004627 13243042053 015335 0ustar00kenhstaff000000 000000 /* makedir.c -- make a directory * * 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. */ /* * Modified to try recursive create. */ #include #include "makedir.h" #include int makedir (const char *dir) { char path[PATH_MAX]; char* folder_perms_ASCII; int had_an_error = 0; mode_t folder_perms, saved_umask; char* c; context_save(); /* save the context file */ fflush(stdout); if (!(folder_perms_ASCII = context_find ("folder-protect"))) folder_perms_ASCII = foldprot; /* defaults to "700" */ /* Because mh-profile.man documents "Folder-Protect:" as an octal constant, and we don't want to force the user to remember to include a leading zero, we call atooi(folder_perms_ASCII) here rather than strtoul(folder_perms_ASCII, NULL, 0). Therefore, if anyone ever tries to specify a mode in say, hex, they'll get garbage. (I guess nmh uses its atooi() function rather than calling strtoul() with a radix of 8 because some ancient platforms are missing that functionality. */ folder_perms = atooi(folder_perms_ASCII); /* Folders have definite desired permissions that are set -- we don't want to interact with the umask. Clear it temporarily. */ saved_umask = umask(0); c = strncpy(path, dir, sizeof(path)); while (!had_an_error && (c = strchr((c + 1), '/')) != NULL) { *c = (char)0; if (access(path, X_OK)) { if (errno != ENOENT){ advise (dir, "unable to create directory"); had_an_error = 1; } /* Create an outer directory. */ if (mkdir(path, folder_perms)) { advise (dir, "unable to create directory"); had_an_error = 1; } } *c = '/'; } if (!had_an_error) { /* Create the innermost nested subdirectory of the path we're being asked to create. */ if (mkdir (dir, folder_perms) == -1) { advise (dir, "unable to create directory"); had_an_error = 1; } } umask(saved_umask); /* put the user's umask back */ if (had_an_error) return 0; /* opposite of UNIX error return convention */ return 1; } nmh-1.7.1-RC3/sbr/makedir.h000644 007761 000024 00000000363 13205305704 015336 0ustar00kenhstaff000000 000000 /* makedir.h -- make a directory. * * This code is Copyright (c) 2017, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ int makedir(const char *dir); nmh-1.7.1-RC3/sbr/md5.c000644 007761 000024 00000023301 13243042053 014374 0ustar00kenhstaff000000 000000 /* md5.c -- md5 message digest algorithm * taken from RFC-1321/Appendix A.3 */ /* * MD5C.C -- RSA Data Security, Inc., MD5 message-digest algorithm */ /* * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All * rights reserved. * * License to copy and use this software is granted provided that it * is identified as the "RSA Data Security, Inc. MD5 Message-Digest * Algorithm" in all material mentioning or referencing this software * or this function. * * License is also granted to make and use derivative works provided * that such works are identified as "derived from the RSA Data * Security, Inc. MD5 Message-Digest Algorithm" in all material * mentioning or referencing the derived work. * * RSA Data Security, Inc. makes no representations concerning either * the merchantability of this software or the suitability of this * software for any particular purpose. It is provided "as is" * without express or implied warranty of any kind. * * These notices must be retained in any copies of any part of this * documentation and/or software. */ #include /* * Constants for MD5Transform routine. */ #define S11 7 #define S12 12 #define S13 17 #define S14 22 #define S21 5 #define S22 9 #define S23 14 #define S24 20 #define S31 4 #define S32 11 #define S33 16 #define S34 23 #define S41 6 #define S42 10 #define S43 15 #define S44 21 static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64])); static void Encode PROTO_LIST ((unsigned char *, UINT4 *, unsigned int)); static void Decode PROTO_LIST ((UINT4 *, unsigned char *, unsigned int)); static unsigned char PADDING[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* F, G, H and I are basic MD5 functions. */ #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) #define G(x, y, z) (((x) & (z)) | ((y) & (~z))) #define H(x, y, z) ((x) ^ (y) ^ (z)) #define I(x, y, z) ((y) ^ ((x) | (~z))) /* ROTATE_LEFT rotates x left n bits. */ #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. Rotation is separate from addition to prevent recomputation. */ #define FF(a, b, c, d, x, s, ac) { \ (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define GG(a, b, c, d, x, s, ac) { \ (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define HH(a, b, c, d, x, s, ac) { \ (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define II(a, b, c, d, x, s, ac) { \ (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } /* MD5 initialization. Begins an MD5 operation, writing a new context. */ void MD5Init (context) MD5_CTX *context; /* context */ { context->count[0] = context->count[1] = 0; /* Load magic initialization constants. */ context->state[0] = 0x67452301; context->state[1] = 0xefcdab89; context->state[2] = 0x98badcfe; context->state[3] = 0x10325476; } /* MD5 block update operation. Continues an MD5 message-digest operation, processing another message block, and updating the context. */ void MD5Update (context, input, inputLen) MD5_CTX *context; /* context */ unsigned char *input; /* input block */ unsigned int inputLen; /* length of input block */ { unsigned int i, index, partLen; /* Compute number of bytes mod 64 */ index = (unsigned int)((context->count[0] >> 3) & 0x3F); /* Update number of bits */ if ((context->count[0] += ((UINT4)inputLen << 3)) < ((UINT4)inputLen << 3)) context->count[1]++; context->count[1] += ((UINT4)inputLen >> 29); partLen = 64 - index; /* Transform as many times as possible. */ if (inputLen >= partLen) { memcpy ((POINTER)&context->buffer[index], (POINTER)input, partLen); MD5Transform (context->state, context->buffer); for (i = partLen; i + 63 < inputLen; i += 64) MD5Transform (context->state, &input[i]); index = 0; } else i = 0; /* Buffer remaining input */ memcpy ((POINTER)&context->buffer[index], (POINTER)&input[i], inputLen-i); } /* * MD5 finalization. Ends an MD5 message-digest operation, writing the * the message digest and zeroizing the context. */ void MD5Final (digest, context) unsigned char digest[16]; /* message digest */ MD5_CTX *context; /* context */ { unsigned char bits[8]; unsigned int index, padLen; /* Save number of bits */ Encode (bits, context->count, 8); /* Pad out to 56 mod 64. */ index = (unsigned int)((context->count[0] >> 3) & 0x3f); padLen = (index < 56) ? (56 - index) : (120 - index); MD5Update (context, PADDING, padLen); /* Append length (before padding) */ MD5Update (context, bits, 8); /* Store state in digest */ Encode (digest, context->state, 16); /* Zeroize sensitive information. */ memset ((POINTER)context, 0, sizeof(*context)); } /* MD5 basic transformation. Transforms state based on block. */ static void MD5Transform (state, block) UINT4 state[4]; unsigned char block[64]; { UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; Decode (x, block, 64); /* Round 1 */ FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ /* Round 2 */ GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ /* Round 3 */ HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ /* Round 4 */ II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; /* Zeroize sensitive information. */ memset ((POINTER)x, 0, sizeof(x)); } /* Encodes input (UINT4) into output (unsigned char). Assumes len is a multiple of 4. */ static void Encode (output, input, len) unsigned char *output; UINT4 *input; unsigned int len; { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) { output[j] = (unsigned char)(input[i] & 0xff); output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); } } /* Decodes input (unsigned char) into output (UINT4). Assumes len is a multiple of 4. */ static void Decode (output, input, len) UINT4 *output; unsigned char *input; unsigned int len; { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); } nmh-1.7.1-RC3/sbr/message_id.c000644 007761 000024 00000006605 13243042053 016017 0ustar00kenhstaff000000 000000 /* message_id.c -- construct the body of a Message-ID or Content-ID * header field * * 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 #include "m_rand.h" #include "message_id.h" #include /* for gettimeofday() */ static enum { NMH_MESSAGE_ID_LOCALNAME, NMH_MESSAGE_ID_RANDOM } message_id_style = NMH_MESSAGE_ID_LOCALNAME; static char message_id_[BUFSIZ]; /* Convert name of message id style to integer value and store it. */ int save_message_id_style (const char *value) { if (! strcasecmp (value, "localname")) { message_id_style = NMH_MESSAGE_ID_LOCALNAME; return 0; } if (! strcasecmp (value, "random")) { message_id_style = NMH_MESSAGE_ID_RANDOM; return 0; } return 1; } char * message_id (time_t tclock, int content_id) { switch (message_id_style) { case NMH_MESSAGE_ID_LOCALNAME: { char *format = content_id ? "<%d.%ld.%%d@%s>" : "<%d.%ld@%s>"; snprintf (message_id_, sizeof message_id_, format, (int) getpid (), (long) tclock, LocalName (1)); break; } case NMH_MESSAGE_ID_RANDOM: { char *format = content_id ? "<%d-%ld.%06ld%%d@%.*s.%.*s.%.*s>" : "<%d-%ld.%06ld@%.*s.%.*s.%.*s>"; /* Use a sequence of digits divisible by 3 because that will expand to base64 without any waste. Must be shorter than 58, see below. */ unsigned char rnd[9]; /* The part after the '@' is divided into thirds. The base64 encoded string will be 4/3 the size of rnd. */ size_t one_third = sizeof rnd * 4/3/3; if (m_rand (rnd, sizeof rnd) == 0) { struct timeval now; /* All we really need is 4 * [sizeof rnd/3] + 2, as long as the base64 encoding stays shorter than 76 bytes so embedded newlines aren't necessary. But use double the sizeof rnd just to be safe. */ unsigned char rnd_base64[2 * sizeof rnd]; unsigned char *cp; int i; writeBase64 (rnd, sizeof rnd, rnd_base64); for (i = strlen ((const char *) rnd_base64) - 1; i > 0 && iscntrl (rnd_base64[i]); --i) { /* Remove trailing newline. rnd_base64 had better be shorter than 76 characters, so don't bother to look for embedded newlines. */ rnd_base64[i] = '\0'; } /* Try to make the base64 string look a little more like a hostname by replacing + with - and / with _. */ for (cp = rnd_base64; *cp; ++cp) { if (*cp == '+') { *cp = '-'; } else if (*cp == '/') { *cp = '_'; } } /* gettimeofday() and getpid() shouldn't fail on POSIX platforms. */ gettimeofday (&now, 0); /* The format string inserts a couple of dots, for the benefit of spam filters that want to see a message id with a final part that resembles a hostname. */ snprintf (message_id_, sizeof message_id_, format, getpid (), (long) now.tv_sec, (long) now.tv_usec, one_third, rnd_base64, one_third, &rnd_base64[one_third], one_third, &rnd_base64[2*one_third]); } break; } } return message_id_; } nmh-1.7.1-RC3/sbr/message_id.h000644 007761 000024 00000001144 13205305704 016020 0ustar00kenhstaff000000 000000 /* message_id.h -- construct the body of a Message-ID or Content-ID. * * This code is Copyright (c) 2017, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ /* What style to use for generated Message-ID and Content-ID header * fields. The localname style is pid.time@localname, where time is * in seconds. The random style replaces the localname with some * (pseudo)random bytes and uses microsecond-resolution time. */ int save_message_id_style(const char *value); char *message_id(time_t tclock, int content_id); nmh-1.7.1-RC3/sbr/mf.c000644 007761 000024 00000032373 13243042053 014322 0ustar00kenhstaff000000 000000 /* mf.c -- mail filter subroutines * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include /* * static prototypes */ static int isat (const char *); static int parse_address (void); static int phrase (char *); static int route_addr (char *); static int local_part (char *); static int domain (char *); static int route (char *); static int my_lex (char *); static int isat (const char *p) { return *p == ' ' && (p[1] == 'a' || p[1] == 'A') && (p[2] == 't' || p[2] == 'T') && p[3] == ' '; } /* * * getadrx() implements a partial 822-style address parser. The parser * is neither complete nor correct. It does however recognize nearly all * of the 822 address syntax. In addition it handles the majority of the * 733 syntax as well. Most problems arise from trying to accommodate both. * * In terms of 822, the route-specification in * * "<" [route] local-part "@" domain ">" * * is parsed and returned unchanged. Multiple at-signs are compressed * via source-routing. Recursive groups are not allowed as per the * standard. * * In terms of 733, " at " is recognized as equivalent to "@". * * In terms of both the parser will not complain about missing hosts. * * ----- * * We should not allow addresses like * * Marshall T. Rose * * but should insist on * * "Marshall T. Rose" * * Unfortunately, a lot of mailers stupidly let people get away with this. * * ----- * * We should not allow addresses like * * * * but should insist on * * MRose@UCI * * Unfortunately, a lot of mailers stupidly let people's UAs get away with * this. * * ----- * * We should not allow addresses like * * @UCI:MRose@UCI-750a * * but should insist on * * Marshall Rose <@UCI:MRose@UCI-750a> * * Unfortunately, a lot of mailers stupidly do this. * */ #define QUOTE '\\' #define LX_END 0 #define LX_ERR 1 #define LX_ATOM 2 #define LX_QSTR 3 #define LX_DLIT 4 #define LX_SEMI 5 #define LX_COMA 6 #define LX_LBRK 7 #define LX_RBRK 8 #define LX_COLN 9 #define LX_DOT 10 #define LX_AT 11 struct specials { char lx_chr; int lx_val; }; static struct specials special[] = { { ';', LX_SEMI }, { ',', LX_COMA }, { '<', LX_LBRK }, { '>', LX_RBRK }, { ':', LX_COLN }, { '.', LX_DOT }, { '@', LX_AT }, { '(', LX_ERR }, { ')', LX_ERR }, { QUOTE, LX_ERR }, { '"', LX_ERR }, { '[', LX_ERR }, { ']', LX_ERR }, { 0, 0 } }; static int glevel = 0; static int ingrp = 0; static int last_lex = LX_END; static char *dp = NULL; static char *cp = NULL; static char *ap = NULL; static char *pers = NULL; static char *mbox = NULL; static char *host = NULL; static char *routepath = NULL; static char *grp = NULL; static char *note = NULL; static char err[BUFSIZ]; static char adr[BUFSIZ]; static struct adrx adrxs2; /* eai = Email Address Internationalization */ struct adrx * getadrx (const char *addrs, int eai) { char *bp; struct adrx *adrxp = &adrxs2; mh_xfree(pers); mh_xfree(mbox); mh_xfree(host); mh_xfree(routepath); mh_xfree(grp); mh_xfree(note); pers = mbox = host = routepath = grp = note = NULL; err[0] = 0; if (dp == NULL) { dp = cp = strdup (FENDNULL(addrs)); glevel = 0; } else if (cp == NULL) { free (dp); dp = NULL; return NULL; } switch (parse_address ()) { case DONE: free (dp); dp = cp = NULL; return NULL; case OK: switch (last_lex) { case LX_COMA: case LX_END: break; default: /* catch trailing comments */ bp = cp; my_lex (adr); cp = bp; break; } break; default: break; } if (! eai) { /* * Reject the address if key fields contain 8bit characters */ if (contains8bit(mbox, NULL) || contains8bit(host, NULL) || contains8bit(routepath, NULL) || contains8bit(grp, NULL)) { strcpy(err, "Address contains 8-bit characters"); } } if (err[0]) for (;;) { switch (last_lex) { case LX_COMA: case LX_END: break; default: my_lex (adr); continue; } break; } while (isspace ((unsigned char) *ap)) ap++; if (cp) snprintf(adr, sizeof adr, "%.*s", (int)(cp - ap), ap); else strcpy (adr, ap); bp = adr + strlen (adr) - 1; if (*bp == ',' || *bp == ';' || *bp == '\n') *bp = 0; adrxp->text = adr; adrxp->pers = pers; adrxp->mbox = mbox; adrxp->host = host; adrxp->path = routepath; adrxp->grp = grp; adrxp->ingrp = ingrp; adrxp->note = note; adrxp->err = err[0] ? err : NULL; return adrxp; } static int parse_address (void) { char buffer[BUFSIZ]; again: ; ap = cp; switch (my_lex (buffer)) { case LX_ATOM: case LX_QSTR: pers = strdup (buffer); break; case LX_SEMI: if (glevel-- <= 0) { strcpy (err, "extraneous semi-colon"); return NOTOK; } /* FALLTHRU */ case LX_COMA: mh_xfree(note); note = NULL; goto again; case LX_END: return DONE; case LX_LBRK: /* sigh (2) */ goto get_addr; case LX_AT: /* sigh (3) */ cp = ap; if (route_addr (buffer) == NOTOK) return NOTOK; return OK; /* why be choosy? */ default: snprintf(err, sizeof err, "illegal address construct (%s)", buffer); return NOTOK; } switch (my_lex (buffer)) { case LX_ATOM: case LX_QSTR: pers = add (buffer, add (" ", pers)); more_phrase: ; /* sigh (1) */ if (phrase (buffer) == NOTOK) return NOTOK; switch (last_lex) { case LX_LBRK: get_addr: ; if (route_addr (buffer) == NOTOK) return NOTOK; if (last_lex == LX_RBRK) return OK; snprintf(err, sizeof err, "missing right-bracket (%s)", buffer); return NOTOK; case LX_COLN: get_group: ; if (glevel++ > 0) { snprintf(err, sizeof err, "nested groups not allowed (%s)", pers); return NOTOK; } grp = add (": ", pers); pers = NULL; { char *pp = cp; for (;;) switch (my_lex (buffer)) { case LX_SEMI: case LX_END: /* tsk, tsk */ glevel--; return OK; case LX_COMA: continue; default: cp = pp; return parse_address (); } } case LX_DOT: /* sigh (1) */ pers = add (".", pers); goto more_phrase; default: snprintf(err, sizeof err, "no mailbox in address, only a phrase (%s%s)", pers, buffer); return NOTOK; } case LX_LBRK: goto get_addr; case LX_COLN: goto get_group; case LX_DOT: mbox = add (buffer, pers); pers = NULL; if (route_addr (buffer) == NOTOK) return NOTOK; goto check_end; case LX_AT: ingrp = glevel; mbox = pers; pers = NULL; if (domain (buffer) == NOTOK) return NOTOK; check_end: ; switch (last_lex) { case LX_SEMI: if (glevel-- <= 0) { strcpy (err, "extraneous semi-colon"); return NOTOK; } return OK; case LX_COMA: case LX_END: return OK; default: snprintf(err, sizeof err, "junk after local@domain (%s)", buffer); return NOTOK; } case LX_SEMI: /* no host */ case LX_COMA: case LX_END: ingrp = glevel; if (last_lex == LX_SEMI && glevel-- <= 0) { strcpy (err, "extraneous semi-colon"); return NOTOK; } mbox = pers; pers = NULL; return OK; default: snprintf(err, sizeof err, "missing mailbox (%s)", buffer); return NOTOK; } } static int phrase (char *buffer) { for (;;) switch (my_lex (buffer)) { case LX_ATOM: case LX_QSTR: pers = add (buffer, add (" ", pers)); continue; default: return OK; } } static int route_addr (char *buffer) { char *pp = cp; if (my_lex (buffer) == LX_AT) { if (route (buffer) == NOTOK) return NOTOK; } else cp = pp; if (local_part (buffer) == NOTOK) return NOTOK; switch (last_lex) { case LX_AT: return domain (buffer); case LX_SEMI: /* if in group */ case LX_RBRK: /* no host */ case LX_COMA: case LX_END: return OK; default: snprintf(err, sizeof err, "no at-sign after local-part (%s)", buffer); return NOTOK; } } static int local_part (char *buffer) { ingrp = glevel; for (;;) { switch (my_lex (buffer)) { case LX_ATOM: case LX_QSTR: mbox = add (buffer, mbox); break; default: snprintf(err, sizeof err, "no mailbox in local-part (%s)", buffer); return NOTOK; } switch (my_lex (buffer)) { case LX_DOT: mbox = add (buffer, mbox); continue; default: return OK; } } } static int domain (char *buffer) { for (;;) { switch (my_lex (buffer)) { case LX_ATOM: case LX_DLIT: host = add (buffer, host); break; default: snprintf(err, sizeof err, "no sub-domain in domain-part of address (%s)", buffer); return NOTOK; } switch (my_lex (buffer)) { case LX_DOT: host = add (buffer, host); continue; case LX_AT: /* sigh (0) */ mbox = add (host, add ("%", mbox)); free (host); host = NULL; continue; default: return OK; } } } static int route (char *buffer) { routepath = mh_xstrdup ("@"); for (;;) { switch (my_lex (buffer)) { case LX_ATOM: case LX_DLIT: routepath = add (buffer, routepath); break; default: snprintf(err, sizeof err, "no sub-domain in domain-part of address (%s)", buffer); return NOTOK; } switch (my_lex (buffer)) { case LX_COMA: routepath = add (buffer, routepath); for (;;) { switch (my_lex (buffer)) { case LX_COMA: continue; case LX_AT: routepath = add (buffer, routepath); break; default: snprintf(err, sizeof err, "no at-sign found for next domain in route (%s)", buffer); } break; } continue; case LX_AT: /* XXX */ case LX_DOT: routepath = add (buffer, routepath); continue; case LX_COLN: routepath = add (buffer, routepath); return OK; default: snprintf(err, sizeof err, "no colon found to terminate route (%s)", buffer); return NOTOK; } } } static int my_lex (char *buffer) { /* buffer should be at least BUFSIZ bytes long */ int i, gotat = 0; char c, *bp; /* Add C to the buffer bp. After use of this macro *bp is guaranteed to be within the buffer. */ #define ADDCHR(C) do { *bp++ = (C); if ((bp - buffer) == (BUFSIZ-1)) goto my_lex_buffull; } while (0) bp = buffer; *bp = 0; if (!cp) return (last_lex = LX_END); gotat = isat (cp); c = *cp++; while (isspace ((unsigned char) c)) c = *cp++; if (c == 0) { cp = NULL; return (last_lex = LX_END); } if (c == '(') { ADDCHR(c); for (i = 0;;) switch (c = *cp++) { case 0: cp = NULL; return (last_lex = LX_ERR); case QUOTE: ADDCHR(c); if ((c = *cp++) == 0) { cp = NULL; return (last_lex = LX_ERR); } ADDCHR(c); continue; case '(': i++; /* FALLTHRU */ default: ADDCHR(c); continue; case ')': ADDCHR(c); if (--i < 0) { *bp = 0; note = note ? add (buffer, add (" ", note)) : strdup (buffer); return my_lex (buffer); } } } if (c == '"') { ADDCHR(c); for (;;) switch (c = *cp++) { case 0: cp = NULL; return (last_lex = LX_ERR); case QUOTE: ADDCHR(c); if ((c = *cp++) == 0) { cp = NULL; return (last_lex = LX_ERR); } /* FALLTHRU */ default: ADDCHR(c); continue; case '"': ADDCHR(c); *bp = 0; return (last_lex = LX_QSTR); } } if (c == '[') { ADDCHR(c); for (;;) switch (c = *cp++) { case 0: cp = NULL; return (last_lex = LX_ERR); case QUOTE: ADDCHR(c); if ((c = *cp++) == 0) { cp = NULL; return (last_lex = LX_ERR); } /* FALLTHRU */ default: ADDCHR(c); continue; case ']': ADDCHR(c); *bp = 0; return (last_lex = LX_DLIT); } } ADDCHR(c); *bp = 0; for (i = 0; special[i].lx_chr != 0; i++) if (c == special[i].lx_chr) return (last_lex = special[i].lx_val); if (iscntrl ((unsigned char) c)) return (last_lex = LX_ERR); for (;;) { if ((c = *cp++) == 0) break; for (i = 0; special[i].lx_chr != 0; i++) if (c == special[i].lx_chr) goto got_atom; if (iscntrl ((unsigned char) c) || isspace ((unsigned char) c)) break; ADDCHR(c); } got_atom: ; if (c == 0) cp = NULL; else cp--; *bp = 0; last_lex = !gotat || cp == NULL || strchr(cp, '<') != NULL ? LX_ATOM : LX_AT; return last_lex; my_lex_buffull: /* Out of buffer space. *bp is the last byte in the buffer */ *bp = 0; return (last_lex = LX_ERR); } char * legal_person (const char *p) { int i; const char *cp; static char buffer[BUFSIZ]; if (*p == '"') return (char *) p; for (cp = p; *cp; cp++) for (i = 0; special[i].lx_chr; i++) if (*cp == special[i].lx_chr) { snprintf(buffer, sizeof buffer, "\"%s\"", p); return buffer; } return (char *) p; } nmh-1.7.1-RC3/sbr/mime_type.c000644 007761 000024 00000011246 13243042053 015704 0ustar00kenhstaff000000 000000 /* mime_type.c -- routine to determine the MIME Content-Type of a file * * This code is Copyright (c) 2014, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include "mime_type.h" #ifdef MIMETYPEPROC static char *get_file_info(const char *, const char *); #endif /* MIMETYPEPROC */ /* * Try to use external command to determine mime type, and possibly * encoding. If that fails try using the filename extension. Caller * is responsible for free'ing returned memory. */ char * mime_type(const char *file_name) { char *content_type = NULL; /* mime content type */ char *p; static int loaded_defaults = 0; #ifdef MIMETYPEPROC char *mimetype; if ((mimetype = get_file_info(MIMETYPEPROC, file_name))) { #ifdef MIMEENCODINGPROC /* Try to append charset for text content. */ char *mimeencoding; if (strncasecmp(mimetype, "text", 4) == 0) { if ((mimeencoding = get_file_info(MIMEENCODINGPROC, file_name))) { content_type = concat(mimetype, "; charset=", mimeencoding, NULL); free (mimetype); } else { content_type = mimetype; } } else { content_type = mimetype; } #else /* MIMEENCODINGPROC */ content_type = mimetype; #endif /* MIMEENCODINGPROC */ } #endif /* MIMETYPEPROC */ /* * If we didn't get the MIME type from the contents (or we don't support * the necessary command) then use the mhshow suffix. */ if (content_type == NULL) { struct node *np; /* Content scan node pointer */ FILE *fp; /* File pointer for mhn.defaults */ if (! loaded_defaults && (fp = fopen(p = etcpath("mhn.defaults"), "r"))) { loaded_defaults = 1; readconfig(NULL, fp, p, 0); fclose(fp); } if ((p = strrchr(file_name, '.')) != NULL) { for (np = m_defs; np; np = np->n_next) { if (strncasecmp(np->n_name, "mhshow-suffix-", 14) == 0 && strcasecmp(p, FENDNULL(np->n_field)) == 0) { content_type = strdup(np->n_name + 14); break; } } } /* * If we didn't match any filename extension, try to infer the * content type. If we have binary, assume application/octet-stream; * otherwise, assume text/plain. */ if (content_type == NULL) { FILE *fp; int binary = 0, c; if (!(fp = fopen(file_name, "r"))) { inform("unable to access file \"%s\"", file_name); return NULL; } while ((c = getc(fp)) != EOF) { if (! isascii(c) || c == 0) { binary = 1; break; } } fclose(fp); content_type = strdup(binary ? "application/octet-stream" : "text/plain"); } } return content_type; } #ifdef MIMETYPEPROC /* * Get information using proc about a file. */ static char * get_file_info(const char *proc, const char *file_name) { char *cmd, *cp; char *quotec = "'"; if ((cp = strchr(file_name, '\''))) { /* file_name contains a single quote. */ if (strchr(file_name, '"')) { inform("filenames containing both single and double quotes " "are unsupported for attachment"); return NULL; } quotec = "\""; } if ((cmd = concat(proc, " ", quotec, file_name, quotec, NULL))) { FILE *fp; if ((fp = popen(cmd, "r")) != NULL) { char buf[max(BUFSIZ, 2048)]; buf[0] = '\0'; if (fgets(buf, sizeof buf, fp)) { char *eol; /* Skip leading :, if present. */ if ((cp = strchr(buf, ':')) != NULL) { ++cp; while (*cp && isblank((unsigned char) *cp)) { ++cp; } } else { cp = buf; } /* Truncate at newline (LF or CR), if present. */ if ((eol = strpbrk(cp, "\n\r")) != NULL) { *eol = '\0'; } } else if (buf[0] == '\0') { /* This can happen on Cygwin if the popen() mysteriously fails. Return NULL so that the caller will use another method to determine the info. */ free (cp); cp = NULL; } (void) pclose(fp); } else { inform("no output from %s", cmd); } free(cmd); } else { inform("concat with \"%s\" failed, out of memory?", proc); } return cp ? strdup(cp) : NULL; } #endif /* MIMETYPEPROC */ nmh-1.7.1-RC3/sbr/mime_type.h000644 007761 000024 00000001745 13205305704 015717 0ustar00kenhstaff000000 000000 /* mime_type.h -- determine the MIME Content-Type of a file. * * This code is Copyright (c) 2017, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ /* Return a MIME content-type string for the specified file. * * If the system supports it, will use the "file" command to determine * the appropriate content-type. Otherwise it will try to determine the * content-type from the suffix. If that fails, the file will be scanned * and either assigned a MIME type of text/plain or application/octet-stream * depending if binary content is present. * * Arguments: * * filename - The name of the file to determine the MIME type of. * * Returns a pointer to a content-type string (which may include MIME * parameters, such as charset). Returns a NULL if it cannot determine * the MIME type of the file. Returns allocated storage that must be * free'd. */ char *mime_type(const char *filename); nmh-1.7.1-RC3/sbr/mts.c000644 007761 000024 00000023775 13243042053 014531 0ustar00kenhstaff000000 000000 /* mts.c -- definitions for the mail transport system * * 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 /* for snprintf() */ #include #define nmhetcdir(file) NMHETCDIR#file #include #include #include #include /* * static prototypes */ static char *tailor_value (char *); static void getuserinfo (void); static const char *get_mtsconf_pathname(void); static const char *get_mtsuserconf_pathname(void); static void mts_read_conf_file (FILE *fp); /* * *mmdfldir and *uucpldir are the maildrop directories. If maildrops * are kept in the user's home directory, then these should be empty * strings. In this case, the appropriate ...lfil array should contain * the name of the file in the user's home directory. Usually, this is * something like ".mail". */ /* * nmh mail transport interface customization file */ static char *mtsconf = nmhetcdir(/mts.conf); static char *localname = ""; static char *localdomain = ""; static char *systemname = ""; char *mmdfldir = MAILSPOOL; char *mmdflfil = ""; char *uucpldir = "/usr/spool/mail"; char *uucplfil = ""; char *spoollocking = DEFAULT_LOCKING; /* Cache the username, fullname, and mailbox of the user */ static char username[BUFSIZ]; static char fullname[BUFSIZ]; static char localmbox[BUFSIZ]; /* * MTS specific variables */ static char *mts_method = "smtp"; int sm_mts = MTS_SMTP; char *sendmail = SENDMAILPATH; /* * SMTP/POP stuff */ char *clientname = NULL; char *servers = "localhost"; char *pophost = ""; /* * Global MailDelivery file */ char *maildelivery = nmhetcdir(/maildelivery); /* * Customize the MTS settings for nmh by adjusting * the file mts.conf in the nmh etc directory. */ struct bind { char *keyword; char **value; }; static struct bind binds[] = { { "localname", &localname }, { "localdomain", &localdomain }, { "systemname", &systemname }, { "mmdfldir", &mmdfldir }, { "mmdflfil", &mmdflfil }, { "spoollocking", &spoollocking }, { "uucpldir", &uucpldir }, { "uucplfil", &uucplfil }, { "mts", &mts_method }, { "sendmail", &sendmail }, { "clientname", &clientname }, { "servers", &servers }, { "pophost", &pophost }, { "maildelivery", &maildelivery }, { NULL, NULL } }; /* Convert name of mts method to integer value and store it. */ void save_mts_method (const char *value) { if (! strcasecmp (value, "smtp")) { mts_method = "smtp"; sm_mts = MTS_SMTP; } else if (! strcasecmp (value, "sendmail/smtp") || ! strcasecmp (value, "sendmail")) { mts_method = "sendmail/smtp"; sm_mts = MTS_SENDMAIL_SMTP; } else if (! strcasecmp (value, "sendmail/pipe")) { mts_method = "sendmail/pipe"; sm_mts = MTS_SENDMAIL_PIPE; } else { adios (NULL, "unsupported mts selection \"%s\"", value); } } /* * Read the configuration file for the nmh interface * to the mail transport system (MTS). */ void mts_init (void) { const char *cp; FILE *fp; static int inited = 0; if (inited++ || (fp = fopen (get_mtsconf_pathname(), "r")) == NULL) return; mts_read_conf_file(fp); fclose (fp); cp = get_mtsuserconf_pathname(); if (cp != NULL && ((fp = fopen (get_mtsuserconf_pathname(), "r")) != NULL)) { mts_read_conf_file(fp); fclose (fp); } save_mts_method (mts_method); } #define QUOTE '\\' /* * Convert escaped values, malloc some new space, * and copy string to malloc'ed memory. */ static char * tailor_value (char *s) { int i, r; char *bp; char buffer[BUFSIZ]; for (bp = buffer; *s; bp++, s++) { if (*s != QUOTE) { *bp = *s; } else { switch (*++s) { case 'b': *bp = '\b'; break; case 'f': *bp = '\f'; break; case 'n': *bp = '\n'; break; case 't': *bp = '\t'; break; case 0: s--; /* FALLTHRU */ case QUOTE: *bp = QUOTE; break; default: if (!isdigit ((unsigned char) *s)) { *bp++ = QUOTE; *bp = *s; } r = ((unsigned char) *s) != '0' ? 10 : 8; for (i = 0; isdigit ((unsigned char) *s); s++) i *= r + ((unsigned char) *s) - '0'; s--; *bp = toascii (i); break; } } } *bp = 0; return mh_xstrdup(buffer); } /* * Get the fully qualified name of the local host. * * If flag is 0, then use anything out of mts.conf (like localname). * If flag is 1, then only use the "proper" local hostname. */ char * LocalName (int flag) { static char buffer0[BUFSIZ] = ""; static char buffer1[BUFSIZ] = ""; static char *buffer[] = { buffer0, buffer1 }; char *buf; struct addrinfo hints, *res; if (flag < 0 || flag > 1) return NULL; buf = buffer[flag]; /* check if we have cached the local name */ if (buf[0]) return buf; mts_init (); /* check if the mts.conf file specifies a "localname" */ if (*localname && flag == 0) { strncpy (buf, localname, sizeof(buffer0)); } else { memset(buf, 0, sizeof(buffer0)); /* first get our local name */ gethostname (buf, sizeof(buffer0) - 1); /* now fully qualify our name */ memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; hints.ai_family = PF_UNSPEC; if (getaddrinfo(buf, NULL, &hints, &res) == 0) { strncpy(buf, res->ai_canonname, sizeof(buffer0) - 1); freeaddrinfo(res); } } /* * If the mts.conf file specifies a "localdomain", * we append that now. This should rarely be needed. */ if (*localdomain) { strcat (buf, "."); strcat (buf, localdomain); } return buf; } /* * This is only for UUCP mail. It gets the hostname * as part of the UUCP "domain". */ char * SystemName (void) { static char buffer[BUFSIZ] = ""; /* check if we have cached the system name */ if (buffer[0]) return buffer; mts_init (); /* check if mts.conf file specifies a "systemname" */ if (*systemname) { strncpy (buffer, systemname, sizeof(buffer)); return buffer; } gethostname (buffer, sizeof(buffer)); return buffer; } /* * Get the username of current user */ char * getusername (void) { if (username[0] == '\0') getuserinfo(); return username; } /* * Get full name of current user (typically from GECOS * field of password file). */ char * getfullname (void) { if (username[0] == '\0') getuserinfo(); return fullname; } /* * Get the full local mailbox name. This is in the form: * * User Name */ char * getlocalmbox (void) { if (username[0] == '\0') getuserinfo(); return localmbox; } /* * Find the user's username and full name, and cache them. */ static void getuserinfo (void) { char *cp, *np; struct passwd *pw; if ((pw = getpwuid (getuid ())) == NULL || pw->pw_name == NULL || *pw->pw_name == '\0') { strncpy (username, "unknown", sizeof(username)); snprintf (fullname, sizeof(fullname), "The Unknown User-ID (%d)", (int) getuid ()); return; } /* username */ /* If there's a Local-Mailbox profile component, try to extract the username from it. But don't try very hard, this assumes the very simple User Name form. Note that post(8) and whom(1) use context_foil (), so they won't see the profile component. */ if ((np = context_find("Local-Mailbox")) != NULL) { char *left_angle_bracket = strchr (np, '<'); char *at_sign = strchr (np, '@'); char *right_angle_bracket = strchr (np, '>'); strncpy(localmbox, np, sizeof(localmbox)); if (left_angle_bracket && at_sign && right_angle_bracket) { if (at_sign > left_angle_bracket && at_sign - left_angle_bracket < BUFSIZ) { strncpy(username, left_angle_bracket + 1, at_sign - left_angle_bracket - 1); } } } if (username[0] == '\0') { strncpy (username, pw->pw_name, sizeof(username)); } username[sizeof(username) - 1] = '\0'; escape_local_part(username, sizeof(username)); /* fullname */ np = pw->pw_gecos; /* Get the user's real name from the GECOS field. Stop once we hit a ',', which some OSes use to separate other 'finger' information in the GECOS field, like phone number. */ for (cp = fullname; *np != '\0' && *np != ','; *cp++ = *np++) continue; *cp = '\0'; /* The $SIGNATURE environment variable overrides the GECOS field's idea of your real name. If SIGNATURE isn't set, use the Signature profile setting if it exists. Note that post(8) and whom(1) use context_foil (), so they won't see the profile component. */ if ((cp = getenv ("SIGNATURE")) && *cp) strncpy (fullname, cp, sizeof(fullname)); else if ((cp = context_find("Signature"))) strncpy (fullname, cp, sizeof(fullname)); fullname[sizeof(fullname) - 1] = '\0'; escape_display_name(fullname, sizeof(fullname)); /* localmbox, if not using Local-Mailbox */ if (localmbox[0] == '\0') { snprintf(localmbox, sizeof(localmbox), "%s <%s@%s>", fullname, username, LocalName(0)); } localmbox[sizeof(localmbox) - 1] = '\0'; } static const char* get_mtsconf_pathname (void) { const char *cp = getenv ( "MHMTSCONF" ); if (cp != NULL && *cp != '\0') { return cp; } return mtsconf; } static const char* get_mtsuserconf_pathname (void) { const char *cp = getenv ( "MHMTSUSERCONF" ); if (cp != NULL && *cp != '\0') { return cp; } return NULL; } static void mts_read_conf_file (FILE *fp) { char *bp, *cp, buffer[BUFSIZ]; struct bind *b; while (fgets (buffer, sizeof(buffer), fp)) { if (!(cp = strchr(buffer, '\n'))) break; *cp = 0; if (*buffer == '#' || *buffer == '\0') continue; if (!(bp = strchr(buffer, ':'))) break; *bp++ = 0; while (isspace ((unsigned char) *bp)) *bp++ = 0; for (b = binds; b->keyword; b++) if (!strcmp (buffer, b->keyword)) break; if (b->keyword && (cp = tailor_value (bp))) *b->value = cp; } } nmh-1.7.1-RC3/sbr/netsec.c000644 007761 000024 00000124470 13243042053 015201 0ustar00kenhstaff000000 000000 /* netsec.c -- Network security routines for handling protocols that * require SASL and/or TLS. * * This code is Copyright (c) 2016, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #ifdef CYRUS_SASL #include #include # if SASL_VERSION_FULL < 0x020125 /* Cyrus SASL 2.1.25 introduced the sasl_callback_ft prototype, which has an explicit void parameter list, according to best practice. So we need to cast to avoid compile warnings. Provide this prototype for earlier versions. */ typedef int (*sasl_callback_ft)(); # endif /* SASL_VERSION_FULL < 0x020125 */ static int netsec_get_user(void *context, int id, const char **result, unsigned int *len); static int netsec_get_password(sasl_conn_t *conn, void *context, int id, sasl_secret_t **psecret); static int sasl_initialized = 0; #define SASL_MAXRECVBUF 65536 #endif /* CYRUS_SASL */ #ifdef TLS_SUPPORT #include #include static int tls_initialized = 0; static SSL_CTX *sslctx = NULL; /* SSL Context */ #endif /* TLS_SUPPORT */ /* I'm going to hardcode this for now; maybe make it adjustable later? */ #define NETSEC_BUFSIZE 65536 /* * Our context structure, which holds all of the relevant information * about a connection. */ struct _netsec_context { int ns_readfd; /* Read descriptor for network connection */ int ns_writefd; /* Write descriptor for network connection */ int ns_noclose; /* Do not close file descriptors if set */ int ns_snoop; /* If true, display network data */ int ns_snoop_noend; /* If true, didn't get a CR/LF on last line */ netsec_snoop_callback *ns_snoop_cb; /* Snoop output callback */ void *ns_snoop_context; /* Context data for snoop function */ int ns_timeout; /* Network read timeout, in seconds */ char *ns_userid; /* Userid for authentication */ char *ns_hostname; /* Hostname we've connected to */ unsigned char *ns_inbuffer; /* Our read input buffer */ unsigned char *ns_inptr; /* Our read buffer input pointer */ unsigned int ns_inbuflen; /* Length of data in input buffer */ unsigned int ns_inbufsize; /* Size of input buffer */ unsigned char *ns_outbuffer;/* Output buffer */ unsigned char *ns_outptr; /* Output buffer pointer */ unsigned int ns_outbuflen; /* Output buffer data length */ unsigned int ns_outbufsize; /* Output buffer size */ char *sasl_mech; /* User-requested mechanism */ char *sasl_chosen_mech; /* Mechanism chosen by SASL */ netsec_sasl_callback sasl_proto_cb; /* SASL callback we use */ #ifdef OAUTH_SUPPORT char *oauth_service; /* OAuth2 service name */ #endif /* OAUTH_SUPPORT */ #ifdef CYRUS_SASL sasl_conn_t *sasl_conn; /* SASL connection context */ sasl_ssf_t sasl_ssf; /* SASL Security Strength Factor */ sasl_callback_t *sasl_cbs; /* Callbacks used by SASL */ nmh_creds_t sasl_creds; /* Credentials (username/password) */ sasl_secret_t *sasl_secret; /* SASL password structure */ int sasl_seclayer; /* If true, SASL security layer is enabled */ char *sasl_tmpbuf; /* Temporary read buffer for decodes */ size_t sasl_maxbufsize; /* Maximum negotiated SASL buffer size */ #endif /* CYRUS_SASL */ #ifdef TLS_SUPPORT BIO *ssl_io; /* BIO used for connection I/O */ int tls_active; /* If true, TLS is running */ #endif /* TLS_SUPPORT */ }; /* * Function to read data from the actual network socket */ static int netsec_fillread(netsec_context *ns_context, char **errstr); /* * Code to check the ASCII content of a byte array. */ static int checkascii(const unsigned char *byte, size_t len); /* * How this code works, in general. * * _If_ we are using no encryption then we buffer the network data * through ns_inbuffer and ns_outbuffer. That should be relatively * self-explanatory. * * If we use encryption, then ns_inbuffer and ns_outbuffer contain the * cleartext data. When it comes time to send the encrypted data on the * (either from a flush or the buffer is full) we either use BIO_write() * for TLS or sasl_encode() (followed by a write() for Cyrus-SASL. For * reads we either use BIO_read() (TLS) or do a network read into a * temporary buffer and use sasl_decode() (Cyrus-SASL). Note that if * negotiate TLS then we disable SASL encryption. * * We used to use a buffering BIO for the reads/writes for TLS, but it * ended up being complicated to special-case the buffering for everything * except TLS, so the buffering is now unified, no matter which encryption * method is being used (even none). * * For SASL authentication, we make use of (for now) the Cyrus-SASL * library. For some mechanisms, we implement those mechanisms directly * since the Cyrus SASL library doesn't support them (like OAuth). */ /* * Allocate and initialize our security context */ netsec_context * netsec_init(void) { netsec_context *nsc; NEW(nsc); nsc->ns_readfd = -1; nsc->ns_writefd = -1; nsc->ns_noclose = 0; nsc->ns_snoop = 0; nsc->ns_snoop_noend = 0; nsc->ns_snoop_cb = NULL; nsc->ns_snoop_context = NULL; nsc->ns_userid = NULL; nsc->ns_hostname = NULL; nsc->ns_timeout = 60; /* Our default */ nsc->ns_inbufsize = NETSEC_BUFSIZE; nsc->ns_inbuffer = mh_xmalloc(nsc->ns_inbufsize); nsc->ns_inptr = nsc->ns_inbuffer; nsc->ns_inbuflen = 0; nsc->ns_outbufsize = NETSEC_BUFSIZE; nsc->ns_outbuffer = mh_xmalloc(nsc->ns_outbufsize); nsc->ns_outptr = nsc->ns_outbuffer; nsc->ns_outbuflen = 0; nsc->sasl_mech = NULL; nsc->sasl_chosen_mech = NULL; nsc->sasl_proto_cb = NULL; #ifdef OAUTH_SUPPORT nsc->oauth_service = NULL; #endif /* OAUTH_SUPPORT */ #ifdef CYRUS_SASL nsc->sasl_conn = NULL; nsc->sasl_cbs = NULL; nsc->sasl_creds = NULL; nsc->sasl_secret = NULL; nsc->sasl_ssf = 0; nsc->sasl_seclayer = 0; nsc->sasl_tmpbuf = NULL; nsc->sasl_maxbufsize = 0; #endif /* CYRUS_SASL */ #ifdef TLS_SUPPORT nsc->ssl_io = NULL; nsc->tls_active = 0; #endif /* TLS_SUPPORT */ return nsc; } /* * Shutdown the connection completely and free all resources. */ void netsec_shutdown(netsec_context *nsc) { mh_xfree(nsc->ns_userid); mh_xfree(nsc->ns_hostname); mh_xfree(nsc->ns_inbuffer); mh_xfree(nsc->ns_outbuffer); mh_xfree(nsc->sasl_mech); mh_xfree(nsc->sasl_chosen_mech); #ifdef OAUTH_SERVICE mh_xfree(nsc->oauth_service); #endif /* OAUTH_SERVICE */ #ifdef CYRUS_SASL if (nsc->sasl_conn) sasl_dispose(&nsc->sasl_conn); mh_xfree(nsc->sasl_cbs); if (nsc->sasl_creds) nmh_credentials_free(nsc->sasl_creds); if (nsc->sasl_secret) { if (nsc->sasl_secret->len > 0) { memset(nsc->sasl_secret->data, 0, nsc->sasl_secret->len); } free(nsc->sasl_secret); } mh_xfree(nsc->sasl_tmpbuf); #endif /* CYRUS_SASL */ #ifdef TLS_SUPPORT if (nsc->ssl_io) /* * I checked; BIO_free_all() will cause SSL_shutdown to be called * on the SSL object in the chain. */ BIO_free_all(nsc->ssl_io); #endif /* TLS_SUPPORT */ if (! nsc->ns_noclose) { if (nsc->ns_readfd != -1) close(nsc->ns_readfd); if (nsc->ns_writefd != -1 && nsc->ns_writefd != nsc->ns_readfd) close(nsc->ns_writefd); } free(nsc); } /* * Set the file descriptor for our context */ void netsec_set_fd(netsec_context *nsc, int readfd, int writefd) { nsc->ns_readfd = readfd; nsc->ns_writefd = writefd; } /* * Set the userid used for authentication for this context */ void netsec_set_userid(netsec_context *nsc, const char *userid) { nsc->ns_userid = getcpy(userid); } /* * Set the hostname of the remote host we're connecting to. */ void netsec_set_hostname(netsec_context *nsc, const char *hostname) { nsc->ns_hostname = mh_xstrdup(hostname); } /* * Get the snoop flag for this connection */ int netsec_get_snoop(netsec_context *nsc) { return nsc->ns_snoop; } /* * Set the snoop flag for this connection */ void netsec_set_snoop(netsec_context *nsc, int snoop) { nsc->ns_snoop = snoop; } /* * Set the snoop callback for this connection. */ void netsec_set_snoop_callback(netsec_context *nsc, netsec_snoop_callback callback, void *context) { nsc->ns_snoop_cb = callback; nsc->ns_snoop_context = context; } /* * A base64-decoding snoop callback */ void netsec_b64_snoop_decoder(netsec_context *nsc, const char *string, size_t len, void *context) { unsigned char *decoded; size_t decodedlen; int offset; NMH_UNUSED(nsc); offset = context ? *((int *) context) : 0; if (offset > 0) { /* * Output non-base64 data first. */ fprintf(stderr, "%.*s", offset, string); string += offset; len -= offset; } if (decodeBase64(string, &decoded, &decodedlen, 1, NULL) == OK) { /* * Some mechanisms produce large binary tokens, which aren't really * readable. So let's do a simple heuristic. If the token is greater * than 100 characters _and_ the first 100 bytes are more than 50% * non-ASCII, then don't print the decoded buffer, just the * base64 text. */ if (decodedlen > 100 && !checkascii(decoded, 100)) { fprintf(stderr, "%.*s\n", (int) len, string); } else { char *hexified; hexify(decoded, decodedlen, &hexified); fprintf(stderr, "b64<%s>\n", hexified); free(hexified); } free(decoded); } else { fprintf(stderr, "%.*s\n", (int) len, string); } } /* * If the ASCII content is > 50%, return 1 */ static int checkascii(const unsigned char *bytes, size_t len) { size_t count = 0, half = len / 2; while (len-- > 0) { if (isascii(*bytes) && isprint(*bytes) && ++count > half) return 1; bytes++; /* No chance by this point */ if (count + len < half) return 0; } return 0; } /* * Set the read timeout for this connection */ void netsec_set_timeout(netsec_context *nsc, int timeout) { nsc->ns_timeout = timeout; } /* * Read data from the network. Basically, return anything in our buffer, * otherwise fill from the network. */ ssize_t netsec_read(netsec_context *nsc, void *buffer, size_t size, char **errstr) { int retlen; /* * If our buffer is empty, then we should fill it now */ if (nsc->ns_inbuflen == 0) { if (netsec_fillread(nsc, errstr) != OK) return NOTOK; } /* * netsec_fillread only returns if the buffer is full, so we can * assume here that this has something in it. */ retlen = min(size, nsc->ns_inbuflen); memcpy(buffer, nsc->ns_inptr, retlen); if (retlen == (int) nsc->ns_inbuflen) { /* * We've emptied our buffer, so reset everything. */ nsc->ns_inptr = nsc->ns_inbuffer; nsc->ns_inbuflen = 0; } else { nsc->ns_inptr += size; nsc->ns_inbuflen -= size; } return OK; } /* * Get a "line" (CR/LF) terminated from the network. * * Okay, we play some games here, so pay attention: * * - Unlike every other function, we return a pointer to the * existing buffer. This pointer is valid until you call another * read function again. * - We NUL-terminate the buffer right at the end, before the CR-LF terminator. * - Technically we look for a LF; if we find a CR right before it, then * we back up one. * - If your data may contain embedded NULs, this won't work. You should * be using netsec_read() in that case. */ char * netsec_readline(netsec_context *nsc, size_t *len, char **errstr) { unsigned char *ptr = nsc->ns_inptr; size_t count = 0, offset; retry: /* * Search through our existing buffer for a LF */ while (count < nsc->ns_inbuflen) { count++; if (*ptr++ == '\n') { char *sptr = (char *) nsc->ns_inptr; if (count > 1 && *(ptr - 2) == '\r') ptr--; *--ptr = '\0'; if (len) *len = ptr - nsc->ns_inptr; nsc->ns_inptr += count; nsc->ns_inbuflen -= count; if (nsc->ns_snoop) { #ifdef CYRUS_SASL if (nsc->sasl_seclayer) fprintf(stderr, "(sasl-decrypted) "); #endif /* CYRUS_SASL */ #ifdef TLS_SUPPORT if (nsc->tls_active) fprintf(stderr, "(tls-decrypted) "); #endif /* TLS_SUPPORT */ fprintf(stderr, "<= "); if (nsc->ns_snoop_cb) nsc->ns_snoop_cb(nsc, sptr, strlen(sptr), nsc->ns_snoop_context); else fprintf(stderr, "%s\n", sptr); } return sptr; } } /* * Hm, we didn't find a \n. If we've already searched half of the input * buffer, return an error. */ if (count >= nsc->ns_inbufsize / 2) { netsec_err(errstr, "Unable to find a line terminator after %d bytes", count); return NULL; } /* * Okay, get some more network data. This may move inptr, so regenerate * our ptr value; */ offset = ptr - nsc->ns_inptr; if (netsec_fillread(nsc, errstr) != OK) return NULL; ptr = nsc->ns_inptr + offset; goto retry; return NULL; /* Should never reach this */ } /* * Fill our read buffer with some data from the network. */ static int netsec_fillread(netsec_context *nsc, char **errstr) { unsigned char *end; char *readbuf; size_t readbufsize, remaining, startoffset; int rc; /* * If inbuflen is zero, that means the buffer has been emptied * completely. In that case move inptr back to the start. */ if (nsc->ns_inbuflen == 0) { nsc->ns_inptr = nsc->ns_inbuffer; } #if defined(CYRUS_SASL) || defined(TLS_SUPPORT) retry: #endif /* CYRUS_SASL || TLS_SUPPORT */ /* * If we are using TLS and there's anything pending, then skip the * select call */ #ifdef TLS_SUPPORT if (!nsc->tls_active || BIO_pending(nsc->ssl_io) == 0) #endif /* TLS_SUPPORT */ { struct timeval tv; fd_set rfds; FD_ZERO(&rfds); FD_SET(nsc->ns_readfd, &rfds); tv.tv_sec = nsc->ns_timeout; tv.tv_usec = 0; rc = select(nsc->ns_readfd + 1, &rfds, NULL, NULL, &tv); if (rc == -1) { netsec_err(errstr, "select() while reading failed: %s", strerror(errno)); return NOTOK; } if (rc == 0) { netsec_err(errstr, "read() timed out after %d seconds", nsc->ns_timeout); return NOTOK; } /* * At this point, we know that rc is 1, so there's not even any * point to check to see if our descriptor is set in rfds. */ } /* * Some explanation: * * startoffset is the offset from the beginning of the input * buffer to data that is in our input buffer, but has not yet * been consumed. This can be non-zero if functions like * netsec_readline() leave leftover data. * * remaining is the remaining amount of unconsumed data in the input * buffer. * * end is a pointer to the end of the valid data + 1; it's where * the next read should go. */ startoffset = nsc->ns_inptr - nsc->ns_inbuffer; remaining = nsc->ns_inbufsize - (startoffset + nsc->ns_inbuflen); end = nsc->ns_inptr + nsc->ns_inbuflen; /* * If we're past the halfway point in our read buffers, shuffle everything * back to the beginning. */ if (startoffset > nsc->ns_inbufsize / 2) { memmove(nsc->ns_inbuffer, nsc->ns_inptr, nsc->ns_inbuflen); nsc->ns_inptr = nsc->ns_inbuffer; startoffset = 0; remaining = nsc->ns_inbufsize - nsc->ns_inbuflen; end = nsc->ns_inptr + nsc->ns_inbuflen; } /* * If we are using TLS, then just read via the BIO. But we still * use our local buffer. */ #ifdef TLS_SUPPORT if (nsc->tls_active) { rc = BIO_read(nsc->ssl_io, end, remaining); if (rc == 0) { SSL *ssl; int errcode; /* * Check to see if we're supposed to retry; if so, * then go back and read again. */ if (BIO_should_retry(nsc->ssl_io)) goto retry; /* * Okay, fine. Get the real error out of the SSL context. */ if (BIO_get_ssl(nsc->ssl_io, &ssl) < 1) { netsec_err(errstr, "SSL_read() returned 0, but cannot " "retrieve SSL context"); return NOTOK; } errcode = SSL_get_error(ssl, rc); if (errcode == SSL_ERROR_ZERO_RETURN) { netsec_err(errstr, "TLS peer closed remote connection"); } else { netsec_err(errstr, "TLS network read failed: %s", ERR_error_string(ERR_peek_last_error(), NULL)); } if (nsc->ns_snoop) ERR_print_errors_fp(stderr); return NOTOK; } if (rc < 0) { /* Definitely an error */ netsec_err(errstr, "Read on TLS connection failed: %s", ERR_error_string(ERR_get_error(), NULL)); return NOTOK; } nsc->ns_inbuflen += rc; return OK; } #endif /* TLS_SUPPORT */ /* * Okay, time to read some data. Either we're just doing it straight * or we're passing it through sasl_decode() first. */ #ifdef CYRUS_SASL if (nsc->sasl_seclayer) { readbuf = nsc->sasl_tmpbuf; readbufsize = nsc->sasl_maxbufsize; } else #endif /* CYRUS_SASL */ { readbuf = (char *) end; readbufsize = remaining; } /* * At this point, we should have active data on the connection (see * select() above) so this read SHOULDN'T block. Hopefully. */ rc = read(nsc->ns_readfd, readbuf, readbufsize); if (rc == 0) { netsec_err(errstr, "Received EOF on network read"); return NOTOK; } if (rc < 0) { netsec_err(errstr, "Network read failed: %s", strerror(errno)); return NOTOK; } /* * Okay, so we've had a successful read. If we are doing SASL security * layers, pass this through sasl_decode(). sasl_decode() can return * 0 bytes decoded; if that happens, jump back to the beginning. Otherwise * we can just update our length pointer. */ #ifdef CYRUS_SASL if (nsc->sasl_seclayer) { const char *tmpout; unsigned int tmpoutlen; rc = sasl_decode(nsc->sasl_conn, nsc->sasl_tmpbuf, rc, &tmpout, &tmpoutlen); if (rc != SASL_OK) { netsec_err(errstr, "Unable to decode SASL network data: %s", sasl_errdetail(nsc->sasl_conn)); return NOTOK; } if (tmpoutlen == 0) goto retry; /* * Just in case ... */ if (tmpoutlen > remaining) { netsec_err(errstr, "Internal error: SASL decode buffer overflow!"); return NOTOK; } memcpy(end, tmpout, tmpoutlen); nsc->ns_inbuflen += tmpoutlen; } else #endif /* CYRUS_SASL */ nsc->ns_inbuflen += rc; return OK; } /* * Write data to our network connection. Really, fill up the buffer as * much as we can, and flush it out if necessary. netsec_flush() does * the real work. */ int netsec_write(netsec_context *nsc, const void *buffer, size_t size, char **errstr) { const unsigned char *bufptr = buffer; int rc, remaining; /* Just in case */ if (size == 0) return OK; /* * Run a loop copying in data to our local buffer; when we're done with * any buffer overflows then just copy any remaining data in. */ while ((int) size >= (remaining = nsc->ns_outbufsize - nsc->ns_outbuflen)) { memcpy(nsc->ns_outptr, bufptr, remaining); /* * In theory I should increment outptr, but netsec_flush just resets * it anyway. */ nsc->ns_outbuflen = nsc->ns_outbufsize; rc = netsec_flush(nsc, errstr); if (rc != OK) return NOTOK; bufptr += remaining; size -= remaining; } /* * Copy any leftover data into the buffer. */ if (size > 0) { memcpy(nsc->ns_outptr, bufptr, size); nsc->ns_outptr += size; nsc->ns_outbuflen += size; } return OK; } /* * Our network printf() routine, which really just calls netsec_vprintf(). */ int netsec_printf(netsec_context *nsc, char **errstr, const char *format, ...) { va_list ap; int rc; va_start(ap, format); rc = netsec_vprintf(nsc, errstr, format, ap); va_end(ap); return rc; } /* * Write bytes to the network using printf()-style formatting. * * Again, for the most part copy stuff into our buffer to be flushed * out later. */ int netsec_vprintf(netsec_context *nsc, char **errstr, const char *format, va_list ap) { int rc; va_list apcopy; /* * Cheat a little. If we can fit the data into our outgoing buffer, * great! If not, generate a flush and retry once. */ retry: va_copy(apcopy, ap); rc = vsnprintf((char *) nsc->ns_outptr, nsc->ns_outbufsize - nsc->ns_outbuflen, format, apcopy); va_end(apcopy); if (rc >= (int) (nsc->ns_outbufsize - nsc->ns_outbuflen)) { /* * This means we have an overflow. Note that we don't actually * make use of the terminating NUL, but according to the spec * vsnprintf() won't write to the last byte in the string; that's * why we have to use >= in the comparison above. */ if (nsc->ns_outbuffer == nsc->ns_outptr) { /* * Whoops, if the buffer pointer was the same as the start of the * buffer, that means we overflowed the internal buffer. * At that point, just give up. */ netsec_err(errstr, "Internal error: wanted to printf() a total of " "%d bytes, but our buffer size was only %d bytes", rc, nsc->ns_outbufsize); return NOTOK; } /* * Generate a flush (which may be inefficient, but hopefully * it isn't) and then try again. */ if (netsec_flush(nsc, errstr) != OK) return NOTOK; /* * After this, outbuffer should == outptr, so we shouldn't * hit this next time around. */ goto retry; } if (nsc->ns_snoop) { int outlen = rc; if (outlen > 0 && nsc->ns_outptr[outlen - 1] == '\n') { outlen--; if (outlen > 0 && nsc->ns_outptr[outlen - 1] == '\r') outlen--; } else { nsc->ns_snoop_noend = 1; } if (outlen > 0 || nsc->ns_snoop_noend == 0) { #ifdef CYRUS_SASL if (nsc->sasl_seclayer) fprintf(stderr, "(sasl-encrypted) "); #endif /* CYRUS_SASL */ #ifdef TLS_SUPPORT if (nsc->tls_active) fprintf(stderr, "(tls-encrypted) "); #endif /* TLS_SUPPORT */ fprintf(stderr, "=> "); if (nsc->ns_snoop_cb) nsc->ns_snoop_cb(nsc, (char *) nsc->ns_outptr, outlen, nsc->ns_snoop_context); else fprintf(stderr, "%.*s\n", outlen, nsc->ns_outptr); } else { nsc->ns_snoop_noend = 0; } } nsc->ns_outptr += rc; nsc->ns_outbuflen += rc; return OK; } /* * Flush out any buffered data in our output buffers. This routine is * actually where the real network writes take place. */ int netsec_flush(netsec_context *nsc, char **errstr) { const char *netoutbuf = (const char *) nsc->ns_outbuffer; unsigned int netoutlen = nsc->ns_outbuflen; int rc; /* * Small optimization */ if (netoutlen == 0) return OK; /* * If SASL security layers are in effect, run the data through * sasl_encode() first. */ #ifdef CYRUS_SASL if (nsc->sasl_seclayer) { rc = sasl_encode(nsc->sasl_conn, (const char *) nsc->ns_outbuffer, nsc->ns_outbuflen, &netoutbuf, &netoutlen); if (rc != SASL_OK) { netsec_err(errstr, "SASL data encoding failed: %s", sasl_errdetail(nsc->sasl_conn)); return NOTOK; } } #endif /* CYRUS_SASL */ /* * If TLS is active, then use those functions to write out the * data. */ #ifdef TLS_SUPPORT if (nsc->tls_active) { if (BIO_write(nsc->ssl_io, netoutbuf, netoutlen) <= 0) { netsec_err(errstr, "Error writing to TLS connection: %s", ERR_error_string(ERR_get_error(), NULL)); return NOTOK; } } else #endif /* TLS_SUPPORT */ { rc = write(nsc->ns_writefd, netoutbuf, netoutlen); if (rc < 0) { netsec_err(errstr, "write() failed: %s", strerror(errno)); return NOTOK; } } nsc->ns_outptr = nsc->ns_outbuffer; nsc->ns_outbuflen = 0; return OK; } /* * Set various SASL protocol parameters */ int netsec_set_sasl_params(netsec_context *nsc, const char *service, const char *mechanism, netsec_sasl_callback callback, char **errstr) { #ifdef CYRUS_SASL sasl_callback_t *sasl_cbs; int retval; if (!nsc->ns_hostname) { netsec_err(errstr, "Internal error: ns_hostname is NULL"); return NOTOK; } if (! sasl_initialized) { retval = sasl_client_init(NULL); if (retval != SASL_OK) { netsec_err(errstr, "SASL client initialization failed: %s", sasl_errstring(retval, NULL, NULL)); return NOTOK; } sasl_initialized++; } /* * Allocate an array of SASL callbacks for this connection. * Right now we just allocate an array of four callbacks. */ sasl_cbs = mh_xmalloc(sizeof(*sasl_cbs) * 4); sasl_cbs[0].id = SASL_CB_USER; sasl_cbs[0].proc = (sasl_callback_ft) netsec_get_user; sasl_cbs[0].context = nsc; sasl_cbs[1].id = SASL_CB_AUTHNAME; sasl_cbs[1].proc = (sasl_callback_ft) netsec_get_user; sasl_cbs[1].context = nsc; sasl_cbs[2].id = SASL_CB_PASS; sasl_cbs[2].proc = (sasl_callback_ft) netsec_get_password; sasl_cbs[2].context = nsc; sasl_cbs[3].id = SASL_CB_LIST_END; sasl_cbs[3].proc = NULL; sasl_cbs[3].context = NULL; nsc->sasl_cbs = sasl_cbs; retval = sasl_client_new(service, nsc->ns_hostname, NULL, NULL, nsc->sasl_cbs, 0, &nsc->sasl_conn); if (retval) { netsec_err(errstr, "SASL new client allocation failed: %s", sasl_errstring(retval, NULL, NULL)); return NOTOK; } /* * Set up our credentials */ nsc->sasl_creds = nmh_get_credentials(nsc->ns_hostname, nsc->ns_userid); #else /* CYRUS_SASL */ NMH_UNUSED(service); NMH_UNUSED(errstr); #endif /* CYRUS_SASL */ /* * According to the RFC, mechanisms can only be uppercase letter, numbers, * and a hyphen or underscore. So make sure we uppercase any letters * in case the user passed in lowercase. */ if (mechanism) { char *p; nsc->sasl_mech = mh_xstrdup(mechanism); for (p = nsc->sasl_mech; *p; p++) if (isascii((unsigned char) *p)) /* Leave non-ASCII lower alone. */ *p = toupper((unsigned char) *p); } nsc->sasl_proto_cb = callback; return OK; } #ifdef CYRUS_SASL /* * Our userid callback; return the specified username to the SASL * library when asked. */ int netsec_get_user(void *context, int id, const char **result, unsigned int *len) { netsec_context *nsc = (netsec_context *) context; if (! result || (id != SASL_CB_USER && id != SASL_CB_AUTHNAME)) return SASL_BADPARAM; *result = nmh_cred_get_user(nsc->sasl_creds); if (len) *len = strlen(*result); return SASL_OK; } /* * Retrieve a password and return it to SASL */ static int netsec_get_password(sasl_conn_t *conn, void *context, int id, sasl_secret_t **psecret) { netsec_context *nsc = (netsec_context *) context; const char *password; int len; NMH_UNUSED(conn); if (! psecret || id != SASL_CB_PASS) return SASL_BADPARAM; password = nmh_cred_get_password(nsc->sasl_creds); len = strlen(password); /* * sasl_secret_t includes 1 bytes for "data" already, so that leaves * us room for a terminating NUL */ *psecret = (sasl_secret_t *) malloc(sizeof(sasl_secret_t) + len); if (! *psecret) return SASL_NOMEM; (*psecret)->len = len; strcpy((char *) (*psecret)->data, password); nsc->sasl_secret = *psecret; return SASL_OK; } #endif /* CYRUS_SASL */ /* * Negotiate SASL on this connection */ int netsec_negotiate_sasl(netsec_context *nsc, const char *mechlist, char **errstr) { #ifdef CYRUS_SASL sasl_security_properties_t secprops; const char *chosen_mech; const unsigned char *saslbuf; unsigned char *outbuf; unsigned int saslbuflen, outbuflen; sasl_ssf_t *ssf; int *outbufmax; #endif #ifdef OAUTH_SUPPORT unsigned char *xoauth_client_res; size_t xoauth_client_res_len; #endif /* OAUTH_SUPPORT */ #if defined CYRUS_SASL || defined OAUTH_SUPPORT int rc; #endif /* CYRUS_SASL || OAUTH_SUPPORT */ /* * If we've been passed a requested mechanism, check our mechanism * list from the protocol. If it's not supported, return an error. */ if (nsc->sasl_mech) { char **str, *mlist = getcpy(mechlist); int i; str = brkstring(mlist, " ", NULL); for (i = 0; str[i] != NULL; i++) { if (strcasecmp(nsc->sasl_mech, str[i]) == 0) { break; } } i = (str[i] == NULL); free(mlist); if (i) { netsec_err(errstr, "Chosen mechanism %s not supported by server", nsc->sasl_mech); return NOTOK; } } #ifdef OAUTH_SUPPORT if (nsc->sasl_mech && strcasecmp(nsc->sasl_mech, "XOAUTH2") == 0) { /* * This should be relatively straightforward, but requires some * help from the plugin. Basically, if XOAUTH2 is a success, * the callback has to return success, but no output data. If * there is output data, it will be assumed that it is the JSON * error message. */ if (! nsc->oauth_service) { netsec_err(errstr, "Internal error: OAuth2 service name not given"); return NOTOK; } nsc->sasl_chosen_mech = mh_xstrdup(nsc->sasl_mech); if (mh_oauth_do_xoauth(nsc->ns_userid, nsc->oauth_service, &xoauth_client_res, &xoauth_client_res_len, nsc->ns_snoop ? stderr : NULL) != OK) { netsec_err(errstr, "Internal error: Unable to get OAuth2 " "bearer token"); return NOTOK; } rc = nsc->sasl_proto_cb(NETSEC_SASL_START, xoauth_client_res, xoauth_client_res_len, NULL, 0, errstr); free(xoauth_client_res); if (rc != OK) return NOTOK; /* * Okay, we need to do a NETSEC_SASL_FINISH now. If we return * success, we indicate that with no output data. But if we * fail, then send a blank message and get the resulting * error. */ rc = nsc->sasl_proto_cb(NETSEC_SASL_FINISH, NULL, 0, NULL, 0, errstr); if (rc != OK) { /* * We're going to assume the error here is a JSON response; * we ignore it and send a blank message in response. We should * then get a failure messages with a useful error. We should * NOT get a success message at this point. */ free(*errstr); nsc->sasl_proto_cb(NETSEC_SASL_WRITE, NULL, 0, NULL, 0, NULL); rc = nsc->sasl_proto_cb(NETSEC_SASL_FINISH, NULL, 0, NULL, 0, errstr); if (rc == 0) { netsec_err(errstr, "Unexpected success after OAuth failure!"); } return NOTOK; } return OK; } #endif /* OAUTH_SUPPORT */ #ifdef CYRUS_SASL /* * In netsec_set_sasl_params, we've already done all of our setup with * sasl_client_init() and sasl_client_new(). So time to set security * properties, call sasl_client_start(), and generate the protocol * messages. */ memset(&secprops, 0, sizeof(secprops)); secprops.maxbufsize = SASL_MAXRECVBUF; /* * If we're using TLS, do not negotiate a security layer */ secprops.max_ssf = #ifdef TLS_SUPPORT nsc->tls_active ? 0 : #endif /* TLS_SUPPORT */ UINT_MAX; rc = sasl_setprop(nsc->sasl_conn, SASL_SEC_PROPS, &secprops); if (rc != SASL_OK) { netsec_err(errstr, "SASL security property initialization failed: %s", sasl_errstring(rc, NULL, NULL)); return NOTOK; } /* * Start the actual protocol negotiation, and go through the * sasl_client_step() loop (after sasl_client_start, of course). */ rc = sasl_client_start(nsc->sasl_conn, nsc->sasl_mech ? nsc->sasl_mech : mechlist, NULL, (const char **) &saslbuf, &saslbuflen, &chosen_mech); if (rc != SASL_OK && rc != SASL_CONTINUE) { netsec_err(errstr, "SASL client start failed: %s", sasl_errdetail(nsc->sasl_conn)); return NOTOK; } nsc->sasl_chosen_mech = getcpy(chosen_mech); if (nsc->sasl_proto_cb(NETSEC_SASL_START, saslbuf, saslbuflen, NULL, 0, errstr) != OK) return NOTOK; /* * We've written out our first message; enter in the step loop */ while (rc == SASL_CONTINUE) { /* * Call our SASL callback, which will handle the details of * reading data from the network. */ if (nsc->sasl_proto_cb(NETSEC_SASL_READ, NULL, 0, &outbuf, &outbuflen, errstr) != OK) { nsc->sasl_proto_cb(NETSEC_SASL_CANCEL, NULL, 0, NULL, 0, NULL); return NOTOK; } rc = sasl_client_step(nsc->sasl_conn, (char *) outbuf, outbuflen, NULL, (const char **) &saslbuf, &saslbuflen); mh_xfree(outbuf); if (rc != SASL_OK && rc != SASL_CONTINUE) { netsec_err(errstr, "SASL client negotiation failed: %s", sasl_errdetail(nsc->sasl_conn)); nsc->sasl_proto_cb(NETSEC_SASL_CANCEL, NULL, 0, NULL, 0, NULL); return NOTOK; } if (nsc->sasl_proto_cb(NETSEC_SASL_WRITE, saslbuf, saslbuflen, NULL, 0, errstr) != OK) { nsc->sasl_proto_cb(NETSEC_SASL_CANCEL, NULL, 0, NULL, 0, NULL); return NOTOK; } } /* * SASL exchanges should be complete, process the final response message * from the server. */ if (nsc->sasl_proto_cb(NETSEC_SASL_FINISH, NULL, 0, NULL, 0, errstr) != OK) { /* * At this point we can't really send an abort since the SASL dialog * has completed, so just bubble back up the error message. */ return NOTOK; } /* * At this point, SASL should be complete. Get a few properties * from the authentication exchange. */ rc = sasl_getprop(nsc->sasl_conn, SASL_SSF, (const void **) &ssf); if (rc != SASL_OK) { netsec_err(errstr, "Cannot retrieve SASL negotiated security " "strength factor: %s", sasl_errstring(rc, NULL, NULL)); return NOTOK; } nsc->sasl_ssf = *ssf; if (nsc->sasl_ssf > 0) { rc = sasl_getprop(nsc->sasl_conn, SASL_MAXOUTBUF, (const void **) &outbufmax); if (rc != SASL_OK) { netsec_err(errstr, "Cannot retrieve SASL negotiated output " "buffer size: %s", sasl_errstring(rc, NULL, NULL)); return NOTOK; } /* * If our output buffer isn't the same size as the input buffer, * reallocate it and set the new size (since we won't encode any * data larger than that). */ nsc->sasl_maxbufsize = *outbufmax; if (nsc->ns_outbufsize != nsc->sasl_maxbufsize) { nsc->ns_outbufsize = nsc->sasl_maxbufsize; nsc->ns_outbuffer = mh_xrealloc(nsc->ns_outbuffer, nsc->ns_outbufsize); /* * There shouldn't be any data in the buffer, but for * consistency's sake discard it. */ nsc->ns_outptr = nsc->ns_outbuffer; nsc->ns_outbuflen = 0; } /* * Allocate a buffer to do temporary reads into, before we * call sasl_decode() */ nsc->sasl_tmpbuf = mh_xmalloc(nsc->sasl_maxbufsize); /* * Okay, this is a bit weird. Make sure that the input buffer * is at least TWICE the size of the max buffer size. That's * because if we're consuming data but want to extend the current * buffer, we want to be sure there's room for another full buffer's * worth of data. */ if (nsc->ns_inbufsize < nsc->sasl_maxbufsize * 2) { size_t offset = nsc->ns_inptr - nsc->ns_inbuffer; nsc->ns_inbufsize = nsc->sasl_maxbufsize * 2; nsc->ns_inbuffer = mh_xrealloc(nsc->ns_inbuffer, nsc->ns_inbufsize); nsc->ns_inptr = nsc->ns_inbuffer + offset; } nsc->sasl_seclayer = 1; } return OK; #else /* * If we're at this point, then either we have NEITHER OAuth2 or * Cyrus-SASL compiled in, or have OAuth2 but didn't give the XOAUTH2 * mechanism on the command line. */ if (! nsc->sasl_mech) netsec_err(errstr, "SASL library support not available; please " "specify a SASL mechanism to use"); else netsec_err(errstr, "No support for the %s SASL mechanism", nsc->sasl_mech); return NOTOK; #endif /* CYRUS_SASL */ } /* * Retrieve our chosen SASL mechanism */ char * netsec_get_sasl_mechanism(netsec_context *nsc) { return nsc->sasl_chosen_mech; } /* * Set an OAuth2 service name, if we support it. */ int netsec_set_oauth_service(netsec_context *nsc, const char *service) { #ifdef OAUTH_SUPPORT nsc->oauth_service = getcpy(service); return OK; #else /* OAUTH_SUPPORT */ NMH_UNUSED(nsc); NMH_UNUSED(service); return NOTOK; #endif /* OAUTH_SUPPORT */ } /* * Initialize (and enable) TLS for this connection */ int netsec_set_tls(netsec_context *nsc, int tls, int noverify, char **errstr) { #ifdef TLS_SUPPORT if (tls) { SSL *ssl; BIO *rbio, *wbio, *ssl_bio; if (! tls_initialized) { SSL_library_init(); SSL_load_error_strings(); /* * Create the SSL context; this has the properties for all * SSL connections (we are only doing one), though. Make sure * we only support secure (known as of now) TLS protocols. */ sslctx = SSL_CTX_new(SSLv23_client_method()); if (! sslctx) { netsec_err(errstr, "Unable to initialize OpenSSL context: %s", ERR_error_string(ERR_get_error(), NULL)); return NOTOK; } SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1); if (!SSL_CTX_set_default_verify_paths(sslctx)) { netsec_err(errstr, "Unable to set default certificate " "verification paths: %s", ERR_error_string(ERR_get_error(), NULL)); return NOTOK; } tls_initialized++; } if (nsc->ns_readfd == -1 || nsc->ns_writefd == -1) { netsec_err(errstr, "Invalid file descriptor in netsec context"); return NOTOK; } /* * Create the SSL structure which holds the data for a single * TLS connection. */ ssl = SSL_new(sslctx); if (! ssl) { netsec_err(errstr, "Unable to create SSL connection: %s", ERR_error_string(ERR_get_error(), NULL)); return NOTOK; } /* * Never bother us, since we are using blocking sockets. */ SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); /* * This is a bit weird, so pay attention. * * We create a socket BIO, and bind it to our SSL connection. * That means reads and writes to the SSL connection will use our * supplied socket. * * Then we create an SSL BIO, and assign our current SSL connection * to it. This is done so our code stays simple if we want to use * any buffering BIOs (right now we do our own buffering). * So the chain looks like: * * SSL BIO -> socket BIO. */ rbio = BIO_new_socket(nsc->ns_readfd, BIO_CLOSE); if (! rbio) { netsec_err(errstr, "Unable to create a read socket BIO: %s", ERR_error_string(ERR_get_error(), NULL)); SSL_free(ssl); return NOTOK; } wbio = BIO_new_socket(nsc->ns_writefd, BIO_CLOSE); if (! wbio) { netsec_err(errstr, "Unable to create a write socket BIO: %s", ERR_error_string(ERR_get_error(), NULL)); SSL_free(ssl); BIO_free(rbio); return NOTOK; } SSL_set_bio(ssl, rbio, wbio); SSL_set_connect_state(ssl); /* * If noverify is NOT set, then do certificate validation. * Turning on SSL_VERIFY_PEER will verify the certificate chain * against locally stored root certificates (the locations are * set using SSL_CTX_set_default_verify_paths()), and we put * the hostname in the X509 verification parameters so the OpenSSL * code will verify that the hostname appears in the server * certificate. */ if (! noverify) { #ifdef HAVE_X509_VERIFY_PARAM_SET1_HOST X509_VERIFY_PARAM *param; #endif /* HAVE_X509_VERIFY_PARAM_SET1_HOST */ SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL); if (! nsc->ns_hostname) { netsec_err(errstr, "Internal error: hostname not set and " "certification verification enabled"); SSL_free(ssl); return NOTOK; } #ifdef HAVE_X509_VERIFY_PARAM_SET1_HOST param = SSL_get0_param(ssl); if (! X509_VERIFY_PARAM_set1_host(param, nsc->ns_hostname, 0)) { netsec_err(errstr, "Unable to add hostname %s to cert " "verification parameters: %s", nsc->ns_hostname, ERR_error_string(ERR_get_error(), NULL)); SSL_free(ssl); return NOTOK; } #endif /* HAVE_X509_VERIFY_PARAM_SET1_HOST */ } ssl_bio = BIO_new(BIO_f_ssl()); if (! ssl_bio) { netsec_err(errstr, "Unable to create a SSL BIO: %s", ERR_error_string(ERR_get_error(), NULL)); SSL_free(ssl); return NOTOK; } BIO_set_ssl(ssl_bio, ssl, BIO_CLOSE); nsc->ssl_io = ssl_bio; /* * Since SSL now owns these file descriptors, have it handle the * closing of them instead of netsec_shutdown(). */ nsc->ns_noclose = 1; return OK; } BIO_free_all(nsc->ssl_io); nsc->ssl_io = NULL; #else /* TLS_SUPPORT */ NMH_UNUSED(nsc); NMH_UNUSED(noverify); if (tls) { netsec_err(errstr, "TLS is not supported"); return NOTOK; } #endif /* TLS_SUPPORT */ return OK; } /* * Start TLS negotiation on this connection */ int netsec_negotiate_tls(netsec_context *nsc, char **errstr) { #ifdef TLS_SUPPORT if (! nsc->ssl_io) { netsec_err(errstr, "TLS has not been configured for this connection"); return NOTOK; } if (BIO_do_handshake(nsc->ssl_io) < 1) { unsigned long errcode = ERR_get_error(); /* * Print a more detailed message if it was certificate verification * failure. */ if (ERR_GET_LIB(errcode) == ERR_LIB_SSL && ERR_GET_REASON(errcode) == SSL_R_CERTIFICATE_VERIFY_FAILED) { SSL *ssl; if (BIO_get_ssl(nsc->ssl_io, &ssl) < 1) { netsec_err(errstr, "Certificate verification failed, but " "cannot retrieve SSL handle: %s", ERR_error_string(ERR_get_error(), NULL)); } else { netsec_err(errstr, "Server certificate verification failed: %s", X509_verify_cert_error_string( SSL_get_verify_result(ssl))); } } else { netsec_err(errstr, "TLS negotiation failed: %s", ERR_error_string(errcode, NULL)); } /* * Because negotiation failed, shut down TLS so we don't get any * garbage on the connection. Because of weirdness with SSL_shutdown, * we end up calling it twice: once explicitly, once as part of * BIO_free_all(). */ BIO_ssl_shutdown(nsc->ssl_io); BIO_free_all(nsc->ssl_io); nsc->ssl_io = NULL; return NOTOK; } if (nsc->ns_snoop) { SSL *ssl; if (BIO_get_ssl(nsc->ssl_io, &ssl) < 1) { fprintf(stderr, "WARNING: cannot determine SSL ciphers\n"); } else { const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl); fprintf(stderr, "TLS negotiation successful: %s(%d) %s\n", SSL_CIPHER_get_name(cipher), SSL_CIPHER_get_bits(cipher, NULL), SSL_CIPHER_get_version(cipher)); SSL_SESSION_print_fp(stderr, SSL_get_session(ssl)); } } nsc->tls_active = 1; return OK; #else /* TLS_SUPPORT */ NMH_UNUSED(nsc); netsec_err(errstr, "TLS not supported"); return NOTOK; #endif /* TLS_SUPPORT */ } /* * Generate an (allocated) error string */ void netsec_err(char **errstr, const char *fmt, ...) { va_list ap; size_t errbufsize; char *errbuf = NULL; int rc = 127; if (! errstr) return; do { errbufsize = rc + 1; errbuf = mh_xrealloc(errbuf, errbufsize); va_start(ap, fmt); rc = vsnprintf(errbuf, errbufsize, fmt, ap); va_end(ap); } while (rc >= (int) errbufsize); *errstr = errbuf; } nmh-1.7.1-RC3/sbr/oauth.c000755 007761 000024 00000077357 13243042053 015056 0ustar00kenhstaff000000 000000 /* oauth.c -- OAuth 2.0 implementation for XOAUTH2 in SMTP and POP3. * * This code is Copyright (c) 2014, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #ifdef OAUTH_SUPPORT #include #include #include #include #include #include #include #include #include #include #include #include #include "lock_file.h" #define JSON_TYPE "application/json" /* We pretend access tokens expire 60 seconds earlier than they actually do to * allow for separate processes to use and refresh access tokens. The process * that uses the access token (post) has an error if the token is expired; the * process that refreshes the access token (send) must have already refreshed if * the expiration is close. * * 60s is arbitrary, and hopefully is enough to allow for clock skew. * Currently only Gmail supports XOAUTH2, and seems to always use a token * life-time of 3600s, but that is not guaranteed. It is possible for Gmail to * issue an access token with a life-time so short that even after send * refreshes it, it's already expired when post tries to use it, but that seems * unlikely. */ #define EXPIRY_FUDGE 60 /* maximum size for HTTP response bodies * (not counting header and not null-terminated) */ #define RESPONSE_BODY_MAX 8192 /* Maximum size for URLs and URI-encoded query strings, null-terminated. * * Actual maximum we need is based on the size of tokens (limited by * RESPONSE_BODY_MAX), code user copies from a web page (arbitrarily large), and * various service parameters (all arbitrarily large). In practice, all these * are just tens of bytes. It's not hard to change this to realloc as needed, * but we should still have some limit, so why not this one? */ #define URL_MAX 8192 struct mh_oauth_cred { mh_oauth_ctx *ctx; /* opaque access token ([1] 1.4) in null-terminated string */ char *access_token; /* opaque refresh token ([1] 1.5) in null-terminated string */ char *refresh_token; /* time at which the access token expires, or 0 if unknown */ time_t expires_at; /* Ignoring token_type ([1] 7.1) because * https://developers.google.com/accounts/docs/OAuth2InstalledApp says * "Currently, this field always has the value Bearer". */ /* only filled while loading cred files, otherwise NULL */ char *user; }; struct mh_oauth_ctx { struct mh_oauth_service_info svc; CURL *curl; FILE *log; char buf[URL_MAX]; char *cred_fn; char *sasl_client_res; char *user_agent; mh_oauth_err_code err_code; /* If any detailed message about the error is available, this points to it. * May point to err_buf, or something else. */ const char *err_details; /* Pointer to buffer mh_oauth_err_get_string allocates. */ char *err_formatted; /* Ask libcurl to store errors here. */ char err_buf[CURL_ERROR_SIZE]; }; struct curl_ctx { /* inputs */ CURL *curl; /* NULL or a file handle to have curl log diagnostics to */ FILE *log; /* outputs */ /* Whether the response was too big; if so, the rest of the output fields * are undefined. */ boolean too_big; /* HTTP response code */ long res_code; /* NULL or null-terminated value of Content-Type response header field */ const char *content_type; /* number of bytes in the response body */ size_t res_len; /* response body; NOT null-terminated */ char res_body[RESPONSE_BODY_MAX]; }; static boolean get_json_strings(const char *, size_t, FILE *, ...); static boolean make_query_url(char *, size_t, CURL *, const char *, ...); static boolean post(struct curl_ctx *, const char *, const char *); int mh_oauth_do_xoauth(const char *user, const char *svc, unsigned char **oauth_res, size_t *oauth_res_len, FILE *log) { mh_oauth_ctx *ctx; mh_oauth_cred *cred; char *fn; int failed_to_lock = 0; FILE *fp; char *client_res; if (!mh_oauth_new (&ctx, svc)) adios(NULL, mh_oauth_get_err_string(ctx)); if (log != NULL) mh_oauth_log_to(stderr, ctx); fn = mh_xstrdup(mh_oauth_cred_fn(svc)); fp = lkfopendata(fn, "r+", &failed_to_lock); if (fp == NULL) { if (errno == ENOENT) { adios(NULL, "no credentials -- run mhlogin -saslmech xoauth2 -authservice %s", svc); } adios(fn, "failed to open"); } if (failed_to_lock) { adios(fn, "failed to lock"); } if ((cred = mh_oauth_cred_load(fp, ctx, user)) == NULL) { adios(NULL, mh_oauth_get_err_string(ctx)); } if (!mh_oauth_access_token_valid(time(NULL), cred)) { if (!mh_oauth_refresh(cred)) { if (mh_oauth_get_err_code(ctx) == MH_OAUTH_NO_REFRESH) { adios(NULL, "no valid credentials -- run mhlogin -saslmech xoauth2 -authservice %s", svc); } if (mh_oauth_get_err_code(ctx) == MH_OAUTH_BAD_GRANT) { adios(NULL, "credentials rejected -- run mhlogin -saslmech xoauth2 -authservice %s", svc); } inform("error refreshing OAuth2 token"); adios(NULL, mh_oauth_get_err_string(ctx)); } fseek(fp, 0, SEEK_SET); if (!mh_oauth_cred_save(fp, cred, user)) { adios(NULL, mh_oauth_get_err_string(ctx)); } } if (lkfclosedata(fp, fn) < 0) { adios(fn, "failed to close"); } free(fn); /* XXX writeBase64raw modifies the source buffer! make a copy */ client_res = mh_xstrdup(mh_oauth_sasl_client_response(oauth_res_len, user, cred)); mh_oauth_cred_free(cred); mh_oauth_free(ctx); *oauth_res = (unsigned char *) client_res; return OK; } static boolean is_json(const char *content_type) { return content_type != NULL && strncasecmp(content_type, JSON_TYPE, LEN(JSON_TYPE)) == 0; } static void set_err_details(mh_oauth_ctx *ctx, mh_oauth_err_code code, const char *details) { ctx->err_code = code; ctx->err_details = details; } static void set_err(mh_oauth_ctx *ctx, mh_oauth_err_code code) { set_err_details(ctx, code, NULL); } static void set_err_http(mh_oauth_ctx *ctx, const struct curl_ctx *curl_ctx) { char *error = NULL; mh_oauth_err_code code; /* 5.2. Error Response says error response should use status code 400 and * application/json body. If Content-Type matches, try to parse the body * regardless of the status code. */ if (curl_ctx->res_len > 0 && is_json(curl_ctx->content_type) && get_json_strings(curl_ctx->res_body, curl_ctx->res_len, ctx->log, "error", &error, (void *)NULL) && error != NULL) { if (strcmp(error, "invalid_grant") == 0) { code = MH_OAUTH_BAD_GRANT; } else { /* All other errors indicate a bug, not anything the user did. */ code = MH_OAUTH_REQUEST_BAD; } } else { code = MH_OAUTH_RESPONSE_BAD; } set_err(ctx, code); free(error); } static char * make_user_agent(void) { const char *curl = curl_version_info(CURLVERSION_NOW)->version; return concat(user_agent, " libcurl/", curl, NULL); } boolean mh_oauth_new(mh_oauth_ctx **result, const char *svc_name) { mh_oauth_ctx *ctx; NEW(ctx); *result = ctx; ctx->curl = NULL; ctx->log = NULL; ctx->cred_fn = ctx->sasl_client_res = ctx->err_formatted = NULL; if (!mh_oauth_get_service_info(svc_name, &ctx->svc, ctx->err_buf, sizeof(ctx->err_buf))) { set_err_details(ctx, MH_OAUTH_BAD_PROFILE, ctx->err_buf); return FALSE; } ctx->curl = curl_easy_init(); if (ctx->curl == NULL) { set_err(ctx, MH_OAUTH_CURL_INIT); return FALSE; } curl_easy_setopt(ctx->curl, CURLOPT_ERRORBUFFER, ctx->err_buf); ctx->user_agent = make_user_agent(); if (curl_easy_setopt(ctx->curl, CURLOPT_USERAGENT, ctx->user_agent) != CURLE_OK) { set_err_details(ctx, MH_OAUTH_CURL_INIT, ctx->err_buf); return FALSE; } return TRUE; } void mh_oauth_free(mh_oauth_ctx *ctx) { free(ctx->svc.name); free(ctx->svc.scope); free(ctx->svc.client_id); free(ctx->svc.client_secret); free(ctx->svc.auth_endpoint); free(ctx->svc.token_endpoint); free(ctx->svc.redirect_uri); free(ctx->cred_fn); free(ctx->sasl_client_res); free(ctx->err_formatted); free(ctx->user_agent); if (ctx->curl != NULL) { curl_easy_cleanup(ctx->curl); } free(ctx); } const char * mh_oauth_svc_display_name(const mh_oauth_ctx *ctx) { return ctx->svc.display_name; } void mh_oauth_log_to(FILE *log, mh_oauth_ctx *ctx) { ctx->log = log; } mh_oauth_err_code mh_oauth_get_err_code(const mh_oauth_ctx *ctx) { return ctx->err_code; } const char * mh_oauth_get_err_string(mh_oauth_ctx *ctx) { const char *base; free(ctx->err_formatted); switch (ctx->err_code) { case MH_OAUTH_BAD_PROFILE: base = "incomplete OAuth2 service definition"; break; case MH_OAUTH_CURL_INIT: base = "error initializing libcurl"; break; case MH_OAUTH_REQUEST_INIT: base = "local error initializing HTTP request"; break; case MH_OAUTH_POST: base = "error making HTTP request to OAuth2 authorization endpoint"; break; case MH_OAUTH_RESPONSE_TOO_BIG: base = "refusing to process response body larger than 8192 bytes"; break; case MH_OAUTH_RESPONSE_BAD: base = "invalid response"; break; case MH_OAUTH_BAD_GRANT: base = "bad grant (authorization code or refresh token)"; break; case MH_OAUTH_REQUEST_BAD: base = "bad OAuth request; re-run with -snoop and send REDACTED output" " to nmh-workers"; break; case MH_OAUTH_NO_REFRESH: base = "no refresh token"; break; case MH_OAUTH_CRED_USER_NOT_FOUND: base = "user not found in cred file"; break; case MH_OAUTH_CRED_FILE: base = "error loading cred file"; break; default: base = "unknown error"; } if (ctx->err_details == NULL) { return ctx->err_formatted = mh_xstrdup(base); } ctx->err_formatted = concat(base, ": ", ctx->err_details, NULL); return ctx->err_formatted; } const char * mh_oauth_get_authorize_url(mh_oauth_ctx *ctx) { /* [1] 4.1.1 Authorization Request */ if (!make_query_url(ctx->buf, sizeof ctx->buf, ctx->curl, ctx->svc.auth_endpoint, "response_type", "code", "client_id", ctx->svc.client_id, "redirect_uri", ctx->svc.redirect_uri, "scope", ctx->svc.scope, (void *)NULL)) { set_err(ctx, MH_OAUTH_REQUEST_INIT); return NULL; } return ctx->buf; } static boolean cred_from_response(mh_oauth_cred *cred, const char *content_type, const char *input, size_t input_len) { boolean result = FALSE; char *access_token, *expires_in, *refresh_token; const mh_oauth_ctx *ctx = cred->ctx; if (!is_json(content_type)) { return FALSE; } access_token = expires_in = refresh_token = NULL; if (!get_json_strings(input, input_len, ctx->log, "access_token", &access_token, "expires_in", &expires_in, "refresh_token", &refresh_token, (void *)NULL)) { goto out; } if (access_token == NULL) { /* Response is invalid, but if it has a refresh token, we can try. */ if (refresh_token == NULL) { goto out; } } result = TRUE; free(cred->access_token); cred->access_token = access_token; access_token = NULL; cred->expires_at = 0; if (expires_in != NULL) { long e; errno = 0; e = strtol(expires_in, NULL, 10); if (errno == 0) { if (e > 0) { cred->expires_at = time(NULL) + e; } } else if (ctx->log != NULL) { fprintf(ctx->log, "* invalid expiration: %s\n", expires_in); } } /* [1] 6 Refreshing an Access Token says a new refresh token may be issued * in refresh responses. */ if (refresh_token != NULL) { free(cred->refresh_token); cred->refresh_token = refresh_token; refresh_token = NULL; } out: free(refresh_token); free(expires_in); free(access_token); return result; } static boolean do_access_request(mh_oauth_cred *cred, const char *req_body) { mh_oauth_ctx *ctx = cred->ctx; struct curl_ctx curl_ctx; curl_ctx.curl = ctx->curl; curl_ctx.log = ctx->log; if (!post(&curl_ctx, ctx->svc.token_endpoint, req_body)) { if (curl_ctx.too_big) { set_err(ctx, MH_OAUTH_RESPONSE_TOO_BIG); } else { set_err_details(ctx, MH_OAUTH_POST, ctx->err_buf); } return FALSE; } if (curl_ctx.res_code != 200) { set_err_http(ctx, &curl_ctx); return FALSE; } if (!cred_from_response(cred, curl_ctx.content_type, curl_ctx.res_body, curl_ctx.res_len)) { set_err(ctx, MH_OAUTH_RESPONSE_BAD); return FALSE; } return TRUE; } mh_oauth_cred * mh_oauth_authorize(const char *code, mh_oauth_ctx *ctx) { mh_oauth_cred *result; if (!make_query_url(ctx->buf, sizeof ctx->buf, ctx->curl, NULL, "code", code, "grant_type", "authorization_code", "redirect_uri", ctx->svc.redirect_uri, "client_id", ctx->svc.client_id, "client_secret", ctx->svc.client_secret, (void *)NULL)) { set_err(ctx, MH_OAUTH_REQUEST_INIT); return NULL; } NEW(result); result->ctx = ctx; result->access_token = result->refresh_token = NULL; if (!do_access_request(result, ctx->buf)) { free(result); return NULL; } return result; } boolean mh_oauth_refresh(mh_oauth_cred *cred) { boolean result; mh_oauth_ctx *ctx = cred->ctx; if (cred->refresh_token == NULL) { set_err(ctx, MH_OAUTH_NO_REFRESH); return FALSE; } if (!make_query_url(ctx->buf, sizeof ctx->buf, ctx->curl, NULL, "grant_type", "refresh_token", "refresh_token", cred->refresh_token, "client_id", ctx->svc.client_id, "client_secret", ctx->svc.client_secret, (void *)NULL)) { set_err(ctx, MH_OAUTH_REQUEST_INIT); return FALSE; } result = do_access_request(cred, ctx->buf); if (result && cred->access_token == NULL) { set_err_details(ctx, MH_OAUTH_RESPONSE_BAD, "no access token"); return FALSE; } return result; } boolean mh_oauth_access_token_valid(time_t t, const mh_oauth_cred *cred) { return cred->access_token != NULL && t + EXPIRY_FUDGE < cred->expires_at; } void mh_oauth_cred_free(mh_oauth_cred *cred) { free(cred->refresh_token); free(cred->access_token); free(cred); } /* for loading multi-user cred files */ struct user_creds { mh_oauth_cred *creds; /* number of allocated mh_oauth_cred structs above points to */ size_t alloc; /* number that are actually filled in and used */ size_t len; }; /* If user has an entry in user_creds, return pointer to it. Else allocate a * new struct in user_creds and return pointer to that. */ static mh_oauth_cred * find_or_alloc_user_creds(struct user_creds user_creds[], const char *user) { mh_oauth_cred *creds = user_creds->creds; size_t i; for (i = 0; i < user_creds->len; i++) { if (strcmp(creds[i].user, user) == 0) { return &creds[i]; } } if (user_creds->alloc == user_creds->len) { user_creds->alloc *= 2; user_creds->creds = mh_xrealloc(user_creds->creds, user_creds->alloc); } creds = user_creds->creds+user_creds->len; user_creds->len++; creds->user = getcpy(user); creds->access_token = creds->refresh_token = NULL; creds->expires_at = 0; return creds; } static void free_user_creds(struct user_creds *user_creds) { mh_oauth_cred *cred; size_t i; cred = user_creds->creds; for (i = 0; i < user_creds->len; i++) { free(cred[i].user); free(cred[i].access_token); free(cred[i].refresh_token); } free(user_creds->creds); free(user_creds); } static boolean load_creds(struct user_creds **result, FILE *fp, mh_oauth_ctx *ctx) { boolean success = FALSE; char name[NAMESZ], value_buf[BUFSIZ]; int state; m_getfld_state_t getfld_ctx = 0; struct user_creds *user_creds; NEW(user_creds); user_creds->alloc = 4; user_creds->len = 0; user_creds->creds = mh_xmalloc(user_creds->alloc * sizeof *user_creds->creds); for (;;) { int size = sizeof value_buf; switch (state = m_getfld(&getfld_ctx, name, value_buf, &size, fp)) { case FLD: case FLDPLUS: { char **save, *expire; time_t *expires_at = NULL; if (has_prefix(name, "access-")) { const char *user = name + 7; mh_oauth_cred *creds = find_or_alloc_user_creds(user_creds, user); save = &creds->access_token; } else if (has_prefix(name, "refresh-")) { const char *user = name + 8; mh_oauth_cred *creds = find_or_alloc_user_creds(user_creds, user); save = &creds->refresh_token; } else if (has_prefix(name, "expire-")) { const char *user = name + 7; mh_oauth_cred *creds = find_or_alloc_user_creds(user_creds, user); expires_at = &creds->expires_at; save = &expire; } else { set_err_details(ctx, MH_OAUTH_CRED_FILE, "unexpected field"); break; } if (state == FLD) { *save = trimcpy(value_buf); } else { char *tmp = getcpy(value_buf); while (state == FLDPLUS) { size = sizeof value_buf; state = m_getfld(&getfld_ctx, name, value_buf, &size, fp); tmp = add(value_buf, tmp); } *save = trimcpy(tmp); free(tmp); } if (expires_at != NULL) { errno = 0; *expires_at = strtol(expire, NULL, 10); free(expire); if (errno != 0) { set_err_details(ctx, MH_OAUTH_CRED_FILE, "invalid expiration time"); break; } expires_at = NULL; } continue; } case BODY: case FILEEOF: success = TRUE; break; default: /* Not adding details for LENERR/FMTERR because m_getfld already * wrote advise message to stderr. */ set_err(ctx, MH_OAUTH_CRED_FILE); break; } break; } m_getfld_state_destroy(&getfld_ctx); if (success) { *result = user_creds; } else { free_user_creds(user_creds); } return success; } static boolean save_user(FILE *fp, const char *user, const char *access, const char *refresh, long expires_at) { if (access != NULL) { if (fprintf(fp, "access-%s: %s\n", user, access) < 0) return FALSE; } if (refresh != NULL) { if (fprintf(fp, "refresh-%s: %s\n", user, refresh) < 0) return FALSE; } if (expires_at > 0) { if (fprintf(fp, "expire-%s: %ld\n", user, (long)expires_at) < 0) { return FALSE; } } return TRUE; } boolean mh_oauth_cred_save(FILE *fp, mh_oauth_cred *cred, const char *user) { struct user_creds *user_creds; int fd = fileno(fp); size_t i; /* Load existing creds if any. */ if (!load_creds(&user_creds, fp, cred->ctx)) { return FALSE; } if (fchmod(fd, S_IRUSR | S_IWUSR) < 0) goto err; if (ftruncate(fd, 0) < 0) goto err; if (fseek(fp, 0, SEEK_SET) < 0) goto err; /* Write all creds except for this user. */ for (i = 0; i < user_creds->len; i++) { mh_oauth_cred *c = &user_creds->creds[i]; if (strcmp(c->user, user) == 0) continue; if (!save_user(fp, c->user, c->access_token, c->refresh_token, c->expires_at)) { goto err; } } /* Write updated creds for this user. */ if (!save_user(fp, user, cred->access_token, cred->refresh_token, cred->expires_at)) { goto err; } free_user_creds(user_creds); return TRUE; err: free_user_creds(user_creds); set_err(cred->ctx, MH_OAUTH_CRED_FILE); return FALSE; } mh_oauth_cred * mh_oauth_cred_load(FILE *fp, mh_oauth_ctx *ctx, const char *user) { mh_oauth_cred *creds, *result = NULL; struct user_creds *user_creds; size_t i; if (!load_creds(&user_creds, fp, ctx)) { return NULL; } /* Search user_creds for this user. If we don't find it, return NULL. * If we do, free fields of all structs except this one, moving this one to * the first struct if necessary. When we return it, it just looks like one * struct to the caller, and the whole array is freed later. */ creds = user_creds->creds; for (i = 0; i < user_creds->len; i++) { if (strcmp(creds[i].user, user) == 0) { result = creds; if (i > 0) { result->access_token = creds[i].access_token; result->refresh_token = creds[i].refresh_token; result->expires_at = creds[i].expires_at; } } else { free(creds[i].access_token); free(creds[i].refresh_token); } free(creds[i].user); } /* No longer need user_creds. result just uses its creds member. */ free(user_creds); if (result == NULL) { set_err_details(ctx, MH_OAUTH_CRED_USER_NOT_FOUND, user); return NULL; } result->ctx = ctx; result->user = NULL; return result; } const char * mh_oauth_sasl_client_response(size_t *res_len, const char *user, const mh_oauth_cred *cred) { char **p; p = &cred->ctx->sasl_client_res; free(*p); *p = concat("user=", user, "\1auth=Bearer ", cred->access_token, "\1\1", NULL); *res_len = strlen(*p); return *p; } /******************************************************************************* * building URLs and making HTTP requests with libcurl */ /* * Build null-terminated URL in the array pointed to by s. If the URL doesn't * fit within size (including the terminating null byte), return FALSE without * * building the entire URL. Some of URL may already have been written into the * result array in that case. */ static boolean make_query_url(char *s, size_t size, CURL *curl, const char *base_url, ...) { boolean result = FALSE; size_t len; char *prefix; va_list ap; const char *name; if (base_url == NULL) { len = 0; prefix = ""; } else { len = strlen(base_url); if (len > size - 1) /* Less one for NUL. */ return FALSE; strcpy(s, base_url); prefix = "?"; } va_start(ap, base_url); for (name = va_arg(ap, char *); name != NULL; name = va_arg(ap, char *)) { char *name_esc = curl_easy_escape(curl, name, 0); char *val_esc = curl_easy_escape(curl, va_arg(ap, char *), 0); /* prefix + name_esc + '=' + val_esc + '\0' must fit within size */ size_t new_len = len + strlen(prefix) + strlen(name_esc) + 1 /* '=' */ + strlen(val_esc); if (new_len + 1 > size) { free(name_esc); free(val_esc); goto out; } sprintf(s + len, "%s%s=%s", prefix, name_esc, val_esc); free(name_esc); free(val_esc); len = new_len; prefix = "&"; } result = TRUE; out: va_end(ap); return result; } static int debug_callback(CURL *handle, curl_infotype type, char *data, size_t size, void *userptr) { FILE *fp = userptr; NMH_UNUSED(handle); switch (type) { case CURLINFO_HEADER_IN: case CURLINFO_DATA_IN: fputs("< ", fp); break; case CURLINFO_HEADER_OUT: case CURLINFO_DATA_OUT: fputs("> ", fp); break; default: return 0; } fwrite(data, 1, size, fp); if (data[size - 1] != '\n') { putc('\n', fp); } fflush(fp); return 0; } static size_t write_callback(const char *ptr, size_t size, size_t nmemb, void *userdata) { struct curl_ctx *ctx = userdata; size_t new_len; if (ctx->too_big) { return 0; } size *= nmemb; new_len = ctx->res_len + size; if (new_len > sizeof ctx->res_body) { ctx->too_big = TRUE; return 0; } memcpy(ctx->res_body + ctx->res_len, ptr, size); ctx->res_len = new_len; return size; } static boolean post(struct curl_ctx *ctx, const char *url, const char *req_body) { CURL *curl = ctx->curl; CURLcode status; ctx->too_big = FALSE; ctx->res_len = 0; if (ctx->log != NULL) { curl_easy_setopt(curl, CURLOPT_VERBOSE, (long)1); curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, debug_callback); curl_easy_setopt(curl, CURLOPT_DEBUGDATA, ctx->log); } if ((status = curl_easy_setopt(curl, CURLOPT_URL, url)) != CURLE_OK) { return FALSE; } curl_easy_setopt(curl, CURLOPT_POSTFIELDS, req_body); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, ctx); if (has_prefix(url, "http://127.0.0.1:")) { /* Hack: on Cygwin, curl doesn't fail to connect with ECONNREFUSED. Instead, it waits to timeout. So set a really short timeout, but just on localhost (for convenience of the user, and the test suite). */ curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 2L); } status = curl_easy_perform(curl); /* first check for error from callback */ if (ctx->too_big) { return FALSE; } /* now from curl */ if (status != CURLE_OK) { return FALSE; } if ((status = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &ctx->res_code)) != CURLE_OK || (status = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ctx->content_type)) != CURLE_OK) { return FALSE; } return TRUE; } /******************************************************************************* * JSON processing */ /* We need 2 for each key/value pair plus 1 for the enclosing object, which * means we only need 9 for Gmail. Clients must not fail if the server returns * more, though, e.g. for protocol extensions. */ #define JSMN_TOKENS 16 /* * Parse JSON, store pointer to array of jsmntok_t in tokens. * * Returns whether parsing is successful. * * Even in that case, tokens has been allocated and must be freed. */ static boolean parse_json(jsmntok_t **tokens, size_t *tokens_len, const char *input, size_t input_len, FILE *log) { jsmn_parser p; jsmnerr_t r; *tokens_len = JSMN_TOKENS; *tokens = mh_xmalloc(*tokens_len * sizeof **tokens); jsmn_init(&p); while ((r = jsmn_parse(&p, input, input_len, *tokens, *tokens_len)) == JSMN_ERROR_NOMEM) { *tokens_len = 2 * *tokens_len; if (log != NULL) { fprintf(log, "* need more jsmntok_t! allocating %ld\n", (long)*tokens_len); } /* Don't need to limit how much we allocate; we already limited the size of the response body. */ *tokens = mh_xrealloc(*tokens, *tokens_len * sizeof **tokens); } if (r <= 0) { return FALSE; } return TRUE; } /* * Search input and tokens for the value identified by null-terminated name. * * If found, allocate a null-terminated copy of the value and store the address * in val. val is left untouched if not found. */ static void get_json_string(char **val, const char *input, const jsmntok_t *tokens, const char *name) { /* number of top-level tokens (not counting object/list children) */ int token_count = tokens[0].size * 2; /* number of tokens to skip when we encounter objects and lists */ /* We only look for top-level strings. */ int skip_tokens = 0; /* whether the current token represents a field name */ /* The next token will be the value. */ boolean is_key = TRUE; int i; for (i = 1; i <= token_count; i++) { const char *key; int key_len; if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { /* We're not interested in any array or object children; skip. */ int children = tokens[i].size; if (tokens[i].type == JSMN_OBJECT) { /* Object size counts key/value pairs, skip both. */ children *= 2; } /* Add children to token_count. */ token_count += children; if (skip_tokens == 0) { /* This token not already skipped; skip it. */ /* Would already be skipped if child of object or list. */ skip_tokens++; } /* Skip this token's children. */ skip_tokens += children; } if (skip_tokens > 0) { skip_tokens--; /* When we finish with the object or list, we'll have a key. */ is_key = TRUE; continue; } if (is_key) { is_key = FALSE; continue; } key = input + tokens[i - 1].start; key_len = tokens[i - 1].end - tokens[i - 1].start; if (strncmp(key, name, key_len) == 0) { int val_len = tokens[i].end - tokens[i].start; *val = mh_xmalloc(val_len + 1); memcpy(*val, input + tokens[i].start, val_len); (*val)[val_len] = '\0'; return; } is_key = TRUE; } } /* * Parse input as JSON, extracting specified string values. * * Variadic arguments are pairs of null-terminated strings indicating the value * to extract from the JSON and addresses into which pointers to null-terminated * copies of the values are written. These must be followed by one NULL pointer * to indicate the end of pairs. * * The extracted strings are copies which caller must free. If any name is not * found, the address to store the value is not touched. * * Returns non-zero if parsing is successful. * * When parsing failed, no strings have been copied. * * log may be used for debug-logging if not NULL. */ static boolean get_json_strings(const char *input, size_t input_len, FILE *log, ...) { boolean result = FALSE; jsmntok_t *tokens; size_t tokens_len; va_list ap; const char *name; if (!parse_json(&tokens, &tokens_len, input, input_len, log)) { goto out; } if (tokens->type != JSMN_OBJECT || tokens->size == 0) { goto out; } result = TRUE; va_start(ap, log); for (name = va_arg(ap, char *); name != NULL; name = va_arg(ap, char *)) { get_json_string(va_arg(ap, char **), input, tokens, name); } out: va_end(ap); free(tokens); return result; } #endif nmh-1.7.1-RC3/sbr/oauth_prof.c000644 007761 000024 00000010267 13243042053 016064 0ustar00kenhstaff000000 000000 /* oauth_prof.c -- OAuth 2.0 implementation for XOAUTH2 in SMTP and POP3. * * This code is Copyright (c) 2014, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #ifdef OAUTH_SUPPORT #include #include #include #include #include #include #include #include #include #include "m_maildir.h" static const struct mh_oauth_service_info SERVICES[] = { /* https://developers.google.com/accounts/docs/OAuth2InstalledApp */ { /* name */ "gmail", /* display_name */ "Gmail", /* client_id */ "91584523849-8lv9kgp1rvp8ahta6fa4b125tn2polcg.apps.googleusercontent.com", /* client_secret */ "Ua8sX34xyv7hVrKM-U70dKI6", /* auth_endpoint */ "https://accounts.google.com/o/oauth2/auth", /* redirect_uri */ "urn:ietf:wg:oauth:2.0:oob", /* token_endpoint */ "https://accounts.google.com/o/oauth2/token", /* scope */ "https://mail.google.com/" } }; /* Copy service info so we don't have to free it only sometimes. */ static void copy_svc(mh_oauth_service_info *to, const mh_oauth_service_info *from) { to->display_name = from->display_name; #define copy(_field_) to->_field_ = getcpy(from->_field_) copy(name); copy(scope); copy(client_id); copy(client_secret); copy(auth_endpoint); copy(token_endpoint); copy(redirect_uri); #undef copy } /* Return profile component node name for a service parameter. */ char * mh_oauth_node_name_for_svc(const char *base_name, const char *svc) { /* TODO: s/_/-/g ? */ return concat("oauth-", svc, "-", base_name, NULL); } /* Update one service_info field if overridden in profile. */ static void update_svc_field(char **field, const char *base_name, const char *svc) { char *name = mh_oauth_node_name_for_svc(base_name, svc); const char *value = context_find(name); if (value != NULL) { free(*field); *field = mh_xstrdup(value); } free(name); } /* Update all service_info fields that are overridden in profile. */ static boolean update_svc(mh_oauth_service_info *svc, const char *svc_name, char *errbuf, size_t errbuflen) { #define update(name) \ update_svc_field(&svc->name, #name, svc_name); \ if (svc->name == NULL) { \ snprintf(errbuf, errbuflen, "%s", #name " is missing"); \ errbuf[errbuflen - 1] = '\0'; \ return FALSE; \ } update(scope); update(client_id); update(client_secret); update(auth_endpoint); update(token_endpoint); update(redirect_uri); #undef update if (svc->name == NULL) { svc->name = getcpy(svc_name); } if (svc->display_name == NULL) { svc->display_name = svc->name; } return TRUE; } boolean mh_oauth_get_service_info(const char *svc_name, mh_oauth_service_info *svcinfo, char *errbuf, size_t errbuflen) { int i; svcinfo->name = svcinfo->display_name = NULL; svcinfo->scope = svcinfo->client_id = NULL; svcinfo->client_secret = svcinfo->auth_endpoint = NULL; svcinfo->token_endpoint = svcinfo->redirect_uri = NULL; for (i = 0; i < (int)DIM(SERVICES); i++) { if (strcmp(SERVICES[i].name, svc_name) == 0) { copy_svc(svcinfo, &SERVICES[i]); break; } } if (!update_svc(svcinfo, svc_name, errbuf, errbuflen)) { return FALSE; } return TRUE; } const char * mh_oauth_cred_fn(const char *svc) { char *result, *result_if_allocated; char *component = mh_oauth_node_name_for_svc("credential-file", svc); result = context_find(component); free(component); if (result == NULL) { result = concat("oauth-", svc, NULL); result_if_allocated = result; } else { result_if_allocated = NULL; } if (result[0] != '/') { const char *tmp = m_maildir(result); free(result_if_allocated); result = getcpy(tmp); } return result; } #endif nmh-1.7.1-RC3/sbr/path.c000644 007761 000024 00000007105 13243042053 014647 0ustar00kenhstaff000000 000000 /* path.c -- return a pathname * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include "m_maildir.h" #define CWD "./" #define DOT "." #define DOTDOT ".." #define PWD "../" static char *pwds; /* * static prototypes */ static char *expath(char *,int); static void compath(char *); char * pluspath(char *name) { return path(name + 1, *name == '+' ? TFOLDER : TSUBCWF); } char * path(char *name, int flag) { char *cp, *ep; if ((cp = expath (name, flag)) && (ep = cp + strlen (cp) - 1) > cp && *ep == '/') *ep = '\0'; return cp; } static char * expath (char *name, int flag) { char *cp, *ep; char buffer[BUFSIZ]; if (flag == TSUBCWF) { snprintf (buffer, sizeof(buffer), "%s/%s", getfolder (1), name); name = m_mailpath (buffer); compath (name); snprintf (buffer, sizeof(buffer), "%s/", m_maildir ("")); if (ssequal (buffer, name)) { cp = name; name = mh_xstrdup(name + strlen(buffer)); free (cp); } flag = TFOLDER; } if (*name == '/' || (flag == TFOLDER && (!has_prefix(name, CWD) && strcmp (name, DOT) && strcmp (name, DOTDOT) && !has_prefix(name, PWD)))) return mh_xstrdup(name); if (pwds == NULL) pwds = pwd (); if (strcmp (name, DOT) == 0 || strcmp (name, CWD) == 0) return mh_xstrdup(pwds); ep = pwds + strlen (pwds); if ((cp = strrchr(pwds, '/')) == NULL) cp = ep; else if (cp == pwds) cp++; if (has_prefix(name, CWD)) name += LEN(CWD); if (strcmp (name, DOTDOT) == 0 || strcmp (name, PWD) == 0) { snprintf (buffer, sizeof(buffer), "%.*s", (int)(cp - pwds), pwds); return mh_xstrdup(buffer); } if (has_prefix(name, PWD)) name += LEN(PWD); else cp = ep; snprintf (buffer, sizeof(buffer), "%.*s/%s", (int)(cp - pwds), pwds, name); return mh_xstrdup(buffer); } static void compath (char *f) { char *cp, *dp; if (*f != '/') return; for (cp = f; *cp;) { if (*cp != '/') { cp++; continue; } switch (*++cp) { case 0: if (--cp > f) *cp = '\0'; return; case '/': for (dp = cp; *dp == '/'; dp++) continue; strcpy (cp--, dp); continue; case '.': if (strcmp (cp, DOT) == 0) { if (cp > f + 1) cp--; *cp = '\0'; return; } if (strcmp (cp, DOTDOT) == 0) { for (cp -= 2; cp > f; cp--) if (*cp == '/') break; if (cp <= f) cp = f + 1; *cp = '\0'; return; } if (has_prefix(cp, PWD)) { for (dp = cp - 2; dp > f; dp--) if (*dp == '/') break; if (dp <= f) dp = f; strcpy (dp, cp + LEN(PWD) - 1); cp = dp; continue; } if (has_prefix(cp, CWD)) { strcpy (cp - 1, cp + LEN(CWD) - 1); cp--; continue; } continue; default: cp++; continue; } } } nmh-1.7.1-RC3/sbr/pidstatus.c000644 007761 000024 00000002776 13243042053 015744 0ustar00kenhstaff000000 000000 /* pidstatus.c -- report child's status * * 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 #ifndef WTERMSIG # define WTERMSIG(s) ((int)((s) & 0x7F)) #endif #ifndef WCOREDUMP # define WCOREDUMP(s) ((s) & 0x80) #endif /* * Return 0 if the command exited with an exit code of zero, a nonzero code * otherwise. * * Print out an appropriate status message we didn't exit with an exit code * of zero. */ int pidstatus (int status, FILE *fp, char *cp) { int signum; char *signame; /* * I have no idea what this is for (rc) * so I'm commenting it out for right now. * * if ((status & 0xff00) == 0xff00) * return status; */ /* If child process returned normally */ if (WIFEXITED(status)) { if ((signum = WEXITSTATUS(status))) { if (cp) fprintf (fp, "%s: ", cp); fprintf (fp, "exit %d\n", signum); } return signum; } if (WIFSIGNALED(status)) { /* If child process terminated due to receipt of a signal */ signum = WTERMSIG(status); if (signum != SIGINT) { if (cp) fprintf (fp, "%s: ", cp); fprintf (fp, "signal %d", signum); errno = 0; signame = strsignal(signum); if (errno) signame = NULL; if (signame) fprintf (fp, " (%s%s)\n", signame, WCOREDUMP(status) ? ", core dumped" : ""); else fprintf (fp, "%s\n", WCOREDUMP(status) ? " (core dumped)" : ""); } } return status; } nmh-1.7.1-RC3/sbr/pidwait.c000644 007761 000024 00000001344 13243042053 015353 0ustar00kenhstaff000000 000000 /* pidwait.c -- wait for child to exit * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include int pidwait (pid_t id, int sigsok) { pid_t pid; SIGNAL_HANDLER istat = NULL, qstat = NULL; int status; if (sigsok == -1) { /* ignore a couple of signals */ istat = SIGNAL (SIGINT, SIG_IGN); qstat = SIGNAL (SIGQUIT, SIG_IGN); } while ((pid = waitpid(id, &status, 0)) == -1 && errno == EINTR) ; if (sigsok == -1) { /* reset the signal handlers */ SIGNAL (SIGINT, istat); SIGNAL (SIGQUIT, qstat); } return (pid == -1 ? -1 : status); } nmh-1.7.1-RC3/sbr/print_help.c000644 007761 000024 00000004334 13243042053 016060 0ustar00kenhstaff000000 000000 /* print_help.c -- print a help message, and possibly the * -- profile/context entries for this command * * 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 void print_help (char *str, struct swit *swp, int print_context) { char *s; /* print Usage string */ printf ("Usage: %s\n", str); /* print all the switches */ puts(" switches are:"); print_sw (ALL, swp, "-", stdout); /* * check if we should print any profile entries */ if (print_context && (s = context_find (invo_name))) { printf ("\nProfile: %s\n", s); } /* and for further info */ putchar('\n'); print_intro (stdout, TRUE); puts ("\nSee the BUGS section of the nmh(7) man page for more information."); } /* * The text below also appears in man/nmh.man. */ static const char nmh_intro1[] = \ "Send bug reports, questions, suggestions, and patches to\n" "nmh-workers@nongnu.org. That mailing list is relatively quiet, so user\n" "questions are encouraged. Users are also encouraged to subscribe, and\n" "view the archives, at https://lists.gnu.org/mailman/listinfo/nmh-workers\n"; /* The text below is split so that string constant length doesn't exceed the C90 minimum maximum length of 509 characters. */ static const char nmh_intro2[] = \ "\n" \ "If problems are encountered with an nmh program, they should be\n" "reported to the local maintainers of nmh, if any, or to the mailing\n" "list noted above. When doing this, the name of the program should be\n" "reported, along with the version information for the program.\n"; static const char nmh_intro3[] = \ "\n" "To find out what version of an nmh program is being run, invoke the\n" "program with the -version switch. This prints the version of nmh, the\n" "host it was compiled on, and the date the program was linked.\n" "\n" "New releases and other information of potential interest are announced\n" "at http://www.nongnu.org/nmh/ .\n"; void print_intro (FILE *file, int brief) { fputs (nmh_intro1, file); if (! brief) { fputs (nmh_intro2, file); fputs (nmh_intro3, file); } } nmh-1.7.1-RC3/sbr/print_sw.c000644 007761 000024 00000002457 13243042053 015565 0ustar00kenhstaff000000 000000 /* print_sw.c -- print switches * * 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 void print_sw (const char *substr, const struct swit *swp, char *prefix, FILE *fp) { int len, optno; int i; char *cp, *cp1, *sp; char buf[128]; len = strlen(substr); for (; swp->sw; swp++) { /* null matches all strings */ if (!*substr || (ssequal (substr, swp->sw) && len >= swp->minchars)) { optno = 0; /* next switch */ if ((sp = (&swp[1])->sw)) { if (!*substr && sp[0] == 'n' && sp[1] == 'o' && strcmp (&sp[2], swp->sw) == 0 && ( ((&swp[1])->minchars == 0 && swp->minchars == 0) || ((&swp[1])->minchars == (swp->minchars) + 2))) optno++; } if (swp->minchars > 0) { cp = buf; *cp++ = '('; if (optno) { strcpy (cp, "[no]"); cp += strlen (cp); } for (cp1 = swp->sw, i = 0; i < swp->minchars; i++) *cp++ = *cp1++; *cp++ = ')'; while ((*cp++ = *cp1++)); fprintf (fp, " %s%s\n", prefix, buf); } else { if (!swp->minchars) fprintf(fp, optno ? " %s[no]%s\n" : " %s%s\n", prefix, swp->sw); } if (optno) swp++; /* skip -noswitch */ } } } nmh-1.7.1-RC3/sbr/print_version.c000644 007761 000024 00000000517 13243042053 016614 0ustar00kenhstaff000000 000000 /* print_version.c -- print a version string * * 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 void print_version (char *invo_name) { printf("%s -- %s\n", invo_name, version_str); } nmh-1.7.1-RC3/sbr/push.c000644 007761 000024 00000002145 13243042053 014671 0ustar00kenhstaff000000 000000 /* push.c -- push a fork into the background * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include "m_mktemp.h" void push(void) { pid_t pid; int i; for (i = 0; (pid = fork()) == -1 && i < 5; i++) sleep (5); switch (pid) { case -1: /* fork error */ inform("unable to fork, so can't push..."); break; case 0: /* child, block a few signals and continue */ SIGNAL (SIGHUP, SIG_IGN); SIGNAL (SIGINT, SIG_IGN); SIGNAL (SIGQUIT, SIG_IGN); SIGNAL (SIGTERM, SIG_IGN); #ifdef SIGTSTP SIGNAL (SIGTSTP, SIG_IGN); SIGNAL (SIGTTIN, SIG_IGN); SIGNAL (SIGTTOU, SIG_IGN); #endif unregister_for_removal(0); if (freopen ("/dev/null", "r", stdin) == NULL) { advise ("stdin", "freopen"); } if (freopen ("/dev/null", "w", stdout) == NULL) { advise ("stdout", "freopen"); } break; default: /* parent, just exit */ done (0); } } nmh-1.7.1-RC3/sbr/r1bindex.c000644 007761 000024 00000001245 13243042053 015426 0ustar00kenhstaff000000 000000 /* r1bindex.c -- Given a string and a character, return a pointer * -- to the right of the rightmost occurrence of the * -- character. If the character doesn't occur, the * -- pointer will be at the beginning of the string. * * 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 char * r1bindex(char *str, int chr) { char *r; if (!chr) return str; /* Match old behaviour, don't know if it's used. */ r = strrchr(str, chr); if (r) return r + 1; return str; } nmh-1.7.1-RC3/sbr/read_line.c000644 007761 000024 00000000432 13243042053 015631 0ustar00kenhstaff000000 000000 #include #include const char * read_line(void) { static char line[BUFSIZ]; fflush(stdout); if (fgets(line, sizeof(line), stdin) == NULL) return NULL; trim_suffix_c(line, '\n'); return line; /* May not be a complete line. */ } nmh-1.7.1-RC3/sbr/read_switch.c000644 007761 000024 00000001652 13243042053 016210 0ustar00kenhstaff000000 000000 /* read_switch.c -- prompt the user for an answer from the list * * 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 int read_switch (const char *prompt, const struct swit *ansp) { int i; char *cp; const struct swit *ap; char ansbuf[BUFSIZ]; for (;;) { fputs(prompt, stdout); fflush (stdout); cp = ansbuf; while ((i = getchar ()) != '\n') { if (i == EOF) return 0; if (cp < &ansbuf[sizeof ansbuf - 1]) { i = tolower(i); *cp++ = i; } } *cp = '\0'; if (ansbuf[0] == '?' || cp == ansbuf) { puts("Options are:"); for (ap = ansp; ap->sw; ap++) printf (" %s\n", ap->sw); continue; } if ((i = smatch (ansbuf, ansp)) < 0) { printf ("%s: %s.\n", ansbuf, i == -1 ? "unknown" : "ambiguous"); continue; } return i; } } nmh-1.7.1-RC3/sbr/read_switch_multiword.c000644 007761 000024 00000004036 13243042053 020315 0ustar00kenhstaff000000 000000 /* read_switch_multiword.c -- get an answer from the user and return a string array * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include static char ansbuf[BUFSIZ]; static sigjmp_buf sigenv; /* * static prototypes */ static void intrser (int); char ** read_switch_multiword (const char *prompt, const struct swit *ansp) { int i; SIGNAL_HANDLER istat = NULL; char *cp, **cpp; if (!(sigsetjmp(sigenv, 1))) { istat = SIGNAL (SIGINT, intrser); } else { SIGNAL (SIGINT, istat); return NULL; } for (;;) { fputs(prompt, stdout); fflush (stdout); cp = ansbuf; while ((i = getchar ()) != '\n') { if (i == EOF) { /* * If we get an EOF, return */ if (feof(stdin)) siglongjmp (sigenv, 1); /* * For errors, if we get an EINTR that means that we got * a signal and we should retry. If we get another error, * then just return. */ else if (ferror(stdin)) { if (errno == EINTR) { clearerr(stdin); continue; } fprintf(stderr, "\nError %s during read\n", strerror(errno)); siglongjmp (sigenv, 1); } else { /* * Just for completeness's sake ... */ fprintf(stderr, "\nUnknown problem in getchar()\n"); siglongjmp (sigenv, 1); } } if (cp < &ansbuf[sizeof ansbuf - 1]) *cp++ = i; } *cp = '\0'; if (ansbuf[0] == '?' || cp == ansbuf) { puts("Options are:"); print_sw (ALL, ansp, "", stdout); continue; } cpp = brkstring (ansbuf, " ", NULL); switch (smatch (*cpp, ansp)) { case AMBIGSW: ambigsw (*cpp, ansp); continue; case UNKWNSW: printf (" -%s unknown. Hit for help.\n", *cpp); continue; default: SIGNAL (SIGINT, istat); return cpp; } } } static void intrser (int i) { NMH_UNUSED (i); /* * should this be siglongjmp? */ siglongjmp (sigenv, 1); } nmh-1.7.1-RC3/sbr/read_switch_multiword_via_readline.c000644 007761 000024 00000004350 13243042053 023016 0ustar00kenhstaff000000 000000 /* read_switch_multiword_via_readline.c -- get an answer from the user, with readline * * 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 #ifdef READLINE_SUPPORT #include #include static struct swit *rl_cmds; static char *nmh_command_generator(const char *, int); static char **nmh_completion(const char *, int, int); static void initialize_readline(void); static char ansbuf[BUFSIZ]; /* * getans, but with readline support */ char ** read_switch_multiword_via_readline(char *prompt, struct swit *ansp) { char *ans, **cpp; initialize_readline(); rl_cmds = ansp; for (;;) { ans = readline(prompt); /* * If we get an EOF, return */ if (ans == NULL) return NULL; if (ans[0] == '?' || ans[0] == '\0') { puts("Options are:"); print_sw(ALL, ansp, "", stdout); free(ans); continue; } add_history(ans); strncpy(ansbuf, ans, sizeof(ansbuf)); ansbuf[sizeof(ansbuf) - 1] = '\0'; cpp = brkstring(ansbuf, " ", NULL); switch (smatch(*cpp, ansp)) { case AMBIGSW: ambigsw(*cpp, ansp); continue; case UNKWNSW: printf(" -%s unknown. Hit for help.\n", *cpp); continue; default: free(ans); return cpp; } free(ans); } } static void initialize_readline(void) { rl_readline_name = "Nmh"; rl_attempted_completion_function = nmh_completion; } static char ** nmh_completion(const char *text, int start, int end) { char **matches; NMH_UNUSED (end); matches = (char **) NULL; if (start == 0) matches = rl_completion_matches(text, nmh_command_generator); return matches; } static char * nmh_command_generator(const char *text, int state) { static int list_index, len; char *name, *p; char buf[256]; if (!state) { list_index = 0; len = strlen(text); } while ((name = rl_cmds[list_index].sw)) { list_index++; strncpy(buf, name, sizeof(buf)); buf[sizeof(buf) - 1] = '\0'; p = *brkstring(buf, " ", NULL); if (strncmp(p, text, len) == 0) return strdup(p); } return NULL; } #endif /* READLINE_SUPPORT */ nmh-1.7.1-RC3/sbr/read_yes_or_no_if_tty.c000644 007761 000024 00000000742 13243042053 020260 0ustar00kenhstaff000000 000000 /* read_yes_or_no_if_tty.c -- get a yes/no answer from the user * * 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 int read_yes_or_no_if_tty (const char *prompt) { static int interactive = -1; if (interactive < 0) interactive = isatty (fileno (stdin)); return (interactive ? read_switch (prompt, anoyes) : 1); } nmh-1.7.1-RC3/sbr/readconfig.c000644 007761 000024 00000010737 13243042053 016021 0ustar00kenhstaff000000 000000 /* readconfig.c -- base routine to read nmh configuration files * -- such as nmh profile, context file, or mhn.defaults. * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include struct procstr { char *procname; char **procnaddr; }; static struct procstr procs[] = { { "context", &context }, { "mh-sequences", &mh_seq }, { "buildmimeproc", &buildmimeproc }, { "fileproc", &fileproc }, { "formatproc", &formatproc }, { "incproc", &incproc }, { "lproc", &lproc }, { "mailproc", &mailproc }, { "mhlproc", &mhlproc }, { "moreproc", &moreproc }, { "packproc", &packproc }, { "postproc", &postproc }, { "rmmproc", &rmmproc }, { "sendproc", &sendproc }, { "showmimeproc", &showmimeproc }, { "showproc", &showproc }, { "whatnowproc", &whatnowproc }, { "whomproc", &whomproc }, { NULL, NULL } }; static struct node **opp = NULL; void readconfig (struct node **npp, FILE *ib, const char *file, int ctx) { int state; char *cp; char name[NAMESZ], field[NMH_BUFSIZ]; struct node *np; struct procstr *ps; m_getfld_state_t gstate = 0; if (npp == NULL && (npp = opp) == NULL) { inform("bug: readconfig called but pump not primed, continuing..."); return; } for (;;) { int fieldsz = sizeof field; switch (state = m_getfld (&gstate, name, field, &fieldsz, ib)) { case FLD: case FLDPLUS: NEW(np); *npp = np; *(npp = &np->n_next) = NULL; np->n_name = mh_xstrdup(name); if (state == FLDPLUS) { cp = mh_xstrdup(field); while (state == FLDPLUS) { fieldsz = sizeof field; state = m_getfld (&gstate, name, field, &fieldsz, ib); cp = add (field, cp); } np->n_field = trimcpy (cp); free (cp); } else { np->n_field = trimcpy (field); } np->n_context = ctx; /* * Now scan the list of `procs' and link in the * field value to the global variable. */ for (ps = procs; ps->procname; ps++) if (strcmp (np->n_name, ps->procname) == 0) { *ps->procnaddr = np->n_field; break; } continue; case BODY: adios (NULL, "no blank lines are permitted in %s", file); case FILEEOF: break; default: adios (NULL, "%s is poorly formatted", file); } break; } m_getfld_state_destroy (&gstate); /* * Special handling for the pager processes: lproc and moreproc. * * If they are not set by the profile, use the callers $PAGER if * available, otherwise set them to DEFAULT_PAGER. */ if (lproc == NULL) { lproc = getenv("PAGER"); if (lproc == NULL || lproc[0] == '\0') lproc = DEFAULT_PAGER; } if (moreproc == NULL) { moreproc = getenv("PAGER"); if (moreproc == NULL || moreproc[0] == '\0') moreproc = DEFAULT_PAGER; } if (opp == NULL) { /* Check for duplicated non-null profile entries. Except allow multiple profile entries named "#", because that's what the mh-profile man page suggests using for comments. Only do this check on the very first call from context_read(), when opp is NULL. That way, entries in mhn.defaults can be overridden without triggering warnings. Note that mhn.defaults, $MHN, $MHBUILD, $MHSHOW, and $MHSTORE all put their entries into just one list, m_defs, the same list that the profile uses. */ struct node *np; for (np = m_defs; np; np = np->n_next) { /* Yes, this is O(N^2). The profile should be small enough so that's not a performance problem. */ if (*np->n_name && strcmp("#", np->n_name)) { struct node *np2; for (np2 = np->n_next; np2; np2 = np2->n_next) { if (! strcasecmp (np->n_name, np2->n_name)) { inform("multiple \"%s\" profile components in %s, " "ignoring \"%s\", continuing...", np->n_name, defpath, np2->n_field); } } } } } opp = npp; } void add_profile_entry (const char *key, const char *value) { struct node *newnode; /* This inserts the new node at the beginning of m_defs because that doesn't require traversing it or checking to see if it's empty. */ NEW(newnode); newnode->n_name = getcpy (key); newnode->n_field = getcpy (value); newnode->n_context = 0; newnode->n_next = m_defs; m_defs = newnode; } nmh-1.7.1-RC3/sbr/refile.c000644 007761 000024 00000002152 13243042053 015156 0ustar00kenhstaff000000 000000 /* refile.c -- call the "fileproc" to refile the * -- msg or draft into another folder * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include int refile (char **arg, char *file) { pid_t pid; int vecp; char **vec; char *program; vec = argsplit(fileproc, &program, &vecp); vec[vecp++] = mh_xstrdup("-nolink"); /* override bad .mh_profile defaults */ vec[vecp++] = mh_xstrdup("-nopreserve"); vec[vecp++] = mh_xstrdup("-file"); vec[vecp++] = getcpy(file); if (arg) { while (*arg) vec[vecp++] = mh_xstrdup(*arg++); } vec[vecp] = NULL; context_save(); /* save the context file */ fflush(stdout); switch (pid = fork()) { case -1: advise ("fork", "unable to"); return -1; case 0: execvp (program, vec); fprintf (stderr, "unable to exec "); perror (fileproc); _exit (-1); default: arglist_free(program, vec); return (pidwait (pid, -1)); } } nmh-1.7.1-RC3/sbr/remdir.c000644 007761 000024 00000000663 13243042053 015177 0ustar00kenhstaff000000 000000 /* remdir.c -- remove a directory * * 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 int remdir (char *dir) { context_save(); /* save the context file */ fflush(stdout); if (rmdir(dir) == -1) { admonish (dir, "unable to remove directory"); return 0; } return 1; } nmh-1.7.1-RC3/sbr/ruserpass.c000644 007761 000024 00000012514 13243042053 015742 0ustar00kenhstaff000000 000000 /* ruserpass.c -- parse .netrc-format file. * * Portions of this code are * Copyright (c) 1985 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Portions of this code are 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 #include #include static FILE *cfile; #define TOK_EOF 0 #define DEFAULT 1 #define LOGIN 2 #define PASSWD 3 #define ACCOUNT 4 #define MACDEF 5 #define ID 10 #define MACH 11 #define MAX_TOKVAL_SIZE 1024 /* Including terminating NUL. */ struct toktab { char *tokstr; int tval; }; static struct toktab toktabs[] = { { "", TOK_EOF }, { "default", DEFAULT }, { "login", LOGIN }, { "password", PASSWD }, { "passwd", PASSWD }, { "account", ACCOUNT }, { "machine", MACH }, { "macdef", MACDEF }, { 0, 0 } }; /* * prototypes */ static int token(char *); void ruserpass(const char *host, char **aname, char **apass, int flags) { int t, usedefault = 0; struct stat stb; init_credentials_file (); cfile = fopen (credentials_file, "r"); if (cfile == NULL) { if (errno != ENOENT) perror (credentials_file); } else { char tokval[MAX_TOKVAL_SIZE]; tokval[0] = '\0'; while ((t = token(tokval))) { switch(t) { case DEFAULT: usedefault = 1; /* FALLTHRU */ case MACH: if (!usedefault) { if (token(tokval) != ID) continue; /* * Allow match either for user's host name. */ if (strcasecmp(host, tokval) == 0) goto match; continue; } match: while ((t = token(tokval)) && t != MACH && t != DEFAULT) { switch(t) { case LOGIN: if (token(tokval) && *aname == 0) *aname = mh_xstrdup(tokval); break; case PASSWD: if (!credentials_no_perm_check && fstat(fileno(cfile), &stb) >= 0 && (stb.st_mode & 077) != 0) { /* We make this a fatal error to force the user to correct it. */ inform("group or other permissions, %#o, " "forbidden: %s", stb.st_mode, credentials_file); adios(NULL, "Remove password or correct file " "permissions."); } if (token(tokval) && *apass == 0) *apass = mh_xstrdup(tokval); break; case ACCOUNT: break; case MACDEF: fclose(cfile); return; default: fprintf(stderr, "Unknown keyword %s in credentials file %s\n", tokval, credentials_file); break; } } return; } } } if (!*aname && ! (flags & RUSERPASS_NO_PROMPT_USER)) { char tmp[80]; char *myname; if ((myname = getlogin()) == NULL) { struct passwd *pp; if ((pp = getpwuid (getuid())) != NULL) myname = pp->pw_name; } printf("Name (%s:%s): ", host, myname); if (fgets(tmp, sizeof tmp, stdin) == NULL) { advise ("tmp", "fgets"); } trim_suffix_c(tmp, '\n'); if (*tmp != '\0' || myname == NULL) { myname = tmp; } *aname = mh_xstrdup(myname); } if (!*apass && ! (flags & RUSERPASS_NO_PROMPT_PASSWORD)) { char prompt[256]; char *mypass; snprintf(prompt, sizeof(prompt), "Password (%s:%s): ", host, *aname); mypass = nmh_getpass(prompt); if (*mypass == '\0') { mypass = *aname; } *aname = mh_xstrdup(mypass); } } static int token(char *tokval) { int c; const char normalStop[] = "\t\n ,"; /* Each breaks a word. */ const char *stop; char *cp; struct toktab *t; if (feof(cfile) || ferror(cfile)) return TOK_EOF; stop = normalStop; while ((c = getc(cfile)) != EOF && c && strchr(stop, c)) ; if (c == EOF) return TOK_EOF; cp = tokval; if (c == '"') /* FIXME: Where is the quoted-string syntax of netrc documented? * This code treats «"foo""bar"» as two tokens without further * separators. */ stop = "\""; else /* Might be backslash. Get it again later. It's handled then. */ if (ungetc(c, cfile) == EOF) return TOK_EOF; while ((c = getc(cfile)) != EOF && c && !strchr(stop, c)) { if (c == '\\' && (c = getc(cfile)) == EOF) return TOK_EOF; /* Discard whole token. */ *cp++ = c; if (cp - tokval > MAX_TOKVAL_SIZE-1) { adios(NULL, "credential tokens restricted to length %d", MAX_TOKVAL_SIZE - 1); } } *cp = '\0'; for (t = toktabs; t->tokstr; t++) if (!strcmp(t->tokstr, tokval)) return (t->tval); return (ID); } nmh-1.7.1-RC3/sbr/seq_add.c000644 007761 000024 00000010121 13243042053 015303 0ustar00kenhstaff000000 000000 /* seq_add.c -- add message(s) to a sequence * * 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 /* * Add all the SELECTED messages to a (possibly new) sequence. * * If public == 1, make sequence public. * If public == 0, make sequence private. * If public == -1, leave the public/private bit alone for existing * sequences. For new sequences, set this bit based * on its readonly status. * * If error, return 0, else return 1. */ int seq_addsel (struct msgs *mp, char *cp, int public, int zero) { unsigned int i; int msgnum, new_seq = 1; if (!seq_nameok (cp)) return 0; /* * We keep mp->curmsg and "cur" sequence in sync. * See seq_list() and seq_init(). */ if (!strcmp (current,cp)) mp->curmsg = mp->hghsel; /* * Get the number for this sequence */ for (i = 0; i < svector_size (mp->msgattrs); i++) { if (!strcmp (svector_at (mp->msgattrs, i), cp)) { new_seq = 0; break; } } /* * If this is a new sequence, add a slot for it */ if (new_seq) { if (!(svector_push_back (mp->msgattrs, strdup (cp)))) { inform("strdup failed"); return 0; } } /* * If sequence is new, or zero flag is set, then first * clear the bit for this sequence from all messages. */ if ((new_seq || zero) && mp->nummsg > 0) { for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg; msgnum++) clear_sequence (mp, i, msgnum); } /* * Now flip on the bit for this sequence * for all selected messages. */ for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) if (is_selected (mp, msgnum)) add_sequence (mp, i, msgnum); /* * Set the public/private bit for this sequence. */ if (public == 1) make_seq_public (mp, i); else if (public == 0) make_seq_private (mp, i); else if (new_seq) { /* * If public == -1, then only set the * public/private bit for new sequences. */ if (is_readonly (mp)) make_seq_private (mp, i); else make_seq_public (mp, i); } mp->msgflags |= SEQMOD; return 1; } /* * Add a message to a (possibly new) sequence. * * If public == 1, make sequence public. * If public == 0, make sequence private. * If public == -1, leave the public/private bit alone for existing * sequences. For new sequences, set this bit based * on its readonly status. * * If error, return 0, else return 1. */ int seq_addmsg (struct msgs *mp, char *cp, int msgnum, int public, int zero) { unsigned int i; int j, new_seq = 1; if (!seq_nameok (cp)) return 0; /* * keep mp->curmsg and msgattrs["cur"] in sync - see seq_list() */ if (!strcmp (current,cp)) mp->curmsg = msgnum; /* * Get the number for this sequence */ for (i = 0; i < svector_size (mp->msgattrs); i++) { if (!strcmp (svector_at (mp->msgattrs, i), cp)) { new_seq = 0; break; } } /* * If this is a new sequence, add a slot for it */ if (new_seq) { if (!(svector_push_back (mp->msgattrs, strdup (cp)))) { inform("strdup failed"); return 0; } } /* * If sequence is new, or zero flag is set, then first * clear the bit for this sequence from all messages. */ if ((new_seq || zero) && mp->nummsg > 0) { for (j = mp->lowmsg; j <= mp->hghmsg; j++) clear_sequence (mp, i, j); } /* * Now flip on the bit for this sequence * for this particular message. */ add_sequence (mp, i, msgnum); /* * Set the public/private bit for this sequence. */ if (public == 1) make_seq_public (mp, i); else if (public == 0) make_seq_private (mp, i); else if (new_seq) { /* * If public == -1, then only set the * public/private bit for new sequences. */ if (is_readonly (mp)) make_seq_private (mp, i); else make_seq_public (mp, i); } mp->msgflags |= SEQMOD; return 1; } nmh-1.7.1-RC3/sbr/seq_bits.c000644 007761 000024 00000001761 13243042053 015526 0ustar00kenhstaff000000 000000 /* seq_bits.c -- return the snprintb() string for a sequence * * 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 char * seq_bits (struct msgs *mp) { size_t i; size_t len; static char buffer[BUFSIZ]; strncpy (buffer, MBITS, sizeof(buffer)); for (i = 0; i < svector_size (mp->msgattrs); i++) { len = strlen (buffer); snprintf (buffer + len, sizeof(buffer) - len, "%c%s", FFATTRSLOT + 1 + (int) i, svector_at (mp->msgattrs, i)); /* * seq_bits() is used by seq_printdebug(), which passes an * unsigned int bit vector to snprintb(). So limit the * size of the return value accordingly. Even worse, * snprintb() only uses characters up through ASCII space * as the delimiter (the %c character above). So limit * based on that. */ if ((int) i == ' ' - FFATTRSLOT - 1) break; } return buffer; } nmh-1.7.1-RC3/sbr/seq_del.c000644 007761 000024 00000005474 13243042053 015336 0ustar00kenhstaff000000 000000 /* seq_del.c -- delete message(s) from a sequence * * 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 /* * Delete all SELECTED messages from sequence * * If public == 1, make sequence public. * If public == 0, make sequence private. * If public == -1, leave the public/private bit alone for existing * sequences. For new sequences, set this bit based * on its readonly status. * * If error, return 0, else return 1. */ int seq_delsel (struct msgs *mp, char *cp, int public, int zero) { unsigned int i; int msgnum, new_seq = 1; if (!seq_nameok (cp)) return 0; /* * Get the number for this sequence */ for (i = 0; i < svector_size (mp->msgattrs); i++) { if (!strcmp (svector_at (mp->msgattrs, i), cp)) { new_seq = 0; break; } } /* * If the zero flag is set, first add all existing * messages in this folder to the sequence. */ if (zero) { /* * create the sequence, if necessary */ if (new_seq) { if (!(svector_push_back (mp->msgattrs, strdup (cp)))) { inform("strdup failed"); return 0; } } /* * now add sequence bit to all existing messages */ for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg; msgnum++) { if (does_exist (mp, msgnum)) add_sequence (mp, i, msgnum); else clear_sequence (mp, i, msgnum); } } else { if (new_seq) { inform("no such sequence as %s", cp); return 0; } } /* * Now clear the bit on all selected messages */ for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) if (is_selected (mp, msgnum)) clear_sequence (mp, i, msgnum); if (! strcmp (cp, current) && mp->lowsel <= mp->curmsg && mp->curmsg <= mp->hghsel) { /* Removed current message indication, so reset curmsg. */ mp->curmsg = 0; } /* * Set the public/private bit for this sequence. */ if (public == 1) make_seq_public (mp, i); else if (public == 0) make_seq_private (mp, i); else if (new_seq) { /* * If public == -1, then only set the * public/private bit for new sequences. */ if (is_readonly (mp)) make_seq_private (mp, i); else make_seq_public (mp, i); } mp->msgflags |= SEQMOD; return 1; } /* * Delete message from sequence. * * If error, return 0, else return 1. */ int seq_delmsg (struct msgs *mp, char *cp, int msgnum) { size_t i; if (!seq_nameok (cp)) return 0; for (i = 0; i < svector_size (mp->msgattrs); i++) { if (!strcmp (svector_at (mp->msgattrs, i), cp)) { clear_sequence (mp, i, msgnum); mp->msgflags |= SEQMOD; return 1; } } inform("no such sequence as %s", cp); return 0; } nmh-1.7.1-RC3/sbr/seq_getnum.c000644 007761 000024 00000000775 13243042053 016070 0ustar00kenhstaff000000 000000 /* seq_getnum.c -- find the index for a sequence * -- return -1 if sequence doesn't exist * * 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 int seq_getnum (struct msgs *mp, char *seqname) { size_t i; for (i = 0; i < svector_size (mp->msgattrs); i++) if (!strcmp (svector_at (mp->msgattrs, i), seqname)) return i; return -1; } nmh-1.7.1-RC3/sbr/seq_list.c000644 007761 000024 00000004662 13243042053 015543 0ustar00kenhstaff000000 000000 /* seq_list.c -- Get all messages in a sequence and return them * -- as a space separated list of message ranges. * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include /* allocate this much buffer space at a time */ #define MAXBUFFER 1024 /* static buffer to collect the sequence line */ static char *buffer = NULL; static int len = 0; char * seq_list(struct msgs *mp, char *seqname) { int i, j, seqnum; char *bp; /* On first invocation, allocate initial buffer space */ if (!buffer) { len = MAXBUFFER; buffer = mh_xmalloc ((size_t) len); } /* * Special processing for "cur" sequence. We assume that the * "cur" sequence and mp->curmsg are in sync (see seq_add.c). * This is returned, even if message doesn't exist or the * folder is empty. */ if (!strcmp (current, seqname)) { if (mp->curmsg) { snprintf(buffer, len, "%s", m_name(mp->curmsg)); return (buffer); } return (NULL); } /* If the folder is empty, just return NULL */ if (mp->nummsg == 0) return NULL; /* Get the index of the sequence */ if ((seqnum = seq_getnum (mp, seqname)) == -1) return NULL; bp = buffer; for (i = mp->lowmsg; i <= mp->hghmsg; ++i) { /* * If message doesn't exist, or isn't in * the sequence, then continue. */ if (!does_exist(mp, i) || !in_sequence(mp, seqnum, i)) continue; /* * See if we need to enlarge buffer. Since we don't know * exactly how many character this particular message range * will need, we enlarge the buffer if we are within * 50 characters of the end. */ if (bp - buffer > len - 50) { char *newbuf; len += MAXBUFFER; newbuf = mh_xrealloc (buffer, (size_t) len); bp = newbuf + (bp - buffer); buffer = newbuf; } /* * If this is not the first message range in * the list, first add a space. */ if (bp > buffer) *bp++ = ' '; strcpy(bp, m_name(i)); bp += strlen(bp); j = i; /* Remember beginning of message range */ /* * Scan to the end of this message range */ for (++i; i <= mp->hghmsg && does_exist(mp, i) && in_sequence(mp, seqnum, i); ++i) ; if (i - j > 1) { *bp++ = '-'; strcpy(bp, m_name(i - 1)); bp += strlen(bp); } } return (bp > buffer? buffer : NULL); } nmh-1.7.1-RC3/sbr/seq_nameok.c000644 007761 000024 00000002157 13243042053 016037 0ustar00kenhstaff000000 000000 /* seq_nameok.c -- check if a sequence name is ok * * 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 int seq_nameok (char *s) { char *pp; if (s == NULL || *s == '\0') { inform("empty sequence name"); return 0; } /* * Make sure sequence name doesn't clash with one * of the `reserved' sequence names. */ if (!(strcmp (s, "new") && strcmp (s, "all") && strcmp (s, "first") && strcmp (s, "last") && strcmp (s, "prev") && strcmp (s, "next"))) { inform("illegal sequence name: %s", s); return 0; } /* * First character in a sequence name must be * an alphabetic character ... */ if (!isalpha ((unsigned char) *s)) { inform("illegal sequence name: %s", s); return 0; } /* * and can be followed by zero or more alphanumeric characters */ for (pp = s + 1; *pp; pp++) if (!isalnum ((unsigned char) *pp)) { inform("illegal sequence name: %s", s); return 0; } return 1; } nmh-1.7.1-RC3/sbr/seq_print.c000644 007761 000024 00000001742 13243042053 015720 0ustar00kenhstaff000000 000000 /* seq_print.c -- Routines to print sequence information. * * 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 /* * Print all the sequences in a folder */ void seq_printall (struct msgs *mp) { size_t i; char *list; for (i = 0; i < svector_size (mp->msgattrs); i++) { list = seq_list (mp, svector_at (mp->msgattrs, i)); printf ("%s%s: %s\n", svector_at (mp->msgattrs, i), is_seq_private (mp, i) ? " (private)" : "", FENDNULL(list)); } } /* * Print a particular sequence in a folder */ void seq_print (struct msgs *mp, char *seqname) { int i; char *list; /* get the index of sequence */ i = seq_getnum (mp, seqname); /* get sequence information */ list = seq_list (mp, seqname); printf ("%s%s: %s\n", seqname, (i == -1) ? "" : is_seq_private(mp, i) ? " (private)" : "", FENDNULL(list)); } nmh-1.7.1-RC3/sbr/seq_read.c000644 007761 000024 00000013642 13243042053 015501 0ustar00kenhstaff000000 000000 /* seq_read.c -- read the .mh_sequence file and * -- initialize sequence information * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include "lock_file.h" /* * static prototypes */ static int seq_init (struct msgs *, char *, char *); static int seq_public (struct msgs *, int, int *); static void seq_private (struct msgs *); /* * Get the sequence information for this folder from * .mh_sequences (or equivalent specified in .mh_profile) * or context file (for private sequences). */ int seq_read (struct msgs *mp, int lockflag) { int failed_to_lock = 0; /* * Initialize the list of sequence names. Go ahead and * add the "cur" sequence to the list of sequences. */ svector_push_back (mp->msgattrs, getcpy (current)); make_all_public (mp); /* initially, make all public */ /* If folder is empty, don't scan for sequence information */ if (mp->nummsg == 0) return OK; /* Initialize the public sequences */ if (seq_public (mp, lockflag, &failed_to_lock) == NOTOK) { if (failed_to_lock) return NOTOK; } /* Initialize the private sequences */ seq_private (mp); return OK; } /* * read folder's sequences file for public sequences */ static int seq_public (struct msgs *mp, int lockflag, int *failed_to_lock) { int state; char *cp, seqfile[PATH_MAX]; char name[NAMESZ], field[NMH_BUFSIZ]; FILE *fp; m_getfld_state_t gstate = 0; /* * If mh_seq == NULL or if *mh_seq == '\0' (the user has defined * the "mh-sequences" profile entry, but left it empty), * then just return, and do not initialize any public sequences. */ if (mh_seq == NULL || *mh_seq == '\0') return OK; /* get filename of sequence file */ snprintf (seqfile, sizeof(seqfile), "%s/%s", mp->foldpath, mh_seq); if ((fp = lkfopendata (seqfile, lockflag ? "r+" : "r", failed_to_lock)) == NULL) return NOTOK; /* Use m_getfld to scan sequence file */ for (;;) { int fieldsz = sizeof field; switch (state = m_getfld (&gstate, name, field, &fieldsz, fp)) { case FLD: case FLDPLUS: if (state == FLDPLUS) { cp = mh_xstrdup(field); while (state == FLDPLUS) { fieldsz = sizeof field; state = m_getfld (&gstate, name, field, &fieldsz, fp); cp = add (field, cp); } seq_init (mp, mh_xstrdup(name), trimcpy (cp)); free (cp); } else { seq_init (mp, mh_xstrdup(name), trimcpy (field)); } continue; case BODY: lkfclosedata (fp, seqfile); adios (NULL, "no blank lines are permitted in %s", seqfile); break; case FILEEOF: break; default: lkfclosedata (fp, seqfile); adios (NULL, "%s is poorly formatted", seqfile); } break; /* break from for loop */ } m_getfld_state_destroy (&gstate); if (lockflag) { mp->seqhandle = fp; mp->seqname = mh_xstrdup(seqfile); } else { lkfclosedata (fp, seqfile); } return OK; } /* * Scan profile/context list for private sequences. * * We search the context list for all keys that look like * "atr-seqname-folderpath", and add them as private sequences. */ static void seq_private (struct msgs *mp) { int i, j, alen, plen; char *cp; struct node *np; alen = LEN("atr-"); plen = strlen (mp->foldpath) + 1; for (np = m_defs; np; np = np->n_next) { if (ssequal ("atr-", np->n_name) && (j = strlen (np->n_name) - plen) > alen && *(np->n_name + j) == '-' && strcmp (mp->foldpath, np->n_name + j + 1) == 0) { cp = mh_xstrdup(np->n_name + alen); *(cp + j - alen) = '\0'; if ((i = seq_init (mp, cp, getcpy (np->n_field))) != -1) make_seq_private (mp, i); } } } /* * Add the name of sequence to the list of folder sequences. * Then parse the list of message ranges for this * sequence, and setup the various bit flags for each * message in the sequence. * * Return internal index for the sequence if successful. * Return -1 on error. */ static int seq_init (struct msgs *mp, char *name, char *field) { unsigned int i; int j, k, is_current; char *cp, **ap; /* * Check if this is "cur" sequence, * so we can do some special things. */ is_current = !strcmp (current, name); /* * Search for this sequence name to see if we've seen * it already. If we've seen this sequence before, * then clear the bit for this sequence from all the * messages in this folder. */ for (i = 0; i < svector_size (mp->msgattrs); i++) { if (!strcmp (svector_at (mp->msgattrs, i), name)) { for (j = mp->lowmsg; j <= mp->hghmsg; j++) clear_sequence (mp, i, j); break; } } /* * If we've already seen this sequence name, just free the * name string. Else add it to the list of sequence names. */ if (svector_at (mp->msgattrs, i)) { free (name); } else { svector_push_back (mp->msgattrs, name); } /* * Split up the different message ranges at whitespace */ for (ap = brkstring (field, " ", "\n"); *ap; ap++) { if ((cp = strchr(*ap, '-'))) *cp++ = '\0'; if ((j = m_atoi (*ap)) > 0) { k = cp ? m_atoi (cp) : j; /* * Keep mp->curmsg and "cur" sequence in synch. Unlike * other sequences, this message doesn't need to exist. * Think about the series of command (rmm; next) to * understand why this can be the case. But if it does * exist, we will still set the bit flag for it like * other sequences. */ if (is_current) mp->curmsg = j; /* * We iterate through messages in this range * and flip on bit for this sequence. */ for (; j <= k; j++) { if (j >= mp->lowmsg && j <= mp->hghmsg && does_exist(mp, j)) add_sequence (mp, i, j); } } } free (field); /* free string containing message ranges */ return i; } nmh-1.7.1-RC3/sbr/seq_save.c000644 007761 000024 00000007023 13243042053 015520 0ustar00kenhstaff000000 000000 /* seq_save.c -- 1) synchronize sequences * -- 2) save public sequences * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include "lock_file.h" #include "m_mktemp.h" /* * 1. If sequence is public and folder is readonly, * then change it to be private * 2a. If sequence is public, then add it to the sequences file * in folder (name specified by mh-sequences profile entry). * 2b. If sequence is private, then add it to the * context file. */ void seq_save (struct msgs *mp) { size_t i; char flags, *cp, attr[BUFSIZ], seqfile[PATH_MAX]; FILE *fp; sigset_t set, oset; /* check if sequence information has changed */ if (!(mp->msgflags & SEQMOD)) { if (mp->seqhandle) { lkfclosedata (mp->seqhandle, mp->seqname); mp->seqhandle = NULL; free(mp->seqname); mp->seqname = NULL; } return; } mp->msgflags &= ~SEQMOD; fp = NULL; flags = mp->msgflags; /* record folder flags */ /* * If no mh-sequences file is defined, or if a mh-sequences file * is defined but empty (*mh_seq == '\0'), then pretend folder * is readonly. This will force all sequences to be private. */ if (mh_seq == NULL || *mh_seq == '\0') set_readonly (mp); else snprintf (seqfile, sizeof(seqfile), "%s/%s", mp->foldpath, mh_seq); for (i = 0; i < svector_size (mp->msgattrs); i++) { snprintf (attr, sizeof(attr), "atr-%s-%s", svector_at (mp->msgattrs, i), mp->foldpath); /* get space separated list of sequence ranges */ if (!(cp = seq_list(mp, svector_at (mp->msgattrs, i)))) { context_del (attr); /* delete sequence from context */ continue; } if (is_readonly(mp) || is_seq_private(mp, i)) { priv: /* * sequence is private */ context_replace (attr, cp); /* update sequence in context */ } else { /* * sequence is public */ context_del (attr); /* delete sequence from context */ if (!fp) { int failed_to_lock = 0; /* * Attempt to open file for public sequences. * If that fails (probably because folder is * readonly), then make sequence private. */ if (mp->seqhandle) { fp = mp->seqhandle; mp->seqhandle = NULL; free(mp->seqname); mp->seqname = NULL; rewind(fp); if (ftruncate(fileno(fp), 0) < 0) { advise ("sequence file", "ftruncate"); } } else if ((fp = lkfopendata (seqfile, "w", &failed_to_lock)) == NULL && (m_unlink (seqfile) == -1 || (fp = lkfopendata (seqfile, "w", &failed_to_lock)) == NULL)) { if (failed_to_lock) { admonish (attr, "unable to lock"); } else { admonish (attr, "unable to write"); } goto priv; } /* block a few signals */ sigemptyset (&set); sigaddset(&set, SIGHUP); sigaddset(&set, SIGINT); sigaddset(&set, SIGQUIT); sigaddset(&set, SIGTERM); sigprocmask (SIG_BLOCK, &set, &oset); } fprintf (fp, "%s: %s\n", svector_at (mp->msgattrs, i), cp); } } if (fp) { lkfclosedata (fp, seqfile); sigprocmask (SIG_SETMASK, &oset, &set); /* reset signal mask */ } else { /* * If folder is not readonly, and we didn't save any * public sequences, then remove that file. */ if (!is_readonly(mp)) (void) m_unlink (seqfile); } /* * Reset folder flag, since we may be * pretending that folder is readonly. */ mp->msgflags = flags; } nmh-1.7.1-RC3/sbr/seq_setcur.c000644 007761 000024 00000000701 13243042053 016063 0ustar00kenhstaff000000 000000 /* seq_setcur.c -- set the current message ("cur" sequence) for a folder * * 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 void seq_setcur (struct msgs *mp, int msgnum) { /* * Just call seq_addmsg() to update the * "cur" sequence. */ seq_addmsg (mp, current, msgnum, -1, 1); } nmh-1.7.1-RC3/sbr/seq_setprev.c000644 007761 000024 00000001655 13243042053 016257 0ustar00kenhstaff000000 000000 /* seq_setprev.c -- set the Previous-Sequence * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include /* * Add all the messages currently SELECTED to * the Previous-Sequence. This way, when the next * command is given, there is a convenient way to * selected all the messages used in the previous * command. */ void seq_setprev (struct msgs *mp) { char **ap, *cp, *dp; /* * Get the list of sequences for Previous-Sequence * and split them. */ if ((cp = context_find (psequence))) { dp = mh_xstrdup(cp); if (!(ap = brkstring (dp, " ", "\n")) || !*ap) { free (dp); return; } } else { return; } /* Now add all SELECTED messages to each sequence */ for (; *ap; ap++) seq_addsel (mp, *ap, -1, 1); free (dp); } nmh-1.7.1-RC3/sbr/seq_setunseen.c000644 007761 000024 00000002677 13243042053 016605 0ustar00kenhstaff000000 000000 /* seq_setunseen.c -- add/delete all messages which have the SELECT_UNSEEN * -- bit set to/from the Unseen-Sequence * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include /* * We scan through the folder and act upon all messages * that are marked with the SELECT_UNSEEN bit. * * If seen == 1, delete messages from unseen sequence. * If seen == 0, add messages to unseen sequence. */ void seq_setunseen (struct msgs *mp, int seen) { int msgnum; char **ap, *cp, *dp; /* * Get the list of sequences for Unseen-Sequence * and split them. */ if ((cp = context_find (usequence))) { dp = mh_xstrdup(cp); if (!(ap = brkstring (dp, " ", "\n")) || !*ap) { free (dp); return; } } else { return; } /* * Now add/delete each message which has the SELECT_UNSEEN * bit set to/from each of these sequences. */ for (; *ap; ap++) { if (seen) { /* make sure sequence exists first */ if (seq_getnum(mp, *ap) != -1) for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) if (is_unseen (mp, msgnum)) seq_delmsg (mp, *ap, msgnum); } else { for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg; msgnum++) if (is_unseen (mp, msgnum)) seq_addmsg (mp, *ap, msgnum, -1, 0); } } free (dp); } nmh-1.7.1-RC3/sbr/showfile.c000644 007761 000024 00000002343 13243042053 015532 0ustar00kenhstaff000000 000000 /* showfile.c -- invoke the `lproc' command * * 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 int showfile (char **arg, char *file) { pid_t pid; int isdraft, vecp; char **vec, *program; int retval = 1; context_save(); /* save the context file */ fflush(stdout); /* * If you have your lproc listed as "mhl", * then really invoked the mhlproc instead * (which is usually mhl anyway). */ if (!strcmp (r1bindex (lproc, '/'), "mhl")) lproc = mhlproc; switch (pid = fork()) { case -1: /* fork error */ advise ("fork", "unable to"); break; case 0: /* child */ vec = argsplit(lproc, &program, &vecp); isdraft = 1; if (arg) { while (*arg) { if (**arg != '-') isdraft = 0; vec[vecp++] = *arg++; } } if (isdraft) { if (!strcmp (vec[0], "show")) vec[vecp++] = "-file"; vec[vecp++] = file; } vec[vecp] = NULL; execvp (program, vec); fprintf (stderr, "unable to exec "); perror (lproc); _exit (-1); default: /* parent */ retval = pidwait (pid, -1) & 0377 ? 1 : 0; } return retval; } nmh-1.7.1-RC3/sbr/signals.c000644 007761 000024 00000005142 13243042053 015352 0ustar00kenhstaff000000 000000 /* signals.c -- general signals interface for nmh * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include "m_mktemp.h" /* * A version of the function `signal' that uses reliable * signals, if the machine supports them. Also, (assuming * OS support), it restarts interrupted system calls for all * signals except SIGALRM. * * Since we are now assuming POSIX signal support everywhere, we always * use reliable signals. */ SIGNAL_HANDLER SIGNAL (int sig, SIGNAL_HANDLER func) { struct sigaction act, oact; act.sa_handler = func; sigemptyset(&act.sa_mask); act.sa_flags = 0; if (sig == SIGALRM) { # ifdef SA_INTERRUPT act.sa_flags |= SA_INTERRUPT; /* SunOS */ # endif } else { # ifdef SA_RESTART act.sa_flags |= SA_RESTART; /* SVR4, BSD4.4 */ # endif } if (sigaction(sig, &act, &oact) < 0) return (SIG_ERR); return (oact.sa_handler); } /* * A version of the function `signal' that will set * the handler of `sig' to `func' if the signal is * not currently set to SIG_IGN. Also uses reliable * signals if available. */ SIGNAL_HANDLER SIGNAL2 (int sig, SIGNAL_HANDLER func) { struct sigaction act, oact; if (sigaction(sig, NULL, &oact) < 0) return (SIG_ERR); if (oact.sa_handler != SIG_IGN) { act.sa_handler = func; sigemptyset(&act.sa_mask); act.sa_flags = 0; if (sig == SIGALRM) { # ifdef SA_INTERRUPT act.sa_flags |= SA_INTERRUPT; /* SunOS */ # endif } else { # ifdef SA_RESTART act.sa_flags |= SA_RESTART; /* SVR4, BSD4.4 */ # endif } if (sigaction(sig, &act, &oact) < 0) return (SIG_ERR); } return (oact.sa_handler); } /* * For use by nmh_init(). */ int setup_signal_handlers(void) { /* * Catch HUP, INT, QUIT, and TERM so that we can clean up tmp * files when the user terminates the process early. And also a * few other common signals that can be thrown due to bugs, stack * overflow, etc. */ if (SIGNAL(SIGHUP, remove_registered_files) == SIG_ERR || SIGNAL(SIGINT, remove_registered_files) == SIG_ERR || SIGNAL(SIGQUIT, remove_registered_files) == SIG_ERR || SIGNAL(SIGTERM, remove_registered_files) == SIG_ERR || SIGNAL(SIGILL, remove_registered_files) == SIG_ERR || # ifdef SIGBUS SIGNAL(SIGBUS, remove_registered_files) == SIG_ERR || # endif SIGNAL(SIGSEGV, remove_registered_files) == SIG_ERR) { return NOTOK; } return OK; } nmh-1.7.1-RC3/sbr/smatch.c000644 007761 000024 00000001624 13243042053 015172 0ustar00kenhstaff000000 000000 /* smatch.c -- match a switch (option) * * 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 int smatch(const char *string, const struct swit *swp) { const char *sp, *tcp; int firstone, len; const struct swit *tp; firstone = UNKWNSW; if (!string) return firstone; len = strlen(string); for (tp = swp; tp->sw; tp++) { tcp = tp->sw; if (len < abs(tp->minchars)) continue; /* no match */ for (sp = string; *sp == *tcp++;) { if (*sp++ == '\0') return tp->swret; /* exact match */ } if (*sp) { if (*sp != ' ') continue; /* no match */ if (*--tcp == '\0') return tp->swret; /* exact match */ } if (firstone == UNKWNSW) firstone = tp->swret; else firstone = AMBIGSW; } return (firstone); } nmh-1.7.1-RC3/sbr/snprintb.c000644 007761 000024 00000001535 13243042053 015553 0ustar00kenhstaff000000 000000 /* snprintb.c -- snprintf a %b string * * 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 char * snprintb (char *buffer, size_t n, unsigned v, char *bits) { size_t len; int i, j; char c, *bp; snprintf (buffer, n, bits && *bits == 010 ? "0%o" : "0x%x", v); len = strlen(buffer); bp = buffer + len; n -= len; if (bits && *++bits) { j = 0; *bp++ = '<'; while ((i = *bits++) && n > 1) if (v & (1 << (i - 1))) { if (j++ && n > 1) { *bp++ = ','; n--; } for (; (c = *bits) > 32 && n > 1; bits++) { *bp++ = c; n--; } } else for (; *bits > 32; bits++) continue; if (n > 1) *bp++ = '>'; *bp = 0; } return buffer; } nmh-1.7.1-RC3/sbr/ssequal.c000644 007761 000024 00000001375 13243042053 015373 0ustar00kenhstaff000000 000000 /* ssequal.c -- check if a string is a substring of another * * 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 /* * THIS CODE DOES NOT WORK AS ADVERTISED. * It is actually checking if s1 is a PREFIX of s2. * All calls to this function need to be checked to see * if that needs to be changed. Prefix checking is cheaper, so * should be kept if it's sufficient. */ /* * Check if s1 is a substring of s2. * If yes, then return 1, else return 0. */ int ssequal (const char *s1, const char *s2) { if (!s1) s1 = ""; if (!s2) s2 = ""; while (*s1) if (*s1++ != *s2++) return 0; return 1; } nmh-1.7.1-RC3/sbr/strindex.c000644 007761 000024 00000000647 13243042053 015557 0ustar00kenhstaff000000 000000 /* strindex.c -- "unsigned" lexical index * * 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 int stringdex (char *p1, char *p2) { char *p; if (p1 == NULL || p2 == NULL) return -1; for (p = p2; *p; p++) if (uprf (p, p1)) return (p - p2); return -1; } nmh-1.7.1-RC3/sbr/terminal.c000644 007761 000024 00000010531 13243042053 015523 0ustar00kenhstaff000000 000000 /* terminal.c -- termcap support * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include #include #include #ifdef WINSIZE_IN_PTEM # include # include #endif static int initLI = 0; static int initCO = 0; static int LI = 40; /* number of lines */ static int CO = 80; /* number of columns */ static char *ti_clear = NULL; /* terminfo string to clear screen */ static char *ti_standend = NULL; /* terminfo string to end standout mode */ static char *ti_standbegin = NULL; /* terminfo string to begin standout mode */ static int termstatus = 0; /* terminfo initialization status */ static char *termcbuf = NULL; /* tputs() output buffer */ static char *termcbufp = NULL; /* tputs() output buffer pointer */ static size_t termcbufsz = 0; /* Size of termcbuf */ static void initialize_terminfo(void); static int termbytes(TPUTS_PUTC_ARG); /* * Initialize the terminfo library. */ static void initialize_terminfo(void) { int errret, rc; if (termstatus) return; rc = setupterm(NULL, fileno(stdout), &errret); if (rc != 0 || errret != 1) { termstatus = -1; return; } termstatus = 1; if (!initCO && (CO = tigetnum ("cols")) <= 0) CO = 80; if (!initLI && (LI = tigetnum ("lines")) <= 0) LI = 24; ti_clear = tigetstr ("clear"); ti_standbegin = tigetstr ("smso"); ti_standend = tigetstr ("rmso"); } int sc_width (void) { #ifdef TIOCGWINSZ struct winsize win; int width; if (ioctl (fileno (stderr), TIOCGWINSZ, &win) != NOTOK && (width = win.ws_col) > 0) { CO = width; initCO++; } else #endif /* TIOCGWINSZ */ initialize_terminfo(); return CO; } int sc_length (void) { #ifdef TIOCGWINSZ struct winsize win; if (ioctl (fileno (stderr), TIOCGWINSZ, &win) != NOTOK && (LI = win.ws_row) > 0) initLI++; else #endif /* TIOCGWINSZ */ initialize_terminfo(); return LI; } static int outc (TPUTS_PUTC_ARG c) { return putchar(c); } void nmh_clear_screen (void) { initialize_terminfo (); if (ti_clear) tputs (ti_clear, LI, outc); else { putchar('\f'); } fflush (stdout); } /* * print in standout mode */ int SOprintf (char *fmt, ...) { va_list ap; initialize_terminfo (); if (!(ti_standbegin && ti_standend)) return NOTOK; tputs (ti_standbegin, 1, outc); va_start(ap, fmt); vprintf (fmt, ap); va_end(ap); tputs (ti_standend, 1, outc); return OK; } /* * Return the specified capability as a string that has already been * processed with tputs(). */ char * get_term_stringcap(char *capability) { char *parm; initialize_terminfo(); if (termstatus == -1) return NULL; termcbufp = termcbuf; parm = tigetstr(capability); if (parm == (char *) -1 || parm == NULL) { return NULL; } tputs(parm, 1, termbytes); *termcbufp = '\0'; return termcbuf; } /* * Return a parameterized terminfo capability */ char * get_term_stringparm(char *capability, long arg1, long arg2) { char *parm; initialize_terminfo(); if (termstatus == -1) return NULL; termcbufp = termcbuf; parm = tigetstr(capability); if (parm == (char *) -1 || parm == NULL) { return NULL; } parm = tparm(parm, arg1, arg2, 0, 0, 0, 0, 0, 0, 0); tputs(parm, 1, termbytes); *termcbufp = '\0'; return termcbuf; } /* * Return the value of the specified numeric capability */ int get_term_numcap(char *capability) { initialize_terminfo(); if (termstatus == -1) return -1; return tigetnum(capability); } /* * Store a sequence of characters in our local buffer */ static int termbytes(TPUTS_PUTC_ARG c) { size_t offset; /* * Bump up the buffer size if we've reached the end (leave room for * a trailing NUL) */ if ((offset = termcbufp - termcbuf) - 1 >= termcbufsz) { termcbufsz += 64; termcbuf = mh_xrealloc(termcbuf, termcbufsz); termcbufp = termcbuf + offset; } *termcbufp++ = c; return 0; } nmh-1.7.1-RC3/sbr/trimcpy.c000644 007761 000024 00000004330 13243042053 015377 0ustar00kenhstaff000000 000000 /* trimcpy.c -- strip leading and trailing whitespace, * -- replace internal whitespace with spaces, * -- then return a copy. * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include char * trimcpy (char *cp) { char *sp; /* skip over leading whitespace */ while (isspace((unsigned char) *cp)) cp++; /* start at the end and zap trailing whitespace */ for (sp = cp + strlen(cp) - 1; sp >= cp; sp--) { if (isspace((unsigned char) *sp)) *sp = '\0'; else break; } /* replace remaining whitespace with spaces */ for (sp = cp; *sp; sp++) { if (isspace((unsigned char) *sp)) *sp = ' '; } /* now return a copy */ return mh_xstrdup(cp); } /* * cpytrim() -- return a copy of the argument with: * -- stripped leading and trailing whitespace, and * -- internal whitespace replaced with spaces. * * 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. */ char * cpytrim (const char *sp) { char *dp; char *cp; /* skip over leading whitespace */ while (isspace ((unsigned char) *sp)) ++sp; dp = mh_xstrdup(sp); /* start at the end and zap trailing whitespace */ for (cp = dp + strlen (dp) - 1; cp >= dp && isspace ((unsigned char) *cp); *cp-- = '\0') continue; /* replace remaining whitespace with spaces */ for (cp = dp; *cp; ++cp) { if (isspace ((unsigned char) *cp)) *cp = ' '; } return dp; } /* * rtrim() -- modify the argument to: * -- strip trailing whitespace * * This code is Copyright (c) 2014, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ char * rtrim (char *sp) { char *cp; /* start at the end and zap trailing whitespace */ for (cp = sp + strlen (sp) - 1; cp >= sp && isspace ((unsigned char) *cp); --cp) { continue; } *++cp = '\0'; return sp; } nmh-1.7.1-RC3/sbr/unquote.c000644 007761 000024 00000001715 13243042053 015414 0ustar00kenhstaff000000 000000 /* unquote.c -- Handle quote removal and quoted-pair strings on * RFC 2822-5322 atoms. * * 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 #include "unquote.h" /* * Remove quotes (and handle escape strings) from RFC 5322 quoted-strings. * * Since we never add characters to the string, the output buffer is assumed * to have at least as many characters as the input string. * */ void unquote_string(const char *input, char *output) { int n = 0; /* n is the position in the input buffer */ int m = 0; /* m is the position in the output buffer */ while ( input[n] != '\0') { switch ( input[n] ) { case '\\': n++; if ( input[n] != '\0') output[m++] = input[n++]; break; case '"': n++; break; default: output[m++] = input[n++]; break; } } output[m] = '\0'; } nmh-1.7.1-RC3/sbr/unquote.h000644 007761 000024 00000001532 13205305704 015421 0ustar00kenhstaff000000 000000 /* unquote.h -- Handle quote removal and quoted-pair strings on * RFC 2822-5322 atoms. * * This code is Copyright (c) 2017, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ /* Remove quotes and quoted-pair sequences from RFC-5322 atoms. * * Currently the actual algorithm is simpler than it technically should * be: any quotes are simply eaten, unless they're preceded by the escape * character (\). This seems to be sufficient for our needs for now. * * Arguments: * * input - The input string * output - The output string; is assumed to have at least as much * room as the input string. At worst the output string * will be the same size as the input string; it might be * smaller. */ void unquote_string(const char *input, char *output); nmh-1.7.1-RC3/sbr/uprf.c000644 007761 000024 00000001213 13243042053 014661 0ustar00kenhstaff000000 000000 /* uprf.c -- "unsigned" lexical prefix * * 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 /* uprf returns true if s starts with prefix, ignoring case. * Otherwise false. If s or prefix are NULL then false results. */ int uprf(const char *s, const char *prefix) { unsigned char *us, *up; if (!s || !prefix) return 0; us = (unsigned char *)s; up = (unsigned char *)prefix; while (*us && tolower(*us) == tolower(*up)) { us++; up++; } return *up == '\0'; } nmh-1.7.1-RC3/sbr/utils.c000644 007761 000024 00000035421 13243042053 015055 0ustar00kenhstaff000000 000000 /* utils.c -- various utility routines * * This code is Copyright (c) 2006, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #include #include "m_mktemp.h" #include "makedir.h" #include #include extern char *mhdocdir; /* plurals gives the letter ess to indicate a plural noun, or an empty * string as plurals+1 for the singular noun. Used by the PLURALS * macro. */ const char plurals[] = "s"; /* * We allocate space for messages (msgs array) * this number of elements at a time. */ #define MAXMSGS 256 /* Call malloc(3), exiting on NULL return. */ void *mh_xmalloc(size_t size) { void *p; if (size == 0) size = 1; /* Some mallocs don't like 0. */ p = malloc(size); if (!p) adios(NULL, "malloc failed, size wanted: %zu", size); return p; } /* Call realloc(3), exiting on NULL return. */ void *mh_xrealloc(void *ptr, size_t size) { void *new; /* Copy POSIX behaviour, coping with non-POSIX systems. */ if (size == 0) { mh_xfree(ptr); return mh_xmalloc(1); /* Get a unique pointer. */ } if (!ptr) return mh_xmalloc(size); new = realloc(ptr, size); if (!new) adios(NULL, "realloc failed, size wanted: %zu", size); return new; } /* Call calloc(3), exiting on NULL return. */ void *mh_xcalloc(size_t nelem, size_t elsize) { void *p; if (!nelem || !elsize) return mh_xmalloc(1); /* Get a unique pointer. */ p = calloc(nelem, elsize); if (!p) adios(NULL, "calloc failed, size wanted: %zu * %zu", nelem, elsize); return p; } /* Duplicate a NUL-terminated string, exit on failure. */ char *mh_xstrdup(const char *src) { size_t n; char *dest; n = strlen(src) + 1; /* Ignore possibility of overflow. */ dest = mh_xmalloc(n); memcpy(dest, src, n); return dest; } /* Call free(3), if ptr isn't NULL. */ void mh_xfree(void *ptr) { if (ptr) free(ptr); /* Some very old platforms can't cope with NULL. */ } /* * Return the present working directory, if the current directory does not * exist, or is too long, make / the pwd. */ char * pwd(void) { char *cp; static char curwd[PATH_MAX]; if (!getcwd (curwd, PATH_MAX)) { inform("unable to determine working directory, continuing..."); if (!mypath || !*mypath || (strcpy (curwd, mypath), chdir (curwd)) == -1) { strcpy (curwd, "/"); if (chdir (curwd) < 0) { advise (curwd, "chdir"); } } return curwd; } if ((cp = curwd + strlen (curwd) - 1) > curwd && *cp == '/') *cp = '\0'; return curwd; } /* * add -- If "s1" is NULL, this routine just creates a * -- copy of "s2" into newly malloc'ed memory. * -- * -- If "s1" is not NULL, then copy the concatenation * -- of "s1" and "s2" (note the order) into newly * -- malloc'ed memory. Then free "s1". */ char * add (const char *s2, char *s1) { char *cp; size_t len1 = 0, len2 = 0; if (s1) len1 = strlen (s1); if (s2) len2 = strlen (s2); cp = mh_xmalloc (len1 + len2 + 1); /* Copy s1 and free it */ if (s1) { memcpy (cp, s1, len1); free (s1); } /* Copy s2 */ if (s2) memcpy (cp + len1, s2, len2); /* Now NULL terminate the string */ cp[len1 + len2] = '\0'; return cp; } /* * addlist * Append an item to a comma separated list */ char * addlist (char *list, const char *item) { if (list) list = add (", ", list); return add (item, list); } /* * folder_exists * Check to see if a folder exists. */ int folder_exists(const char *folder) { struct stat st; return stat(folder, &st) != -1; } /* * create_folder * Check to see if a folder exists, if not, prompt the user to create * it. */ void create_folder(char *folder, int autocreate, void (*done_callback)(int)) { struct stat st; extern int errno; char *cp; if (stat (folder, &st) == -1) { if (errno != ENOENT) adios (folder, "error on folder"); if (autocreate == 0) { /* ask before creating folder */ cp = concat ("Create folder \"", folder, "\"? ", NULL); if (!read_yes_or_no_if_tty (cp)) done_callback (1); free (cp); } else if (autocreate == -1) { /* do not create, so exit */ done_callback (1); } if (!makedir (folder)) adios (NULL, "unable to create folder %s", folder); } } /* * num_digits * Return the number of digits in a nonnegative integer. */ int num_digits (int n) { int ndigits = 0; /* Sanity check */ if (n < 0) adios (NULL, "oops, num_digits called with negative value"); if (n == 0) return 1; while (n) { n /= 10; ndigits++; } return ndigits; } /* * Append a message arg to an array of them, resizing it if necessary. * Really a simple vector-of-(char *) maintenance routine. */ void app_msgarg(struct msgs_array *msgs, char *cp) { if(msgs->size >= msgs->max) { msgs->max += MAXMSGS; msgs->msgs = mh_xrealloc(msgs->msgs, msgs->max * sizeof(*msgs->msgs)); } msgs->msgs[msgs->size++] = cp; } /* * Append a message number to an array of them, resizing it if necessary. * Like app_msgarg, but with a vector-of-ints instead. */ void app_msgnum(struct msgnum_array *msgs, int msgnum) { if (msgs->size >= msgs->max) { msgs->max += MAXMSGS; msgs->msgnums = mh_xrealloc(msgs->msgnums, msgs->max * sizeof(*msgs->msgnums)); } msgs->msgnums[msgs->size++] = msgnum; } /* * Finds first occurrence of str in buf. buf is not a C string but a * byte array of length buflen. str is a null-terminated C string. * find_str() does not modify buf but passes back a non-const char * * pointer so that the caller can modify it. */ char * find_str (const char buf[], size_t buflen, const char *str) { const size_t len = strlen (str); size_t i; for (i = 0; i + len <= buflen; ++i, ++buf) { if (! memcmp (buf, str, len)) return (char *) buf; } return NULL; } /* * Finds last occurrence of str in buf. buf is not a C string but a * byte array of length buflen. str is a null-terminated C string. * find_str() does not modify buf but passes back a non-const char * * pointer so that the caller can modify it. */ char * rfind_str (const char buf[], size_t buflen, const char *str) { const size_t len = strlen (str); size_t i; for (i = 0, buf += buflen - len; i + len <= buflen; ++i, --buf) { if (! memcmp (buf, str, len)) return (char *) buf; } return NULL; } /* POSIX doesn't have strcasestr() so emulate it. */ char * nmh_strcasestr (const char *s1, const char *s2) { const size_t len = strlen (s2); if (isupper ((unsigned char) s2[0]) || islower ((unsigned char)s2[0])) { char first[3]; first[0] = (char) toupper ((unsigned char) s2[0]); first[1] = (char) tolower ((unsigned char) s2[0]); first[2] = '\0'; for (s1 = strpbrk (s1, first); s1; s1 = strpbrk (++s1, first)) { if (! strncasecmp (s1, s2, len)) return (char *) s1; } } else { for (s1 = strchr (s1, s2[0]); s1; s1 = strchr (++s1, s2[0])) { if (! strncasecmp (s1, s2, len)) return (char *) s1; } } return NULL; } /* truncpy copies at most size - 1 chars from non-NULL src to non-NULL, * non-overlapping, dst, and ensures dst is NUL terminated. If size is * zero then it aborts as dst cannot be NUL terminated. * * It's to be used when truncation is intended and correct, e.g. * reporting a possibly very long external string back to the user. One * of its advantages over strncpy(3) is it doesn't pad in the common * case of no truncation. */ void trunccpy(char *dst, const char *src, size_t size) { if (!size) { inform("trunccpy: zero-length destination: \"%.20s\"", src ? src : "null"); abort(); } if (strnlen(src, size) < size) { strcpy(dst, src); } else { memcpy(dst, src, size - 1); dst[size - 1] = '\0'; } } /* has_prefix returns true if non-NULL s starts with non-NULL prefix. */ bool has_prefix(const char *s, const char *prefix) { while (*s && *s == *prefix) { s++; prefix++; } return *prefix == '\0'; } /* has_suffix returns true if non-NULL s ends with non-NULL suffix. */ bool has_suffix(const char *s, const char *suffix) { size_t ls, lsuf; ls = strlen(s); lsuf = strlen(suffix); return lsuf <= ls && !strcmp(s + ls - lsuf, suffix); } /* has_suffix_c returns true if non-NULL string s ends with a c before the * terminating NUL. */ bool has_suffix_c(const char *s, int c) { return *s && s[strlen(s) - 1] == c; } /* trim_suffix_c deletes c from the end of non-NULL string s if it's * present, shortening s by 1. Only one instance of c is removed. */ void trim_suffix_c(char *s, int c) { if (!*s) return; s += strlen(s) - 1; if (*s == c) *s = '\0'; } /* to_lower runs all of s through tolower(3). */ void to_lower(char *s) { unsigned char *b; for (b = (unsigned char *)s; (*b = tolower(*b)); b++) ; } /* to_upper runs all of s through toupper(3). */ void to_upper(char *s) { unsigned char *b; for (b = (unsigned char *)s; (*b = toupper(*b)); b++) ; } int nmh_init(const char *argv0, int read_context) { int status = OK; char *locale; invo_name = r1bindex ((char *) argv0, '/'); if (setup_signal_handlers()) { admonish("sigaction", "unable to set up signal handlers"); } /* POSIX atexit() does not define any error conditions. */ if (atexit(remove_registered_files_atexit)) { admonish("atexit", "unable to register atexit function"); } /* Read context, if supposed to. */ if (read_context) { int allow_version_check = 1; int check_older_version = 0; char *cp; context_read(); if (read_context != 1 || ((cp = context_find ("Welcome")) && strcasecmp (cp, "disable") == 0)) { allow_version_check = 0; } else if ((cp = getenv ("MHCONTEXT")) != NULL && *cp != '\0') { /* Context file comes from $MHCONTEXT, so only print the message if the context file has an older version. If it does, or if it doesn't have a version at all, update the version. */ check_older_version = 1; } /* Check to see if the user is running a different (or older, if specified) version of nmh than they had run before, and notify them if so. But only if read_context was set to a value to enable. */ if (allow_version_check && isatty (fileno (stdin)) && isatty (fileno (stdout)) && isatty (fileno (stderr))) { if (nmh_version_changed (check_older_version)) { printf ("===================================================" "=====================\n"); printf ("Welcome to nmh version %s\n\n", VERSION); printf ("See the release notes in %s/NEWS\n\n", mhdocdir); print_intro (stdout, 1); printf ("\nThis message will not be repeated until " "nmh is next updated.\n"); printf ("===================================================" "=====================\n\n"); fputs ("Press enter to continue: ", stdout); (void) read_line (); putchar ('\n'); } } } else { if ((status = context_foil(NULL)) != OK) { advise("", "failed to create minimal profile/context"); } } /* Allow the user to set a locale in their profile. Otherwise, use the "" string to pull it from their environment, see setlocale(3). */ if ((locale = context_find ("locale")) == NULL) { locale = ""; } if (! setlocale (LC_ALL, locale)) { inform("setlocale failed, check your LC_ALL, LC_CTYPE, and LANG " "environment variables, continuing..."); } return status; } /* * Check stored version, and return 1 if out-of-date or non-existent. * Because the output of "mhparam version" is prefixed with "nmh-", * use that prefix here. */ int nmh_version_changed (int older) { const char *const context_version = context_find("Version"); if (older) { /* Convert the version strings to floats and compare them. This will break for versions with multiple decimal points, etc. */ const float current_version = strtof (VERSION, NULL); const float old_version = context_version && has_prefix(context_version, "nmh-") ? strtof (context_version + 4, NULL) : 99999999; if (context_version == NULL || old_version < current_version) { context_replace ("Version", "nmh-" VERSION); } return old_version < current_version; } if (context_version == NULL || strcmp(context_version, "nmh-" VERSION) != 0) { context_replace ("Version", "nmh-" VERSION); return 1; } return 0; } /* * Scan for any 8-bit characters. Return 1 if they exist. * * Scan up until the given endpoint (but not the actual endpoint itself). * If the endpoint is NULL, scan until a '\0' is reached. */ int contains8bit(const char *start, const char *end) { if (! start) return 0; while (*start != '\0' && (!end || (start < end))) if (! isascii((unsigned char) *start++)) return 1; return 0; } /* * See if input has any 8-bit bytes. */ int scan_input (int fd, int *eightbit) { int state; char buf[BUFSIZ]; *eightbit = 0; lseek(fd, 0, SEEK_SET); while ((state = read (fd, buf, sizeof buf)) > 0) { if (contains8bit (buf, buf + state)) { *eightbit = 1; return OK; } } return state == NOTOK ? NOTOK : OK; } /* * Convert an int to a char string. */ char * m_str(int value) { return m_strn(value, 0); } /* * Convert an int to a char string, of limited width if > 0. */ #define STR(s) #s /* SIZE(n) includes NUL. n must just be digits, not an equation. */ #define SIZE(n) (sizeof STR(n)) char * m_strn(int value, unsigned int width) { /* Need to include space for negative sign. But don't use INT_MIN because it could be a macro that would fool SIZE(n). */ static char buffer[SIZE(-INT_MAX)]; const int num_chars = snprintf(buffer, sizeof buffer, "%d", value); return num_chars > 0 && (width == 0 || (unsigned int) num_chars <= width) ? buffer : "?"; } nmh-1.7.1-RC3/sbr/vector.c000644 007761 000024 00000015720 13243042053 015217 0ustar00kenhstaff000000 000000 /* vector.c -- dynamically sized vectors * * 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. */ /* * This file defines several kinds of vectors: * bvector: bit vector * svector: vector of char arrays * ivector: vector of ints * * The interfaces provide only the capabilities needed by nmh. The * implementations rely on dynamic allocation, so that a vector * can be as large as needed, as long as it fits in (virtual) memory. */ #include #include /* The default size of a struct bvector's bits, measured in bits. * The struct's tiny member is used for storage. */ #define BVEC_INIT_SIZE (sizeof *(((bvector_t)NULL)->tiny) * CHAR_BIT) /* The default number of char pointers in a struct svector. */ #define SVEC_INIT_SIZE 256 /* The default number of ints in a struct ivector. */ #define IVEC_INIT_SIZE 256 /* * These try to hide the type of the "bits" member of bvector. But if * that is changed to a type that's wider than unsigned long, the 1ul * constants in the code below must also be changed to a 1 that's at * least as wide as the new type. */ /* The *sizeof* struct bvector's bits member. Not its size in bits. */ #define BVEC_SIZEOF_BITS (sizeof *(((bvector_t)NULL)->bits)) /* The number of bits held in one element of the bits member. */ #define BVEC_BITS_BITS (BVEC_SIZEOF_BITS * CHAR_BIT) /* The index of bit n in struct bvector's bits member. */ #define BVEC_WORD(n) ((n) / BVEC_BITS_BITS) /* The index of bit n within a single struct bvector's bits member. */ #define BVEC_OFFSET(n) ((n) % BVEC_BITS_BITS) /* The number of elements bits needs to cover bit n, measured in bytes. */ #define BVEC_BYTES(n) (((n) / BVEC_BITS_BITS + 1) * BVEC_SIZEOF_BITS) /* bvector_resize ensures the storage used for bits can cover bit * newsize. It always increases the size of the storage used for bits, * even if newsize would have been covered by the existing storage. * Thus it's normally only called when it's known the storage must grow. */ static void bvector_resize (bvector_t vec, size_t newsize); bvector_t bvector_create (void) { bvector_t vec; /* See "wider than unsigned long" comment above. */ assert (sizeof *vec->bits <= sizeof 1ul); NEW(vec); bvector_init(vec); return vec; } void bvector_init(struct bvector *bv) { bv->bits = bv->tiny; bv->maxsize = BVEC_INIT_SIZE; memset(bv->tiny, 0, sizeof bv->tiny); } void bvector_copy (bvector_t dest, bvector_t src) { size_t bytes = BVEC_BYTES(src->maxsize); if (dest->bits != dest->tiny) free(dest->bits); if (bytes <= sizeof dest->tiny) dest->bits = dest->tiny; else dest->bits = mh_xmalloc (bytes); memcpy (dest->bits, src->bits, bytes); dest->maxsize = src->maxsize; } void bvector_free (bvector_t vec) { bvector_fini(vec); free (vec); } void bvector_fini(struct bvector *bv) { if (bv->bits != bv->tiny) free(bv->bits); } void bvector_clear (bvector_t vec, size_t n) { if (n < vec->maxsize) vec->bits[BVEC_WORD(n)] &= ~(1ul << BVEC_OFFSET(n)); } void bvector_clear_all (bvector_t vec) { memset (vec->bits, 0, BVEC_BYTES(vec->maxsize)); } void bvector_set (bvector_t vec, size_t n) { size_t word = BVEC_WORD(n); size_t offset = BVEC_OFFSET(n); if (n >= vec->maxsize) bvector_resize (vec, n); vec->bits[word] |= 1ul << offset; } unsigned int bvector_at (bvector_t vec, size_t i) { if (i < vec->maxsize) return !!(vec->bits[BVEC_WORD(i)] & (1ul << BVEC_OFFSET(i))); return 0; } static void bvector_resize (bvector_t vec, size_t newsize) { size_t oldsize = vec->maxsize; size_t bytes; while ((vec->maxsize *= 2) < newsize) ; bytes = BVEC_BYTES(vec->maxsize); if (vec->bits == vec->tiny) { vec->bits = mh_xmalloc(bytes); memcpy(vec->bits, vec->tiny, sizeof vec->tiny); } else vec->bits = mh_xrealloc(vec->bits, bytes); memset(vec->bits + (oldsize / BVEC_BITS_BITS), 0, (vec->maxsize - oldsize) / CHAR_BIT); } unsigned long bvector_first_bits (bvector_t vec) { return *vec->bits; } struct svector { char **strs; size_t maxsize; size_t size; }; static void svector_resize (svector_t, size_t); svector_t svector_create (size_t init_size) { svector_t vec; size_t bytes; NEW(vec); vec->maxsize = init_size ? init_size : SVEC_INIT_SIZE; bytes = vec->maxsize * sizeof (char *); vec->strs = mh_xcalloc (1, bytes); vec->size = 0; return vec; } void svector_free (svector_t vec) { free (vec->strs); free (vec); } char * svector_push_back (svector_t vec, char *s) { if (++vec->size >= vec->maxsize) svector_resize (vec, vec->size); return vec->strs[vec->size-1] = s; } char * svector_at (svector_t vec, size_t i) { if (i >= vec->maxsize) svector_resize (vec, i); return vec->strs[i]; } /* * Return address of first element that stringwise matches s. * The caller can replace the contents of the return address. */ char ** svector_find (svector_t vec, const char *s) { size_t i; char **str = vec->strs; for (i = 0; i < vec->size; ++i, ++str) { if (*str && ! strcmp(*str, s)) { return str; } } return NULL; } char ** svector_strs (svector_t vec) { return vec->strs; } size_t svector_size (svector_t vec) { return vec->size; } static void svector_resize (svector_t vec, size_t maxsize) { size_t old_maxsize = vec->maxsize; while ((vec->maxsize *= 2) < maxsize) ; vec->strs = mh_xrealloc (vec->strs, vec->maxsize * sizeof (char *)); memset(vec->strs + old_maxsize, 0, (vec->maxsize - old_maxsize) * sizeof *vec->strs); } struct ivector { int *ints; size_t maxsize; size_t size; }; static void ivector_resize (ivector_t, size_t); ivector_t ivector_create (size_t init_size) { ivector_t vec; size_t bytes; NEW(vec); vec->maxsize = init_size ? init_size : IVEC_INIT_SIZE; bytes = vec->maxsize * sizeof (int); vec->ints = mh_xcalloc (1, bytes); vec->size = 0; return vec; } void ivector_free (ivector_t vec) { free (vec->ints); free (vec); } int ivector_push_back (ivector_t vec, int n) { if (++vec->size >= vec->maxsize) ivector_resize (vec, vec->size); return vec->ints[vec->size-1] = n; } int ivector_at (ivector_t vec, size_t i) { if (i >= vec->maxsize) ivector_resize (vec, i); return vec->ints[i]; } int * ivector_atp (ivector_t vec, size_t i) { if (i >= vec->maxsize) ivector_resize (vec, i); return &vec->ints[i]; } static void ivector_resize (ivector_t vec, size_t maxsize) { size_t old_maxsize = vec->maxsize; while ((vec->maxsize *= 2) < maxsize) ; vec->ints = mh_xrealloc (vec->ints, vec->maxsize * sizeof (int)); memset(vec->ints + old_maxsize, 0, (vec->maxsize - old_maxsize) * sizeof *vec->ints); } nmh-1.7.1-RC3/sbr/vfgets.c000644 007761 000024 00000002422 13243042053 015206 0ustar00kenhstaff000000 000000 /* vfgets.c -- virtual fgets * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include #define QUOTE '\\' int vfgets (FILE *in, char **bp) { int toggle; char *cp, *dp, *ep, *fp; static int len = 0; static char *pp = NULL; if (pp == NULL) pp = mh_xmalloc ((size_t) (len = BUFSIZ)); for (ep = (cp = pp) + len - 1;;) { if (fgets (cp, ep - cp + 1, in) == NULL) { if (cp != pp) { *bp = pp; return 0; } return (ferror (in) && !feof (in) ? -1 : 1); } if ((dp = cp + strlen (cp) - 2) < cp || *dp != QUOTE) { wrong_guess: if (cp > ++dp) adios (NULL, "vfgets() botch -- you lose big"); if (*dp == '\n') { *bp = pp; return 0; } cp = ++dp; } else { for (fp = dp - 1, toggle = 0; fp >= cp; fp--) { if (*fp != QUOTE) break; else toggle = !toggle; } if (toggle) goto wrong_guess; if (*++dp == '\n') { *--dp = 0; cp = dp; } else { cp = ++dp; } } if (cp >= ep) { int curlen = cp - pp; dp = mh_xrealloc (pp, (size_t) (len += BUFSIZ)); cp = dp + curlen; ep = (pp = dp) + len - 1; } } } nmh-1.7.1-RC3/mts/smtp/000755 007761 000024 00000000000 13243043704 014550 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/mts/smtp/smtp.c000644 007761 000024 00000054624 13243042053 015706 0ustar00kenhstaff000000 000000 /* smtp.c -- nmh SMTP interface * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include "smtp.h" #include #include #include #include #include /* * This module implements an interface to SendMail very similar * to the MMDF mm_(3) routines. The sm_() routines herein talk * SMTP to a sendmail process, mapping SMTP reply codes into * RP_-style codes. */ #define NBITS ((sizeof (int)) * 8) /* Timeout in seconds for SMTP commands. * Lore has it they must be distinct. */ #define SM_OPEN 300 /* Changed to 5 minutes to comply with a SHOULD in RFC 1123 */ #define SM_HELO 20 #define SM_RSET 15 #define SM_MAIL 301 /* changed to 5 minutes and a second (for uniqueness), see above */ #define SM_RCPT 302 /* see above */ #define SM_DATA 120 /* see above */ #define SM_DOT 600 /* see above */ #define SM_QUIT 30 static int sm_addrs = 0; static int sm_child = NOTOK; static int sm_debug = 0; static int sm_nl = TRUE; static int sm_verbose = 0; static netsec_context *nsc = NULL; static char *sm_noreply = "No reply text given"; static char *sm_moreply = "; "; static struct smtp sm_reply; #define MAXEHLO 20 static int doingEHLO; static char *EHLOkeys[MAXEHLO + 1]; /* * static prototypes */ static int smtp_init (char *, char *, char *, int, int, int, int, const char *, const char *, const char *, int); static int sendmail_init (char *, int, int, int, int, const char *, const char *); static int rclient (char *, char *, char **); static int sm_ierror (const char *fmt, ...); static int sm_nerror (char *); static int smtalk (int time, char *fmt, ...); static int sm_wstream (char *, int); static int smhear (void); static char *EHLOset (char *); static int sm_sasl_callback(enum sasl_message_type, unsigned const char *, unsigned int, unsigned char **, unsigned int *, char **); int sm_init (char *client, char *server, char *port, int watch, int verbose, int debug, int sasl, const char *saslmech, const char *user, const char *oauth_svc, int tls) { if (sm_mts == MTS_SMTP) return smtp_init (client, server, port, watch, verbose, debug, sasl, saslmech, user, oauth_svc, tls); return sendmail_init (client, watch, verbose, debug, sasl, saslmech, user); } static int smtp_init (char *client, char *server, char *port, int watch, int verbose, int debug, int sasl, const char *saslmech, const char *user, const char *oauth_svc, int tls) { int result, sd1; char *errstr, *chosen_server; if (watch) verbose = TRUE; sm_verbose = verbose; sm_debug = debug; if (nsc != NULL) goto send_options; if (client == NULL || *client == '\0') { if (clientname) { client = clientname; } else { client = LocalName(1); /* no clientname -> LocalName */ } /* * Last-ditch check just in case client still isn't set to anything */ if (client == NULL || *client == '\0') client = "localhost"; } nsc = netsec_init(); if (user) netsec_set_userid(nsc, user); if ((sd1 = rclient (server, port, &chosen_server)) == NOTOK) return RP_BHST; SIGNAL (SIGPIPE, SIG_IGN); netsec_set_fd(nsc, sd1, sd1); netsec_set_hostname(nsc, chosen_server); if (sm_debug) netsec_set_snoop(nsc, 1); if (sasl) { if (netsec_set_sasl_params(nsc, "smtp", saslmech, sm_sasl_callback, &errstr) != OK) return sm_nerror(errstr); } if (oauth_svc) { if (netsec_set_oauth_service(nsc, oauth_svc) != OK) return sm_ierror("OAuth2 not supported"); } if (tls & S_TLSENABLEMASK) { if (netsec_set_tls(nsc, 1, tls & S_NOVERIFY, &errstr) != OK) return sm_nerror(errstr); } /* * If tls == S_INITTLS, that means that the user requested * "initial" TLS, which happens right after the connection has * opened. Do that negotiation now */ if (tls & S_INITTLS) { if (netsec_negotiate_tls(nsc, &errstr) != OK) { sm_end(NOTOK); return sm_nerror(errstr); } } netsec_set_timeout(nsc, SM_OPEN); result = smhear (); switch (result) { case 220: break; default: sm_end (NOTOK); return RP_RPLY; } /* * Give EHLO or HELO command */ doingEHLO = 1; result = smtalk (SM_HELO, "EHLO %s", client); doingEHLO = 0; if (result >= 500 && result <= 599) result = smtalk (SM_HELO, "HELO %s", client); if (result != 250) { sm_end (NOTOK); return RP_RPLY; } /* * If the user requested TLS support, then try to do the STARTTLS command * as part of the initial dialog. Assuming this works, we then need to * restart the EHLO dialog after TLS negotiation is complete. */ if (tls & S_STARTTLS) { if (! EHLOset("STARTTLS")) { sm_end(NOTOK); return sm_ierror("SMTP server does not support TLS"); } result = smtalk(SM_HELO, "STARTTLS"); if (result != 220) { sm_end(NOTOK); return RP_RPLY; } /* * Okay, the other side should be waiting for us to start TLS * negotiation. Oblige them. */ if (netsec_negotiate_tls(nsc, &errstr) != OK) { sm_end(NOTOK); return sm_nerror(errstr); } doingEHLO = 1; result = smtalk (SM_HELO, "EHLO %s", client); doingEHLO = 0; if (result != 250) { sm_end (NOTOK); return RP_RPLY; } } /* * If the user asked for SASL, then check to see if the SMTP server * supports it. Otherwise, error out (because the SMTP server * might have been spoofed; we don't want to just silently not * do authentication */ if (sasl) { char *server_mechs; if (! (server_mechs = EHLOset("AUTH"))) { sm_end(NOTOK); return sm_ierror("SMTP server does not support SASL"); } if (netsec_negotiate_sasl(nsc, server_mechs, &errstr) != OK) { sm_end(NOTOK); return sm_nerror(errstr); } } send_options: ; if (watch && EHLOset ("XVRB")) smtalk (SM_HELO, "VERB on"); return RP_OK; } int sendmail_init (char *client, int watch, int verbose, int debug, int sasl, const char *saslmech, const char *user) { unsigned int i, result, vecp; int pdi[2], pdo[2]; char *vec[15], *errstr; if (watch) verbose = TRUE; sm_verbose = verbose; sm_debug = debug; if (nsc) return RP_OK; if (client == NULL || *client == '\0') { if (clientname) client = clientname; else client = LocalName(1); /* no clientname -> LocalName */ /* * Last-ditch check just in case client still isn't set to anything */ if (client == NULL || *client == '\0') client = "localhost"; } nsc = netsec_init(); if (user) netsec_set_userid(nsc, user); netsec_set_hostname(nsc, client); if (sm_debug) netsec_set_snoop(nsc, 1); if (sasl) { if (netsec_set_sasl_params(nsc, "smtp", saslmech, sm_sasl_callback, &errstr) != OK) return sm_nerror(errstr); } if (pipe (pdi) == NOTOK) return sm_ierror ("no pipes"); if (pipe (pdo) == NOTOK) { close (pdi[0]); close (pdi[1]); return sm_ierror ("no pipes"); } for (i = 0; (sm_child = fork ()) == NOTOK && i < 5; i++) sleep (5); switch (sm_child) { case NOTOK: close (pdo[0]); close (pdo[1]); close (pdi[0]); close (pdi[1]); return sm_ierror ("unable to fork"); case OK: if (pdo[0] != fileno (stdin)) dup2 (pdo[0], fileno (stdin)); if (pdi[1] != fileno (stdout)) dup2 (pdi[1], fileno (stdout)); if (pdi[1] != fileno (stderr)) dup2 (pdi[1], fileno (stderr)); for (i = fileno (stderr) + 1; i < NBITS; i++) close (i); vecp = 0; vec[vecp++] = r1bindex (sendmail, '/'); vec[vecp++] = "-bs"; vec[vecp++] = watch ? "-odi" : "-odb"; vec[vecp++] = "-oem"; vec[vecp++] = "-om"; if (verbose) vec[vecp++] = "-ov"; vec[vecp++] = NULL; execvp (sendmail, vec); fprintf (stderr, "unable to exec "); perror (sendmail); _exit (-1); /* NOTREACHED */ default: SIGNAL (SIGPIPE, SIG_IGN); close (pdi[1]); close (pdo[0]); netsec_set_fd(nsc, pdi[i], pdo[1]); netsec_set_timeout(nsc, SM_OPEN); result = smhear (); switch (result) { case 220: break; default: sm_end (NOTOK); return RP_RPLY; } doingEHLO = 1; result = smtalk (SM_HELO, "EHLO %s", client); doingEHLO = 0; if (500 <= result && result <= 599) result = smtalk (SM_HELO, "HELO %s", client); switch (result) { case 250: break; default: sm_end (NOTOK); return RP_RPLY; } /* * If the user asked for SASL, then check to see if the SMTP server * supports it. Otherwise, error out (because the SMTP server * might have been spoofed; we don't want to just silently not * do authentication */ if (sasl) { char *server_mechs; if (! (server_mechs = EHLOset("AUTH"))) { sm_end(NOTOK); return sm_ierror("SMTP server does not support SASL"); } if (netsec_negotiate_sasl(nsc, server_mechs, &errstr) != OK) { sm_end(NOTOK); return sm_nerror(errstr); } } if (watch) smtalk (SM_HELO, "VERB on"); return RP_OK; } } static int rclient (char *server, char *service, char **chosen_server) { int sd; char response[BUFSIZ]; if (server == NULL) server = servers; *chosen_server = server; if ((sd = client (server, service, response, sizeof(response), sm_debug)) != NOTOK) return sd; sm_ierror ("%s", response); return NOTOK; } int sm_winit (char *from, int smtputf8, int eightbit) { const char *mail_parameters = ""; if (smtputf8) { /* Just for information, if an attempt is made to send to an 8-bit address without specifying SMTPUTF8, Gmail responds with 555 5.5.2 Syntax error. Gmail doesn't require the 8BITMIME, but RFC 6531 Sec. 1.2 does. */ if (EHLOset ("8BITMIME") && EHLOset ("SMTPUTF8")) { mail_parameters = " BODY=8BITMIME SMTPUTF8"; } else { inform("SMTP server does not support %s, not sending.\n" "Rebuild message with 7-bit headers, WITHOUT -headerencoding utf-8.", EHLOset ("SMTPUTF8") ? "8BITMIME" : "SMTPUTF8"); sm_end (NOTOK); return RP_UCMD; } } else if (eightbit) { /* Comply with RFC 6152, for messages that have any 8-bit characters in their body. */ if (EHLOset ("8BITMIME")) { mail_parameters = " BODY=8BITMIME"; } else { inform("SMTP server does not support 8BITMIME, not sending.\n" "Suggest encoding message for 7-bit transport by setting your\n" "locale to C, and/or specifying *b64 in mhbuild directives."); sm_end (NOTOK); return RP_UCMD; } } switch (smtalk (SM_MAIL, "MAIL FROM:<%s>%s", from, mail_parameters)) { case 250: sm_addrs = 0; return RP_OK; case 500: case 501: case 552: return RP_PARM; default: return RP_RPLY; } } int sm_wadr (char *mbox, char *host, char *path) { switch (smtalk (SM_RCPT, host && *host ? "RCPT TO:<%s%s@%s>" : "RCPT TO:<%s%s>", FENDNULL(path), mbox, host)) { case 250: case 251: sm_addrs++; return RP_OK; case 451: case 421: case 450: case 452: return RP_NO; case 500: case 501: return RP_PARM; case 550: case 551: case 552: case 553: return RP_USER; default: return RP_RPLY; } } int sm_waend (void) { switch (smtalk (SM_DATA, "DATA")) { case 354: sm_nl = TRUE; return RP_OK; case 451: case 421: return RP_NO; case 500: case 501: case 503: case 554: return RP_NDEL; default: return RP_RPLY; } } int sm_wtxt (char *buffer, int len) { int result; result = sm_wstream (buffer, len); return (result == NOTOK ? RP_BHST : RP_OK); } int sm_wtend (void) { if (sm_wstream ((char *) NULL, 0) == NOTOK) return RP_BHST; switch (smtalk (SM_DOT + 3 * sm_addrs, ".")) { case 250: case 251: return RP_OK; case 451: case 452: default: return RP_NO; case 552: case 554: return RP_NDEL; } } int sm_end (int type) { int status; struct smtp sm_note; if (sm_mts == MTS_SENDMAIL_SMTP) { switch (sm_child) { case NOTOK: case OK: return RP_OK; default: break; } } if (nsc == NULL) return RP_OK; switch (type) { case OK: smtalk (SM_QUIT, "QUIT"); break; case NOTOK: sm_note.code = sm_reply.code; sm_note.length = sm_reply.length; memcpy (sm_note.text, sm_reply.text, sm_reply.length + 1); /* FALLTHRU */ case DONE: if (smtalk (SM_RSET, "RSET") == 250 && type == DONE) return RP_OK; 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); sm_child = NOTOK; } if (type == NOTOK) { sm_reply.code = sm_note.code; sm_reply.length = sm_note.length; memcpy (sm_reply.text, sm_note.text, sm_note.length + 1); } break; } if (nsc != NULL) { netsec_shutdown(nsc); nsc = NULL; } if (sm_mts == MTS_SMTP) { status = 0; } else if (sm_child != NOTOK) { status = pidwait (sm_child, OK); sm_child = NOTOK; } else { status = OK; } return (status ? RP_BHST : RP_OK); } static int sm_ierror (const char *fmt, ...) { va_list ap; va_start(ap, fmt); vsnprintf (sm_reply.text, sizeof(sm_reply.text), fmt, ap); va_end(ap); sm_reply.length = strlen (sm_reply.text); sm_reply.code = NOTOK; return RP_BHST; } /* * Like sm_ierror, but assume it's an allocated error string we need to free. */ static int sm_nerror (char *str) { strncpy(sm_reply.text, str, sizeof(sm_reply.text)); sm_reply.text[sizeof(sm_reply.text) - 1] = '\0'; sm_reply.length = strlen(sm_reply.text); sm_reply.code = NOTOK; free(str); return RP_BHST; } static int smtalk (int time, char *fmt, ...) { va_list ap; char *errstr; int result; va_start(ap, fmt); result = netsec_vprintf (nsc, &errstr, fmt, ap); va_end(ap); if (result != OK) return sm_nerror(errstr); if (netsec_printf (nsc, &errstr, "\r\n") != OK) return sm_nerror(errstr); if (netsec_flush (nsc, &errstr) != OK) return sm_nerror(errstr); netsec_set_timeout(nsc, time); return smhear (); } static int sm_wstream (char *buffer, int len) { char *bp, *errstr; static char lc = '\0'; int rc; if (nsc == NULL) { sm_ierror("No socket opened"); return NOTOK; } if (buffer == NULL && len == 0) { rc = OK; if (lc != '\n') rc = netsec_write(nsc, "\r\n", 2, &errstr); lc = '\0'; if (rc != OK) sm_nerror(errstr); return rc; } for (bp = buffer; bp && len > 0; bp++, len--) { switch (*bp) { case '\n': sm_nl = TRUE; if (netsec_write(nsc, "\r", 1, &errstr) != OK) { sm_nerror(errstr); return NOTOK; } break; case '.': if (sm_nl) if (netsec_write(nsc, ".", 1, &errstr) != OK) { sm_nerror(errstr); return NOTOK; } /* FALLTHRU */ default: sm_nl = FALSE; } if (netsec_write(nsc, bp, 1, &errstr) != OK) { sm_nerror(errstr); return NOTOK; } } if (bp > buffer) lc = *--bp; return OK; } static int smhear (void) { int i, code, cont, more; size_t buflen, rc; unsigned char *bp; char *rp; char *errstr; char **ehlo = EHLOkeys, *buffer; if (doingEHLO) { static int at_least_once = 0; if (at_least_once) { char *ep; for (ehlo = EHLOkeys; *ehlo; ehlo++) { ep = *ehlo; free (ep); } } else { at_least_once = 1; } ehlo = EHLOkeys; *ehlo = NULL; } again: ; sm_reply.length = 0; sm_reply.text[0] = 0; rp = sm_reply.text; rc = sizeof(sm_reply.text) - 1; for (more = FALSE; (buffer = netsec_readline(nsc, &buflen, &errstr)) != NULL ; ) { if (doingEHLO && has_prefix(buffer, "250") && (buffer[3] == '-' || doingEHLO == 2) && buffer[4]) { if (doingEHLO == 2) { if ((*ehlo = malloc ((size_t) (strlen (buffer + 4) + 1)))) { strcpy (*ehlo++, buffer + 4); *ehlo = NULL; if (ehlo >= EHLOkeys + MAXEHLO) doingEHLO = 0; } else doingEHLO = 0; } else doingEHLO = 2; } bp = (unsigned char *) buffer; for (; buflen > 0 && (!isascii (*bp) || !isdigit (*bp)); bp++, buflen--) continue; cont = FALSE; code = atoi ((char *) bp); bp += 3, buflen -= 3; for (; buflen > 0 && isspace (*bp); bp++, buflen--) continue; if (buflen > 0 && *bp == '-') { cont = TRUE; bp++, buflen--; for (; buflen > 0 && isspace (*bp); bp++, buflen--) continue; } if (more) { if (code != sm_reply.code || cont) continue; more = FALSE; } else { sm_reply.code = code; more = cont; if (buflen <= 0) { bp = (unsigned char *) sm_noreply; buflen = strlen (sm_noreply); } } if ((i = min (buflen, rc)) > 0) { memcpy (rp, bp, i); rp += i; rc -= i; i = strlen(sm_moreply); if (more && (int) rc > i + 1) { memcpy (rp, sm_moreply, i); /* safe because of check in if() */ rp += i; rc -= i; } } if (more) continue; if (sm_reply.code < 100) { if (sm_verbose) { puts(sm_reply.text); fflush (stdout); } goto again; } sm_reply.length = rp - sm_reply.text; sm_reply.text[sm_reply.length] = 0; return sm_reply.code; } sm_nerror(errstr); return NOTOK; } char * rp_string (int code) { char *text; /* The additional space is to avoid warning from gcc -Wformat-truncation. */ static char buffer[BUFSIZ + 19]; switch (sm_reply.code != NOTOK ? code : NOTOK) { case RP_AOK: text = "AOK"; break; case RP_MOK: text = "MOK"; break; case RP_OK: text = "OK"; break; case RP_RPLY: text = "RPLY"; break; case RP_BHST: default: text = "BHST"; snprintf (buffer, sizeof(buffer), "[%s] %s", text, sm_reply.text); return buffer; case RP_PARM: text = "PARM"; break; case RP_NO: text = "NO"; break; case RP_USER: text = "USER"; break; case RP_NDEL: text = "NDEL"; break; } snprintf (buffer, sizeof(buffer), "[%s] %3d %s", text, sm_reply.code, sm_reply.text); return buffer; } static char * EHLOset (char *s) { size_t len; char *ep, **ehlo; len = strlen (s); for (ehlo = EHLOkeys; *ehlo; ehlo++) { ep = *ehlo; if (has_prefix(ep, s)) { for (ep += len; *ep == ' '; ep++) continue; return ep; } } return 0; } /* * Our SASL callback; we are either given SASL tokens to generate network * protocols messages for, or we decode incoming protocol messages and * convert them to binary SASL tokens to pass up into the SASL library. */ static int sm_sasl_callback(enum sasl_message_type mtype, unsigned const char *indata, unsigned int indatalen, unsigned char **outdata, unsigned int *outdatalen, char **errstr) { int rc, snoopoffset; char *mech, *line; size_t len; switch (mtype) { case NETSEC_SASL_START: /* * Generate an AUTH message; if we were given an input token * then generate a an AUTH message that includes the initial * response. */ mech = netsec_get_sasl_mechanism(nsc); if (indatalen) { char *b64data; b64data = mh_xmalloc(BASE64SIZE(indatalen)); writeBase64raw(indata, indatalen, (unsigned char *) b64data); netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, &snoopoffset); snoopoffset = 6 + strlen(mech); rc = netsec_printf(nsc, errstr, "AUTH %s %s\r\n", mech, b64data); free(b64data); netsec_set_snoop_callback(nsc, NULL, NULL); } else { rc = netsec_printf(nsc, errstr, "AUTH %s\r\n", mech); } if (rc != OK) return NOTOK; if (netsec_flush(nsc, errstr) != OK) return NOTOK; break; case NETSEC_SASL_READ: /* * Read in a line that should contain a 334 response code, followed * by base64 response data. */ netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, &snoopoffset); snoopoffset = 4; line = netsec_readline(nsc, &len, errstr); netsec_set_snoop_callback(nsc, NULL, NULL); if (line == NULL) return NOTOK; if (len < 4) { netsec_err(errstr, "Invalid format for SASL response"); return NOTOK; } if (!has_prefix(line, "334 ")) { netsec_err(errstr, "Improper SASL protocol response: %s", line); return NOTOK; } if (len == 4) { *outdata = NULL; *outdatalen = 0; } else { rc = decodeBase64(line + 4, outdata, &len, 0, NULL); if (rc != OK) { netsec_err(errstr, "Unable to decode base64 response"); return NOTOK; } *outdatalen = len; } break; case NETSEC_SASL_WRITE: /* * The output encoding is pretty simple, so this is easy. */ if (indatalen == 0) { rc = netsec_printf(nsc, errstr, "\r\n"); } else { unsigned char *b64data; b64data = mh_xmalloc(BASE64SIZE(indatalen)); writeBase64raw(indata, indatalen, b64data); netsec_set_snoop_callback(nsc, netsec_b64_snoop_decoder, NULL); rc = netsec_printf(nsc, errstr, "%s\r\n", b64data); netsec_set_snoop_callback(nsc, NULL, NULL); free(b64data); } if (rc != OK) return NOTOK; if (netsec_flush(nsc, errstr) != OK) return NOTOK; break; case NETSEC_SASL_FINISH: /* * Finish the protocol; we're looking for a 235 message. */ line = netsec_readline(nsc, &len, errstr); if (line == NULL) return NOTOK; if (!has_prefix(line, "235 ")) { if (len > 4) netsec_err(errstr, "Authentication failed: %s", line + 4); else netsec_err(errstr, "Authentication failed: %s", line); return NOTOK; } break; case NETSEC_SASL_CANCEL: /* * Cancel the SASL exchange; this is done by sending a single "*". */ rc = netsec_printf(nsc, errstr, "*\r\n"); if (rc == OK) rc = netsec_flush(nsc, errstr); if (rc != OK) return NOTOK; break; } return OK; } nmh-1.7.1-RC3/mts/smtp/smtp.h000644 007761 000024 00000011241 13205305704 015702 0ustar00kenhstaff000000 000000 /* smtp.h -- definitions for the nmh SMTP Interface */ /* length is the length of the string in text[], which is also NUL * terminated, so s.text[s.length] should always be 0. */ struct smtp { int code; int length; char text[BUFSIZ]; }; /* * prototypes */ /* int client (); */ /* TLS flags */ #define S_STARTTLS 0x01 #define S_INITTLS 0x02 #define S_TLSENABLEMASK 0x03 #define S_NOVERIFY 0x04 int sm_init (char *, char *, char *, int, int, int, int, const char *, const char *, const char *, int); int sm_winit (char *, int, int); int sm_wadr (char *, char *, char *); int sm_waend (void); int sm_wtxt (char *, int); int sm_wtend (void); int sm_end (int); char *rp_string (int); /* The remainder of this file is derived from "mmdf.h" */ /* * Copyright (C) 1979,1980,1981,1982,1983 University of Delaware * Used by permission, May, 1984. */ /* * MULTI-CHANNEL MEMO DISTRIBUTION FACILITY (MMDF) * * * Copyright (C) 1979,1980,1981,1982,1983 University of Delaware * * Department of Electrical Engineering * University of Delaware * Newark, Delaware 19711 * * Phone: (302) 738-1163 * * * This program module was developed as part of the University * of Delaware's Multi-Channel Memo Distribution Facility (MMDF). * * Acquisition, use, and distribution of this module and its listings * are subject restricted to the terms of a license agreement. * Documents describing systems using this module must cite its source. * * The above statements must be retained with all copies of this * program and may not be removed without the consent of the * University of Delaware. * */ /* Reply Codes for MMDF * * Based on: "Revised FTP Reply Codes", by Jon Postel & Nancy Neigus Arpanet * RFC 640 / NIC 30843, in the "Arpanet Protocol Handbook", E. Feinler * and J. Postel (eds.), NIC 7104, Network Information Center, SRI * International: Menlo Park, CA. (NTIS AD-A0038901) * * Actual values are different, but scheme is same. Codes must fit into * 8-bits (to pass on exit() calls); fields are packed 2-3-3 and interpreted * as octal numbers. * * Basic format: * * 0yz: positive completion; entire action done * 1yz: positive intermediate; only part done * 2yz: Transient negative completion; may work later * 3yz: Permanent negative completion; you lose forever * * x0z: syntax * x1z: general; doesn't fit any other category * x2z: connections; truly transfer-related * x3z: user/authentication/account * x4x: mail * x5z: file system * * 3-bit z field is unique to the reply. In the following, * the RP_xVAL defines are available for masking to obtain a field. */ /* * FIELD DEFINITIONS & BASIC VALUES */ /* FIELD 1: Basic degree of success (2-bits) */ #define RP_BOK '\000' /* went fine; all done */ #define RP_BPOK '\100' /* only the first part got done */ #define RP_BTNO '\200' /* temporary failure; try later */ #define RP_BNO '\300' /* not now, nor never; you lose */ /* FIELD 2: Basic domain of discourse (3-bits) */ #define RP_CSYN '\000' /* purely a matter of form */ #define RP_CGEN '\010' /* couldn't find anywhere else for it */ #define RP_CCON '\020' /* data-transfer-related issue */ #define RP_CUSR '\030' /* pertaining to the user */ #define RP_CMAI '\040' /* specific to mail semantics */ /* * SPECIFIC SUCCESS VALUES */ /* * Complete Success */ /* general-purpose OK */ #define RP_OK (RP_BOK | RP_CGEN | '\001') /* message is accepted (w/text) */ #define RP_MOK (RP_BOK | RP_CMAI | '\000') /* * Partial Success */ /* message address is accepted */ #define RP_AOK (RP_BPOK| RP_CMAI | '\000') /* * SPECIFIC FAILURE VALUES */ /* * Partial Failure */ /* foreign host screwed up */ #define RP_BHST (RP_BTNO | RP_CCON | '\001') /* * Complete Failure */ /* general-purpose NO */ #define RP_NO (RP_BNO | RP_CGEN | '\001') /* bad reply code (PERMANENT ERROR) */ #define RP_RPLY (RP_BNO | RP_CCON | '\001') /* couldn't deliver */ #define RP_NDEL (RP_BNO | RP_CMAI | '\000') /* bad parameter */ #define RP_PARM (RP_BNO | RP_CSYN | '\002') /* command not implemented */ #define RP_UCMD (RP_BNO | RP_CSYN | '\003') /* unknown user */ #define RP_USER (RP_BNO | RP_CUSR | '\000') /* * MACHINE DEPENDENCY * * The following treat the value as strictly numeric. * It relies on the negative values being numerically * negative. */ /* is return value negative? */ #define rp_isbad(val) (((signed char)(val)) < 0) nmh-1.7.1-RC3/man/ali.man000644 007761 000024 00000003635 13205305704 015005 0ustar00kenhstaff000000 000000 .TH ALI %manext1% 2013-12-05 "%nmhversion%" . .\" %nmhwarning% . .SH NAME ali \- list nmh mail aliases .SH SYNOPSIS .HP 5 .na .B ali .RB [ \-help ] .RB [ \-version ] .RB [ \-alias .IR aliasfile ] .RB [ \-list " | " \-nolist ] .RB [ \-user " | " \-nouser ] .RI [ aliases " ...]" .ad .SH DESCRIPTION .B ali searches the named mail alias files for each of the given .IR aliases . It creates a list of addresses for those .IR aliases , and writes that list on standard output. If no arguments are given, .B ali outputs all alias entries. .PP By default, when an alias expands to multiple addresses, the addresses are separated by commas and printed on as few lines as possible. If the .B \-list switch is specified, and an address expands to multiple addresses, each address will appear on a separate line. .PP The .B \-user switch directs .B ali to perform its processing in an inverted fashion: instead of listing the addresses that each given alias expands to, .B ali will list the aliases that expand to each given address. .PP The files specified by the profile entry .RI \*(lq Aliasfile \*(rq and any additional alias files given by the .B \-alias .I aliasfile switch will be read. Each .I alias is processed as described in .IR mh\-alias (5). .SH FILES Alias files are looked up in multiple locations: if the pathname is absolute or starts with .RI \*(lq . \*(rq or .RI \*(lq .. \*(rq it is accessed directly; otherwise tilde expansion is done on usernames, then files are searched for in the user's .I Mail directory as specified in their profile. If not found there, the directory .RI \*(lq %nmhetcdir% \*(rq is checked. .PP .TP 20 $HOME/.mh_profile The user's profile. .SH "PROFILE COMPONENTS" .PP .PD 0 .TP 20 Path: To determine the user's nmh directory .TP Aliasfile: For a default alias file .PD .SH "SEE ALSO" .IR mh\-alias (5) .SH DEFAULTS .PD 0 .TP 20 aliasfile %nmhetcdir%/MailAliases .TP \-nolist .TP \-nouser .PD .SH CONTEXT None nmh-1.7.1-RC3/man/anno.man000644 007761 000024 00000007737 13205305704 015202 0ustar00kenhstaff000000 000000 .TH ANNO %manext1% 2005-12-07 "%nmhversion%" . .\" %nmhwarning% . .SH NAME anno \- annotate nmh messages .SH SYNOPSIS .HP 5 .na .B anno .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RI [ msgs ] .RB [ \-component .IR field ] .RB [ \-inplace " | " \-noinplace ] .RB [ \-date " | " \-nodate ] .RB [ \-draft ] .RB [ \-append ] .RB [ \-list ] .RB [ \-delete ] .RB [ \-number .IR [ num|all ]] .RB [ \-preserve " | " \-nopreserve ] .RB [ \-text .IR body ] .ad .SH DESCRIPTION .B anno manipulates header fields or .I annotations in messages. Header fields consist of a field name and an optional field body as defined by RFC 2822. The .B -component switch specifies the field name, and the .B -text switch specifies the field body. .PP The messages are either the .I msgs in the named folder, or the draft if invoked with the .B -draft switch. .PP Usually, annotation is performed by the commands .BR dist , .BR forw , and .BR repl , if they are given the .B \-anno switch. This allows you to keep track of your distribution of, forwarding of, and replies to a message. .PP By using .BR anno , you can perform arbitrary annotations of your own. Each message selected will be annotated with the lines .PP field:\ date field:\ body .PP The .B \-nodate switch inhibits the date annotation, leaving only the body annotation. .PP By default, .B anno prepends the annotations to the message. Annotations are instead appended if the .B -append switch is specified. .PP If a .B \-component .I field is not specified when .B anno is invoked, .B anno will prompt the user for a field name. .PP The field specified must be a valid RFC 2822-style message field name, consisting only of alphanumeric characters and dashes. The body may consist of arbitrary text. .PP Normally .B anno does the annotation in place in order to preserve any links to the message. You may change this by using the .B \-noinplace switch. .PP The .B -list switch produces a listing of the field bodies for header fields with names matching the specified component, one per line. The listing is numbered, starting at 1, if the .B -number switch is also used. A tab character separates the number and the field body. The field body is treated as if it is a file name, and only the final path name component is listed. The complete field body is listed if the .B -text switch is used; the argument to the .B -text switch is required but ignored. .PP The .B -delete switch removes header fields from messages. The first header field whose name matches the component is deleted if no other options are specified. If the .B -text switch is used in conjunction with the .B -delete switch, the first header field whose name matches the component and whose body matches the text is deleted. The text is treated as if it was a file name; if it begins with a slash, the entire field body must match the text, otherwise just the last path name component of the field body must match. If the .B -number switch is used in conjunction with the .B -delete switch, header field .I num whose name matches the component is deleted. The number matches that which is produced by the .B -list switch. The special value .B all can be used for the number, and causes all components that match the name to be deleted. .PP By default, .B anno changes the last-accessed and last-modified times on annotated messages to the time of the annotation. .B anno preserves the original times if the .B -preserve switch is used. A matching .B -nopreserve switch allows time preservation to be turned off, if enabled in the profile. .SH FILES .TP 20 $HOME/.mh_profile The user's profile. .SH "PROFILE COMPONENTS" .PD 0 .TP 20 Path: To determine the user's nmh directory. .TP Current\-Folder: To find the default current folder. .PD .SH "SEE ALSO" .IR dist (1), .IR forw (1), .IR repl (1) .SH DEFAULTS .PD 0 .TP 20 +folder The current folder. .TP msgs The current message. .TP -inplace .TP -date .PD .SH CONTEXT If a folder is given, it will become the current folder. The first message annotated will become the current message. nmh-1.7.1-RC3/man/ap.man000644 007761 000024 00000003574 13205305704 014642 0ustar00kenhstaff000000 000000 .TH AP %manext8% 2013-12-05 "%nmhversion%" . .\" %nmhwarning% . .SH NAME ap \- nmh parser of RFC 822-style addresses .SH SYNOPSIS .HP 5 .na .B %nmhlibexecdir%/ap .RB [ \-help ] .RB [ \-version ] .RB [ \-form .IR formatfile ] .RB [ \-format .IR string ] .RB [ \-width .IR columns ] .I addrs \&... .ad .SH DESCRIPTION .B ap is a program that parses addresses according to the ARPA Internet standard. It also understands many non-standard formats. It is useful for seeing how .B nmh will interpret an address. .PP The .B ap program treats each argument as one or more addresses, and prints those addresses out in the official RFC 822 format. Hence, it is usually best to enclose each argument in quotes for the shell. .PP To override the output format used by .BR ap , the .B \-format .I string or .B \-format .I file switches are used. This permits individual fields of the address to be extracted with ease. The string is simply a format string, and the file is simply a format file. See .IR mh\-format (5) for the details. .PP In addition to the standard escapes, .B ap also recognizes the following additional escape: .PP .RS 5 .nf .ta \w'Escape 'u +\w'Returns 'u .I "Escape Returns Description" error string A diagnostic if the parse failed .RE .fi .PP Here is the default format string used by .BR ap : .PP .RS 5 %<{error}%{error}: %{text}%|%(putstr(proper{text}))%> .RE .PP which says that if an error was detected, print the error, a `:', and the address in error. Otherwise, output the RFC 822\-proper format of the address. .SH FILES .PD 0 .TP 20 $HOME/.mh_profile The user's profile. .TP %nmhetcdir%/mts.conf The mts configuration file. .PD .SH "PROFILE COMPONENTS" None .SH "SEE ALSO" .IR fmttest (1), .IR dp (8) .PP .I Standard for the Format of ARPA Internet Text Messages (RFC 822) .SH DEFAULTS .PD 0 .TP 20 -format As described above. .TP \-width The width of the terminal. .PD .SH CONTEXT None nmh-1.7.1-RC3/man/burst.man000644 007761 000024 00000007710 13205305704 015375 0ustar00kenhstaff000000 000000 .TH BURST %manext1% 2013-02-08 "%nmhversion%" . .\" %nmhwarning% . .SH NAME burst \- explode digests into nmh messages .SH SYNOPSIS .HP 5 .na .B burst .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RI [ msgs ] .RB [ \-inplace " | " \-noinplace ] .RB [ \-mime " | " \-nomime ] .RB [ \-automime ] .RB [ \-quiet " | " \-noquiet ] .RB [ \-verbose " | " \-noverbose ] .ad .SH DESCRIPTION .B burst considers the specified messages in the named folder to be Internet digests, and explodes them in that folder. .PP If .B \-inplace is given, each digest is replaced by its \*(lqtable of contents\*(rq and the digest is removed. .B burst then renumbers the messages which follow the digest, in the folder, making room for each of the exploded messages, which are placed immediately after the \*(lqtable of contents\*(rq. .PP If .B \-noinplace is given, each digest is preserved, no table of contents is produced, and the exploded messages are placed at the end of the folder. Other messages in the folder are not affected. .PP If .B \-automime is given, .B burst will try to determine if the message is formatted with MIME and contains MIME parts of type \*(lqmessage/rfc822\*(rq. If it does, it will burst the message using MIME formatting rules. The .B \-mime switch can be used to enforce the use of MIME formatting. The .B \-nomime switch will force .B burst to use RFC 934 rules. .PP The .B \-quiet switch directs .B burst to be silent about reporting messages that are not in digest format. .PP The .B \-verbose switch directs .B burst to tell the user the general actions that it is taking to explode the digest. .PP It turns out that .B burst works equally well on forwarded messages and blind-carbon-copies as on Internet digests, provided that the former were generated by .B forw or .BR send . .SH FILES .TP 20 $HOME/.mh_profile The user's profile. .SH "PROFILE COMPONENTS" .PD 0 .TP 20 Path: To determine the user's nmh directory. .TP Current\-Folder: To find the default current folder. .TP Msg\-Protect: To set mode when creating a new message. .PD .SH "SEE ALSO" .IR inc (1), .IR pack (1) .PP .I Proposed Standard for Message Encapsulation (RFC 934) .SH DEFAULTS .PD 0 .TP 20 +folder The current folder. .TP msgs The current message. .TP \-noinplace .TP \-automime .TP \-noquiet .TP \-noverbose .PD .SH CONTEXT If a folder is given, it will become the current folder. If .B \-inplace is given, then the first message burst becomes the current message. This leaves the context ready for a .B show of the table of contents of the digest, and a .B next to see the first message of the digest. If .B \-noinplace is given, then the first message extracted from the first digest burst becomes the current message. This leaves the context in a similar, but not identical, state to the context achieved when using .BR \-inplace . .SH BUGS The .B burst program enforces a limit of approximately 1,000 on the number of messages which may be .B burst from a single message. There is usually no limit on the number of messages which may reside in the folder after the .BR burst ing. .PP Although .B burst uses a sophisticated algorithm to determine where one encapsulated message ends and another begins, not all digestifying programs use an encapsulation algorithm. In degenerate cases, this usually results in .B burst finding an encapsulation boundary prematurely and splitting a single encapsulated message into two or more messages. These erroneous digestifying programs should be fixed. .PP Furthermore, any text which appears after the last encapsulated message is not placed in a separate message by .BR burst . In the case of digestified messages, this text is usually an \*(lqEnd of digest\*(rq string. As a result of this possibly unfriendly behavior on the part of .BR burst , note that when the .B \-inplace option is used, this trailing information is lost. In practice, this is not a problem since correspondents usually place remarks in text prior to the first encapsulated message, and this information is not lost. nmh-1.7.1-RC3/man/comp.man000644 007761 000024 00000013736 13243042053 015176 0ustar00kenhstaff000000 000000 .TH COMP %manext1% 2013-10-18 "%nmhversion%" . .\" %nmhwarning% . .SH NAME comp \- compose an nmh message .SH SYNOPSIS .HP 5 .na .B comp .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RI [ msg ] .RB [ \-form .IR formfile ] .RB [ \-use " | " \-nouse ] .RB [ \-file .IR file ] .RB [ \-draftfolder .IR +folder ] .RB [ \-draftmessage .IR msg ] .RB [ \-nodraftfolder ] .RB [ \-editor .IR editor ] .RB [ \-noedit ] .RB [ \-width .IR columns ] .RB [ \-from .IR address ] .RB [ \-to .IR address ] .RB [ \-cc .IR address ] .RB [ \-fcc .IR +folder ] .RB [ \-subject .IR text ] .RB [ \-whatnowproc .IR program ] .RB [ \-nowhatnowproc ] .RB [ \-build ] .ad .SH DESCRIPTION .B comp is used to create a new message to be mailed. It copies a message form to the draft being composed and then invokes an editor on the draft (unless .B \-noedit is given, in which case the initial edit is suppressed). .PP The default message template \*(lqcomponents\*(rq will direct .B comp to construct the message draft as follows: .PP .RS 5 .nf From: {from switch} or or To: {to switch} or blank cc: {cc switch} or blank Fcc: {fcc switch} or +outbox Subject: {subject switch} or blank -------- .fi .RE .PP If a file named .RI \*(lq components \*(rq exists in the user's nmh directory, it will be used instead of this form. You may specify an alternate forms file with the switch .B \-form .IR formfile . .PP You may also start .B comp using the contents of an existing message as the form. If you supply either a .I +folder or .I msg argument, that message will be used as the message form. You may not supply both a .B \-form .I formfile and a .I +folder or .I msg argument. The line of dashes or a blank line must be left between the header and the body of the message for the message to be identified properly when it is sent (see .IR send (1)). .PP The switch .B \-use directs .B comp to continue editing an already started message. That is, if a .B comp (or .BR dist , .BR repl , or .BR forw ) is terminated without sending the draft, the draft can be edited again via .RB \*(lq comp .BR \-use \*(rq. .PP The .B \-file .I file switch says to use the named file as the message draft. .PP Forms that are selected via the .B \-form switch are processed via the .B nmh template system; see .IR mh\-format (5) for details. Drafts constructed from another message or with the .B \-use or .B \-file switches will .I not be processed with .IR mh\-format (5). .PP In addition to the standard .IR mh\-format (5) escapes, the following .I component escapes are either new or have an alternate meaning: .PP .RS 5 .nf .ta \w'Escape 'u +\w'Returns 'u .I "Escape Returns Description" fcc string Any folders specified with `\-fcc\ folder' from string Any addresses specified with `\-from\ address' to string Any addresses specified with `\-to\ address' cc string Any addresses specified with `\-cc\ address' subject string Any text specified with `\-subject\ text' .fi .RE .PP By default the \*(lqTo:\*(rq and \*(lqcc:\*(rq fields are empty. You may add addresses to these fields with the .B \-to .I address and .B \-cc .I address switches. You may give these switches multiple times to add multiple addresses. .PP By default the \*(lqFrom:\*(rq field has either the value of the .B Local\-Mailbox profile entry or a system default email address. This default can be overridden by using the .B \-from .I address switch. The default mailbox in the \*(lqFcc:\*(rq field is .IR +outbox . This can be overridden by the .B \-fcc switch. .PP Any text you give to the .B \-subject switch will be placed in the \*(lqSubject:\*(rq field in the draft. .PP If the draft already exists, .B comp will ask you as to the disposition of the draft. A reply of .B quit will abort .BR comp , leaving the draft intact; .B replace will replace the existing draft with the appropriate form; .B list will display the draft; .B use will use the draft for further composition; and .B refile .I +folder will file the draft in the given folder, and give you a new draft with the appropriate form. (The .I +folder argument to .B refile is required.) .PP The .B \-draftfolder .I +folder and .B \-draftmessage .I msg switches invoke the .B nmh draft folder facility. This is an advanced (and highly useful) feature. Consult the .IR mh-draft (5) man page for more information. .PP The .B \-editor .I editor switch indicates the editor to use for the initial edit. Upon exiting from the editor, .B comp will invoke the .B whatnow program (see .IR whatnow (1) for a discussion of available options). The invocation of this program can be inhibited by using the .B \-nowhatnowproc switch. (In fact, it is the .I whatnow program which starts the initial edit. Hence, .B \-nowhatnowproc will prevent any edit from occurring.) .PP The .B \-build switch is intended to be used by the Emacs mh-e interface to .BR nmh . It implies .BR \-nowhatnowproc . It causes a file /draft to be created, containing the draft message that would normally be presented to the user for editing. No mail is actually sent. .SH FILES .PD 0 .TP 20 %nmhetcdir%/components The default message skeleton. .TP /components The user's message skeleton. .TP $HOME/.mh_profile The user's profile. .PD .SH "PROFILE COMPONENTS" .PD 0 .TP 20 Path: To determine the user's nmh directory. .TP Draft\-Folder: To find the default draft-folder. .TP Editor: To override the default editor. .TP Msg\-Protect: To set mode when creating a new message (draft). .TP fileproc: Program to refile the message. .TP whatnowproc: Program to ask the \*(lqWhat now?\*(rq questions .PD .SH "SEE ALSO" .IR dist (1), .IR forw (1), .IR repl (1), .IR send (1), .IR whatnow (1), .IR mh-profile (5) .SH DEFAULTS .PD 0 .TP 20 +folder The current folder. .TP msg The current message. .TP \-nodraftfolder .TP \-nouse .PD .SH CONTEXT None .SH BUGS If .I whatnowproc is .BR whatnow , then .B comp uses a built-in .BR whatnow , it does not actually run the .B whatnow program. Hence, if you define your own .IR whatnowproc , don't call it .B whatnow since .B comp won't run it. nmh-1.7.1-RC3/man/dist.man000644 007761 000024 00000014634 13243042053 015201 0ustar00kenhstaff000000 000000 .TH DIST %manext1% 2012-12-04 "%nmhversion%" . .\" %nmhwarning% . .SH NAME dist \- distribute an nmh message to additional addresses .SH SYNOPSIS .HP 5 .na .B dist .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RI [ msg ] .RB [ \-form .IR formfile ] .RB [ \-annotate " | " \-noannotate ] .RB [ \-inplace " | " \-noinplace ] .RB [ \-draftfolder .IR +folder ] .RB [ \-draftmessage .IR msg ] .RB [ \-nodraftfolder ] .RB [ \-editor .IR editor ] .RB [ \-noedit ] .RB [ \-width .IR columns ] .RB [ \-from .IR address ] .RB [ \-to .IR address ] .RB [ \-cc .IR address ] .RB [ \-fcc .IR +folder ] .RB [ \-whatnowproc .IR program ] .RB [ \-nowhatnowproc ] .RB [ \-atfile ] .RB [ \-noatfile ] .ad .SH DESCRIPTION .B dist is similar to .BR forw . It prepares the specified message for redistribution to addresses that (presumably) are not on the original address list. .PP The default message form contains the following elements: .PP .RS 5 .nf Resent-From: {from switch} or or Resent-To: {to switch} or blank Resent-cc: {cc switch} or blank Resent-fcc: {fcc switch} or blank .fi .RE .PP If a file named .RI \*(lq distcomps \*(rq exists in the user's nmh directory, it will be used instead of this default form. You may specify an alternate forms file with the switch .B \-form .IR formfile . Forms are processed via the .B nmh template system; see .IR mh\-format (5) for details. Components from the redistributed message are available as standard component escapes in the forms file. .PP In addition to the standard .IR mh\-format (5) escapes, the following .I component escapes are also supported: .PP .RS 5 .nf .ta \w'Escape 'u +\w'Returns 'u .I "Escape Returns Description" fcc string Any folders specified with `\-fcc\ folder' nmh\-from string Addresses specified with `\-from\ address' nmh\-to string Addresses specified with `\-to\ address' nmh\-cc string Addresses specified with `\-cc\ address' .fi .RE .PP See the .IR forw (1) man page for descriptions of the .BR \-from , .BR \-to , .BR \-cc , and .B \-fcc switches. .PP If the draft already exists, .B dist will ask you as to the disposition of the draft. A reply of .B quit will abort .BR dist , leaving the draft intact; .B replace will replace the existing draft with a blank skeleton; and .B list will display the draft. .PP Only those addresses in .RI \*(lq Resent\-To: \*(rq, .RI \*(lq Resent\-cc: \*(rq, and .RI \*(lq Resent\-Bcc: \*(rq will be sent. Also, a .RI \*(lq "Resent\-Fcc: folder" \*(rq will be honored (see .IR send (1)). Note that with .BR dist , the draft should contain only .RI \*(lq Resent\-xxx: \*(rq fields and no body. The headers and the body of the original message are copied to the draft when the message is sent. Use care in constructing the headers for the redistribution. .PP Because the draft is minimal, the .IR prompter (1) editor is quite useful with .BR dist . .PP If the .B \-annotate switch is given, the message being distributed will be annotated with the lines: .RS Resent:\ date .br Resent:\ addrs .RE where each address list contains as many lines as required. This annotation will be done only if the message is sent directly from .BR dist . If the message is not sent immediately from .BR dist , .RB \*(lq comp .BR \-use \*(rq may be used to re-edit and send the constructed message, but the annotations won't take place. Normally annotations are done in place in order to preserve any links to the message. You may use the .B \-noinplace switch to change this. .PP See .IR comp (1) for a description of the .B \-editor and .B \-noedit switches. Note that while in the editor, with .B \-atfile and if the current directory is writable, the message being resent is available through a link named \*(lq@\*(rq (assuming the default .IR whatnowproc ). In addition, the actual pathname of the message is stored in the environment variable .BR $editalt , and the pathname of the folder containing the message is stored in the environment variable .BR $mhfolder . The creation of the \*(lq@\*(rq file is controlled via the .B \-atfile and .B \-noatfile options. .PP The .B \-draftfolder .I +folder and .B \-draftmessage .I msg switches invoke the .B nmh draft folder facility. This is an advanced (and highly useful) feature. Consult the .IR mh-draft (5) man page for more information. .PP Upon exiting from the editor, .B dist will invoke the .B whatnow program. See .IR whatnow (1) for a discussion of available options. The invocation of this program can be inhibited by using the .B \-nowhatnowproc switch. (In fact, it is the .B whatnow program which starts the initial edit. Hence, .B \-nowhatnowproc will prevent any edit from occurring.) .SH FILES .PD 0 .TP 20 %nmhetcdir%/distcomps The default message skeleton. .TP 20 /distcomps The user's message skeleton. .TP 20 $HOME/.mh_profile The user's profile. .TP 20 /draft The draft file. .PD .SH "PROFILE COMPONENTS" .PD 0 .TP 20 Path: To determine the user's nmh directory. .TP 20 Current\-Folder: To find the default current folder. .TP 20 Draft\-Folder: To find the default draft-folder. .TP 20 Editor: To override the default editor. .TP 20 fileproc: Program to refile the message. .TP 20 whatnowproc: Program to ask the \*(lqWhat now?\*(rq questions. .PD .SH "SEE ALSO" .IR comp (1), .IR forw (1), .IR prompter (1), .IR repl (1), .IR send (1), .IR whatnow (1) .SH DEFAULTS .PD 0 .TP 20 +folder The current folder. .TP 20 msg The current message. .TP 20 \-noannotate .TP 20 \-nodraftfolder .TP 20 \-inplace .TP 20 \-noatfile .PD .SH CONTEXT If a folder is given, it will become the current folder. The message distributed will become the current message. .SH HISTORY .B dist originally used headers of the form .RI \*(lq Distribute\-xxx: \*(rq instead of .RI \*(lq Resent\-xxx: \*(rq. In order to conform with the ARPA Internet standard, RFC 822, the .RI \*(lq Resent\-xxx: \*(rq form is now used. .B dist will recognize .RI \*(lq Distribute\-xxx: \*(rq type headers and automatically convert them to .RI \*(lq Resent\-xxx: \*(rq. .SH BUGS .B dist does not rigorously check the message being distributed for adherence to the transport standard, but .B post called by .B send does. The .B post program will balk (and rightly so) at poorly formatted messages, and .B dist won't correct things for you. .PP If .I whatnowproc is .BR whatnow , then .B comp uses a built-in .BR whatnow , it does not actually run the .B whatnow program. Hence, if you define your own .IR whatnowproc , don't call it .B whatnow since .B comp won't run it. nmh-1.7.1-RC3/man/dp.man000644 007761 000024 00000003211 13243042053 014626 0ustar00kenhstaff000000 000000 .TH DP %manext8% 1999-04-30 "%nmhversion%" . .\" %nmhwarning% . .SH NAME dp \- nmh parser of RFC 822-style dates .SH SYNOPSIS .HP 5 .na .B %nmhlibexecdir%/dp .RB [ \-help ] .RB [ \-version ] .RB [ \-form .IR formatfile ] .RB [ \-format .IR string ] .RB [ \-width .IR columns ] .I dates \&... .ad .SH DESCRIPTION .B dp is a program that parses dates according to the ARPA Internet standard. It also understands many non-standard formats, such as those produced by TOPS\-20 sites and some Unix sites using .IR ctime (3). It is useful for seeing how .B nmh will interpret a date. .PP The .B dp program treats each argument as a single date, and prints the date out in the official RFC 822 format. Hence, it is usually best to enclose each argument in quotes for the shell. .PP To override the output format used by .BR dp , the .B \-format .I string or .B \-format .I file switches are used. This permits individual fields of the address to be extracted with ease. The string is simply a format string and the file is simply a format file. See .IR mh\-format (5) for the details. .PP Here is the default format string used by .BR dp : .PP .RS 5 %<(nodate{text})error: %{text}%|%(putstr(pretty{text}))%> .RE .PP which says that if an error was detected, print the error, a `:', and the date in error. Otherwise, output the RFC 822\-proper format of the date. .SH FILES .TP 20 $HOME/.mh_profile The user's profile. .SH "PROFILE COMPONENTS" None .SH "SEE ALSO" .IR fmttest (1), .IR ap (8), .PP .I "Standard for the Format of ARPA Internet Text Messages" (RFC 822) .SH DEFAULTS .PD 0 .TP 20 \-format As described above. .TP \-width The width of the terminal. .PD .SH CONTEXT None nmh-1.7.1-RC3/man/flist.man000644 007761 000024 00000012171 13243042053 015351 0ustar00kenhstaff000000 000000 .TH FLIST %manext1% 1999-04-30 "%nmhversion%" . .\" %nmhwarning% . .SH NAME flist, flists \- list the number of nmh messages in given sequences .SH SYNOPSIS .HP 5 .na .B flist .RB [ \-help ] .RB [ \-version ] .RI [ +folder1 .RI [ +folder2 \&...]] .RB [ \-sequence .I name1 .RB [ \-sequence .I name2 \&...]] .RB [ \-all " | " \-noall ] .RB [ \-showzero " | " \-noshowzero ] .RB [ \-recurse " | " \-norecurse ] .RB [ \-fast " | " \-nofast ] .RB [ \-alpha " | " \-noalpha ] .PP .HP 5 .B flists is equivalent to .B flist .B \-all .ad .SH DESCRIPTION .B flist is used to search a list of folders and display the number of messages in these folders that are in a given sequence or set of sequences (for example the .RI \*(lq unseen \*(rq sequence). This is especially useful if you use some mechanism such as .B slocal or .B procmail (typically in conjunction with .BR rcvstore ) to pre-sort your mail into different folders before you view it. .PP By default, the command .B flist will search the current folder for the given sequence or sequences (usually .RI \*(lq unseen \*(rq). If (possibly multiple) folders are specified on the command line with .IR +folder , then all these folders are searched for the given sequence(s). .B flist will display for each folder searched, the number of messages in each of the specified sequences, and the total number of messages. .PP The .B \-sequence switch specifies the sequence to which messages should belong. This switch may be given multiple times to specify multiple sequences. If it is not given, then the default is to search for all the sequences specified by the .RI \*(lq Unseen-Sequence \*(rq profile component. For more details about sequences, read the .IR mh\-sequence (5) man page. .PP Typically, .B flist will produce a line for each sequence, for every folder that is searched, even those which do not contain any messages in the given sequence. Specifying .B \-noshowzero will cause .B flist to print only those folder/sequence combinations where the folder has a non-zero number of messages in the given sequence. .PP If .B \-recurse is given, then for each folder that is searched, .B flist will also recursively descend into those folders to search subfolders for the given sequence. .PP If .B \-fast is given, only the names of the folders searched will be displayed, and .B flist will suppress all other output. If this option is used in conjunction with .BR \-noshowzero , then .B flist will only print the names of those folders searched that contain messages in in at least one of the specified sequences. .SS "Multiple Folders" If the .B \-all switch is given (and no folders are specified with .IR +folder ), then .B flist will search all the folders in the top level of the users nmh directory. These folders are all preceded by the read-only folders, which occur as .RI \*(lq atr\-cur\- \*(rq entries in the user's .B nmh context. .PP An example of the output of .B flist .B \-all is: .PP .RS 5 .nf /work/Mail has 5 in sequence unseen (private); out of 46 inbox+ has 10 in sequence unseen ; out of 153 junklist has 0 in sequence unseen ; out of 63 postmaster has 1 in sequence unseen ; out of 3 .fi .RE .PP The \*(lq+\*(rq after .I inbox indicates that it is the current folder. .PP The \*(lqprivate\*(rq flag indicates that the given sequence for that folder is private. See the .IR mh\-sequence (5) man page for details about private sequences. .PP If the option .B \-all and .I +folder are both specified, then .B flist will search this folder, and all its first level subfolders for the given sequence. You may specify multiple folders in this way. .PP If .B flist is invoked by a name ending with \*(lqs\*(rq (e.g. .BR flists ), then the switch .B \-all is assumed by default. .PP The sorting order for the listing is alphabetical (with .BR \-alpha ), or in a priority order defined by the .RI \*(lq Flist-Order \*(rq profile entry (with .BR \-noalpha ). Each item in the .RI \*(lq Flist-Order \*(rq is a folder name or a folder name pattern that uses * to match zero or more characters. Longer matching patterns have precedence over shorter matching patterns. For example: .PP .RS 5 .nf Flist-Order: personal petproject mh* * admin *junk .fi .RE .PP This order puts a few interesting folders first, such as those with mail addressed to you personally, those about a pet project, and those about mh-related things. It places uninteresting folders at the end, and it puts everything else in the middle in alphabetical order. .SH FILES .TP 20 $HOME/.mh_profile The user's profile. .SH "PROFILE COMPONENTS" .PD 0 .TP 20 Path: To determine the user's nmh directory. .TP mh-sequences: File that contains public sequences. .TP Unseen-Sequence: The name of the unseen message sequence. .TP Flist-Order: To sort folders by priority. .PD .SH "SEE ALSO" .IR folder (1), .IR rcvstore (1), .IR slocal (1), .IR mh\-sequence (5) .SH DEFAULTS .PD 0 .TP 20 -sequence The Unseen-Sequence profile entry. .TP \-showzero .TP \-noall .TP \-norecurse .TP \-noalpha .TP \-nofast .PD .SH CONTEXT If .I +folder is given, it will become the current folder. If multiple folders are given, the last one specified will become the current folder. nmh-1.7.1-RC3/man/flists.man000644 007761 000024 00000000021 11732520432 015526 0ustar00kenhstaff000000 000000 .so man1/flist.1 nmh-1.7.1-RC3/man/fmtdump.man000644 007761 000024 00000001620 13205305704 015704 0ustar00kenhstaff000000 000000 .TH FMTDUMP %manext8% 1999-04-30 "%nmhversion%" . .\" %nmhwarning% . .SH NAME fmtdump \- decode nmh's \fImh-format\fP\^(5) files .SH SYNOPSIS .HP 5 .na .B %nmhlibexecdir%/fmtdump .RB [ \-help ] .RB [ \-version ] .RB [ \-form .IR formatfile ] .RB [ \-format .IR string ] .ad .SH DESCRIPTION .B fmtdump parses an .B nmh format file and produces a pseudo-language listing of how .B nmh interprets the file. This is useful when debugging a complicated format file. .PP The .B \-format .I string and .B \-form .I formatfile switches may be used to specify a format string or format file to read. See .IR mh-format (5) for details. .SH FILES .PD 0 .TP 20 $HOME/.mh_profile The user's profile. .TP %nmhetcdir%/scan.default The default format file. .PD .SH "PROFILE COMPONENTS" .TP 20 Path: To determine the user's nmh directory. .SH "SEE ALSO" .IR fmttest (1), .IR mh-format (5), .IR mh-sequences (8) .SH CONTEXT None nmh-1.7.1-RC3/man/fmttest.man000644 007761 000024 00000027200 13205305704 015720 0ustar00kenhstaff000000 000000 .TH FMTTEST %manext1% 2014-08-31 "%nmhversion%" . .\" %nmhwarning% . .SH NAME fmttest \- test programs in nmh's \fImh-format\fP\^(5) language .SH SYNOPSIS .HP 5 .na .B fmttest .RB [ \-help ] .RB [ \-version ] .RB [ \-form .IR formatfile ] .RB [ \-format .IR formatstring ] .RB [ \-address " | " \-raw " | " \-date " | " \-message ] .RB [ \-file " | " \-nofile ] .RB [ \-\|\-component .IR component-text ] .RB [ \-dupaddrs " | " \-nodupaddrs ] .RB [ \-ccme " | " \-noccme ] .RB [ \-outsize .IR size-in-characters ] .RB [ \-width .IR column-width ] .RB [ \-msgnum .IR number ] .RB [ \-msgcur .IR flag ] .RB [ \-msgsize .IR size ] .RB [ \-unseen .IR flag ] .RB [ \-dump " | " \-nodump ] .RB [ \-trace " | " \-notrace ] .RI [ +folder ] .RI [ msgs " | " strings ] .ad .SH DESCRIPTION .B fmttest is used to test programs written for the .B nmh format language as specified by .IR mh-format (5). It is also intended to replace the .BR ap , .BR dp , and .B fmtdump programs. .SS Format Program Selection The .B \-format .I string and .B \-form .I formatfile specify a format string or file to read. A format string, if given, must be a single argument to the .B \-format switch. If a format file name is passed to the .BR \-form , switch, the file is searched for using the normal .B nmh rules: absolute pathnames are accessed directly, tilde expansion is done on usernames, and files are searched for in the user's .I Mail directory as specified in their profile. If not found there, the directory .RI \*(lq %nmhetcdir% \*(rq is checked. .SS Mode Selection and Component Specification .B fmttest has four operating modes - address, raw, date, and message - which are selected by the .BR \-address , .BR \-raw , .BR \-date , and .B \-message switches, respectively. .PP Address mode treats every argument as an email address to be processed by nmh's email parser using the specified format program. The parsed address is made available as a special .RI %{ text } component escape, and the output from the program is printed on standard output. If there was an error parsing the email address the error message is stored in the .RI %{ error } component escape. If no format program is given on the command line, the following default program is used: .PP .RS 5 .nf %<{error}%{error}: %{text}%|%(putstr(proper{text}))%> .fi .RE .PP Address mode is equivalent to .IR ap (8). .PP In raw mode, no processing of the specified arguments is done. Each argument is run against the specified format program with the argument text available in the .RI %{ text } component. You must specify a format with .B \-form or .B \-format when using raw mode. .PP Date mode is identical to raw mode, with one exception: if no format is specified, the following format string is used: .PP .RS 5 .nf %<(nodate{text})error: %{text}%|%(putstr(pretty{text}))%> .fi .RE .PP Date mode is equivalent to .IR dp (8). .PP In message mode the arguments to .B fmttest are interpreted as an optional folder and messages. .B fmttest will read each specified message and make all of the components in the message available to the format program. Also, the appropriate information for the .RI %( msg ), .RI %( cur ), .RI %( unseen ), and .RI %( size ) function escapes will be made available for each message. If the .B \-file switch is given, the arguments are interpreted as filenames instead of message numbers, but otherwise the behavior is the same (except that the .RI %( msg ), .RI %( cur ), and .RI %( unseen ) function escapes will not provide any useful information). .PP The default format used in address mode is the default format used by .BR scan . The following command can replicate the functionality of the .B repl command. .PP .RS 5 .nf fmttest \-nodupaddrs \-form replcomps \-outsize max [+folder] message .fi .RE .PP Regardless of the mode, other components can be provided to the format program by the use of the .B \-\|\-component switch. For example, the following program will test the use of the .RB \*(lq encrypted \*(rq component: .PP .RS 5 .nf fmttest \-\|\-encrypted yes \-message cur .fi .RE .PP In message mode, components supplied on the command line will override components from messages. .SS Additional Switches The .B \-dupaddrs and .B \-nodupaddrs switches control whether duplicate addresses are allowed or suppressed by the .B FORMATADDR instruction, which is used by the .RI `%( formataddr )' function escape. In normal operation duplicate addresses are only suppressed by .BR repl . .PP The .B \-ccme and .B \-noccme switches control whether or not to count the user's local mailbox as a duplicate address. This replicates the behavior of the .B \-cc .I me switch to .BR repl , and only applies if .B \-nodupaddrs is in effect. .PP The .B \-outsize switch controls the maximum number of printable characters that the format engine will produce. Characters marked as non-printing by the format engine with .RI `%( zputlit )', characters with zero width, and extra bytes that are part of a multibyte character are not counted against this total. Two special values are supported: .RI \*(lq max \*(rq, which means as many characters as the format engine can produce (limited by internal buffers), and .RI \*(lq width \*(rq, which will set the value to the width of the terminal. In message mode it defaults to .RI \*(lq width \*(rq, otherwise the default is .RI \*(lq max \*(rq. .PP The .B \-width switch controls the column width which is used by the .RI `%( width )' function escape. It defaults to the terminal width. .PP The .BR \-msgnum , .BR \-msgcur , .BR \-msgsize , and the .B \-unseen switches all control the values used, respectively, by the following function escapes: .RI `%( num )', .RI `%( cur )', .RI `%( size )', and .RI `%( unseen )'. If none are supplied, these values are taken from the message in message mode; in all other modes the default values are 0. .SS Compiling and Tracing Format Programs The .B \-dump switch outputs the complete set of format instructions for the specified format program. The .B \-trace switch will output each format instruction as it is being executed, and show the values of the .I num and .I str registers if they have changed from the previous instruction. The output buffer is also printed if it has changed from the previous instruction. .SS Format Instructions It should be noted that there is not a one-to-one correspondence between format escapes and format instructions; many instructions have side effects. Instructions prefixed with .RI \*(lq LV \*(rq generally return a integer into the .I num (value) register; instructions prefixed with a .RI \*(lq LS \*(rq return a string into the .I str register. .PP .nf .ta \w'LS_DECODECOMP 'u .I "Instruction Description" COMP Output component COMPF Formatted output component LIT Output literal text LITF Formatted literal text output CHAR Output single character NUM Output the \fInum\fR register NUMF Formatted output of the \fInum\fR register STR Output the \fIstr\fR register STRF Formatted output of the \fIstr\fR register STRFW Not used PUTADDR Output address list in \fIstr\fR register STRLIT Output \fIstr\fR, no space compression STRLITZ Like \fBSTRLIT\fR, but not counted against width LS_COMP Write component to \fIstr\fR register LS_LIT Write literal to \fIstr\fR register LS_GETENV Write environment var to \fIstr\fR register LS_DECODECOMP Decode RFC 2047 encoded component to \fIstr\fR register LS_DECODE Decode RFC 2047 encoded string to \fIstr\fR register LS_TRIM Trim trailing whitespace from \fIstr\fR register LV_COMP Convert component to integer, store in \fInum\fR register LV_COMPFLAG Set \fInum\fR to 1 if \fBTRUE\fR set in component LV_LIT Load literal value into \fInum\fR register LV_DAT Load value from \fIdat\fR array into \fInum\fR register (see note) LV_STRLEN Set \fInum\fR to the length of \fIstr\fR LV_PLUS_L Add value to \fInum\fR register LV_MINUS_L Subtract value from \fInum\fR register LV_DIVIDE_L Divide \fInum\fR register by value LV_MODULO_L \fInum\fR modulo value LV_CHAR_LEFT Store remaining number of printable chars in \fInum\fR LS_MONTH Write short name of month to \fIstr\fR from date component LS_LMONTH Write long name of month to \fIstr\fR from date component LS_ZONE Write time zone offset to \fIstr\fR from date component LS_DAY Write short name of day of week to \fIstr\fR from date component LS_WEEKDAY Write long name of day of week to \fIstr\fR from date component LS_822DATE Write RFC 822 compatible date to \fIstr\fR from date component LS_PRETTY Write date with \*(lqpretty\*(rq timezone to \fIstr\fR LV_SEC Write date component seconds to \fInum\fR LV_MIN Write date component minutes to \fInum\fR LV_HOUR Write date component hour to \fInum\fR LV_MON Write date component numeric month to \fInum\fR (start at 1) LV_YEAR Write date component year to \fInum\fR LV_YDAY Write date component Julian day to \fInum\fR LV_WDAY Write date component day of week to \fInum\fR (0 == Sunday) LV_ZONE Write date component time zone offset to \fInum\fR LV_CLOCK Write date component in Unix epoch time to \fInum\fR LV_RCLOCK Write offset of date component from current time to \fInum\fR LV_DAYF Write 1 to \fInum\fR if day of week is explicit LV_DST Write 1 to \fInum\fR if DST is in effect for date component LV_ZONEF Write 1 to \fInum\fR if timezone is explicit LS_ADDR Write email address of addr component to \fIstr\fR LS_PERS Write personal name of addr component to \fIstr\fR LS_MBOX Write mailbox (username) of addr component to \fIstr\fR LS_HOST Write host of addr component to \fIstr\fR LS_PATH Write host route of addr component to \fIstr\fR LS_GNAME Write group name of addr component to \fIstr\fR LS_NOTE Write note portion of addr component to \fIstr\fR LS_822ADDR Write \*(lqproper\*(rq RFC 822 version of addr component to \fIstr\fR LS_FRIENDLY Write friendly (name or note) of address component to \fIstr\fR LS_UNQUOTE Remove RFC 2822 quotes from string LV_HOSTTYPE Set \fInum\fR to type of host (0=local, 1=network) LV_INGRPF Set \fInum\fR to 1 if address was inside of group LV_NOHOSTF Set \fInum\fR to 1 of no host was present in address component LOCALDATE Convert date component to local timezone GMTDATE Convert date component to GMT PARSEDATE Parse date component PARSEADDR Parse address component FORMATADDR Add address component to list in \fIstr\fR CONCATADDR Like \fBFORMATADDR\fR, but will not suppress duplicates MYMBOX Set \fInum\fR if address component is a local address SAVESTR Save \fIstr\fR register temporarily DONE End program NOP No operation GOTO Jump to new instruction IF_S_NULL Branch if \fIstr\fR is \fBNULL\fR IF_S Branch if \fIstr\fR is not \fBNULL\fR IF_V_EQ Branch if \fInum\fR is equal to value IF_V_NE Branch if \fInum\fR is not equal to value IF_V_GT Branch if \fInum\fR is greater than value IF_MATCH Branch if \fIstr\fR contains string IF_AMATCH Branch if \fIstr\fR starts with string S_NULL Set \fInum\fR to 1 if \fIstr\fR is \fBNULL\fR S_NONNULL Set \fInum\fR to 1 if \fIstr\fR is not \fBNULL\fR V_EQ Set \fInum\fR to 1 if \fInum\fR equals value V_NE Set \fInum\fR to 1 if \fInum\fR does not equal value V_GT Set \fInum\fR to 1 if \fInum\fR is greater than value V_MATCH Set \fInum\fR to 1 if \fIstr\fR contains string V_AMATCH Set \fInum\fR to 1 if \fIstr\fR starts with string .fi .PP The .B LV_DAT instruction is a bit special. Callers of the format library pass in an array of integers that are used by certain format escapes. The current list of format escapes and the indexes they use are: .PP .RS 5 .nf .ta \w'dat[5]\0\0'u dat[0] %(\fInum\fR) dat[1] %(\fIcur\fR) dat[2] %(\fIsize\fR) dat[3] %(\fIwidth\fR) dat[4] %(\fIunseen\fR) .fi .RE .SH "SEE ALSO" .IR mh-format (5), .IR repl (1), .IR ap (8), .IR dp (8), .IR fmtdump (8) .SH DEFAULTS .nf .RB ` \-message ' .RB ` \-nofile ' .RB ` \-dupaddrs ' .fi .SH BUGS It shouldn't require as much code from other programs as it does. nmh-1.7.1-RC3/man/fnext.man000644 007761 000024 00000000017 11732520432 015353 0ustar00kenhstaff000000 000000 .so man1/new.1 nmh-1.7.1-RC3/man/folder.man000644 007761 000024 00000015241 13243042053 015504 0ustar00kenhstaff000000 000000 .TH FOLDER %manext1% 2016-08-29 "%nmhversion%" . .\" %nmhwarning% . .SH NAME folder, folders \- set/list current nmh folder/message .SH SYNOPSIS .HP 5 .na .B folder .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RI [ msg ] .RB [ \-all " | " \-noall ] .RB [ \-create " | " \-nocreate ] .RB [ \-fast " | " \-nofast ] .RB [ \-header " | " \-noheader ] .RB [ \-recurse " | " \-norecurse ] .RB [ \-total " | " \-nototal ] .RB [ \-list " | " \-nolist ] .RB [ \-push " | " \-pop ] .RB [ \-pack " | " \-nopack ] .RB [ \-print ] .RB [ \-verbose " | " \-noverbose ] .HP 5 .B folders is equivalent to .B folder .B \-all .ad .SH DESCRIPTION When .B folder is given the .B \-print switch (the default), it lists: the current folder, the number of messages in it and their range (low-high), the folder's current message, and an indication of extra files, if any. For example: .PP .RS 5 .nf .ta \w'/rnd/phyl/Mail/EP 'u +\w'has ddd messages 'u +\w'(ddd\-ddd); 'u inbox+ has \016 messages (\0\03\-\022); cur=\0\05. .fi .RE .PP If a .I +folder and/or .I msg are specified, they will become the current folder and/or message. (When a .I +folder argument is given, this corresponds to a \*(lqcd\*(rq operation in the shell; when no .I +folder argument is given, this corresponds roughly to a \*(lqpwd\*(rq operation in the shell.) .PP If the specified (or default) folder doesn't exist, .B folder will ask the user if the folder should be created; when standard input is not a tty, the answer is assumed to be \*(lqyes\*(rq. The .B \-create switch tells .B folder to create new folders without query. (This is an easy way to create an empty folder for later use.) Specifying .B \-nocreate will cause .B folder to print an error message and exit without creating a folder. .\" .\" note - this doesn't work at present .\" If `\-noprint' is specified, .\" a `+folder' and/or `msg' may still be specified .\" to set the current folder and/or message, .\" but the folder summary will not be printed. .SS "Multiple Folders" Specifying .B \-all will produce a summary line for each top-level folder in the user's .B nmh directory, sorted alphabetically. (If .B folder is invoked by a name ending with \*(lqs\*(rq (e.g. .BR folders ), .B \-all is assumed.) Specifying .B \-recurse with .B \-all will include a line for all sub-folders. These folders are all preceded by any read-only folders, which occur as .RI \*(lq atr\-cur\- \*(rq entries in the user's .B nmh context. For example: .PP .RS 5 .nf .ta \w'/rnd/phyl/Mail/EP 'u +\w'has ddd messages 'u +\w'(ddd\-ddd); 'u FOLDER \0\0\0\0\0\0# MESSAGES RANGE CUR (OTHERS) /var/work/folder has \035 messages (\01\-\035); cur=23. /usr/bugs/Mail has \082 messages (\01\-108); cur=82. ff has \0no messages. inbox+ has \016 messages (\03\-\022); cur=\05. mh has \076 messages (15\-\076); cur=70. notes has \0\02 messages (\01\-\0\02); cur=\01. ucom has 124 messages (\01\-124); cur=\06; (others). .ta \w'/rnd/phyl/Mail/EP has 'u TOTAL = 339 messages in 7 folders .fi .RE .PP The \*(lq+\*(rq after .I inbox indicates that it is the current folder. The \*(lq(others)\*(rq indicates that the folder .I ucom contains files which aren't messages; these may either be sub-folders, or files that don't belong under the .B nmh file naming scheme. .PP The header is output if either the .B \-all or .B \-header switches are specified. It is suppressed by .BR \-noheader . .PP The folder and message totals are output if either the .B \-all or .B \-total switches are specified. They are suppressed by .BR \-nototal . .PP If .B \-fast is given, only the folder name (or names, in the case of .BR \-all ) will be listed. (This is faster because the folders need not be read.) .PP If a .I +folder is given with the .B \-all switch, .B folder will, in addition to setting the current folder, list the top-level sub-folders for the current folder (with .BR \-norecurse ) or list all sub-folders under the current folder recursively (with .BR \-recurse ). .PP If .I msg is supplied, together with .I +folder or without .BR \-all , it will become the current message of .I +folder (if it had been supplied) or the current folder. .PP The .B \-recurse switch lists each folder recursively, so its use effectively defeats the speed enhancement of .BR \-fast , since each folder must be searched for sub-folders. Nevertheless, the combination of these options is useful. .SS "Compacting a Folder" The .B \-pack switch will compress the message names in the designated folders, removing holes in message numbering. The .B \-verbose switch directs .B folder to tell the user the general actions it is taking to compress the folder. .SS "The Folder Stack" The .B \-push switch directs .B folder to push the current folder onto the .IR folder-stack , and make the .I +folder argument the current folder. If .I +folder is not given, the current folder and the top of the .I folder-stack are exchanged. This corresponds to the \*(lqpushd\*(rq operation in the shell. .PP The .B \-pop switch directs .B folder to discard the top of the .IR folder-stack , after setting the current folder to that value. No .I +folder argument is allowed. This corresponds to the \*(lqpopd\*(rq operation in the shell. The .B \-push and .B \-pop switches are mutually exclusive: the last occurrence of either one overrides any previous occurrence of the other. The use of either of these switches also sets .BR \-list , by default. .PP The .B \-list switch directs .B folder to list the .IR folder-stack . No .I +folder argument is allowed. After a successful .B \-push or .BR \-pop , the .B \-list action is taken, unless a .B \-nolist switch follows them on the command line. This corresponds to the \*(lqdirs\*(rq operation in the shell. The .BR \-push , .BR \-pop , and .B \-list switches all disable .BR \-print . .SH FILES .TP 20 $HOME/.mh_profile The user's profile. .SH "PROFILE COMPONENTS" .PD 0 .TP 20 Path: To determine the user's nmh directory. .TP Current\-Folder: To find the default current folder. .TP Folder\-Protect: To set mode when creating a new folder. .TP Folder\-Stack: To determine the folder stack. .\" ^lsproc:~^Program to list the contents of a folder .PD .SH "SEE ALSO" .IR mhpath (1), .IR refile (1), .IR rmf (1) .SH DEFAULTS .PD 0 .TP 20 +folder The current folder. .TP msg \*(lqnone\*(rq .TP \-nofast .TP \-noheader .TP \-nototal .TP \-nopack .TP \-norecurse .TP \-noverbose .TP \-print is the default if no .BR -list , .BR \-push , or .B \-pop is specified. .TP \-list is the default if .BR \-push , or .B \-pop is specified. .PD .SH CONTEXT If .I +folder and/or .I msg are given, they will become the current folder and/or message. .SH BUGS There is no way to restore the default behavior (to ask the user whether to create a non-existent folder) after .B \-create or .B \-nocreate is given. nmh-1.7.1-RC3/man/folders.man000644 007761 000024 00000000022 11732520432 015661 0ustar00kenhstaff000000 000000 .so man1/folder.1 nmh-1.7.1-RC3/man/forw.man000644 007761 000024 00000024070 13243042053 015206 0ustar00kenhstaff000000 000000 .TH FORW %manext1% 2013-03-22 "%nmhversion%" . .\" %nmhwarning% . .SH NAME forw \- forward nmh messages .SH SYNOPSIS .HP 5 .na .B forw .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RI [ msgs ] .RB [ \-annotate " | " \-noannotate ] .RB [ \-form .IR formfile ] .RB [ \-format " | " \-noformat ] .RB [ \-filter .IR filterfile ] .RB [ \-inplace " | " \-noinplace ] .RB [ \-mime " | " \-nomime ] .RB [ \-draftfolder .IR +folder ] .RB [ \-draftmessage .IR msg ] .RB [ \-nodraftfolder ] .RB [ \-editor .IR editor ] .RB [ \-noedit ] .RB [ \-width .IR columns ] .RB [ \-from .IR address ] .RB [ \-to .IR address ] .RB [ \-cc .IR address ] .RB [ \-fcc .IR +folder ] .RB [ \-subject .IR text ] .RB [ \-whatnowproc .IR program ] .RB [ \-nowhatnowproc ] .RB [ \-dashstuffing " | " \-nodashstuffing ] .RB [ \-build ] .RB [ \-file .IR msgfile ] .HP 5 .B forw .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RI [ msgs ] .RB [ \-digest .IR list ] .RB [ \-issue .IR number ] .RB [ \-volume .IR number ] [other\ switches\ for .BR forw ] .ad .SH DESCRIPTION .B forw constructs a new message from a forms (components) file, with a body composed of the message(s) to be forwarded. An editor is invoked and, after editing is complete, the user is prompted before the message is sent. .PP The default message template will direct .B forw to construct the draft as follows: .PP .RS 5 .nf From: {from switch} or or To: {to switch} or blank Fcc: {fcc switch} or +outbox Subject: {subject switch} or "{original subject} (fwd)" -------- .fi .RE .PP If a file named .RI \*(lq forwcomps \*(rq exists in the user's nmh directory, it will be used instead of this default form. You may also specify an alternate forms file with the switch .B \-form .IR formfile . Forms are processed via the .B nmh template system; see .IR mh\-format (5) for details. Components from the first forwarded message are available as standard component escapes in the forms file. .PP In addition to the standard .I mh\-format escapes, the following .I component escapes are also supported: .PP .RS 5 .nf .ta \w'nmh\-subject 'u +\w'Returns 'u .I "Escape Returns Description" fcc string Any folders specified with `\-fcc\ folder' nmh\-from string Addresses specified with `\-from\ address' nmh\-to string Addresses specified with `\-to\ address' nmh\-cc string Addresses specified with `\-cc\ address' nmh\-subject string Any text specified with `\-subject\ text' .fi .RE .PP By default, the \*(lqTo:\*(rq and \*(lqcc:\*(rq fields are empty. You may add addresses to these fields with the .B \-to .I address and .B \-cc .I address switches. You may give these switches multiple times to add multiple addresses. .PP By default, the \*(lqFrom:\*(rq field contains either the value of the .B Local\-Mailbox profile entry, or a system default email address. This default can be overridden by using the .B \-from .I address switch. The default mailbox in the \*(lqFcc:\*(rq field is .IR +outbox . This can be overridden by the .B \-fcc switch. .PP Any text given to the .B \-subject switch will be placed in the \*(lqSubject:\*(rq field in the draft. .PP If the draft already exists, .B forw will ask you as to the disposition of the draft. A reply of .B quit will abort .BR forw , leaving the draft intact; .B replace will replace the existing draft with a blank skeleton; and .B list will display the draft. .PP If the .B \-annotate switch is given, each message being forwarded will be annotated with the lines: .PP .RS 5 .nf Forwarded:\ date Forwarded:\ addrs .fi .RE .PP where each address list contains as many lines as required. This annotation will be done only if the message is sent directly from .BR forw . If the message is not sent immediately from .BR forw , .RB \*(lq comp .BR \-use \*(rq may be used to re-edit and send the constructed message, but the annotations won't take place. Normally, annotations are done in place in order to preserve any links to the message. You may change this by using the .B \-noinplace switch. .PP See .IR comp (1) for a description of the .B \-editor and .B \-noedit switches. .PP Although .B forw uses a forms (components) file to construct the initial draft, a message filter file is used to format each forwarded message in the body of the draft. The filter file for \fIforw\fR should be a standard form file for .IR mhl (1), as .B forw will invoke .B mhl to filter (re-format) the forwarded messages prior to being output to the body of the draft. .PP The switches .BR \-noformat , .BR \-format , and .B \-filter .I filterfile specify which message filter file to use. If .B \-noformat is specified (this is the default), then each forwarded message is output into the draft exactly as it appears, with no .B mhl filtering. If .B \-format is specified, then the following default message filter file, .RI \*(lq mhl.forward \*(rq , which should be adequate for most users, is used: .PP .RS 5 .nf %mhl_forward% .fi .RE .PP If a file named .RI \*(lq mhl.forward \*(rq exists in the user's nmh directory, it will be used instead. You may specify an alternate message filter file with the switch .B \-filter .IR filterfile . .PP Each forwarded message is separated with an encapsulation delimiter. By default, any dashes in the first column of the forwarded messages will be prepended with `\-\ ' so that when received, the message is suitable for bursting by .IR burst (1). This follows the guidelines in RFC 934. You may use the .B \-nodashstuffing switch to suppress this form of quoting. .PP Users of .IR prompter (1) can, by specifying .BR prompter 's .B \-prepend switch in the .I \&.mh_profile file, prepend any commentary text before the forwarded messages. .PP To use the MIME rules for encapsulation, specify the .B \-mime switch. This directs .B forw to generate an .B mhbuild composition file. Note that .B nmh will not invoke .B mhbuild automatically; you must specifically give the command .PP .RS 5 .nf What now? mime .fi .RE .PP prior to sending the draft. .PP The .B \-draftfolder .I +folder and .B \-draftmessage .I msg switches invoke the .B nmh draft folder facility. This is an advanced (and highly useful) feature. Consult the .IR mh-draft (5) man page for more information. .PP The .B \-editor .I editor switch indicates the editor to use for the initial edit. Upon exiting from the editor, .B comp will invoke the .B whatnow program. See .IR whatnow (1) for a discussion of available options. The invocation of this program can be inhibited by using the .B \-nowhatnowproc switch. (In fact, it is the .I whatnow program which starts the initial edit. Hence, .B \-nowhatnowproc will prevent any edit from occurring.) .PP The .B \-build switch is intended to be used by the Emacs mh-e interface to .BR nmh . It implies .BR \-nowhatnowproc . It causes a file /draft to be created, containing the draft message that would normally be presented to the user for editing. No mail is actually sent. .PP The .B \-file .I msgfile switch specifies the message to be forwarded as an exact filename rather than as an .B nmh folder and message number. This switch implies .BR \-noannotate . The forwarded message is simply copied verbatim into the draft; the processing implied by the .BR \-filter , .BR \-mime , and .B \-digest switches is bypassed, and the usual leading and trailing 'Forwarded Message' delimiters are not added. The same caveats apply to this option as to the .B \-build switch. .PP The .B \-digest .IR list , .B \-issue .IR number , and .B \-volume .I number switches implement a digest facility for .BR nmh . Specifying these switches enables and/or overloads the following escapes: .PP .RS 5 .nf .ta \w'Component 'u +\w'Escape 'u +\w'Returns 'u .I "Type Escape Returns Description" component digest string Argument to `\-digest' function cur integer Argument to `\-volume' function msg integer Argument to `\-issue' .fi .RE .SH FILES .B forw looks for format and filter files in multiple locations: absolute pathnames are accessed directly, tilde expansion is done on usernames, and files are searched for in the user's .I Mail directory as specified in their profile. If not found there, the directory .RI \*(lq %nmhetcdir% \*(rq is checked. .PP .PD 0 .TP 25 %nmhetcdir%/forwcomps The default message skeleton. .TP /forwcomps The user's message skeleton. .TP %nmhetcdir%/digestcomps The default message skeleton if .B \-digest is given. .TP /digestcomps The user's .B \-digest skeleton. .TP ^%nmhetcdir%/mhl.forward The default message filter. .TP /mhl.forward The user's message filter. .TP ^$HOME/.mh_profile The user's profile. .PD .SH "PROFILE COMPONENTS" .PD 0 .TP 25 Path: To determine the user's nmh directory. .TP Current\-Folder: To find the default current folder. .TP Draft\-Folder: To find the default draft-folder. .TP Editor: To override the default editor. .TP Msg\-Protect: To set mode when creating a new message (draft). .TP fileproc: Program to refile the message. .TP mhlproc: Program to filter messages being forwarded. .TP whatnowproc: Program to ask the \*(lqWhat now?\*(rq questions. .PD .SH "SEE ALSO" .IR burst (1), .IR comp (1), .IR mh\-format (5) .IR mhbuild (1), .IR mhl (1), .IR prompter (1), .IR repl (1), .IR send (1), .IR whatnow (1), .PP .I Proposed Standard for Message Encapsulation (RFC 934) .SH DEFAULTS .PD 0 .TP 25 +folder The current folder. .TP msgs The current message. .TP \-noannotate .TP \-nodraftfolder .TP \-noformat .TP \-inplace .TP \-dashstuffing .TP \-nomime .PD .SH CONTEXT If a folder is given, it will become the current folder. The first message forwarded will become the current message. .SH BUGS If .I whatnowproc is .BR whatnow , then .B forw uses a built-in .BR whatnow , it does not actually run the .B whatnow program. Hence, if you define your own .IR whatnowproc , don't call it .B whatnow since .B forw won't run it. .PP When .B forw is told to annotate the messages it forwards, it doesn't actually annotate them until the draft is successfully sent. If, from the .IR whatnowproc , you .B push instead of .BR send , it is possible to confuse .B forw by re-ordering the file (e.g.\& by using .RB \*(lq folder .BR \-pack \*(rq) before the message is successfully sent. .B dist and .B repl don't have this problem. nmh-1.7.1-RC3/man/fprev.man000644 007761 000024 00000000017 11732520432 015351 0ustar00kenhstaff000000 000000 .so man1/new.1 nmh-1.7.1-RC3/man/inc.man000644 007761 000024 00000021205 13243042053 014777 0ustar00kenhstaff000000 000000 .TH INC %manext1% 2016-11-02 "%nmhversion%" . .\" %nmhwarning% . .SH NAME inc \- incorporate new mail to an nmh folder .SH SYNOPSIS .HP 5 .na .B inc .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RB [ \-audit .IR audit-file ] .RB [ \-noaudit ] .RB [ \-changecur " | " \-nochangecur ] .RB [ \-form .IR formfile ] .RB [ \-format .IR string ] .RB [ \-file .IR name ] .RB [ \-silent " | " \-nosilent ] .RB [ \-truncate " | " \-notruncate ] .RB [ \-width .IR columns ] .RB [ \-host .IR hostname ] .RB [ \-port .IR portname/number ] .RB [ \-user .IR username ] .RB [ \-proxy .IR command ] .RB [ \-sasl " | " \-nosasl ] .RB [ \-saslmech .IR mechanism ] .RB [ \-authservice .IR service ] .RB [ \-initialtls ] .RB [ \-notls ] .RB [ \-certverify " | " \-nocertverify ] .RB [ \-snoop ] .ad .SH DESCRIPTION .B inc incorporates mail from the user's incoming mail drop into an .B nmh folder. If the mail drop is a file, it can be in .B mbox or .B MMDF format. If the mail drop is a directory it is considered to be in .B Maildir format. .PP You may specify which folder to use with .IR +folder . If no folder is specified, then .B inc will use either the folder given by a (non-empty) .RI \*(lq Inbox \*(rq entry in the user's profile, or the folder named .RI \*(lq inbox \*(rq. If the specified (or default) folder doesn't exist, the user will be queried prior to its creation. .PP When the new messages are incorporated into the folder, they are assigned numbers starting with the next highest number for the folder. As the messages are processed, a .B scan listing of the new mail is produced. .PP The newly created messages will have a mode of 0600, see chmod(1), on filesystems that support it. Alternatively, a .RI \*(lq "Msg\-Protect: nnn" \*(rq profile entry gives the mode to use, in octal. For all subsequent operations on these messages, this initially assigned mode will be preserved. .PP If the switch .B \-audit .I audit-file is specified (usually as a default switch in the user's profile), then .B inc will append a header line and a line per message to the specified audit-file with the format: .PP .RS 5 .nf <> date .fi .RE .PP This is useful for keeping track of volume and source of incoming mail. Eventually, .BR repl , .BR forw , .BR comp , and .B dist may also output audit information to this (or another) file, perhaps with .RI \*(lq Message\-Id \*(rq information to keep an exact correspondence history. .RI \*(lq Audit-file \*(rq is assumed to be in the user's nmh directory unless a full path is specified. .PP .B inc will incorporate even improperly formatted messages into the user's nmh folder, inserting a blank line prior to the offending component and printing a comment identifying the bad message. .PP In all cases, except the use of .B \-file .I name (see below), the user's mail drop will be zeroed, unless the .B \-notruncate switch is given. .PP If the profile entry .RI \*(lq Unseen\-Sequence \*(rq is present and non-empty, then .B inc will add each of the newly incorporated messages to each sequence named in the profile entry. .B inc will not zero each sequence prior to adding messages. .PP The interpretation of the .B \-form .IR formatfile , .B \-format .IR string , and .B \-width .I columns switches is the same as in .IR scan (1). .PP By using the .B \-file .I name switch, one can direct .B inc to incorporate messages from a file other than the user's mail drop. Note that the named file will .I not be zeroed, unless the .B \-truncate switch is given. .PP The .B \-file switch does not support the use of standard input. Instead, the .B rcvstore command can be used to incorporate mail from the standard input stream. .PP If the environment variable .B $MAILDROP is set, then .B inc uses it as the location of the user's mail drop instead of the default (the .B -file .I name switch still overrides this, however). If this environment variable is not set, then .B inc will consult the profile entry .RI \*(lq MailDrop \*(rq for this information. If the value found is not absolute, then it is interpreted relative to the user's .B nmh directory. If the value is not found, then .B inc will look in the standard system location for the user's mail drop. .PP The .B \-silent switch directs .B inc to be quiet and not ask any questions at all. This is useful for putting .B inc in the background and going on to other things. .SS "Using POP" .B inc will normally check local mail drops for mail, as covered above. But if the option .RI \*(lq pophost \*(rq is set in .RI \*(lq mts.conf \*(rq, or if the .B \-host .I hostname switch is given, or if the .B $MAILHOST environment variable is set, then .B inc will query this POP service host for mail to incorporate. If .B $MAILHOST is set and .B \-host is specified as well, the command-line switch will override the environment variable. The .B \-port switch specifies the port name or number used to connect to the POP server. If unspecified, the default is \*(lqpop3\*(rq. .PP To specify a username for authentication with the POP server, use the .B \-user .I username switch. The credentials profile entry in .IR mh\-profile (5) describes the ways to supply a username and password. .PP If passed the .B \-proxy .I command switch, .B inc will use the specified command to establish the connection to the POP server. The string .I %h in the command will be substituted by the hostname to connect to. .PP For debugging purposes, you may give the switch .BR \-snoop , which will allow you to monitor the POP transaction. If .B \-sasl \-saslmech xoauth2 is used, the HTTP transaction is also shown. .PP If .B nmh has been compiled with SASL support, the .B \-sasl switch will enable the use of SASL authentication. Depending on the SASL mechanism used, this may require an additional password prompt from the user (but the .I netrc file can be used to store this password, as described in .IR mh\-profile (5)). The .B \-saslmech switch can be used to select a particular SASL mechanism. .PP If SASL authentication is successful, .B inc will attempt to negotiate a security layer for session encryption. Encrypted traffic is labelled with `(encrypted)' and `(decrypted)' when viewing the POP transaction with the .B \-snoop switch; see the .B post man page description of .B \-snoop for its other features. .PP If .B nmh has been compiled with OAuth support, the .B \-sasl and .B \-saslmech xoauth2 switches will enable OAuth authentication. The .B \-user switch must be used, and the .I user-name must be an email address the user has for the service, which must be specified with the .B \-authservice .I service switch. Before using this, the user must authorize nmh by running .B mhlogin and granting authorization to that account. See .IR mhlogin (1) for more details. .PP If .B nmh has been compiled with TLS support, the .B \-initialtls switch will require the negotiation of TLS when connecting to the remote POP server. .B inc will negotiate TLS immediately after the connection has taken place, before any POP commands are sent or received. Data encrypted by TLS is labeled `(tls-encrypted)' and `(tls-decrypted)` when viewing the POP transaction with the .B \-snoop switch. The .B \-notls switch will disable all attempts to negotiate TLS. .PP When using TLS the default is to verify the remote certificate and SubjectName against the local trusted certificate store. This can be controlled by the .B \-certverify and .B \-nocertverify switches. See your OpenSSL documentation for more information on certificate verification. .SH FILES .PD 0 .TP 20 $HOME/.mh_profile The user's profile. .TP %nmhetcdir%/mts.conf mts configuration file. .TP %mailspool%/$USER Location of the system mail drop. .PD .SH "PROFILE COMPONENTS" .PD 0 .TP 20 Path: To determine the user's nmh directory. .TP Alternate\-Mailboxes: To determine the user's mailboxes. .TP Inbox: To determine the inbox. .TP Folder\-Protect: To set mode when creating a new folder. .TP Msg\-Protect: To set mode when creating a new message and audit-file. .TP Unseen\-Sequence: To name sequences denoting unseen messages. .PD .SH "SEE ALSO" .IR mhmail (1), .IR scan (1), .IR mh\-mail (5), .IR mh\-profile (5), .IR mhlogin (1), .IR post (8), .IR rcvstore (1) .SH DEFAULTS .PD 0 .TP 20 +folder defaulted by \*(lqInbox\*(rq above. .TP \-noaudit .TP \-changecur .TP \-format As described above. .TP \-nosilent .TP \-nosasl .TP \-notruncate Unless .B \-file .I name is given. .TP \-width The width of the terminal. .PD .SH CONTEXT The folder into which messages are being incorporated will become the current folder. The first message incorporated will become the current message, unless the .B \-nochangecur option is specified. This leaves the context ready for a .B show of the first new message. nmh-1.7.1-RC3/man/install-mh.man000644 007761 000024 00000003463 13205305704 016307 0ustar00kenhstaff000000 000000 .TH INSTALL-MH %manext1% 2002-11-18 "%nmhversion%" . .\" %nmhwarning% . .SH NAME install-mh \- initialize the nmh environment .SH SYNOPSIS .HP 5 .na .B %nmhlibexecdir%/install\-mh .RB [ \-help ] .RB [ \-version ] .RB [ \-auto ] .RB [ \-check ] .ad .SH DESCRIPTION .B install\-mh creates the initial setup for a first-time .B nmh user. .B install\-mh is installed in two locations for historical reasons. .PP The \fB\-auto\fP switch does things as automatically as possible and makes \fBinstall\-mh\fP less chatty. .PP The user is prompted for the name of the directory to be designated as the user's .B nmh directory. If this directory does not exist, the user is asked if it should be created. Normally, this directory should be under the user's home directory, and has the default name of \fI`Mail'\fP. .B install\-mh writes an initial .I \&.mh_profile for the user. .PP As with all .B nmh commands, .B install\-mh first checks for the existence of the \fB$MH\fP environment variable, since that, if set, gives the profile path. If it isn't set, the .B $HOME environment variable is consulted to determine the user's home directory. If .B $HOME is not set, then the .I /etc/passwd file is consulted. .PP When creating the user's .IR \&.mh_profile , .B install\-mh will check for the existence of a global profile at .IR %nmhetcdir%/mh.profile . If found, this will be used to initialize the new .IR \&.mh_profile . .PP The \fB\-check\fP switch checks if .B nmh is installed. (This can be used by other programs to determine if .B nmh has been installed.) .SH FILES .PD 0 .TP 20 $HOME/.mh_profile The user's profile. .TP %nmhetcdir%/mh.profile Used to initialize user's profile. .PD .SH "PROFILE COMPONENTS" .TP 20 Path: To set the user's nmh directory. .SH CONTEXT With .BR \-auto , the current folder is changed to .RI \*(lq inbox \*(rq. nmh-1.7.1-RC3/man/mark.man000644 007761 000024 00000012630 13243042053 015162 0ustar00kenhstaff000000 000000 .TH MARK %manext1% 2013-03-31 "%nmhversion%" . .\" %nmhwarning% . .SH NAME mark \- manipulate nmh message sequences .SH SYNOPSIS .HP 5 .na .B mark .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RI [ msgs ] .RB [ \-sequence .I name \&...] .RB [ \-add " | " \-delete ] .RB [ \-list ] .RB [ \-public " | " \-nopublic ] .RB [ \-zero " | " \-nozero ] .ad .SH DESCRIPTION The .B mark command manipulates message sequences by adding or deleting message numbers from folder-specific message sequences, or by listing those sequences and messages. .PP A message sequence is a keyword, just like one of the \*(lqreserved\*(rq message names, such as \*(lqfirst\*(rq or \*(lqnext\*(rq. Unlike the \*(lqreserved\*(rq message names, which have a fixed semantics on a per-folder basis, the semantics of a message sequence may be defined, modified, and removed by the user. Message sequences are folder-specific, e.g., the sequence name \*(lqseen\*(rq in the context of folder .RI \*(lq +inbox \*(rq need not have any relation whatsoever to the sequence of the same name in a folder of a different name. .PP Three action switches direct the operation of .BR mark . These switches are mutually exclusive: the last occurrence of any of them overrides any previous occurrence of the other two. .PP The .B \-add switch tells .B mark to add messages to sequences or to create a new sequence. For each sequence named via the .B \-sequence .I name argument (which must occur at least once) the messages named via .I msgs (which defaults to \*(lqcur\*(rq if no .I msgs are given), are added to the sequence. The messages to be added need not be absent from the sequence. If the .B \-zero switch is specified, the sequence will be emptied prior to adding the messages. Hence, .B \-add .B \-zero means that each sequence should be initialized to the indicated messages, while .B \-add .B \-nozero means that each sequence should be appended to by the indicated messages. .PP The .B \-delete switch tells .B mark to delete messages from sequences, and is the dual of .BR \-add . For each of the named sequences, the named messages are removed from the sequence. These messages need not be already present in the sequence. If the .B \-zero switch is specified, then all messages in the folder are added to the sequence (first creating the sequence, if necessary) before removing the messages. Hence, .B \-delete .B \-zero means that each sequence should contain all messages except those indicated, while .B \-delete .B \-nozero means that only the indicated messages should be removed from each sequence. As expected, the command .RB \*(lq mark .B \-sequence .I foo .B \-delete all\*(rq empties the sequence \*(lqfoo\*(rq, and therefore removes that sequence from the current folder's list of sequences. .PP When creating or modifying sequences, you can specify the switches .B \-public or .B \-nopublic to force the new or modified sequences to be \*(lqpublic\*(rq or \*(lqprivate\*(rq. The switch .B \-public indicates that the sequences should be made \*(lqpublic\*(rq. These sequences will then be readable by all .B nmh users with permission to read the relevant folders. In contrast, the .B \-nopublic switch indicates that the sequences should be made \*(lqprivate\*(rq, and will only be accessible by you. If neither of these switches is specified, then existing sequences will maintain their current status, and new sequences will default to \*(lqpublic\*(rq if you have write permission for the relevant folder. Check the .IR mh\-sequence (5) man page for more details about the difference between \*(lqpublic\*(rq and \*(lqprivate\*(rq sequences. .PP The .B \-list switch tells .B mark to list both the sequences defined for the folder and the messages associated with those sequences. .B mark will list the name of each sequence given by .B \-sequence .I name and the messages associated with that sequence. If the sequence is private, this will also be indicated. If no sequence is specified by the .B \-sequence switch, then all sequences for this folder will be listed. The .B \-zero switch does not affect the operation of .BR \-list . .PP The restrictions on sequences are: .PP .IP \(bu 2 The name used to denote a message sequence must consist of an alphabetic character followed by zero or more alphanumeric characters, and cannot be one of the (reserved) message names \*(lqnew\*(rq, \*(lqfirst\*(rq, \*(lqlast\*(rq, \*(lqall\*(rq, \*(lqnext\*(rq, or \*(lqprev\*(rq. .PP .IP \(bu 2 Message ranges with user-defined sequence names are restricted to the form \*(lqname:n\*(rq, \*(lqname:+n\*(rq, or \*(lqname:-n\*(rq, and refer to the first or last `n' messages of the sequence `name', respectively. Constructs of the form \*(lqname1\-name2\*(rq are forbidden for user defined sequences. .SH FILES .TP 20 $HOME/.mh_profile The user's profile. .SH "PROFILE COMPONENTS" .PD 0 .TP 20 Path: To determine the user's nmh directory. .TP Current\-Folder: To find the default current folder. .PD .SH "SEE ALSO" .IR flist (1), .IR pick (1), .IR mh-sequence (5) .SH DEFAULTS .PD 0 .TP 20 +folder The current folder. .TP \-add If .B \-sequence is specified, .B \-list otherwise. .TP msgs The current message, or .B all if .B \-list is specified. .TP \-nozero .PD .SH CONTEXT If a folder is given, it will become the current folder. .SH "HELPFUL HINTS" Use .B flist to find folders with a given sequence, and .RB \*(lq pick .I sequence .BR \-list \*(rq to enumerate those messages in the sequence (such as for use by a shell script). nmh-1.7.1-RC3/man/mh-alias.man000644 007761 000024 00000010412 13205305704 015722 0ustar00kenhstaff000000 000000 .TH MH-ALIAS %manext5% 2014-04-18 "%nmhversion%" . .\" %nmhwarning% . .SH NAME mh-alias \- format of nmh email-address alias files .SH DESCRIPTION .PP Each line of an .B nmh alias file takes one of the following forms: .PP .RS 5 .I alias .B : .I address-group .RE .sp .RS 5 .I alias .B ; .I address-group .RE .sp .RS 5 .B < .I alias-file .RE .sp .RS 5 .B ; | .B : | .B # .I comment .RE .PP where: .PP .RS 5 .nf .IR address-group " := " address-list .RI " | < " file .IR address-list " := " address .RI " | " address-list ", " address .fi .RE .PP Continuation lines end with \*(lq\\\*(rq followed by a newline character. This also applies to comment lines. Thus, the line following a \*(lq\\\*(rq-terminated comment line is a continuation of that comment line. .PP .I Alias-file and .I file are Unix file names. Alias file contents are case-insensitive, with the exception of filesystem path names. .PP If the line starts with a \*(lq<\*(rq, the file named after the \*(lq<\*(rq is read for more alias definitions. The reading is done recursively, so a \*(lq<\*(rq may occur in the beginning of an alias file with the expected results. .PP If the .I address-group starts with a \*(lq<\*(rq, the file named after the \*(lq<\*(rq is read and its contents are added to the .I address-list for the alias. .PP In match, a trailing \*(lq*\*(rq on an alias will match just about anything appropriate. .PP An approximation of the way aliases are resolved at posting time is: .IP 1) Build a list of all addresses from the message to be delivered, eliminating duplicate addresses. .IP 2) For those addresses in the message that have no host specified, perform alias resolution. .IP 3) For each line in the alias file, compare \*(lqalias\*(rq against all of the existing addresses. If a match, remove the matched \*(lqalias\*(rq from the address list, and add each new address in the address-group to the address list if it is not already on the list. The alias itself is not usually output, rather the address-group that the alias maps to is output instead. If \*(lqalias\*(rq is terminated with a \*(lq;\*(rq instead of a \*(lq:\*(rq, then both the \*(lqalias\*(rq and the address are output in the correct format (with the alias quoted if necessary and the address wrapped in <>). .PP Since the .I mh-alias file is read line by line, forward references work, but backward references are not recognized. .SS Example Alias File .PP .RS 5 .nf <%nmhetcdir%/BBoardAliases sgroup: fred, fear, freida fred: frated@UCI.example b-people: Blind List: bill, betty Unix\-committee: /dev/null; then #### Extract lines from just after .SH SYNOPSIS to just before .ad. #### Filter out the "typical usage:" section in pick.man. awk '/.SH SYNOPSIS/,/^(\.ad|typical usage:)/ { if ($0 !~ /^(\.SH SYNOPSIS|\.na|\.ad|typical usage:)/) print }' "$i" echo fi ;; esac done cat <<'EOF' .ad .SH "SEE ALSO" .IR nmh (7), .IR mh\-mime (7) EOF nmh-1.7.1-RC3/man/mh-draft.man000644 007761 000024 00000014323 13243042053 015733 0ustar00kenhstaff000000 000000 .TH MH-DRAFT %manext5% 2012-03-18 "%nmhversion%" . .\" %nmhwarning% . .SH NAME mh-draft \- draft folder facility for nmh message system .SH DESCRIPTION There are a number of interesting advanced facilities for the composition of outgoing mail. .SS "The Draft Folder" The .BR comp , .BR dist , .BR forw , .BR repl , .BR send , and .B whom commands each take the switches .B \-draftfolder .I +folder and .B \-draftmessage .IR msg , which allow you to manipulate the various draft messages you are composing. .PP If .B \-draftfolder .I +folder is used, draft messages will be constructed in the indicated folder. The .RI \*(lq Draft\-Folder \*(rq profile entry may be used to specify a default draft folder. .PP If the switch .B \-draftmessage .I msg is given, the specified draft is used to compose the message. If .B \-draftmessage .I msg is not used, then the draft defaults to `new' (create a new draft) unless the user invokes .B comp with .BR \-use , in which case the default is `cur'. .PP Hence, the user may have several message compositions in progress simultaneously. Now, all of the .B nmh tools are available on each of the user's message drafts (e.g. .BR show , .BR scan , .BR pick , and so on). If the folder does not exist, the user is asked if it should be created (just like with .BR refile ). The last draft message the user was composing is known as `cur' in the draft folder. .PP Using .BR send , the user can send drafts using the standard .B nmh `msgs' convention with .B \-draftmessage .IR msgs . If no `msgs' are given, it defaults to `cur'. .PP In addition, all of these programs have a .B \-nodraftfolder switch, which undoes the last occurrence of .B \-draftfolder .I folder (useful if a default is specified in the user's .B nmh profile). .PP If the user does not give the .B \-draftfolder .I +folder switch, then all these commands act \*(lqnormally\*(rq. Note that the .B \-draft switch to .B send and .B show still refers to the file called `draft' in the user's .B nmh directory. In the interests of economy of expression, when using .B comp or .BR send , the user needn't prefix the draft `msg' or `msgs' with .BR \-draftmessage . Both of these commands accept a `file' or `files' argument and they will, if given .B \-draftfolder .IR +folder , treat these arguments as `msg' or `msgs'. (This may appear to be inconsistent, at first, but it saves a lot of typing.) Hence, .PP .RS .nf send -draftfolder +drafts first .fi .RE .PP is the same as .PP .RS .nf send -draftfolder +drafts -draftmessage first .fi .RE .PP To make all this a bit more clear, here are some examples. Let's assume that the following entries are in the .B nmh profile: .PP .RS 5 .nf Draft\-Folder: drafts sendf: \-draftfolder +drafts .fi .RE .PP Furthermore, let's assume that the program .B sendf is a (symbolic) link in the user's .I $HOME/bin/ directory to .BR send . Now, .PP .RS 5 .nf comp dist forw repl .fi .RE .PP will construct the message draft in the `draft' folder using the `new' message number. Furthermore, they each define `cur' in this folder to be that message draft. If the user were to use the .B quit option at the `What now?' prompt, then later on, if no other draft composition was done, the draft could be sent with simply .PP .RS 5 .nf sendf .fi .RE .PP Or, if more editing was required, the draft could be edited with .PP .RS 5 .nf comp -use .fi .RE .PP If other drafts had been composed in the meantime, so that this message draft was no longer known as `cur' in the `draft' folder, then the user could .B scan the folder to see which message draft should be used for editing or sending. Clever users could even employ a backquoted .B pick to do the work: .PP .RS 5 .nf comp -use `pick +drafts -to nmh-workers` .fi .RE .PP or .PP .RS 5 .nf sendf `pick +drafts -to nmh-workers` .fi .RE .PP Note that in the .B comp example, the output from .B pick must resolve to a single message draft (it makes no sense to talk about composing two or more drafts with one invocation of .BR comp ). In contrast, in the .B send example, as many message drafts as desired can appear, since .B send doesn't mind sending more than one draft at a time. .PP Note that the argument .B \-draftfolder .I +folder is not included in the profile entry for .BR send , since when .BR comp , et al, invoke .B send directly, they supply .B send with the Unix pathname of the message draft; .I not a .B \-draftmessage .I msg argument. As far as .B send is concerned, a draft folder is not being used. .PP It is important to realize that .B nmh treats the draft folder like a standard .B nmh folder in nearly all respects. There are two exceptions: .PP First, under no circumstances will the .B \-draftfolder .I folder switch cause the named folder to become the current folder. Obviously, if the folder appeared in the context of a standard .I +folder argument to an .B nmh program, as in .PP .RS 5 .nf scan +drafts .fi .RE .PP it might become the current folder, depending on the context changes of the .B nmh program in question. .PP Second, although conceptually .B send deletes the `msgs' named in the draft folder, it does not call .I delete\-prog to perform the deletion. .SS "What Happens if the Draft Exists" When the .BR comp , .BR dist , .BR forw , and .B repl commands are invoked and the draft you indicated already exists, these programs will prompt the user for a response directing the program's action. The prompt is .PP .RS 5 .nf Draft ``/home/foobar/nmhbox/draft'' exists (xx bytes). Disposition? .fi .RE .PP The appropriate responses and their meanings are: .PP .RS 5 .PD 0 .TP 10 .B replace deletes the draft and starts afresh .TP .B list lists the draft .TP .B refile files the draft into a folder and starts afresh .TP 10 .B quit leaves the draft intact and exits .PD .RE .PP In addition, if you specified .B \-draftfolder .I folder to the command, then one other response will be accepted: .PP .RS 5 .PD 0 .TP 10 .B new creates a new draft .PD .RE .PP just as if .B \-draftmessage .I new had been given. Finally, the .B comp command will accept one more response: .PP .RS 5 .PD 0 .TP 10 .B use re-uses the draft .PD .RE .PP just as if .B \-use had been given. .SH FILES .PP .TP 20 $HOME/.mh_profile The user's profile. .SH "PROFILE COMPONENTS" .PP .PD 0 .TP 20 Draft\-Folder: For a default draft folder .PD .SH CONTEXT None nmh-1.7.1-RC3/man/mh-folders.man000644 007761 000024 00000011757 13243042053 016301 0ustar00kenhstaff000000 000000 .TH MH-FOLDERS %manext5% 2016-02-25 "%nmhversion%" . .\" %nmhwarning% . .SH NAME mh-folders \- storage format used by nmh message system .SH DESCRIPTION .B nmh stores messages in the files and directories of the host filesystem according to the following rules: .PP .B one folder per directory .RS 5 An .B nmh folder corresponds to a directory. There are no limits on folder names beyond those of the host filesystem. .RE .PP .B one message per file .RS 5 The file name is a positive integer. Other files containing metadata or arbitrary names can exist in a folder; while the preference is that non-message files begin with \*(lq.\*(rq, all files that are not positive integers .I must be ignored by an .BR MH \-compatible implementation. However, implementations are free to indicate to the user the existence of non-message files that are not prefixed with a \*(lq.\*(rq. .PP The filename for a new message is one greater than the highest numbered message in the folder; its full path can be accessed by the pseudo-sequence .I new (e.g., .B mhpath .IR new ). New messages are .I only permitted to be added to a folder at the end of the message number range. .PP To add a new message to a folder, the recommended sequence is: .IP \(bu 4 Create a temporary file in the desired folder. .IP \(bu 4 Attempt to link the temporary file to the new message number. .IP \(bu 4 If successful, remove the temporary file. If the link fails, increment the message number and try again. .RE .B context .RS 5 There is one context file. Its default location is in the user's Path and its default name is .IR context , but these can be overridden by the $MHCONTEXT environment variable. .B context has the following format: .PP .RS 5 .BI "Current-Folder: +" folder .RE .RS 5 .BI "atr-" sequence-path ": " "m[-n] [...]" .RE .PP where .I folder is the directory name of the current folder. Lines beginning with \*(lqatr\*(rq are used for private sequences. .I sequence is the name of the private sequence, .I path is the full path to the folder with the private sequence, and .I m[-n] is a message number or range of message numbers in the sequence. .RE .PP .B sequences .RS 5 There is one sequences file in each .B nmh folder. Its default name is .IR \&.mh_sequences , but this can be overridden by the \*(lqmh\-sequences\*(rq profile entry. .B sequences has the following format: .PP .RS 5 .BI "sequence: " "m[-n] [...]" .RE .PP showing the (possibly empty) message numbers and/or ranges of message numbers in each sequence. The .B cur sequence has at most just a single message number, not a range. .PP Sequence names have a maximum size of 998 characters. Each line is also limited to a maximum of 998 characters, but RFC 822 continuation rules apply; sequences can be continued across multiple lines by prefixing continuation lines with a whitespace character. .PP If an implementation finds messages in a sequence that do not exist, the sequence file should be updated to remove the missing messages from the sequence. If a sequence contains no messages, it should be removed from the sequence file. The exception to this is the .B cur sequence, which can refer to a nonexistent message. .RE .SS Locking .B nmh programs read and write the context and sequences files, and lock these files when accessing them. There should not be a need to access these files directly; instead, programs such as .BR flist , .BR folder , .BR mark , .BR pick , and .B rcvstore should be used to query and update their contents. Any program outside of .B nmh that accesses these files must be sure to lock them using the same locking method as .BR nmh . The default data locking method is selected when .B nmh is configured and can be accessed as a string using .BR "mhparam datalocking" . By default, fcntl locking is used, but this may be overridden by the .B datalocking profile entry. .PP A second, possibly different, locking method is used by .BR inc (1) when accessing the user's mail spool file or by .B nmh programs that open any mbox file. This locking method can be overridden when .B nmh is configured, or in the .B nmh mts configuration file, and can be accessed as a string using .BR "mhparam spoollocking" . By default, kernel-level locking is used if appropriate for the platform, and it is for popular platforms. That default should also be the same as used by the .B mail program, if provided on the platform. .SS Naming .B nmh folders can be given arbitrary names, with one exception: folders should not be given all-numeric names. This limitation results from .B nmh messages themselves being stored in numerically named files -- allowing folders to be named similarly would make .B nmh slower, and introduce usage ambiguities. .SH FILES .PD 0 .TP 20 /context The user's context. .TP 20 $MHCONTEXT Overrides the above context. .TP 20 /.mh\-sequences Public sequences for . .SH "SEE ALSO" .IR flist (1), .IR folder (1), .IR mail (1), .IR mark (1), .IR mhparam (1), .IR mhpath (1), .IR mh\-profile (5), .IR mh\-sequence (5), .IR mh\-tailor (5), .IR pick (1), .IR rcvstore (1) nmh-1.7.1-RC3/man/mh-format.man000644 007761 000024 00000060656 13243042053 016135 0ustar00kenhstaff000000 000000 .TH MH-FORMAT %manext5% 2015-01-10 "%nmhversion%" . .\" %nmhwarning% . .SH NAME mh-format \- formatting language for nmh message system .SH DESCRIPTION Several .B nmh commands utilize either a .I format string or a .I format file during their execution. For example, .B scan uses a format string to generate its listing of messages; .B repl uses a format file to generate message replies, and so on. .PP There are a number of scan listing formats available, including .IR nmh/etc/scan.time , .IR nmh/etc/scan.size , and .IR nmh/etc/scan.timely . Look in .I %nmhetcdir% for other .B scan and .B repl format files which may have been written at your site. .PP You can have your local .B nmh expert write new format commands or modify existing ones, or you can try your hand at it yourself. This manual section explains how to do that. Note: some familiarity with the C .B printf routine is assumed. .PP A format string consists of ordinary text combined with special, multi-character, escape sequences which begin with `%'. When specifying a format string, the usual C backslash characters are honored: `\\b', `\\f', `\\n', `\\r', and `\\t'. Continuation lines in format files end with `\\' followed by the newline character. A literal `%' can be inserted into a format file by using the sequence `%%'. .\" TALK ABOUT SYNTAX FIRST, THEN SEMANTICS .SS SYNTAX Format strings are built around .IR "escape sequences" . There are three types of escape sequence: header .IR components , built-in .IR functions , and flow .IR control . Comments may be inserted in most places where a function argument is not expected. A comment begins with `%;' and ends with a (non-escaped) newline. .SS "Component escapes" A .I component escape is specified as .RI `%{ component }', and exists for each header in the message being processed. For example, .RI `%{ date }' refers to the \*(lqDate:\*(rq field of the message. All component escapes have a string value. Such values are usually compressed by converting any control characters (tab and newline included) to spaces, then eliding any leading or multiple spaces. Some commands, however, may interpret some component escapes differently; be sure to refer to each command's manual entry for details. Some commands (such as .IR ap (8) and .IR mhl (1) ) use a special component .RI `%{ text }' to refer to the text being processed; see their respective man pages for details and examples. .SS "Function escapes" A .I function escape is specified as .RI `%( function )'. All functions are built-in, and most have a string or integer value. A function escape may take an .IR argument . The argument follows the function escape (and any separating whitespace is discarded) as in the following example: .PP .RS 5 .nf .RI %( function " " argument ) .fi .RE .PP In addition to literal numbers or strings, the argument to a function escape can be another function, or a component, or a control escape. When the argument is a function or a component, the argument is specified without a leading `%'. When the argument is a control escape, it is specified with a leading `%'. .SS "Control escapes" A .I control escape is one of: `%<', `%?', `%|', or `%>'. These are combined into the conditional execution construct: .PP .RS 5 .nf .RI "%< " condition " " "format-text" .RI "%? " condition " " "format-text" ... .RI "%| " "format-text" %> .fi .RE .PP (Extra white space is shown here only for clarity.) These constructs, which may be nested without ambiguity, form a general .B if-elseif-else-endif block where only one of the format-texts is interpreted. In other words, `%<' is like the "if", `%?' is like the "elseif", `%|' is like "else", and `%>' is like "endif". .PP A `%<' or `%?' control escape causes its condition to be evaluated. This condition is a .I component or .IR function . For components and functions whose value is an integer, the condition is true if it is non-zero, and false if zero. For components and functions whose value is a string, the condition is true it is a non-empty string, and false if an empty string. .PP The `%?' control escape is optional, and can be used multiple times in a conditional block. The `%|' control escape is also optional, but may only be used once. .SS "Function escapes" Functions expecting an argument generally require an argument of a particular type. In addition to the integer and string types, these include: .PP .RS 5 .nf .ta +\w'Argument 'u +\w'An optional component, 'u .I "Argument Description Example Syntax" literal A literal number %(\fIfunc\fR 1234) or string %(\fIfunc\fR text string) comp Any component %(\fIfunc\fR\^{\fIin-reply-to\fR\^}) date A date component %(\fIfunc\fR\^{\fIdate\fR\^}) addr An address component %(\fIfunc\fR\^{\fIfrom\fR\^}) expr Nothing %(\fIfunc\fR) or a subexpression %(\fIfunc\fR\^(\fIfunc2\fR\^)) or control escape %(\fIfunc\fR %<{\fIreply-to\fR\^}%|%{\fIfrom\fR\^}%>) .fi .RE .PP The .I date and .I addr types have the same syntax as the component type, .IR comp , but require a header component which is a date, or address, string, respectively. .PP Most arguments not of type .I expr are required. When escapes are nested (via expr arguments), evaluation is done from innermost to outermost. As noted above, for the .I expr argument type, functions and components are written without a leading `%'. Control escape arguments must use a leading `%', preceded by a space. .PP For example, .PP .RS 5 .nf %<(mymbox{from}) To: %{to}%> .fi .RE .PP writes the value of the header component \*(lqFrom:\*(rq to the internal register named str; then (\fImymbox\fR\^) reads str and writes its result to the internal register named .IR num ; then the control escape, `%<', evaluates .IR num . If .I num is non-zero, the string \*(lqTo:\*(rq is printed followed by the value of the header component \*(lqTo:\*(rq. .SS Evaluation The evaluation of format strings is performed by a small virtual machine. The machine is capable of evaluating nested expressions (as described above) and, in addition, has an integer register .IR num , and a text string register .IR str . When a function escape that accepts an optional argument is processed, and the argument is not present, the current value of either .I num or .I str is substituted as the argument: the register used depends on the function, as listed below. .PP Component escapes write the value of their message header in .IR str . Function escapes write their return value in .I num for functions returning integer or boolean values, and in .I str for functions returning string values. (The boolean type is a subset of integers, with usual values 0=false and 1=true.) Control escapes return a boolean value, setting .I num to 1 if the last explicit condition evaluated by a `%<' or `%?' control escape succeeded, and 0 otherwise. .PP All component escapes, and those function escapes which return an integer or string value, evaluate to their value as well as setting .I str or .IR num . Outermost escape expressions in these forms will print their value, but outermost escapes which return a boolean value do not result in printed output. .SS Functions The function escapes may be roughly grouped into a few categories. .PP .RS 5 .nf .ta \w'Fformataddr 'u +\w'Aboolean 'u +\w'Rboolean 'u .I "Function Argument Return Description" msg integer message number cur integer message is current (0 or 1) unseen integer message is unseen (0 or 1) size integer size of message strlen integer length of \fIstr\fR width integer column width of terminal charleft integer bytes left in output buffer timenow integer seconds since the Unix epoch me string the user's mailbox (username) myhost string the user's local hostname myname string the user's name localmbox string the complete local mailbox eq literal boolean \fInum\fR == \fIarg\fR ne literal boolean \fInum\fR != \fIarg\fR gt literal boolean \fInum\fR > \fIarg\fR match literal boolean \fIstr\fR contains \fIarg\fR amatch literal boolean \fIstr\fR starts with \fIarg\fR plus literal integer \fIarg\fR plus \fInum\fR minus literal integer \fIarg\fR minus \fInum\fR multiply literal integer \fInum\fR multiplied by \fIarg\fR divide literal integer \fInum\fR divided by \fIarg\fR modulo literal integer \fInum\fR modulo \fIarg\fR num literal integer Set \fInum\fR to \fIarg\fR. num integer Set \fInum\fR to zero. lit literal string Set \fIstr\fR to \fIarg\fR. lit string Clear \fIstr\fR. getenv literal string Set \fIstr\fR to environment value of \fIarg\fR profile literal string Set \fIstr\fR to profile component \fIarg\fR value .\" dat literal int return value of dat[arg] nonzero expr boolean \fInum\fR is non-zero zero expr boolean \fInum\fR is zero null expr boolean \fIstr\fR is empty nonnull expr boolean \fIstr\fR is non-empty void expr Set \fIstr\fR or \fInum\fR comp comp string Set \fIstr\fR to component text compval comp integer Set \fInum\fR to \*(lq\fBatoi\fR(\fIcomp\fR\^)\*(rq .\" compflag comp integer Set \fInum\fR to component flags bits (internal) .\" decodecomp comp string Set \fIstr\fR to RFC 2047 decoded component text decode expr string decode \fIstr\fR as RFC 2047 (MIME-encoded) component unquote expr string remove RFC 2822 quotes from \fIstr\fR trim expr trim trailing whitespace from \fIstr\fR kilo expr string express in SI units: 15.9K, 2.3M, etc. %(kilo) scales by factors of 1000, kibi expr string express in IEC units: 15.5Ki, 2.2Mi. %(kibi) scales by factors of 1024. putstr expr print \fIstr\fR putstrf expr print \fIstr\fR in a fixed width putnum expr print \fInum\fR putnumf expr print \fInum\fR in a fixed width putlit expr print \fIstr\fR without space compression zputlit expr print \fIstr\fR without space compression; \fIstr\fR must occupy no width on display bold string set terminal bold mode underline string set terminal underlined mode standout string set terminal standout mode resetterm string reset all terminal attributes hascolor boolean terminal supports color fgcolor literal string set terminal foreground color bgcolor literal string set terminal background color formataddr expr append \fIarg\fR to \fIstr\fR as a (comma separated) address list concataddr expr append \fIarg\fR to \fIstr\fR as a (comma separated) address list, including duplicates, see Special Handling putaddr literal print \fIstr\fR address list with \fIarg\fR as optional label; get line width from \fInum\fR .fi .RE .PP The (\fIme\fR\^) function returns the username of the current user. The (\fImyhost\fR\^) function returns the .B localname entry in .IR mts.conf , or the local hostname if .B localname is not configured. The (\fImyname\fR\^) function will return the value of the .B SIGNATURE environment variable if set, otherwise it will return the passwd GECOS field (truncated at the first comma if it contains one) for the current user. The (\fIlocalmbox\fR\^) function will return the complete form of the local mailbox, suitable for use in a \*(lqFrom\*(rq header. It will return the .RI \*(lq Local-Mailbox \*(rq profile entry if there is one; if not, it will be equivalent to: .PP .RS 5 .nf %(myname) <%(me)@%(myhost)> .fi .RE .PP The following functions require a date component as an argument: .PP .RS 5 .nf .ta \w'Fformataddr 'u +\w'Aboolean 'u +\w'Rboolean 'u .I "Function Argument Return Description" sec date integer seconds of the minute min date integer minutes of the hour hour date integer hours of the day (0-23) wday date integer day of the week (Sun=0) day date string day of the week (abbrev.) weekday date string day of the week sday date integer day of the week known? (1=explicit,0=implicit,\-1=unknown) mday date integer day of the month yday date integer day of the year mon date integer month of the year month date string month of the year (abbrev.) lmonth date string month of the year year date integer year (may be > 100) zone date integer timezone in minutes tzone date string timezone string szone date integer timezone explicit? (1=explicit,0=implicit,\-1=unknown) date2local date coerce date to local timezone date2gmt date coerce date to GMT dst date integer daylight savings in effect? (0 or 1) clock date integer seconds since the Unix epoch rclock date integer seconds prior to current time tws date string official RFC 822 rendering pretty date string user-friendly rendering nodate date integer returns 1 if date is invalid .fi .RE .PP The following functions require an address component as an argument. The return value of functions noted with `*' is computed from the first address present in the header component. .PP .RS 5 .nf .ta \w'Fformataddr 'u +\w'Aboolean 'u +\w'Rboolean 'u .I "Function Argument Return Description" proper addr string official RFC 822 rendering friendly addr string user-friendly rendering addr addr string mbox@host or host!mbox rendering* pers addr string the personal name* note addr string commentary text* mbox addr string the local mailbox* mymbox addr integer list has the user's address? (0 or 1) getmymbox addr string the user's (first) address, with personal name getmyaddr addr string the user's (first) address, without personal name host addr string the host domain* nohost addr integer no host was present (0 or 1)* type addr integer host type* (0=local,1=network, \-1=uucp,2=unknown) path addr string any leading host route* ingrp addr integer address was inside a group (0 or 1)* gname addr string name of group* .fi .RE .PP (A clarification on (\fImymbox\fR\^{\fIcomp\fR\^}) is in order. This function checks each of the addresses in the header component \*(lq\fIcomp\fR\*(rq against the user's mailbox name and any .RI \*(lq Alternate-Mailboxes \*(rq. It returns true if any address matches. However, it also returns true if the \*(lq\fIcomp\fR\*(rq header is not present in the message. If needed, the (\fInull\fR\^) function can be used to explicitly test for this case.) .SS Formatting When a function or component escape is interpreted and the result will be printed immediately, an optional field width can be specified to print the field in exactly a given number of characters. For example, a numeric escape like %4(\fIsize\fR\^) will print at most 4 digits of the message size; overflow will be indicated by a `?' in the first position (like `?234'). A string escape like %4(\fIme\fR\^) will print the first 4 characters and truncate at the end. Short fields are padded at the right with the fill character (normally, a blank). If the field width argument begins with a leading zero, then the fill character is set to a zero. .PP The functions (\fIputnumf\fR\^) and (\fIputstrf\fR\^) print their result in exactly the number of characters specified by their leading field width argument. For example, %06(\fIputnumf\fR\^(\fIsize\fR\^)) will print the message size in a field six characters wide filled with leading zeros; %14(\fIputstrf\^\fR{\fIfrom\^\fR}) will print the \*(lqFrom:\*(rq header component in fourteen characters with trailing spaces added as needed. Using a negative value for the field width causes right-justification within the field, with padding on the left up to the field width. Padding is with spaces except for a left-padded .I putnumf when the width starts with zero. The functions (\fIputnum\fR\^) and (\fIputstr\fR\^) are somewhat special: they print their result in the minimum number of characters required, and ignore any leading field width argument. The (\fIputlit\fR\^) function outputs the exact contents of the str register without any changes such as duplicate space removal or control character conversion. Similarly, the (\fIzputlit\fR\^) function outputs the exact contents of the str register, but requires that those contents not occupy any output width. It can therefore be used for outputting terminal escape sequences. .PP There are a limited number of function escapes to output terminal escape sequences. These sequences are retrieved from the .IR terminfo (5) database according to the current terminal setting. The (\fIbold\fR\^), (\fIunderline\fR\^), and (\fIstandout\fR\^) escapes set bold mode, underline mode, and standout mode respectively. (\fIhascolor\fR\^) can be used to determine if the current terminal supports color. (\fIfgcolor\fR\^) and (\fIbgcolor\fR\^) set the foreground and background colors respectively. Both of these escapes take one literal argument, the color name, which can be one of: black, red, green, yellow, blue, magenta, cyan, white. (\fIresetterm\fR\^) resets all terminal attributes to their default setting. These terminal escapes should be used in conjunction with (\fIzputlit\fR\^) (preferred) or (\fIputlit\fR\^), as the normal (\fIputstr\fR\^) function will strip out control characters. .PP The available output width is kept in an internal register; any output exceeding this width will be truncated. The one exception to this is that (\fIzputlit\fR\^) functions will still be executed if a terminal reset code is being placed at the end of a line. .SS Special Handling Some functions have different behavior depending on the command they are invoked from. .PP In .B repl the (\fIformataddr\fR\^) function stores all email addresses encountered into an internal cache and will use this cache to suppress duplicate addresses. If you need to create an address list that includes previously-seen addresses you may use the (\fIconcataddr\fR\^) function, which is identical to (\fIformataddr\fR\^) in all other respects. Note that (\fIconcataddr\fR\^) does .I not add addresses to the duplicate-suppression cache. .SS Other Hints and Tips Sometimes, the writer of a format function is confused because output is duplicated. The general rule to remember is simple: If a function or component escape begins with a `%', it will generate text in the output file. Otherwise, it will not. .PP A good example is a simple attempt to generate a To: header based on the From: and Reply-To: headers: .PP .RS 5 .nf %(formataddr %<{reply-to}%|%{from})%(putaddr To: ) .fi .RE .PP Unfortunately, if the Reply-to: header is .I not present, the output line will be something like: .PP .RS 5 .nf My From User To: My From User .fi .RE .PP What went wrong? When performing the test for the .B if clause (%<), the component is not output because it is considered an argument to the .B if statement (so the rule about not starting with % applies). But the component escape in our .B else statement (everything after the `%|') is .I not an argument to anything; it begins with a %, and thus the value of that component is output. This also has the side effect of setting the .I str register, which is later picked up by the (\fIformataddr\fR\^) function and then output by (\fIputaddr\fR\^). The example format string above has another bug: there should always be a valid width value in the .I num register when (\fIputaddr\fR\^) is called, otherwise bad formatting can take place. .PP The solution is to use the (\fIvoid\fR\^) function; this will prevent the function or component from outputting any text. With this in place (and using (\fIwidth\fR\^) to set the .I num register for the width) a better implementation would look like: .PP .RS 3 .nf %(formataddr %<{reply-to}%|%(void{from})%(void(width))%(putaddr To: ) .fi .RE .PP It should be noted here that the side effects of function and component escapes are still in force and, as a result, each component test in the .B if-elseif-else-endif clause sets the .I str register. .PP As an additional note, the (\fIformataddr\fR\^) and (\fIconcataddr\fR\^) functions have special behavior when it comes to the .I str register. The starting point of the register is saved and is used to build up entries in the address list. .PP You will find the .IR fmttest (1) utility invaluable when debugging problems with format strings. .SS Examples With all the above in mind, here is a breakdown of the default format string for .BR scan . The first part is: .PP .RS .nf %4(msg)%<(cur)+%| %>%<{replied}\-%?{encrypted}E%| %> .fi .RE .PP which says that the message number should be printed in four digits. If the message is the current message then a `+', else a space, should be printed; if a \*(lqReplied:\*(rq field is present then a `\-', else if an \*(lqEncrypted:\*(rq field is present then an `E', otherwise a space, should be printed. Next: .PP .RS .nf %02(mon{date})/%02(mday{date}) .fi .RE .PP the month and date are printed in two digits (zero filled) separated by a slash. Next, .PP .RS 5 .nf %<{date} %|*%> .fi .RE .PP If a \*(lqDate:\*(rq field is present it is printed, followed by a space; otherwise a `*' is printed. Next, .PP .RS 5 .nf %<(mymbox{from})%<{to}To:%14(decode(friendly{to}))%>%> .fi .RE .PP if the message is from me, and there is a \*(lqTo:\*(rq header, print \*(lqTo:\*(rq followed by a \*(lquser-friendly\*(rq rendering of the first address in the \*(lqTo:\*(rq field; any MIME-encoded characters are decoded into the actual characters. Continuing, .PP .RS 5 .nf %<(zero)%17(decode(friendly{from}))%> .fi .RE .PP if either of the above two tests failed, then the \*(lqFrom:\*(rq address is printed in a mime-decoded, \*(lquser-friendly\*(rq format. And finally, .PP .RS 5 .nf %(decode{subject})%<{body}<<%{body}>>%> .fi .RE .PP the mime-decoded subject and initial body (if any) are printed. .PP For a more complicated example, consider a possible .I replcomps format file. .PP .RS 5 .nf %(lit)%(formataddr %<{reply-to} .fi .RE .PP This clears .I str and formats the \*(lqReply-To:\*(rq header if present. If not present, the else-if clause is executed. .PP .RS 5 .nf %?{from}%?{sender}%?{return-path}%>)\\ .fi .RE .PP This formats the \*(lqFrom:\*(rq, \*(lqSender:\*(rq and \*(lqReturn-Path:\*(rq headers, stopping as soon as one of them is present. Next: .PP .RS 5 .nf %<(nonnull)%(void(width))%(putaddr To: )\\n%>\\ .fi .RE .PP If the \fIformataddr\fR result is non-null, it is printed as an address (with line folding if needed) in a field \fIwidth\fR wide, with a leading label of \*(lqTo:\*(rq. .PP .RS 5 .nf %(lit)%(formataddr{to})%(formataddr{cc})%(formataddr(me))\\ .fi .RE .PP .I str is cleared, and the \*(lqTo:\*(rq and \*(lqCc:\*(rq headers, along with the user's address (depending on what was specified with the \*(lq\-cc\*(rq switch to \fIrepl\fR\^) are formatted. .PP .RS 5 .nf %<(nonnull)%(void(width))%(putaddr cc: )\\n%>\\ .fi .RE .PP If the result is non-null, it is printed as above with a leading label of \*(lqcc:\*(rq. .PP .RS 5 .nf %<{fcc}Fcc: %{fcc}\\n%>\\ .fi .RE .PP If a .B \-fcc .I folder switch was given to .B repl (see .IR repl (1) for more details about %{\fIfcc\fR\^}), an \*(lqFcc:\*(rq header is output. .PP .RS 5 .nf %<{subject}Subject: Re: %{subject}\\n%>\\ .fi .RE .PP If a subject component was present, a suitable reply subject is output. .PP .RS 5 .nf %<{message-id}In-Reply-To: %{message-id}\\n%>\\ %<{message-id}References: %<{references} %{references}%>\\ %{message-id}\\n%> \-\-\-\-\-\-\-\- .fi .RE .PP If a message-id component was present, an \*(lqIn-Reply-To:\*(rq header is output including the message-id, followed by a \*(lqReferences:\*(rq header with references, if present, and the message-id. As with all plain-text, the row of dashes are output as-is. .PP This last part is a good example for a little more elaboration. Here's that part again in pseudo-code: .PP .RS 5 .nf .ta .5i 1i 1.5i 2i if (comp_exists(message-id)) then print (\*(lqIn-reply-to: \*(rq) print (message-id.value) print (\*(lq\\n\*(rq) endif if (comp_exists(message-id)) then print (\*(lqReferences: \*(rq) if (comp_exists(references)) then print(references.value); endif print (message-id.value) print (\*(lq\\n\*(rq) endif .fi .RE .PP .\" (Note that this pseudocode begs the question ``why not just .\" support this syntax?'' MH has been hacked on for a long time...) .\".PP One more example: Currently, .B nmh supports very large message numbers, and it is not uncommon for a folder to have far more than 10000 messages. .\" (Indeed, the original MH .\" tutorial document by Rose and Romine is entitled "How to .\" process 200 messages a day and still get some real work .\" done." The authors apparently only planned to get .\" real work done for about 50 days per folder.) Nonetheless (as noted above) the various scan format strings, inherited from older MH versions, are generally hard-coded to 4 digits for the message number. Thereafter, formatting problems occur. The nmh format strings can be modified to behave more sensibly with larger message numbers: .PP .RS .nf %(void(msg))%<(gt 9999)%(msg)%|%4(msg)%> .fi .RE .PP The current message number is placed in \fInum\fP. (Note that .RI ( msg ) is a function escape which returns an integer, it is not a component.) The .RI ( gt ) conditional is used to test whether the message number has 5 or more digits. If so, it is printed at full width, otherwise at 4 digits. .SH "SEE ALSO" .IR scan (1), .IR repl (1), .IR fmttest (1), .SH CONTEXT None nmh-1.7.1-RC3/man/mh-mail.man000644 007761 000024 00000016642 13243042053 015563 0ustar00kenhstaff000000 000000 .TH MH-MAIL %manext5% 2014-01-08 "%nmhversion%" . .\" %nmhwarning% . .SH NAME mh-mail \- message format for nmh message system .SH DESCRIPTION .B nmh processes messages in a particular format. It should be noted that although neither Bell nor Berkeley mailers produce message files in the format that .B nmh prefers, .B nmh can read message files in that format. .PP Each user possesses a mail drop which initially receives all messages processed by .BR post . .B inc will read from that mail drop and incorporate new messages found there into the user's own mail folders (typically .RI \*(lq +inbox \*(rq). The mail drop consists of one or more messages. .PP Messages are expected to consist of lines of text. Graphics and binary data are not handled. No data compression is accepted. All text is clear ASCII 7-bit data. .PP The general \*(lqmemo\*(rq framework of RFC 822 is used. A message consists of a block of information in a rigid format, followed by general text with no specified format. The rigidly formatted first part of a message is called the header, and the free-format portion is called the body. The header must always exist, but the body is optional. These parts are separated by an empty line, i.e., two consecutive newline characters. Within .BR nmh , the header and body may be separated by a line consisting of dashes: .PP .RS 5 .nf From: Local Mailbox To: cc: Fcc: +outbox Subject: .fi .RE .PP The header is composed of one or more header items. Each header item can be viewed as a single logical line of ASCII characters. If the text of a header item extends across several real lines, the continuation lines are indicated by leading spaces or tabs. .PP Each header item is called a component and is composed of a keyword or name, along with associated text. The keyword begins at the left margin, may .I not contain spaces or tabs, may not exceed 63 characters (as specified by RFC 822), and is terminated by a colon (`:'). Certain components (as identified by their keywords) must follow rigidly defined formats in their text portions. .PP The text for most formatted components (e.g., \*(lqDate:\*(rq and \*(lqMessage\-Id:\*(rq) is produced automatically. The only ones entered by the user are address fields such as \*(lqTo:\*(rq, \*(lqcc:\*(rq, etc. Internet addresses are assigned mailbox names and host computer specifications. The rough format is \*(lqlocal@domain\*(rq, such as \*(lqMH@UCI\*(rq, or \*(lqMH@UCI\-ICSA.ARPA\*(rq. Multiple addresses are separated by commas. A missing host/domain is assumed to be the local host/domain. .PP As mentioned above, a blank line (or a line of dashes) signals that all following text up to the end of the file is the body. No formatting is expected or enforced within the body. .PP Following is a list of header components that are considered meaningful to various .B nmh programs. .PP .BR Date : .RS 5 Added by .BR post , contains date and time of the message's entry into the mail transport system. .RE .PP .BR From : .RS 5 This header is filled in by default with the system's idea of the user's local mailbox. This can be changed with the .B Local\-Mailbox profile entry. It contains the address of the author or authors (may be more than one if a \*(lqSender:\*(rq field is present). For a standard reply (using .BR repl ), the reply address is constructed by checking the following headers (in this order): \*(lqMail-Reply\-To:\*(rq, \*(lqReply\-To:\*(rq, \*(lqFrom:\*(rq, \*(lqSender:\*(rq. A \*(lqFrom:\*(rq header MUST exist when the message is sent to .BR post, otherwise the message will be rejected. .RE .PP .BR Envelope\-From : .RS 5 Used by .B post to specify a value for the sender's envelope address to the mail transport system. If omitted, .B post will use the value of the \*(lqSender:\*(rq or the \*(lqFrom:\*(rq header. See .IR send (1) for more details. .RE .PP .BR Mail\-Reply\-To : .RS 5 For a standard reply (using .BR repl ), the reply address is constructed by checking the following headers (in this order): \*(lqMail-Reply\-To:\*(rq, \*(lqReply\-To:\*(rq, \*(lqFrom:\*(rq, \*(lqSender:\*(rq. .RE .PP .BR Mail\-Followup\-To : .RS 5 When making a \*(lqgroup\*(rq reply (using .B repl .BR \-group ), any addresses in this field will take precedence, and no other reply address will be added to the draft. If this header is not available, then the return addresses will be constructed from the \*(lqMail-Reply\-To:\*(rq, or \*(lqReply\-To:\*(rq, or \*(lqFrom:\*(rq, along with adding the addresses from the headers \*(lqTo:\*(rq, \*(lqcc:\*(rq, as well as adding your personal address. .RE .PP .BR Reply\-To : .RS 5 For a standard reply (using .BR repl ), the reply address is constructed by checking the following headers (in this order): \*(lqMail-Reply\-To:\*(rq, \*(lqReply\-To:\*(rq, \*(lqFrom:\*(rq, \*(lqSender:\*(rq. .RE .PP .BR Sender : .RS 5 Required by .B post in the event that the message has multiple addresses on the \*(lqFrom:\*(rq line. It is otherwise optional. This line should contain the address of the actual sender. .RE .PP .BR To : .RS 5 Contains addresses of primary recipients. .RE .PP .BR cc : .RS 5 Contains addresses of secondary recipients. .RE .PP .BR Bcc : .RS 5 Still more recipients. However, the \*(lqBcc:\*(rq line is not copied onto the message as delivered, so these recipients are not listed. .B nmh uses an encapsulation method for blind copies, see .IR send (1). .RE .PP .BR Dcc : .RS 5 Still more recipients. However, the \*(lqDcc:\*(rq line is not copied onto the messages as delivered. Recipients on the \*(lqDcc:\*(rq line receive the same message as recipients on the \*(lqTo:\*(rq and \*(lqcc:\*(rq lines. See .IR send (1) for more details. .B Dcc is not supported with the .B sendmail/pipe mail transport method. .RE .PP .BR Fcc : .RS 5 Causes .B post to copy the message into the specified folder for the sender, if the message was successfully given to the transport system. .RE .PP .BR Message\-ID : .RS 5 A unique message identifier added by .B post if the .B \-msgid flag is set. .RE .PP .BR Subject : .RS 5 Sender's commentary. It is displayed by .BR scan . .RE .PP .BR In\-Reply\-To : .RS 5 A commentary line added by .B repl when replying to a message. .RE .PP .BR Resent\-Date : .RS 5 Added when redistributing a message by .BR post . .RE .PP .BR Resent\-From : .RS 5 Used instead of the \*(lqFrom:\*(rq header when .B post redistributes a message. See \*(lqFrom:\*(rq. .RE .PP .BR Resent\-To: .RS 5 New recipients for a message resent by .BR dist . .RE .PP .BR Resent\-cc : .RS 5 Still more recipients. See \*(lqcc:\*(rq and \*(lqResent\-To:\*(rq. .RE .PP .BR Resent\-Bcc : .RS 5 Even more recipients. See \*(lqBcc:\*(rq and \*(lqResent\-To:\*(rq. .RE .PP .BR Resent\-Fcc : .RS 5 Copy resent message into a folder. See \*(lqFcc:\*(rq and \*(lqResent\-To:\*(rq. .RE .PP .BR Resent\-Message\-Id : .RS 5 A unique identifier glued on by .B post if the .B \-msgid flag is set. See \*(lqMessage\-Id:\*(rq and \*(lqResent\-To:\*(rq. .RE .PP .BR Resent : .RS 5 Annotation for .B dist under the .B \-annotate option. .RE .PP .BR Forwarded : .RS 5 Annotation for .B forw under the .B \-annotate option. .RE .PP .BR Replied : .RS 5 Annotation for .B repl under the .B \-annotate option. .RE .PP .BR Attach : .RS 5 Used by .B mhbuild to specify a filename to attach to this message. See .IR mhbuild (1) for more information. .RE .SH FILES .TP 20 %mailspool%/$USER Location of mail drop. .SH "SEE ALSO" .I Standard for the Format of ARPA Internet Text Messages (RFC 822) .SH CONTEXT None nmh-1.7.1-RC3/man/mh-mime.man000644 007761 000024 00000012654 13243042053 015567 0ustar00kenhstaff000000 000000 .TH MH\-MIME %manext7% 2014-12-15 "%nmhversion%" . .\" %nmhwarning% . .SH NAME mh\-mime \- overview of nmh MIME message composition and display .\" .SH DESCRIPTION The acronym MIME stands for Multipurpose Internet Mail Extensions, the format of Internet messages used to send multi-media content. The .B nmh command suite has support for the display and composition of MIME messages, but currently MIME support is not completely integrated into all tools. This document provides an overview as to which tools support MIME message display, storage, and composition. .SS Local Character Set Conversion All of the .B nmh commands convert non-native character sets to the local character set, as specified by the operating system locale settings. See .IR locale (1) for more details on the environment variables used to set the local character set. Character set conversion will only take place if .B nmh was built with .IR iconv (3) support. See the .IR mhparam (1) man page for how to determine whether your .B nmh installation includes .IR iconv (3) support. .PP Depending on the source and target character set, it may not be possible to convert all characters to the local character set. In this case a substitution character will be used for the characters that cannot be converted. .SS Message Display The default format used by .IR scan (1) will automatically decode MIME-encoded headers. If you have a custom .B scan format, see the examples provided with the .B nmh distribution (found in the .RI \*(lq %nmhetcdir% \*(rq directory) and .IR mh\-format (5) for details on how to make sure your MIME headers are properly decoded. .PP By default, if .B show detects that it is reading a MIME message it will invoke .IR mhshow (1). The default behavior of .B mhshow is to only display text parts that are not marked as attachments. See .IR mhshow (1) for details on how to control what .B mhshow will display. .SS Message Interrogation and Storage The .IR mhlist (1) command will display a listing of the MIME parts contained within a message. That information can be used in conjunction with the .B mhstore command to save individual parts or content types of a message. See .IR mhlist (1) and .IR mhstore (1) for more details on how these commands work. .SS Message Composition and Reply All messages sent by .IR send (1) will automatically be processed by .IR mhbuild (1) before being passed to .IR post (1) for message submission. .B mhbuild will use the locale settings to mark text content with the appropriate character set and apply any necessary encoding. If you wish to include text in your message using a character set that does not match your locale, you will need to specify the character set using an .B mhbuild directive; see .IR mhbuild (1) for more information. .PP For attaching files or composing other non-text content, there are two options: the attach system and .B mhbuild directives. .PP The attach system is best suited for content where one or more files are being attached to a message. You can use the attach system by either using the .B attach command at the \*(lqWhat now?\*(rq prompt, or by inserting an \*(lqAttach:\*(rq header in the message draft containing the name of the file you wish to attach to the message (note that all the .B attach command does is place an \*(lqAttach:\*(rq header in the message draft). .B mhbuild will then automatically include the specified file(s) in the outgoing message. See .IR send (1) for details on how .B mhbuild determines the proper content type of attached files. .PP The other method of composing MIME messages is to use .B mhbuild directives. This allows exact control over the contents and format of the MIME message, but has a more complicated syntax. .IR mhbuild (1) contains details on the directive syntax and examples of directives for different media types. It is important to note that when using .B mhbuild directives the user must run .B mhbuild outside of .B send to have it process directives; when being run by .BR send , .B mhbuild is configured to not process directives so normal user text is not mistaken for a directive. When using directives a user typically uses the .B mime command at the \*(lqWhat now?\*(rq prompt to process them. .PP When replying to messages using .IR repl (1) the traditional MH method of including the original text in the reply does not interoperate with MIME messages. The .B \-convertargs switch to .IR repl (1) provides one solution. Another solution: the contrib directory .RI ( %docdir%/contrib ) contains a Perl program called .B replyfilter which will decode text parts and present them in an appropriate manner to be included in a message reply. See the comments at the top of .B replyfilter for instructions on how to configure .B nmh to work with it. .SS Message Rewrite The .IR mhfixmsg (1) command can apply various transformations to MIME messages, including decoding of text parts, converting the character set of text parts, and insertion of text/plain parts to correspond to text parts of other subtypes. .B mhfixmsg can also repair defects in MIME messages, such as mismatched top-level boundary indicators and invalid Content-Transfer-Encoding values. .SH "SEE ALSO" .IR comp (1), .IR iconv (3), .IR mh\-format (5) .IR mhbuild (1), .IR mhfixmsg (1), .IR mhparam (1), .IR nmh (7), .IR repl (1), .IR whatnow (1), .br .IR %docdir%/contrib/replyfilter , .br .I %docdir%/contrib/replaliases .SH BUGS MIME support should be more integrated into all of the .B nmh tools than it currently is. nmh-1.7.1-RC3/man/mh-mkstemp.man000644 007761 000024 00000002774 13243042053 016322 0ustar00kenhstaff000000 000000 .TH MH-MKSTEMP %manext1% 2014-03-16 "%nmhversion%" . .\" %nmhwarning% . .SH NAME mkstemp \- create a temporary file .SH SYNOPSIS .HP 5 .na .B %nmhlibexecdir%/mkstemp .RB [ \-help ] .RB [ \-version ] .RB [ \-directory .IR directory ] .RB [ \-prefix .IR prefix ] .RB [ \-suffix .IR suffix ] .ad .SH DESCRIPTION .B mkstemp creates a temporary file using .IR mkstemp (3), or if the .B \-suffix switch is available and used, .IR mkstemps (3). The file name identifies a unique, newly created file, and always contains 6 characters that appear to be random. .PP The .B \-directory switch specifies a .I directory in which to create the file. .PP The .B \-prefix switch specifies an initial part, before the 6 characters, of the file name. .PP The .B \-suffix switch is only supported on platforms that provide the .IR mkstemps (3) library function. It specifies a .I suffix to appear after the 6 characters; if it should begin with a special character such as a period, that must be explicit in .IR suffix . .PP Unlike arguments to most switches of other .B nmh commands, the arguments to .B mkstemp switches can begin with a dash. .SH "EXIT STATUS" If .B mkstemp successfully creates the temporary file, it prints the file name on standard output and exits with status 0. On failure, it prints a diagnostic message on standard error and exits with status 255. .SH "PROFILE COMPONENTS" None .SH "SEE ALSO" .IR mkstemp (3), .IR mkstemps (3) .SH DEFAULTS .PD 0 .TP 14 \-directory current directory .TP \-prefix none .TP \-suffix none .PD nmh-1.7.1-RC3/man/mh-profile.man000644 007761 000024 00000061666 13243042053 016307 0ustar00kenhstaff000000 000000 .TH MH-PROFILE %manext5% 2016-10-19 "%nmhversion%" . .\" %nmhwarning% . .SH NAME mh-profile \- user customization for nmh message handler .SH DESCRIPTION Each user of .B nmh is expected to have a file named .I \&.mh\-profile in their home directory. This file contains a set of user parameters used by the .B nmh family of programs. Each entry in the file is of the format .PP .RS 5 .IR profile-component ": " value .RE .PP If the text of a profile entry is long, you may extend it across several real lines by indenting the continuation lines with leading spaces or tabs. Comments may be introduced by a line starting with `#:': .PP .RS 5 .IR # ": " This is a comment. .RE .PP Blank lines are not permitted in .IR \&.mh\-profile. Shell quoting conventions are not available; each token is separated by whitespace. .SS "Standard Profile Entries" The possible profile components are exemplified below. The only mandatory entry is `Path:'. The others are optional; some have default values if they are not present. In the notation used below, (profile, default) indicates whether the information is kept in the user's .B nmh profile or .B nmh context, and indicates what the default value is. Note that a profile component can only appear once. Multiple appearances will trigger a warning that all appearances after the first are ignored. .PP Some MH programs, including .BR mhbuild , .BR mhshow , and .BR mhstore , have specific profile components that are described in their respective man pages. Each component name specific to these programs begins with the name of the program and is followed by a dash. .PP .BR Path : Mail .RS 5 Locates .B nmh transactions in directory \*(lqMail\*(rq. This is the only mandatory profile entry. (profile, no default) .RE .PP .BR locale : locale .RS 5 Set the locale for all .B nmh programs except .BR post , .BR install-mh , and .BR slocal . See the LC_ALL, LC_CTYPE, and LANG variables in the "ENVIRONMENT" section below for a reference on how the locale is set if this profile component is not used. .RE .PP .BR context : context .RS 5 Declares the location of the .B nmh context file. This can be overridden by the environment variable MHCONTEXT. See the .B HISTORY section below. (profile, default: /context) .RE .PP .BR Current\-Folder : inbox .RS 5 Keeps track of the current open folder. (context, default: folder specified by \*(lqInbox\*(rq) .RE .PP .BR Inbox : inbox .RS 5 Defines the name of the default inbox. (profile, default: inbox) .RE .PP .BR Previous\-Sequence : .I pseq .RS 5 Names the sequence or sequences which should be defined as the `msgs' or `msg' argument given to any .B nmh command. If not present or empty, no such sequences are defined. Otherwise, for each name given, the sequence is first zeroed and then each message is added to the sequence. Read the .IR mh\-sequence (5) man page for the details about this sequence. (profile, no default) .RE .PP .BR Sequence\-Negation : not .RS 5 Defines the string which, when prefixed to a sequence name, negates that sequence. Hence, \*(lqnotseen\*(rq means all those messages that are not a member of the sequence \*(lqseen\*(rq. Read the .IR mh\-sequence (5) man page for the details. (profile, no default) .RE .PP .BR Unseen\-Sequence : unseen .RS 5 Names the sequence or sequences which should be defined as those messages which are unread. The commands .BR inc , .BR rcvstore , .BR mhshow , and .B show will add or remove messages from these sequences when they are incorporated or read. If not present or empty, no such sequences are defined. Otherwise, each message is added to, or removed from, each sequence name given. Read the .IR mh\-sequence (5) man page for the details about this sequence. (profile, no default) .RE .PP .BR mh\-sequences : \&.mh\-sequences .RS 5 The name of the file in each folder which defines public sequences. To disable the use of public sequences, leave the value portion of this entry blank. (profile, default: \&.mh\-sequences) .RE .PP .BI atr\- seq \- folder : 172\0178\-181\0212 .RS 5 Keeps track of the private sequence called \*(lqseq\*(rq in the specified folder. Private sequences are generally used for read-only folders. See the .IR mh\-sequence (5) man page for details about private sequences. (context, no default) .RE .PP .BR Editor : vi .RS 5 Defines the editor to be used by the commands .BR comp , .BR dist , .BR forw , and .BR repl . If not set, the value will be taken from the VISUAL and EDITOR environment variables. (profile, default: vi) .RE .PP .BR Msg\-Protect : 600 .RS 5 An octal number which defines the permission bits for new message files. See .IR chmod (1) for an explanation of the octal number. Note that some filesystems, such as FAT32, do not support removal of read file permissions. (profile, default: 0600) .RE .PP .BR Folder\-Protect : 700 .RS 5 An octal number which defines the permission bits for new folder directories. See .IR chmod (1) for an explanation of the octal number. (profile, default: 700) .RE .PP .BR datalocking : fcntl .RS 5 The locking algorithm used to lock changes to any .B nmh data files, such as sequences or context. The locking algorithm is any one of the following entries: .PP .RS 5 .nf %supported_locks% .fi .RE .PP Available locking algorithms can vary depending on the operating system. Note: currently, transactional locking is only supported on public sequences; see .IR mh\-sequence (5) for more information. (profile, default: fcntl) .RE .PP .IR program : .I default switches .RS 5 Sets default switches to be used whenever the mh program .I program is invoked. For example, one could override the \*(lqEditor:\*(rq profile component when replying to messages by adding a component such as: .PP .RS 5 repl: \-editor /bin/ed .RE .PP (profile, no defaults) .RE .PP .IB lasteditor "-next:" .I nexteditor .RS 5 Names \*(lqnexteditor\*(rq to be the default editor after using \*(lqlasteditor\*(rq. This takes effect at the \*(lqWhat now?\*(rq prompt in .BR comp , .BR dist , .BR forw , and .BR repl . After editing the draft with \*(lqlasteditor\*(rq, the default editor is set to be \*(lqnexteditor\*(rq. If the user types \*(lqedit\*(rq without any arguments to \*(lqWhat now?\*(rq, then \*(lqnexteditor\*(rq is used. (profile, no default) .RE .PP .BR Folder\-Stack : .I folders .RS 5 The contents of the folder-stack for the .B folder command. (context, no default) .RE .PP .BR Local\-Mailbox : Your Username .RS 5 Tells the MH programs what your local mailbox is. If set, it will be used by the default component files by programs like .B comp and .B repl to construct your default \*(lqFrom:\*(rq header. The text used here will be copied exactly to your \*(lqFrom:\*(rq header, so it should already be RFC 822 compliant. If this is set, the .B Signature profile entry is .I not used, so it should include a signature as well. (profile, default: userid@local.hostname) .RE .PP .BR Alternate\-Mailboxes : mh@uci\-750a, bug-mh* .RS 5 Tells .B repl and .B scan which additional addresses are yours. In this way, .B repl knows which addresses should be included in the reply, and .B scan knows if a message originated from you. Addresses must be separated by a comma, and the hostnames listed should be the \*(lqofficial\*(rq hostnames for the mailboxes you indicate, as local nicknames for hosts are not replaced with their official site names. For each address, if a host is not given, then that address on any host is considered to be you. In addition, an asterisk (`*') may appear at either or both ends of the mailbox and host to indicate wild-card matching. (profile, default: your user-id) .RE .PP .BR Aliasfile : aliases .I other-aliases .RS 5 Indicates alias files for .BR ali , .BR whom , and .BR send . This may be used instead of the .B \-alias .I file switch. (profile, no default) .RE .PP .BR Draft\-Folder : drafts .RS 5 Indicates a default draft folder for .BR comp , .BR dist , .BR forw , .BR refile , and .BR repl . Read the .IR mh\-draft (5) man page for details. (profile, no default) .RE .PP .BI digest\-issue\- list : 1 .RS 5 Tells .B forw the last issue of the last volume sent for the digest .IR list . (context, no default) .RE .PP .BI digest\-volume\- list : 1 .RS 5 Tells .B forw the last volume sent for the digest .IR list . (context, no default) .RE .PP .BR MailDrop : \&.mail .RS 5 Tells .B inc your mail drop, if different from the default. This is superseded by the environment variable MAILDROP. (profile, default: %mailspool%/$USER) .RE .PP .BR Signature : RAND MH System (agent: Marshall Rose) .RS 5 Tells front-end programs such as .BR comp, .BR forw, and .B repl your mail signature. (This is not to be confused with a .signature that might be appended to mails.) This is superseded by the environment variable SIGNATURE. If SIGNATURE is not set and this profile entry is not present, the \*(lqgcos\*(rq field of the \fI/etc/passwd\fP file will be used. Your signature will be added to the address .B send puts in the \*(lqFrom:\*(rq header; do not include an address in the signature text. The \*(lqLocal\-Mailbox\*(rq profile component supersedes all of this. (profile, no default) .RE .PP .BR credentials : legacy .RS 5 Indicates how the username and password credentials will be retrieved for access to external servers, such as those that provide SMTP or POP service. The supported entry values are \*(lqlegacy\*(rq, .RI \*(lqfile: netrc \*(rq, and .RI \*(lqfile\-nopermcheck: netrc \*(rq. With \*(lqlegacy\*(rq, or if there is no credentials entry, the username is the first of: .RS 5 .TP 5 .PD 0 1) .B \-user switch to .BR inc , .BR msgchk , .BR post , .BR send , or .B whom program .TP 2) the login name on the local machine .PD .RE .PP The password for SMTP services is the first of: .RS 5 .TP 5 .PD 0 1) password value from matching entry in file named \*(lq.netrc\*(rq in the user's home directory .TP 2) password obtained by interactively prompting the user .PD .RE .PP The password for POP service when the .B \-sasl switch is used with one of these programs is the login name on the local machine. .PP With a .RI \*(lqfile: netrc \*(rq .B credentials entry, the username is the first of: .RS 5 .PD 0 .TP 5 1) .B \-user switch to program .TP 5 2) login name from matching entry in .I netrc file .TP 5 3) value provided by user in response to interactive query .PD .RE .PP Similarly, the password is provided either in the .I netrc file or interactively. .I netrc can be any valid filename, either absolute or relative to Path or $HOME. The .I netrc file contains authentication information, for each server, using a line of the following form. (Replace .IR myserver , .IR mylogin , and .I mypassword with your own account information.) .PP .RS 5 .B machine .I myserver .B login .I mylogin .B password .I mypassword .RE .PP This .I netrc file must be owned and readable only by you. .PP The .RI \*(lqfile\-nopermcheck: netrc \*(rq .B credentials entry is identical in behavior to the \*(lqfile\*(rq entry, with the exception that the permission checks done by \*(lqfile\*(rq are not performed. This entry should be used with caution and only when absolutely necessary. (profile, default: legacy) .RE .PP .BR Welcome : disable .RS 5 If the Welcome component is not present, or its value is not .RI \*(lq disable \*(rq, a welcome message will be displayed the first time that an interactive .B nmh program is run after updating the .B nmh installation. The user must press the Enter key to continue. .PP If the MHCONTEXT environment variable is set and non-empty (and the Welcome component is not .RI \*(lq disable \*(rq), the welcome message is only displayed if the context file contains a version reference, and that reference is older than the installed .B nmh version. The version reference is of the form: .PP .RS 5 .nf Version: %nmhversion% .fi .RE .SS "Process Profile Entries" The following profile elements are used whenever an .B nmh program invokes some other program, such as .BR more . The .I \&.mh\-profile can be used to select alternate programs if the user wishes. The default values are given in the examples. .PP If the profile element contains spaces, the element is split at spaces into tokens and each token is given as a separate argument to the .IR execvp (2) system call. If the element contains shell metacharacters then the entire element is executed using .BR /bin/sh . .PP .BR buildmimeproc : %bindir%/mhbuild .RS 5 This is the program used by .B whatnow to process drafts which are MIME composition files. .RE .PP .BR fileproc : %bindir%/refile .RS 5 This program is used to refile or link a message to another folder. It is used by .B send to file a copy of a message into a folder given by a \*(lqFcc:\*(rq field. It is used by the draft folder facility in .BR comp , .BR dist , .BR forw , and .B repl to refile a draft message into another folder. It is used to refile a draft message in response to the .B refile directive at the \*(lqWhat now?\*(rq prompt. .RE .PP .BR formatproc : .RS 5 Program called by .B mhl to filter a component when it is tagged with the \*(lqformat\*(rq variable in the mhl filter. See .IR mhl (5) for more information. .RE .PP .BR incproc : %bindir%/inc .RS 5 Program called by .B mhmail to incorporate new mail when it is invoked with no arguments. .RE .PP .BR lproc : more .RS 5 This program is used to list the contents of a message in response to the .B list directive at the \*(lqWhat now?\*(rq prompt. It is also used by the draft folder facility in .BR comp , .BR dist , .BR forw , and .B repl to display the draft message. (Note that the environment variable PAGER supersedes the default built-in pager command.) .RE .PP .BR mailproc : %bindir%/mhmail .RS 5 This is the program used to automatically mail various messages and notifications. It is used by .B send to post failure notices. It is used to retrieve an external-body with access-type `mail-server' (such as when storing the body with .BR mhstore ). .RE .PP .BR mhlproc : %nmhlibexecdir%/mhl .RS 5 This is the program used to filter messages in various ways. It is used by .B mhshow to filter and display the message headers of MIME messages. When the .B \-format or .B \-filter option is used by .B forw or .BR repl , the .I mhlproc is used to filter the message that you are forwarding, or to which you are replying. When the .B \-filter option is given to .BR send , the .I mhlproc is used to filter the copy of the message that is sent to \*(lqBcc:\*(rq recipients. .RE .PP .BR moreproc : more .RS 5 This is the program used by .B mhl to page the .B mhl formatted message when displaying to a terminal. It is also the default program used by .B mhshow to display message bodies (or message parts) of type text/plain. (Note that the environment variable PAGER supersedes the default built-in pager command.) .RE .PP .BR packproc : %bindir%/packf .RS 5 Currently not used. .RE .PP .BR postproc : %nmhlibexecdir%/post .RS 5 This is the program used by .BR send , .BR mhmail , .BR rcvdist , and .B viamail (used by the .B sendfiles shell script) to post a message to the mail transport system. It is also called by .B whom (called with the switches .B \-whom and .BR \-library ) to do address verification. .RE .PP .BR rmmproc : none .RS 5 This is the program used by .BR rmm , .BR refile , and .B mhfixmsg to delete a message from a folder. .RE .PP .BR sendproc : %bindir%/send .RS 5 This is the program used by .B whatnow to actually send the message .RE .PP .BR showmimeproc : %bindir%/mhshow .RS 5 This is the program used by .B show to process and display non-text (MIME) messages. .RE .PP .BR showproc : %nmhlibexecdir%/mhl .RS 5 This is the program used by .B show to filter and display text (non-MIME) messages. .RE .PP .BR whatnowproc : %bindir%/whatnow .RS 5 This is the program invoked by .BR comp , .BR dist , .BR forw , and .B repl to query about the disposition of a composed draft message. .RE .PP .BR whomproc : %bindir%/whom .RS 5 This is the program used by .B whatnow to determine to whom a message would be sent. .RE .SS "Profile Lookup" After consulting .mh_profile, some programs read an optional profile specified by a program-specific environment variable, and then the system-wide profile %nmhetcdir%/mhn.defaults. These programs are .BR mhbuild , .BR mhshow , .BR mhstore , and .BR mhn . .B mhfixmsg is similar, but has no optional profile. .PP The first occurrence of a component is used, e.g.\& .mh_profile's trumps $MHSHOW's. A component with no value still stops further occurrences being used, but is considered absent. .PP The .I \&.mh\-profile contains only static information, which .B nmh programs will .I not update. Changes in context are made to the .I context file kept in the users .B nmh directory. This includes, but is not limited to: the \*(lqCurrent\-Folder\*(rq entry and all private sequence information. Public sequence information is kept in each folder in the file determined by the \*(lqmh\-sequences\*(rq profile entry (default is .IR \&.mh\-sequences ). .PP The .I \&.mh\-profile may override the path of the .I context file, by specifying a \*(lqcontext\*(rq entry (this must be in lower-case). If the entry is not absolute (does not start with a \*(lq/\*(rq), then it is interpreted relative to the user's .B nmh directory. As a result, you can actually have more than one set of private sequences by using different context files. .SH ENVIRONMENT The operation of .B nmh and its commands it also controlled by the presence of certain environment variables. .PP Many of these environment variables are used internally by the \*(lqWhat now?\*(rq interface. It's amazing all the information that has to get passed via environment variables to make the \*(lqWhat now?\*(rq interface look squeaky clean to the .B nmh user, isn't it? The reason for all this is that the .B nmh user can select any program as the .IR whatnowproc , including one of the standard shells. As a result, it's not possible to pass information via an argument list. The convention is that environment variables whose names are all upper-case are user-settable; those whose names are lower-case only are used internally by nmh and should not generally be set by the user. .TP LC_ALL, LC_CTYPE, and LANG These variables are used to set the locale, see locale(1). The \*(lqlocale\*(rq profile entry supersedes these. .TP MAILDROP This variable tells .B inc the default mail drop. This supersedes the \*(lqMailDrop\*(rq profile entry. .TP MAILHOST This variable tells .B inc the POP host to query for mail to incorporate. See the .IR inc (1) man page for more information. .TP MH With this environment variable, you can specify a profile other than .I \&.mh\-profile to be read by the .B nmh programs that you invoke. If the value of MH is not absolute, (i.e., does not begin with a \*(lq/\*(rq), it will be presumed to start from the current working directory. This is one of the very few exceptions in .B nmh where non-absolute pathnames are not considered relative to the user's .B nmh directory. .TP MHBUILD With this environment variable, you can specify an additional user profile (file) to be read by .BR mhbuild , in addition to the mhn.defaults profile. .TP MHCONTEXT With this environment variable, you can specify a context other than the normal context file (as specified in the .B nmh profile). As usual, unless the value of MHCONTEXT is absolute, it will be presumed to start from your .B nmh directory. .TP MHLDEBUG If this variable is set to a non-null value, .B mhl will emit debugging information. .TP MHMTSCONF If this variable is set to a non-null value, it specifies the name of the mail transport configuration file to use by .BR inc , .BR post , and other programs that interact with the mail transport system, instead of the default. See .IR mh-tailor (5). .TP MHMTSUSERCONF If this variable is set to a non-null value, it specifies the name of a mail transport configuration file to be read in addition to the default. See .IR mh-tailor (5). .TP MHN With this environment variable, you can specify an additional user profile (file) to be read by .BR mhn , in addition to the mhn.defaults profile. .B mhn is deprecated, so support for this variable will be removed from a future nmh release. .TP MHSHOW With this environment variable, you can specify an additional user profile (file) to be read by .BR mhshow , in addition to the mhn.defaults profile. .TP MHSTORE With this environment variable, you can specify an additional user profile (file) to be read by .BR mhstore , in addition to the mhn.defaults profile. .TP MHPDEBUG If this variable is set to a non-null value, .B pick will emit a representation of the search pattern. MHPDEBUG is deprecated, so support for this variable will be removed from a future nmh release. Instead, .B pick now supports a .B \-debug switch. .TP MHTMPDIR, TMPDIR These variables are searched, in order, for the directory in which to create some temporary files. MHTMPDIR is deprecated and will be removed in a future release of nmh. .TP MHWDEBUG If this variable is set to a non-null value, .B nmh commands that use the .B Alternate\-Mailboxes profile entry will display debugging information about the values in that entry. .TP PAGER If set to a non-null value, this supersedes the value of the default built-in pager command. .TP SIGNATURE This variable tells .B send and .B post your mail signature. This supersedes the \*(lqSignature\*(rq profile entry, and is not used when the \*(lqLocal\-Mailbox\*(rq profile component is set. .TP USER This variable tells .B repl your user name and .B inc your default mail drop: see the \*(lqMailDrop\*(rq profile entry. .TP USERNAME_EXTENSION This variable is for use with username_extension masquerading. See the .IR mh-tailor (5) man page. .TP editalt This is the alternate message. This is set by .B dist and .B repl during edit sessions so you can peruse the message being distributed or replied to. The message is also available, when the .B \-atfile switch is used, through a link called \*(lq@\*(rq in the current directory if your current working directory and the folder the message lives in are on the same Unix filesystem, and if your current working directory is writable. .TP mhaltmsg .B dist and .B repl set mhaltmsg to tell the .I whatnowproc about an alternate message associated with the draft (the message being distributed or replied to). .TP mhannotate This is set by .BR dist , .BR forw , and .B repl if annotations are to occur. .TP mhdist .B dist sets mhdist to tell the .I whatnowproc that message re-distribution is occurring. .TP mhdraft This is the path to the working draft. It is set by .BR comp , .BR dist , .BR forw , and .B repl to tell the .I whatnowproc which file to ask \*(lqWhat now?\*(rq questions about. .TP mheditor This is set by .BR comp , .BR repl , .BR forw , and .B dist to tell the .I whatnowproc the user's choice of editor (unless overridden by .BR \-noedit ). .TP mhfolder This is the folder containing the alternate message. It is set by .B dist and .B repl during edit sessions so you can peruse other messages in the current folder besides the one being distributed or replied to. The environment variable mhfolder is also set by .BR next , .BR prev , and .B show for use by .BR mhl . .TP mhinplace This is set by .BR dist , .BR forw , and .B repl if annotations are to occur. .TP mhmessages This is set by .BR dist , .BR forw , and .B repl if annotations are to occur. .TP mhuse This may be set by .BR comp . .SH FILES .PD 0 .TP 20 $HOME/.mh\-profile The user's profile. .TP /context The user's context .TP /.mh\-sequences Public sequences for . .PD .SH "SEE ALSO" .IR mhbuild (1), .IR mhshow (1), .IR mhstore (1), .IR mh-sequence (5), .IR nmh (7) .SH BUGS There is some question as to what kind of arguments should be placed in the profile as options. In order to provide a clear answer, recall the command line semantics of all .B nmh programs: conflicting switches (e.g. .B \-header and .BR \-noheader ) may occur more than one time on the command line, with the last switch taking effect. Other arguments, such as message sequences, filenames and folders, are always remembered on the invocation line and are not superseded by following arguments of the same type. Hence, it is safe to place only switches (and their arguments) in the profile. .PP If one finds that an .B nmh program is being invoked again and again with the same arguments, and those arguments aren't switches, then there are a few possible solutions to this problem. The first is to create a (soft) link in your .I $HOME/bin directory to the .B nmh program of your choice. By giving this link a different name, you can create a new entry in your profile and use an alternate set of defaults for the .B nmh command. Similarly, you could create a small shell script which called the .B nmh program of your choice with an alternate set of invocation line switches (using links and an alternate profile entry is preferable to this solution). .PP Finally, the .B csh user could create an alias for the command of the form: .PP .RS 5 alias cmd 'cmd arg1 arg2 ...' .RE .PP In this way, the user can avoid lengthy type-in to the shell, and still give .B nmh commands safely. (Recall that some .B nmh commands invoke others, and that in all cases, the profile is read, meaning that aliases are disregarded beyond an initial command invocation) nmh-1.7.1-RC3/man/mh-sequence.man000644 007761 000024 00000026734 13205305704 016457 0ustar00kenhstaff000000 000000 .TH MH-SEQUENCE %manext5% 2013-10-17 "%nmhversion%" . .\" %nmhwarning% . .SH NAME mh-sequence \- sequence specification for nmh message system .SH DESCRIPTION A sequence (or sequence set) is a symbolic name representing a message or collection of messages. .B nmh has several internally defined sequences, as well as allowing users to define their own sequences. .SS "Message Specification and Pre-Defined Message Sequences" Most .B nmh commands accept a `msg' or `msgs' specification, where `msg' indicates one message and `msgs' indicates one or more messages. To designate a message, you may use either its number (e.g., 1, 10, 234) or one of these \*(lqreserved\*(rq message names: .PP .RS 5 .PD 0 .TP .B first the first message in the folder .TP .B last the last message in the folder .TP .B cur the most recently accessed message .TP .B prev the message numerically preceding \*(lqcur\*(rq .TP .B next the message numerically following \*(lqcur\*(rq .RE .PD .PP In commands that take a `msg' argument, the default is \*(lqcur\*(rq. As a shorthand, \*(lq.\*(rq is equivalent to \*(lqcur\*(rq. .PP For example: In a folder containing five messages numbered 5, 10, 94, 177 and 325, \*(lqfirst\*(rq is 5 and \*(lqlast\*(rq is 325. If \*(lqcur\*(rq is 94, then \*(lqprev\*(rq is 10 and \*(lqnext\*(rq is 177. .PP The word `msgs' indicates that one or more messages may be specified. Such a specification consists of one message designation or of several message designations, as separate arguments. A message designation consists either of a message name as defined above, or a message range. .PP A message range is specified as \*(lqname1\-name2\*(rq or \*(lqname:n\*(rq, where `name', `name1' and `name2' are message names, and `n' is an integer. .PP The specification \*(lqname1\-name2\*(rq designates all currently existing messages from `name1' to `name2' inclusive. The \*(lqreserved\*(rq message name \*(lqall\*(rq is a shorthand for the message range \*(lqfirst\-last\*(rq. .PP The specification \*(lqname:n\*(rq designates up to `n' messages. These messages start with `name' if `name' is a message number or one of the reserved names \*(lqfirst\*(rq \*(lqcur\*(rq, or \*(lqnext\*(rq, The messages end with `name' if `name' is \*(lqprev\*(rq or \*(lqlast\*(rq. The interpretation of `n' may be overridden by preceding `n' with a plus or minus sign; `+n' always means up to `n' messages starting with `name', and `\-n' always means up to `n' messages ending with `name'. .PP Substituting `=' for `:' (i.e., \*(lqname=n\*(rq) will reduce the selection from a range of up to `n' messages, to a selection of just the `n'th message. So for example, while \*(lqname:-3\*(rq selects the 3 messages ending with `name', \*(lqname=-3\*(rq selects just the 2nd previous message. It is an error if the requested message does not exist (i.e., there aren't enough messages in the folder). .PP In commands which accept a `msgs' argument, the default is either \*(lqcur\*(rq or \*(lqall\*(rq, depending on which makes more sense for each command (see the individual man pages for details). Repeated specifications of the same message have the same effect as a single specification of the message. .PP There is also a special \*(lqreserved\*(rq message name \*(lqnew\*(rq which is used by the .B mhpath command. .SS "User\-Defined Message Sequences" In addition to the \*(lqreserved\*(rq (pre-defined) message names given above, .B nmh supports user-defined sequence names. User-defined sequences allow the .B nmh user a tremendous amount of power in dealing with groups of messages in the same folder by allowing the user to bind a group of messages to a meaningful symbolic name. .PP The name used to denote a message sequence must consist of an alphabetic character followed by zero or more alphanumeric characters, and can not be one of the \*(lqreserved\*(rq message names above. After defining a sequence, it can be used wherever an .B nmh command expects a `msg' or `msgs' argument. .PP Some forms of message ranges are allowed with user-defined sequences. The specification \*(lqname:n\*(rq may be used, and it designates up to the first `n' messages (or last `n' messages for `\-n') which are elements of the user-defined sequence `name'. .PP The specifications \*(lqname:next\*(rq and \*(lqname:prev\*(rq may also be used, and they designate the next or previous message (relative to the current message) which is an element of the user-defined sequence `name'. The specifications \*(lqname:first\*(rq and \*(lqname:last\*(rq are equivalent to \*(lqname:1\*(rq and \*(lqname:\-1\*(rq, respectively. The specification \*(lqname:cur\*(rq is not allowed (use just \*(lqcur\*(rq instead). The syntax of these message range specifications is subject to change in the future. .PP Single messages (as opposed to ranges) may also be selected by substituting `=' for `:', as in \*(lqname=n\*(rq. This will reduce the selection from being a range of up to `n' messages, to being a selection of just the `n'th message. So while \*(lqseq:5\*(rq selects the first 5 messages of sequence `seq', \*(lqseq=5\*(rq selects just the 5th message of the sequence. It is an error if the requested message does not exist (i.e., there aren't at least `n' messages in the sequence). .PP User-defined sequence names are specific to each folder. They are defined using the .B pick and .B mark commands. .SS "Public and Private User-Defined Sequences" There are two varieties of user-defined sequences: public and private. Public sequences of a folder are accessible to any .B nmh user that can read that folder. They are kept in each folder in the file determined by the \*(lqmh\-sequences\*(rq profile entry (default is .IR \&.mh_sequences ). Private sequences are accessible only to the .B nmh user that defined those sequences and are kept in the user's .B nmh context file. .PP In general, the commands that create sequences (such as .B pick and .BR mark ) will create public sequences if the folder for which the sequences are being defined is writable by the .B nmh user. For most commands, this can be overridden by using the switches .B \-public and .BR \-private . But if the folder is read-only, or if the \*(lqmh\-sequences\*(rq profile entry is defined but empty, then \fIprivate\fR sequences will be created instead. .SS "Sequence Negation" .B Nmh provides the ability to select all messages not elements of a user-defined sequence. To do this, the user should define the entry \*(lqSequence\-Negation\*(rq in the .B nmh profile file; its value may be any string. This string is then used to preface an existing user-defined sequence name. This specification then refers to those messages not elements of the specified sequence name. For example, if the profile entry is: .PP .RS 5 Sequence\-Negation: not .RE .PP then any time an .B nmh command is given \*(lqnotfoo\*(rq as a `msg' or `msgs' argument, it would substitute all messages that are not elements of the sequence \*(lqfoo\*(rq. .PP Obviously, the user should beware of defining sequences with names that begin with the value of the \*(lqSequence\-Negation\*(rq profile entry. .SS "The Previous Sequence" .B Nmh provides the ability to remember the `msgs' or `msg' argument last given to an .B nmh command. The entry \*(lqPrevious\-Sequence\*(rq should be defined in the .B nmh profile; its value should be a sequence name or multiple sequence names, as separate arguments. If this entry is defined, when an .B nmh command finishes, it will define the sequence(s) named in the value of this entry to be those messages that were specified to the command. Hence, a profile entry of .PP .RS 5 Previous\-Sequence: pseq .RE .PP directs any .B nmh command that accepts a `msg' or `msgs' argument to define the sequence \*(lqpseq\*(rq as those messages when it finishes. .PP .BR Note : there can be a performance penalty in using the \*(lqPrevious\-Sequence\*(rq facility. If it is used, .B all .B nmh programs have to write the sequence information to the .I \&.mh_sequences file for the folder each time they run. If the \*(lqPrevious\-Sequence\*(rq profile entry is not included, only .B pick and .B mark will write to the .B \&.mh_sequences file. .SS "The Unseen Sequence" Finally, many users like to indicate which messages have not been previously seen by them. The commands .BR flist , .BR inc , .BR mhshow , .BR rcvstore , and .B show honor the profile entry \*(lqUnseen\-Sequence\*(rq to support this activity. This entry in the .I \&.mh_profile should be defined as one or more sequence names, as separate arguments. If there is a value for \*(lqUnseen\-Sequence\*(rq in the profile, then whenever new messages are placed in a folder (using .B inc or .BR rcvstore ), the new messages will also be added to all the sequences named in this profile entry. For example, a profile entry of .PP .RS 5 Unseen\-Sequence: unseen .RE .PP directs .B inc to add new messages to the sequence \*(lqunseen\*(rq. Unlike the behavior of the \*(lqPrevious\-Sequence\*(rq entry in the profile, however, the sequence(s) will .I not be zeroed by .BR inc . .PP Similarly, whenever .BR show , .BR mhshow , .BR next , or .B prev displays a message, that message will be removed from any sequences named by the \*(lqUnseen\-Sequence\*(rq entry in the profile. .SS Sequence File Format The sequence file format is based on the RFC 5322 message format. Each line of the sequence file corresponds to one sequence. The line starts with the sequence name followed by a `:', then followed by a space-separated list of message numbers that correspond to messages that are part of the named sequence. A contiguous range of messages can be represented as \*(lqlownum\-highnum\*(rq. .PP .B Sample sequence file .PP .RS 5 .nf work: 3 6 8 22-33 46 unseen: 47 49-51 54 cur: 46 .fi .RE .PP .B Nmh commands that modify the sequence file will silently remove sequences for nonexistent messages when the sequence file is updated. The exception to this is the \*(lqcur\*(rq sequence, which is allowed to point to a nonexistent message. .SS Sequence File Locking The \*(lqdatalocking\*(rq profile entry controls the type of locking used when reading and writing sequence files. The locking mechanisms supported are detailed in .IR mh\-profile (5). This protects sequence file integrity when multiple .B nmh commands are run simultaneously. .B Nmh commands that modify the sequence file use transactional locks; the lock is held from the time the sequence file is read until it it written out. This ensures that modifications to the sequence file will not be lost if multiple commands are run simultaneously. Long-running .B nmh commands, such as .B inc and .BR pick , will release the sequence lock during the bulk of their runtime and reread the sequence file after their processing is complete to reduce lock contention time. .PP Note: Currently transactional locks are only supported for public sequences; private sequences will not get corrupted, but the possibility exists that two .B nmh commands run simultaneously that add messages to a private sequence could result in one command's messages not appearing on the requested sequence. .SH FILES .PD 0 .TP 20 $HOME/.mh\-profile The user's profile. .TP 20 /context The user's context. .TP 20 /.mh\-sequences File for public sequences. .PD .SH "PROFILE COMPONENTS" .PD 0 .TP 20 mh-sequences: Name of file to store public sequences. .TP 20 Sequence\-Negation: To designate messages not in a sequence. .TP 20 Previous\-Sequence: The last message specification given. .TP 20 Unseen\-Sequence: Those messages not yet seen by the user. .PD .SH "SEE ALSO" .IR flist (1), .IR mark (1), .IR pick (1), .IR mh-profile (5) .SH DEFAULTS None nmh-1.7.1-RC3/man/mh-tailor.man000644 007761 000024 00000020115 13243042053 016121 0ustar00kenhstaff000000 000000 .TH MH-TAILOR %manext5% 2017-02-19 "%nmhversion%" . .\" %nmhwarning% . .SH NAME mh-tailor, mts.conf \- mail transport configuration for nmh message handler .SH DESCRIPTION The file .I %nmhetcdir%/mts.conf defines run-time options for those .B nmh programs which interact (in some form) with the message transport system. At present, these (user) programs are: .BR ap , .BR inc , .BR msgchk , .BR post , .BR rcvdist , and .BR rcvpack . .PP Each option should be given on a single line. Blank lines and lines which begin with `#' are ignored. The options available along with default values and a description of their meanings are listed below: .PP .BR mts : .RS 5 The mail transport method to use. The three acceptable options are .B smtp (which is the default), .BR sendmail/smtp , and .BR sendmail/pipe . .PP If you use .BR smtp , this will enable a direct SMTP interface in .BR nmh . When sending mail, instead of passing the message to the mail transport agent, .B post will open a socket connection to the mail port on the machine specified in the .B servers entry. .PP If you use .BR sendmail/smtp , then .B post will send messages by forking a local copy of .BR sendmail . It will still speak SMTP with this local copy of .BR sendmail . For backward compatibility, .B sendmail/smtp can be abbreviated to .BR sendmail . .PP The third alternative, .BR sendmail/pipe , also forks a local copy of .B sendmail but feeds the message directly to it, using .B sendmail .BR -t . This replaces the old, undocumented .B spost mechanism and retains some of its limitations, such as lack of support for the .B \-whom switch and \*(lqDcc:\*(rq header field. .RE .PP .BR localname : .RS 5 The hostname .B nmh considers local. It should typically be a fully qualified hostname. If this is not set, depending on the version of Unix you're running, .B nmh will query the system for this value (e.g.\& uname, gethostname, etc.), and attempt to fully qualify this value. .PP If you are using POP to retrieve new messages, you may want to set this value to the name of the POP server, so that outgoing messages appear to have originated on the POP server. .RE .PP .BR localdomain : .RS 5 If this is set, a `.' followed by this string will be appended to your hostname. .PP This should only be needed, if for some reason .B nmh is not able to fully qualify the hostname returned by the system (e.g.\& uname, gethostname, etc.). .RE .PP .BR clientname : .RS 5 This option specifies the host name that .B nmh will give in the SMTP .B HELO (and .BR EHLO ) command, when posting mail. If not set, the default is to use the host name that .B nmh considers local (see .B localname above). If this option is set, but empty, no .B HELO command will be given. .PP Although the .B HELO command is required by RFC 821, many SMTP servers do not require it. Early versions of .I SendMail will fail if the hostname given in the .B HELO command is the local host. Later versions of .I SendMail will complain if you omit the .B HELO command. If you run .IR SendMail , find out what your system expects and set this field if needed. .RE .PP .BR systemname : .RS 5 This option is only used for UUCP mail. It specifies the name of the local host in the UUCP \*(lqdomain\*(rq. If not set, depending on the version of Unix you're running, .B nmh will query the system for this value. This has no equivalent in the .B nmh configuration file. .RE .PP .BR mmdfldir : %mailspool% .RS 5 The directory where mail drops are kept. If this option is set, but empty, the user's home directory is used. This overrides the default value chosen at the time of compilation. .RE .PP .BR mmdflfil : .RS 5 The name of the mail drop file in the directory where mail drops are kept. If this is empty, the user's login name is used. This overrides the default value (which is empty). .RE .PP .BR spoollocking : %default_locking% .RS 5 The locking algorithm to use when opening the mail drop. Can be any one of the following: .PP .RS 5 .nf %supported_locks% .fi .RE .RE .PP .BR maildelivery : %nmhlibexecdir%/maildelivery .RS 5 The name of the system-wide default .I maildelivery file. See .IR slocal (1) for the details. .RE .SS "SMTP support" This option is only available if you set .B mts to .BR smtp . .PP .BR servers : localhost .RS 5 A single hostname to be used when performing mail submission via SMTP. Previous versions of .B nmh supported multiple hostnames for .BR servers , but the current version of .B nmh only supports a single entry (the name is kept for backwards compatibility reasons). This can be overridden via the .B \-server switch to .IR send (1). It is not possible to change the mail submission port number in the .B servers entry; see the .B \-port switch to .BR send (1) for this functionality. .SS "SendMail" This option is only available if you set .B mts to .BR sendmail . .PP .BR sendmail : %sendmailpath% .RS 5 The pathname to the .B sendmail program. .RE .SS "Post Office Protocol" .BR pophost : .RS 5 The name of the default POP service host. If this is not set, then .B nmh looks in the standard mail drop areas for waiting mail, otherwise the named POP service host is consulted. .RE .\" .SS "BBoards Delivery" .\" This option is only available if you compiled \fInmh\fP with .\" \*(lqbbdelivery:\ on\*(rq. .\" .PP .\" .BR bbdomain : .\" .RS 5 .\" The local BBoards domain (a UCI hack). .\" .RE .\" .SS "BBoards & The POP" .\" These options are only available if you compiled \fInmh\fP with .\" \*(lqbboards:\ pop\*(rq and \*(lqpop:\ on\*(rq. .\" .PP .\" .BR popbbhost : .\" .RS 5 .\" The POP service host which also acts as a BBoard server. This variable .\" should be set on the POP BBoards client host. .\" .RE .\" .PP .\" .BR popbbuser : .\" .RS 5 .\" The guest account on the POP/BB service host. This should be a different .\" login ID than either the POP user or the BBoards user. (The user-id .\" \*(lqftp\*(rq is highly recommended.) This variable should be set on .\" both the POP BBoards client and service hosts. .\" .RE .\" .PP .\" .BR popbblist : .\" %nmhetcdir%/hosts.popbb .\" .RS 5 .\" A file containing of lists of hosts that are allowed to use the POP .\" facility to access BBoards using the guest account. If this file is not .\" present, then no check is made. This variable should be set on the POP .\" BBoards service host. .\" .RE .SS "File Locking" A few words on locking: .B nmh has two main uses for locking: locking the mail spool during mail incorporation, and locking metadata files (sequence files, the context) during updates. These locking methods can be configured separately from each other. .PP For locking the mail spool, the .B spoollocking entry in .IR mh\-tailor (5) will control the locking algorithm to use when .B inc incorporates mail from the spool file. If no entry is given, a default based on the operating system type will be chosen. .PP For locking all other files, the .B datalocking entry in .IR mh-profile (5) controls the locking algorithm used for all other file access. If no entry is given, the .B fcntl lock method will be chosen. .PP If you do not wish to use kernel-based locking, .I dot locking is an option available. If \*(lq--enable-lockdir=directory\*(rq is not specified at build time, lock files will be created in the directory where the file being locked resides. Otherwise, lock files will be created in the directory specified by \*(lq--enable-lockdir\*(rq. .PP Prior to installing .BR nmh , you should see how locking is done at your site, and set the appropriate values. .SH FILES .TP 20 %nmhetcdir%/mts.conf nmh mts configuration file .SH "PROFILE COMPONENTS" None .SH "SEE ALSO" .IR mh\-mts (8), .IR post (8) .SH DEFAULTS As listed above. The path of the mail transport configuration file can be changed with the MHMTSCONF environment variable and augmented with the MHMTSUSERCONF environment variable, see .IR mh\-profile (5). .SH BUGS Failure to open any mail transport configuration file is silently ignored. Therefore, it's best to avoid dynamic creation of such a file with the intent of use via the MHMTSCONF or MHMTSUSERCONF environment variables. If such use is necessary, the ability to successfully open the file should first be verified. nmh-1.7.1-RC3/man/MH.man000644 007761 000024 00000000017 13205305704 014533 0ustar00kenhstaff000000 000000 .so man7/nmh.7 nmh-1.7.1-RC3/man/mh_profile.man000644 007761 000024 00000000026 12437351011 016351 0ustar00kenhstaff000000 000000 .so man5/mh-profile.5 nmh-1.7.1-RC3/man/mhbuild.man000644 007761 000024 00000066516 13243042053 015670 0ustar00kenhstaff000000 000000 .TH MHBUILD %manext1% 2016-10-15 "%nmhversion%" . .\" %nmhwarning% . .SH NAME mhbuild \- translate MIME composition drafts for nmh messages .SH SYNOPSIS .na .HP 5 .B mhbuild .RB [ \-help ] .RB [ \-version ] .I file .RB [ \-auto " | " \-noauto ] .RB [ \-list " | " \-nolist ] .RB [ \-realsize " | " \-norealsize ] .RB [ \-headers " | " \-noheaders ] .RB [ \-directives " | " \-nodirectives ] .RB [ \-rfc934mode " | " \-norfc934mode ] .RB [ \-contentid " | " \-nocontentid ] .RB [ \-verbose " | " \-noverbose ] .RB [ \-disposition " | " \-nodisposition ] .RB [ \-check " | " \-nocheck ] .RB [ \-headerencoding .IR encoding-algorithm .RB " | " \-autoheaderencoding ] .RB [ \-maxunencoded .IR line-length ] .RB [ \-dist ] .ad .SH DESCRIPTION The .B mhbuild command will translate a MIME composition draft into a valid MIME message. .PP .B mhbuild creates multi-media messages as specified in RFCs 2045 through 2049. This includes the encoding of message headers as specified by RFC 2047, and, additionally, the encoding of MIME parameters as specified in RFC 2231. .PP If you specify the name of the composition file as \*(lq-\*(rq, then .B mhbuild will accept the composition draft on the standard input. If the translation of this input is successful, .B mhbuild will output the new MIME message to the standard output. This argument must be the last argument on the command line. .PP Otherwise, if the file argument to .B mhbuild is the name of a valid composition file, and the translation is successful, .B mhbuild will replace the original file with the new MIME message. It will rename the original file to start with the \*(lq,\*(rq character and end with the string \*(lq.orig\*(rq, e.g., if you are editing the file \*(lqdraft\*(rq, it will be renamed to \*(lq,draft.orig\*(rq. This allows you to easily recover the .B mhbuild input file. .SS "Listing the Contents" The .B \-list switch tells .B mhbuild to list the table of contents associated with the MIME message that is created. .PP The .B \-headers switch indicates that a one-line banner should be displayed above the listing. The .B \-realsize switch tells .B mhbuild to evaluate the \*(lqnative\*(rq (decoded) format of each content prior to listing. This provides an accurate count at the expense of a small delay. If the .B \-verbose switch is present, then the listing will show any \*(lqextra\*(rq information that is present in the message, such as comments in the \*(lqContent-Type\*(rq header. .PP If the .B \-disposition switch is present, then the listing will show any relevant information from the \*(lqContent-Disposition\*(rq header. .SS "Simplified Attachment Interface" For users who wish to simply attach files to text content, .B mhbuild will scan the composition file for \*(lqAttach\*(rq headers. An \*(lqAttach\*(rq header contains a filename that will be appended to the message using normal MIME encapsulation rules. One filename is allowed per \*(lqAttach\*(rq header, but multiple \*(lqAttach\*(rq headers are allowed per composition file. .PP These files will be appended after any other MIME content, including any content specified by .B mhbuild directives (see below). See .IR send (1) for more details. .PP By default, the Content-Disposition will be \*(lqattachment\*(rq. .B mhbuild looks for user profile and .I mhn.defaults entries of the form .PP .RS 5 .BI mhbuild-disposition- type / subtype .RE or .RS 5 .BI mhbuild-disposition- type .RE .PP to supply the disposition value. The only supported values are \*(lqattachment\*(rq and \*(lqinline\*(rq. .SS "Convert Interface" The convert interface is a powerful mechanism that supports replying to MIME messages. These placeholders are used in the following description: .RS 5 .TP 15 .PD 0 TYPE content type/subtype .TP CONVERTER external program, and any fixed arguments, to convert content, such as from a request to a reply .TP ARGSTRING arguments to pass from .B repl to .I CONVERTER .TP FILE full path of message being replied to .PD .RE The convert support is based on pseudoheaders of the form .PP .RS 5 .nf .BI Nmh-mhbuild-file- TYPE : \0FILE .BI Nmh-mhbuild-args- TYPE : \0ARGSTRING .fi .RE .PP in the draft. For each such pseudoheader, mhbuild looks in the profile and .I mhn.defaults for the corresponding .I TYPE entry to find the converter that supports it: .PP .RS 5 .BI mhbuild-convert- TYPE : \0CONVERTER .RE .PP It's a fatal error if no such entry is found for .IR TYPE . An empty entry, e.g., .PP .RS 5 .B mhbuild-convert-text/html: .RE .PP excludes parts of that .I TYPE from the draft. .PP The .I mhn.defaults file contains default .B mhbuild-convert-text/html and .BR mhbuild-convert-text/plain entries. Profile entries can be used to override corresponding .I mhn.defaults entries, as usual. Text converters should limit text line lengths to a maximum of 78 characters, and must limit them to a maximum of 998 characters, per RFC 5322 Sec.\& 2.1.1. .PP For each .I TYPE part in .IR FILE , .B mhbuild runs .I CONVERTER ARGSTRING on the content of the part. Each part in .I FILE that has no corresponding TYPE entry in the profile or .I mhn.defaults is excluded from the draft; the user can include them using mhbuild directives. .PP .B repl inserts .B Nmh-mhbuild-text/html: and .B Nmh-mhbuild-text/plain: pseudoheaders in every draft. The user can prevent insertion of content parts of either of those types by putting corresponding empty entries in their profile. .PP Only the highest precedence alternative with a supported .I TYPE of a multipart/alternative part is used. .PP mhn.defaults.sh selects the text/html-to-text/plain converter at install time. It includes .B iconv and .BR par , or .BR fmt , in the pipeline only if they are found. .PP Some content types require the addition of parameters to the Content-Type header, such as \*(lqmethod=REPLY\*(rq for text/calendar. .B mhbuild looks for a Content-Type header, followed by a blank line, at the beginning of the converter output. If one is found, it is used for the corresponding part in the reply draft. .PP The convert interface doesn't support different .IR ARGSTRING s or different converters for different parts of the same .IR TYPE . That would require associating parts by part number with the .IR ARGSTRING s or converters. Instead, that can be done (currently, without using the convert support), with .B mhbuild directives as described below, e.g., .PP .RS 5 #text/html; charset=utf-8 *8bit | mhstore -noverbose -part 42.7 -outfile - | w3m -dump -cols 64 -T text/html -O utf-8 .RE .PP The only way to mix convert pseudoheaders and .B mhbuild directives is to insert the directives before .B mhbuild is run, which is typically done by entering .I mime at the \*(lqWhat now?\*(rq prompt, or with an .B \-editor mhbuild switch. .PP These (optional) setup steps can make the convert support easier to use: .TP 5 1) If the .B par program is installed on your system, it will be set by default (in .IR mhn.defaults ) to filter the converter output. It helps to set the PARINIT environment variable, as described in .IR par (1). .TP 5 2) Add this line to your profile: .IP "" 10 mhbuild-next: $EDITOR .IP "" 5 assuming that your EDITOR environment variable is set; if not, replace EDITOR with the name of your editor. Without that profile entry, a response of \*(lqe[dit]\*(rq at the What now? prompt will require specification of your editor if an .B \-editor mhbuild switch is used. .TP 5 3) If using .BR repl , source the Bourne-shell compatible functions in .IR %docdir%/contrib/replaliases . .br That script also sets the PARINIT environment variable if it was not set. .SS "Translating the Composition File" .B mhbuild is essentially a filter to aid in the composition of MIME messages. .B mhbuild will convert an .B mhbuild \*(lqcomposition file\*(rq into a valid MIME message. An .B mhbuild \*(lqcomposition file\*(rq is just a file containing plain text that is interspersed with various .B mhbuild directives. When this file is processed by .BR mhbuild , the various directives will be expanded to the appropriate content, and will be encoded according to the MIME standards. The resulting MIME message can then be sent by electronic mail. .PP The formal syntax for a .B mhbuild composition file is defined at the end of this document, but the ideas behind this format are not complex. Basically, the body contains one or more contents. A content consists of either a directive, indicated with a \*(lq#\*(rq as the first character of a line; or, plaintext (one or more lines of text). The continuation character, \*(lq\\\*(lq, may be used to enter a single directive on more than one line, e.g., .PP .RS 5 .nf #image/png \\ /home/foobar/junk/picture.png .fi .RE .PP There are five kinds of directives: \*(lqtype\*(rq directives, which name the type and subtype of the content; \*(lqexternal-type\*(rq directives, which also name the type and subtype of the content; the \*(lqmessage\*(rq directive (#forw), which is used to forward one or more messages; the \*(lqbegin\*(rq directive (#begin), which is used to create a multipart content; and the \*(lqon/off/pop\*(rq directives (#on, #off, #pop) which control whether any other directives are honored at all. .PP The .B \-directives switch allows control over whether mhbuild will honor any of the \*(lq#\*(rq-directives. This can also be affected with the #on or #off directives, and #pop, which restores the state of processing to that preceding the most recent #on or #off. (The #on, #off, and #pop directives are always honored, of course.) This allows inclusion of plain text which looks like mhbuild directives, without causing errors: .PP .RS 5 .nf #off #include printf("Hello, World!"); #pop .fi .RE .PP Currently the stack depth for the #on/off/pop directives is 32. .PP The \*(lqtype\*(rq directive is used to directly specify the type and subtype of a content. You may only specify discrete types in this manner (can't specify the types multipart or message with this directive). You may optionally specify the name of a file containing the contents in \*(lqnative\*(rq (decoded) format. If this filename starts with the \*(lq|\*(rq character, then it represents a command to execute whose output is captured accordingly. For example, .PP .RS 5 .nf #audio/basic |raw2audio -F < /usr/lib/sound/giggle.au .fi .RE .PP If a filename is not given, .B mhbuild will look for information in the user's profile to determine how the different contents should be composed. This is accomplished by consulting a composition string, and executing it under .BR /bin/sh , with the standard output set to the content. If the .B \-verbose switch is given, .B mhbuild will echo any commands that are used to create contents in this way. .PP The composition string may contain the following escapes: .PP .RS 5 .PD 0 .IP %a Insert parameters from directive .IP %f Insert filename containing content .IP %F %f, and stdout is not re-directed .IP %s Insert content subtype .IP %% Insert character % .PD .RE .PP First, .B mhbuild will look for an entry of the form: .PP .RS 5 .BI mhbuild-compose- type / subtype .RE .PP to determine the command to use to compose the content. If this isn't found, .B mhbuild will look for an entry of the form: .PP .RS 5 .BI mhbuild-compose- type .RE .PP to determine the composition command. If this isn't found, .B mhbuild will complain. .PP An example entry might be: .PP .RS 5 mhbuild-compose-audio/basic: record | raw2audio -F .RE .PP Because commands like these will vary, depending on the display environment used for login, composition strings for different contents should probably be put in the file specified by the MHBUILD environment variable, instead of directly in your user profile. .PP The \*(lqexternal-type\*(rq directives are used to provide a MIME reference to a content, rather than enclosing the contents itself (for instance, by specifying an ftp site). Hence, instead of providing a filename as with the type directives, external-parameters are supplied. These look like regular parameters, so they must be separated accordingly. For example, .PP .RS 5 .nf #@application/octet-stream; \\ type=tar; \\ conversions=compress \\ [this is the nmh distribution] \\ {attachment; filename="nmh.tar.gz"} \\ name="nmh.tar.gz"; \\ directory="/pub/nmh"; \\ site="ftp.math.gatech.edu"; \\ access-type=anon-ftp; \\ mode="image" .fi .RE .PP You must give a description string to separate the content parameters from the external-parameters (although this string may be empty). This description string is specified by enclosing it within \*(lq[]\*(rq. A disposition string, to appear in a \*(lqContent-Disposition\*(rq header, may appear in the optional \*(lq{}\*(rq. .PP These parameters are of the form: .PP .RS 5 .nf .ta \w'access-type= 'u access-type= usually \*(lqanon-ftp\*(rq, \*(lqmail-server\*(rq, or \*(lqurl\*(rq name= filename permission= read-only or read-write site= hostname directory= directoryname (optional) mode= usually \*(lqascii\*(rq or \*(lqimage\*(rq (optional) size= number of octets server= mailbox subject= subject to send body= command to send for retrieval url= URL of content .fi .RE .PP A minimum \*(lqexternal\-type\*(rq directive for the .B url .I access-type would be as follows: .PP .RS 3 .nf #@application/octet-stream [] access-type=url; \\ url="http://download.savannah.gnu.org/releases/nmh/nmh-1.5.tar.gz" .fi .RE .PP Any long URLs will be wrapped according to RFC 2231 rules. .PP The \*(lqmessage\*(rq directive (#forw) is used to specify a message or group of messages to include. You may optionally specify the name of the folder and which messages are to be forwarded. If a folder is not given, it defaults to the current folder. Similarly, if a message is not given, it defaults to the current message. Hence, the message directive is similar to the .B forw command, except that the former uses the MIME rules for encapsulation rather than those specified in RFC 934. For example, .PP .RS 5 .nf #forw +inbox 42 43 99 .fi .RE .PP If you include a single message, it will be included directly as a content of type \*(lqmessage/rfc822\*(rq. If you include more than one message, then .B mhbuild will add a content of type \*(lqmultipart/digest\*(rq and include each message as a subpart of this content. .PP If you are using this directive to include more than one message, you may use the .B \-rfc934mode switch. This switch will indicate that .B mhbuild should attempt to utilize the MIME encapsulation rules in such a way that the \*(lqmultipart/digest\*(rq that is created is (mostly) compatible with the encapsulation specified in RFC 934. If given, then RFC 934 compliant user-agents should be able to burst the message on reception\0--\0providing that the messages being encapsulated do not contain encapsulated messages themselves. The drawback of this approach is that the encapsulations are generated by placing an extra newline at the end of the body of each message. .PP The \*(lqbegin\*(rq directive is used to create a multipart content. When using the \*(lqbegin\*(rq directive, you must specify at least one content between the begin and end pairs. .PP .RS 5 .nf #begin This will be a multipart with only one part. #end .fi .RE .PP If you use multiple directives in a composition draft, .B mhbuild will automatically encapsulate them inside a multipart content. Therefore the \*(lqbegin\*(rq directive is only necessary if you wish to use nested multiparts, or create a multipart message containing only one part. .PP For all of these directives, the user may include a brief description of the content between the \*(lq[\*(rq character and the \*(lq]\*(rq character. This description will be copied into the \*(lqContent-Description\*(rq header when the directive is processed. .PP .RS 5 .nf #forw [important mail from Bob] +bob 1 2 3 4 5 .fi .RE .PP Similarly, a disposition string may optionally be provided between \*(lq{\*(rq and \*(lq}\*(rq characters; it will be copied into the \*(lqContent-Disposition\*(rq header when the directive is processed. If a disposition string is provided that does not contain a filename parameter, and a filename is provided in the directive, it will be added to the \*(lqContent-Disposition\*(rq header. For example, the following directive: .PP .RS 5 .nf #text/plain; charset=iso-8859-1 <>{attachment} /tmp/summary.txt .fi .RE .PP creates these message part headers: .PP .RS 5 .nf Content-Type: text/plain; charset="iso-8859-1" Content-Disposition: attachment; filename="summary.txt" .fi .RE .PP By default, .B mhbuild will generate a unique \*(lqContent-ID:\*(rq for each directive, corresponding to each message part; however, the user may override this by defining the ID using the \*(lq<\*(rq and \*(lq>\*(rq characters. The .B \-nocontentid switch suppresses creation of all \*(lqContent-ID:\*(rq headers, even in the top level of the message. .PP Normally .B mhbuild will choose an appropriate Content\-Transfer\-Encoding based on the content and the MIME Content\-Type. However, you can override that in an .B mhbuild directive by specifying \*(lq*\*(rq and the encoding. Acceptable encoding values are \*(lq8bit\*(rq, \*(lqqp\*(rq (for quoted-printable), and \*(lqb64\*(rq (for base64 encoding). It should be noted that undesired results may occur if 8bit or quoted-printable is selected for binary content, due to the translation between Unix line endings and the line endings use by the mail transport system. .PP In addition to the various directives, plaintext can be present. Plaintext is gathered, until a directive is found or the draft is exhausted, and this is made to form a text content. If the plaintext must contain a \*(lq#\*(rq at the beginning of a line, simply double it, e.g., .PP .RS 5 ##when sent, this line will start with only one # .RE .PP If you want to end the plaintext prior to a directive, e.g., to have two plaintext contents adjacent, simply insert a line containing a single \*(lq#\*(rq character, e.g., .PP .RS 5 .nf this is the first content # and this is the second .fi .RE .PP Finally, if the plaintext starts with a line of the form: .PP .RS 5 Content-Description: text .RE .PP then this will be used to describe the plaintext content. You MUST follow this line with a blank line before starting your text. .PP By default, plaintext is captured as a text/plain content. You can override this by starting the plaintext with \*(lq#<\*(rq followed by a content-type specification. For example, e.g., .PP .RS 5 .nf #" ] [ "[" description "]" ] [ "{" disposition "}" ] [ "*8bit" | "*qp" | "*b64" ] [ filename ] EOL | "#@" type "/" subtype 0*(";" attribute "=" value) [ "(" comment ")" ] [ "<" id ">" ] [ "[" description "]" ] [ "{" disposition "}" ] [ "*8bit" | "*qp" | "*b64" ] external-parameters EOL | "#forw" [ "<" id ">" ] [ "[" description "]" ] [ "{" disposition "}" ] [ "+"folder ] [ 0*msg ] EOL | "#begin" [ "<" id ">" ] [ "[" description "]" ] [ "{" disposition "}" ] [ "alternative" | "parallel" | something-else ] EOL 1*body "#end" EOL plaintext ::= [ "Content-Description:" description EOL EOL ] 1*line [ "#" EOL ] | "#<" type "/" subtype 0*(";" attribute "=" value) [ "(" comment ")" ] [ "[" description "]" ] [ "{" disposition "}" ] [ "*8bit" | "*qp" | "*b64" ] EOL 1*line [ "#" EOL ] line ::= "##" text EOL -- interpreted as "#"text EOL | text EOL .fi .RE .SH FILES .B mhbuild looks for additional user profile files and .I mhn.defaults in multiple locations: absolute pathnames are accessed directly, tilde expansion is done on usernames, and files are searched for in the user's .I Mail directory as specified in their profile. If not found there, the directory .RI \*(lq %nmhetcdir% \*(rq is checked. .PP .PD 0 .TP 20 $HOME/.mh_profile The user's profile. .TP $MHBUILD Additional profile entries. .TP %nmhetcdir%/mhn.defaults System default MIME profile entries. .PD .SH "PROFILE COMPONENTS" .PD 0 .TP 20 Path: To determine the user's nmh directory. .TP Current\-Folder: To find the default current folder. .TP .RI mhbuild-compose- type* : Template for composing contents. .PD .SH "SEE ALSO" .IR mhlist (1), .IR mhshow (1), .IR mhstore (1) .PP .I "Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies" (RFC 2045) .PP .I "Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types" (RFC 2046) .PP .I "Multipurpose Internet Mail Extensions (MIME) Part Three: Message Header Extensions for Non-ASCII Text" (RFC 2047) .PP .I "Internet Message Format" (RFC 5322) .PP .I "MIME Parameter Value and Encoded Word Extensions: Character Sets, Languages, and Continuations" (RFC 2231) .PP .I "Proposed Standard for Message Encapsulation" (RFC 934) .PP .I "The Content-MD5 Header Field" (RFC 1864) .PP .I "Definition of the URL MIME External-Body Access-Type" (RFC 2017) .PP .I "Overview and Framework for Internationalized Email" (RFC 6530) .PP .I "SMTP Extension for Internationalized Email" (RFC 6531) .SH DEFAULTS .nf \-autoheaderencoding \-contentid \-headers \-maxunencoded 78 \-nocheck \-nodisposition \-norfc934mode \-noverbose \-realsize .fi nmh-1.7.1-RC3/man/mhfixmsg.man000644 007761 000024 00000035113 13243042053 016053 0ustar00kenhstaff000000 000000 .TH MHFIXMSG %manext1% 2016-11-08 "%nmhversion%" . .\" %nmhwarning% . .SH NAME mhfixmsg \- nmh's MIME-email rewriter with various transformations .SH SYNOPSIS .HP 5 .na .B mhfixmsg .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RI [ msgs " | " .IR "absolute pathname" " | " .RB \-file .IR file ] .RB [ \-decodetext 8bit|7bit|binary | .BR \-nodecodetext ] .RB [ \-decodetypes .IR "type/[subtype][,...]" ] .RB [ \-crlflinebreaks " | " \-nocrlflinebreaks ] .RB [ \-textcharset .I charset .RB "| " \-notextcharset ] .RB [ \-reformat " | " \-noreformat ] .RB [ \-replacetextplain " | " \-noreplacetextplain ] .RB [ \-fixboundary " | " \-nofixboundary ] .RB [ \-fixcte " | " \-nofixcte ] .RB [ \-fixtype .IR mimetype ] .RB [ \-outfile .IR outfile ] .RB [ \-rmmproc .IR program ] .RB [ \-normmproc ] .RB [ \-changecur " | " \-nochangecur ] .RB [ \-verbose " | " \-noverbose ] .ad .SH DESCRIPTION .B mhfixmsg rewrites MIME messages, applying specific transformations such as decoding of MIME-encoded message parts and repairing invalid MIME headers. .PP MIME messages are specified in RFC 2045 to RFC 2049 (see .IR mhbuild (1)). The .B mhlist command is invaluable for viewing the content structure of MIME messages. .B mhfixmsg passes non-MIME messages through without any transformations. If no transformations apply to a MIME message, the original message or file is not modified or removed. Thus, .B mhfixmsg can safely be run multiple times on a message. .PP The .B \-decodetext switch enables a transformation to decode each base64 and quoted-printable text message part to the selected 8-bit, 7-bit, or binary encoding. If 7-bit is selected for a base64 part but it will only fit 8-bit, as defined by RFC 2045, then it will be decoded to 8-bit quoted-printable. Similarly, with 8-bit, if the decoded text would be binary, then the part is not decoded (and a message will be displayed if .B \-verbose is enabled). Note that .B \-decodetext binary can produce messages that are not RFC 2045 compliant. .PP When the .B \-decodetext switch is enabled, each carriage return character that precedes a linefeed character is removed from text parts encoded in ASCII, ISO-8859-x, UTF-8, or Windows-12xx. .PP The .B \-decodetypes switch specifies the message parts, by type and optionally subtype, to which .B \-decodetext applies. Its argument is a comma-separated list of type/subtype elements. If an element does not contain a subtype, then .B \-decodetext applies to all subtypes of the type. The default is .B \-decodetypes .IR text ; it can be overridden, e.g., with .B \-decodetypes .I text/plain to restrict .B \-decodetext to just text/plain parts. .PP By default, carriage return characters are preserved or inserted at the end of each line of text content. The .B \-crlflinebreaks switch selects this behavior and is enabled by default. The .B \-nocrlflinebreaks switch causes carriage return characters to be stripped from, and not inserted in, text content when it is decoded and encoded. Note that its use can cause the generation of MIME messages that do not conform to RFC 2046, §4.1.1, paragraph 1. .PP The .B \-textcharset switch specifies that all text/plain parts of the message(s) should be converted to .IR charset . Charset conversions require that .B nmh be built with .IR iconv (3); see the .BR mhparam (1) man page for how determine whether your .B nmh installation includes that. To convert text parts other than text/plain, an external program can be used, via the .B \-reformat switch. .PP The .B \-reformat switch enables a transformation for text parts in the message. For each text part that is not text/plain and that does not have a corresponding text/plain in a multipart/alternative part, .B mhfixmsg looks for a mhfixmsg-format-text/subtype profile entry that matches the subtype of the part. If one is found and can be used to successfully convert the part to text/plain, .B mhfixmsg inserts that text/plain part at the beginning of the containing multipart/alternative part, if present. If not, it creates a multipart/alternative part. .PP With the .B \-reformat switch, multipart/related parts are handled differently than multipart/alternative. If the multipart/related has only a single part that is not text/plain and can be converted to text/plain, a text/plain part is added and the type of the part is changed to multipart/alternative. If the multipart/related has more than one part but does not have a text/plain part, .B mhfixmsg tries to add one. .PP The .B \-replacetextplain switch broadens the applicability of .BR \-reformat , by always replacing a corresponding text/plain part, if one exists. If .B \-verbose is enabled, the replacement will be shown as two steps: a removal of the text/plain part, followed by the usual insertion of a new part. .PP .B \-reformat requires a profile entry for each text part subtype to be reformatted. The mhfixmsg-format-text/subtype profile entries are based on external conversion programs, and are used in the same way that .B mhshow uses its mhshow-show-text/subtype entries. When .B nmh is installed, it searches for a conversion program for text/html content, and if one is found, inserts a mhfixmsg-format-text/html entry in %nmhetcdir%/mhn.defaults. An entry of the same name in the user's profile takes precedence. The user can add entries for other text subtypes to their profile. .PP The .B \-fixboundary switch enables a transformation to repair the boundary portion of the Content-Type header field of the message to match the boundaries of the outermost multipart part of the message, if it does not. That condition is indicated by a \*(lqbogus multipart content in message\*(rq error message from .B mhlist and other .B nmh programs that parse MIME messages. .PP The .B \-fixcte switch enables a transformation to change the Content-Transfer-Encoding from an invalid value to 8-bit in message parts with a Content-Type of multipart and message, as required by RFC 2045, §6.4. That condition is indicated by a \*(lqmust be encoded in 7bit, 8bit, or binary\*(rq error message from .B mhlist and other .B nmh programs that parse MIME messages. .PP The .B \-fixtype switch ensures that each part of the message has the correct MIME type shown in its Content-Type header. It may be repeated. It is typically used to replace \*(lqapplication/octet-stream\*(rq with a more descriptive MIME type. It may not be used for multipart and message types. .PP .B mhfixmsg applies two transformations unconditionally. The first removes an extraneous trailing semicolon from the parameter lists of MIME header field values. The second replaces RFC 2047 encoding with RFC 2231 encoding of name and filename parameters in Content-Type and Content-Disposition header field values, respectively. .PP The .B \-verbose switch directs .B mhfixmsg to output informational message for each transformation applied. .PP The return status of .B mhfixmsg is 0 if all of the requested transformations are performed, or non-zero otherwise. .RB ( mhfixmsg will not decode to binary content with the default .B \-decodetext setting, but a request to do so is not considered a failure, and is noted with .BR \-verbose .) If a problem is detected with any one of multiple messages such that the return status is non-zero, then none of the messages will be modified. .PP The .B \-file .I file switch directs .B mhfixmsg to use the specified file as the source message, rather than a message from a folder. Only one file argument may be provided. The .B \-file switch is implied if .I file is an absolute pathname. If the file is \*(lq-\*(rq, then .B mhfixmsg accepts the source message on the standard input stream. If the .B \-outfile switch is not enabled when using the standard input stream, .B mhfixmsg will not produce a transformed output message. .PP .BR mhfixmsg , by default, transforms the message in place. If the .B \-outfile switch is enabled, then .B mhfixmsg does not modify the input message or file, but instead places its output in the specified file. An outfile name of \*(lq-\*(rq specifies the standard output stream. .PP Combined with the .B \-verbose switch, the .B \-outfile switch can be used to show what transformations .B mhfixmsg would apply without actually applying them, e.g., .PP .RS 5 mhfixmsg -outfile /dev/null -verbose .RE .PP As always, this usage obeys any .B mhfixmsg switches in the user's profile. .PP .B \-outfile can be combined with .B rcvstore to add a single transformed message to a different folder, e.g., .PP .RS 5 mhfixmsg -outfile - | \\ .RS 0 %nmhlibexecdir%/rcvstore +folder .RE .RE .SS Summary of Applicability The transformations apply to the parts of a message depending on content type and/or encoding as follows: .PP .RS 5 .nf .ta \w'\-crlflinebreaks 'u \-decodetext base64 and quoted-printable encoded text parts \-decodetypes limits parts to which -decodetext applies \-crlflinebreaks text parts \-textcharset text/plain parts \-reformat text parts that are not text/plain \-fixboundary outermost multipart part \-fixcte multipart or message part \-fixtype all except multipart and message parts .fi .RE .SS "Backup of Original Message/File" If it applies any transformations to a message or file, and the .B \-outfile switch is not used, .B mhfixmsg backs up the original the same way as .BR rmm . That is, it uses the .I rmmproc profile component, if present. If not present, .B mhfixmsg moves the original message to a backup file. The .B \-rmmproc switch may be used to override this profile component. The .B \-normmproc switch disables the use of any .I rmmproc profile component and negates all prior .B \-rmmproc switches. .SS "Integration with inc" .B mhfixmsg can be used as an add-hook, as described in %docdir%/README-HOOKS. Note that add-hooks are called from all .B nmh programs that add a message to a folder, not just .BR inc . Alternatively, a simple shell alias or function can be used to call .B mhfixmsg immediately after a successful invocation of .BR inc . One approach could be based on: .PP .RS 5 msgs=`inc -format '%(msg)'` && [ -n "$msgs" ] && scan $msgs && \ mhfixmsg -nochangecur $msgs .RE .PP Another approach would rely on adding a sequence to Unseen-Sequence, which .B inc sets with the newly incorporated messages. Those could then be supplied to .BR mhfixmsg . An example is shown below. .SS "Integration with procmail" By way of example, here is an excerpt from a procmailrc file that filters messages through .B mhfixmsg before storing them in the user's .I nmh-workers folder. It also stores the incoming message in the .I Backups folder in a filename generated by .BR mkstemp , which is a non-POSIX utility to generate a temporary file. Alternatively, .B mhfixmsg could be called on the message after it is stored. .PP .RS 5 .nf .ta \w'\-fixboundary 'u PATH = %bindir%:$PATH LANG = en_US.utf8 MAILDIR = `mhparam path` #### The Backups directory is relative to MAILDIR. MKSTEMP = 'mkstemp -directory Backups -prefix mhfixmsg' MHFIXMSG = 'mhfixmsg -noverbose -file - -outfile -' STORE = %nmhlibexecdir%/rcvstore :0 w: nmh-workers/procmail.$LOCKEXT * ^TOnmh-workers@nongnu.org | tee `$MKSTEMP` | $MHFIXMSG | $STORE +nmh-workers .fi .RE .SH "EXAMPLES" .SS Basic usage To run .B mhfixmsg on the current message in the current folder, with default transformations to fix MIME boundaries and Content-Transfer-Encoding, to decode text and application/ics content parts to 8 bit, and to add a corresponding text/plain part where lacking: .PP .RS .nf mhfixmsg -verbose .fi .RE .SS Specified folder and messages To run .B mhfixmsg on specified messages, without its informational output: .PP .RS .nf mhfixmsg +inbox last:4 .fi .RE .SS View without modification By default, .B mhfixmsg transforms the message in place. To view the MIME structure that would result from running .B mhfixmsg on the current message, without modifying the message: .PP .RS .nf mhfixmsg -outfile - | mhlist -file - .fi .RE .SS Search message without modification To search the current message, which possibly contains base64 or quoted printable encoded text parts, without modifying it, use the .B \-outfile switch: .PP .RS .nf mhfixmsg -outfile - | grep \fIpattern\fR .fi .RE .PP .B \-outfile can be abbreviated in usual MH fashion, e.g., to -o. The search will be on the entire message, not just text parts. .SS Translate text/plain parts to UTF-8 To translate all text/plain parts in the current message to UTF-8, in addition to all of the default transformations: .PP .RS .nf mhfixmsg -textcharset utf-8 .fi .RE .SS Fix all messages in a folder To run .B mhfixmsg on all of the messages in a folder: .PP .RS .nf mhfixmsg +folder all .fi .RE .PP Alternatively, .B mhfixmsg can be run on each message separately, e.g., using a Bourne shell loop: .PP .RS .nf for msg in `pick +folder`; do mhfixmsg +folder $msg; done .fi .RE .PP The two appearances of the .B +folder switch in that command protect against concurrent context changes by other .B nmh command invocations. .SS Run on newly incorporated messages To run .B mhfixmsg on messages as they are incorporated: .PP .RS .nf inc && mhfixmsg -nochangecur unseen .fi .RE .PP This assumes that the Unseen-Sequence profile entry is set to .BR unseen , as shown in .IR mh-profile (5). .SH FILES .B mhfixmsg looks for mhn.defaults in multiple locations: absolute pathnames are accessed directly, tilde expansion is done on usernames, and files are searched for in the user's .I Mail directory as specified in their profile. If not found there, the directory .RI \*(lq %nmhetcdir% \*(rq is checked. .PP .fc ^ ~ .nf .ta \w'%nmhetcdir%/mhn.defaults 'u ^$HOME/.mh_profile~^The user profile ^%nmhetcdir%/mhn.defaults~^Default mhfixmsg conversion entries .fi .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u ^Path:~^To determine the user's nmh directory ^Current\-Folder:~^To find the default current folder ^rmmproc:~^Program to delete original messages or files .fi .SH "SEE ALSO" .IR iconv (3), .IR inc (1), .IR mh-mkstemp (1), .IR mh-profile (5), .IR mhbuild (1), .IR mhlist (1), .IR mhparam (1), .IR mhshow (1), .IR procmail (1), .IR procmailrc (5), .IR rcvstore (1), .IR rmm (1) .SH DEFAULTS .nf .RB ` +folder "' defaults to the current folder" .RB ` msgs "' defaults to cur" .RB ` "\-decodetext 8bit"' .RB ` "\-decodetypes text,application/ics"' .RB ` \-crlflinebreaks ' .RB ` \-notextcharset ' .RB ` \-reformat ' .RB ` \-noreplacetextplain ' .RB ` \-fixboundary ' .RB ` \-fixcte ' .RB ` \-changecur ' .RB ` \-noverbose ' .fi .SH CONTEXT If a folder is given, it will become the current folder. The last message selected from a folder will become the current message, unless the .B \-nochangecur switch is enabled. If the .B \-file switch or an absolute pathname is used, the context will not be modified. nmh-1.7.1-RC3/man/mhical.man000644 007761 000024 00000007754 13243042053 015500 0ustar00kenhstaff000000 000000 .TH MHICAL %manext1% 2015-01-04 "%nmhversion%" . .\" %nmhwarning% . .SH NAME mhical \- nmh's manipulator of iCalendar event requests .SH SYNOPSIS .HP 5 .na .B mhical .RB [ \-help ] .RB [ \-version ] .RB [ \-form .IR formatfile ] .RB [ \-format .IR formatstring ] .RB [[ \-reply .IR "accept" " | " "decline" " | " "tentative" "] |" .BR \-cancel ] .RB [ \-contenttype ] .RB [ \-infile .IR infile ] .RB [ \-outfile .IR outfile ] .RB [ \-unfold ] .RB [ \-debug ] .ad .SH DESCRIPTION .B mhical manipulates an iCalendar (.ics) event request, to display it, generate a reply to it, or cancel it. iCalendar event requests and replies are defined by RFC 5545. .PP The default operation is to display the iCalendar event request in a human-readable format. .PP For the display operation, the .B \-format .I string and .B \-form .I formatfile switches may be used to specify a format string or a format file to read. If given a format string, it must be specified as a single argument to the .B \-format switch. If given a format file name with .BR \-form , the file is searched for using the normal .B nmh rules: absolute pathnames are accessed directly, tilde expansion is done on usernames, and files are searched for in the user's .I Mail directory as specified in their profile. If not found there, the directory .RI \*(lq %nmhetcdir% \*(rq is checked. .B mhical defaults to using a format file named .BR mhical.24hour , and will use the one installed in the .RI \*(lq %nmhetcdir% \*(rq directory if not found elsewhere. .PP The following format components are supported: .PP .RS 5 .fc ^ ~ .nf .ta \w'description 'u .BR ^method~^ .BR ^organizer~^ .BR ^summary~^ .BR ^description~^ .BR ^location~^ .BR ^dtstart~^ .BR ^dtend~^ .BR ^attendees~^ .fi .RE .PP Those format names are case-sensitive. Each corresponds to the iCalendar property of the same name as defined in RFC 5545, with the exception of .BR attendees . That is a comma-delimited list of the common name (CN), if available, or email address of Attendee properties. A maximum of 20 will be displayed. .SS Timezone .B mhical will display the event with times converted to the timezone specified by the .B TZ environment variable, if it is set, see tzset(3). If not set, its behavior is implementation defined, but may use the user's local timezone. .SS Reply The .B \-reply switch generates a reply from the event request. The required action parameter must be one of .IR "accept" , .IR "decline" ", or" .IR "tentative" . Delegation is not supported. .SS Cancel The .B \-cancel switch generates an iCalendar event that can be used to cancel the event request. .SS "Input/Output" By default, .B mhical reads from standard input and writes to standard output. The .B \-infile and .BR \-outfile , respectively, switches can be used to override these defaults. .SS "Miscellaneous Switches" The .B \-contenttype switch instructs .B mhical to insert a Content-Type header at the beginning of its output, for use by .BR mhbuild . It can only be used with .B \-reply and .BR \-cancel . .PP The .B \-unfold switch echoes the event request, but with all lines unfolded. .PP The .B \-debug switch reveals minute details of the parse process. .SH FILES .B mhical looks for format files in multiple locations: absolute pathnames are accessed directly, tilde expansion is done on usernames, and files are searched for in the user's .I Mail directory as specified in their profile. If not found there, the directory .RI \*(lq %nmhetcdir% \*(rq is checked. .PP .fc ^ ~ .nf .ta \w'%nmhetcdir%/mhical.24hour 'u ^%nmhetcdir%/mhical.24hour~^The default display template ^%nmhetcdir%/mhical.12hour~^Display template that uses 12-hour clock .fi .SH "SEE ALSO" .IR mhbuild (1), .IR mh\-format (5), .IR tzset (3), .IR repl (1) .SH DEFAULTS .nf .RB ` \-form "' defaults to mhical.24hour" .RB ` \-infile "' defaults to standard input" .RB ` \-outfile "' defaults to standard output" .fi .SH BUGS .B mhical supports only a very limited subset of RRULE formats. Specifically, only a frequency of YEARLY and an interval of 1 are supported. nmh-1.7.1-RC3/man/mhl.man000644 007761 000024 00000025764 13243042053 015024 0ustar00kenhstaff000000 000000 .TH MHL %manext1% 2014-09-15 "%nmhversion%" . .\" %nmhwarning% . .SH NAME mhl \- produce formatted listings of nmh messages .SH SYNOPSIS .HP 5 .na .B %nmhlibexecdir%/mhl .RB [ \-help ] .RB [ \-version ] .RB [ \-bell " | " \-nobell ] .RB [ \-clear " | " \-noclear ] .RB [ \-folder .IR +folder ] .RB [ \-form .IR formfile ] .RB [ \-length .IR lines ] .RB [ \-width .IR columns ] .RB [ \-moreproc .IR program ] .RB [ \-nomoreproc ] .RB [ \-fmtproc .IR program ] .RB [ \-nofmtproc ] .RI [ files .IR \&... ] .ad .SH DESCRIPTION .B mhl is an .B nmh command for filtering and/or displaying text messages. It is the default method of displaying text messages for .B nmh (it is the default .IR showproc ). .PP As with .BR more , each of the messages specified as arguments (or the standard input) will be output. If more than one message file is specified, the user will be prompted prior to each one, and a or will begin the output, with clearing the screen (if appropriate), and (usually CTRL-D) suppressing the screen clear. An (usually CTRL-C) will abort the current message output, prompting for the next message (if there is one), and a (usually CTRL-\) will terminate the program (without core dump). .PP The .B \-bell option tells .B mhl to ring the terminal's bell at the end of each page, while the .B \-clear option tells .B mhl to clear the screen at the end of each page (or output a formfeed after each message). Both of these switches (and their inverse counterparts) take effect only if the profile entry .I moreproc is defined but empty, and .B mhl is outputting to a terminal. If the .I moreproc entry is defined and non-empty, and .B mhl is outputting to a terminal, then .B mhl will cause the .I moreproc to be placed between the terminal and .B mhl and the switches are ignored. Furthermore, if the .B \-clear switch is used and .IR mhl 's output is directed to a terminal, then .B mhl will consult the TERM and TERMCAP environment variables to determine the user's terminal type in order to find out how to clear the screen. If the .B \-clear switch is given and .BR mhl 's output is not directed to a terminal (e.g., a pipe or a file), then .B mhl will send a formfeed after each message. .PP To override the default .I moreproc and the profile entry, use the .B \-moreproc .I program switch. Note that .B mhl will never start a .I moreproc if invoked on a hardcopy terminal. .PP The .B \-length .I length and .B \-width .I width switches set the screen length and width, respectively. These default to the values indicated by TERMCAP, if appropriate, otherwise they default to 40 and 80, respectively. .PP The default format file used by .B mhl is called .RI \*(lq mhl.format \*(rq. .B mhl will first search for this file in the user's .B nmh directory, and will then search in the directory .IR %nmhetcdir% . This default can be changed by using the .B \-form .I formatfile switch. .PP Finally, the .B \-folder .I +folder switch sets the .B nmh folder name, which is used for the \*(lqmessagename:\*(rq field described below. The environment variable .B $mhfolder is consulted for the default value, which .BR next , .BR show , and .B prev initialize appropriately. .PP .B mhl operates in two phases: 1) read and parse the format file, and 2) process each message (file). During phase 1, an internal description of the format is produced as a structured list. In phase 2, this list is walked for each message, outputting message information under the format constraints from the format file. .PP The format file can contain information controlling screen clearing, screen size, wrap-around control, transparent text, component ordering, and component formatting. Also, a list of components to ignore may be specified, and a couple of \*(lqspecial\*(rq components are defined to provide added functionality. Message output will be in the order specified by the order in the format file. .PP Each line of a format file has one of the following forms: .PP .RS 5 .nf ;comment :cleartext variable[,variable...] component:[variable,...] .fi .RE .IP \(bu 4 A line beginning with a `;' is a comment, and is ignored. .IP \(bu 4 A line beginning with a `:' is clear text, and is output exactly as is. .IP \(bu 4 A line containing only a `:' produces a blank line in the output. .IP \(bu 4 A line beginning with \*(lqcomponent:\*(rq defines the format for the specified component, .IP \(bu 4 Remaining lines define the global environment. .PP For example, the line: .PP .RS 5 width=80,length=40,clearscreen,overflowtext="***",overflowoffset=5 .RE .PP defines the screen size to be 80 columns by 40 rows, specifies that the screen should be cleared prior to each page, that the overflow indentation is 5, and that overflow text should be flagged with \*(lq***\*(rq. .PP Following are all of the current variables and their arguments. If they follow a component, they apply only to that component, otherwise, their affect is global. Since the whole format is parsed before any output processing, the last global switch setting for a variable applies to the whole message if that variable is used in a global context (i.e., bell, clearscreen, width, length). .PP .RS 5 .nf .ta \w'noclearscreen 'u +\w'integer/G 'u .I "variable type semantics" width integer screen width or component width length integer screen length or component length offset integer positions to indent \*(lqcomponent: \*(rq overflowtext string text to use at the beginning of an overflow line overflowoffset integer positions to indent overflow lines compwidth integer positions to indent component text after the first line is output uppercase flag output text of this component in all upper case nouppercase flag don't uppercase clearscreen flag/G clear the screen prior to each page noclearscreen flag/G don't clearscreen bell flag/G ring the bell at the end of each page nobell flag/G don't bell component string/L name to use instead of \*(lqcomponent\*(rq for this component nocomponent flag don't output \*(lqcomponent: \*(rq for this component center flag center component on line (works for one-line components only) nocenter flag don't center leftadjust flag strip off leading whitespace on each line of text noleftadjust flag don't leftadjust rtrim flag trim whitespace at end of text lines nortrim flag retain whitespace at end of text lines (default) compress flag change newlines in text to spaces nocompress flag don't compress wrap flag Wrap lines that exceed width (default) nowrap flag Do not perform line wrapping split flag don't combine multiple fields into a single field nosplit flag combine multiple fields into a single field newline flag print newline at end of components (this is the default) nonewline flag don't print newline at end of components formatfield string format string for this component (see below) decode flag decode text as RFC 2047 encoded header field addrfield flag field contains addresses datefield flag field contains dates format flag Run component through formatproc filter (body only) noformat flag Do not run component through formatproc filter (default) formatarg string Argument to format filter .fi .RE .PP To specify the value of integer-valued and string-valued variables, follow their name with an equals-sign and the value. Integer-valued variables are given decimal values, while string-valued variables are given arbitrary text bracketed by double-quotes. If a value is suffixed by \*(lq/G\*(rq or \*(lq/L\*(rq, then its value is useful in a global-only or local-only context (respectively). .PP A line of the form: .PP .RS 5 ignores=component,... .RE .PP specifies a list of components which are never output. .PP The component \*(lqMessageName\*(rq (case-insensitive) will output the actual message name (file name) preceded by the folder name if one is specified or found in the environment. The format is identical to that produced by the .B \-header option to .BR show . .PP The component \*(lqExtras\*(rq will output all of the components of the message which were not matched by explicit components, or included in the ignore list. If this component is not specified, an ignore list is not needed since all non-specified components will be ignored. .PP If \*(lqnocomponent\*(rq is .I not specified, then the component name will be output as it appears in the format file. .PP The default format file is: .PP .RS 5 .nf %mhl_format% .fi .RE .PP The variable \*(lqformatfield\*(rq specifies a format string (see .IR mh\-format (5)). The flag variables \*(lqaddrfield\*(rq and \*(lqdatefield\*(rq (which are mutually exclusive), tell .B mhl to interpret the escapes in the format string as either addresses or dates, respectively. .PP By default, .B mhl does not apply any formatting string to fields containing address or dates (see .IR mh\-mail (5) for a list of these fields). Note that this results in faster operation since .B mhl must parse both addresses and dates in order to apply a format string to them. If desired, .B mhl can be given a default format string for either address or date fields (but not both). To do this, on a global line specify: either the flag addrfield or datefield, along with the appropriate formatfield variable string. .PP The \*(lqformat\*(rq flag specifies that this component will be run through the filter program specified by the .IR formatproc profile entry. This filter program is expected to read data on standard input and output data on standard output. Currently the \*(lqformat\*(rq flag is only supported for the \*(lqbody\*(rq component. The component name will be prefixed to the output .IR after the filter has been run. The expected use of this is to filter a message body to create more pleasing text to use in a reply message. A suggested filter to use for .IR repl(1) is as follows: .PP .RS 5 body:component=">",overflowtext=">",overflowoffset=0,format,nowrap .RE .PP The .B \-fmtproc and .B \-nofmtproc switches can be used to override the .I formatproc profile entry. .PP The .I formatarg option specifies a string that is used as an argument to the format filter. This string is processed by .IR mh\-format (5) and all of the message components are available for use. Multiple .I formatarg options can be used to build up multiple arguments to the format filter. .SH FILES .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^%nmhetcdir%/mhl.format~^The message template ^or /mhl.format~^Rather than the standard template ^$HOME/.mh_profile~^The user profile .fi .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u ^moreproc:~^Program to use as interactive front-end ^formatproc:~^Program to use as a filter for components that ^^have the \*(lqformat\*(rq flag set. .fi .SH "SEE ALSO" .IR show (1), .IR ap (8), .IR dp (8) .SH DEFAULTS .nf .RB ` \-bell ' .RB ` \-noclear ' .RB ` \-length\ 40 ' .RB ` \-width\ 80 ' .fi .SH CONTEXT None .SH BUGS There should be some way to pass `bell' and `clear' information to the front-end. .PP The \*(lqnonewline\*(rq option interacts badly with \*(lqcompress\*(rq and \*(lqsplit\*(rq. .PP The \*(lqformat\*(rq option really should work on something other than the body component. nmh-1.7.1-RC3/man/mhlist.man000644 007761 000024 00000015131 13205305704 015532 0ustar00kenhstaff000000 000000 .TH MHLIST %manext1% 2015-02-06 "%nmhversion%" . .\" %nmhwarning% . .SH NAME mhlist \- list information about nmh MIME messages .SH SYNOPSIS .HP 5 .na .B mhlist .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RI [ msgs ] .RB [ \-file .IR file ] .RB [ \-part .IR number ] \&... .RB [ \-type .IR content ] \&... .RB [ \-prefer .IR content ] \&... .RB [ \-noprefer ] .RB [ \-headers " | " \-noheaders ] .RB [ \-realsize " | " \-norealsize ] .RB [ \-rcache .IR policy ] .RB [ \-wcache .IR policy ] .RB [ \-check " | " \-nocheck ] .RB [ \-changecur " | " \-nochangecur ] .RB [ \-verbose " | " \-noverbose ] .RB [ \-disposition " | " \-nodisposition ] .ad .SH DESCRIPTION The .B mhlist command allows you to list information (a table of contents, essentially) about the various parts of a collection of MIME (multi-media) messages. .PP .B mhlist manipulates MIME messages as specified in RFC 2045 to RFC 2049 (See .IR mhbuild (1)). .PP The .B \-headers switch indicates that a one-line banner should be displayed above the listing (the default). .PP The .B \-realsize switch tells .B mhlist to evaluate the \*(lqnative\*(rq (decoded) format of each content prior to listing. This provides an accurate count at the expense of a small delay. In either case, sizes will be expressed using SI prefix abbreviations (K/M/G/T), which are based on factors of 1000. .PP If the .B \-verbose switch is present, then the listing will show any \*(lqextra\*(rq information that is present in the message, such as comments in the \*(lqContent-Type\*(rq header. .PP If the .B \-disposition switch is present, then the listing will show any relevant information from the \*(lqContent-Disposition\*(rq header. .PP The option .B \-file .I file directs .B mhlist to use the specified file as the source message, rather than a message from a folder. If you specify this file as \*(lq-\*(rq, then .B mhlist will accept the source message on the standard input. Note that the file, or input from standard input should be a validly formatted message, just like any other .B nmh message. It should .I not be in mail drop format (to convert a file in mail drop format to a folder of .B nmh messages, see .IR inc (1)). .PP By default, .B mhlist will list information about the entire message (all of its parts). By using the .BR \-part , .BR \-type , and .B \-prefer switches, you may limit and reorder the set of parts to be listed, based on part number and/or content type. .PP A part specification consists of a series of numbers separated by dots. For example, in a multipart content containing three parts, these would be named as 1, 2, and 3, respectively. If part 2 was also a multipart content containing two parts, these would be named as 2.1 and 2.2, respectively. Note that the .B \-part switch is effective only for messages containing a multipart content. If a message has some other kind of content, or if the part is itself another multipart content, the .B \-part switch will not prevent the content from being acted upon. .PP The .B \-type switch can also be used to restrict (or, when used in conjunction with .BR \-part , to further restrict) the selection of parts according to content type. One or more .B \-type switches part will only select the first match from a multipart/alternative, even if there is more than one subpart that matches (one of) the given content type(s). .PP Using either .B \-part or .B -type switches alone will cause either to select the part(s) they match. Using them together will select only the part(s) matched by both (sets of) switches. In other words, the result is the intersection, and not the union, of their separate match results. .PP A content specification consists of a content type and a subtype. The initial list of \*(lqstandard\*(rq content types and subtypes can be found in RFC 2046. .PP A list of commonly used contents is briefly reproduced here: .PP .RS 5 .nf .ta \w'application 'u Type Subtypes ---- -------- text plain, enriched multipart mixed, alternative, digest, parallel message rfc822, partial, external-body application octet-stream, postscript image jpeg, gif, png audio basic video mpeg .fi .RE .PP A legal MIME message must contain a subtype specification. .PP To specify a content, regardless of its subtype, just use the name of the content, e.g., \*(lqaudio\*(rq. To specify a specific subtype, separate the two with a slash, e.g., \*(lqaudio/basic\*(rq. Note that regardless of the values given to the .B \-type switch, a multipart content (of any subtype listed above) is always acted upon. Further note that if the .B \-type switch is used, and it is desirable to act on a message/external-body content, then the .B \-type switch must be used twice: once for message/external-body and once for the content externally referenced. .PP By default, the parts of a multipart/alternative part are listed in the reverse order of their placement in the message. The listing, therefore, is in decreasing order of preference, as defined in RFC 2046. The .B \-prefer switch can be used (one or more times, in order of ascending preference) to let MH know which content types from a multipart/alternative MIME part are preferred by the user, in order to override the default preference order. Thus, when viewed by .BR mhlist , the ordering of multipart/alternative parts will appear to change when invoked with or without various .B \-prefer switches. The .B \-noprefer switch will cancel any previous .B \-prefer switches. The .B \-prefer and .B \-noprefer switches are functionally most important for .BR mhshow , but are also implemented in .B mhlist and .B mhstore to make common part numbering possible across all three programs. .SS "Checking the Contents" The .B \-check switch tells .B mhlist to check each content for an integrity checksum. If a content has such a checksum (specified as a Content-MD5 header field), then .B mhlist will attempt to verify the integrity of the content. .SH FILES .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^$HOME/.mh_profile~^The user profile .fi .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u ^Path:~^To determine the user's nmh directory ^Current\-Folder:~^To find the default current folder .fi .SH "SEE ALSO" .IR mhbuild (1), .IR mhshow (1), .IR mhstore (1) .SH DEFAULTS .nf .RB ` +folder "' defaults to the current folder" .RB ` msgs "' defaults to cur" .RB ` \-nocheck ' .RB ` \-headers ' .RB ` \-realsize ' .RB ` \-rcache\ ask ' .RB ` \-wcache\ ask ' .RB ` \-changecur ' .RB ` \-noverbose ' .RB ` \-nodisposition ' .fi .SH CONTEXT If a folder is given, it will become the current folder. The last message selected will become the current message, unless the .B \-nochangecur option is specified. nmh-1.7.1-RC3/man/mhlogin.man000644 007761 000024 00000004743 13205305704 015676 0ustar00kenhstaff000000 000000 .TH MHLOGIN %manext1% 2016-10-10 "%nmhversion%" . .\" %nmhwarning% . .SH NAME mhlogin \- nmh login to external (OAuth) services .SH SYNOPSIS .HP 5 .na .B mhlogin .RB [ \-help ] .RB [ \-version ] .RB [ \-user .IR username ] .RB [ \-saslmech .IR mechanism ] .RB [ \-authservice .IR service ] .RB [ \-browser .IR command ] .RB [ \-snoop ] .ad .SH DESCRIPTION .B mhlogin currently only supports OAuth for Gmail. Run .B mhlogin .B \-user .I username .B \-saslmech xoauth2 .B \-authservice .I gmail and load the printed URL in your browser. Login to a Gmail account, grant authorization, and copy and paste the code into the .B mhlogin prompt. Be sure to use the same account with the .B -user switch to .BR send . See the EXAMPLES section below for an example. .PP The .B \-browser switch causes .B mhlogin to load the URL directly into a new browser session. The command argument must include the browser invocation name, and can include any browser arguments in the .B \-browser argument string, e.g., 'google-chrome --new-window'. .PP The .B \-snoop switch can be used to view the HTTP transaction. .PP All parameters configuring the service may be overridden by profile components, and even though only Gmail is supported out of the box, the user can define new services entirely in the profile. Profile components are prefixed by .IR oauth-service- , for example, .I oauth-gmail-credential-file which specifies where .B mhlogin should write credentials and where .B send should read them. .SH "EXAMPLES" .PP .SS Gmail First, login to the Gmail account that you want to use, e.g, user@example.com, using a web browser. Then, enter a .B mhlogin command such as: .PP .RS .nf mhlogin -user user@example.com -saslmech xoauth2 -authservice gmail \ -browser 'google-chrome --new-window' .fi .RE .PP The .I username should be a complete email address. Respond to the prompt in the browser window, then copy and paste the authorization code in response to the .B mhlogin prompt. .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u ^oauth-gmail-credential-file:~^oauth-gmail ^oauth-gmail-client_id:~^nmh project client_id ^oauth-gmail-client_secret:~^nmh project client_secret ^oauth-gmail-auth_endpoint:~^https://accounts.google.com/o/oauth2/auth ^oauth-gmail-redirect_uri:~^urn:ietf:wg:oauth:2.0:oob ^oauth-gmail-token_endpoint:~^https://accounts.google.com/o/oauth2/token ^oauth-gmail-scope:~^https://mail.google.com/ .fi .SH "SEE ALSO" .IR send (1) .SH DEFAULTS .nf .RB ` \-saslmech "' xoauth2" .fi nmh-1.7.1-RC3/man/mhmail.man000644 007761 000024 00000012531 13243042053 015477 0ustar00kenhstaff000000 000000 .TH MHMAIL %manext1% 2012-07-01 "%nmhversion%" . .\" %nmhwarning% . .SH NAME mhmail \- send or read mail non-interactively with nmh .SH SYNOPSIS .HP 5 .na .B mhmail .RB [ \-help ] .RB [ \-version ] .RB [ \-to ] .RI addrs \&... .RB [ \-attach .IR file ] .RB [ \-body .IR text ] .RB [ \-cc .I addrs \&...] .RB [ \-from .IR addr ] .RB [ \-headerfield .IR name:value ] .RB [ \-subject .IR subject ] .RB [ \-resent ] [switches\ for .I post \&... | .RB \-profile [switches\ for .I send \&...]] .RB [ \-send " | " \-nosend ] .HP 5 .B mhmail with no arguments is equivalent to .B inc .ad .SH DESCRIPTION .B mhmail is intended as a replacement, compatible with .BR nmh , for the standard Berkeley mail program .RB ( mail or .BR mailx ). .B nmh is intended for the use of programs such as .BR cron , which expect to send mail automatically. It is also used by some .B nmh commands to mail error notifications. Although .B mhmail can be used interactively, it is recommended that .B comp and .B send be used instead, to send messages. .PP When invoked without arguments, .B mhmail simply invokes .B inc to incorporate new messages from the user's mail drop. .PP When one or more addresses are specified, a message is read from the standard input and spooled to a temporary file. .B mhmail then invokes by default, with the name of the temporary file as its argument, to by default, with the name of the temporary file as its argument to deliver the message to the specified address. .PP The .B \-subject switch can be used to specify the \*(lqSubject:\*(rq field of the message. \*(lqSubject:\*(rq field of the message. .PP The .B \-resent switch indicates that the message body is a fully formed message that will be resent, as .B dist would do. For example: .PP .RS 5 .nf mhmail u2@example.com -resent < `mhpath cur` .fi .RE .PP By default, .B mhmail will read the message to be sent from the standard input. You can specify the text of the message at the command line with the .B \-body .I text switch. If the standard input has zero length, .B mhmail will not send the message and return with status 1. You can use the switch .B \-body \*(lq\*(rq to force an empty message. .PP Normally, addresses appearing as arguments are put in the \*(lqTo:\*(rq field. At least one such address is required when sending a message, i.e., if any other switches are supplied. If the .B \-cc switch is used, all addresses following it, even if there are intervening switches other than .BR \-to , are placed in the \*(lqcc:\*(rq field. The optional .B \-to switch can appear in front of any addresses to signify their placement in the \*(lqTo:\*(rq field. The .B \-to and .B \-cc switches may be given multiple times. .PP By using .B \-from .IR addr , you can specify the \*(lqFrom:\*(rq header of the draft. If no .B \-from switch is used when sending, .B mhmail will supply a \*(lqFrom:\*(rq header field using the sender's local mailbox, see .I localmbox in .IR mh-format (5). Naturally, .B post will fill in the \*(lqSender:\*(rq header correctly. .PP The .B \-headerfield .I name:value switch adds a header field with the specified name and value to the message. (The .I value is called the .I field body in RFC 2822, but that's too easily confused with the message body.) There need not be a space after the colon that separates the name and value in the argument to this switch. It is usually best to enclose the argument in quotes to protect it from the shell. The .B \-headerfield switch may be given multiple times to add multiple header fields, for example, .PP .RS 5 .nf mhmail -from sender@example.com \\ -headerfield 'MIME-Version:1.0' \\ -headerfield 'Content-Type:text/plain; charset=utf-8' \\ -headerfield 'Content-Transfer-Encoding:8bit' \\ recipient@example.com .fi .RE .PP Note about this example: the .B \-attach switch causes .I MIME-Version and .I Content-Type headers to be added to the message. .PP The .B \-profile switch instructs .B mhmail to use .B send instead of .B post to send the message. This allows use of the user's context and aliases. .PP The .B \-attach .I file switch attaches the specified file to the message. Use of .B \-attach enables .B \-profile because .B mhmail uses .B send to handle the attachment. It is usually best to enclose the argument in quotes to protect it from the shell. The .B \-attach switch may be given multiple times to add multiple attachments. .PP The .B \-nosend option shows the draft file that would be posted/sent on the command's standard output but does not post or send it. .B \-send provides the default behavior of posting or sending the message. It can be used to disable .BR \-nosend , for example, when using a shell alias. .PP All other switches are passed to .B post if .B \-profile is not used, or .B send if .B \-profile is used. .SH FILES .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^%bindir%/inc~^Program to incorporate mail drop into folder ^%nmhlibexecdir%/post~^Program to deliver a message ^/tmp/mhmail*~^Temporary copy of message .fi .SH "SEE ALSO" .IR dist (1), .IR send (1), .IR mh-format (5), .IR send (1), .IR post (8) .SH DEFAULTS .nf .RB ` "\-from localmbox" ' .RB ` \-profile "' is enabled by default only with " \-attach .RB ` \-send ' .fi .SH CONTEXT If .B inc is invoked, then .BR inc 's context changes occur. With the .B \-profile switch, the context of .B send is used. .B mhmail does not read the context file itself, so an entry for it will be ignored. nmh-1.7.1-RC3/man/mhn.man000644 007761 000024 00000002025 13205305704 015012 0ustar00kenhstaff000000 000000 .TH MHN %manext1% 2013-01-04 "%nmhversion%" . .\" %nmhwarning% . .SH NAME mhn \- display/list/store/cache nmh MIME messages .SH SYNOPSIS .HP 5 .na .B mhn .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RI [ msgs ] .RB [ \-file .IR file ] .RB [ \-part .IR number ] \&... .RB [ \-type .IR content ] \&... .RB [ \-show " | " \-noshow ] .RB [ \-list " | " \-nolist ] .RB [ \-store " | " \-nostore ] .RB [ \-cache " | " \-nocache ] .RB [ \-headers " | " \-noheaders ] .RB [ \-realsize " | " \-norealsize ] .RB [ \-serialonly " | " \-noserialonly ] .RB [ \-form .IR formfile ] .RB [ \-pause " | " \-nopause ] .RB [ \-auto " | " \-noauto ] .RB [ \-rcache .IR policy ] .RB [ \-wcache .IR policy ] .RB [ \-check " | " \-nocheck ] .PP .HP 5 .B mhn .B \-build .I file .RB [ \-rfc934mode " | " \-norfc934mode ] .ad .SH DESCRIPTION .B mhn is deprecated. It is retained only for backwards compatibility. .PP You should migrate to using the commands .BR mhlist , .BR mhshow , and .BR mhstore . .SH "SEE ALSO" .IR mhlist (1), .IR mhshow (1), .IR mhstore (1) nmh-1.7.1-RC3/man/mhparam.man000644 007761 000024 00000007060 13243042053 015656 0ustar00kenhstaff000000 000000 .TH MHPARAM %manext1% 2017-02-18 "%nmhversion%" . .\" %nmhwarning% . .SH NAME mhparam \- print nmh profile and context components .SH SYNOPSIS .HP 5 .na .B mhparam .RB [ \-help ] .RB [ \-version ] .RI [ components ] .RB [ \-all ] .RB [ \-component " | " \-nocomponent ] .RB [ \-debug ] .ad .SH DESCRIPTION .B mhparam writes the value of the specified profile component to the standard output, separated by newlines. Component name matching is case-insensitive. If the profile component is not present, the default value (or nothing, if there is no default) is printed. .PP If the switch .B \-component is given, then the component name is displayed along with the profile components value. This can be disabled with the switch .BR \-nocomponent . .PP If more than one component is specified in the .I components list, then the switch .B \-component is on by default. If only one component is specified, then the switch .B \-nocomponent is on by default. .PP If .B \-all is specified, then all components in the nmh profile are displayed and other arguments are ignored. .PP .B mhparam can provide other information, such as the .B nmh version identifier, the locations of the nmh .IR bindir , .IR libexecdir , .IR etcdir , and .I docdir install directories, all .I proc settings, and the .I datalocking method described in the .IR mh\-profile (5) man page. Information about the configuration of the .B nmh installation is also available, including the default mail spool locking method. To test whether the configuration includes support for SASL, TLS, .IR iconv (3), and oauth, the following commands, respectively, will output a non-null string to indicate support: .PP .RS 5 .nf mhparam\0sasl mhparam\0tls mhparam\0iconv mhparam\0oauth .fi .RE .PP Conversely, no output means that the specified support is not included. The .B \-debug switch displays all such other information available from .BR mhparam . .PP Note that the internal .B libdir component has been replaced by .BR libexecdir . The old form is deprecated and will be removed in a future release. .PP Examples: .PP .RS 5 .nf .ta \w'AliasFile:'u+2n % mhparam path Mail % mhparam mhlproc %nmhlibexecdir%/mhl % mhparam \-component Path Path: Mail % mhparam AliasFile rmmproc AliasFile: aliases rmmproc: rmmproc % mhparam \-nocomponent AliasFile rmmproc aliases rmmproc % mhparam path nonexistent context Path: Mail context: context % mhparam version %nmhversion% % mhparam etcdir %nmhetcdir% % mhparam libexecdir %nmhlibexecdir% % mhparam spoollocking %default_locking% % mhparam datalocking fcntl % mhparam sasl cyrus_sasl % mhparam tls tls % mhparam iconv iconv % mhparam oauth oauth .fi .RE .PP .B mhparam is also useful in backquoted operations: .PP .RS 5 .nf % fgrep cornell.edu `mhpath +`/`mhparam aliasfile` .fi .SH "EXIT STATUS" .B mhparam returns the number of components that were not found, but limits the return value to 120 to avoid ambiguity, e.g.\& 127 is used by shells to indicate `command not found', and 256 would wrap to 0, falsely indicating success. . .SH FILES .fc ^ ~ .nf .ta \w'ExtraBigProfileName 'u ^$HOME/.mh_profile~^The user profile ^or $MH~^Rather than the standard profile ^/context~^The user context ^or $MHCONTEXT~^Rather than the standard context .fi .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u ^context:~^To determine the context file .fi .SH "SEE ALSO" .IR mh-profile (5) .SH DEFAULTS .nf .RB ` \-nocomponent "' if only one component is specified" .RB ` \-component "' if more than one component is specified" .RB ` components "' defaults to none" .fi .SH CONTEXT None nmh-1.7.1-RC3/man/mhpath.man000644 007761 000024 00000006774 13243042053 015525 0ustar00kenhstaff000000 000000 .TH MHPATH %manext1% 2012-02-18 "%nmhversion%" . .\" %nmhwarning% . .SH NAME mhpath \- print full pathnames of nmh messages and folders .SH SYNOPSIS .HP 5 .na .B mhpath .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RI [ msgs ] .ad .SH DESCRIPTION .B mhpath expands and sorts the message list `msgs' and writes the full pathnames of the messages to the standard output, separated by newlines. If no `msgs' are specified, .B mhpath outputs the current mail folder's pathname instead. If the only argument is `+', your .B nmh \*(lqPath\*(rq is output; this can be useful in shell scripts. .PP In contrast with other .B nmh commands, a message argument to .B mhpath may often be intended for writing. Because of this: .IP 1) 4 the name \*(lqnew\*(rq has been added to .BR mhpath 's list of reserved message names (the others are \*(lqfirst\*(rq, \*(lqlast\*(rq, \*(lqprev\*(rq, \*(lqnext\*(rq, \*(lqcur\*(rq, and \*(lqall\*(rq). The new message is equivalent to the message after the last message in a folder (and equivalent to 1 in a folder without messages). The \*(lqnew\*(rq message may not be used as part of a message range. .IP 2) 4 Within a message list, the following designations may refer to messages that do not exist: a single numeric message name, the single message name \*(lqcur\*(rq, and (obviously) the single message name \*(lqnew\*(rq. All other message designations must refer to at least one existing message, if the folder contains messages. .IP 3) 4 An empty folder is not, in itself, an error. .PP A message number less than that of the smallest existing message in a folder is treated as if the message already exists. A message number greater than that of the highest existing message in a folder causes an \*(lqout of range\*(rq error message to be displayed. .PP As part of a range designation that contains messages that do exist, message numbers less than the smallest, or greater than the highest, existing message in a folder are ignored. .PP Examples: The current folder foo contains messages 3 5 6. Cur is 4. .PP .RS 5 .nf % mhpath /r/phyl/Mail/foo % mhpath all /r/phyl/Mail/foo/3 /r/phyl/Mail/foo/5 /r/phyl/Mail/foo/6 % mhpath 2001 mhpath: message 2001 out of range 1-6 % mhpath 1\-2001 /r/phyl/Mail/foo/3 /r/phyl/Mail/foo/5 /r/phyl/Mail/foo/6 % mhpath new /r/phyl/Mail/foo/7 % mhpath last new /r/phyl/Mail/foo/6 /r/phyl/Mail/foo/7 % mhpath last\-new mhpath: bad message list last\-new % mhpath cur /r/phyl/Mail/foo/4 % mhpath 1\-2 mhpath: no messages in range 1\-2 % mhpath first:2 /r/phyl/Mail/foo/3 /r/phyl/Mail/foo/5 % mhpath 1 2 /r/phyl/Mail/foo/1 /r/phyl/Mail/foo/2 .fi .RE .PP .B mhpath is also useful in backquoted operations: .PP .RS 5 .nf % cd `mhpath +inbox` % echo `mhpath +` /r/phyl/Mail .fi .RE .PP Because .B mhpath expands and sorts .RI [ msgs ]. the command .PP .RS 5 .nf mv `mhpath 501 500` .fi .RE .PP to will not move 501 to 500; quite the reverse. But .PP .RS 5 .nf mv `mhpath 501` `mhpath 500` .fi .RE .PP will do the trick. .PP Out-of-range message 0 produces a different error message than large out-of-range message numbers. But both cause .B mhpath to exit with non-zero status. .SH FILES .fc ^ ~ .nf .ta \w'ExtraBigProfileName 'u ^$HOME/.mh_profile~^The user profile .fi .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u ^Path:~^To determine the user's nmh directory ^Current\-Folder:~^To find the default current folder .fi .SH "SEE ALSO" .IR folder (1) .SH DEFAULTS .nf .RB ` +folder "' defaults to the current folder" .RB ` msgs "' defaults to none" .fi .SH CONTEXT None nmh-1.7.1-RC3/man/mhshow.man000644 007761 000024 00000053576 13243042053 015553 0ustar00kenhstaff000000 000000 .TH MHSHOW %manext1% 2015-02-08 "%nmhversion%" . .\" %nmhwarning% . .SH NAME mhshow \- display nmh MIME messages .SH SYNOPSIS .HP 5 .na .B mhshow .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RI [ msgs ] .RB [ \-file .IR file ] .RB [ \-part .IR number ] \&... .RB [ \-type .IR content ] \&... .RB [ \-prefer .IR content ] \&... .RB [ \-noprefer ] .RB [ \-concat " | " \-noconcat ] .RB [ \-textonly " | " \-notextonly ] .RB [ \-inlineonly " | " \-noinlineonly ] .RB [ \-header " | " \-noheader ] .RB [ \-form .IR formfile ] .RB [ \-markform .IR formfile ] .RB [ \-rcache .IR policy ] .RB [ \-wcache .IR policy ] .RB [ \-check " | " \-nocheck ] .ad .SH DESCRIPTION The .B mhshow command displays contents of a MIME (multi-media) message, or collection of messages. .PP .B mhshow manipulates multi-media messages as specified in RFC 2045 to RFC 2049. Currently .B mhshow only supports encodings in message bodies, and does not support the encoding of message headers as specified in RFC 2047. .PP By default, .B mhshow will display only the text parts of a message that are not marked as attachments. This behavior can be changed by the .B \-notextonly and .B \-noinlineonly switches. In addition, by using the .BR \-part , .BR \-type , and .B \-prefer switches, you may limit and reorder the set of parts to be displayed, based on part number and/or content type. The inclusion of any .B \-part or .B \-type switches will override the default settings of .B \-textonly and .BR \-inlineonly. .PP The .B \-header switch controls whether .B mhshow will print a message separator header before each message that it displays. The header format can be controlled using .BR \-headerform , to specify a file containing .IR mh\-format (5) instructions. A copy of the built-in default headerform can be found in %nmhetcdir%/mhshow.header, for reference. In addition to the normal set of .IR mh\-format (5) instructions, a "%{folder}" escape provides a string representing the current folder. .PP By default, .B mhshow will concatenate all content under one pager. If you want each part to be displayed separately, you can override the default behavior with .B \-noconcat. .PP The .B \-file .I file switch directs .B mhshow to use the specified file as the source message, rather than a message from a folder. If you specify this file as \*(lq-\*(rq, then .B mhshow will accept the source message on the standard input. Note that the file, or input from standard input, should be a validly formatted message, just like any other .B nmh message. It should .I not be in mail drop format (to convert a file in mail drop format to a folder of .B nmh messages, see .IR inc (1)). .PP The .B \-part switch can be given (one or more times) to restrict the set of subparts that will be displayed. (Obviously with no .B \-part switches, all parts will be considered.) If a .B \-part switch specifies a specific subpart (i.e., a "leaf" in the tree of MIME parts), then that part will always be displayed. If a .B \-part switch references a multipart/alternative part, then (in the absence of a .B \-type switch) only the default subpart of that multipart will be displayed. .PP A part specification consists of a series of numbers separated by dots. For example, in a multipart content containing three parts, these would be named as 1, 2, and 3, respectively. If part 2 was also a multipart content containing two parts, these would be named as 2.1 and 2.2, respectively. Note that the .B \-part switch is effective only for messages containing a multipart content. If a message has some other kind of content, or if the part is itself another multipart content, the .B \-part switch will not prevent the content from being acted upon. .PP The .B \-type switch can also be used to restrict (or, when used in conjunction with .BR \-part , to further restrict) the display of parts according to content type. One or more .B \-type switches part will only select the first match from a multipart/alternative, even if there is more than one subpart that matches (one of) the given content type(s). .PP Using either .B \-part or .B -type switches alone will cause either switch to select the part(s) they match. Using them together will select only the part(s) matched by both (sets of) switches. In other words, the result is the intersection, and not the union, of their separate match results. .PP A content specification consists of a content type and a subtype. The initial list of \*(lqstandard\*(rq content types and subtypes can be found in RFC 2046. .PP A list of commonly used contents is briefly reproduced here: .PP .RS 5 .nf .ta \w'application 'u Type Subtypes ---- -------- text plain, enriched multipart mixed, alternative, digest, parallel message rfc822, partial, external-body application octet-stream, postscript image jpeg, gif, png audio basic video mpeg .fi .RE .PP A legal MIME message must contain a subtype specification. .PP To specify a content, regardless of its subtype, just use the name of the content, e.g., \*(lqaudio\*(rq. To specify a specific subtype, separate the two with a slash, e.g., \*(lqaudio/basic\*(rq. Note that regardless of the values given to the .B \-type switch, a multipart content (of any subtype listed above) is always acted upon. Further note that if the .B \-type switch is used, and it is desirable to act on a message/external-body content, then the .B \-type switch must be used twice: once for message/external-body and once for the content externally referenced. .PP In the absence of .BR \-prefer , .B mhshow will select the "best" displayable subpart from multipart/alternative content. The .B \-prefer switch can be used (one or more times, in order of ascending preference) to let MH know which content types from a multipart/alternative MIME part are preferred by the user, in order to override the default selection for display. For example, mail is often sent containing both plaintext and HTML-formatted versions of the same content, and the HTML version is usually indicated to be the "best" format for viewing. Using \*(lq-prefer text/plain\*(rq will cause the plaintext version to be displayed if possible, but still allow display of the HTML part if there is no plaintext subpart available. Using \*(lq-prefer text/plain -prefer image/png\*(rq would add a preference for PNG images, which might or might not ever appear in the same multipart/alternative section with text/plain. Implementation note: RFC 2046 requires that the subparts of a multipart/alternative be ordered according to "faithfulness to the original content", and MH by default selects the subpart ranked most "faithful" by that ordering. The .B \-prefer switch reorders the alternative parts (only internally, never changing the message file) to move the user's preferred part(s) to the "most faithful" position. Thus, when viewed by .BR mhlist , the ordering of multipart/alternative parts will appear to change when invoked with or without various .B \-prefer switches. Since the last of multiple .B \-prefer options "wins", a .B \-prefer on the command line will override any in a profile entry. .PP The .B \-noprefer switch will cancel any previous .B \-prefer switches. .SS "Unseen Sequence" If the profile entry \*(lqUnseen\-Sequence\*(rq is present and non-empty, then .B mhshow will remove each of the messages shown from each sequence named by the profile entry. .SS "Checking the Contents" The .B \-check switch tells .B mhshow to check each content for an integrity checksum. If a content has such a checksum (specified as a Content-MD5 header field), then .B mhshow will attempt to verify the integrity of the content. .SS "Showing the Contents" The headers of each message are displayed with the .I mhlproc (usually .BR mhl ), using the standard format file, .IR mhl.headers . You may specify an alternative format file with the .B \-form .I formfile switch. If the format file .I mhl.null is specified, then the display of the message headers is suppressed. .PP Next, the contents are extracted from the message and are stored in a temporary file. Usually, the name of the temporary file is the word \*(lqmhshow\*(rq followed by a string of characters. Occasionally, the method used to display a content (described next), requires that the file end in a specific suffix. For example, the .B soffice command (part of the StarOffice package) can be used to display Microsoft Word content, but it uses the suffix to determine how to display the file. If no suffix is present, the file is not correctly loaded. Similarly, older versions of the .B gs command append a \*(lq.ps\*(rq suffix to the filename if one was missing. As a result, these cannot be used to read the default temporary file. .PP To get around this, your profile can contain lines of the form: .PP .RS 5 mhshow-suffix-/: .RE .PP or .PP .RS 5 mhshow-suffix-: .RE .PP to specify a suffix which can be automatically added to the temporary file created for a specific content type. For example, the following lines might appear in your profile: .PP .RS 5 .nf mhshow-suffix-text: .txt mhshow-suffix-application/msword: .doc mhshow-suffix-application/PostScript: .ps .fi .RE .PP to automatically append a suffix to the temporary files. .PP The method used to display the different contents in the messages bodies will be determined by a \*(lqdisplay string\*(rq. To find the display string, .B mhshow will first search your profile for an entry of the form: .PP .RS 5 mhshow-show-/ .RE .PP If this isn't found, .B mhshow will search for an entry of the form: .PP .RS 5 mhshow-show- .RE .PP to determine the display string. .PP If a display string is found, any escapes (given below) will be expanded. The result will be executed under \*(lq/bin/sh\*(rq, with the standard input set to the content. .PP The display string may contain the following escapes: .PP .RS 5 .nf .ta \w'%F 'u %a Insert parameters from Content-Type field %{parameter} Insert the parameter value from the Content-Type field %f Insert filename containing content %F %f, and stdin is terminal not content %l display listing prior to displaying content %s Insert content subtype %d Insert content description %% Insert the character % .fi .RE .PP .B mhshow will execute at most one display string at any given time, and wait for the current display string to finish execution before executing the next display string. .PP The {parameter} escape is typically used in a command line argument that should only be present if it has a non-null value. It is highly recommended that the entire escape be wrapped in double quotes. Shell parameter expansion can construct the argument only when it is non-null, e.g., .PP .RS 5 .nf mhshow-show-text/html: charset="%{charset}"; w3m ${charset:+-I $charset} -T text/html %F .fi .RE .PP That example also shows the use of indentation to signify continuation: the two text lines combine to form a single entry. Note that when dealing with text that has been converted internally by .IR iconv (3), the \*(lqcharset\*(rq parameter will reflect the target character set of the text, rather than the original character set in the message. .PP Note that if the content being displayed is multipart, but not one of the subtypes listed above, then the f- and F-escapes expand to multiple filenames, one for each subordinate content. Furthermore, stdin is not redirected from the terminal to the content. .PP If a display string is not found, .B mhshow behaves as if these profile entries were supplied and supported: .PP .RS 5 .nf mhshow-show-text/plain: %lmoreproc %F mhshow-show-message/rfc822: %lshow -file %F .fi .RE .PP Note that \*(lqmoreproc\*(rq is not supported in user profile display strings. .PP If a subtype of type text doesn't have a profile entry, it will be treated as text/plain. .PP .B mhshow has default methods for handling multipart messages of subtype mixed, alternative, parallel, and digest. Any unknown subtype of type multipart (without a profile entry), will be treated as multipart/mixed. .PP If none of these apply, then .B mhshow will check to see if the message has an application/octet-stream content with parameter \*(lqtype=tar\*(rq. If so, .B mhshow will use an appropriate command. If not, .B mhshow will complain. .PP Example entries might be: .PP .RS 5 .nf mhshow-show-audio/basic: raw2audio 2>/dev/null | play mhshow-show-image: xv %f mhshow-show-application/PostScript: lpr -Pps .fi .RE .PP If an f- or F-escape is not quoted with single quotes, its expansion will be wrapped with single quotes. .PP Finally, .B mhshow will process each message serially\0--\0it won't start showing the next message until all the commands executed to display the current message have terminated. .SS "Showing Alternate Character Sets" If .B mhshow was built with .IR iconv (3), then all text/plain parts of the message(s) will be displayed using the character set of the current locale. See the .IR mhparam (1) man page for how to determine whether your .B nmh installation includes .IR iconv (3) support. To convert text parts other than text/plain, or if .B mhshow was not built with .IR iconv , an external program can be used, as described next. .PP Because a content of type text might be in a non-ASCII character set, when .B mhshow encounters a \*(lqcharset\*(rq parameter for this content, it checks if your terminal can display this character set natively. .B mhshow checks this by examining the current character set defined by the .IR locale (1) environment variables. If the value of the locale character set is equal to the value of the charset parameter, then .B mhshow assumes it can display this content without any additional setup. If the locale is not set properly, .B mhshow will assume a value of \*(lqUS-ASCII\*(rq. If the character set cannot be displayed natively, then .B mhshow will look for an entry of the form: .PP .RS 5 mhshow-charset- .RE .PP which should contain a command creating an environment to render the character set. This command string should containing a single \*(lq%s\*(rq, which will be filled-in with the command to display the content. .PP Example entries might be: .PP .RS 5 mhshow-charset-iso-8859-1: xterm -fn '-*-*-medium-r-normal-*-*-120-*-*-c-*-iso8859-*' -e %s .RE .PP or .PP .RS 5 mhshow-charset-iso-8859-1: '%s' .RE .PP The first example tells .B mhshow to start .B xterm and load the appropriate character set for that message content. The second example tells .B mhshow that your pager (or other program handling that content type) can handle that character set, and that no special processing is needed beforehand. .PP Note that many pagers strip off the high-order bit, or have problems displaying text with the high-order bit set. However, the pager .B less has support for single-octet character sets. For example, messages encoded in the ISO-8859-1 character set can be viewed using .BR less , with these environment variable settings: .PP .RS 5 .nf .ta \w'%F 'u LESSCHARSET latin1 LESS -f .fi .RE .PP The first setting tells .B less to use the ISO-8859-1 definition to determine whether a character is \*(lqnormal\*(rq, \*(lqcontrol\*(lq, or \*(lqbinary\*(rq. The second setting tells .B less not to warn you if it encounters a file that has non-ASCII characters. Then, simply set the .I moreproc profile entry to .BR less , and it will get called automatically. (To handle other single-octet character sets, look at the .IR less (1) manual entry for information about the LESSCHARDEF environment variable.) .SS "Messages of Type message/partial" .B mhshow cannot directly display messages of type partial. You must first reassemble them into a normal message using .BR mhstore . Check .IR mhstore (1) for details. .SS "External Access" For contents of type message/external-body, .B mhshow supports these access-types: .IP \(bu 4 afs .IP \(bu 4 anon-ftp .IP \(bu 4 ftp .IP \(bu 4 local-file .IP \(bu 4 mail-server .IP \(bu 4 url .PP For the \*(lqanon-ftp\*(rq and \*(lqftp\*(rq access types, .B mhshow will look for the \*(lqnmh-access-ftp\*(rq profile entry, e.g., .PP .RS 5 nmh-access-ftp: myftp.sh .RE .PP to determine the pathname of a program to perform the FTP retrieval. .PP This program is invoked with these arguments: .PP .RS 5 .nf domain name of FTP-site username password remote directory remote filename local filename \*(lqascii\*(rq or \*(lqbinary\*(rq .fi .RE .PP The program should terminate with an exit status of zero if the retrieval is successful, and a non-zero exit status otherwise. .PP For the \*(lqurl\*(rq access-type, .B mhshow will look for the \*(lqnmh-access-url\*(rq profile entry. See .IR mhstore (1) for more details. .SS "The Content Cache" When .B mhshow encounters an external content containing a \*(lqContent-ID:\*(rq field, and if the content allows caching, then depending on the caching behavior of .BR mhshow , the content might be read from or written to a cache. .PP The caching behavior of .B mhshow is controlled with the .B \-rcache and .B \-wcache switches, which define the policy for reading from, and writing to, the cache, respectively. One of four policies may be specified: \*(lqpublic\*(rq, indicating that .B mhshow should make use of a publicly-accessible content cache; \*(lqprivate\*(rq, indicating that .B mhshow should make use of the user's private content cache; \*(lqnever\*(rq, indicating that .B mhshow should never make use of caching; and, \*(lqask\*(rq, indicating that .B mhshow should ask the user. .PP There are two directories where contents may be cached: the profile entry \*(lqnmh-cache\*(rq names a directory containing world-readable contents, and, the profile entry \*(lqnmh-private-cache\*(rq names a directory containing private contents. The former should be an absolute (rooted) directory name. .PP For example, .PP .RS 5 nmh-cache: /tmp .RE .PP might be used if you didn't care that the cache got wiped after each reboot of the system. The latter is interpreted relative to the user's nmh directory, if not rooted, e.g., .PP .RS 5 nmh-private-cache: .cache .RE .PP (which is the default value). .SS "User Environment" Because the display environment in which .B mhshow operates may vary for different machines, .B mhshow will look for the environment variable MHSHOW. If present, this specifies the name of an additional user profile which should be read. Hence, when a user logs in on a particular display device, this environment variable should be set to refer to a file containing definitions useful for the given display device. Normally, only entries that deal with the methods to display different content type and subtypes .PP .RS 5 .nf mhshow-show-/ mhshow-show- .fi .RE .PP need be present in this additional profile. Finally, .B mhshow will attempt to consult .PP .RS 5 %nmhetcdir%/mhn.defaults .RE .PP which is created automatically during .B nmh installation. .PP See "Profile Lookup" in .IR mh-profile (5) for the profile search order, and for how duplicate entries are treated. .SS Content-Type Marker .B mhshow will display a marker containing information about the part being displayed next. The default marker can be changed using the .B \-markform switch to specify a file containing .IR mh\-format (5) instructions to use when displaying the content marker. A copy of the default markform can be found in %nmhetcdir%/mhshow.marker, for reference. In addition to the normal set of .IR mh\-format (5) instructions, the following .I component escapes are supported: .PP .RS 5 .nf .ta \w'cdispo- 'u +\w'Returns 'u .I "Escape Returns Description" part string MIME part number content\-type string MIME Content\-Type of part description string Content\-Description header disposition string Content disposition (attachment or inline) ctype- string Value of from Content\-Type header cdispo- string Value of from Content\-Disposition header %(size) integer The size of the decoded part, in bytes %(unseen) boolean Returns true for suppressed parts .fi In this context, the %(unseen) function indicates whether .B mhshow has decided to not display a particular part due to the .B \-textonly or .B \-inlineonly switches. .RE All MIME parameters and the \*(lqContent-Description\*(rq header will have RFC 2231 decoding applied and be converted to the local character set. .SH FILES .B mhshow looks for all format files and mhn.defaults in multiple locations: absolute pathnames are accessed directly, tilde expansion is done on usernames, and files are searched for in the user's .I Mail directory, as specified in their profile. If not found there, the directory .RI \*(lq %nmhetcdir% \*(rq is checked. .PP .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^$HOME/.mh_profile~^The user profile ^$MHSHOW~^Additional profile entries ^%nmhetcdir%/mhn.defaults~^System default MIME profile entries ^%nmhetcdir%/mhl.headers~^The headers template ^%nmhetcdir%/mhshow.marker~^Example content marker ^%nmhetcdir%/mhshow.header~^Example message separator header .fi .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u ^Path:~^To determine the user's nmh directory ^Current\-Folder:~^To find the default current folder ^Unseen\-Sequence:~^To name sequences denoting unseen messages ^mhlproc:~^Default program to display message headers ^nmh-access-ftp:~^Program to retrieve contents via FTP ^nmh-access-url:~^Program to retrieve contents via HTTP ^nmh-cache~^Public directory to store cached external contents ^nmh-private-cache~^Personal directory to store cached external contents ^mhshow-charset-~^Template for environment to render character sets ^mhshow-show-*~^Template for displaying contents ^moreproc:~^Default program to display text/plain content .fi .SH "SEE ALSO" .IR iconv (3), .IR mhbuild (1), .IR mhl (1), .IR mhlist (1), .IR mhparam (1), .IR mhstore (1), .IR sendfiles (1) .SH DEFAULTS .nf .RB ` +folder "' defaults to the current folder" .RB ` msgs "' defaults to cur" .RB ` \-nocheck ' .RB ` \-concat ' .RB ` \-textonly ' .RB ` \-inlineonly ' .RB ` \-form\ mhl.headers ' .RB ` \-rcache\ ask ' .RB ` \-wcache\ ask ' .fi .SH CONTEXT If a folder is given, it will become the current folder. The last message selected will become the current message. nmh-1.7.1-RC3/man/mhstore.man000644 007761 000024 00000043133 13243042053 015713 0ustar00kenhstaff000000 000000 .TH MHSTORE %manext1% 2015-02-06 "%nmhversion%" . .\" %nmhwarning% . .SH NAME mhstore \- store contents of nmh MIME messages into files .SH SYNOPSIS .HP 5 .na .B mhstore .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RI [ msgs ] .RB [ \-file .IR file ] .RB [ \-outfile .IR outfile ] .RB [ \-part .IR number ] \&... .RB [ \-type .IR content ] \&... .RB [ \-prefer .IR content ] \&... .RB [ \-noprefer ] .RB [ \-auto " | " \-noauto ] .RB [ \-clobber .IR always " | " auto " | " suffix " | " ask " | " never ] .RB [ \-rcache .IR policy ] .RB [ \-wcache .IR policy ] .RB [ \-check " | " \-nocheck ] .RB [ \-verbose " | " \-noverbose ] .ad .SH DESCRIPTION The .B mhstore command allows you to store the contents of a collection of MIME (multi-media) messages into files or other messages. .PP .B mhstore manipulates multi-media messages as specified in RFC 2045 to RFC 2049. .PP By default, .B mhstore will store all the parts of each message. Each part will be stored in a separate file. The header fields of the message are not stored. By using the .BR \-part , .BR \-type , and .B \-prefer switches, you may limit and reorder the set of parts to be stored, based on part number and/or content type. .PP The .B \-file .I file switch directs .B mhstore to use the specified file as the source message, rather than a message from a folder. If you specify this file as \*(lq-\*(rq, then .B mhstore will accept the source message on the standard input. Note that the file, or input from standard input, should be a validly formatted message, just like any other .B nmh message. It should .I not be in mail drop format (to convert a file in mail drop format to a folder of .B nmh messages, see .IR inc (1)). .PP A part specification consists of a series of numbers separated by dots. For example, in a multipart content containing three parts, these would be named as 1, 2, and 3, respectively. If part 2 was also a multipart content containing two parts, these would be named as 2.1 and 2.2, respectively. Note that the .B \-part switch is effective only for messages containing a multipart content. If a message has some other kind of content, or if the part is itself another multipart content, the .B \-part switch will not prevent the content from being acted upon. .PP The .B \-type switch can also be used to restrict (or, when used in conjunction with .BR \-part , to further restrict) the selection of parts according to content type. One or more .B \-type switches part will only select the first match from a multipart/alternative, even if there is more than one subpart that matches (one of) the given content type(s). .PP Using either .B \-part or .B -type switches alone will cause either to select the part(s) they match. Using them together will select only the part(s) matched by both (sets of) switches. In other words, the result is the intersection, and not the union, of their separate match results. .PP A content specification consists of a content type and a subtype. The initial list of \*(lqstandard\*(rq content types and subtypes can be found in RFC 2046. .PP A list of commonly used contents is briefly reproduced here: .PP .RS 5 .nf .ta \w'application 'u Type Subtypes ---- -------- text plain, enriched multipart mixed, alternative, digest, parallel message rfc822, partial, external-body application octet-stream, postscript image jpeg, gif, png audio basic video mpeg .fi .RE .PP A legal MIME message must contain a subtype specification. .PP To specify a content, regardless of its subtype, just use the name of the content, e.g., \*(lqaudio\*(rq. To specify a specific subtype, separate the two with a slash, e.g., \*(lqaudio/basic\*(rq. Note that regardless of the values given to the .B \-type switch, a multipart content (of any subtype listed above) is always acted upon. Further note that if the .B \-type switch is used, and it is desirable to act on a message/external-body content, then the .B \-type switch must be used twice: once for message/external-body and once for the content externally referenced. .PP The .B \-prefer switch will alter the part-ordering of multipart/alternative MIME sections in order to override the sender-imposed default ordering. The .B \-prefer switch is functionally most important for .BR mhshow , but is also implemented in .B mhlist and .B mhstore to make common part-numbering possible across all three programs. The last of multiple .B \-prefer switches will have the highest priority. This allows the command line switches to override profile entries. See .IR mhlist (1) and .IR mhshow (1) for more information on .BR \-prefer. .PP The .B \-noprefer switch will cancel any previous .B \-prefer switches. .SS "Checking the Contents" The .B \-check switch tells .B mhstore to check each content for an integrity checksum. If a content has such a checksum (specified as a Content-MD5 header field), then .B mhstore will attempt to verify the integrity of the content. .SS "Storing the Contents" .B mhstore will store the contents of the named messages in \*(lqnative\*(rq (decoded) format. Two things must be determined: the directory in which to store the content, and the filenames. Files are written in the directory given by the \*(lqnmh-storage\*(rq profile entry, e.g., .PP .RS 5 nmh-storage: /tmp .RE .PP If this entry isn't present, the current working directory is used. .PP If the .B \-outfile switch is given, its argument is used for the filename to store all of the content, with \*(lq-\*(rq indicating standard output. If the .B \-auto switch is given, then .B mhstore will check if the message contains information indicating the filename that should be used to store the content. This information should be specified as the \*(lqfilename\*(rq attribute in the \*(lqContent-Disposition\*(rq header or as the \*(lqname\*(rq attribute in the \*(lqContent-Type\*(rq header for the content you are storing. For security reasons, this filename will be ignored if it begins with the character '/', '.', '|', or '!', or if it contains the character '%'. We also recommend using a \*(lqnmh-storage\*(rq profile entry or a .B \-clobber switch setting other than the default of \*(lqalways\*(rq to avoid overwriting existing files. .PP If the .B \-auto switch is not given (or is being ignored for security reasons) then .B mhstore will look in the user's profile for a \*(lqformatting string\*(rq to determine how the different contents should be stored. First, .B mhstore will look for an entry of the form: .PP .RS 5 mhstore-store-/ .RE .PP to determine the formatting string. If this isn't found, .B mhstore will look for an entry of the form: .PP .RS 5 mhstore-store- .RE .PP to determine the formatting string. .PP If the formatting string starts with a \*(lq+\*(rq character, then content is stored in the named folder. A formatting string consisting solely of a \*(lq+\*(rq character is interpreted to be the current folder. .PP If the formatting string consists solely of a \*(lq-\*(rq character, then the content is sent to the standard output. .PP If the formatting string starts with a '|', then it represents a command for .B mhstore to execute which should ultimately store the content. The content will be passed to the standard input of the command. Before the command is executed, .B mhstore will change to the appropriate directory, and any escapes (given below) in the formatting string will be expanded. The use of the \*(lq%a\*(rq sequence is not recommended because the user has no control over the Content-Type parameter data. .PP Otherwise, the formatting string will represent a pathname in which to store the content. If the formatting string starts with a '/', then the content will be stored in the full path given, else the file name will be relative to the value of \*(lqnmh-storage\*(rq or the current working directory. Any escapes (given below) will be expanded, except for the a-escape. Note that if \*(lqnmh-storage\*(rq is not an absolute path, it will be relative to the folder that contains the message(s). .PP A command or pathname formatting string may contain the following escapes. If the content isn't part of a multipart (of any subtype listed above) content, the p-escapes are ignored. .PP .RS 5 .nf .ta \w'%P 'u %a Parameters from Content-Type (only valid with command) %m Insert message number %P Insert part number with leading dot %p Insert part number without leading dot %t Insert content type %s Insert content subtype %% Insert character % .fi .RE .PP If no formatting string is found, .B mhstore will check to see if the content is application/octet-stream with parameter \*(lqtype=tar\*(rq. If so, .B mhstore will choose an appropriate filename. If the content is not application/octet-stream, then .B mhstore will check to see if the content is a message. If so, .B mhstore will use the value \*(lq+\*(rq. As a last resort, .B mhstore will use the value \*(lq%m%P.%s\*(rq. .PP Example profile entries might be: .PP .RS 5 .nf mhstore-store-text: %m%P.txt mhstore-store-text: +inbox mhstore-store-message/partial: + mhstore-store-audio/basic: | raw2audio -e ulaw -s 8000 -c 1 > %m%P.au mhstore-store-image/jpeg: %m%P.jpg mhstore-store-application/PostScript: %m%P.ps .fi .RE .PP The .B \-verbose switch directs .B mhstore to print out the names of files that it stores. For backward compatibility, it is the default. The .B \-noverbose switch suppresses these printouts. .SS "Overwriting Existing Files" The .B \-clobber switch controls whether .B mhstore should overwrite existing files. The allowed values for this switch and corresponding behavior when .B mhstore encounters an existing file are: .PP .RS 5 .nf .ta \w'suffix 'u always Overwrite existing file (default) auto Create new file of form name-n.extension suffix Create new file of form name.extension.n ask Prompt the user to specify whether or not to overwrite the existing file never Do not overwrite existing file .fi .RE .PP With .I auto and .IR suffix , .I n is the lowest unused number, starting from one, in the same form. If a filename does not have an extension (following a '.'), then .I auto and .I suffix create a new file of the form .I name-n and .IR name.n , respectively. With .I never and .IR ask , the exit status of .B mhstore will be the number of files that were requested but not stored. .PP With .IR ask , if standard input is connected to a terminal, the user is prompted to respond .IR yes , .IR no , or .IR rename , to whether the file should be overwritten. The responses can be abbreviated. If the user responds with .IR rename , then .B mhstore prompts the user for the name of the new file to be created. If it is a relative path name (does not begin with '/'), then it is relative to the current directory. If it is an absolute or relative path to a directory that does not exist, the user will be prompted whether to create the directory. If standard input is not connected to a terminal, .I ask behaves the same as .IR always . .SS "Reassembling Messages of Type message/partial" .B mhstore is also able to reassemble messages that have been split into multiple messages of type \*(lqmessage/partial\*(rq. .PP When asked to store a content containing a partial message, .B mhstore will try to locate all of the portions and combine them accordingly. The default is to store the combined parts as a new message in the current folder, although this can be changed using formatting strings as discussed above. Thus, if someone has sent you a message in several parts (such as the output from .BR sendfiles ), you can easily reassemble them into a single message in the following fashion: .PP .RS 5 .nf % mhlist 5-8 msg part type/subtype size description 5 message/partial 47K part 1 of 4 6 message/partial 47K part 2 of 4 7 message/partial 47K part 3 of 4 8 message/partial 18K part 4 of 4 % mhstore 5-8 reassembling partials 5,6,7,8 to folder inbox as message 9 % mhlist -verbose 9 msg part type/subtype size description 9 application/octet-stream 118K (extract with uncompress | tar xvpf -) type=tar conversions=compress .fi .RE .PP This will store exactly one message, containing the sum of the parts. It doesn't matter whether the partials are specified in order, since .B mhstore will sort the partials, so that they are combined in the correct order. But if .B mhstore can not locate every partial necessary to reassemble the message, it will not store anything. .SS "External Access" For contents of type message/external-body, \fImhstore\fR supports these access-types: .IP \(bu 4 afs .IP \(bu 4 anon-ftp .IP \(bu 4 ftp .IP \(bu 4 local-file .IP \(bu 4 mail-server .IP \(bu 4 url .PP For the \*(lqanon-ftp\*(rq and \*(lqftp\*(rq access types, .B mhstore will look for the \*(lqnmh-access-ftp\*(rq profile entry, e.g., .PP .RS 5 nmh-access-ftp: myftp.sh .RE .PP to determine the pathname of a program to perform the FTP retrieval. This program is invoked with these arguments: .PP .RS 5 .nf domain name of FTP-site username password remote directory remote filename local filename \*(lqascii\*(rq or \*(lqbinary\*(rq .fi .RE .PP The program should terminate with an exit status of zero if the retrieval is successful, and a non-zero exit status otherwise. .PP For the \*(lqurl\*(rq access types, .B mhstore will look for the \*(lqnmh-access-url\*(rq profile entry, e.g., .PP .RS 5 nmh-access-url: curl -L .RE .PP to determine the program to use to perform the HTTP retrieval. This program is invoked with one argument: the URL of the content to retrieve. The program should write the content to standard out, and should terminate with a status of zero if the retrieval is successful and a non-zero exit status otherwise. .SS "The Content Cache" When .B mhstore encounters an external content containing a \*(lqContent-ID:\*(rq field, and if the content allows caching, then depending on the caching behavior of .BR mhstore , the content might be read from or written to a cache. .PP The caching behavior of .B mhstore is controlled with the .B \-rcache and .B \-wcache switches, which define the policy for reading from, and writing to, the cache, respectively. One of four policies may be specified: \*(lqpublic\*(rq, indicating that .B mhstore should make use of a publicly-accessible content cache; \*(lqprivate\*(rq, indicating that .B mhstore should make use of the user's private content cache; \*(lqnever\*(rq, indicating that .B mhstore should never make use of caching; and, \*(lqask\*(rq, indicating that .B mhstore should ask the user. .PP There are two directories where contents may be cached: the profile entry \*(lqnmh-cache\*(rq names a directory containing world-readable contents, and, the profile entry \*(lqnmh-private-cache\*(rq names a directory containing private contents. The former should be an absolute (rooted) directory name. .PP For example, .PP .RS 5 nmh-cache: /tmp .RE .PP might be used if you didn't care that the cache got wiped after each reboot of the system. The latter is interpreted relative to the user's nmh directory, if not rooted, e.g., .PP .RS 5 nmh-private-cache: .cache .RE .PP (which is the default value). .SS "User Environment" Because the environment in which .B mhstore operates may vary for different machines, .B mhstore will look for the environment variable MHSTORE . If present, this specifies the name of an additional user profile which should be read. Hence, when a user logs in on a particular machine, this environment variable should be set to refer to a file containing definitions useful for that machine. Finally, .B mhstore will attempt to consult .PP .RS 5 %nmhetcdir%/mhn.defaults .RE .PP which is created automatically during .B nmh installation. .PP See "Profile Lookup" in .IR mh-profile (5) for the profile search order, and for how duplicate entries are treated. .SH EXAMPLES .SS Decoding RFC 2047-encoded file names The improper RFC 2047 encoding of file name parameters can be replaced with correct RFC 2231 encoding using .BR mhfixmsg , either permanently or ephemerally, e.g., .PP .RS .nf mhfixmsg -outfile - | mhstore -auto -clobber ask -file - .fi .RE .PP The .BI \-clobber ask is not necessary, though recommended to avoid silently overwriting an existing file. .SH FILES .B mhstore looks for additional profile files in multiple locations: absolute pathnames are accessed directly, tilde expansion is done on usernames, and files are searched for in the user's .I Mail directory as specified in their profile. If not found there, the directory .RI \*(lq %nmhetcdir% \*(rq is checked. .PP .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^$HOME/.mh_profile~^The user profile ^$MHSTORE~^Additional profile entries ^%nmhetcdir%/mhn.defaults~^System default MIME profile entries .fi .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u ^Path:~^To determine the user's nmh directory ^Current\-Folder:~^To find the default current folder ^nmh-access-ftp:~^Program to retrieve contents via FTP ^nmh-access-url:~^Program to retrieve contents via HTTP ^nmh-cache~^Public directory to store cached external contents ^nmh-private-cache~^Personal directory to store cached external contents ^nmh-storage~^Directory to store contents ^mhstore-store-*~^Template for storing contents .fi .SH "SEE ALSO" .IR mhbuild (1), .IR mhfixmsg (1), .IR mhlist (1), .IR mhshow (1), .IR sendfiles (1) .SH DEFAULTS .nf .RB ` +folder "' defaults to the current folder" .RB ` msgs "' defaults to cur" .RB ` \-noauto ' .RB ` \-clobber\ always ' .RB ` \-nocheck ' .RB ` \-rcache\ ask ' .RB ` \-wcache\ ask ' .RB ` \-verbose ' .SH CONTEXT If a folder is given, it will become the current folder. The last message selected will become the current message. .SH BUGS Partial messages contained within a multipart content are not reassembled. nmh-1.7.1-RC3/man/msgchk.man000644 007761 000024 00000011345 13243042053 015506 0ustar00kenhstaff000000 000000 .TH MSGCHK %manext1% 2016-11-02 "%nmhversion%" . .\" %nmhwarning% . .SH NAME msgchk \- nmh's check for incoming email .SH SYNOPSIS .HP 5 .na .B msgchk .RB [ \-help ] .RB [ \-version ] .RB [ \-date " | " \-nodate ] .RB [ \-notify all/mail/nomail ] .RB [ \-nonotify all/mail/nomail ] .RB [ \-host .IR hostname ] .RB [ \-user .IR username ] .RB [ \-sasl " | " \-nosasl ] .RB [ \-saslmech .IR mechanism ] .RB [ \-initialtls ] .RB [ \-notls ] .RB [ \-certverify " | " \-nocertverify ] .RB [ \-authservice .IR service ] .RB [ \-snoop ] .RI [ users \&... ] .ad .SH DESCRIPTION The .B msgchk program checks all known mail drops for mail waiting for you. For those drops which have mail for you, .B msgchk will indicate if it believes that you have seen the mail in question before. .PP The .B \-notify .I type switch indicates under what circumstances .B msgchk should produce a message. The default is .B \-notify .I all which says that .B msgchk should always report the status of the users mail drop. Other values for `type' include `mail' which says that .B msgchk should report the status of waiting mail; and, `nomail' which says that .B msgchk should report the status of empty mail drops. The .B \-nonotify .I type switch has the inverted sense, so .B \-nonotify .I all directs .B msgchk to never report the status of mail drops. This is useful if the user wishes to check .BR msgchk 's exit status. A non-zero exit status indicates that mail was .I not waiting for at least one of the indicated users. .PP If .B msgchk produces output, then the .B \-date switch directs .B msgchk to print out the last date mail was read, if this can be determined. .SS "Using POP" .B msgchk will normally check all the local mail drops, but if the option \*(lqpophost:\*(rq is set in the mts configuration file \*(lqmts.conf\*(rq, or if the .B \-host .I hostname switch is given, .B msgchk will query this POP service host as to the status of mail waiting. .PP To specify a username for authentication with the POP server, use the .B \-user .I username switch. The credentials profile entry in the mh\-profile(5) man page describes the ways to supply a username and password. .PP For debugging purposes, there is also a switch .BR \-snoop , which will allow you to watch the POP transaction take place between you and the POP server. If .B \-sasl \-saslmech xoauth2 is used, the HTTP transaction is also shown. .PP If .B nmh has been compiled with SASL support, the .B \-sasl switch will enable the use of SASL authentication. Depending on the SASL mechanism used, this may require an additional password prompt from the user (but the .I netrc file can be used to store this password, as described in the mh-profile(5) man page). The .B \-saslmech switch can be used to select a particular SASL mechanism. .PP If SASL authentication is successful, .B msgchk will attempt to negotiate a security layer for session encryption. Encrypted traffic is labelled with `(encrypted)' and `(decrypted)' when viewing the POP transaction with the .B \-snoop switch; see the .B post man page description of .B \-snoop for its other features. .PP If .B nmh has been compiled with OAuth support, the .B \-sasl \-saslmech xoauth2 switch will enable OAuth authentication. The .B \-user switch must be used, and the .I user-name must be an email address the user has for the service, which must be specified with the .B \-authservice .I service switch. Before using this, the user must authorize nmh by running .B mhlogin and grant authorization to that account. See the .B mhlogin man page for more details. .PP If .B nmh has been compiled with TLS support, the .B \-initialtls switch will require the negotiation of TLS when connecting to the remote POP server. The .B \-initialtls switch will negotiate TLS immediately after the connection has taken place, before any POP commands are sent or received. Data encrypted by TLS is labeled `(tls-encrypted)' and `(tls-decrypted)` with viewing the POP transaction with the .B \-snoop switch. The .B \-notls switch will disable all attempts to negotiate TLS. .PP When using TLS the default is to verify the remote certificate and SubjectName against the local trusted certificate store. This can be controlled by the .B \-certverify and .B \-nocertverify switches. See your OpenSSL documentation for more information on certificate verification. .SH FILES .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^$HOME/.mh_profile~^The user profile ^%nmhetcdir%/mts.conf~^nmh mts configuration file ^%mailspool%/$USER~^Location of mail drop .fi .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u None .fi .SH "SEE ALSO" .IR inc (1), .IR mh\-mail (5) .IR post (8) .SH DEFAULTS .nf .RB ` user "' defaults to the current user" .RB ` \-date ' .RB ` "\-notify\ all" ' .fi .SH CONTEXT None nmh-1.7.1-RC3/man/mts.conf.man000644 007761 000024 00000000025 11732520432 015755 0ustar00kenhstaff000000 000000 .so man5/mh-tailor.5 nmh-1.7.1-RC3/man/new.man000644 007761 000024 00000003727 13205305704 015033 0ustar00kenhstaff000000 000000 .TH NEW %manext1% 2009-01-17 "%nmhversion%" . .\" %nmhwarning% . .SH NAME new \- report on nmh folders with new messages .br fnext \- set current nmh folder to next folder with new messages .br fprev \- set current nmh folder to previous folder with new messages .br unseen \- scan any new messages in all nmh folders .SH SYNOPSIS .HP 5 .na .B new .RB [ \-help ] .RB [ \-version ] .RI [ sequences ] .RB [ \-mode .IR mode ] .RB [ \-folders .IR foldersfile ] .HP 5 .B fnext is equivalent to .B new \-mode fnext .HP 5 .B fprev is equivalent to .B new \-mode fprev .HP 5 .B unseen is equivalent to .B new \-mode unseen .ad .SH DESCRIPTION .BR new , in its default mode, produces a one-line-per-folder listing of all folders which contain messages in the specified .IR sequences , or in the sequence(s) listed in the profile entry .RI \*(lq Unseen-Sequence \*(rq. Each line consists of the folder name, the total number of messages in the specified sequences, and a list of messages derived from the \&.mh_sequence file. For example: .PP .RS 5 .nf foo 11.* 40\-50 bar 380. 760\-772 824\-828 total 391. .fi .RE .PP The `*' on foo indicates that it is the current folder. The last line shows the total number of messages in the desired sequences. .PP .B new crawls the folder hierarchy recursively to find all folders, and prints them in lexicographic order. Override this behavior by providing a .I foldersfile containing the pre-sorted list of folders which .B new should check, one per line. .PP In .B fnext and .B fprev modes, .B new changes to the next or previous matching folder, respectively. .PP In .B unseen mode, .B new executes .B scan .I sequences for each matching folder. .SH FILES .TP 20 $HOME/.mh_profile The user profile .SH "PROFILE COMPONENTS" .PD 0 .TP 20 Path: To determine the user's nmh directory. .TP 20 Current\-Folder: To find the default current folder. .TP 20 Unseen-Sequence: The name of the unseen message sequence. .PD .SH "SEE ALSO" .IR scan (1), .IR mh\-format (5) nmh-1.7.1-RC3/man/next.man000644 007761 000024 00000003171 13243042053 015206 0ustar00kenhstaff000000 000000 .TH NEXT %manext1% 1999-04-30 "%nmhversion%" . .\" %nmhwarning% . .SH NAME next \- show the next nmh message .SH SYNOPSIS .HP 5 .na .B next .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RB [\-showproc .IR program ] .RB [ \-showmimeproc .IR program ] .RB [ \-header " | " \-noheader ] .RB [ \-checkmime " | " \-nocheckmime ] [switches\ for .I showproc or .IR showmimeproc ] .ad .SH DESCRIPTION .B next performs a .B show on the next message in the specified (or current) folder. Like .BR show , it passes any switches on to the program .I showproc or .IR showmimeproc , which is called to list the message. This command is almost exactly equivalent to .RB \*(lq show .BR next \*(rq. Consult the manual entry for .IR show (1) for all the details. .SH FILES .TP 20 $HOME/.mh_profile The user profile .SH "PROFILE COMPONENTS" .PD 0 .TP 20 Path: To determine the user's nmh directory .TP 20 Current\-Folder: To find the default current folder .TP 20 showproc: Program to show non-MIME messages .TP 20 showmimeproc: Program to show MIME messages .PD .SH "SEE ALSO" .IR prev (1), .IR show (1) .SH DEFAULTS .PD 0 .TP 20 +folder The current folder. .TP 20 \-checkmime .TP 20 \-header .PD .SH CONTEXT If a folder is specified, it will become the current folder. The message that is shown (i.e., the next message in sequence) will become the current message. .SH BUGS .B next is really a link to the .B show program. As a result, if you make a link to .B next and that link is not called .BR next , your link will act like .B show instead. To circumvent this, add a profile-entry for the link to your .B nmh profile and add the argument .I next to the entry. nmh-1.7.1-RC3/man/nmh.man000644 007761 000024 00000030204 13243042053 015007 0ustar00kenhstaff000000 000000 .TH NMH %manext7% 2016-09-26 "%nmhversion%" . .\" %nmhwarning% . .SH NAME nmh \- new MH message system . .\" Register 'tt' contains the indent for .TP in the COMMANDS section: .nr tt \w'\fImh-sequence\fR(5)\0\0'u . .SH DESCRIPTION .B nmh is the name of a powerful message handling system. Rather than being a single comprehensive program, .B nmh consists of a collection of fairly simple single-purpose programs to send, retrieve, save, and manipulate messages. .PP Unlike most mail clients in Unix, .B nmh is not a closed system which must be explicitly run, then exited when you wish to return to the shell. You may freely intersperse .B nmh commands with other shell commands, allowing you to read and answer your mail while you have (for example) a compilation running, or search for a file or run programs as needed to find the answer to someone's question before answering their mail. .PP The rest of this manual entry is a quick tutorial which will teach you the basics of .BR nmh . You should read the manual entries for the individual programs for complete documentation (see the section on .I COMMANDS below). .PP To get started using .BR nmh , put the directory \*(lq%bindir%\*(rq in your .BR $PATH . Run the .B install-mh command. If you've never used .B nmh before, it will create the necessary default files and directories after asking you if you wish it to do so. .PP .B inc moves mail from your system mail drop into your .B nmh \*(lq+inbox\*(rq folder, breaking it up into separate files and converting it to .B nmh format. It prints one line for each message it processes, containing the from field, the subject field and as much of the first line of the message as will fit. It leaves the first message it processes as your current message. You'll need to run .B inc each time you wish to incorporate new mail into your .B nmh file. .PP .B scan prints a list of the messages in your current folder. .PP The commands .BR show , .BR next , and .B prev are used to read specific messages from the current folder. .B show displays the current message, or a specific message specified by its number which is passed as an argument. .B next and .B prev display, respectively, the message numerically after or before the current message. In all cases, the message displayed becomes the current message. If there is no current message, .B show may be called with an argument, or .B next may be used to advance to the first message. .PP .B rmm (remove message) deletes the current message. It may be called, with message numbers passed as arguments, to delete specific messages. .PP .B repl is used to respond to the current message (by default). It places you in the editor with a prototype response form. While you're in the editor, you may peruse the item you're responding to by reading the file .BR @ . After completing your response, type \*(lql\*(rq to .B list (review) it, or \*(lqs\*(rq to .B send it. .PP .B comp allows you to compose a message by putting you in the editor on a prototype message form, and then lets you send it via the .B whatnow command. .B whatnow also supports easy-to-use management of MIME attachments via its .B attach and related responses, as described in its man page. .PP .B nmh command arguments are usually called .IR switches . Some switches have a corresponding \*(lq\-no\*(rq switch, which negates all previous occurrences of that switch on the command line. This allows a user to conveniently override, on the command line, a switch in their profile. Switches may be abbreviated as long as there is no ambiguity with another switch of the same command. To avoid ambiguity with any switches that may be added in the future, it is recommended that full switch names be used in durable code such as shell scripts, functions, and aliases. .PP Each .B nmh command may be run with the single switch .BR \-help , which causes it to print its available switches, along with any profile components that apply, and then exit. .PP All the .B nmh commands may be run with the single switch .BR \-version , which causes them to print the version number of the .B nmh distribution, and then exit. .PP Commands which take a message number as an argument .RB ( scan , .BR show , .BR repl , \&...) also take one of the words \*(lqfirst\*(rq, \*(lqprev\*(rq, \*(lqcur\*(rq, \*(lqnext\*(rq, or \*(lqlast\*(rq to indicate (respectively) the first, previous, current, next, or last message in the current folder (assuming they are defined). As a shorthand, \*(lq.\*(rq is equivalent to \*(lqcur\*(rq. .PP Commands which take a range of message numbers .RB ( rmm , .BR scan , .BR show , \&...) also take any of the abbreviations: .TP \n(ttu .IR - Indicates all messages in the range to , inclusive. The range must be nonempty. .TP .RI all Indicates all messages, i.e., .IR first - last . .TP .IR :+ N .PD 0 .TP .IR :\-N Up to .IR N , where .I N must be a positive number, messages beginning with (or ending with) message .IR num . .I Num may be any of the pre-defined symbols .BR first , .BR prev , .BR cur , .B next or .BR last . The + can be omitted. .PD .TP .RI first: N .PD 0 .TP .RI prev: N .TP .RI next: N .TP .RI last: N As many of the first, previous, next, or last N messages that exist. As above, N can be preceded with - to end the listing at the specified message, or with an optional +. .PD .PP Commands that take a folder name .RB ( inc , .BR refile , .BR scan, \&...) accept the folder name in two formats: \*(lq+folder\*(rq or \*(lq@folder\*(rq. In both cases, \*(lqfolder\*(rq can be a \*(lq/\*(rq-separated path, e.g.\& \*(lqfoo/bar\*(rq. \*(lq+folder\*(rq specifies a directory path to a folder. If \*(lqfolder\*(rq starts with \*(lq/\*(rq then it's an absolute path from the root directory. If it is \*(lq.\*(rq or \*(lq..\*(rq, or starts with \*(lq./\*(rq or \*(lq../\*(rq, then it's relative to the current working directory. Otherwise it's relative to mh-profile(5)'s .RI \*(lq Path \*(rq, i.e.\& as given by .RB ` "mhpath +" `. \*(lq@folder\*(rq is a shorthand for \*(lq+curfolder/folder\*(rq; it's a relative path from the current folder. \*(lqcurfolder\*(rq is given by .RB ` mhpath `. For example, assuming a .B Path profile component of Mail, .TP \n(ttu .PD 0 .BI "scan " +inbox scans $HOME/Mail/inbox .TP .BI "scan " +work/todo scans $HOME/Mail/work/todo .TP .BI "scan " @todo scans $HOME/Mail/work/todo, if current folder is +work .TP .BI "refile " @../done refiles to $HOME/Mail/work/done, if the current folder is +work/todo .TP .BI "scan " +/tmp scans /tmp .TP .BI "scan " +. scans the current directory .TP .BI "refile " @. refiles current message to end of current folder. .PD .PP There are many other possibilities such as creating multiple folders for different topics, and automatically refiling messages according to subject, source, destination, or content. These are beyond the scope of this manual entry. .ne 4 .SH COMMANDS .PP Following is a list of all the .B nmh commands, grouped loosely according to their role. .ne 4 .SS Sending .TP \n(ttu .PD 0 .IR comp (1) compose a message .TP .IR forw (1) forward messages .TP .IR repl (1) reply to a message .TP .IR whatnow (1) prompting front-end for send .PD .PP Note that although .B whatnow provides much of the primary .B nmh user interface for sending mail, it is almost never invoked manually, but rather is invoked indirectly by one of the above commands, after you've composed a message in your editor, and before you've decided to send it. Here you can add attachments, check the recipient list, decide to quit and send it later, etc. .PP Related utilities: .TP \n(ttu .PD 0 .IR ali (1) list mail aliases .TP .IR anno (1) annotate messages .TP .IR whom (1) report to whom a message would go .TP .IR dist (1) redistribute a message to additional addresses .PD .PP Advanced commands, only sometimes invoked directly: .TP \n(ttu .PD 0 .IR mhbuild (1) translate MIME composition draft .TP .IR send (1) send a message .TP .IR sendfiles (1) send multiple files in a MIME message .PD .ne 4 .SS Incorporating .TP \n(ttu .IR inc (1) incorporate new mail .PP Related utilities: .TP \n(ttu .PD 0 .IR burst (1) explode digests into messages .TP .IR msgchk (1) check for messages .TP .IR rcvdist (1) asynchronously redistribute new mail .TP .IR rcvpack (1) append message to file .TP .IR rcvstore (1) asynchronously incorporate new mail .TP .IR slocal (1) asynchronously filter and deliver new mail .PD .ne 4 .SS Viewing .TP \n(ttu .PD 0 .IR next (1) show the next message .TP .IR prev (1) show the previous message .TP .IR show (1) show (display) messages .TP .IR scan (1) produce a one line per message scan listing .TP .IR fnext (1) select the next folder with new messages .TP .IR fprev (1) select the previous folder with new messages .PD .PP Related utilities, only sometimes invoked directly: .TP \n(ttu .PD 0 .IR mhl (1) produce formatted listings of nmh messages .TP .IR mhlist (1) list information about content of MIME messages .TP .IR mhn (1) display/list/store/cache MIME messages .TP .IR mhshow (1) display MIME messages .TP .IR mhstore (1) store contents of MIME messages into files .PD .ne 4 .SS Searching .PP Within a folder: .TP \n(ttu .IR pick (1) select messages by content .PP Across folders: .TP \n(ttu .PD 0 .IR new (1) list folders with new messages .TP .IR unseen (1) list new messages in a given set of folders .TP .IR flist (1) list folders with messages in given sequence(s) .TP .IR flists (1) list all folders with messages in given sequence(s) .TP .IR folder (1) set/list current folder/message .TP .IR folders (1) list all folders .PD .ne 4 .SS Organizing .TP \n(ttu .PD 0 .IR mark (1) mark messages .TP .IR refile (1) file messages in other folders .TP .IR rmf (1) remove folder .TP .IR rmm (1) remove messages .TP .IR sortm (1) sort messages .PD .ne 4 .SS Convenience Wrappers .TP \n(ttu .PD 0 .IR mhmail (1) send or read mail .PD .ne 4 .SS Utilities .TP \n(ttu .PD 0 .IR mhfixmsg (1) rewrite MIME messages with various transformations .TP .IR mhparam (1) print nmh profile components .TP .IR mhpath (1) print full pathnames of nmh messages and folders .TP .IR packf (1) compress a folder into a single file .TP .IR prompter (1) prompting editor front end .TP .IR rcvtty (1) report new mail .PD .ne 4 .SS Indirectly Invoked Commands .TP \n(ttu .PD 0 .IR ap (8) parse addresses RFC 822\-style .TP .IR dp (8) parse dates RFC 822\-style .TP .IR fmtdump (8) decode .IR mh-format (5) files .TP .IR install\-mh (8) initialize the nmh environment .TP .IR post (8) deliver a message .PD .ne 4 .SS Files Used by nmh Commands .TP \n(ttu .PD 0 .IR mh\-alias (5) alias file for nmh message system .TP .IR mh\-format (5) format file for nmh message system .TP .IR mh\-profile (5) user customization for nmh message system .TP .IR mh\-tailor (5) mail transport customization for nmh message system .PD .ne 4 .SS Formats .TP \n(ttu .PD 0 .IR mh\-draft (5) draft folder facility .TP .IR mh\-folders (5) nmh message storage format specification .TP .IR mh\-mail (5) message format for nmh message system .TP .IR mh\-sequence (5) sequence specification for nmh message system .PD .ne 4 .SH FILES .TP %bindir% contains .B nmh commands .TP %nmhetcdir% contains .B nmh format files .TP %nmhlibexecdir% contains .B nmh library commands .TP $HOME/.mh_profile The user's nmh profile .ne 4 .SH "SEE ALSO" .IR install-mh (1), .IR mh-profile (5), .IR mh-chart (7), .IR mh-mime (7) .ne 4 .SH BUGS \" The contents of this section also appear in sbr/print_help.c . Send bug reports, questions, suggestions, and patches to .IR nmh-workers@nongnu.org . That mailing list is relatively quiet, so user questions are encouraged. Users are also encouraged to subscribe, and view the archives, at https://lists.gnu.org/mailman/listinfo/nmh-workers . .PP If problems are encountered with an .B nmh program, they should be reported to the local maintainers of .BR nmh , if any, or to the mailing list noted above. When doing this, the name of the program should be reported, along with the version information for the program. .PP To find out what version of an .B nmh program is being run, invoke the program with the .B \-version switch. This prints the version of .BR nmh , the host it was compiled on, and the date the program was linked. .PP New releases, and other information of potential interest, are announced at http://www.nongnu.org/nmh/ nmh-1.7.1-RC3/man/packf.man000644 007761 000024 00000004245 13243042053 015317 0ustar00kenhstaff000000 000000 .TH PACKF %manext1% 1999-05-13 "%nmhversion%" . .\" %nmhwarning% . .SH NAME packf \- pack messages in nmh folder into a single file .SH SYNOPSIS .HP 5 .na .B packf .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RI [ msgs ] .RB [ \-file .IR name ] .RB [ \-mbox ] .RB [ \-mmdf ] .ad .SH DESCRIPTION .B packf will pack copies of messages from a folder, into a single file. .PP If the .B \-mbox switch is given (the default), then the messages are separated using mbox (uucp) style delimiters. This is the format used by most mail clients (elm, mailx, etc.). .PP If the .B \-mmdf switch is given, then the messages are separated by mmdf style delimiters. Each message in the file is separated by four CTRL\-A's and a newline. .PP You may specify the name of the file in which to pack messages with the .B \-file .I name switch. If you do not specify the name of the file, it will default to .RI \*(lq msgbox \*(rq. .PP If the given file name points to an existing file, then the specified messages will be appended to the end of the file, otherwise the file will be created and the messages appended. .PP .B packf makes an mbox-style delimiter by examining the first line of the message. If the first line is a \*(lqReturn-Path\*(rq field, its address and the current date and time are used. Otherwise, if the first line has an \*(lqX-Envelope-From\*(rq field, its contents (which should already be in the correct format) are used. Otherwise, a dummy address and the current date and time are used. .PP Messages that are packed by .B packf can be unpacked using .BR inc . .SH FILES .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^$HOME/.mh_profile~^The user profile .fi .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u ^Path:~^To determine the user's nmh directory ^Current\-Folder:~^To find the default current folder ^Msg\-Protect:~^To set mode when creating a new `file' .fi .SH "SEE ALSO" .IR inc (1), .SH DEFAULTS .nf .RB ` +folder "' defaults to the current folder" .RB ` msgs "' defaults to all" .RB ` \-mbox ' .RB ` "\-file ./msgbox" ' .fi .SH CONTEXT If a folder is given, it will become the current folder. The first message packed will become the current message. nmh-1.7.1-RC3/man/pick.man000644 007761 000024 00000023153 13243042053 015160 0ustar00kenhstaff000000 000000 .TH PICK %manext1% 2016-03-12 "%nmhversion%" . .\" %nmhwarning% . .SH NAME pick \- search nmh messages .SH SYNOPSIS .HP 5 .na .B pick .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RI [ msgs ] .RB [ \-reverse \&...] .RB [ \-and \&...] .RB [ \-or \&...] .RB [ \-not \&...] .RB [ \-lbrace \&... .BR \-rbrace ] .RB [ \-\|\-component .IR pattern ] .RB [ \-cc .IR pattern ] .RB [ \-date .IR pattern ] .RB [ \-from .IR pattern ] .RB [ \-search .IR pattern ] .RB [ \-subject .IR pattern ] .RB [ \-to .IR pattern ] .RB [ \-after .IR date ] .RB [ \-before .IR date ] .RB [ \-datefield .IR field ] .RB [ \-sequence .I name \&...] .RB [ \-nosequence ] .RB [ \-public " | " \-nopublic ] .RB [ \-zero " | " \-nozero ] .RB [ \-list " | " \-nolist ] .RB [ \-debug ] .PP typical usage: .PP .RS 5 .nf scan\0`pick\0\-from\0jones` pick\0\-to\0holloway\0\-sequence\0select show\0`pick\0\-before\0friday` .fi .RE .ad .SH DESCRIPTION .B pick searches within a folder for messages with the specified contents, and then identifies those messages. Two types of search primitives are available: pattern matching and date constraint operations. .PP A modified .IR grep (1) is used to perform the matching, so the full regular expression (see .IR ed (1)) facility is available within .IR pattern . With .BR \-search , .I pattern is used directly, and with the others, the grep pattern constructed is: .PP .RS 5 `component[ \\t]*:.*pattern' .RE .PP This means that the pattern specified for a .B \-search will be found everywhere in the message, including the header and the body, while the other pattern matching requests are limited to the single specified component. The expression .PP .RS 5 `\-\|\-component\ pattern' .RE .PP is a shorthand for specifying .PP .RS 5 `\-search \*(lqcomponent[ \\t]*:.*pattern\*(rq\ ' .RE .PP It is used to pick a component which is not one of \*(lqTo:\*(rq, \*(lqcc:\*(rq, \*(lqDate:\*(rq, \*(lqFrom:\*(rq, or \*(lqSubject:\*(rq. An example is .RB \*(lq "pick\0\-\|\-reply\-to\0pooh" \*(rq. .PP Pattern matching is performed on a per-line basis. Within the header of the message, each component is treated as one long line, but in the body, each line is separate. Lower-case letters in the search pattern will match either lower or upper case in the message, while upper case will match only upper case. .PP Note that since the .B \-date switch is a pattern matching operation (as described above), to find messages sent on a certain date the pattern string must match the text of the \*(lqDate:\*(rq field of the message. .PP Independent of any pattern matching operations requested, the switches .B \-after .I date or .B \-before .I date may also be used to introduce date/time constraints on all of the messages. By default, the \*(lqDate:\*(rq field is consulted, but if another date-yielding field (such as \*(lqBB\-Posted:\*(rq or \*(lqDelivery\-Date:\*(rq) should be used, the .B \-datefield .I field switch may be used. .PP With .B \-before and .BR \-after , .B pick will actually parse the date fields in each of the messages specified in `msgs' and compare them to the date/time specified. If .B \-after is given, then only those messages whose \*(lqDate:\*(rq field value is chronologically after the date specified will be considered. The .B \-before switch specifies the complementary action. .PP Both the .B \-after and .B \-before switches take legal RFC 822-style date specifications as arguments. .B pick will default certain missing fields so that the entire date need not be specified. These fields are (in order of defaulting): timezone, time and timezone, date, date and timezone. All defaults are taken from the current date, time, and timezone. .PP In addition to RFC 822-style dates, .B pick will also recognize any of the days of the week (\*(lqsunday\*(rq, \*(lqmonday\*(rq, and so on), and the special dates \*(lqtoday\*(rq, \*(lqyesterday\*(rq (24 hours ago), and \*(lqtomorrow\*(rq (24 hours from now). All days of the week are judged to refer to a day in the past (e.g., telling \fIpick\fR \*(lqsaturday\*(rq on a \*(lqtuesday\*(rq means \*(lqlast\ saturday\*(rq not \*(lqthis\ saturday\*(rq). .PP Finally, in addition to these special specifications, .B pick will also honor a specification of the form \*(lq\-dd\*(rq, which means \*(lqdd days ago\*(rq. .PP Use the .BR \-reverse switch to make .B pick find matching messages in reverse order, working from the highest message number down to the lowest. This can be useful in searching for recent messages in large folders, for example, .PP .RS 5 .nf pick\0\-reverse\0\-from\0frated\0|\0xargs\0\-n1\0scan .fi .RE .PP .B pick supports complex boolean operations on the searching primitives with the .BR \-and , .BR \-or , .BR \-not , and .B \-lbrace .B \&... .B \-rbrace switches. For example, .PP .RS 5 .nf pick\0\-after\0yesterday\0\-and \-lbrace\0\-from\0freida\0\-or\0\-from\0fear\0\-rbrace .fi .RE .PP identifies messages recently sent by \*(lqfrieda\*(rq or \*(lqfear\*(rq. .PP The matching primitives take precedence over the .B \-not switch, which in turn takes precedence over .B \-and which in turn takes precedence over .BR \-or . To override the default precedence, the .B \-lbrace and .B \-rbrace switches are provided, which act just like opening and closing parentheses in logical expressions. .PP If no search criteria are given, all the messages specified on the command line are selected (this defaults to \*(lqall\*(rq). .PP Once the search has been performed, if the .B \-list switch is given, the message numbers of the selected messages are written to the standard output separated by newlines. This is .I extremely useful for quickly generating arguments for other .B nmh programs by using the \*(lqbackquoting\*(rq syntax of the shell. For example, the command .PP .RS 5 scan\0`pick\0+todo\0\-after\0\*(lq31 Mar 83 0123 PST\*(rq` .RE .PP says to .B scan those messages in the indicated folder which meet the appropriate criterion. Note that since .BR pick 's context changes are written out prior to .BR scan 's invocation, you need not give the folder argument to .B scan as well. .PP The .B \-sequence .I name switch may be given once for each sequence the user wishes to define. For each sequence named, that sequence will be defined to mean exactly those messages selected by .BR pick . For example, .PP .RS 5 pick\0\-from\0frated\0\-seq\0fred .RE .PP defines a new message sequence for the current folder called \*(lqfred\*(rq which contains exactly those messages that were selected. .PP The .B \-nosequence switch will disable all previously named sequences, allowing those established by a profile component to be overridden. .PP By default, .B pick will zero a sequence before adding it. This action can be disabled with the .B \-nozero switch, which means that the messages selected by .B pick will be added to the sequence, if it already exists, and any messages already a part of that sequence will remain so. .PP The .B \-public and .B \-nopublic switches are used by .B pick in the same way .B mark uses them. .PP The .B \-debug switch causes pick to output a representation of the search pattern. .SS "Output when no messages are matched" If .B pick is used in a backquoted operation, such as .PP .RS 5 scan\0`pick\0\-from\0jones` .RE .PP and .B pick selects no messages (e.g., no messages are from \*(lqjones\*(rq), then the shell will still run the outer command (e.g., .BR scan ). Since no messages were matched, .B pick produced no output, and the argument given to the outer command as a result of backquoting .B pick is empty. In the case of .B nmh programs, the outer command now acts as if the default `msg' or `msgs' should be used (e.g., \*(lqall\*(rq in the case of .BR scan ). To prevent this unexpected behavior, if .B \-list was given, and if its standard output is not a tty, then .B pick outputs the illegal message number \*(lq0\*(rq when it fails. This lets the outer command fail gracefully as well. .SH FILES .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^$HOME/.mh_profile~^The user profile .fi .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u ^Path:~^To determine the user's nmh directory ^Current\-Folder:~^To find the default current folder .fi .SH "SEE ALSO" .IR mark (1) .SH DEFAULTS .nf .RB ` +folder "' defaults to the current folder" .RB ` msgs "' defaults to all" .RB ` "\-datefield date" ' .RB ` \-zero ' .RB ` \-list "' is the default if no `\-sequence', `\-nolist' otherwise" .fi .SH CONTEXT If a folder is given, it will become the current folder. .SH HISTORY In previous versions of .BR MH , the .B pick command would .BR show , .BR scan , or .B refile the selected messages. This was rather \*(lqinverted logic\*(rq from the Unix point of view, so .B pick was changed to define sequences and output those sequences. Hence, .B pick can be used to generate the arguments for all other .B MH commands, instead of giving .B pick endless switches for invoking those commands itself. .PP Also, previous versions of .B pick balked if you didn't specify a search string or a date/time constraint. The current version does not, and merely matches the messages you specify. This lets you type something like: .PP .RS 5 show\0`pick\0last:20\0\-seq\0fear` .RE .PP instead of typing .PP .RS 5 .nf mark\0\-add\0\-nozero\0\-seq\0fear\0last:20 show\0fear .fi .RE .PP Finally, timezones used to be ignored when comparing dates: they aren't any more. .SH "HELPFUL HINTS" Use .RB \*(lq "pick sequence \-list" \*(rq to enumerate the messages in a sequence (such as for use by a shell script). .SH BUGS Any occurrence of .B \-datefield must occur prior to the .B \-after or .B \-before switch it applies to. .PP The pattern syntax \*(lq[l-r]\*(rq is not supported; each letter to be matched must be included within the square brackets. nmh-1.7.1-RC3/man/post.man000644 007761 000024 00000021703 13243042053 015216 0ustar00kenhstaff000000 000000 .TH POST %manext8% 2016-10-17 "%nmhversion%" . .\" %nmhwarning% . .SH NAME post \- deliver an nmh message .SH SYNOPSIS .HP 5 .na .B %nmhlibexecdir%/post .RB [ \-help ] .RB [ \-version ] .RB [ \-alias .IR aliasfile ] .RB [ \-filter .IR filterfile ] .RB [ \-nofilter ] .RB [ \-format " | " \-noformat ] .RB [ \-mime " | " \-nomime ] .RB [ \-msgid " | " \-nomsgid ] .RB [ \-messageid .IR localname " | " random ] .RB [ \-verbose " | " \-noverbose ] .RB [ \-watch " | " \-nowatch ] .RB [ \-width .IR columns ] .RB [ \-mts .IR smtp " | " sendmail/smtp " | " sendmail/pipe ] .RB [ \-sendmail .IR program ] .RB [ \-server .IR servername ] .RB [ \-port .IR portname/number ] .RB [ \-sasl ] .RB [ \-nosasl ] .RB [ \-saslmech .IR mechanism ] .RB [ \-user .IR username ] .RB [ \-tls ] .RB [ \-initialtls ] .RB [ \-notls ] .I file .ad .SH DESCRIPTION .B post is the default program called by .B send to deliver the message in .I file to local and remote users. In fact, most of the features attributed to .B send in its manual page are performed by .BR post , with .B send acting as a relatively simple preprocessor. Thus, it is .B post which parses the various header fields, appends a \*(lqDate:\*(rq line, and interacts with the mail transport system. .B post will not normally be called directly by the user, but can be replaced by the user with a .I postproc profile component that will have .I file as its final argument. See .IR mh-profile (5) for more information on postproc. .PP .B post searches the \*(lqTo:\*(rq, \*(lqcc:\*(rq, \*(lqBcc:\*(rq, \*(lqFcc:\*(rq, and \*(lqResent\-xxx:\*(rq header lines of the specified message for destination addresses, checks these addresses for validity, and formats them so as to conform to ARPAnet Internet Message Format protocol, unless the .B \-noformat flag is set. This will normally cause \*(lq@\fIlocal\-site\fR\*(rq to be appended to each local destination address, as well as any local return addresses. The .B \-width .I columns switch can be used to indicate the preferred length of the header components that contain addresses. .PP If a \*(lqBcc:\*(rq field is encountered, its addresses will be used for delivery, and the \*(lqBcc:\*(rq field will be removed from the message sent to sighted recipients. The blind recipients will receive an entirely new message with a minimal set of headers. Included in the body of the message will be a copy of the message sent to the sighted recipients. If .B \-filter .I filterfile is specified, then this copy is filtered (re-formatted) by .B mhl prior to being sent to the blind recipients. Alternately, if the .B \-mime switch is given, then .B post will use the MIME rules for encapsulation. .PP The .B \-alias .I aliasfile switch can be used to specify a file that post should read aliases from. More than one file can be specified, with each being preceded by .BR \-alias . In any event, the primary alias file is read first. .PP The .B \-msgid switch indicates that a \*(lqMessage\-ID:\*(rq or \*(lqResent\-Message\-ID:\*(rq field should be added to the header. .PP The .B \-messageid switch selects the style used for the part appearing after the @ in \*(lqMessage\-ID:\*(rq, \*(lqResent\-Message\-ID:\*(rq, and \*(lqContent\-ID:\*(rq header fields. The two acceptable options are .B localname (which is the default), and .BR random . With .BR localname , the local hostname is used. With .BR random , a random sequence of characters is used instead. Note that the .B \-msgid switch must be enabled for this switch to have any effect. .PP The .B \-verbose switch indicates that the user should be informed of each step of the posting/filing process. .PP The .B \-watch switch indicates that the user would like to watch the transport system's handling of the message (e.g., local and \*(lqfast\*(rq delivery). .PP Under normal circumstances, .B post uses the \*(lqFrom:\*(rq line in the message draft as the identity of the originating mailbox. A \*(lqFrom:\*(rq line is required in all message drafts. By default the message composition utilities such as .BR comp , .B repl and .B mhmail will automatically place a \*(lqFrom:\*(rq line in the message draft. There are two ways to override this behavior, however. Note that they apply equally to \*(lqResent\-From:\*(rq lines in messages sent with .BR dist . .PP The first way is to supply a \*(lqSender:\*(rq line. The value of this field will be used as the originating mailbox identity when submitting the message to the mail transport system. If multiple addresses are given in the \*(lqFrom:\*(rq line, a \*(lqSender:\*(rq line is .BR required . If an \*(lqEnvelope-From:\*(rq line is supplied when multiple addresses are given in the \*(lqFrom:\*(rq line, a \*(lqSender:\*(rq header will be generated using the value of the \*(lqEnvelope-From:\*(rq line, .B if the \*(lqEnvelope-From:\*(rq line is not blank. .PP The second way is to supply a \*(lqEnvelope-From:\*(rq line. The value of this field will be used as the originating mailbox identity when submitting the message to the mail transport system. This will override both the value of the \*(lqFrom:\*(rq line and a \*(lqSender:\*(rq line (if one is supplied). The \*(lqEnvelope-From:\*(rq line is allowed to have a blank value; if the value is blank, then the mail transport system will be instructed to not send any bounces in response to the message. Not all mail transport systems support this feature. .PP The mail transport system default is defined in .I %nmhetcdir%/mts.conf but can be overridden here with the .B \-mts switch. .PP If nmh is using .BR sendmail/pipe , as its mail transport system, the .B \-sendmail switch can be used to override the default .B sendmail program. .PP If nmh is using the SMTP MTA, the .B \-server and .B \-port switches can be used to override the default mail server and port. The default server is set with .I servers in .IR %nmhetcdir%/mts.conf , and the default port is .IR submission , 587. .PP If .B nmh has been compiled with SASL support, the .B \-sasl and .B \-nosasl switches will enable and disable the use of SASL authentication with the SMTP MTA. Depending on the SASL mechanism used, this may require an additional password prompt from the user (but the .I netrc file can be used to store this password, as described in .IR mh-profile (5). The .B \-saslmech switch can be used to select a particular SASL mechanism, and the .B \-user switch can be used to select an authorization userid to provide to SASL, other than the default. The credentials profile entry in .IR mh-profile (5) describes the ways to supply a username and password. .PP If SASL authentication is successful, .BR nmh will attempt to negotiate a security layer for session encryption. Encrypted data is labelled with `(sasl-encrypted)' and `(sasl-decrypted)' when viewing the SMTP transaction with the .B \-snoop switch. Base64-encoded data is wrapped with `b64<>'. (Beware that the SMTP transaction may contain authentication information either in plaintext or easily decoded base64.) .PP If .B nmh has been compiled with TLS support, the .B \-tls and .B \-initialtls switches will require the negotiation of TLS when connecting to the SMTP MTA. The .B \-tls switch will negotiate TLS as part of the normal SMTP protocol using the STARTTLS command. The .B \-initialtls will negotiate TLS immediately after the connection has taken place, before any SMTP commands are sent or received. Encrypted data is labelled with `(tls-encrypted)' and `(tls-decrypted)' when viewing the SMTP transaction with the .B \-snoop switch. Base64-encoded data is wrapped with `b64<>'. (Beware that the SMTP transaction may contain authentication information either in plaintext or easily decoded base64.) The .B \-notls switch will disable all attempts to negotiate TLS. .PP If port 465 is specified and none of the TLS switches were enabled, .B \-initialtls will be implied if TLS support was compiled in. Though port 465 for SMTPS (SMTP over SSL) was deregistered by IANA in 1998, it is still used for that service. .PP .B post filters out header lines with names beginning with \*(lqNmh-\*(rq (case insensitive) from the message draft. Those lines are reserved for internal .B nmh use. .SH FILES .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^%nmhetcdir%/mts.conf~^nmh mts configuration file ^%nmhetcdir%/MailAliases~^global nmh alias file ^%bindir%/refile~^Program to process Fcc:s ^%nmhlibexecdir%/mhl~^Program to process Bcc:s .fi .SH "PROFILE COMPONENTS" .B post does .I not consult the user's .I \&.mh_profile .SH "SEE ALSO" .IR mhmail (1), .IR send (1), .IR mh\-mail (5), .IR mh\-alias (5), .IR mh\-profile (5), .IR mh\-tailor (5) .PP .I "Standard for the Format of ARPA Internet Text Messages" (RFC 822) .SH DEFAULTS .nf .RB ` \-alias "' defaults to %nmhetcdir%/MailAliases" .RB ` \-format ' .RB ` \-nomime ' .RB ` \-nomsgid ' .RB ` "\-messageid\ localname" ' .RB ` \-noverbose ' .RB ` \-nowatch ' .RB ` "\-width\ 72" ' .RB ` \-nofilter ' .fi .SH CONTEXT None .SH BUGS \*(lqReply\-To:\*(rq fields are allowed to have groups in them according to the RFC 822 specification, but .B post won't let you use them. nmh-1.7.1-RC3/man/prev.man000644 007761 000024 00000003347 13243042053 015211 0ustar00kenhstaff000000 000000 .TH PREV %manext1% 1999-04-30 "%nmhversion%" . .\" %nmhwarning% . .SH NAME prev \- show the previous nmh message .SH SYNOPSIS .HP 5 .na .B prev .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RB [\-showproc .IR program ] .RB [ \-showmimeproc .IR program ] .RB [ \-header " | " \-noheader ] .RB [ \-checkmime " | " \-nocheckmime ] [switches\ for .I showproc or .IR showmimeproc ] .ad .SH DESCRIPTION .B prev performs a .B show on the previous message in the specified (or current) folder. Like .BR show , it passes any switches on to the program named by .I showproc or .IR showmimeproc , which is called to list the message. This command is almost exactly equivalent to .RB \*(lq "show prev" \*(rq. Consult the manual entry for .IR show (1) for all the details. .SH FILES .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^$HOME/.mh_profile~^The user profile .fi .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u ^Path:~^To determine the user's nmh directory ^Current\-Folder:~^To find the default current folder ^showproc:~^Program to show non-MIME messages ^showmimeproc:~^Program to show MIME messages .fi .SH "SEE ALSO" .IR next (1), .IR show (1) .SH DEFAULTS .nf .RB ` +folder "' defaults to the current folder" .RB ` \-checkmime ' .RB ` \-header ' .fi .SH CONTEXT If a folder is specified, it will become the current folder. The message that is shown (i.e., the previous message in sequence) will become the current message. .SH BUGS .B prev is really a link to the .B show program. As a result, if you make a link to .B prev and that link is not called .BR prev , your link will act like .B show instead. To circumvent this, add a profile-entry for the link to your .B nmh profile and add the argument .B prev to the entry. nmh-1.7.1-RC3/man/prompter.man000644 007761 000024 00000010542 13205305704 016103 0ustar00kenhstaff000000 000000 .TH PROMPTER %manext1% 1999-04-30 "%nmhversion%" . .\" %nmhwarning% . .SH NAME prompter \- nmh's prompting editor front-end .SH SYNOPSIS .HP 5 .na .B prompter .RB [ \-help ] .RB [ \-version ] .RB [ \-erase .IR chr ] .RB [ \-kill .IR chr ] .RB [ \-prepend " | " \-noprepend ] .RB [ \-rapid " | " \-norapid ] .RB [ \-doteof " | " \-nodoteof ] .I file .ad .SH DESCRIPTION .B prompter is an editor front-end for .B nmh which allows rapid composition of messages. This program is not normally invoked directly by users but takes the place of an editor and acts as an editor front-end. It operates on an RFC 822-style message draft skeleton specified by .IR file , normally provided by the .B nmh commands .BR comp , .BR dist , .BR forw , or .BR repl . .PP .B prompter is particularly useful when composing messages over slow network or modem lines. It is an .B nmh program in that it can have its own profile entry with switches, but it is not invoked directly by the user. The commands .BR comp , .BR dist , .BR forw , and .B repl invoke .B prompter as an editor, either when invoked with .B \-editor .IR prompter , or by the profile entry \*(lqEditor:\ prompter\*(rq, or when given the command .B edit .B prompter at the \*(lqWhat now?\*(rq prompt. .PP For each empty component .B prompter finds in the draft, the user is prompted for a response; A will cause the whole component to be left out. Otherwise, a `\\' preceding a will continue the response on the next line, allowing for multiline components. Continuation lines .I must begin with a space or tab. .PP Each non-empty component is copied to the draft and displayed on the terminal. .PP The start of the message body is denoted by a blank line or a line of dashes. If the body is non-empty, the prompt, which isn't written to the file, is .PP .RS 5 --------Enter additional text .RE .PP or (if .B \-prepend was given) .PP .RS 5 --------Enter initial text .RE .PP Message-body typing is terminated with an end-of-file (usually CTRL-D). With the .B \-doteof switch, a period on a line all by itself also signifies end-of-file. At this point control is returned to the calling program, where the user is asked \*(lqWhat now?\*(rq. See .IR whatnow (1) for the valid options to this query. .PP By using the .B \-prepend switch, the user can add type-in to the beginning of the message body and have the rest of the body follow. This is useful for the .B forw command. .PP By using the .B \-rapid switch, if the draft already contains text in the message-body, it is not displayed on the user's terminal. This is useful for low-speed terminals. .PP The line editing characters for kill and erase may be specified by the user via the arguments .B \-kill .I chr and .B \-erase .IR chr , where .I chr may be a character; or `\\nnn', where \*(lqnnn\*(rq is the octal value for the character. .PP An interrupt (usually CTRL-C) during component typing will abort .B prompter and the .B nmh command that invoked it. An interrupt during message-body typing is equivalent to CTRL-D, for historical reasons. This means that .B prompter should finish up and exit. .PP The first non-flag argument to .B prompter is taken as the name of the draft file, and subsequent non-flag arguments are ignored. .\" (\fIrepl\fR invokes editors with two file arguments: .\" the draft file name and the replied-to message file name.) .SH FILES .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^$HOME/.mh_profile~^The user profile ^/tmp/prompter*~^Temporary copy of message .fi .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u prompter\-next: To name the editor to be used on exit from .B prompter ^Msg\-Protect:~^To set mode when creating a new draft .fi .SH "SEE ALSO" .IR comp (1), .IR dist (1), .IR forw (1), .IR repl (1), .IR whatnow (1) .SH DEFAULTS .nf .RB ` \-prepend ' .RB ` \-norapid ' .RB ` \-nodoteof ' .fi .SH CONTEXT None .SH "HELPFUL HINTS" The .B \-rapid option is particularly useful with .BR forw , and .B \-noprepend is useful with .B comp .BR \-use . .PP The user may wish to link .B prompter under several names (e.g., \*(lqrapid\*(rq) and give appropriate switches in the profile entries under these names (e.g., \*(lqrapid: -rapid\*(rq). This facilitates invoking prompter differently for different .B nmh commands (e.g., \*(lqforw: -editor rapid\*(rq). .SH BUGS .B prompter uses .IR stdio (3), so it will lose if you edit files with nulls in them. nmh-1.7.1-RC3/man/rcvdist.man000644 007761 000024 00000003207 13205305704 015711 0ustar00kenhstaff000000 000000 .TH RCVDIST %manext1% 1999-04-30 "%nmhversion%" . .\" %nmhwarning% . .SH NAME rcvdist \- asynchronously receive and distribute new email .SH SYNOPSIS .HP 5 .na .B %nmhlibexecdir%/rcvdist .RB [ \-help ] .RB [ \-version ] .RB [ \-form .IR formfile ] [switches\ for .IR postproc ] .I address1 \&... .ad .SH DESCRIPTION .B rcvdist accepts a message on its standard input and resends a copy of the message to all of the addresses listed on its command line. .PP The format of the Resent-xxx header fields is specified by the form file .RI \*(lq rcvdistcomps \*(rq. If a file named .RI \*(lq rcvdistcomps \*(rq exists in the user's nmh directory, it will be used instead of the default file. You may specify an alternate forms file with .B \-form .IR formfile . .PP The .RI \*(lq rcvdistcomps \*(rq file uses the format string facility described in .IR mh\-format (5). In addition to the standard format escapes, .B rcvdist also recognizes the following .I component escape: .PP .RS 5 .nf .ta \w'Dtimenow 'u +\w'Returns 'u .I "Escape Returns Description" addresses string the addresses to distribute to .fi .RE .PP By default, .B rcvdist uses the .B post program to deliver the message, although this can be changed by defining the .I postproc profile component. .SH FILES .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^%nmhetcdir%/rcvdistcomps~^Default message skeleton ^or /rcvdistcomps~^User's message skeleton ^%nmhetcdir%/mts.conf~^nmh mts configuration file ^%nmhetcdir%/maildelivery~^Default delivery file ^$HOME/.maildelivery~^User's delivery file .fi .SH "SEE ALSO" .IR rcvpack (1), .IR rcvstore (1), .IR rcvtty (1), .IR slocal (1), .IR mh\-format (5) nmh-1.7.1-RC3/man/rcvpack.man000644 007761 000024 00000002311 13205305704 015657 0ustar00kenhstaff000000 000000 .TH RCVPACK %manext1% 1999-04-30 "%nmhversion%" . .\" %nmhwarning% . .SH NAME rcvpack \- append an email from standard input to a file .SH SYNOPSIS .HP 5 .na .B %nmhlibexecdir%/rcvpack .RB [ \-help ] .RB [ \-version ] .I file .RB [ \-mbox ] .RB [ \-mmdf ] .ad .SH DESCRIPTION .B rcvpack appends a copy of a message to the file specified on its command line. .PP If the .B \-mbox switch is given (the default), messages are separated by mbox (uucp) style delimiters. This is the format used by most mail clients (elm, mailx, etc.). .PP Alternatively, if the .B \-mmdf switch is given, messages are separated by mmdf style delimiters, each message being separated by four CTRL\-A's and a newline. .PP .B rcvpack will correctly lock and unlock the file to serialize access when running multiple copies of .BR rcvpack . .PP In general, .B rcvpack has been rendered obsolete by the .B file action of .BR slocal , although it may still have some use in shell scripts. .SH FILES .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^%nmhetcdir%/mts.conf~^nmh mts configuration file .fi .SH "SEE ALSO" .IR rcvdist (1), .IR rcvstore (1), .IR rcvtty (1), .IR slocal (1) .SH BUGS Only two return codes are meaningful, others should be. nmh-1.7.1-RC3/man/rcvstore.man000644 007761 000024 00000007416 13205305704 016110 0ustar00kenhstaff000000 000000 .TH RCVSTORE %manext1% 2013-02-19 "%nmhversion%" . .\" %nmhwarning% . .SH NAME rcvstore \- asynchronously incorporate mail into an nmh folder .SH SYNOPSIS .HP 5 .na .B %nmhlibexecdir%/rcvstore .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RB [ \-create " | " \-nocreate ] .RB [ \-unseen " | " \-nounseen ] .RB [ \-zero " | " \-nozero ] .RB [ \-sequence .I name \&...] .RB [ \-public " | " \-nopublic ] .ad .SH DESCRIPTION .B rcvstore incorporates a message from the standard input into an .B nmh folder. This command is typically used in conjunction with mail filtering programs such as .B slocal and .BR procmail , to filter your mail into different folders. .PP You may specify which folder to use with .IR +folder . If no folder is specified, .B rcvstore will use the folder given by a non-empty \*(lqInbox:\*(rq entry in the user's profile, else it will use the folder named \*(lqinbox\*(rq. .PP If the switch .B \-create is given (it is the default) and if the specified (or default) folder does not exist, then it will be created. You may disable this with the .B \-nocreate option. In this case .B rcvstore will exit if the specified folder does not exist. .PP When the new message is incorporated into the folder, it is assigned the next highest number for that folder. .PP .B rcvstore will incorporate anything except zero length messages into the user's .B nmh folder. It will not change the message in any way. .PP If the user's profile contains a .RI \*(lq "Msg\-Protect: nnn" \*(rq entry, it will be used as the mode to use, in octal, on the newly created message, otherwise the .B nmh default mode of 0600, see .IR chmod (1), will be used (on filesystems that support it). For all subsequent operations on this message, this initially assigned mode will be preserved. .PP If the switch .B \-unseen is given (it is on by default), and if the profile entry \*(lqUnseen\-Sequence\*(rq is present and non-empty, then .B rcvstore will add the newly incorporated message to each sequence named by this profile entry. You may use the switch .B \-nounseen to disable this. These sequences will not be zeroed by .B rcvstore prior to adding the new message. .PP Furthermore, the incoming messages may be added to additional sequences as they arrive by the use of the .B \-sequence switch. As with the commands .B pick and .BR mark , you may also use the switches .B \-zero and .B \-nozero to specify whether to zero old sequences or not. Similarly, use of the .B \-public and .B \-nopublic switches may be used to force these sequences to be public or private sequences. .SS Locking and \-unseen If you use the \*(lqUnseen-Sequence\*(rq profile entry, rcvstore could try to read and update its sequence state while another .B nmh process is also trying to do so. This can cause the sequence state to lose track. To avoid this, just between asynchronous invocations of .BR rcvstore , do not use it without an external locking mechanism, for example, a .IR procmailrc (5) local lockfile, if you use the \*(lqUnseen-Sequence\*(rq profile entry. .SH FILES .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^$HOME/.mh_profile~^The user profile .fi .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u ^Path:~^To determine the user's nmh directory ^Folder\-Protect:~^To set mode when creating a new folder ^Inbox:~^To find the default inbox ^Msg\-Protect:~^To set mode when creating a new message ^Unseen\-Sequence:~^To name sequences denoting unseen messages .fi .SH "SEE ALSO" .IR mh\-sequence (5), .IR procmailex (5), .IR procmailrc (5), .IR rcvdist (1), .IR rcvpack (1), .IR rcvtty (1) .SH DEFAULTS .nf .RB ` +folder "' defaults to \*(lqInbox\*(rq profile entry" .RB ` \-create ' .RB ` \-unseen ' .RB ` \-nozero ' .fi .SH CONTEXT No context changes will be attempted, with the exception of sequence manipulation. nmh-1.7.1-RC3/man/rcvtty.man000644 007761 000024 00000005014 13205305704 015564 0ustar00kenhstaff000000 000000 .TH RCVTTY %manext1% 1999-04-30 "%nmhversion%" . .\" %nmhwarning% . .SH NAME rcvtty \- report new mail with nmh .SH SYNOPSIS .HP 5 .na .B %nmhlibexecdir%/rcvtty .RB [ \-help ] .RB [ \-version ] .RI [ command ] .RB [ \-form .IR formatfile ] .RB [ \-format .IR string ] .RB [ \-width .IR columns ] .RB [ \-bell " | " \-nobell ] .RB [ \-newline " | " \-nonewline ] .RB [ \-biff ] .ad .SH DESCRIPTION The .B rcvtty command can be used to report new mail. It is used primarily in conjunction with mail filtering agents such as .B slocal or .BR procmail . .PP .B rcvtty executes the named command with the message as its standard input, and writes the resulting output on your terminal. .PP Alternatively, if no command is specified (or the command is bogus), then .B rcvtty will instead write a one-line scan listing. The default output format of this scan listing may be overridden by using either the .B \-form .I formatfile or .B \-format .I string option, similar to the equivalent options for .B scan and .BR inc . See .IR mh\-format (5) for details. .PP A newline is output before the message output, and the terminal bell is rung after the output. The .B \-nonewline and .B \-nobell switches will inhibit these functions. .PP The switch .B \-width .I columns may be given to specify the width of the scan line. The default is to use the width of the terminal. .PP In addition to the standard format escapes described in .IR mh\-format (5), .B rcvtty also recognizes the following additional .I component escapes: .PP .RS 5 .nf .ta \w'Dtimenow 'u +\w'Returns 'u Escape Returns Description body string the (compressed) first part of the body dtimenow date the current date folder string the name of the current folder .fi .RE .PP By default, .B rcvtty will send its output to every terminal on the local machine that is owned by current user, and that has given write permission as granted by the command .IR mesg (1). If the option .B \-biff is given, then .B rcvtty will obey the notification status set by the command .IR biff (1) instead. .SH FILES .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^%nmhetcdir%/mts.conf~^nmh mts configuration file ^$HOME/.maildelivery~^The file controlling local delivery ^%nmhetcdir%/maildelivery~^Rather than the standard file .fi .SH CONTEXT None .SH DEFAULTS .nf .RB ` \-width "' defaults to the width of the terminal" .RB ` \-newline ' .RB ` \-bell ' .fi .SH "SEE ALSO" .IR mh-format (5), .IR rcvdist (1), .IR rcvpack (1), .IR rcvstore (1), .IR slocal (1) .SH BUGS Only two return codes are meaningful, others should be. nmh-1.7.1-RC3/man/refile.man000644 007761 000024 00000013376 13205305704 015511 0ustar00kenhstaff000000 000000 .TH REFILE %manext1% 2013-03-19 "%nmhversion%" . .\" %nmhwarning% . .SH NAME refile \- file message in nmh folders .SH SYNOPSIS .HP 5 .na .B refile .RB [ \-help ] .RB [ \-version ] .RI [ msgs ] .RB [ \-draft ] .RB [ \-link " | " \-nolink ] .RB [ \-preserve " | " \-nopreserve ] .RB [ \-retainsequences " | " \-noretainsequences ] .RB [ \-unlink " | " \-nounlink ] .RB [ \-src .IR +folder ] .RB [ \-file .IR file ] .RB [ \-rmmproc .IR program ] .RB [ \-normmproc ] .I +folder1 \&... .ad .SH DESCRIPTION .B refile moves (see .IR mv (1)) or links (see .IR ln (1)) messages from a source folder into one or more destination folders. .PP If you think of a message as a sheet of paper, this operation is not unlike filing the sheet of paper (or copies) in file cabinet folders. When a message is filed, it is linked into the destination folder(s) if possible, and is copied otherwise. As long as the destination folders are all on the same file system, multiple filing causes little storage overhead. This facility provides a good way to cross-file or multiple-index messages. For example, if a message is received from Jones about the ARPA Map Project, the command .PP .RS 5 refile\0cur\0+jones\0+Map .RE .PP would allow the message to be found in either of the two folders `jones' or `Map'. .PP You may specify the source folder using .B \-src .IR +folder . If this is not given, the current folder is used by default. If no message is specified, then `cur' is used by default. .PP The option .B \-file .I file directs .B refile to use the specified file as the source message to be filed, rather than a message from a folder. Note that the file should be a validly formatted message, just like any other .B nmh message. It should .I not be in mail drop format (to convert a file in mail drop format to a folder of .B nmh messages, see .IR inc (1)). .PP If a destination folder doesn't exist, .B refile will ask if you want to create it. A negative response will abort the file operation. If the standard input for .B refile is .I not a tty, then .B refile will not ask any questions and will proceed as if the user answered \*(lqyes\*(rq to all questions. .PP The option .B \-link preserves the source folder copy of the message (i.e., it does an .IR ln (1) rather than a .IR mv (1)), whereas, .B \-nolink (the default) deletes the filed messages from the source folder. .PP Normally when a message is refiled, for each destination folder it is assigned the number which is one above the current highest message number in that folder. Use of the .B \-preserve switch will override this message renaming, and try to preserve the number of the message. If a conflict for a particular folder occurs when using the .B \-preserve switch, then .B refile will use the next available message number which is above the message number you wish to preserve. .PP As message sequences are folder-specific, moving the message from the source folder removes it from all its sequences in that folder. .B \-retainsequences adds it to those same sequences in the destination folder, creating any that don't exist. This adding does not apply for the \*(lqcur\*(rq sequence. .PP If .B \-link is not specified (or .B \-nolink is specified), the filed messages will be removed from the source folder. The default is to remove these messages by renaming them with a site-dependent prefix (usually a comma). Such files will then need to be removed in some manner after a certain amount of time. Many sites arrange for .B cron to remove these files once a day, so check with your system administrator. .PP Alternately, if you wish for .B refile to really remove the files representing these messages from the source folder, you can use the .B \-unlink switch (not to be confused with the .B \-link switch). But messages removed by this method cannot be later recovered. .PP If you prefer a more sophisticated method of `removing' the messages from the source folder, you can define the .B rmmproc profile component. For example, you can add a profile component such as .PP .RS 5 rmmproc: /home/coleman/bin/rmm_msgs .RE .PP then .B refile will instead call the named program or script to handle the message files. .PP The user may specify .B \-rmmproc .I program on the command line to override this profile specification. The .B \-normmproc option forces the message files to be deleted by renaming or unlinking them as described above. .PP The .B \-draft switch tells .B refile to file the /draft. .SH FILES .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^$HOME/.mh_profile~^The user profile .fi .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u ^Path:~^To determine the user's nmh directory ^Current\-Folder:~^To find the default current folder ^Folder\-Protect:~^To set mode when creating a new folder ^rmmproc:~^Program to delete the message .fi .SH "SEE ALSO" .IR folder (1), .IR mh-sequence (5), .IR rmf (1), .IR rmm (1) .SH DEFAULTS .nf .RB ` "\-src\ +folder" "' defaults to the current folder" .RB ` msgs "' defaults to cur" .RB ` \-nolink ' .RB ` \-nounlink ' .RB ` \-nopreserve ' .RB ` \-noretainsequences ' .fi .SH CONTEXT If .B \-src .I +folder is given, it will become the current folder. If neither .B \-link nor `all' is specified, the current message in the source folder will be set to the last message specified; otherwise, the current message won't be changed. .PP If the \*(lqPrevious\-Sequence\*(rq profile entry is set, in addition to defining the named sequences from the source folder, .B refile will also define those sequences for the destination folders. See .IR mh\-sequence (5) for information concerning the previous sequence. .SH BUGS Since .B refile and .B rmm use your .I rmmproc to delete the message, the .I rmmproc must .I not call .B refile or .B rmm without specifying .BR \-normmproc , or you will create an infinite loop. nmh-1.7.1-RC3/man/repl.man000644 007761 000024 00000033020 13243042053 015166 0ustar00kenhstaff000000 000000 .TH REPL %manext1% 2014-12-15 "%nmhversion%" . .\" %nmhwarning% . .SH NAME repl \- reply to an nmh message .SH SYNOPSIS .HP 5 .na .B repl .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RI [ msg ] .RB [ \-annotate " | " \-noannotate ] .RB [ \-group " | " \-nogroup ] .RB [ \-cc all/to/cc/me] .RB [ \-nocc all/to/cc/me] .RB [ \-query " | " \-noquery ] .RB [ \-form .IR formfile ] .RB [ \-format " | " \-noformat ] .RB [ \-filter .IR filterfile ] .RB [ \-inplace " | " \-noinplace ] .RB [ \-mime " | " \-nomime ] .RB [ \-fcc .IR +folder ] .RB [ \-width .IR columns ] .RB [ \-draftfolder .IR +folder ] .RB [ \-draftmessage .IR msg ] .RB [ \-nodraftfolder ] .RB [ \-editor .IR editor ] .RB [ \-noedit ] .RB [ \-convertargs .IR "type argstring" ] .RB [ \-whatnowproc .IR program ] .RB [ \-nowhatnowproc ] .RB [ \-atfile ] .RB [ \-noatfile ] .RB [ \-fmtproc .IR program ] .RB [ \-nofmtproc ] .RB [ \-build ] .RB [ \-file .IR msgfile ] .ad .SH DESCRIPTION .B repl may be used to reply to a message. .PP In its simplest form (with no arguments), .B repl will set up a message-form skeleton in reply to the current message in the current folder, and invoke the .B whatnow shell. .PP .B repl uses a reply template to construct the draft of the reply. A reply template is simply an .B mhl format file (see .IR mh\-format (5) for details). .PP If the switch .B \-nogroup is given (it is on by default), then .B repl will use the standard forms file \*(lqreplcomps\*(rq. This will construct a draft message that is intended to be sent only to the author of the message to which you are replying. If a file named \*(lqreplcomps\*(rq exists in the user's .B nmh directory, it will be used instead of this default forms file. .PP The default reply template \*(lqreplcomps\*(rq will direct .B repl to construct the reply message draft as follows: .PP .RS 5 .nf To: or or cc: and and Fcc: {fcc switch} or +outbox Subject: Re: In\-Reply\-To: References: Comments: In\-Reply\-To or or .ti +3 message dated -------- .fi .RE .PP where field names enclosed in angle brackets (<\ >) indicate the contents of the named field from the message to which the reply is being made. .PP By default, the \*(lqcc:\*(rq field is empty. You may selectively add addresses to this default with the .B \-cc .I type switch. This switch takes an argument .RI ( all / to / cc / me ) which specifies who gets added to the default \*(lqcc:\*(rq list of the reply. You may give this switch multiple times (with different arguments) if you wish to add multiple types of address. .PP If the switch .B \-group is given, then .B repl will use the standard forms file \*(lqreplgroupcomps\*(rq. This will construct a draft message that is intended as a group or followup reply. If a file named \*(lqreplgroupcomps\*(rq exists in the user's nmh directory, it will be used instead of this default forms file, unless you specify another forms file on the command line or in your profile. .PP The default group reply template \*(lqreplgroupcomps\*(rq will direct .B repl to construct the reply message draft as follows: .PP .RS 5 .nf To: Subject: Re: In\-Reply\-To: Message from of . .ti +\w'In\-Reply\-To: 'u -------- .fi .RE .PP or if the field is not available: .PP .RS 5 .nf To: or or cc: and and Subject: Re: In\-Reply\-To: Message from of . .ti +\w'In\-Reply\-To: 'u -------- .fi .RE .PP By default, the \*(lqcc:\*(rq contains all the addresses shown. You may selectively remove addresses from this default with the .B \-nocc .I type switch. This switch takes an argument ( .IR all / to / cc / me ) which specifies who gets removed from the default \*(lqcc:\*(rq list of the reply. You may give this switch multiple times (with different arguments) if you wish to remove multiple types of address. .PP In any case, you may specify an alternative forms file with the switch .B \-form .IR formfile . .PP The .B \-query switch modifies the action of .B \-nocc .I type switch by interactively asking you if each address that normally would be placed in the \*(lqTo:\*(rq and \*(lqcc:\*(rq list should actually be sent a copy. This is useful for special-purpose replies. Note that the position of the .B \-cc and .B \-nocc switches, like all other switches which take a positive and negative form, is important. .PP Lines beginning with the fields \*(lqTo:\*(rq, \*(lqcc:\*(rq, and \*(rqBcc:\*(rq will be standardized and have duplicate addresses removed. In addition, the .B \-width .I columns switch will guide .BR repl 's formatting of these fields. .PP If the draft already exists, .B repl will ask you as to the disposition of the draft. A reply of .B quit will abort .BR repl , leaving the draft intact; .B replace will replace the existing draft with a blank skeleton; and .B list will display the draft. .PP See .IR comp (1) for a description of the .B \-editor and .B \-noedit switches. Note that while in the editor, with .B \-atfile and if the current directory is writable, the message being replied to is available through a link named \*(lq@\*(rq (assuming the default .IR whatnowproc ). In addition, the actual pathname of the message is stored in the environment variable .BR $editalt , and the pathname of the folder containing the message is stored in the environment variable .BR $mhfolder . The creation of the \*(lq@\*(rq file is controlled via the .B \-atfile and .B \-noatfile options. .PP The .B \-convertargs switch directs .B repl to pass the arguments for .I type to .BR mhbuild . Both arguments are required; .I type must be non-empty while .I argstring can be empty, e.g., '' in a shell command line. The .B \-convertargs switch can be used multiple times. See the Convert Interface section of .IR mhbuild (1) for a description of the convert mechanism, and .I %docdir%/contrib/replaliases for examples of its use. .PP Although .B repl uses a forms file to direct it how to construct the beginning of the draft, it uses a message filter file to direct it as to how the message to which you are replying should be filtered (re-formatted) in the body of the draft. The filter file for .B repl should be a standard form file for .BR mhl , as .B repl will invoke .B mhl to format the message to which you are replying. .PP The switches .BR \-noformat , .BR \-format , and .B \-filter .I filterfile specify which message filter file to use. .PP If the switch .B \-noformat is given (it is the default) and the .B \-filter switch is not used, then the message to which you are replying is not included in the body of the draft. .PP If the switch .B \-format is given, then a default message filter file is used. This default message filter should be adequate for most users. This default filter .RI \*(lq mhl.reply \*(rq is: .PP .RS 5 .nf %mhl_reply% .fi .RE .PP which outputs each line of the body of the message prefaced with the \*(lq>\*(rq character and a space. .PP If a file named .RI \*(lq mhl.reply \*(rq exists in the user's .B nmh directory, it will be used instead of this form. You may specify an alternate message filter file with the switch .B \-filter .IR filterfile . .PP Other reply filters are commonly used, such as: .PP .RS 5 .nf : body:nocomponent,compwidth=9,offset=9 .fi .RE .PP which says to output a blank line, and then the body of the message being replied to, indented by one tab stop. Another popular format is: .PP .RS 5 .nf message-id:nocomponent,\|nonewline,\\ formatfield=\*(lqIn message %{text},\ \*(rq from:nocomponent,\|formatfield=\*(lq%(decode(friendly{text})) writes:\*(rq body:component=\*(lq>\*(rq,\|overflowtext=\*(lq>\*(rq,\|overflowoffset=0 .fi .RE .PP This message filter file cites the Message-ID and author of the message being replied to, and then outputs each line of the body prefaced with the \*(lq>\*(rq character. .PP You can also use an external format program to format the message body. The format program is specified by the .IR formatproc profile entry, and is enabled by the \*(lqformat\*(rq flag. A message filter using an external format program would look like this: .PP .RS 5 .nf body:component=\*(lq>\*(rq,\|nowrap,\|format .fi .RE .PP See the .IR mhl (1) documentation for more information. The format program can be changed by the .B \-fmtproc .I program and .B \-nofmtproc switches. .PP To use the MIME rules for encapsulation, specify the .B \-mime switch. This directs .B repl to generate an .B mhbuild composition file. Note that .B nmh will not invoke .B mhbuild automatically; you must specifically give the command .PP .RS 5 What now? mime .RE .PP prior to sending the draft. .PP If the .B \-annotate switch is given, the message being replied to will be annotated with the lines .PP .RS 5 Replied:\ date Replied:\ addrs .RE .PP where the address list contains one line for each addressee. The annotation will be done only if the message is sent directly from .BR repl . If the message is not sent immediately from .BR repl , .RB \*(lq "comp\ \-use" \*(rq may be used to re-edit and send the constructed message, but the annotations won't take place. Normally annotations are done inplace in order to preserve any links to the message. You may use the .B \-noinplace switch to change this. .PP Although the default template specifies that a copy of the reply will be put in the folder 'outbox', if the .B \-fcc .I +folder switch is given it will override the default value. More than one folder, each preceded by .B \-fcc can be named. .PP In addition to the standard .IR mh\-format (5) escapes, .B repl also recognizes the following additional .I component escape: .PP .RS 5 .nf .ta \w'Escape 'u +\w'Returns 'u .I "Escape Returns Description" fcc string Any folders specified with `\-fcc\ folder' .fi .RE .PP To avoid reiteration, .B repl strips any leading `Re: ' strings from the .I subject component. .PP The .B \-draftfolder .I +folder and .B \-draftmessage .I msg switches invoke the .B nmh draft folder facility. This is an advanced (and highly useful) feature. Consult the .IR mh-draft (5) man page for more information. .PP Upon exiting from the editor, .B repl will invoke the .B whatnow program. See .IR whatnow (1) for a discussion of available options. The invocation of this program can be inhibited by using the .B \-nowhatnowproc switch. (In fact, it is the .B whatnow program which starts the initial edit. Hence, .B \-nowhatnowproc will prevent any edit from occurring.) .PP The .B \-build switch is intended to be used by the Emacs mh-e interface to .BR nmh . It implies .BR \-nowhatnowproc . It causes a file .I /reply to be created, containing the draft message that would normally be presented to the user for editing. No mail is actually sent. .PP The .B \-file .I msgfile switch specifies the message to be replied to as an exact filename rather than as an .B nmh folder and message number. The same caveats apply to this option as to the .B \-build switch. .SH FILES .B repl looks for all format, filter and template files in multiple locations: absolute pathnames are accessed directly, tilde expansion is done on usernames, and files are searched for in the user's .I Mail directory as specified in their profile. If not found there, the directory .RI \*(lq %nmhetcdir% \*(rq is checked. .PP .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^%nmhetcdir%/replcomps~^The standard reply template ^or /replcomps~^Rather than the standard template ^%nmhetcdir%/replgroupcomps~^The standard `reply -group' template ^or /replgroupcomps~^Rather than the standard template ^%nmhetcdir%/mhl.reply~^The standard message filter ^or /mhl.reply~^Rather than the standard filter ^$HOME/.mh_profile~^The user profile ^/draft~^The draft file .fi .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u ^Path:~^To determine the user's nmh directory ^Alternate\-Mailboxes:~^To determine the user's mailboxes ^Current\-Folder:~^To find the default current folder ^Draft\-Folder:~^To find the default draft-folder ^Editor:~^To override the default editor ^Msg\-Protect:~^To set mode when creating a new message (draft) ^fileproc:~^Program to refile the message ^mhlproc:~^Program to filter message being replied-to ^whatnowproc:~^Program to ask the \*(lqWhat now?\*(rq questions .fi .SH "SEE ALSO" .IR comp (1), .IR forw (1), .IR mh\-format (5), .IR mhbuild (1), .IR send (1), .IR whatnow (1) .PP .I %docdir%/contrib/replaliases .SH DEFAULTS .nf .RB ` +folder "' defaults to the current folder" .RB ` msg "' defaults to cur" .RB ` \-nogroup ' .RB ` "\-nocc\ all" "' with `\-nogroup', `\-cc\ all' with `\-group'" .RB ` \-noannotate ' .RB ` \-nodraftfolder ' .RB ` \-noformat ' .RB ` \-inplace ' .RB ` \-nomime ' .RB ` \-noquery ' .RB ` \-noatfile ' .RB ` "\-width\ 72" ' .fi .SH CONTEXT If a folder is given, it will become the current folder. The message replied to will become the current message. .SH BUGS If any addresses occur in the reply template, addresses in the template that do not contain hosts are defaulted incorrectly. Instead of using the localhost for the default, .B repl uses the sender's host. Moral of the story: if you're going to include addresses in a reply template, include the host portion of the address. .PP The .B \-width .I columns switch is only used to do address-folding; other headers are not line-wrapped. .PP If .I whatnowproc is .BR whatnow , then .B repl uses a built-in .BR whatnow , it does not actually run the .B whatnow program. Hence, if you define your own .IR whatnowproc , don't call it .B whatnow since .B repl won't run it. nmh-1.7.1-RC3/man/rmf.man000644 007761 000024 00000004737 13205305704 015030 0ustar00kenhstaff000000 000000 .TH RMF %manext1% 1999-04-30 "%nmhversion%" . .\" %nmhwarning% . .SH NAME rmf \- remove an nmh folder .SH SYNOPSIS .HP 5 .na .B rmf .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RB [ \-interactive " | " \-nointeractive ] .ad .SH DESCRIPTION .B rmf removes all of the messages (files) within the specified (or default) folder, and then removes the folder (directory) itself. .PP If there are any files within the folder which are not a part of .BR nmh , they will .I not be removed, and an error will be produced. If the folder is given explicitly, or the .B \-nointeractive option is given, then the folder will be removed without confirmation. Otherwise, the user will be asked for confirmation. If .B rmf can't, for some reason, find the current folder the folder to be removed defaults to `+inbox' (unless overridden by the user's profile entry \*(lqInbox\*(rq), with confirmation. .PP If the folder being removed is a subfolder, the parent folder will become the new current folder, and .B rmf will produce a message telling the user this has happened. This provides an easy mechanism for selecting a set of messages, operating on the list, then removing the list and returning to the current folder, from which the list was extracted. .PP If .B rmf is used on a read-only folder, it will delete all the private sequences (i.e., .RI \*(lqatr\- seq \- folder \*(rq entries) for this folder from your context without affecting the folder itself. .PP .B rmf irreversibly deletes messages that don't have other links, so use it with caution. .SH FILES .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^$HOME/.mh_profile~^The user profile .fi .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u ^Path:~^To determine the user's nmh directory ^Current\-Folder:~^To find the default current folder ^Inbox:~^To find the default inbox .fi .SH "SEE ALSO" .IR folder (1), .IR rmm (1) .SH DEFAULTS .nf .RB ` +folder "' defaults to the current folder, usually with confirmation" .RB ` \-interactive "' if +folder' not given, `\-nointeractive' otherwise" .fi .SH CONTEXT .B rmf will set the current folder to the parent folder if a subfolder is removed; or if the current folder is removed, it will make \*(lqinbox\*(rq current. Otherwise, it doesn't change the current folder or message. .SH BUGS Although intuitively one would suspect that .B rmf works recursively, it does not. Hence, if you have a sub-folder within a folder, in order to .B rmf the parent, you must first .B rmf each of the children. nmh-1.7.1-RC3/man/rmm.man000644 007761 000024 00000005242 13243042053 015024 0ustar00kenhstaff000000 000000 .TH RMM %manext1% 2013-03-19 "%nmhversion%" . .\" %nmhwarning% . .SH NAME rmm \- remove nmh messages .SH SYNOPSIS .HP 5 .na .B rmm .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RI [ msgs ] .RB [ \-unlink " | " \-nounlink ] .RB [ \-rmmproc .IR program ] .RB [ \-normmproc ] .ad .SH DESCRIPTION By default, .B rmm will remove the specified messages by renaming each of the message files with a site-dependent prefix (usually a comma). Such files will then need to be removed in some manner after a period of time. Many sites arrange for .B cron to remove these files once a day, so check with your system administrator. .PP Alternately, if you wish for .B rmm to really remove the files representing these messages, you can use the .B \-unlink switch. But messages removed by this method cannot be later recovered. .PP If you prefer a more sophisticated method of `removing' messages, you can define the .I rmmproc profile component. For example, you can add a profile component such as .PP .RS 5 rmmproc: /home/foouser/bin/rmm_msgs .RE .PP Then instead of simply renaming the message file, .B rmm will call the named program or script to handle the files that represent the messages to be deleted. The .B \-rmmproc switch may be used to override this profile component. The .B \-normmproc switch disables the use of any .I rmmproc profile component and negates all prior .B \-rmmproc switches. .PP An example of a .I rmmproc script that saves a message based in its Message-ID is provided in %nmhetcdir%/rmmproc.messageid. To enable it, simply add an .I rmmproc component that names it, to your profile. .PP Some users of .B csh prefer the following: .PP .RS 5 alias rmm 'refile +d' .RE .PP where folder `+d' is a folder for deleted messages, and .PP .RS 5 alias mexp 'rm `mhpath +d all`' .RE .PP is used to \*(lqexpunge\*(rq deleted messages. .PP The current message is not changed by .BR rmm , so a .B next will advance to the next message in the folder as expected. .SH FILES .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^$HOME/.mh_profile~^The user profile .fi .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u ^Path:~^To determine the user's nmh directory ^Current\-Folder:~^To find the default current folder ^rmmproc:~^Program to delete the message .fi .SH "SEE ALSO" .IR rmf (1) .SH DEFAULTS .nf .RB ` +folder "' defaults to the current folder" .RB ` msgs "' defaults to cur" .RB ` -nounlink ' .fi .SH CONTEXT If a folder is given, it will become the current folder. .SH BUGS Since .B rmm and .B refile use your .I rmmproc to delete the message, the .I rmmproc must .I not call .B rmm or .B refile without specifying .BR \-normmproc , or you will create an infinite loop. nmh-1.7.1-RC3/man/scan.man000644 007761 000024 00000014100 13205305704 015151 0ustar00kenhstaff000000 000000 .TH SCAN %manext1% 2014-01-20 "%nmhversion%" . .\" %nmhwarning% . .SH NAME scan \- produce a summary listing of nmh messages .SH SYNOPSIS .HP 5 .na .B scan .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RI [ msgs ] .RB [ \-clear " | " \-noclear ] .RB [ \-form .IR formatfile ] .RB [ \-format .IR string ] .RB [ \-header " | " \-noheader ] .RB [ \-width .IR columns ] .RB [ \-reverse " | " \-noreverse ] .RB [ \-file .IR filename ] .ad .SH DESCRIPTION .B scan produces a one-line-per-message listing of the specified folder or messages. Each .B scan line contains the message number (name), the date, the \*(lqFrom:\*(rq field, the \*(lqSubject\*(rq field, and, if room allows, some of the body of the message. For example: .PP .RS 5 .nf .ta \w'15+- 'u +\w'07/\|05x 'u +\w'Dcrocker 'u 15+ 10/\|05 crocker nned\0\0<>\*(rq if the body is sufficiently short. .B scan actually reads each of the specified messages and parses them to extract the desired fields. During parsing, appropriate error messages will be produced if there are format errors in any of the messages. .PP By default, .B scan will decode RFC 2047 (MIME) encoding in these scan listings. .B scan will only decode these fields if your terminal can natively display the character set used in the encoding. You should set the appropriate .IR locale (1) environment variables to your native character set, if it is not US-ASCII. See .IR locale (1) for more details on the appropriate environment variables. .PP The switch .BR \-reverse , makes .B scan list the messages in reverse order. .PP The .B \-file .I filename switch allows the user to obtain a .B scan listing of a mail drop file as produced by .BR packf . This listing includes every message in the file (you can't scan individual messages). The switch .B \-reverse is ignored with this option. .PP The switch .B \-width .I columns may be used to specify the width of the scan line. The default is to use the width of the terminal. .PP The .B \-header switch produces a header line prior to the .B scan listing. Currently, the name of the folder and the current date and time are output (see the .B HISTORY section for more information). .PP If the .B \-clear switch is used and .BR scan 's output is directed to a terminal, then .B scan will consult the environment variables .B $TERM and .B $TERMCAP to determine your terminal type in order to find out how to clear the screen prior to exiting. If the .B \-clear switch is used and .BR scan 's output is not directed to a terminal (e.g., a pipe or a file), then .B scan will send a formfeed prior to exiting. .PP For example, the command: .PP .RS 5 (scan \-clear \-header; show all \-show pr \-f) | lpr .RE .PP produces a scan listing of the current folder, followed by a formfeed, followed by a formatted listing of all messages in the folder, one per page. Omitting .RB \*(lq "\-show\ pr\ \-f" \*(rq will cause the messages to be concatenated, separated by a one-line header and two blank lines. .PP To override the output format used by .BR scan , the .B \-format .I string or .B \-form .I file switches are used. This permits individual fields of the scan listing to be extracted with ease. The string is simply a format string and the file is simply a format file. See .IR mh\-format (5) for the details. .PP In addition to the standard .IR mh\-format (5) escapes, .B scan also recognizes the following additional .I component escapes: .PP .RS 5 .nf .ta \w'Dtimenow 'u +\w'Returns 'u .I "Escape Returns Description" body string the (compressed) first part of the body dtimenow date the current date folder string the name of the current folder .fi .RE .PP .RB { body } returns a string without MIME decoding, i.e.\& the MIME boundary seperator may be the first text shown. .PP If no date header is present in the message, the .I function escapes which operate on .RB { date } will return values for the date of last modification of the message file itself. This feature is handy for scanning a draft folder, as message drafts usually aren't allowed to have dates in them. .PP The .B %nmhetcdir% directory contains several format files as examples of customized .B scan output. .PP .B scan will update the .B nmh context prior to starting the listing, so interrupting a long .B scan listing preserves the new context. .B nmh purists hate this idea. .SH FILES .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^$HOME/.mh_profile~^The user profile .fi .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u ^Path:~^To determine the user's nmh directory ^Alternate\-Mailboxes:~^To determine the user's mailboxes ^Current\-Folder:~^To find the default current folder .fi .SH "SEE ALSO" .IR pick (1), .IR show (1), .IR mh\-format (5) .SH DEFAULTS .nf .RB ` +folder "' defaults to the current folder" .RB ` msgs "' defaults to all" .RB ` \-format "' defaulted as described above" .RB ` \-noheader ' .RB ` \-width "' defaulted to the width of the terminal" .fi .SH CONTEXT If a folder is given, it will become the current folder. .SH HISTORY Prior to using the format string mechanism, .B \-header used to generate a heading saying what each column in the listing was. Format strings prevent this from happening. .SH BUGS The value of each .I component escape is set by .B scan to the contents of the first message header .B scan encounters with the corresponding component name; any following headers with the same component name are ignored. nmh-1.7.1-RC3/man/send.man000644 007761 000024 00000044116 13243042053 015165 0ustar00kenhstaff000000 000000 .TH SEND %manext1% 2017-05-11 "%nmhversion%" . .\" %nmhwarning% . .SH NAME send \- send an nmh message .SH SYNOPSIS .HP 5 .na .B send .RB [ \-help ] .RB [ \-version ] .RB [ \-alias .IR aliasfile ] .RB [ \-draft ] .RB [ \-draftfolder .IR +folder ] .RB [ \-draftmessage .IR msg ] .RB [ \-nodraftfolder ] .RB [ \-filter .IR filterfile ] .RB [ \-nofilter ] .RB [ \-format " | " \-noformat ] .RB [ \-forward " | " \-noforward ] .RB [ \-mime " | " \-nomime ] .RB [ \-msgid " | " \-nomsgid ] .RB [ \-messageid .IR localname " | " random ] .RB [ \-push " | " \-nopush ] .RB [ \-split .IR seconds ] .RB [ \-verbose " | " \-noverbose ] .RB [ \-watch " | " \-nowatch ] .RB [ \-mts .IR smtp " | " sendmail/smtp " | " sendmail/pipe ] .RB [ \-sendmail .IR program ] .RB [ \-server .IR servername ] .RB [ \-port .IR port-name/number ] .RB [ \-sasl ] .RB [ \-nosasl ] .RB [ \-saslmech .IR mechanism ] .RB [ \-authservice .IR service ] .RB [ \-snoop ] .RB [ \-user .IR username ] .RB [ \-tls ] .RB [ \-initialtls ] .RB [ \-notls ] .RB [ \-certverify ] .RB [ \-nocertverify ] .RB [ \-width .IR columns ] .RB [ file \&...] .ad .SH DESCRIPTION .B send will cause each of the specified files to be delivered to each of the destinations in the \*(lqTo:\*(rq, \*(lqcc:\*(rq, \*(lqBcc:\*(rq, \*(lqDcc:\*(rq, and \*(lqFcc:\*(rq fields of the message. If .B send is re-distributing a message, as invoked from .BR dist , then the corresponding \*(lqResent\-xxx\*(rq fields are examined instead. .PP By default, .B send uses the program .B post to do the actual delivery of the messages, although this can be changed by defining the .I postproc profile component. Most of the features attributed to .B send are actually performed by .BR post . .PP Before .B send gives the message to .B post for delivery, the message is processed by .B mhbuild to perform any necessary MIME encoding of the outgoing message. This can be changed by the .I buildmimeproc profile component. .B mhbuild is invoked with the .B \-auto switch, so .B mhbuild directives are not processed by default. See .IR mhbuild (1) for more information. .PP .B mhbuild will scan the message draft for a header named .IR Attach . The draft is converted to a MIME message if one or more matches are found. This conversion occurs before all other processing. The .IR whatnow (1) man page describes the user interface for managing MIME attachments via this mechanism. .PP The first part of the MIME message is the draft body if that body contains any non-blank characters. The body of each .I Attach header field is interpreted as a file name, and each file named is included as a separate part in the MIME message. .PP Determination of the content MIME type inserted into the Content-Type header for each part depends on how the .B nmh installation was configured. If a program, such as .B file with a .B \-\-mime or .B \-i option, was found that can specify the type of a file as a MIME type string, then that will be used. To determine if your .B nmh was so configured, run .B mhparam mimetypeproc and see if a non-empty string is displayed. .PP If your .B nmh was not configured with a program to specify a file type as a MIME string, then a different method is used to determine the content-type string. For file names with dot suffixes, the profile is scanned for a .I mhshow-suffix- entry for that suffix. The content-type for the part is taken from that profile entry if a match is found. If a match is not found in the user profile, the mhn.defaults profile is scanned next. If no match is found or the file does not have a dot suffix, the content-type is text/plain if the file contains only ASCII characters or application/octet-stream if it contains characters outside of the ASCII range. See .IR mhshow (1) for more details and example syntax. .PP Each attached MIME part contains a \*(lqContent-Description\*(rq header that includes the filename, and adds a \*(lqContent-Disposition\*(rq header. Here is an example of MIME part headers for an attachment: .PP .nf Content-Type: text/plain; name="VERSION"; charset="us-ascii" Content-Description: VERSION Content-Disposition: attachment; filename="VERSION" .fi .PP See .IR mhbuild (1) for explanation of how the Content-Disposition value is selected. .PP If .B \-push is specified, .B send will detach itself from the user's terminal and perform its actions in the background. If .BR push 'd and the draft can't be sent, then an error message will be sent (using the mailproc) back to the user. If .B \-forward is given, then a copy of the draft will be attached to this failure notice. Using .B \-push differs from putting .B send in the background because the output is trapped and analyzed by .BR nmh . .PP If .B \-verbose is specified, .B send will indicate the interactions occurring with the transport system, prior to actual delivery. If .B \-watch is specified .B send will monitor the delivery of local and network mail. Hence, by specifying both switches, a large detail of information can be gathered about each step of the message's entry into the transport system. .PP The .B \-draftfolder .I +folder and .B \-draftmessage .I msg switches invoke the .B nmh draft folder facility. This is an advanced (and highly useful) feature. Consult the .IR mh-draft (5) man page for more information. .PP If .B \-split is specified, .B send will split the draft into one or more partial messages prior to sending. This makes use of the MIME features in .BR nmh . Note however that if .B send is invoked under .BR dist , then this switch is ignored\0--\0it makes no sense to redistribute a message in this fashion. Sometimes you want .B send to pause after posting a partial message. This is usually the case when you are running .B sendmail and expect to generate a lot of partial messages. The argument to .B \-split tells it how long to pause between postings. .PP .B send with no .I file argument will query whether the draft is the intended file, whereas .B \-draft will suppress this question. Once the transport system has successfully accepted custody of the message, the file will be renamed with a site-dependent prefix (usually a comma), which allows it to be retrieved until the next draft message is sent. If there are errors in the formatting of the message, .B send will abort with a (hopefully) helpful error message. .PP If a \*(lqBcc:\*(rq field is encountered, its addresses will be used for delivery, and the \*(lqBcc:\*(rq field will be removed from the message sent to sighted recipients. The blind recipients will receive an entirely new message with a minimal set of headers. Included in the body of the message will be a copy of the message sent to the sighted recipients. .PP If a \*(lqDcc:\*(rq field is encountered and the .B sendmail/pipe mail transport method is not in use, its addresses will be used for delivery, and the \*(lqDcc:\*(rq field will be removed from the message. The blind recipients will receive the same message sent to the sighted recipients. *WARNING* Recipients listed in the \*(lqDcc:\*(rq field receive no explicit indication that they have received a \*(lqblind copy\*(rq. This can cause blind recipients to inadvertently reply to all of the sighted recipients of the original message, revealing that they received a blind copy. On the other hand, since a normal reply to a message sent via a \*(lqBcc:\*(rq field will generate a reply only to the sender of the original message, it takes extra effort in most mailers to reply to the included message, and so would usually only be done deliberately, rather than by accident. .PP If .B \-filter .I filterfile is specified, then this copy is filtered (re-formatted) by .B mhl prior to being sent to the blind recipients. Alternately, if you specify the .B -mime switch, then .B send will use the MIME rules for encapsulation. .PP Prior to sending the message, the \*(lqDate:\ now\*(rq field will be appended to the headers in the message. If .B \-msgid is specified, then a \*(lqMessage\-ID:\*(rq field will also be added to the message. .PP The .B \-messageid switch selects the style used for the part appearing after the @ in \*(lqMessage\-ID:\*(rq, \*(lqResent\-Message\-ID:\*(rq, and \*(lqContent\-ID:\*(rq header fields. The two acceptable options are .B localname (which is the default), and .BR random . With .BR localname , the local hostname is used. With .BR random , a random sequence of characters is used instead. Note that the .B \-msgid switch must be enabled for this switch to have any effect. .PP If .B send is re-distributing a message (when invoked by .BR dist ), then \*(lqResent\-\*(rq will be prepended to each of these fields: \*(lqFrom:\*(rq, \*(lqDate:\*(rq, and \*(lqMessage\-ID:\*(rq. .PP A \*(lqFrom:\*(rq field is required for all outgoing messages. Multiple addresses are permitted in the \*(lqFrom:\*(rq field, but a \*(lqSender:\*(rq field is required in this case. Otherwise a \*(lqSender:\*(rq field is optional. .PP If a message with multiple \*(lqFrom:\*(rq addresses does .I not include a \*(lqSender:\*(rq field but does include an \*(lqEnvelope\-From:\*(rq field, the \*(lqEnvelope\-From:\*(rq field will be used to construct a \*(lqSender:\*(rq field. .PP When using SMTP for mail submission, the envelope-from used for the SMTP transaction is derived from the \*(lqEnvelope\-From:\*(rq field. If no \*(lqEnvelope\-From:\*(rq field is present, the \*(lqSender:\*(rq field is used. If neither the \*(lqEnvelope\-From:\*(rq nor the \*(lqSender:\*(rq field is present, the \*(lqFrom:\*(rq field is used. When \*(lqEnvelope\-From:\*(rq appears in a message it will be removed from the final outgoing message. .PP By using the .B \-format switch, each of the entries in the \*(lqTo:\*(rq and \*(lqcc:\*(rq fields will be replaced with \*(lqstandard\*(rq format entries. This standard format is designed to be usable by all of the message handlers on the various systems around the Internet. If .B \-noformat is given, then headers are output exactly as they appear in the message draft. .PP If an \*(lqFcc:\ folder\*(rq is encountered, the message will be copied to the specified folder for the sender in the format in which it will appear to any non\-Bcc receivers of the message. That is, it will have the appended fields and field reformatting. The \*(lqFcc:\*(rq fields will be removed from all outgoing copies of the message. .PP Beware that if an \*(lqFcc:\*(rq with one or more folders is present but none of the folders exist, and the default .I fileproc and .I postproc are in use, then .B refile will prompt the user to create the folder(s) if .B \-push is not specified. If all responses are negative, or creation of each folder fails, or .B \-push is specified, the message will not be copied to any folder and will be removed by .BR post. With the default .B refile switches, the message draft will be renamed according to the specification of its .B \-nolink switch. .PP By using the .B \-width .I columns switch, the user can direct .B send as to how long it should make header lines containing addresses. .PP The mail transport system default is provided in .I %nmhetcdir%/mts.conf but can be overridden here with the .B \-mts switch. .PP If nmh is using as its mail transport system .BR sendmail/pipe , the .B \-sendmail switch can be used to override the default .B sendmail program. .PP If nmh is using the SMTP MTA, the .B \-server and the .B \-port switches can be used to override the default mail server (defined by the .I %nmhetcdir%/mts.conf .RI servers entry). The .B \-snoop switch can be used to view the SMTP transaction. (Beware that the SMTP transaction may contain authentication information either in plaintext or easily decoded base64.) If .B \-sasl \-saslmech xoauth2 is used, the HTTP transaction is also shown. .PP If .B nmh has been compiled with SASL support, the .B \-sasl and .B \-nosasl switches will enable and disable the use of SASL authentication with the SMTP MTA. Depending on the SASL mechanism used, this may require an additional password prompt from the user (but the .I netrc file can be used to store this password, as described in the mh-profile(5) man page). The .B \-saslmech switch can be used to select a particular SASL mechanism, and the .B \-user switch can be used to select a authorization userid to provide to SASL other than the default. The credentials profile entry in the mh\-profile(5) man page describes the ways to supply a username and password. .PP If SASL authentication is successful, .BR nmh will attempt to negotiate a security layer for session encryption. Encrypted data is labelled with `(encrypted)' and `(decrypted)' when viewing the SMTP transaction with the .B \-snoop switch; see the .B post man page description of .B \-snoop for its other features. .PP If .B nmh has been compiled with OAuth support, the .B \-sasl and .B \-saslmech xoauth2 switches will enable OAuth authentication. The .B \-user switch must be used, and the .I username must be an email address the user has for the service, which must be specified with the .B \-authservice .I service switch. Before using OAuth authentication, the user must authorize nmh by running .B mhlogin and grant authorization to that account. See the .IR mhlogin (1) man page for more details. .PP If .B nmh has been compiled with TLS support, the .B \-tls and .B \-initialtls switches will require the negotiation of TLS when connecting to the SMTP MTA. The .B \-tls switch will negotiate TLS as part of the normal SMTP protocol using the STARTTLS command. The .B \-initialtls will negotiate TLS immediately after the connection has taken place, before any SMTP commands are sent or received. Encrypted data is labelled with `(tls-encrypted)' and `(tls-decrypted)' when viewing the SMTP transaction with the .B \-snoop switch; see the .B post man page description of .B \-snoop for its other features. The .B \-notls switch will disable all attempts to negotiate TLS. .PP If port 465 is specified and none of the TLS switches were enabled, .B \-initialtls will be implied if TLS support was compiled in. Though port 465 for SMTPS (SMTP over SSL) was deregistered by IANA in 1998, it is still used for that service. .PP When using TLS the default is to verify the remote certificate and SubjectName against the local trusted certificate store. This can be controlled by the .B \-certverify and .B \-nocertverify switches. See your OpenSSL documentation for more information on certificate verification. .PP The files specified by the profile entry \*(lqAliasfile:\*(rq and any additional alias files given by the .B \-alias .I aliasfile switch will be read (more than one file, each preceded by .BR \-alias , can be named). See .IR mh\-alias (5) for more information. .SS Selection based on sender address: sendfrom One or more .I sendfrom profile components can be used to select a mail server address, mail server port, or any other switch that can be supplied to .BR post . It works by first looking at the sender address and domain name in the message draft, as described below. It then looks for a corresponding profile entry, which contains the .B post switches. To enable, add profile entries of the form: .PP .RS 5 .RI sendfrom- "address/domain name" : " post switches" .RE .PP The email address is extracted from the Envelope-From: header, if not blank, the Sender: header, or the From: header line in the message draft. Multiple profile entries, with different email addresses or domain names, are supported. This allows different switches to .BR post , such as -user, to be associated with different email addresses. If a domain name is used, it matches all users in that domain. .PP Here is an example profile entry using OAuth for an account hosted by gmail: .PP .nf .RS 5 sendfrom-gmail_address@example.com: -sasl -saslmech xoauth2 .RS 5 -authservice gmail -tls -server smtp.gmail.com -user gmail_login@example.com .RE .RE .fi .PP (Indentation indicates a continued line, as supported in MH profiles.) The username need not be the same as the sender address, which was extracted from the appropriate header line as noted above. .PP Here are example profile entries that use an nmh credentials file: .PP .nf .RS 5 credentials: file:nmhcreds sendfrom-sendgrid_address@example.com: -sasl -tls .RS 5 -server smtp.sendgrid.net .RE sendfrom-outbound.att.net: -sasl -initialtls .RS 5 -server outbound.att.net -port 465 .RE sendfrom-fastmail.com: -initialtls -sasl -saslmech LOGIN .RS 5 -server smtps-proxy.messagingengine.com -port 80 .RE .RE .fi .PP where nmhcreds is in the user's nmh directory (from the Path profile component) and contains: .PP .nf .RS 5 machine smtp.sendgrid.net .RS 5 login sendgrid_login@example.com password ******** .RE machine outbound.att.net .RS 5 login att_login@example.com password ******** .RE machine smtps-proxy.messagingengine.com .RS 5 login fastmail_login@example.com password ******** .RE .RE .fi .PP For more information on authentication to mail servers, see the .IR mhlogin (1) man page for OAuth services, and .IR mh-profile (5) man page for login credentials. .PP .SH FILES .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^$HOME/.mh_profile~^The user profile .fi .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u ^Path:~^To determine the user's nmh directory ^Draft\-Folder:~^To find the default draft-folder ^Aliasfile:~^For a default alias file ^Signature:~^To determine the user's mail signature ^mailproc:~^Program to post failure notices ^postproc:~^Program to post the message ^sendfrom-address:~^Switches to post for sender address ^sendfrom-domain:~^Switches to post for sender domain name .fi .SH "SEE ALSO" .IR comp (1), .IR dist (1), .IR file (1), .IR forw (1), .IR mhbuild (1), .IR mhparam (1), .IR mhlogin (1), .IR refile (1), .IR repl (1), .IR whatnow (1), .IR mh\-alias (5), .IR mh\-profile (5), .IR mh\-tailor (5), .IR post (8) .SH DEFAULTS .nf .RB ` file "' defaults to /draft" .RB ` \-alias "' defaults to %nmhetcdir%/MailAliases" .RB ` \-nodraftfolder ' .RB ` \-nofilter ' .RB ` \-format ' .RB ` \-forward ' .RB ` \-nomime ' .RB ` \-nomsgid ' .RB ` "\-messageid\ localname" ' .RB ` \-nopush ' .RB ` \-noverbose ' .RB ` \-nowatch ' .RB ` "\-width\ 72" ' .RB ` \-certverify ' .fi .SH CONTEXT None .SH BUGS Under some configurations, it is not possible to monitor the mail delivery transaction; .B \-watch is a no-op on those systems. .PP Using .B \-split .I 0 doesn't work correctly. nmh-1.7.1-RC3/man/sendfiles.man000644 007761 000024 00000011432 13243042053 016203 0ustar00kenhstaff000000 000000 .TH SENDFILES %manext1% 2012-11-14 "%nmhversion%" . .\" %nmhwarning% . .SH NAME sendfiles \- send multiple files by MIME message with nmh .SH SYNOPSIS .HP 5 .na .B sendfiles .RB [ \-help ] .RB [ \-version ] .RB [ -compress .IR bzip2 " | " compress " | " gzip " | " lzma " | " none ] .br .RB [ \-from .IR sender ] .RI [ "\-delay n" " | " \-n ] .br .B \-to .I recipient .B \-subject .IR subject " | " .I recipient .I subject .br .I file/directory1 .RI [ file/directory2 \&...] .ad .SH DESCRIPTION The shell script .BR sendfiles is used to send a collection of files and directories via electronic mail. .PP .B sendfiles will archive the files and directories you name with the .B tar command, and then mail the compressed archive to the \*(lqrecipient\*(rq with the given \*(lqsubject\*(rq. The archive will be automatically split up into as many messages as necessary in order to get past most mailers. .PP The .B \-to switch specifies the recipient. The .B \-subject switch specifies the subject. Alternatively, these two required values can be provided without their corresponding switch names. .PP The .B \-from switch can, and should, be used to specify the sender's mailbox (name and email address). Alternatively, the .B PERSON environment variable can be used for the same purpose. If neither is used, .B sendfiles will supply a \*(lqFrom:\*(rq header field using the sender's local mailbox, see .I localmbox in .IR mh-format (5). .PP The .B \-compress command line switch can be used to override the run-time determination of the compression program by .BR sendfiles . .B \-compress .I none (alternatively, .BR \-none ) disables compression. .PP Sometimes you want .B sendfiles to pause after posting a partial message. This is usually the case when you are running .B sendmail and expect to generate a lot of partial messages. The .B \-delay switch specifies the number of seconds to pause in between postings, e.g., .PP .RS 5 sendfiles -delay 30 -to recipient -subject \*(lqsubject\*(rq files\0... .RE .PP will pause 30 seconds in between each posting. An alternate form of the switch with just the delay time, .BR \-30 , for example, is also supported. .PP .SS "Extracting the Received Files" When these messages are received, invoke .B mhstore once for the list of messages. The default is for .B mhstore to store the combined parts as a new message in the current folder, although this can be changed using storage formatting strings. You can then use .B mhlist to find out what's inside; possibly followed by .B mhstore again to write the archive to a file where you can subsequently uncompress and untar it. For instance: .PP .RS 5 .nf % mhlist 5-8 msg part type/subtype size description 5 message/partial 47K part 1 of 4 6 message/partial 47K part 2 of 4 7 message/partial 47K part 3 of 4 8 message/partial 18K part 4 of 4 % mhstore 5-8 reassembling partials 5,6,7,8 to folder inbox as message 9 % mhlist -verbose 9 msg part type/subtype size description 9 application/octet-stream 118K (extract with uncompress | tar xvpf -) type=tar conversions=compress % mhstore 9 % uncompress < 9.tar.Z | tar xvpf - .fi .RE .PP Alternately, by using the .B \-auto switch, .B mhstore will automatically do the extraction for you: .PP .RS 5 .nf % mhlist 5-8 msg part type/subtype size description 5 message/partial 47K part 1 of 4 6 message/partial 47K part 2 of 4 7 message/partial 47K part 3 of 4 8 message/partial 18K part 4 of 4 % mhstore 5-8 reassembling partials 5,6,7,8 to folder inbox as message 9 % mhlist -verbose 9 msg part type/subtype size description 9 application/octet-stream 118K (extract with uncompress | tar xvpf -) type=tar conversions=compress % mhstore -auto 9 -- tar listing appears here as files are extracted .fi .RE .PP As the second .B tar listing is generated, the files are extracted. A prudent user will never put .B \-auto in the .I \&.mh_profile file. The correct procedure is to first use .B mhlist to find out what will be extracted. Then .B mhstore can be invoked with .B \-auto to perform the extraction. .SH FILES .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^$HOME/.mh_profile~^The user profile .fi .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u ^Path:~^To determine the user's nmh directory ^Current\-Folder:~^To find the default current folder .fi .SH "SEE ALSO" .IR mhbuild (1), .IR mhlist (1), .IR mhshow (1), .IR mhstore (1), .IR mh-format (5) .PP .I "Proposed Standard for Message Encapsulation" (RFC 934) .SH DEFAULTS .nf .RB ` "\-delay\ 0" ' .RB ` "\-from localmbox" ' .fi .SH CONTEXT None nmh-1.7.1-RC3/man/show.man000644 007761 000024 00000014357 13243042053 015220 0ustar00kenhstaff000000 000000 .TH SHOW %manext1% 2016-03-24 "%nmhversion%" . .\" %nmhwarning% . .SH NAME show \- display nmh messages .SH SYNOPSIS .HP 5 .na .B show .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RI [ msgs ] .RB [ \-draft ] .RB [\-showproc .IR program ] .RB [ \-showmimeproc .IR program ] .RB [ \-header " | " \-noheader ] .RB [ \-checkmime " | " \-nocheckmime ] .RB [ \-concat " | " \-noconcat ] [switches\ for .I showproc or .IR showmimeproc ] .ad .SH DESCRIPTION .B show lists each of the specified messages to the standard output (typically, the terminal). .PP By default, text (non-MIME) messages are filtered and displayed by the .B nmh command .BR mhl . This command will display text messages in a nice, uniform format. It also allows you to configure the format of the displayed messages and which headers fields are shown. See the .IR mhl (1) manual page for the details about this command. This default can be changed by defining the .I showproc profile component. Any switches not recognized by .BR show , as well as .B \-header and .BR \-noheader , are passed along to that program. To override the default and the .I showproc profile component, use the .B \-showproc .I program switch. For example, .B \-showproc .I more will cause the .B more program to list the messages with no reformatting. Normally, this program is specified as the .I showproc in the user's .IR \&.mh_profile , rather than using a command line switch. .PP By default, non-text messages (MIME messages with multi-media contents) are processed and displayed by the .B nmh command .BR mhshow . See the .IR mhshow (1) manual page for details about this command. This default can changed by defining the .I showmimeproc profile component. Any switches not recognized by .B show are passed along to that program. To override this default and the .B showmimeproc profile component, use the .B \-showmimeproc .I program switch. .PP Note that in some cases, .B show may invoke the .I showmimeproc even for textual contents. This will happen for text messages that specify a transfer encoding (such as MIME quoted-printable or base64) or specify a character set that .B show doesn't believe can be displayed natively. The appropriate .IR locale (1) environment variables should be set to the terminal's native character set to avoid gratuitous invocations of the .IR showmimeproc . See the .IR locale (1) man page for details about these environment variables. .PP The option .B \-checkmime (set by default) instructs .B show to test if any of the messages to be displayed are non-text (MIME) messages. If any are non-text, they are displayed by the program .IR showmimeproc , else they are displayed by the program .IR showproc . The option .B \-nocheckmime disables this test and instructs .B show to use .IR showproc , regardless of whether any of the messages are non-text (MIME) messages. .P The .B \-noshowproc switch will disable any formatting or paging of messages. It is equivalent to .B \-nocheckmime .B \-showproc .IR cat . It is still accepted, but should be considered (somewhat) obsolete. .PP The .B \-header switch tells .B show to display a one-line description of the message being shown. This description includes the folder and the message number. .PP By default .B show will concatenate all content under one pager. If you want each part to displayed separately, you can override the default behavior with .B \-noconcat. .PP If no `msgs' are specified, the current message is used. Although it depends on the specific .I showproc or .IR showmimeproc , in the default setup when more than one message is specified, you will be prompted for a prior to listing each message. Each message will be listed a page at a time, and when the end of page is reached, the program will wait for a or . If a is entered, it will print the next line, whereas will print the next screenful. .PP If the standard output is not a terminal, no queries are made, and each file is listed with a one-line header and two lines of separation. .PP .RB \*(lq "show \-draft" \*(rq will list the file /draft if it exists. .PP If the profile entry \*(lqUnseen\-Sequence\*(rq is present and non-empty, then .B show will remove each of the messages shown from each sequence named by the profile entry. .SH FILES .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^$HOME/.mh_profile~^The user profile .fi .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u ^Path:~^To determine the user's nmh directory ^Current\-Folder:~^To find the default current folder ^Unseen\-Sequence:~^To name sequences denoting unseen messages ^showproc:~^Program to show text (non-MIME) messages ^showmimeproc:~^Program to show non-text (MIME) messages .fi .SH "SEE ALSO" .IR mhl (1), .IR mhshow (1), .IR next (1), .IR prev (1), .IR scan (1) .SH DEFAULTS .nf .RB ` +folder "' defaults to the current folder" .RB ` msgs "' defaults to cur" .RB ` \-checkmime ' .RB ` \-header ' .RB ` \-concat ' .fi .SH CONTEXT If a folder is given, it will become the current folder. The last message selected will become the current message. .SH BUGS The .B \-header switch doesn't work when `msgs' expands to more than one message. If the .I showproc is .BR mhl , then this problem can be circumvented by referencing the \*(lqmessagename\*(rq field in the .B mhl format file. .PP .B show updates the user's context before showing the message. Hence .B show will mark messages as seen prior to the user actually seeing them. This is generally not a problem, unless the user relies on the \*(lqunseen\*(rq messages mechanism, and interrupts .B show while it is showing \*(lqunseen\*(rq messages. .PP If your .I showproc is .B mhl (the default), then .B show uses a built-in .BR mhl : it does not actually run the .B mhl program. Hence, if you define your own .BR showproc , don't call it .B mhl since .B show won't run it. .PP If your .I showproc is the pager .BR more , then avoid running .B show in the background with only its standard output piped to another process, as in .PP .RS 5 show | imprint & .RE .PP Due to a bug in .BR more , show will go into a \*(lqtty input\*(rq state. To avoid this problem, re-direct .BR show 's diagnostic output as well. For users of .BR csh : .PP .RS 5 show |& imprint & .RE .PP For users of .BR sh : .PP .RS 5 show 2>&1 | imprint & .RE nmh-1.7.1-RC3/man/slocal.man000644 007761 000024 00000027206 13243042053 015512 0ustar00kenhstaff000000 000000 .TH SLOCAL %manext1% 2016-05-02 "%nmhversion%" . .\" %nmhwarning% . .SH NAME slocal \- asynchronously filter and deliver new mail to nmh .SH SYNOPSIS .HP 5 .na .B %nmhlibexecdir%/slocal .RB [ \-help ] .RB [ \-version ] .RB [ \-addr .IR address ] .RB [ \-info .IR data ] .RB [ \-sender .IR sender ] .RB [ \-user .IR username ] .RB [ \-mailbox .IR mbox ] .\" \%[\-home\ homedir] .RB [ \-file .IR file ] .RB [ \-maildelivery .IR deliveryfile ] .RB [ \-verbose " | " \-noverbose ] .RB [ \-suppressdup " | " \-nosuppressdup ] .RB [ \-debug ] .ad .SH DESCRIPTION .B slocal is a program designed to allow you to have your inbound mail processed according to a complex set of selection criteria. You do not normally invoke .B slocal yourself, rather .B slocal is invoked on your behalf by your system's Message Transfer Agent (such as .BR sendmail ) when the message arrives. .PP The message selection criteria used by .B slocal is specified in the file .RI \*(lq .maildelivery \*(rq in the user's home directory. You can specify an alternate file with the .B \-maildelivery .I file option. The syntax of this file is specified below. .PP The message delivery address and message sender are determined from the Message Transfer Agent envelope information, if possible. Under .BR sendmail , the sender will obtained from the UUCP \*(lqFrom:\*(rq line, if present. The user may override these values with the .B \-addr and .B \-sender switches. .PP The message is normally read from the standard input. The .B \-file switch sets the name of the file from which the message should be read, instead of reading stdin. This is useful when debugging a .RI \*(lq .maildelivery \*(rq file. .PP The .B \-user switch tells .B slocal the name of the user for whom it is delivering mail. It must exist on the local system. The .B \-mailbox switch tells .B slocal the name of the user's mail drop file. .PP .B slocal is able to detect and suppress duplicate messages. To enable this, use the option .BR \-suppressdup . .B slocal will keep a database containing the Message-ID's of incoming messages, in order to detect duplicates. Depending on your configuration, this database will be in either ndbm or Berkeley db format. .PP The .B \-info switch may be used to pass an arbitrary argument to sub-processes which .B slocal may invoke on your behalf. .PP The .B \-verbose switch causes .B slocal to give information on stdout about its progress. The .B \-debug switch produces more verbose debugging output on stderr. These flags are useful when creating and debugging your .RI \*(lq .maildelivery \*(rq file, as they allow you to see the decisions and actions that .B slocal is taking, as well as check for syntax errors in your .RI \*(lq .maildelivery \*(rq file. .SS "Message Transfer Agents" Most modern MTAs including .BR sendmail , .BR postfix and .BR exim support a \&.forward file for directing incoming mail. You should include the line .PP .ce \*(lq|\ %nmhlibexecdir%/slocal\ \-user\ username\*(rq .PP in your \&.forward file in your home directory. This will cause your MTA to invoke .B slocal on your behalf when a message arrives. .SS "The Maildelivery File" The .RI \*(lq .maildelivery \*(rq file controls how .B slocal filters and delivers incoming mail. Each line of this file consists of five fields, separated by whitespace or comma. Since double-quotes are honored, these characters may be included in a single argument by enclosing the entire argument in double-quotes. A double-quote can be included by preceding it with a backslash. Lines beginning with `#' and blank lines are ignored. .PP The format of each line in the .RI \*(lq .maildelivery \*(rq file is: .PP .RS 5 .B "header pattern action result string" .RE .PP .BR header : .RS 5 The name of a header field (such as To, Cc, or From) that is to be searched for a pattern. This is any field in the headers of the message that might be present. .PP The following special fields are also defined: .TP \w'defaultrrr'u .I source the out-of-band sender information .TP \w'defaultrrr'u .I addr the address that was used to cause delivery to the recipient .TP \w'defaultrrr'u .I default this matches .I only if the message hasn't been delivered yet .TP \w'defaultrrr'u .I * this always matches .RE .PP .BR pattern : .RS 5 The sequence of characters to match in the specified header field. Matching is case-insensitive, but does not use regular expressions. .RE .PP .BR action : .RS 5 The action to take to deliver the message. When a message is delivered, a \*(lqDelivery\-Date:\ date\*(rq header is added which indicates the date and time that message was delivered. .TP 4 .I destroy This action always succeeds. .TP 4 .IR file ", " mbox ", or " > Append the message to the file named by .IR string . The message is appended to the file in mbox (uucp) format. This is the format used by most other mail clients (such as mailx, elm). If the message can be appended to the file, then this action succeeds. .TP 4 .I mmdf Identical to .IR file , but always appends the message using the MMDF mailbox format. .TP 4 .IR pipe " or " | Pipe the message as the standard input to the command named by .IR string , using the Bourne shell .B sh to interpret the string. Prior to giving the string to the shell, it is expanded with the following built-in variables: .RS .TP \w'zzreplyztozaaa'u $(sender) the out-of-band sender information .TP \w'zzreplyztozaaa'u $(address) the address that was used to cause delivery to the recipient .TP \w'zzreplyztozaaa'u $(size) the size of the message in bytes .TP \w'zzreplyztozaaa'u $(reply\-to) either the \*(lqReply\-To:\*(rq or \*(lqFrom:\*(rq field of the message .TP \w'zzreplyztozaaa'u $(info) the out-of-band information specified .RE .TP 4 .IR qpipe " or " ^ Similar to .IR pipe , but executes the command directly, after built-in variable expansion, without assistance from the shell. This action can be used to avoid quoting special characters which your shell might interpret. .TP 4 .IR folder " or " + Store the message in the .B nmh folder named by .IR string . Currently this is handled by piping the message to the .B nmh program .BR rcvstore , although this may change in the future. .RE .PP .BR result : .RS 5 Indicates how the action should be performed: .TP \w'Azzz'u .I A Perform the action. If the action succeeds, then the message is considered delivered. .TP \w'Azzz'u .I R Perform the action. Regardless of the outcome of the action, the message is not considered delivered. .TP \w'Azzz'u .I ? Perform the action only if the message has not been delivered. If the action succeeds, then the message is considered delivered. .TP \w'Azzz'u .I N Perform the action only if the message has not been delivered and the previous action succeeded. If this action succeeds, then the message is considered delivered. .PP The delivery file is always read completely, so that several matches can be made and several actions can be taken. .RE .SS "Security of Delivery Files" In order to prevent security problems, the .RI \*(lq .maildelivery \*(rq file must be owned either by the user or by root, and must be writable only by the owner. If this is not the case, the file is not read. .PP If the .RI \*(lq .maildelivery \*(rq file cannot be found, or does not perform an action which delivers the message, then .B slocal will check for a global delivery file at .IR %nmhetcdir%/maildelivery . This file is read according to the same rules. This file must be owned by root and must be writable only by root. .PP If a global delivery file cannot be found or does not perform an action which delivers the message, then standard delivery to the user's mail drop is performed. .SS "Example Delivery File" To summarize, here's an example delivery file: .PP .nf .ta \w'default 'u +\w'mh-workersxx 'uC +\w'destroy 'uC +\w'result 'u # # .maildelivery file for nmh's slocal # # Blank lines and lines beginning with a '#' are ignored # # FIELD PATTERN ACTION RESULT STRING # # File mail with foobar in the \*(lqTo:\*(rq line into file foobar.log To foobar file A foobar.log # Pipe messages from coleman to the program message-archive From coleman pipe A /bin/message-archive # Anything to the \*(lqnmh-workers\*(rq mailing list is put in # its own folder, if not filed already To nmh-workers folder ? nmh-workers # Anything with Unix in the subject is put into # the file unix-mail Subject unix file A unix-mail # I don't want to read mail from Steve, so destroy it From steve destroy A \- # Put anything not matched yet into mailbox default \- file ? mailbox # always run rcvtty * \- pipe R %nmhlibexecdir%/rcvtty .fi .SS "Sub-process environment" When a process is invoked, its environment is: the user/group-ids are set to recipient's ids; the working directory is the recipient's home directory; the umask is 0077; the process has no /dev/tty; the standard input is set to the message; the standard output and diagnostic output are set to /dev/null; all other file-descriptors are closed; the environment variables .BR $USER , .BR $HOME , .B $SHELL are set appropriately, and no other environment variables exist. .PP The process is given a certain amount of time to execute. If the process does not exit within this limit, the process will be terminated with extreme prejudice. The amount of time is calculated as ((size / 60) + 300) seconds, where size is the number of bytes in the message (with 30 minutes the maximum time allowed). .PP The exit status of the process is consulted in determining the success of the action. An exit status of zero means that the action succeeded. Any other exit status (or abnormal termination) means that the action failed. .PP In order to avoid any time limitations, you might implement a process that began by .IR fork ()-ing. The parent would return the appropriate value immediately, and the child could continue on, doing whatever it wanted for as long as it wanted. This approach is somewhat risky if the parent is going to return an exit status of zero. If the parent is going to return a non-zero exit status, then this approach can lead to quicker delivery into your mail drop. .SH FILES .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^%nmhetcdir%/mts.conf~^nmh mts configuration file ^$HOME/.maildelivery~^The file controlling local delivery ^%nmhetcdir%/maildelivery~^Rather than the standard file ^%mailspool%/$USER~^The default mail drop .fi .SH "SEE ALSO" .IR rcvdist (1), .IR rcvpack (1), .IR rcvstore (1), .IR rcvtty (1), .IR mh\-format (5) .SH DEFAULTS .nf .RB ` \-noverbose ' .RB ` \-nosuppressdup ' .RB ` \-maildelivery "' defaults to $HOME/.maildelivery" .RB ` \-mailbox "' defaults to %mailspool%/$USER" .RB ` \-file "' defaults to stdin" .RB ` \-addr "' defaults to the current user" .RB ` \-user "' defaults to the current user" .fi .PP .B \-addr and .B \-user will be set the the user part of the Local-Mailbox profile entry, if set. .SH CONTEXT None .SH HISTORY .B slocal was originally designed to be backward-compatible with the .B maildelivery facility provided by .BR MMDF-II . Thus, the .RI \*(lq .maildelivery \*(rq file syntax is somewhat limited. But .B slocal has been modified and extended, so that is it no longer compatible with .BR MMDF-II . .PP In addition to an exit status of zero, the .B MMDF values .B RP_MOK (32) and .B RP_OK (9) mean that the message has been fully delivered. Any other non-zero exit status, including abnormal termination, is interpreted as the .B MMDF value .B RP_MECH (200), which means \*(lquse an alternate route\*(rq (deliver the message to the mail drop). .SH BUGS Only two return codes are meaningful, others should be. .PP .B slocal was originally designed to be backwards-compatible with the .B maildelivery functionality provided by .BR MMDF-II . nmh-1.7.1-RC3/man/sortm.man000644 007761 000024 00000010400 13205305704 015370 0ustar00kenhstaff000000 000000 .TH SORTM %manext1% 2014-03-23 "%nmhversion%" . .\" %nmhwarning% . .SH NAME sortm \- sort nmh messages .SH SYNOPSIS .HP 5 .na .B sortm .RB [ \-help ] .RB [ \-version ] .RI [ +folder ] .RI [ msgs ] .RB [ \-all " | " \-noall ] .RB [ \-datefield .IR field ] .RB [ \-textfield .IR field ] .RB [ \-notextfield ] .RB [ \-limit .IR days ] .RB [ \-nolimit ] .RB [ \-check " | " \-nocheck ] .RB [ \-verbose " | " \-noverbose ] .ad .SH DESCRIPTION .B sortm sorts the specified messages in the named folder according to the chronological order of the \*(lqDate:\*(rq field of each message. .PP If no messages are specified, the default is all messages in the folder. However, if no messages are specified and the .B \-noall switch is enabled, then .B sortm reports that as an error and exits with non-zero status. .B \-noall is most useful in the user's profile, to avoid inadvertent sorting of an entire folder. The .B \-all switch can then be used on the command line to disable it. Of course, a message specification of .I all can be used in any case. .PP The .B \-verbose switch directs .B sortm to tell the user the general actions that it is taking to place the folder in sorted order. .PP The .B \-datefield .I field switch tells .B sortm the name of the field to use when making the date comparison. If the user has a special field in each message, such as \*(lqBB\-Posted:\*(rq or \*(lqDelivery\-Date:\*(rq, then the .B \-datefield switch can be used to direct .B sortm which field to examine. .PP The .B \-textfield .I field switch causes .B sortm to sort messages by the specified text field. All characters except letters and numbers are stripped and the resulting strings are sorted datefield-major, textfield-minor, using a case insensitive comparison. If this field is \*(lqsubject\*(rq, any leading "re:" is stripped off. .PP With .B \-textfield .IR field , if .B \-limit .I days is specified, messages with the same textfields that are dated within `days' of each other appear together. Specifying .B \-nolimit makes the limit infinity. With .B \-limit .IR 0 , the sort is instead simply textfield-major. .PP For example, to order a folder by date-major, grouping messages with the same subject on the same date together, use: .PP .RS 5 sortm -textfield subject +folder .RE .PP .B sortm always issues a warning for each message that is missing a \*(lqDate:\*(rq field, has a \*(lqDate:\*(rq field that cannot be parsed, or has a format error in any header field. With the .B \-check switch, .B sortm inhibits all modifications to the folder if there are any such messages, and exits with non-zero status. With the default of .BR \-nocheck , .B sortm sorts messages with a missing or invalid \*(lqDate:\*(rq field using their file modification times. .PP When ordering messages based on their dates, if they have the same dates, their original message order is preserved. .SH FILES .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^$HOME/.mh_profile~^The user profile .fi .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u ^Path:~^To determine the user's nmh directory ^Current\-Folder:~^To find the default current folder .fi .SH "SEE ALSO" .IR folder (1) .SH DEFAULTS .nf .RB ` +folder "' defaults to the current folder" .RB ` msgs"' defaults to all without -noall, no default with -noall" .RB ` \-all ' .RB ` \-datefield "' defaults to date" .RB ` \-notextfield ' .RB ` \-noverbose ' .RB ` \-nolimit ' .RB ` \-nocheck ' .fi .SH CONTEXT If a folder is given, it will become the current folder. If the current message is moved, .B sortm will preserve its status as current. .SH HISTORY Timezones used to be ignored when comparing dates: they aren't any more. .PP Messages which were in the folder, but not specified by `msgs', used to be moved to the end of the folder; now such messages are left untouched. .PP .B sortm sometimes did not preserve the message numbering in a folder (e.g., messages 1, 3, and 5, might have been renumbered to 1, 2, 3 after sorting). This was a bug, and has been fixed. To compress the message numbering in a folder, use .RB \*(lq "folder\ \-pack" \*(rq as always. .SH BUGS When .B sortm complains about a message which it can't temporally order, it complains about the message number .I prior to sorting. It should indicate what the message number will be .B after sorting. nmh-1.7.1-RC3/man/unseen.man000644 007761 000024 00000000017 11732520432 015524 0ustar00kenhstaff000000 000000 .so man1/new.1 nmh-1.7.1-RC3/man/whatnow.man000644 007761 000024 00000013756 13243042053 015731 0ustar00kenhstaff000000 000000 .TH WHATNOW %manext1% 2014-01-23 "%nmhversion%" . .\" %nmhwarning% . .SH NAME whatnow \- prompting front-end for writing nmh messages .SH SYNOPSIS .HP 5 .na .B whatnow .RB [ \-help ] .RB [ \-version ] .RB [ \-draftfolder .IR +folder ] .RB [ \-draftmessage .IR msg ] .RB [ \-nodraftfolder ] .RB [ \-editor .IR editor ] .RB [ \-noedit ] .RB [ \-prompt .IR string ] .RI [ file ] .ad .SH DESCRIPTION .B whatnow is the default program that queries the user about the disposition of a composed draft. It is normally automatically invoked by one of the .B nmh commands .BR comp , .BR dist , .BR forw , or .B repl after the initial edit. .PP When started, the editor is started on the draft (unless .B \-noedit is given, in which case the initial edit is suppressed). Then, .B whatnow repetitively prompts the user with \*(lqWhat now?\*(rq and awaits a response. The valid responses are: .PP .RS 5 .TP \w'refilezzzzfolderz'u .B edit re-edit using the same editor that was used on the preceding round unless a profile entry \*(lq\-next: \*(rq names an alternate editor .TP \w'refilezzzzfolderz'u \fBedit\fP \fIeditor\fP invoke .I editor for further editing .TP \w'refilezzzzfolderz'u \fBrefile\fP \fI+folder\fP refile the draft into the given folder .TP \w'refilezzzzfolderz'u .B mime process the draft as MIME composition file using the .I buildmimeproc command .RB ( mhbuild by default) .TP \w'refilezzzzfolderz'u .B display list the message being distributed/replied-to on the terminal .TP \w'refilezzzzfolderz'u .B list list the draft on the terminal .TP \w'refilezzzzfolderz'u .B send send the message .TP \w'refilezzzzfolderz'u .B send \-watch send the message and monitor the delivery process .TP \w'refilezzzzfolderz'u .B push send the message in the background .TP \w'refilezzzzfolderz'u .B whom list the addresses that the message will go to .TP \w'refilezzzzfolderz'u .B whom \-check list the addresses and verify that they are acceptable to the transport service .TP \w'refilezzzzfolderz'u .B quit preserve the draft and exit .TP \w'refilezzzzfolderz'u .B quit \-delete delete the draft and exit .TP \w'refilezzzzfolderz'u .B delete delete the draft and exit .TP \w'refilezzzzfolderz'u \fBcd\fP \fIdirectory\fP use .I directory when interpreting attachment file names .TP \w'refilezzzzfolderz'u .B pwd print the working directory for attachment files .TP \w'refilezzzzfolderz'u \fBls\fP [\fIls-options\fP\^] list files in the attachment working directory using the ls command .TP \w'refilezzzzfolderz'u \fBattach [-v]\fP \fIfiles\fP add the named files to the message as MIME attachments; -v displays the mhbuild directive that .IR send (1) will use .TP \w'refilezzzzfolderz'u .B alist [-ln] list the MIME attachments, either short, long [-l] or numbered [-n] .TP \w'refilezzzzfolderz'u \fBdetach [-n]\fP \fIfiles-or-numbers\fP remove MIME attachments, either by file name or by number with -n .RE .PP When entering your response, you need only type enough characters to uniquely identify the response. .PP For the .B edit response, any valid switch to the editor is valid. .PP For the .B send and .B push responses, any valid switch to .IR send (1) is valid (as .B push merely invokes .B send with the .B \-push option). .PP For the .B whom response, any valid switch to .IR whom (1) is valid. .PP For the .B refile response, any valid switch to the .I fileproc is valid. .PP For the .B display and .B list responses, any valid argument to the .I lproc is valid. If any non-switch arguments are present, then the pathname of the draft will be excluded from the argument list given to the .I lproc (this is useful for listing another .B nmh message). .PP See .IR mh\-profile (5) for further information about how editors are used by .BR nmh . It also discusses how environment variables can be used to direct .BR whatnow 's actions in complex ways. .PP The .B \-prompt .I string switch sets the prompting string for .BR whatnow . .PP The .B \-draftfolder .I +folder and .B \-draftmessage .I msg switches invoke the .B nmh draft folder facility. This is an advanced (and highly useful) feature. Consult the .IR mh-draft (5) man page for more information. .PP If your .B nmh was configured with readline enabled, you'll be able to use filename completion and other readline features at the prompt. These are particularly useful with the .BR cd , .BR ls , .BR attach , and .B detach commands for managing MIME attachments. .SH FILES .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^$HOME/.mh_profile~^The user profile ^/draft~^The draft file .fi .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u ^Path:~^To determine the user's nmh directory ^Draft\-Folder:~^To find the default draft-folder ^Editor:~^To override the default editor ^\-next:~^To name an editor to be used after exit ^~^from ^buildmimeproc:~^Program to translate MIME composition files ^fileproc:~^Program to refile the message ^lproc:~^Program to list the contents of a message ^sendproc:~^Program to use to send the message ^whomproc:~^Program to determine who a message would go to .fi .SH "SEE ALSO" .IR send (1), .IR whom (1) .SH DEFAULTS .nf .RB ` \-prompt "' defaults to \*(lqWhat\ Now?\ \*(rq" .fi .SH BUGS If the initial edit fails, .B whatnow deletes your draft (by renaming it with a site-dependent prefix (usually a comma); failure of a later edit preserves the draft. .PP If the .I buildmimeproc fails (returns a nonzero status), .B whatnow simply prints a \*(lqWhat now?\*(rq prompt. .B whatnow depends on the .I buildmimeproc to tell the user that something went wrong. .PP If .I whatnowproc is .BR whatnow , then .BR comp , .BR dist , .BR forw , and .B repl use a built-in .BR whatnow , and do not actually run the .B whatnow program. Hence, if you define your own .IR whatnowproc , don't call it .B whatnow since it won't be run. .PP If .I sendproc is .BR send , then .B whatnow uses a built-in .BR send , it does not actually run the .B send program. Hence, if you define your own .IR sendproc , don't call it .B send since .B whatnow won't run it. nmh-1.7.1-RC3/man/whom.man000644 007761 000024 00000010226 13243042053 015201 0ustar00kenhstaff000000 000000 .TH WHOM %manext1% 2016-09-23 "%nmhversion%" . .\" %nmhwarning% . .SH NAME whom \- show to whom an nmh message would be sent .SH SYNOPSIS .HP 5 .na .B whom .RB [ \-help ] .RB [ \-version ] .RB [ \-alias .IR aliasfile ] .RB [ \-check " | " \-nocheck ] .RB [ \-draftfolder .IR +folder ] .RB [ \-draftmessage .IR msg ] .RB [ \-nodraftfolder ] .RB [ \-mts .IR smtp " | " sendmail/smtp " | " sendmail/pipe ] .RB [ \-server .IR servername ] .RB [ \-port .IR port-name/number ] .RB [ \-sasl ] .RB [ \-saslmech .IR mechanism ] .RB [ \-snoop ] .RB [ \-user .IR username ] .RB [ \-tls ] .RB [ \-initialtls ] .RB [ \-notls ] .RI [ file ] .RB [ \-draft ] .ad .SH DESCRIPTION .B whom is used to expand the headers of a message into a set of addresses and optionally verify that those addresses are deliverable at that time (if .B \-check is given). .PP The .B \-draftfolder .I +folder and .B \-draftmessage .I msg switches invoke the .B nmh draft folder facility. This is an advanced (and highly useful) feature. Consult the .IR mh-draft (5) man page for more information. .PP The mail transport system default is provided in .I %nmhetcdir%/mts.conf but can be overridden here with the .B \-mts switch. .PP If nmh is using the SMTP MTA, the .B \-server and the .B \-port switches can be used to override the default mail server (defined by the .I %nmhetcdir%/mts.conf .RI servers entry). The .B \-snoop switch can be used to view the SMTP transaction. (Beware that the SMTP transaction may contain authentication information either in plaintext or easily decoded base64.) .PP If .B nmh has been compiled with SASL support, the .B \-sasl switch will enable the use of SASL authentication with the SMTP MTA. Depending on the SASL mechanism used, this may require an additional password prompt from the user (but the .I netrc file can be used to store this password, as described in the mh-profile(5) man page). The .B \-saslmech switch can be used to select a particular SASL mechanism, and the .B \-user switch can be used to select a authorization userid to provide to SASL other than the default. The credentials profile entry in the mh\-profile(5) man page describes the ways to supply a username and password. .PP If SASL authentication is successful, .BR nmh will attempt to negotiate a security layer for session encryption. Encrypted data is labelled with `(encrypted)' and `(decrypted)' when viewing the SMTP transaction with the .B \-snoop switch; see the .B post man page description of .B \-snoop for its other features. .PP If .B nmh has been compiled with TLS support, the .BR \-tls , .BR \-initialtls , and .B \-notls switches will require and disable the negotiation of TLS support when connecting to the SMTP MTA. Encrypted data is labelled with `(tls-encrypted)' and `(tls-decrypted)' when viewing the SMTP transaction with the .B \-snoop switch; see the .B post man page description of .B \-snoop and the TLS flags for more details. .PP The files specified by the profile entry \*(lqAliasfile:\*(rq and any additional alias files given by the .B \-alias .I aliasfile switch will be read (more than one file, each preceded by .BR \-alias , can be named). See .IR mh\-alias (5) for more information. .SH FILES .fc ^ ~ .nf .ta \w'%nmhetcdir%/ExtraBigFileName 'u ^$HOME/.mh_profile~^The user profile .fi .SH "PROFILE COMPONENTS" .fc ^ ~ .nf .ta 2.4i .ta \w'ExtraBigProfileName 'u ^Path:~^To determine the user's nmh directory ^Draft\-Folder:~^To find the default draft-folder ^Aliasfile:~^For a default alias file ^postproc:~^Program to post the message .fi .SH "SEE ALSO" .IR mh\-alias (5), .IR mh\-profile (5), .IR post (8) .SH DEFAULTS .nf .RB ` file "' defaults to /draft" .RB ` \-nocheck ' .RB ` \-alias "' defaults to %nmhetcdir%/MailAliases" .fi .SH CONTEXT None .SH BUGS With the .B \-check option, .B whom makes no guarantees that the addresses listed as being ok are really deliverable, rather, an address being listed as ok means that at the time that .B whom was run the address was thought to be deliverable by the transport service. For local addresses, this is absolute; for network addresses, it means that the host is known; for uucp addresses, it (often) means that the .B UUCP network is available for use. nmh-1.7.1-RC3/m4/cppflags.m4000644 007761 000024 00000005070 13243042053 015341 0ustar00kenhstaff000000 000000 dnl This is intended to be extensible, by just adding candidate C preprocessor dnl options to be checked in the for loop. The first candidate is empty, in dnl case none are needed. Also, the test program can be readily augmented. dnl dnl On glibc we need to define at least the '_XOPEN_SOURCE' level of features, dnl or wchar.h doesn't declare a prototype for wcwidth(). But if we only define dnl that level then db.h won't compile. So we define _GNU_SOURCE which turns dnl on everything. Perhaps other OSes need some feature switch set to get dnl wcwidth() declared; if so they should have an entry added to this case dnl statement. NB that we must define this on the compiler command line, not dnl in config.h, because it must be set before any system header is included dnl and there's no portable way to make sure that files generated by lex dnl include config.h before system header files. dnl dnl Setting AM_CPPFLAGS directly is like DEFS, but doesn't get stomped on by dnl configure when using config.h. AC_DEFUN([NMH_ADDL_CPPFLAGS], [AC_CACHE_CHECK([platform-specific additional CPPFLAGS], [nmh_cv_addl_cppflags], [ dnl Turn warnings into errors. AC_LANG_WERROR nmh_saved_cppflags="$CPPFLAGS" dnl autoconf doesn't look at AM_CFLAGS, so merge it into CFLAGS. nmh_saved_cflags="$CFLAGS" CFLAGS="$AM_CFLAGS $CFLAGS" dnl On successful compilation, break out of loop with the AM_CPPFLAGS. for nmh_cv_addl_cppflags in "" "-D_GNU_SOURCE"; do dnl Reload initial CPPFLAGS so candidates aren't accumulated. CPPFLAGS="$nmh_saved_cppflags" dnl Only add non-empty nmh_cv_addl_cppflags to CPPFLAGS. AS_IF([test x"${nmh_cv_addl_cppflags}" != x], [CPPFLAGS="${CPPFLAGS:+$CPPFLAGS }$nmh_cv_addl_cppflags"]) AS_IF([test ${MULTIBYTE_ENABLED} = 1], [AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([#include #include ], [return wcwidth(0) + strdup("x") == 0])], [AM_CPPFLAGS="${nmh_cv_addl_cppflags}"; break;])], [AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([#include ], [return strdup("x") == 0])], [AM_CPPFLAGS="${nmh_cv_addl_cppflags}"; break;])]) done]) CFLAGS="$nmh_saved_cflags" CPPFLAGS="$nmh_saved_cppflags" dnl autoconf doesn't currently provide a macro to disable AC_LANG_WERROR, dnl so do it this way: AS_UNSET(ac_c_werror_flag) AC_SUBST([AM_CPPFLAGS]) ]) nmh-1.7.1-RC3/m4/iconv.m4000644 007761 000024 00000003344 13240376505 014673 0ustar00kenhstaff000000 000000 dnl Check for iconv support. It may be in libiconv and may be iconv() dnl or libiconv() dnl AC_DEFUN([NMH_CHECK_ICONV], [ICONV_ENABLED=0 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 ])], [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.]) ICONV_ENABLED=1 AC_CACHE_CHECK([for iconv declaration], [nmh_cv_iconv_const], [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include #include ]], [[#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])]) AC_SUBST([ICONV_ENABLED]) nmh-1.7.1-RC3/m4/locking.m4000644 007761 000024 00000003556 13240376505 015210 0ustar00kenhstaff000000 000000 dnl Our functions to check the locking functions available and select a dnl default locking function for the spool file dnl dnl Since we're assuming POSIX as a minimum, we always assume we have fcntl dnl locking available. dnl AC_DEFUN([NMH_LOCKING], [AC_CHECK_FUNCS([flock lockf]) AS_CASE(["$host_os"], [aix*|cygwin*|linux*], [default_locktype="fcntl"], [freebsd*|*netbsd*|openbsd*|darwin*], [default_locktype="flock"], [default_locktype="dot"]) AC_MSG_CHECKING([default locking method for the mail spool]) AC_ARG_WITH([locking], AS_HELP_STRING([--with-locking=@<:@dot|fcntl|flock|lockf@:>@], [The default locking method for the mail spool file]), , [with_locking="$default_locktype"]) AS_CASE([$with_locking], [fcntl|dot], , [flock], [AS_IF([test x"$ac_cv_func_flock" != x"yes"], [AC_MSG_ERROR([flock locks not supported on this system])])], [lockf], [AS_IF([test x"$ac_cv_func_lockf" != x"yes"], [AC_MSG_ERROR([lockf locks not supported on this system])])], [no], [AC_MSG_ERROR([--without-locking not supported])], [AC_MSG_ERROR([Unknown locking type $with_locking])]) AC_DEFINE_UNQUOTED([DEFAULT_LOCKING], ["$with_locking"], [The default lock type for the mail spool file]) AC_SUBST([default_locking], [$with_locking]) AC_MSG_RESULT([$with_locking]) supported_locks="fcntl dot" AS_IF([test x"$ac_cv_func_flock" = x"yes"], [supported_locks="$supported_locks flock"]) AS_IF([test x"$ac_cv_func_lockf" = x"yes"], [supported_locks="$supported_locks lockf"]) AC_SUBST([supported_locks]) dnl Should we use a locking directory? AC_ARG_ENABLE([lockdir], [AS_HELP_STRING([--enable-lockdir=dir], [Store dot-lock files in "dir"])], [ AS_IF([test "x$enableval" = xyes],[ AC_MSG_ERROR([--enable-lockdir requires an argument])]) AC_DEFINE_UNQUOTED([LOCKDIR], ["$enableval"], [Directory to store dot-locking lock files]) ])]) nmh-1.7.1-RC3/m4/mimetype.m4000644 007761 000024 00000003537 13240376505 015412 0ustar00kenhstaff000000 000000 dnl Try to see if we have a program that can determine the MIME type dnl of a particular file dnl dnl Assume that if file(1) doesn't support --mime-type, then it's dnl unusable. The --mime option to file 4.17 on CentOS 5.9, for dnl example, prints out a long description after the mime type. We dnl don't want that. AC_DEFUN([NMH_MIMETYPEPROC], [AC_CACHE_CHECK([for a program to provide a MIME type string], [nmh_cv_mimetype_proc], [nmh_cv_mimetype_proc= for mprog in 'file --brief --dereference --mime-type' \ 'file --dereference --mime-type' \ 'file --brief --mime-type' \ 'file --mime-type' do AS_IF([$mprog "${srcdir}/configure" > /dev/null 2>&1], [nmh_cv_mimetype_proc="$mprog"; break]) done]) AS_IF([test X"$nmh_cv_mimetype_proc" != X], [mimetype_proc="\"${nmh_cv_mimetype_proc}\"" AC_DEFINE_UNQUOTED([MIMETYPEPROC], [$mimetype_proc], [Program, with arguments, to provide MIME type.])])]) dnl The OpenBSD 5.4 file (4.24) reports --mime-encoding of text dnl files as "binary". Detect that by only accepting "us-ascii". AC_DEFUN([NMH_MIMEENCODINGPROC], [AC_CACHE_CHECK([for a program to provide a MIME encoding string], [nmh_cv_mimeencoding_proc], [nmh_cv_mimeencoding_proc= for mprog in 'file --brief --dereference --mime-encoding' \ 'file --dereference --mime-encoding' \ 'file --brief --mime-encoding' \ 'file --mime-encoding' do AS_IF([$mprog "${srcdir}/DATE" > /dev/null 2>&1], AS_CASE([`$mprog "${srcdir}/DATE"`], [us-ascii],[nmh_cv_mimeencoding_proc="$mprog"; break])) done]) AS_IF([test X"$nmh_cv_mimeencoding_proc" != X], [mimeencoding_proc="\"${nmh_cv_mimeencoding_proc}\"" AC_DEFINE_UNQUOTED([MIMEENCODINGPROC], [$mimeencoding_proc], [Program, with arguments, to provide MIME encoding.])])]) nmh-1.7.1-RC3/m4/ndbm.m4000644 007761 000024 00000003532 12755125044 014474 0ustar00kenhstaff000000 000000 dnl -------------- dnl CHECK FOR NDBM dnl -------------- dnl dnl NMH_CHECK_DBM(include,library,action-if-found,action-if-not) dnl Check for presence of dbm_open() in the specified library dnl and with the specified include file (if libname is the empty dnl string then don't try to link against any particular library). dnl We set nmh_ndbm_found to 'yes' or 'no'; if found we set dnl nmh_ndbmheader to the first arg and nmh_ndbm to the second. dnl If this macro accepted a list of include,library tuples dnl to test in order that would be cleaner than the current dnl nest of calls in configure.in. dnl We try to link our own code fragment (which includes the dnl headers in the same way slocal.c does) rather than dnl using AC_CHECK_LIB because on later versions of libdb dnl the dbm_open() function is provided via a #define and dnl we don't want to hardcode searching for the internal dnl function that lies behind it. (AC_CHECK_LIB works by dnl defining its own bogus prototype rather than pulling in dnl the right header files.) dnl An oddity (bug) of this macro is that if you haven't dnl done AC_PROG_CC or something that implies it before dnl using this macro autoconf complains about a recursive dnl expansion. AC_DEFUN([NMH_CHECK_NDBM], [ if test "x$2" = "x"; then nmh_libs= AC_MSG_CHECKING([for dbm in $1]) else nmh_libs="-l$2 " AC_MSG_CHECKING([for dbm in $1 and $2]) fi dnl We don't try to cache the result, because that exceeds dnl my autoconf skills -- feel free to put it in :-> -- PMM nmh_saved_libs="$LIBS" LIBS="$nmh_libs $5 $LIBS" AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #define DB_DBM_HSEARCH 1 #include <$1> ]], [[dbm_open("",0,0);]])],[nmh_ndbm_found=yes],[nmh_ndbm_found=no]) LIBS="$nmh_saved_libs" if test "$nmh_ndbm_found" = "yes"; then AC_MSG_RESULT(yes) nmh_ndbmheader="$1" nmh_ndbm="$2" $3 else AC_MSG_RESULT(no) $4 : fi ])dnl nmh-1.7.1-RC3/m4/netlibs.m4000644 007761 000024 00000000513 13240376505 015210 0ustar00kenhstaff000000 000000 dnl Updated for more modern systems. Check to see if we need to link against dnl optional libraries for networking functions. dnl AC_DEFUN([NMH_CHECK_NETLIBS], [AC_SEARCH_LIBS([gethostbyname], [nsl], , [AC_MSG_ERROR([gethostbyname not found])]) AC_SEARCH_LIBS([connect], [socket], , [AC_MSG_ERROR([connect not found])]) ])dnl nmh-1.7.1-RC3/m4/readline.m4000644 007761 000024 00000001554 13240376505 015341 0ustar00kenhstaff000000 000000 dnl Our readline heuristic. If we haven't been asked about readline, then dnl try to compile with it. If we've been asked for it, then we fail dnl if we cannot use it. If we were explicitly NOT asked for it, then dnl don't even try to use it. dnl AC_DEFUN([NMH_READLINE], [AC_ARG_WITH([readline], AS_HELP_STRING([--with-readline], [enable readline editing for whatnow (default=maybe)]), [], [with_readline=maybe]) AS_IF([test x"$with_readline" = xyes -o x"$with_readline" = xmaybe], [save_LIBS="$LIBS" LIBS= AC_SEARCH_LIBS([readline], [readline editline], [READLINELIB="$LIBS" AC_DEFINE([READLINE_SUPPORT], [1], [Support for using readline() in whatnow])], [AS_IF([test x"$with_readline" = xyes], [AC_MSG_ERROR([Unable to find a readline library])])], [$TERMLIB]) LIBS="$save_LIBS"]) ]) AC_SUBST([READLINELIB]) nmh-1.7.1-RC3/m4/tputs.m4000644 007761 000024 00000002133 13240376505 014727 0ustar00kenhstaff000000 000000 dnl Some systems have different arguments to the tputs callback; it can dnl be int (*)(int), or int (*)(char). Try to probe to see which one it dnl actually is, so our callback can match the prototype. dnl dnl The first argument to tputs sometimes is char *, other times is dnl const char *, so we have to include that in the test as well, but dnl we don't provide any definitions for it (since it's not necessary) dnl AC_DEFUN([NMH_TPUTS_PUTC_ARG], [AC_CACHE_CHECK([the argument of the tputs() callback], [nmh_cv_tputs_putc_arg], [for tputs_arg1 in 'const char *' 'char *'; do for tputs_putc_arg in 'int' 'char'; do AC_COMPILE_IFELSE( [AC_LANG_PROGRAM( [AC_INCLUDES_DEFAULT #include #include ], [extern int tputs($tputs_arg1, int, int (*)($tputs_putc_arg));])], [nmh_cv_tputs_putc_arg="$tputs_putc_arg"; break 2]) done done AS_IF([test "X$nmh_cv_tputs_putc_arg" = X], [AC_MSG_FAILURE([cannot determine tputs callback argument])])]) AC_DEFINE_UNQUOTED([TPUTS_PUTC_ARG], [$nmh_cv_tputs_putc_arg], [The type of the argument of the tputs() callback]) ]) nmh-1.7.1-RC3/h/addrsbr.h000644 007761 000024 00000006733 13243042053 015010 0ustar00kenhstaff000000 000000 /* addrsbr.h -- definitions for the address parsing system */ #define UUCPHOST (-1) #define LOCALHOST 0 #define NETHOST 1 #define BADHOST 2 /* * The email structure used by nmh to define an email address */ struct mailname { struct mailname *m_next; /* Linked list linkage; available for */ /* application use */ char *m_text; /* Full unparsed text of email address */ char *m_pers; /* display-name in RFC 5322 parlance */ char *m_mbox; /* local-part in RFC 5322 parlance */ char *m_host; /* domain in RFC 5322 parlance */ char *m_path; /* Host routing; should not be used */ int m_type; /* UUCPHOST, LOCALHOST, NETHOST, or BADHOST */ char m_nohost; /* True if no host part available */ char m_bcc; /* Used by post to keep track of bcc's */ int m_ingrp; /* True if email address is in a group */ char *m_gname; /* display-name of group */ char *m_note; /* Note (post-address comment) */ }; /* * See notes for auxformat() below. */ #define adrformat(m) auxformat ((m), 1) /* * prototypes */ void mnfree(struct mailname *); int ismymbox(struct mailname *); /* * Enable Email Address Internationalization, which requires * support of 8-bit addresses. */ void enable_eai(void); /* * Parse an address header, and return a sequence of email addresses. * This function is the main entry point into the nmh address parser. * It is used in conjunction with getm() to parse an email header. * * Arguments include: * * header - Pointer to the start of an email header. * * On the first call, header is copied and saved internally. Each email * address in the header is returned on the first and subsequent calls * to getname(). When there are no more email addresses available in * the header, NULL is returned and the parser's internal state is * reset. */ char *getname(const char *header); /* * Format an email address given a struct mailname. * * This function takes a pointer to a struct mailname and returns a pointer * to a static buffer holding the resulting email address. * * It is worth noting that group names are NOT handled, so if you want to * do something with groups you need to handle it externally to this function. * * Arguments include: * * mp - Pointer to mailname structure * extras - If true, include the personal name and/or note in the * address. Otherwise, omit it. */ char *auxformat(struct mailname *mp, int extras); /* * Parse an email address into it's components. * * Used in conjunction with getname() to parse a complete email header. * * Arguments include: * * str - Email address being parsed. * dfhost - A default host to append to the email address if * one is not included. If NULL, use nmh's idea of * localhost(). * dftype - If dfhost is given, use dftype as the email address type * if no host is in the email address. * eresult - A buffer containing an error message returned by the * address parser. May be NULL. * eresultsize - The size of the buffer passed in eresult. * * A pointer to an allocated struct mailname corresponding to the email * address is returned. * * This function used to have an argument called 'wanthost' which would * control whether or not it would canonicalize hostnames in email * addresses. This functionality was removed for nmh 1.5, and eventually * all of the code that used this argument was garbage collected. */ struct mailname *getm(char *str, char *dfhost, int dftype, char *eresult, size_t eresultsize); nmh-1.7.1-RC3/h/aliasbr.h000644 007761 000024 00000001662 13243042053 015000 0ustar00kenhstaff000000 000000 /* aliasbr.h -- definitions for the aliasing system * */ extern char *AliasFile; /* mh-alias(5) */ struct aka { char *ak_name; /* name to match against */ struct adr *ak_addr; /* list of addresses that it maps to */ struct aka *ak_next; /* next aka in list */ char ak_visible; /* should be visible in headers */ }; struct adr { char *ad_text; /* text of this address in list */ struct adr *ad_next; /* next adr in list */ char ad_local; /* text is local (check for expansion) */ }; /* * prototypes */ int alias (char *); int akvisible (void); char *akresult (struct aka *); char *akvalue (char *); char *akerror (int); /* codes returned by alias() */ #define AK_OK 0 /* file parsed OK */ #define AK_NOFILE 1 /* couldn't read file */ #define AK_ERROR 2 /* error parsing file */ #define AK_LIMIT 3 /* memory limit exceeded */ nmh-1.7.1-RC3/h/crawl_folders.h000644 007761 000024 00000001173 13243042053 016206 0ustar00kenhstaff000000 000000 /* crawl_folders.h -- crawl folder hierarchy */ #define CRAWL_NUMFOLDERS 100 /* Callbacks return TRUE crawl_folders should crawl the children of `folder'. * Callbacks need not duplicate folder, as crawl_folders does not free it. */ typedef boolean (crawl_callback_t)(char *folder, void *baton); /* Crawl the folder hierarchy rooted at the relative path `dir'. For each * folder, pass `callback' the folder name (as a path relative to the current * directory) and `baton'; the callback may direct crawl_folders not to crawl * its children; see above. */ void crawl_folders (char *dir, crawl_callback_t *callback, void *baton); nmh-1.7.1-RC3/h/dropsbr.h000644 007761 000024 00000000477 13205305704 015044 0ustar00kenhstaff000000 000000 /* dropsbr.h -- definitions for maildrop-style files */ /* * various formats for maildrop files */ #define OTHER_FORMAT 0 #define MBOX_FORMAT 1 #define MMDF_FORMAT 2 /* * prototypes */ int mbx_open (char *, int, uid_t, gid_t, mode_t); int mbx_copy (char *, int, int, int, char *); int mbx_close (char *, int); nmh-1.7.1-RC3/h/fmt_compile.h000644 007761 000024 00000016641 13205305704 015667 0ustar00kenhstaff000000 000000 /* fmt_compile.h -- format types */ /* types that output text */ #define FT_COMP 1 /* the text of a component */ #define FT_COMPF 2 /* comp text, filled */ #define FT_LIT 3 /* literal text */ #define FT_LITF 4 /* literal text, filled */ #define FT_CHAR 5 /* a single ASCII character */ #define FT_NUM 6 /* "value" as decimal number */ #define FT_NUMF 7 /* "value" as filled dec number */ #define FT_STR 8 /* "str" as text */ #define FT_STRF 9 /* "str" as text, filled */ #define FT_STRFW 10 /* "str" as text, filled, width in "value" */ #define FT_STRLIT 11 /* "str" as text, no space compression */ #define FT_STRLITZ 12 /* literal text with zero display width */ #define FT_PUTADDR 13 /* split and print address line */ /* types that modify the "str" or "value" registers */ #define FT_LS_COMP 14 /* set "str" to component text */ #define FT_LS_LIT 15 /* set "str" to literal text */ #define FT_LS_GETENV 16 /* set "str" to getenv(text) */ #define FT_LS_CFIND 17 /* set "str" to context_find(text) */ #define FT_LS_DECODECOMP 18 /* set "str" to decoded component text */ #define FT_LS_DECODE 19 /* decode "str" as RFC-2047 header */ #define FT_LS_TRIM 20 /* trim trailing white space from "str" */ #define FT_LV_COMP 21 /* set "value" to comp (as dec. num) */ #define FT_LV_COMPFLAG 22 /* set "value" to comp flag word */ #define FT_LV_LIT 23 /* set "value" to literal num */ #define FT_LV_DAT 24 /* set "value" to dat[n] */ #define FT_LV_STRLEN 25 /* set "value" to length of "str" */ #define FT_LV_PLUS_L 26 /* set "value" += literal */ #define FT_LV_MINUS_L 27 /* set "value" -= literal */ #define FT_LV_MULTIPLY_L 28 /* set "value" to value * literal */ #define FT_LV_DIVIDE_L 29 /* set "value" to value / literal */ #define FT_LV_MODULO_L 30 /* set "value" to value % literal */ #define FT_LV_CHAR_LEFT 31 /* set "value" to char left in output */ #define FT_LS_MONTH 32 /* set "str" to tws month */ #define FT_LS_LMONTH 33 /* set "str" to long tws month */ #define FT_LS_ZONE 34 /* set "str" to tws timezone */ #define FT_LS_DAY 35 /* set "str" to tws weekday */ #define FT_LS_WEEKDAY 36 /* set "str" to long tws weekday */ #define FT_LS_822DATE 37 /* set "str" to 822 date str */ #define FT_LS_PRETTY 38 /* set "str" to pretty (?) date str */ #define FT_LS_KILO 39 /* set "str" to "[KMGT]" */ #define FT_LS_KIBI 40 /* set "str" to "[KMGT]" */ #define FT_LV_SEC 41 /* set "value" to tws second */ #define FT_LV_MIN 42 /* set "value" to tws minute */ #define FT_LV_HOUR 43 /* set "value" to tws hour */ #define FT_LV_MDAY 44 /* set "value" to tws day of month */ #define FT_LV_MON 45 /* set "value" to tws month */ #define FT_LV_YEAR 46 /* set "value" to tws year */ #define FT_LV_YDAY 47 /* set "value" to tws day of year */ #define FT_LV_WDAY 48 /* set "value" to tws weekday */ #define FT_LV_ZONE 49 /* set "value" to tws timezone */ #define FT_LV_CLOCK 50 /* set "value" to tws clock */ #define FT_LV_RCLOCK 51 /* set "value" to now - tws clock */ #define FT_LV_DAYF 52 /* set "value" to tws day flag */ #define FT_LV_DST 53 /* set "value" to tws daylight savings flag */ #define FT_LV_ZONEF 54 /* set "value" to tws timezone flag */ #define FT_LS_PERS 55 /* set "str" to person part of addr */ #define FT_LS_MBOX 56 /* set "str" to mbox part of addr */ #define FT_LS_HOST 57 /* set "str" to host part of addr */ #define FT_LS_PATH 58 /* set "str" to route part of addr */ #define FT_LS_GNAME 59 /* set "str" to group part of addr */ #define FT_LS_NOTE 60 /* set "str" to comment part of addr */ #define FT_LS_ADDR 61 /* set "str" to mbox@host */ #define FT_LS_822ADDR 62 /* set "str" to 822 format addr */ #define FT_LS_FRIENDLY 63 /* set "str" to "friendly" format addr */ #define FT_LV_HOSTTYPE 64 /* set "value" to addr host type */ #define FT_LV_INGRPF 65 /* set "value" to addr in-group flag */ #define FT_LS_UNQUOTE 66 /* remove RFC 2822 quotes from "str" */ #define FT_LV_NOHOSTF 67 /* set "value" to addr no-host flag */ /* Date Coercion */ #define FT_LOCALDATE 68 /* Coerce date to local timezone */ #define FT_GMTDATE 69 /* Coerce date to GMT */ /* pre-format processing */ #define FT_PARSEDATE 70 /* parse comp into a date (tws) struct */ #define FT_PARSEADDR 71 /* parse comp into a mailaddr struct */ #define FT_FORMATADDR 72 /* let external routine format addr */ #define FT_CONCATADDR 73 /* formataddr w/out duplicate removal */ #define FT_MYMBOX 74 /* do "mymbox" test on comp */ #define FT_GETMYMBOX 75 /* return "mymbox" mailbox string */ #define FT_GETMYADDR 76 /* return "mymbox" addr string */ /* conditionals & control flow (must be last) */ #define FT_SAVESTR 77 /* save current str reg */ #define FT_DONE 78 /* stop formatting */ #define FT_PAUSE 79 /* pause */ #define FT_NOP 80 /* no-op */ #define FT_GOTO 81 /* (relative) goto */ #define FT_IF_S_NULL 82 /* test if "str" null */ #define FT_IF_S 83 /* test if "str" non-null */ #define FT_IF_V_EQ 84 /* test if "value" = literal */ #define FT_IF_V_NE 85 /* test if "value" != literal */ #define FT_IF_V_GT 86 /* test if "value" > literal */ #define FT_IF_MATCH 87 /* test if "str" contains literal */ #define FT_IF_AMATCH 88 /* test if "str" starts with literal */ #define FT_S_NULL 89 /* V = 1 if "str" null */ #define FT_S_NONNULL 90 /* V = 1 if "str" non-null */ #define FT_V_EQ 91 /* V = 1 if "value" = literal */ #define FT_V_NE 92 /* V = 1 if "value" != literal */ #define FT_V_GT 93 /* V = 1 if "value" > literal */ #define FT_V_MATCH 94 /* V = 1 if "str" contains literal */ #define FT_V_AMATCH 95 /* V = 1 if "str" starts with literal */ #define IF_FUNCS FT_S_NULL /* start of "if" functions */ nmh-1.7.1-RC3/h/fmt_scan.h000644 007761 000024 00000024774 13243042053 015166 0ustar00kenhstaff000000 000000 /* fmt_scan.h -- definitions for fmt_scan() */ /* * This structure describes an "interesting" component. It holds * the name & text from the component (if found) and one piece of * auxiliary info. The structure for a particular component is located * by (open) hashing the name and using it as an index into the ptr array * "wantcomp". All format entries that reference a particular component * point to its comp struct (so we only have to do component specific * processing once. e.g., parse an address.). * * In previous implementations "wantcomp" was made available to other * functions, but now it's private and is accessed via functions. */ struct comp { char *c_name; /* component name (in lower case) */ char *c_text; /* component text (if found) */ struct comp *c_next; /* hash chain linkage */ short c_flags; /* misc. flags (from fmt_scan) */ short c_type; /* type info (from fmt_compile) */ union { struct tws *c_u_tws; struct mailname *c_u_mn; } c_un; int c_refcount; /* Reference count */ }; #define c_tws c_un.c_u_tws #define c_mn c_un.c_u_mn /* * c_type bits */ #define CT_ADDR (1<<0) /* referenced as address */ #define CT_DATE (1<<1) /* referenced as date */ #define CT_BITS "\020\01ADDR\02DATE" /* * c_flags bits */ #define CF_TRUE (1<<0) /* usually means component is present */ #define CF_PARSED (1<<1) /* address/date has been parsed */ #define CF_DATEFAB (1<<2) /* datefield fabricated */ #define CF_TRIMMED (1<<3) /* Component has been trimmed */ #define CF_BITS "\020\01TRUE\02PARSED\03CF_DATEFAB\04TRIMMED" /* * This structure defines one formatting instruction. */ struct format { unsigned char f_type; char f_fill; short f_width; /* output field width */ union { struct comp *f_u_comp; /* associated component */ char *f_u_text; /* literal text */ char f_u_char; /* literal character */ int f_u_value; /* literal value */ } f_un; short f_flags; /* misc. flags */ }; #define f_skip f_width /* instr to skip (false "if") */ #define f_comp f_un.f_u_comp #define f_text f_un.f_u_text #define f_char f_un.f_u_char #define f_value f_un.f_u_value /* * f_flags bits */ #define FF_STRALLOC (1<<0) /* String has been allocated */ #define FF_COMPREF (1<<1) /* Component reference */ /* * prototypes used by the format engine */ /* * These are the definitions used by the callbacks for fmt_scan() */ typedef char * (*formataddr_cb)(char *, char *); typedef char * (*concataddr_cb)(char *, char *); typedef void (*trace_cb)(void *, struct format *, int, char *, const char *); struct fmt_callbacks { formataddr_cb formataddr; concataddr_cb concataddr; trace_cb trace_func; void * trace_context; }; /* * Create a new format string. Arguments are: * * form - Name of format file. Will be searched by etcpath(), see that * function for details. * format - The format string to be used if no format file is given * default_fs - The default format string to be used if neither form nor * format is given * * This function also takes care of processing \ escapes like \n, \t, etc. * * Returns an allocated format string. */ char *new_fs (char *form, char *format, char *default_fs); /* * Free memory allocated by new_fs(). It allocates to a static so * no argument is necessary. */ void free_fs(void); /* * Compile a format string into a set of format instructions. Arguments are: * * fstring - The format string (the "source code"). * fmt - Returns an allocated array of "struct fmt" elements. Each * struct fmt is one format instruction interpreted by the * format engine. * reset - If set to true, the format compiler will reset the * component hash table. The component hash table contains * all of the references to message components referred to in * the format instructions. If you have multiple format * strings that you want to compile and operate on the * same message, this should be set to false. * * Returns the total number of components referenced by all format instructions * since the last reset of the hash table. */ int fmt_compile (char *fstring, struct format **fmt, int reset); /* * Interpret a sequence of compiled format instructions. Arguments are: * * format - Array of format instructions generated by fmt_compile() * scanl - Passed-in charstring_t object (created with * charstring_create() and later destroyed with * charstring_free()) that will contain the output of the * format instructions. Is always terminated with a * newline (\n). * width - Maximum number of displayed characters. Does not include * characters marked as non-printing or (depending on the * encoding) bytes in a multibyte encoding that exceed the * character's column width. * dat - An integer array that contains data used by certain format * functions. Currently the following instructions use * dat[]: * * dat[0] - %(msg), %(dat) * dat[1] - %(cur) * dat[2] - %(size) * dat[3] - %(width) * dat[4] - %(unseen) * * callbacks - A set of a callback functions used by the format engine. * Can be NULL. If structure elements are NULL, a default * function will be used. Callback structure elements are: * * formataddr - A callback for the %(formataddr) instruction * concataddr - A callback for the %(concataddr) instruction * trace - Called for every format instruction executed * * The return value is a pointer to the next format instruction to * execute, which is currently always NULL. */ struct format *fmt_scan (struct format *format, charstring_t scanl, int width, int *dat, struct fmt_callbacks *callbacks); /* * Free a format structure and/or component hash table. Arguments are: * * format - An array of format structures allocated by fmt_compile, * or NULL. * reset - If true, reset and remove all references in the component * hash table. */ void fmt_free (struct format *fmt, int reset); /* * Free all of the component text structures in the component hash table */ void fmt_freecomptext(void); /* * Search for a component structure in the component hash table. Arguments are: * * component - The name of the component to search for. By convention * all component names used in format strings are lower case, * but for backwards compatibility this search is done in * a case-SENSITIVE manner. * * This function returns a "struct comp" corresponding to the named component, * or NULL if the component is not found in the hash table. */ struct comp *fmt_findcomp(char *component); /* * Search for a component structure in the component hash table. * * Identical to fmd_findcomp(), but is case-INSENSITIVE. */ struct comp *fmt_findcasecomp(char *component); /* * Add a component entry to the component hash table * * component - The name of the component to add to the hash table. * * If the component is already in the hash table, this function will do * nothing. Returns 1 if a component was added, 0 if it already existed. */ int fmt_addcompentry(char *component); /* * Add a string to a component hash table entry. Arguments are: * * component - The name of the component to add text to. The component * is searched for in a case-INSENSITIVE manner (note that * this is different than fmt_findcomp()). If the component * is not found in the hash table, this function will silently * return. * text - The text to add to a component hash table entry. Note that * if the last character of the existing component * text is a newline AND it is marked as an address * component (the the CT_ADDR flag is set) existing * component buffer is a newline, it will be separated * from previous text by ",\n\t"; otherwise if the last * character of the previous text is a newline it will * simply be separated by a "\t". This unusual processing * is designed to handle the case where you have multiple * headers with the same name (e.g.: multiple "cc:" headers, * even though that isn't technically allowed in the RFCs). * * This function is designed to be called when you start processing a new * component. The function returns the integer value of the hash table * bucket corresponding to this component. If there was no entry found * in the component hash table, this function will return -1. */ int fmt_addcomptext(char *component, char *text); /* * Append to an existing component. Arguments are: * * bucket - The hash table bucket corresponding to this component, * as returned by fmt_addcomp(). If -1, this function will * return with no actions performed. * component - The component to append text to. Like fmt_addcomp, the * component is searched case-INSENSITIVELY. * text - The text to append to the component. No special processing * is done. * * This function is designed to be called when you are processing continuation * lines on the same header (state == FLDPLUS). */ void fmt_appendcomp(int bucket, char *component, char *text); /* * Iterate over the complete hash table of component structures. * * Arguments are: * * comp - Pointer to the current component structure. The next * component in the hash table after this component. To * start (or restart) the iteration of the hash table * this argument should be NULL. * bucket - Pointer to hash bucket. Will be managed by this function, * the caller should not modify this value. * * Returns the next component in the hash table. This value should be * passed into the next call to fmt_nextcomp(). Returns NULL at the end * of the hash table. */ struct comp *fmt_nextcomp(struct comp *comp, unsigned int *bucket); /* * The implementation of the %(formataddr) function. This is available for * programs to provide their own local implementation if they wish to do * special processing (see uip/replsbr.c for an example). Arguments are: * * orig - Existing list of addresses * str - New address(es) to append to list. * * This function returns an allocated string containing the new list of * addresses. */ char *formataddr(char *orig, char *str); /* * The implementation of the %(concataddr) function. Arguments and behavior * are the same as %(formataddr). Again, see uip/replsbr.c to see how you * can override this behavior. */ char *concataddr(char *orig, char *str); nmh-1.7.1-RC3/h/icalendar.h000644 007761 000024 00000006500 13243042053 015301 0ustar00kenhstaff000000 000000 /* icalendar.h -- data structures and common code for icalendar scanner, * parser, and application code * * This code is Copyright (c) 2014, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ /* * Types used in struct contentline below. */ typedef struct value_list { char *value; struct value_list *next; } value_list; typedef struct param_list { char *param_name; /* Name of property parameter. */ struct value_list *values; /* List of its values. */ struct param_list *next; /* Next node in list of property parameters. */ } param_list; typedef enum cr_indicator { CR_UNSET = 0, LF_ONLY, CR_BEFORE_LF } cr_indicator; /* * Each (unfolded) line in the .ics file is represented by a struct * contentline. */ typedef struct contentline { char *name; /* The name of the property, calprops, or BEGIN. */ struct param_list *params; /* List parameters. */ char *value; /* Everything after the ':'. */ char *input_line; /* The (unfolded) input line. */ size_t input_line_len; /* Amount of text stored in input_line. */ size_t input_line_size; /* Size of allocated input_line. */ charstring_t unexpected; /* Accumulate unexpected characters in input. */ cr_indicator cr_before_lf; /* To support CR before LF. If the first line of the input has a CR before its LF, assume that all output lines need to. Only used in root node. */ struct contentline *next; /* Next node in list of content lines. */ struct contentline *last; /* Last node of list. Only used in root node. */ } contentline; /* * List of vevents, each of which is a list of contentlines. */ typedef struct vevent { contentline *contentlines; struct vevent *next; /* The following is only used in the root node. */ struct vevent *last; } vevent; /* * Exported functions. */ void remove_contentline (contentline *); contentline *add_contentline (contentline *, const char *); void add_param_name (contentline *, char *); void add_param_value (contentline *, char *); void remove_value (value_list *); struct contentline *find_contentline (contentline *, const char *, const char *); void free_contentlines (contentline *); typedef struct tzdesc *tzdesc_t; tzdesc_t load_timezones (const contentline *); void free_timezones (tzdesc_t); char *format_datetime (tzdesc_t, const contentline *); /* * The following provide access to, and by, the iCalendar parser. */ /* This YYSTYPE definition prevents problems with Solaris yacc, which has declarations of two variables of type YYSTYPE * in one statement. */ typedef char *charptr; #define YYSTYPE charptr extern int icaldebug; int icalparse (void); extern vevent vevents; int icallex (void); extern int parser_status; /* And this is for the icalendar scanner. */ extern YYSTYPE icallval; /* * For directing the scanner to use files other than stdin/stdout. * These don't use the accessors provided by modern flex because * flex 2.5.4 doesn't supply them. */ void icalset_inputfile (FILE *); void icalset_outputfile (FILE *); nmh-1.7.1-RC3/h/md5.h000644 007761 000024 00000004426 13243042053 014051 0ustar00kenhstaff000000 000000 /* md5.h -- header file for md5 message digest * taken from RFC-1321/Appendices A.1/A.2 */ /* * RSAREF types and constants */ /* * Use include for nmh/mh */ #include /* * We need this for uint32_t */ #include /* * Use prototypes for nmh/mh */ #define PROTOTYPES 1 /* * PROTOTYPES should be set to one if and only if the compiler * supports function argument prototyping. The following makes * PROTOTYPES default to 0 if it has not already been defined * with C compiler flags. */ #ifndef PROTOTYPES #define PROTOTYPES 0 #endif /* POINTER defines a generic pointer type */ typedef unsigned char *POINTER; /* UINT4 defines a four byte word */ typedef uint32_t UINT4; /* PROTO_LIST is defined depending on how PROTOTYPES is defined above. If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it returns an empty list. */ #if PROTOTYPES #define PROTO_LIST(list) list #else #define PROTO_LIST(list) () #endif /* MD5.H - header file for MD5C.C */ /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved. License to copy and use this software is granted provided that it is identified as the "RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing this software or this function. License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing the derived work. RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. These notices must be retained in any copies of any part of this documentation and/or software. */ /* MD5 context. */ typedef struct { UINT4 state[4]; /* state (ABCD) */ UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } MD5_CTX; void MD5Init PROTO_LIST ((MD5_CTX *)); void MD5Update PROTO_LIST ((MD5_CTX *, unsigned char *, unsigned int)); void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *)); nmh-1.7.1-RC3/h/mf.h000644 007761 000024 00000001004 13243042053 013753 0ustar00kenhstaff000000 000000 /* mf.h -- include file for mailbox filters */ #include #ifndef TRUE # define TRUE 1 #endif #ifndef FALSE # define FALSE 0 #endif #ifndef NOTOK # define NOTOK (-1) #endif #ifndef OK # define OK 0 #endif #ifndef DONE # define DONE 1 #endif struct adrx { char *text; char *pers; char *mbox; char *host; char *path; char *grp; int ingrp; char *note; char *err; }; /* * prototypes */ char *legal_person (const char *); struct adrx *getadrx (const char *, int); nmh-1.7.1-RC3/h/mh.h000644 007761 000024 00000035051 13243042053 013766 0ustar00kenhstaff000000 000000 /* mh.h -- main header file for all of nmh */ #include /* * Well-used constants */ #define NOTOK (-1) /* syscall()s return this on error */ #define OK 0 /* ditto on success */ #define DONE 1 /* ternary logic */ #define ALL "" #define MAXARGS 1000 /* max arguments to exec */ #define NFOLDERS 1000 /* max folder arguments on command line */ #define DMAXFOLDER 4 /* typical number of digits */ #define MAXFOLDER 1000 /* message increment */ /* * This macro is for use by scan, for example, so that platforms with * a small BUFSIZ can easily allocate larger buffers. */ #define NMH_BUFSIZ max(BUFSIZ, 8192) #ifndef FALSE #define FALSE false #endif #ifndef TRUE #define TRUE true #endif typedef unsigned char boolean; /* not int so we can pack in a structure */ /* If we're using gcc then give it some information about * functions that abort. */ #if __GNUC__ > 2 #define NORETURN __attribute__((__noreturn__)) #define NMH_UNUSED(i) (void) i #else #define NORETURN #define NMH_UNUSED(i) i #endif /* DIM gives the number of elements in the one-dimensional array a. */ #define DIM(a) (sizeof (a) / sizeof (*(a))) /* LEN gives the strlen() of string constant s, excluding the * terminating NUL. */ #define LEN(s) (sizeof (s) - 1) /* FENDNULL fends off NULL by giving an empty string instead. */ #define FENDNULL(s) ((s) ? (s) : "") /* * char array that keeps track of size in both bytes and characters * Usage note: * Don't store return value of charstring_buffer() and use later * after intervening push_back's; use charstring_buffer_copy() * instead. */ typedef struct charstring *charstring_t; charstring_t charstring_create (size_t); charstring_t charstring_copy (const charstring_t); void charstring_free (charstring_t); /* Append a single-byte character: */ void charstring_push_back (charstring_t, const char); /* Append possibly multi-byte character(s): */ void charstring_push_back_chars (charstring_t, const char [], size_t, size_t); void charstring_append (charstring_t, const charstring_t); void charstring_append_cstring (charstring_t, const char []); void charstring_clear (charstring_t); /* Don't store return value of charstring_buffer() and use later after intervening push_back's; use charstring_buffer_copy() instead. */ const char *charstring_buffer (const charstring_t); /* User is responsible for free'ing result of buffer copy. */ char *charstring_buffer_copy (const charstring_t); size_t charstring_bytes (const charstring_t); size_t charstring_chars (const charstring_t); /* Length of the last character in the charstring. */ int charstring_last_char_len (const charstring_t); /* * user context/profile structure */ struct node { char *n_name; /* key */ char *n_field; /* value */ char n_context; /* context, not profile */ struct node *n_next; /* next entry */ }; /* * switches structure */ #define AMBIGSW (-2) /* from smatch() on ambiguous switch */ #define UNKWNSW (-1) /* from smatch() on unknown switch */ struct swit { /* * Switch name */ char *sw; /* The minchars field is apparently used like this: -# : Switch can be abbreviated to # characters; switch hidden in -help. 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 use a technique 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. * Note that the last entry in the above definition must either omit the * continuation backslash, or be followed by a blank line. In the nmh * code the style is to have every line include a backslash and follow * the SWITCHES macro definition by a blank line. * * 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 */ /* * general folder attributes */ #define READONLY (1<<0) /* No write access to folder */ #define SEQMOD (1<<1) /* folder's sequences modified */ #define ALLOW_NEW (1<<2) /* allow the "new" sequence */ #define OTHERS (1<<3) /* folder has other files */ #define FBITS "\020\01READONLY\02SEQMOD\03ALLOW_NEW\04OTHERS" /* * first free slot for user defined sequences * and attributes */ #define FFATTRSLOT 4 /* * internal messages attributes (sequences) */ #define EXISTS (0) /* exists */ #define SELECTED (1) /* selected for use */ #define SELECT_EMPTY (2) /* "new" message */ #define SELECT_UNSEEN (3) /* inc/show "unseen" */ #define MBITS "\020\01EXISTS\02SELECTED\03NEW\04UNSEEN" /* A vector of bits for tracking the sequence membership of a single * message. Do not access the struct members; use vector.c. * Do not move or copy this struct as it may contain a pointer to * itself; use bvector_copy(). */ struct bvector { unsigned long *bits; size_t maxsize; unsigned long tiny[2]; /* Default fixed-size storage for bits. */ }; typedef struct bvector *bvector_t; bvector_t bvector_create (void); void bvector_init(struct bvector *bv); void bvector_copy (bvector_t, bvector_t); void bvector_free (bvector_t); void bvector_fini(struct bvector *bv); void bvector_clear (bvector_t, size_t); void bvector_clear_all (bvector_t); void bvector_set (bvector_t, size_t); unsigned int bvector_at (bvector_t, size_t); unsigned long bvector_first_bits (bvector_t); typedef struct svector *svector_t; svector_t svector_create (size_t); void svector_free (svector_t); char *svector_push_back (svector_t, char *); char *svector_at (svector_t, size_t); char **svector_find(svector_t, const char *); char **svector_strs (svector_t); size_t svector_size (svector_t); typedef struct ivector *ivector_t; ivector_t ivector_create (size_t); void ivector_free (ivector_t); int ivector_push_back (ivector_t, int); int ivector_at (ivector_t, size_t); int *ivector_atp (ivector_t, size_t); /* * Primary structure of folder/message information */ struct msgs { int lowmsg; /* Lowest msg number */ int hghmsg; /* Highest msg number */ int nummsg; /* Actual Number of msgs */ int lowsel; /* Lowest selected msg number */ int hghsel; /* Highest selected msg number */ int numsel; /* Number of msgs selected */ int curmsg; /* Number of current msg if any */ int msgflags; /* Folder attributes (READONLY, etc) */ char *foldpath; /* Pathname of folder */ /* * Name of sequences in this folder. */ svector_t msgattrs; /* * bit flags for whether sequence * is public (0), or private (1) */ bvector_t attrstats; /* * These represent the lowest and highest possible * message numbers we can put in the message status * area, without calling folder_realloc(). */ int lowoff; int hghoff; /* * This is an array of bvector_t which we allocate dynamically. * Each bvector_t is a set of bits flags for a particular message. * These bit flags represent general attributes such as * EXISTS, SELECTED, etc. as well as track if message is * in a particular sequence. */ size_t num_msgstats; struct bvector *msgstats; /* msg status */ /* * A FILE handle containing an open filehandle for the sequence file * for this folder. If non-NULL, use it when the sequence file is * written. */ FILE *seqhandle; /* * The name of the public sequence file; required by lkfclose() */ char *seqname; }; /* * Amount of space to allocate for msgstats. Allocate * the array to have space for messages numbered lo to hi. * Use MSGSTATNUM to load mp->num_msgstats first. */ #define MSGSTATNUM(lo, hi) ((size_t) ((hi) - (lo) + 1)) #define MSGSTATSIZE(mp) ((mp)->num_msgstats * sizeof *(mp)->msgstats) /* * macros for message and sequence manipulation */ #define msgstat(mp,n) ((mp)->msgstats + (n) - mp->lowoff) #define clear_msg_flags(mp,msgnum) bvector_clear_all (msgstat(mp, msgnum)) #define copy_msg_flags(mp,i,j) bvector_copy (msgstat(mp,i), msgstat(mp,j)) #define get_msg_flags(mp,ptr,msgnum) bvector_copy (ptr, msgstat(mp, msgnum)) #define set_msg_flags(mp,ptr,msgnum) bvector_copy (msgstat(mp, msgnum), ptr) #define does_exist(mp,msgnum) bvector_at (msgstat(mp, msgnum), EXISTS) #define unset_exists(mp,msgnum) bvector_clear (msgstat(mp, msgnum), EXISTS) #define set_exists(mp,msgnum) bvector_set (msgstat(mp, msgnum), EXISTS) #define is_selected(mp,msgnum) bvector_at (msgstat(mp, msgnum), SELECTED) #define unset_selected(mp,msgnum) bvector_clear (msgstat(mp, msgnum), SELECTED) #define set_selected(mp,msgnum) bvector_set (msgstat(mp, msgnum), SELECTED) #define is_select_empty(mp,msgnum) \ bvector_at (msgstat(mp, msgnum), SELECT_EMPTY) #define set_select_empty(mp,msgnum) \ bvector_set (msgstat(mp, msgnum), SELECT_EMPTY) #define is_unseen(mp,msgnum) \ bvector_at (msgstat(mp, msgnum), SELECT_UNSEEN) #define unset_unseen(mp,msgnum) \ bvector_clear (msgstat(mp, msgnum), SELECT_UNSEEN) #define set_unseen(mp,msgnum) \ bvector_set (msgstat(mp, msgnum), SELECT_UNSEEN) #define in_sequence(mp,seqnum,msgnum) \ bvector_at (msgstat(mp, msgnum), FFATTRSLOT + seqnum) #define clear_sequence(mp,seqnum,msgnum) \ bvector_clear (msgstat(mp, msgnum), FFATTRSLOT + seqnum) #define add_sequence(mp,seqnum,msgnum) \ bvector_set (msgstat(mp, msgnum), FFATTRSLOT + seqnum) #define is_seq_private(mp,seqnum) \ bvector_at (mp->attrstats, FFATTRSLOT + seqnum) #define make_seq_public(mp,seqnum) \ bvector_clear (mp->attrstats, FFATTRSLOT + seqnum) #define make_seq_private(mp,seqnum) \ bvector_set (mp->attrstats, FFATTRSLOT + seqnum) #define make_all_public(mp) \ mp->attrstats = bvector_create(); bvector_clear_all (mp->attrstats) /* * macros for folder attributes */ #define clear_folder_flags(mp) ((mp)->msgflags = 0) #define is_readonly(mp) ((mp)->msgflags & READONLY) #define set_readonly(mp) ((mp)->msgflags |= READONLY) #define other_files(mp) ((mp)->msgflags & OTHERS) #define set_other_files(mp) ((mp)->msgflags |= OTHERS) /* * m_getfld() message parsing */ #define NAMESZ 999 /* Limit on component name size. RFC 2822 limits line lengths to 998 characters, so a header name can be at most that long. m_getfld limits header names to 2 less than NAMESZ, which is fine, because header names must be followed by a colon. Add one for terminating NULL. */ #define LENERR (-2) /* Name too long error from getfld */ #define FMTERR (-3) /* Message Format error */ #define FLD 0 /* Field returned */ #define FLDPLUS 1 /* Field returned with more to come */ #define BODY 3 /* Body returned with more to come */ #define FILEEOF 5 /* Reached end of input file */ typedef struct m_getfld_state *m_getfld_state_t; #define NOUSE 0 /* draft being re-used */ #define TFOLDER 0 /* path() given a +folder */ #define TFILE 1 /* path() given a file */ #define TSUBCWF 2 /* path() given a @folder */ #define OUTPUTLINELEN 72 /* default line length for headers */ #define LINK "@" /* Name of link to file to which you are */ /* replying. */ /* * credentials management */ typedef struct nmh_creds *nmh_creds_t; /* * miscellaneous macros */ #define pidXwait(pid,cp) pidstatus (pidwait (pid, NOTOK), stdout, cp) #ifndef max # define max(a,b) ((a) > (b) ? (a) : (b)) #endif #ifndef min # define min(a,b) ((a) < (b) ? (a) : (b)) #endif #ifndef abs # define abs(a) ((a) > 0 ? (a) : -(a)) #endif /* * GLOBAL VARIABLES */ #define CTXMOD 0x01 /* context information modified */ #define DBITS "\020\01CTXMOD" extern char ctxflags; extern char *invo_name; /* command invocation name */ extern char *mypath; /* user's $HOME */ extern char *defpath; /* pathname of user's profile */ extern char *ctxpath; /* pathname of user's context */ extern struct node *m_defs; /* list of profile/context entries */ /* * These standard strings are defined in config.c. They are the * only system-dependent parameters in nmh, and thus by redefining * their values and reloading the various modules, nmh will run * on any system. */ extern char *buildmimeproc; extern char *catproc; extern char *components; extern char *context; extern char *current; extern char *credentials_file; extern int credentials_no_perm_check; extern char *defaultfolder; extern char *digestcomps; extern char *distcomps; extern char *draft; extern char *fileproc; extern char *foldprot; extern char *formatproc; extern char *forwcomps; extern char *inbox; extern char *incproc; extern char *lproc; extern char *mailproc; extern char *mh_defaults; extern char *mh_profile; extern char *mh_seq; extern char *mhlformat; extern char *mhlforward; extern char *mhlproc; extern char *mhlreply; extern char *moreproc; extern char *msgprot; extern char *nmhaccessftp; extern char *nmhaccessurl; extern char *nmhstorage; extern char *nmhcache; extern char *nmhprivcache; extern char *nsequence; extern char *packproc; extern char *postproc; extern char *pfolder; extern char *psequence; extern char *rcvdistcomps; extern char *rcvstoreproc; extern char *replcomps; extern char *replgroupcomps; extern char *rmmproc; extern char *sendproc; extern char *showmimeproc; extern char *showproc; extern char *usequence; extern char *user_agent; extern char *version_num; extern char *version_str; extern char *whatnowproc; extern char *whomproc; extern void (*done) (int) NORETURN; #include nmh-1.7.1-RC3/h/mhcachesbr.h000644 007761 000024 00000001117 13205305704 015460 0ustar00kenhstaff000000 000000 /* mhcachesbr.h -- definitions for manipulating MIME content cache */ /* * various cache policies */ #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 extern struct swit *cache_policy; void cache_all_messages(CT *cts); int find_cache(CT ct, int policy, int *writing, char *id, char *buffer, int buflen); extern int rcachesw; extern int wcachesw; extern char *cache_public; extern char *cache_private; nmh-1.7.1-RC3/h/mhparse.h000644 007761 000024 00000041200 13243042053 015012 0ustar00kenhstaff000000 000000 /* mhparse.h -- definitions for parsing/building of MIME content * -- (mhparse.c/mhbuildsbr.c) */ #define NPARTS 50 #define NTYPES 20 #define NPREFS 20 /* * Abstract type for header fields */ typedef struct hfield *HF; /* * Abstract types for MIME parsing/building */ typedef struct cefile *CE; typedef struct CTinfo *CI; typedef struct Content *CT; typedef struct Parameter *PM; /* * type for Init function (both type and transfer encoding) */ typedef int (*InitFunc) (CT); /* * types for various transfer encoding access functions */ typedef int (*OpenCEFunc) (CT, char **); typedef void (*CloseCEFunc) (CT); typedef unsigned long (*SizeCEFunc) (CT); /* * Structure for storing/encoding/decoding * a header field and its value. */ struct hfield { char *name; /* field name */ char *value; /* field body */ int hf_encoding; /* internal flag for transfer encoding to use */ HF next; /* link to next header field */ }; /* * Structure for holding MIME parameter elements. */ struct Parameter { char *pm_name; /* Parameter name */ char *pm_value; /* Parameter value */ char *pm_charset; /* Parameter character set (optional) */ char *pm_lang; /* Parameter language tag (optional) */ PM pm_next; /* Pointer to next element */ }; /* * Structure for storing parsed elements * of the Content-Type component. */ struct CTinfo { char *ci_type; /* content type */ char *ci_subtype; /* content subtype */ PM ci_first_pm; /* Pointer to first MIME parameter */ PM ci_last_pm; /* Pointer to last MIME parameter */ char *ci_comment; /* RFC-822 comments */ char *ci_magic; }; /* * Structure for storing decoded contents after * removing Content-Transfer-Encoding. */ struct cefile { char *ce_file; /* decoded content (file) */ FILE *ce_fp; /* decoded content (stream) */ int ce_unlink; /* remove file when done? */ }; /* * Primary structure for handling Content (Entity) * * Some more explanation of this: * * This structure recursively describes a complete MIME message. * At the top level, the c_first_hf list has a list of all message * headers. If the content-type is multipart (c_type == CT_MULTIPART) * then c_ctparams will contain a pointer to a struct multipart. * A struct multipart contains (among other things) a linked list * of struct part elements, and THOSE contain a pointer to the sub-part's * Content structure. * * An extra note for message/external-body parts. The enclosing * content structure is marked as a message/external-body; the c_ctparams * contains a pointer to a struct exbody, which contains a pointer to * (among other things) the "real" content (e.g., application/octet-stream). * The "real" content structure has the c_ctexbody pointer back to the * same struct exbody sees in the enclosing content structure (the struct * exbody contains parent pointers if you need to traverse up the content * structure). Hopefully this makes it clearer: * * Enclosing content: * Type: message/external-body * c_ctparams: pointer to "struct exbody" * c_ctexbody: NULL * * "Real" content: * Type: application/octet-stream (or whatever) * c_ctparams: NULL * c_ctexbody: pointer to "struct exbody" * */ struct Content { /* source (read) file */ char *c_file; /* read contents (file) */ FILE *c_fp; /* read contents (stream) */ int c_unlink; /* remove file when done? */ long c_begin; /* where content body starts in file */ long c_end; /* where content body ends in file */ /* linked list of header fields */ HF c_first_hf; /* pointer to first header field */ HF c_last_hf; /* pointer to last header field */ /* copies of MIME related header fields */ char *c_vrsn; /* MIME-Version: */ char *c_ctline; /* Content-Type: */ char *c_celine; /* Content-Transfer-Encoding: */ char *c_id; /* Content-ID: */ char *c_descr; /* Content-Description: */ char *c_dispo; /* Content-Disposition: */ char *c_dispo_type; /* Type of Content-Disposition */ PM c_dispo_first; /* Pointer to first disposition parm */ PM c_dispo_last; /* Pointer to last disposition parm */ char *c_partno; /* within multipart content */ /* Content-Type info */ struct CTinfo c_ctinfo; /* parsed elements of Content-Type */ int c_type; /* internal flag for content type */ int c_subtype; /* internal flag for content subtype */ /* Content-Transfer-Encoding info (decoded contents) */ struct cefile c_cefile; /* structure holding decoded content */ int c_encoding; /* internal flag for encoding type */ int c_reqencoding; /* Requested encoding (by mhbuild) */ /* Content-MD5 info */ int c_digested; /* have we seen this header before? */ unsigned char c_digest[16]; /* decoded MD5 checksum */ /* pointers to content-specific structures */ void *c_ctparams; /* content type specific data */ struct exbody *c_ctexbody; /* data for type message/external */ /* function pointers */ InitFunc c_ctinitfnx; /* parse content body */ OpenCEFunc c_ceopenfnx; /* get a stream to decoded contents */ CloseCEFunc c_ceclosefnx; /* release stream */ SizeCEFunc c_cesizefnx; /* size of decoded contents */ int c_umask; /* associated umask */ int c_rfc934; /* RFC 934 compatibility flag */ char *c_showproc; /* default, if not in profile */ char *c_termproc; /* for charset madness... */ char *c_storeproc; /* overrides profile entry, if any */ char *c_storage; /* write contents (file) */ char *c_folder; /* write contents (folder) */ }; /* * Flags for Content-Type (Content->c_type) */ #define CT_UNKNOWN 0x00 #define CT_APPLICATION 0x01 #define CT_AUDIO 0x02 #define CT_IMAGE 0x03 #define CT_MESSAGE 0x04 #define CT_MULTIPART 0x05 #define CT_TEXT 0x06 #define CT_VIDEO 0x07 #define CT_EXTENSION 0x08 /* * Flags for Content-Transfer-Encoding (Content->c_encoding) */ #define CE_UNKNOWN 0x00 #define CE_BASE64 0x01 #define CE_QUOTED 0x02 #define CE_8BIT 0x03 #define CE_7BIT 0x04 #define CE_BINARY 0x05 #define CE_EXTENSION 0x06 #define CE_EXTERNAL 0x07 /* for external-body */ /* * TEXT content */ /* Flags for subtypes of TEXT */ #define TEXT_UNKNOWN 0x00 #define TEXT_PLAIN 0x01 #define TEXT_RICHTEXT 0x02 #define TEXT_ENRICHED 0x03 /* Flags for character sets */ #define CHARSET_SPECIFIED 0x00 #define CHARSET_UNSPECIFIED 0x01 /* only needed when building drafts */ /* Structure for text content */ struct text { int tx_charset; /* flag for character set */ int lf_line_endings; /* Whether to use CR LF (0) or LF (1) line endings. The meaning of 0 was selected so that CR LF is the default, in accordance with RFC 2046, Sec. 4.1.1, Par. 1. */ }; /* * MULTIPART content */ /* Flags for subtypes of MULTIPART */ #define MULTI_UNKNOWN 0x00 #define MULTI_MIXED 0x01 #define MULTI_ALTERNATE 0x02 #define MULTI_DIGEST 0x03 #define MULTI_PARALLEL 0x04 #define MULTI_RELATED 0x05 /* Structure for subparts of a multipart content */ struct part { CT mp_part; /* Content structure for subpart */ struct part *mp_next; /* pointer to next subpart structure */ }; /* Main structure for multipart content */ struct multipart { char *mp_start; /* boundary string separating parts */ char *mp_stop; /* terminating boundary string */ char *mp_content_before; /* any content before the first subpart */ char *mp_content_after; /* any content after the last subpart */ struct part *mp_parts; /* pointer to first subpart structure */ }; /* * MESSAGE content */ /* Flags for subtypes of MESSAGE */ #define MESSAGE_UNKNOWN 0x00 #define MESSAGE_RFC822 0x01 #define MESSAGE_PARTIAL 0x02 #define MESSAGE_EXTERNAL 0x03 /* Structure for message/partial */ struct partial { char *pm_partid; int pm_partno; int pm_maxno; int pm_marked; int pm_stored; }; /* Structure for message/external */ struct exbody { CT eb_parent; /* pointer to controlling content structure */ CT eb_content; /* pointer to internal content structure */ char *eb_partno; char *eb_access; int eb_flags; char *eb_name; char *eb_permission; char *eb_site; char *eb_dir; char *eb_mode; unsigned long eb_size; char *eb_server; char *eb_subject; char *eb_body; char *eb_url; }; /* * APPLICATION content */ /* Flags for subtype of APPLICATION */ #define APPLICATION_UNKNOWN 0x00 #define APPLICATION_OCTETS 0x01 #define APPLICATION_POSTSCRIPT 0x02 /* * Structures for mapping types to their internal flags */ struct k2v { char *kv_key; int kv_value; }; extern struct k2v SubText[]; extern struct k2v Charset[]; extern struct k2v SubMultiPart[]; extern struct k2v SubMessage[]; extern struct k2v SubApplication[]; /* * Structures for mapping (content) types to * the functions to handle them. */ struct str2init { char *si_key; int si_val; InitFunc si_init; }; extern struct str2init str2cts[]; extern struct str2init str2ces[]; extern struct str2init str2methods[]; /* * prototypes */ CT parse_mime (char *); /* * Translate a composition file into a MIME data structure. Arguments are: * * infile - Name of input filename * autobuild - A flag to indicate if the composition file parser is * being run in automatic mode or not. In auto mode, * if a MIME-Version header is encountered it is assumed * that the composition file is already in MIME format * and will not be processed further. Otherwise, an * error is generated. * dist - A flag to indicate if we are being run by "dist". In * that case, add no MIME headers to the message. Existing * headers will still be encoded by RFC 2047. * directives - A flag to control whether or not build directives are * processed by default. * encoding - The default encoding to use when doing RFC 2047 header * encoding. Must be one of CE_UNKNOWN, CE_BASE64, or * CE_QUOTED. * maxunencoded - The maximum line length before the default encoding for * text parts is quoted-printable. * verbose - If 1, output verbose information during message composition * * Returns a CT structure describing the resulting MIME message. If the * -auto flag is set and a MIME-Version header is encountered, the return * value is NULL. */ CT build_mime (char *infile, int autobuild, int dist, int directives, int encoding, size_t maxunencoded, int verbose); int add_header (CT, char *, char *); int get_ctinfo (char *, CT, int); int params_external (CT, int); int open7Bit (CT, char **); void close_encoding (CT); char *ct_type_str (int); char *ct_subtype_str (int, int); int ct_str_type (const char *); int ct_str_subtype (int, const char *); const struct str2init *get_ct_init (int); const char *ce_str (int); const struct str2init *get_ce_method (const char *); char *content_charset (CT); void reverse_alternative_parts (CT); /* * Given a content structure, return true if the content has a disposition * of "inline". * * Arguments are: * * ct - Content structure to examine */ int is_inline(CT ct); /* * Given a list of messages, display information about them on standard * output. * * Arguments are: * * cts - An array of CT elements of messages that need to be * displayed. Array is terminated by a NULL. * headsw - If 1, display a column header. * sizesw - If 1, display the size of the part. * verbosw - If 1, display verbose information * debugsw - If 1, turn on debugging for the output. * disposw - If 1, display MIME part disposition information. * */ void list_all_messages(CT *cts, int headsw, int sizesw, int verbosw, int debugsw, int disposw); /* * List the content information of a single MIME part on stdout. * * Arguments are: * * ct - MIME Content structure to display. * toplevel - If set, we're at the top level of a message * realsize - If set, determine the real size of the content * verbose - If set, output verbose information * debug - If set, turn on debugging for the output * dispo - If set, display MIME part disposition information. * * Returns OK on success, NOTOK otherwise. */ int list_content(CT ct, int toplevel, int realsize, int verbose, int debug, int dispo); /* * Display content-appropriate information on MIME parts, descending recursively * into multipart content if appropriate. Uses list_content() for displaying * generic information. * * Arguments and return value are the same as list_content(). */ int list_switch(CT ct, int toplevel, int realsize, int verbose, int debug, int dispo); /* * Given a linked list of parameters, build an output string for them. This * string is designed to be concatenated on an already-built header. * * Arguments are: * * initialwidth - Current width of the header. Used to compute when to wrap * parameters on the first line. The following lines will * be prefixed by a tab (\t) character. * params - Pointer to head of linked list of parameters. * offsetout - The final line offset after all the parameters have been * output. May be NULL. * external - If set, outputting an external-body type and will not * output a "body" parameter. * Returns a pointer to the resulting parameter string. This string must * be free()'d by the caller. Returns NULL on error. */ char *output_params(size_t initialwidth, PM params, int *offsetout, int external); /* * Encode a parameter value using RFC 2231 encode. * * Arguments are: * * pm - PM containing the parameter value and related info. * output - Output buffer. * len - Size, in octets, of output buffer. * valuelen - Number of characters in the value * valueoff - Offset into value field (pm->pm_value). * index - If 0, output character set and language tag. */ size_t encode_param(PM pm, char *output, size_t len, size_t valuelen, size_t valueoff, int index); /* * Add a parameter to the parameter linked list. * * Arguments are: * * first - Pointer to head of linked list * last - Pointer to tail of linked list * name - Name of parameter * value - Value of parameter * nocopy - If set, will use the pointer values directly for "name" * and "value" instead of making their own copy. These * pointers will be free()'d later by the MIME routines, so * they should not be used after calling this function! * * Returns allocated parameter element */ PM add_param(PM *first, PM *last, char *name, char *value, int nocopy); /* * Replace (or add) a parameter to the parameter linked list. * * If the named parameter already exists on the parameter linked list, * replace the value with the new one. Otherwise add it to the linked * list. All parameters are identical to add_param(). */ PM replace_param(PM *first, PM *last, char *name, char *value, int nocopy); /* * Retrieve a parameter value from a parameter linked list. Convert to the * local character set if required. * * Arguments are: * * first - Pointer to head of parameter linked list. * name - Name of parameter. * replace - If characters in the parameter list cannot be converted to * the local character set, replace with this character. * fetchonly - If true, return pointer to original value, no conversion * performed. * * Returns parameter value if found, NULL otherwise. Memory must be free()'d * unless fetchonly is set. */ char *get_param(PM first, const char *name, char replace, int fetchonly); /* * Fetch a parameter value from a parameter structure, converting it to * the local character set. * * Arguments are: * * pm - Pointer to parameter structure * replace - If characters in the parameter list cannot be converted to * the local character set, replace with this character. * * Returns a pointer to the parameter value. Memory is stored in an * internal buffer, so the returned value is only valid until the next * call to get_param_value() or get_param() (get_param() uses get_param_value() * internally). */ char *get_param_value(PM pm, char replace); extern int checksw; /* Add Content-MD5 field */ /* * mhstore * Put it here because it uses the CT typedef. */ typedef struct mhstoreinfo *mhstoreinfo_t; mhstoreinfo_t mhstoreinfo_create(CT *, char *, const char *, int, int); int mhstoreinfo_files_not_clobbered(const mhstoreinfo_t); void mhstoreinfo_free(mhstoreinfo_t); void store_all_messages (mhstoreinfo_t); nmh-1.7.1-RC3/h/mime.h000644 007761 000024 00000003427 13205305704 014316 0ustar00kenhstaff000000 000000 /* mime.h -- definitions for MIME */ #define VRSN_FIELD "MIME-Version" #define VRSN_VALUE "1.0" #define XXX_FIELD_PRF "Content-" #define TYPE_FIELD "Content-Type" #define ENCODING_FIELD "Content-Transfer-Encoding" #define ID_FIELD "Content-ID" #define DESCR_FIELD "Content-Description" #define DISPO_FIELD "Content-Disposition" #define MD5_FIELD "Content-MD5" #define PSEUDOHEADER_PREFIX "Nmh-" #define ATTACH_FIELD PSEUDOHEADER_PREFIX "Attach" #define ATTACH_FIELD_ALT "Attach" #define MHBUILD_FILE_PSEUDOHEADER PSEUDOHEADER_PREFIX "mhbuild-file-" #define MHBUILD_ARGS_PSEUDOHEADER PSEUDOHEADER_PREFIX "mhbuild-args-" /* * Test for valid characters used in "token" * as defined in RFC2045 */ #define istoken(c) (isascii((unsigned char) c) \ && !isspace ((unsigned char) c) \ && !iscntrl ((unsigned char) c) && (c) != '(' \ && (c) != ')' && (c) != '<' && (c) != '>' \ && (c) != '@' && (c) != ',' && (c) != ';' \ && (c) != ':' && (c) != '\\' && (c) != '"' \ && (c) != '/' && (c) != '[' && (c) != ']' \ && (c) != '?' && (c) != '=') /* * Definitions for RFC 2231 encoding */ #define istspecial(c) ((c) == '(' || (c) == ')' || (c) == '<' || (c) == '>' \ || (c) == '@' || (c) == ',' || (c) == ';' \ || (c) == ':' || (c) == '\\' || (c) == '"' \ || (c) == '/' || (c) == '[' || (c) == ']' \ || (c) == '?' || (c) == '=') #define isparamencode(c) (!isascii((unsigned char) c) || \ iscntrl((unsigned char) c) || istspecial(c) || \ (c) == ' ' || (c) == '*' || (c) == '\'' || \ (c) == '%') #define MAXTEXTPERLN 78 #define MAXLONGLINE 998 #define CPERLIN 76 #define BPERLIN (CPERLIN / 4) #define LPERMSG 632 #define CPERMSG (LPERMSG * CPERLIN) nmh-1.7.1-RC3/h/mts.h000644 007761 000024 00000002006 13205305704 014162 0ustar00kenhstaff000000 000000 /* mts.h -- definitions for the mail system */ /* * Local and UUCP Host Name */ char *LocalName(int); char *SystemName(void); /* * Mailboxes */ extern char *mmdfldir; extern char *mmdflfil; extern char *uucpldir; extern char *uucplfil; extern char *spoollocking; #define MAILDIR (mmdfldir && *mmdfldir ? mmdfldir : getenv ("HOME")) #define MAILFIL (mmdflfil && *mmdflfil ? mmdflfil : getusername ()) char *getusername(void); char *getfullname(void); char *getlocalmbox(void); /* * Separators */ #define MMDF_DELIM "\001\001\001\001\n" /* * Read mts.conf file */ void mts_init (void); /* * MTS specific variables */ /* whether to speak SMTP, and over the network or directly to sendmail */ #define MTS_SMTP 0 #define MTS_SENDMAIL_SMTP 1 #define MTS_SENDMAIL_PIPE 2 extern int sm_mts; void save_mts_method (const char *); extern char *sendmail; /* * SMTP/POP stuff */ extern char *clientname; extern char *servers; extern char *pophost; /* * Global MailDelivery File */ extern char *maildelivery; nmh-1.7.1-RC3/h/netsec.h000644 007761 000024 00000027371 13243042053 014651 0ustar00kenhstaff000000 000000 /* netsec.h -- network-security library routines. * * These are a common set of routines to handle network security for * things like SASL and OpenSSL. */ typedef struct _netsec_context netsec_context; /* * Create a network security context. Returns the allocated network * security context. Cannot fail. */ netsec_context *netsec_init(void); /* * Shuts down the security context for a connection and frees all * associated resources. Will unconditionally close the network socket * as well. * * Arguments: * * ns_context - Network security context */ void netsec_shutdown(netsec_context *ns_context); /* * Sets the file descriptor for this connection. This will be used by * the underlying communication. * * Arguments: * * ns_context - Network security context * readfd - Read file descriptor of remote connection. * writefd - Write file descriptor of remote connection */ void netsec_set_fd(netsec_context *ns_context, int readfd, int writefd); /* * Set the userid used to authenticate to this connection. * * Arguments: * * ns_context - Network security context * userid - Userid to be used for authentication. Cannot be NULL. */ void netsec_set_userid(netsec_context *ns_context, const char *userid); /* * Set the hostname of the server we're connecting to. This is used * by the Cyrus-SASL library and by the TLS code. This must be called * before netsec_negotiate_tls() or netsec_set_sasl_params(). * * Arguments: * * ns_context - Network security context * hostname - FQDN of remote host. Cannot be NULL. */ void netsec_set_hostname(netsec_context *ns_context, const char *hostname); /* * Returns "snoop" status on current connection. * * Arguments: * * ns_context - Network security context * * Returns "1" if snoop is enabled, 0 if it is not. */ int netsec_get_snoop(netsec_context *ns_context); /* * Sets "snoop" status; if snoop is set to a nonzero value, network traffic * will be logged on standard error. * * Arguments: * * ns_context - Network security context * snoop - Integer value; set to nonzero to enable traffic logging */ void netsec_set_snoop(netsec_context *ns_context, int snoop); /* * A callback designed to handle the snoop output; it can be used by * a protocol to massage the data in a more user-friendly way. * * Arguments: * * ns_context - Network security context * string - String to output * len - Length of string * context - "Extra" context information to be used by callback. */ typedef void (netsec_snoop_callback)(netsec_context *ns_context, const char *string, size_t len, void *context); /* * Set the snoop callback function; will be used to handle protocol-specific * messages. Set to NULL to disable. * * Arguments: * * ns_context - Network security context * callback - Snoop callback * context - Extra context information to be passed to callback. */ void netsec_set_snoop_callback(netsec_context *ns_context, netsec_snoop_callback *callback, void *context); /* * A sample callback protocols can utilize; decode base64 tokens in the * output. The context is a pointer to an int which contains an offset * into the data to start decoding. */ extern netsec_snoop_callback netsec_b64_snoop_decoder; /* * Set the read timeout for this connection. * * Arguments: * * ns_context - Network security context * timeout - Read timeout, in seconds. */ void netsec_set_timeout(netsec_context *ns_context, int timeout); /* * Read a "line" from the network. This reads one CR/LF terminated line. * Returns a pointer to a NUL-terminated string. This memory is valid * until the next call to any read function. Will return an error if * the line does not terminate with a CR/LF. * * Arguments: * * ns_context - Network security context * length - Returned length of string * errstr - Error string * * Returns pointer to string, or NULL on error. */ char *netsec_readline(netsec_context *ns_context, size_t *length, char **errstr); /* * Read bytes from the network. * * Arguments: * * ns_context - Network security context * buffer - Read buffer * size - Buffer size * errstr - Error size * * Returns number of bytes read, or -1 on error. */ ssize_t netsec_read(netsec_context *ns_context, void *buffer, size_t size, char **errstr); /* * Write data to the network; if encryption is being performed, we will * do it. Data may be buffered; use netsec_flush() to flush any outstanding * data to the network. * * Arguments: * * ns_context - Network security context * buffer - Output buffer to write to network * size - Size of data to write to network * errstr - Error string * * Returns OK on success, NOTOK otherwise. */ int netsec_write(netsec_context *ns_context, const void *buffer, size_t size, char **errstr); /* * Write bytes using printf formatting * * Arguments: * * ns_context - Network security context * errstr - Error string * format - Format string * ... - Arguments for format string * * Returns OK on success, NOTOK on error. */ int netsec_printf(netsec_context *ns_context, char **errstr, const char *format, ...); /* * Write bytes using a va_list argument. * * Arguments: * * ns_context - Network security context * errstr - Error string * format - Format string * ap - stdarg list. * * Returns OK on success, NOTOK on error. */ int netsec_vprintf(netsec_context *ns_context, char **errstr, const char *format, va_list ap); /* * Flush any buffered bytes to the network. * * Arguments: * * ns_context - Network security context * errstr - Error string * * Returns OK on success, NOTOK on error. */ int netsec_flush(netsec_context *ns_context, char **errstr); /* * Enumerated types for the type of message we are sending/receiving. */ enum sasl_message_type { NETSEC_SASL_START, /* Start of SASL authentication */ NETSEC_SASL_READ, /* Reading a message */ NETSEC_SASL_WRITE, /* Writing a message */ NETSEC_SASL_FINISH, /* Complete SASL exchange */ NETSEC_SASL_CANCEL /* Cancel a SASL exchange */ }; /* * The SASL callback; this is designed to parse a protocol-specific * message and return the SASL protocol message back. * * The meaning of the arguments to the callback depend on the mtype * arguments. See below for more detail. * * Arguments: * * mtype - The type of message we are processing (read/write/cancel). * indata - A pointer to any input data. * indatasize - The size of the input data in bytes * outdata - Output data (freed by caller) * outdatasize - Size of output data * errstr - An error string to be returned (freed by caller). * * As a general note, plugins should perform their own I/O. Buffers returned * by NETSEC_SASL_READ should be allocated by the plugins and will be freed * by the netsec package. Error messages returned should be created by * netsec_err(). * * Parameter interpretation based on mtype value: * * NETSEC_SASL_START - Create a protocol message that starts SASL * authentication. If an initial response is * supported, indata and indatasize will contain it. * Otherwise they will be set to NULL and 0. * NETSEC_SASL_READ - Parse and decode a protocol message and extract * out the SASL payload data. indata will be set * to NULL; the callback must read in the necessary * data using the appropriate netsec function. * outdata/outdatasize should contain the decoded * SASL message (again, must be free()d by the caller). * NETSEC_SASL_WRITE - Generate a protocol message to send over the * network. indata/indatasize will contain the * SASL payload data. * NETSEC_SASL_FINISH - Process the final SASL message exchange; at * this point SASL exchange should have completed * and we should get a message back from the server * telling us whether or not authentication is * successful. All buffer parameters are NULL. * NETSEC_SASL_CANCEL - Generate a protocol message that cancels the * SASL protocol exchange; outdata/outdatasize * should contain this message. * * The callback should return OK on success, NOTOK on failure. Depending * at the point of the authentication exchange, the callback may be asked * to generate a cancel message. */ typedef int (*netsec_sasl_callback)(enum sasl_message_type mtype, unsigned const char *indata, unsigned int indatasize, unsigned char **outdata, unsigned int *outdatasize, char **errstr); /* * Sets the SASL parameters for this connection. If this function is * not called or is called with NULL for arguments, SASL authentication * will not be attempted for this connection. * * The caller must provide a callback to parse the protocol and return * the SASL protocol messages (see above for callback details). * * Arguments: * * ns_context - Network security context * service - Service name (set to NULL to disable SASL). * mechanism - The mechanism desired by the user. If NULL, the SASL * library will attempt to negotiate the best mechanism. * callback - SASL protocol callbacks * errstr - Error string. * * Returns NOTOK if SASL is not supported. */ int netsec_set_sasl_params(netsec_context *ns_context, const char *service, const char *mechanism, netsec_sasl_callback callback, char **errstr); /* * Start SASL negotiation. The Netsec library will use the callbacks * supplied in netsec_set_sasl_params() to format and parse the protocol * messages. * * Arguments: * * ns_context - Network security context * mechlist - Space-separated list of supported SASL mechanisms * errstr - An error string to be returned upon error. * * Returns OK on success, NOTOK on failure. */ int netsec_negotiate_sasl(netsec_context *ns_context, const char *mechlist, char **errstr); /* * Returns the chosen SASL mechanism by the SASL library or netsec. * * Arguments: * * ns_context - Network security context * * Returns a string containing the chosen mech, or NULL if SASL is not * supported or in use. */ char *netsec_get_sasl_mechanism(netsec_context *ns_context); /* * Set the OAuth service name used to retrieve the OAuth parameters from * user's profile. Just calling this function is not enough to guarantee * that XOAUTH2 authentication will be performed; the appropriate mechanism * name must be passed into netsec_set_sasl_params(). * * Arguments: * * ns_context - Network security context * service - OAuth2 service names. * * Returns NOTOK if OAuth2 is not supported. */ int netsec_set_oauth_service(netsec_context *ns_context, const char *service); /* * Controls whether or not TLS will be negotiated for this connection. * * Note: callers still have to call netsec_tls_negotiate() to start * TLS negotiation at the appropriate point in the protocol. The * remote hostname (controlled by netsec_set_hostname()) should have * already been set before this function is called unless certificate * verification is disabled. * * Arguments * * tls - If nonzero, enable TLS. Otherwise disable TLS * negotiation. * noverify - If nonzero, disable server certificate and hostname * validation. * * Returns NOTOK if TLS is not supported or was unable to initialize. */ int netsec_set_tls(netsec_context *context, int tls, int noverify, char **errstr); /* * Start TLS negotiation on this protocol. This connection should have * netsec_set_tls() called on it. * * Arguments: * * ns_context - Network security context * errstr - Error string upon failure. * * Returns OK on success, NOTOK on failure. */ int netsec_negotiate_tls(netsec_context *ns_context, char **errstr); /* * Allocate and format an error string; should be used by plugins * to report errors. * * Arguments: * * errstr - Error string to be returned * format - printf(3) format string * ... - Arguments to printf(3) * */ void netsec_err(char **errstr, const char *format, ...); nmh-1.7.1-RC3/h/nmh.h000644 007761 000024 00000002663 13243042053 014147 0ustar00kenhstaff000000 000000 /* nmh.h -- system configuration header file */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #ifndef NDEBUG /* See etc/gen-ctype-checked.c. */ # include #endif #include #ifdef HAVE_STDBOOL_H # include #else # define bool int # define true 1 # define false 0 #endif #include #include # include #include #include #include #ifdef HAVE_SYS_PARAM_H # include #endif #include #include #include /* * we should be getting this value from pathconf(_PC_PATH_MAX) */ #ifndef PATH_MAX # ifdef MAXPATHLEN # define PATH_MAX MAXPATHLEN # else /* so we will just pick something */ # define PATH_MAX 1024 # endif #endif /* * we should get this value from sysconf(_SC_NGROUPS_MAX) */ #ifndef NGROUPS_MAX # ifdef NGROUPS # define NGROUPS_MAX NGROUPS # else # define NGROUPS_MAX 16 # endif #endif /* * we should be getting this value from sysconf(_SC_OPEN_MAX) */ #ifndef OPEN_MAX # ifdef NOFILE # define OPEN_MAX NOFILE # else /* so we will just pick something */ # define OPEN_MAX 64 # endif #endif #ifndef HAVE_GETLINE ssize_t getline(char **lineptr, size_t *n, FILE *stream); #endif /* * Defaults for programs if they aren't configured in a user's profile */ #define DEFAULT_PAGER "more" #define DEFAULT_EDITOR "vi" nmh-1.7.1-RC3/h/oauth.h000644 007761 000024 00000016732 13243042053 014507 0ustar00kenhstaff000000 000000 /* oauth.h -- OAuth 2.0 implementation for XOAUTH2 in SMTP and POP3. * * Google defined XOAUTH2 for SMTP, and that's what we use here. If other * providers implement XOAUTH2 or some similar OAuth-based SMTP authentication * protocol, it should be simple to extend this. * * OAuth https://tools.ietf.org/html/rfc6749 * SMTP https://developers.google.com/gmail/xoauth2_protocol * POP3 http://googleappsdeveloper.blogspot.com/2014/10/updates-on-authentication-for-gmail.html * * Presumably [2] should document POP3 and that is an over-sight. As it stands, * that blog post is the closest we have to documentation. * * According to [1] 2.1 Client Types, this is a "native application", a * "public" client. * * To summarize the flow: * * 1. User runs mhlogin which prints a URL the user must visit, and prompts for * a code retrieved from that page. * * 2. User visits this URL in browser, signs in with some Google account, and * copies and pastes the resulting code back to mhlogin. * * 3. mhlogin does HTTP POST to Google to exchange the user-provided code for a * short-lived access token and a long-lived refresh token. * * 4. send uses the access token in SMTP auth if not expired. If it is expired, * it does HTTP POST to Google including the refresh token and gets back a * new access token (and possibly refresh token). If the refresh token has * become invalid (e.g. if the user took some reset action on the Google * account), the user must use mhlogin again, then re-run send. */ typedef enum { /* error loading profile */ MH_OAUTH_BAD_PROFILE = OK + 1, /* error initializing libcurl */ MH_OAUTH_CURL_INIT, /* local error initializing HTTP request */ MH_OAUTH_REQUEST_INIT, /* error executing HTTP POST request */ MH_OAUTH_POST, /* HTTP response body is too big. */ MH_OAUTH_RESPONSE_TOO_BIG, /* Can't process HTTP response body. */ MH_OAUTH_RESPONSE_BAD, /* The authorization server rejected the grant (authorization code or * refresh token); possibly the user entered a bad code, or the refresh * token has become invalid, etc. */ MH_OAUTH_BAD_GRANT, /* HTTP server indicates something is wrong with our request. */ MH_OAUTH_REQUEST_BAD, /* Attempting to refresh an access token without a refresh token. */ MH_OAUTH_NO_REFRESH, /* requested user not in cred file */ MH_OAUTH_CRED_USER_NOT_FOUND, /* error loading serialized credentials */ MH_OAUTH_CRED_FILE } mh_oauth_err_code; typedef struct mh_oauth_ctx mh_oauth_ctx; typedef struct mh_oauth_cred mh_oauth_cred; typedef struct mh_oauth_service_info mh_oauth_service_info; struct mh_oauth_service_info { /* Name of service, so we can search static internal services array * and for determining default credential file name. */ char *name; /* Human-readable name of the service; in mh_oauth_ctx::svc this is not * another buffer to free, but a pointer to either static SERVICE data * (below) or to the name field. */ char *display_name; /* [1] 2.2 Client Identifier, 2.3.1 Client Password */ char *client_id; /* [1] 2.3.1 Client Password */ char *client_secret; /* [1] 3.1 Authorization Endpoint */ char *auth_endpoint; /* [1] 3.1.2 Redirection Endpoint */ char *redirect_uri; /* [1] 3.2 Token Endpoint */ char *token_endpoint; /* [1] 3.3 Access Token Scope */ char *scope; }; /* * Do the complete dance for XOAUTH2 as used by POP3 and SMTP. * * Load tokens for svc from disk, refresh if necessary, and return the * client response in client_response and client_response_len. * * If refreshing, writes freshened tokens to disk. * * Exits via adios on any error. * * Always returns OK for now, but in the future could return NOTOK on error. */ int mh_oauth_do_xoauth(const char *user, const char *svc, unsigned char **oauth_res, size_t *oauth_res_len, FILE *log); /* * Allocate and initialize a new OAuth context. * * Caller must call mh_oauth_free(ctx) when finished, even on error. * * svc_name must point to a null-terminated string identifying the service * provider. Support for "gmail" is built-in; anything else must be defined in * the user's profile. The profile can also override "gmail" settings. * * Accesses global m_defs via context_find. * * On error, return FALSE and set an error in ctx; ctx is always allocated. */ boolean mh_oauth_new(mh_oauth_ctx **ctx, const char *svc_name); /* * Free all resources associated with ctx. */ void mh_oauth_free(mh_oauth_ctx *ctx); /* * Return null-terminated human-readable name of the service, e.g. "Gmail". * * Never returns NULL. */ const char * mh_oauth_svc_display_name(const mh_oauth_ctx *ctx); /* * Enable logging for subsequent operations on ctx. * * log must not be closed until after mh_oauth_free. * * For all HTTP requests, the request is logged with each line prefixed with * "< ", and the response with "> ". Other messages are prefixed with "* ". */ void mh_oauth_log_to(FILE *log, mh_oauth_ctx *ctx); /* * Return the error code after some function indicated an error. * * Must not be called if an error was not indicated. */ mh_oauth_err_code mh_oauth_get_err_code(const mh_oauth_ctx *ctx); /* * Return null-terminated error message after some function indicated an error. * * Never returns NULL, but must not be called if an error was not indicated. */ const char * mh_oauth_get_err_string(mh_oauth_ctx *ctx); /* * Return the null-terminated URL the user needs to visit to authorize access. * * URL may be invalidated by subsequent calls to mh_oauth_get_authorize_url, * mh_oauth_authorize, or mh_oauth_refresh. * * On error, return NULL. */ const char * mh_oauth_get_authorize_url(mh_oauth_ctx *ctx); /* * Exchange code provided by the user for access (and maybe refresh) token. * * On error, return NULL. */ mh_oauth_cred * mh_oauth_authorize(const char *code, mh_oauth_ctx *ctx); /* * Refresh access (and maybe refresh) token if refresh token present. * * On error, return FALSE and leave cred untouched. */ boolean mh_oauth_refresh(mh_oauth_cred *cred); /* * Return whether access token is present and not expired at time T. */ boolean mh_oauth_access_token_valid(time_t t, const mh_oauth_cred *cred); /* * Free all resources associated with cred. */ void mh_oauth_cred_free(mh_oauth_cred *cred); /* * Return the null-terminated file name for storing this service's OAuth tokens. * * Accesses global m_defs via context_find. * * Never returns NULL. */ const char * mh_oauth_cred_fn(const char *svc_name); /* * Serialize OAuth tokens to file. * * On error, return FALSE. */ boolean mh_oauth_cred_save(FILE *fp, mh_oauth_cred *cred, const char *user); /* * Load OAuth tokens from file. * * Calls m_getfld(), which writes to stderr with advise(). * * On error, return NULL. */ mh_oauth_cred * mh_oauth_cred_load(FILE *fp, mh_oauth_ctx *ctx, const char *user); /* * Return null-terminated SASL client response for XOAUTH2 from access token. * * Store the length in res_len. * * Must not be called except after successful mh_oauth_access_token_valid or * mh_oauth_refresh call; i.e. must have a valid access token. */ const char * mh_oauth_sasl_client_response(size_t *res_len, const char *user, const mh_oauth_cred *cred); /* * Retrieve the various entries for the OAuth mechanism */ boolean mh_oauth_get_service_info(const char *svc_name, mh_oauth_service_info *svcinfo, char *errbuf, size_t errbuflen); nmh-1.7.1-RC3/h/picksbr.h000644 007761 000024 00000000221 13243042053 015006 0ustar00kenhstaff000000 000000 /* picksbr.h -- definitions for picksbr.c */ /* * prototypes */ int pcompile (char **, char *); int pmatches (FILE *, int, long, long, int); nmh-1.7.1-RC3/h/popsbr.h000644 007761 000024 00000000624 13243042053 014665 0ustar00kenhstaff000000 000000 /* popsbr.h -- header for POP client subroutines */ /* TLS flags */ #define P_INITTLS 0x01 #define P_NOVERIFY 0x02 int pop_init (char *, char *, char *, char *, int, int, char *, int, const char *); int pop_fd (char *, int, char *, int); int pop_stat (int *, int *); int pop_retr (int, int (*)(char *)); int pop_dele (int); int pop_quit (void); int pop_done (void); int pop_set (int, int, int); nmh-1.7.1-RC3/h/prototypes.h000644 007761 000024 00000035075 13243042053 015620 0ustar00kenhstaff000000 000000 /* prototypes.h -- various prototypes * * If you modify functions here, please document their current behavior * as much as practical. */ /* * prototype from config.h */ char *etcpath(char *); /* * prototypes from the nmh subroutine library */ struct msgs_array; void add_profile_entry (const char *, const char *); void inform(char *fmt, ...); void adios (const char *, const char *, ...) NORETURN; void admonish (char *, char *, ...); void advertise (const char *, char *, const char *, va_list); void advise (const char *, const char *, ...); char **argsplit (char *, char **, int *); void argsplit_msgarg (struct msgs_array *, char *, char **); void argsplit_insert (struct msgs_array *, char *, char **); void arglist_free (char *, char **); void ambigsw (const char *, const struct swit *); int atooi(char *); char **brkstring (char *, char *, char *); /* * Check to see if we can display a given character set natively. * Arguments include: * * str - Name of character set to check against * len - Length of "str" * * Returns 1 if the specified character set can be displayed natively, * 0 otherwise. */ int check_charset (char *, int); int client(char *, char *, char *, int, int); void closefds(int); char *concat (const char *, ...); int context_del (char *); char *context_find (const char *); char *context_find_by_type (const char *, const char *, const char *); int context_find_prefix(const char *); int context_foil (char *); void context_read (void); void context_replace (char *, char *); void context_save (void); char **copyip (char **, char **, int); void cpydata (int, int, const char *, const char *); void cpydgst (int, int, char *, char *); char *cpytrim (const char *); char *rtrim (char *); int decode_rfc2047 (char *, char *, size_t); void discard (FILE *); /* * Decode two characters into their quoted-printable representation. * * Arguments are: * * byte1 - First character of Q-P representation * byte2 - Second character of Q-P representation * * Returns the decoded value, -1 if the conversion failed. */ int decode_qp(unsigned char byte1, unsigned char byte2); int default_done (int); /* * Encode a message header using RFC 2047 encoding. If the message contains * no non-ASCII characters, then leave the header as-is. * * Arguments include: * * name - Message header name * value - Message header content; must point to allocated memory * (may be changed if encoding is necessary) * encoding - Encoding type. May be one of CE_UNKNOWN (function chooses * the encoding), CE_BASE64 or CE_QUOTED * charset - Charset used for encoding. If NULL, obtain from system * locale. * * Returns 0 on success, any other value on failure. */ int encode_rfc2047(const char *name, char **value, int encoding, const char *charset); void escape_display_name (char *, size_t); void escape_local_part (char *, size_t); int ext_hook(char *, char *, char *); int fdcompare (int, int); int folder_addmsg (struct msgs **, char *, int, int, int, int, char *); int folder_delmsgs (struct msgs *, int, int); void folder_free (struct msgs *); int folder_pack (struct msgs **, int); /* * Read a MH folder structure and return an allocated "struct msgs" * corresponding to the contents of the folder. * * Arguments include: * * name - Name of folder * lockflag - If true, write-lock (and keep open) metadata files. * See comments for seq_read() for more information. */ struct msgs *folder_read (char *name, int lockflag); struct msgs *folder_realloc (struct msgs *, int, int); /* * Flush standard output, read a line from standard input into a static buffer, * zero out the newline, and return a pointer to the buffer. * On error, return NULL. */ const char *read_line(void); /* * Print null-terminated PROMPT to and flush standard output. Read answers from * standard input until one matches an entry in SWITCHES. When one matches, * return its swret field. Return 0 on EOF. */ int read_switch(const char *PROMPT, const struct swit *SWITCHES); /* * If standard input is not a tty, return 1 without printing anything. Else, * print null-terminated PROMPT to and flush standard output. Read answers from * standard input until one is "yes" or "no", returning 1 for "yes" and 0 for * "no". Also return 0 on EOF. */ int read_yes_or_no_if_tty(const char *PROMPT); /* * Print null-terminated PROMPT to and flush standard output. Read multi-word * answers from standard input until a first word matches an entry in SWITCHES. * When one matches, return a pointer to an array of pointers to the words. * Return NULL on EOF, interrupt, or other error. */ char **read_switch_multiword(const char *PROMPT, const struct swit *SWITCHES); /* * Same as read_switch_multiword but using readline(3) for input. */ #ifdef READLINE_SUPPORT char **read_switch_multiword_via_readline (char *, struct swit *); #endif /* READLINE_SUPPORT */ char **getarguments (char *, int, char **, int); /* * Returns the MIME character set indicated by the current locale setting. * Should be used by routines that want to convert to/from the local * character set, or if you want to check to see if you can display content * in the local character set. */ char *get_charset(void); /* Return malloc'd copy of str, or of "" if NULL, exit on failure. */ char *getcpy(const char *str); char *get_default_editor(void); char *getfolder(int); /* * Get a string from the terminfo database for the current terminal. * * Retrieve the specified terminfo capability and return a string that * can be output to the terminal. The string returned has already been * processed by tputs(), so it is safe to output directly. The return * value of this function is valid until the next call. * * Arguments: * * capability - The name of the terminfo capability (see terminfo(5)). * * Returns a tputs-processed string, or NULL if terminal initialization failed * or the capability wasn't found. */ char *get_term_stringcap(char *capability); /* * Get a parameterized string from the terminfo database for the current * terminal. * * We don't yet have a standardized tparm() that will take a stdarg * argument. Right now we don't want many parameters, so we only * take two. Everything gets passed to tparm() as-is. If we need * a capability with more arguments, we'll just add more later. * * Arguments: * * capability - The name of the terminfo capability (see terminfo(5)). * arg1..argN - Arguments 1-N. * * Returns a tparm and tputs-processed string, or NULL if there was a problem * initialising the terminal or retrieving the capability. */ char *get_term_stringparm(char *capability, long arg1, long arg2); /* * Get a number from the terminfo database for the current terminal. * * Retrieve the specified terminfo capability and return the numeric * value of that capability from the terminfo database. * * Arguments: * * capability - The name of the terminfo capability (see terminfo(5)). * * Returns the output of tigetnum() for that capability, or -1 if it was * unable to initialize the terminfo database. */ int get_term_numcap(char *capability); int m_atoi (char *); char *m_backup (const char *); int m_convert (struct msgs *, char *); char *m_draft (char *, char *, 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 *, char[NAMESZ], char *, int *, FILE *); int m_gmprot (void); char *m_name (int); void m_unknown(m_getfld_state_t *, FILE *); /* * Clear the screen, using the appropriate entry from the terminfo database */ void nmh_clear_screen(void); char *nmh_getpass(const char *); char *new_fs (char *, char *, char *); char *path(char *, int); int pidwait (pid_t, int); int pidstatus (int, FILE *, char *); char *pluspath(char *); void print_help (char *, struct swit *, int); void print_intro (FILE *, int); void print_sw (const char *, const struct swit *, char *, FILE *); void print_version (char *); void push (void); char *r1bindex(char *, int); void readconfig (struct node **, FILE *, const char *, int); int refile (char **, char *); /* * Read our credentials file and (optionally) ask the user for anything * missing. * * Arguments: * * host - Hostname (to scan credentials file) * aname - Pointer to filled-in username * apass - Pointer to filled-in password * flags - One or more of RUSERPASS_NO_PROMPT_USER, * RUSERPASS_NO_PROMPT_PASSWORD */ void ruserpass (const char *host, char **aname, char **apass, int flags); #define RUSERPASS_NO_PROMPT_USER 0x01 #define RUSERPASS_NO_PROMPT_PASSWORD 0x02 int remdir (char *); void scan_detect_mbox_style (FILE *); void scan_finished(void); int seq_addmsg (struct msgs *, char *, int, int, int); int seq_addsel (struct msgs *, char *, int, int); char *seq_bits (struct msgs *); int seq_delmsg (struct msgs *, char *, int); int seq_delsel (struct msgs *, char *, int, int); int seq_getnum (struct msgs *, char *); char *seq_list (struct msgs *, char *); int seq_nameok (char *); void seq_print (struct msgs *, char *); void seq_printall (struct msgs *); /* * Read the sequence files for the folder referenced in the given * struct msgs and populate the sequence entries in the struct msgs. * * Arguments: * * mp - Folder structure to add sequence entries to * lockflag - If true, obtain a write lock on the sequence file. * Additionally, the sequence file will remain open * and a pointer to the filehandle will be stored in * folder structure, where it will later be used by * seq_save(). * * Return values: * OK - successfully read the sequence files, or they don't exist * NOTOK - failed to lock sequence file */ int seq_read (struct msgs * mp, int lockflag); void seq_save (struct msgs *); void seq_setcur (struct msgs *, int); void seq_setprev (struct msgs *); void seq_setunseen (struct msgs *, int); int showfile (char **, char *); int smatch(const char *, const struct swit *); /* * Convert a set of bit flags to printable format. * * Arguments: * * buffer - Buffer to output string to. * size - Size of buffer in bytes. Buffer is always NUL terminated. * flags - Binary flags to output * bitfield - Textual representation of bits to output. This string * is in the following format: * * Option byte 0x01 STRING1 0x02 STRING2 .... * * The first byte is an option byte to snprintb(). Currently the only option * supported is 0x08, which indicates that the flags should be output in * octal format; if the option byte is any other value, the flags will be * output in hexadecimal. * * After the option bytes are series of text strings, prefixed by the number * of the bit they correspond to. For example, the bitfield string: * * "\020\01FLAG1\02FLAG2\03FLAG3\04FLAG4" * * will output the following string if "flags" is set to 0x09: * * 0x2 * * You don't have to use octal in the bitfield string, that's just the * convention currently used by the nmh code. The order of flags in the * bitfield string is not significant, but again, general convention is * from least significant bit to most significant. */ char *snprintb (char *buffer, size_t size, unsigned flags, char *bitfield); int ssequal (const char *, const char *); int stringdex (char *, char *); char *trimcpy (char *); int uprf (const char *, const char *); int vfgets (FILE *, char **); /* * Output the local character set name, but make sure it is suitable for * 8-bit characters. */ char *write_charset_8bit (void); /* * some prototypes for address parsing system * (others are in addrsbr.h) */ char *LocalName(int); char *SystemName(void); /* * prototypes for some routines in uip */ int annotate (char *, char *, char *, int, int, int, int); void annolist(char *, char *, char *, int); void annopreserve(int); void m_pclose(void); int make_intermediates(char *); int mhl(int, char **); int mhlsbr(int, char **, FILE *(*)(char *)); int distout (char *, char *, char *); void replout (FILE *, char *, char *, struct msgs *, int, int, char *, char *, char *, int); int sc_length(void); int sc_width(void); int build_form (char *, char *, int *, char *, char *, char *, char *, char *, char *); int sendsbr (char **, int, char *, char *, struct stat *, int, const char *); int SOprintf (char *, ...); int what_now (char *, int, int, char *, char *, int, struct msgs *, char *, int, char *, int); int WhatNow(int, char **); /* Includes trailing NUL */ #define BASE64SIZE(x) ((((x + 2) / 3) * 4) + 1) /* * Copy data from one file to another, converting to base64-encoding. * * Arguments include: * * in - Input filehandle (unencoded data) * out - Output filename (base64-encoded data) * crlf - If set, output encoded CRLF for every LF on input. * * Returns OK on success, NOTOK otherwise. */ int writeBase64aux(FILE *in, FILE *out, int crlf); int writeBase64 (const unsigned char *, size_t, unsigned char *); int writeBase64raw (const unsigned char *, size_t, unsigned char *); /* * encoded - the string to be decoded * decoded - the decoded bytes * len - number of decoded bytes * skip-crs - non-zero for text content, and for which CR's should be * skipped * digest - for an MD5 digest, it can be null */ int decodeBase64 (const char *encoded, unsigned char **decoded, size_t *len, int skip_crs, unsigned char *digest); void hexify (const unsigned char *, size_t, char **); /* * credentials management */ void init_credentials_file(void); /* * Allocate and return a credentials structure. The credentials structure * is now opaque; you need to use accessors to get inside of it. The * accessors will only prompt the user for missing fields if they are * needed. * * Arguments: * * host - Hostname we're connecting to (used to search credentials file) * user - Username we are logging in as; can be NULL. * * Returns NULL on error, otherwise an allocated nmh_creds structure. */ nmh_creds_t nmh_get_credentials (const char *host, const char *user); /* * Retrieve the user from a nmh_creds structure. May prompt the user * if one is not defined. * * Arguments: * * creds - Structure from previous nmh_get_credentials() call * * Returns NULL on error, otherwise a NUL-terminated string containing * the username. Points to allocated memory in the credentials structure * that is free()d by nmh_free_credentials(). */ const char *nmh_cred_get_user(nmh_creds_t creds); /* * Retrieve the password from an nmh_creds structure. Otherwise identical * to nmh_cred_get_user(). */ const char *nmh_cred_get_password(nmh_creds_t creds); /* * Free an allocated nmh_creds structure. */ void nmh_credentials_free(nmh_creds_t creds); nmh-1.7.1-RC3/h/rcvmail.h000644 007761 000024 00000000277 13243042053 015021 0ustar00kenhstaff000000 000000 /* rcvmail.h -- rcvmail hook definitions */ #include #include #include #include #include #define RCV_MOK 0 #define RCV_MBX 1 nmh-1.7.1-RC3/h/scansbr.h000644 007761 000024 00000002167 13243042053 015017 0ustar00kenhstaff000000 000000 /* scansbr.h -- definitions for scan() */ #define SCNENC 2 /* message just fine, but encrypted(!!) */ #define SCNMSG 1 /* message just fine */ #define SCNEOF 0 /* empty message */ #define SCNERR (-1) /* error message */ #define SCNNUM (-2) /* number out of range */ #define SCNFAT (-3) /* fatal error */ /* * default format for `scan' and `inc' */ #ifndef UK #define FORMAT \ "%4(msg)%<(cur)+%| %>%<{replied}-%?{encrypted}E%| %>\ %02(mon{date})/%02(mday{date})%<{date} %|*%>\ %<(mymbox{from})%<{to}To:%14(decode(friendly{to}))%>%>\ %<(zero)%17(decode(friendly{from}))%> \ %(decode{subject})%<{body}<<%{body}>>%>\n" #else #define FORMAT \ "%4(msg)%<(cur)+%| %>%<{replied}-%?{encrypted}E%| %>\ %02(mday{date})/%02(mon{date})%<{date} %|*%>\ %<(mymbox{from})%<{to}To:%14(decode(friendly{to}))%>%>\ %<(zero)%17(decode(friendly{from}))%> \ %(decode{subject})%<{body}<<%{body}>>%>\n" #endif #define WIDTH 78 /* * prototypes */ int scan (FILE *, int, int, char *, int, int, int, char *, long, int, charstring_t *); nmh-1.7.1-RC3/h/signals.h000644 007761 000024 00000000540 13243042053 015015 0ustar00kenhstaff000000 000000 /* signals.h -- header file for nmh signal interface */ #ifdef HAVE_CONFIG_H # include #endif #include /* * The type for a signal handler */ typedef void (*SIGNAL_HANDLER)(int); /* * prototypes */ SIGNAL_HANDLER SIGNAL (int, SIGNAL_HANDLER); SIGNAL_HANDLER SIGNAL2 (int, SIGNAL_HANDLER); int setup_signal_handlers(void); nmh-1.7.1-RC3/h/tws.h000644 007761 000024 00000003640 13243042053 014176 0ustar00kenhstaff000000 000000 /* tws.h -- time routines. */ /* A timezone given as a numeric-only offset will be treated specially if it's in a zone that observes Daylight Saving Time. For instance, during DST, a Date: like "Mon, 24 Jul 2000 12:31:44 -0700" will be printed as "Mon, 24 Jul 2000 12:31:44 PDT". Without the code activated by the following #define, that would be incorrectly printed as "...MST". */ struct tws { int tw_sec; /* seconds after the minute - [0, 61] */ int tw_min; /* minutes after the hour - [0, 59] */ int tw_hour; /* hour since midnight - [0, 23] */ int tw_mday; /* day of the month - [1, 31] */ int tw_mon; /* months since January - [0, 11] */ int tw_year; /* 4 digit year (e.g. 1997) */ int tw_wday; /* days since Sunday - [0, 6] */ int tw_yday; /* days since January 1 - [0, 365] */ int tw_zone; time_t tw_clock; /* if != 0, corresponding calendar value */ int tw_flags; }; #define TW_NULL 0x0000 #define TW_SDAY 0x0003 /* how day-of-week was determined */ #define TW_SEXP 0x0001 /* explicitly given */ #define TW_SIMP 0x0002 /* implicitly given */ #define TW_SZEXP 0x0004 /* Explicit timezone. */ #define TW_DST 0x0010 /* daylight savings time */ #define TW_ZONE 0x0020 /* use numeric timezones only */ #define TW_SUCC 0x0040 /* Parsing was successful. */ #define dtwszone(tw) dtimezone (tw->tw_zone, tw->tw_flags) extern char *tw_dotw[]; extern char *tw_ldotw[]; extern char *tw_moty[]; /* * prototypes */ char *dtime (time_t *, int); char *dtimenow (int); char *dctime (struct tws *); struct tws *dlocaltimenow (void); struct tws *dlocaltime (time_t *); struct tws *dgmtime (time_t *); char *dasctime (struct tws *, int); char *dtimezone (int, int); int twsort (struct tws *, struct tws *); time_t dmktime (struct tws *); void set_dotw (struct tws *); struct tws *dparsetime (char *); nmh-1.7.1-RC3/h/utils.h000644 007761 000024 00000010073 13243042053 014517 0ustar00kenhstaff000000 000000 /* utils.h -- utility prototypes */ /* PLURALS gives a pointer to the string "s" when n isn't 1, and to the * empty string "" when it is. Suitable for obtaining the plural `s' * used for English nouns. It treats -1 as plural, as does GNU gettext. * Having output vary for plurals is annoying for those writing parsers; * better to phrase the output such that no test is needed, e.g. * "messages found: 42". */ extern const char plurals[]; #define PLURALS(n) (plurals + ((n) == 1)) /* Call malloc(3), exiting on NULL return. */ void *mh_xmalloc(size_t size); /* Call realloc(3), exiting on NULL return. */ void *mh_xrealloc(void *ptr, size_t size); /* Call calloc(3), exiting on NULL return. */ void *mh_xcalloc(size_t nelem, size_t elsize); /* Duplicate a NUL-terminated string, exit on failure. */ char *mh_xstrdup(const char *src); /* Call free(3), if ptr isn't NULL. */ void mh_xfree(void *ptr); /* Set p to point to newly allocated, uninitialised, memory. */ #define NEW(p) ((p) = mh_xmalloc(sizeof *(p))) /* Set p to point to newly allocated, zeroed, memory. */ #define NEW0(p) ((p) = mh_xcalloc(1, sizeof *(p))) char *pwd(void); char *add(const char *, char *); char *addlist(char *, const char *); int folder_exists(const char *); void create_folder(char *, int, void (*)(int)); int num_digits(int); /* * A vector of char array, used to hold a list of string message numbers * or command arguments. */ struct msgs_array { int max, size; char **msgs; }; /* * Same as msgs_array, but for a vector of ints */ struct msgnum_array { int max, size; int *msgnums; }; /* * Add a argument to the given msgs_array or msgnum_array structure; extend * the array size if necessary */ void app_msgarg(struct msgs_array *, char *); void app_msgnum(struct msgnum_array *, int); char *find_str (const char [], size_t, const char *); char *rfind_str (const char [], size_t, const char *); char *nmh_strcasestr (const char *, const char *); void trunccpy(char *dst, const char *src, size_t size); /* A convenience for the common case of dst being an array. */ #define TRUNCCPY(dst, src) trunccpy(dst, src, sizeof (dst)) bool has_prefix(const char *s, const char *prefix); bool has_suffix(const char *s, const char *suffix); bool has_suffix_c(const char *s, int c); void trim_suffix_c(char *s, int c); void to_lower(char *s); void to_upper(char *s); /* * See if a string contains 8 bit characters (use isascii() for the test). * Arguments include: * * start - Pointer to start of string to test. * end - End of string to test (test will stop before reaching * this point). If NULL, continue until reaching '\0'. * * This function always stops at '\0' regardless of the value of 'end'. * Returns 1 if the string contains an 8-bit character, 0 if it does not. */ int contains8bit(const char *start, const char *end); /* * See if file has any 8-bit bytes. * Arguments include: * * fd - file descriptor * eightbit - address of result, will be set to 1 if the file contains * any 8-bit bytes, 0 otherwise. * * Returns OK on success, NOTOK on read failure. * */ int scan_input (int fd, int *eightbit); /* * Returns string representation of int, in static memory. */ char *m_str(int value); /* * Returns string representation of an int, in static memory. If width * == 0, does not limit the width. If width > 0 and value will not fit * in field of that size, including any negative sign but excluding * terminating null, then returns "?". */ char *m_strn(int value, unsigned int width); /* * program initialization * * argv0 - argv[0], presumably the program name * read_context - 0: don't read context * - 1: read context, check nmh version, and issue warning message * if non-existent or old * - 2: read context, don't check nmh version */ int nmh_init(const char *argv0, int read_context); /* * Compares prior version of nmh with current version. Returns 1 * if they compare the be the same, 0 if not. * * older - 0 for difference comparison, 1 for only if older */ int nmh_version_changed (int older); nmh-1.7.1-RC3/etc/bash_completion_nmh-gen000755 007761 000024 00000005110 13205305704 020236 0ustar00kenhstaff000000 000000 #! /bin/sh # # Generates COMPLETION-BASH from man/mh-chart.man. # # This code is Copyright (c) 2016, by the authors of nmh. # See the COPYRIGHT file in the root directory of the nmh # distribution for complete copyright information. mhchart=man/mh-chart.man #### Extract switches for nmh program. prog_switches() { program=$1 #### Extract lines from just after .B program-name to just before #### blank line, and then only those that start with .RB, e.g., #### .RB [ \-list " | " \-nolist ] #### .RB " | " \-autoheaderencoding ] #### .RB [ \-\|\-component awk '/^.B.*(\/| )'"$program"'/,/^$/ { if (/^\.RB /) print }' "$mhchart" | \ tr -d '\n' | \ sed -e 's/\.RB //g' -e 's/\[//g' -e 's/\]//g' \ -e 's/\(\\\)*//g' -e 's/-|-/-/g' -e 's/" *| "//g' \ -e 's/^ *//' -e 's/ *$//' -e 's/ */ /g' } cat <<'EOF' # bash completions for nmh commands -*- shell-script -*- # This file was generated by etc/bash_completion_nmh-gen. # # This code is Copyright (c) 2016, by the authors of nmh. # See the COPYRIGHT file in the root directory of the nmh # distribution for complete copyright information. # # To use: source at a bash prompt or in an initialization file. _nmh() { local -a switches COMPREPLY=() #### Complete filenames. compopt -o default case ${COMP_WORDS[COMP_CWORD]} in -*) case $1 in EOF #### Extract program names from lines such as: #### .B %nmhlibexecdir%/install\-mh #### .B new \-mode fnext programs=`egrep '\.B [^\-]' "$mhchart" | \ sed -e 's/^\.B //' -e 's/ .*//' -e 's|%[^%]*%/||' -e 's/\\-/-/'` for program in $programs; do switches=`prog_switches "$program"` # Support mime as alias for mhbuild. [ "$program" = mhbuild ] && program='mhbuild|mime' printf ' %s) switches=(%s) ;;\n' "$program" "$switches" done programs="$programs mime" cat <<'EOF' esac ;; +*) switches=($(folder -all -fast -recurse | sed 's/^/+/')) ;; #### Complete special message names, except after -file. The compopt -o default above provides filename completions. Assume that -file was fully completed, so don't need to match -fil, etc. [flc.np]*) [ ${COMP_CWORD:-0} -lt 2 -o ${COMP_WORDS[$(($COMP_CWORD - 1))]} != -file ] && switches=(first last cur . next prev) ;; esac #### Special case: add "new" to mhpath's completions. [ $1 = mhpath ] && switches=("${switches[*]}" + new) COMPREPLY=($(compgen -W "${switches[*]}" -- ${COMP_WORDS[COMP_CWORD]})) } EOF #### There better not be an nmh program name with whitespace in it. echo complete -F _nmh $programs nmh-1.7.1-RC3/etc/components000644 007761 000024 00000001473 13240376505 015657 0ustar00kenhstaff000000 000000 %; Our default components file. Used by `comp' %; %; %; This line creates our From: header based on the following ordering: %; %; - Use a -from switch if it exists ({from}) %; - Use our local mailbox identity; first from the Local-Mailbox profile %; entry, otherwise gets the information from the local system %; %<{from}%|%(void(localmbox))%>%(void(width))%(putaddr From: ) %; %; Here we include an address list if one or more "-to" arguments were %; given, otherwise just output a blank header. We do the same for the %; "cc" header as well. %; %<{to}%(void(width))%(putaddr To: )%|To:%> %<{cc}%(void(width))%(putaddr cc: )%|cc:%> %; %; Slight difference here: if we're not given "-fcc" on the command line, %; make the default mailbox +outbox %; Fcc: %<{fcc}%(putstr)%|+outbox%> Subject:%<{subject} %(putstr)%> -------- nmh-1.7.1-RC3/etc/digestcomps000644 007761 000024 00000001425 13240376505 016010 0ustar00kenhstaff000000 000000 %; digestcomps - the component template file used when doing "forw -digest" %; %; What happens here is the following: %; %; - Try to make reasonable defaults when using -digest %; - Allow users to override headers if they give them %; %; See forwcomps for more details on how this works %; %<{nmh-from}%(void(width))%(putaddr From: )%|From: %{digest}-Request%> %<{nmh-to}%(void(width))%(putaddr To: )%|To: %{digest} Distribution: dist-%{digest};%> %<{nmh-cc}%(void(width))%(putaddr cc: )\n%>\ %<{fcc}Fcc: %(putstr)\n%>\ Subject: %<{nmh-subject}%(putlit)%|%{digest} Digest V%(cur) #%(msg)%> Reply-To: %{digest} -------- %{digest} Digest %(weekday{nmh-date}), %2(mday{nmh-date}) %(month{nmh-date}) %(year{nmh-date}) Volume %(cur) : Issue %(msg) Today's Topics: nmh-1.7.1-RC3/etc/distcomps000644 007761 000024 00000001240 13240376505 015467 0ustar00kenhstaff000000 000000 %; distcomps - Our components file for "dist" %; %; This is modeled after the components file for forw, so check that %; file for more explanation as to what is going on here. %; %; When using "dist" we have to use the special Resent- headers, since %; we're keeping the original headers of the message intact. %; %; All of the header components from the original message are available %; if you wish to use them. %; %<{nmh-from}%|%(void(localmbox))%>%(void(width))%(putaddr Resent-From: ) %<{nmh-to}%(void(width))%(putaddr Resent-To: )%|Resent-To:%> %<{nmh-cc}%(void(width))%(putaddr Resent-cc: )%|Resent-cc:%> %<{fcc}%(void(width))%(putaddr Resent-fcc: )%|Resent-fcc:%> nmh-1.7.1-RC3/etc/forwcomps000644 007761 000024 00000002334 13240376505 015506 0ustar00kenhstaff000000 000000 %; forwcomps - Our components file when we're using "forw" %; %; We want people to be able to use the components from forwarded %; messages in this file, so we have to cheat a bit. We create a series %; of pseudo-components with a "nmh" prefix to represent arguments given %; on the command line. We don't do this for %{fcc} since there's already %; precedence for this from "repl". %; %; If we're given multiple messages to forward, provide the components %; from the first one. Can't really think of anything better to do there. %; %; Generate a "From:" header; if we don't give one, use %(localmbox) %; %<{nmh-from}%|%(void(localmbox))%>%(void(width))%(putaddr From: ) %; %; Generate To: and cc: headers; if we're given ones, put something in there %; otherwise leave them blank. %; %<{nmh-to}%(void(width))%(putaddr To: )%|To:%> %<{nmh-cc}%(void(width))%(putaddr cc: )%|cc:%> %; %; If we're not given a -fcc switch, then default to +outbox %; Fcc: %<{fcc}%(putstr)%|+outbox%> %; %; If we're not given a -subject switch, then use the original message %; subject, but adding (fwd) on the end. I got this idea from exmh, and %; I've always liked it. %; Subject:%<{nmh-subject} %(trim)%(putlit)%?{subject} %(trim)%(putlit) (fwd)%> -------- nmh-1.7.1-RC3/etc/MailAliases000644 007761 000024 00000002425 13240376505 015654 0ustar00kenhstaff000000 000000 ; MailAliases -- nmh global aliases file ; ; This file is used to define aliases that are valid for all mh users. ; This file is almost empty as MH now supports personal aliases. ; ; If you need to define system wide aliases such as "everyone", it is ; preferable that this be done as the mail transport level, so that they ; will be valid for users of other mail clients. ; everyone: * ; Blank lines and lines beginning with a ;, :, or # are ignored. ; < file -> read more aliases from "file" ; foo: fum -> simple replacement ; foo: fum, fie -> list replacement ; foo: < file -> list replacement from "file" ; foo: = group -> list replacement from UNIX group ; foo: + group -> list replacement by ALL users in /etc/passwd ; with gid == group ; foo: * -> list replacement by ALL users in /etc/passwd ; with uid >= 200 ; foo*: fum -> matches foo (including the empty string) ; ; using a ';' instead of a ':' indicates that the alias should be displayed ; along with the addresses used (normally, the addresses replace the alias ; completely) ; ; A backslash at the end of a line escapes the following newline, even ; in comment lines. Thus, comments endinf with a \ will be continued even # without a leading ;, :, or # on the followling line. nmh-1.7.1-RC3/etc/mhical.12hour000644 007761 000024 00000004070 13205305704 016034 0ustar00kenhstaff000000 000000 %; mhical.12hour %; Form file for mhical that directs it to use 12-hour instead of 24-hour %; time format. %; %; See mhical.24hour for list of supported components. %; %; Here's what it does to the %{dtstart} special component: %; %; 1) Enable bold, and if the terminal supports color, green attributes. %; 2) If the time zone is explicit, coerce the date to the local time zone; %; otherwise, assume that it's a floating time. %; 3) Output the date in "ddd DD MM YYYY" format. %; 4) Convert hours from 24- to 12-hour clock and output them as soon as %; they are calculated. Store AM or PM in the str register. %; 5) Output :minutes. %; 6) Output AM or PM. %; 7) If the time zone is explicit, output it. %; 8) Reset all terminal attributes. %; The timezone is not output for the dtend component because it is %; almost always (except across a daylight saving time transition) %; the same as for the dtstart component. %; %<(nonnull{method})Method: %(putstr{method})\n%>\ %<(nonnull{organizer})Organizer: %(putstr{organizer})\n%>\ %<(nonnull{summary})Summary: %(putstr{summary})\n%>\ %<(nonnull{description})Description: %(putstr{description})\n%>\ %<(nonnull{location})Location: %(putstr{location})\n%>\ %<(nonnull{dtstart})At: \ %<(hascolor)%(zputlit(fgcolor green))%>%(zputlit(bold))\ %(void(szone{dtstart}))%<(gt 0)%(date2local{dtstart})%>\ %(day{dtstart}), %02(mday{dtstart}) %(month{dtstart}) %(year{dtstart}) \ %(void(hour{dtstart}))%<(eq 0)%(num 12)%(void(lit AM))\ %?(eq 12)%(num 12)%(void(lit PM))\ %?(gt 12)%2(modulo 12)%(void(lit PM))\ %|%2(putnumf)%(void(lit AM))%>\ :%02(min{dtstart}) \ %(putlit)%; AM or PM %(void(szone{dtstart}))%<(gt 0) %(tzone{dtstart})%>\ %(zputlit(resetterm))\n%>\ %<(nonnull{dtstart})To: \ %(void(szone{dtend}))%<(gt 0)%(date2local{dtend})%>\ %(day{dtend}), %02(mday{dtend}) %(month{dtend}) %(year{dtend}) \ %(void(hour{dtend}))%<(eq 0)%(num 12)%(void(lit AM))\ %?(eq 12)%(num 12)%(void(lit PM))\ %?(gt 12)%2(modulo 12)%(void(lit PM))\ %|%2(putnumf)%(void(lit AM))%>\ :%02(min{dtend}) \ %(putlit)\n%>%; AM or PM %<(nonnull{attendees})%(putstr{attendees})\n%>\ nmh-1.7.1-RC3/etc/mhical.24hour000644 007761 000024 00000004101 13205305704 016032 0ustar00kenhstaff000000 000000 %; mhical.24hour %; Form file for mhical that directs it to use 24-hour time format. %; %; Default form file for mhical. The following components %; are supported: %; method %; organizer %; summary %; description %; location %; dtstart %; dtend %; attendees %; Each corresponds to the iCalendar property of the same name as %; defined in RFC 5545, with the exception of "attendees". That is a %; comma-delimited list of the common name (CN), if available, or %; email address of Attendee properties. %; The component names listed above are case-sensitive because %; fmt_findcomp() is case-sensitive. %; %; Here's what it does to the %{dtstart} special component for the %; event: %; 1) Enable bold, and if the terminal supports color, green attributes. %; 2) If the time zone is explicit, coerce the date to the local time zone; %; otherwise, assume that it's a floating time. %; 3) Output the date in "ddd DD MM YYYY" format. %; 4) Output the time in "HH:MM" format. %; 5) If the time zone is explicit, output it. %; 6) Reset all terminal attributes. %; The timezone is not output for the dtend component because it is %; almost always (except across a daylight saving time transition) %; the same as for the dtstart component. %; %<(nonnull{method})Method: %(putstr{method})\n%>\ %<(nonnull{organizer})Organizer: %(putstr{organizer})\n%>\ %<(nonnull{summary})Summary: %(putstr{summary})\n%>\ %<(nonnull{description})Description: %(putstr{description})\n%>\ %<(nonnull{location})Location: %(putstr{location})\n%>\ %<(nonnull{dtstart})At: \ %<(hascolor)%(zputlit(fgcolor green))%>%(zputlit(bold))\ %(void(szone{dtstart}))%<(gt 0)%(date2local{dtstart})%>\ %(day{dtstart}), %02(mday{dtstart}) %(month{dtstart}) %(year{dtstart}) \ %02(hour{dtstart}):%02(min{dtstart})\ %(void(szone{dtstart}))%<(gt 0) %(tzone{dtstart})%>\ %(zputlit(resetterm))\n%>\ %<(nonnull{dtstart})To: \ %(void(szone{dtend}))%<(gt 0)%(date2local{dtend})%>\ %(day{dtend}), %02(mday{dtend}) %(month{dtend}) %(year{dtend}) \ %02(hour{dtend}):%02(min{dtend})\n%>\ %<(nonnull{attendees})%(putstr{attendees})\n%>\ nmh-1.7.1-RC3/etc/mhl.body000644 007761 000024 00000000056 11476243570 015206 0ustar00kenhstaff000000 000000 width=10000 body:nocomponent,overflowoffset=0 nmh-1.7.1-RC3/etc/mhl.digest000644 007761 000024 00000000301 11476243570 015521 0ustar00kenhstaff000000 000000 width=80,overflowoffset=10 leftadjust,compress,compwidth=9 Date:formatfield="%<(nodate{text})%{text}%|%(tws{text})%>" From: Subject: : body:nocomponent,overflowoffset=0,noleftadjust,nocompress nmh-1.7.1-RC3/etc/mhl.format000644 007761 000024 00000000633 13205305704 015530 0ustar00kenhstaff000000 000000 ; mhl.format ; ; default message filter for `show' ; : overflowtext="***",overflowoffset=5 leftadjust,compwidth=9 ignores=msgid,message-id,received,content-type,content-transfer-encoding,content-id Date:formatfield="%<(nodate{text})%{text}%|%(pretty{text})%>" To: cc: From:formatfield="%(unquote(decode{text}))" Subject:decode : extras:nocomponent : body:nocomponent,overflowtext=,overflowoffset=0,noleftadjust nmh-1.7.1-RC3/etc/mhl.forward000644 007761 000024 00000000434 11476243570 015715 0ustar00kenhstaff000000 000000 ; mhl.forward ; ; default message filter for `forw' (forw -format) ; width=80,overflowtext=,overflowoffset=10 leftadjust,compress,compwidth=9 Date:formatfield="%<(nodate{text})%{text}%|%(tws{text})%>" From: To: cc: Subject: : body:nocomponent,overflowoffset=0,noleftadjust,nocompress nmh-1.7.1-RC3/etc/mhl.headers000644 007761 000024 00000000677 13205305704 015663 0ustar00kenhstaff000000 000000 ; mhl.headers ; ; Default format file for displaying headers in ; MIME messages. mhn calls the mhlproc with this ; filter to display message header. ; overflowtext="***",overflowoffset=5 leftadjust,compwidth=9 ignores=msgid,message-id,received,content-type,content-transfer-encoding,content-id Date:formatfield="%<(nodate{text})%{text}%|%(pretty{text})%>" To: cc: From:formatfield="%(unquote(decode{text}))" Subject:decode : extras:nocomponent : nmh-1.7.1-RC3/etc/mhl.reply000644 007761 000024 00000000304 13205305704 015366 0ustar00kenhstaff000000 000000 ; mhl.reply ; ; default message filter for `repl' (repl -format) ; from:nocomponent,formatfield="%(unquote(decode(friendly{text}))) writes:" body:component="> ",overflowtext="> ",overflowoffset=0 nmh-1.7.1-RC3/etc/mhl.replywithoutbody000644 007761 000024 00000000257 13205305704 017677 0ustar00kenhstaff000000 000000 ; mhl.replywithoutbody ; ; message filter for `repl' (repl -format) that excludes the message body ; from:nocomponent,formatfield="%(unquote(decode(friendly{text}))) writes:" nmh-1.7.1-RC3/etc/mhn.defaults.sh000755 007761 000024 00000034556 13240377167 016513 0ustar00kenhstaff000000 000000 #! /bin/sh # # mhn.defaults.sh -- create extra profile file for MIME handling # # USAGE: mhn.defaults.sh [ search-path [ search-prog ]] # If a search path is passed to the script, we # use that, else we use a default search path. if [ -n "$1" ]; then SEARCHPATH=$1 else SEARCHPATH="$PATH" fi # If a search program is passed to the script, we # use that, else we use a default search program. if [ -n "$2" ]; then SEARCHPROG=$2 else SEARCHPROG="mhn.find.sh" fi # put output into a temporary file, so we # can sort it before output. TMP=/tmp/nmh_temp.$$ trap "rm -f $TMP" 0 1 2 3 13 15 if [ ! -z `$SEARCHPROG "$SEARCHPATH" par` ]; then #### The widths here correspond to those for the text browsers below. textfmt=' | par 64' replfmt=" | sed 's/^\(.\)/> \1/; s/^$/>/;' | par 64" elif [ ! -z `$SEARCHPROG "$SEARCHPATH" fmt` ]; then textfmt=' | fmt' replfmt=" | fmt | sed 's/^\(.\)/> \1/; s/^$/>/;'" else textfmt= replfmt= fi [ ! -z `$SEARCHPROG "$SEARCHPATH" iconv` ] && charsetconv=' | iconv -f ${charset:-us-ascii} -t utf-8'"${textfmt}" || charsetconv= cat >>"$TMP" <<'EOF' mhstore-store-text: %m%P.txt mhstore-store-text/calendar: %m%P.ics mhstore-store-text/html: %m%P.html mhstore-store-text/richtext: %m%P.rt mhstore-store-video/mpeg: %m%P.mpg mhstore-store-application/PostScript: %m%P.ps EOF PGM=`$SEARCHPROG "$SEARCHPATH" xwud` if [ ! -z "$PGM" ]; then XWUD="$PGM" X11DIR="`echo $PGM | awk -F/ '{ for(i=2;i> $TMP elif [ ! -z $"NETPBM" -a ! -z "$XWUD" ]; then echo "mhshow-show-image/gif: %l${NETPBMDIR}giftopnm | ${NETPBMDIR}ppmtopgm | ${NETPBMDIR}pgmtopbm | ${NETPBMDIR}pnmtoxwd | $XWUD -geometry =-0+0" >> $TMP echo "mhshow-show-image/x-pnm: %l${NETPBMDIR}pnmtoxwd | $XWUD -geometry =-0+0" >> $TMP echo "mhshow-show-image/x-pgm: %l${NETPBMDIR}pgmtopbm | ${NETPBMDIR}pnmtoxwd | $XWUD -geometry =-0+0" >> $TMP echo "mhshow-show-image/x-ppm: %l${NETPBMDIR}ppmtopgm | ${NETPBMDIR}pgmtopbm | ${NETPBMDIR}pnmtoxwd | $XWUD -geometry =-0+0" >> $TMP echo "mhshow-show-image/x-xwd: %l$XWUD -geometry =-0+0" >> $TMP PGM=`$SEARCHPROG "$SEARCHPATH" djpeg` if [ ! -z "$PGM" ]; then echo "mhshow-show-image/jpeg: %l$PGM -Pg | ${NETPBMDIR}ppmtopgm | ${NETPBMDIR}pgmtopbm | ${NETPBMDIR}pnmtoxwd | $XWUD -geometry =-0+0" >> $TMP fi fi if [ -f "/dev/audioIU" ]; then PGM=`$SEARCHPROG "$SEARCHPATH" recorder` if [ ! -z "$PGM" ]; then echo "mhstore-store-audio/basic: %m%P.au" >> $TMP echo "mhbuild-compose-audio/basic: ${AUDIODIR}recorder %f -au -pause > /dev/tty" >> $TMP echo "mhshow-show-audio/basic: %l${AUDIODIR}splayer -au" >> $TMP fi elif [ -f "/dev/audio" ]; then PGM=`$SEARCHPROG "$SEARCHPATH" raw2audio` if [ ! -z "$PGM" ]; then AUDIODIR="`echo $PGM | awk -F/ '{ for(i=2;i %m%P.au" >> $TMP echo "mhstore-store-audio/x-next: %m%P.au" >> $TMP AUDIOTOOL=`$SEARCHPROG "$SEARCHPATH" audiotool` if [ ! -z "$AUDIOTOOL" ]; then echo "mhbuild-compose-audio/basic: $AUDIOTOOL %f && ${AUDIODIR}raw2audio -F < %f" >> $TMP else echo "mhbuild-compose-audio/basic: trap \"exit 0\" 2 && ${AUDIODIR}record | ${AUDIODIR}raw2audio -F" >> $TMP fi echo "mhshow-show-audio/basic: %l${AUDIODIR}raw2audio 2>/dev/null | ${AUDIODIR}play" >> $TMP PGM=`$SEARCHPROG "$SEARCHPATH" adpcm_enc` if [ ! -z "$PGM" ]; then DIR="`echo $PGM | awk -F/ '{ for(i=2;i> $TMP else echo "mhbuild-compose-audio/x-next: ${AUDIODIR}record | ${DIR}adpcm_enc" >> $TMP fi echo "mhshow-show-audio/x-next: %l${DIR}adpcm_dec | ${AUDIODIR}play" >> $TMP else if [ ! -z "$AUDIOTOOL" ]; then echo "mhbuild-compose-audio/x-next: $AUDIOTOOL %f" >> $TMP else echo "mhbuild-compose-audio/x-next: ${AUDIODIR}record" >> $TMP fi echo "mhshow-show-audio/x-next: %l${AUDIODIR}play" >> $TMP fi else echo "mhbuild-compose-audio/basic: cat < /dev/audio" >> $TMP echo "mhshow-show-audio/basic: %lcat > /dev/audio" >> $TMP fi fi #### #### mhbuild-disposition-[/] entries are used by the #### WhatNow attach for deciding whether the Content-Disposition #### should be 'attachment' or 'inline'. Only those values are #### supported. mhbuild-convert-text/html is defined below. #### cat <>${TMP} mhbuild-convert-text/calendar: mhical -infile %F -contenttype mhbuild-convert-text: charset=%{charset}; iconv -f \${charset:-us-ascii} -t utf-8 %F${replfmt} mhbuild-disposition-text/calendar: inline mhbuild-disposition-message/rfc822: inline EOF PGM=`$SEARCHPROG "$SEARCHPATH" mpeg_play` if [ ! -z "$PGM" ]; then echo "mhshow-show-video/mpeg: %l$PGM %f" >> $TMP fi PGM=`$SEARCHPROG "$SEARCHPATH" okular` if [ ! -z "$PGM" ]; then echo "mhshow-show-application/PostScript: %l$PGM %F" >> $TMP else PGM=`$SEARCHPROG "$SEARCHPATH" evince` if [ ! -z "$PGM" ]; then echo "mhshow-show-application/PostScript: %l$PGM %F" >> $TMP else PGM=`$SEARCHPROG "$SEARCHPATH" gv` if [ ! -z "$PGM" ]; then echo "mhshow-show-application/PostScript: %l$PGM %F" >> $TMP fi fi fi PGM=`$SEARCHPROG "$SEARCHPATH" acroread` if [ ! -z "$PGM" ]; then echo "mhshow-show-application/pdf: %l$PGM %F" >> $TMP else PGM=`$SEARCHPROG "$SEARCHPATH" okular` if [ ! -z "$PGM" ]; then echo "mhshow-show-application/pdf: %l$PGM %F" >> $TMP else PGM=`$SEARCHPROG "$SEARCHPATH" evince` if [ ! -z "$PGM" ]; then echo "mhshow-show-application/pdf: %l$PGM %F" >> $TMP else PGM=`$SEARCHPROG "$SEARCHPATH" xpdf` if [ ! -z "$PGM" ]; then echo "mhshow-show-application/pdf: %l$PGM %F" >> $TMP else PGM=`$SEARCHPROG "$SEARCHPATH" gv` if [ ! -z "$PGM" ]; then echo "mhshow-show-application/pdf: %l$PGM %F" >> $TMP fi fi fi fi fi echo "mhshow-show-text/calendar: mhical -infile %F" >> $TMP echo "mhshow-show-application/ics: mhical -infile %F" >> $TMP echo "mhfixmsg-format-text/calendar: mhical -infile %F" >> $TMP echo "mhfixmsg-format-application/ics: mhical -infile %F" >> $TMP PGM=`$SEARCHPROG "$SEARCHPATH" ivs_replay` if [ ! -z "$PGM" ]; then echo "mhshow-show-application/x-ivs: %l$PGM -o %F" >> $TMP fi # The application/vnd.openxmlformats-officedocument.wordprocessingml.document # through application/onenote associations are from # http://technet.microsoft.com/en-us/library/cc179224.aspx cat <> ${TMP} mhshow-suffix-application/msword: .doc mhshow-suffix-application/ogg: .ogg mhshow-suffix-application/pdf: .pdf mhshow-suffix-application/postscript: .ps mhshow-suffix-application/rtf: .rtf mhshow-suffix-application/vnd.ms-excel: .xla mhshow-suffix-application/vnd.ms-excel: .xlc mhshow-suffix-application/vnd.ms-excel: .xld mhshow-suffix-application/vnd.ms-excel: .xll mhshow-suffix-application/vnd.ms-excel: .xlm mhshow-suffix-application/vnd.ms-excel: .xls mhshow-suffix-application/vnd.ms-excel: .xlt mhshow-suffix-application/vnd.ms-excel: .xlw mhshow-suffix-application/vnd.ms-powerpoint: .pot mhshow-suffix-application/vnd.ms-powerpoint: .pps mhshow-suffix-application/vnd.ms-powerpoint: .ppt mhshow-suffix-application/vnd.ms-powerpoint: .ppz mhshow-suffix-application/vnd.openxmlformats-officedocument.wordprocessingml.document: .docx mhshow-suffix-application/vnd.ms-word.document.macroEnabled.12: .docm mhshow-suffix-application/vnd.openxmlformats-officedocument.wordprocessingml.template: .dotx mhshow-suffix-application/vnd.ms-word.template.macroEnabled.12: .dotm mhshow-suffix-application/vnd.openxmlformats-officedocument.spreadsheetml.sheet: .xlsx mhshow-suffix-application/vnd.ms-excel.sheet.macroEnabled.12: .xlsm mhshow-suffix-application/vnd.openxmlformats-officedocument.spreadsheetml.template: .xltx mhshow-suffix-application/vnd.ms-excel.template.macroEnabled.12: .xltm mhshow-suffix-application/vnd.ms-excel.sheet.binary.macroEnabled.12: .xlsb mhshow-suffix-application/vnd.ms-excel.addin.macroEnabled.12: .xlam mhshow-suffix-application/vnd.openxmlformats-officedocument.presentationml.presentation: .pptx mhshow-suffix-application/vnd.ms-powerpoint.presentation.macroEnabled.12: .pptm mhshow-suffix-application/vnd.openxmlformats-officedocument.presentationml.slideshow: .ppsx mhshow-suffix-application/vnd.ms-powerpoint.slideshow.macroEnabled.12: .ppsm mhshow-suffix-application/vnd.openxmlformats-officedocument.presentationml.template: .potx mhshow-suffix-application/vnd.ms-powerpoint.template.macroEnabled.12: .potm mhshow-suffix-application/vnd.ms-powerpoint.addin.macroEnabled.12: .ppam mhshow-suffix-application/vnd.openxmlformats-officedocument.presentationml.slide: .sldx mhshow-suffix-application/vnd.ms-powerpoint.slide.macroEnabled.12: .sldm mhshow-suffix-application/onenote: .onetoc mhshow-suffix-application/onenote: .onetoc2 mhshow-suffix-application/onenote: .onetmp mhshow-suffix-application/onenote: .onepkg mhshow-suffix-application/x-bzip2: .bz2 mhshow-suffix-application/x-cpio: .cpio mhshow-suffix-application/x-dvi: .dvi mhshow-suffix-application/x-gzip: .gz mhshow-suffix-application/x-java-archive: .jar mhshow-suffix-application/x-javascript: .js mhshow-suffix-application/x-latex: .latex mhshow-suffix-application/x-sh: .sh mhshow-suffix-application/x-tar: .tar mhshow-suffix-application/x-texinfo: .texinfo mhshow-suffix-application/x-tex: .tex mhshow-suffix-application/x-troff-man: .man mhshow-suffix-application/x-troff-me: .me mhshow-suffix-application/x-troff-ms: .ms mhshow-suffix-application/x-troff: .t mhshow-suffix-application/zip: .zip mhshow-suffix-audio/basic: .au mhshow-suffix-audio/midi: .midi mhshow-suffix-audio/mpeg: .mp3 mhshow-suffix-audio/mpeg: .mpg mhshow-suffix-audio/x-ms-wma: .wma mhshow-suffix-audio/x-wav: .wav mhshow-suffix-image/gif: .gif mhshow-suffix-image/jpeg: .jpeg mhshow-suffix-image/jpeg: .jpg mhshow-suffix-image/png: .png mhshow-suffix-image/tiff: .tif mhshow-suffix-image/tiff: .tiff mhshow-suffix-text: .txt mhshow-suffix-text/calendar: .ics mhshow-suffix-text/css: .css mhshow-suffix-text/html: .html mhshow-suffix-text/rtf: .rtf mhshow-suffix-text/sgml: .sgml mhshow-suffix-text/xml: .xml mhshow-suffix-video/mpeg: .mpeg mhshow-suffix-video/mpeg: .mpg mhshow-suffix-video/quicktime: .moov mhshow-suffix-video/quicktime: .mov mhshow-suffix-video/quicktime: .qt mhshow-suffix-video/quicktime: .qtvr mhshow-suffix-video/x-msvideo: .avi mhshow-suffix-video/x-ms-wmv: .wmv EOF # I'd like to check if netscape is available and use it preferentially to lynx, # but only once I've added a new %-escape that makes more permanent temp files, # so netscape -remote can be used (without -remote you get a complaint dialog # that another netscape is already running and certain things can't be done). PGM=`$SEARCHPROG "$SEARCHPATH" w3m` if [ ! -z "$PGM" ]; then echo 'mhshow-show-text/html: charset="%{charset}"; '"\ %l$PGM"' -dump ${charset:+-I} ${charset:+"$charset"} -T text/html %F' >> $TMP echo 'mhfixmsg-format-text/html: charset="%{charset}"; '"\ $PGM "'-dump ${charset:+-I} ${charset:+"$charset"} -O utf-8 -T text/html %F' \ >> $TMP echo 'mhbuild-convert-text/html: charset="%{charset}"; '"\ $PGM "'-dump ${charset:+-I} ${charset:+"$charset"} -O utf-8 -T text/html %F '"\ ${replfmt}" >> $TMP else PGM=`$SEARCHPROG "$SEARCHPATH" lynx` if [ ! -z "$PGM" ]; then echo 'mhshow-show-text/html: charset="%{charset}"; '"\ %l$PGM"' -child -dump -force-html ${charset:+--assume_charset} ${charset:+"$charset"} %F' >> $TMP #### lynx indents with 3 spaces, remove them and any trailing spaces. echo 'mhfixmsg-format-text/html: charset="%{charset}"; '"\ $PGM "'-child -dump -force_html ${charset:+--assume_charset} ${charset:+"$charset"} %F | '"\ expand | sed -e 's/^ //' -e 's/ *$//'" >> $TMP echo 'mhbuild-convert-text/html: charset="%{charset}"; '"\ $PGM "'-child -dump -force_html ${charset:+--assume_charset} ${charset:+"$charset"} '"\ %F${replfmt}" >> $TMP else PGM=`$SEARCHPROG "$SEARCHPATH" elinks` if [ ! -z "$PGM" ]; then echo "mhshow-show-text/html: %l$PGM -dump -force-html \ -eval 'set document.browse.margin_width = 0' %F" >> $TMP echo "mhfixmsg-format-text/html: $PGM -dump -force-html \ -no-numbering -eval 'set document.browse.margin_width = 0' %F" >> $TMP echo "mhbuild-convert-text/html: $PGM -dump -force-html \ -no-numbering -eval 'set document.browse.margin_width = 0' %F${replfmt}" >> $TMP else echo 'mhbuild-convert-text/html: cat %F' >> $TMP fi fi fi PGM=`$SEARCHPROG "$SEARCHPATH" richtext` if [ ! -z "$PGM" ]; then echo "mhshow-show-text/richtext: %l$PGM -p %F" >> $TMP else PGM=`$SEARCHPROG "$SEARCHPATH" rt2raw` if [ ! -z "$PGM" ]; then echo "mhshow-show-text/richtext: %l$PGM < %f | fmt -78 | more" >> $TMP fi fi # staroffice to read .doc files PGM=`$SEARCHPROG "$SEARCHPATH" soffice` if [ ! -z "$PGM" ]; then echo "mhshow-show-application/msword: %l$PGM %F" >> $TMP fi # This entry is used to retrieve external-body types that use a "url" # access-type. case "`uname`" in FreeBSD) echo "nmh-access-url: fetch -o -" >> $TMP ;; *) PGM=`$SEARCHPROG "$SEARCHPATH" curl` if [ ! -z "$PGM" ]; then echo "nmh-access-url: $PGM -L" >> $TMP fi ;; esac # Output a sorted version of the file, along with some comments in # appropriate places. echo '#: This file was generated by mhn.defaults.sh.' sort < $TMP | \ sed -e 's|^\(mhshow-show-application/ics:.*\)|#: might need -notextonly -noinlineonly or -part/-type to show application/ics parts\n\1|' exit 0 ############################################################################### ############################################################################### #### #### Note the exit 0 above; everything below is unused. #### ############################################################################### ############################################################################### : have to experiment more with this PGM=`$SEARCHPROG "$SEARCHPATH" ivs_record` if [ ! -z "$PGM" ]; then echo "mhbuild-compose-application/x-ivs: $PGM -u localhost %F" >> $TMP fi nmh-1.7.1-RC3/etc/mhn.find.sh000755 007761 000024 00000001250 13205305704 015572 0ustar00kenhstaff000000 000000 #! /bin/sh # # mhn.find.sh -- check if a particular command is available # if test -z "$2"; then echo "usage: mhn.find.sh search-path program" 1>&2 exit 1 fi # PATH to search for programs SEARCHPATH=$1 # program to search for PROGRAM=$2 PGM= oIFS="$IFS" IFS=":" for A in $SEARCHPATH; do # skip the directories `.' and `..' if test "$A" = "." -o "$A" = ".."; then continue fi # if program was found in /usr/local/bin, then # just echo program name, else echo full pathname if test -f "$A/$PROGRAM"; then if test "$A" = "/usr/local/bin"; then PGM="$PROGRAM" else PGM="$A/$PROGRAM" fi echo "$PGM" exit 0 fi done IFS="$oIFS" nmh-1.7.1-RC3/etc/mhshow.marker000644 007761 000024 00000000460 13240376505 016252 0ustar00kenhstaff000000 000000 %; This is provided as reference only; it shows the default content marker %; used by mhshow when it decides to not display content. %; [ part %{part} - %{content-type} - %<{description}\ %{description}%?{cdispo-filename}%{cdispo-filename}%|%{ctype-name}%> \ %(kilo(size))B %<(unseen)\(suppressed\)%> ] nmh-1.7.1-RC3/etc/mts.conf.in000644 007761 000024 00000003457 13243042053 015621 0ustar00kenhstaff000000 000000 # nmh mail transport interface customization file. # # Check the mh-tailor(5) man page for descriptions of available options. # # The delivery method to use, which must be one of the following: # smtp: nmh opens a socket connection to the appropriate port # on the servers listed below and speaks SMTP to the # first one that responds. This is the default. # sendmail/smtp: nmh pipes messages directly to the sendmail program, # speaking SMTP. Can be abbreviated to "sendmail". # sendmail/pipe: nmh pipes messages directly to the sendmail program, # using the -t option so that addresses are retrieved # from the message. mts: %mts% # Name that nmh considers `local'. If not set, nmh will # query the system for this value (gethostname, etc...). #localname: foo.bar.com # Default location of mail drops. If this option is # set, but empty, the user's home directory is used. mmdfldir: %mailspool% # The name of the maildrop file in the directory where maildrops # are kept. If this is empty, the user's login name is used. mmdflfil: # # The locking algorithm to use on the spool file. Valid settings are: # # fcntl Locking using the fcntl() function # dot "Dot" locking using an external lock file # flock Locking using the flock() function (if supported by OS) # lockf Locking using the lockf() function (if supported by OS) # # Locking algorithms supported on this installation are: # # %supported_locks% # # The default spool locking configured on this system is %default_locking%; # change the line below to get a different value #spoollocking: %default_locking% # Hardcoded POP server name (prevents inc'ing from local mail spool). #pophost: localhost # A SINGLE SMTP server to use when using SMTP support servers: %smtpserver% nmh-1.7.1-RC3/etc/rcvdistcomps000644 007761 000024 00000000215 12437351010 016172 0ustar00kenhstaff000000 000000 %(void(localmbox))%(void(width))%(putaddr Resent-From: ) %(lit)%(formataddr{addresses})\ %<(nonnull)%(void(width))%(putaddr Resent-To: )\n%> nmh-1.7.1-RC3/etc/rcvdistcomps.outbox000644 007761 000024 00000000241 12437351010 017510 0ustar00kenhstaff000000 000000 %(void(localmbox))%(void(width))%(putaddr Resent-From: ) %(lit)%(formataddr{addresses})\ %<(nonnull)%(void(width))%(putaddr Resent-To: )\n%>\ Resent-Fcc: outbox nmh-1.7.1-RC3/etc/replcomps000644 007761 000024 00000002650 13240376505 015474 0ustar00kenhstaff000000 000000 %; replcomps - our default component file for "repl" %; %; %; First, output a "From" header. %(void(localmbox))%(void(width))%(putaddr From: ) %; %; These next lines slurp in lots of addresses for To: and cc:. %; Use with repl -query or else you may get flooded with addresses! %; Currently %(decode) should NOT be used on address fields, in case invalid %; characters are in an address. %; %; If no To:/cc:/Fcc: text, we output empty fields for prompter to fill in. %; %(lit)%(formataddr{reply-to})\ %(formataddr %<{from}%(void{from})%|%(void{apparently-from})%>)\ %(formataddr{resent-to})\ %(formataddr{prev-resent-to})\ %(formataddr{x-to})\ %(formataddr{apparently-to})\ %(void(width))%(putaddr To: ) %(lit)%(formataddr{to})\ %(formataddr{cc})\ %(formataddr{x-cc})\ %(formataddr{resent-cc})\ %(formataddr{prev-resent-cc})\ %(formataddr(localmbox))\ %(void(width))%(putaddr cc: ) Fcc: %<{fcc}%{fcc}%|+outbox%> Subject: %<{subject}Re: %(void{subject})%(trim)%(putstr)%> %; %; Make References: and In-reply-to: fields for threading. %; Use (void), (trim) and (putstr) to eat trailing whitespace. %; %<{message-id}In-reply-to: %{message-id}\n%>\ %<{message-id}References: \ %<{references}%(void{references})%(trim)%(putstr) %>\ %(void{message-id})%(trim)%(putstr)\n%>\ Comments: In-reply-to \ %<{from}%(void{from})%?(void{apparently-from})%|%(void{sender})%>\ %(trim)%(putstr)\n\ message dated "%<(nodate{date})%{date}%|%(tws{date})%>." -------- nmh-1.7.1-RC3/etc/replgroupcomps000644 007761 000024 00000002733 12437351010 016542 0ustar00kenhstaff000000 000000 %; replgroupcomps %; %; form (components) file for `repl -group' %; %; Check the following headers to create reply addresses. %; %; To: Mail-Followup-To %; %; OR %; %; To: Mail-Reply-To (or) %; Reply-To (or) %; From (or) %; Sender (or) %; Return-Path %; %; AND %; %; cc: To (and) %; cc (and) %; personal address %; %; Note that addresses should not have %(decode) run on them in case invalid %; characters are in the address field. %; %(void(localmbox))%(void(width))%(putaddr From: ) %(lit)%(formataddr{mail-followup-to})\ %<(nonnull)%(void(width))%(putaddr To: )\n\ %(putaddr Mail-Followup-To: )\n\ %|\ %(lit)%(formataddr %<{mail-reply-to}%?{reply-to}%?{from}%?{sender}%?{return-path}%>)\ %<(nonnull)%(void(width))%(putaddr To: )\n%>\ %(lit)%(formataddr{to})%(formataddr{cc})%(formataddr(localmbox))\ %<(nonnull)%(void(width))%(putaddr cc: )\n%>%>\ %; Fcc: %<{fcc}%{fcc}%|+outbox%> Subject: %<{subject}Re: %(void{subject})%(trim)%(putstr)%> %; %; Make References: and In-reply-to: fields for threading. %; Use (void), (trim) and (putstr) to eat trailing whitespace. %; %<{message-id}In-reply-to: %{message-id}\n%>\ %<{message-id}References: \ %<{references}%(void{references})%(trim)%(putstr) %>\ %(void{message-id})%(trim)%(putstr)\n%>\ Comments: In-reply-to \ %<{from}%(void{from})%?(void{apparently-from})%|%(void{sender})%>\ %(trim)%(putstr)\n\ message dated "%<(nodate{date})%{date}%|%(tws{date})%>." -------- nmh-1.7.1-RC3/etc/rmmproc.messageid000755 007761 000024 00000004474 12437351010 017107 0ustar00kenhstaff000000 000000 #! /bin/sh ## # rmmproc.messageid -- tries to back up each message/file to a file # that's named based on Message ID # # 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. # # If called on messages, the current directory is the message folder # and the script arguments are the message filenames. If called on # files, the arguments are the full paths to the files. # # The backup directory will be: # 1) If input is messages, the folder of the messages. # 2) If input is files, the directories of the files. # 3) If input is standard input (-), the user's MHPATH directory. # # Each backup filename will be: # 1) Message-ID with all / and \ converted to periods. # Message-IDs should not contain \, but some filesystems can't # handle them. Message-IDs should be unique, so there should be # no need to backup a file with the same name, especially if the # result of malicious action. If the backup file already # exists, use 2). # NOTE: conversion of some characters in the filename could # result in an unintended name collision. If that is a concern, # a program that uses mkstemp(3) to create a temporary file might # be the basis for a remedy. # 2) Concatenation of BACKUP_PREFIX and input filename. # NOTE: if a file of that name already exists in the destination # directory, it will be overwritten by the mv below. ## for i in "$@"; do if [ "$i" = - ]; then #### Input is stdin; put backup in user's MHPATH directory. dir=`mhparam path` #### If Path is relative, prepend home directory. [ `dirname "$dir"` = . ] && dir="$HOME/$dir" else dir=`dirname "$i"` fi #### Extract first Message-Id, remove <>, substitute / and \. messageid=`sed -n ' /^$/q; /^[Mm][Ee][Ss][Ss][Aa][Gg][Ee]-[Ii][Dd]:/!d s/>.*//; s/.*%>\ %; %; If it's unseen, mark it with bold (or the color green) %; %<(unseen)%<(hascolor)%(zputlit(fgcolor green))%|%(zputlit(bold))%>%>\ %; %; Next, output the message number. We print it out using 4 digits, right- %; justified, padding with spaces. %; %4(msg)\ %; %; If it's the current message, output a '+' in the next column, otherwise %; a space. Also use '-' if it's got a "Replied" header and 'E' if it's %; encrypted (not currently supported) %; %<(cur)+%| %>%<{replied}-%?{encrypted}E%| %>\ %; %; Output the date, but mark it with a '*' if it's missing and was synthesized. %; Note the use of 02 to make sure the date is padded with a leading zero. %; %02(mon{date})/%02(mday{date})%<{date} %|*%>\ %; %; If the message is from me, print out who the message was sent to. %; Otherwise, print out who it was from. %<(mymbox{from})%<{to}To:%14(unquote(decode(friendly{to})))%>%>\ %<(zero)%17(unquote(decode(friendly{from})))%> \ %; %; Print out the subject and any of the message body that will fit on the %; rest of the line. After that, print the terminal reset code to reset %; all of the attributes to the next line. %; %; There's actually special handling in the format engine that will output %; any data specified with %(zputlit) even if you've exceeded the column %; width, so it's safe to put any reset characters at the end; they'll %; still be output. %; %(decode{subject})%<{body}<<%{body}>>%>%(zputlit(resetterm)) nmh-1.7.1-RC3/etc/scan.default000644 007761 000024 00000000731 13205305704 016027 0ustar00kenhstaff000000 000000 %; scan.default %; %; This file is supplied for reference only; it shows the default %; format string (for non-UK sites) which was compiled into the %; command "scan". See the source file "h/scansbr.h" for details. %; %4(msg)%<(cur)+%| %>%<{replied}-%?{encrypted}E%| %>\ %02(mon{date})/%02(mday{date})%<{date} %|*%>\ %<(mymbox{from})%<{to}To:%14(unquote(decode(friendly{to})))%>%>\ %<(zero)%17(unquote(decode(friendly{from})))%> \ %(decode{subject})%<{body}<<%{body}>>%> nmh-1.7.1-RC3/etc/scan.highlighted000644 007761 000024 00000002722 13243042053 016662 0ustar00kenhstaff000000 000000 %; scan.highlighted %; %; This file shows how to use ANSI escape sequences to highlight a %; current message in yellow and any unseen messages in cyan (both on %; black background). It differs from the default scan format in the %; two additional lines at the beginning and the literal sequence at %; the end. %; %; To enable use of this format, add "-form scan.highlighted" to your %; scan invocation or to your profile (~/.mh_profile), e.g.: %; scan: -form scan.highlighted %; %; You can optionally copy this file to your MH Path and modify as %; desired. %; %; The mh-sequence(5) man page describes the unseen sequence. %; %; A more readable approach would add escape sequences to your profile, e.g.: %; normal:  %; bright-black:  %; red:  %; green:  %; yellow:  %; blue:  %; magenta:  %; cyan:  %; bright-white:  %; underlined-white:  %; To use them in the format, e.g., at the beginning: %; %<(cur)%(zputlit(profile yellow))%>\ %; %<(unseen)%(zputlit(profile cyan))%>\ %; and at the end: %; %(void(profile normal))%(zputlit) %; %<(cur)%(zputlit(lit ))%>\ %<(unseen)%(zputlit(lit ))%>\ %4(msg)%<(cur)+%| %>%<{replied}-%?{encrypted}E%| %>\ %02(mon{date})/%02(mday{date})%<{date} %|*%>\ %<(mymbox{from})%<{to}To:%14(unquote(decode(friendly{to})))%>%>\ %<(zero)%17(unquote(decode(friendly{from})))%> \ %(decode{subject})%<{body}<<%{body}>>%>%(zputlit(lit )) nmh-1.7.1-RC3/etc/scan.mailx000644 007761 000024 00000000443 13205305704 015515 0ustar00kenhstaff000000 000000 %<(cur)>%| %>\ %<{status} %|N%>\ %<{replied}R%?{encrypted}E%| %>\ %4(msg) \ %<(mymbox{from})%<{to}To: %13(unquote(decode(friendly{to})))%>%>\ %<(zero)%17(unquote(decode(friendly{from})))%> \ %3(day{date}) %3(month{date}) %02(mday{date}) \ %02(hour{date}):%02(min{date}) \ %(decode{subject}) nmh-1.7.1-RC3/etc/scan.MMDDYY000644 007761 000024 00000000615 13205305704 015407 0ustar00kenhstaff000000 000000 %; scan.MMDDYY %; %; Like scan.default, but the date is printed in MM/DD/YY format rather than %; MM/DD. %; %4(msg)%<(cur)+%| %>%<{replied}-%?{encrypted}E%| %>\ %02(mon{date})/%02(mday{date})/%(void(year{date}))%02(modulo 100)%<{date} %|*%>\ %<(mymbox{from})%<{to}To:%14(unquote(decode(friendly{to})))%>%>\ %<(zero)%17(unquote(decode(friendly{from})))%> \ %(decode{subject})%<{body}<<%{body}>>%> nmh-1.7.1-RC3/etc/scan.nomime000644 007761 000024 00000000572 11476243570 015704 0ustar00kenhstaff000000 000000 %; scan.nomime %; %; This file is a modification of the standard (non-UK version) %; format for scan, that doesn't do any RFC-2047 decoding of %; header components. %; %4(msg)%<(cur)+%| %>%<{replied}-%?{encrypted}E%| %>\ %02(mon{date})/%02(mday{date})%<{date} %|*%>\ %<(mymbox{from})%<{to}To:%14(friendly{to})%>%>%<(zero)%17(friendly{from})%> \ %{subject}%<{body}<<%{body}>>%> nmh-1.7.1-RC3/etc/scan.size000644 007761 000024 00000000407 13205305704 015355 0ustar00kenhstaff000000 000000 %4(msg)%<(cur)+%| %>%<{replied}-%?{encrypted}E%| %>\ %02(mon{date})/%02(mday{date})%<{date} %|*%>\ %5(size) \ %<(mymbox{from})%<{to}To:%14(unquote(decode(friendly{to})))%>%>\ %<(zero)%17(unquote(decode(friendly{from})))%> \ %(decode{subject})%<{body}<<%{body}%> nmh-1.7.1-RC3/etc/scan.time000644 007761 000024 00000000456 13205305704 015345 0ustar00kenhstaff000000 000000 %4(msg)%<(cur)+%| %>%<{replied}-%?{encrypted}E%| %>\ %02(mon{date})/%02(mday{date}) \ %02(hour{date}):%02(min{date})%3(tzone{date})\ %<{date} %|*%>\ %<(mymbox{from})%<{to}To:%14(unquote(decode(friendly{to})))%>%>\ %<(zero)%17(unquote(decode(friendly{from})))%> \ %(decode{subject})%<{body}<<%{body}%> nmh-1.7.1-RC3/etc/scan.timely000644 007761 000024 00000000646 13205305704 015713 0ustar00kenhstaff000000 000000 %4(msg)%<(cur)+%| %>%<{replied}-%?{encrypted}E%| %>\ %(void(rclock{date}))\ %<(gt 15768000)%03(month{date})%(void(year{date}))%02(modulo 100)\ %?(gt 604800)%02(mday{date})%03(month{date})\ %?(gt 86400) %(day{date}) %|\ %02(hour{date}):%02(min{date})%>\ %<{date} %|*%>\ %<(mymbox{from})%<{to}To:%14(unquote(decode(friendly{to})))%>%>\ %<(zero)%17(unquote(decode(friendly{from})))%> \ %(decode{subject})%<{body}<<%{body}%> nmh-1.7.1-RC3/etc/scan.unseen000644 007761 000024 00000000416 13205305704 015700 0ustar00kenhstaff000000 000000 %4(msg)%<(cur)+%| %>%<(unseen)U%| %>%<{replied}-%?{encrypted}E%| %>\ %02(mon{date})/%02(mday{date})%<{date} %|*%>\ %<(mymbox{from})%<{to}To:%14(unquote(decode(friendly{to})))%>%>\ %<(zero)%17(unquote(decode(friendly{from})))%> \ %(decode{subject})%<{body}<<%{body}>>%> nmh-1.7.1-RC3/etc/scan.YYYYMMDD000644 007761 000024 00000000575 13205305704 015676 0ustar00kenhstaff000000 000000 %; scan.YYYYMMDD %; %; Like scan.default, but the date is printed in YYYY-MM-DD format rather than %; MM/DD. %; %4(msg)%<(cur)+%| %>%<{replied}-%?{encrypted}E%| %>\ %4(year{date})-%02(mon{date})-%02(mday{date})%<{date} %|*%>\ %<(mymbox{from})%<{to}To:%14(unquote(decode(friendly{to})))%>%>\ %<(zero)%17(unquote(decode(friendly{from})))%> \ %(decode{subject})%<{body}<<%{body}>>%> nmh-1.7.1-RC3/etc/sendfiles000755 007761 000024 00000012403 13243042053 015433 0ustar00kenhstaff000000 000000 #! /bin/sh # # Sends multiple files and/or directories in a MIME message. # Requires tar and any specified compression program. # # 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. usage='Usage: sendfiles [switches] -to recipient -subject subject '"\ "'file1 [file2 ...] or sendfiles [switches] recipient subject file1 [file2 ...] switches are: -compress [bzip2 | compress | gzip | lzma | none] -from -[delay] (expressed in seconds) -version -help Can use PERSON environment variable instead of -from switch.' #### 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 } help() { printf '%s\n' "$usage" #### Print the nmh intro text. ${nmhbindir}/mhparam -help | sed -n -e '/^$/,$p' exit } die() { printf '%s\n' "$usage" exit ${1:-1} } bindir=`finddir $0` nmhbindir=`cd "$bindir" && pwd` nmhlibexecdir=`$nmhbindir/mhparam libexecdir` #### Process switches. compress= ## compress method compressarg=0 ## whether currently handling -compress delay= ## delay value delayarg=0 ## whether currently handling -delay from= ## From: contents fromarg=0 ## whether currently handling -from subject= ## Subject: contents subjectarg=0 ## whether currently handling -subject to= ## To: address toarg=0 ## whether currently handling -to for arg in "$@"; do case $arg in -c|-co|-com|-comp|-compr|-compre|-compres|-compress) compressarg=1 ;; -d|-de|-del|-dela|-delay) delayarg=1 ;; -[0-9]|-[0-9][0-9]|-[0-9][0-9][0-9]|-[0-9][0-9][0-9][0-9]) delay=`printf '%s\n' "$arg" | sed -e 's%-%%'` ;; -f|-fr|-fro|-from) fromarg=1 ;; #### Support -gzip for backward compatibility. -gzip) compress=gzip ;; -h|-he|-hel|-help) help ;; #### Support -none for backward compatibility. -none) compress=none ;; -s|-su|-sub|-subj|-subje|-subjec|-subject) subjectarg=1 ;; -t|-to) toarg=1 ;; -v|-ve|-ver|-vers|-versi|-versio|-version) "$nmhlibexecdir/viamail" -version | sed 's/viamail/sendfiles/'; exit ;; -*) die ;; *) if [ $compressarg -eq 1 ]; then compress="$arg" compressarg=0 elif [ $delayarg -eq 1 ]; then delay="$arg" delayarg=0 elif [ $fromarg -eq 1 ]; then from="$arg" fromarg=0 elif [ $subjectarg -eq 1 ]; then subject="$arg" subjectarg=0 elif [ $toarg -eq 1 ]; then to="$arg" toarg=0 else #### Argument doesn't apply to a switch, so we're done with switches. break fi ;; esac shift done #### Check for switch after non-switch argument. for arg in "$@"; do case $arg in -*) die ;; esac done #### Check for required arguments (to, subject, file(s)). if [ x"$to" = x ]; then if [ x"$subject" = x ]; then if [ $# -ge 3 ]; then to="$1"; shift subject="$1"; shift else die fi else die fi else [ x"$subject" = x -o $# -lt 1 ] && die fi #### Check for missing mandatory arguments. checkforargs() { if [ $compressarg -eq 1 ]; then printf 'sendfiles: missing argument to -compress\n' >&2; exit 1 elif [ $delayarg -eq 1 ]; then printf 'sendfiles: missing argument to -delay\n' >&2; exit 1 elif [ $fromarg -eq 1 ]; then printf 'sendfiles: missing argument to -from\n' >&2; exit 1 elif [ $subjectarg -eq 1 ]; then printf 'sendfiles: missing argument to -subject\n' >&2; exit 1 elif [ $toarg -eq 1 ]; then printf 'sendfiles: missing argument to -to\n' >&2; exit 1 fi } checkforargs [ $# -eq 0 ] && die if [ x"$from" = x ]; then if [ x"$PERSON" = x ]; then from=`"$nmhlibexecdir/ap" -format '%(localmbox)' 0` else from="$PERSON" fi fi #### Determine compression method and descriptive info. if [ x"$compress" = x ]; then for compressor in gzip bzip2 lzma compress none; do if [ x"`finddir $compressor`" = x ]; then :; else compress="$compressor" break fi done fi case $compress in bzip2) uncompress=bzcat; conversion='; x-conversions=bzip2' ;; compress) compress='compress -c'; uncompress='uncompress -c'; conversion='; x-conversions=compress' ;; gzip) compress='gzip -c'; uncompress='gzip -cd' conversion='; x-conversions=gzip' ;; lzma) compress='lzma -c'; uncompress='lzma -cd' conversion='; x-conversions=lzma' ;; none) compress=cat uncompress=cat; conversion= ;; *) printf 'sendfiles: unknown compression method "%s"\n' \ "$compress" >&2 die ;; esac #### Send using viamail. tar cvf - "$@" | $compress | \ "$nmhlibexecdir/viamail" -to "$to" -subject "$subject" \ -from "$from" -parameters "type=tar$conversion" \ -comment "extract with $uncompress | tar xvpf -" \ -delay "$delay" -verbose nmh-1.7.1-RC3/docs/ChangeLog_MH-3_to_MH-6.6000644 007761 000024 00000456277 11723762073 017642 0ustar00kenhstaff000000 000000 MHCHANGES from MH 6.1 to MH 6.6 [It appears that there may be some undocumented changes to MH 6.6 that should appear here. --Dan Harkless] Sun Jan 4 11:16:54 1987 /mtr uip/mhlsbr.c: "extras" hack for Elz Sat Jan 3 15:03:00 1987 /mtr h/formatsbr.h: parenthesize better, use case-sensitive in bucket search since hashing is case-sensitive uip/{rcvdist,replsbr}.c: CT_ADDR hacks Sat Jan 3 13:11:22 1987 /mtr conf/config/mts.c, mts/sendmail/hosts.c: BIND fix-up Fri Jan 2 23:41:19 1987 /mtr uip/rcvdist.c: touch-ups to sync with replsbr.c uip/scansbr.c: trash trailing whitespace in header components for formating Fri Jan 2 18:43:09 1987 /mtr zotnet/tws/dtimep.lex: ctime w/o TZ hack Fri Jan 2 18:42:55 1987 /mtr uip/dropsbr.c: fixes uip/msh.c, support/pop/popser.c: ditto Mon Dec 22 12:32:45 1986 /mtr (agent: Marshall Rose) -- From Stanford -- h/dropsbr.h, uip/dropsbr.c, support/pop/popser.c: support LAST command in POP service uip/{inc,mshcmds}.c: ditto Mon Dec 15 11:11:32 1986 /mtr (agent: Marshall Rose) uip/post.c: patch for MMDF-IIb submit Wed Dec 3 22:03:58 1986 /mtr support/pop/popd.c: minor fix Tue Dec 2 13:57:41 1986 /mtr (agent: Marshall Rose) support/bboards/bbtar.c: fix for sequent machines Sat Nov 22 20:36:31 1986 /mtr uip/bbc.c: set up time-bomb after HUP Fri Nov 21 14:33:28 1986 /mtr (agent: Marshall Rose) sbr/smatch.c: deref null bug Fri Nov 14 17:25:23 1986 /mtr conf/doc/mhook: typo found by Phyl Mon Nov 10 16:57:41 1986 /mtr (agent: Marshall Rose) -- More stuff from Jef -- zotnet/tws/dtimep.lex: default timezone to localone one Mon Nov 10 08:12:16 1986 /mtr -- Stuff from Jef Poskanzer -- uip/forw.c: add -[no]dashmunging, a hidden option uip/mhlsbr.c: add -[no]dashmunging, a hidden option {conf/doc/mhl.rf,uip/mhlsbr.c}: add [no]split variable Mon Nov 3 15:21:38 1986 /mtr (agent: Marshall Rose) sbr/m_sync.c: fix for sequent machines Mon Nov 3 14:11:48 1986 /mtr (agent: Marshall Rose) uip/msgchk.c: another SUN fix Thu Oct 30 13:03:02 1986 /mtr (agent: Marshall Rose) uip/{rcvtty,ttyw}.c: if no BSD42, turn off TTYD Thu Oct 30 12:57:52 1986 /mtr (agent: Marshall Rose) sbr/formataddr.c, uip/replsbr.c: another realloc() bug found by Terry West Thu Oct 9 12:52:41 1986 /mtr (agent: Marshall Rose) h/mh.h: make ruserpass nonsense based on NFS not SUN Wed Oct 8 15:59:05 1986 /mtr (agent: Marshall Rose) uip/vmh.c: more SYS5 mods from Bob Desinger Mon Oct 6 12:07:02 1986 /mtr (agent: Marshall Rose) conf/examples/encore: config file for Encore Multimax, from Mike Iglesias of UCI Thu Oct 2 12:37:57 1986 /mtr support/pop/popd.c: fixes for 4.3BSD set setsockopt Mon Sep 8 12:47:58 1986 /mtr (agent: Marshall Rose) conf/config/MakeBBoards: smarter Fri Sep 5 14:02:36 1986 /mtr (agent: Marshall Rose) zotnet/bboards/bboards.h: add BB_SEEN to fix list-handling bug in bbc uip/bbc.c: use it Fri Sep 5 09:40:35 1986 /mtr (agent: Marshall Rose) uip/msh.c: add hidden "advance" command uip/wmh.c: use it Fri Sep 5 09:08:17 1986 /mtr (agent: Marshall Rose) mts/sendmail/smail.c: define discard() as void Tue Sep 2 15:27:34 1986 /mtr uip/{bbc,burst,popsbr}.c: ULTRIX loses on ferror() vs. feof() sbr/vfgets.c: ditto Fri Aug 29 09:08:15 1986 /mtr (agent: Marshall Rose) uip/wmh.c: for pTTY() make original window the top one Thu Aug 28 19:39:47 1986 /mtr (agent: Marshall Rose) uip/send.c: handle dist in a read-only folder support/pop/popser.c: anonymous fix for DPOP/BPOP Wed Aug 20 17:23:39 1986 /mtr (agent: Marshall Rose) uip/mhlsbr.c: a bit less demanding on errors when processing the face Wed Aug 20 14:16:12 1986 /mtr (agent: Marshall Rose) conf/config/MakeBBoards: smarter rule Mon Aug 18 10:38:34 1986 /mtr (agent: Marshall Rose) uip/wmh.c: new program--Windowing MH for Integrated Solutions Graphics Workstations; not standardly installed for now since requires special load libraries conf/doc/wmh.rf: man page conf/makefiles/uip: support wmh Fri Aug 15 23:01:06 1986 /mtr sbr/advertise.c: slight touch-up Fri Aug 15 13:58:25 1986 /mtr (agent: Marshall Rose) uip/vmh.c: slight clean-up Thu Aug 14 22:25:23 1986 /mtr support/general/replcomps: add return-path to To: list Tue Aug 12 10:54:47 1986 /mtr (agent: Marshall Rose) support/pop/popser.c: small fix from Dave Cohrs Tue Aug 12 10:53:47 1986 /mtr (agent: Marshall Rose) uip/mhlsbr.c: finally stabilize it Mon Aug 11 10:10:33 1986 /mtr (agent: Marshall Rose) uip/mhlsbr.c: choose default face from from: line Fri Aug 8 12:57:35 1986 /mtr (agent: Marshall Rose) conf/config/config.c, h/mh.h, sbr/m_readefs.c, uip/mhlsbr.c: add support for "faceproc" Sun Jul 27 11:52:37 1986 /mtr conf/doc/show.rf: typos Tue Jul 15 20:26:05 1986 /mtr papers/{bboards/bboards,tutorial/tutorial}.tex: botched MTR's address Fri Jul 11 10:50:31 1986 /mtr MH 6.5 official, out of beta, released for UCI distribution Tue Jul 8 10:50:39 1986 /mtr uip/scansbr.c: split-up a statement for the RT compiler conf/mh-gen.8: add some stuff on POP conf/doc/{ADMIN,popaka}.rf: ditto Sun Jun 29 21:11:30 1986 /mtr sbr/addrsbr.c: yet another fix for the SUN (yaffts) conf/mhconfig.c: if both mts/smtp and options BERK, turn off SMTP Mon Jun 23 20:45:35 1986 /mtr uip/vmh.c: Bob gives us another sys5 fix Thu Jun 19 19:51:43 1986 /mtr zotnet/tws/dtimep.lex: fix spelling for august Wed Jun 18 19:57:09 1986 /mtr uip/vmh.c: sanitize for 8-bit whacko characters Wed Jun 18 11:05:40 1986 /mtr support/bboards/bbexp.c: create archives in BBMODE format, private bboards should have archives created by the BBoards user (just like the standard file) Tue Jun 17 15:23:27 1986 /mtr h/mh.h: add vfork for hpux Tue Jun 17 14:21:08 1986 /mtr uip/scan.c: forgot to make -header always force ATZ behavior Tue Jun 17 10:44:06 1986 /mtr uip/trmsbr.c: no TIOCGWINSZ working on 4.2BSD ULTRIX! Mon Jun 16 19:56:09 1986 /mtr sbr/{m_gmsg,pwd}.c, uip/{bbl,conflict,folder,rmf}.c: add NDIR compile-time option if -lndir include file is called instead of (non BSD systems) h/local.h: new file to make this easier Sun Jun 15 14:20:10 1986 /mtr h/scansbr.h, support/general/scan.{timely,time,size}: remove JLR's fix since it doesn't work right Fri Jun 13 20:08:36 1986 /mtr uip/aliasbr.c: not testing for relative names correctly Fri Jun 13 15:28:10 1986 /mtr sbr/addrsbr.c: another #ifdef BERK fix for the SUN Fri 13 Jun 86 10:29 John Romine h/scansbr.h, support/general/scan.{timely,time,size}: add ">>" at end of body in format string Tue 10 Jun 86 15:34 John Romine h/scansbr.h: eliminate superfluous space from default format string Fri Jun 6 10:56:40 1986 /mtr miscellany/less/screen.c: handle HP terminals better Sun Jun 1 23:07:24 1986 /mtr uip/trmsbr.c: add sc_hardcopy() uip/mhlsbr.c: use it so we don't fork a more on hardcopy ttys conf/doc/mhl.rf: document it Thu May 29 23:42:54 1986 /mtr support/general/scan.mailx: mailx scan format from Bob Simpson of plus5 support/general/mhl.body: format from mtrenv Wed May 28 16:56:40 1986 /mtr conf/examples/nrtc-gremlin: add -125 switch for GHS compiler sbr/getans.c,uip/{mhlsbr,prompter,rcvtty,sendsbr}.c: a bit more careful with the setjmp() Wed May 28 12:44:21 1986 /mtr sbr/fmtcompile.c: allow literal '%'s in format files Tue May 27 19:35:38 1986 /mtr support/pop/popd.c: support for 4.3BSD syslog Thu May 22 15:08:06 1986 /mtr support/general/replcomps: typo Thu May 22 08:13:17 1986 /mtr conf/mh-gen.rf: update Thu May 22 08:05:03 1986 /mtr -- Two New Documents from UCI -- conf/makefiles/{papers,dist}: update dist/READ-ME: remove conf/doc/MH.rf: update papers/beginners: new paper "MH for Beginners" papers/mh4mm: new paper "MH for MM Users" Wed May 21 20:51:47 1986 /mtr conf/{mh-gen.8,doc/{ADMIN,MH}.rf, papers/*/*, COVER-LETTER: update mail addresses Wed May 21 10:10:21 1986 /mtr uip/{rcvdist,replsbr}.c: malloc/free fixes from Steve Smith Tue May 20 22:51:13 1986 /mtr -- From Steve Smith -- conf/examples/ridge: config file sbr/{m_gmsg,pwd}.c: although SYS5, uses uip/show.c: not null-terminating argvector uip/{bbc,vmh}.c: although SYS5, has SIGTSTP uip/sbboards.c: pre-emptive reference of discard to help SYS5 loader conf/{mh-gen.8,mhconfig.c}: add "oldload none" Tue May 20 19:09:15 1986 /mtr uip/scan.c: free'ing a static, tsk Thu May 15 17:09:34 1986 /mtr uip/msgchk.c, conf/doc/{mh-chart,msgchk}.rf: add -[no]date, and -[no]notify type switches Thu May 15 16:36:19 1986 /mtr uip/{inc,msgchk,post,send}.c: improve #define-dependent switches declarations Tue May 13 17:44:47 1986 /mtr sbr/{fmtcompile,formatsbr}.c, support/pop/popwrd.c, uip/{ap,inc,rcvtty,post,spost,whatnowsbr}.c: add some lint stuff conf/makefiles/uip: better lint support for TMA Tue May 13 15:14:07 1986 /mtr -- Some Fixes from Hokey -- uip/vmh.c: a few more SYS5 dependencies zotnet/tws/dtimep.lex: added #include strings.h conf/makefiles/zotnet/tws: added dependency for above uip/post.c: pre-emptive reference of discard to help SYS5 loader conf/examples/plus5: update miscellany/less/Makefile: add SHELL=/bin/sh sbr/m_getfld.c: slight redeclaration for SYS5 Tue May 13 07:59:36 1986 /mtr uip/replsbr.c: some fixes from Van Mon May 12 09:12:39 1986 /mtr sbr/m_getfld.c: new version of matchc() from Van that doesn't give the SUN indigestion Sun May 11 12:40:34 1986 /mtr miscellany/scripts/READ-ME: add amhmail description miscellany/scripts/amhmail.sh: new script Thu May 8 17:50:22 1986 /mtr support/bboards/bbexp.c: set the mode on the archive file if creating it, since m_gmprot() isn't a good default for this application Wed May 7 13:16:45 1986 /mtr uip/post.c: modification for fcc:s broke stand-alone behavior for daemons, etc.; use old method as a fall-back sbr/m_foil.c: also improve modification a bit support/pop/smtpd.c: dead weight Mon May 5 16:07:12 1986 /mtr support/bboards/mmdfII/bboards/bb_wtmail.c: patch for IDIOTIC change in qu_rtxt() Mon May 5 13:32:37 1986 /mtr uip/trmsbr.c: try Van's version for a while miscellany/patch: updates from Van Sun May 4 18:08:47 1986 /mtr MH 6.5 #1[UCI] (nrtc-gremlin) made available to Van Jacobson for inclusion in 4.3BSD UNIX Sun May 4 17:49:43 1986 /mtr sbr/pidwait.c, uip/{bbc,sendsbr,vmh}.c: back off signal handling modifications Sun May 4 16:10:36 1986 /mtr conf/doc/mh.rf: forgot about TMA stuff conf/makefiles/doc: forgot rcvstore Sun May 4 14:18:15 1986 /mtr support/general/replcomps: use %tws instead of %pretty support/general/mhl.*: streamline slight Sun May 4 13:28:23 1986 /mtr uip/msgchk.c: change the "last read" message to use alpha-timezones Sat May 3 02:49:29 1986 /mtr zotnet/tws/{tws.h,dtime.c,dtimep.lex}: fixes for DST conf/makefiles/zotnet/tws: add -n to lex's invocation Sat May 3 01:37:15 1986 /mtr sbr/{m_{sync,update},pidwait}.c, uip/{bbc,sendsbr,vmh}: inspired by Van's 4.2BSD signal optimizations Fri May 2 17:02:01 1986 /mtr uip/show.c: WHATNOW botch fixed by Jim Valerio Fri May 2 16:35:11 1986 /mtr -- More Bug Fixes from Van -- uip/scansbr.c: check return from fclose() uip/inc.c: avoid locking/stat race condition sbr/m_sync.c: lock signals out during update of sequences Thu May 1 15:30:07 1986 /mtr -- From Craig Partridge -- support/pop/mmdfII/pop/READ-ME: fixes Tue Apr 29 20:17:11 1986 /mtr conf/doc/mhook.rf: extra tip with SendMail and slocal Mon Apr 28 21:00:21 1986 /mtr -- Yet Another Fix from Terry -- uip/dropsbr.c: another typo Sun Apr 27 17:23:56 1986 /mtr uip/scansbr.c: recognition of 822 Encrypted: header a bit botched h/scansbr.h, support/general/scan.*: support encrypted Fri Apr 25 13:39:55 1986 /mtr -- From Craig Partridge -- support/bboards/mmdfII/bboards/getbbent.c: bad field in BBoards file causes hang, note it and skip! Fri Apr 25 10:47:19 1986 /mtr uip/trmsbr.c: use stdout (not stderr) for termcap checking Fri Apr 25 00:01:50 1986 /mtr conf/ADMIN.rf: slight touch-up Thu Apr 24 23:53:57 1986 /mtr -- From Craig Partridge -- support/bboards/mmdfII/bboards/*: bug fixes for MMDF-IIb conf/mh-gen.8: mention that MMDF-IIb has the BBoards distribution Thu Apr 24 20:13:28 1986 /mtr uip/msgchk.c: print out last read date conf/makefiles/uip: add tws dependency Thu Apr 24 19:37:09 1986 /mtr conf/doc/ADMIN.rf: typos Thu Apr 24 10:34:06 1986 /mtr zotnet/mts/lock.c: lint touch-up support/pop/popd.c: ditto Thu Apr 24 00:19:35 1986 /mtr conf/doc/mh-chart.rf: slight mods for TMA mods Mon Apr 21 17:31:43 1986 /mtr uip/{inc,post}.c: slight mods for TMA mods conf/doc/mh-chart.rf: ditto Mon Apr 21 10:22:09 1986 /mtr zotnet/mf/mf.c: sanity check in getadrx() on string to parse Thu Apr 17 20:51:53 1986 /mtr zotnet/mts/lock.c: add some more #ifdefs to support stand-alone locking library conf/examples/udel*: update papers/myths/: remove conf/makefile/papers: update Thu Apr 17 13:25:20 1986 /mtr sbr/addrsbr.c: fix from Terry West, more alternate-mailbox misery Mon Apr 14 23:52:03 1986 /mtr sbr/m_getfld.c: locc() not range checking on cnt Mon Apr 14 22:56:46 1986 /mtr support/bboards/bbexp.c: not ending msh correctly, msh tried to update the maildrop even though it was already locked by bbexp Sat Apr 12 16:32:21 1986 /mtr uip/post.c: try to keep fcc:s under MH-directory so links are maintained Thu Apr 10 15:06:59 1986 /mtr conf/config/bboards.*: mail reports to PostMaster Thu Apr 10 10:42:25 1986 /mtr uip/scansbr.c: recognize the 822 "Encrypted:" header instead of doing a uprf() on the body uip/{scan,mshcmds}.c: recognize SCNENC return from scan () Thu Apr 10 03:47:48 1986 /mtr sbr/m_getfld.c: Van fixes Marshall's fix Thu Apr 10 02:26:52 1986 /mtr Makefile: touch-up "make distribution" conf/examples/nrtc-*-mtr: remove conf/makefiles/uip: touch-up conf/doc/MH.rf: add TMA stuff, conditionally Wed Apr 9 22:08:37 1986 /mtr uip/vmh.c: output non-standard control characters in carat format Wed Apr 9 12:36:58 1986 /mtr -- MTR actually gets to fix something! -- sbr/m_getfld.c: messages with an empty body caused inc to prematurely think the maildrop had reached EOF. Believe it or not, the mhmail fix last month exercised this! Wed Apr 9 12:04:56 1986 /mtr -- Van fixes some more bugs -- sbr/m_getfld.c: not handling buffer boundary cases right uip/replsbr.c: not adding "," correctly when concatenating an address string during message scan sbr/formatsbr.c: mymbox test dumped core if address parse failed h/{fmtcompile,formatsbr}.h, sbr/{fmtcompile,formatsbr}.c: more enhancements Mon Apr 7 09:55:23 1986 /mtr mts/sendmail/smail.c: slight "client" check Sun Apr 6 19:22:52 1986 /mtr uip/inc.c: forgot to initialize some FILE*'s; dumps core on celerity Wed Apr 2 17:17:32 1986 /mtr sbr/addrsbr.c: slight typo in comment Mon Mar 31 15:07:26 1986 /mtr uip/replsbr.c: handle bad addresses with better diagnostics Sat Mar 22 18:24:35 1986 /mtr uip/mhmail.c: handle -body better Sat Mar 22 11:51:45 1986 /mtr -- Fixes from Phyllis Kantar -- uip/dropsbr.c: typo conf/doc/{send,pick}.rf: typos conf/makefiles/doc: forgot $(OPTIONSn) in $(MAN1) definition Fri Mar 21 21:12:39 1986 /mtr conf/doc/{MH,mh-format}.rf: typos Thu Mar 20 23:05:10 1986 /mtr uip/mhlsbr.c: mhl enhancement from JLR permitting a prefix string for each line of the body (e.g, "component=" > ") Wed Mar 19 23:12:54 1986 /mtr -- Changes for MMDF-IIb -- uip/post.c, support/bboards/mmdfII/bboards/bb_wtmail.c: know about new mm_winit protocol and RP_NS/RP_DOK responses Wed Mar 19 23:00:53 1986 /mtr support/pop/popser.c: one last fix for ENOENT mailboxes Sun Mar 16 15:20:27 1986 /mtr miscellany/mem: appointment diary support from Ken Yap Tue Mar 11 19:43:27 1986 /mtr h/dropsbr.h, uip/dropsbr.c: new routines mbx_read() and mbx_write() uip/{msh,mshcmds}.c, support/pop/popser.c: use it h/{addr,format,scan}sbr.h, sbr/addrsbr.c: slight touch-up uip/inc.c: slight touch-up Mon Mar 10 18:08:37 1986 /mtr uip/post.c: fix handling of (in)visible addresses uip/rcvdist.c: re-do to use format facility uip/{replsbr,forw}.c: touch-ups conf/config/config.c, h/mh.h: new variable rcvdistcomps conf/{makefiles/{uip,support/general},doc/mhook.rf}: update sbr/m_getfld.c: bstring() support for non BSD42, SYS5 systems conf/doc/ADMIN.rf: update Mon Mar 10 10:17:29 1986 /mtr {sbr/formatsbr,uip/scansbr}.c: more optimizations from Van! sbr/m_getfld.c: Van fixes problems due to losing vanilla-4.2 C optimizer! sbr/m_getfld.c: slight touch-up by MTR uip/bbc.c: remove #ifdef MTR bracketing, code works fine uip/refile.c: slight touch-ups sbr/m_getfld.c: on xxxERR returns, forgetting to zero value buffer Mon Mar 10 00:43:19 1986 /mtr uip/{msh,mshcmds}.c: packf hack, ala refile hack uip/{post,rcvdist}.c, support/bboards/mmdfII/bboards/bb_wtmail.c: MMDF-II nameserver support from Steve Kille Sun Mar 9 20:09:35 1986 /mtr zotnet/bboards/bboards.h: add BB_REMOTE flag for bbc uip/bbc.c: support BB_REMOTE, under #ifdef MTR for the moment uip/bbc.c: allow bb_aka (again?!?) Sun Mar 9 18:52:37 1986 /mtr h/scansbr.h, support/general/{digestcomps,mhl.forward,scan.*}: update Sun Mar 9 14:06:54 1986 /mtr h/scansbr.h, sbr/fmtcompile.c: better versions from Van support/general/{replcomps,scan.timely}: better versions from Van (snuck the %pretty instead of %tws in, eh Van?) support/general/{digestcomps,mhl.forward,scan.{size,time}}: update Sun Mar 9 14:04:26 1986 /mtr conf/mh-gen.8: add a line about chown and sys5 sbr/m_convert.c: better BADRNG diagnostic uip/mshcmds.c: oops, typo Thu Mar 6 13:36:26 1986 /mtr uip/addrsbr.c: yet another fix for ismymbox() uip/replsbr.c: #ifdef ISI code to avoid duplicate replies (due to Jim Koda) Wed Mar 5 12:48:58 1986 /mtr dist/READ-ME: oops, forgot usenix name change conf/makefiles/uip: hmm, interesting loader problem Tue Mar 4 09:53:31 1986 /mtr papers/usenix/: change to realwork/ Tue Mar 4 08:15:17 1986 /mtr -- Van sends fixes to my updates -- uip/mhlsbr.c: not resetting mhlsbr for formatting zotnet/tws/dtimep.lex: not getting MIL-TZ's right Mon Mar 3 16:53:19 1986 /mtr uip/sendsbr.c: oops, close() on an uninitialized variable! (thanks to Jim Koda) Mon Mar 3 10:18:40 1986 /mtr -- Van sends fixes to my updates -- uip/mshcmds.c: not resetting scansbr for formatting uip/scansbr.c: oops, typo! Thu Feb 27 22:16:43 1986 /mtr sbr/formataddr.c: remove sbr/addrsbr.c: Van doesn't like "user*" instead of "user" as the default is-my-mailbox for BERK. Since he's the BERK-author, I'll assume he knows what he's doing... support/general/replcomps: Use "tws", instead of "pretty" for in-reply-to: uip/whatnowsbr.c: If -draft{folder,message} and -nodraftfolder are added as no-ops, make them "hidden" from -help output uip/{{a,d}p,forw,mhlsbr}.c: update Thu Feb 27 22:12:53 1986 /mtr -- Van sends updates -- conf/makefiles/uip, h/fmtcompile.h, sbr/{format{addr,sbr},fmtcompile,addrsbr}.c, support/general/replcomps, uip/{repl,mhl,scan,whatnow}sbr.c Wed Feb 26 21:05:46 1986 /mtr uip/sendsbr.c: better diagnostics when post fails Tue Feb 25 17:45:28 1986 /mtr h/mshsbr.h, uip/msh*.c: add direct folder support for symmetry's sake, ugh! Tue Feb 25 09:47:09 1986 /mtr uip/{scan,mshcmds}.c: slight touch-ups uip/mhlsbr.c: fix up SIGPIPE handling, again support/general/scan.time: fix up for numeric timezone uip/scansbr.c: re-support "encrypted" uip/msh.c: add "exit" command for Dave Farber miscellany/convert: new directory Tue Feb 25 08:08:43 1986 /mtr uip/burst.c: another realloc() fix from Terry West sbr/vfgets.c: ditto support/pop/popser.c: enhancmenets from Dave Cohrs conf/doc/pop5.rf: document it conf/mhconfig.c: support "debug" directive makefiles/*: use it Mon Feb 24 17:14:39 1986 /mtr uip/inc.c: have -host/-file ask if file doesn't exist uip/{packf,mshcmds}.c: ditto Sun Feb 23 13:59:46 1986 /mtr sbr/m_gmsg.c: big bug fix from Terry West. Thanks, Terry! h/strings.h: System5 bcopy-equivalents from Doug Gwyn zotnet/tws/tws.h: support #ifdef ATZ conf/makefiles/uip: slight lint botch Thu Feb 20 22:57:33 1986 /mtr MH 6.4 #1[UCI] (nrtc-gremlin) made available to Van Jacobson for inclusion in 4.3BSD UNIX Thu Feb 20 19:55:20 1986 /mtr uip/mhlsbr.c: add formatsbr support sbr/addrsbr.c: use better default matching in ismymbox miscellany/mtrenv: update support/general/mhl.*: update Thu Feb 20 08:07:49 1986 /mtr uip/{a,d}p.c: start working on it h/formatsbr.h: new variable fmt_norm sbr/formatsbr.c: use it h/fmtcompile.c, sbr/{fmtcompile,formatsbr}.c: define "pretty" sbr/formataddr.c: sight touch-up uip/formatsbr.c: oops, bug in PUTD() uip/{fmtcompile,formatsbr}.c: init mn structures in case of error. This is still buggy since: 1) the structure still doesn't get reset on errors, and 2) you can still dereference nulls zotnet/tws/dtimep.lex: slight touch-up Wed Feb 19 10:50:04 1986 /mtr papers/mh6.4: new interim documentation directory, for 4.3BSD conf/doc/{MH,ap,dp,mh,mh-chart,mhl,repl,scan}.rf: update conf/doc/mh-format.rf: new file support/general/replcomps: oops, should call formataddr on all addrs Wed Feb 19 03:11:42 1986 /mtr sbr/{formataddr,fmtcompile,m_{draft,getfld,maildir},printsw,pwd}.c: lint it uip/{formatsbr,forw,msh,replsbr,scan,scansbr,spost}.c: lint it support/pop/popser.c: lint it sbr/formatsbr.c: remove MHFMTDEBUG code */Makefile: depend 'em Wed Feb 19 01:55:40 1986 /mtr h/mh.h: add msg_* vars in m_getfld() as externs uip/{msh,{repl,scan}sbr}.c: remove msg_* declarations sbr/m_getfld.c: add a bit of BODYEOF support (without slowing it down, wouldn't want to upset Van!) Wed Feb 19 00:56:30 1986 /mtr sbr/m_getfld.c: different fix for packf'd files from Van Wed Feb 19 00:16:55 1986 /mtr uip/dist.c, support/general/distcomps, sbr/fmtcompile.c: updates from Van sbr/formatsbr.c: remove ismymbox prime sbr/fmtcompile.c: use adios(), not exit()! Tue Feb 18 22:14:51 1986 /mtr sbr/m_getfld.c: eom_action() lacking argument sbr/m_getfld.c: not working right on packf'd files uip/{msh,mshcmds}.c: under BPOP, need to fix things so m_getfld() doesn't dump core! Tue Feb 18 02:15:00 1986 /mtr uip/bbc.c: upgrade for new m_getfld() support/general/scan.*, h/scansbr.h: still more changes support/general/replcomps: still more changes Tue Feb 18 01:13:51 1986 /mtr h/formatsbr.h: updates from Van Mon Feb 17 20:14:35 1986 /mtr support/general/scan.{time,size}: mday/month inverted sbr/{formatsbr,fmtcompile}.c: bring upto date with MH 6.3+ sbr/formatsbr.c: missing tzone/sday/dst handling! h/scansbr.h: slight update uip/scansbr.c: try using formataddr() routine to do "correct" formatting of scan'd addresses, didn't work! use friendly zotnet/tws/dtimep.lex: tsk, use lint! also, fix numeric timezones sbr/addrsbr.c: some ismymbox fixes for non-BERK code (from 6.3) sbr/formatsbr.c: not priming the pump! h/fmtcompile.h, sbr/{formatsbr,fmtcompile}.c: add "friendly" support/general/scan.time2: call it scan.timely conf/makefiles/support/general: support scan.timely Sun Feb 16 23:04:34 1986 /mtr zotnet/fmt/: move into sbr/ to avoid loading problems sbr/{addrsbr,formatsbr,fmtcompile,formataddr}.c: new files h/fmtcompile.h: new file conf/makefiles/{sbr,zotnetM}: update sbr/llib-lmh: update Sun Feb 16 19:11:33 1986 /mtr -- Incorporate Berkeley enhancements, courtesy of Van Jacobson -- h/{format,scan}sbr.h: updated for new formatsbr stuff h/mh.h: updated for new m_getfld conf/MH: new default file conf/config/config.c: support spost under BERK and SENDMTS conf/mhconfig.c: support new zotnet/fmt/ directory conf/makefiles/uip: support spost conf/makefiles/zotnetM: support new zotnet/fmt/ directory conf/makefiles/zotnet/fmt: new Makefile conf/makefiles/zotnet/tws: support for new lex-based date parser sbr/m_gmsg.c,uip/msh.c: change init of READONLY sbr/m_getfld.c: re-written, super optimized! support/general/{digestcomps,mhl.digest,mhl.forward,scan.*}: use new fmt stuff zotnet/fmt/: new directory zotnet/tws/{dtimep.lex,lexedit.sed,lexstring.c}: new files zotnet/tws/dtime.c: update uip/{forw,scan,scansbr}.c: use new format stuff uip/{inc,mhlsbr,mshcmds,replsbr}.c: use new format stuff uip/trmsbr.c: use stderr for ioctl()s uip/spost.c: new file uip/{addr,format}sbr.c: remove, they're in zotnet/fmt/ Sun Feb 16 15:40:20 1986 /mtr sbr/m_setvis.c: oops, fix-up unseen sequence stuff uip/whatnowsbr.c: oops, a couple of typos Sun Feb 9 22:14:10 1986 /mtr support/pop/syslog.c: #ifdef BSD43 means use standard syslog Wed Feb 5 14:42:55 1986 /mtr zotnet/tws/{tws.h,dtime.c}: new argument to dasctime() uip/{format,pick}sbr.c: make use of it Wed Feb 5 11:25:05 1986 /mtr MH 6.3 #1[UCI] (nrtc-gremlin) is official, still awaiting Berkeley enhancements Wed Feb 5 09:32:08 1986 /mtr support/bboards/mmdfII/READ-ME: update Mon Feb 3 11:21:49 1986 /mtr uip/whatnowsbr.c: oops, slight dist botch support/general/mhl.format: make date display user-friendly conf/mh-gen.8: clean-up descriptions of options uip/sbboards.c: normalize code wrt to MMDF-II BBoards channel uip/msh.c: when running under vmh and not in control of TTY, ignore TSTP so BPOP can spool ahead! papers/{usenix/usenix,multifarious/multifarios,trusted/trusted}.tex: fix up banners a bit Sun Feb 2 20:47:36 1986 /mtr miscellany/replies/: new directory Sun Feb 2 14:01:28 1986 /mtr zotnet/tws/dtime.c: twsort() fix from John Romine for ALTOS uip/addrsbr.c: smarter ismymbox for default case conf/{mh-gen.8,doc/repl.rf}, uip/repl.c: add #ifdef ATHENA code Fri Jan 31 13:25:17 1986 /mtr COVER-LETTER: update support/general/mhl.format: Remove length/width constraints Mon Jan 27 17:51:07 1986 /mtr uip/whatnowsbr.c: forgot to put -[no]push for built-in send h/addrsbr.h, uip/{addrsbr,post}.c: introduce auxformat(), the back-end to adrformat(); post calls auxformat directly in certain cases uip/{dp,forw}.c: was cheating on adrformat, now on auxformat Sun Jan 26 16:57:18 1986 /mtr {conf/makefiles/uip,uip/post.c}: lint touch-up conf/doc/{inc,mh-chart,send,post}.rf: add the #ifdef TMA stuff sbr/m_remsg.c: tuning uip/mark.c: re-arrange debug output slightly h/mh.h: add some padding to fix some m_remsg bugs uip/{inc,rcvstore}.c: oops, mp -> hghmsg not keeping pace with m_remsg! Wed Jan 22 11:13:08 1986 /mtr support/pop/popwrd.c: squash bug h/mh.h: remove sigmask definition uip/{bbc,vmh}.c: add sigmask if not defined in (4.3BSD finally wised up!) Fri Jan 17 13:19:23 1986 /mtr uip/ali.c: add -noalias for RaJ Wed Jan 15 23:15:54 1986 /mtr support/pop/popsbr.c: pophack on PASS command Wed Jan 15 19:03:54 1986 /mtr COVER-LETTER: update Wed Jan 15 18:44:32 1986 /mtr uip/addrsbr.c: ismymbox() losing under #ifdef DUMB, oops! Wed Jan 15 04:43:33 1986 /mtr miscellany/netnews/: more stuff Sun Jan 12 22:58:34 1986 /mtr uip/bbc.c: getbbvis a bit too agressive, use popd algorithm Sun Jan 12 14:01:25 1986 /mtr miscellany/mh-e: new version from James Larus Fri Jan 10 10:17:57 1986 /mtr uip/sbboards.c: botch multiple bboard handling (forgot to rewind input, thanks to Larry Henry) support/bboards/mmdfII/bboards/bb_wtmail.c: not handling errors right sbr/cpydgst.c: stay symmetric with change to bb_wtmail.c, the code worked fine, adding matching braces for clarity (!!) Thu Jan 9 22:37:29 1986 /mtr MH 6.2 is official, awaiting enhancements Berkeley! Thu Jan 9 16:31:28 1986 /mtr uip/mshcmds.c: don't rmm() messages which don't get refiled uip/vmh.c: truncate stuff on Scan window (finally) uip/scansbr.c: work on diagnostics a bit Thu Jan 9 15:29:09 1986 /mtr -- Fixes Suggested by Craig Partridge -- support/bboards/mmdfII/bboards/mmdfonly.h: if V4_2BSD on, set BSD42 conf/doc/{mhl,show}.rf: talk more about moreproc uip/mhlsbr.c: have INTR work as advertised uip/{send,whatnowsbr}.c: link on dist botched, oops! Wed Jan 8 23:16:10 1986 /mtr uip/trmsbr.c: better defaults for "li" and "co" Tue Jan 7 15:06:05 1986 /mtr uip/bbc.c: got the SIGTSTP problem, now wait on child to stop prior to stopping ourselves... Mon Jan 6 15:25:20 1986 /mtr uip/{msh,mshcmds}.c: work on refile uip/{vmh,msh}.c: support FAST quit (no final refresh on updated mailbox) Sun Jan 5 20:06:03 1986 /mtr (agent: Marshall Rose) -- Interface TTI TMA to MH #6.2 -- [ N.B.: The TTI TMA is NOT in the public domain; the MH support for the TTI TMA IS in the public domain! ] conf/{mh-gen.8,mhconfig.c,doc/ADMIN.rf}: support "tma on" conf/makefiles/{doc,uip}: ditto Makefile: for the moment Fri Jan 3 13:11:03 1986 /mtr uip/bbc.c: SIGTSTP race condition, #undef for now Tue Dec 31 23:21:21 1985 /mtr uip/mhlsbr.c: a bit more pipe trickyness (this gets old real fast) conf/doc/ADMIN.rf: talk about popd and /etc/rc.local papers/{myths,mznet}/Makefile: update uip/bbc.c: augment XTND2 botch diagnostic uip/msh.c: if popd says BBoard-ID: for a message is 0, read it ourselves Tue Dec 31 22:23:43 1985 /mtr conf/doc/mhook.rf: minor typos miscellany/rcvtrip/*: update Tue Dec 31 19:16:23 1985 /mtr zotnet/tws/{dtime,dtimep}.c: dst fix-ups conf/doc/send.rf: append, not prepend uip/rmail.c: slight touch-up uip/ap.c: oops, not printing all info zotnet/mf/mf.c: botching trailing comment handling! uip/scansbr.c: have cpy() omit trailing >>blank<< sbr/m_gmsg.c: not zero'ing msgstats[] under non-MTR code Tue Dec 31 13:53:14 1985 /mtr conf/doc/whatnow.rf, uip/whatnowsbr.c: remove "headers" option conf/doc/ADMIN.rf: clear-up post -debug documentation conf/doc/{mh-chart,send,post}.rf, uip/{post,send,whatnowsbr}.c: remove -[no]remove switches uip/{repl,post}.c: some touch-ups Tue Dec 31 10:13:44 1985 /mtr conf/doc/vmh.rf: back-down last update conf/mh-gen.8: forgot an \& conf/examples/nrtc-{gw,mtr}, h/rcvmail.h: tsk, NRTC running an old MMDF-II Mon Dec 30 20:03:25 1985 /mtr conf/Makefile: options mangled(!?!) uip/msh.c: if update of mailbox fails, it gets zero'd(!!) (oops, not checking error condition) support/pop/popser.c: if update of mailbox fails, clean-up correctly (no zero problem here!) uip/inc.c: on truncate of maildrop, remove mailbox map (XXX) conf/makefiles/uip, uip/{send,whatnowsbr}.c: move send into the WhatNow shell uip/sendsbr.c: new file conf/doc/whatnow.rf: update Sun Dec 29 19:58:43 1985 /mtr zotnet/mts/client.c: fix #ifdef BIND stuff a bit h/mshsbr.h, uip/{mhlsbr,msh,mshcmds}.c: try to fix lost peer problems... conf/doc/vmh.rf: update zotnet/drop/lock.c: not returning right errno uip/dropsbr.c: ditto, plus not trying enough conf/makefiles/doc: "make tar" forgetting tmac.h uip/addrsbr.c: strcpy de-referencing NULL uip/refile.c: got rid of a spurious \n (!!) conf/examples/{udel,nrtc-mtr}: new files h/mh.h, sbr/m_{convert,gmsg}.c, uip/{msh,rcvstore,refile}.c: fix LOWSEL logic uip/vmh.c: fix slight bug in sideground handling (misspelled #ifdef, oops!) conf/{mh-gen.8,config/mts.c},mts/*/hosts.c: remove the NETWORK option Thu Dec 19 23:58:44 1985 /mtr Release MH 6.2 to selected sites, including Berkeley for 4.3BSD testing Thu Dec 19 22:34:23 1985 /mtr zotnet/mts/client.c: #ifdef BIND code when no gethostent() conf/{mh-gen.8,doc/mh-tailor.rf}: document it Thu Dec 19 08:16:54 1985 /mtr uip/refile.c: better diagnostic from Fred Blonder Wed Dec 18 22:51:58 1985 /mtr uip/bbc.c: optimize on calling mshproc, check size of maildrop first; if empty, don't invoke it! Wed Dec 18 20:27:38 1985 /mtr uip/slocal.c: minor touch up uip/umhook.c: moved from zotnet/mf Wed Dec 18 13:37:09 1985 /mtr uip/bbc.c: make second, optimized pass to catch private bboards that the user knows about uip/popsbr.c: ditto uip/popser.c: slight tune-up Tue Dec 17 21:42:44 1985 /mtr conf/makefiles/sbr, h/mh.h, sbr/llib-lmh: cndfree() removed sbr/{add,m_{delete,replace}}.c, uip/{mhl,vmh}sbr.c: replace cndfree sbr/m_foil.c, uip/install-mh.c: compensate Tue Dec 17 18:26:34 1985 /mtr sbr/m_getfld.c, uip/{format,mhl,pick}sbr.c: clean-up indirection code for less tolerant compilers uip/bbc.c: add -[no]rcfile switch uip/msh.c: clean up a diagnostic Tue Dec 17 08:53:52 1985 /mtr conf/makefiles/sbr, sbr/cndfree.c: clean-up a bit Tue Dec 17 08:36:59 1985 /mtr uip/send.c: different alert announcement based on -forward Wed Dec 11 19:08:20 1985 /mtr miscellany/libndir: -lndir for non-BSD sites, graciously supplied by Kirk McKusick Tue Dec 10 23:28:20 1985 /mtr uip/sbboards.c: oops, typo found by lint Tue Dec 10 22:38:23 1985 /mtr uip/addrsbr.c: normalize a bit (finally) uip/addrsbr.c: new routine adrsprintf() to remove #ifdef BANG dependencies uip/{post,rcvdist,replsbr,sbboards}.c: use adrsprintf() uip/post.c: remove #ifdef MF dependency for stand-alone MH, remove #ifdef DUMB dependency by making addrsbr.c smarter about being dumber mts/mmdf/hosts.c: remove #ifdef DUMB dependency (right now, addrsbr:getm() is the only one that calls it and it doesn't call it under #ifdef DUMB... Tue Dec 10 21:11:45 1985 /mtr conf/mh-gen.8: clear up some sys5 stuff zotnet/mf/umhook.c: sys5-ize uip/addrsbr.c: alternate-mailboxes: defaulted wrong under #ifdef BERK, it's now "*" conf/doc/mh-profile.rf: fix documentation to reflect reality Tue Dec 10 18:39:37 1985 /mtr zotnet/mts/client.c: moved from mts/sendmail/client.c conf/makefiles/{mts/sendmail,zotnet/mts}: changed mts/support/llib-lsendmail, zotnet/mts/llib-lmts: changed mts/sendmail/client.c: 4.2BSD specific only! conf/config/mts.c, zotnet/mts/mts.h: update conf/mhconfig.c: update conf/Makefile: simplify Sun Dec 8 18:39:01 1985 /mtr uip/send.c: always remove dist file uip/vmh.c: work on erase-word handling, a bit uip/folder.c: -fast -vs- -pack fixup uip/mhlsbr.c: %text defined for date fields Fri Dec 6 11:08:20 1985 /mtr support/bboards/mmdfII/gen: wrong filename Thu Dec 5 19:55:11 1985 /mtr uip/scansbr.c: fix machine dependency pointed out by Chuck Collins dist/READ-ME: new file talking about make bug COVER-LETTER, conf/{mh-gen.8,doc/MH.rf}: change UCI -> UCI.EDU Wed Dec 4 23:38:06 1985 /mtr zotnet/mts/mts.h: oops for MMDFONLY conf/{mh-gen.8,makefiles/zotnet/mts}: talk about -Dlocname Sun Dec 1 16:11:03 1985 /mtr uip/inc.c: more idiotic de-referncing of NULL, found on SUNs uip/replsbr.c: ditto uip/show.c: recognize more of mhl's switches Sun Dec 1 07:58:50 1985 /mtr uip/vmh.c: remove double-scroll uip/annosbr.c: oops, closing fd: without unlocking! sbr/makedir.c: plug an obscure security hole in inc uip/mhlsbr.c: read_termcap being called prematurely zotnet/tws/dtime.c: load tw_sday appropriately zotnet/tws/*.c: try using numeric timezone for official renditions, under #ifdef MTR for now Sat Nov 30 22:36:49 1985 /mtr zotnet/tws/dtime.c: add #ifdef INETONLY uip/post.c: for #ifdef BERK don't say {Local,UUCP,Network} Recipients conf/doc/sortm.rf: note problem with errors uip/bbc.c: for getbbvis() insist on readability support/bboards/bbexp.c: oops, calling pick wrong conf/doc/pick.rf: document -datefield anomaly conf/makefiles/support/bboards: oops, left context owned by root h/mh.h: ruserpass -> _ruserpass for SUN. why? Tue Nov 26 00:22:17 1985 /mtr uip/refile.c: oops, forgot copy-back on optimzied m_remsg Sun Nov 24 18:58:41 1985 /mtr uip/slocal.c: some tuning, also fix a bug in usr_pipe() uip/dropsbr.c: have mbx_copy support noisy uip/{packf,post,rcvpack,sbboards,slocal}.c: use this change Wed Nov 20 10:58:40 1985 /mtr MH 6.1 covert update for sbr/m_convert.c, uip/send.c Tue Nov 19 23:06:16 1985 /mtr uip/send.c: de-referencing NULL due to bad precedence, tsk Sun Nov 17 16:28:23 1985 /mtr conf/doc/{ap,mhl,repl,scan}.rf: note that #ifdef BERK kills address parsing conf/makefiles/{doc,uip,support/*,zotnet/*}: make tar command visible sbr/m_convert.c: oops, new message numbering resulted in bad diagnostic papers/*/Makefile: fix LaTeX rule for v2.08 Fri Nov 15 19:14:44 1985 /mtr uip/{rcvtty,slocal}.c: touch-ups Tue Nov 12 11:24:46 1985 /mtr MH 6.1 is official. MHCHANGES from mh.5 to mh.6 Mon Nov 11 07:47:05 1985 /mtr uip/slocal.c: implemenet MailDelivery, ala MMDF-II uip/rcv*.c: take advantage of it uip/rcvs{br,elect}.c: no longer needed uip/{folder,inc,refile}.c: done(1) if user doesn't want to create folders Sun Nov 10 16:30:46 1985 /mtr uip/refile.c: set previous sequence on destination folders uip/rcvsbr.c: new file uip/rcvpack.c: change Cron-Date: to Delivery-Date: Sun Nov 10 11:52:50 1985 /mtr uip/send.c: oops, annotations botched for forw! Thu Nov 7 00:31:45 1985 /mtr sbr/m_tmpfil.c: new routine uip/*.c: use it if necessary Wed Nov 6 23:05:00 1985 /mtr uip/inc.c: add -[pa]ck file switches to packf(1) with the POP uip/bbc.c: add $MHBBRC support Wed Nov 6 20:47:55 1985 /mtr uip/msh.c: more msh-using-POP-to-read-BBoards speed improvements Wed Nov 6 14:08:08 1985 /mtr uip/mshcmds.c: burst wasn't resetting scan listing cache mts/sendmail/client.c: don't use servers defaulting if name of service host is explicitly given Wed Nov 6 01:55:16 1985 /mtr support/bboards/mmdfII/bb_wtmail.c, uip/sbboards.c: use encapsulation format when returning failed mail Tue Nov 5 22:43:50 1985 /mtr zotnet/bboards/{bboards.h,getbbent.c}: new routine getbbtime() support/pop/{popd,popser}.c: use getbbtime() to speed start-up time, a major win! conf/makefiles/uip: oops, sbboards installed in wrong area! Tue Nov 5 22:29:29 1985 /mtr sbr/m_replace.c: fix logic glitch: not using getcpy() on update! Tue Nov 5 16:15:52 1985 /mtr zotnet/bboards/getbbent.c: optimize a bit zotnet/bboards/{bboards.h,getbbent.c}: new routine setpwinfo() support/{bboards/mmdfII/bboards/bb_wtmail,pop/pop{ser,wrd}}.c, uip/sbboards.c: use setpwinfo () uip/mshcmds.c: slight typo in msh$pick Mon Nov 4 16:00:56 1985 /mtr uip/vmh.c: Wgetstr() now minibuffer-exit's right Mon Nov 4 09:16:56 1985 /mtr uip/send.c: oops, bug in dist handling conf/{mhconfig.c,mh-gen.8}: warn about mhconfig requiring make clean later Sun Nov 3 22:06:58 1985 /mtr uip/vmh.c: work-around standout bug in curses, under #ifdef XYZ uip/vmh.c: try slight work-around for double-scroll'ing effect Sun Nov 3 13:12:51 1985 /mtr uip/version.sh: smarter wrt finding hostname uip/msh.c: finally got re-direction under vmh right! uip/mhlsbr.c: for moreproc, get signal handling right Thu Oct 31 21:40:50 1985 /mtr Makefile, conf/makefiles/*: rm core in unclean sbr/m_atoi.c: renamed from mu_atoi() uip/bbc.c: minor add_bb() logic fix uip/new.c, support/news/: de-supported! uip/msh.c: re-direction under vmh was losing Wed Oct 30 18:20:11 1985 /mtr -- Suggested by James M. Galvin -- uip/bbl.c: invoke inc with -file not -ms Wed Oct 30 18:19:49 1985 /mtr -- Suggested by Douglas P. Kingston -- mts/mmdf/hosts.c: remove bogus gethostname() logic, let the mtstailor file handle it. Wed Oct 30 16:39:56 1985 /mtr Makefile: add "make checkout" for MH maintainers only! uip/version.sh: extend Tue Oct 29 22:33:45 1985 /mtr h/dropsbr.h: new routine map_read() uip/dropsbr.c: performance improvement in map_read() uip/msh.c: -[no]topcur for vmh usage Tue Oct 29 01:25:36 1985 /mtr uip/addrsbr.c: freeing a couple of things twice! uip/msh.c: a malloc() bug! Mon Oct 28 19:31:13 1985 /mtr uip/vmh.c: don't read tty modes unless in foreground Sun Oct 27 22:13:23 1985 /mtr h/dropsbr.h, uip/dropsbr.c: add new field, m_size, to maildrop structure (and bump version number). This keeps track of the number of ARPA Internet octets in the message support/bboards/mmdf*/bboards/bb_wtmail.c, support/pop/popser.c, uip/dropsbr.c, uip/mshcmds.c, uip/rcvpack.c, uip/sbboards.c: all affected... Sun Oct 27 17:40:20 1985 /mtr zotnet/bboards/{bboards.h,getbbent.c}: make make_lower() integral uip/vmh.c: avoid ~'s when possible (actually forever owing to pWIN logic!) uip/vmh.c: make STATUS window be reverse-video, make prompt not be reverse-video uip/vmh.c: have EOT work as expected under bbc uip/vmh.c: if CE set, then don't scroll on exit uip/msh.c: make readids() logic smarter in the degenerate case h/mshsbr.h, uip/{msh,mshcmds}.c: keep scan line cached uip/{msh,mshcmds}.c: clean-up handling under vmh a bit uip/{bbc,inc,msgchk}.c: improve defaulting for nullifying host conf/config/mts.c: with flock() retry 5 times at 5 second intervals Fri Oct 25 08:38:35 1985 /mtr support/pop/popser.c, uip/bbc.c: don't recognize bb_aka's in name lookups Thu Oct 24 21:07:37 1985 /mtr conf/config/mts.c: new variable popbblist which, if present, lists only thoses hosts that can use BBoards over POP Wed Oct 23 20:46:17 1985 /mtr uip/prompter.c: -prepend is the default now uip/burst.c: -noinplace is the default now Wed Oct 23 12:34:04 1985 /mtr conf/config/mts.c: two new variables: popbbhost and popbbuser, under #ifdef BPOP uip/bbc.c: use same support/pop/pop.txt: revise remove HEAD in favor of more general TOP Wed Oct 23 01:34:54 1985 /mtr conf/mhconfig.c: change default bbhome to /usr/spool/bboards support/pop/popser.c: support maildrop mapping uip/dropsbr.c: some optimizations support/pop/popsbr.c: link into uip/ directory to simplify top-level Makefile Tue Oct 22 21:47:01 1985 /mtr uip/bbc.c: don't have -help imply -topics Mon Oct 21 18:45:29 1985 /mtr conf/mh-gen.8: mention gould stuff conf/doc/*.rf: talk about quoting of arguments Mon Oct 21 12:26:56 1985 /mtr uip/{msh,vmh}.c: some tuning uip/bbc.c: know about SIGTSTP Sun Oct 20 22:11:58 1985 /mtr -- Suggested by Hokey for SYS5 -- conf/mh-gen.8: mention -lndir for SYS5 sbr/m_gmsg.c: fix stand-alone continue makefiles: add SHELL=/bin/sh Sun Oct 20 13:03:13 1985 /mtr conf/config/bboards.*: fix to work under sh or csh Sun Oct 20 13:02:59 1985 /mtr uip/rmf.c: add -[no]interactive switch Thu Oct 17 19:41:18 1985 /mtr -- Suggested by Dave Yost -- uip/install-mh.c: new variable, mh_defaults, to default user's profile Thu Oct 17 16:02:25 1985 /mtr uip/msh.c: move pgmwait out of msh and into it's own sbr/ file h/mh.h, {sbr,uip}/*.c: normalize pidwait stuff sbr/m_foil.c, uip/{post,send,whom}.c: fix bug in alias mechanism when following included files uip/{inc,post,send,whom}.c: normalize switch handling a bit Tue Oct 15 18:52:49 1985 /mtr uip/prompter.c: add hidden -[no]body switch sbr/vfgets.c: slight logic botch Tue Oct 15 17:14:11 1985 /mtr h/mh.h, sbr/m_{convert,gmsg,remsg}.c, uip/{burst,inc,rcvstore,refile}.c: final XYZ check-out, remove #ifdefs Mon Oct 14 12:03:39 1985 /mtr uip/send.c: still more work on annotation logic... Sun Oct 13 18:17:10 1985 /mtr sbr/vfgets.c: oops, minor typo sbr/m_gmsg.c: re-think alloc strategy a bit sbr/m_gmsg.c: use #ifdef XYZ experimental code for no limits to #-messages in a folder! sbr/m_file.c: move into uip/refile.c h/folder.h: remove Sun Oct 13 14:17:10 1985 /mtr h/mshsbr.h, uip/{msh,mshcmds,vmh}.c: fix signal handling for forks under vmh support/bboards/mmdf*/bboards/ch_bboards.c: remove some logging info Wed Oct 9 19:49:04 1985 /mtr uip/send.c: fix bogus annotation handling, e.g., send -push; rmm; folder -pack uip/{forw,mhlsbr}.c: add extra blank line after final EB so user can add suffix text with an editor (e.g., prompter) and not screw-up conf/doc/burst.rf: warn about text after final EB being lost with -inplace Sun Oct 6 20:38:29 1985 /mtr uip/msh.c: fseek() too tricky for our own good... uip/{burst,mshcmds}.c: try to recover from errors more gracefully (ha!) Sun Oct 6 11:46:11 1985 /mtr uip/{folder,scan}.c: context changes ASAP sbr/remdir.c: clean-up h/mh.h, uip/{mhlsbr,mhmail,msh,post,prompter}.c: fix up signal handling when in background Sat Oct 5 23:17:39 1985 /mtr Makefile, conf/makefiles/*: fix "make tar" uip/mshcmds.c: finally track down that mhl pipe problem Makefile, conf/makefiles/*: clean->unclean,squeaky->clean Sat Oct 5 17:22:56 1985 /mtr -- Suggested by Dave Yost -- h/mh.h, conf/config/config.c: define globals in config.c, extern 'em in mh.h conf/mhconfig.c: rm files prior to creating 'em for CTM uip/version.sh: ditto Sat Oct 5 14:20:02 1985 /mtr uip/{post,rcvdist}.c: add call to mmdf_init() under #ifdef MMDFII h/mh.h, *: XYZ becomes the "real thing" Fri Oct 4 21:08:26 1985 /mtr uip/{comp,dist,forw,repl}.c: -[no]whatnow changed to -[no]whatnowproc uip/{next,prev,show}.c: -[no]show changed to -[no]showproc uip/vmh.c: -[no]visual changed to -[no]vmhproc uip/rmm.c: Delete-Prog: changed to rmmproc Fri Oct 4 19:36:56 1985 /mtr h/mh.h, conf/config/config.c, sbr/m_getdefs.c: make vmhproc a built-in uip/vmh.c: ditto, also better help message Thu Oct 3 23:43:35 1985 /mtr uip/inc.c: change "-ms ms-file" to "-file name" to be more consistent uip/inc.c: also, if -notruncate, don't zero POP maildrop! Wed Oct 2 21:34:44 1985 /mtr uip/vmh.c: a bit more tuning Wed Oct 2 11:31:49 1985 /mtr -- Suggested by Dave Yost -- sbr/m_getdefs.c: avoid a cast (and structure dependencies) by using a popular C idiom (taught to Dave by Bakul Shah). [This also makes MH work on the Gould...] h/mh.h,sbr/m_delete.c: take the opportunity to clean things up a bit Wed Oct 2 11:12:52 1985 /mtr uip/{burst,mshcmds}.c: oops, another "slight" typo Wed Oct 2 10:03:12 1985 /mtr -- Pointed out by Bob Designer -- uip/slocal.c: oops, typo! Wed Oct 2 02:48:02 1985 /mtr uip/vmh.c: add less-like interface to command handling Tue Oct 1 22:08:32 1985 /mtr h/mh.h, sbr/m_gmsg.c: slight XYZ tuning Tue Oct 1 14:31:54 1985 /mtr conf/makefiles/doc: oops, version.me -> version.rf uip/msh.c: oops, zero'd name of BBoard prior to putenv of mhfolder conf/mhconfig.c: support ldflags for options to ld at beginning of command Tue Oct 1 10:15:24 1985 /mtr sbr/m_getdefs.c: set[ug]id() to real [ug]ids prior to exec of install-mh uip/install-mh.c: don't need set[ug]ids, also if -auto, don't ask questions, say what you're going to do and do it! zotnet/mts/mts.h: remove reference to "../h/strings.h" conf/config/mts.c,support/bboards/bbaka.c: ask for "../h/strings.h" mts/{mh/{hosts,netmail},sendmail/{client,hosts,smail},mmdf/hosts}.c: ditto zotnet/mf/mf.h: ditto Thu Sep 26 11:42:18 1985 /mtr uip/addrsbr.c: change Alternate-Mailboxes: defaulting Tue Sep 24 19:18:49 1985 /mtr uip/burst.c: make static structure an alloc'd structure uip/{burst,mshcmd}.c: trim extra trailing newline if present Mon Sep 23 10:42:18 1985 /mtr support/bboards/mmdf*/bboards/bb_wtmail.c: remove bogus ch_host hackery; use the BBoard file instead! uip/bbc.c: add -[no]protocol to tell bbc if mshproc knows about bbc protocol Mon Sep 23 04:25:33 1985 /mtr uip/show.c: normalize showproc handling; remove -[no]format and -[no]pr, add -show program and -noshow Sun Sep 22 21:06:21 1985 /mtr uip/{msh,mshcmds}.c: interface to vmh Sat Sep 21 00:12:47 1985 /mtr h/vmhsbr.h, uip/{vmh,vmhsbr,vmhtest}.c: experimental new visual front-end to msh sbr/*.c: break many aggregate files into smaller ones Fri Sep 20 22:35:56 1985 /mtr uip/msh.c: have "quit" command update msgbox after confirmation if changed uip/{mhlsbr,repl}.c: on forwardings/replies force -noclear (HACK) uip/prompter.c: fold in SYS5 terminal handling better Fri Sep 20 21:22:55 1985 /mtr conf/mhconfig.c: add mandir entry to overrid /usr/man zotnet/mf/uumm.c: simplify a conditional for the ALTOS Fri Sep 20 20:59:19 1985 /mtr uip/msh.c: split into h/mshsbr.h, uip/{msh,mshcmds}.c uip/mshcmds.c: on refile, without -link, mark messages as deleted Fri Sep 20 09:48:06 1985 /mtr miscellany/mh-e: GNU Emacs front-end to MH from James Larus Wed Sep 18 23:23:28 1985 /mtr conf/mhconfig.c: oops, toss (void)'s Wed Sep 18 07:49:27 1985 /mtr sbr/discard.c: oops, logic was botched for all versions of UNIX! Tue Sep 17 09:47:55 1985 /mtr uip/addrsbr.c: slight tuning to #ifdef BERK Mon Sep 16 21:50:01 1985 /mtr -- Suggestion from John Shepherd -- uip/slocal.c: handle idiotic multiple "From " lines Mon Sep 16 20:53:18 1985 /mtr -- Fixes from Hokey (mostly SYS5) -- uip/version.sh: generate version.rf not version.me so it stays around conf/doc/{ADMIN,MH}.rf: use same conf/mhconfig.c: new option "ranlib" for BSD or SYS5 conf/makefiles/*: use same Mon Sep 16 20:50:32 1985 /mtr miscellany/less: sources to Mark Nudelman's "less" program included Thanks, Mark! zotnet/tws/dtime.c: support illegal GreyBook timezone strings Wed Sep 11 22:02:17 1985 /mtr -- Suggested by John A. Dilly -- mts/sendmail/smail.c: fix bug with intermittant dot being added during sm_wtxt(); thanks, John! conf/config/config.c: support ~/.mhrc by allowing libpath() recognize the CShell ~-construct. This is under #ifdef MHRC Wed Sep 11 11:03:29 1985 /mtr conf/makefiles/*, conf/makefiles/*/*: unifdef stuff wasn't working out, remove it Wed Sep 11 10:10:33 1985 /mtr -- More doc fixes from Phyllis Kantar -- conf/doc/{comp,dist,mh,mhl,repl,whatnow}.rf: doc fixes Tue Sep 10 17:47:35 1985 /mtr conf/{mhconfig.c,mh-gen.8}: change "uucp" option to "mf" option conf/{examples,tailor}/READ-ME: remove since mh-gen.8 contains this information now Tue Sep 10 16:23:23 1985 /mtr Makefile, conf/Makefile, conf/makefiles/*: implement "make squeaky" and "make tar" Mon Sep 9 22:12:59 1985 /mtr zotnet/bboards/{bboards.h,getbbent.c}: flags for setbbent() uip/bbc.c, support/{bboards/*,pop/*}.c: use 'em Mon Sep 9 19:42:13 1985 /mtr conf/doc/{MH,comp,dist,forw,mh-mail,mhl,repl}.rf: better verbatim mode in roff zotnet/tws/dtime*.c: more SYS5 cleanup conf/doc/{ADMIN,MH,mh-mts,popd}.rf: more doc hackery uip/post.c: remove tmpfil/bccfil when dying() Sat Sep 7 17:43:53 1985 /mtr -- Major Directory Tree Re-Organization -- papers/: new directory, move TeX stuff from othersupport/ there conf/{mhconfig.c,makefiles/{othersupport,papers}}: support this config/*.h, */*.c: move .h files to new directory h/, update .c files accordingly h/strings.h: new .h file to define all those string functions once and for all! {bboards,mts,mf,tws}/: move under zotnet/ mts/: new directory {mhmts,sendmts,mmdf}/: move under mts/ {support,popsupport,newsupport,bbsupport}: move under support/ Sat Sep 7 17:43:24 1985 /mtr uip/msh.c: advise of gap when BBoard reading Sat Sep 7 16:42:06 1985 /mtr conf/config/mts.c, config/mh.h, mf/mf.h: remove dup2() define for SYS5 and add it as a real routine conf/doc/{MH,bbleader,burst,forw,mf,mh-profile,scan}.rf: doc fixes Sun Sep 1 17:12:54 1985 /mtr conf/doc/MH.rf: minor typo and change the names of a few chapters Thu Aug 29 20:13:47 1985 /mtr bboards/getbbent.c, tws/dtimep.c: normalize Thu Aug 29 15:09:25 1985 /mtr uip/{ali,post}.c: load system aliases file last instead of first. This lets users override system aliases AND rely on host-specific alias for final resolution! Thu Aug 29 10:52:41 1985 /mtr -- Merge in changes for SYS5 -- conf/examples/READ-ME: all non-sprintf changes under #ifdef SYS5 conf/{mhconfig.c,config/{config,mts}.c}, sbr/*.c, tws/dtime*.c, uip/*.c: sprintf() returns an int, so always (void) it tws/dtime*.c: no ftime() conf/mhdoc: echo works differently, ridiculous! config/mh.h: dup2() doesn't exist, so define it conf/mhconfig.c, uip/post.c: enums might not exist sbr/discard.c, uip/{prompter,trmsbr}.c: ioctl()'s different Thu Aug 22 20:12:05 1985 /mtr uip/{forw,mhlsbr}.c: let mhl know about digest handling so forw becomes less complicated (mhl already knows about forwarding)! Wed Aug 21 11:12:33 1985 /mtr conf/{config/config.c,makefiles/{support,uip}}, config/mh.h, conf/doc/{MH,forw,mh-profile}.rf,uip/forw.c: use formatsbr to do digestifying uip/formatsbr.c: fix minor typo tws/{tws.h,dtime.c}: new routine, twsnow() mf/uumm.c, tws/dtime.c, uip/{msh,picksbr,scansbr,sortm}.c: use twsnow() Tue Aug 20 22:19:18 1985 /mtr Makefile,conf/makefiles/{sbr,zotnet}: clean-up make clean a bit Tue Aug 20 15:59:46 1985 /mtr conf/doc/{ADMIN,pop8,rcvstore}.rf: minor clean-up Tue Aug 20 11:27:22 1985 /mtr othersupport/Mail: new directory, unsupported Mon Aug 19 20:07:50 1985 /mtr conf/{mhconfig.c,mh-gen.8}: new config option "bbhome" conf/config/bboards.{daily,weekly}: moved from bbsupport/ conf/{config/crontab,doc/{ADMIN,bbc}.rf,makefiles/{bbsupport,uip}}: support bbhome conf/examples/nrtc-isc: renamed to nrtc-gremlin conf/MAKE: modified accordingly Sun Aug 18 20:22:17 1985 /mtr uip/{burst,msh,picksbr}.c: augment botch message a bit Fri Aug 16 05:48:51 1985 /mtr mf/{mf.h,{mf,mmuu,umhook,uumm}.c}: change vfgets() to mfgets(), and slight bug fix in the process conf/makefiles/sbr, config/mh.h, sbr/llib-lmh: new vfgets() sbr/vfgets.c: new routine to support virtual-fgets uip/{alias,format,mhl}sbr.c: call vfgets to handle continuation lines conf/doc/{ap,dp,mh-alias,mhl,repl,scan}.rf: continuation lines now supported support/replcomps conf/config/mts.c, sbr/m_{draft,getdefs,whatnow}.c, sendmts/smail.c, tws/dtime.c, uip/{comp,inc,mark,mhpath,msh,post,rcvstore,refile,send}.c: notdef cleanup sendmts/hosts.c, uip/{aliasbr,dropsbr,rcvdist,send}.c: minor cleanup sbr/{add,m_replace}.c: ditto uip/mhlsbr.c: minor parenthization for ALTOS Fri Aug 16 04:48:13 1985 /mtr conf/{mhconfig.c,mh-gen.8,makefiles/uip}: fix long standing bug about sbboards, slocal, and spop being installed even for MMDF configurations Fri Aug 16 03:55:21 1985 /mtr sbr/m_getfld.c, uip/msh.c: fix trailing newline bug with mhl+no moreproc uip/addrsbr.c: slight touch-up Thu Aug 15 16:58:13 1985 /mtr conf/doc/{bbleader,bboards,mh-profile,prompter,show}.rf: minor touch-up Thu Aug 15 16:42:26 1985 /mtr CMP: shell script to aid Bug-MH in figuring out what's changed Thu Aug 15 11:19:26 1985 /mtr uip/inc.c: forgot an #ifdef for POP Wed Aug 14 21:54:20 1985 /mtr conf/config/mts.c, config/aliasbr.h, sbr/{m_getdefs,path}.c, popsupport/popd.c, uip/{ali,aliasbr,msh,picksbr,post}.c: a couple more touch-ups Wed Aug 14 17:27:41 1985 /mtr config/aliasbr.h: optimize structures for ALTOS uip/aliasbr.c: optimize for ALTOS and UNIX in general Mon Aug 12 19:42:28 1985 /mtr uip/mhlsbr.c: slight clarification for ontty == NOTTY and -clear at termination; also, try to get signals right again Thu Aug 8 00:00:00 1985 /mtr MH #6.59 enters beta Wed Aug 7 21:14:19 1985 /mtr uip/mhlsbr.c: m_popen_pid -> m_pid for 7limit Tue Aug 6 17:22:59 1985 /mtr -- From John Romine -- conf/makefiles/mmdf: slight typo mmdf/LN: better version conf/{mh-gen.8,mhconfig.c,makefiles/doc}: support two new options for manual pages: "none" and "gen" Mon Aug 5 20:57:47 1985 /mtr sbr/m_gmsg.c, uip/{bbl,mhlsbr,post,refile}.c: minor notdef touch-up conf/doc/inc.rf: slight touch-up conf/mhconfig.c: support some invocation arguments uip/sortm.c: alloc structure dynamically Mon Aug 5 20:27:12 1985 /mtr uip/rcvstore.c, conf/doc/rcvstore.rf: new program from Julian Onions conf/{makefiles/uip,doc/{MH,mh,mh-chart,mhook}.rf}: upgrade Mon Aug 5 12:29:56 1985 /mtr -- From John Romine -- conf/config/mts.c: do lock structure allocation dynamically and free up 25K of static data space (which may never even be referenced!) Sun Aug 4 14:23:35 1985 /mtr -- Suggested by Phyllis Kanter -- conf/doc/*.rf: doc fixes Sun Aug 4 14:23:58 1985 /mtr conf/doc/{ADMIN,mh-mts,bboards8}.rf: doc fixes Thu Aug 1 21:30:36 1985 /mtr uip/inc.c: fix conflict between -ms and POP Wed Jul 31 10:44:22 1985 /mtr conf/doc/{tmac.h,{ADMIN,MH,bbl,folder,mh-profile,msh,scan,whatnow}.rf}: documentation fixes conf/doc/{mhpath,show}.rf: ditto uip/msh.c: slight typo Tue Jul 30 21:44:00 1985 /mtr -- Suggested by Phyllis Kanter -- uip/folder.c: fix -fast and -recurse mis-interaction uip/burst.c: fix non-existant message handling when expanding the folder conf/config/config.c: fix comment re: whatnowproc config/mh.h, sendmts/smail.c: declare a couple of things that should be in sbr/m_getdefs.c: don't complain if "context: file" isn't there. sbr/m_{convert,file,gmsg,name}.c: fix boundary handling of MAXFOLDER conf/mh-gen.8: say a few words about chown, remove in MH config file conf/{config/config.c,examples/READ-ME}: two new options, FOLDPROT, MSGPROT conf/{config/config.c,doc/mh-profile.rf}, config/mh.h: add the "unseen-sequence" sbr/{m_setcur.c,llib-lmh}, uip/{inc,show}.c: do the UNSEEN business Sat Jul 27 12:55:27 1985 /mtr sbr/m_sync: slight adjustment uip/{addr,format,pick}sbr.c: a bit more debug info Sat Jul 27 12:46:12 1985 /mtr -- Documentation Fixes from Bob Designer -- conf/doc/{post,mh-profile,show,send,repl,next,folder}.rf: typos uip/whatnowsbr.c: back to the old prompt Sat Jul 27 00:33:39 1985 /mtr conf/doc/{mhl,show}.rf: upgrade a bit conf/makefiles/uip, uip/{mhl,mhlsbr,show}.c: add address/date parsing on demand conf/doc/{dp,scan}.rf, uip/formatsbr.c: slight upgrade support/mhl.{format,forward}: update a bit Fri Jul 26 11:09:35 1985 /mtr sendmts/smail.c: slight fix for major bug with #ifdef BERK Thu Jul 25 21:31:00 1985 /mtr conf/doc/pick.rf: finally get documentation right conf/makefiles/dist: a few more things Thu Jul 25 17:00:17 1985 /mtr conf/doc/ADMIN.rf, uip/{inc,msgchk}.c: minor re-work POP debug features Thu Jul 25 00:00:00 1985 /mtr MH #6.24 enters beta Wed Jul 24 23:42:41 1985 /mtr uip/addrsbr.c: bug with #ifdef BERK, mp -> m_nohost not getting set so no aliasing done! conf/config/mts.c: lockfile name building botched! Wed Jul 24 21:01:15 1985 /mtr uip/forw.c: -build logic botched Wed Jul 24 14:07:31 1985 /mtr conf/mh.h, sbr/m_getfld.c, uip/{msh,{mhl,scan}sbr}.c: fix broken msh message delimiting behavior and broken mhl behavior under msh Tue Jul 23 20:30:39 1985 /mtr uip/whom.c: pass more switches to post. Since they're ALL secret, no documentation needed! Mon Jul 22 16:50:54 1985 /mtr uip/picksbr.c: logic for handling "--header value" botched Sun Jul 21 15:36:24 1985 /mtr conf/doc/{send,whom,mh-alias}.rf: aliasing hints conf/doc/{{MH,tmac}.h,template}: support hints section conf/doc/mh-mts.rf: minor fix Thu Jul 18 15:59:19 1985 /mtr conf/mh-gen.8: typo Wed Jul 17 09:47:19 1985 /mtr bboards/mmdf/mmdf.2/bboards/bb_wtmail: change dist_address to ds_address, dist_log to ds_log Tue Jul 16 12:41:54 1985 /mtr uip/ali.c: forgot to call mts_init() to get "everyone", and "noshell" Sun Jul 14 18:51:22 1985 /mtr uip/formatsbr.c: handle the blank line bug by hacking it (see the "echo controversy" discussed above). The solution is to insert a space in truly blank lines... Sun Jul 14 13:44:13 1985 /mtr othersupport/bboards: version #2.1 as suggested by Jerry Sweet conf/doc/{ADMIN,mf,mh-{mts,tailor},bb{exp,oards5,tar},pop8}.rf: fixes suggested by Jerry Sweet Sun Jul 14 13:23:49 1985 /mtr tws/dtimep.c: have "BST" mean British Summer Time not Bering Standard Time Sun Jul 14 12:54:55 1985 /mtr -- Enhancements from John L. Romine -- uip/mhlsbr.c: minor cleanup Fri Jul 12 10:32:40 1985 /mtr config/mh.h,sbr/uleq.c: change strindex() -> stringdex () to avoid MMDF name conflict uip/{addrsbr,dropsbr,msh,rcvpack,sbboards}.c: ditto Thu Jul 11 12:34:15 1985 /mtr conf/makefiles/uip: oops, forgot a @END: SENDMTS inside an @BEGIN: POP Wed Jul 10 20:40:53 1985 /mtr conf/config/config.c,config/mh.h,sbr/m_getdefs.c,uip/mhlsbr.c: mhl's choice of mhlproc was confusing to forw. Add new variable moreproc to fix the problem. Note as a result, the old BERK behavior is the default, you have to turn off moreproc in your .mh_profile if you don't want mhl to use it Wed Jul 10 14:48:05 1985 /mtr uip/mhlsbr.c: don't SIG_DFL signals on start-up; if run from msh, this loses big, if not run from msh, then signals are SIG_DFL anyway... Wed Jul 10 14:08:39 1985 /mtr conf/makefiles/popsupport,popsupport/popd.{c,8c}: a bit of clean-up Wed Jul 10 12:07:42 1985 /mtr uip/addrsbr.c: another de-reference of NULL fixed Wed Jul 10 09:04:04 1985 /mtr uip/send.c: typo defining LISTDSW Tue Jul 9 18:59:21 1985 /mtr -- Suggested by Thomas Scott Christiansen -- uip/msh.c: move big Msgs[] structure from auto to static othersupport/netnews/{.,mhbox}/: new directories othersupport/netnews/{mh_profile,mhbox/flupcomps} new files Sun Jul 7 13:31:01 1985 /mtr othersupport/scripts/: new directory for scripts. First is Bob Designer's modifications to JLR's append script. othersupport/mtrenv/bin/append: remove Sun Jul 7 13:26:28 1985 /mtr uip/{addsbr,post,rcvdist,replsbr,sbboards}.c: support #ifdef BANG conf/examples/READ-ME: ditto Thu Jul 4 17:36:34 1985 /mtr uip/msh.c: "pack" should be called "packf". Thu Jul 4 16:00:38 1985 /mtr othersupport/mtrenv/mhbox/dp.debug: new file Thu Jul 4 08:38:01 1985 /mtr tws/{dtime,dtimep}.c: know about J{D,S}T, also under #ifdef HUJI generate it if appropriate. (from Danny Braniss) Thu Jul 4 08:29:11 1985 /mtr conf/doc/ADMIN.rf: put in a word or two about running conflict conf/makefiles/dist: add rules for .imp files Mon Jul 1 22:22:49 1985 /mtr conf/doc/mhl.rf, uip/mhlsbr.c: remove the #ifdef BERK stuff and generalize it. If the MH profile entry mhlproc is defined, then you get the BERK behavior using the mhlproc as the output filter. Otherwise, you get the old behavior. If this works nice, I'll make "more" the default mhlproc and set-up config.c, mh.h, and m_getdefs.c as appropriate (with the documentation mh-profile.rf) For the moment, I'm using "less" as my mhlproc and it works fine. Mon Jul 1 09:18:42 1985 /mtr sbr/m_{file,gmsg}.c, uip/{msh,refile,rmm,send}.c: #ifdef notdef the stuff marking messages as DELETED, since it's not used Mon Jul 1 06:26:38 1985 /mtr -- Suggestions from Bob Desinger -- config/mh.h, sbr/m_backup.c: locate SBACKUP definition in mh.h sbr/m_gmsg.c, uip/rmf.c: handle SBACKUP prefix files appropriately, also, slight optimizations Wed Jun 26 12:36:38 1985 /mtr MH #5.457 becomes MH #6.1 in beta Mon Jun 24 23:31:42 1985 /mtr uip/send.c: try to prevent confused annotations. The algorithm works for dist and repl, but not forw Mon Jun 24 14:58:25 1985 /mtr conf/doc/*.rf: Numerous documentation fixes suggested by Jerry Sweet. conf/doc/ADMIN.rf: New document: Administrator's Guide Fri Jun 21 13:09:29 1985 /mtr uip/addrsbr.c: liked the wild-carding, so even for #ifndef BERK you get it. Of course in this case, you can wildcard on both the mbox and the host. It turns out that this is really useful for people who have many mailboxes and get a lot of munged mail. Thu Jun 20 19:55:23 1985 /mtr -- Performance Enhancements from the 4.3BSD folks (by Van Jacobson) -- config/mh.h: define vfork for systems without it sbr/{refile,showfile}.c,uip/{replsbr,send,whatnowsbr}.c: replace fork() with vfork() config/mh.h: move Van's getfld.h definitions into here sbr/m_getfld.c: major performance tuning! (use -DRPATHS to get Return-Path: info from UNIX from: line) uip/{inc,msh}.c: m_unknown parameter added uip/trmsbr.c: support for TIOCGWINSZ in 4.3BSD(!!) uip/scan.c: -[no]reverse under #ifdef BERK (I really HATE this) also, update context prior to scan, again under #ifdef BERK uip/scansbr.c: performance enhancements plus inline copy of message body to output file for inc uip/mhlsbr.c: under #ifdef BERK pipe output to /usr/ucb/more if stdoutput is a terminal. uip/post.c: #ifdef DUMB a bit dumber for Berkeley addrsbr (actually these changes were made earlier for other reasons) uip/addrsbr.c: use prescan-like routine in SendMail under #ifdef BERK, also enable wild-carding. The former probably breaks the stuff in ap, et. al. Sun Jun 16 10:21:33 1985 /mtr uip/{ap,dp,{repl,scan}sbr}.c: the old echo controversy raises it's ugly head: suppose we have a line in a replcomps file which is entirely in a %<...%> conditional and the conditional is false. In that case, we still get a blank line. This is very BAD if it occurs in the headers. Two solutions possible: 1. If a call to FSprintf() returns a empty string, don't put out a \n. 2. In new_fs, put the \n's in and just return one big string instead of an array of strings. Option [2] was implemented initially because it lets conditionals span multiple lines in the file. In order to keep the format files from looking too complicated, EOL was ignored in format files, \n's should be embedded where appropriate. A single format string argument is considered to have an implicit \n. This is inconsistent, but it keeps the format files readable. Option [2] was discarded though since it required a \n at the end of each line in the format file if there was no conditional stuff there. So, option [1] got implemented even though it doesn't allow conditionals to be multi-line (which is okay, since you can use \n in a line). Sun Jun 9 16:37:40 1985 /mtr uip/dropsbr.c, uip/sbboards.c: .cnt mechanism broken, introduce new routine mbx_openX() in dropsbr.c and use that instead of mbx_open when opening an .cnt file Sun Jun 9 14:44:36 1985 /mtr conf/makefiles/uip,uip/show.c: make show/next/prev one program uip/{show,next,prev}hdr.c: remove as a result of above conf/doc/{next,prev}.rf: update Thu Jun 6 23:03:09 1985 /mtr uip/{format,mhl}sbr.c: add some definitions for sprintb() bboards/bboards.h: define BBITS there instead of uip/bbc.c Tue Jun 4 20:00:32 1985 /mtr -- Suggested by Dave Yost -- conf/doc/tmac.h: use ".nf" after ".SH" inside various macros (since ".SH" tends to set ".fi") sbr/m_{gmsg,sync}.c: some .mh_sequences optimizations for hm conf/config/config.c: support #ifdef NOMHSEQ Tue Jun 4 13:30:27 1985 /mtr uip/trmsbr.c: optimize a bit, the ontty test in clear_screen () isn't needed Mon Jun 3 22:15:18 1985 /mtr conf/doc/packd.rf, uip/packd.c: de-implement, essentially useless under 4.2BSD Mon Jun 3 14:54:30 1985 /mtr othersupport/usenix: new directory containing the MH paper presented at the 1985 Summer Usenix Conference Mon Jun 3 11:28:46 1985 /mtr TODO: remove since there's nothing worth left doing in it! Sun Jun 2 18:36:19 1985 /mtr conf/doc/*.rf: more clean-up uip/ali.c: change help messages a bit, and add -[no]normalize switches conf/doc/mh-tailor.rf: new file config/mh.h,uip/{post,repl}.c: move definition of OUTPUTLINELEN to mh.h so sbr/help.c can use it sbr/help.c: smarter output routine for options Sun Jun 2 14:07:46 1985 /mtr uip/whatnowsbr.c: don't say the draft's left around if it isn't (suggested by Mike O'Brien) uip/whatnowsbr.c: return value from non-initial calls to m_edit() not handled right (pointed out by Richard Johnson) sbr/m_getfld.c: be a bit smarter when recognizing that idiotic "From " line from silly UNIX-style maildrops Sat Jun 1 14:45:25 1985 /mtr uip/{pick,picksbr,msh}.c: bite the bullet and have pick allow complex booleans conf/doc/{mh-chart,pick}.rf: ditto Sat Jun 1 11:18:06 1985 /mtr mf/mf.c, uip/*sbr.c: more register declarations Sat Jun 1 01:35:06 1985 /mtr conf/doc/mhook.rf, uip/rcv*.c: account for MMDF-II change regarding rcvmail hooks and maildelivery(5) Fri May 31 23:33:59 1985 /mtr conf/doc/*.rf: more doc fixes; document WHATNOW, OVERHEAD sbr/m_getdefs.c: more OVERHEAD code to optimize MH subforks Fri May 31 22:19:15 1985 /mtr uip/replsbr.c: bite the bullet and have repl use the format string routines as well Wed May 29 16:38:49 1985 /mtr Makefile, conf/makefiles/*: support depend. N.B.: This is for DEVELOPMENT WORK ONLY. "make depend" runs unifdef because some #include files are configuration specific. Sadly, unifdef isn't on all systems (it originated at Rand and migrated to 4.2BSD). As a result, unless you have unifdef, don't run make depend. The dependencies listed in the conf/makefiles/* files are "generic". Wed May 29 14:53:33 1985 /mtr othersupport/mtrenv/*: update Tue May 28 19:45:36 1985 /mtr config/scansbr.h,uip/{inc,msh,rcvtty,scan,scansbr}.c: bite the bullet and have scansbr use a format string uip/{inc,scan}.c: no more -[no]numdate, -[no]size, -[no]time and use -format string and -width columns instead Mon May 27 21:45:23 1985 /mtr uip/{ap,addrsbr}.c: upgrade ap to use formatsbr; required a new param to getm(), so modules which call getm() got changed as well othersupport/rcvtrip/rcvtrip: upgrade Mon May 27 17:05:18 1985 /mtr tws/dp.c: move to uip/ uip/formatsbr.c: new module config/scansbr.h: define stuff for formatsbr Mon May 27 11:33:32 1985 /mtr config/mh.h, sbr/{closefds,m_getdefs}.c: #ifdef OVERHEAD experimental code Thu May 23 22:06:25 1985 /mtr conf/makfiles/uip,uip/*.c: next step in the lint process config/mh.h, sbr/llib-lmh, uip/rmf.c: move remdir() to sbr/makedir.c Thu May 23 09:06:32 1985 /mtr conf/makefiles/{mts,uip}, uip/msgchk.c: moved from mts/ Wed May 22 19:49:43 1985 /mtr Makefile, config/mh.h, conf/makefiles/*, bboards/getbbent.c, */llib-l*, tws/{dtime,dtimep}.c: start the linting process, lint everything except the uip/ directory sendmts/smail.c, uip/trmsbr.c: move discard to sbr/ library mf/mf.c: lint fixes sbr/{getans,m_{gmsg,setcur},refile,showfile}.c: lint fixes sbr/{putenv,sprintb}.c: #include mh.h sbr/*: VOID -> (void) bbsupport/bb{aka,exp,tar}.c: lint fixes Wed May 22 15:29:25 1985 /mtr popsupport/popser.c: if maildrop doesn't exist, note it and continue conf/doc/bbc.rf, uip/bbc.c: add -user switch to help POP debugging bboards/getbbent.c: have getbberr() return useful info for setbbfile (), setbbinfo (), and setbbent () popsupport/{popaka,popser,popwrd}.c, uip/{bbc,spop}.c: take advantage of getbberr() Wed May 22 10:16:17 1985 /mtr sbr/m_getfld.c: Eom() was botching gathering the UNIX from line (fix from Matt Crawford ) sendmts/smail.c: sm_end(NOTOK) was clobbering sm_reply Tue May 21 22:33:58 1985 /mtr uip/scansbr.c: when copying characters to the scan listing, know about underlining conventions Tue May 21 21:29:18 1985 /mtr Begin work on research-version of MH (#5.380[NRTC]). This version won't be sent out to the MH-Workers list, so I can do some power coding for a change. -- WHATNOW changes -- uip/{refile,send,show,whom}.c: #ifdef WHATNOW experimental code sbr/m_whatnow.c, uip/{whatnow,whatnowsbr}.c: default whatnow is a built-in for comp, et. al. sbr/{m_{edit,send},showhom}.c: removed since whatnowsbr has 'em sbr/showfile.c: likewise, showhead function removed -- POP changes -- conf/doc/inc.rf, uip/inc.c: pop now lives in inc uip/spop.c: link to sbboards.c, the POP mailer for SendMail popsupport/: new directory from the ashes of othersupport/popsupport/, containing many new programs, files, and documentation bboards/{bboards.h,getbbent.c}: new functions to support popsupport/mmdfII/: the POP channel for MMDF-II, linked to the BBoards channel, as appropriate conf/doc/msgchk.rf, mts/msgchk.c: support POP -- Bug Fixes -- uip/post.c: for path code, fixed a couple of dumb typos. uip/replsbr.c: if -noformat, don't worry about no addresses uip/bbc.c: another couple of nasty bugs fixed sendmts/smail.c: don't send HELO if talking to SendMail on the local host conf/doc/{MH,repl,forw,comp,dist,show,mh,mh-chart,whom}.rf: bug fixes -- Configuration and Clean-up -- conf/mhconfig.c: support new options: pop, chown, remove conf/makefiles/*: more chmods where appropriate config/config.c, sbr/help.c: include compile-time options in help listing. sbr/m_backup.c,uip/forw.c: remove makename in favor of mktemp sbr/pr_array.c: removed, since no one was using it config/mh.h, sbr/llib-lmh: update for all this othersupport/patch/: the latest version Thu May 2 21:14:56 1985 /mtr (agent: Marshall Rose) MH #5.360[UCI] (uci-750a) released to MH-Workers Thu May 2 21:13:32 1985 /mtr (agent: Marshall Rose) conf/makefiles/uip: make whatnow chmod +t'd Thu May 2 21:13:32 1985 /mtr (agent: Marshall Rose) uip/post.c: a few more back-offs with #ifdef DUMB... Thu May 2 21:13:03 1985 /mtr (agent: Marshall Rose) uip/sbboards.c: fdopen() called with wrong arg! Wed Apr 24 22:45:39 1985 /mtr (agent: Marshall Rose) conf/doc/MH.rf: just a few more fixes... Wed Apr 24 22:44:30 1985 /mtr (agent: Marshall Rose) sbr/m_whatnow.c, uip/{dist,forw,repl}.c: fix obscure "@" bug. Sat Apr 20 14:46:10 1985 /mtr (agent: Marshall Rose) sbr/m_send.c, uip/whatnow.c: on "push", let send do push() instead of whatnow Fri Apr 19 19:44:25 1985 /mtr (agent: Marshall Rose) uip/send.c: on annotations, if push'd avoid getting upset if message to annotate isn't there uip/send.c: fix "typo" for r1bindex () uip/send.c: put ~/.signature support back in under #ifdef UCI uip/send.c: use mktemp() instead of bogus makename! uip/send.c: fix screwy interaction between msh, dist, whatnow, and send (oh no!) Fri Apr 19 19:23:39 1985 /mtr (agent: Marshall Rose) uip/whatnow.c: if edit fails, it's time to go away sbr/m_edit.c: minor cosmetic change Fri Apr 19 19:13:44 1985 /mtr (agent: Marshall Rose) uip/post.c: more #ifdef DUMB madness, for local addresses, if no host portion given, then don't give it to sm_wadr() uip/post.c: back #ifdef DUMB off a bit in From: for MMDFMTS Fri Apr 19 18:32:13 1985 /mtr (agent: Marshall Rose) conf/doc/MH.rf, sbr/m_send.c: de-implement "push" in whatnow having send look for profile-entry of "push" rather than "send" to confusing to the user "community" Fri Apr 19 18:28:44 1985 /mtr (agent: Marshall Rose) bboards/bboards.h, uip/bbc.c: support BB_INVIS for "hidden" BBoards in -topic uip/bbc.c: catch a long name that got past us uip/bbc.c: fix -topics logic when BBoards given Fri Apr 19 18:27:16 1985 /mtr (agent: Marshall Rose) conf/{config/mts.c,tailor/READ-ME}, mts/mts.h, uip/inc.c: support the new MTS variable "pophost" Sat Apr 6 16:17:23 1985 /mtr (agent: Marshall Rose) MH #5.348[UCI] (uci-750a) released to MH-Workers Wed Apr 3 23:53:12 1985 /mtr (agent: Marshall Rose) ohtersupport/mtrenv/bin/whatnow: new file Wed Apr 3 23:52:13 1985 /mtr (agent: Marshall Rose) sendmts/smail.c: comment out an extra RSET for UCI's losing MMDF-I SMTP server Tue Mar 26 18:32:49 1985 /mtr (agent: Marshall Rose) conf/{config/mts.c,tailor/READ-ME}, config/aliasbr.h, mts/mts.h, uip/aliasbr.c: make "*" logic mts-tailorable (ugh), you get to choose highest non-user uid and non-user shell Tue Mar 26 18:02:52 1985 /mtr (agent: Marshall Rose) conf/doc/repl.rf: document bug in replcomps Mon Mar 25 18:06:48 1985 /mtr (agent: Marshall Rose) mf/mf.c: avoid (incorrectly) recognizing " at " for "@" by using a heuristic suggested by JSol. Sun Mar 24 18:32:47 1985 /mtr (agent: Marshall Rose) sbr/m_draft.c, uip/{comp,dist,forw,refile,repl,send,show,whatnow,whom}.c: have -nodraftfolder override "Draft-Folder:" profile entry Sat Mar 23 12:48:30 1985 /mtr (agent: Marshall Rose) -- Support the WhatNow shell -- conf/makefiles/{sbr,uip}: updates for all of this uip/{comp,dist,forw,repl}.c: remove What now? code, add -whatnow program, -nowhatnow sbr/m_whatnow.c: new module conf/config/config.c,config/mh.h,sbr/m_getdefs.c: new variable whatnowproc sbr/llib-lmh: update uip/whatnow.c: new program, the first WhatNow shell conf/doc/{mh-chart,whom}.rf, uip/whom.c: upgrade to take draftfolder arguments sbr/putenv.c: update for above sbr/m_send.c: undo previous edits, m_whatnow() takes care of it uip/distsbr.c: new module for dist-style support uip/{send,whom}.c: call distout() in distsbr.c conf/doc/whatnow.rf: new file conf/doc/{MH,comp,dist,forw,mh,mh-{chart,profile},repl}.rf: updates conf/doc/template: fix Thu Mar 21 08:45:11 1985 /mtr (agent: Marshall Rose) sendmts/smail.c: fix logic error in sm_end(); MMDF-I has this problem, MMDF-II might! Tue Mar 19 18:16:33 1985 /mtr (agent: Marshall Rose) conf/doc/msgchk.rf: new file conf/{doc/{mh,mh-chart,MH}.rf,makefiles/doc}: update for msgchk Tue Mar 19 17:31:14 1985 /mtr (agent: Marshall Rose) conf/doc/{ap,mh-chart}.rf, uip/ap.c: accept -help switch Tue Mar 19 14:17:30 1985 /mtr (agent: Marshall Rose) othersupport/mtrenv/bin/{distf,mpick,packit}: updates Sat Mar 16 12:49:48 1985 /mtr (agent: Marshall Rose) Makefile: simply Makefile using sh, also make DESTDIR work conf/makefiles/othersupport: simplify Makefile Sat Mar 16 12:23:37 1985 /mtr (agent: Marshall Rose) uip/{mark,msh}.c: don't set previous-sequence to make debugging easier Sat Mar 16 01:38:06 1985 /mtr (agent: Marshall Rose) conf/config/mts.c: add a few calls to mts_init ("mts") at strategic places Sat Mar 16 00:28:01 1985 /mtr (agent: Marshall Rose) uip/{inc,msh,rcvtty,scan,scansbr}.c: clean up handling of inc -silent sbr/{llib-lmh,m_send.c}, uip/{annosbr,comp,dist,forw,repl}.c: move annotations into send conf/makefiles/uip, uip/{send,post}.c: ditto conf/doc/{dist,forw,repl}.rf: ditto uip/anno.c: forgot to check (mp -> msgstats[msgnum] & SELECTED) Fri Mar 15 23:21:29 1985 /mtr (agent: Marshall Rose) sbr/printsw.c: compress output of printed switches sbr/m_getdefs.c: let $MHCONTEXT override context variable sbr/m_{getdefs,gmsg,sync}.c, conf/doc/mh-profile.rf: let the profile entry "mh-sequences" override .mh_sequences sbr/m_seq.c: optimization Fri Mar 15 23:05:43 1985 /mtr (agent: Marshall Rose) bbsupport/bbexp.c: fix string botch for command to popen. also allow extra arguments to indicate aging period. Fri Mar 15 11:45:00 1985 /mtr (agent: Marshall Rose) othersupport/emh/READ-ME: new file Thu Mar 14 22:41:37 1985 /mtr (agent: Marshall Rose) -- Fixes suggested by John Dilley -- conf/{config/mts.c,tailor/READ-ME}: add new mtstailor variables localname, systemname, and uucpchan mts/mts.h, conf/{mh-gen.8,config/{mts.c,mtstailor},tailor/READ-ME}: add new mtstailor variable lockstyle to control style of locking sbr/m_getfld.c: catch the UNIX "from user" line uip/scansbr.c: make use of the UNIX "from user" line uip/addrsbr.c: more #ifdef DUMB support uip/inc.c: minor bug in inc w.r.t. closing locked file uip/post.c: more #ifdef DUMB support uip/replsbr.c: support Return-Path: for defaulting host names as a last resort Wed Mar 13 22:24:07 1985 /mtr (agent: Marshall Rose) uip/send.c: fix "use xxx logic" uip/msh.c: a NULL vs. "" typo Wed Mar 13 22:01:37 1985 /mtr (agent: Marshall Rose) -- Fixes suggested by Phyllis Kantar -- uip/{comp,dist,forw,repl}.c: fix quit -delete logic conf/doc/{comp,mh-chart}.rf: document "-file file" switch uip/send.c: "send -help" should done (1) for comp, et. al. uip/send.c: typo "tempoary" conf/doc/{send,whom}.rf: Profile Components forgot Draft-Folder uip/ali.c: always load system aliases conf/doc/{MH,comp,dist,forw,mhook,repl,send,show,mh-alias,mh-mail, mh-profile,mhl,post}.rf: typo fixes conf/doc/send.rf, uip/send.c: -forward now the default, also don't gripe about "show -draft file" Tue Mar 12 18:07:44 1985 /mtr (agent: Marshall Rose) othersupport/pop/pop.txt: a few minor corrections to typos. Sat Mar 9 15:54:40 1985 /mtr (agent: Marshall Rose) uip/dropsbr.c: fix bug when fixing stomped maildrop. Sat Mar 9 15:36:13 1985 /mtr (agent: Marshall Rose) bboards/mmdf/mmdf.{1,2}/bboards/bb_wtmail.c, uip/sbboards.c: fix minor bug requiring nearly major re-write!!! Wed Mar 6 18:59:22 1985 /mtr (agent: Marshall Rose) -- Fixes from Robert Elz -- sbr/makedir.c: use mkdir() under #ifdef BSD42 uip/rmf.c: use rmdir() under #ifdef BSD42 Wed Mar 6 18:19:46 1985 /mtr (agent: Marshall Rose) TODO, config/addrsbr.h, sendmts/smail.c, mf/mf.{c,h}, uip/{addrsbr,ap,post,rcvdist,sbboards}.c: handle 822-style routing Wed Mar 6 18:08:11 1985 /mtr (agent: Marshall Rose) uip/{dropsbr,packf,post,slocal}.c: fix to maildrop mapping bug with MHMTS and local delivery in post, and SENDMTS and local delivery in slocal Sat Mar 1 20:21:17 1985 /mtr (agent: Marshall Rose) MH #5.321[UCI] (uci-750a) released to MH-Workers Fri Mar 1 19:59:32 1985 /mtr (agent: Marshall Rose) uip/trmsbr.c: forgot to make a termcap buffer TXTSIZ'd instead of BUFSIZ'd. Fri Mar 1 19:56:43 1985 /mtr (agent: Marshall Rose) conf/config/mts.c: for the DUAL, you can't link to a file that you can't read, unbelievable, eh?, so change the creat (foo, 0000) to creat (foo, 0400). Also, fix up some botched args to a sprintf() call. Fri Mar 1 19:48:53 1985 /mtr (agent: Marshall Rose) conf/config/config.c: if MORE is defined, used that instead of /usr/ucb/more. The #ifdef ALTOS dependency is removed. ALTOS users should use options MORE='"/usr/bin/more"', just like users of the Dual. conf/examples/READ-ME: document same Wed Feb 20 20:48:12 1985 /mtr (agent: Marshall Rose) sbr/adios.c: save errno prior to doing fancy perror stuff Wed Feb 20 20:40:14 1985 /mtr (agent: Marshall Rose) uip/inc.c: fix suggested by John Dilley at Purdue, inc now ignore signals if it's going to zero the maildrop. Mon Feb 18 12:53:50 1985 /mtr (agent: Marshall Rose) conf/doc/send.rf, uip/send.c: de-implement ~/.signature support Tue Feb 12 19:33:14 1985 /mtr (agent: Marshall Rose) uip/mhlsbr.c: clear_screen() logic between messages botched Sun Jan 27 18:42:49 1985 /mtr (agent: Marshall Rose) conf/makefiles/mts: dependency screw-up on mts.o Sun Jan 27 17:41:03 1985 /mtr (agent: Marshall Rose) sendmts/smail.c, uip/post.c: with -DSMTP, keep one SMTP connection open, instead of starting a new one for each transaction othersupport/pop/{Makefile,{popd,popser,inc,popsbr}.c}: support "rpop" under #ifdef RPOP othersupport/pop/client.c: remove conf/{config/mts.c,tailor/READ-ME,makefiles/sendmts}, mts/mts.h, sendmts/{smail,client}.c: support new server search list facility used by both -DSMTP and -DPOP Sat Jan 26 09:12:27 1985 /mtr (agent: Marshall Rose) MH #5.310[UCI] (uci-750a) released to MH-Workers Sat Jan 26 09:38:08 1985 /mtr (agent: Marshall Rose) tws/dtime.c: #define dysize(), since could be a macro in ctime.c (thanks, Fred) Sat Jan 26 09:08:43 1985 /mtr (agent: Marshall Rose) uip/{inc,post}.c: changes for #ifdef TMA; this stuff is still under non-disclosure (not the MH code, just the -ltma library which doesn't come with MH) Sat Jan 26 09:05:52 1985 /mtr (agent: Marshall Rose) -- Fixes for MHMTS configuration -- conf/makefiles/uip: shouldn't build rcvdist on an MHMTS system conf/doc/mhook.rf: ditto conf/config/mts.c, mhmts/netmail.c, mts/mts.h, uip/rmail.c: some typos in the declarations of global MTS variables that are MHMTS specific mf/mmuu.c: addr_convert() conflicted with routine of same name in uumm.c uip/news.c: looking in the wrong place for on 4.2BSD systems Tue Jan 8 13:54:13 1985 /mtr (agent: Marshall Rose) MH.5 is finished, finally. MHCHANGES from mh.4 to mh.5 Thu May 2 21:14:56 1985 /mtr (agent: Marshall Rose) MH #5.360[UCI] (uci-750a) released to MH-Workers Thu May 2 21:13:32 1985 /mtr (agent: Marshall Rose) conf/makefiles/uip: make whatnow chmod +t'd Thu May 2 21:13:32 1985 /mtr (agent: Marshall Rose) uip/post.c: a few more back-offs with #ifdef DUMB... Thu May 2 21:13:03 1985 /mtr (agent: Marshall Rose) uip/sbboards.c: fdopen() called with wrong arg! Wed Apr 24 22:45:39 1985 /mtr (agent: Marshall Rose) conf/doc/MH.rf: just a few more fixes... Wed Apr 24 22:44:30 1985 /mtr (agent: Marshall Rose) sbr/m_whatnow.c, uip/{dist,forw,repl}.c: fix obscure "@" bug. Sat Apr 20 14:46:10 1985 /mtr (agent: Marshall Rose) sbr/m_send.c, uip/whatnow.c: on "push", let send do push() instead of whatnow Fri Apr 19 19:44:25 1985 /mtr (agent: Marshall Rose) uip/send.c: on annotations, if push'd avoid getting upset if message to annotate isn't there uip/send.c: fix "typo" for r1bindex () uip/send.c: put ~/.signature support back in under #ifdef UCI uip/send.c: use mktemp() instead of bogus makename! uip/send.c: fix screwy interaction between msh, dist, whatnow, and send (oh no!) Fri Apr 19 19:23:39 1985 /mtr (agent: Marshall Rose) uip/whatnow.c: if edit fails, it's time to go away sbr/m_edit.c: minor cosmetic change Fri Apr 19 19:13:44 1985 /mtr (agent: Marshall Rose) uip/post.c: more #ifdef DUMB madness, for local addresses, if no host portion given, then don't give it to sm_wadr() uip/post.c: back #ifdef DUMB off a bit in From: for MMDFMTS Fri Apr 19 18:32:13 1985 /mtr (agent: Marshall Rose) conf/doc/MH.rf, sbr/m_send.c: de-implement "push" in whatnow having send look for profile-entry of "push" rather than "send" to confusing to the user "community" Fri Apr 19 18:28:44 1985 /mtr (agent: Marshall Rose) bboards/bboards.h, uip/bbc.c: support BB_INVIS for "hidden" BBoards in -topic uip/bbc.c: catch a long name that got past us uip/bbc.c: fix -topics logic when BBoards given Fri Apr 19 18:27:16 1985 /mtr (agent: Marshall Rose) conf/{config/mts.c,tailor/READ-ME}, mts/mts.h, uip/inc.c: support the new MTS variable "pophost" Sat Apr 6 16:17:23 1985 /mtr (agent: Marshall Rose) MH #5.348[UCI] (uci-750a) released to MH-Workers Wed Apr 3 23:53:12 1985 /mtr (agent: Marshall Rose) ohtersupport/mtrenv/bin/whatnow: new file Wed Apr 3 23:52:13 1985 /mtr (agent: Marshall Rose) sendmts/smail.c: comment out an extra RSET for UCI's losing MMDF-I SMTP server Tue Mar 26 18:32:49 1985 /mtr (agent: Marshall Rose) conf/{config/mts.c,tailor/READ-ME}, config/aliasbr.h, mts/mts.h, uip/aliasbr.c: make "*" logic mts-tailorable (ugh), you get to choose highest non-user uid and non-user shell Tue Mar 26 18:02:52 1985 /mtr (agent: Marshall Rose) conf/doc/repl.rf: document bug in replcomps Mon Mar 25 18:06:48 1985 /mtr (agent: Marshall Rose) mf/mf.c: avoid (incorrectly) recognizing " at " for "@" by using a heuristic suggested by JSol. Sun Mar 24 18:32:47 1985 /mtr (agent: Marshall Rose) sbr/m_draft.c, uip/{comp,dist,forw,refile,repl,send,show,whatnow,whom}.c: have -nodraftfolder override "Draft-Folder:" profile entry Sat Mar 23 12:48:30 1985 /mtr (agent: Marshall Rose) -- Support the WhatNow shell -- conf/makefiles/{sbr,uip}: updates for all of this uip/{comp,dist,forw,repl}.c: remove What now? code, add -whatnow program, -nowhatnow sbr/m_whatnow.c: new module conf/config/config.c,config/mh.h,sbr/m_getdefs.c: new variable whatnowproc sbr/llib-lmh: update uip/whatnow.c: new program, the first WhatNow shell conf/doc/{mh-chart,whom}.rf, uip/whom.c: upgrade to take draftfolder arguments sbr/putenv.c: update for above sbr/m_send.c: undo previous edits, m_whatnow() takes care of it uip/distsbr.c: new module for dist-style support uip/{send,whom}.c: call distout() in distsbr.c conf/doc/whatnow.rf: new file conf/doc/{MH,comp,dist,forw,mh,mh-{chart,profile},repl}.rf: updates conf/doc/template: fix Thu Mar 21 08:45:11 1985 /mtr (agent: Marshall Rose) sendmts/smail.c: fix logic error in sm_end(); MMDF-I has this problem, MMDF-II might! Tue Mar 19 18:16:33 1985 /mtr (agent: Marshall Rose) conf/doc/msgchk.rf: new file conf/{doc/{mh,mh-chart,MH}.rf,makefiles/doc}: update for msgchk Tue Mar 19 17:31:14 1985 /mtr (agent: Marshall Rose) conf/doc/{ap,mh-chart}.rf, uip/ap.c: accept -help switch Tue Mar 19 14:17:30 1985 /mtr (agent: Marshall Rose) othersupport/mtrenv/bin/{distf,mpick,packit}: updates Sat Mar 16 12:49:48 1985 /mtr (agent: Marshall Rose) Makefile: simply Makefile using sh, also make DESTDIR work conf/makefiles/othersupport: simplify Makefile Sat Mar 16 12:23:37 1985 /mtr (agent: Marshall Rose) uip/{mark,msh}.c: don't set previous-sequence to make debugging easier Sat Mar 16 01:38:06 1985 /mtr (agent: Marshall Rose) conf/config/mts.c: add a few calls to mts_init ("mts") at strategic places Sat Mar 16 00:28:01 1985 /mtr (agent: Marshall Rose) uip/{inc,msh,rcvtty,scan,scansbr}.c: clean up handling of inc -silent sbr/{llib-lmh,m_send.c}, uip/{annosbr,comp,dist,forw,repl}.c: move annotations into send conf/makefiles/uip, uip/{send,post}.c: ditto conf/doc/{dist,forw,repl}.rf: ditto uip/anno.c: forgot to check (mp -> msgstats[msgnum] & SELECTED) Fri Mar 15 23:21:29 1985 /mtr (agent: Marshall Rose) sbr/printsw.c: compress output of printed switches sbr/m_getdefs.c: let $MHCONTEXT override context variable sbr/m_{getdefs,gmsg,sync}.c, conf/doc/mh-profile.rf: let the profile entry "mh-sequences" override .mh_sequences sbr/m_seq.c: optimization Fri Mar 15 23:05:43 1985 /mtr (agent: Marshall Rose) bbsupport/bbexp.c: fix string botch for command to popen. also allow extra arguments to indicate aging period. Fri Mar 15 11:45:00 1985 /mtr (agent: Marshall Rose) othersupport/emh/READ-ME: new file Thu Mar 14 22:41:37 1985 /mtr (agent: Marshall Rose) -- Fixes suggested by John Dilley -- conf/{config/mts.c,tailor/READ-ME}: add new mtstailor variables localname, systemname, and uucpchan mts/mts.h, conf/{mh-gen.8,config/{mts.c,mtstailor},tailor/READ-ME}: add new mtstailor variable lockstyle to control style of locking sbr/m_getfld.c: catch the UNIX "from user" line uip/scansbr.c: make use of the UNIX "from user" line uip/addrsbr.c: more #ifdef DUMB support uip/inc.c: minor bug in inc w.r.t. closing locked file uip/post.c: more #ifdef DUMB support uip/replsbr.c: support Return-Path: for defaulting host names as a last resort Wed Mar 13 22:24:07 1985 /mtr (agent: Marshall Rose) uip/send.c: fix "use xxx logic" uip/msh.c: a NULL vs. "" typo Wed Mar 13 22:01:37 1985 /mtr (agent: Marshall Rose) -- Fixes suggested by Phyllis Kantar -- uip/{comp,dist,forw,repl}.c: fix quit -delete logic conf/doc/{comp,mh-chart}.rf: document "-file file" switch uip/send.c: "send -help" should done (1) for comp, et. al. uip/send.c: typo "tempoary" conf/doc/{send,whom}.rf: Profile Components forgot Draft-Folder uip/ali.c: always load system aliases conf/doc/{MH,comp,dist,forw,mhook,repl,send,show,mh-alias,mh-mail, mh-profile,mhl,post}.rf: typo fixes conf/doc/send.rf, uip/send.c: -forward now the default, also don't gripe about "show -draft file" Tue Mar 12 18:07:44 1985 /mtr (agent: Marshall Rose) othersupport/pop/pop.txt: a few minor corrections to typos. Sat Mar 9 15:54:40 1985 /mtr (agent: Marshall Rose) uip/dropsbr.c: fix bug when fixing stomped maildrop. Sat Mar 9 15:36:13 1985 /mtr (agent: Marshall Rose) bboards/mmdf/mmdf.{1,2}/bboards/bb_wtmail.c, uip/sbboards.c: fix minor bug requiring nearly major re-write!!! Wed Mar 6 18:59:22 1985 /mtr (agent: Marshall Rose) -- Fixes from Robert Elz -- sbr/makedir.c: use mkdir() under #ifdef BSD42 uip/rmf.c: use rmdir() under #ifdef BSD42 Wed Mar 6 18:19:46 1985 /mtr (agent: Marshall Rose) TODO, config/addrsbr.h, sendmts/smail.c, mf/mf.{c,h}, uip/{addrsbr,ap,post,rcvdist,sbboards}.c: handle 822-style routing Wed Mar 6 18:08:11 1985 /mtr (agent: Marshall Rose) uip/{dropsbr,packf,post,slocal}.c: fix to maildrop mapping bug with MHMTS and local delivery in post, and SENDMTS and local delivery in slocal Sat Mar 1 20:21:17 1985 /mtr (agent: Marshall Rose) MH #5.321[UCI] (uci-750a) released to MH-Workers Fri Mar 1 19:59:32 1985 /mtr (agent: Marshall Rose) uip/trmsbr.c: forgot to make a termcap buffer TXTSIZ'd instead of BUFSIZ'd. Fri Mar 1 19:56:43 1985 /mtr (agent: Marshall Rose) conf/config/mts.c: for the DUAL, you can't link to a file that you can't read, unbelievable, eh?, so change the creat (foo, 0000) to creat (foo, 0400). Also, fix up some botched args to a sprintf() call. Fri Mar 1 19:48:53 1985 /mtr (agent: Marshall Rose) conf/config/config.c: if MORE is defined, used that instead of /usr/ucb/more. The #ifdef ALTOS dependency is removed. ALTOS users should use options MORE='"/usr/bin/more"', just like users of the Dual. conf/examples/READ-ME: document same Wed Feb 20 20:48:12 1985 /mtr (agent: Marshall Rose) sbr/adios.c: save errno prior to doing fancy perror stuff Wed Feb 20 20:40:14 1985 /mtr (agent: Marshall Rose) uip/inc.c: fix suggested by John Dilley at Purdue, inc now ignore signals if it's going to zero the maildrop. Mon Feb 18 12:53:50 1985 /mtr (agent: Marshall Rose) conf/doc/send.rf, uip/send.c: de-implement ~/.signature support Tue Feb 12 19:33:14 1985 /mtr (agent: Marshall Rose) uip/mhlsbr.c: clear_screen() logic between messages botched Sun Jan 27 18:42:49 1985 /mtr (agent: Marshall Rose) conf/makefiles/mts: dependency screw-up on mts.o Sun Jan 27 17:41:03 1985 /mtr (agent: Marshall Rose) sendmts/smail.c, uip/post.c: with -DSMTP, keep one SMTP connection open, instead of starting a new one for each transaction othersupport/pop/{Makefile,{popd,popser,inc,popsbr}.c}: support "rpop" under #ifdef RPOP othersupport/pop/client.c: remove conf/{config/mts.c,tailor/READ-ME,makefiles/sendmts}, mts/mts.h, sendmts/{smail,client}.c: support new server search list facility used by both -DSMTP and -DPOP Sat Jan 26 09:12:27 1985 /mtr (agent: Marshall Rose) MH #5.310[UCI] (uci-750a) released to MH-Workers Sat Jan 26 09:38:08 1985 /mtr (agent: Marshall Rose) tws/dtime.c: #define dysize(), since could be a macro in ctime.c (thanks, Fred) Sat Jan 26 09:08:43 1985 /mtr (agent: Marshall Rose) uip/{inc,post}.c: changes for #ifdef TMA; this stuff is still under non-disclosure (not the MH code, just the -ltma library which doesn't come with MH) Sat Jan 26 09:05:52 1985 /mtr (agent: Marshall Rose) -- Fixes for MHMTS configuration -- conf/makefiles/uip: shouldn't build rcvdist on an MHMTS system conf/doc/mhook.rf: ditto conf/config/mts.c, mhmts/netmail.c, mts/mts.h, uip/rmail.c: some typos in the declarations of global MTS variables that are MHMTS specific mf/mmuu.c: addr_convert() conflicted with routine of same name in uumm.c uip/news.c: looking in the wrong place for on 4.2BSD systems Tue Jan 8 13:54:13 1985 /mtr (agent: Marshall Rose) MH.5 is finished, finally. Tue Jan 8 09:45:25 1985 /mtr (agent: Marshall Rose) sbr/m_edit.c: from Mike O'Brien on 4.2BSD use symlinks if "@" is across file systems uip/inc.c: slight botch in -[no]truncate Tue Jan 8 09:12:42 1985 /mtr (agent: Marshall Rose) conf/{mh-gen,doc/MH}.rf: last change, fix public domain notice config/notice.h: remove uip/version.sh: don't include ../config/notice.h Mon Jan 7 19:05:22 1985 /mtr (agent: Marshall Rose) uip/inc.c: add -[no]truncate conf/doc/*: change up documentation a bit Fri Jan 4 16:28:49 1985 /mtr (agent: Marshall Rose) uip/addrsbr.c: SENDMTS was botching UUCP addrs Wed Jan 2 13:20:42 1985 /mtr (agent: Marshall Rose) uip/addrsbr.c: #ifdef DUMB inserted Mon Dec 31 21:28:07 1984 /mtr (agent: Marshall Rose) uip/packf.c, conf/doc/packf.c, conf/{config/config.c,makefiles/uip}, change pack to packf config/mh.h: make MAXFOLDERS smaller for the ALTOS Mon Dec 31 17:43:49 1984 /mtr (agent: Marshall Rose) tws/{tws.h,dtime.c}: add dgmtime() Sun Dec 30 19:52:27 1984 /mtr (agent: Marshall Rose) conf/config/{config,mts}.c, mmdf/hosts.c, uip/trmsbr.c, bboards/getbbent.c, config/mh.h: minor cleanup. Sun Dec 30 12:11:45 1984 /mtr (agent: Marshall Rose) uip/post.c: have non-recipient addresses honor aliases Sun Dec 30 12:01:08 1984 /mtr (agent: Marshall Rose) uip/sortm.c: fix for holes in "msgs" from Mike O'Brien Sun Dec 30 11:50:57 1984 /mtr (agent: Marshall Rose) uip/post.c: one more -noverbose fix Sat Dec 29 16:56:59 1984 /mtr (agent: Marshall Rose) conf/makefiles/sbr, config/mh.h, sbr/llib-lmh, sbr/closefds.c, uip/{msh,post,rcvtty,replsbr,send,slocal,whom}.c: implement closefds () Sat Dec 29 12:17:50 1984 /mtr (agent: Marshall Rose) conf/{config/config.c,doc/{folder,mh-profile}.rf}, sbr/m_getdefs.c, uip/folder.c: fix folder -fast -recurse Sat Dec 29 10:45:08 1984 /mtr (agent: Marshall Rose) sbr/m_sync.c: handle public and read-only sequences correctly uip/rmf.c: fix botch for handling read-only folders Sat Dec 29 10:43:12 1984 /mtr (agent: Marshall Rose) uip/msh.c: improved $mhfolder handling for -prompt. Wed Dec 19 12:49:42 1984 /mtr (agent: Marshall Rose) sbr/m_getfld.c: advise() with inverted arguments Tue Dec 18 16:48:17 1984 /mtr (agent: Marshall Rose) bboards/*.c, conf/config/mts.c, mhmts/*.c, mmdf/*.c, sendmts/*.c, tws/*.c: register madness Tue Dec 18 16:00:48 1984 /mtr (agent: Marshall Rose) uip/{bbc,msh}.c: for Farber, say name of BBoard not name of file Tue Dec 18 16:00:07 1984 /mtr (agent: Marshall Rose) bboards/getbbent.c, conf/config/mts.c, sbr/m_backup.c, uip/dropsbr.c: for ALTOS "%.*s" doesn't work if * evals to 0, so kludge around it Tue Dec 18 15:59:34 1984 /mtr (agent: Marshall Rose) sbr/m_getfld.c, uip/scansbr.c: some speed improvements from Jim Larus at UCB Thu Dec 13 00:05:42 1984 /mtr (agent: Marshall Rose) sbr/m_getfld.c: big fields were having their headers zero'd Wed Dec 12 11:51:52 1984 /mtr (agent: Marshall Rose) tws/{tws.h,dtime.c}: use modified version of gtime() to add new structure element to (struct tws *). This makes time comparisons insensitive to timezones, etc. Tue Dec 11 22:35:58 1984 /mtr (agent: Marshall Rose) -- Fixes from Julian Onions at Nottingham -- conf/makfiles/*: "ld -x -r" terminates with status 1 even if all goes well, so tell make not to worry about it config/mh.h,conf/examples/READ-ME: talk about void=int uip/{msh,post,rcv{dist,pack,tty},slocal}.c: include if not V7 Tue Dec 11 17:05:36 1984 /mtr (agent: Marshall Rose) uip/trmsbr.c: minor fix in discard() for #ifdef ALTOS Mon Dec 10 23:38:05 1984 /mtr (agent: Marshall Rose) config/scansbr.h, uip/{inc,scansbr,send,post}.c: add support for TTI's prototype TMA under #ifdef TMA uip/tmasbr.c: new module for support Sat Dec 8 18:16:41 1984 /mtr (agent: Marshall Rose) config/mh.h, tws/tws.h, conf/config/mts.c: remove the void definitions conf/Makefile, config/makefiles/*: remove -ns from LDFLAGS conf/makefiles/uip: don't use the -g option for ls for s{bboards,local} conf/makefiles/*: use -l to ls not -ls Sat Dec 8 18:16:20 1984 /mtr (agent: Marshall Rose) uip/rcvtty.c: minor-cleanup Fri Dec 7 00:25:24 1984 /mtr (agent: Marshall Rose) uip/{inc,show}.c: implement "unseen" for TGC. This feature is currently undocumented pending field-testing. Wed Dec 5 22:58:11 1984 /mtr (agent: Marshall Rose) uip/sbboards.c: on distribution, if a particular address loses, keep on going and report the error later on. bboards/mmdf/mmdf.{1,2}/bboards/bb_wtmail.c: in addition to above fix to sbboards, post failure notices to the local-XXX-request address. Wed Dec 5 14:28:18 1984 /mtr (agent: Marshall Rose) mts/msgchk.c, Makefile, conf/makefiles/mts: honor MF conventions in msgchk, required MH sbr library uip/inc.c: better check of umincproc uip/{dist,forw,repl}.c: typo prevented annotation with the pyramid cc conf/makefiles/{bbsupport,uip}: give path to chown uip/dropsbr.c: no diagnostic if map is empty conf/config/mts.c, bboards/getbbent.c: more ALTOS stuff for v7 cc sbr/m_getfld.c, uip/mhlsbr.c: botched pointer to function notation, visible on v7 cc bbsupport/bbexp.c: forgot to foil m_getdefs() sbr/m_{setcur,seq}.c: handle "cur" correctly sbr/m_getfld.c: in msh$mhl with a message with no body, big loss uip/post.c: don't ask sbr/m_getfld.c, conf/makefiles/sbr: use the mts stuff to initialize the delimiter. The programs that need this will call mts_init() themselvess prior to calling m_getfld() Fri Nov 30 08:47:52 1984 /mtr (agent: Marshall Rose) uip/news.c: forgot to include mh.h; no one must be using it, love to trash it from the distribution. -- Enter BETA Testing -- Thu Nov 29 01:55:12 1984 /mtr (agent: Marshall Rose) uip/pick.c: don't output that "0" on error exits if stdout is a tty... (yep, pick acts differently for ttys, just like ls) Wed Nov 28 22:59:34 1984 /mtr (agent: Marshall Rose) uip/msh.c: add -draft argument to msh$refile; clean-up -draft argument in msh$show sbr/m_draft.c: call path() on value of Draft-Folder: so relative folders work (!!) uip/repl.c: expand fcc: @folder arguments Wed Nov 28 20:42:21 1984 /mtr (agent: Marshall Rose) conf/makefiles/*: for installations, use mv -f to save backup Wed Nov 28 20:37:16 1984 /mtr (agent: Marshall Rose) uip/comp.c: restore old context-sensitive behavior Wed Nov 28 19:57:44 1984 /mtr (agent: Marshall Rose) uip/rcv{pack,tty}.c: move inclusion of and to the not MMDFMTS part, since "util.h" includes 'em Wed Nov 28 11:28:56 1984 /mtr (agent: Marshall Rose) uip/mhlsbr.c: ignores wasn't being handled properly (logic bug) Wed Nov 28 08:24:04 1984 /mtr (agent: Marshall Rose) uip/refile.c: if +folder arg is forgotten, don't print usage string. Also add -draft switch. Wed Nov 28 00:15:25 1984 /mtr (agent: Marshall Rose) uip/trmsbr.c: always read termcap and do what we can. When called from in a non-interactive environment, do the right thing at the right time... uip/msh.c: call sc_width() at start-up to read good values from trmsbr Tue Nov 27 21:02:41 1984 /mtr (agent: Marshall Rose) uip/send.c: re-implement the -[no]unique switches for JLR. Tue Nov 27 20:44:45 1984 /mtr (agent: Marshall Rose) -- More Changes for the ALTOS -- conf/makefiles/{mts,tws}: @(LDOPTIONS) was being left out of LDFLAGS config/aliasbr.h,uip/{ali,aliasbr}.c: prefix members of the aka structure with ak_, prefix members of the adr structure with ad_ tws/tws.h: type "void" undefined uip/rcv{dist,pack,tty}.c: include only if not on ALTOS uip/ttyw.c: put everything under #ifdef TTYD Tue Nov 27 19:22:51 1984 /mtr (agent: Marshall Rose) sbr/m_getfld.c: add m_eomsbr() for msh$mhl for bursting (sigh) Tue Nov 27 19:08:46 1984 /mtr (agent: Marshall Rose) uip/addrsbr.c: in addition to griping about bogus addresses in the "alternate-mailboxes:" entry, add a line saying to fix it (and where) uip/scansbr.c: very minor cosmetic change in cpyfrm() for group handling Tue Nov 27 16:54:51 1984 /mtr (agent: Marshall Rose) sbr/m_draft.c: add new result parameter which tells if a draft-folder is being used uip/{comp,dist,forw,repl,show,send,whom}.c: modified appropriately for extra parameter; this info is needed to decide which prompt and options to offer the user if the draft chosen exists Tue Nov 27 14:19:18 1984 /mtr (agent: Marshall Rose) uip/post.c: ignore Fcc:s when disting Mon Nov 26 20:34:18 1984 /mtr (agent: Marshall Rose) sbr/refile.c: new module; implements the "refile" option at "What now?" level uip/{comp,dist,forw,repl}.c: new switch -noedit, says to skip the initial edit and proceed directly to "What now?" level. Also make use of the new "refile" option at "What now?" level uip/comp.c: support for JLR's comp from a folder/msg notion Mon Nov 26 12:26:28 1984 /mtr (agent: Marshall Rose) uip/mhlsbr.c: add -[no]bell Mon Nov 26 10:20:07 1984 /mtr (agent: Marshall Rose) uip/send.c: add -[no]forward Sun Nov 25 23:36:59 1984 /mtr (agent: Marshall Rose) uip/{mhl,trm}sbr.c: move discard() from mhlsbr to trmsbr Sun Nov 25 19:30:46 1984 /mtr (agent: Marshall Rose) bbsupport/bboards.{dai,week}ly: if the bboards login shell is csh, can't use /bin/sh format... Sun Nov 25 13:28:47 1984 /mtr (agent: Marshall Rose) uip/{{mhl,trm}sbr,msh}.c: use and support SOprintf() for output to terminal uip/mhlsbr.c: add support for built-in mhl in msh, mhlsbr() uip/msh.c: use new support for built-in mhl sbr/m_getfld.c: some mis-logic in Eom(); if style is UNKNOWN, ALWAYS figure out what it is prior to going on Sat Nov 24 22:29:09 1984 /mtr (agent: Marshall Rose) uip/mhlsbr.c: into the fold Sat Nov 24 19:09:14 1984 /mtr (agent: Marshall Rose) sbr/showfile.c: if lproc is "mhl", use mhlproc for consistency (Actually, user should use "lproc: show", "showproc: mhl".) Sat Nov 24 09:59:31 1984 /mtr (agent: Marshall Rose) -- Fixes from John Romine at TGC -- conf/mh-gen.8: include "dm.h" in list of include files for MMDF2 conf/mh-gen.8: typo "ggenerate" conf/examples/READ-ME: BSD41a => BSD41A conf/mhconfig.c: V7 compiler tosses its cookies on reasonably formed structure members. Fix conf/config/config.c: remove comment about "pick -show" conf/{config/config.c,doc/mh-profile.rf}, config/mh.h sbr/m_getdefs.c: remove scanproc, since that's used only by "pick -scan" which does not exist conf/mhdoc: make into a Bourne shell script. Fri Nov 23 21:08:04 1984 /mtr (agent: Marshall Rose) -- More Changes for the ALTOS -- config/altos.h: didn't work, idiotic V7 compiler (cpp) didn't do "the right thing", so get rid of it and change the variable names in-line conf/config/mts.c: make isdlm{1,2} into macros instead of routines in mf/mf.c; also move getusr() there. conf/config/mts.c: make getfullname () standard and add new mtstailor option, mailid, to do the BRL/NRTC stuff with pw_gecos Fri Nov 23 19:26:35 1984 /mtr (agent: Marshall Rose) uip/{bbc,post,prompter,rcvdist,rmail,{repl,scan}sbr,s{bboards,local}}.c: minor clean-up Wed Nov 21 13:35:33 1984 /mtr (agent: Marshall Rose) config/dropsbr.h: new include file uip/dropsbr.c: add support for maildrop mapping uip/dropsbr.c: add new parameter to mbx_open() for default mode on creation uip/{msh,pack,post,rcvpack,s{bboards,local}}.c: modify to use new support for maildrop mapping Tue Nov 20 16:56:14 1984 /mtr (agent: Marshall Rose) bboards/{bboards.h,getbbent.c}: change bboard structure to make life easier for bbc. Also add new structure for use with msh. Mon Nov 19 23:36:57 1984 /mtr (agent: Marshall Rose) uip/bbc.c: neaten handling of distribution addresses on `-topics' output. Sun Nov 18 15:00:07 1984 /mtr (agent: Marshall Rose) uip/pick.c: if -help, set -nozero so done() doesn't print "0". Moby hack. Sat Nov 17 22:43:11 1984 /mtr (agent: Marshall Rose) uip/msh.c: add msh$pack command. uip/pack.c: simplify a bit. Sat Nov 17 21:22:35 1984 /mtr (agent: Marshall Rose) conf/makefiles/{mts,uip}: change PGMPROT to 755 for dpk. Sat Nov 17 15:33:14 1984 /mtr (agent: Marshall Rose) uip/{mhl,trm}sbr.c: add sc_length() to return li#. Have mhl assume co# and li# based on termcap entry if not given on command line. If entries aren't present in termcap, use values in template. Sat Nov 17 13:49:12 1984 /mtr (agent: Marshall Rose) config/mh.h,uip/{folder,refile}.c: add NFOLDERS to denote max number of folders/files on command line. Fri Nov 16 19:01:32 1984 /mtr (agent: Marshall Rose) uip/msh.c: remove -[no]burst switches. Add "rmm" command, but don't document it yet. Still have to resolve a few problems. Fri Nov 16 08:21:08 1984 /mtr (agent: Marshall Rose) -- More fixes from Fred Blonder at UMCP-CS -- conf/mhconfig.c: #define SVAL(s) to handle those pesky de-references to NULL. Fri Nov 16 08:20:50 1984 /mtr (agent: Marshall Rose) sbr/m_getdefs.c: close up COMPAT code slightly. conf/makefiles/*: change "-cp $(BINDIR)/cmd zcmd" to use "-mv". (On a trial basis.) Thu Nov 15 21:15:41 1984 /mtr (agent: Marshall Rose) -- Fixes from John Romine at TGC -- sbr/m_getdefs.c: use (FILE *)NULL instead of NULL when testing fopen()'s return value. Thu Nov 15 12:11:58 1984 /mtr (agent: Marshall Rose) mmdf/hosts.c: at the suggestion of Doug Kingston, use dm_v2route() to map host references to official domain strings. Thu Nov 15 09:29:43 1984 /mtr (agent: Marshall Rose) -- Fixes from John Romine at TGC -- uip/{forw,mhlsbr}.c: using NULL instead of "" in a couple of places. Thu Nov 15 09:24:32 1984 /mtr (agent: Marshall Rose) -- More fixes from Fred Blonder at UMCP-CS -- sbr/concat.c: botched installation for the pyramid. use Fred's code. Wed Nov 14 23:24:56 1984 /mtr (agent: Marshall Rose) -- All suggestions from Phyllis Kantar at Rand -- sbr/{ssequal,uleq}.c: default arguments to "" if NULL. uip/addrsbr.c: have ismymbox() recognize localhost!user. uip/folder.c: have "folder -fast msg" set "msg" as cur. sbr/m_getdefs.c: if using $MH, and it isn't relative, after expanding it, setenv it to an absolute pathname for subshells. Wed Nov 14 22:19:10 1984 /mtr (agent: Marshall Rose) sbr/m_gmsg.c: undo curmsg "fix" above, it broke MH mightily! sbr/m_convert.c: check curmsg here, so explicit references to "cur", when it doesn't exist, fails. Wed Nov 14 20:16:04 1984 /mtr (agent: Marshall Rose) sbr/adios.c: for 4.2BSD use writev() on the adios() family of routines, gives much smoother output. uip/mhlsbr.c: call the adios() family of routines instead of explicitly using stderr. Wed Nov 14 19:06:24 1984 /mtr (agent: Marshall Rose) sbr/m_{gmsg,seq}.c: fix various logic bugs that prevented private sequences from being recognized as such. Wed Nov 14 13:30:00 1984 /mtr (agent: Marshall Rose) sbr/m_convert.c: if "0" is given as a message number, print special error message (for use with backquoted pick). sbr/m_gmsg.c: be more careful about saying when "cur" exists. (don't set "curmsg" unless "mp -> msgstats[curmsg] & EXISTS"). Wed Nov 14 10:23:19 1984 /mtr (agent: Marshall Rose) -- All suggestions from Phyllis Kantar at Rand -- mf/mf.{h,c}: add new field entry "note" for 822-style comments. config/addrsbr.h: add corresponding field entry m_note. also change m_hnum to m_type. uip/addrsbr.c: add a new argument to getm() to say what type the default host is. Tue Nov 13 21:05:53 1984 /mtr (agent: Marshall Rose) uip/msh.c: add "sortm" command. uip/sortm.c: clean it up a bit. Tue Nov 13 18:58:43 1984 /mtr (agent: Marshall Rose) tws/{tws.h,dtime.c}: move tws_compare() from uip/picksbr.c to dtime.c, call it twsort(). Tue Nov 13 13:08:41 1984 /mtr (agent: Marshall Rose) newsupport/mh_receive: make it generated during MH configuration. conf/mhconfig.c: support above change. Tue Nov 13 00:58:41 1984 /mtr (agent: Marshall Rose) uip/msh.c: add "inc" and "mhmail" commands (big deal). Tue Nov 13 00:08:01 1984 /mtr (agent: Marshall Rose) uip/{burst,msh}.c: fix bursting algorithm to support forwardings/bcc:s. uip/{forw,mhlsbr,post}.c: strip one extra \n from last encapsulation boundary. Mon Nov 12 22:15:53 1984 /mtr (agent: Marshall Rose) -- All fixes from Fred Blonder at UMCP-CS -- conf/doc/mh.rf: add more details (mini tutorial). sbr/{concat.c,llib-lmh}: use sbr/m_name.c: use simpler method, sprintf(). Also fix size of name[] buffer. Mon Nov 12 11:01:51 1984 /mtr (agent: Marshall Rose) uip/post.c: re-arrange the code a bit for better organization. Mon Nov 12 08:29:19 1984 /mtr (agent: Marshall Rose) conf/makefiles/bbsupport: when MH profile was installed for the BBoards login, the context file wasn't. sbr/m_getdefs.c: if "context:" isn't set in the MH profile, then don't complain if it's not there. Mon Nov 12 08:15:59 1984 /mtr (agent: Marshall Rose) uip/msh.c: msh$show didn't know about the `-form formfile' switch. Sat Nov 10 16:10:33 1984 /mtr (agent: Marshall Rose) sbr/trimcpy.c: remove all trailing [lt]wsp. Thu Nov 8 16:59:37 1984 /mtr (agent: Marshall Rose) uip/bbc.c: trap sigTERM just like sigEMT so user can kill bbc and "have the right thing happen". Wed Nov 7 21:51:56 1984 /mtr (agent: Marshall Rose) uip/post.c: make Bcc:s look more line a forwarded message. uip/mhl.c: add -forwall flag to help forw for batching. the -forward flag now just uses the encapsulation algorithm. Wed Nov 7 20:45:44 1984 /mtr (agent: Marshall Rose) uip/{clr,scan}sbr.c: read termcap to ascertain the length of the scan line. uip/trmsbr.c: used to be called uip/clrsbr.c Wed Nov 7 20:12:04 1984 /mtr (agent: Marshall Rose) sbr/m_draft.c: "Draft-Folder: +drafts" loses. Strip the '+' if need-be. Tue Nov 6 21:33:39 1984 /mtr (agent: Marshall Rose) uip/dist.c: on "push" call ready_draft() prior to actual push() since if dist is invoked from bbr the file being distributed will get zapped prior to ready_draft() getting called. Moby hack. Tue Nov 6 21:16:42 1984 /mtr (agent: Marshall Rose) uip/msh.c: call m_unknown() since advanced m_getfld() algorithm loses otherwise (a long story). Tue Nov 6 09:56:55 1984 /mtr (agent: Marshall Rose) sbr/{m_edit.c,llib-lmh}: add extra argument for $cwd for edit. uip/{comp,dist,forw,repl}.c: call pwd() and invoke m_edit with the extra argument. Tue Nov 6 09:56:21 1984 /mtr (agent: Marshall Rose) conf/mhconfig.c: add "oldload" option for ALTOS. Mon Nov 5 18:15:01 1984 /mtr (agent: Marshall Rose) -- ALTOS port of MH.5 (under #ifdef ALTOS) -- conf/config/config.c: "more" resides in /usr/bin/. "ls" resides in /bin/. conf/config/mts.c: read /etc/mhid for {Local,System}Name(). Also add routine gethostname () which reads /etc/systemid. config/mh.h: #include "../config/altos.h" on #ifdef ALTOS. Also, new #define LINK which is "@" unless ALTOS else "#". config/altos.h: to get past V7 compiler... mf/msgchk.c: was using NULL instead of "" mf/mf.h: #include "../config/altos.h" on #ifdef ALTOS. sbr/m_edit.c: use LINK instead of "@" sbr/m_gmsg.c: use LINK instead of "@" sbr/m_seq.c: was using NULL instead of "" uip/clrsbr.c: use minimum of 2048 size for termcap buffer uip/dist.c: use LINK instead of "@" uip/install-mh.c: use (FILE *)NULL instead of NULL uip/msh.c: don't #include if ALTOS uip/repl.c: use link instead of "@" uip/rmf.c: use link instead of "@" Mon Nov 5 13:14:36 1984 /mtr (agent: Marshall Rose) uip/replsbr.c: don't adios() when can't understand "From:" or "Sender:" field. Continue on, gracefully (ha!) Sun Nov 4 17:40:04 1984 /mtr (agent: Marshall Rose) uip/folder.c: forgot the m_sync() after m_setcur(). This prevented "folder +folder msg" from setting msg as cur. Sun Nov 4 15:00:20 1984 /mtr (agent: Marshall Rose) sbr/m_getfld.c: in the interests of speed-up, change eom() to a macro that calls the auxilary function Eom() if need be. This, along with the addition of a new mbx_style, DEFAULT, should give a significant speed-up in parsing individual files and the MH profile. Finally, make Getc() a macro as well, which calls the routine GETC() only on special occasions. config/mh.h,sbr/{llib-lmh,m_getfld.c}: change mbx_unknown() to m_unknown(). Sat Nov 3 19:56:51 1984 /mtr (agent: Marshall Rose) uip/bbc.c: get this: "bbc -quiet" with no other arguments and a bogus "bboards:" entry in the profile would yield a core dump. Marvelous. Fri Nov 2 17:08:18 1984 /mtr (agent: Marshall Rose) uip/forwsbr.c: remove, put cpydgst() into sbr/cpydata.c config/mh.h, sbr/llib-lmh: declare cpydgst(). Fri Nov 2 13:44:50 1984 /mtr (agent: Marshall Rose) uip/{forw,forwsbr}.c: change encapsulation algorithm to use different bit-stuffing scheme. uip/mhlsbr.c: with -forward (interface from forw), support change in encapsulation algorithm. Fri Nov 2 13:17:27 1984 /mtr (agent: Marshall Rose) uip/replsbr.c: don't bomb if returnee's host is unknown (use AD_HOST instead of AD_NAME). mmdf/hosts.c: when calling mmdf_init() use invo_name and not "mh". Fri Nov 2 07:56:36 1984 /mtr (agent: Marshall Rose) uip/pick.c: if no matches and -list output a "0" so backquoting fails. Thu Nov 1 18:42:44 1984 /mtr (agent: Marshall Rose) sbr/brkstring.c: brkany() wasn't checking for a null string. It does now. Thu Nov 1 15:14:43 1984 /mtr (agent: Marshall Rose) support/mhl.format: change terminal length from 40 to 23. Thu Nov 1 00:33:24 1984 /mtr (agent: Marshall Rose) bbsupport/{bboards.{daily,weekly},bb{save,remove}} - use /bin/sh not /bin/csh bbsupport/bb{aka,exp,tar}.c - call setbbent() with the right argument. Where applicable use /bin/sh not /bin/csh conf/config/MakeBBoards - remove dependencies conf/mhconfig.c - support for empty mmdfldir and non-empty mmdflfil. Wed Oct 31 22:27:33 1984 /mtr (agent: Marshall Rose) uip/repl.c: since post can handle multiple folders in an fcc: line, take advantage of it. Wed Oct 31 20:23:13 1984 /mtr (agent: Marshall Rose) -- All fixes from Phyllis Kantar at Rand -- uip/repl.c: should use done(1) if the initial m_edit fails instead of done(0). sendmts/smail.c: comment out passing of "-ov" to SendMail if compiled at Rand. Wed Oct 31 19:12:58 1984 /mtr (agent: Marshall Rose) uip/rcv{cron,tty}.c: include "../mmdf/util.h" when MMDFMTS. Wed Oct 31 14:41:06 1984 /mtr (agent: Marshall Rose) uip/scansbr.c: change SLINE to 78 (instead of 79). We really should read termcap or an MH profile entry though. Wed Oct 31 08:13:36 1984 /mtr (agent: Marshall Rose) uip/prompter.c: if the skeleton lacked a body sometimes prompter would ask for a body and sometimes it wouldn't. Now it ALWAYS does. uip/show.c: "show -pr -f n" exec'd "pr inbox/-f inbox/n". Now it exec's "pr -f inbox/n" like it should. Wed Oct 31 07:54:41 1984 /mtr (agent: Marshall Rose) mmdf/hosts.c: somehow "mmdf.h" and "util.h" weren't included. Tue Oct 30 22:14:19 1984 /mtr (agent: Marshall Rose) uip/post.c: if we get an address-bearing field without any address, just ignore it instead of complaining about it. Tue Oct 30 21:30:38 1984 /mtr (agent: Marshall Rose) tws/dtimep.c: parse ctime(3) strings, since some fool hosts actually permit that to get into the Internet. Tue Oct 30 18:59:45 1984 /mtr (agent: Marshall Rose) mf/mf.c: very minor clean-up of isfrom(). mhmts/{hosts.c,netmail.c},{mmdf,sendmts}/hosts.c: include mts.h Tue Oct 30 16:35:37 1984 /mtr (agent: Marshall Rose) uip/prompter.c: if the skeleton lacked a body sometimes prompter would ask for a body and sometimes it wouldn't. Now it doesn't. uip/dist.c: call ready_msg() each time ready_draft() is called so user can edit message being dist'd. (sigh) Tue Oct 30 08:12:50 1984 /mtr (agent: Marshall Rose) uip/{comp,dist,forw,repl}.c: make the "push" option at "What now?" level visible. Document the draftfolder switches in the manual page uip/bbc.c: document `-file BBoardsfile' in manual page uip/bbl.c: remove -debug switch uip/repl.c: remove -debug switch uip/send.c: document -[no]remove in manual page, make -push visible and add -nopush. Document the draftfolder switches in the manual pages Mon Oct 29 19:23:10 1984 /mtr (agent: Marshall Rose) uip/bbc.c: remove a couple of calls to setbbent(). They were defeating setbbfile(). They weren't even needed since the first thing that bbc does (even before parsing arguments) is to call setbbent(). uip/show.c: force -noformat, -noheader, and -nopr to be at least three characters for recognition. uip/post.c: when invoking fileproc, add a '+' only if it doesn't start with '+' or '@'. Sun Oct 28 22:12:22 1984 /mtr (agent: Marshall Rose) uip/bbr$repl: forgot to support -[no]query. conf/doc/tmac.h: add .nf and .fi at the right spots for "FILES", etc. Sun Oct 28 20:36:45 1984 /mtr (agent: Marshall Rose) uip/folder.c: On "folder +foo", if +foo doesn't exist, ask if it should be. Sun Oct 28 10:32:06 1984 /mtr (agent: Marshall Rose) uip/*.c: remove calls to m_news(), also add m_foil() to foil implicit calls to m_getdefs (). {sbr/m_getdefs,uip/rmf}.c: make mp->others checking a bit smarter for #ifdef UCI. Sat Oct 27 23:08:23 1984 /mtr (agent: Marshall Rose) sbr/m_getdefs.c: create the MH-directory if it's not there. uip/rmf.c: when rmf'ing a folder make sure parent's folder is writable as well as the folder. Wed Oct 24 21:46:22 1984 /mtr (agent: Marshall Rose) conf/config/config.c, config/mh.h: add libpath() which looks first in m_maildir and then etcpath for the file. Get rid of the std* variables since libpath() now does the same thing. With libpath, we now search m_maildir and then etcpath for alias files for send and whom, form files for comp, dist, forw, and repl, and filter files for forw and mhl. Wed Oct 24 11:00:55 1984 /mtr (agent: Marshall Rose) -- All fixes from Terry Domae at NRTC -- conf/mhconfig.c: invoke mhdoc with csh explicitly since V7 doesn't. conf/config/config.c, config/mh.h: add new global variable libpath. uip/mhlsbr.c: support libpath for system-wide forms. config/mh.h,mf/mf.c,sbr/getusr.c,uip/post.c: add -DNRTC for MAILID support uip/replsbr.c: don't panic if the host for the sender/from field is unknown. uip/{send,whom}.c: forgot to use m_draft() instead of m_maildir(draft). sbr/m_draft.c: fix things up for show -draft. uip/show.c: add a "-form formfile" switch. Also, support for -draft to reflect draftfolders. Tue Oct 23 12:35:58 1984 /mtr (agent: Marshall Rose) conf/config/mts.c, mts/mts.h: remove the mbx_lock() and mbx_unlk() routines and replace them with the lock-and-open routines lkopen(), lkclose(), lkfopen(), and lkfclose(). lkopen() acquires an exclusive lock on the named file (which *must* exist) and then the appropriate open. lkclose() releases the lock and closes the file. lkfopen() is to lkopen() as fopen() is to open(). lkfclose() is to lkclose() as fclose() is to close(). I had to do all this so with 4.2BSD we can use flock to do the locking instead of the link/unlink business. Mon Oct 22 11:37:30 1984 /mtr (agent: Marshall Rose) sendmts/smail.c: forgot to declare parameter watch for -DSENDMAIL. conf/makefiles/*: make "make install" a synonym for "make inst-all". conf/makefiles/*: support $(DESTDIR) convention. Sat Oct 20 11:47:26 1984 /mtr (agent: Marshall Rose) uip/post.c: let fcc: fields have more than one folder entry. Fri Oct 19 08:57:23 1984 /mtr (agent: Marshall Rose) uip/dist.c: instead of introducing Prev-Resent-Header: just prepend Prev- to previous resent-XXX: fields. uip/{post,dist}.c: append resent-XXX: fields instead of prepending them. Also some minor clean-up. tws/dtime.c: use a better structure to permit "fool-proof" generation of time with dst. tws/dtimep.c: minor clean-up. Thu Oct 18 11:14:15 1984 /mtr (agent: Marshall Rose) uip/annosbr.c: if file doesn't exist, don't spit out error diagnostic (comp/dist/forw/send -anno followed by push). Wed Oct 17 10:02:27 1984 /mtr (agent: Marshall Rose) uip/inc.c: more mtstailor fixes, always read MAILDIR. uip/prompter.c: add the -[no]rapid switch. Mon Oct 15 08:27:13 1984 /mtr (agent: Marshall Rose) conf/{mhconfig.c,config/config.c}: make the default editor configurable. conf/mhconfig.c: add support for othersupport/Makefile. Makefile,conf/{config/mts.c,makefiles/mts}: add support for the mtstailor file. othersupport/tutorial/: include the MH tutorial uip/{ap,bbr,conflict,inc,post,rcvcron,rcvlink,rmail,sbboards,slocal}.c, mts/msgchk.c: add support for the mtstailor file. uip/{rmail,sbboards,slocal}.c: foil m_getdefs() (just in case). Fri Oct 12 09:53:56 1984 Rand MH Mail Handler (agent: Marshall Rose) uip/ap.c: be sure to foil m_getdefs() for consistency. Fri Oct 12 09:52:19 1984 Rand MH Mail Handler (agent: Marshall Rose) sbr/m_edit.c: change rindex() to r1bindex(). Silly typo. Wed Oct 10 14:41:30 1984 Rand MH Mail Handler (agent: Marshall Rose) uip/rcv{cron,link,tty}.c: foil m_getdefs() for JLR. Wed Oct 10 09:15:23 1984 Rand MH Mail Handler (agent: Marshall Rose) uip/install-mh.c: fix minor typo in display of help message. Mon Oct 1 20:49:32 1984 Rand MH Mail Handler (agent: Marshall Rose) uip/repl{,sbr}.c: add the -[no]query switch which interactively prompts the user for info on who should be replied-to. Mon Oct 1 20:48:25 1984 Rand MH Mail Handler (agent: Marshall Rose) uip/{scan,inc,scansbr}.c: change scansbr.h to #define the return codes from scansbr$scan(). Modify scan.c to say if a null message is empty. Sat Sep 22 20:19:40 1984 Rand MH Mail Handler (agent: Marshall Rose) uip/rcvlink.c: new rcvmail hook, just like the old rcvlink hook used in the ZOTnet. Sat Sep 22 19:03:02 1984 Rand MH Mail Handler (agent: Marshall Rose) uip/sbboards.c: forgot a few arguments in a couple of printf-like strings. Fri Sep 21 19:25:25 1984 Rand MH Mail Handler (agent: Marshall Rose) sendmts/hosts.c: change ALLHOSTS logic: if we're running with an exception file, then turn ALLHOSTS on (let mail system be final arbitrator). Also, if using an exception file, play along if the file can't be opened. Wed Sep 19 16:02:18 1984 Rand MH Mail Handler (agent: Marshall Rose) uip/scan..c: if message is unreadable (errno==EACCES), just say "unreadble", don't bother to call admonish(). Tue Sep 18 14:30:57 1984 Rand MH Mail Handler (agent: Marshall Rose) uip/inc.c: Check $MAILDROP prior to checking the Maildrop: profile entry. Tue Sep 18 14:16:53 1984 Rand MH Mail Handler (agent: Marshall Rose) uip/folder.c: if folder is unreadable (errno==EACCES), just say "unreadable", don't bother to call admonish(). Sun Sep 16 16:08:39 1984 Rand MH Mail Handler (agent: Marshall Rose) uip/folder.c: change capitalization of "%d Folder%s" to "%d folder%s". Wed Sep 12 20:02:22 1984 Rand MH Mail Handler (agent: Marshall Rose) uip/rcv{cron,tty}.c: if not reading mmdf.h, then read smail.h to get proper definitions of RP_M{ECH,OK}. Tue Sep 11 19:59:24 1984 Rand MH Mail Handler (agent: Marshall Rose) tws/dtime.c: have it know about EDT. Really, dtimezone needs to get fixed up and use two tables instead of one... Mon Aug 27 05:07:37 1984 Rand MH Mail Handler (agent: Marshall Rose) uip/inc.c: examine the profile entry "maildrop" to override the default maildrop if necessary. "maildrop" is interpreted with m_mailpath(), so if not an absolute path, it's interpreted relative to the user's MH directory. Mon Aug 27 05:00:44 1984 Rand MH Mail Handler (agent: Marshall Rose) Decide that mh.4 is finished. This file keeps track of the changes made between the mh.4 and mh.5 versions. As usual, it's being kept in add-source-change format. [Actually, mh.4 was finished on July 1, 1984. For obscure reasons, this ChangeLog didn't start until August 27th though.] MHCHANGES from mh.3 to mh.4 Fri Oct 26 22:19:42 1984 Rand MH Mail Handler (agent: John Romine) conf/Makefile: make CFLAGS=-O, LDFLAGS=-ns sendmts/smail.c: line 99: formal parameter 'watch' was missing. Thu Aug 2 15:05:29 1984 Rand MH Mail Handler (agent: Marshall Rose) uip/rcv{cron,tty}.c: move the ``#include '' above the ``#include "mmdf.h"'' mf/*.{h,c}: change lexequ() to lequal() to avoid conflict with MMDF-II routine name. Wed Jul 25 08:49:44 1984 Rand MH Mail Handler (agent: Marshall Rose) uip/bbr.c: bring upto date with dist/forw/repl's -nodraftfolder. sbr/trimcpy.c: fold tabs into spaces in addition to newlines. Mon Jul 23 19:07:00 1984 Rand MH Mail Handler (agent: Marshall Rose) sbr/m_getdefs.c: allow long lines in MH profile. uip/ptt.c: rename ptt.c to ap.c and install in MH etc directory. Mon Jul 23 16:09:04 1984 Rand MH Mail Handler (agent: Marshall Rose) uip/{scan,replsbr}.c: use ismymbox to determine if address is my mailbox. uip/addrsbr.c: add ismymbox() to say just that. Mon Jul 23 14:27:51 1984 Rand MH Mail Handler (agent: Marshall Rose) uip/{comp,dist,forw,repl,send}.c: add -nodraftfolder switch to turn off draft folder. uip/send.c: add -[no]unique switch to enable/disable message renaming on pushes. Mon Jul 23 09:11:27 1984 Rand MH Mail Handler (agent: Marshall Rose) uip/scansbr.c: If the message has no date, flag it and use the date on the file, if appropriate (e.g., from 'scan' not 'inc'). Mon Jul 23 09:08:12 1984 Rand MH Mail Handler (agent: Marshall Rose) uip/{dist,forw,repl}.c: fix busted logic when m_draft() is called after we've built the msgs structure for the folder we're working on. Call m_draft() first. Other solution was to have m_draft() do a pwd(), save the result, do its work, and then chdir() back. Sigh. Sat Jul 21 14:15:43 1984 Rand MH Mail Handler (agent: Marshall Rose) sbr/{m_gmsg,m_seq}.c: allow "compressed" sequence descriptors (e.g., x-y instead of x x+1 ... y-1 y). Makes things run faster and avoids problems if a sequence is really *big*. Fri Jul 20 21:27:03 1984 Rand MH Mail Handler (agent: Marshall Rose) uip/{comp,dist,forw,repl}.c: new logic if draft exists. uip/{comp,dist,forw,refile,repl,send}.c: fix miscalculation in path of draft/source folder. Thu Jul 19 19:56:16 1984 Rand MH Mail Handler (agent: Marshall Rose) sbr/m_edit.c: put back in the draft preserve/delete logic from mh.2 sbr/m_draft.c: add the "use" parameter saying whether "new" or "cur" should be the default. Wed Jul 18 20:39:29 1984 Rand MH mail system (agent: Marshall Rose) sbr/path.c: add compath() logic to compress things like @.. and so on. Wed Jul 18 05:35:14 1984 Rand MH mail system (agent: Marshall Rose) uip/{comp,dist,forw,repl}.c: Add -draft{folder,message} switches, remove -[no]unique switches sbr/m_draft.c: New module to interpret -draft switches uip/send.c: Handle multiple messages, add -draft{folder,message} switches, add -push switch uip/bbr.c: bring dist, forw, and repl up to date with all these changes conf/config/config.c: change mh_deliver to postproc Wed Jul 18 03:01:11 1984 Rand MH mail system (agent: Marshall Rose) Install the code necesary for the @folder notation, meaning +cwf/folder (TSUBCWF). Tue Jul 17 19:20:10 1984 Rand MH mail system (agent: Marshall Rose) uip/anno.c: don't require -text. Also fix bug in prompting. Tue Jul 17 16:19:14 1984 Rand MH mail system (agent: Marshall Rose) uip/folder.c: handle +folder and msg argument with -all. Tue Jul 17 16:02:02 1984 Rand MH mail system (agent: Marshall Rose) uip/bbr.c: bring dist, forw, and repl up to date with -[no]unique. Tue Jul 17 00:08:52 1984 Rand MH mail system (agent: Marshall Rose) Install the Sequence-Negation mechanism. Mon Jul 16 22:07:40 1984 Rand MH mail system (agent: Marshall Rose) uip/*.c: Change arguments[50] to arguments[MAXARGS]; change msgs[100] to msgs[MAXARGS] to avoid argument overflow with new pick. Mon Jul 16 15:51:28 1984 Rand MH mail system (agent: Marshall Rose) Gather up the ZOTnet libraries into zotnet/libzot.a, makes things less complicated. Mon Jul 16 00:21:52 1984 Rand MH mail system (agent: Marshall Rose) Install the new Previous-Sequence mechanism. Introduce the SEQMOD flag to the msgs structure. Just about every MH program now calls m_setseq () upon parsing the messages and calls m_sync() prior to exiting. Mon Jul 16 00:18:49 1984 Rand MH mail system (agent: Marshall Rose) uip/{comp,dist,forw,repl}.c: If "quit" with no "delete, tell the user the name of the draft file. uip/send.c: if invoked as "push", act accordingly sbr/m_send.c: know about "push". uip/mhpath.c: -help wasn't any. uip/rcv{cron,tty}.c: set-up for an MMDF system. Sun Jul 15 17:10:38 1984 Rand MH mail system (agent: Marshall Rose) uip/{comp,dist,forw,repl}.c: Add -[no]unique switch. uip/send.c: Remove -[no]unique switch, also read ~/.signature file and define $SIGNATURE if need be. uip/post.c: Don't read ~/.signature file, use $SIGNATURE only. uip/{bbr$scan,inc,scan,scansbr}.c: Only do the ftell() business with -size on an inc. The others can do an fstat or pointer arithmentic to calculate the size. Sun Jul 15 03:01:12 1984 Rand MH mail system (agent: Marshall Rose) uip/{comp,dist,forw,repl}.c: If send of draft loses, come back to "What now?" level. Also fix bug with invocation of editor. Fri Jul 13 13:37:21 1984 Rand MH mail system (agent: Marshall Rose) uip/scansbr.c: Compress the fields a bit. Right-justify some parts of the header. Fri Jul 13 13:17:48 1984 Rand MH mail system (agent: Marshall Rose) uip/folder.c: Set up things so DMAXFOLDER is used when formatting the output strings. Wed Jul 11 18:41:07 1984 Rand MH mail system (agent: Marshall Rose) uip/folder.c: remove -up, -down, and -short uip/pick.c: toss all the file-op:s, -scan, and -show. Just define sequences, or spit 'em to stdout. The select sub-folder is dead! Long live user-defined sequences! Pick got rid of 11 (!!) switches this way, and we've taken our first step into a new age of functionality. Wed Jul 11 02:25:25 1984 Rand MH mail system (agent: Marshall Rose) uip/repl.c: toss the hidden -[no]ccme switches. Tue Jul 10 01:15:22 1984 Rand MH mail system (agent: Marshall Rose) config/mh.h, conf/config/config.c, sbr/m_{getdefs,update}.c: add "context" file in addition to the MH-profile. The former is dynamic, it contains pfolder and private sequences. The latter is static, it contains switches, etc. The ctx file defaults to Mail/context. But in the MH-profile, you can define the entry for "context" to be whatever you want... Mon Jul 9 23:15:20 1984 Rand MH mail system (agent: Marshall Rose) uip/{scan,inc,bbr}.c: new switches -[no]size to show the size of the message. uip/scansbr.c: implement -size for scan, inc, and bbr$scan. uip/folder.c: new switches to implement the folder stack. uip/clrsbr.c: consolidate clear_screen() into one file. Mon Jul 9 17:05:09 1984 Rand MH mail system (agent: Marshall Rose) sbr/showfile.c: take arg vector from caller. uip/show.c: new "-file file" switch for showfile. sbr/m_edit.c: take arg vector from caller. If present, give to editor in exec. Mon Jul 9 14:48:51 1984 Rand MH mail system (agent: Marshall Rose) config/mh.h: add extern char *version. sbr/help.c: have help() print out program name and version info. conf/makefiles/uip: use version.sh to create version.c for loading with uip:s. Mon Jul 9 00:01:01 1984 Rand MH mail system (agent: Marshall Rose) uip/prompter.c: with BSD42, do a clearerr() on stdin when we get an EOF. Otherwise, with an EOF in the headers, we lose big... Sun Jul 8 23:58:56 1984 Rand MH mail system (agent: Marshall Rose) uip/bbr.c: add the hidden "-prompt string" switch for JLR. Sat Jul 7 18:51:02 1984 Rand MH mail system (agent: Marshall Rose) mhmts/hosts.c: add '#include ' for #ifdef BSD42. sbr/m_gmsg.c: fix initializatino of flags[]. uip/whom.c: close down fd:s, just like send does, to avoid the infamous "too many open" files error with the MMDFMTS version of post. uip/pick.c: fix-up "[Folder xyz being re-used]" message. It was using the wrong string for the folder name. Sat Jul 7 01:03:02 1984 Rand MH mail system (agent: Marshall Rose) sbr/m_edit.c: #undef the $EDITOR stuff, maybe it's not such a good idea... Mon Jul 2 02:07:37 1984 Rand MH mail system (agent: Marshall Rose) uip/post, uip/send: rework BCC handling to allow the use of a filter file. Sat Jun 30 23:27:27 1984 Rand MH mail system (agent: Marshall Rose) uip/send: if $SIGNATURE is empty, and there's a "signature" entry in the profile, set $SIGNATURE to that for post. Sat Jun 30 16:40:22 1984 Rand MH mail system (agent: Marshall Rose) sbr/m_edit.c: On first edit, if "-editor pgm" not specified, try to use $EDITOR prior to using the profile entry for editor. Sat Jun 30 16:23:20 1984 Rand MH mail system (agent: Marshall Rose) Add the -[no]public switches to bbr$mark, bbr$pick, mark, and pick. Sat Jun 30 16:23:01 1984 Rand MH mail system (agent: Marshall Rose) Add the SMTP option to the SendMail configuration. Extend post/send to accept -mail, -soml, -saml, and -send. Also add -client host and -server host. Sat Jun 30 12:29:53 1984 Rand MH mail system (agent: Marshall Rose) config/mh.h: Raise MAXFOLDER to 2K-1 and modify DMAXFOLDER as appropriate. Also, make LOWSEL dependent on MAXFOLDER. Sat Jun 30 12:28:48 1984 Rand MH mail system (agent: Marshall Rose) config/mh.h: compact msgs structure a bit. Also add new entry, mp -> attrstats, which tells if the corresponding attribute named in mp -> msgattrs is public or private. Sat Jun 30 12:28:21 1984 Rand MH mail system (agent: Marshall Rose) sbr/m_getdefs.c: make sure $MH is non-empty before using it. Fri Apr 6 10:52:26 1984 PostMaster (agent: uip/show.c: mhl wasn't seeing its name so it wasn't checking its profile entry. (fix from spencer thomas at utah-gr). Mon Apr 2 07:34:35 1984 PostMaster (agent: John Romine) uip/refile.c: remove(): bug fix. call delete-prog if (filep > 0) instead of if (filep > 1). Sat Mar 31 08:26:29 1984 PostMaster (agent: John Romine) uip/mhmail.c: unlink temp file when exiting due to null input. Fri Feb 17 09:10:55 1984 Rand MH System (agent: John Romine) uip/bbc.c: output last update date with -topics in short form instead of local leaders. local leaders are listed with the other fields with -topics -verbose. Thu Feb 16 10:19:12 1984 PostMaster (agent: Marshall Rose) uip/bbr.c - Have bbr use a different prompt based on the name it was invoked with. This is useful, since it used to use the same prompt as "ex". This got confusing since sometimes you'd be editing a file in ex while composing a message from bbr. Wed Feb 15 14:47:18 1984 PostMaster (agent: Marshall Rose) Decide that mh.3 is finished. This file keeps track of the changes made between the mh.3 and mh.4 versions. Note that it's being kept in add-source-change format instead of the usual add-change-log-entry format. [Unfortunately, changes up through MH 3 are apparently lost, unless people at Rand and/or UCI have them stashed away somewhere... --Dan Harkless] nmh-1.7.1-RC3/docs/ChangeLog_MH-6.7.0_to_MH-6.8.4.html000644 007761 000024 00000135420 11723762073 021237 0ustar00kenhstaff000000 000000 MH Change Log

                                   Changes to
                      The RAND MH Message Handling System:
                               UCI version MH 6.8


                                 John L. Romine

                            Computing Support Group
                        Information and Computer Science
                        University of California, Irvine
                             Irvine, CA  92717-3425
                               Bug-MH@ICS.UCI.EDU
                           http://www.ics.uci.edu/~mh/


                                   ABSTRACT


                    This document describes the changes to the
               UCI version of the RAND MH system from MH 6.6 to
               this release of MH 6.8.  This document is meant to
               supplement, not supersede, the standard MH User's
               manual and MH Administrator's manual.

                    Comments concerning this documentation should
               be addressed to the mailbox Bug-MH@ICS.UCI.EDU.
               Current information about MH can be obtained from
               the MH Home Page on the World Wide Web at
               http://www.ics.uci.edu/~mh/.



          ACKNOWLEDGEMENTS

          The MH system described herein is based on the original RAND
          MH system.  It has been extensively developed (perhaps too
          much so) by Marshall T. Rose and John L. Romine at the
          University of California, Irvine.  Einar A. Stefferud, Jerry
          N. Sweet, and Terry P. Domae provided numerous suggestions
          to improve the UCI version of MH.

               Of course, a large number of people have helped MH
          along.  The list of "MH immortals" is too long to list here.
          For this release, numerous MH-Workers sent in fixes and
          other changes.  A handful of courageous MH-Workers volun-
          teered to beta-test these changes; their help is particu-
          larly appreciated.

          DISCLAIMER

          The Regents of the University of California wish to make  it
          known that:

               Although each  program  has  been  tested  by  its
               contributor,  no  warranty, express or implied, is
               made by  the  contributor  or  the  University  of
               California,  as to the accuracy and functioning of
               the program  and  related  program  material,  nor
               shall the fact of distribution constitute any such
               warranty, and no responsibility is assumed by  the
               contributor  or  the  University  of California in
               connection herewith.

          CONVENTIONS

          In this document, certain formatting conventions are adhered
          to:

               The names of UNIX commands, such as comp are  presented
               in italics.

               Arguments to programs, such as `msgs' and `-nobell' are
               delimited by single-quotes.

               Text that  should  be  typed  exactly  as-is,  such  as
               command  lines (e.g., "folder -pack"), are delimited by
               double-quotes.

               UNIX pathnames and envariables, such  as  /usr/uci  and
               $SIGNATURE, are presented in bold font.


          CHANGES FOR MH 6.8.4

          The MH 6.8.4 release is a minor maintenance release, and
          contains few user-visible changes.  The changes consist
          mostly of documentation improvements, minor bug fixes, and
          some portability enhancements for BSD 4.4 and Solaris 2.x
          (contributed changes for HPUX and OSF1 have not yet been
          integrated into this release).  This is the current version
          of MH as of February 8, 1996.

          Runtime Tailoring

          By default post will now give the SMTP HELO command with the
          local hostname.  If you specify a hostname with the
          clientname: option in the mtstailor file, post will give the
          HELO command with that name instead.  If the argument to the
          clientname: option is empty, no HELO command is given.  See
          mh-tailor(5) for more details.

          Multi-media Mail & Encryption

          A few new PGP support programs can be found in the
          support/general directory.  repl supports the `-[no]mime'
          option.  See repl(1) for more details.


          CHANGES FOR MH 6.8.3

          The MH 6.8.3 maintenance release contains few user-visible
          changes.  Most of the changes are internal to the multi-
          media display program mhn to support RFC 1521 (the new MIME
          standard).  This is the current version of MH as of December
          1, 1993.

          Runtime Tailoring

          When posting mail using the SMTP, post did not normally send
          the HELO command. This was because SendMail would fail if
          the host name given in the HELO command was the local host.
          Later versions of SendMail will now complain if you omit the
          HELO command.

          User Interface Programs

          folder  The folder command now has `-create' and `-nocreate'
                  options.  See folder(1) for details.

          inc     A bug where `-host' would not override the pophost
                  as set in the mtstailor file has been fixed.  This
                  bug was also fixed in msgchk.

          mhn     The mhn command has several changes:  updates for
                  conformance with RFC 1521, addition of two caches:
                  public and private, addition of two caching poli-
                  cies: one for reading and one for writing, support
                  for storing multipart entities, and a few bug fixes.
                  See mhn(1) for complete details.

          CHANGES FOR MH 6.8.2

          The MH.6.8.2 patch release contains only internal changes to
          support the BSD 4.4 and 386BSD versions of UNIX.  This ver-
          sion of MH was released August 25, 1993, but was not widely
          distributed.

          CHANGES FOR MH 6.8.1

          The MH.6.8.1 patch release is a maintenance release.  This
          is the current released version of MH as of August 20, 1993.

               This release includes a small number of bug fixes, a
          few minor enhancements, some changes for the new MIME stan-
          dard, and support for ESMTP (RFC 1425).  Support for BSD 4.4
          and 386BSD is planned for the next release.

               Many other fixes which have already been received are
          still being merged.  If you've sent an update for MH 6.8 to
          Bug-MH@ics.uci.edu and it isn't in this release, it'll prob-
          ably appear in the next release.

          Fixes and Enhancements

          Many minor documentation corrections were made.  There are
          also a few program changes:

          mhn   The `-cache policy', `-[no]check', and `-[no]pause'
                switches have been added.   Some other minor changes
                have been made to comply with the new MIME standard.
                See mhn(1) for complete details.

          post  When posting mail with SendMail, post will not use the
                ONEX command when it is posting a message with BCCs.

          scan  scan will now work with big width values.

          Format Strings

          One new function has been added:

          %(profile arg)  This function looks up a component in the
                          .mh_profile or context files and returns the
                          value of that component.

          Configuration

          Two new configuration options are present:

          GCOS_HACK    The so-called "gcos" field of the password file
                       is used as a last resort to find the user's
                       full name (see mh-profile(5) for details).
                       Enable this option if your passwd(5) man page
                       notes that the `&' character in the "gcos"
                       field stands for the login name.

          NORUSERPASS  Tells MH that your system doesn't have the
                       ruserpass(3) routine; MH will include its own
                       copy of this routine in its library.


          CHANGES FOR MH 6.8

          This is the current released version of MH as of December
          14, 1992.  This release includes a number of bug fixes and
          internal changes to make the code more portable.  Two new
          authentication methods are provided for the POP, and support
          for SVR4 shared libraries is complete.

               The major user-visible change in this release is the
          incorporation of support for multi-media mail as specified
          by the Multi-purpose Internet Mail Extensions (MIME)
          RFC 1341.  This allows you to include things like audio,
          graphics, and the like, in your mail messages.  A new com-
          mand, mhn, has been provided to support MIME and a detailed
          man page is provided in mhn(1).

          Documentation

          The documentation has some general improvements, and the
          READ-ME document has been re-organized to help MH adminis-
          trators find the appropriate configuration options for their
          system.  The Makefiles in the papers/ hierarchy have been
          changed to invoke TeX as "tex" (instead of "tex82").

          The following new man pages are also available:

          mhn(1)      mhn helps the user process multi-media mail.

          mhparam(1)  mhparam lets the user extract information from
                      the MH profile.

          popauth(8)  the APOP database administration program (see
                      below).

          popi(1)     the POP initiator (see below).

          slocal(1)   fully documents slocal.  The mhook(1) man page
                      now documents only the MH receive-mail hooks.

          Internal Changes

          The MH source code is in the process of being cleaned up to
          make pedantic ANSI C compilers happy.  Occurrences of "NULL"
          have been replaced by "0" where appropriate.  Extra tokens
          after "#else" and "#endif" have been put inside comments
          (this is still in progress).  The code should now compile
          cleanly on many more systems, specifically, more variants of
          SVR4.

               The version of tws/dtimep.c which was included in MH
          6.7.2 was incompatible with the lex library on some systems,
          and has been removed.

               A bug in the handling of blind lists inside alias files
          has been fixed.

          Post Office Protocol

          There were three new options added to the POP.

          APOP  This option indicates that the POP daemon will support
                the   non-standard   APOP  command  which  provides  a
                challenge-based authentication system  using  the  MD5
                message digest algorithm.

                This option also causes  the  popauth  program  to  be
                installed,   which   allows   the   administrator   to
                manipulate the APOP authorization database.

          KPOP  Support for KERBEROS with POP.  This code builds popd,
                inc and msgchk to support only the "kpop" protocol.
                This code is still expiremental, but is available for
                those sites wishing to test it.

          MPOP  This option indicates that the POP daemon will support
                the non-standard XTND SCAN command which provides per-
                formance enhancements when using the POP over low-
                speed connections.

                This option also causes an interactive POP client pro-
                gram, popi, to be compiled and installed.  A man page
                for the popi program is also provided.  This option
                requires the configuration to have "bboards: pop".

          The APOP and MPOP non-standard POP facilities are documented
          in The Internet Message (ISBN 0-13-092941-7), a book by
          Marshall T. Rose.  For more details, see support/pop/pop-
          more.txt and the Administrator's Guide.  The APOP option
          peacefully co-exists with the standard POP, KPOP completely
          replaces the standard POP, and MPOP requires "bboards: pop".

          File Locking

          The file locking code has been cleaned up to support three
          kinds of kernel-level file locking.  As appropriate for your
          system, include the LOCKF, FCNTL or FLOCK option.  For more
          details, see mh-tailor(5).

          Configuration Directives

          A number of new configuration directives have been added  or
          changed.  The full details are given in the READ-ME.

          cp:        The command used to  install  new  files  if  not
                     "cp".

          ln:        The command used to link files  together  in  the
                     source tree if not "ln".

          mts:       Full support for ZMAILER has been added.

          popdir:    The directory where popd will be installed if not
                     /usr/etc.

          regtest:   Set to "on" to prevent the hostname  and  compile
                     date from being included in MH binaries.

          sharedlib: You may now specify "sun4" or "sys5"  (for  SVR4)
                     shared libraries.

          signal:    Specifies the base type of the function  returned
                     by  signal().   This  was previously defined with
                     "options TYPESIG".

          Several `-D' options to cc have been added or changed:

          APOP       Authenticated POP (see above).

          AUX        Support for A/UX systems.

          DBMPWD     The DBM option has been renamed DBMPWD.

          HESIOD     Support for the HESIOD name server.

          KPOP       KERBEROS POP (see above).

          LOCALE     Support for local characters sets; uses the set-
                     local() function.

          MAILGROUP  Makes inc set-group-id.  You may need this option
                     if your /usr/spool/mail is not world-writeable.

          MIME       Multi-media mail.

          MPOP       Mobile POP (see above).

          MSGID      Enables slocal to detect and surpress duplicate
                     messages.

          OSF1       Support for DEC OSF1 systems.  May be incomplete.

          RENAME     Include this option if your system has a rename()
                     system call.

          SVR4       Support for System 5 Release 4 or newer systems.

          TYPESIG    This option has been dropped.  See `signal'
                     above.

          UNISTD     Include this option if your system has the
                     include file <unistd.h>.

          VSPRINTF   Include this option if your system has the
                     vsprintf() library routine; otherwise, _doprnt()
                     will be used.

          YEARMOD    Forces the mh-format `year' function to return
                     2-digit values.  Use this option during a brief
                     transition period if you have local mh-format
                     files which need to be converted to support 4-
                     digit years.

          FUNCTIONAL CHANGES

          In addition to the configuration changes mentioned above, a
          number of functional changes have been made to the system.
          Many programs have new features added and a few new programs
          have are provided. Each command's manual page gives complete
          information about the its operation.  Here is a short sum-
          mary of the changes.

          MH Sequences

          A larger number of user-defined sequences are available.
          Previously, this number had been 10.  On 32-bit systems, 26
          user-defined sequences are available.

          Profile Components

          MH programs will now complain if the .mh_profile does not
          end in a newline.  Also, one enhancement and one new profile
          component are provided:

          Aliasfile:  Multiple filenames may now be given.

          Inbox:      New; the default folder (for inc, etc.) if not
                      "inbox".

          Format Strings

          A few minor bugs were fixed in format string handling, and a
          few  new features were added.  See mh-format(5) for complete
          details.

          Addresses      An  attempt  is  made   to   decipher   X.400
                         RFC 987-style addresses.

          Comments       Comments may be added to mh-format  files;  a
                         comment  begins with the 2-character sequence
                         "%;", and ends with an un-escaped newline.

          %(modulo n)    The `modulo' function escape has been added.

          %(year{date})  The  date  parser  has   been   enhanced   to
                         understand  more illegal date formats; `year'
                         now returns a 4-digit number.

          User Interface Programs

          A number of MH commands have minor changes:

          ali       The output with `-user -list' was changed to match
                    the output with `-nouser -list'.

          burst     Will no longer drop the last message of a digest.

          inc       Accepts the `-apop' switch for authenticated POP
                    (see above); will attempt to detect write errors
                    (e.g., no space left on device) when incorporating
                    mail; no longer replaces newline characters with
                    NULLs.

          folder    The `-noprint' option was broken and has been
                    dropped.

          forw      Supports `-mime' to use MIME-style multi-part mes-
                    sages.

          mhl       Will no longer put an extra space at the end of
                    the `%{text}' in a formatfield.

          mhn       New; manipulates multi-media (MIME) messages; a
                    detailed man page is provided.

          mhparam   New; reads the MH profile (and context) and writes
                    the values of the specified components on the
                    standard output; useful in programmatic con-
                    structs.

          msgchk    Supports `-apop' (see above).

          packmbox  New; packs an MH folder into a UUCP-style mailbox.

          popi      New; a client-side POP initiator; available only
                    if you built MH with the MPOP option (see above).

          refile    A bug where the `rmmproc' did not remove all
                    specified message files has been fixed.

          scan      The `-file' option is fully supported and will no
                    longer complain about empty folders.

          send      Supports `-mime' and `-split' to split large mes-
                    sages into multiple partial messages using MIME.

          Support Programs

          fmtdump   Can now read a format file, or a format string
                    given on the command line.

          popauth   New; manages the APOP authorization database (see
                    above).

          sendmail  The sendmail replacement will be installed only if
                    your `mts' setting uses the `/smtp' option.

          slocal    A new man page for slocal is available; the new
                    `mbox' action is available to write a file in
                    packf format; a bug where extra `>' characters
                    were written to MMDF-style maildrops has been
                    fixed; if compiled with the MSGID option, can
                    detect and suppress reception of duplicate mes-
                    sages.

          viamail   New; bundles a directory (like shar) and sends it
                    through multi-media mail.


          CHANGES FOR MH 6.7.2

          The MH.6.7.2 patch release is a maintenance release.  This
          is the current released version of MH as of February 1,
          1992.

               This release now supports the NCR Tower running SYS5R4.
          The WP changes installed in MH.6.7.0 have been removed.

          Shared Libraries

          Support for SYS 5 shared libraries is in progress.

               Support for Sun OS 4.0 shared libraries had been
          improved.  The MH library has been modified to move initial-
          ized data into a data definition file.  The shared library
          will now consist of a libmh.so and libmh.sa file.  The
          shared library version number will no longer track the MH
          patch release number, and its numbering begins with version
          `1.1' with this release.

          Replacement SendMail

          Since many standard system programs expect to post mail by
          invoking /usr/lib/sendmail, a minimal replacement SendMail
          is provided in this release.  This replacement is meant to
          be installed on (e.g., diskless) client workstations which
          post mail using SMTP, and do not run a message transport
          system.  It will call post to post mail; be sure you have
          configured MH with the `/smtp' mts option.  This sendmail
          replacement is installed in your MH etc directory, and you
          should link /usr/lib/sendmail to it.

          Format Strings

          A manual page for the fmtdump format string disassembler  is
          supplied, and some new format functions were added:

          folder   In scan, this component escape contains the name of
                   the current folder.  It is not defined for other MH
                   commands.

          getenv   This  function  escape  returns  the  value  of  an
                   environment variable.

               There will be some additional changes in these routines
          in the next patch release.

          Other Bug Fixes and Enhancements

          In addition to some other minor enhancements, some bugs were
          fixed which in general were not user-visible:

          Blind lists   Users may now specify RFC822 address groups in
                        their   alias   files.    These   groups   are
                        implemented by MH as blind lists.

          date parsing  A number of sites have brain-damaged  versions
                        of lex.  MH will now come with the date parser
                        already run through lex.

          mark          A bug dealing with mark and the sequence named
                        `cur' is fixed.  This was previously a problem
                        for mh-e users.

          MH.doc        The MH nroff version of the manual  no  longer
                        contains teletype escape sequences.

          scan          Can now handle headers as long as 512 bytes.

          Signals       MH programs will no longer catch the  HUP  and
                        TERM  signals while waiting for a sub-process.
                        This was  causing  hung  processes  when  your
                        terminal line was was dropped unexpectedly.

          Signature     If your signature is not defined, MH will  use
                        the   value   of   the  gecos  field  of  your
                        /etc/passwd entry as your signature.

          version.sh    A bug in the awk script  in  config/version.sh
                        was fixed.


          CHANGES FOR MH 6.7.1a

          The MH.6.7.1a patch was made available on January 25, 1991
          for limited distribution only.  (This release had some known
          bugs, and so was not widely distributed.)  This release
          incorporates several new features of particular note to
          users of sequences and format strings, as well as some gen-
          eral documentation improvements.  There are a few minor
          enhancements and internal bug fixes also.  Complete documen-
          tation of these changes is given in the individual manual
          pages, and the READ-ME file.

          Message Sequences

          A new manual page, mh-sequence (5), has been added.  This
          manual page attempts to completely document the syntax and
          semantics of MH message sequence specifications.

               A powerful new feature is the ability to specify mes-
          sage ranges with user-defined sequences.  The  specification
          "name:n" may be used, and it designates up to the first `n'
          messages (or  last  `n' messages  for  `-n') which  are
          elements  of the user-defined sequence `name'.

               The message specifications "name:next" and "name:prev"
          may also be used, and they designate the next or previous
          message (relative to the current message) which is an ele-
          ment of the user-defined sequence `name'.  The specifica-
          tions "name:first" and "name:last" are equivalent to
          "name:1" and "name:-1", respectively.  The specification
          "name:cur" is not allowed (use just "cur" instead).

               These specifications allow the user to step through a
          sequence with a command like "show name:next".

          Format Strings

          MH format strings now support an if-then-elseif-else clause
          (the `elseif' is new).  This will make format strings with
          multi-case conditions somewhat less complex.

               A new format function `addr' had been added.  This
          function takes an address header name as its argument, and
          returns a rendering of the address contained in that header
          as "user@host" or "host!user".

               Format widths now may be specified as a negative
          number.  This causes the output to be right-justified within
          the format width.

          Other Changes

          Along with a few minor enhancements, some  bugs  were  fixed
          which in general were not user-visible:

          fmtdump  This  new  program  produces   an   pseudo-language
                   representation   of  an  MH  format  file,  vaguely
                   reminiscent  of  assembly  language.   While   this
                   output  format is not explicitly documented, it can
                   still be useful when debugging MH format files.

          refile   Now takes a `-[no]rmmproc' switch.  This  makes  it
                   easier  to  avoid  loops  when your "rmmproc" calls
                   refile.

          slocal   A  problem  with  the  UUCP-style  mailboxes,   the
                   `RPATHS'  configuration  option,  and  the "Return-
                   Path:" header was fixed.

          sortm    Will ensure that no messages  are  lost  if  it  is
                   interrupted.

          whatnow  Will now tell you where it is  leaving  the  draft,
                   when  interrupted  in the initial edit.  Previously
                   the draft was simply unlinked.

          Compilation Options

          LOCKF    This option causes MH to  use  the  lockf()  system
                   call   for   locking  (if  available),  instead  of
                   flock().


          CHANGES FOR MH 6.7.1

          The MH.6.7.1 patch release is a maintenance release, and as
          such, provides few changes from the previous release.  This
          is the current released version of MH as of December 14,
          1990.

          User-Visible Changes

          The major change in this release is to the POP daemon
          (popd).  In MH 6.7, it was changed to be able to read both
          UUCP and MMDF-style mailboxes.  This did not work as
          reported.  The code has now been changed to parse MMDF-style
          mailboxes if you are configuring MH to run with MMDF as your
          message transport system.  Otherwise, UUCP-style mailboxes
          are expected.

               Since there are number of client programs available for
          only the POP2 protocol instead of POP3, popd has been
          updated to support both protocols.  This is a major win.  If
          you are compiling with POP turned on, add the `POP2' option
          to your MH config file, and the POP daemon will respond to
          POP2 or POP3 commands.  If you're using POP, there's no rea-
          son not to include this option; it does not affect the
          existing support for POP3.

          Internal Changes

          Some bugs were fixed which in general were not user-visible:

          context     Errors when writing out sequences  are  detected
                      correctly.

          inc         No  longer  inserts  extra  blank   lines   into
                      messages.

          mh-format   A nil pointer bug  in  the  address  parser  was
                      fixed.

          repl, etc.  The malloc/free problem has been fixed.

          rmf         A spelling error in the `-nointeractive'  switch
                      has been corrected.

          rcvtty      Will not print the message size if not available
                      (i.e., zero).

          send/post   Illegal signatures  (those  containing  unquoted
                      "."s) will be quoted.


          GENERAL CHANGES FOR MH 6.7.0

          The author is pleased to announce that there are very few
          user-visible changes to MH 6.7 from the previous MH 6.6 dis-
          tribution.  The majority of development was in the form of
          bug fixes and slight enhancements.  In addition, this
          release is slightly faster than the previous release.  With
          a few minor exceptions, it is backward-compatible with the
          previous release.  MH 6.7.0 is the current released version
          of MH as of April 12, 1990.

               The changes were made mainly to generalize the source
          code to be compatible with a larger range of systems and
          compilers.  There were many small changes to add declara-
          tions for ANSI C compliance.  The System 5 support has been
          brought up to SYS5 R3, and there is support for Sun OS 4.0.

          User-Visible Changes

          Here a quick summary of the changes that were made which are
          not backward-compatible with the previous release of MH:

          repl   The `-format' and `-noformat' switches have not been
                 functional since MH 5, and have been removed.  Any
                 users who have these switches in their .mh_profile,
                 will have to remove them.

          sortm  Previously, in most cases sortm would fill-in any
                 gaps in the numbering of a folder, by renumbering the
                 messages starting with `1'.  This will no longer
                 occur; for this behavior, use "folder -pack".


          Using Aliases

          A new profile entry `Aliasfile:' has been added.  The ali,
          send, and whom programs will look for this profile entry and
          treat it as they would an argument to `-alias'.  This should
          make it easier for novice MH users to begin using aliases.


          Reading Network News & BBoards

          The UCI BBoards facility can read local BBoards, and if com-
          piled with the `bboards: pop' and `pop: on' options, can
          also read remote BBoards using the Post Office Protocol (POP
          ver. 3).  With this release, MH can instead be compiled to
          read the Network News (i.e., USENET) using the Network News
          Transfer Protocol (NNTP).

               This capability is enabled by compiling MH with the
          `bboards: nntp' and `pop: on' options.  Unfortunately, read-
          ing remote BBoards via the POP and reading the Network News
          via the NNTP are mutually exclusive options.

               To support the NNTP, a new module, uip/pshsbr.c, is
          compiled and loaded into bbc and msh instead of
          uip/popsbr.c.  The default BBoard is changed from "system"
          to "general" for the NNTP.

               When reading BBoards, bbc will first look for local
          BBoards, and then contact the NNTP server to read the Net-
          work News.  The location of the NNTP server should be speci-
          fied with the `nntphost:'  entry in the mtstailor file (see
          the MH Administrator's Guide for details), or may be speci-
          fied on the command line with the `-host' switch.


          Format Strings

          The manual page mh-format (5) has been rewritten to give a
          better explanation of how to write format strings, and how
          they are interpreted by MH.  A line-by-line description of
          the default repl form file (replcomps) is now included in
          that manual page.

          Some new  format  functions  were  added,  and  others  were
          augmented:

          trim        Strips any leading and trailing white-space from
                      the current string value.

          date2local  Will coerce the date to the local timezone.

          date2gmt    Will coerce the date to GMT.

          divide      Divides  the  current  numeric  value   by   its
                      argument.   This  could  be  useful for building
                      scan format strings which  print  large  message
                      sizes in "Kb" or "Mb".

          friendly    If the address  field  cannot  be  parsed,  this
                      function  will  return  the  text of the address
                      header, instead of a null string.

          szone       A  flag  indicating  whether  the  timezone  was
                      explicit in the date string.

          PROGRAM CHANGES

          In addition to the general changes mentioned above, many
          programs have specific new features added, either by new
          switches or by expanded functionality.  Each command's
          manual page gives complete information about its new
          options.  Here is a short summary.

          User Interface Programs

          anno      Accepts a `-nodate' switch which inhibits the date
                    annotation, leaving only the body annotation.

          folder    When invoked with the `-pack' switch and the new
                    `-verbose' switch, folder will give information
                    about the actions taken to renumber the folder.

                    On most systems, folder can now create any
                    non-existing parent folders of a new sub-folder.

          forw      When making digests, forw will put the issue and
                    volume numbers in addition to the digest list
                    name, in the digest trailer.

          inc       Detects NFS write failures, and will not zero your
                    maildrop in that event.

          msh       Supports a variant of the new sortm.

          prompter  Considers a period on a line by itself to signify
                    end-of-file when the `-doteof' switch is speci-
                    fied.

          repl      The `-[no]format' switches have not been used
                    since MH 5 and have been deleted. repl will now
                    find filter files in the MH library area.

          scan      With the `-file msgbox' switch, scan can list a
                    packf'd-format file directly (without using msh).

                    Lists messages in reverse order with the
                    `-reverse' switch.  This should be considered a
                    bug.

          sortm     Now has the options:  `-textfield field',
                    `-notextfield', `-limit days', and `-nolimit'.

                    With these options, sortm can be instructed to
                    sort a folder based on the contents of an arbi-
                    trary header such as "subject".

                    sortm minimizes renaming messages, and will no
                    longer arbitrarily pack folders; for this
                    behavior, use "folder -pack".

          whatnow   Deletes the draft by renaming it with leading
                    comma, instead of unlinking it.

          MH Support Programs

          The  following  support  programs  also  have   changes   or
          enhancements:

          mhl     Will now accept a format string  on  any  component,
                  not just on addresses and dates.

          popd    Will use shadow passwords if compiled with the SHA-
                  DOW option.  It can now also read UUCP-style mail-
                  drops directly.

          rcvtty  If given no arguments, rcvtty will produce a scan
                  listing as specified by a format string or file; a
                  default format string is used if one is not speci-
                  fied.

                  Before the listing is written to the users terminal,
                  the terminal's bell is rung and a newline is output.
                  The `-nobell' and the `-nonewline' options inhibit
                  these functions.

                  rcvtty will obey terminal write notification set by
                  mesg.  With the `-biff' switch, rcvtty will also
                  obey the mail notification status set by biff.

                  On BSD43 systems, as with write, rcvtty will be
                  installed set-group-id to the group "tty".

          slocal  Understands UUCP-style "From " lines and will write
                  output files using this format if appropriate.
                  Before invoking a delivery program, slocal will
                  strip such lines unless compiled with the RPATHS
                  option, in which case it will will convert such
                  lines into "Return-Path:" headers.

                  slocal has a new result code "N", for use in .mail-
                  delivery files.  With this result code, slocal will
                  perform the action only if the message has not been
                  delivered and the previous action succeeded.  This
                  allows for performing an action only if multiple
                  conditions are true.

          DOCUMENTATION

          Several of the older MH papers have been difficult to format
          because they depended on an older version of PhDTeX which
          was not supplied.  These papers have been updated, and some
          TeX library files are supplied in papers/doclib/, so that
          these papers may be generated on any system with TeX.

               Many of the manual pages have been revised to include
          documentation of new command options, and some have been
          expanded to give more detail.  All are now slightly refor-
          matted at installation time to make them more compatible
          with programs like makewhatis.


          MH ADMINISTRATION

          This section describes changes in configuring, compiling and
          installing MH 6.7 and should not be of interest to casual MH
          users.  The READ-ME file has been considerably revised and
          expanded to give more detail about the configuration and
          compilation options which have been included in this
          release.  Some compilation options have been removed, and
          many new options have been added.

               All MH Makefiles have been updated to work around some
          incompatibilities introduced in newer versions of make.  MH
          programs will no longer be installed with the sticky-bit
          turned on.

               Reading this section not a substitute for carefully
          reading the READ-ME file before attempting to compile MH


          Bug Fixes

          Some bugs were fixed which in general were not user-visible:

          address parser  Fixed to allow use of the "AT"  domain,  and
                          some  minor  bugs  were  fixed pertaining to
                          address groups.

          date parser     Improved to accept  more  forms  of  illegal
                          dates.  Military timezones were removed.

          dynamic memory  Many problems with corruption of the dynamic
                          memory pool have been fixed.

          locking         Will open files for write, if  necessary  to
                          enable locking.

          nil pointers    All reported nil pointer problems have  been
                          fixed.

          replcomps       The "In-Reply-To:" header had  quotes  added
                          around the date field to comply with RFC822.

          White Pages

          If MH is compiled with the WP option, send recognizes an
          address between "<<" and ">>" characters such as:

                  To: << rose -org psi >>

          to be a name meaningful to a whitepages service.  In order
          to expand the name, send must be invoked interactively
          (i.e., not from push).  For each name, send will invoke a
          command called fred in a special mode asking to expand the
          name.

               To get a copy of the white pages service, contact
          wpp-manager@psi.com.

          Configuration Options

          Some configuration options have been added or changed:

          cc          To specify an alternate C compiler.

          ccoptions   Defaults to `-O'.

          bboards     May now be defined as "on", "off", "pop", or
                      "nntp".

          bbdelivery  Determines whether the bboard delivery agent and
                      library files should be installed.

          lex         To specify an alternate version of lex.

          mailgroup   If defined, inc will be made set-group-id to
                      this group.

          sharedlib   For SUN40 systems; if "on", makes libmh.a into a
                      shared library.

          slibdir     The directory where the above shared library
                      should be installed.

          sprintf     Set this to "int" if that's what your
                      sprintf (3) library routine returns.

          Compilation Options

          For different configurations, several `-D' options to cc
          have been added or changed:

          BERK        This disables the address and date parsing rou-
                      tines.  If you want to do much with
                      mh-format (5), don't enable this.

          BSD43       Will make rcvtty set-group-id to the group
                      "tty".

          DBM         For sites with a dbm-style password file (such
                      as with Yellow Pages), MH will not read the
                      entire passwd file into a cache.  At one site
                      that runs YP on a large passwd file, using this
                      showed a 6:1 performance improvement.

          NETWORK     This option has been deleted.  See SOCKETS.

          NOIOCTLH    Tells MH not to include the file sys/ioctl.h.
                      Use this if this file is not present on your
                      system.

          NTOHLSWAP   On systems with TCP/IP networking, msh will try
                      to use the ntohl() macro from the file
                      netinet/in.h to byte-swap the binary map files
                      it writes.

          SENDMAILBUG Some versions of sendmail return a 451 (failure)
                      reply code when they don't mean to indicate
                      failure.  This option considers that code to be
                      equivalent to 250 (OK).

          SHADOW      Causes popd to read the file /etc/shadow for
                      encrypted passwords instead of /etc/passwd.  Use
                      this if you have a shadow password file (such as
                      on newer versions of SYSTEM 5).

          SOCKETS     Enable this if you are on a non-BSD system with
                      a socket interface for TCP/IP networking compa-
                      tible with 4.2BSD UNIX.

          SUN40       Use on Suns running Sun OS 4.0 and later.

          SYS5        This option has been updated to refer to SYS5 R3
                      and later systems.

          SYS5DIR     Use this if your system uses "struct dirent"
                      instead of "struct direct".  This should be true
                      for systems based on SYS5 R3 and later.

          TYPESIG     Defines the base type for the signal system
                      call.  This defaults to "int", but should be
                      defined as "void" if appropriate for your sys-
                      tem.

          WP          Enables support for the White Pages service.

          Installation

          MH will now explicitly set the protection mode on every file
          it installs.

               Previously any existing file installed by MH would be
          backed up into the source tree, and then overwritten.  Now,
          a few system-dependent files will not be overwritten, and
          your changes will have to be merged in by hand.  See the
          READ-ME file for more details.

nmh-1.7.1-RC3/docs/COMPLETION-TCSH000644 007761 000024 00000003253 11723762073 016060 0ustar00kenhstaff000000 000000 # This file, to be sourced by tcsh, contains useful command completions for nmh. # [There's lots more that can be done -- folder name completion is just the most # useful ...] # Note that if you use nested folders, the below completions will not find # them. If you are in this boat, you might want to use something like: # # set nmh_mail_dirs = `folder -all -fast -recurse` # # complete anno c%+%"($nmh_mail_dirs)"% # [...] # # The problem with that is that new folders you create won't be available for # completion until you re-source this file. # # Note also that if you use '%'s in your folder names, you'll need to use a # different separator character below. set nmh_mail_dir = $HOME/`mhparam Path` complete anno c%+%D:$nmh_mail_dir% complete burst c%+%D:$nmh_mail_dir% complete comp c%+%D:$nmh_mail_dir% complete dist c%+%D:$nmh_mail_dir% complete flist c%+%D:$nmh_mail_dir% complete folder c%+%D:$nmh_mail_dir% complete forw c%+%D:$nmh_mail_dir% complete inc c%+%D:$nmh_mail_dir% complete mark c%+%D:$nmh_mail_dir% complete mhl c%+%D:$nmh_mail_dir% complete mhn c%+%D:$nmh_mail_dir% complete mhpath c%+%D:$nmh_mail_dir% complete next c%+%D:$nmh_mail_dir% complete packf c%+%D:$nmh_mail_dir% complete pick c%+%D:$nmh_mail_dir% complete prev c%+%D:$nmh_mail_dir% complete rcvstore c%+%D:$nmh_mail_dir% complete refile c%+%D:$nmh_mail_dir% complete repl c%+%D:$nmh_mail_dir% complete rmf c%+%D:$nmh_mail_dir% complete rmm c%+%D:$nmh_mail_dir% complete scan c%+%D:$nmh_mail_dir% complete send c%+%D:$nmh_mail_dir% complete show c%+%D:$nmh_mail_dir% complete sortm c%+%D:$nmh_mail_dir% complete whatnow c%+%D:$nmh_mail_dir% complete whom c%+%D:$nmh_mail_dir% nmh-1.7.1-RC3/docs/COMPLETION-ZSH000644 007761 000024 00000014631 13205305704 015754 0ustar00kenhstaff000000 000000 # # The following several shell functions and `compctl' commands # that will configure the programmable command completion of # the Z Shell (zsh) for the nmh mail system. # # You may need to edit where it says EDIT ME. # These were originally written for MH by Peter Stephenson # The following three functions are best autoloaded. # # mhcomp completes folders (including subfolders). # mhfseq completes sequence names and message numbers. # mhfile completes files in standard nmh locations. # # Completion function for nmh folders. Works with # both + (relative to top) and @ (relative to current). # function mhcomp { local nword args pref char mhpath read -nc nword read -cA args pref=$args[$nword] char=$pref[1] pref=$pref[2,-1] # The $(...) here accounts for most of the time spent in this function. if [[ $char = + ]]; then # mhpath=$(mhpath +) # EDIT ME: use a hard wired value here: it's faster. mhpath=~/Mail elif [[ $char = @ ]]; then mhpath=$(mhpath) fi eval "reply=($mhpath/$pref*(N-/))" # I'm frankly amazed that this next step works, but it does. reply=(${reply#$mhpath/}) } # # Extract nmh message names and numbers for completion. Use of the # correct folder, if it is not the current one, requires that it # should be the previous command line argument. If the previous # argument is `-draftmessage', a hard wired draft folder name is used. # mhfseq() { local folder foldpath words pos nums read -cA words read -cn pos # Look for a folder name. # First try the previous word. if [[ $words[$pos-1] = [@+]* ]]; then folder=$words[$pos-1] # Next look and see if we're looking for a draftmessage elif [[ $words[$pos-1] = -draftmessage ]]; then # EDIT ME: shortcut -- hard-wire draftfolder here # Should really look for a +draftfolder argument. folder=+drafts fi # Else use the current folder ($folder empty) if [[ $folder = +* ]]; then # EDIT ME: use hard-wired path with + for speed. foldpath=~/Mail/$folder[2,-1] else foldpath=$(mhpath $folder) fi # Extract all existing message numbers from the folder. nums=($foldpath/<->(N:t)) # If that worked, look for marked sequences. # EDIT ME # if you never use non-standard sequences, comment out # or delete the next three lines. if (( $#nums )); then nums=($nums $(mark $folder | awk -F: '{print $1}')) fi # EDIT ME: `unseen' is the value of Unseen-Sequence, if it exists; set -A reply next cur prev first last all unseen $nums } # # Find an nmh file; for use with -form arguments and the like. # Use with compctl -K mhfile. # mhfile () { local mhfpath file # EDIT ME # Array containing all the places nmh will look for templates etc. mhfpath=(~/Mail /usr/local/nmh/lib) # Emulate completeinword behaviour as appropriate local wordstr if [[ -o completeinword ]]; then wordstr='$1*$2' else wordstr='$1$2*' fi if [[ $1$2 = */* ]]; then # path given: don't search nmh locations eval "reply=($wordstr(.N))" else # no path: only search nmh locations. eval "reply=(\$mhfpath/$wordstr(.N:t))" fi } # Note: you must type the initial + or @ of a folder name to get # completion, even in places where only folder names are allowed. # Abbreviations for options are not recognised. Hit tab to complete # the option name first. compctl -K mhfseq -x 's[+][@]' -K mhcomp -S / -q - \ 's[-]' -k "(all noall fast nofast header noheader help list nolist \ pack nopack pop push recurse norecurse total nototal)" -- folder folders compctl -K mhfseq -x 's[+][@]' -K mhcomp -S / -q - \ 's[-]' -k "(sequence all noall recurse norecurse showzero noshowzero \ alpha noalpha fast nofast help)" -- flist flists compctl -K mhfseq -x 's[+][@],c[-1,-draftfolder] s[+][@]' \ -K mhcomp -S / -q - 'c[-1,-draftmessage]' -K mhfseq - \ 'C[-1,-(editor|whatnowproc)]' -c - \ 's[-]' -k "(draftfolder draftmessage nodraftfolder editor noedit \ file form use nouse whatnowproc nowhatnowproc help)" - \ 'c[-1,-form]' -K mhfile -- comp compctl -K mhfseq -x 's[+][@]' \ -K mhcomp -S / -q - 'c[-1,-draftmessage]' -K mhfseq -\ 's[-]' -k "(annotate noannotate cc nocc draftfolder nodraftfolder \ draftmessage editor noedit fcc filter form group nogroup inplace noinplace query noquery width whatnowproc nowhatnowproc help)" - 'c[-1,(cc|nocc)]' \ -k "(all to cc me)" - 'C[-1,-(filter|form)]' -K mhfile - \ 'C[-1,-(editor|whatnowproc)]' -c -- repl compctl -K mhfseq -x 's[+][@]' -K mhcomp -S / -q - \ 's[-]' -k "(audit noaudit changecur nochangecur form format \ file silent nosilent truncate notruncate width help)" - \ 'C[-1,-(audit|form)]' -K mhfile - 'c[-1,-file]' -f + -- inc compctl -K mhfseq -x 's[+][@]' -K mhcomp -S / -q - \ 's[-]' -k "(sequence add delete list public nopublic zero nozero help)" -- \ mark compctl -K mhfseq -x 's[+][@]' \ -K mhcomp -S / -q - 'c[-1,-file]' -f - 'c[-1,-rmmprov]' -c - \ 's[-]' -k "(draft link nolink preserve nopreserve src file \ rmmproc normmproc help)" -- refile compctl -K mhfseq -x 's[+][@]' -K mhcomp -S / -q - \ 's[-]' -k "(clear noclear form format header noheader reverse noreverse \ file help width)" - 'c[-1,-file]' -f - 'c[-1,-form]' -K mhfile -- scan compctl -K mhfseq -x 's[+][@]' -K mhcomp -S / -q - \ 's[-]' -k "(draft form moreproc nomoreproc header noheader \ showproc noshowproc length width help)" - 'C[-1,-(show|more)proc]' -c - \ 'c[-1,-file]' -f - 'c[-1,-form]' -K mhfile - \ 'c[-1,-length]' -s '$LINES' - 'c[-1,-width]' -s '$COLUMNS' -- show next prev compctl -K mhfseq -x 's[+][@]' -K mhcomp -S / -q - 's[-]' \ -k "(help)" -- rmm compctl -K mhfseq -x 's[+][@]' -K mhcomp -S / -q - \ 's[-]' -k "(after before cc date datefield from help list nolist \ public nopublic search sequence subject to zero nozero not or and \ lbrace rbrace)" -- pick compctl -K mhfseq -x 's[+][@]' -K mhcomp -S / -q - 's[-]' \ -k "(alias check draft draftfolder draftmessage help nocheck \ nodraftfolder)" -- whom 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 \ rfc934mode norfc934mode verbose noverbose help)" - \ 'c[-1,-file]' -f - 'c[-1,-form]' -K mhfile - \ 'C[-1,-[rw]cache]' -k '(public private never ask)' -- mhn compctl -K mhfseq -x 's[+][@]' -K mhcomp -S / -q - 's[-]' -k '(help)' -- mhpath nmh-1.7.1-RC3/docs/contrib/000755 007761 000024 00000000000 13243043704 015352 5ustar00kenhstaff000000 000000 nmh-1.7.1-RC3/docs/DIFFERENCES000644 007761 000024 00000025060 11732520431 015353 0ustar00kenhstaff000000 000000 [NOTE: This file is out-of-date. Updating it every time new features are added to nmh forevermore is a pain. Perhaps we should limit it to documentation of _incompatibilities_ with MH (which should be rare).] The following are the differences between nmh and MH-6.8.3. UCI has since released MH-6.8.4. Most of the new features it adds have also been added to nmh, but those differences are not listed here. There are a few new features in MH-6.8.4 that are missing from nmh, but they are primarily undocumented in MH-6.8.4 (and no one has ever asked me for them). GENERAL ------- *) nmh has been converted to autoconf (configure) and should be more portable and easier to install than MH. In particular, nmh will now compile on Linux. *) All of MH's Makefiles have been rewritten for nmh. You can now use GNU make without any problems. Also, if your make supports the VPATH variable (such as GNU make), you can now compile in a different directory from the one containing the source code. *) The source code for nmh has been substantially cleaned up. It now requires an ANSI C compiler (gcc is fine) to compile. *) A new option `-version' has been added to all the commands. *) The POP server (popd) has been removed from the distribution. RPOP on the client side is not currently supported. *) The support for MH-style bulletin boards has been removed (NNTP makes this obsolete anyway). *) Currently nmh doesn't support using shared libraries for libmh. This may return in the future, but is not a high priority, since the nmh commands are not that large, and disk space gets cheaper every day. *) Almost all of the commands in nmh have been modified to accept an arbitrary number of command line arguments (most MH commands will not accept more than 1000 arguments on the command line). *) nmh should be more secure than MH. Hundreds of buffer overflow problems have been fixed in the source code. Of course, I still don't make any guarantees. DOCUMENTATION ------------- *) Many of the man pages have been cleaned up or clarified. *) The mhook man page has been split into separate man pages for rcvtty, rcvdist, and rcvpack. *) Added new man page `mh-draft' which discusses the nmh draft folder facility. *) The various `procs' (rmmproc, moreproc, showmimeproc, etc...) are now documented in the "mh-profile" man page. Many of these were previously undocumented. FORMATTING ---------- *) Added a new formatting string escape %(decode) to decode and display RFC-2047 encoded header fields. SEQUENCES --------- *) The is no longer a limitation on the length of lines in the file containing your public sequences (.mh_sequences). That should be the end of the error message ".mh_sequences is poorly formatted". ANNO ---- *) The switch -inplace is now on by default. CONFLICT -------- *) Conflict now works on systems that define more than 100 groups. DIST ---- *) The switch -inplace is now on by default. FLIST ----- *) A new command `flist' has been added to nmh, that will list the folders that contain messages in a given sequence (such as the unseen sequence). This was a much needed command in the MH suite of programs. FOLDER ------ *) `folder -all' now dynamically allocates space for folder names and can handle more than 300 folders. *) `folder' now uses the standard Unix trick of looking at the number of links to a directory entry, in order to avoid doing a stat(2) call on messages in folders with no subfolders. This greatly increases the speed of `folder -all -recurse' on large mail setups. *) The switches `-header' and `-total' are more orthogonal. The command `folder -all -noheader -nototal' now does the right thing. FORW ---- *) The switch -inplace is now on by default. *) Added switches `-dashstuffing' and `-nodashstuffing', to determine whether forwarded messages are RFC934 quotes (dashstuffed). (This corresponds to the undocumented switch "nodashmunging" in MH). INC --- *) If compiled with RPATHS, a Delivery-Date header is now added to all messages incorporated with `inc'. *) Using the new format string escape %(decode), the scan lines for `inc' will correctly decode RFC-2047 encoded headers. MARK ---- *) If neither of the switches -public/-nopublic are specified, then existing sequences will retain their current public/private status, instead of being changed to public. *) The command "mark -list -sequence foo" will now indicate if the sequence "foo" is a private sequence. MHBUILD ------- *) The functionality in `mhn' to create MIME messages, has been cleaned up substantially, and moved to separate command `mhbuild'. *) If given a file argument of "-", mhbuild will now accept the MIME composition file on the standard input, and output the new MIME message to the standard output. This makes it much easier to use this functionality in shell scripts. *) The switch -norfc934mode is now the default. MHL --- *) There is a new variable "decode" which instructs `mhl' to decode a component as a RFC-2047 encoded header field. MHLIST ------ *) The functionality of `mhn -list' has been moved to the new command `mhlist'. MHN --- *) mhn is now obsolete. It has been split into the commands mhbuild, mhlist, mhshow, mhstore, and viamail. mhn still exists for backward compatibility, but the new commands should be preferred. *) Changed the profile entry automhnproc to automimeproc (which has slightly different semantics). MHPATH ------ *) `mhpath all' will no longer abort if the folder has more than 998 messages. MHSHOW ------ *) The functionality of `mhn -show' has been moved to the new command `mhshow'. *) mhshow now correctly treats unknown subtypes of text as text/plain, as specified by RFC-2046. *) mhshow now correctly treats unknown subtypes of multipart as multipart/mixed, as specified by RFC-2046. *) You can now override the default method by which mhshow handles subtypes of multipart that are known internally (mixed, alternate, etc...). Previously the behavior on these types could not be changed. MHSTORE ------- *) The functionality of `mhn -store' has been moved to the new command `mhstore'. *) mhstore will now correctly identify a formatting string of "-" and send the content to stdout. PACKF ----- *) When packing a folder, the default format is now `mbox' format, rather than `mmdf' format. The options -mbox and -mmdf have been added to `packf' so you can choose the desired format. PACKMBOX -------- *) The script packmbox has been removed from the nmh distribution, since its functionality has been added to the command packf. PICK ---- *) If neither of the switches -public/-nopublic are specified, then existing sequences will retain their current public/private status, instead of being changed to public. RCVPACK ------- *) The default format for `rcvpack' is now `mbox' format, rather than `mmdf' format. The options -mbox and -mmdf have been added to `rcvpack' so you can choose the desired format. *) Rcvpack no longer adds the field "Delivery-Date", as that is added by `slocal'. RCVSTORE -------- *) Added new switches -unseen/-nounseen to control whether new messages are added to the Unseen-Sequence. RCVTTY ------ *) The option `-width' has been added. REFILE ------ *) If an conflict occurs when using the `-preserve' switch, then refile will search for and use the next available message number above the one you wish to preserve, rather than aborting with an error. *) Added new options `-unlink' and `-nounlink' which specify that that messages "removed" from the source folder should just be unlinked, rather than moved to name with prefix. REPL ---- *) Added new options `-format' and `-noformat'. The switch `-format' will filter the message to which you are replying with a standard message filter "mhl.reply" which is included in the distribution. The switch `-noformat' will negate `-format' and `-filter', so that the message to which you are replying is not included in the draft. *) Added new options `-group' and `-nogroup'. These switches direct repl as to whether or not this is a group reply. A group reply uses a different forms (components) file (default is replgroupcomps). *) The standard forms files "replcomps" and "replgroupcomps" now have support for the "Mail-Reply-To:" and "Mail-Followup-To:" header fields. *) The switch -inplace is now on by default. RMM --- *) Added new options `-unlink' and `-nounlink' which specify that that "removed" messages should just be unlinked, rather than moved to name with prefix. SCAN ---- *) Using the new format string escape %(decode), the scan lines created by `scan' will correctly decode RFC-2047 encoded headers. SHOW/NEXT/PREV -------------- *) Added new options `-checkmime' and `-nocheckmime' which allow you to enable and disable the test for MIME messages. *) The "mhnproc" profile entry has been changed to "showmimeproc". *) Added `-showmimeproc' switch to specify the showmimeproc at the command line. *) The default "showproc" has been changed to `mhl'. *) The default "showmimeproc" is now `mhshow'. *) `show' is better at handling alternate character sets. It knows that US-ASCII is a subset of any ISO-8859-X character set. SLOCAL ------ *) Added new action `folder' or `+' to slocal, which adds new message to a nmh folder. Currently, this is handled by piping the new message to rcvstore, although this may change in the future. *) The action `mbox' now delivers to a file in mbox format. Previously it delivered to a file in mmdf format. *) Added new action `mmdf' to deliver to a file in mmdf format. *) Added new options -[no]suppressdup to slocal to check for duplicate messages. The code for suppression of duplicate messages (MH config was MSGID) is now always built into slocal. *) Improved the debugging of slocal ".maildelivery" files. It will now warn when an entry in this file is skipped because there are not enough fields. Also the debugging output of slocal has been cleaned up, so that it is much easier to read. *) Slocal now adds the Delivery-Date header to all delivered messages. Previously it only added them to messages delivered to a file. VIAMAIL ------- *) The functionality of this new command, was formerly part of `mhn' as the (undocumented) option `mhn -viamail'. WHATNOW ------- *) Added new action "mime" to whatnow, which causes whatnow to call program specified by "buildmimeproc" profile entry, to process MIME composition files (default is mhbuild). *) Added new action "delete" to whatnow, which deletes draft file and exits. nmh-1.7.1-RC3/docs/FAQ000644 007761 000024 00000512550 13205305704 014253 0ustar00kenhstaff000000 000000 Newsgroups: comp.mail.mh,comp.answers,news.answers Subject: MH Frequently Asked Questions (FAQ) with Answers Keywords: FAQ,mh,mail,question,answer,pop,slocal,letter,signature, draft,message,folder,xmh,olmh,vmail,vmailtool,comp,repl, forw,scan,SMTP,bind,MH-E,MIME,plum,exmh,nmh Summary: This document answers Frequently Asked Questions about MH, a sophisticated mail interface. It should be read by new MH users and comp.mail.mh readers and before posting to this group. Followup-To: poster Approved: news-answers-request@MIT.Edu Reply-To: Bill Wohler From: Bill Wohler Organization: Newt Software, Menlo Park, California, USA Archive-name: mail/mh-faq/part1 Last-modified: $Date: 2012-11-23 21:47:03 -0800 (Fri, 23 Nov 2012) $ Version: $Revision: 11334 $ Posting-Frequency: monthly This is a living list of frequently asked questions on the mailer user interface, Mail Handler, or MH. The point of this is to circulate existing information, and avoid rehashing old answers. Better to build on top than start again. Please read this document before ever posting to this newsgroup. This article is posted monthly. If it has already expired and you're not reading this, you can hope that you saved the instructions to retrieve the FAQ (see "Where can I get MH") so that you can get a copy through other means. Please do not post an answer when someone posts a frequently asked question; rather, email the relevant section of the FAQ to eliminate unnecessary traffic in this newsgroup. This list depends on your comments, additions and fixes: please send them to Bill Wohler . Copyright 1991-1999, 2001, 2004-2007, 2012 Bill Wohler Permission to use, copy, distribute, and translate this document for any non-commercial purpose is hereby granted, provided that this copyright notice appears in all copies. Commercial distributions require prior written consent. This article is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ---------------------------------------------------------------------- Subject: Table of Contents From: Bill Wohler Date: Sat, 3 Mar 2001 11:29:16 -0800 Legend: + new, - deleted, ! changed __________________ 01.00 Introduction 01.01 Why should I use MH? !01.02 What is the current version/status of MH? !01.03 Where can I get MH? 01.04 What references exist for MH? 01.05 What other MH software is available? 01.06 How can I print a MH manual? 01.07 How should I report bugs? 01.08 How can I convert from my mailer to MH? 01.09 What is the copyright status of nmh? _________________ 02.00 Building MH 02.01 What machines does MH run on? 02.02 How do I build MH? 02.03 What options should I use? 02.04 What do I need to do to use POP? 02.05 Does MH support IMAP? 02.06 Why does "mailgroup mail" only affect inc and not slocal? 02.07 How can I build MH on Solaris 2? 02.08 How can I build MH on Linux? 02.09 How can I build MH on IRIX? 02.10 How can I get MH to interpret the Content-Length field? 02.11 How do I build MH on HP-UX? 02.12 Can I prevent adding the local hostname to addresses behind firewalls? 02.13 Is there a patch to fix this or that? 02.14 How can I build MH on OS/2? 02.15 Do any POP/IMAP servers handle MH format? !02.16 How can I build MH on Windows? !02.17 How can I build MH on a Mac? ________________________ 03.00 Scanning & Reading 03.01 What do I do if scan shows the wrong date? 03.02 How would one go about reading Usenet with MH? 03.03 How can I search through multiple folders? 03.04 Why don't MH format commands such as %(friendly) work? 03.05 Why doesn't "show" display all of a MIME message? 03.06 Can I get show not to run "less" so much on MIME messages? 03.07 Why do I get "mhn: don't know how to display content"? 03.08 How can I automatically delete MH backup files? 03.09 Fixing "cannot fopen and lock /var/spool/mail/(user)" 03.10 Can I read my mail with a Web browser? 03.11 How can I run inc automatically with POP? 03.12 Why does inc hang (on Sun)? 03.13 How can I get POP to work? 03.14 How do I persuade mhshow (mhn) not to bring up a new window? 03.15 How do I turn off of all the mhshow (mhn) prompts? 03.16 Why is inc splitting messages improperly? 03.17 Can MH thread messages? 03.18 How can I avoid reading the HTML version of the message? 03.19 How do I view or save attachments? 03.20 How do I view HTML attachments with Netscape? 03.21 Fixing folders: unable to allocate storage for msgstats 03.22 How do I recursively list message attachments? 03.23 Why do folder and flist overlook some of my sub-folders? ____________ 04.00 Filing 04.01 Can I append MH messages to a Unix mailbox format file? 04.02 Can I append MH messages to a GNU Emacs rmail BABYL-format file? 04.03 Why do I get ".../.mh_sequences is poorly formatted?" 04.04 How can you save News articles into an MH folder? 04.05 Are there any good tools to archive MH messages? 04.06 How can I remove duplicate messages? 04.07 How can I remove holes in numbering? __________________________ 05.00 Composing & Replying 05.01 Why does repl add a "Re:" to a message that already has one? 05.02 How do I include messages in repl with or without ">"? 05.03 How can I eliminate duplicate copies of letters to myself? 05.04 How can I include my signature? 05.05 How do I call my editor with arguments? 05.06 How can I digestify messages in a folder for mail to another user? 05.07 How can I change my return address? 05.08 How can I change my From header? 05.09 How can I save a copy of all messages I send? 05.10 Can the folder in Fcc: be dynamically specified? 05.11 Can I post secure/encryped mail? 05.12 How can I send multi-media (MIME) attachments? 05.13 What's the best way to send mail to a long list of people? 05.14 What is the Dcc header? 05.15 How can I make sense of the replcomps file? 05.16 How can I convert quoted-printable to 8bit in quoted text in replies? 05.17 Can I have aliases include aliases? 05.18 Why doesn't mhmail understand aliases? 05.19 How do I send blind carbon copies? 05.20 When I forward a message, can I use its Subject? 05.21 Why is the timezone field in my 'Date:' field wrong? 05.22 Can I automate the comp -editor mhn process? 05.23 How can I remove those "=20" characters when forwarding? 05.24 Can I use mh-format substitution with forw? 05.25 How can I keep repl from breaking long lines? 05.26 How do I fix a bogus In-Reply-To or missing References field? _____________ 06.00 Posting 06.01 What to do with "Problems with edit - draft removed". 06.02 Can I run my message through a program (e.g., ispell) before sending? 06.03 What to do with "bad address 'xxx' - no at-sign after local-part". !06.04 Fixing "post: problem initializing server; [BHST] no servers available" 06.05 Fixing "post: problem initializing server; [RPLY] 503 Sender already specified" 06.06 Fixing "post: unexpected response; [BHST] no socket opened" 06.07 How do I fix the "X-Authentication-Warning" header? 06.08 Fixing "post: unexpected response; [RPLY] 503 Need MAIL before RCPT" !06.09 Fixing "post: problem initializing server; [BHST] premature end-of-file on socket" 06.10 Fixing "Sender didn't use the HELO protocol" 06.11 Fixing "post: problem initializing server; [RPLY] 553 Local configuration error, hostname not recognized as local" __________________ 07.00 Mail Filters 07.01 What mail filters are available? 07.02 Why slocal writes messages to system mailbox that from(1) can't read. 07.03 Where can I read about slocal and the format of .maildelivery? 07.04 How do I debug my .maildelivery file? 07.05 Why isn't slocal working? 07.06 Are there any good biff applications for MH? 07.07 How do I read new messages filed by procmail? __________ 08.00 MH-E 08.01 I have a question about MH-E _________ 09.00 Xmh 09.01 How can I get xmh to use Emacs as the editor? 09.02 Does xmh support subfolders? 09.03 How do I precede included messages with ">" when replying in xmh? ________ Appendix Glossary & Acknowledgments Switching xmh's editor babyl2mh.pl inco - babyl to MH converter t2h - add hyperlinks to message viewed srvrsmtp.c patch IRIX config file HP-UX 10.20 config file Removing duplicate messages (Bourne) Removing duplicate messages (Perl) Removing duplicate messages (Perl) ------------------------------ Subject: Viewing This Article From: Bill Wohler Date: Mon, 27 Nov 1995 14:44:19 -0800 To skip to a particular question with Subject or number xx, use "/^S.*xx" with most pagers. In GNU Emacs type "M-C-s ^S.*xx", (or C-r to search backwards), followed by ESC to end the search. To skip to new or changed questions, use "/^S.*[!+]" with most pagers and "M-C-s ^S.*[!+]" in GNU Emacs. This article is in digest format. nn may have already broken this message into separate articles; if not, then type "G %". In rn, use ^G to skip sections. This article is treated as an outline when edited by GNU Emacs. Run "M-x describe-mode" to see available outline-mode commands. Useful commands are "M-x hide-body", "C-c C-s" (show-subtree) and "M-x show-all" Check out the Usenet Hypertext FAQ Archive (see "What references exist for nn?"). Files available by ftp, man pages, and other Web pages, as well as cross-references like the one in this paragraph are just a click away. A "Date" field whose time is 00:00:00 is approximate. The month and year in these fields represent the time they were added to the FAQ, rather than when they were contributed by the author, as is the case since November, 1995. If you should need the Internet address, use nslookup or dig if you have them, or send mail to with "help" for a Subject. References to $MHLIB refer to the directory that contains MH support files and routines. This directory is usually /usr/lib/mh or /usr/local/lib/mh (or /usr/local/nmh/lib or /etc/nmh for nmh). Do not use $MHLIB literally; use the real, absolute path to your MH library directory. There are slight differences between the original MH and nmh. In the text, the nmh command or filename is preferred, and the MH equivalent is placed in parenthesis. For example, the MH configuration is in $MHLIB/mts.conf (mtstailor); mhshow (mhn -show) is used to view attachments. Note that due to bottom feeding email address harvesting spam scum, mailto links have been removed and @s in addresses have been replaced by "at." ------------------------------ Subject: 01.00 ***** Introduction ***** From: Bill Wohler Date: Fri, 1 Mar 1991 13:03:15 -0800 ------------------------------ Subject: 01.01 Why should I use MH? From: Jerry Peek Date: Fri, 1 Mar 1991 13:03:15 -0800 The MH message handling system is a set of electronic mail programs in the public domain. If your computer runs Unix, it can probably run MH. The big difference between MH and most other "mail user agents" is that you can use MH from a Unix shell prompt. In MH, each command is a separate program, and the shell is used as an interpreter. So, all the power of Unix shells (pipes, redirection, history, aliases, and so on) works with MH--you don't have to learn a new interface. Other mail agents have their own command interpreter for their individual mail commands (although the mush mail agent simulates a Unix shell). Because MH commands aren't part of a monolithic mail system, you can use them at any time; you don't have to start or quit the mail agent. Because you use them from a shell prompt, you can use all the power of the shell. If your shell has time-saving aliases or functions (and most do), you'll be able to use them with MH, of course. And because MH isn't a monolithic mail agent, you can use MH commands in Unix shell scripts, or call them from programs in high-level languages like C. Unlike most mail agents, MH keeps each message in a separate file. The filename is the message number. To rearrange the messages, MH just changes the filenames. MH can use standard Unix file system operations such as removing, copying and linking messages. The message files are grouped into one or more folders, which are actually Unix directories. MH is free, powerful, flexible--and the basics are easy to learn. ------------------------------ Subject: !01.02 What is the current version/status of MH. From: Bill Wohler Date: Sun, 23 Sep 2007 23:51:52 -0700 The current official version of MH is 6.8.3, although a beta of 6.8.4 is available. This version includes MIME, a multi-media MH package that implements the new IETF work on Multi-media 822 (MIME). This allows you to include things like audio, graphics, and the like, in your mail messages. --Marshall Rose MH now works with Kerberos as well. In addition, a new program called mhparam extracts arguments from .mh_profile which is useful in shell scripts. Please see the file CHANGES in the distribution for more details. Due to the languishing state of MH, Richard Coleman created another version of MH called nmh based upon MH 6.8.3. He added GNU autoconf to ease installation considerably and fixed several bugs and inconsistencies. Doug Morris picked up the torch in 2002 and moved development to Savannah where Jon Steinhart joined him as a project maintainer. See http://www.nongnu.org/nmh/. The stable version of nmh is 1.5. The file docs/DIFFERENCES in the nmh distribution contains a list of differences between nmh and MH. GNU mailutils (version 2.99.97) is a collection of mail-related utilities. At the core of mailutils is libmailbox, a library which provides access to various forms of mailbox files (including remote mailboxes via popular protocols and MH). See http://www.gnu.org/software/mailutils/. ------------------------------ Subject: !01.03 Where can I get MH? From: Bill Wohler Date: Fri, 23 Nov 2012 12:19:17 -0800 MH comes standard with many systems. nmh (or mailutils) can be installed on Debian-based systems with: aptitude install nmh On Red Hat-based systems, use: yum install nmh nmh source code releases are available at: http://download.savannah.nongnu.org/releases/nmh/ GNU mailutils source code releases are available at: http://ftp.gnu.org/gnu/mailutils/mailutils-latest.tar.gz (or .bz2 or .lzma or .xz) ------------------------------ Subject: 01.04 What references exist for MH? From: Bill Wohler Date: Sun, 23 Sep 2007 23:51:41 -0700 The Web: http://rand-mh.sourceforge.net/ http://www.nongnu.org/nmh/ http://www.gnu.org/software/mailutils/ http://mh-e.sourceforge.net/ Books: MH & xmh: E-mail for Users & Programmers. Third edition. Jerry Peek, with Bill Wohler and Brent Welch. ISBN 1-56592-093-7. 738 pages. O'Reilly & Associates, Inc. Out of print as of August, 1996. References to "the MH book" in this document refer to the third edition (plus updates) of this book online at http://rand-mh.sourceforge.net/book/. Section numbers for the second edition may appear in parentheses. There is another book that contains a number of examples of advanced mail handing using MH as the example message handler. It's also quite a good reference on email in general. The Internet Message. Marshall T. Rose ISBN 0-13-092941-7. 396 pages. P T R Prentice Hall Papers: MHN Tutorial by Jerry Sweet ftp://ftp.ics.uci.edu/pub/mh/contrib/multimedia/mhn-tutorial.ps.Z 141k ftp://ftp.ics.uci.edu/pub/mh/contrib/multimedia/mhn-tutorial.tex.Z 48k Usenet: comp.mail.mh gmane.mail.exmh.devel gmane.mail.exmh.user gmane.mail.mh-e.announce gmane.mail.mh-e.devel gmane.mail.mh-e.user gmane.mail.nmh.devel Mailing lists: There are three mailing lists for nmh: nmh-announce, nmh-workers, and nmh-commits. See: http://savannah.nongnu.org/mail/?group=nmh The page for each list contains a link to the archives. MH-users archives: Current archives can be found at: http://lists.nongnu.org/archive/html/nmh-workers/ Older archive can be found in the mh-users and mh-workers archives at: http://sourceforge.net/project/showfiles.php?group_id=143658&package_id=188462 There are directions in the release notes. Basically, you can use the individual commands "inc -file" to get the messages into a folder, and then "scan", "pick", "show", and so on (or your favorite commands in xmh, MH-E, etc.). --Jerry Peek This document: http://www.newt.com/faq/mh.html http://faqs.cs.uu.nl/na-dir/mail/mh-faq/part1.html MH-E documentation: GNU Emacs 19.29 comes with a version of MH-E that includes online (Texinfo) documentation. Try "C-h i m mh-e RET". It is also available in HTML and PDF formats at http://mh-e.sourceforge.net/manual/. See also "What other MH software is available?" to see where you can get the latest version of MH-E which includes the documentation sources. exmh: The FAQ is available at http://www.beedub.com/exmh/exmh-faq.html. The online exmh sections from the MH book can be found at http://rand-mh.sourceforge.net/book/index.html#chTourexmh Signature and Finger FAQ: http://www.faqs.org/faqs/usenet/signature-faq/ ------------------------------ Subject: 01.05 What other MH software is available? From: Stephen Gildea , Bill Wohler Date: Thu, 19 May 2005 21:20:57 -0700 MH-E is the Emacs interface to the MH mail system. It offers all the functionality of MH, the visual orientation and simplicity of use of a GUI, and full integration with Emacs and XEmacs, including thorough configuration and online help. MH-E allows one to read and process mail very quickly: many commands are single characters; completion and smart defaults are used for folder names and aliases. With MH-E you compose outgoing messages in Emacs. This is a big plus for Emacs users, but even non-Emacs users have been known to use MH-E after only learning the most basic cursor motion commands. Additional features include: * attractive text rendering with font lock * composition and display of MIME body parts * display of images and HTML within the Emacs frame * folder browsing with speedbar * threading * ticking messages * lightning-fast full-text indexed searches of all of your email * virtual folders to view ticked and unseen messages, search results * multiple personalities * signing and encrypting * spam filter interaction * XFace, Face, X-Image-URL header field support with picons The GNU Emacs distribution includes MH-E. MH-E is maintained at SourceForge: http://mh-e.sourceforge.net/ From: Chris Menzel Date: Sat, 15 Dec 2001 10:02:38 -0600 The terminal-oriented, fast, and powerful mutt mail client not only supports the MH mail format but also supports .mh_sequences files, providing a robust interface to MH. It is also amazingly configurable and is very adept at handling MIME attachments and HTML mail. Unlike MH, the displayed message numbers do not necessarily correspond to the message filenames. This makes threading and sorting lightning fast but slower to display very large folders. http://www.mutt.org/ From: Brent Welch Date: Tue, 20 Mar 2001 22:42:15 -0800 EXMH is a user interface for the MH mail system written in TCL/TK. Exmh has MIME support, color feedback in the scan listing, a folder display with one label per folder, clever scan caching, facesaver bitmap display; background inc, various inc styles, searching over folder listing and message body, a dialog-box interface to MH pick, a simple built-in emacs-like editor, interfaces to other editors, user preferences, user hacking support. For more info or to obtain exmh, see: http://exmh.sourceforge.net/ From: "Eric D. Friedman" Date: Tue, 9 Feb 1999 22:52:44 -0800 Mhtake is a perl script that lets you add people to your mail aliases file by typing mhtake [message #]. http://orion.oac.uci.edu/~friedman/mhtake.txt From: Steinar Bang Date: Fri, 26 Jan 1996 13:51:08 +0100 Mew (an Emacs interface to MH that has MIME and PGP capabilities) is found at: ftp://ftp.aist-nara.ac.jp/pub/elisp/Mew/mew-current.tar.gz [MH-E has had these capabilities since version 7.0 so mew is obsolete if you use MH-E. --Ed] From: James Perkins Date: Fri, 1 Jan 1993 00:00:00 -0800 Vmh is designed for people using the bulletin-board features of MH, where mail is stored in packed (single-file) folders. As a result, use of this program cannot be mixed with the use of normal MH commands. Vmh is a part of the official MH distribution. From: James Perkins Date: Fri, 1 Jan 1993 00:00:00 -0800 Xmh is a X11 mouse-based MH browsing tool. It is very powerful and feature-filled and thus comes with a moderate learning curve. Its dependence on the X11 environment makes it very reconfigurable, but only by people well-versed in X applications programming. Its message reply built-in-editor interface is not always popular among those used to having MH bring up the editor of their choice. Date: Fri, 1 Jan 1993 00:00:00 -0800 xmh is part of the standard X Window System distribution from the X Consortium. Ultrix also ships dxmail which is similar. ftp://cs.utk.edu/pub/xmh.shar.Z 162k From: Harald Tveit Alvestrand Date: Fri, 1 Jan 1993 00:00:00 -0800 Here's a version of xmh that includes MIME. ftp://aun.uninett.no/pub/mail/mixmh/mixmh-0.3.tar.Z 232k From: Nathaniel Borenstein Date: Sun, 26 Nov 1995 19:04:51 -0800 Metamail is a package that can be used to convert virtually ANY mail-reading program on Unix into a multi-media mail-reading program. It is an extremely generic implementation of MIME (Multipurpose Internet Mail Extensions), the proposed standard for multi-media mail formats on the Internet. The implementation is extremely flexible and extensible, using a "mailcap" file mechanism for adding support for new data formats when sent through the mail. At a heterogeneous site where many mail readers are in use, the mailcap mechanism can be used to extend them all to support new types of multi-media mail by a single addition to a mailcap file. The metamail distribution comes complete with a small patch for each of over a dozen popular mail reading programs, including Berkeley mail, mh, Elm, Xmh, Xmail, Mailtool, Emacs Rmail, Emacs VM, Andrew, and others. Note that the MH patches are now integrated into MH 6.8. ftp://ftp.bellcore.com/pub/nsb/mm2.7.tar.Z From: Tom Christiansen Date: Tue, 9 Feb 1999 22:55:24 -0800 Plum is a highly configurable and extensible screen-oriented front-end for processing MH mail on ASCII terminals. Unlike MH-E, the extension language used in plum is perl, not LISP. Plum offers many of the advantages of xmh, but lacks several of xmh's disadvantages. The look&feel derives more from vi than from emacs. Key bindings and functions may be changed on the fly to suit the user's preference. It offers filename and word completion on folder, variables, and command names. Until it is included in the standard distribution (under miscellany), you can find a copy on: http://www.cpan.org/authors/Tom_Christiansen/scripts/plum.gz 29k or mail requests to Tom From: Jerry Sweet Date: Tue, 1 Nov 1994 00:00:00 -0800 Mhunify is a set of perl scripts and templates that provides shell-level MH functionality with USENET news. Since MH supports MIME, MIME-format news articles just work. I've found that being able to handle news in the same way that I handle email is very useful, although there are some tradeoffs. Mhunify also treats MH folders just like news groups. If you subscribe to several mailing lists, and your email is automatically delivered to separate folders, say, via procmail or via MMDF's .maildelivery, the mhunify package lets you progress automatically through your folders just as you would news groups. ftp://ftp.ics.uci.edu/pub/mh/contrib/multimedia/mhunify.shar.gz From: Dale Carstensen Date: Tue, 1 Nov 1994 00:00:00 -0800 olmh is a demo for OLIT (Open Look Interface Toolkit, the Open Look wrapper to Xt) in Sun's Open Windows 3 that does handle 3rd and subsequent levels of nesting of folders. Obtain the Open Windows 3 distribution CD/ROM from Sun (SPARC only). To do this, call 1-800-USA-4SUN and send tone "2" for telemarketing after it answers. The 4.1.2 CD/ROM may also have Open Windows 3. The list price for the 4.1.2 CD/ROM is $200. From: James Perkins Date: Sun, 1 May 1994 00:00:00 -0800 Vmail is a curses-based, vi-like message browser which calls on MH programs to manipulate mail. It can be used on almost any terminal. It organizes mail folders into index pages, from which a message can be selected to be shown, replied-to, forwarded, refiled, deleted, and so on. The vi-like interface and command keystrokes are comfortable to less-experienced Unix users, and it is a small, compact program, unlike the MH-E Emacs package. This version of vmail has been bugfixed and enhanced from the original vmail published on the net in 1987 by J. Zobel. ftp://ftp.uu.net/comp.sources.unix/volume12/vmail/part0*.Z 46k ftp://ftp.ucs.ubc.ca/pub/mh/vmail.[1-3]of3.Z 58k Or mail requests to James. From: James Perkins Date: Sun, 1 May 1994 00:00:00 -0800 vmailtool may be for you if you have a Sun workstation. It is a button gadget panel for the above-mentioned vmail program. It brings vmail into the windows era where people no longer need to memorize specific command keystrokes. It also provides a mail icon with the flag that pops up when new mail arrives. Again, this is a compact, simple tool, unlike the powerful xmh program. Still, it's a welcome alternative for many people who are running SunView or OpenWindows. ftp://ftp.ucs.ubc.ca/pub/mh/vmailtool.Z 18k or mail requests to James. MMH, My Mail Handler, is a Motif interface for reading and sending mail. It uses the MH commands to actually handle sending a receiving messages. It does not support all the capabilities of MH, but offers a large enough subset to handle the majority of users. Its intended user is someone between "bumbling email novice" and "sophisticated user". Hooks are provided to allow the user to customize and add new commands. ftp://ftp.eos.ncsu.edu/pub/bill/bill.tar.Z 120k From: Andrew Waugh Date: Fri, 1 Jan 1993 00:00:00 -0800 X.500 lookups: If a name is enclosed in square brackets, when entering a destination address: To: [Greg Wickham,CSIRO] a search will be made in the X.500 Directory for the individual's entry. If an address exists then it will be extracted and placed into the headers. Mail requests for the software to the author. From: Barbara Dyker Date: Fri, 1 Jan 1993 00:00:00 -0800 QueueMH is an email based service request and tracking system based on the Rand Mail Handler. ftp://ftp.cs.colorado.edu/pub/cs/sysadmin/utilities/queuemh.tar.Z 98k From: Date: Mon, 1 Mar 1993 00:00:00 -0800 Qmh is an MH-based group mail management tool. Written entirely in perl, Qmh combines the best aspects of MH with group mail heuristics and delivers a sensible package for all levels of Unix users. A limitless number of individual queues and associated groups of permitted users can be established. Specific functionality includes the following modes of operation; checking header dates and sending reminder/deadline mail, editing existing messages, help screens, creating new messages from scratch or exiting messages, resolving messages, scanning queue folders, and annotating with status both by editing and sending mail. Qmh is a single generic program in and of itself from which all modes of operation are invoked. Additionally, each separate queue may be accessed via a link to the single program. All system configuration is maintained in a single file that is read upon each invocation of Qmh. Formatting and template files are provided in the system library, although individual users can override the defaults simply by creating equivalent files in their own MH mail directory. Qmh provides a powerful database-like functionality by allowing limitless per-queue X-Qmh-<$value> headers to be included in messages. These "fields" then form the context of the queue messages and provide a user-defined, but yet structured environment for queries, reporting, and random information. Qmh is designed to provide a complete solution for SA groups, help desks, support organizations, or wherever two or more individuals are trying to manage multiple mail requests. Qmh is also compatible with versions of xmh that provide user-level command buttons. Provided in the Qmh package is a ~/.Xdefaults template file that's setup to harness the power of Qmh. From: Jerry Peek , Shannon Yeh Date: Sun, 11 Mar 2001 00:23:21 -0800 MacMH and PC/MH: These were available only for non-commercial degree-granting institutions from: Networking & Communication Systems 115 Pine Hall Stanford University Stanford, CA 94305-4122 Phone: +1 415-723-3909 See also: ftp://netix.com/pub/pc-mh-info/* For more PC/MH info, contact: Netix Communications, Inc. 15375 Barranca Parkway Building G, Suite 107 Irvine, CA 92718 Phone: +1 714-727-9532 FAX: +1 714-727-3922 Internet: info at netix.com In addition, you might try Wollongong, to see if they have something you can get. [This information appears to be out of date. Please send me pointers to valid information. Potential sites include jessica.stanford.edu. --Ed] Two other potential methods to run MH under Windows: Run Unix under Windows with VMware (http://www.vmware.com/) or try to compile nmh with the Cygwin tools (http://www.cygwin.com/). ------------------------------ Subject: 01.06 How can I print a MH manual? From: Bill Wohler , Jos Vos Date: Sun, 23 Sep 2007 23:51:33 -0700 Documentation in text and PostScript format is found in the MH-doc.tgz tarball on: http://sourceforge.net/project/showfiles.php?group_id=143658&package_id=188464 To generate your own copy for printing, first obtain the MH sources (see "Where can I get MH?") if you don't already have it. Go into the "doc" directory and run "make guide" to create the administrators guide and "make manual" to create a user's manual which includes tutorials and man pages. If the doc directory is empty or is missing the Makefile, you'll have to run "mhconfig MH" in the conf directory so that the documentation with correct local information is created. For properly formatting the documentation (at least the manual pages) you might even have to install MH, because a reference to a tmac.h file in the MH lib directory is made in the manual pages. ------------------------------ Subject: 01.07 How should I report bugs? From: Bill Wohler Date: Wed, 29 Sep 2004 00:12:42 -0700 Bugs in nmh should be reported at: http://savannah.nongnu.org/bugs/?group=nmh Bugs in MH-E should be reported at: http://sourceforge.net/tracker/?atid=113357&group_id=13357 ------------------------------ Subject: 01.08 How can I convert from my mailer to MH? From: Mike Sutton Date: 7 Jul 1995 10:03:50 GMT The unrmail function will convert rmail format to mbox format. From: Jerry Peek Date: Fri, 1 Mar 1991 13:03:15 -0800 If you use one of a mail agent like 'mail', 'mailx', 'elm' or 'mush', converting to MH is easy. When you run the 'inc' command, it reads all new messages from the system mailbox into your 'inbox' folder. Those mail agents also have separate files or "folders" that hold messages in the same format as the system mailbox. You can read them with the 'inc -file' command. For example, to read the messages from your 'mbox' mail file into your MH 'inbox' folder, you'd type: % cd % cp mbox mbox.backup % inc -file mbox If you see the usual "Incorporating new mail into inbox..." message and a scan listing, the messages probably were converted. Read some or all of them (with the 'show' command) and be sure. The 'inc' won't remove your mbox unless you use '-truncate'. From: "Jason R. Mastaler" Date: Mon, 1 May 1995 00:00:00 -0800 You can also specify an alternate folder to inc. Here's how you can convert all your folders en masse: for arg in `cat flist`; do echo "converting $arg" inc +"$arg" -file "$arg" -silent done Section D.4 of the MH book's second edition lists two scripts to convert mail files to MH folders: babyl2mh to convert from rmail's BABYL format; vmsmail2mh to convert from VMS's mail (see "What references exist for MH") to see where the book's examples can be ftped from). These scripts aren't in the third edition but are in its archive file. From: Vivek Khera Date: Fri, 1 Jan 1993 00:00:00 -0800 I rewrote the above script in Perl since the original script doesn't work for some people (see "babyl2mh.pl" below). From: Juergen Nickelsen Date: Fri, 1 Jan 1993 00:00:00 -0800 You can remove the second to last second line ("> $input"), so that the script doesn't zero out your RMAIL file. Another alternative is to replace this line with "inc -file $tmpmbox $folder && > $input", so that the RMAIL is only zeroed if inc successfully incorporated the mail. Finally one could add a switch -z, so that the RMAIL file is only zeroed if the switch is given. (See "Appendix inco".) Date: Sun, 1 May 1994 00:00:00 -0800 Use the following to convert a BABYL format file to Unix mail format. ftp://inf.informatik.uni-stuttgart.de/pub/gnu/emacs_extras/rmailtovm.el.Z 6k See also MH book second edition (Appendix D). ------------------------------ Subject: 01.09 What is the copyright status of nmh? From: Richard Coleman Date: Mon, 10 Oct 2005 18:16:58 -0700 nmh is distributed under a variant of the classical BSD copyright. Check the COPYRIGHT file in the nmh distribution for the details. There are some specific files which were contributed to the original MH package that are copyrighted by their original author. We have retained the copyright notices of these authors in these files. ------------------------------ Subject: 02.00 ***** Building MH ***** From: Bill Wohler Date: Fri, 1 Mar 1991 13:03:15 -0800 ------------------------------ Subject: 02.01 What machines does MH run on? From: Bill Wohler Date: Thu, 19 May 2005 21:22:55 -0700 MH isn't just for Unix any more. Versions are reported to run on OS/2 (see "How can I build MH on OS/2?"), Windows (see "How can I build MH on Windows?"), and Mac (see "How can I build MH on Mac?"). Oh yeah, the Mac is now Unix. Maybe Windows Longhorn will be built on Unix too. From: Jerry Peek Date: Fri, 1 Mar 1991 13:03:15 -0800 If you have a computer running Unix, you can probably run MH. ------------------------------ Subject: 02.02 How do I build MH? From: Bill Wohler Date: Sun, 8 Sep 1996 15:13:12 -0700 If you're using Linux, you can simply install the nmh or MH package which is available in most distributions. If you want to build nmh, follow the directions in the file named INSTALL. Basically, it's simply "./configure; make; make install." If you have MH on the other hand, if you carefully read the file named READ-ME in the root of the source hierarchy, you should not have any trouble building MH. If you're having troubles building MH, it could be that the problem has already been fixed, but hasn't yet gotten into an official release. Please see http://www.gw.com/mail/mh/patches/ for more info. ------------------------------ Subject: 02.03 What options should I use? From: Bill Wohler Date: Tue, 1 Dec 1992 00:00:00 -0800 BERK: Do NOT include the BERK option (in versions 6.7 or later)! BERK breaks the mh-format functions that take apart address lines, for example mbox, from, and friendly. This would really put a crimp on my replcomps file. LOCKF: if you have NFS, you need to lock your mailbox with lockf() so the lock will be honored by all machines on the local network. If you have the lockf() system call, include LOCKF. JQ Johnson makes the point that one should use this option carefully since it requires a robust lockf() call. For example, this option caused serious problems on his SunOS 4.1.1. He suggested using LOK_BELL instead, and adding "lockstyle: 1" to $MHLIB/mts.conf (mtstailor). ATZ: makes your timezones print like "EST" instead of "-0500". Much prettier. --Stephen Gildea However, Tony Landells replies: "Yes; very pretty. How unfortunate that timezone names are so ambiguous, so that EST can be interpreted, at a minimum, as (American) Eastern Standard Time, (Australian) Eastern Standard Time, or (Australian) Eastern Summer Time (and yes, I think it's dumb having the same acronym for both normal and Summer time, but that's a different problem). While the numeric timezones may not look as nice, they are, at least, reasonably unambiguous. I would urge anyone who ever intends/hopes/expects to use email outside the U.S. to NOT use ATZ (sorry Stephen)." At any rate, the conf/examples directory has been updated and contains many examples show you which options are required on your platform and which are optional (in the upcoming version MH 6.8). At any rate, it is recommended that you examine the options in the example configuration files, and read about them in READ-ME. RPATHS: a side-effect is that slocal writes messages to your system maildrop without the MMDF C-A's that separate messages, so your BSD tools like from work. ------------------------------ Subject: 02.04 What do I need to do to use POP? From: Bill Wohler Date: Sun, 8 Sep 1996 23:31:01 -0700 MH6.7 (and earlier versions too) include a server for version 3 of POP. From: Morgan Fletcher Date: 14 Mar 1996 19:24:23 -0800 Ensure that /etc/services contains the following: pop2 109/tcp postoffice # POP version 2 pop2 109/udp ->pop 110/tcp # POP version 3 (MH's inc thinks it's "pop") ->pop 110/udp pop3 110/tcp # POP version 3 pop3 110/udp Also compile with the POP options: POP, DPOP, RPOP, etc. From: Richard Coleman Date: 06 Feb 1997 03:43:17 -0500 To get MH to use the pop3 service, add POPSERVICE=pop3 to your MH configuration and recompile: ------------------------------ Subject: 02.05 Does MH support IMAP? From: Lyndon Nerenberg Date: 27 Jul 1999 11:33:39 -0600 Run exmh on the laptop, and modify your .mh_profile to inc using APOP. This is how I run MH-E and it works fine. (I did have to modify MH-E a wee bit to allow it to prompt for the password. You would likely have to do something similar with exmh.) As a spare time project I'm adding enough IMAP support to MH (6.8.3) to allow you to 'inc -imap [-imapfolder foo]'. If I ever get this done I'll stick the diffs up somewhere. (It's not a big priority as I can get at my IMAP INBOX using APOP.) From: Tim Showalter , John Prevost Date: Wed, 25 Sep 1996 21:34:56 -0400 We are developing fmh and intend to support as much of MH as is feasible. However, MH and IMAP don't necessarily agree as to what things are going to look like. MH has static message numbers until you pack a folder; IMAP keeps two numbers on a message, one which is absolutely static and one which is relative to the top of a mailbox. Messages in IMAP are essentially immutable. IMAP doesn't (currently) allow message annotations. fmh will keep state with a background daemon instead of writing it to disk, and will probably try and keep as little on disk as possible. fmh doesn't understand MH folders at the moment, and probably won't for a really long time, if ever. As I said before, we're mostly interested in the IMAP aspects as we're using a networked file system and saving stuff on the local disk just isn't an option. fmh is not MH at a very fundamental level. It is very unlikely that it will be merged, as we're not quite as interested in creating something that is MH and IMAP as we are in writing a good IMAP client. Also, the MH code isn't going to take the introduction of IMAP without a near complete rewrite. It is not available yet. Inquiries are welcome at . From: Rahul Dhesi Date: 23 Sep 1996 08:39:52 GMT What prevents people from doing a telnet to their mail server, logging in, and firing up MH directly? Site policy? An operating system that does not let MH compile or run? Overloaded machine with insufficient processing power for MH? All these are site-specific problems and the solution lies in solving them locally, not in forcing MH to go over IMAP. IMAP was never designed to emulate a filesytem. MH was designed to make direct advantage of the filesytem structure. There is no compatibility between the two. By the time IMAP is revised enough to support MH you will have reinvented NFS. There *is* scope for redesign here, though. It would be nice to have a single-user filesystem. Create a binary telnet session to the filesystem server, log in as yourself, and then over that session run a filesystem protocol. Normal filesystem protections at the other end will be sufficient for all permissions checking, so the filesystem protocol would need to do no other permissions checking. The question of whom to export directories to would go away: They are exported to whoever completes a successful login, and accessible to the user if he would be able to access them on the server as his login id. You could even use challenge-response for the initial login, coupled with ssh-based encryption, so you automatically have a secure filesystem without even trying. IMAP is too restricted in its scope to be easily modifiable to emulate such a filesystem. It would have to be a redesign from scratch. From: John Romine Date: Sun, 8 Sep 1996 15:45:27 -0700 No. MH only supports retrieving mail using POP3. POP3 is on the "standards track"--it is now an elective Internet Draft Standard (see RFC 1939 for more details). At this point, IMAP[23] are "experimental, limited use" protocols; it is unlikely that MH will support them. From: Bill Wohler Date: Sun, 8 Sep 1996 15:45:32 -0700 Since John posted the message above, IMAP has progressed from an "experiemental, limited use" protocol. While IMAP is not universal, many vendors now have implementations. I've found several things which might help. First, a definition lifted from the Pine FAQ: What is IMAP? IMAP stands for "Internet Message Access Protocol". An IMAP client program on any platform at any location on the Internet can access email folders on an IMAP server. While the messages appear to be local, they reside on the server until the client explicitly moves or deletes them. The IMAP protocol is a superset of POP, containing all POP commands plus more. For a comparison of IMAP and POP, see the paper Comparing Two Approaches to Remote Mailbox Access: IMAP vs. POP (in ftp.cac.washington.edu:/mail/imap.vs.pop). IMAP is what allows Pine (or any other IMAP client) to get to email on a central campus email server. There are current IETF working groups revising IMAP and readying it to become an Internet standard. A copy of the latest IMAP draft may be obtained from: ftp://ftp.cac.washington.edu/mail/latest-imap-draft For a list of IMAP clients, see the file imap.software, in the same directory. From: David L Miller Date: Mon, 1 Aug 1994 00:00:00 -0800 ipop3d from the UW IMAP toolkit can operate in a couple modes. As a straight POP3 server, it uses the same C-client library as imapd, so it co-exists comfortably with imapd. It can also operate as a POP-to-IMAP gateway so that your POP-only clients can access IMAP services. ftp://ftp.cac.washington.edu/mail/imap.tar.Z 1.0M From: Mark Crispin Date: Mon, 1 Aug 1994 00:00:00 -0800 The only answer I can give for [how MH users can use IMAP] is that Pine can read mailboxes in MH format; and that someone might in the future develop a version of MH that can use IMAP. ------------------------------ Subject: 02.06 Why does "mailgroup mail" only affect inc but not slocal? From: John Romine Date: Fri, 1 Jan 1993 00:00:00 -0800 If "mailgroup" is set, inc is made set-group-id to this group name. Some SYS5 systems want this to be set to "mail". Set this if /usr/spool/mail (or /usr/mail) is not world-writable. These changes were contributed by Peter Marvit, and "inc" is very careful about its use of the set-gid privilege. Note that slocal doesn't know how to deal with this, and will not work under these systems; just making it set-group-id will open a security hole (since it doesn't know when to drop the set-gid privileges). If you're using "mailgroup", you should remove slocal (and its man page) from your system. Alternatives to slocal include deliver, procmail, and mailagent. (See "What mail filters are available?") ------------------------------ Subject: 02.07 How can I build MH on Solaris 2? From: Richard Coleman Date: Tue, 20 Jan 1998 02:19:58 -0500 nmh builds out of the box on Solaris. From: Bill Wohler Date: Sun, 8 Sep 1996 15:56:31 -0700 See http://www.gw.com/mail/mh/patches/solaris/ for patches you may need. From: Neil Rickert , Scott K. Hutton , Casper H.S. Dik Date: Sun, 8 Sep 1996 15:57:25 -0700 First, don't use the BSD compatible stuff. Make sure that the Sun or GNU compiler appear before the BSD compiler in your PATH (e.g., /usr/ccs/bin). Second, don't use GNU make. Make sure that the Sun make appears before the GNU make in your PATH. Use conf/examples/solaris2.sun.com and fix the paths, if necessary. Optionally change the following to use the GNU compiler, to perform optimization, and to create shared libraries. cc gcc ccoptions -O -g -msupersparc slflags -shared Fix mhn.c with the diff in http://www.gw.com/mail/mh/patches/solaris/si_value_2.3. Optionally incorporate the Content-Length header fix. (See "How can I get MH to interpret the Content-Length field?") Linking with /usr/ucblib/libucb.so is incompatible with including . When compiling, you can ignore the following warning: fmtcompile.c, line 238: warning: semantics of "/" change in ANSI C; use explicit cast If you're using AFS, you'll have to replace any occurrence of "ln" with "ln -s" wherever the make dies when it tries to make a link "on a different file system." See also ftp://ftp.fwi.uva.nl/pub/solaris/solaris2.faq. Date: Thu, 1 Dec 1994 00:00:00 -0800 Unset LD_LIBRARY_PATH. From: Gary Strand Date: Mon, 1 May 1995 00:00:00 -0800 To cure slocal's Segmentation Fault problems, I decided to try 'cc' instead of 'gcc' (an alleged no-no under Solaris) and MH built just fine, and it's working perfectly. From: "Jason R. Mastaler" Date: Mon, 25 Sep 1995 17:35:13 -0400 Don't use "ldoptions -s" with gcc. It may cause the compile to fail with: gcc: Internal compiler error: program ld got fatal signal 11 *** Error code 1 From: "Jeffrey T. Eaton" Date: Fri, 04 Apr 1997 15:30:36 GMT Fixed [DBM_PAGFNO_NOT_AVAILABLE error] by getting the latest gdbm package, compiling and installing it and the dbm/ndbm compatability stuff, and moving Sun's broken ndbm.h out of /usr/include. To fix "../sbr/libmh.so: undefined reference to `__builtin_va_arg_incr'", add "option __BUILTIN_VA_ARG_INCR" to your MH configuration. ------------------------------ Subject: 02.08 How can I build MH on Linux? From: Richard Coleman Date: Tue, 20 Jan 1998 02:19:58 -0500 nmh should build out of the box for most Linux systems. From: Bill Wohler Date: Tue, 9 Feb 1999 23:04:53 -0800 The Debian distribution of Linux comes with an MH and nmh packages. See http://www.debian.org/. See also http://www.gw.com/mail/mh/patches/linux/. From: "James A. Robinson" Date: 17 Apr 96 20:39:02 GMT Somebody on Debian ported it to Linux ELF. Look on ftp://ftp.debian.org/debian/stable/binary/mail/mh_6.8.4-13.deb for the .deb package of MH (it's a compressed tar file). The source is in ftp://ftp.debian.org/debian/stable/source/mail/mh_6.8.4-orig.tar.gz and mh_6.8.4-13.diff.gz. From: Brian Kirouac Date: 18 Apr 96 14:00:20 GMT If you are running Redhat and have rpm available you can also use ftp://???/pub/redhat-3.0.3/i386/RedHat/RPMS/mh-6.8.3-5.i386.rpm. The source code is in ftp://???/pub/redhat-3.0.3/i386/SRPMS/mh-6.8.3-5.i386.rpm From: "Brandon S. Allbery" Date: Sun, 26 Nov 1995 16:18:50 -0800 The current patch is the first one listed below. The old patch only works with libc-4.4, which is no longer used. The current patch is split into two pieces, as with the previous patch, but now the divisions are purely functional: the first diff enables MH to compile, the second allows creation of a shared library. [The paths are up to date, but I think the info in this paragraph is old. --Ed] Recent versions of GNU make choke on MH's makefiles. Unfortunately, the shared library patches depend on "export". If you have problems building MH, remove the "export" lines from all of the makefiles (if you applied the shared library patches) and try using BSD pmake instead. If you don't want to compile MH, the second file contains pre-compiled ready-to-run binaries which can simply be extracted in the root directory. ftp://sunsite.unc.edu/pub/Linux/system/Mail/readers/mh-6.8.3-diffs.tar.gz ftp://sunsite.unc.edu/pub/Linux/system/Mail/readers/mh-6.8.3-bin.tar.gz The sizes are 650k and 22k respectively. Note that these files are occasionally "cleaned up" by accident so please let me know if they are missing. ------------------------------ Subject: 02.09 How can I build MH on IRIX? From: Richard Coleman Date: Tue, 20 Jan 1998 02:19:58 -0500 nmh should build out of the box for Irix. From: Bill Wohler Date: Sun, 8 Sep 1996 15:33:22 -0700 See http://www.gw.com/mail/mh/patches/sgi/ for patches you may need. From: Arne K. Frick Date: 06 Jun 1995 18:30:01 GMT There is a file at viz.tamu.edu:/pub/sgi (see FAQ) containing a diff and sample configuration. If you cannot locate it, I can mail it to you. Note, however, that I had tremendous difficulties with them under 5.3: 1. Be sure to use /bin/make, NOT GNU make. 2. patch vomits over the diff. You can get around this by increasing the "fuzz factor" to 4. 3. The Makefile target for the shared library doesn't work. I had to do it by hand. But I'm stuck compiling mhn.c. From: Shankar Unni Date: 9 Jun 1995 01:53:48 GMT The fix for compiling mhn.c is in http://www.gw.com/mail/mh/patches/solaris/si_value_2.3. From: Jack Repenning Date: 25 Jul 1995 02:35:41 GMT (See "IRIX config file") below. ------------------------------ Subject: 02.10 How can I get MH to interpret the Content-Length field? From: Casper H.S. Dik Date: Sun, 8 Sep 1996 15:38:30 -0700 Apply http://www.gw.com/mail/mh/patches/solaris/content_length to your MH distribution and add the configuration option "CONTENT_LENGTH". It also includes the si_ fix in http://www.gw.com/mail/mh/patches/solaris/si_value_2.3 ------------------------------ Subject: 02.11 How can I build MH on HP-UX? From: Bill Wohler Date: Sun, 8 Sep 1996 15:50:54 -0700 If you find that your zotnet/tws directory isn't compiling, upgrade your MH (see "What is the current version/status of MH?") which includes fixes to lexedit.sed. See http://www.gw.com/mail/mh/patches/hp/ for for patches you may need. ------------------------------ Subject: 02.12 Can I prevent adding the local hostname to addresses behind firewalls? From: Ted Remillard Date: 24 Jun 1996 08:53:42 -0700 You can get MH to stop managing the headers and let the email server to do it. To do this, build MH with the options DUMB and REALLYDUMB. In the $MHLIB/mts.conf (mtstailor) file, set the server option to the IP address of the email server. After this is done, MH sends email directly to the email server and Local email To: and From: fields just have the user's simple email address, e.g., , and the remote email From: header will contain user@domainname, e.g., . Don't forget to define the REALLYDUMB option in the file sbr/addrsbr.c described below. From: Bret Rothenberg Date: Tue, 23 Jan 1996 12:25:24 -0800 (PST) Yes, use the "localname" parameter in "$MHLIB/mts.conf" (mtstailor) to specify the desired hostname. From: Ken Hornstein Date: 18 Aug 1995 23:51:48 -0400 If you're behind a firewall and sendmail gives you fits because MH adds the node name or site name to each address in the To: and CC: fields, you'll need to modify the MH source. The relevant source has to do with the REALLYDUMB option in sbr/addrsbr.c. Essentially what you need to do is set it up so REALLYDUMB is turned on (normally, it's turned off if you have MMDF or SMTP turned on). This will do what you want. I did this at our site, and it's been working great. The stuff for REALLYDUMB starts around line 613. ------------------------------ Subject: 02.13 Is there a patch to fix this or that? From: Kimmo Suominen Date: Sat, 3 Mar 2001 13:40:35 -0800 The MH Patch Archive has been opened at http://www.gw.com/mail/mh/patches/ It is a collection of patches to MH (the RAND MH Message Handling System), a set of electronic mail programs in the public domain. Since the last complete release of MH (version 6.8.3) UNIX systems have evolved making changes in the MH code necessary. Several new UNIX systems have emerged requiring new configuration templates and examples. This archive tries to collect all these fixes and enhancements that in the past have been available only through word-of-mouth and occasional reposts to newsgroups or mailing lists. The initial archive layout and the very time consuming collecting and categorizing of patches has been done by Jerry Peek. I will be the primary maintainer of the archive. Even though I will be monitoring several sources for new material (mainly the comp.mail.mh newsgroup but also the mailing lists , and ), I'd like to encourage everyone to submit patches also directly to the archive at . ------------------------------ Subject: 02.14 How can I build MH on OS/2? From: Sanjay Aiyagari Date: 21 Nov 1996 19:37:10 GMT ftp://ftp.jaist.ac.jp/pub/os/os2/network/MH/ ------------------------------ Subject: 02.15 Do any POP/IMAP servers handle MH format? From: "Carl S. Gutekunst" Date: 27 May 1997 07:24:34 GMT The University of Washington POP3 and IMAP servers can be backended by a variety of stores, including MH. This is the basis for Netscape's store, curiously enough. I haven't looked closely at how Mark Crispin implemented support for the new IMAP4 features when using an MH backend; it seems like there is a lot of computation when opening a folder for the first time, writing in the UID fields and such. But it basically appears to work. From: Lyndon Nerenberg Date: 27 Jul 1999 11:36:25 -0600 But [the UW IMAP server] can't delete/expunge from MH folders. (At least I've never been able to get it to work, and I've tried just about everything.) #mh in UW imapd isn't something I'd recommend to any serious MH user. From: Mark Crispin Date: Tue, 27 Jul 1999 14:43:25 -0700 > But it can't delete/expunge from MH folders. That's a very old version. delete/expunge has been in imap-4.x for a long while. However, there's no sticky flags. > #mh in UW imapd isn't something I'd recommend to any serious MH user. The converse is also true. The two don't play ball very well. From: Dieter Weber Date: 11 Feb 2003 04:23:38 -0800 The UW imap server supports MH folders. In order to see the MH mailboxes, you need to "subscribe" to the folders or add them to the .mailboxlist file in your home directory. ------------------------------ Subject: !02.16 How can I build MH on Windows? From: David Levine Date: Sun Sep 30 22:45:08 CDT 2012 nmh is now available as a Cygwin package. Select it using Cygwin setup. Or, download and build from source. Hacks are no longer needed. From: Satyaki Das Date: Wed, 19 Jun 2002 20:57:19 -0700 I have gotten MH-E to work on Windows (under Cygwin) using Earl Hood's patched nmh. It was really quite simple, but not very portable. I just needed to add/subtract "c:/cygwin" from a couple of places. Now it can read and send mail (even does PGP attachments). Thought this might be of interest to those of you stuck using Windows at work. From: Earl Hood Date: Sat, 08 Jun 2002 20:30:44 GMT I've made a tar/bz2 bundle available at This includes the patched source with binaries pre-built. I just remembered that I also had to hack the makefiles to get things to install since windoze executables have to end with .exe. I hacked the generated makefiles, so if you rerun configure, you may lose the hacks. Also, I believe the install will fail when trying to install the documentation, so to force things do: make -i install The binaries and support files should get installed (under /usr/local/nmh), but the docs probably won't. Then you will need to edit /usr/local/nmh/etc/mts.conf to reflect your local configuration. If anyone has any problems installing, I could zip up my /usr/local/nmh since I think it contains everything needed for runtime usage. From: Bill Goffe Date: 25 May 1999 18:13:55 GMT If you have Windows, consider looking at VMware http://www.vmware.com/ which provides a virtual machine where you can run Unix and therefore MH under Windows. From: Ted Nolan Date: 24 May 99 17:20:27 GMT The latest Cygnus Cygwin, GNU tools that run under Windows, http://www.cygwin.com/ seems to work pretty well and may well be able to build nmh. ------------------------------ Subject: 02.17 How can I build MH on a Mac? From: David Levine Date: Sun Sep 30 22:47:12 CDT 2012 nmh 1.3 and later build on Mac OS X out of the box. From: Dr Eberhard W Lisse Date: Sun, 05 Jun 2005 13:43:19 +0100 nmh compiles on the G4 iBook running Mac OS X 10.3.7 more or less out of the box with the powerpc HOST option. Use make all install. Use fink to install the nmh package on Max OS X 10.3.9 (and 10.4.1). metamail does not work out of the box. However, metamail-2.7.19-1030.src.rpm (SuSE) which compiles and installs cleanly. For exmh, first use fink to install the tcltk package. Then use fink to install exmh. ------------------------------ Subject: 03.00 ***** Scanning & Reading ***** From: Bill Wohler Date: Fri, 1 Mar 1991 13:03:15 -0800 ------------------------------ Subject: 03.01 What do I do if scan shows the wrong date? From: Bill Wohler Date: Fri, 1 Jan 1993 00:00:00 -0800 Upgrade to MH 6.8 or nmh. From: Darryl Okahata Date: 19 Jan 2000 23:01:10 -0800 MH 6.8.3 and nmh 1.0 still have a minor buglet where sortm doesn't always sort messages properly. If a (questionable) mail client sends messages with 2-digit years, like: Date: Sat, 23 Oct 09 22:02:01 EST or sends out buggy dates like (as buggy versions of Elm do): Date: Sat, 23 Oct 100 22:02:01 EST then sortm will not sort these messages properly. I have submitted patches to nmh-workers. ------------------------------ Subject: 03.02 How would one go about reading Usenet with MH? From: Bill Wohler Date: Sun, 26 Nov 1995 12:32:09 -0800 You can post via mail. Send your article to with a legitimate Newsgroups field. From: Jerry Peek Date: Tue, 1 Nov 1994 00:00:00 -0800 You can save articles in the news readers for later perusal with MH. First, create a symbolic link from your mail directory (e.g., usenet) to your news directory (e.g., "ln -s ~/News ~/Mail/usenet"). You can then treat your news directory as a mail folder. Thus, to select a news group, use "folder +usenet/comp/mail/mh". To set the default save location correctly in rn, use: rn -M -/ or in your nn presentation sequence: news.announce. +$F/$N comp.mail.mh + . . If there's news spooled on your machine (that is, not via NNTP) then you can read a newsgroup with commands like: show first +/usr/spool/news/comp/mail/mh next ... You can also use sequences to keep track of what you've read. MH will automatically set a "cur" sequence in each newsgroup you read that way. So, to continue reading the newsgroup sometime later, after you've read some other folder, you can do: next +/usr/spool/news/comp/mail/mh and you'll read the next (new) article (if any) in that newsgroup. Note that this can eventually make your private context file pretty huge; if there's a group you don't read often, you can remove its context entries with a command like: rmf +/usr/spool/news/comp/mail/mh Don't try that on a folder full of mail (a folder that isn't read-only), though... in that case, it'll remove all the messages! I haven't looked into posting. It seems like it shouldn't be hard. You could set up a "sendproc" that would look at outgoing email messages. If the message had a Newsgroups: header field, your sendproc could call inews(1) instead of post(8). I haven't seen much in the MH manpages or documentation about sendprocs (though I haven't looked for a couple of years...). See the "mysend" script in the MH book section 7.1.4 (13.13), or the URL: http://rand-mh.sourceforge.net/book/mh/senove.html#ASAtDm A threaded news reader like trn or tin is so much nicer, though, that reading news with MH may not be worth the hassle. See also MH book section 9.9 (8.7), or the URL: http://rand-mh.sourceforge.net/book/mh/shafol.html From: Stephen Gildea Date: Fri, 1 Mar 1991 13:03:15 -0800 Although news readers are better, if one really wants to use MH, bbc will do the job. For example, "bbc comp.mail.mh" reads this newsgroup. To enable bbc, you have to specify "bboards" when you build MH. From: Kimmo Suominen Date: 15 Aug 1996 18:18:10 GMT Sendmail v8 comes with MAILER(pop) which was written for the MH spop. Since I use bboards with NNTP, I never looked at the bboards setup. Date: Tue, 1 Nov 1994 00:00:00 -0800 See mhunify in (see also "What other MH software is available?"). ------------------------------ Subject: 03.03 How can I search through multiple folders? From: Jerry Peek Date: Mon, 1 Mar 1993 00:00:00 -0800 Recurse through the folders (in csh and sh): % foreach f (`folders -f`) $ for f in `folders -f` ? pick [switches] +$f > pick [switches] +$f ? end > done Or create a folder that contains links to all messages (in csh and sh): % foreach f (`folders -f | grep -v -x ln`) ? refile -src +$f -link all +ln ? end $ for f in `folders -f | grep -v -x ln` > do refile -src +$f -link all +ln > done and in the future, refile messages with "refile +folder +ln". To find something, use: % pick [switches] +ln See MH book sections 8.2.9 (7.2.9), 8.9.3 (7.8.3), or the URLs: http://rand-mh.sourceforge.net/book/mh/finpic.html#SeMTOnFo http://rand-mh.sourceforge.net/book/mh/usilin.html#AFoFuoLi ------------------------------ Subject: 03.04 Why don't MH format commands such as %(friendly) work? From: Anthony Baxter Date: Sun, 1 May 1994 00:00:00 -0800 The BERK option disables address parsing and therefore functions such as %(friendly). Recompile MH without the BERK option. ------------------------------ Subject: 03.05 Why doesn't "show" display all of a MIME message? From: Jerry Peek Date: Mon, 1 Aug 1994 00:00:00 -0800 It's not the fault of the "show" command or of MH in general. It's your system's configuration. Check the $MHLIB/mhn.defaults (mhn_defaults) file; if it doesn't have defaults for all content types, add them. Or, if you can't (or shouldn't) change mhn.defaults (mhn_defaults), you can put default entries in your MH profile file for those content types. Here's the part of the mhshow(1) (mhn(1)) manpage that explains how content types are handled. The example is for mhshow, but if you're using mhn, you'd replace mhshow with mhn: First, mhshow will look for an entry of the form: mhshow-show-/ to determine the command to use to display the content. If this isn't found, mhshow will look for an entry of the form: mhshow-show- to determine the display command. If this isn't found, mhshow has two default values: mhshow-show-text/plain: %pmoreproc '%F' mhshow-show-message/rfc822: %pshow -file '%F' If neither apply, mhshow will check to see if the message has a application/octet-stream content with parameter "type=tar". If so, mhshow will use an appropriate command. If not, mhshow will complain. So, add defaults that cover the types MH doesn't handle right now (or doesn't handle the way you want it to). Your defaults will override corresponding defaults in the $MHLIB/mhn.defaults (mhn_defaults) file. For example, if you don't have an HTML editor/browser on your system, you could tell MH to use the "less" paginator for HTML message parts: mhshow-show-text/x-html: less %F You can put that line in your MH profile. You can even set different defaults for different terminal types (say, your VT100 at home and your X setup at work). Make a file in the same format as mhn.defaults (mhn_defaults); store its pathname in the MHSHOW (MHN) environment variable. Add a test to your shell setup file (.bash_profile, .profile, .login) that tests the value of the TERM variable -- and, if you have an mhshow (mhn) setup file for that terminal type, store its pathname in the MHSHOW (MHN) variable. See also MH book sections 6.2.3, 9.4.4, 9.4.5, or the URLs: http://rand-mh.sourceforge.net/book/mh/remime.html#HomhShMe http://rand-mh.sourceforge.net/book/mh/confmhn.html#ShComhsh http://rand-mh.sourceforge.net/book/mh/confmhn.html#DiOChSmc From: Michael K. Neylon Date: Tue, 1 Nov 1994 00:00:00 -0800 If you are not using the X Window System, you may have to add this line to your MH profile: mhshow-charset-iso-8859-1: /bin/sh -c '%s' # nmh mhn-charset-iso-8859-1: /bin/sh -c '%s' # MH ------------------------------ Subject: 03.06 Can I get show not to run "less" so much on MIME messages? From: Richard Coleman Date: Tue, 20 Jan 1998 02:19:58 -0500 On nmh, you can do this just by "show -nocheckmime". This will disable the detection of MIME messages. From: Bill Wohler Date: Tue, 1 Nov 1994 00:00:00 -0800 If you say, "show all," and one of the messages was a MIME message, your pager will be run several times on each message, rather than once on all the messages as a whole. If you find this annoying, use -nocheckmime. See also MH book sections 6.2.3, 6.2.10, or the URLs: http://rand-mh.sourceforge.net/book/mh/remime.html#HomhShMe http://rand-mh.sourceforge.net/book/mh/remime.html#Alttomhn ------------------------------ Subject: 03.07 Why do I get "mhn: don't know how to display content"? From: Richard Coleman Date: Tue, 20 Jan 1998 02:19:58 -0500 This has already been fixed in nmh. From: Keith Moore Date: Sun, 8 Sep 1996 15:49:50 -0700 MH 6.8.3 has a bug where it will not handle multipart/foo correctly if it doesn't know about foo. The patch: http://www.gw.com/mail/mh/patches/all/mhn_multipart tells it to treat such things as if they were multipart/mixed. (See also "Why doesn't "show" display all of a MIME message?"). ------------------------------ Subject: 03.08 How can I automatically delete MH backup files? From: mccammaa at expt05.stp.xfi.bp.com (Andy McCammont) Date: 22 May 1995 06:27:36 -0400 On System V system, add this to your crontab. If you don't have one, put this in a file, and run "crontab file". If your system does not support personal crontab files, get your system administrator to add an equivalent line to the system crontab file or daily clean-up script. Note that some administrators set the prefix character to '#'. # Remove old MH files 5 5 * * * find /PATH/TO/HOME/Mail -name ",*" -mtime +5 -exec rm {} \; ------------------------------ Subject: 03.09 Fixing "cannot fopen and lock /var/spool/mail/(user)" From: Patrick.Wambacq at esat.kuleuven.ac.be Date: Mon, 30 Sep 96 15:00:16 +0200 One should put the following lines in the $MHLIB/mts.conf (mtstailor) file: lockldir: lockstyle: 1 This prevents MH from using kernel level locking, and uses lock files instead. It solved the problem for me on two different architectures. When the lockldir entry is left empty as above, the lock file is put in the same directory as the file to be locked. If another directory is wanted, its name should be put here. From: alhy at MAILBOX.SLAC.Stanford.EDU Date: Mon, 9 Sep 1996 01:01:16 -0700 Often, this is caused by an NFS file lock. Don't ask me how it got there in the first place. To remove the file lock, do the following: # cd /var/spool/mail # cp user /tmp/user.tmp; rm user # save mail; remove locked file # chown user /tmp/user.tmp # allow user to inc old mail # su - user user% inc -file user.tmp # incorporate user's old mail Any mail that you receive in the fraction of a second that the second set of commands takes will be lost. (See also "Why does inc hang (on Sun)?") ------------------------------ Subject: 03.10 Can I read my mail with a Web browser? From: Jerry Heyman Date: Sat, 09 Oct 2004 12:41:03 -0400 See http://www.squirrelmail.org/ SquirrelMail is a standards-based webmail package written in PHP4. It includes built-in pure PHP support for the IMAP and SMTP protocols, and all pages render in pure HTML 4.0 (with no JavaScript required) for maximum compatibility across browsers. It has very few requirements and is very easy to configure and install. SquirrelMail has all the functionality you would want from an email client, including strong MIME support, address books, and folder manipulation. No MH support. Unless you're willing to write it... From: J C Lawrence Date: Wed, 10 Dec 2003 09:54:15 -0500 UW-imap can read MH folders although it doesn't maintain sequence files properly. Drop any of the IMAP web front ends in front of that. From: aeriksson at fastmail.fm Date: Wed, 10 Dec 2003 22:36:52 +0100 Have a peek at http://wmh.sf.net/. It's been a while since I worked on it, but it does give me what I need. Date: Mon, 05 Oct 1998 11:02:52 -0500 From: Kent Landfield Hypermail now supports MIME and alternate mailbox formats and sorts by author, date, and thread and can be read by a WWW reader. http://www.landfield.com/hypermail/ From: "Patrick A. Coronato" Date: 8 Sep 1995 16:36:03 GMT MHonArc, by Earl Hood from Convex, will read MH mailboxes as well as Unix mailboxes, create HTML "archives" and will also sort by date, thread and author and has support for MIME. Also, MHonArc is written in the Perl language. (You should go to this site if nothing more than to see the cool logo!) http://www.mhonarc.org/ ------------------------------ Subject: 03.11 How can I run inc automatically with POP? From: Bill Wohler Date: Mon, 27 Nov 1995 12:23:51 -0800 If MH has been compiled with RPOP, then the POP server host either needs to have your host in /etc/hosts.equiv or in your .rhosts file. Then add to your MH profile: inc: -host cuckoo given that "cuckoo" is the name of the your POP server. From: Andy Norman Date: Mon, 1 May 1995 00:00:00 -0800 Assuming your POP server is called cuckoo, add an entry to your MH profile for 'inc' like so: inc: -noaudit -norpop -noapop -host cuckoo Add the following to ~/.netrc and ensure it [grants no permissions to group or other] (e.g., chmod 600 .netrc): machine cuckoo.domain.name login joeuser password secret Replace the hostname, login and password with your own, of course. The hostname probably has to be fully qualified (i.e., include the full domain name). This example assumes that you can send mail by other means (e.g., with SMTP). ------------------------------ Subject: 03.12 Why does inc hang (on Sun)? From: ericding at mit.edu (Eric J. Ding) Date: 30 Apr 1996 00:22:01 -0400 This may be due to a non-robust implementation of lockf() over NFS. Try setting lockstyle to 1 in the $MHLIB/mts.conf (mtstailor) file so that MH uses dotfile locking rather than FLOCK or LOCKF. ------------------------------ Subject: 03.13 How can I get POP to work? From: Jonathan George Date: Tue, 23 Apr 1996 10:23:16 GMT If you get the error: inc: -ERR Unknown command: "rpop" you're trying to use "rpop" as the mechanism to authenticate the user. This mechanism is specified in RFC 1225 and then removed by RFC 1460. Your POP server is (rightly) rejecting this. The POP specification (RFC 1939) states that authentication is done either via a USER/PASS pair or via the APOP command. Try running inc with -noapop -norpop flags. ------------------------------ Subject: 03.14 How do I persuade mhshow (mhn) not to bring up a new window? From: Joel Reicher Date: Tue, 13 Nov 2001 16:49:04 +1100 I personally think [the solution below] is not the right solution. There's a reason that new window is opened--to ensure the correct characters are available. The "right" solution is surely to set the MM_CHARSET env var to iso-8859-1 and make the appropriate adjustments to the pager (in the case of less, setting LESSCHARSET=latin1). From: Larry Daffner Date: 27 Mar 1996 16:53:39 -0600 Add one of the following to your .mh_profile: mhshow-charset-iso-8859-1: %s # nmh mhn-charset-iso-8859-1: %s # MH ------------------------------ Subject: 03.15 How do I turn off of all the mhshow (mhn) prompts? From: Bill Wohler Date: Sun, 11 Mar 2001 11:33:10 -0800 In nmh, use mhshow -nopause. From: Larry Daffner Date: 27 Mar 1996 16:53:39 -0600 The "part xxx" message is controlled by the -list switch to mhn so add "mhn: -nolist" to your .mh_profile. To remove the pause, add an entry for "mhn-show-text/plain: more '%F'" to override the default which includes the "%p" escape. All of this is covered in the mhn man page (sort of--you need to add 2+2). It's a bit long, but well worth reading. ------------------------------ Subject: 03.16 Why is inc splitting messages improperly? From: Mayank Choudhary Date: Mon, 29 Apr 1996 09:39:29 -0700 MH considers "From " lines as message separators, so if this string is found within the body, inc splits the message. Add the following line to your .forward "|/usr/bin/mailcompat " where user-name is your login-id. See mailcompat(1) for more information. ------------------------------ Subject: 03.17 Can MH thread messages? From: "John W. Coomes" Date: 30 Apr 1997 13:02:10 -0500 Sort of. You can resort your folders by Subject with: sortm -textfield subject ------------------------------ Subject: 03.18 How can I avoid reading the HTML version of the message? From: Bill Wohler Date: 23 Jun 2000 10:19:34 -0700 You might find that you have two versions of the same message within the message. For example, one part might have a content type of text/plain and the other might be text/html. You may find that mhshow (mhn -show) wants to show the HTML version This is a feature of the multipart/alternative content type. If you prefer reading the the plain text version over the HTML version, you'd have to remove the line in $MHLIB/mhn.defaults or ~/.mh_profile that starts with mhshow-show-text/html (mhn-show-text/html). Of course, the tradeoff is that you'd never be able to view text/html at all, but you probably wouldn't care. ------------------------------ Subject: 03.19 How do I view or save attachments? From: Bill Wohler Date: Mon, 5 Mar 2001 09:12:15 -0800 Use mhshow (mhn -show) and mhstore (mhn -store) respectively. See the man pages for more details. ------------------------------ Subject: 03.20 How do I view HTML attachments with Netscape? From: Bill Wohler Date: Mon, 5 Mar 2001 09:58:05 -0800 Add one of the following to ~/.mh_profile: mhshow-show-text/html: %lnetscape -remote 'openURL(file:%f, new-window)' mhn-show-text/html: %lnetscape -remote 'openURL(file:%f, new-window)' The % escapes are described in the mhshow (mhn) man page. The ", new-window" argument in the netscape invocation is optional, but handy. After reading the message, you can dismiss the window with M-w and go back to reading mail. ------------------------------ Subject: 03.21 Fixing folders: unable to allocate storage for msgstats From: Pete Phillips Date: 30 Jan 2003 03:33:57 -0800 I found the following in my context file: atr-cur-/tmp: 1 atr-pseq-/tmp: 1 For some reason folders doesn't like this. Whether it's because of permission problems or just the size of my tmp directory (about 3/4 of a GB) I don't know, but removing these lines from my context file fixed the problem. ------------------------------ Subject: 03.22 How do I recursively list message attachments? From: Joel Reicher Date: 31 Oct 2001 00:36:14 +1100 I haven't quite managed a recursive listing, but I have worked out a recursive store, which is still useful. Hinted by a builtin display string for mhshow, I found the following works for mhstore: mhstore-store-message/rfc822: | mhstore -file - With that, mhstore will happily recurse down storing everything on its way. Not very discriminate, but the line can be altered to limit without destroying the recursion: mhstore-store-message/rfc822: | mhstore -auto -type message/rfc822 -type image/jpeg -file - which also names the files automatically for good measure. And, FWIW, I engage this by putting it in a separate file and invoking mhstore like env MHSTORE=mhn.rec mhstore ------------------------------ Subject: 03.23 Why do folder and flist overlook some of my sub-folders? From: Richard Coleman Date: Mon, 10 Oct 2005 18:14:24 -0700 There was a bug in these commands which caused them to quit searching a folder for sub-folders too early if the folder contained sub-folders which were symbolic links. This has been improved in nmh-0.25, but folder and flist will still not recurse into folders that contain only symbolic links. ------------------------------ Subject: 04.00 ***** Filing ***** From: Bill Wohler Date: Fri, 1 Mar 1991 13:03:15 -0800 ------------------------------ Subject: 04.01 Can I append MH messages to a Unix mailbox format file? From: Richard Coleman Date: Tue, 20 Jan 1998 02:19:58 -0500 In nmh, use packf instead. From: Bill Wohler Date: Fri, 1 Jan 1993 00:00:00 -0800 Yes, see $MHLIB/packmbox. ------------------------------ Subject: 04.02 Can I append MH messages to a GNU Emacs rmail BABYL-format file? From: Bill Wohler Date: Fri, 1 Mar 1991 13:03:15 -0800 To convert your MH folders to BABYL folders, first run the following script on your Mail directory. #!/bin/sh for f in Mail/*; do if [ -d $f ]; then touch msgbox folder=`basename $f` echo -n packing $folder ... packf +$folder echo done mv msgbox Mail-rmail/$folder fi done This assumes you don't have nested folders. Your rmail folders will be left in $HOME/Mail-rmail in MMDF format which rmail can read. Then run rmail-input for each folder, which converts each folder into BABYL format. Be sure not to append any messages before they are converted from MMDF to BABYL, since there may be really strange results. ------------------------------ Subject: 04.03 Why do I get ".../.mh_sequences is poorly formatted?" From: Richard Coleman Date: Tue, 20 Jan 1998 02:19:58 -0500 This bug has been fixed in nmh (as of version 0.20). There are no limitations on the length of an entry in the .mh_sequences file. From: Jerry Peek Date: Mon, 1 Aug 1994 00:00:00 -0800 There is a line length limit in this file. When sequences are unbroken (without gaps in numbering), that makes short entries in the .mh_sequences file, like this: inftex: 72-8000 But when there are lots of numbering gaps, the entry gets long: inftex: 76 79-81 87 95-96 105 109 120 124 135 141 158 163... That's when you run into problems, and why it's good to keep the folder packed when you can. Simply run "folder -pack +folder". If you're refiling a lot of messages in a large folder, you might not be able to use sequences. Use backquotes to give the message numbers directly to "refile". For example: refile +tex/info-tex `pick -to info-tex` That can still generate a long list of arguments to the "refile" command, and some Unixes can't handle that. In that case, use xargs(1): pick -to info-tex | xargs refile +tex/info-tex If worse comes to worst, fire up a Bourne shell and use a "while" loop: pick -to info-tex | fmt | while read nums; do refile +tex/info-tex $nums done The fmt(1) command breaks long lines into manageable chunks of 72 characters or so, splitting arguments at whitespace. When you redirect the input of a while loop, a "read" command will read the incoming text and store it in a shell variable line by line. This is a quick-&-dirty way to write xargs(1) if you don't have it. ------------------------------ Subject: 04.04 How can you save News articles into an MH folder? From: Jerry Peek Date: Mon, 1 May 1995 00:00:00 -0800 If your newsreader handles backquotes on its command line, you can use the mhpath command. For instance, if your "save" command is "s": s `mhpath new +somefolder` Or if your newsreader lets you define your own commands, as in shell aliases, you could define that as a command. If your newsreader can pipe an article to the standard input of a program, use the "rcvstore" command (in the MH library). For instance, if your "pipe" command is "|": | $MHLIB/rcvstore +somefolder Of course, you can also put that in a little shell script. ------------------------------ Subject: 04.05 Are there any good tools to archive MH messages? From: Bill Wohler Date: Sun, 23 Sep 2007 18:35:53 -0700 For those of lesser means, I have three shell scripts for archiving, seeking, and extracting MH messages that I had been using for a couple of decades. Send mail if interested. However, now that disk space is cheap and one can index years worth of mail in a minute or two, I haven't run those scripts in a few years. I intend to update them to index and archive a years-worth of mail at some point. Since glimpse is no longer free (as in speech), I've switched to swish++. Other indexing tools (which are also compatible with MH-E) include mairix and namazu. From: glimpse at cs.arizona.edu Date: Sun, 4 Mar 2001 10:26:24 -0800 Glimpse is a very powerful indexing and query system that allows you to search through all your files very quickly. It can be used by individuals for their personal file systems as well as by organizations for large data collections. http://www.webglimpse.org/ ------------------------------ Subject: 04.06 How can I remove duplicate messages? From: Bill Wohler Date: Sun, 17 Oct 2004 13:04:57 -0700 Don't let them get in there in the first place. Add the following to your .promailrc: :0 * ? formail -D 16384 $PM_CACHE/msgid /dev/null If it's too late, you might be interested in mhfinddup, attached below, which is an embellishment of the Perl script in (see "Removing duplicate messages (Perl)"). From: Jerry Peek Date: 20 Nov 1995 18:51:24 GMT The easiest way I know of is to sort the folder by the Message-ID field using the sortm(1) command. After the sort, each message should be next to its duplicates in the folder. Use a script (shell, Perl, etc.) to weed out the duplicates. (See "Removing duplicate messages (Bourne)"). The Perl script in (see "Removing duplicate messages (Perl)") does not require that you first sort the folder. ------------------------------ Subject: 04.07 How can I remove holes in numbering? From: Bill Wohler folder -pack ------------------------------ Subject: 05.00 ***** Composing & Replying ***** From: Bill Wohler Date: Fri, 1 Mar 1991 13:03:15 -0800 ------------------------------ Subject: 05.01 Why does repl add a "Re:" to a message that already has one? From: Larry McVoy Date: Fri, 1 Mar 1991 13:03:15 -0800 I carefully reconfigured and rebuilt MH from scratch and the problem went away. ------------------------------ Subject: 05.02 How do I include messages in repl with or without ">"? From: Richard Coleman Date: Tue, 20 Jan 1998 02:19:58 -0500 In nmh, to include a message in a reply with a leading ">", just use "repl -format". From: Alan Thew , Mike Schwager , James T Perkins Date: Fri, 1 Jan 1993 00:00:00 -0800 When making a reply, specify a filter file on the command line: repl -filter repl.format This filter file must be in your MH mail directory (usually "Mail", in your home directory). Here are a couple of example repl.format files: overflowtext="",overflowoffset=0 message-id:nocomponent,formatfield=\ "In message %{text}, you wrote:" body:component="> ",overflowtext="> ",overflowoffset=0 or overflowtext="",overflowoffset=0 date:component="Your message dated",formatfield=\ "%<(nodate{text})%{text}%|%(pretty{text})%>" body:component="> ",overflowtext="> ",overflowoffset=0 Setting overflowoffset to 0 keeps MH from doing anything to extra-long lines in the headers. In the body, however, this behavior is overridden so that long lines are automatically broken and a ">" is inserted before every line. You could put almost whatever you want between those quotes, although the "standard" ">" makes it easier to read notes that have been included several times. The examples differ with the descriptive text that is inserted before the included body. It is suggested not to use the "prompter" editor in this case, since it is likely that you'll not want to use all of the included message. Indeed, it is proper etiquette to edit out all unnecessary include verbiage so readers don't have to wade through the morass to read your pearls of wisdom. WARNING: the '>' appears on the first line ONLY in versions prior to 6.7.2. Upgrade to MH 6.8. See also MH book sections 7.8.4 (6.7.4), 7.8.5 (6.7.5), 10.4.1 (9.4.1), or the URLs: http://rand-mh.sourceforge.net/book/mh/reprep-2.html#ReaEdi http://rand-mh.sourceforge.net/book/mh/reprep-2.html#Inc http://rand-mh.sourceforge.net/book/mh/verrep.html#IncRep ------------------------------ Subject: 05.03 How can I eliminate duplicate copies of letters to myself? From: Bill Wohler Date: Fri, 1 Mar 1991 13:03:15 -0800 Add these two lines to your MH profile file: Alternate-Mailboxes: user@host1, user@host2, ... repl: -nocc me The Alternate-Mailboxes also tells scan which messages are really from you so that it can place the recipient in the scan line instead of the sender. From: Jerry Peek Date: Fri, 1 Mar 1991 13:03:15 -0800 To get one copy, you can either: - Take out the "-nocc me"... then you'll get exactly one copy of your replies (assuming all your addresses are listed in Alternate-Mailboxes), or - (See also "How can I save a copy of all messages I send?"). For more info, see the man pages comp(1), repl(1), forw(1), dist(1) and mh-mail(5). See also MH book sections 7.8.2 (6.7.2), 9.8 (8.6), or the URLs: http://rand-mh.sourceforge.net/book/mh/reprep-2.html#Sel http://rand-mh.sourceforge.net/book/mh/defmai.html From: Alec Wolman Date: Fri, 1 Mar 1991 13:03:15 -0800 Listing the name of a mailing list in Alternate-Mailboxes is also a convenient way to AVOID automatically cc-ing a mailing list when replying to a person who sent the message to the mailing-list. From: Andre Srinivasan Date: Fri, 24 Jan 1997 09:33:19 -0800 Rather than specify the hostname as part of the mailbox, you can simply specify the username and it will match on any host: Alternate-Mailboxes: asriniva ------------------------------ Subject: 05.04 How can I include my signature? From: Eric W. Ziegast , Hardy Mayer Date: Tue, 1 Nov 1994 00:00:00 -0800 There are several ways. 1) The MH way. 1a) In your Mail directory, create files that include your signature into the format of the message. ~/Mail/components: To: cc: Subject: -------- -- Eric Ziegast ziegast at uunet.uu.net UUNET Technologies uunet!ziegast ~/Mail/replfmt body:component="> ",compwidth=2 :-- :Eric Ziegast ziegast at uunet.uu.net :UUNET Technologies uunet!ziegast To use the replfmt file, add the following to your ~/.mh_profile: repl: -filter replfmt When comp is used, your signature is already there along with my headers. When repl is used, the mhl program takes the body of the letter you're replying to, prepends '> ' to each line and then adds your signature at the end (available after version 6.7). 1b) Create an "editor" which can be called from whatnow to add the signature when desired or create a frontend to post (use the .mh_profile line "postproc: postproc" to call it) that always appends the .signature file before calling post to mail the message. David J. Fiander , David A. Truesdell and Tom Wilmore have sample scripts to do these. From: Jerry Peek Date: Tue, 1 Sep 1992 00:00:00 -0800 1c) mysend, a sendproc script, processes a message after "What now? send". See "What references exist for MH" to see where the MH book scripts can be ftped from. The script is explained in MH book Section 7.1.4 (13.13), or the URL: http://rand-mh.sourceforge.net/book/mh/senove.html#ASAtDm 2) Using your editor. If you use vi, you can use something like: map S :r ~/.signature to load your signature out of .signature every time you hit 'S'. 3) Use your windowing system. xterm, for example, can provide key and button mappings for the utterly lazy. 4) If you use Emacs with MH-E: 4a) C-c C-s will append the signature. From: Andre Srinivasan Date: Mon, 1 May 1995 00:00:00 -0800 4b) Add the following to your .emacs file: (add-hook 'mh-compose-letter-function (function (lambda(a b c) (save-excursion (goto-char (point-max)) (beginning-of-line) (mh-insert-signature))))) This hook is called after the draft buffer has been initialized, but before you have a chance to type anything. From: Tom Christiansen Date: Tue, 1 Nov 1994 00:00:00 -0800 Tired of the same old signature? Want different signatures for different newsgroups? Here's a program to help you out. The way it works is to have .signature be a named pipe, so if you don't have named pipes, just say 'n'. The sigrand program then feeds stuff down the pipe every time someone wants to read it. That way it works for more than just news, but for anything that wants to read your .signature, like a mailer. You have your choice of three kinds of signatures: 1) random (short) fortune from "fortune -s"; you get these if you don't have a global sig file. 2) random fortune from ~/News/SIGNATURES [global sig file] 3) random fortune form ~/News/(newsgroup)/SIGNATURES [local sig files] Send mail if interested. Date: Tue, 1 Nov 1994 00:00:00 -0800 See also the Signature FAQ (see "What references exist for MH?"). ------------------------------ Subject: 05.05 How do I call my editor with arguments? From: John Romine Date: Mon, 1 May 1995 00:00:00 -0800 Set your editor (in .mh_profile) to the following shellscript. #/bin/sh "$@" exit 0 From: Ray Nickson Date: Fri, 1 Mar 1991 13:03:15 -0800 You might find it useful to make $EDITOR, or to use different arguments depending on your EDITOR environment variable. ------------------------------ Subject: 05.06 How can I digestify messages in a folder for mail to another user? From: Jerry Peek , Bill Wohler Date: Fri, 1 Mar 1991 13:03:15 -0800 How about: forw [-digest tmp] [-form forwcomps] [-filter mhl.digest] messages +folder These messages can be un-digestified :-) by the MH burst(1) program. See also MH book sections 7.9.7 (6.8.7), 8.10 (7.9), or the URLs: http://rand-mh.sourceforge.net/book/mh/forfor-2.html#CreDig http://rand-mh.sourceforge.net/book/mh/burdig.html From: Glenn Vanderburg Date: Tue, 1 Nov 1994 00:00:00 -0800 There's another way, which is better if the recipient understands MIME. forw -mime messages +folder (Make sure that you either have "automhnproc: mhn" in your mh profile, or type "edit mhn" to whatnow before you send it.) This bundles each message in a MIME message/rfc822 part, and then bundles the whole mess up in a multipart/digest part. You can still add your own text at the beginning. The MH burst program can also understand these messages and split them apart with no problem. This works beautifully with MIME-capable mail readers, especially exmh. ------------------------------ Subject: 05.07 How can I change my return address? From: Bill Wohler Date: Tue, 1 Dec 1992 00:00:00 -0800 If you find that your mailer creates a From header that others have trouble replying to, you can add a Reply-To header to override the From header in replies. Copy the components and replcomps files which are normally found in $MHLIB into your Mail directory and add a line like the following after the Subject header replacing my address with your address: Reply-To: jack@newt.com ------------------------------ Subject: 05.08 How can I change my From header? From: Bill Wohler Date: Mon, 27 Nov 1995 11:40:50 -0800 With either of the following solutions, you'll need to add an Alternate-Mailboxes entry in your MH profile so that scan prints "To: recipient" rather than your faked address. For example, if your real address is user@somedomain.com and you've added a From field of: From: Joe Bob you'll add the following to .mh_profile: Alternate-Mailboxes: joe.bob@somedomain.com From: Bill Wisner Date: Tue, 1 Dec 1992 00:00:00 -0800 If you're just interested in changing the hostname, add a line to $MHLIB/mts.conf (mtstailor): localname: desired_host_name From: Jerry Peek Date: Tue, 1 Dec 1992 00:00:00 -0800 Just put a "From:" header in your "components", "replcomps" and "forwcomps" files. MH will add a "Sender:" header with what it thinks is your real address. ------------------------------ Subject: 05.09 How can I save a copy of all messages I send? From: Ping Huang Date: Mon, 18 Dec 1995 17:51:33 -0800 I suggest the use of the Dcc: field (See "What is the Dcc header?"), since the use of "Dcc:" solves the issue of having the same Message-Id. The warning about using Dcc: in general contexts doesn't apply to self-blind-carbon copies, and if "Dcc:" is used and you are automatically sorting messages into folders based on mailing lists, messages which you send will get refiled in the same way. Some may prefer all outgoing messages to be segregated; others (including myself) prefer not to segregate outgoing messages. From: Bill Wohler , Jerry Peek Date: Mon, 1 Aug 1994 00:00:00 -0800 Copy the components and replcomps files which are normally found in $MHLIB into your Mail directory and add a line like the following after the cc header: Fcc: +out All outgoing messages will then be saved in the +out folder. If you make a distcomps file, it needs "Resent-Fcc:". From: Jeppe Sigbrandt Date: Sat, 5 Apr 1997 02:04:53 +0100 You can also use @ in the Fcc field to file the outgoing message in the current folder. Fcc: @ This is useful if you filter your mail (e.g., with procmail) and you read your mail in folders other than +inbox. From: David S. Goldberg Date: 30 Oct 1995 10:23:55 -0500 You can get the Message-ID field by placing the folder in the "Fcc" field and adding: send: -msgid to your .mh_profile. Unfortunately, this Message-ID isn't as useful as sendmail's--it doesn't include the date. ------------------------------ Subject: 05.10 Can the folder in Fcc: be dynamically specified? From: Andy Rabagliati Date: Mon, 1 Aug 1994 00:00:00 -0800 My suggestion would be to run Tom Christiansen's rfi script. If you cannot find it on *.sources archive sites (please try first), I can mail it to you. One good idea would be to write a whatnowproc that files the mail based on a procmail or deliver file. Then you can use the same file for incoming and outgoing mail. ------------------------------ Subject: 05.11 Can I post secure/encryped mail? From: Bill Wohler Date: Thu, 19 May 2005 18:06:39 -0700 MH-E 7.0 supports GPG out of the box. From: Bill Wohler Date: Mon, 5 Mar 2001 05:30:43 -0800 PGP keys can be obtained via mail from , and via the Web at http://www.pgp.net/pgpnet/pks-commands.html. Many PGP front-ends (e.g., mailcrypt) automatically obtain keys for you. See http://www.pgp.net/ for more info. From: Vivek Khera Date: 19 Jun 1995 22:06:37 GMT A much more robust Perl script I wrote is appended below. [Send a note to Vivek for the script. --Ed] It works its way through aliases, and avoids problems with full names in the headers. Here is my mhn profile entry to display the messages. mhshow-show-application/x-pgp: %l pgp -m '%F' # nmh mhn-show-application/x-pgp: %l pgp -m '%F' # MH to use the script, after you edit the message, at the What now? prompt, type "edit pgpmail" for plain ascii encryption or "pgpmail -m" for a MIME formatted encryption. If you want to add a digital signature, give the script the -s flag also. From: Jeffrey C. Ollie Date: Mon, 1 May 1995 00:00:00 -0800 TIS has a free, draft-standard compliant public key system that works with MH (PEM). Check it out on ftp.tis.com. From: Kimmo Suominen Date: Mon, 1 May 1995 00:00:00 -0800 You could try looking at the URL http://www.tac.nyc.ny.us/ and following the link from the cover page. Everything you need for PGP to work with MH is there (scripts and mhn entries). From: mathew at mantis.co.uk Date: Mon, 1 May 1995 00:00:00 -0800 Excellent stuff. I've tried altering it to conform to draft-borenstein-pgp-mime-00.txt. Unfortunately, I can't get mhn to tag PGP-armoured text as application/pgp; format=text without it insisting on base64 encoding it. So I can't quite manage to implement the standard. *sigh* Presumably mhn thinks that anything which isn't text/* must be encoded. From: John R MacMillan Date: Wed, 16 Apr 1997 00:06:59 -0700 Premail, in conjunction with MH, can display and compose security multiparts (e.g., multipart/signed and multipart/encrypted PGP mail, non-MIME PGP, and some S/MIME). Check out http://www.c2.org/~raph/premail/ for details. ------------------------------ Subject: 05.12 How can I send multi-media (MIME) attachments? From: Brian Exelbierd Date: Mon, 09 Oct 1995 08:05:55 -0400 The short guide: 1. Compose a letter using comp. 2. When you get to a point where you want to include a MIME attachment, type the following to include a GIF image (note: the '#' must be in the first column): #image/gif [Pictures at an Exhibition] /usr/lib/pictures/exhibition.gif 3. Finish your letter, adding more text or attachments as needed. 4. Save your letter and exit the editor. At the Whatnow prompt type "edit mhn". mhn will automatically format your letter with the MIME attachments leaving the original letter in ,##,orig where ## is the letter number. 5. Type "send" at the Whatnow prompt, and poof, you have just sent MIME mail. I strongly recommend you practice sending yourself MIME mail first. For more information, see the mhn(1) man page, ftp://ftp.isi.edu/in-notes/iana/assignments/media-types/media-types for a list of allowed media types in addition to image/gif, and Chapter 3 in the MH book or the URL: http://rand-mh.sourceforge.net/book/overall/tocs/intmime.html ------------------------------ Subject: 05.13 What's the best way to send mail to a long list of people? From: Bill Wohler Date: Thu, 12 Oct 1995 07:53:53 -0700 There are three ways to keep the list of members from appearing in everyone's header. If you're planning on mailing to these people regularly, the best way is to create an alias in /etc/aliases (/usr/lib/aliases). That way, recipients can send and reply to the list as well. The other two ways allow you to manage the list privately, but the recipients cannot send to the list (unless you set something up with your deliver or procmail script). One is with a group list. It looks like this: To: All-members: member1, member2, member3, ..., membern; The recipients see this: To: All-members:; You can make this an MH alias as well. The second way is to use a blind carbon copy (see "How do I send blind carbon copies?"). Or you could also use the undocumented Dcc field which is used like the Bcc field, but doesn't inject the "Blind-Carbon-Copy." Warning: (See "What is the Dcc header?") ------------------------------ Subject: 05.14 What is the Dcc header? From: jpeek at jpeek.com (Jerry Peek) Date: 14 Sep 96 05:51:13 GMT If you put the alias in the Dcc field and leave the To: field empty, there's a good chance that the recipients will get a message with the header field: Apparently-to: and it might even list several addresses. To avoid that, use a To: field with some address (like yours) in it. I use a comment that tells people what's really happening--like this, more or less: To: "Faculty members, c/o" dcc: faculty There are some other choices, like using an un-replyable group list in the To: field, but I think they tend to confuse non-techies. Date: Wed, 27 Sep 1995 09:46:37 -0700 From: John Romine The Dcc (Distribution Carbon Copy) field behaves much like the Bcc field, but does not add the "Blind-Carbon-Copy" notice. This header is removed before posting the message,and a copy of the message is distributed to each listed address. This could be considered a form of Blind Carbon Copy which is best used for sending to an address which would never reply (such as an auto-archiver). People should not be using Dcc as a substitute-Bcc to send to other people. When users use Dcc as a substitute for Bcc, there is *no* indication to the "blind" recipients that they have received a blind copy. If those recipients should reply (and they have no indication why they shouldn't), the original author could be very embarassed (or worse). ------------------------------ Subject: 05.15 How can I make sense of the replcomps file? From: Bill Wohler Date: Thu, 9 Mar 2006 19:27:14 -0800 The best thing to do is curl up with the mh-format(5) man page, or Section 11.2 of the MH book, or the URL: http://rand-mh.sourceforge.net/book/mh/mhstr.html These will explain the default replcomps file, included here. Don't start with the first four lines--the latter group of lines are much easier to understand. %; $Header: /cvsroot/nmh/nmh/etc/replcomps,v 1.3.2.1 2003/10/24 20:14:46 kenh Exp $ %; %; These next lines slurp in lots of addresses for To: and cc:. %; Use with repl -query or else you may get flooded with addresses! %; %; If no To:/cc:/Fcc: text, we output empty fields for prompter to fill in. %; %(lit)%(formataddr{reply-to})\ %(formataddr %<{from}%(void{from})%|%(void{apparently-from})%>)\ %(formataddr{resent-to})\ %(formataddr{prev-resent-to})\ %(formataddr{x-to})\ %(formataddr{apparently-to})\ %(void(width))%(putaddr To: ) %(lit)%(formataddr{to})\ %(formataddr{cc})\ %(formataddr{x-cc})\ %(formataddr{resent-cc})\ %(formataddr{prev-resent-cc})\ %(formataddr(me))\ %(void(width))%(putaddr cc: ) Fcc: %<{fcc}%{fcc}%|+outbox%> Subject: %<{subject}Re: %{subject}%> %; %; Make References: and In-reply-to: fields for threading. %; Use (void), (trim) and (putstr) to eat trailing whitespace. %; %<{message-id}In-reply-to: %{message-id}\n%>\ %<{message-id}References: \ %<{references}%(void{references})%(trim)%(putstr) %>\ %(void{message-id})%(trim)%(putstr)\n%>\ Comments: In-reply-to \ %<{from}%(void{from})%?(void{apparently-from})%|%(void{sender})%>\ %(trim)%(putstr)\n\ message dated "%<(nodate{date})%{date}%|%(tws{date})%>." -------- In particular, note the following: \ consider the following line to be part of the current line. If this continuation character is absent, a newline (\n) will always be inserted. Note that if the field is conditional, and the condition is false, and there isn't a trailing backslash, then a blank line will appear in your reply. Since the rest of the header will now be considered to be part of the body, this is probably not what you want. \n inject an actual newline into the reply. Note that inserting a field without a trailing backslash (\) will cause that field to be emitted in the reply as well. %<{field}, %?{field}, %|, %> if field exists, else if field exists, else, endif. Conditional fields nearly always contain an explicit newline (\n) and end with a continuation character (\). %(command) mh-format commands %{field} value of the header field inserted at this point To add new fields, you can either add fields based on whether certain fields exist in the original message (e.g., %<{message-id}...), or hard-code them, as in the Fcc, Subject, or Comments fields above. ------------------------------ Subject: 05.16 How can I convert quoted-printable to 8bit in quoted text in replies? From: Jarle F. Greipsland Date: 22 Aug 1995 10:42:07 +0200 The idea behind the solution is that I need mhn to store the contents of the mail in the native iso8859-1 format somewhere. I did this by creating a custom editor that is invoked when I reply to a message. This editor extracts the body of the message (sorry, no multipart stuff), indents it with '> ', appends it to the draft message and invokes the ordinary editor on it. Here are the details: `isorepl' is a symbolic link from my $HOME/bin-directory to `repl'. In my .mh_profile I added the following two lines: isorepl: -form isoreplcomps -editor isoextract isoextract-next: vi The isoreplcomps file in my Mail-directory contains: %(lit)%(formataddr %<{reply-to}%?{from}%?{sender}%?{return-path}%>)\ %<(nonnull)%(void(width))%(putaddr To: )\n%>\ %(lit)%(formataddr{to})%(formataddr{cc})%(formataddr(me))\ %<(nonnull)%(void(width))%(putaddr cc: )\n%>\ %<{fcc}Fcc: %{fcc}\n%>\ %<{subject}Subject: Re: %{subject}\n%>\ %<{date}In-reply-to: Your message of "\ %<(nodate{date})%{date}%|%(pretty{date})%>."%<{message-id} %{message-id}%>\n%>\ -------- #\ %<{from}%(friendly{from}) writes%|You write%>: This is a "Usenet-like" quoting style. Modify to suit your own taste. This form will setup the proper header, as well as the first line of the new message (In nnnn writes etc.). The first editor, `isoextract', looks like this: #!/bin/sh # # Called from within repl where the "editalt" variable is valid # # Point to a special MHN configuration file (save old one) OLDMHN="$MHN" MHN=$HOME/`mhparam Path`/isoquotemsg export MHN # Extract message body to "native" format (should be iso-8859-1) # > More bla bla. mhn -file "$editalt" -store >> $1 2>/dev/null MHN="$OLDMHN" myname=`basename $0` next=`mhparam ${myname}-next` if [ "x$next" != "x" ]; then exec $next "$@" fi `isoquotemsg' has just one rule; how mhn should store a text message. mhn-store-text: |sed -e 's/^[ ]*$//' \ -e 's/^\([>|]\)\(.*\)$/>\1\2/' \ -e 's/^\([^>|].*\)$/> \1/' This tells mhn to pipe the message to stdout, where the sed commands will do the reformatting/quoting. (Note: the first pair of square brackets contains a space and a tab.) So, when I do a `isorepl' to a message, `repl' will create the draft message with the proper headers (based on the `isoreplcomps' format file), fire off its first editor, `isoextract', with the name of the draft file as its parameter. `isoextract' then invokes mhn in a suitable environment, tells it that it is to use the file $editalt as its source, and orders it to store the contents. The store-text rule in the custom MHN-file tells it to just pipe the message (in native iso8859-1 form) through a small set of sed commands, and `isoextract' uses the normal shell construct to append the result to the draft file. Then, if there's defined a `isoextract-next' entry in the .mh_profile, isoextract exec's this editor. ------------------------------ Subject: 05.17 Can I have aliases include aliases? From: Bruce Cox Date: Fri, 16 Aug 1996 14:26:12 +1000 Indeed, you can. You just need to remember the way MH expands aliases. In particular, the right hand sides are only expanded by the aliases below them in your aliases file. So, if you put in: dead-men: presidents, authors presidents: washington, lincoln, jefferson, roosevelt authors: thoreau, irving, london and type: ali dead-men then you would get the response: washington, lincoln, jefferson, roosevelt, thoreau, irving, london If you had the dead-men line after the presidents and authors aliases, the response would be: presidents, authors ------------------------------ Subject: 05.18 Why doesn't mhmail understand aliases? From: "John L. Romine" Date: 25 Apr 1996 16:34:10 GMT One way that mhmail might be run is from a shell script. This means that the user running it might not use MH, and would not have a .mh_profile, etc. If you want to use aliases with mhmail, expand them before passing them as arguments (e.g., "mhmail `ali joe`"). ------------------------------ Subject: 05.19 How do I send blind carbon copies? From: Bill Wohler Date: Mon, 9 Sep 1996 00:32:14 -0700 Use the Bcc header field: To: your-address-here Bcc: member1, member2, member3, ..., membern The recipients see this: To: your-address-here ------- Blind-Carbon-Copy Content of message, with headers If you don't want the "Blind-Carbon-Copy" message, use the Dcc field, but this is discouraged in true blind carbon copies since the warning may prevent the recipient from embarrassing someone inadvertently. Read the warning in (see "What is the Dcc header?"). ------------------------------ Subject: 05.20 When I forward a message, can I use its Subject? From: Jerry Peek Date: Sun, 17 Nov 1996 20:16:31 -0800 Obtain forwedit. http://rand-mh.sourceforge.net/book/examples/mh/bin/forwedit ------------------------------ Subject: 05.21 Why is the timezone field in my 'Date:' field wrong? From: Alex Tomlinson Date: Wed, 11 Jun 1997 09:16:41 -0500 If the date field in your mail header looks like this: Date: Tue, 10 Jun 1997 15:59:03 +2228904 remove -lbsd from your MH configuration, add "curses -lcurses", and rebuild. ------------------------------ Subject: 05.22 Can I automate the comp -editor mhn process? From: Soren Dayton Date: Tue, 21 Jan 1997 17:23:32 GMT Add automhnproc: mhn to your MH profile. ------------------------------ Subject: 05.23 How can I remove those "=20" characters when forwarding? From: Dave Marquardt Date: 12 Oct 2000 10:27:38 -0500 Use `forw -mime'. ------------------------------ Subject: 05.24 Can I use mh-format substitution with forw? From: Dave Marquardt Date: Tue, 3 Aug 1999 13:28:30 -0500 (EST) The answer is no, and the real question is why not? ------------------------------ Subject: 05.25 How can I keep repl from breaking long lines? From: Jerry Peek Date: Fri, 14 May 1999 11:15:07 -0400 Try adding width=10000 (or so) to your replcomps. It should work unless you have messages with lines longer than that... ------------------------------ Subject: 05.26 How do I fix a bogus In-Reply-To or missing References field? From: Bill Wohler Date: Thu, 9 Mar 2006 21:42:21 -0800 In the past, the In-reply-to header field looked as it does in the new Comments field (see "How can I make sense of the replcomps file?"). However, the old format is no longer allowable under RFC 2822 which specifies that this field should only include the Message-ID. You can fix the replcomps and replgroupcomps files by upgrading to nmh 1.1 (be sure to update your personal copies if applicable) or simply by fixing the In-reply-to field in your own replcomps file using the example in the question referenced in this paragraph. In addition, older replcomps files lacked the References field which enables threading in capable UIs. You can get it in the same fashion as the In-reply-to field--by upgrading or copying. ------------------------------ Subject: 06.00 ***** Posting ***** From: Bill Wohler Date: Fri, 1 Mar 1991 13:03:15 -0800 ------------------------------ Subject: 06.01 What to do with "Problems with edit - draft removed". From: John Romine Date: Mon, 1 May 1995 00:00:00 -0800 If your users are using an AT&T version of "vi", it's exiting with non-zero status (supposedly a count of the "errors" during the edit). Move "vi" to "broken_vi" and put it its place : #! /bin/sh /usr/ucb/broken_vi "$@" exit 0 Alternatively, compile MH with the ATTVIBUG option. Then complain to your vendor that "vi" is broken, and they shouldfix it. ------------------------------ Subject: 06.02 Can I run my message through a program (e.g., ispell) before sending? From: Jerry Peek Date: Fri, 1 Mar 1991 13:03:15 -0800 It's pretty simple. If your speller is called myspell, use: What now? edit myspell MH will actually execute: myspell /your-mail-draft-directory/draftfile and give the entire draft message to your speller. The header will probably be "misspelled," of course, though you might be able to tell the speller to ignore it--or you could hack up a little shell script to run the speller on just the message body, then tack the corrected body back onto the header before sending. You can automate this some more. For example, if you want your speller to run after your first edit with "prompter" and also after you leave the "vi" editor, add these lines to your MH profile: prompter-next: myspell vi-next: myspell Then, at the "What now?" prompt: What now? e your speller will run. For more info, see the mh-profile(5) man page or section 7.2.1 (6.2.1) of the MH book, or the URL: http://rand-mh.sourceforge.net/book/mh/chaedi.html#Edi ------------------------------ Subject: 06.03 What to do with "bad address 'xxx' - no at-sign after local-part". From: Owen Rees Date: Fri, 1 Jan 1993 00:00:00 -0800 You may find that post returns the following message: post: bad address 'Mr. Foo Bar ' - no at-sign after local-part (Bar), continuing... The unquoted dot causes "Mr. Foo" to be parsed as the local part of the address. Either remove the dot, or rewrite the address as follows: "Mr. Foo Bar" (Mr. Foo Bar) (Mr. Foo Bar) fb@somewhere.edu ------------------------------ Subject: !06.04 Fixing "post: problem initializing server; [BHST] no servers available" From: Peter Marvit , Eric Bracken Date: Tue, 1 Nov 1994 00:00:00 -0800 The error message itself is essentially correct. However, what this really means is: MH's post cannot connect to a running sendmail over an SMTP port (MH configured with SMTP and SENDMTS). The potential problems: 1. Your local sendmail daemon is dying or not running for some reason. 2. You use BIND and your local nameserver is not responding. Solution: Delete "/etc/resolv.conf." 3. Your $MHLIB/mts.conf (mtstailor) has its "servers:" pointing to a non-existent machine or a machine which is a) not reachable or b) not running the sendmail daemon. From: Bdale Garbee , Eric Bracken Date: Sun, 1 May 1994 00:00:00 -0800 4. The hostname localhost [127.0.0.1] is missing from /etc/hosts. Solution: add an entry for "localhost" to /etc/hosts or your DNS database or add the following to $MHLIB/mts.conf (mtstailor): servers: 127.0.0.1 \01localnet From: David Levine Date: Sun Sep 30 22:47:12 CDT 2012 From: Larry Daffner Date: 3 Mar 1996 14:39:54 -0600 5. Your load average is so high that sendmail is refusing connections. Solution: Change your configuration from "mts: smtp" to "mts: sendmail" (after nmh 1.5, "mts: sendmail/smtp" or "mts: sendmail/pipe") so that a sendmail processes is spawned to deliver the message. This is a double-edged sword since the extra process only makes the load worse. From: Neil W Rickert Date: 13 Apr 2001 18:47:43 -0500 8. You don't want to use an available server. See David Levine's answer in Fixing "post: problem initializing server; [BHST] premature end-of-file on socket." ------------------------------ Subject: 06.05 Fixing "post: problem initializing server; [RPLY] 503 Sender already specified" From: Paul Pomes Date: Mon, 1 Mar 1993 00:00:00 -0800 The problem in sendmail is that the RSET after the ONEX does not reset all the state information. Normally sendmail fork()s after the Mail from: statement and a RSET causes that child to exit. This automatically cleans up. If the fork() is suppressed by ONEX, then the source must be modified to do the cleanup. See "srvrsmtp.c patch" in the Appendix. If you don't have the sources, modify your MH sources to not use the ONEX verb. ------------------------------ Subject: 06.06 Fixing "post: unexpected response; [BHST] no socket opened" From: Steve Lembark , Bill Wohler Date: Mon, 1 Aug 1994 00:00:00 -0800 This problem happens when there is no interface defined within the tcp system. A couple of workarounds include: o Use a hostname (other than the local host) instead of localhost in the "servers" entry of the $MHLIB/mts.conf (mtstailor) file. o Recompile MH with sendmail instead of sendmail/smtp (not very elegant). A better fix would be to define your tcp interface. Here, you run ifconfig and route (as root) to define the loopback device and route. You should add them to rc.local so they are effected at every boot. # ifconfig lo 127.0.0.1 # Linux # ifconfig lo0 127.0.0.1 # Sun # route 127.0.0.1 If all is well, "ifconfig lo" (or lo0), will show something like this (on my Linux system): lo Link encap Local Loopback inet addr 127.0.0.1 Bcast 127.255.255.255 Mask 255.0.0.0 UP LOOPBACK RUNNING MTU 2000 Metric 0 RX packets 0 errors 0 dropped 0 overrun 0 TX packets 519 errors 0 dropped 0 overrun 0 and "netstat -r" will show: # netstat -r Destination net/address Gateway address Flags RefCnt Use Iface 127.0.0.0 * UN 0 519 lo If you're not on a network and running DNS, your /etc/hosts will need at least: 127.0.0.1 your_host_name localhost # loopback address Note: put your name FIRST on the localhost line. This official name is used by sendmail to determine your return address. If you are on a network and running DNS, you might find that putting your host name in the localhost entry might gum up other things, in which case you'll want your hostname to have its own proper address. This might not do it though. David Youatt says that his network was happy but he still had the problem until he upgraded his system and got the latest revision of sendmail as well. He says: "Turns out that that the problem I was having seems to be caused (at least partly, maybe entirely) by the version of sendmail that is shipped with IRIX 5.2 (sendmail 5.65, I think). The version shipped w/IRIX 5.3 (in beta) is sendmail 8.6.9 and works fine." I'm not entirely happy with this section, so please give me some feedback. If you have this problem, please send me a brief description so I'll know which problems and solutions seem to be the most prevalent. ------------------------------ Subject: 06.07 How do I fix the "X-Authentication-Warning" header? From: Bill Wohler Date: Mon, 9 Sep 1996 01:32:15 -0700 (See "Fixing "Sender didn't use the HELO protocol"".) ------------------------------ Subject: 06.08 Fixing "post: unexpected response; [RPLY] 503 Need MAIL before RCPT" From: Bjoern Stabell Date: Mon, 1 May 1995 00:00:00 -0800 I inserted: clientname: localhost in the $MHLIB/mts.conf (mtstailor) file, and that fixed the problem. ------------------------------ Subject: !06.09 Fixing "post: problem initializing server; [BHST] premature end-of-file on socket" From: David Levine Date: Sun Sep 30 22:52:46 CDT 2012 To use a different SMTP server temporarily (after nmh 1.5): What now? send -server smtp.example.com Use the name or address of your SMTP server, of course. Alternatively, if you can use your local sendmail program, then enable that by one of these methods: 1. Change the mts setting in your mts.conf to: mts: sendmail/pipe 2. Add the mts setting to a send entry in your profile. For example, send: -mts sendmail/pipe 3. Override the mts setting temporarily: What now? send -mts sendmail/pipe 4. Add the following to your profile: postproc: $MHLIB/spost This is the only available solution if you are running a version of MH other than nmh 1.5 and higher. However, the use of spost is discouraged because: a) It requires the local sendmail to be configured for delivery to all possible addresses. This may not be as common as it used to be, as it is limited by many ISPs. b) spost and blind MH aliases turn out to be a potentially dangerous combination: spost expands them as if they weren't blind, so all recipients see them. From: Ginko Date: Thu, 8 Mar 2001 09:18:14 +0000 (UTC) I have sendmail under control of tcpwrapper started by inetd and didn't want to take it away, the very simple fix to this problem was to allow the localhost on /etc/hosts.allow on the sendmail entry. From: Chuck Mattern Date: Mon, 1 May 1995 00:00:00 -0800 If you are running sendmail instead of smail, make sure that all smtp entries in /etc/inetd.conf are commented out. If you do edit /etc/inetd.conf, don't forget to run to restart inetd with "kill -1 ". ------------------------------ Subject: 06.10 Fixing "Sender didn't use the HELO protocol" From: rickert at cs.niu.edu (Neil Rickert) Date: Tue, 20 Mar 2001 22:01:16 -0800 If you are sharing your $MHLIB/mts.conf (mtstailor) file among several machines, and you are connecting to the local sendmail, then use 'localhost' as the hostname argument to the clientname parameter (described below). Otherwise, place mts.conf somewhere under /etc on each system, and install a symlink to it on the shared file system. From: labrown at dg-rtp.dg.com (Lance A. Brown) Date: 23 Apr 1996 14:43:04 -0400 You can solve this by putting localname: localhostname localdomain: local.domain.name in your $MHLIB/mts.conf (mtstailor) file. This will make MH send a HELO string in the SMTP transaction. From: Terry Manderson Date: Mon, 1 May 1995 00:00:00 -0800 Add clientname sender to $MHLIB/mts.conf (mtstailor) where sender is the name of the machine sending the message. The error message occurs because newer MTA's require SMTP's "HELO" command which MH omits in some configurations. When you add the above line, it forces MH to use the HELO command. From: Bill Wohler Date: Fri, 1 Mar 1991 13:03:15 -0800 You get a header like: X-Authentication-Warning: screamer.rtp.ericsson.se: Host rcur7.rtp.ericsson.se didn't use HELO protocol Easy possibilities are: apply the patch to MH that comes with Sendmail 8.X.X and makes it use HELO, or comment out the line that says Opauthwarnings in your sendmail.cf. ------------------------------ Subject: 06.11 Fixing "post: problem initializing server; [RPLY] 553 Local configuration error, hostname not recognized as local" From: "Matthew V. J. Whalen" Date: Mon, 1 May 1995 00:00:00 -0800 Change your "mts" in "conf/MH" from "sendmail/smtp" to just "sendmail." From: Bill Wohler Date: Mon, 1 May 1995 00:00:00 -0800 The solution above will keep MH from using any SMTP server on your network. require sendmail to be installed on all machines. You could take advantage of the "sendmail/smtp" option to have MH talk to a non-local sendmail. In $MHLIB/mts.conf (mtstailor) add: servers It may also be caused by old versions of sendmail. ------------------------------ Subject: 07.00 ***** Mail Filters ***** From: Bill Wohler Date: Fri, 1 Mar 1991 13:03:15 -0800 ------------------------------ Subject: 07.01 What mail filters are available? From: Bill Wohler Date: Sun, 11 Mar 2001 10:27:24 -0800 The list currently includes slocal (included with MH), deliver, procmail and mailagent. They are briefly described here. Slocal is probably the most popular by virtue of being included in the distribution. The next most popular entry is procmail, followed by deliver. Slocal comes with MH. It can be used to process incoming mail based on the contents of any of the headers. Actions include filing messages, running commands, printing messages on your terminal and so on. The configuration is made in ~/.maildelivery. People seem to have trouble with slocal bugs, and you can't use it if you don't have write permission on your system maildrop so a lot of people have opted for the alternatives, but it's easy to use and comes with MH. procmail is quite popular and has a very powerful configuration file. However, the syntax is its own, but it is easy to learn given a couple of good examples. Its advantages are its small size and speed. Like deliver, procmail may be installed as a delivery agent so you would not even have to have a .forward file. Deliver can run any script or program (called ~/.deliver), so you really can do anything you want to incoming mail. One feature that it sports that no other does is that you can install it as a local mailer in place of /bin/mail. If it's the local mailer, you don't need to have a .forward--~/.deliver is run anyway. In addition, it allows the system administrator to write some programs to filter everybody's mail. It came with my Linux system, so installation was non-existent. I started with slocal, and then moved to deliver. I switched to procmail because of a bug in deliver (which I think has since been fixed) whereby a blank line would be inserted into the header before header fields with numbers in them. I am still using procmail and probably will do so indefinitely since it is powerful, there are many spam filters written in it, and it coexists with MH and Gnus so well. My recommendation is to use the one that is installed on your system or get procmail. Here are the URLs for the filters mentioned in this document: http://www.procmail.org/ From: "Eric D. Friedman" Date: 28 Aug 1996 08:28:46 GMT See http://www.faqs.org/faqs/mail/filtering-faq/index.html. From: Stephen R. van den Berg Date: Mon, 1 Aug 1994 00:00:00 -0800 Procmail can be used to create mail-servers, mailing lists, sort your incoming mail into separate folders/files (real convenient when subscribing to one or more mailing lists or for prioritizing your mail), preprocess your mail, start any programs upon mail arrival (e.g. to generate different chimes on your workstation for different types of mail) or selectively forward certain incoming mail automatically to someone. From: Raphael Manfredi Date: Tue, 28 Jul 1998 13:22:07 +0200 "mailagent" is yet another mail filter, written in perl, which will let you do anything with your mail. It has all the features you may expect from a filter: mailing lists sorting, forwarding to MTA or to inews, pre-processing of message before saving into folder, vacation mode, etc. It was initially written as an Elm-filter replacement, but has now enough power to also supplant MMDF's .maildelivery. There is also a support for @SH mail hooks, which allows you to automatically distribute patches or software via command mails. The mailagent was designed to make mail filtering as easy as it can be. It is highly configurable and fairly complete. Rules are specified in a lex-like style, with the full power of perl's regular expressions. The automaton supports the notion of mode, and header selection has many magic features built-in, to ease the rule writing process. The distribution comes with a set of examples, an exhaustive test suite, and naturally a detailed manual page. It should be noted that the mailagent will work even if your system administrator forbids "| programs" hooks in the ~/.forward, provided you have access to some sort of cron daemon. http://www.cpan.org/authors/Raphael_Manfredi/ ------------------------------ Subject: 07.02 Why slocal writes messages to system mailbox that from(1) can't read. From: Bill Wohler Date: Mon, 1 May 1995 00:00:00 -0800 Upgrade to MH 6.8 and set the RPATHS option. Better yet, use a more MH-like command instead of from: "scan -file $MAIL". ------------------------------ Subject: 07.03 Where can I read about slocal and the format of .maildelivery? From: Bill Wohler Date: Fri, 1 Mar 1991 13:03:15 -0800 See the slocal man page. Here is brief example of a .maildelivery file that stores messages to babble in a folder and the system mailbox, stores mh-users in a folder but not the system mailbox, and puts the rest in the system mailbox. to mh-users | A "$MHLIB/rcvstore -create +lists/mh-users" cc mh-users | A "$MHLIB/rcvstore -create +lists/mh-users" to babble | R "$MHLIB/rcvstore -create +lists/babble" cc babble | R "$MHLIB/rcvstore -create +lists/babble" default - > ? /usr/spool/mail/wohler Your .forward file may look like (quotes necessary): "| $MHLIB/slocal -user your_login" In some implementations, the "-user your_login" is not needed. If not, manually running slocal with the flag will produce an error. See also chapter 12 (11) in the MH book, or the URL: http://rand-mh.sourceforge.net/book/mh/tocs/prmaau.html Alternatives to slocal include deliver, procmail, and mailagent. (See "What mail filters are available?") ------------------------------ Subject: 07.04 How do I debug my .maildelivery file? From: Bill Wohler Date: Mon, 1 Mar 1993 00:00:00 -0800 Use as many of the following as necessary. Put a message into a file and call slocal directly on it. $MHLIB/slocal -user $USER -verbose -debug < test-msg Modify your .forward to look like: "|/bin/sh -c 'exec >> /tmp/out 2>&1; $MHLIB/slocal -user $USER -verbose -debug'" Or modify a rule in .maildelivery to look like this: to foo | R "set -xv; exec >/tmp/out 2>&1; $MHLIB/rcvstore +foo" The previous examples are broken up for readability; the text must appear on one line. See also MH book section 12.11 (11.11), or the URL: http://rand-mh.sourceforge.net/book/mh/debugti.html ------------------------------ Subject: 07.05 Why isn't slocal working? From: Bill Wohler Date: Mon, 1 Mar 1993 00:00:00 -0800 If slocal doesn't appear to be doing anything, run the following $MHLIB/slocal -user your_login -verbose < file where "file" is some message in a mail folder. If you get something like: .maildelivery: ownership/modes bad (0, 154,154,0100666) your .maildelivery is writable by too many people. Make it writable only by you by running "chmod 644 .maildelivery". See also "How do I debug my .maildelivery file?" ------------------------------ Subject: 07.06 Are there any good biff applications for MH? From: Rob Austein Date: Tue, 01 Dec 1998 03:02:34 -0500 I've been been using a program called xlbiff (X Literate Biff) and have been quite happy with it. By default, xlbiff generates its pop-up listings by running scan on your mail drop file, but it's not a big deal to customize xlbiff for more complicated setups if you make heavy use of procmail, multiple mail drops, and so on. From: Richard Coleman Date: 07 Jul 1997 03:31:42 -0400 nmh (new MH) has an additional command (flist) that will tell you which folders have unseen messages. I can't imagine using MH without it. From: crow at tivoli.com (David L. Crow) Date: 7 Jul 97 09:36:32 GMT I have used the following X resource with xbiff before: xbiff*checkCommand: grep -q '^unread' `mhpath +inbox`/.mh_sequences \ && exit 0 || exit 2 This should be all one line, but I split it with a line continuation character for readability. ------------------------------ Subject: 07.07 How do I read new messages filed by procmail? From: Bill Wohler Date: Sun, 17 Oct 2004 15:17:14 -0700 If you use MH-E, use "F n (mh-index-new-messages)" to display unseen messages. From: Neil W Rickert Date: 23 Apr 2002 20:38:57 GMT Here is my "unseen" shell script: #! /bin/sh - case "$1" in "") grep unseen $HOME/Mail/context $HOME/Mail/*/.mh_sequences | sed -e '/\/fromme\//d' \ -e "s=$HOME/Mail/==" \ -e 's=/.mh_sequences:unseen==' ;; "+") shift mark -sequence unseen -add "$@" ;; "-") shift mark -sequence unseen -delete "$@" ;; *) echo "Invalid arguments $*" ;; esac From: Paul Fox Date: Tue, 23 Apr 2002 20:13:42 GMT I have procmail deliver to a set of mbox files and use "inc -f foo" to inc from them. The names of the mbox files are the same as the MH folders which makes it easy to write a script that does something like this: cd Mailboxes for x in *; do inc -f $x +$x done ------------------------------ Subject: 08.00 ***** MH-E ***** From: Bill Wohler Date: Fri, 1 Mar 1991 13:03:15 -0800 ------------------------------ Subject: 08.01 I have a question about MH-E From: Bill Wohler Date: Sat, 3 Mar 2001 13:51:29 -0800 Let me send you over to: http://mh-e.sourceforge.net/ This is the SourceForge MH-E project. It has mailing lists and files to download, and will let you submit patches or support requests. The Support Requests section may already contain an answer to your question. If not, you can post your question: http://sourceforge.net/tracker/?group_id=13357&atid=213357 ------------------------------ Subject: 09.00 ***** Xmh ***** From: Bill Wohler Date: Fri, 1 Mar 1991 13:03:15 -0800 ------------------------------ Subject: 09.01 How can I get xmh to use Emacs as the editor? From: Bob Ellison Date: Fri, 1 Mar 1991 13:03:15 -0800 The modifications to xmh to support an external editor, annotations, and an append command can be found in the these places. ftp://ftp.x.org/R5contrib/xmh-mods-R5-1.7.Z 37k ftp://ftp.sei.cmu.edu/pub/xmh/xmh-mods-R5-1.7.Z 37k ftp://ftp.sei.cmu.edu/pub/xmh/xmh-mods-R6-1.0.Z 37k From: Andrew Wason Date: Fri, 1 Mar 1991 13:03:15 -0800 As of R5, xmh has a new action proc called XmhShellCommand. A string parameter will be executed as a shell command with the currently selected messages as parameters (or the current message if there are no selected messages). Using this new action, a couple of shell scripts, a window version of emacs (e.g. xemacs) and some elisp code, xmh can use emacs as its editor instead of the built in Athena text widget editor. This doesn't require any source code changes to xmh. These are included in the Appendix "Switching xmh's editor". ------------------------------ Subject: 09.02 Does xmh support subfolders? From: Steve Malowany Date: Fri, 1 Mar 1991 13:03:15 -0800 Yes. Create one by invoking "Create Folder" as usual, and enter something like: existing-folder/new-sub-folder. You can then access the subfolder by popping up a menu over the "existing-folder" button item. But: From: John Cooper Date: Fri, 1 Mar 1991 13:03:15 -0800 The R5 version of xmh does *not* handle nested sub-folders. If you create a folder as 'grab/some/bandwidth', xmh displays this folder name for the remainder of the session where it was created, BUT if you later re-run xmh, the folder is no longer visible to xmh. See also MH book section 15.6.2 (15.6.2), or the URL: http://rand-mh.sourceforge.net/book/xmh/orgfol.html#FolaSub ------------------------------ Subject: 09.03 How do I precede included messages with ">" when replying in xmh? From: Len Makin Date: Fri, 1 Mar 1991 13:03:15 -0800 Include the following line in your ~/app-defaults/XMh file: Xmh*replyInsertFilter: "sed 's/^/> /'" or, Xmh.ReplyInsertFilter: $MHLIB/mhl -form repl.filter From: Andy Linton Date: Fri, 1 Mar 1991 13:03:15 -0800 Using this means that you can chose to insert the original by use of the "Insert" button in the Draft message pane. See "How do I include messages in repl with or without ">"?" to find examples of repl.filter. See also MH book sections 15.1.4 (15.1.4), 16.3.3 (16.3.3), or the URLs: http://rand-mh.sourceforge.net/book/xmh/senmai.html#MorRep http://rand-mh.sourceforge.net/book/xmh/resfun.html#Rep ------------------------------ Subject: Glossary From: Bill Wohler Date: Wed, 29 Sep 2004 00:04:34 -0700 MH Mail Handler MHLIB Where MH support routines and files are kept; usually /usr/lib/mh or /usr/local/lib/mh. POP3 Post Office Protocol, RFC 1939 MMDF Multi-channel Memo Distribution Facility MIME Multipurpose Internet Mail Extensions, RFC 1521 IMAP Internet Message Access Protocol, RFC 1064, 1176 TIS Trusted Information Systems PEM Privacy Enhanced Mail PGP Pretty Good Privacy SMTP Simple Mail Transport Protocol (STD 10; RFC 821) ------------------------------ Subject: Acknowledgments From: Bill Wohler Date: Mon, 9 Sep 1996 01:37:27 -0700 I'd like to thank the following people for providing ideas on the layout of this article: Joe Wells Richard M. Stallman David Elliott Tom Christiansen Eugene N. Miya We are also grateful to Kim F. Storm and Edward Vielmetti and the folks mentioned in the text of this document who have provided answers or other information to make this a better document. I regret that it is possible that some names have been accidently omitted. I would also like to thank all the readers of comp.mail.mh. I'd also like to thank John Romine for maintaining MH and the MH Web page, Jerry Peek for writing the MH bible and for all his hard work with the entire MH project, Stephen Gildea for maintaining MH-E in years past and always sending me lots of great comments, Kimmo Suominen for maintaining the MH patch page, and Richard Coleman for taking MH to nmh. ------------------------------ Subject: Switching xmh's editor From: Andrew Wason Date: Fri, 1 Mar 1991 13:03:15 -0800 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh 'README' <<'END_OF_FILE' XThis is a short description of what to do with each of the enclosed files. X XXmh.ad X Merge this in with your xmh resources. If you already have X user defined buttons, then you may need to renumber the X buttons in this resource file. X Xxmh-command.el X Byte compile this file and put it in your GNU emacs load-path. X Xxmhcommand Xxmhemacs X Put these somewhere in your path. X X XOnce you have installed these, restart the R5 xmh with the new Xresources. When you press the repl, forw or comp buttons Xan xemacs window will come up with your draft message. X XOnce you have written your mail, save it and exit GNU emacs (C-xC-c). XYou will be prompted if you want to send the current message. XIf you enter 'y', the message will be sent and the output will Xbe displayed in an emacs window (in case you use -verbose or -snoop). XThen you will be prompted to exit emacs. Enter 'y' when you are ready. X XIf you answered 'n' when prompted to send the message, Xthen the draft message will be deleted and emacs will exit. X XYou can modify the Xmh.ad resources to add more buttons. XAny MH command which accepts "+folder msg" can be used X(e.g. a replx shell script which includes the body of the Xmessage being replied to can be bound to a replx button) X X XAndrew Wason Xaw at bae.bellcore.com END_OF_FILE if test 1269 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'Xmh.ad' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Xmh.ad'\" else echo shar: Extracting \"'Xmh.ad'\" \(457 characters\) sed "s/^X//" >'Xmh.ad' <<'END_OF_FILE' XXmh*CommandButtonCount: 3 X XXmh*commandBox.button1.label: repl XXmh*commandBox.button1.translations:\ X #override\n\ X : XmhShellCommand(xmhcommand y repl) unset() X XXmh*commandBox.button2.label: forw XXmh*commandBox.button2.translations:\ X #override\n\ X : XmhShellCommand(xmhcommand y forw) unset() X XXmh*commandBox.button3.label: comp XXmh*commandBox.button3.translations:\ X #override\n\ X : XmhShellCommand(xmhcommand n comp) unset() END_OF_FILE if test 457 -ne `wc -c <'Xmh.ad'`; then echo shar: \"'Xmh.ad'\" unpacked with wrong size! fi # end of 'Xmh.ad' fi if test -f 'xmh-command.el' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xmh-command.el'\" else echo shar: Extracting \"'xmh-command.el'\" \(1294 characters\) sed "s/^X//" >'xmh-command.el' <<'END_OF_FILE' X;;; These functions are for use with xemacs and xmh. X;;; The R5 xmh has a new action - XmhShellCommand which executes X;;; a shell command with the current msg as an arg. X;;; By executing something like: X;;; XmhShellCommand(xmhcommand repl) X;;; you can use xemacs as your editor with xmh. X;;; X;;; The following elisp functions perform the basic whatnowproc functionality X;;; (quitting and deleting, sending) X;;; X;;; Andrew Wason aw at bae.bellcore.com X X X;;; Override C-xC-c X(define-key indented-text-mode-map "\C-x\C-c" 'xmh-command-send-or-delete) X X X(setq mhdraft (getenv "mhdraft")) ; save the filename of the draft X X X(find-file mhdraft) ; load the draft letter X(indented-text-mode) X(setq draft-buffer (current-buffer)) ; save the buffer the draft is in X X X(defun xmh-command-send-or-delete () X "Prompt to send or delete letter, then quit." X (interactive) X (set-buffer draft-buffer) X (if (y-or-n-p "Send message? ") X (progn X (save-buffer) ; save the draft buffer X (message "Sending...") X (pop-to-buffer "MH mail delivery"); pop to a buffer for "send" output X (erase-buffer) X (call-process "send" nil t t mhdraft) ; call MH "send" X (if (y-or-n-p "Exit? ") X (kill-emacs))) ; exit emacs X (delete-file mhdraft) ; delete the draft letter X (kill-emacs))) ; exit emacs END_OF_FILE if test 1294 -ne `wc -c <'xmh-command.el'`; then echo shar: \"'xmh-command.el'\" unpacked with wrong size! fi # end of 'xmh-command.el' fi if test -f 'xmhcommand' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xmhcommand'\" else echo shar: Extracting \"'xmhcommand'\" \(669 characters\) sed "s/^X//" >'xmhcommand' <<'END_OF_FILE' X#!/bin/sh X# This shell should be invoked by the xmh XmhShellCommand() action as X# XmhShellCommand(xmhcommand y repl) X# XmhShellCommand(xmhcommand n comp) etc. X# If the second arg is y, then the message list will be used. X X# We invoke the passed MH command on the identified message X# (we must strip the message number and folder from the pathname) X(if [ $1 = "y" ] Xthen X $2 -whatnowproc xmhemacs +`dirname \`echo $3 | \ X sed "s;\\\`mhpath +\\\`/;;"\`` `basename $3` X X# You can use this more readable version instead if you have ksh X# $2 -whatnowproc xmhemacs +$(dirname $(echo $3 | \ X# sed "s;$(mhpath +)/;;")) $(basename $3) X Xelse X $2 -whatnowproc xmhemacs Xfi)& END_OF_FILE if test 669 -ne `wc -c <'xmhcommand'`; then echo shar: \"'xmhcommand'\" unpacked with wrong size! fi chmod +x 'xmhcommand' # end of 'xmhcommand' fi if test -f 'xmhemacs' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xmhemacs'\" else echo shar: Extracting \"'xmhemacs'\" \(116 characters\) sed "s/^X//" >'xmhemacs' <<'END_OF_FILE' X#!/bin/sh X# Invoke xemacs and load the xmh-command.el stuff. X# xmhemacs is used by xmhcommand Xxemacs -l xmh-command END_OF_FILE if test 116 -ne `wc -c <'xmhemacs'`; then echo shar: \"'xmhemacs'\" unpacked with wrong size! fi chmod +x 'xmhemacs' # end of 'xmhemacs' fi echo shar: End of shell archive. exit 0 ------------------------------ Subject: babyl2mh.pl From: Vivek Khera Date: Fri, 1 Mar 1991 13:03:15 -0800 #!/usr/gnu/bin/perl # incorporate an RMAIL babyl file into an MH folder # # usage: babyl2mh +folder babyl-file # # V. Khera 17-JUL-1991 # where to find rcvstore $rcvstore = "/usr/local/lib/mh/rcvstore"; # # pull out command line args # die "usage: babyl2mh +folder babyl-file\n" unless @ARGV == 2; $folder = shift; # make sure folder name starts with a "+" (substr($folder,0,1) eq "+") || (substr($folder,0,0) = "+"); $bfname = shift; print "Incorporating RMAIL file $bfname into MH folder $folder\n"; # # read in babyl file. # $/ = "\037"; # this separates the records in a babyl file $* = 1; # records are multi-lines open(BABYL,$bfname) || die "Couldn't open $bfname\n"; $_ = ; # discard header. $msgnum = 0; while () { chop; # get rid of delimeter s/\f(.|\n)*\*\*\* EOOH \*\*\*\n//; # remove duplicate header information open(RCVSTORE,"|" . $rcvstore . " $folder"); print RCVSTORE $_; $msgnum++; print "Message $msgnum done.\n"; } ------------------------------ Subject: inco - babyl to MH converter From: Juergen Nickelsen Date: Fri, 1 Mar 1991 13:03:15 -0800 #!/bin/sh # Usage: inco [from [folder]] # "from" defaults to $HOME/Mail/outbound, "folder" to +inbox. lispfile=/tmp/inco.$$.el input=${1-$HOME/Mail/outbound} tmpmbox=/tmp/inc.$$.mbox folder=${2-+inbox} if [ $# -ge 3 ]; then echo Usage: `basename $0` [ from [ folder ]] exit 2 fi trap "rm -f $lispfile $tmpmbox ; exit 1" 1 2 15 touch $tmpmbox chmod 600 $tmpmbox echo '(rmail-input "'$input'") (rmail-last-message) (setq last (rmail-what-message)) (rmail-show-message 1) (while (not (equal (rmail-what-message) last)) (rmail-output "'$tmpmbox'") (rmail-delete-forward nil)) (rmail-output "'$tmpmbox'") (kill-buffer (current-buffer)) ' > $lispfile emacs -batch -l $lispfile inc -file $tmpmbox $folder > $input rm -f $lispfile $tmpmbox ------------------------------ Subject: t2h - add hyperlinks to message viewed From: TANAKA Tomoyuki Date: Mon, 13 Sep 1999 11:35:43 -0600 #! /bin/sed -f # "t2h" by TT news:alt.tanaka-tomoyuki http://listen.to/TT # USE: t2h file.html # Or: show | t2h | lynx - s/&/\&/g s//\>/g s/http:[^ "&) ]*/&<\/a>/g s/news:[^ "&) ]*/&<\/a>/g s/ftp:[^ "&) ]*/&<\/a>/g s/telnet:[^ "&) ]*/&<\/a>/g 1i\

$a\
------------------------------ Subject: srvrsmtp.c patch From: Paul Pomes Date: Fri, 1 Mar 1991 13:03:15 -0800 >From the 5.67 sources: *** srvrsmtp.c- Mon Feb 22 12:25:54 1993 --- srvrsmtp.c Mon Feb 22 12:29:09 1993 *************** *** 384,389 **** --- 384,395 ---- message("250", "Reset state"); if (InChild) finis(); + + /* clean up a bit if running in parent */ + hasmail = FALSE; + dropenvelope(CurEnv); + CurEnv = newenvelope(CurEnv); + CurEnv->e_flags = BlankEnvelope.e_flags; break; case CMDVRFY: /* vrfy -- verify address */ ------------------------------ Subject: IRIX config file From: Jack Repenning Date: 25 Jul 1995 02:35:41 GMT # Irix 5.3 (based on examples/sys5r4) bboards on bin /usr/local/bin/mh cc cc ccoptions -g chown /bin/chown curses -lcurses etc /usr/local/lib/mh ldoptions -L/usr/local/lib/mh mail /usr/mail mailgroup: mail manuals local mts sendmail/smtp pop on popdir /usr/local/bin ranlib off #sharedlib sys5 #slibdir /usr/local/lib/mh signal void sprintf int options BIND options DBMPWD options DUMB options FOLDPROT='"0700"' options MHE options MHRC options MIME options MORE='"/usr/bsd/more"' options MSGPROT='"0600"' options RENAME options RPATHS options SBACKUP='"\\#"' #options SENDMTS options SGI #options SMTP options SOCKETS options SVR4 options SYS5 options SYS5DIR options UNISTD options _XOPEN_SOURCE options VSPRINTF From: David Paschich Date: 23 Apr 96 21:27:12 GMT # @(#)$Id: mh.faq 11334 2012-11-24 05:47:03Z wohler $ # a 4.2BSD VAX system running SendMail bin /usr/local/bin/mh bboards off etc /usr/local/lib/mh mail /var/mail manuals local mandir /usr/local/man chown /sbin/chown ranlib off mts sendmail signal void options BIND LOCKF FOLDPROT='"0700"' MHE MHRC MORE='"/usr/bsd/more"' options MSGPROT='"0600"' RPATHS SENDMTS SGI SMTP SOCKETS SYS5 options TYPESIG="void" ncr MIME VSPRINTF UNISTD SYSVR4 SYS5DIR ------------------------------ Subject: HP-UX 10.20 config file From: Marko Heikkinen Date: 06 Jan 1997 17:19:07 +0000 bin /opt/mail/bin bboards on etc /opt/mail/lib/mh editor prompter remove mv -f mail /var/mail mandir /opt/man manuals standard chown /bin/chown cc cc ccoptions +DA1.0 +DS1.0 curses -lcurses mts sendmail/smtp pop off slibdir: /opt/mail/lib options SYS5 options MHE options MIME options ATZ options BIND options MHE options MIME options ATZ options BIND options MHE options MHRC options MORE='"/opt/gnu/bin/less"' options MSGPROT='"0600"' options NDIR options NTOHLSWAP options POPUUMBOX options SOCKETS options SYS5 options TZNAME options TYPESIG=void options VSPRINTF options WHATNOW options _STRINGS signal void curses -lcurses -ltermlib sprintf int ------------------------------ Subject: Removing duplicate messages (Bourne) From: Jerry Peek Date: 20 Nov 1995 18:51:24 GMT Here's a simple-minded Bourne shell version. It uses "scan" to get the message number and message-id of each message. If a message has the same message-id as the previous message, the script adds its message number to the "remove" shell variable. #!/bin/sh lastmsgid=hahahaha remove= scan -width 300 -format '%(msg) %{message-id}' | while read msg msgid; do if [ "$msgid" = "$lastmsgid" ]; then remove="$remove $msg" else lastmsgid="$msgid" fi done rmm $remove That's pretty simple-minded. For example, if the $remove variable gets too big, your system may complain. And I'm sure there are some more-efficient ways to find the list of duplicate message-ids. But that's the idea. Subject: Removing duplicate messages (Perl) From: rtor at ansa.co.uk (Owen Rees) Date: 20 Nov 1995 12:39:47 GMT I wrote a perl script to do this some time ago. All the usual dire warnings about destructive technology apply - take a backup, do it on a copy, try it on a small test case first etc. Don't use this script unless you are prepared to accept the consequences. #!/usr/local/bin/perl $version = "rmmdup 1"; if (@ARGV == 0) { $folder = ""; } elsif (@ARGV == 1) { $folder = $ARGV[0]; unless ( $folder =~ /^\+.+$/ ) { die "usage $0 [+folder]\n"; }; } else { die "usage $0 [+folder]\n"; }; $rmmlist = ""; open (scan, "scan $folder -format '%(msg) %{message-id}'|"); while () { if ( ($msg,$msgid) = /^(\d+) (<.*>)$/) { if ($msgs{$msgid}) { print "$msg duplicates $msgs{$msgid}\n"; $rmmlist .= " $msg"; } else { $msgs{$msgid} = $msg; }; }; }; if ( $rmmlist ) { exec "rmm $folder $rmmlist"; }; exit; Subject: Removing duplicate messages (Perl) From: Bill Wohler Date: Sun, 17 Oct 2004 13:00:20 -0700 #!/usr/bin/perl -w # # Id: mhfinddup 6593 2004-09-02 16:34:24Z wohler =head1 NAME mhfinddup - find duplicate messages =head1 SYNOPSIS mhfinddup [options] [folder ...] =head1 DESCRIPTION B finds and removes duplicate MH messages in the folders listed on the command line (default: current folder). By default, you deal with duplicate messages interactively. You can either remove the duplicate, not remove the duplicate, or view the original and duplicate message before deciding. If you use the B<-msgid> option to B, then you probably don't want to list any F<+outbox> folders if you are using the B<--no-same-folder> option and you want to preserve your sent messages as well as your messages to mailing lists. Note that if you specify one or more folders, or if you use the B<--all> option, B recursively descends the given folders. =head1 CONTEXT Context is per B(1). That is, if F<+folder> is given, it will become the current folder. If multiple folders are given, the last one specified will become the current folder. =head1 OPTIONS =over 4 =item --all Look for duplicates in all folders. If any folders are specified, this option is ignored. =item --debug Turn on debugging messages. =item --help Display the usage of this command. =item --list List duplicated messages. =item --no-same-folder Since it is common to use C to file a message in multiple folders, this script doesn't consider messages in different folders to be duplicates. Specify this option to list or remove duplicates across folders. =item --rmm Remove messages non-interactively. Use with care! For safety, the B<--list> option takes precedence if specified and is a good option to use before using B<--rmm>. =item --version Display program version. =back =head1 RETURN VALUE Returns 0 if all is well; non-zero otherwise. =head1 EXAMPLES =over 0 =item mhfinddup Interactively remove duplicates from the current folder. =item mhfinddup --all --list --no-same-folder List all duplicates regardless if they are in different folders or not. =item mhfinddup --rmm +lists Remove all duplicates in F<+lists>, recursively. =back =head1 SEE ALSO B(1), B(1), B(1) =head1 VERSION Revision: 6593 =head1 AUTHOR Bill Wohler Copyright (c) 2003 Newt Software. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, you can find it at http://www.gnu.org/copyleft/gpl.html or write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. =head1 METHODS =cut # Packages and pragmas. use Getopt::Long; use strict; # Constants. my $cmd; # name by which command called ($cmd = $0) =~ s|^\./||; # ...minus the leading ./ my $ver = '6593'; # program version with CVS noise # Variables (may be overridden by arguments). my $all = 0; # look in all folders my $debug = 0; # verbose mode my $help = 0; # display usage my $version = 0; # display version my $list = 0; # list duplicates my $no_same_folder = 0; # consider duplicates across folders my $rmm = 0; # remove duplicates without asking # Constants. my $mhl = "/usr/lib/mh/mhl"; my $tmp = "/tmp/mhfinddup$$"; # Parse command line. # The use of the posix_default option is to ensure that folders like +a are # not confused with --all. I'd really prefer to set prefix_pattern to "(--|-)" # so that abbreviations of options can be used without being confused with # folders, but I couldn't make it so. my %opts; Getopt::Long::Configure("pass_through", "posix_default"); GetOptions('all' => \$all, 'debug' => \$debug, 'help' => \$help, 'list' => \$list, 'no-same-folder' => \$no_same_folder, 'rmm' => \$rmm, 'version' => \$version, ) or usage(); show_version() if ($version); usage() if ($help || int(@ARGV) != int(map(/^\+/, @ARGV))); my @folders = expand_folders(@ARGV); print("Expanded " . join(" ", @ARGV) . " into\n" . join("\n", @folders) . "\n") if ($debug); print("Scanning for duplicate messages...\n"); my %msgs; foreach my $folder (sort @folders) { print("Scanning $folder...\n") if ($debug); open (SCAN, "MHCONTEXT=$tmp scan +$folder -format '%(msg) %{message-id}'|"); while () { if (my ($msg, $msgid) = /^(\d+) (<.*>)$/) { if ($msgs{$msgid}) { $msgs{$msgid} =~ m|^\+(.*)/(\d+)$|; my($f, $m) = ($1, $2); if ($folder eq $f || $no_same_folder) { handle_dup($f, $m, $folder, $msg); } } else { $msgs{$msgid} = "+$folder/$msg"; } } } close(SCAN); } unlink("$tmp"); sub expand_folders { my @folders = @_; print("Getting list of folders..."); open(FOLDERS, "flist -recurse " . (($all == 1 && @folders == 0) ? "-all" : join(" ", @folders)) . "|") or die("Could not determine folders\n"); @folders = (); chomp(my $current_folder = `mhparam Current-Folder`); $current_folder = quotemeta($current_folder); while () { chomp; my ($folder, $a, $b, $c, $d, $e, $f, $g, $count) = split; if ($folder =~ /^$current_folder\+$/) { $folder =~ s/\+$//; # remove current folder indication } next if ($count == 0); push(@folders, $folder); } close(FOLDERS); print("done\n"); return(@folders); } sub handle_dup { my($f1, $m1, $f2, $m2) = @_; my $ans; repeat: print("+$f2/$m2 duplicate of +$f1/$m1"); if ($list) { print("\n"); } else { if ($rmm) { $ans = "y"; print("\n"); } else { print(", remove? [Yns?] "); chomp($ans = ); } if ($ans eq "y" || $ans eq "") { system("rmm +$f2 $m2"); } elsif ($ans eq "s") { system("$mhl `mhpath +$f1 $m1` `mhpath +$f2 $m2`"); goto repeat; } elsif ($ans eq "?") { print("y, remove message (default)\n" . "n, don't remove message\n" . "s, show messages\n" . "?, show this message\n"); goto repeat; } } } =head2 usage Display usage information and exit. =cut sub usage { print <\n\n". "$cmd comes with ABSOLUTELY NO WARRANTY.\n\n". "This is free software, and you are welcome\n". "to redistribute it under certain conditions.\n\n". "See `http://www.gnu.org/copyleft/gpl.html' for details.\n"); exit(0); } Local Variables: mode: outline outline-regexp: "^Subject:" fill-prefix: " " End: nmh-1.7.1-RC3/docs/MAIL.FILTERING000644 007761 000024 00000007645 13240376505 015722 0ustar00kenhstaff000000 000000 INTRODUCTION ------------ It is a common practice when using nmh to filter your inbound mail directly into nmh folders. There are several programs which allow you to do this, of which two common ones are procmail and slocal. SLOCAL ------ The slocal command is part of the nmh distribution. It is a fairly simple mail filtering program. Check the slocal man page for an example filtering file (called .maildelivery). PROCMAIL -------- Probably the most popular mail filtering command is procmail. It can filter mail into standard mbox-style spool files, as well as into MH/nmh style folders. Although procmail knows how to put a message directly into an nmh folder, this is not recommended. Procmail doesn't know about nmh sequences. Instead you should have procmail use the nmh command `rcvstore' to put the message into the folder. The `rcvstore' command will (by default) add each new message to the "unseen" sequence, so you can detect new messages in folders with the `flist' command. Also, nmh commands generally like to keep mail messages in RFC-822 format. But by default, procmail will leave the first line of the message unchanged. This line (which usually begins with "From ") is not in the standard RFC-822 format. It is recommended that you use the command `formail' (which comes in the procmail distribution) to rewrite this line so that it begins with the header name "X-Envelope-From:". An example of how to do this is given below. The reason the header name "X-Envelope-From:" is recommended, is that the nmh command `packf' (as of version 0.23) will check for this header when packing folders. The `packf' command knows how to undo the rewriting of the "From " line to the "X-Envelope-From:" line. By checking for this header name, `packf' is able to pack the folder into exactly the form that is used if procmail delivers to the standard mail spool. If you do not rewrite the "From " line into this format, the `packf' command will still work. But it may create fake "From " lines which are not the same as the originals. Alternatively, you might be able to suppress generation of the "From " line. If your procmail invocation includes the -f or -r option, remove. Those options add a "From " line to incoming beginning of messages that do not have them. Here is a typical .procmailrc file for using procmail in conjunction with nmh. For more information, see the manual pages for procmail, procmailrc and procmailex. ################################################################### # .procmailrc ################################################################### # To use procmail, put the next line in your .forward file: # "|IFS=' ' && exec /usr/local/bin/procmail -f- || exit 75 #XXX" # Do not remove the double quotes. Change XXX to your username. # Edit path to procmail above, and the VARIABLES below, as needed. # Adapt the MAILING LIST section below for lists you subscribe to. # Your .forward needs to be world-readable, but not world-writable. ################################################################### # This .procmailrc is written for use with nmh/mh/exmh/mh-e ################################################################### ### VARIABLES ### VERBOSE=off SHELL=/bin/sh PATH=/usr/local/nmh/lib:/usr/local/nmh/bin:/usr/bin:/usr/local/bin MAILDIR=$HOME/Mail LOGFILE=$MAILDIR/procmail.log LOCKEXT=.lock ################# # CLEANUP MESSAGE ################# # Force the "From user date" to become part of header :0 Whf | formail -z -R 'From ' X-Envelope-From: ############### # MAILING LISTS ############### :0 w: nmh-workers/$LOCKEXT * ^Resent-from: *nmh-workers | rcvstore +nmh-workers # catches exmh-{announce,users,workers} :0 w: exmh/$LOCKEXT * ^TOexmh | rcvstore +exmh # Catch junk. Don't add it to "unseen" sequence (nmh only) :0 w: junk/$LOCKEXT * ^(reply-to|from|sender):.*(spammer|flamer|evil-host) | rcvstore -nounseen +junk ################ # DEFAULT ACTION ################ :0 w: inbox/$LOCKEXT | rcvstore +inbox nmh-1.7.1-RC3/docs/MAILING-LISTS000644 007761 000024 00000002331 11732520431 015606 0ustar00kenhstaff000000 000000 There are currently three mailing lists related to nmh: nmh-announce@nongnu.org ----------------------- This is a very low-traffic mailing list for announcing new releases, patches, and important events related to nmh. To subscribe or manage your subscription options, go to: https://lists.nongnu.org/mailman/listinfo/nmh-announce nmh-workers@nongnu.org ---------------------- This is the main list for discussing work on nmh. There is currently no nmh-users mailing list, so user questions are acceptable here (the comp.mail.mh newsgroup is another good option). Bug reports and feedback should be submitted here. To subscribe or manage your subscription options, go to: https://lists.nongnu.org/mailman/listinfo/nmh-workers nmh-commits@nongnu.org ---------------------- All commits to the nmh source code repository are copied to this list. Therefore, it is probably only of interest to nmh developers. To subscribe or manage your subscription options, go to: https://lists.nongnu.org/mailman/listinfo/nmh-commit mail archives ------------- The nmh-workers and nmh-commits mailings lists archives are available here: http://lists.nongnu.org/archive/html/nmh-workers/ http://lists.nongnu.org/archive/html/nmh-commits/ nmh-1.7.1-RC3/docs/README-ATTACHMENTS000644 007761 000024 00000026524 13205305704 016353 0ustar00kenhstaff000000 000000 This document describes the previous attach interface. The attach interface has changes for nmh 1.6 and later. The interface is documented in send(1), whatnow(1), and mhbuild(1). No configuration is required, and the same commands exist in whatnow; the two main differences are that the header is now named "Attach", and mhbuild takes care of the actual header processing. Jon Steinhart's (jon@fourwinds.com) Attachment Handling Mods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ A bunch of changes have been made to improve the nmh user interface for handling MIME attachments. This document provides the background and implementation details of this so-called attach feature. The user documentation for the attach feature is in the nmh send(1) and whatnow(1) man pages. Why Did I Do This? ~~~~~~~~~~~~~~~~~~ Although nmh contains the necessary functionality for MIME message handing, the interface to this functionality is pretty obtuse. There's no way that I'm ever going to convince my partner to write mhbuild composition files! And even though I know how to write them, I often screw up when sending a message that contains a shell script because I forget that I have to double any # at the start of a line, which shell scripts have galore. These changes simplify the task of managing attachments on draft files. They allow attachments to be added, listed, and deleted. MIME messages are automatically created when drafts with attachments are sent. The Simple Setup ~~~~~~~~~~~~~~~~ Starting with nmh version 1.5, no setup is necessary. ====================================================================== Through nmh 1.4, and optionally with nmh 1.5 and beyond, here's how to set things up. This only works if you're using the "standard" interface, i.e., whatnow. Life is more complicated if you run mh-e. Add the following to your .mh_profile: send: -attach Nmh-Attachment whatnow: -attach Nmh-Attachment You may already have send and whatnow lines in your .mh_profile; if you do, just add the new stuff to the end of the line. For example, mine looks like: send: -alias aliases -attach Nmh-Attachment whatnow: -attach Nmh-Attachment That's it. Next time you want to send an attachment, say "attach filename" at the whatnow prompt and you're done. You can check your attachments by saying "alist". ====================================================================== Did I Do This Correctly? ~~~~~~~~~~~~~~~~~~~~~~~~ Hard to say. Despite lots of time looking at the nmh code, I can't say that I get the philosophy behind its structure. I am aware of two deviations from what I saw in the nmh code. 1. I commented my changes. 2. It's been years since I've used a VT-100, so I don't try to make code fit into 80 columns anymore. Seems silly to me. (Some of us might disagree. :-) What Did I Do? ~~~~~~~~~~~~~~ I made changes to the following files: h/ prototypes.h man/ anno.man send.man whatnow.man uip/ Makefile.in anno.c annosbr.c send.c sendsbr.c viamail.c (needed change for new sendsbr argument) whatnowsbr.c Attachments are associated with messages using header fields. For example, a draft that looks like this To: jon Subject: test of attachments Nmh-Attachment: /export/home/jon/foo Nmh-Attachment: /export/home/jon/bar Nmh-Attachment: /export/home/jon/test/foo -------- has the files "foo", "bar", and foo as attachments. Although I use the header field name "Nmh-Attachment" to indicate attachments, the implementation allows any header field name. (Originally, Jon used X-MH-Attachment. We have globally changed that to Nmh-Attachment to prevent contributing to the X- header field namespace.) The advantage of using header fields is that the list of attachments travels with the draft so it remains valid across editing sessions. Note that the header fields for attachments are removed from the message before it is sent. Since I was adding header fields to messages, it seemed sensible to use the existing anno program to do this for me. This required several changes to generalize anno: o I added a -draft option that permits annotations (header fields) to be added to the draft instead of a message sequence. o I added a -delete option that allows annotations to be deleted. o I added a -list option that allows annotations to be listed. o I added a -number option that modifies the behavior of -delete and -list. o I added a -append option so that annotations are appended to the headers instead of the default prepend. Without this, attachments come out in reverse order. Using the modified anno, the example above could be created (assuming that the draft exists) by prompt% anno -draft -comp Nmh-Attachment -text /export/home/jon/foo -nodate -append prompt% anno -draft -comp Nmh-Attachment -text /export/home/jon/bar -nodate -append prompt% anno -draft -comp Nmh-Attachment -text /export/home/jon/test/foo -nodate -append One can quite easily make an "attach" command using shell scripts, aliases or functions. For example, here's a bash function that does the job: function attach() { for i in $*; do anno -append -nodate -draft -comp Nmh-Attachment -text "$i"; done; } The following examples show the different ways in which attachments can be listed. prompt% anno -list -draft -comp Nmh-Attachment foo bar foo prompt% anno -list -draft -comp Nmh-Attachment -text / /export/home/jon/foo /export/home/jon/bar /export/home/jon/test/foo prompt% anno -list -draft -comp Nmh-Attachment -number 1 foo 2 bar 3 foo prompt% anno -list -draft -comp Nmh-Attachment -text / -number 1 /export/home/jon/foo 2 /export/home/jon/bar 3 /export/home/jon/test/foo prompt% Why all these listing options? I feel that the listing as produced by the first example is what most people would want most of the time. The listing as produced by the second example seemed necessary for situations where there were several attachments with the same file name in different directories. I included the numbering option so that attachments could be deleted by number which might be easier in situations where there were several attachments with the same file name in different directories, as in the above example. Attachments are deleted using the -delete option. prompt% anno -delete -draft -comp Nmh-Attachment -text foo deletes the first attachment since the foo matches the basename of the attachment name. prompt% anno -delete -draft -comp Nmh-Attachment -text /export/home/jon/test/foo deletes the third attachment since the text is a full path name and matches. prompt% anno -delete -draft -comp Nmh-Attachment -number 2 deletes the second attachment. The attachment annotations are converted to a MIME message by send. I'm not completely sure that this is the right place to do it, as opposed to doing it in post, but both would work. It seemed to me to make more sense to do it in send so that all of the various post options would apply to the MIME message instead of the original draft file. I added an -attach option to send that specifies the header field name used for attachments. Send performs the following additional steps if this option is set: o It scans the header of the draft for attachments. Normal behavior applies if none exist. o A temporary mhbuild composition file is created if there are attachments. o All non-attachment headers are copied from the draft file to the composition file. o The body of the draft is copied to a temporary body file if it contains at least one non-whitespace character. A mhbuild directive for this file is appended to the composition file. Note that this eliminates the problem of lines beginning with the # character in the message body. o A mhbuild directive is appended to the composition file for each attachment header. o mhbuild is run on the composition file, converting it to a MIME message. o The converted composition file is substituted for the original draft file and run through the rest of send. o The original draft file is renamed instead of the converted composition file. This preserves the original message instead of the composition file which is really what a user would want. o The ,file.orig file created by mhbuild is removed as it's a nuisance. The mhbuild directives appended to the composition file are constructed as follows: o The content-type a file with a dot-suffix is obtained from the list of mhshow-suffix- entries in the profile. o A file with no dot-suffix or no entry in the profile is assigned a content-type of application/octet-stream if it contains any non-ASCII characters. o A file with no dot-suffix or no entry in the profile is assigned a content-type of text/plain if it contains only ASCII characters. o The directive is of the form: #content-type; name="basename"; x-unix-mode=mode [ description ] filename The content type is derived as discussed above. The basename is the last component of the pathname given in the body of the attachment header field. The mode is file permissions. The description is obtained by running the file command on the attachment file. The filename is the field body from the attachment header field. I added an -attach option to whatnow that specifies the header field name for attachments. I added to the commands available at the whatnow prompt to provide an interface to the attachment mechanism. I'm not completely happy with some of these additions because they duplicate shell functionality. I'm not sure that there's a good way around it other than to not use whatnow. The first three additions (the ones I'm not happy with) are cd, ls, and pwd. These do the same thing as their system counterparts. As a matter of fact, these are implemented by running the commands in a subshell. I did this because I wanted proper interpretation of shell-specific things like ~ and wildcard expansion. The next command is attach. This takes a list of files and adds them to the draft as attachments using the same code as the modified anno. The list of files is run through ls using the user's shell, so wildcard expansion and all that works. The alist command lists the attachments on the current draft using listing function that I added to anno. It takes two optional options, -l for a long listing meaning full path names, and -n for a numbered listing. The detach command removes attachments from the current draft, again using the modified anno. The arguments are interpreted as numbers if the -n option is used, otherwise they're interpreted as file names. File names are shoveled through ls using the user's shell in the directory containing the file for wildcard expansion and such. File names are matched against the last pathname component unless they begin with a / in which case they're matched against the entire name. What's Left To Do? ~~~~~~~~~~~~~~~~~~ Nothing on this stuff. When I get time I'd like to improve the interface for reading messages with attachments. It's my opinion that, because of the command line nature of nmh, it makes the most sense to treat attachments as separate messages. In other words one should be able to read the next attachment using next, and the previous one using prev. One should be able to show and scan attachments. This would probably involve a major change in the message numbering scheme to allow something like 123.4 to indicate attachment 4 on message 123. Jon Steinhart nmh-1.7.1-RC3/docs/README-components000644 007761 000024 00000004266 13205305704 016764 0ustar00kenhstaff000000 000000 As of the 1.5 release, nmh has made significant changes to the way most of the message composition utilities work, specifically with the way the components templates are handled. If you use the default components templates that come with nmh then everything should work with only minor changes, but if you have custom component templates you should read this information carefully to understand how you might need to adapt your component templates. - "post" now requires a From: header in all drafts that it processes for sending (a "Resent-From" header is accepted for use with "dist"). - You should now use %(localmbox) instead of %(me) especially in replcomps and replgroupcomps. - The nmh programs "comp", "forw", and "dist" now process all component template files using the format routines in mh-format(5). The default templates are configured to place an appropriate From: header in them. Any custom templates you use will either have to be adapter to add an appropriate From: header or you will have to manually put one in the draft. - "comp", "forw", and "dist" all have new switches "-from", "-to", "-cc", "-fcc", and "-subject" that can be used to adjust the headers that appear in the draft. See the default component files and the program man pages to see exactly how this works with mh-format. - The default From: header is constructed based on the Unix username and the local hostname. This can be overridden using the Local-Mailbox profile entry. - A number of new format instructions are available: %(myhost) - The local hostname %(myname) - The local user's name (GECOS field) %(localmbox) - The local mailbox (either Local-Mailbox or user@host). This should now be used instead of %(me) in nearly all cases (%(me) only outputs the local Unix username). %(putlit) - Out the contents of the str register without space compression. %(concataddr) - Construct an address list like %(formataddr), except that it will NOT perform duplicate suppression (currently duplicate suppression only happens inside of "repl"). One possible use of this function is to construct an address list and use %(match) to decide which "From:" address to use. nmh-1.7.1-RC3/docs/README-HOOKS000644 007761 000024 00000010055 11732520431 015452 0ustar00kenhstaff000000 000000 Jon Steinhart's (jon@fourwinds.com) External Program Hooks ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This blurb describes a changes to nmh that implement an interface to external programs. This interface is different than the limited interface provided by things like the rmmproc context entry. Why Did I Do This? ~~~~~~~~~~~~~~~~~~ I'm working on a project (grokmail) that will get released via GPL sometime soon. This project keeps a database synchronized with the messages in the mail system. New functionality is built on top of this database. This functionality allows fast searching, and searching based on interest criteria. The latter can be used for spam filtering. The changes to nmh allow external programs to be run whenever a message is added to a folder, removed from a folder, or refiled. The changes are implemented in a general way so that it can be used for other purposes than mine. What Are The Changes? ~~~~~~~~~~~~~~~~~~~~~ The changes add four new profile components: add-hook: This is the full pathname of a program that is invoked whenever a message is added to a folder. The program is passed one argument which is the full pathname of the message file. The program is executed after the message is written so that it can act upon that message. del-hook: This is the full pathname of a program that is invoked whenever a message is deleted from a folder. The program is passed one argument which is the full pathname of the message file. The program is executed before the message is written so that it can act upon that message. ref-hook: This is the full pathname of a program that is invoked whenever a message is refiled. The program is passed two arguments: the first is the full pathname of the original message file, the second is the full pathname of the final message file. The program is executed after the message is written. msg-hook: This is a text message that is output if the execution of one of the external hook programs fails. There is a built-in default message if none is specified. The definition of refiling is a bit tricky. The refile hook is executed if a message is moved from one place to another. So, for example, the command refile -link causes the add hook to be executed, not the refile hook, because a new message is created, the old one isn't moved. These changes affect the following commands: burst: The add hook is executed for messages burst from a digest, and for the table of contents if -inplace is specified. The delete hook is executed for the original message if -inplace is specified. The refile hook is executed for messages that are moved. folder: The refile hook is executed for -pack. inc: The add hook is executed when messages are incorporated. refile: Either the add or refile hooks are executed. rmf: The delete hook is executed when messages are deleted. rmm: The delete hook is executed when messages are deleted. sortm: The refile hook is executed for each message moved. Note that a magic temporary message number of 2147483647 is used to hold messages as they are being shuffled. rcvstore: The add hook is executed when messages are stored. mhstore: The add hook is executed when messages are stored. Did I Do This Correctly? ~~~~~~~~~~~~~~~~~~~~~~~~ Well, sort of. This all works, but I'm not really happy with it. The issue is that an examination of the nmh code shows that message handling is scattered all over the place. Although there are library routines such as folder_addmsg and folder_delmsgs, they are not used consistently. Long term, I think that it would be better to make all message handling go through the same choke points. Also, I added a function to run the external programs. This sort of stuff is also scattered around the nmh code, for example in the code to run the rmmproc. Again, I'd like to make this more consistent in the long term. What Files Did I Change? ~~~~~~~~~~~~~~~~~~~~~~~~ uip/ burst.c inc.c refile.c rmf.c sortm.c sbr/ folder_addmsg.c folder_delmsgs.c folder_pack.c ext_hook.c (new file) nmh-1.7.1-RC3/docs/README.about000644 007761 000024 00000003467 13240376505 015722 0ustar00kenhstaff000000 000000 # README.about -- about nmh # ----------- what is it? ----------- nmh (new MH) is an electronic mail handling system. It was originally based on the package MH-6.8.3, and is intended to be a (mostly) compatible drop-in replacement for MH. If you have previously used MH, check the file DIFFERENCES for a list of the differences between nmh and MH (not up-to-date as of this writing). Although development of nmh is ongoing, it is generally stable and is in current use. But it is possible that we may break things as changes are made. -------------------------------- ftp and web sites, mailing lists -------------------------------- To find out about the mailing lists, ftp sites, and web page for nmh, check the FAQ included in this distribution. --------------- nmh maintenance --------------- nmh is currently being developed and maintained by a loosely organized group of volunteers. General discussion of the development work takes place on the nmh-workers@nongnu.org mailing list. Please send bug reports and suggestions there. ---------------- acknowledgments ---------------- The MH system was originally developed in 1979 by the RAND Corporation. It was written primarily by Bruce S. Borden after ideas in a memo by R. Stockton Gaines and Norman Z. Shapiro. In 1982, the University of California, Irvine took up maintenance of the software, under the direction of Marshall T. Rose and John L. Romine. nmh was started by Richard Coleman (coleman@math.gatech.edu) after development on MH mostly stopped. He did the original autoconfiscation and most of the other work up until version 1.0. nmh uses (v)snprintf code from the Apache web server, so we need to make the following acknowlegement: This product includes software developed by the Apache Group for use in the Apache HTTP server project (http://www.apache.org/). nmh-1.7.1-RC3/docs/README.developers000644 007761 000024 00000026773 13243042053 016754 0ustar00kenhstaff000000 000000 # README.developers # This file is intended to provide a few tips for anyone doing development on nmh. Developers who learn things "the hard way" about the nmh codebase (as opposed to local info best encoded in a comment) are encouraged to share their wisdom here. Following a commit checklist, the topics are organized alphabetically. ---------------- commit checklist ---------------- 1. code updated? 2. test added? 3. make distcheck passed? 4. man page and other documentation updated? 5. docs/pending-release-notes updated? 6. should commit message reference bug report? 7. update/close bug report (with commit id)? 8. notify nmh-users? A buildbot at http://orthanc.ca:8010/waterfall polls for new commits and builds them on a few platforms. Keep an eye on its progress in case you've committed something non-portable. (If you can provide another platform, contact the nmh-workers list.) --------------------------------- C library/system call usage notes --------------------------------- * Use m_mktemp2() or m_mktemp() instead of mkstemp(3) (see section on nmh temporary files below). * Use m_unlink() instead of unlink(3). * Use done() instead of _exit(3) except after a fork(3). ------------------------- autoconf & automake files ------------------------- If you wish to change the `configure' script, the generated Makefile or other related files, you'll need to first install GNU m4, available from , then GNU autoconf () and GNU automake (). Nmh is currently using a 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 and any autoconf macros in the m4 directory. Don't, for instance, edit config.h.in. Though it is an input file from the point of view of the users (and the configure script) it is an output file from the point of view of the developers (and the autoconf script). If you wish to add a new autoconf macro, it should be placed in it's own file and put in the m4 directory; aclocal will automatically pick it up and automake will add it to the distribution target automatically. If you wish to make changes to the Makefile, you will need to edit Makefile.am. See the automake documentation if you need further help. You should always check changes to Makefile.am by using "make distcheck". Note that the automatically generated autotools files (such as config.h.in, Makefile.in, and configure), are NOT kept in git. Thus, when you check out a git tree, you need to run the autogen.sh script before you can build anything: % ./autogen.sh ------------------- directory structure ------------------- Following is a list of nmh's directories along with a brief description of the purpose of each one. Meanings are given for the abbreviations, but note that these meanings are just informed guesses as to what the MH developers were thinking. ./ The top-level directory. Contains files like README and INSTALL. config/ Contains utility files for the `configure' process. Ordinarily nothing in here needs to be messed with. docs/ Contains more specialized documentation, such as this file and the FAQ. etc/ Contains files, file templates, and scripts to generate files that will be installed in the ${prefix}/etc directory. Stuff like replcomps. h/ Most of nmh's header (.h) files are kept not in the individual source directories, but in this central location. man/ Contains all the input files that are processed to generate nmh's manual pages. mts/ "mts" stands for "Message Transfer Service". Source files specific to the different MTSs go in the subdirectories. mts/smtp/ When nmh is configured to just talk to an SMTP server over TCP/IP, the source in this directory is compiled. sbr/ "sbr" stands for "subroutine(s)". For the most part, each source file in this directory contains a single function with the same name as the source file. These functions are of general use and are called from throughout nmh. SPECS/ Contains files such as RPM specs. test/ The num unit test suite. tools/ "tools" contains tools, scripts, and supporting files used by the developers while writing, debugging, and testing the code. uip/ "uip" stands for "User Interface Programs". Most nmh commands have a file in this directory named .c containing the code for that command (e.g. repl.c). In some cases there is also an auxiliary file called sbr.c which contains additional subroutines called from .c (which would contain not much else besides main()). --- git --- As of December 2010, nmh has switched to using git for revision control instead of CVS. While the topic of git is beyond the scope of this FAQ, to get started with git & nmh, you can run the following command to checkout the nmh repository (with read-only access to it): % git clone git://git.savannah.nongnu.org/nmh.git That will create a workspace called nmh. To update that workspace with changes to the master, cd to it and run: % git pull If you are a project member and want write access to the repository, you'll have to checkout with the following command instead of the one above: % git clone @git.sv.nongnu.org:/srv/git/nmh.git We suggest using git pull --rebase instead of the default merge for git pull. If you don't want to add the --rebase option every time, you can tell git pull to always rebase in your nmh workspace by cd'ing to it and running the following command: % git config --bool branch.master.rebase true And you'll probably want the following, also, so that --rebase applies to any new branches that you create: % git config branch.autosetuprebase always ------------------------------------------------------- nmh-local functions to use in preference to OS versions ------------------------------------------------------- For some system functions whose availability or behavior varies from OS to OS, nmh conditionally uses a local definition with the same name as the OS function (e.g. snprintf()). For other functions, developers need to avoid the OS versions and always use the nmh-supplied function. Here is a list of such functions: OS function nmh-local version to use instead =========== ================================ getpass() nmh_getpass() ------------------- nmh temporary files ------------------- To create a temporary file, use m_mktemp2() or m_mktemp(). They use mkstemp(3), but they also register the temporary file for removal on program termination. So, do not use mkstemp() directly. To further support this, nmh_init() must be called at the beginning of main(). And, if a child process is not going to immediately call one of the exec(3) functions or _exit(3) after a fork(3), it should call unregister_for_removal(0). Finally, nmh_init() sets up signal handlers for several signals: these signal handlers should not be disabled. -------------- nmh test suite -------------- The nmh test suite is run through the Makefile, with "make check" or "make distcheck". In the nmh test suite, nmh programs to be tested should be invoked through the run_test or run_prog shell functions defined in test/common.sh. Instead of echoing test progress, use start_test()/finish_test() from tests/common.sh. These will report the particular test name, within the test, only if there is a failure. To enable the use of valgrind, where available, set the environment variable NMH_VALGRIND to a non-null value. However, a separate environment variable, VALGRIND_ME, triggers the use of valgrind in test/inc/test-eom-align because it greatly extends the duration of that test. If valgrind complains about "serious error when reading debuginfo" from a library, either update or remove the debuginfo package for the offending library. ------------- releasing nmh ------------- To make a public release of nmh (we'll use version 1.5 as the example here; the convention for release candidates is to use something like "1.5-RC1"): 1. Create a release branch. The convention is to name release branches with the name "-release". % git branch 1.5-release Note you are still on the master branch at this point. Mark the current revision as the branchpoint for the new release branch: % git tag -a -m "This tag marks the point where we started the branch for 1.5" 1.5-branchpoint Now mark the master branch with a post-release version number (the convention here is to use VERSION+dev as the version number). % echo 1.5+dev > VERSION % git commit VERSION % git push % git push --tags Then do: % git checkout 1.5-release You are now on the 1.5 release branch. 2. % echo 1.5 > VERSION % date +"%e %B %Y" > DATE (DATE should contain something like "30 December 2000") 3. % git commit VERSION DATE; git push 4. % git tag -a 1.5 -m 'Releasing nmh-1.5.' % git push --tags Note that the new convention for tagging is to simply tag with the version number (tag formats in the past have varied). 5. % make distcheck If you want to check the distribution build with some particular configure options, set the DISTCHECK_CONFIGURE_FLAGS variable. E.g.: % make distcheck DISTCHECK_CONFIGURE_FLAGS=--with-cyrus-sasl 6. Upload the distribution file to savannah. You can automate this process by doing: % make upload SAVANNAH_USERNAME=username This will automatically call gpg to sign the release. You can bypass this step by setting the SKIP_GPG_SIG variable. 7. Update the http://www.nongnu.org/nmh/ homepage. (It lives in the CVS 'webpages repository'; see https://savannah.nongnu.org/cvs/?group=nmh) 8. Add a news item to the savannah nmh page. You'll have to submit it first and then separately approve it (under News->Manage). 9. Send the release announcement email to the following places: nmh-workers@nongnu.org nmh-announce@nongnu.org exmh-users@redhat.com exmh-workers@redhat.com mh-e-users@lists.sourceforge.net If the release fixes significant security holes, also send an announcement to bugtraq@securityfocus.com. The exmh lists require you to be subscribed in order to post. Note that you don't need to post separately to comp.mail.mh, as the mh-users mailing list is apparently bidirectionally gatewayed to it. Preferably, the announcement should contain the MD5 hash generated above, and should be PGP-signed. It should include the URL for the tarball as well as the URL of the website. It should contain a brief summary of visible changes, as well as the URL of the git diff page that would show a detailed list of changes. The changes between 1.5 and 1.4 would be shown by [this is just a guess, I don't know anything about cgit, and it assumes that we tag with nmh-x_x-release from now on]: http://git.savannah.gnu.org/cgit/nmh.git/diff/?h=nmh-1_5-release?h=nmh-1_4-release --------------- after a release --------------- Keep an eye on Debian's packaging, especially what patches they have to apply, and the results of their Lintian checker, which even includes spelling errors in man pages and binaries. https://sources.debian.net/src/nmh/1.6-16/debian/patches/ https://lintian.debian.org/full/az@debian.org.html#nmh Perhaps some nmh developer that uses Debian, or Ubuntu?, could provide package-building commands, including lintian(1), for Makefile.am so Lintian's complaints are known before release. nmh-1.7.1-RC3/docs/README.manpages000644 007761 000024 00000022074 13205305704 016370 0ustar00kenhstaff000000 000000 NMH MANPAGE STYLE GUIDE ======================= Nmh manpages generally follow the traditional Bell Labs formatting conventions. We do adopt a few conventions from BSD (primarily, section ordering), and have a few of our own (mostly related to indentation). Troff Considerations Proper sentences end with a period followed by a newline: This is a sentence. It is followed by another, longer, sentence, but which makes no more sense than the previous one. not This is a sentence. It is followed by another, longer, sentence, but which makes no more sense than the previous one. This allows troff to set the correct inter-sentence spacing based on the output device. When quoting, use \*(lq and \*(rq. This ensures correct formatting on typesetter-like devices. A man page's source is ASCII, not UTF-8. troff has escapes for non-ASCII characters, e.g. \(em for an em-dash, U+2014, that are mapped onto whatever the output device supports, e.g. UTF-8 or PDF. Section Ordering Always present sections in the following order: NAME [*] SYNOPSIS [*] DESCRIPTION [*] PROFILE COMPONENTS DEFAULTS CONTEXT ENVIRONMENT FILES EXAMPLES DIAGNOSTICS [*] SEE ALSO HISTORY BUGS Sections marked with a [*] are mandatory. Only include the others if they are specifically applicable. DIAGNOSTICS must document any non-zero exit codes, and can provide context to error messages. Obviously it only applies to section 1 and 8 manpages. Dates The DATE in the .TH macro is in `yyyy-mm-dd' format, and should reflect the most recent *non-trivial* update to the *content* of the manpage; formatting changes don't count, nor does expanding the `SEE ALSO' list. Ask "Would the familiar user wish to re-read this page to learn of this change?" Program Names In running text, nmh program names should be set in bold, unless you are explicitly referring to the command's documentation, in which case use manpage cross-reference style. .B comp .BR comp , .IR comp (1). Be careful when referring to programs that are not part of nmh itself. For commands that are almost guaranteed to be part of the base OS, use a manpage cross-reference (e.g. ".IR cat (1)"). For other third-party utilities, it might be best to set the command name in double quotes. Use your best judgement to make it clear when you're referring to tools that might not be present. SYNPOSIS Section Set literal text (such as flags) in bold. Set parameters in italic. Mutually exclusive options (like "-foo" and "-nofoo") should be grouped together and separated by a "|": .RI [ +folder ] <---- parameter .RI [ msgs ] <---- parameter .RB [ \-version ] <---- flag .RB [ \-editor <---- flag with .IR editor ] parameter .RB [ \-use " | " \-nouse ] <---- exclusive parameters References to these flags or parameters in the body text of the manpage should reflect these conventions: You may not supply both a .B \-form .I formfile and a .I +folder or .I msg argument. In particular, don't enclose them in single quotes. For "-flag param" situations, try to use a .B/.I combination instead of a single .BI, since it allows more flexibility in case of punctuation, and we get an automatic space between flag and param for free, without having to manual force it. Subsections Use ".SS" to denote a subsection Tables The folder manpage has an example of a table. .PP .RS 5 .nf .ta \w'/rnd/phyl/Mail/EP 'u +\w'has ddd messages 'u +\w'(ddd\-ddd); 'u FOLDER \0\0\0\0\0\0# MESSAGES RANGE CUR (OTHERS) ff has \0no messages. inbox+ has \016 messages (\03\-\022); cur=\05. mh has \076 messages (15\-\076); cur=70. .fi .RE .PP Environment Variables These are always set in roman text. The surrounding text should make clear you are referring to an environment variable. In some cases, like when dealing with all-lower-case variable names, setting the name inside double quotes can help clarify the context. Never prepend a '$' character to an environment variable name, unless you are directly referring to a variable substitution in, say, a pathname. Other Italicized Text Italicize file names, profile entries, and folder names: If a file named .RI \*(lq components \*(rq exists in the user's nmh directory, If the user's profile contains a .RI \*(lq "Msg\-Protect: nnn" \*(rq entry, it The \*(lq+\*(rq after .I inbox indicates that it is the current folder. Enclose the file names and profile entries in lq/rq quotes, too. Relative Indentation Use .RS 5 / .RE to indent paragraphs, etc. '.IP 5' can be useful, too. Try to use an offset of '5' as much as possible to maintain visual consistency. Tagged Lists In PROFILE COMPONENTS, DEFAULTS, ENVIRONMENT, and FILES, use tagged paragraphs with an offset of 20. Do not set the tag in bold or italic, or wrap it in quotes, unless this is absolutely necessary to make the context clear. .SH DEFAULTS .PD 0 .TP 20 +folder defaults to the current folder .TP msgs defaults to .I cur .TP -decodetext 8bit .TP -decodetypes text,application/ics .TP -crlflinebreaks .PD .SH [...] Source Files There should be no ".so" commands to source an external file, since these break on Linux, where the man program does not allow source files outside the man/ hierarchy. Instead, insert this fragment: .PP .RS 5 .nf %components% .fi .RE .PP Of course, replace "components" with a unique identifier that reflects the content being included, like "mts_conf" for etc/mts.conf. Then, add two lines to the man.sed target in Makefile.in like: echo '/%components%/r $(top_srcdir)/etc/components' >> $@ echo ' s,%components%,,g' >> $@ At compile time, the contents of the file will physically incorporated into the body of the man page. This is somewhat unfortunate, since later modifications won't be reflected in the manpage, but on the other hand, the manpage will show the default configuration and not local modifications. Pointer Manpages Certain manpages are shared between one or more programs (such as folder/folders). The secondary program should have a man page that only contains: .so man1/folder.1 Also, add this manpage to the appropriate section in Makefile.in AUTHOR and HISTORY Sections These have no place in a manpage. If you want everlasting glory, try the release notes. But note that a HISTORY section might be appropriate for documenting incompatibility with older versions of MH. Common errors and subjective conventions Try to mention `nmh' in the NAME section if it's not too awkward. The command-line `-foo' is an option, not a switch. Describe the default behaviour, then how it can be altered, e.g. an option. It's `see foo(1)', not `see the foo(1) man page for more detail'. Emails have `From' and `Date' headers, not `From:' and `Date:'. An mbox-format file has `"From "' envelope-address headers. A hyphen is input as an ASCII minus sign, `non-standard', not as `\-' which is the input to output a minus sign. Use an unbreakable space for RFCs: `RFC\ 822'. Hyphenate compound adjectives, e.g. `mail-drop format'. Don't SHOUT for emphasis. Use `.I' for normal emphasis and `.B' for strongest. Use `Unix', not `UNIX'. Use `user ID' and `group ID', not `user-id'. Use `zeroed', not `zero'd'. Use `mail drop', not `maildrop' or `drop box'. Use `messages', not `message(s)', ditto `folders', etc. Use `e.g.', not `eg.', and `i.e.', not `ie.'. Use a pair of commas, like this, for parenthetical asides. Use `that' when the clause is essential, without a comma. Use comma then `which' when it's non-essential. `Hence' means `from here'; it's `thus' to introduce a conclusion. ------------------------------------------------------------------------------ [ This template is a bit behind the times. I will bring it into conformance with the notes above once the notes settle down. --lyndon ] .TH COMP %manext1% "DATE" "%nmhversion%" .\" .\" %nmhwarning% .\" .SH NAME comp \- compose a message .\" .SH SYNOPSIS .HP 5 .na .B comp .RI [ +folder ] .RI [ msgs ] .RB [ \-form .IR formfile ] .RB [ \-use " | " \-nouse ] .RB [ \-version ] .RB [ \-help ] .ad .SH DESCRIPTION .B Comp is used to create a new message to be mailed. It copies something. .\" .SH "PROFILE COMPONENTS" .TP 20 Path Location of the user's MH folder directory .TP moreproc The pager command name .\" .SH DEFAULTS .TP 20 .RI + folder defaults to the current folder .\" .SH CONTEXT None .\" .SH FILES .TP 20 filename1 description of filename1 .TP filename2 description of filename2 .\" .SH "SEE ALSO" .BR dist (1), .BR forw (1), .BR repl (1), .BR send (1), .BR whatnow (1), .BR mh-profile (5) .\" Leave out the BUGS section if there are none worth describing. .SH BUGS None nmh-1.7.1-RC3/docs/README.SASL000644 007761 000024 00000003470 13240376505 015344 0ustar00kenhstaff000000 000000 # README.SASL - Readme about SASL support in nmh # SASL is short for the Simple Authentication and Security Layer. Is is a framework for adding authentication and encryption to network protocols. It is described in IETF RFC 2222. This release of nmh supports SASL for POP and SMTP. The SASL support is implemented using the Cyrus-SASL library. This library can be found at ftp://ftp.andrew.cmu.edu/pub/cyrus-mail. Obviously, SASL support only works if you use --enable-pop and the SMTP mail transport. This release of NMH only supports "Version 2" of the Cyrus SASL library. It should work with any newer Cyrus SASL release, but it was tested with Cyrus SASL 2.1.22. In particular, the CRAM-MD5 and GSSAPI (Kerberos 5) mechanisms were tested. Older versions of Cyrus-SASL had a bug which could manifest when negotiating encrypting depending on the encryption type you used, so a newer version of Cyrus-SASL is recommended. Currently, security layers ("encryption" in SASL-speak) are supported for both POP and SMTP. This means that if your POP or SMTP server _and_ the selected SASL mechanism supports it, client-server communications will be encrypted. In theory this should work with any SASL mechanism that supports security layers; it has only been tested with the GSSAPI mechanism. If you are curious as to whether or not your communications are actually encrypted or not, you can use the -snoop flag to the POP or SMTP utilities. Communication that is encrypted is preceded by an (encrypted) or (decrypted), depending on the direction of communication. If you would like to use the GSSAPI SASL mechanism (Kerberos V), you should read very carefully the documentation that comes with Cyrus-SASL, specifically the GSSAPI documentation. Getting the GSSAPI plugin to work correctly with SASL can be "interesting" to say the least. nmh-1.7.1-RC3/docs/TODO000644 007761 000024 00000013574 13205305704 014413 0ustar00kenhstaff000000 000000 [TODO] * Add IPv6 support. * Write different function to read configuration files, instead of using m_getfld.c * convert calls from sprintf/vsprintf to snprintf/vsnprintf * convert calls from getcpy to strdup * modularize access to context/profile list. * add command printm to print messages * finish changing to macros for msgstats and msgflags * Add support for Mail-Followup-To and Mail-Reply-To * Add support for profile entry "Mailing-Lists" * let mhn and mhl accept files on standard in, and output to standard out, when filtering files. * Add switch -more to `show' to call moreproc. * Add new command "show" at WhatNow? prompt. * Add command to reverse the action of rmm [-nounlink] -- "urmm"? "umm"? "um"? * Allow user customization of which kinds of text parts in multipart/alternative messages are preferred. It would be nice if one selectable behavior would be to be prompted at runtime for which version to show. * Add a new %-escape that makes temp files more permanent than %f, so that you can use gnuclient -q or netscape -remote on message parts. Put netscape -remote in mhn.defaults for text/html once this is done. * Change all man pages to group all the commandline options together in one section with each as a separate mini-heading. Having to dig through prose to find what a particular option does is a pain in the nads. * Add some way to configure whether you prefer to see text/plain or text/html parts of multipart/alternative messages. * Allow multiple simultaneous differing contexts, probably each tied to a parent (terminal) process. [POSSIBILITIES] MAN PAGES --------- * Update mh-tailor man page. * update default mode in man pages with sed SEQUENCES --------- * Maybe add option gracefully handle empty sequences (-force). ENVIRONMENT/PROFILE ------------------- * Should nmh check for EDITOR environment variable? OPTIONS ------- * change switches to accept two dashes (--help) * can we move option checking to its own function? Currently each command is doing that itself. * make the option parsing code dynamic, so that there is no limit to the number of command line arguments (this has been done for most all the commands). * Add switch descriptions to -help output. COMP ---- * add option so that prompter can be used to input addresses, before the real editor is called to edit message. * fix -nowhatnowproc switch. Right now whatnowproc starts the edit session instead of comp, so -nowhatnowproc does nothing. FLIST ----- * add -format option so you can specify the look of the output of flist. * add Flist-Exclude profile component FOLDER ------ * add Folder-Order profile component (same as flist) * add Folder-Exclude profile component FORMATS ------- * add escape %(sequence{foobar}) to detect arbitrary sequences. FORW ---- * Decode RFC-2047 headers in messages included when replying or forwarding. * Merge code for forw and repl. INC --- * Add ability to do filtering (call filterproc) when incorporating mail * Change inc to use library function folder_addmsg(). MHBUILD ------- * add ability to specify Content-Transfer-Encoding in composition drafts. * remove the code for caching from mhbuild. MHL --- * remove naming hack in mhlsbr.c for adios and done. * add ability to filter parts of the message by calling an external filtering program. * fix internal pager for mhl? MHN/MHSHOW/MHLIST/MHSTORE ------------------------- * add way so user can tell mhn to use internal method for handling type, such as multipart/mixed. * add way so user can tell mhn to use a certain `proc' such as moreproc, for certain content types. * merge the two places in which mhshowsbr.c reads display strings. * when storing to a folder, should we save the folder context first, so that storage string of "+" stores to the new folder? PICK ---- * split regex code out into library. * replace regex code with Henry Spencer's regex library. POST ---- * make -msgid the default * factor msgid code into own function PROMPTER -------- * maybe add ability to use prompter just for headers, and then use primary editor for editing message. RCVSTORE -------- * Change rcvstore so that it can store into multiple folders. * Add folder locking. REPL ---- * Decode RFC-2047 headers in messages included when replying or forwarding. * Merge code for forw and repl. SEND/SENDSBR ------------ * Add ability for returned messages from "send -push" to be in MIME format (this is actually a change in mhmail). * make -msgid the default. * Add RFC-2047 encoding support for out-going messages. This will probably require hooking mhparse into sendsbr.c, and doing a complete MIME parsing. Then all handling of Content encoding can be on the backend. SLOCAL ----- * Change slocal to use .slocalrc file, instead of .maildelivery? * Add ability to use regular expressions in header matching. * Add support for Berkeley db. * Clean up output from -debug option. * Add -debuglevel to control the amount of debug info that is output. * Add -debuglog to specify file to save debugging output. * Add -logfile (or -audit) to specify where to record info about successful deliveries. MTA INTERFACE ------------- * Fix locking code. Add lockfile command. * Think about support for DSN (Delivery Status Notification) * Test nmh with qmail. Add qmail's maildir format. * Relax restrictions on what can be done with headers in send/post. * figure out why smail.c and client.c need their own copies of getcpy, copyip, etc... (funny linking problem) GENERAL ------- * see if the various versions of copyfile and copyf can be merged. * Add MH-6.8.4 features into nmh (mostly done). * Maybe should move etcpath to sbr and add to libmh. * collect winsize, struct termio, etc... together into a ttyinfo structure. * change adios to take exit code argument. * use wait3 if not waitpid (maybe) * some of the calls to setjmp/longjmp should be replaced with sigsetjmp/siglongjmp. * replace use of ftell with fgetpos. nmh-1.7.1-RC3/docs/contrib/localpostproc000755 007761 000024 00000003515 13243042053 020164 0ustar00kenhstaff000000 000000 #!/bin/sh # # localpostproc - A sample postproc which changes the submission email server # based on user-supplied criteria. # # The basic concept is that we change where we submit mail to based on the # message contents. We use scan(1) to get out fields we care about. But # really, you could use ANY criteria, such as environment variables, # recipients, etc etc. # # # Find the draft message, always the last argument, and whether we've # been called with -whom; the latter sucks. # # The case statement has to know about switches that take arguments; # add to this list as necessary. # whom=0 find_draftmessage() { while test $# -gt 0; do case "$1" in -al* | -filt* | -wi* | -client | -idanno | -server | \ -partno | -saslmech | -user | -por* | -width | \ -file* | -mhl* | -mt* | -cr* | -lib* | -auth* | -sendmail) shift ;; -whom) whom=1 ;; -*) ;; *) draftmessage="$1" return 0 ;; esac shift done echo "Cannot find draft message name in argument list" exit 1 } realpost="$(mhparam libdir)/post" if [ $# -eq 0 ]; then echo "Usage: [post switches] filename" exit 1 fi find_draftmessage "$@" if [ $whom -eq 1 ]; then exec "$realpost" "$@" fi fromhost=$(scan -format '%<{resent-from}%(host{resent-from})%|%(host{from})%>' -file "$draftmessage") if [ $? -ne 0 ]; then echo "Unable to run scan on draft file $draftmessage, aborting" exit 1 fi if [ -z "$fromhost" ]; then echo "Could not determine hostname of From: address" exit 1; fi # # Here we use the hostname in the "from" address, but you could use anything # case "$fromhost" in *host1.com) postflags="-server smtp.host1.com -sasl -port submission" ;; host2.com) postflags="-server smtp.host2.com -sasl -tls -port submission" ;; *) echo "Don't know how to send email from $fromhost" exit 1 ;; esac exec "$realpost" $postflags "$@" nmh-1.7.1-RC3/docs/contrib/ml000755 007761 000024 00000041446 13205103206 015711 0ustar00kenhstaff000000 000000 #!/bin/bash # see several paragraphs below for more on the choice of shell interpreter. # ml is a mail reading interface for mh(1). the design is that of # a thin wrapper (this script) which uses 'less' for message # display, and mh commands for doing the real work. # # this script was completely and utterly inspired by a message # posted by Ralph Corderoy to the nmh developer's list, describing # his similar, unpublished, script: # http://lists.nongnu.org/archive/html/nmh-workers/2012-02/msg00148.html # # see the usage() and help() functions, below, for more detail. (or # use 'ml -?' for usage, and '?' within ml for help.) # # ml creates its own lesskeys map file the first time you run it, # called ~/Mail/ml_lesskeymap. # # there are a number of places where i let ml invoke my own wrapper # scripts to do something mh-like. these wrappers do things like # provide safe(r) message deletion, select among repl formats, etc. # all of these can be easily changed -- see the do_xxxx() functions. # all are assumed to operate on mh-style message specifications, and # on 'cur' by default. # # this script uses the sequences 'ml', 'mldel', 'mlspam', 'mlunr', # 'mlkeep', and 'mlrepl'. it also manipulates the user's Unseen-sequence. # # the shell dialect used is very conservative. dash (debian's # /bin/sh), bash, ksh, and solaris /bin/sh will all work, and probably # the current bsd /bin/sh variants as well, with very slightly # improved function in bash or ksh. the only non-posix shell feature # used is an argument to "read". search for the function ask_init() # for more detail. # # paul fox, pgf@foxharp.boston.ma.us, february 2012 # ------------ create_lesskey_map() { # the lesskey(1) bindings that cause less to work well with ml are: lesskey -o $lesskeymap -- - <<-EOF \^ quit \^ \? quit \? E quit E H quit H J quit J n quit n K quit K P quit P p quit p Q quit Q q quit q R quit R S quit S U quit U V quit V X quit X d quit d f quit f r quit r s quit s u quit u i quit i # \40 maps the space char, to force the last page to start at # the end of prev page, rather than lining up with bottom of # screen. \40 forw-screen-force EOF } # # the functions named do_xxxx() are the ones that are most ripe for # customization. feel free to nuke my personal preferences. # do_rmm() { # d "$@" ; return # pgf's private alias rmm "$@" } do_spamremove() { # spam "$@" ; return # pgf's private alias refile +spambucket "$@" # you're on your own } do_reply() { # rf "$@" ; return # pgf's private alias repl "$@" } do_replyall() { # R "$@" ; return # pgf's private alias repl -cc to -cc cc "$@" } do_forw() { # f "$@" ; return # pgf's private alias forw "$@" } do_edit() { ${VISUAL:-${EDITOR:-vi}} $(mhpath cur) } do_urlview() { urlview $(mhpath cur) } do_viewhtml() { echo 'mhshow-show-text/html: ' \ ' %p/usr/bin/lynx -force_html '%F' -dump | less' \ > /tmp/ml-mhshow-html$$ MHSHOW=/tmp/ml-mhshow-html$$ \ LC_ALL=C \ mhshow -type text/html "$@" rm -f /tmp/ml-mhshow-html$$ } do_sort() { # the intent is to apply some sort of thread/date ordering. # be sure no sequences have been started verify_empty "Sorting requires starting over." mldel || return verify_empty "Sorting requires starting over." mlspam || return verify_empty "Sorting requires starting over." mlunr || return # sort by date, then by subject, to get, to get subject-major, # date-minor ordering sortm ml sortm -textfield subject ml } usage() { cat <&2 usage: $me [ msgs | -s | -a ] $me will present the specified 'msgs' (any valid MH message specification). With no arguments, messages will come from the '$ml_unseen_seq' sequence. Use "$me -s" to get the status of sequences used internally by $me, or "$me -a" to apply previous results (shouldn't usually be needed). Use ? when in less to display help for '$me'. EOF exit 1 } help() { less -c </dev/null exit } ask_init() { # if "read -n 1" gives an error message, it's unsupported, # so don't use it -- the user will need to hit . # this test works on dash, bash, ksh, and a recent solaris # /bin/sh, but fails on zsh. no_immed=$(read -n 1 < /dev/null 2>&1) } ask() { immed=; if [ "$1" = -i ] then test "$no_immed" || immed="-n 1" shift fi echo -n "${1}? [N/y] " read $immed a case $a in [Yy]*) return 0 ;; *) return 1 ;; esac } # ensure the given sequence is empty verify_empty() { pre="$1" seq=$2 if pick $seq:first >/dev/null 2>&1 then echo $pre if ask "Non-empty '$seq' sequence found, okay to continue" then mark -sequence $seq -delete all 2>/dev/null else return 1 fi fi return 0 } # safely return the (non-zero) length of given sequence, with error if empty seq_count() { msgs=$(pick $1 2>/dev/null) || return 1 echo "$msgs" | wc -l } # move 'ml' to 'mlprev' preserve_ml_seq() { mark -sequence mlprev -zero -add ml 2>/dev/null mark -sequence ml -delete all 2>/dev/null } # restore the unseen sequence to its value on entry restore_unseen() { mark -sequence $ml_unseen_seq -add saveunseen 2>/dev/null } # add the message to just one of the special sequences. markit() { case $1 in mlkeep) # this is really an undo, since it restores default action mark -add -sequence mlkeep cur mark -delete -sequence mlspam cur 2>/dev/null mark -delete -sequence mldel cur 2>/dev/null mark -delete -sequence mlunr cur 2>/dev/null ;; mlspam) mark -delete -sequence mlkeep cur 2>/dev/null mark -add -sequence mlspam cur mark -delete -sequence mldel cur 2>/dev/null mark -delete -sequence mlunr cur 2>/dev/null ;; mldel) mark -delete -sequence mlkeep cur 2>/dev/null mark -delete -sequence mlspam cur 2>/dev/null mark -add -sequence mldel cur mark -delete -sequence mlunr cur 2>/dev/null ;; mlunr) mark -delete -sequence mlkeep cur 2>/dev/null mark -delete -sequence mlspam cur 2>/dev/null mark -delete -sequence mldel cur 2>/dev/null mark -add -sequence mlunr cur ;; mlrepl) # this sequence only affects the displayed header of the message. mark -add -sequence mlrepl cur ;; esac } # emit an informational header at the top of each message. header() { local msg=$1 this_mess="${BOLD}Message $folder:$msg${NORMAL}" # get index of current message mindex=$(echo "$ml_contents" | grep -xn $msg) mindex=${mindex%:*} # are we on the first or last or only messages? if [ $ml_len != 1 ] then if [ $mindex = 1 ] then mindex="${BOLD}FIRST${NORMAL}" elif [ $mindex = $ml_len ] then mindex="${BOLD}LAST${NORMAL}" fi fi position="($mindex of $ml_len)" # have we done anything to this message? r=; s=; if pick mlrepl 2>/dev/null | grep -qx $msg then r="${BLUE}Replied ${NORMAL}" fi if pick mldel 2>/dev/null | grep -qx $msg then s="${RED}Deleted ${NORMAL}" elif pick mlspam 2>/dev/null | grep -qx $msg then s="${RED}Spam ${NORMAL}" elif pick mlunr 2>/dev/null | grep -qx $msg then s="${RED}Unread ${NORMAL}" fi status=${r}${s} # show progress for whole ml run (how many deleted, etc.) scnt=$(seq_count mlspam) dcnt=$(seq_count mldel) ucnt=$(seq_count mlunr) others="${scnt:+$scnt spam }${dcnt:+$dcnt deleted }${ucnt:+$ucnt marked unread}" others="${others:+[$others]}" statusline="$this_mess $position $status $others" echo $statusline } # emit the header again footer() { echo "-----------" echo "$statusline" } # make the Subject: and From: headers stand out colorize() { sed \ -e 's/^\(Subject: *\)\(.*\)/\1'"$RED"'\2'"$NORMAL"'/' \ -e 's/^\(From: *\)\(.*\)/\1'"$BLUE"'\2'"$NORMAL"'/' # 2>/dev/null } cleanup() { # the first replacement gets rid of the default header that # show emits with every message -- we provide our own. # for the second: i think the 'Press text is a bug in # mhl. there's no reason to display this message when not # actually pausing for to be pressed. sed -e '1s/^(Message .*)$/---------/' \ -e 's/Press to show content\.\.\.//' } # this is the where the message is displayed, using less show_msg() { local nmsg local which=$1 # only (re)set $msg if pick succeeds if nmsg=$(pick ml:$which 2>/dev/null) then msg=$nmsg viewcount=0 else # do we keep hitting the same message? : $(( viewcount += 1 )) if [ $viewcount -gt 2 ] then if ask -i "See message $msg yet again" then viewcount=0 else normal_quit fi fi fi ( header $msg Mail=$(mhpath +) export NMH_NON_INTERACTIVE=1 export MHSHOW=$Mail/mhn.noshow mhshow $msg | cleanup | colorize footer ) | LESS=miXcR less $lesskeyfileopt return $? # return less' exit code } # bad things would happen if we were to keep going after the current # folder has been changed from another shell. check_current_folder() { curfold=$(folder -fast) if [ "$curfold" != "$folder" ] # danger, will robinson!! then echo "Current folder has changed to '$curfold'!" echo "Answering 'no' will discard changes, and exit." if ask "Switch back to '$folder'" then folder +$folder else restore_unseen preserve_ml_seq exit fi fi } loop() { local nextmsg nextmsg=first while : do check_current_folder show_msg $nextmsg cmd=$? # save the less exit code check_current_folder # by default, stay on the same message nextmsg=cur case $cmd in # help $_ques) help ;; # dispatch $_d) markit mldel ##nextmsg=next ;; $_s) markit mlspam ##nextmsg=next ;; $_u) markit mlunr ##nextmsg=next ;; $_U) markit mlkeep ##nextmsg=next ;; # send mail $_r) do_reply markit mlrepl #nextmsg=cur ;; $_R) do_replyall markit mlrepl #nextmsg=cur ;; $_f) do_forw markit mlrepl #nextmsg=cur ;; # special viewers $_H) do_viewhtml #nextmsg=cur ;; $_V) do_urlview #nextmsg=cur ;; $_E) do_edit #nextmsg=cur ;; $_i) show_status | less -c #nextmsg=cur ;; # quitting $_q) normal_quit ;; $_X|$_Q) restore_unseen preserve_ml_seq exit ;; # other $_S) do_sort nextmsg=first ;; # navigation $_up) nextmsg=first ;; $_K) nextmsg=prev ;; $_p|$_P) nextmsg=prev ;; $_n|$_J) nextmsg=next ;; *) nextmsg=next ;; esac done } # summarize ml's internal sequences, for "ml -s" show_status() { echo Folder: $folder for s in mlspam mldel mlrepl mlunr do #pick $s:first >/dev/null 2>&1 || continue case $s in mlrepl) echo "Have attempted a reply: (sequence $s)" ;; mldel) echo "Will delete: (sequence $s)" ;; mlspam) echo "Will mark as spam: (sequence $s)" ;; mlunr) echo "Will mark as unseen: (sequence $s)" ;; # mlkeep) echo "Will leave as seen: (sequence $s)" ;; esac scan $s 2>/dev/null || echo ' none' done } apply_changes() { if cnt=$(seq_count mlspam) then echo "Marking $cnt messages as spam." do_spamremove mlspam fi if cnt=$(seq_count mldel) then echo "Removing $cnt messages." do_rmm mldel fi if cnt=$(seq_count mlunr) then echo "Marking $cnt messages unread." mark -add -sequence $ml_unseen_seq mlunr 2>/dev/null mark -sequence mlunr -delete all fi if cnt=$(seq_count mlkeep) then echo "Keeping $cnt messages in sequence 'mlkeep':" scan mlkeep fi } # decimal to character mappings. lesskeys lets you specify exit codes # from less as ascii characters, but the shell really wants them to be # numeric, in decimal. these definitions let you do "quit S" in # lesskeys, and then check against $_S here in the shell. char_init() { _A=65; _B=66; _C=67; _D=68; _E=69; _F=70; _G=71; _H=72; _I=73; _J=74; _K=75; _L=76; _M=77; _N=78; _O=79; _P=80; _Q=81; _R=82; _S=83; _T=84; _U=85; _V=86; _W=87; _X=88; _Y=89; _Z=90; _a=97; _b=98; _c=99; _d=100; _e=101; _f=102; _g=103; _h=104; _i=105; _j=106; _k=107; _l=108; _m=109; _n=110; _o=111; _p=112; _q=113; _r=114; _s=115; _t=116; _u=117; _v=118; _w=119; _x=120; _y=121; _z=122; _up=94; _ques=63; } color_init() { RED="$(printf \\033[1\;31m)" GREEN="$(printf \\033[1\;32m)" YELLOW="$(printf \\033[1\;33m)" BLUE="$(printf \\033[1\;34m)" PURPLE="$(printf \\033[1\;35m)" CYAN="$(printf \\033[1\;36m)" BOLD="$(printf \\033[1m)" NORMAL="$(printf \\033[m)" ESC="$(printf \\033)" } # in-line execution starts here set -u # be defensive me=${0##*/} folder=$(folder -fast) lesskeymap=$(mhpath +)/ml_lesskeymap lesskeyfileopt="--lesskey-file=$lesskeymap" if [ ! -f $lesskeymap -o $0 -nt $lesskeymap ] then create_lesskey_map fi ml_unseen_seq=$(mhparam Unseen-Sequence) : ${ml_unseen_seq:=unseen} # default to "unseen" # check arguments case ${1:-} in -s) show_status; exit ;; # "ml -s" -a) apply_changes; exit ;; # "ml -a" -k) create_lesskey_map; exit ;; # "ml -k" (should be automatic) -*) usage ;; # "ml -?" "") starting_seq=$ml_unseen_seq ;; # "ml" *) starting_seq="$*" ;; # "ml picked ..." esac # if sequence ml isn't empty, another instance may be running verify_empty "Another instance of ml may be running." ml || exit # gather any user message specifications into the sequence 'ml' if ! mark -sequence ml -zero -add $starting_seq >/dev/null 2>&1 then echo "No messages (or message sequence) specified." exit 1 fi # uncomment for debug # exec 2>/tmp/ml.log; set -x # get the full list of messages, and count them ml_contents=$(pick ml) ml_len=$(echo "$ml_contents" | wc -l) # if these aren't empty, we might not have "ml a"pplied changes from # a previous invocation, so warn. verify_empty "You might want to run 'ml -a'." mldel || exit verify_empty "You might want to run 'ml -a'." mlspam || exit verify_empty "You might want to run 'ml -a'." mlunr || exit mark -sequence mlrepl -delete all 2>/dev/null # initialize 'mlkeep' to 'ml', since we assume all undeleted non-spam # messages will be kept. mark -zero -sequence mlkeep ml # save a copy of the unseen sequence, for restore if 'X' is used to quit. mark -zero -sequence saveunseen $ml_unseen_seq ask_init char_init color_init loop nmh-1.7.1-RC3/docs/contrib/replaliases000644 007761 000024 00000005261 13205305704 017604 0ustar00kenhstaff000000 000000 #### replaliases #### #### convenience functions for various repl(1) commands #### #### They're functions instead of aliases for portability. This file #### is intended to be sourced from a Bourne-compatible shell, e.g., #### source `mhparam docdir`/contrib/replaliases #### to declare the functions. #### #### Author: David Levine #### If using par (see mhn.defaults), it helps to have its PARINIT #### environment variable set. If you really want it to be null, #### either comment this out or set it to, e.g., ' '. #### Removed "R" from PARINIT recommendation in par(1) man page so #### that it doesn't consider words that are too long to be an error. if [ -z "$PARINIT" ]; then PARINIT='rTbgq B=.,?_A_a Q=_s>|' export PARINIT fi #### Reply, including text/html (converted to text/plain) and #### text/plain parts. #### #### Optional arguments: #### -h to disable conversion of text/html parts #### -p to disable conversion of text/plain parts #### All other arguments are passed to repl. #### The -p argument can be useful with improperly structured #### messages, such as those that use multipart/related when they #### should have used multipart/alternative. rt() { if [ "$1" = -h ]; then shift \repl -filter mhl.replywithoutbody -convertargs text/plain '' "$@" elif [ "$1" = -p ]; then shift \repl -filter mhl.replywithoutbody -convertargs text/html '' "$@" else \repl -filter mhl.replywithoutbody \ -convertargs text/html '' -convertargs text/plain '' "$@" fi } #### Add -editor mhbuild to above. Useful only when attachments #### won't be added to the message. #### #### To ease editing at the What now? prompt, add a line like this to #### your .mh_profile: #### mhbuild-next: $EDITOR #### assuming that your EDTIOR environment variable is set; if not, #### replace $EDITOR above with the name of your editor. Without that #### profile entry, enter "e[dit] $EDITOR" at the What now? prompt. rtm() { rt -editor mhbuild "$@" } #### accept a calendar request calaccept() { \repl -noformat -editor mhbuild \ -convertargs text/calendar '-reply accept -contenttype' "$@" } #### decline a calendar request caldecline() { \repl -noformat -editor mhbuild \ -convertargs text/calendar '-reply decline -contenttype' "$@" } #### reply as tentative to a calendar request caltentative() { \repl -noformat -editor mhbuild \ -convertargs text/calendar '-reply tentative -contenttype' "$@" } #### cancel a calendar request calcancel() { \repl -noformat -editor mhbuild \ -convertargs text/calendar '-cancel -contenttype' "$@" } # Local Variables: # mode: sh # End: nmh-1.7.1-RC3/docs/contrib/replyfilter000755 007761 000024 00000034663 13205305704 017654 0ustar00kenhstaff000000 000000 #!/usr/bin/perl # # replyfilter - A reply filter for nmh # # The idea behind this program is that it will act as a format filter # for nmh. It will try to extract out all text/plain parts and format # them if necessary using a filter program. # # To use this program, configure nmh in the following way (nmh 1.5 or later): # # - Put the path to this program in your .mh_profile under formatproc: # # formatproc: replyfilter # # or invoke repl with "-fmtproc replyfilter". # # - Create an mhl reply filter that consists of the following line: # # body:nocomponent,format,nowrap,formatarg="%(trim{content-type})%(putstr)",formatarg="%(trim{content-transfer-encoding})%(putstr)",formatarg=">" # # By default, repl will look for the mhl reply filter by the name # "mhl.reply", but it will look elsewhere if the -filter switch is given. # # To decode this a bit: # # body - Output the "body" component # nocomponent - Don't output a component prefix (normally here we use a # component prefix of ">" as a quote character, but we're # going to have replyfilter do that). # nowrap - Don't wrap lines if they exceed the column width # formatarg - Arguments to formatproc. The first argument is the value # of the Content-type header; the second is the value of the # Content-Transfer-Encoding header. The last "formatarg" # is used as your quoting prefix. Replace it with whatever # you want. # use Mail::Field; use MIME::Head; use MIME::QuotedPrint; use MIME::Base64; use Encode; # # The program we use to format "long" text. Should be capable of reading # from standard input and sending the formatted text to standard output. # $filterprogram = 'par'; # # If the above filter program has problems with some input, use the following # regular expression to remove any problematic input. In this example we # filter out the UTF-8 non-breaking space (U+00A0) because that makes par # mangle the output. Uncomment this if this ends up being a problem for # you, or feel free to add others. # #%filterreplace = ( "\N{U+a0}" => " " ); # # Our output character set. This script assumes a UTF-8 locale, but if you # want to run under a different locale the change it here. # $outcharset = 'utf-8'; # # Maximum column width (used by the HTML converter and to decide if we need # to invoke the filter program # $maxcolwidth = 78; # # Out HTML converter program & arguments. charset will be appended # @htmlconv = ('w3m', '-dump', '-cols', $maxcolwidth - 2, '-T', 'text/html', '-O', $outcharset, '-I'); die "Usage: $0 Content-type content-transfer-encoding quote-prefix\n" if $#ARGV != 2; if ($ARGV[0] ne "") { my $ctype = Mail::Field->new('Content-Type', $ARGV[0]); $content_type = $ctype->type; $charset = $ctype->charset; $boundary = $ctype->boundary; } else { $content_type = 'text/plain'; $charset = 'us-ascii'; } $encoding = $ARGV[1] eq "" ? '7bit' : lc($ARGV[1]); $quoteprefix = $ARGV[2]; # # Set up our output to be in our character set # binmode(STDOUT, ":encoding($outcharset)"); # # The simplest case: if we have a single type of text/plain, send it # to our format subroutine. # if ($content_type eq 'text/plain') { process_text(\*STDIN, $encoding, $charset); exit 0; } # # Alright, here's what we need to do. # # Find any text/plain parts and decode them. Decode them via base64 or # quoted-printable, and feed them to our formatting filter when appropriate. # Put markers in the output for other content types. # ($type) = (split('/', $content_type)); if ($type eq 'multipart') { # # For multipart messages we have to do a little extra. # Eat the MIME prologue (everything up until the first boundary) # if (! defined $boundary || $boundary eq '') { print "No boundary in Content-Type header!\n"; eat_part(\*STDIN); exit 1; } while () { last if match_boundary($_, $boundary); } if (eof(STDIN)) { print "Unable to find boundary in message\n"; exit 1; } } else { undef $boundary; } process_part(\*STDIN, $content_type, $encoding, $charset, $boundary); if ($boundary) { # # Eat the MIME epilog # eat_part(\*STDIN); } exit 0; # # Handled encoded text. I think we can assume if the encoding is q-p # or base64 to feed it into a formatting filter. # sub process_text { my ($input, $encoding, $charset, $boundary) = @_; my $text, $filterpid, $prefixpid, $finread, $finwrite; my $foutread, $foutwrite, $decoder, $ret, $filterflag; my $text, $maxline = 0; # # In the simple case, just spit out the text prefixed by the # quote character # if ($encoding eq '7bit' || $encoding eq '8bit') { # # Switch the character set to whatever is specified by # the MIME message # binmode($input, ":encoding($charset)"); while (<$input>) { $ret = match_boundary($_, $boundary); if (defined $ret) { binmode($input, ':encoding(us-ascii)'); return $ret; } print $quoteprefix, $_; } return 'EOF'; } else { # # If we've got some other encoding, the input text is almost # certainly US-ASCII # binmode($input, ':encoding(us-ascii)'); $decoder = find_decoder(lc($encoding)); if (! defined $decoder) { return 'EOF'; } } # # Okay, assume that the encoding will make it so that we MIGHT need # to filter it. Read it in; if the lines are too long, filter it # my $chardecode = find_encoding($charset); while (<$input>) { my @lines, $len; last if ($ret = match_boundary($_, $boundary)); $text .= $_; } binmode($input, ':encoding(us-ascii)'); $text = $chardecode->decode(&$decoder($text)); grep { my $len; if (($len = length) > $maxline) { $maxline = $len; }} split(/^/, $text); if (! defined $ret) { $ret = 'EOF'; } if ($maxline <= $maxcolwidth) { # # These are short enough; just output it now as-is # foreach my $line (split(/^/, $text)) { print STDOUT $quoteprefix, $line; } return $ret; } # # We fork a copy of ourselves to read the output from the filter # program and prefix the quote character. # pipe($finread, $finwrite) || die "pipe() failed: $!\n"; pipe($foutread, $foutwrite) || die "pipe() (second) failed: $!\n"; binmode($finread, ":encoding($outcharset)"); binmode($finwrite, ":encoding($outcharset)"); binmode($foutread, ":encoding($outcharset)"); binmode($foutwrite, ":encoding($outcharset)"); if ($filterpid = fork) { # # Close the pipes in the parent that we're not using # close($finread); close($foutwrite); } elsif (defined $filterpid) { # # Close our ununsed filehandles # close($finwrite); close($foutread); # # Dup() down the filehandles to standard input and output # open(STDIN, "<&", $finread) || die "dup(filterin) failed: $!\n"; open(STDOUT, ">&", $foutwrite) || die "dup(filterout) failed: $!\n"; # # Close our copies. # close($finread); close($foutwrite); # # Exec our filter # exec $filterprogram || die "Unable to exec $filterprogram: $!\n"; } else { die "Fork for $filterprogram failed: $!\n"; } # # Fork our output handler. # if ($prefixpid = fork) { # # We don't need these anymore # close($foutread); } elsif (defined $prefixpid) { # # Read from foutwrite, and output (with prefix) to stdout # close($finwrite); while (<$foutread>) { print STDOUT $quoteprefix, $_; } exit 0; } # # Send our input to the filter program # if (%filterreplace) { foreach my $match (keys %filterreplace) { $text =~ s/$match/$filterreplace{$match}/g; } } print $finwrite $text; close($finwrite); waitpid $filterpid, 0; warn "Filter process exited with ", ($? >> 8), "\n" if $?; waitpid $prefixpid, 0; warn "Pipe reader process exited with ", ($? >> 8), "\n" if $?; return $ret; } # # Filter HTML through a converter program # sub process_html { my ($input, $encoding, $charset, $boundary) = @_; my $filterpid, $prefixpid, $finread, $finwrite; my $foutread, $foutwrite, $decoder, $ret; if (! defined($decoder = find_decoder(lc($encoding)))) { return 'EOF'; } # # We fork a copy of ourselves to read the output from the filter # program and prefix the quote character. # pipe($finread, $finwrite) || die "pipe() failed: $!\n"; pipe($foutread, $foutwrite) || die "pipe() (second) failed: $!\n"; binmode($finread, ":encoding($outcharset)"); binmode($finread, ":encoding($outcharset)"); binmode($foutread, ":encoding($outcharset)"); binmode($foutwrite, ":encoding($outcharset)"); if ($filterpid = fork) { # # Close the pipes in the parent that we're not using # close($finread); close($foutwrite); } elsif (defined $filterpid) { # # Close our ununsed filehandles # close($finwrite); close($foutread); # # Dup() down the filehandles to standard input and output # open(STDIN, "<&", $finread) || die "dup(filterin) failed: $!\n"; open(STDOUT, ">&", $foutwrite) || die "dup(filterout) failed: $!\n"; # # Close our copies. # close($finread); close($foutwrite); # # Exec our converter # my @conv = (@htmlconv, $charset); exec (@conv) || die "Unable to exec $htmlconv[0]: $!\n"; } else { die "Fork for $htmlconv[0] failed: $!\n"; } # # Fork our output handler. # if ($prefixpid = fork) { # # We don't need these anymore # close($foutread); } elsif (defined $prefixpid) { # # Read from foutwrite, and output (with prefix) to stdout # close($finwrite); while (<$foutread>) { print STDOUT $quoteprefix, $_; } exit 0; } # # Send our input to the filter program # while (<$input>) { last if ($ret = match_boundary($_, $boundary)); print $finwrite (&$decoder($_)); } if (! defined $ret) { $ret = 'EOF'; } close($finwrite); waitpid $filterpid, 0; warn "HTML converter process exited with ", scalar($? >> 8), "\n" if $?; waitpid $prefixpid, 0; warn "Pipe reader process exited with ", $? >> 8, "\n" if $?; return $ret; } # # Decide what to do, based on what kind of content it is. # sub process_part { my ($input, $content_type, $encoding, $charset, $boundary, $name) = @_; my ($type, $subtype) = (split('/', $content_type, -1), ''); if ($type eq 'text') { # # If this is a text part, right now we only deal with # plain and HTML parts. # if ($subtype eq 'plain') { return process_text($input, $encoding, $charset, $boundary); } elsif ($subtype eq 'html') { return process_html($input, $encoding, $charset, $boundary); } else { print ">>> $content_type content\n"; return eat_part($input, $boundary); } } elsif ($type eq 'multipart') { return process_multipart($input, $subtype, $boundary); } else { # # Other types we're not sure what to do with right now # Just put a marker in there # print ">>> $content_type attachment"; if (defined $name) { print ", name=$name"; } print "\n"; return eat_part($input, $boundary); } } # # Process a multipart message. # # When called, we should be right after the beginning of the first # boundary marker. So we should be pointed at header lines which describe # the content of this part # sub process_multipart { my ($input, $subtype, $boundary) = @_; my $altout; while (1) { my $encoding, $type, $end, $name, $charset; # # Use the Mail::Header package to read in any headers # corresponding to this part # my $head = Mail::Header->new($input, (MailFrom => 'IGNORE')); # # Extract out any Content-Type, Content-Transfer-Encoding, and # Content-Disposition headers # my $ctype = Mail::Field->extract('Content-Type', $head); my $cte = Mail::Field->extract('Content-Transfer-Encoding', $head); my $cdispo = Mail::Field->extract('Content-Disposition', $head); if (defined $ctype) { $type = $ctype->type; $charset = $ctype->charset; } else { $type = 'text/plain'; $charset = 'us-ascii'; } $encoding = defined $cte ? lc($cte->param('_')) : '7bit'; $name = defined $cdispo ? $cdispo->param('filename') : undef; # # Special handling for multipart/alternative; pick # the "first" one we can handle (which is usually # text/plain) and silently eat the rest, but output a # warning if we can't handle anything. # if ($altout) { $end = eat_part($input, $boundary); } else { my $subboundary = $boundary; my $maintype = (split('/', $type))[0]; if ($maintype eq 'multipart') { $subboundary = $ctype->boundary; # # Go until we find our beginning of this # part # my $subend = eat_part($input, $subboundary); if ($subend ne 'EOP') { print ">>> WARNING: malformed ", "nested multipart\n"; return $subend; } } $end = process_part($input, $type, $encoding, $charset, $subboundary, $name); if ($subtype eq 'alternative' && ! defined $altout && $type eq 'text/plain') { $altout = 1; } # # Since we changed the semantics of $boundary # above for nested multiparts, if we are # handling a nested multipart then find the end # of our current part # if ($maintype eq 'multipart') { $end = eat_part($input, $boundary); } } if ($end eq 'EOM' || $end eq 'EOF') { if ($subtype eq 'alternative' && !defined $altout) { print ">>>multipart/alternative: no suitable ", "parts\n"; } return $end; } } } # # "Eat" a MIME part; consume content until we hit the boundary or EOF # sub eat_part { my ($input, $boundary) = @_; my $ret; # # If we weren't given a boundary just eat input until EOF # if (! defined $boundary) { while (<$input>) { } return 'EOF'; } # # Otherwise, consume data until we hit our boundary # while (<$input>) { if ($ret = match_boundary($_, $boundary)) { return $ret; } } return 'EOF'; } # # Return the decoder subroutine to use # sub find_decoder { my ($encoding) = @_; if ($encoding eq '7bit' || $encoding eq '8bit') { return \&null_decoder; } elsif ($encoding eq 'base64') { return \&decode_base64; } elsif ($encoding eq 'quoted-printable') { return \&decode_qp; } else { warn "Unknown encoding: $encoding\n"; return undef; } } sub null_decoder { my ($input) = @_; return $input; } # # Match a line against the boundary string # sub match_boundary { my ($line, $boundary) = @_; return if ! defined $boundary; if (substr($line, 0, 2) eq '--') { $line =~ s/[ \t\r\n]+\Z//; if ($line eq "--$boundary") { return 'EOP'; } elsif ($line eq "--$boundary--") { return 'EOM'; } } return undef; } nmh-1.7.1-RC3/docs/contrib/vpick000755 007761 000024 00000031040 13205305704 016411 0ustar00kenhstaff000000 000000 #!/usr/bin/perl -w use strict; use vars qw($cui $list $win $VERSION); #5.12 introduced a warning about prototypes that afflicts old Curses::UI #BEGIN{ if( $^V lt v5.12.0 ){eval "use Curses::UI"}else{ eval "no warnings 'illegalproto'; use Curses::UI" } } use Curses::UI 0.9608; use Getopt::Long; $VERSION = 0.14; my %opts = configure(); my $exit = sprintf("marked sequence %s in +%s\n", ($opts{newsequence}||$opts{sequence}), $opts{'+'}); $SIG{CONT} = sub{ $cui->leave_curses(); $cui->reset_curses() }; $cui = new Curses::UI; $cui->add('status', 'Window', -y=>-1, -height=>1)-> #, -htmltext=>1 add('explain', 'Label', -reverse=>1, -bold=>1, -text=> ' H)elp I)nvert V)iew Q)uit S)ave '. # "+$opts{'+'} -seq $opts{sequence}". ($opts{cull}?' -cull':'').($opts{zero}?' -zero':''). ($opts{newsequence}?" -new $opts{newsequence}":'')); $cui->set_binding(\&help, 'h'); $cui->set_binding($SIG{CONT}, "\cL"); $cui->set_binding(\&setSequence, 's'); $cui->set_binding(sub{ kill "STOP", $$}, "\cZ"); #XXX clear on sleep? my(@values, %labels, %indices); scan(\@values, \%labels, \%indices); $win = $cui->add('window', 'Window', -padbottom=>1); $list = $win-> add('mylistbox', 'Listbox', -multi=>1, -values=>\@values, -labels=>\%labels, -htmltext=>0); #XXX use -bindings and -routines as in Widget to clean up code? $list->set_binding(sub{ $exit=''; exit }, "\cC", 'q'); $list->set_binding(\&invert=>'i'); $list->set_binding(\&view, 'v', 'm'); $list->set_binding(\&pgdn, "\cV", ' ' ); $list->set_binding(\&pgup, "\eV", 'b'); $list->set_selection(@indices{getSequence()}) unless $opts{zero}; $list->focus(); $cui->mainloop; ##Heavy Lifting END{ $cui->leave_curses(); print "\n", $exit; exit; } sub configure{ my %args = (_MBMHR=>(eval "use Mail::Box::MH::Resource 0.06", !$@), _NR =>(eval "use Number::Range", !$@) ); {#Get default values local $_; my $nom = $0; $nom =~ s%^.+/%%; $_ = $args{_MBMHR} ? Mail::Box::MH::Resource->new()->get($nom) : `mhparam $nom`; unshift(@ARGV, split) if defined; } Getopt::Long::Configure qw(auto_abbrev pass_through); GetOptions (\%args, 'sequence=s', 'newsequence:s', 'cull!', 'reverse!', 'zero!'); $args{'+'} = (grep {/^\+/} @ARGV)[0] || ''; $args{'+'} =~ s/^\+//; unless( $args{sequence} ){ $args{sequence}='vpick'; $args{zero} = 1; } $args{newsequence} ||= 'vpick' if defined $args{newsequence}; if( $args{_MBMHR} ){ my $MHR = Mail::Box::MH::Resource->new(); $args{_Path} = $MHR->get('Path'); $args{_Path} = File::Spec->file_name_is_absolute($args{_Path}) ? $args{_Path} : File::Spec->catfile($ENV{HOME}, $args{_Path}); $MHR = Mail::Box::MH::Resource->new(File::Spec->catfile($args{_Path}, 'context')); $args{'+'} ||= $MHR->get('Current-Folder'); } else{ $args{zero} = 1; } return %args; } sub help{ $cui->dialog( -title =>'Navigation', -message =>< Top of list b Page up k Scroll up l Mark message y 1 Mark & advance n 0 Unmark & advance j Scroll down ^V Page down ^E Bottom of list / Search forward ? Search backward \0 MESSAGE ); } sub invert{ my %count; my @F = getSequence(); foreach($list->get(), @values){ $count{$_}++ } foreach(keys %count){ delete($count{$_}) if $count{$_} > 1 } $list->clear_selection(); $list->set_selection(@indices{%count}); $list->draw(); } sub pgdn{ my $this = shift; if ($this->{-ypos} >= $this->{-max_selected}) { $this->dobeep; return $this; } { use integer; $this->{-ypos} = $this->canvasheight * ( 2 + $this->{-ypos}/$this->canvasheight ); } $this->run_event('-onselchange'); #This is critical for to end up at the top of the screen, #and why jumped two pages $this->draw(); $this->{-ypos} -= $this->canvasheight; $this->run_event('-onselchange'); $this->schedule_draw(1); return $this; } sub pgup{ my $this = shift; if ($this->{-ypos} <= 0) { $this->dobeep; return $this; } $this->{-ypos} -= $this->canvasheight +$this->{-ypos}%$this->canvasheight; $this->run_event('-onselchange'); $this->schedule_draw(1); return $this; } sub scan{ #Add back space for wide msg number, less the space used by the checkbox #XXX #my $width = q'-width '. (qx'scan -format "%(width)" -noheader last'+6); my $width = q'-width '. ($ENV{COLS} + 6); my $format= q`-format '%9(msg) %02(mon{date})/%02(mday{date})/%(void(year{date}))%02(modulo 100)%<{date}%> %<(mymbox{from})%<{to}To:%21(addr{to})%>%>%<(zero)%24(addr{from})%> %{subject}%<{body}<<%{body}>>%>'`; my $args = "+$opts{'+'} " if $opts{_MBMHR}; $args.= $opts{reverse} ? '-reverse' : '-noreverse'; $args.= " $opts{sequence}" if $opts{cull}; my $i=0; foreach( split/\n/, qx/scan -noheader $width $format $args/ ){ my (undef, $value, $label) = split(/\s+/, $_, 3); push @{$_[0]}, $value; $_[1]->{$value} = $label; $_[2]->{$value} = $i++; } } sub view{ my $view; if( $view = $win->getobj('view') ){ $view->focus(); } else{ $view = $win->add('view', 'TextViewer', -vscrollbar=>1, -wrapping=>1); $view->set_binding(sub{ $list->focus(); $win->delete('view') }, "\cC", 'q', 'v', 'm'); # $view->set_binding(sub{ $list->focus() }, "\cC", 'q', 'v', 'm'); $view->set_binding('cursor-pagedown'=>"\cV"); $view->set_binding('cursor-pageup' =>"\eV", 'b'); } my $path; my $msg = $list->get_active_value(); if( $opts{_MBMHR} ){ $path = File::Spec->catfile($opts{_Path},$opts{'+'},$msg); } else{ $path = qx(mhpath $msg); } $view->text("Message: $msg\n". do{ local $/=undef; open(MSG, $path); }); #XXX || Error $view->focus(); } sub getSequence{ my $MHR = Mail::Box::MH::Resource->new( File::Spec->catfile($opts{_Path}, $opts{'+'}, '.mh_sequences') ); local $_ = $MHR->get($opts{sequence}); s/(?=\s)/,/g; s/-/\.\./g; eval; } sub setSequence{ if( $opts{_NR} && $opts{_MBMHR} ){ my $seq = scalar Number::Range->new($list->get())->range(); $seq =~ s/\.\./-/g; $seq =~ y/,/ /; my $MHR = Mail::Box::MH::Resource->new( File::Spec->catfile($opts{_Path},$opts{'+'},'.mh_sequences')); $MHR->set($opts{newsequence}||$opts{sequence}=>$seq); exit $MHR->close(); } else{ exit system('mark', '-zero', '-seq', $opts{sequence}, $list->get())>>8;} } __END__ =pod =head1 NAME vpick - visual pick, mark a message sequence by eye =head1 SYNOPSIS vpick [+folder] [B<-sequence> name] [B<-newsequence> [name]] [B<-cull>] [B<-zero>] [B<-reverse>] [B] =begin html =head1 SCREENSHOT =head1 DOWNLOAD =over =item The script source.
vpick =item A binary for i686 Linux (Perl 5.8.0) for testing the software without ins\ talling the L. vpick.gz =back =end html =head1 DESCRIPTION A nifty little tool for those dyed-in-the-wool MH users whom occasionally envy those pine/elm/mutt users. For those times when you'll know what you want when you see it and mark just won't cut it. vpick allows you to check boxes for individual messages to save them in a sequence. If you're lucky and your local curses library has mouse support you might even be the envy of your friends. =head2 INTERFACE =over =item * C Online navigation help. =item * C Invert the current message selections. =item * C, C Toggle a display of the highlighted message. =item * C Save the sequence and exit. =item * C Exit without saving changes to the sequence. =back =head3 Navigation =over =item * C, C, C Add the current message to the sequence. =item * C<1>, C Add the current message to the sequence and advance to the next message. =item * C<0>, C Remove the current message from the sequence and advance to the next message. =item * C, C Advance to the next message. =item * C, C Select previous message. =item * C, C, C Scroll up a page. =item * C, C Scroll down a page. =item * C, C Select the first message in the folder. =item * C, C Select the last message in the folder. =item * C Search message entries with a 'less'-like search system. A searchstring is entered and selection advances to the first match. After that the C will search for the next occurrence, and C the previous. =item * C The same as C, only it will search in the opposite direction. =back =head1 OPTIONS Like MH commands, vpick options can be abbreviated to a shortest unique string, and any option that does not take an argument can be prefixed by I to override earlier options. =over =item B<+folder> The name of the folder to edit a sequence for. Defaults to the current folder. =item B<-sequence> name The name of the sequence to edit. Defaults to I. =item B Only display the messages in the specified sequence. You probably want B<-cull> instead. =back =over =item B<-cull>, B<-nocull> Only display the messages currently in B<-sequence>. Shorthand for: -seq foo foo =item B<-reverse>, B<-noreverse> View the folder in reverse order. =item B<-newsequence> name Save the altered message sequence as this new name, rather than clobber the existing sequence. The sequence name is otpional, and defaults to I. This is useful for catching up on a backlog of unread messages like so: -seq unseen -new -cull This preserves your I sequence, so that when you C the chaff in I, I contains only wheat. =item B<-zero>, B<-nozero> Zeroing loads an empty sequence, B<-nozero> flags existing messages from the sequence. Default is B<-nozero> unless B<-sequence> defaults to I. See L. =back =head1 REQUIREMENTS =over =item C To provide the nifty visual interface. =item C Required to summarize folder contents. But then you use MH, you knew that. =item C OR C + C Required to preserve sequences. The latter is preferred, without it some functionality will be disabled i.e; vpick will be forced to run as if -zero were given. Strictly speaking, you can also use vpick with MBMHR and not Number::Range. =back =head1 CAVEATS If using C instead of MBMHR and Number::Range with large sequences you may loose; blame the shell. You should not do anything to alter message ordering/numbering while vpick is running e.g; L, L -pack Other operations are fine. =head1 RESTRICTIONS The scan format is embedded in the program, it doesn't seem worthwhile to abstract it to a user configurable setting. =head1 SEE ALSO L, L, L =head1 AUTHOR Jerrad Pierce . =head1 LICENSE =over =item * Thou shalt not claim ownership of unmodified materials. =item * Thou shalt not claim whole ownership of modified materials. =item * Thou shalt grant the indemnity of the provider of materials. =item * Thou shalt use and dispense freely without other restrictions. =back =head1 CHANGES 0.14 =over =item Removed warning under modern perls 5.12 introduced a warning about prototypes that Curses::UI has not yet fixed =back 0.13 =over =item Fix inclusion of year in scan format. =item Documentation clean-up. =item Check profile for default switches, using the name we're invoked as. =item Added display of B<-cull> and B<-newsequence> to the status line =item Fixed exit status message, which didn't account for B<-newsequence>. =item Removed closing reverse tag from status Curses::UI implies support for that feature but it doesn't offer it yet :-/ =back 0.12 =over =item Added -cull & -newsquence options =back 0.11 =over =item Fixed status bar, it always showed -zero =back 0.10 =over =item Fixed paging behavior, it only DWIMd if you were on the first item of a page. =back 0.09 =over =item Changed paging behavior to more closely Do What I Mean =back 0.08 =over =item Added support for ^Z =back 0.07 =over =item Added message viewing =back =head1 TODO =over =item shift for self or root to kill use vars =item switch scan from qx to pipe read to minimize delay? =item M-< / M-> for end/begin? =item Add back to status once Curses::UI better supports htmltext =back =cut nmh-1.7.1-RC3/config/config.c000644 007761 000024 00000017245 13243042053 015645 0ustar00kenhstaff000000 000000 /* config.c -- master nmh configuration file * * This code is Copyright (c) 2002, by the authors of nmh. See the * COPYRIGHT file in the root directory of the nmh distribution for * complete copyright information. */ #include #include "../sbr/m_maildir.h" #include #define nmhbindir(file) NMHBINDIR#file #define nmhlibexecdir(file) NMHLIBEXECDIR#file #define nmhetcdir(file) NMHETCDIR#file #define nmhdocdir(file) NMHDOCDIR#file /* * Find the location of a format or configuration * file, and return its absolute pathname. * * 1) If already absolute pathname, then leave unchanged. * 2) Next, if it begins with ~user, then expand it. * 3) Next, check in nmh Mail directory. * 4) Next, check in nmh `etc' directory. * */ char * etcpath (char *file) { static char epath[PATH_MAX]; char *cp; char *pp; struct passwd *pw; context_read(); switch (*file) { case '/': /* If already absolute pathname, return it */ return file; case '~': /* Expand ~username */ if ((cp = strchr(pp = file + 1, '/'))) *cp++ = '\0'; if (*pp == '\0') { pp = mypath; } else { if ((pw = getpwnam (pp))) pp = pw->pw_dir; else { if (cp) *--cp = '/'; goto try_it; } } snprintf (epath, sizeof(epath), "%s/%s", pp, FENDNULL(cp)); if (cp) *--cp = '/'; if (access (epath, R_OK) != NOTOK) return epath; /* FALLTHRU */ try_it: default: /* Check nmh Mail directory */ if (access ((cp = m_mailpath (file)), R_OK) != NOTOK) { /* Will leak because caller doesn't know cp was dynamically allocated. */ return cp; } free (cp); } /* Check nmh `etc' directory */ snprintf (epath, sizeof(epath), nmhetcdir(/%s), file); return (access (epath, R_OK) != NOTOK ? epath : file); } /* * Standard yes/no switches structure */ struct swit anoyes[] = { { "no", 0, 0 }, { "yes", 0, 1 }, { NULL, 0, 0 } }; /* * nmh constants */ /* initial profile for new users */ char *mh_defaults = nmhetcdir (/mh.profile); /* default name of user profile */ char *mh_profile = ".mh_profile"; /* name of credentials file, defaults to .netrc in either Path or $HOME. */ char *credentials_file; /* if set to 1, do not check permissions on credentials file */ int credentials_no_perm_check = 0; /* name of current message "sequence" */ char *current = "cur"; /* standard component files */ char *components = "components"; /* comp */ char *replcomps = "replcomps"; /* repl */ char *replgroupcomps = "replgroupcomps"; /* repl -group */ char *forwcomps = "forwcomps"; /* forw */ char *distcomps = "distcomps"; /* dist */ char *rcvdistcomps = "rcvdistcomps"; /* rcvdist */ char *digestcomps = "digestcomps"; /* forw -digest */ /* standard format (filter) files */ char *mhlformat = "mhl.format"; /* show */ char *mhlreply = "mhl.reply"; /* repl -filter */ char *mhlforward = "mhl.forward"; /* forw -filter */ char *draft = "draft"; char *inbox = "Inbox"; char *defaultfolder = "inbox"; char *pfolder = "Current-Folder"; char *usequence = "Unseen-Sequence"; char *psequence = "Previous-Sequence"; char *nsequence = "Sequence-Negation"; /* profile entries for storage locations */ char *nmhstorage = "nmh-storage"; char *nmhcache = "nmh-cache"; char *nmhprivcache = "nmh-private-cache"; /* profile entry for external ftp access command */ char *nmhaccessftp = "nmh-access-ftp"; /* profile entry for external url access command */ char *nmhaccessurl = "nmh-access-url"; char *mhbindir = NMHBINDIR; char *mhlibexecdir = NMHLIBEXECDIR; char *mhetcdir = NMHETCDIR; char *mhdocdir = NMHDOCDIR; /* * nmh not-so constants */ /* * Default name for the nmh context file. */ char *context = "context"; /* * Default name of file for public sequences. If "\0" (an empty * "mh-sequences" profile entry), then nmh will use private sequences by * default. */ char *mh_seq = ".mh_sequences"; /* * nmh globals */ char ctxflags; /* status of user's context */ char *invo_name; /* command invocation name */ char *mypath; /* user's $HOME */ char *defpath; /* pathname of user's profile */ char *ctxpath; /* pathname of user's context */ struct node *m_defs; /* profile/context structure */ /* * nmh processes */ /* * This is the program to process MIME composition files */ char *buildmimeproc = nmhbindir (/mhbuild); /* * This is the program to `cat' a file. */ char *catproc = "/bin/cat"; /* * This program is usually called directly by users, but it is * also invoked by the post program to process an "Fcc", or by * comp/repl/forw/dist to refile a draft message. */ char *fileproc = nmhbindir (/refile); /* * This program is used to optionally format the bodies of messages by * "mhl". */ char *formatproc = NULL; /* * This program is called to incorporate messages into a folder. */ char *incproc = nmhbindir (/inc); /* * This is the default program invoked by a "list" response * at the "What now?" prompt. It is also used by the draft * folder facility in comp/dist/forw/repl to display the * draft message. */ char *lproc = NULL; /* * This is the path for the Bell equivalent mail program. */ char *mailproc = nmhbindir (/mhmail); /* * This is used by mhl as a front-end. It is also used * by mhn as the default method of displaying message bodies * or message parts of type text/plain. */ char *moreproc = NULL; /* * This is the program (mhl) used to filter messages. It is * used by mhn to filter and display the message headers of * MIME messages. It is used by repl/forw (with -filter) * to filter the message to which you are replying/forwarding. * It is used by send/post (with -filter) to filter the message * for "Bcc:" recipients. */ char *mhlproc = nmhlibexecdir (/mhl); /* * This program is called to pack a folder. */ char *packproc = nmhbindir (/packf); /* * This is the delivery program called by send to actually * deliver mail to users. This is the interface to the MTS. */ char *postproc = nmhlibexecdir (/post); /* * This is program is called by slocal to handle * the action `folder' or `+'. */ char *rcvstoreproc = nmhlibexecdir (/rcvstore); /* * This program is called to remove a message by rmm or refile -nolink. * It's usually empty, which means to rename the file to a backup name. */ char *rmmproc = NULL; /* * This program is usually called by the user's whatnowproc, but it * may also be called directly to send a message previously composed. */ char *sendproc = nmhbindir (/send); /* * This is the path to the program used by "show" * to display non-text (MIME) messages. */ char *showmimeproc = nmhbindir (/mhshow); /* * This is the default program called by "show" to filter * and display standard text (non-MIME) messages. It can be * changed to a pager (such as "more" or "less") if you prefer * that such message not be filtered in any way. */ char *showproc = nmhlibexecdir (/mhl); /* * This program is called after comp, et. al., have built a draft */ char *whatnowproc = nmhbindir (/whatnow); /* * This program is called to list/validate the addresses in a message. */ char *whomproc = nmhbindir (/whom); /* * This is the global nmh alias file. It is somewhat obsolete, since * global aliases should be handled by the Mail Transport Agent (MTA). */ char *AliasFile = nmhetcdir (/MailAliases); /* * File protections */ /* * Folders (directories) are created with this protection (mode) */ char *foldprot = "700"; /* * Every NEW message will be created with this protection. When a * message is filed it retains its protection, so this only applies * to messages coming in through inc. */ char *msgprot = "600"; nmh-1.7.1-RC3/config/version.c000644 007761 000024 00000000301 13243043464 016055 0ustar00kenhstaff000000 000000 char *version_str = "nmh-1.7.1-RC3 1.7.1-RC3-0-gf494bd6 built 2018-02-20 16:05:08 +0000 on zoolander.cmf.nrl.navy.mil"; char *version_num = "nmh-1.7.1-RC3"; char *user_agent = "nmh/1.7.1-RC3"; nmh-1.7.1-RC3/config/version.sh000755 007761 000024 00000000710 13205305704 016250 0ustar00kenhstaff000000 000000 #! /bin/sh # # version.sh -- script to create version string(s) for nmh. # You need to pass the script the version number to use. set -e version=${1?} host=`uname -n` if test -d "$srcdir/.git"; then git=" `git -C $srcdir describe --long --dirty`" else git= fi date="`TZ=GMT0 date +'%Y-%m-%d %T'` +0000" cat <
Mile $0.00
Time$78.71
<= font face=3D"Arial, Helvetica, sans-serif" color=3D"#333333" size=3D"2">State Tax $5.90
Vehicle License Fee $1.84
State Txn Tax $6.00