#!/bin/sh
# vminc --- incorporate new mail into VM inbox

# Copyright (C) 1993, 1995 Noah S. Friedman

# Author: Noah Friedman <friedman@prep.ai.mit.edu>
# Created: 1993-12-31
# Public domain

# $Id: vminc,v 1.4 1996/03/03 23:01:58 friedman Exp $

# 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, you can either send email to this
# program's maintainer or write to: The Free Software Foundation,
# Inc.; 59 Temple Place, Suite 330; Boston, MA 02111-1307, USA.

# Commentary:
# Code:

# Name by which this script was invoked.
progname=`echo "$0" | sed -e 's/[^\/]*\///g'`

# To prevent hairy quoting and escaping later.
bq='`'
eq="'"

usage="Usage: $progname {options}

Options are:
-D, --debug                  Turn on shell debugging (${bq}set -x$eq).
-c, --crash-file  CFILE      Temporary crash recovery folder.
-h, --help                   You're looking at it.
-i, --inbox-file  IFILE      VM primary incoming message folder pathname.
-m, --mail-file   MFILE      Mail spool file (for new mail).
-n, --no-vmincrc             Do not read vminc init file.
-V, --vminrc-file VFILE      vminc init file (default $bq~/.vmincrc$eq).
-v, --verbose                Report operations as they occur.

Parameters can be set in the file specified by the VMINCRC environment
variable (which defaults to ~/.vmincrc).  The useful parameters to set
include MAIL, VMINBOX, VMCRASH, and perhaps PATH.  The syntax is bourne
shell, e.g.

        # To include path of ${bq}movemail$eq
        PATH=/usr/local/lib/emacs/etc:\$PATH
        VMINBOX=\$HOME/mail/INBOX

"

# Usage: eval "$getopt"; value=$optarg
# or     optarg_optional=t; eval "$getopt"; value=$optarg
#
# This function automatically shifts the positional args as appropriate.
# The argument to an option is optional if the variable `optarg_optional'
# is non-empty.  Otherwise, the argument is required and getopt will cause
# the program to exit on an error.  optarg_optional is reset to be empty
# after every call to getopt.  The argument (if any) is stored in the
# variable `optarg'.
#
# Long option syntax is `--foo=bar' or `--foo bar'.  2nd argument
# won't get used if first long option syntax was used.
#
# Note: because of broken bourne shells, using --foo=bar syntax can
# actually screw the quoting of args that end with trailing newlines.
# Specifically, most shells strip trailing newlines from substituted
# output, regardless of quoting.
getopt='
  {
    optarg=
    case "$1" in
      --*=* )
        optarg=`echo "$1" | sed -e "1s/^[^=]*=//"`
        shift
       ;;
      * )
        case ${2+set} in
          set )
            optarg="$2"
            shift
            shift
           ;;
          * )
            case "$optarg_optional" in
              "" )
                case "$1" in
                  --*=* ) option=`echo "$1" | sed -e "1s/=.*//;q"` ;;
                  * ) option="$1" ;;
                esac
                exec 1>&2
                echo "$progname: option $bq$option$eq requires argument."
                echo "$progname: use $bq--help$eq to list option syntax."
                exit 1
               ;;
           esac
         ;;
        esac
     ;;
    esac
    optarg_optional=
  }'

# Initialize variables.
# Don't use `unset' since old bourne shells don't have this command.
# Instead, assign them an empty value.
debug=
verbose=
inhibit_vmincrc=

# Parse command line arguments.
# Make sure that all wildcarded options are long enough to be unambiguous.
# It's a good idea to document the full long option name in each case.
# Long options which take arguments will need a `*' appended to the
# canonical name to match the value appended after the `=' character.
while test $# != 0; do
  case "$1" in
    -D | --debug | --d* )
      debug=t
      shift
     ;;
    -c | --crash-file* | --c* )
      eval "$getopt"
      VMCRASH=$optarg
     ;;
    -h | --help | --h )
      echo "$usage" 1>&2
      exit 1
     ;;
    -i | --inbox-file* | --i* )
      eval "$getopt"
      VMINBOX=$optarg
     ;;
    -m | --mail-file* | --c* )
      eval "$getopt"
      MAIL=$optarg
     ;;
    -n | --no-vmincrc | --n* )
      inhibit_vmincrc=t
      shift
     ;;
    -V | --vmincrc-file* | --vm* )
      eval "$getopt"
      VMINCRC=$optarg
     ;;
    -v | --verbose | --ve* )
      verbose=t
      shift
     ;;
    -- )     # Stop option processing
      shift
      break
     ;;
    -? | --* )
      case "$1" in
        --*=* ) arg=`echo "$1" | sed -e 's/=.*//'` ;;
        * )     arg="$1" ;;
      esac
      exec 1>&2
      echo "$progname: unknown or ambiguous option $bq$arg$eq"
      echo "$progname: Use $bq--help$eq for a list of options."
      exit 1
     ;;
    -??* )
      # Split grouped single options into separate args and try again
      optarg="$1"
      shift
      set fnord `echo "x$optarg" | sed -e 's/^x-//;s/\(.\)/-\1 /g'` ${1+"$@"}
      shift
     ;;
    * )
      break
     ;;
  esac
