system: Linux mars.sprixweb.com 3.10.0-1160.119.1.el7.x86_64 #1 SMP Tue Jun 4 14:43:51 UTC 2024 x86_64
#! /bin/sh
umask 022
# postmulti(1) contract:
#
# Arguments:
# postmulti-script -e <edit_command>
#
# Environment:
#
# All actions:
#
# MAIL_CONFIG - config_directory of primary instance
# command_directory - From primary instance
# daemon_directory - From primary instance
# meta_directory - From primary instance
# shlib_directory - From primary instance
# config_directroy - config_directory of target instance
# queue_directory - queue_directory of target instance
# data_directory - data_directory of target instance
#
# Create, destroy, import and deport:
#
# multi_instance_directories - New value for primary instance
#
# Create, import and assign (unset == nochange, "-" == clear):
#
# multi_instance_group - New value for target instance
# multi_instance_name - New value for target instance
: ${MAIL_CONFIG:?"do not invoke this command directly"}
: ${command_directory:?"do not invoke this command directly"}
: ${daemon_directory:?"do not invoke this command directly"}
: ${meta_directory:?"do not invoke this command directly"}
: ${shlib_directory:?"do not invoke this command directly"}
USAGE="$0 -e create|destroy|import|deport|enable|disable|assign|init"
usage() { echo "$0: Error: Usage: $USAGE" >&2; exit 1; }
TAG="$MAIL_LOGTAG/postmulti-script"
fatal() { postlog -p fatal -t "$TAG" "$1"; exit 1; }
# args: add|del $dir
#
update_cfdirs() {
op=$1
dir=$2
alt=`postconf -h alternate_config_directories` || return 1
shift $# # Needed on SunOS where bare "set --" is NOP!
IFS="$IFS,"; set -- $alt; IFS="$BACKUP_IFS"
keep=
found=
# Portability: SunOS "sh" needs 'in "$@"' for one-line for-loop.
for d in "$@"; do [ "$d" = "$dir" ] && found=1 || keep="$keep $d"; done
set -- "multi_instance_directories = $multi_instance_directories"
case $op in
add) test -n "$found" ||
set -- "$@" "alternate_config_directories =$keep $dir";;
del) test -n "$found" &&
set -- "$@" "alternate_config_directories =$keep";;
*) return 1;; # XXX: Internal error
esac
postconf -e "$@" || return 1
}
assign_names() {
# Set the instance name and group
#
test -n "$multi_instance_name" && {
test "$multi_instance_name" = "-" && multi_instance_name=
set -- "$@" "multi_instance_name = $multi_instance_name"
}
test -n "$multi_instance_group" && {
test "$multi_instance_group" = "-" && multi_instance_group=
set -- "$@" "multi_instance_group = $multi_instance_group"
}
test $# -eq 0 || postconf -c "$config_directory" -e "$@" || return 1
}
# Process command-line options and parameter settings. Work around
# brain damaged shells. "IFS=value command" should not make the
# IFS=value setting permanent. But some broken standard allows it.
BACKUP_IFS="$IFS"
action=
while getopts ":e:" opt
do
case $opt in
e) action="$OPTARG";;
*) usage;;
esac
done
shift `expr $OPTIND - 1`
# Check for valid action and required instance name
case "$action" in
create|import|destroy|deport|enable|disable|assign|init) ;;
*) usage;;
esac
test $# -eq 0 || usage
case $action in
init)
postconf -e \
'multi_instance_wrapper = ${command_directory}/postmulti -p --' \
'multi_instance_enable = yes'
exit $? ;;
esac
# Backport note: "-x" requires 2.10 or later, and is not essential here.
#
wrapper=`postconf -hx multi_instance_wrapper` || exit 1
enable=`postconf -hx multi_instance_enable` || exit 1
test -n "$wrapper" ||
fatal "multi_instance_wrapper is empty, run 'postmulti -e init' first."
test "$enable" = "yes" ||
fatal "multi_instance_enable!=yes, run 'postmulti -e init' first."
: ${config_directory:?"Invalid empty target instance config_directory"}
case $action in
create|import)
# Atomically install stock main.cf/master.cf files. We install the
# master.cf file last. Once it is present the instance is complete.
#
test -f $config_directory/main.cf -a \
-f $config_directory/master.cf || {
test "$action" = "create" || {
test -f $config_directory/main.cf ||
fatal "'$config_directory' lacks a main.cf file"
test -f $config_directory/master.cf ||
fatal "'$config_directory' lacks a master.cf file"
}
test -f $meta_directory/main.cf.proto ||
fatal "Missing main.cf prototype: $meta_directory/main.cf.proto"
test -f $meta_directory/master.cf.proto ||
fatal "Missing master.cf prototype: $meta_directory/master.cf.proto"
# Create instance-specific directories
#
test -d $config_directory ||
{ (umask 022; mkdir -p $config_directory) || exit 1; }
test -d $queue_directory ||
{ (umask 022; mkdir -p $queue_directory) || exit 1; }
test -d $data_directory ||
{ (umask 077; mkdir -p $data_directory) || exit 1; }
tmpdir=$config_directory/.tmp
(umask 077; mkdir -p $tmpdir) || exit 1
cp -p $meta_directory/main.cf.proto $tmpdir/main.cf || exit 1
# Shared install parameters are cloned from user-specified values in
# the default instance, but only if explicitly set there. Otherwise,
# they are commented out in the new main.cf file.
#
SHARED_PARAMETERS="
command_directory
daemon_directory
meta_directory
mail_owner
setgid_group
sendmail_path
mailq_path
newaliases_path
html_directory
manpage_directory
sample_directory
readme_directory
shlib_directory
"
shift $# # Needed on SunOS where bare "set --" is NOP!
comment_out=
for p in $SHARED_PARAMETERS; do
val=`postconf -nh $p` || exit 1
test -n "$val" && { set -- "$@" "$p = $val"; continue; }
comment_out="$comment_out $p"
done
# First comment-out any parameters that take default values
test -n "$comment_out" && {
postconf -c $tmpdir -# $comment_out || exit 1
}
# Now add instance-specific and non-default values.
# By default, disable inet services and local submission
# in new instances
#
postconf -c $tmpdir -e \
"queue_directory = $queue_directory" \
"data_directory = $data_directory" \
"authorized_submit_users =" \
"master_service_disable = inet" \
"$@" || exit 1
cp -p $meta_directory/master.cf.proto $tmpdir/master.cf || exit 1
mv $tmpdir/main.cf $config_directory/main.cf || exit 1
mv $tmpdir/master.cf $config_directory/master.cf || exit 1
rmdir $tmpdir 2>/dev/null
}
# Set instance name and group
#
assign_names || exit 1
# Update multi_instance_directories
# and drop from alternate_config_directories
#
# XXX: Must happen before set-permissions below, otherwise instance
# is treated as a non-slave instance by post-install via postfix(1).
#
update_cfdirs del $config_directory || exit 1
# Update permissions of private files. Verifies existence of
# queue_directory and data_directory, ...
#
# XXX: Must happen after instance list updates above, otherwise instance
# is treated as a non-slave instance by post-install via postfix(1).
#
postfix -c $config_directory set-permissions || exit 1
;;
deport)
# Deporting an already deleted instance?
#
[ -f "$config_directory/main.cf" ] || {
update_cfdirs del $config_directory
exit $?
}
postfix -c "$config_directory" status >/dev/null 2>&1 &&
fatal "Instance '$config_directory' is not stopped"
# Update multi_instance_directories
# and add to alternate_config_directories
#
update_cfdirs add $config_directory || exit 1
;;
destroy)
# "postmulti -e destroy" will remove an entire instance only when
# invoked immediately after "postmulti -e create" (i.e. before
# other files are added to the instance). We delete only known
# safe names without "/".
#
QUEUE_SUBDIRS="active bounce corrupt defer deferred flush hold \
incoming maildrop pid private public saved trace"
#DEBUG=echo
WARN="postlog -p warn -t $TAG"
# Locate the target instance
#
[ -f "$config_directory/main.cf" ] ||
fatal "$config_directory/main.cf file not found"
postfix -c "$config_directory" status >/dev/null 2>&1 &&
fatal "Instance '$config_directory' is not stopped"
# Update multi_instance directories
# and also (just in case) drop from alternate_config_directories
#
$DEBUG update_cfdirs del "$config_directory" || exit 1
# XXX: Internal "postfix /some/cmd" interface.
#
postfix -c "$config_directory" /bin/sh -c "
for q in $QUEUE_SUBDIRS
do
$DEBUG rmdir -- \$q ||
$WARN \`pwd\`/\$q: please verify contents and remove by hand
done
"
postfix -c "$config_directory" /bin/sh -c "
for dir in \$data_directory \$queue_directory
do
$DEBUG rmdir -- \$dir ||
$WARN \$dir: please verify contents and remove by hand
done
"
# In the configuration directory remove just the main.cf and master.cf
# files.
$DEBUG rm -f -- "$config_directory/master.cf" "$config_directory/main.cf" 2>/dev/null
$DEBUG rmdir -- "$config_directory" ||
$WARN $config_directory: please verify contents and remove by hand
;;
enable)
postconf -c "$config_directory" -e \
"multi_instance_enable = yes" || exit 1;;
disable)
postconf -c "$config_directory" -e \
"multi_instance_enable = no" || exit 1;;
assign)
assign_names || exit 1;;
esac
exit 0