qmail Digest 21 Feb 1999 11:00:01 -0000 Issue 558

Topics (messages 22250 through 22262):

Trigger help  and adduser scripts
        22250 by: "Scott D. Yelich" <[EMAIL PROTECTED]>

Help ASAP: queued message, disk full, general chaos
        22251 by: Harald Hanche-Olsen <[EMAIL PROTECTED]>
        22256 by: Scott Schwartz <[EMAIL PROTECTED]>
        22258 by: Harald Hanche-Olsen <[EMAIL PROTECTED]>
        22259 by: "Fred Lindberg" <[EMAIL PROTECTED]>
        22260 by: Scott Schwartz <[EMAIL PROTECTED]>
        22261 by: Mark Delany <[EMAIL PROTECTED]>

need some spam/relay help
        22252 by: Glenn <[EMAIL PROTECTED]>
        22254 by: Glenn <[EMAIL PROTECTED]>

Any way to read vmailmgr-mails via IMAP ?
        22253 by: Qmail ML <[EMAIL PROTECTED]>

Qmail mailing list and ReplyTo:
        22255 by: Bruno Wolff III <[EMAIL PROTECTED]>

System w/o /etc/passwd
        22257 by: [EMAIL PROTECTED]

Relay-mail-from patch
        22262 by: Chris Johnson <[EMAIL PROTECTED]>

Administrivia:

To subscribe to the digest, e-mail:
        [EMAIL PROTECTED]

To unsubscribe from the digest, e-mail:
        [EMAIL PROTECTED]

To bug my human owner, e-mail:
        [EMAIL PROTECTED]

To post to the list, e-mail:
        [EMAIL PROTECTED]


----------------------------------------------------------------------


>  > I also was looking around for examples of standard "adduser" 
>  > scripts that had been modified for use with qmail.


Do you want the whole thing or just the relevant parts?

BTW: *DO* *NOT* run this script on your system -- it's is completely
customized for an ISP.  I don't have a way of having tthe script show
the commands that it is issuing without actually issuing them (ie: set
-x) -- I guess I should build that into the script.  This script took an
ISP from manually creating accounts that required work on 2 or more
machines to one machine and the time required down from 30+ minutes per
account to mere seconds.  The best part is that all the accounts are
created the same way -- no mistakes from manual effort.

People seem to get a kick out of my shell scripting "technique" ...  so
I thought I'd pass this along.  Of course, this script isn't finished --
but it's been in use for a while now. 

I'm having a bit of trouble getting a value from a sub processes with a
timeout (ie: wait/kill/signal -- ie get the dns servers from internic --
when internic of the net is slow).  Other than that, this script has
served me well for a while now.  You said you wanted an example -- and
there might be some useful tidbits here if you're into shell scripting
and willing to dig a little. 

Scott
ps: *enjoy*

--------[ CUT HERE 8< ]--------------------------------------------------


#!/bin/sh -                                     # mongo

CREDITS="
    _________ __________  _____.___.     ________    __________    ________
   /   _____/ \______   \ \__  |   |     \_      \   \______   \  /  _____/
   \_____  \   |     ___/  /   |   |      /   |   \   |       _/ /   \  ___
   /        \  |    |      \____   |     /    |    \  |    |   \ \    \_\  \ 
  /_______  /  |____|      / ______|  /\ \_______  /  |____|_  /  \______  /
          \/               \/         \/         \/          \/          \/
 (C) Copyright 1998 Scott D. Yelich                    ALL RIGHTS RESERVED
 P.O. Box 5178, Santa Fe, NM 87502-5178
 E-Mail [EMAIL PROTECTED] URL http://www.spy.org

 mongo v0.12 08/20/98 - 09/30/98
"
                                                # 
case " $@ " in                                  # quick hack to get debug on
 *" -debug "* | *" -bug "* |*" -d "*) set -x;;  #  debug parameter passed?
esac                                            # end of case
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
# v0.01                                         # Mon Aug 10 16:34:52 MDT 1998
# v0.02                                         # Thu Aug 27 10:39:13 MDT 1998
# v0.03                                         # Fri Sep  4 13:51:38 MDT 1998
#       menu
# v0.04                                         # Wed Sep  9 11:52:32 MDT 1998
#       setupDNS, lcase, ucase, promptinput
#       pressreturn, MONGOLIB

#
# v0.05                                         # Thu Sep 10 11:31:45 MDT 1998
# v0.06  change from rcpthosts.save to rcpthosts# Jan 16


#       checkAccount, getHomeDir, getUserShell

#       checkFile, checkDir, checkLink
#       getDOTQmail, getDNSSERVERS, getMX
#       checkZoneFile, checkQMVD, getIP
#       checkMDNSConf, checkSDNSConf,
#       checkHTTPDConf, checkIPMatches
#       check IPAlias
#       
# v0.06                                         # Thu Sep 10 11:31:45 MDT 1998
#       setupHomeDir
# v0.07                                         # Mon Sep 14 14:25:18 MDT 1998
#       getNextUID
# v0.08                                         # Tue Sep 15 10:21:56 MDT 1998
#       setupQMVD
# v0.09                                         # Thu Sep 17 12:47:00 MDT 1998
#       checkEtcHosts, addToEtcHosts, setMX
#       getTheIP
# v0.10                                         # Fri Sep 18 14:47:00 MDT 1998
#       checkEtcHosts, addToEtcHosts, setMX
#       getTheIP
# v0.11                                         # Tue Sep 22 16:58:53 MDT 1998
#       setupDOTQmail, setupDOTQmailDefault     
# v0.12                                         # Wed Sep 30 12:05:46 MDT 1998
#       getNextIP major fix! checkEtcHosts
#       menu, mainMenu, extMenu, swapMenu
#       QMAIL/HTTPD/NAMED fixes/logger/etc
#       getVirtAfD, getVirtDfA
#
# v0.13                                         # Thu Dec  3 14:45:42 MST 1998
#       Fixed account substring bug...
#
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
#
# TODO / IDEAS
#
# (1) Make a -x or some option per function to over-ride checks and
#     simply do what the function was meant to do.  This means
#     things like setupQMVD doesn't just echo>>file, but first take
#     out old data with an egrep -v and then echo>>file.
# (2)
#
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
initialize () {                                 # FUNCTION: INITIALIZE
 PATH=                                          #  do not trust passed path
 MYPATH="/usr/bin /usr/ucb"                     #  set my preferred path
 OFS="$IFS"                                     #  old file separators
 TRUE='1'                                       #  test evaluates to true
 FALSE=''                                       #  test evaluates to false
 findBin LS ls                                  #  find ls binary
 findBin RM rm                                  #  find rm binary
 findBin TR tr                                  #  find tr binary
 findBin CAT cat                                #  find cat binary
 findBin ECHO echo /usr/ucb $MYPATH             #  find echo binary
 findBin KILL kill                              #  find kill binary
 findBin DATE date                              #  find date binary
 findBin MKDIR mkdir                            #  find mkdir binary
 findBin CHMOD chmod                            #  find chmod binary
 findBin BASENAME basename                      #  find basebane binary
 wProg="$0"                                     #  whole path program name
 lProg=`$BASENAME $wProg`                       #  lowercae program name
 uProg=`$BASENAME $lProg | $TR "[a-z]" "[A-Z]"` #  uppercase program name
 NOOPTS="$TRUE"                                 #  set noopts  
 test $# -gt 0 && NOOPTS="$FALSE"               #  if anything, reset noopts
 getOpts "$@"                                   #  get options from passed
 UNIQ=$$                                        #  A unique string
 PID=$$                                         #  This process's id
 TMP=/tmp                                       #  temporary file directory
 TEMPTEMP="$TMP/$uProg.$USER.$PID_";            #  temporary file name start
 NULL=/dev/null                                 #  null device
 STDOUT=""                                      #  Standard output
 STDERR="/dev/tty"                              #  Standard error
 ECODE=0                                        #  Error/Exit code
 test "x$NOOPTS" != "x" && {                    # 
  toggle DOHELP                                 # 
 }                                              # 
 test "x$DOHELP" != "x" && help                 #  do help?
 progInit                                       #  Initialize program specifics
}                                               # end of initialize
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
default () {                                    # FUNCTION: DEFAULT
 set x "$@"; shift                              #  set passed to positional
 VARIABLE=$1                                    #  VARIABLE is first, then
 shift                                          #  move positional params
 VALUE="$@"                                     #  VALUE is rest
 eval DEFAULT=\$$VARIABLE                       #  get VALUE of VARIABLE
 test "x$DEFAULT" = "x" && {                    #  if VARIABLE not set, then
  eval $VARIABLE="$VALUE"                       #   make VARIABLE = VALUE
 }                                              #  endif
}                                               # end of default
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
verbose () {                                    # FUNCTION: VERBOSE
 test "x$VERBOSE" != "x" && {                   #  if VERBOSE set, then
  TD=`$DATE +"%m/%d/%y %H:%M:%S"`               #  set TD to current date/time
  $ECHO "$uProg- $TD : $@" >>$STDERR            #  output progname + text
 }                                              #  endif
}                                               # end of verbose
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
error () {                                      # FUNCTION: ERROR
 $ECHO "$uProg*ERROR- $@" >>$STDERR             #  output progname + error
}                                               # end of error
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
fatalError () {                                 # FUNCTION: FATALERROR
 $ECHO "$uProg*FATAL-ERROR! $@" >>$STDERR       #  output progname + 
 endProgram                                     #  call: endProgram
}                                               # end of fatal error 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
endProgram () {                                 # FUNCTION: ENDPROGRAM
 cleanUp                                        #   call: cleanUp
 verbose "Exiting ..."                          #   call: verbose w/ output
#   test "$KILL" && $KILL -9 0                  #   if kill set, kill this proc
#  $KILL -TERM 0                                #   kill this proc
  exit $ECODE                                   #   exit with error code
}                                               # end of endProgram
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
cleanUp () {                                    # FUNCTION: CLEANUP
 verbose "Cleaning up."                         #  call: verbose w/ output
 test "x$RM" != "x" && {                        #  if RM set, then
  $RM -rf $TMP/$TEMPTEMP*                       #   remove these files
 }                                              #  end if RM set
}                                               # end of cleanUp
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
getOpts () {                                    # FUNCTION: GETOPTS
 test $# -gt 0 && {                             #  if passed, then
  set x "$@"; shift                             #  set passed to positional
  while test $# -gt 0                           #  while positional left
  do                                            #   do
   case "$1" in                                 #   check first positional
    "-verbose"     |"-verb"    |"-v") toggleVerbose           ; shift 1 ;;
    "-help"        |"-help"    |"-h") toggle DOHELP           ; shift 1 ;;
    "-debug"       |"-bug"     |"-d")                           shift 1 ;;
    "-background"  |"-back"    |"-b") toggle BACKGROUND       ; shift 1 ;;
    "-accountid"   |"-account" |"-1") ACCOUNT="$2"            ; shift 2 ;;
    "-domainname"  |"-domain"  |"-2") setDomainName "$2"      ; shift 2 ;;
    "-interactive" |"-inter"   |"-i") toggle INTERACTIVE      ; shift 1 ;;
    * ) error "\"$1\" unrecognized command line option."      ; shift 1 ;;
   esac                                         #   end case/check
  done                                          #  done while
 }                                              #  end test passwd
}                                               # end getOpts
                                                #  
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
findBin () {                                    # FUNCTION: FINDBIN
 VARIABLE=$1                                    #  VARIABLE is first passed
 PROGRAM=$2                                     #  PROGRAM is second passed
 shift 2;                                       #  move positional 2 spots
 test $# = 0 && { set x $MYPATH; shift; }       #  if no passed path, set
 NOTFOUND=""                                    #  initialize
 while test -z "$NOTFOUND" -a $# -gt 0          #  while not found, 
 do                                             #  do
  test -x "$1/$PROGRAM" && {                    #   if path/program, then
   eval $VARIABLE="$1/$PROGRAM"                 #    set VARIABLE and
   toggle NOTFOUND                              #    toggle NOTFOUND
  }                                             #   end if path/program
  shift                                         #   move positional params
 done                                           #  done while
 test -z "$NOTFOUND" && fatalError "$PROGRAM not found ..."
}                                               # end findbin
                                                #  
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
toggle () {                                     # FUNCTION: TOGGLE
 eval ONOFF=\$$@                                #  set ONOFF to passed var
 test "x$ONOFF" != "x" && {                     #  is VARIABLE on or off?
  eval $@="$FALSE"                              #   if on, set to off
 } || {                                         #  or else
  eval $@="$TRUE"                               #   if off, set to on
 }                                              #  end of variable on or off
}                                               # end toggle
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
help () {                                       # FUNCTION: HELP
 test "x$DOHELP" != "x" && {                    #  do help?
 $CAT <<EOHELP                                  #   yes, do help, display:
$CREDITS

USAGE: $lProg [options]
  -verbose    |-verb  |-v --> show program operations
  -help       |-help  |-h --> 
  -debug      |-bug   |-d --> debug ... make program noisy!
  -background |-back  |-b --> daemon / run in background.

EOHELP
 
 endProgram                                     #  exit program
 }                                              #  end if do help
}                                               # end help
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
finish () {                                     # FUNCTION: finish
 verbose "Finishing ..."                        #  call: verbose w/ params
}                                               # end finish
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
progInit () {                                   # FUNCTION: progInit
 verbose "Initializing ..."                     #  output if verbose
 findBin CP cp                                  #  find cp binary
 findBin ID id                                  #  find id binary
 findBin LN ln                                  #  find ln binary
 findBin WC wc                                  #  find wc binary
 findBin SED sed                                #  find sed binary
 findBin AWK awk                                #  find awk binary
 findBin SORT sort                              #  find sort binary
 findBin EXPR expr                              #  find expr binary
 findBin EGREP egrep                            #  find egrep binary
 findBin CLEAR clear                            #  find clear binary
 findBin SLEEP sleep                            #  find sleep binary
 findBin CHOWN chown                            #  find chown binary
 findBin RUNAS runas /export/home/system/bin    #  find runas binary
 findBin LOGGER logger                          #  find logger binary
 findBin USERADD useradd /usr/sbin /sbin        #  find useradd binary
 findBin IFCONFIG ifconfig /usr/sbin            #  find ifconfig binary
 findBin NSLOOKUP nslookup /usr/sbin /sbin      #  find nslookup binary
 DONIC="1"                                      #  do whois lookups
 ERRDELAY="1"                                   #  sleep on error delay
 WAITNIC="3"                                    #  wait for internic to reply
 WAITGIP="2"                                    #  wait for dns server to reply
 WAITMX="2"                                     #  wait for dns server to reply
 MENU="1"                                       #  menu to start with
 HOSTFILE="/etc/hosts"                          #  password file
 PASSWORDFILE="/etc/passwd"                     #  password file
 IPBASE="208.136.89"                            # 
 DMX="mail1.lobodirect.com"                     # 
 DCONTACT="Mark Biernacki"                      # 
 IPDEFAULT="208.136.89.10"                      # 
 IPSTART="100"                                  # 
 IPSTOP="250"                                   # 
 TAB="  "                                       #  a "TAB" (\t) inside ""'s
 NETINT="hme0"                                  #  set network alias interface
 default DEFAULT default                        #  set DEFAULT or use default
 DEFAULTGID=100                                 # 
 USERSHELL="/bin/false"                         # 
 LOWUID=1000                                    #  lowest valid user id
 HIGHUID=9999                                   #  highest valid uiser id
 RC_QMAIL="/etc/init.d/qmail"                   #  rc.qmail
 RC_HTTPD="/etc/init.d/httpd"                   #  rc.httpd
 RC_NAMED="/usr/sbin/ndc"                       # 
 LOGPRIORITY="auth.err"                         #  auth.err --> /adm/messages
 INTERNIC="/export/home/system/bin/internic"    #  set INTERNIC bin path
 MONGOLIB="/export/home/system/lib/mongo"       #
 DNSTEMPLATE="$MONGOLIB/dnstemplate.txt"        # 
 MDNSTEMPLATE="$MONGOLIB/namedmt.txt"           # 
 SDNSTEMPLATE="$MONGOLIB/namedst.txt"           # 
 HTTPVIRT="$MONGOLIB/httpvirt.txt"              # 
 HTTPDCONF="/usr/local/etc/httpd/conf/httpd.conf"       # 
 HTTPIDX="$MONGOLIB/ldindex.html"               # 
 DNSDIR="/var/named"                            # 
 MDNSCONF="$DNSDIR/etc/master"                  # 
 SDNSCONF="$DNSDIR/etc/slave"                   # 
 test "x$BACKGROUND" != "x" && BACKGROUND="&"   #  alter BACKGROUND value
 COMMANDS="$COMMANDS rootcheck mongo"           #  program commands
 QMD="/var/qmail"                               # 
 QMCVD="$QMD/control/virtualdomains"            # 
 QMCRH="$QMD/control/rcpthosts"                 # changed from rcpthosts.save 
 WEBSERVER="/usr/local/etc/httpd"               # 
 HTTPDCONF="$WEBSERVER/conf/httpd.conf"         # 
 LINKHOME="/export/home"                        # 
 HOMEDIRS="/usr/local/etc/home"                 # 
 HOMEUSER="/export/home/system/lib/user"        #  example home directory
 FS='
}                                               # end progInit
                                                # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