done

case "$debug" in t ) set -x ;; esac

# Precedence for defs (highest->lowest): options, env, ~/.vmincrc, default
VMINCRC=${VMINCRC-$HOME/.vmincrc}

# Save env
case "${MAIL+set}"    in set ) env_MAIL=$MAIL       ;; esac
case "${VMINBOX+set}" in set ) env_VMINBOX=$VMINBOX ;; esac
case "${VMCRASH+set}" in set ) env_VMCRASH=$VMCRASH ;; esac

# Set defaults
# TODO: Implement an inline frob which runs emacs, loads your .vm, and has
# some other elisp commands to emit bourne shell code setting these
# environment variables from the elisp defaults, which is evaled.
#
# Since setting MAIL is expensive, don't try to calculate the default
# unless there really wasn't one inherited from the environment (which
# would override anyway)
case "$MAIL" in
  '' )
    USER=${USER-${LOGNAME-`{ id | sed -ne 's/.*uid=[0-9]*(//
                                           s/).*//
                                           p'
                           } \
                           || { (whoami) 2> /dev/null; }`}}

    for dir in /var/spool/mail /var/mail /usr/spool/mail /usr/mail; do
      if test -d "$dir" ; then
        MAIL=$dir/$USER
        if test -s "$MAIL" ; then
          break
        fi
      fi
    done
   ;;
esac
VMINBOX=$HOME/INBOX
VMCRASH=$HOME/CRASH

# Read from ~/.vmincrc if it exists
if test ".$inhibit_vmincrc" != .t -a -f "$VMINCRC" ; then
  case "$verbose" in t )
    echo "Reading $VMINCRC" ;;
  esac
  . "$VMINCRC"
fi

# Restore env
MAIL=${env_MAIL-$MAIL}
VMINBOX=${env_VMINBOX-$VMINBOX}
VMCRASH=${env_VMCRASH-$VMCRASH}

# Abort if there is an autosave for the inbox file and the autosave is newer.
{
  set fnord `echo "$VMINBOX" \
             | sed -ne 's,/$,,g;s,\(.*\)/\(.*\),\1/ \2,p'`
  shift
  vminbox_autosave="$1#$2#"

  set fnord `ls -t "$VMINBOX" "$vminbox_autosave" 2> /dev/null`
  shift
  case "$1" in "$vminbox_autosave" )
    exec 1>&2
    echo "$progname: Inbox autosave is newer than actual file.  Aborting."
    ls -ltd "$vminbox_autosave" "$VMINBOX"
    exit 1
   ;;
  esac
}

# If there is a crashbox already, incorporate it first.
{
  if test -f "$VMCRASH" ; then
    case "$verbose" in t )
      echo "Incorporating existing crashbox into inbox."
      echo "${PS4-+} cat $VMCRASH >> $VMINBOX"
     ;;
    esac
    cat "$VMCRASH" >> "$VMINBOX"
    exitstat=$?
    case $exitstat in
      0 )
        case "$verbose" in t )
          echo "${PS4-+} rm $VMCRASH"
         ;;
        esac
        if rm "$VMCRASH"; then
          :
        else
          exec 1>&2
          echo "$progname: Deletion of existing crashbox failed.  Aborting."
          ls -ld "$VMCRASH"
          exit 1
        fi
       ;;
      * )
        exec 1>&2
        echo "$progname: Incorporation of existing crashbox failed.  Aborting."
        ls -ld "$VMCRASH" "$VMINBOX"
        exit $exitstat
       ;;
    esac
  fi
}

# If spool file is empty or nonexistent, stop now.
{
  if test -s "$MAIL" ; then
    :
  else
    exec 1>&2
    if test -f "$MAIL"; then
      echo "$progname: Mail spool file is empty; nothing to incorporate."
      ls -ld "$MAIL" 2> /dev/null
    else
      echo "$progname: Mail spool file is nonexistent; nothing to incorporate."
    fi
    exit 0
  fi
}

# Incorporate new mail.
{
  case "$verbose" in t )
    echo "Incorporating new mail."
    echo "${PS4-+} ${MOVEMAIL-movemail} $MAIL $VMCRASH"
   ;;
  esac
  ${MOVEMAIL-movemail} "$MAIL" "$VMCRASH" \
   && {
        case "$verbose" in t )
          echo "${PS4-+} cat $VMCRASH >> $VMINBOX" ;;
        esac
        cat "$VMCRASH" >> "$VMINBOX"
      } \
   && {
        case "$verbose" in t )
          echo "${PS4-+} rm $VMCRASH" ;;
        esac
        rm "$VMCRASH"
      }
}

# vminc ends here