HTTPD () {                                      # FUNCTION: HTTPD
 verbose "HTTPD [$@]"                           # 
 set x $*; shift                                #  dequote 
 while test $# -gt 0                            # 
 do                                             # 
  case "$1" in                                  # 
   status  )  $RC_HTTPD status                  # 
              PAUSE="$TRUE"                     # 
            ;;                                  # 
   stop    )  $RC_HTTPD stop                    # 
              logger "HTTPD: stop"              # 
            ;;                                  # 
   start   )  $RC_HTTPD start                   # 
              logger "HTTPD: start"             # 
            ;;                                  # 
   restart )  $RC_HTTPD restart                 # 
              logger "HTTPD: restart"           # 
            ;;                                  # 
   nothing )  :                                 # 
            ;;                                  # 
   *       ) error "HTTPD: Unrecognized: $1"    # 
            ;;                                  # 
  esac                                          # 
  shift                                         # 
 done                                           # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
QMAIL () {                                      # FUNCTION: QMAIL
 verbose "QMAIL [$@]"                           # 
 set x $*; shift                                #  dequote 
 while test $# -gt 0                            # 
 do                                             # 
  case "$1" in                                  # 
   status  )  $RC_QMAIL status                  # 
              PAUSE="$TRUE"                     # 
            ;;                                  # 
   stop    )  $RC_QMAIL stop                    # 
              logger "QMAIL: stop"              # 
            ;;                                  # 
   start   )  $RC_QMAIL start                   # 
              logger "QMAIL: start"             # 
            ;;                                  # 
   restart )  $RC_QMAIL restart                 # 
              logger "QMAIL: restart"           # 
            ;;                                  # 
   nothing )  :                                 # 
            ;;                                  # 
   *       ) error "QMAIL: Unrecognized: $1"    # 
            ;;                                  # 
  esac                                          # 
  shift                                         # 
 done                                           # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
NAMED () {                                      # FUNCTION: NAMED_RESTART
 verbose "NAMED [$@]"                           # 
 set x $*; shift                                #  dequote 
 while test $# -gt 0                            # 
 do                                             # 
  case "$1" in                                  # 
   status  )  $RC_NAMED status                  # 
              PAUSE="$TRUE"                     # 
            ;;                                  # 
   stop    )  $RC_NAMED stop                    # 
              logger "NAMED: stop"              # 
            ;;                                  # 
   start   )  $RC_NAMED start                   # 
              logger "NAMED: start"             # 
            ;;                                  # 
   restart )  $RC_NAMED restart                 # 
              logger "NAMED: restart"           # 
            ;;                                  # 
   nothing )  :                                 # 
            ;;                                  # 
   *       ) error "NAMED: Unrecognized: $1"    # 
            ;;                                  # 
  esac                                          # 
  shift                                         # 
 done                                           # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
promptinput () {                                # 
 test $# -gt 0 && P="$1" || P="Input: "         # 
 test $# -gt 1 && V="$2" || V="_"               # 
 $ECHO -n "$P"                                  #  Prompt for input
 read INPUT                                     #  Read/Get input 
 set x "$INPUT"; shift                          # 
 eval $V=\"$@\"                                 # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
lcase () {                                      # 
 verbose "lcase"                                #  blah
 test $# = 0 && {                               # 
  P="Word to convert to lowercase"              # 
  promptinput "$P"                              # 
  set x "$_"; shift                             # 
 }                                              # 
 set x `$ECHO "$@" | $TR "[A-Z]" "[a-z]"`;shift # 
 $ECHO "$@"                                     # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
ucase () {                                      # 
 verbose "lcase"                                #  blah
 test $# = 0 && {                               # 
  P="Word to convert to uppercase"              # 
  promptinput "$P"                              # 
  set x "$_"; shift                             # 
 }                                              # 
 set x `$ECHO "$@" | $TR "[a-z]" "[A-Z]"`;shift # 
 $ECHO "$@"                                     # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
cls () {                                        # FUNCTION: CLS
 $CLEAR                                         #  clear screen
}                                               # end CLS
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
pressreturn () {                                # 
 test "x$NOPAUSE" = "x" && {                    # 
  $ECHO -n "Press [RETURN] to continue:"        # 
  read INPUT                                    # 
 }                                              # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
pausereturn () {                                # 
 X="$NOPAUSE"                                   # 
 NOPAUSE=""                                     # 
 test "x$PAUSE" != "x" && pressreturn           # 
 NOPAUSE="$X"                                   # 
 PAUSE=""                                       # 
}                                               # 
                                                # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
logger () {                                     # FUNCTION: LOGGER
 verbose "logger [$@]"                          # 
 $LOGGER -p $LOGPRIORITY "[DEBUGGING] $uProg- $@"               # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
toggleVerbose () {                              # FUNCTION: TOGGLEVERBOSE
 verbose "verbose"                              # 
 toggle VERBOSE                                 #
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
toggleDebug () {                                # FUNCTION: TOGGLEDEBUG
 verbose "debug"                                # 
 toggle DEBUG                                   # 
 test "x$DEBUG" != "x" && {                     # 
  set -x                                        # 
 } || {                                         # 
  set +x                                        # 
 }                                              # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
getVirtAfD () {                                 # FUNCTION: GETVIRTAFD
 local _gVA X                                   # 
 test $# -gt 0 && X="$1" || X="$DOMAIN"         # 
 verbose "getVirtAfD [$X]"                      # 
 test "x$X" != "x" && {                         # 
  IFS=":"                                       # 
  set x `$EGREP "^$X:" $QMCVD`; shift           # 
  IFS="$OFS"                                    # 
  test "x$1" != "x" && shift                    # 
 } || {                                         # 
  set x; shift                                  # 
 }                                              # 
 test "x$1" != "x" && {                         # 
  ACCOUNT="$@"                                  # 
 }                                              # 
 _="$@"; echo "$_"                              # 
 eval $_gVA                                     # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
getVirtDfA () {                                 # FUNCTION: GETVIRTDFA
 local _gVD X                                   # 
 test $# -gt 0 && X="$1" || X="$ACCOUNT"        # 
 verbose "getVirtDfA [$X]"                      # 
 test "x$X" != "x" && {                         # 
  IFS=":$IFS"                                   # 
  set x `$EGREP ":$X^" $QMCVD`; shift           # 
  IFS="$OFS"                                    # 
  test "x$1" != "x" && {                        # 
   set x "$1"; shift                            # 
  }                                             # 
 } || {                                         # 
  set x; shift                                  # 
 }                                              # 
 test "x$1" != "x" && {                         # 
  DOMAIN="$@"                                   # 
 }                                              # 
 _="$@"; echo "$_"                              # 
 eval $_gVD                                     # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
getNextUID () {                                 # FUNCTION: GETNEXTUID
 verbose "getNextUID"                           # 
 set x `$AWK -F: '$3>'$LOWUID' && $3<'$HIGHUID' {u=$3} END {print u}'< $PASSWORDFILE`; 
shift    # 
 set x `$EXPR $1 + 1`; shift                    # 
 _="$@"; echo "$_"                              # 
}                                               # 
                                                # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
getNextIP () {                                  # FUNCTION: GETNEXTIP
 test $# -gt 0 && X="$1" || X="$IPBASE"         # 
 test $# -gt 1 && Y="$2" || Y="$IPSTART"        # 
 test $# -gt 2 && Z="$3" || Z="$IPSTOP"         # 
 verbose "getNextIP [$X] [$Y] [$Z]"             # 
 set x `echo "$IPBASE" | $WC -c`; shift         # 
 BASEL="$1"                                     # 
 $SORT -n +0.$BASEL $HOSTFILE | $AWK '
  {print "["$0"]"; printf ""}
 ' >>/tmp/g
 set x `$SORT -n +0.$BASEL $HOSTFILE |  $AWK '
  BEGIN {
         BASE    = "'$X'";
         IPSTART = "'$Y'";
         IPSTOP  = "'$Z'";
         FREE    = "'$Y'"
        }
  substr($1,0,length(BASE)) == BASE {
    IP=substr($1,length(BASE)+2,3);
    if ( int(IP) >= int(IPSTART) && \
    int(IP) <= int(IPSTOP) ) {
      if ( int(IP) > int(FREE)) {
        exit
      };
      if ( int(IP) != DUPIP ) {
       FREE=FREE+1
      }
    }
    DUPIP = IP
  }
  END { if (int(FREE) <= int(IPSTOP)) print FREE }
  '`; shift                                     # 
 case "$X" in                                   # 
  *"." ) set x "$X$1" ; shift ;;                # 
  *    ) set x "$X.$1"; shift ;;                # 
 esac                                           # 
 _="$@"                                         # 
}                                               # 
                                                # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
freeIP () {                                     # FUNCTION: GETNEXTIP
 verbose "freeIP"                               # 
 getNextIP; set x "$_"; shift                   # 
 echo "Next Available IP: $@"                   # 
 PAUSE="$TRUE"                                  # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
addToEtcHosts () {                              # FUNCTION: ADDTOETCHOSTS
 test $# -gt 0 && X="$1" || X="$DOMAIN"         # 
 test $# -gt 1 && Y="$2" || Y="$IP"             # 
 test $# -gt 2 && Z="$3" || Z="$DCONTACT"       # 
 verbose "AddToEtcHosts [$X] [$Y]"              # 
 checkEtcHosts "$X" "$Y"; set x "$_"; shift     # 
 test "x$1" = "x" && {                          # 
  O="$Y $X      $TWOLDOM                # $Z"   # 
  echo "$O" >>$HOSTFILE                         # 
 } || {                                         # 
  error "$X already in $HOSTFILE!"              # 
  PAUSE="$TRUE"                                 # 
 }                                              # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
getTheIP () {                                   # FUNCTION: GETTHEIP
 test $# -gt 0 && X="$1" || X="$DOMAIN"         # 
 verbose "getTheIP [$X]"                        # 
 checkEtcHosts "$X"; set x "$_"; shift          # 
 test "x$1" = "x" && {                          # 
  getNextIP; set x "$_"; shift                  # 
 } || {                                         # 
  set x "$_"; shift                             # 
  set x $*; shift                               #  dequote
  set x $1; shift                               # 
 }                                              # 
 setIP "$@";                                    #  
 _="$@"
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
makeUserAccount () {                            # FUNCTION: MAKEUSERACCOUNT
 test $# -gt 0 && X="$1" || X="$ACCOUNT"        # 
 verbose "makeUserAccount [$X]"                 # 
 set x `$EGREP "^$X:" $PASSWORDFILE`; shift     # bah! fixed 12/03/98
 test $# = 0 && {                               # 
  NUID=`getNextUID`                             # 
  MSG="Creating:  Account=$X UID=$NUID"         # 
  verbose "$MSG"                                #
  logger "$MSG"                                 # 
#  $LN -s "$HOMEDIRS/$X" $LINKHOME/$X           # not needed after 12/09/98
 # $USERADD -u $NUID -g $DEFAULTGID -d "$LINKHOME/$X" -s $USERSHELL -m -k $HOMEUSER $X 
>>/dev/tty
  $USERADD -u $NUID -g $DEFAULTGID -d "$LINKHOME/$X" -s $USERSHELL $X >>/dev/tty
  setupHomeDir "$X"                             # 
 } || {                                         # 
  error "Account $X already exists!"            # 
  PAUSE="$TRUE"                                 # 
 }                                              # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                #
swapMenu () {                                   # FUNCTION: SWAPME
 local _sMnu X                                  # 
 test $# -gt 0 && X="$1" || X="$MENU"           # 
 verbose "swapMenu [$X]"                        #   call: verbose w/ output
 case "x$MENU" in                               # 
  x"1" ) MENU="2" ;;                            # 
  *    ) MENU="1" ;;                            # 
 esac                                           # 
 eval $_sMnu                                    # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                #
menu () {                                       # FUNCTION: MAINMENU
 local _mnu X                                   # 
 test $# -gt 0 && X="$1" || X="$MENU"           # 
 verbose "Menu [$X]"                            #   call: verbose w/ output
 case "x$X" in                                  # 
  x"2" ) extMenu  ;;                            # 
  *    ) mainMenu ;;                            # 
 esac                                           # 
 eval $_mnu                                     # 
}                                               # 
                                                #
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
mainMenu () {                                   # FUNCTION: MENU
 cls
 $CAT <<EOF


              _____   ________    _______    ________ ________    
             /     \  \_____  \   \      \  /  _____/ \_____  \   
            /  \ /  \  /   |   \  /   |   \/   \  ___  /   |   \  
           /    Y    \/    |    \/    |    \    \_\  \/    |    \ 
           \M___|__  /\O______  /\N___|__  /\G_____  /\O______  / 
                   \/         \/         \/        \/     (TM)\/ 

         ----------==========[ MONGO MAIN MENU ]==========----------

    (1,a) Set Account ID                        ( v ) Verbose [$VERBOSE]
    (2,d) Set Domain name                       (bug) Debug   [$DEBUG]
    (3,i) Set IP                                ( x ) eXtended Menu

    (svd) Setup Virtual Domain                  (fip) Get next free IP
    (mka) Make Account                          ( ip) Get IP (match/next)
    (shd) Setup Home Directory                  (cps) Check /etc/passwd
    (dns) Setup DNS                             (gva) Get domain account
                      Account : $ACCOUNT
                      Domain  : $DOMAIN
                      IP      : $IP

 (Q,q) Quit, (0) Check Everything, (00) Do everything... start praying!
EOF
}                                               #
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
extMenu () {                                    # FUNCTION: EXTMENU
 cls
 $CAT <<EOF


              _____   ________    _______    ________ ________    
             /     \  \_____  \   \      \  /  _____/ \_____  \   
            /  \ /  \  /   |   \  /   |   \/   \  ___  /   |   \  
           /    Y    \/    |    \/    |    \    \_\  \/    |    \ 
           \M___|__  /\O______  /\N___|__  /\G_____  /\O______  / 
                   \/         \/         \/        \/     (TM)\/ 
      ----------==========[ MONGO EXTENDED MENU ]==========----------

 (1,a) Set Account ID       (4,?) ?                   (7,?) Get DNS Servers
 (2,d) Set Domain name      (5,?) ?                   (8, ) Mongo Sys Status
 (3,i) Set IP               (6,?)                     (9,?) Mongo Sys Whacker
 (svd) Setup Virtual Domain ( x ) Swap Menus          ( v ) Verbose [$VERBOSE]
 (mka) Make Account         (fip) Get next free IP    (bug) Debug   [$DEBUG]
 (shd) Setup Home Directory ( ip) Get IP (match/next) (gvd) Get account domain
 (dns) Setup DNS            (cps) Check /etc/passwd   (gva) Get domain account
 (gmx) Get MX record info   (ath) add to /etc/hosts   (sys) Mongo Sys Whacker

 (www) HTTPD [Re]start      (qm ) QMAIL [Re]start     (ndc) NAMED [Re]start
 (wws) HTTPD Status         (qms) QMAIL Status        (dns) NAMED Status
 (wwx) HTTPD Stop           (qmx) QMAIL Stop          (dnx) NAMED Stop

 Account=[$ACCOUNT] Domain=[$DOMAIN] IP=[$IP]
 (Q,q) Quit, (0) Check Everything, (00) Do everything... start praying!
EOF
}                                               #
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
setupDOTQmail () {                              # 
 local _sDQM X                                  # 
 test $# -gt 0 && X="$1" || X="$ACCOUNT"        # 
 verbose "setupDOTQmail [$X]"                   # 
 getHomeDir "$X"; HOMEDIR="$_"                  # 
 test "x$HOMEDIR" != "x" && {                   # 
  test -s "$HOMEDIR/.qmail" || {                # 
   verbose "Creating: $HOMEDIR/.qmail"          # 
   $CP -p $HOMEUSER/.qmail $HOMEDIR             # 
   $CHOWN "$X" $HOMEDIR/.qmail                  # 
  }                                             # 
 }                                              # 
 eval $_sDQM                                    # 
}                                               # 
                                                # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
setupDOTQmailDefault () {                       # 
 local _sDQMD X                                 # 
 test $# -gt 0 && X="$1" || X="$ACCOUNT"        # 
 verbose "setupDOTQmailDefault [$X]"            # 
 setupDOTQmail "$X"                             # 
 test "x$HOMEDIR" != "x" && {                   # 
  test ! -s "$HOMEDIR/.qmail-default" -a \
      ! -h "$HOMEDIR/.qmail-default" && {       # 
   verbose "Creating: $HOMEDIR/.qmail-default"  # 
   $RUNAS -"$X" $LN -s "$HOMEDIR/.qmail" "$HOMEDIR/.qmail-default"      # 
#   $CP -p $HOMEUSER/.qmail-default $HOMEDIR    # 
#   $CHOWN "$X" $HOMEDIR/.qmail-default         # 
  }                                             # 
 }                                              # 
 eval $_sDQMD                                   # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
setupHomeDir () {                               # 
 test $# -gt 0 && X="$1" || X="$ACCOUNT"        # 
 test $# -gt 1 && X="$2" || Y="$HOMEDIRS"       # 
 verbose "setupHomeDir [$X] [$Y]"               # 
 HOME="$Y/$X"                                   # 
 GROUP="none"                                   # 
 getHomeDir "$X"; HOMEDIR="$_"                  # 
# test -h "$LINKHOME/$X" || {                   # not needed after 12/09/98
#  verbose "Linking: $LINKHOME/$X --> $HOME"    # not needed after 12/09/98
#  $LN -s "$HOME" "$LINKHOME/$X"                # not needed after 12/09/98
# }                                             # not needed after 12/09/98
 test -d "$HOME" || {                           # 
  verbose "Creating Directory: $HOME"           # 
  $MKDIR "$HOME"                                # 
  $CHOWN "$X" "$HOME"                           # 
 }                                              # 
 test -d "$HOME/public_html" || {               # 
  verbose "Creating: $HOME/public_html"         # 
  $CP -Rp $HOMEUSER/public_html $HOME           # 
  $CHOWN -R "$X" $HOME/public_html              # 
 }                                              # 
 test -d "$HOME/Maildir" || {                   # 
  verbose "Creating: $HOME/Maildir"             # 
  $CP -Rp $HOMEUSER/Maildir $HOME               # 
  $CHOWN -R "$X" $HOME/Maildir                  # 
 }                                              # 
 setupDOTQmail "$X"                             # 
 setupDOTQmailDefault "$X"                      # 
# test -s "$HOMEDIR" || {                       # not needed after 12/09/98
#  verbose "Linking: $HOMEDIR --> $HOME"        # not needed after 12/09/98
#  $LN -s "$LINKHOME/$X" "$HOMEDIR"             # not needed after 12/09/98
# }                                             # not needed after 12/09/98
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
setupDNS () {                                   # 
 test $# -gt 0 && X="$1" || X="$DOMAIN"         # 
 test $# -gt 1 && Y="$2" || Y="$IP"             # 
 test $# -gt 2 && Z="$3" || Z=""                # 
 test $# -gt 3 && V="$4" || V="$ACCOUNT"        # 
 verbose "setupDNS [$X] --> [$Y] [$Z] [$V]"     # 
 _X="$X"; _Y="$Y"; _Z="$Z";                     # 
 test "x$Y" = "x" && {                          # 
  getTheIP "$X"; _Y="$_"                        # 
 }                                              # 
 X="$_X"; Y="$_Y"; Z="$_Z";                     # 
 verbose "setupDNS [$X] --> [$Y] [$Z] [$V]"     # 
 test "x$Z" = "x" && {                          # 
  setMX "$DMX"; Z="$_"                          # 
 }                                              # 
 U="$V, $DCONTACT"                              # FIX CONTACT
 TD=`$DATE +"%m/%d/%y %H:%M:%S"`                #  set TD to current date/time
 W="$TD - $TD $uProg"                           # 
 verbose "setupDNS [$X] [$Y] [$Z] [$U] [$V] [$W]"               # 
 test "x$X" = "x" && {                          # 
  error "No domain provided???"                 # 
 }                                              # 
 test "x$Y" = "x" && {                          # 
  error "No IP provided???"                     # 
 }                                              # 
 test "x$Z" = "x" && {                          # 
  error "No MX provided???"                     # 
 }                                              # 
 test "x${X}x${Y}x${Z}x" != "xxx" && {          # 
  FILE="$DNSDIR/master/$X"                      # assumes domain is file name
  test ! -s "$FILE" && {                        # 
   verbose "$X --> $FILE"                       # 
   PROG="s/%D%/$X/g; s/%IP%/$Y/g; s/%MX%/$Z/g; "        # 
   PROG="$PROG s/%C%/$U/g; s/%A%/$V/g; "        # 
   PROG="$PROG s|%T%|$W|g; "                    # 
   $SED -e "$PROG" <$DNSTEMPLATE >$FILE         # 
  } || {                                        # 
   error "$FILE already exists!"                # 
   PAUSE="$TRUE"                                # 
  }                                             # 
  PAT="zone .$X. in {"                          # 
  set x `$EGREP "$PAT" $MDNSCONF`; shift        # 
  test $# = 0 && {                              # 
   verbose "$X --> $MDNSCONF"                   # 
   $SED -e "$PROG" <$MDNSTEMPLATE >>$MDNSCONF   # 
  }                                             # 
  set x `$EGREP "$PAT" $SDNSCONF`; shift        # 
  test $# = 0 && {                              # 
   verbose "$X --> $SDNSCONF"                   # 
   $SED -e "$PROG" <$SDNSTEMPLATE >>$SDNSCONF   # 
  }                                             # 
  NAMED restart 1>/dev/null 2>/dev/null         # 
  addToEtcHosts "$X" "$Y" "$U"                  # 
 }                                              # 
}                                               # 
                                                # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
setupIPAlias () {                               # 
 test $# -gt 0 && X="$1" || X="$DOMAIN"         # 
 verbose "setupIPAlias [$X]"                    # 
 _X="$X"                                        # 
 getTheIP "$X"; Y="$_"                          # 
 X="$_X"                                        # 
 IFS="."                                        # 
 set x $Y; shift                                # 
 IFS="$OFS"                                     # 
 Z="$4"                                         # 
 echo "CHECK --> IP[$IP] Y[$Y]"
 IPAF="/etc/hostname.$NETINT:$Z"                # 
 set x `$CAT $IPAF 2>/dev/null`; shift          # 
 test $# -gt 0 && {                             # 
  error "Wrote over $IPAF --> $1"               # 
  PAUSE="$TRUE"                                 # 
 }                                              # 
 verbose "Creating: $IPAV --> $X"               # 
 echo "$X" >$IPAF                               # 
 verbose "ifconfig: $NETINT:$Z $Y up"           # 
 logger "$X ==> ifconfig: $NETINT:$Z --> $Y up" # 
 $IFCONFIG $NETINT:$Z $Y up                     # 
 _="$@"                                         # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
sub () {                                        # 
 verbose "sub"                                  #  blah
 X=""
 Y="Y BEFORE"
 echo "0 before X[$X] Y[$Y]"
 getPWENT "$ACCOUNT" 7                          # 
 echo "1 after X[$X] Y[$Y]"
echo "SUB _pWE [$_pWE]"
 eval $_pWE
 echo "2 after X[$X] Y[$Y]"
 echo "pw res --> [$_]" >>/dev/tty                              # 
 PAUSE="$TRUE"                                  # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
interactive () {                                # FUNCTION: COMMAND
 verbose "interactive"                          #  blah
 DONE=""                                        # 
 while test "x$DONE" = "x"                      # 
 do                                             # 
  PAUSE="$VERBOSE"                              # 
  STAT=""                                       # 
  menu                                          # 
  $ECHO -n " Choice: "                          # 
  read COMMAND                                  # 
  BAD=""                                        # 
  test "x$COMMAND" = "xz" && COMMAND="sub"      # used for quick menu testing
  case "$COMMAND" in                            # 
   "everything"|"0" |"0") checkEverything    ;; # 
   "check"     |"00"    ) doEverything       ;; # 
   "account"   |"a" |"1") setAccountID       ;; #
   "domain"    |"2" |"d") setDomainName      ;; # 
   "setip"     |"3" |"i") setIP              ;; # 
   "sdomain"   |"D" |"D") setDomainName      ;; # 
   "cdomain"   |"d" |"d") setDomainName      ;; # 
   "quit"      |"Q" |"q") DONE="1"           ;; # 
   "verbose"   |"V" |"v") toggleVerbose      ;; # 
   "bug"       |"." |".") toggleDebug        ;; # 
   "whodns"    |"7" |"7") getVal getDNSServ  ;; # 
   "sys"       |"8" |"8") sysStatus          ;; # 
   "whack"     |"9" |"9") sysWhack           ;; # 
   "menu"      |"X" |"x") swapMenu           ;; # 
   "sub"                ) sub                ;; # 
   "cps"                ) checkPasswdString  ;; # 
   "shd"                ) setupHomeDir       ;; # 
   "sqmvd"              ) setupQMVD          ;; # 
   "wvirt"              ) setupHTTPVirt      ;; # 
   "svd"                ) setupVD            ;; # 
   "ip"                 ) getTheIP           ;; # 
   "gva"                ) getVirtAfD         ;; # 
   "gvd"                ) getVirtDfA         ;; # 
   "gmx"                ) getVal getMX       ;; # 
   "ath"                ) addToEtcHosts      ;; # 
   "mka"                ) makeUserAccount    ;; # 
   "fip"                ) freeIP             ;; # 
   "mx"                 ) setMX              ;; # 
   "dns"                ) setupDNS           ;; # 
   "ndc"                ) NAMED restart      ;; # 
   "nds"                ) NAMED status       ;; # 
   "ndx"                ) NAMED stop         ;; # 
   "qm"                 ) QMAIL restart      ;; # 
   "qms"                ) QMAIL status       ;; #
   "qmx"                ) QMAIL stop         ;; #
   "www"                ) HTTPD restart      ;; # 
   "wws"                ) HTTPD status       ;; # 
   "wwx"                ) HTTPD status       ;; # 
   * ) echo "Command unrecognized: $COMMAND"; $SLEEP $ERRDELAY ;;       # 
  esac                                          # 
  pausereturn                                   # 
 done                                           # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
#xcxc
formOUT () {                                    # FUNCTION: formOUT
# $CLEAR                                                # 
 test "x$ACCOUNT" != "x" && {                   # 
  $CAT <<EOF

ACCOUNT:
User Name       : $ACCOUNT
Account Info    : $SACCOUNT
Home Directory  : $HOMEDIR
Shell           : $SSHELL
Home Dir Info   : $SHOMEDIR
Home Dir Link   : $LHOMEDIR
Account .qmail  : $SDOTQM
EOF
 }                                              # 
 test "x$DOMAIN" != "x" && {                    # 
  $CAT <<EOF

DOMAIN:
Domain          : $DOMAIN = $IP
IP Config       : $SINT $SIPM
DNS Servers     : $DNSSERVERS
MX Servers      : $SMX
Zone File       : $ZONEFILE
Master/Slave    : $SMDNS/$SSDNS
Qmail V Domain  : $QMVD

WEB:
Virtual Web     : $SVWWW
WWW Domain Link : $SDWLINK
Server index    : $SINDEX
Server logs     : $SLOGS
Server cgi-bin  : $SCGI
EOF
 }                                              # 
$CAT <<EOF

STATUS          : $STAT

EOF
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
formMark () {                                   # FUNCTION: formMark
 $CLEAR
 $CAT <<EOF
User Name                               : $ACCOUNT
Password                                : $passwd
HOST                                    : $host
~$ACCOUNT/public_html/logs/             : 
~$ACCOUNT/public_html/cgi-bin/          : 
~$ACCOUNT/public_html/index.html/       : 
Account Verified                        :
Mail Host                               : 
MX Record                               : 
Send Welcome Email                      :
NIC ID#                                 : 
Whois Verified                          : 
IP #                                    : 
Named.conf                              : 
zone file                               : 
DNS Verified                            : 
WWW, and A                              : 
Host.conf entry                         : 
Restart WWW Verified                    : 
Browse Same Index Page                  : 
FTP Upload sample Image                 :
EOF
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
local () {                                      # FUNCTION: LOCAL
 _l="$1"; shift                                 # 
 while test $# -gt 0                            # 
 do                                             # 
  eval __l="$1=\'\$$1\'"                        # -
  ___l="$___l${___l:+;}$__l"
  shift                                         # -
 done                                           # 
 eval $_l=\"$___l\"                             # 
 ___l=""                                        # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
getPWENT () {                                   # FUNCTION: GETPWENT
 local _pWE X Y                                 # 
 test $# -gt 0 && X="$1" || X="$ACCOUNT"        # 
 test $# -gt 1 && Y="$2" || Y="@"               # 
 IFS=""                                         # 
 set x `$EGREP "^$X:" $PASSWORDFILE`; shift     # 
 IFS="$OFS"                                     # 
 test "$Y" != '@' && {                          # 
  case "$@" in                                  # 
   *"::"* ) set x `$ECHO "$@" | $SED 's/::/:BLANK:/g'`; shift ;;        # 
  esac
  IFS=":"                                       # 
  set x $@; shift                               # 
  IFS="$OFS"                                    # 
 }                                              # 
 eval _=\"\$$Y\"                                # 
 eval $_pWE                                     # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
getHomeDir () {                                 # FUNCTION: GETPWENT
 local _gHD X                                   # 
 test $# -gt 0 && X="$1" || X="$ACCOUNT"        # 
 verbose "getHomeDir [$X]"                      # 
 getPWENT "$X" 6; set x "$_"; shift             # 
 _="$@"                                         # 
 eval $_gHD
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
getUserShell () {                               # FUNCTION: GETUSERSHELL
 local _gUS X                                   # 
 test $# -gt 0 && X="$1" || X="$ACCOUNT"        # 
 verbose "getUserShell [$X]"                    # 
 getPWENT "$X" 7; set x "$_"; shift             # 
 _="$@"                                         # 
 eval $_gUS                                     # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
checkPasswdString () {                          # FUNCTION: CHECKPASSWDSTRING
 test $# -gt 0 && X="$@" || X="$ACCOUNT"        # 
 verbose "checkPasswdString [$X]"               # 
 test "x$X" != "x" && {                         # 
  set x "$X"; shift                             # 
 }                                              # 
 test $# = 0 && {                               # 
  $ECHO -n "String: "                           # 
  read INPUT                                    # 
  test "x$INPUT" != "x" && {                    # 
   set x "$INPUT"; shift                        # 
  }                                             # 
 }                                              # 
 test $# -gt 0 && {                             # 
  set x $*; shift                               # 
  while test $# -gt 0                           # 
  do                                            # 
   echo ""                                      # 
   echo "Searching: \`\`$1'' in $PASSWORDFILE"  # 
   $EGREP "$1" $PASSWORDFILE                    # 
   shift                                        # 
  done                                          # 
  test "x$VERBOSE" = "x" && pressreturn         # 
 }                                              # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
checkZoneFile () {                              # FUNCTION: CHECKZONEFILE
 local _cZF X                                   # 
 test $# -gt 0 && X="$@" || X="$DOMAIN"         # 
 verbose "checkZoneFile [$X]"                   # 
 FILE="$DNSDIR/master/$X"                       # assumes domain is file name
 test -f "$FILE" && {                           # 
  set "$FILE"                                   # 
 } || {                                         # 
  set "MISSING"                                 # 
  stat "NOZONE"                                 # 
 }                                              # 
 _="$@"                                         # 
 eval $_cZF                                     # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
checkDir () {                                   # FUNCTION: CHECKDIR
 local _cD X                                    # 
 test $# -gt 0 && X="$1" || X="$DIR"            # 
 verbose "checkDir [$X]"                        #  blah
 set x `$LS -ld $X/. 2>&1`; shift               #  ls dir, not link!
 test $# = 9 && {                               # 
  set x "$1 $3 $4 $5 $X"; shift                 # 
 } || {                                         # 
  set x "MISSING --> $X"; shift                 # 
 }                                              # 
 _="$@"                                         # 
 eval $_cD                                      # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
checkFile () {                                  # FUNCTION: CHECKFILE
 local _cF X                                    # 
 test $# -gt 0 && X="$@" || X="$FILE"           # 
 verbose "checkFile [$X]"                       #  blah
 set x `$LS -ld $X 2>&1`; shift                 #  ls dir, not link!
 test $# = 9 && {                               # 
  set x "$1 $3 $4 $5 $9"; shift                 # 
 } || {                                         # 
  set x "MISSING --> $X"; shift                 # 
 }                                              # 
 _="$@"                                         # 
 eval $_cF                                      # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
checkLink () {                                  # FUNCTION: CHECKFILE
 local _cL X                                    # 
 test $# -gt 0 && X="$@" || X="$FILE"           # 
 verbose "checkLink [$X]"                       #  blah
 set x `$LS -ld $X 2>/dev/null`; shift          #  ls dir, not link!
 test $# = 11 && {                              # 
  shift 8                                       # 
  set x "$@"; shift                             # 
 } || {                                         # 
  checkFile "$X"; set x $_; shift               # 
 }                                              # 
 _="$@"                                         # 
 eval $_cL                                      # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
stat () {                                       # FUNCTION: STAT
 STAT="$STAT${STAT:+ }$@"                       # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
checkAccount () {                               # FUNCTION: CHECKACCOUNT
 local _cA X                                    # 
 test $# -gt 0 && X="$@" || X="$ACCOUNT"        # 
 verbose "checkAccount [$X]"                    #  blah
 getPWENT "$X"                                  # 
 test "x$_" = "x" && {                          # 
  set x "NO ACCOUNT"; shift                     # 
  stat "NOACCOUNT"                              # 
 } || {                                         # 
  IFS=":"                                       # 
  set x $_; shift                               # 
  IFS="$OFS"                                    # 
  set x "$5, $3 $4"; shift                      # 
 }                                              # 
 _="$@"                                         # 
 eval $_cA                                      # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
checkHomeDir () {                               # FUNCTION: CHECKHOMEDIR
 local _cHD X Y Z V F                           # 
 test $# -gt 0 && X="$1" || X="$ACCOUNT"        # 
 verbose "checkHomeDir [$X]"                    # 
# set x `$INTERNIC -n $X`; shift 2              # 
 getHomeDir "$X"; HOMEDIR="$_"                  # 
 V=""                                           #  OWNER
 Y=""                                           #  PERMS
 Z=""                                           #  FILES
 F="$HOMEDIR/."                                 # 
 verbose "Checking: $F"                         # 
 test -d "$F" || {                              # 
  Z="$HOMEDIR"                                  # 
 } && {                                         # 
  checkDir "$F"; set x $_; shift                # 
  case "$1" in                                  # 
   "drwx"?????"x" ) :           ;;              # 
   *              ) Y="$Y${Y:+ }homedir"        #  chmod here?
  esac                                          # 
  test "x$2" = "x$X" || {                       # 
   V="$V${V:+ }homedir"                         #  chown here?
  }                                             # 
  F="$HOMEDIR/.qmail"                           # 
  verbose "Checking: $F"                        # 
  test -s "$HOMEDIR/.qmail" && {                # 
   checkFile "$F"; set x $_; shift              # 
   test "x$2" = "x$X" || {                      # 
    V="$V${V:+ }.qmail"                         #  chown here?
   }                                            # 
  } || {                                        # 
   Z="$Z${Z:+ }.qmail"                          # 
  }                                             # 
  F="$HOMEDIR/public_html/."                    # 
  verbose "Checking: $F"                        # 
  test -d "$F" && {                             # 
   checkDir "$F"; set x $_; shift               # 
   case "$1" in                                 # 
    "drwx"?????"x" ) :           ;;             # 
    *              ) Y="$Y${Y:+ }public_html"   #  chmod here?
   esac                                         # 
   test "x$2" = "x$X" || {                      # 
    V="$V${V:+ }public_html"                    #  chown here?
   }                                            # 
   F="$HOMEDIR/public_html/logs/."              # 
   verbose "Checking: $F"                       # 
   test -d "$F" && {                            # 
    checkDir "$F"; set x $_; shift              # 
    test "x$2" = "x$X" || {                     # 
     V="$V${V:+ }public_html/logs"              #  chown here?
    }                                           # 
   } || {                                       # 
    Z="$Z${Z:+ }public_html/logs"               # 
   }                                            # 
   F="$HOMEDIR/public_html/cgi-bin/."           # 
   verbose "Checking: $F"                       # 
   test -d "$F" && {                            # 
    checkDir "$F"; set x $_; shift              # 
    test "x$2" = "x$X" || {                     # 
     V="$V${V:+ }public_html/cgi-bin"           #  chown here?
    }                                           # 
   } || {                                       # 
    Z="$Z${Z:+ }public_html/cgi-bin"            # 
   }                                            # 
   F="$HOMEDIR/public_html/index.html"          # 
   verbose "Checking: $F"                       # 
   test -f "$F" && {                            # 
    checkFile "$F"; set x $_; shift             # 
    test "x$2" = "x$X" || {                     # 
     V="$V${V:+ }public_html/index.html"        #  chown here?
    }                                           # 
   } || {                                       # 
    Z="$Z${Z:+ }public_html/index.html"         # 
   }                                            # 
  } || {                                        # 
   Z="$Z${Z:+ }public_html"                     # 
  }                                             # 
 }                                              # 
 test "x$Z" = "x" && {                          # 
  test "x$V$Y" != "x" || {                      # 
   Z="ok, whew!"                                # 
  }                                             # 
 } || {                                         #   
  Z="MISSING --> $Z"                            # 
 }                                              # 
 test "x$Y" = "x" || {                          # 
  Z="$Z${Z:+, }PERMS --> $Y"                    # 
 }                                              # 
 test "x$V" = "x" || {                          # 
  Z="$Z${Z:+, }OWNER --> $V"                    # 
 }                                              # 
 set x "$Z"; shift                              # 
 _="$@"                                         # 
 eval $_cHD                                     # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
getDNSServ () {                                 # FUNCTION: GETDNSSERV
 local _gDNSS X                                 # 
 test $# -gt 0 && X="$1" || X="$DOMAIN"         # 
 verbose "getDNSServ [$X]"                      # 
# set x `( ( $INTERNIC -n "$X" 2>&1 ) & ( $SLEEP $WAITNIC; kill $! 2>/dev/null) & )`; 
shift 
 set x `( ( $INTERNIC -n "$X" ) & ( $SLEEP $WAITNIC; kill $! ) & )`; shift 
echo "$# = $@"
test "x$1" != "x" && shift
echo "done!"
 _="$@"                                         # 
 eval $_gDNSS                                   # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
getDOTQmail () {                                # FUNCTION: GETDOTQMAIL
 local _gDQM X                                  # 
 test $# -gt 0 && X="$1" || X="$ACCOUNT"        # 
 verbose "getDOTQmail [$X]"                     # 
 getHomeDir "$X"; HOMEDIR="$_"                  # 
 Y="$HOMEDIR"                                   # 
 test -f "$Y/.qmail" && {                       # 
  set x `$CAT $Y/.qmail`; shift                 # 
 } || {                                         # 
  set x "MISSING --> $Y/.qmail"; shift          # 
 }                                              # 
 _="$@"                                         # 
 eval $_gDQM                                    # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
getVal () {                                     # FUNCTION: GETVAL
 local _gVAL X                                  # 
 test $# -gt 0 && X="$1" || X="$DOMAIN"         # 
 verbose "getVal [$X]"                          # 
 eval $X                                        # 
 echo "$_"                                      # 
 test "x$VERBOSE$PAUSE" = "x" && pressreturn    # 
 eval $_gVAL                                    # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
sysStatus () {                                  # FUNCTION: SYSSTATUS
 verbose "sysStatus"                            # 
 cls
 $CAT <<EOF


              _____   ________    _______    ________ ________    
             /     \  \_____  \   \      \  /  _____/ \_____  \   
            /  \ /  \  /   |   \  /   |   \/   \  ___  /   |   \  
           /    Y    \/    |    \/    |    \    \_\  \/    |    \ 
           \M___|__  /\O______  /\N___|__  /\G_____  /\O______  / 
                   \/         \/         \/        \/     (TM)\/ 

       ----------==========[ MONGO SYSTEM STATUS ]==========----------
EOF
 PAUSE="$TRUE"                                  # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
sysWhack () {                                   # FUNCTION: SYSWHACK
 cls                                            # 
 verbose "sysWhack"                             # 
 echo ""                                        # 
 $ECHO -n "WARNING!!! ARE YOU SURE YOU REALLY WANNA RM -RF /? [N] "
 $SLEEP 2                                       # 
 echo "Yes"                                     # 
 $ECHO  "ok, man, you asked for it!  Hope you have a backup!"   # 
 $ECHO -n "Whacking system ..."                 # 
 for x in 1 2 3 4 5                             # 
 do                                             # 
  $ECHO -n "."                                  # 
  $SLEEP 1                                      # 
 done                                           # 
 echo "JUST KIDDING! h0h0h0 ..."               # 
 PAUSE="$TRUE"                                  # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
getMX () {                                      # FUNCTION: GETMX
 local _gMX X Y                                 # 
 test $# -gt 0 && X="$1" || X="$DOMAIN"         # 
 verbose "getMX [$X]"                           # 
 Y=""
 IFS=",$OFS"                                    # 
 set x `( ( $NSLOOKUP -q=mx "$X" 2>&1 ) & ( $SLEEP $WAITNIC; kill $! 2>/dev/null) & 
)`; shift 
 IFS="$OFS"                                     # 
 test "x$1" != "x" && shift
 while test $# -gt 0                            # 
 do                                             # 
  case "$2 $3 $5 $6 $7" in                      # 
   "preference = mail exchanger =" ) Y="$4=$8${Y:+, }$Y" ;;     # 
   * ) : ;;                                     # 
  esac                                          # 
  shift                                         # 
 done                                           # 
 set x "$Y"; shift                              # 
 _="$@"                                         # 
 eval $_gMX                                     # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
getIP () {                                      # FUNCTION: GETIP
 local _gIP X                                   # 
 test $# -gt 0 && X="$1" || X="$HOST"           # 
 verbose "getIP [$X]"                           # 
 set x `( ( $NSLOOKUP "$X" 2>&1 ) & ( $SLEEP $WAITGIP; kill $! 2>/dev/null) & )`; 
shift 
 while test $# -gt 0                            # 
 do                                             # 
  case "$1 $2" in                               # 
   "$DOMAIN Address:" ) Y="$3"; set x        ;; # 
   * ) : ;;                                     # 
  esac                                          # 
  shift                                         # 
 done                                           # 
 set x "$Y"; shift                              # 
 _="$@"                                         # 
 eval $_gIP                                     # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,

checkEtcHosts () {                              # FUNCTION: CHECKETCHOSTS
 test $# -gt 0 && X="$1" || X="$DOMAIN"         # 
 test $# -gt 1 && Y="$2" || Y="$IP"             # 
 verbose "checkEtcHosts [$X] [$Y]"              # 
 test "x$X" != "x" && {                         # 
  test "x$IP" = "x" && IPP="[0-9]+"             # 
  IFS="$OFS."                                   # 
  set x $X; shift                               # 
  TWOLDOM="$1"                                  # 
  IFS="$OFS"                                    # 
  PAT="$IPP[ $TAB]+$X[ $TAB]+$TWOLDOM[ $TAB]+"  # check /etc/hosts format!
  set x `$EGREP "$PAT" $HOSTFILE`; shift        # 
  } || {                                        # 
   set x; shift                                 # 
  }                                             # 
  _="$@"                                        # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
checkIPMatches () {                             # FUNCTION: CHECKIPMATCHES
 local _cIPM X Y                                # 
 test $# -gt 0 && X="$1" || X="$HOST"           # 
 test $# -gt 1 && Y="$2" || Y="$IP"             # 
 verbose "checkIPMatches [$X] [$Y]"             # 
 checkEtcHosts "$X" "$Y"; set x "$_"; shift     # 
 test $# = 0 && {                               # 
  set x "CHECK-HOSTS"; shift                    # 
  stat "CHECK-HOSTS"                            # 
 } || {                                         # 
  set x; shift                                  # 
 }                                              # 
 _="$@"                                         # 
 eval $_cIPM                                    # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
checkIPAlias () {                               # FUNCTION: CHECKIPALIAS
 local _cIPA X Y                                # 
 test $# -gt 0 && X="$1" || X="$HOST"           # 
 test $# -gt 1 && Y="$2" || Y="$IP"             # 
 verbose "checkIPAlias [$X] [$Y]"               # 
 IFS="."                                        # 
 set x $IP; shift                               # 
 IFS="$OFS"                                     # 
 Z="$4"                                         # 
 IPAF="/etc/hostname.$NETINT:$Z"                # 
 set x `$CAT $IPAF 2>/dev/null`; shift          # 
 MSG="CHECK-$NETINT:$Z --> $1"                  # 
 test $# = 0 && {                               # 
  set x "$MSG"; shift                           # 
 } || {                                         # 
  test "x$@" = "x$DOMAIN" && {                  # 
   set x "alias-ok"; shift                      # 
  } || {                                        # 
   set x "$MSG"; shift                          # 
   stat "$NETINT:$Z"                            # 
  }                                             # 
 }                                              # 
 _="$@"                                         # 
 eval $_cIPA                                    # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
checkQMVD () {                                  # FUNCTION: checkQMVD
 local _cQMVD X Y                               # 
 test $# -gt 0 && X="$1" || X="$DOMAIN"         # 
 test $# -gt 1 && Y="$2" || Y="$ACCOUNT"        # 
 verbose "checkQMVD [$X] [$Y]"                  # 
 set x `$EGREP "^$DOMAIN:" $QMCVD`; shift       # 
 test $# = 0 && {                               # 
  set x "NOVIRT"; shift                         # 
  stat "NOVIRT"                                 # 
 } || {                                         # 
  test "x$Y" != "x" && {                        # 
   case "$@" in                                 # 
    *"$Y" ) : ;;                                # 
    *     ) set x "$@ CHECK-ACCOUNT"; shift ; stat "QVIRT-ACCT";;       # 
   esac                                         # 
  }                                             # 
 }                                              # 
 Z="$@"                                         # 
 set x `$EGREP "^$DOMAIN\$" $QMCRH`; shift      # 
 test $# = 0 && {                               # 
  Z="$Z NORCPT"                                 # 
  stat "NORCPT"                                 # 
 }                                              # 
 set "$Z"                                       # 
 _="$@"                                         # 
 eval $_cQMVD                                   # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
setupVD () {                                    # FUNCTION: setupVD
 test $# -gt 0 && X="$1" || X="$DOMAIN"         # 
 test $# -gt 1 && Y="$2" || Y="$ACCOUNT"        # 
 verbose "setupVD [$X] [$Y]"                    # 
 test "x$X" !=  "x" -a "x$Y" != "x" && {        # 
  setupQMVD "$X" "$Y"                           # 
  setupHTTPVirt "$X" "$Y"                       # 
 } || {                                         # 
  error "Must provide account and domain"       # 
 }                                              # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
setupQMVD () {                                  # FUNCTION: setupQMVD
 local _sQMVD X Y                               # 
 test $# -gt 0 && X="$1" || X="$DOMAIN"         # 
 test $# -gt 1 && Y="$2" || Y="$ACCOUNT"        # 
 verbose "setupQMVD [$X] [$Y]"                  # 
 test "x$X" !=  "x" -a "x$Y" != "x" && {        # 
  set x `$EGREP "^$DOMAIN:" $QMCVD`; shift      # 
  test $# = 0 && {                              # 
   verbose "Adding $X to $QMCVD"                # 
   echo "$DOMAIN:$ACCOUNT" >>$QMCVD             # 
  } || {                                        # 
   :                                            # 
  }                                             # 
  set x `$EGREP "^$DOMAIN\$" $QMCRH`; shift     # 
  test $# = 0 && {                              # 
   verbose "Adding $X to $QMCRH"                # 
   echo "$DOMAIN" >>$QMCRH                      # 
  } || {                                        # 
   :                                            # 
  }                                             # 
  getHomeDir "$Y"; HOMEDIR="$_"                 # 
  setupDOTQmailDefault                          # 
  QMAIL restart                                 # 
 } || {                                         # 
  error "No account and domain!???"             # 
 }                                              # 
 set x;  shift                                  # 
 _="$@"                                         # 
 eval $_sQMVD                                   # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
checkMDNSConf () {                              # FUNCTION: CHECKMDNSCONF
 local _cMDNSC X                                # 
 test $# -gt 0 && X="$1" || X="$DOMAIN"         # 
 verbose "checkMDNSConf [$X]"                   # 
 PAT="zone .$X. in {"                           # 
 set x `$EGREP "$PAT" $MDNSCONF`; shift         # 
 test $# = 0 && {                               # 
  set x "MISSING"; shift                        # 
  stat "NOMASTER"                               # 
 } || {                                         # 
  set x "present"; shift                        # 
 }                                              # 
 _="$@"                                         # 
 eval  $_cMDNSC                                 # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
checkSDNSConf () {                              # FUNCTION: CHECKSDNSCONF
 local _cSDNSC X                                # 
 test $# -gt 0 && X="$1" || X="$DOMAIN"         # 
 verbose "checkSDNSConf [$X]"                   # 
 PAT="zone .$X. in {"                           # 
 set x `$EGREP "$PAT" $SDNSCONF`; shift         # 
 test $# = 0 && {                               # 
  set x "MISSING"; shift                        # 
  stat "NOSLAVE"                                # 
 } || {                                         # 
  set x "present"; shift                        # 
 }                                              # 
 _="$@"                                         # 
 eval $_cSDNSC                                  # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
checkHTTPDConf () {                             # FUNCTION: CHECKHTTPDCONF
 local _cHC X                                   # 
 test $# -gt 0 && X="$1" || X="$DOMAIN"         # 
 verbose "checkHTTPDConf [$X]"                  # 
 PAT="^ *servername *www.$X\$"                  # 
 set x `$EGREP -i "$PAT" $HTTPDCONF`; shift     # 
 test $# = 0 && {                               # 
  set x "MISSING"; shift                        # 
  stat "HTTPDCONF"                              # 
 } || {                                         # 
  set x "present"; shift                        # 
 }                                              # 
 _="$@"                                         # 
 eval $_cHC                                     # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
setupHTTPVirt () {                              # FUNCTION: SETUPHTTPVIRT
 test $# -gt 0 && X="$1" || X="$DOMAIN"         # 
 test $# -gt 1 && Y="$2" || Y="$ACCOUNT"        # 
 verbose "setupHTTPVirt [$X] [$Y]"              # 
 test "x$X" != "x" && {                         #
  PAT="^ *servername *www.$X\$"                 # 
  set x `$EGREP -i "$PAT" $HTTPDCONF`; shift    # 
  test $# = 0 && {                              # 
   set x "$X" "$Y"; shift                       # 
   FILE="$HTTPDCONF"                            # 
   PROG="s/%D%/$1/g;"                           # 
   TMPF="${TEMPTEMP}HTTPDCONF";                 #  temporary file name start
   $SED -e "$PROG" <$HTTPVIRT >>$FILE           # 
   getHomeDir "$2"; set x "$@" "$_"; shift      # 
   FILE="$3/public_html/index.html"             # 
   verbose "Linking: /www/$1 --> $3/public_html"        # 
   $LN -s "$3/public_html" "/www/$1"            # 
   FILE="$3/public_html/index.html"             #  index
   test -f "$FILE" || {                         # 
    verbose "Creating: $FILE "                  # 
    $SED -e "$PROG" <$HTTPIDX >$FILE            #  overwrite old index
   }                                            # 
   HTTPD restart                                # 
  } || {                                        # 
   :                                            # 
  }                                             # 
 }                                              # 
 _="$@"                                         # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
checkEverything () {                            # FUNCTION: CHECKEVERYTHING
 local _cE X Y                                  # 
 test $# -gt 0 && X="$1" || X="$DOMAIN"         # 
 test $# -gt 1 && Y="$2" || Y="$ACCOUNT"        # 
 MSG="Check everything: Account=$Y Domain=$X"   # 
 echo ""                                        # 
 echo "$MSG"                                    # 
 test "x$Y" != "x" && {                         # 
  echo "Checking account: Account --> [$Y] ..." # 
  checkAccount "$Y"; SACCOUNT="$_"              # 
  getHomeDir "$Y"; HOMEDIR="$_"                 # 
  checkHomeDir "$Y"; SHOMEDIR="$_"              # 
  getUserShell "$Y"; SSHELL="$_"                # 
  checkLink "/export/home/$Y"; LHOMEDIR="$_"    # 
  getDOTQmail "$Y"; SDOTQM="$_"                 # 
 }                                              # 
 test "x$X" != "x" && {                         # 
  echo "Checking domain : Domain  --> [$X] ..." # 
  getDNSServ "$X"; DNSSERVERS="$_"              # 
  checkZoneFile "$DOMAIN";  ZONEFILE="$_"       # 
  checkQMVD "$X"; QMVD="$_"                     # 
  checkMDNSConf "$X"; SMDNS="$_"                # 
  checkSDNSConf "$X"; SSDNS="$_"                # 
  getMX "$X"; SMX="$_"                          # 
  getIP "$X"; IP="$_"                           # 
  checkIPMatches "$X" "$IP"; SIPM="$_"          # 
  checkIPAlias "$X" "$IP"; SINT="$_"            # 
  checkLink "/www/$DOMAIN"; SDWLINK="$_"        # 
  checkHTTPDConf "$X"; SVWWW="$_"               # 
  checkDir "/www/$DOMAIN/cgi-bin"; SCGI="$_"    # 
  checkFile "/www/$DOMAIN/index.html"; SINDEX="$_"      # 
  checkDir "/www/$DOMAIN/logs"; SLOGS="$_"      # 
 }                                              # 
 formOUT                                        # 
 pressreturn                                    # 
 eval $_cE                                      # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
doEverything () {                               # FUNCTION: DOEVERYTHING
 test $# -gt 0 && X="$1" || X="$DOMAIN"         # 
 test $# -gt 1 && Y="$2" || Y="$ACCOUNT"        # 
 verbose "doEverything [$X] [$Y]"               #  blah
 test "x$X" !=  "x" -a "x$Y" != "x" && {        # 
  echo "Doing everything, please wait ..."      # 
  set x "$X" "$Y"; shift                        # 
  makeUserAccount "$2"                          # 
  setupDNS "$1" "$IP" "" "$2"                   # 
  setupQMVD "$1" "$2"                           # 
  setupHTTPVirt "$1" "$2"                       # 
  setupIPAlias "$1"                             # 
 } || {                                         # 
  error "Must provide account and domain"       # 
  PAUSE="$TRUE"                                 # 
 }                                              # 
 _="$@"                                         # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
setAccountID () {                               # FUNCTION: SETACCOUNTID
 verbose "setAccountID"                         #  blah
 test $# = 0 && {                               # 
  $ECHO -n "Account ID: "                       # 
  read INPUT                                    # 
  set x "$INPUT"; shift                         # 
 }                                              # 
 test $# -gt 0 && {                             # 
  ACCOUNT="$@"                                  # check validity of ID? FIX
 }                                              # 
}                                               #
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
setDomainName () {                              # FUNCTION: SETDOMAINNAME
 verbose "setDomainName"                        #  blah
 test $# = 0 && {                               # 
  promptinput "Domain Name: "                   #
  set x "$_"; shift                             # 
 }                                              # 
 test $# -gt 0 && {                             # 
  DOMAIN="$@"                                   # check validity of DN? FIX
 }                                              # 
 DOMAIN=`lcase "$DOMAIN"`                       # 
}                                               #
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
setIP () {                                      # FUNCTION: SETIP
 verbose "setIP [$@]"                           #  blah
 test $# = 0 && {                               # 
  $ECHO -n "IP: "                               # 
  read INPUT                                    # 
  set x "$INPUT"; shift                         # 
 }                                              # 
 test `echo "$@" | $WC -c` -lt 8 && {           # 
  case "$@" in                                  # 
   *"." ) set x "$IPBASE$1" ; shift ;;          # 
   ""   ) set x             ; shift ;;          # 
   *    ) set x "$IPBASE.$1"; shift ;;          # 
  esac                                          # 
 }                                              # 
 _="$@"                                         # 
 IP="$_"                                        # 
}                                               #
                                                # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
setMX () {                                      # FUNCTION: SETIP
 verbose "setMX [$@]"                           #  blah
 test $# = 0 && {                               # 
  $ECHO -n "MX: "                               # 
  read INPUT                                    # 
  set x "$INPUT"; shift                         # 
 }                                              # 
 case "$@" in                                   # 
  *"."* ) :                         ;;          # 
  *     ) set x "$@."$DOMAIN; shift ;;          # 
 esac                                           # 
 _="$@"                                         # 
 MX="$_"                                        # 
}                                               #
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
rootcheck () {                                  # FUNCTION: COMMAND
 verbose "rootcheck"                            #  blah
 set x `$ID`; shift                             # 
 case "$@" in                                   # 
  *"uid=0("* ) :                             ;; # 
  *          ) fatalError "Must run as root!";; # 
 esac                                           # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
mongo () {                                      # FUNCTION: COMMAND
 verbose "mongo"                                #  blah
 test "x$INTERACTIVE" != "x" && interactive     # 
}                                               # 
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
command () {                                    # FUNCTION: COMMAND
 verbose "*BEGIN* $@"                           #  blah
 eval "$@"                                      #  evaluate/exec command!
 verbose "* END * $@"                           #  blah
}                                               # end command
                                                # 
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                # 
doProgram () {                                  # FUNCTION: doProgram
 verbose "Running ..."                          #  call: verbose w/ params
 set x $COMMANDS; shift                         #  set values
 while test $# -gt 0                            #  while things to do
 do                                             #  do
  command "$1"                                  #   things
  shift                                         #   one less thing to do
 done                                           #  done doing things
 finish                                         #  call: finish
}                                               # end doProgram
                                                #  
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                #  
main () {                                       # FUNCTION: main 
 initialize "$@"                                #  call: initialize
 eval doProgram $BACKGROUND                     #  call: doProgram
}                                               # end main
                                                #  
# ,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-, # ,-*~'`^`'~*-,._.,-*~'`^`'~*-,
                                                #  
main "$@"                                       #  call: main w/ passed params
                                                #  

#
# !NOT WORKING! WARNING - DO NOT RUN ANY OF THE BELOW OPTIONS!
# (F) Forward Email Address             (MX) Check MX
# (V) Virtual Email Domain              (W) Web domain.
# (I) IP                                        (v) Verbose : $VERBOSE
# (0) Check Everything! Do Everything! Bwahahahahahahahahab!
# (9) Display DNS servers
# (qm ) QMAIL restart                   (qms) QMAIL status
# (www) HTTPD restart                   (wws) HTTPD status
# 




#
#  _______  _____  __   _  ______  _____ 
#  |  |  | |     | | \  | |  ____ |     |
#  |  |  | |_____| |  \_| |_____| |_____|
#


#  \|/ ____ \|/
#   @~/ ,. \~@
#  /_( \__/ )_\
#     \__U_/

#
#              _____   ________    _______    ________ ________    
#             /     \  \_____  \   \      \  /  _____/ \_____  \   
#            /  \ /  \  /   |   \  /   |   \/   \  ___  /   |   \  
#           /    Y    \/    |    \/    |    \    \_\  \/    |    \ 
#           \M___|__  /\O______  /\N___|__  /\G_____  /\O______  / 
#                   \/         \/         \/        \/     (TM)\/ 
#






- Chris Hardie <[EMAIL PROTECTED]>:

| Howdy; please help ASAP: We're running Qmail on FreeBSD 2.2.8.
| Someone sent a 17 MB message to one of our users.  /var, where qmail
| is located, is only a 30 MB partition, and with that message sitting
| in the queue, only has about 3 MB left on it.
| 
| In the maillog, the message
| 
|   deferral: Unable_to_forward_message :_qq_write_error_or_disk_full_(#4.3.0)./
| 
| appears repeatedly.  There's plenty of space on the user's partition
| and their quota will allow for the message just fine.  It appears
| that qmail somehow needs to re-write the message somewhere in it's
| own hierarchy on the same partition before it can forward it on.

Yes indeed, forwarding a message means requeueing it.

| I tried reducing the queue lifetime so the message would bounce, but
| qmail can't bounce it either, the same messages of "file system
| full" keep appearing.

No surprise there.

| I tried (much to your dismay) to move the queue directory to another
| partition, and got an error message at startup about "cannot start:
| unable to open mutex" so I didn't pursue that any further (can
| anyone say what "mutex" is?)

Ouch.  Moving the queue directory is *dangerous*:  There is not only
the special files in queue/lock/, but certain files need to have their
name and inode numbers matching, or else.

| So, I'd *really* like to know:

|   1) In the short term, is there a way to deliver or bounce this
| message without just deleting the queue file manually?

That's what I have done in similar situations.  Stop the queue, move
all the files concerning the big message to a different file system,
and restart qmail.  Now at least other mail can flow freely again.

Second, figure out the real destination address of the the problem
message and reinject it manually using

  qmail-inject -a -f$SENDER $RECIPIENT

where you replace $SENDER and $RECIPIENT by the envelope sender and
recipient, respectively (you can find these in the other files
associated with the message, namely info/*/# and local/*/#.  Except,
of course, you must now supply the forwarding address, so the message
doesn't have to be regurgitated through the queue again.

|   2) In general, did this problem arise because we improperly
| installed qmail to a small partition, or is there something about
| qmail that should be better in handling large messages (i.e. file
| system full problems) that it can't really handle?

I'll say a 30 MB partition is a mite small, yes.  But also, it is true
that qmail doesn't gracefully handle the sort of situation you are
describing.  Making it do so is not a trivial task, however.

|   3) If it's a disk space issue, is there a way to have the queue
| directory somewhere else or do we need to move the whole ball of
| wax?

I think there is no problem with having /var/qmail/queue being a
symlink to a directory on a different filesystem.  On the other hand,
the queue at its largest is usually vastly larger than the rest of the
qmail files combined, so I would generally recommend moving the whole
shebang.  In my opinion, mail is so important it pays to have a
separate filesystem for it.  If you can spare a disk partition, mount
it on /var/qmail and put everything there.  The best way to get it
back in operation, is to reinstall qmail (just run `make setup') and
then to copy everything from the old alias and control directories to
the new partition.  Finally, if there were messages in the old queue,
copy them to the new queue (*all* files) and run the queue-fix program
(link at <URL:http://www.qmail.org/>).  DON'T forget this last step,
as starting the qmail daemons, or even allowing qmail-queue to run
with the queue in a wrong state, can result in a corrupted queue and
lost mail.

|   4) Is there a way to restrict incoming/outgoing message size?

Incoming, yes.  Use control/databytes (RTFM qmail-smtpd).

- Harald




Harald Hanche-Olsen <[EMAIL PROTECTED]> writes:
| I'll say a 30 MB partition is a mite small, yes.  But also, it is true
| that qmail doesn't gracefully handle the sort of situation you are
| describing.  Making it do so is not a trivial task, however.

Of course it is trivial.  There's no reason to include the body of a
message in the bounce.  Just send the first, say, 4k, of the message,
and rely on the sender to have saved a copy if they want to resend.  If
you are receptive to creeping features, qmail could try to send the
whole useless message body, and fall back to just the headers if that
fails.  





- Scott Schwartz <[EMAIL PROTECTED]>:

| Harald Hanche-Olsen <[EMAIL PROTECTED]> writes:
| | I'll say a 30 MB partition is a mite small, yes.  But also, it is true
| | that qmail doesn't gracefully handle the sort of situation you are
| | describing.  Making it do so is not a trivial task, however.
| 
| Of course it is trivial.  There's no reason to include the body of a
| message in the bounce.

What I had in mind is the case of a message that wants to be
forwarded, but which is too big to fit in queue twice.  I agree that
cutting back the size of bounce messages is trivial in comparison.

- Harald




On 20 Feb 1999 14:13:41 -0500, Scott Schwartz wrote:

>Of course it is trivial.  There's no reason to include the body of a
>message in the bounce.  Just send the first, say, 4k, of the message,

Quite hard to do when there is no space. You can't remove the old
message before you've queued the bounce.


-Sincerely, Fred

(Frederik Lindberg, Infectious Diseases, WashU, St. Louis, MO, USA)






"Fred Lindberg" <[EMAIL PROTECTED]> writes:
| >Of course it is trivial.  There's no reason to include the body of a
| >message in the bounce.  Just send the first, say, 4k, of the message,
| 
| Quite hard to do when there is no space. You can't remove the old
| message before you've queued the bounce.

True; in pathological cases you should probably just treat it as a
triple bounce and discard it.  However, it's likely that there is
*some* space, so a 4K bounce for a 20M message is less likely to fail
than a 20M bounce.





This may have already been covered, but if I'm desperate for space on 
/var/qmail, I've been known to trash move everything out of /var/qmail 
(except /var/qmail/qmail) to another FS and symlink back.

That usually gives me enough space and inodes to start draining the queue.


Regards.


At 09:12 PM 2/20/99 -0500, Scott Schwartz wrote:
>"Fred Lindberg" <[EMAIL PROTECTED]> writes:
>| >Of course it is trivial.  There's no reason to include the body of a
>| >message in the bounce.  Just send the first, say, 4k, of the message,
>| 
>| Quite hard to do when there is no space. You can't remove the old
>| message before you've queued the bounce.
>
>True; in pathological cases you should probably just treat it as a
>triple bounce and discard it.  However, it's likely that there is
>*some* space, so a 4K bounce for a 20M message is less likely to fail
>than a 20M bounce.
>
>
>




> | I don't recommend that anyone run an open relay and I'll continue to tell
> | people not to and to refer them to FAQ 5.4, but I'm becoming increasingly
> | sympathetic to people who think they need to. Whether the problem can be 
> | fixed without some kind of username/password authentication in SMTP I
> | don't know, but I think it's something worth talking about.
> 
> Probably the easiest solution is an applet on the PC that tunnels
> 127.0.0.1:25 to a private smtp or qmtp server on the mail host, doing
> authentication in the process.  SMOP.  Wasn't there a usenix paper about
> this a while back?

Bingo!  This solution allows all dumb MUAs to function, as well as
unattended server scripts.  On my laptop (running Linux), I use an ssh
tunnel to relay my queued mail.  It's secure and it uses data compression,
so my mail is sent more quickly.  I'd be more than happy to describe my
setup for those that want to emulate it.

What's needed for Windows is a simple, but configurable program that
runs on the user's machine and listens to localhost:25.  This program
waits for the user's MUA to send mail and then initiates a connection
to the mail relay, authenticating in the process.  I could write this in
Perl, but that would require users to download and install ActiveState's
Perl for Win32 on their machines.  Anyone interested in writing a little
executable? 

We all agree that the ony solution to provide service for users and
not to spammers is authentication before allowing the relay of mail.
Since there is no standard (RFC) for this -- and even if there was,
there would be many MUAs that didn't follow the standard -- the only
solutions are a) to authenticate to server and then allow relaying
for a certain amount of time (e.g. POP before relay), or b) taking all
the dumb MUAs out of the loop by intercepting the sending of mail.
Implementing BOTH is the best solution, IMHO, but a program has yet 
to be written to do the latter.

Glenn Strauss
<[EMAIL PROTECTED]> 





A few people requested a description of how I collect and send the mail
from my laptop, a 486 running RedHat Linux 5.2, over SSH tunnels. 
...No problems with authenticated relaying here. :-) 

Feel free to email me with additional questions on my setup.

Glenn Strauss
<[EMAIL PROTECTED]>

Server requirements: (i.e. the pop server to which you connect)
  MTA (any)
  SSH which allows user logins 

Required packages: (on the client machine)
  qmail      http://www.qmail.org/
  serialmail ftp://koobera.math.uic.edu/www/serialmail.html
  fetchmail  http://www.tuxedo.org/~esr/fetchmail/
  ssh        http://www.ssh.fi/ 

Basically, follow the instructions that come with each package. I compiled
and installed the packages using default settings, and configured qmail to
catch all outgoing mail in a maildir ~alias/pppdir, as recommended by
serialmail docs.  Also, to avoid being prompted by ssh for a password you
must set up a ~/.ssh/identity for RSA authentication.

The only non-standard thing I did was modify /usr/local/bin/maildirsmtp,
which I included below.  I changed the port number from 25 (standard SMTP)
to 1111 because I run my own qmail-smtpd on port 25 and want to send mail
out to the remote server's smtp port 25.   Port 1111 is just an arbitrary
free port on my machine over which I chose to use ssh to tunnel the
relayed mail; port 1111 on my machine is effectively port 25 on the remote
server.

> /usr/local/bin/maildirsmtp

#!/bin/sh 
# WARNING: This file was auto-generated. Do not edit! 

exec \
/usr/local/bin/maildirserial -b -t 1209600 -- "$1" "$2" \ 
tcpclient -RHl0 -- "$3" 1111 \ 
/usr/local/bin/serialsmtp "$2" "$4" 


I run 'fetchmail', which uses my .fetchmailrc (below), in
/etc/ppp/ip-up.local each time I dial in, and I run 'upload-mail' (below)
before I shut down the ppp connection.  Each time ssh is invoked below, it
makes the connection and issues the command 'sleep 10' on the remote
machine, giving the fetchmail or maildirsmtp process 10 seconds (ample
time) to set up its own secure connection, before the original ssh
connection is closed.

> /root/.fetchmailrc

# .fetchmailrc 
defaults
  forcecr 
poll localhost protocol pop3 port 1111:
  preconnect "ssh -C -f [EMAIL PROTECTED] -L 1111:netspace.org:110 sleep 10"
  user gs is gs
  pass MyPaSsWoRd


> /root/bin/upload-mail

#!/bin/sh 

# use serialmail to send queued mail 
ssh -C -f [EMAIL PROTECTED] -L 1111:netspace.org:25 sleep 10
/usr/local/bin/maildirsmtp ~alias/pppdir alias-ppp- localhost gs.netspace.org





I'm looking for a way to let my vmailmgrd users to read their
mail using IMAP (for example via imp). Is there a way to make this
work ?

Why isn't there and standard imap client with qmail ? Would it
be so difficult to programm ? :)

Cheers,
Olivier





On Fri, Feb 19, 1999 at 10:45:21AM -0800,
  Kai MacTane <[EMAIL PROTECTED]> wrote:
> 
> Like it wouldn't be already? Or are you suggesting that the originator
> would manage all the mail coming back to hir, acting as a temporary gateway
> between the two lists?
> 

The Mail-Followup-To header will make this work correctly for people who
use MUAs that support it. When people do group replies, the mail will be
sent to both lists.




>> In a previous message someone asked:

   Anyone know of a way to get around this? Say, to tell qmail to drop all
   mail to something like /mail/u/s/username?

>> On Fri, 19 Feb 1999 21:04:39 -0500 (EST), 
>> [EMAIL PROTECTED] said:

S> maildrop allegedly supports hashed spool directories, see
S> http://maildropl.listbot.com

   Procmail does support hashed spool directories; it's done by choosing a
   macro setting before compiling.
 
    ftp://ftp.net.ohio-state.edu/pub/networking/mail/procmail
    ftp://ftp.psg.com/pub/unix/procmail
    ftp://hub.ucsb.edu/pub/mail             (hand updated)
    ftp://ftp.tamu.edu/pub/Unix/Mail        (hand updated)
    ftp://ftp.informatik.rwth-aachen.de/pub/packages/procmail/procmail.tar.gz

-- 
Karl Vogel
ASC/YCOA, Wright-Patterson AFB, OH 45433, USA
[EMAIL PROTECTED]




I've written a patch to qmail-smtpd that I don't think anyone ought to use: it
lets you control relaying based on envelope sender.

Please don't write to me and point out that this isn't secure--I know that. But
it's something people have asked to be able to do, and combined with tarpitting
and running your SMTP daemon on a non-standard port, it may provide an
acceptable level of safety.

As with the unpatched version of qmail-smtpd, relaying is allowed whenever
RELAYCLIENT is set. This patch adds a control file called relaymailfrom;
envelope senders listed in the file will also be allowed to relay. Entries in
relaymailfrom can be e-mail addresses, or just the domain (with the @ sign). So
if I want [EMAIL PROTECTED] and anyone in domain2.com to be able to relay, my
control/relaymailfrom file would contain:

[EMAIL PROTECTED]
@domain2.com

Controlling relaying based on envelope sender address isn't something I'd
recommend, but if you feel you need to do it, the patch is at
http://www.palomine.net/qmail/relaymailfrom.patch. Also see
http://www.palomine.net/qmail/relaymailfrom.README.

I haven't tested it extensively, but it's pretty simple and most of it is
lifted off of Dan's badmailfrom code. In fact, I think there's only one line
that isn't directly copied and pasted.

Chris


Reply via email to